* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    /* Match the app's dark-blue theme used by the load overlay (darker) */
    background: #041018;
    color: #e2e2e2;
    overflow: hidden;
    height: 100vh;
}

/* Headings use Orbitron for a tech/retro look */
h1, h2, h3, h4, h5, h6 {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, sans-serif;
    font-weight: 700;
}
.root-vars {
    /* Ripple configuration: maximum ripple diameter. Use CSS custom property so JS can read it. */
}

:root {
    --ripple-max-size: 140px; /* maximum diameter for ripple rings (slightly smaller) */
    /* Sidebar background used across sidebar and footer */
    --sidebar-bg: linear-gradient(180deg, #0a1929 0%, #041018 100%);
    /* Height of the footer area (buttons + spacing). Adjust to match actual button sizes. */
    --sidebar-footer-height: 120px;
    /* vertical offset used to align sidebar gradient and hints/consent overlay
       (footer height). Keep in sync by referencing the footer height variable. */
    --sidebar-overlay-bottom: var(--sidebar-footer-height);
}
.load-fade-keeper {}

/* Full-screen load fade overlay (fades from black to transparent) */
#loadFade {
    position: fixed;
    inset: 0;
    z-index: 100000;
    /* Use the app's dark background color (matches the screenshot) so the site fades from that color */
    background: #041018;
    opacity: 1;
    transition: opacity 600ms ease;
    pointer-events: none;
    will-change: opacity;
}

#loadFade.fade-out { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
    #loadFade { transition: none; opacity: 0; }
}
.app-container {
    display: flex;
    height: 100vh;
}

/* Loader logo centered inside the load overlay */
#loadFade .loader {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 220px;
    height: 220px;
    pointer-events: none;
}

.loading-logo {
    width: 160px;
    height: 160px;
    display: block;
    animation: logo-spin 1600ms linear infinite;
    will-change: transform;
}

/* Larger stacked logo sizing specifically for the load overlay */
#loadFade .logo-stack {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

#loadFade .logo-stack .logo-ball {
    width: 160px;
}

#loadFade .logo-stack .logo-geotag {
    width: 112px;
    transform: translateY(-8px);
}

@media (prefers-reduced-motion: reduce) {
    .loading-logo { animation: none; transform: none !important; }
}

/* Sidebar */
.sidebar {

/* Grayscale tile variants are provided by server-side folders (sat_bw / holo_bw).
   Runtime canvas or DOM filters are no longer used for grayscale.
*/
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 280px;
    background: var(--sidebar-bg);
    border-right: 1px solid #0e4a6e;
    display: flex;
    flex-direction: column;
    z-index: 200;
    transition: transform 280ms linear;
    will-change: transform;
    /* manipulation: allows double-tap zoom and pinch (which we block globally), 
       but tells browser not to delay interactions after nearby pan gestures */
    touch-action: manipulation;
}

/* Subtle cyan gradient box at the bottom of the sidebar
   — cyan from below, fading to transparent above. Non-interactive. */
.sidebar::after {
    /* Gradient overlay anchored to the top edge of the sidebar and ending
       at the same vertical position as the hints/consent overlay bottom.
       Use CSS variable so we keep the edges synced. */
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0; /* align upper edge with sidebar upper edge */
    bottom: var(--sidebar-overlay-bottom); /* align lower edge with overlay bottom */
    pointer-events: none;
    z-index: 2; /* keep overlay above backgrounds but below interactive controls */
    background: linear-gradient(to top, rgba(34,211,238,0.32) 0%, rgba(34,211,238,0.08) 30%, rgba(34,211,238,0) 100%);
    animation: sidebarGradientPulse 6s ease-in-out infinite;
}

/* Subtle pulsating animation for the sidebar gradient overlay. */
@keyframes sidebarGradientPulse {
    0%   { opacity: 1; }
    50%  { opacity: 0.25; }
    100% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .sidebar::after {
        animation: none !important;
    }
}

/* Collapsed sidebar */
.app-container.sidebar-collapsed .sidebar {
    transform: translateX(-100%);
}
/* Sidebar handle - rebuilt to share animations with mini toggle group */
#sidebarHandle {
    width: 40px;
    height: 40px;
    background: linear-gradient(180deg, #0d2137 0%, #091521 100%);
    background-color: #0b2236; /* fallback */
    border: 1px solid #0e4a6e;
    border-radius: 8px;
    color: #22d3ee;
    font-size: 20px;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    /* Match zoom-btn transition */
    transition: background 150ms ease, transform 120ms ease, border-color 150ms;
    padding: 0;
    appearance: none;
    -webkit-appearance: none;
    /* Prevent browser double-tap zoom on touch devices and stop native scrolling when swiping rows */
    touch-action: none;
}

#sidebarHandle:active,
#sidebarHandle.pressed {
    /* Unified pressed visual feedback with other mini buttons */
    background: linear-gradient(180deg, var(--edit-layer-press1, #0891b2) 0%, var(--edit-layer-press2, #065666) 100%);
    border-color: var(--edit-layer-border, #0891b2);
    transform: scale(0.95);
    transition: transform 10ms ease;
}

#sidebarHandle .mini-icon {
    color: var(--edit-layer-icon, #22d3ee);
    font-size: 18px;
    transition: none;
    transform-origin: center center;
    display: inline-block;
    transform: translateY(-4px);
}

.app-container.sidebar-collapsed #sidebarHandle .mini-icon {
    /* icon glyphs are swapped via JS; no CSS rotation */
}

/* Sidebar handle emphasized state when consent is not given */
#sidebarHandle.emphasized {
    background: linear-gradient(180deg, #04121a 0%, #021018 100%);
    border-color: #033747;
    color: #cfeff5;
    /* inline (inset) cyan border + outer glow placeholder (animated) */
    box-shadow: inset 0 0 0 2px #22d3ee, 0 0 0 rgba(34,211,238,0);
    animation: consentPulse 1800ms ease-in-out infinite;
}

/* When emphasized and pressed, remove animation but keep box-shadow for consistent outline */
#sidebarHandle.emphasized.pressed {
    animation: none;
}

.header {
    padding: 16px;
    border-bottom: 1px solid #0e4a6e;
    background: linear-gradient(135deg, #0891b2 0%, #065666 100%);
    display: flex;
    align-items: center;
    gap: 12px;
}

/* stacked logo left of header text */
.logo-stack {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 48px;
    /* Nudge whole logo stack slightly to the right for visual balance */
    transform: translateX(6px);
}
.logo-stack img {
    display: block;
    height: auto;
}
/* specific sizing per asset to preserve exported proportions */
.logo-stack .logo-ball {
    width: 40px;
    transform-origin: center center;
    animation: logo-spin 4s linear infinite;
}
.logo-stack .logo-geotag {
    width: 28px;
    /* nudge up slightly so the pinshape visually stacks on the ball */
    transform: translateY(-4px);
}

/* Logo spin animation (reduce-motion respected below) */
@keyframes logo-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .logo-stack .logo-ball {
        animation: none !important;
        transform: none !important;
    }
}
.title-block h1 {
    font-size: 12px;
    font-weight: 500;
    opacity: 0.95;
    margin-bottom: 2px;
}
.title-block h2 {
    font-size: 14px;
    font-weight: 500;
    margin: 0;
}

/* Ensure header title/subtitle are left-aligned and white, next to the icon */
.title-block {
    text-align: left;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    /* keep title aligned with nudged logo */
    margin-left: 6px;
}
.title-block h1,
.title-block h2 {
    color: #ffffff;
    text-align: left;
}

/* Ensure layer rows keep left-aligned text and don't inherit centered button styles */
.layer-toggle {
    justify-content: flex-start;
    text-align: left;
}
.layer-info {
    text-align: left;
}

.header h1 {
    font-size: 14px;
    font-weight: 500;
    opacity: 0.9;
    margin-bottom: 4px;
}

.header h2 {
    font-size: 16px;
    font-weight: 700;
}

.controls {
    padding: 16px;
    flex: 1;
    overflow-y: auto;
    /* manipulation tells browser not to delay scroll in gesture interpretation window */
    touch-action: manipulation;
}

/* Hide scrollbar visually while keeping scroll behavior. Cross-browser rules. */
.controls {
    -ms-overflow-style: none; /* IE and Edge */
    scrollbar-width: none; /* Firefox */
}
.controls::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;
}

.control-group {
    margin-bottom: 20px;
}

/* Reduce spacing before the footer: last control group shouldn't add extra gap */
/* (reverted experimental spacing tweak) */

.control-group h3 {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: #22d3ee;
    margin-bottom: 12px;
}

/* Glow effect for specific section titles (cyan) */
.control-group.section-glow > h3 {
    text-shadow: 0 0 10px rgba(34, 211, 238, 0.55), 0 0 22px rgba(34, 211, 238, 0.18);
}

/* Separator line under each section title to match the cyan glow */
.control-group > h3 {
    position: relative;
}
.control-group > h3::after {
    content: "";
    display: block;
    height: 2px;
    width: 100%;
    margin-top: 8px;
    border-radius: 2px;
    background: rgba(34, 211, 238, 0.12);
    box-shadow: 0 0 8px rgba(34, 211, 238, 0.25), 0 0 18px rgba(34, 211, 238, 0.08);
}

/* Stronger, colored separator for section-glow titles */
.control-group.section-glow > h3::after {
    background: linear-gradient(90deg, rgba(34,211,238,0.95), rgba(34,211,238,0.6));
    box-shadow: 0 0 12px rgba(34, 211, 238, 0.45), 0 0 28px rgba(34, 211, 238, 0.18);
}

/* Layer list container: vertical stack with 1px spacing between rows */
#layerList {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.layer-toggle {
    display: flex;
    align-items: center;
    gap: 12px; /* tighter spacing between icon/checkbox and text */
    padding: 10px 12px; /* match control buttons for consistent vertical sizing */
    min-height: 48px; /* ensure consistent row height for all layers */
    height: 48px; /* enforce uniform row height to match other sidebar controls */
    width: calc(100% - 48px);
    margin-right: 48px; /* leave a vertical touch area on the right for scrolling */
    box-sizing: border-box;
    /* Darken default (disabled) state slightly so active rows stand out more */
    background: rgba(34, 211, 238, 0.03);
    border-radius: 8px;
    cursor: pointer;
    transition: none; /* disable transitions for instant toggle changes */
    box-shadow: none;
    border: none;
    /* Prevent browser double-tap zoom on touch devices */
    touch-action: manipulation;
    position: relative; /* for absolutely-positioned checkbox inside */
}

/* Disabled state for layer rows when editing custom markers - block interaction but don't darken */
.layer-toggle.disabled {
    pointer-events: none;
}
/* Active state: brighter background when the layer is enabled */
.layer-toggle.active {
    /* Slight bluish active state */
    background: rgba(34, 211, 238, 0.12);
}

/* Inline inset border for layer rows when the layer is highlighted.
   `has-inline-highlight` is toggled on the row by JS so the border
   matches the intended visual outline and does not rely on pseudo-elements. */
.sidebar #layerList .layer-toggle.has-inline-highlight {
    /* Stronger, more robust inline highlight:
       - inset box-shadow when supported
       - outline fallback for cases where box-shadow is overridden or clipped
       - use higher specificity to reduce accidental overrides */
    /* color exposed via CSS variable so JS can read it at runtime */
    --layer-inline-highlight-color: #22d3ee;
    box-shadow: inset 0 0 0 2px var(--layer-inline-highlight-color);
    outline: 2px solid var(--layer-inline-highlight-color);
    outline-offset: -2px;
}

/* Edit-mode only outline: second animated outline visible only during edit mode for route/marker layers */
.sidebar #layerList .layer-toggle.edit-mode-outline {
    --edit-mode-outline-color: #a78bfa; /* default purple, overridden by layer color in JS */
    box-shadow: inset 0 0 0 4px var(--edit-mode-outline-color);
    animation: pulse-edit-outline 0.4s ease-in-out infinite;
}

/* Pulsating opacity animation for edit-mode outline only (uses layer's color from CSS variable) */
@keyframes pulse-outline-opacity {
    0%, 100% {
        box-shadow: inset 0 0 0 2px var(--layer-inline-highlight-color);
        outline: 2px solid var(--layer-inline-highlight-color);
    }
    50% {
        box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--layer-inline-highlight-color) 0%, transparent);
        outline: 2px solid color-mix(in srgb, var(--layer-inline-highlight-color) 0%, transparent);
    }
}

/* Pulsating animation for edit-mode outline (breathing effect) */
@keyframes pulse-edit-outline {
    0%, 100% {
        box-shadow: inset 0 0 0 4px var(--edit-mode-outline-color);
    }
    50% {
        box-shadow: inset 0 0 0 4px color-mix(in srgb, var(--edit-mode-outline-color) 40%, transparent);
    }
}

/* Layer-toggle no-longer uses hidden native checkboxes; state is represented
   by the `.layer-toggle.active` class and `aria-pressed` on the button rows. */

.layer-icon {
    width: 36px;
    height: 36px;
    background: #22d3ee; /* cyan backdrop by default; can be overridden per-layer via data */
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    line-height: 1;
}

/* Visual state for highlighted layer icon backdrop */
.layer-icon.highlighted {
    transform: scale(1.05);
}

/* Grid quadrant labels placed in the middle of each 8x8 cell when grid highlight is on */
#gridQuadLabels {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 15; /* sit above canvas but below sidebar */
}

/* In-map heatmap toggle removed; styling not needed. Use sidebar `#gridHeatmapBtn` for controls. */
.grid-quad-label {
    position: absolute;
    transform: translate3d(-50%, -50%, 0);
    font-size: 12px;
    /* Use Orbitron for quadrant indices (fall back to Space Grotesk then system fonts) */
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    font-weight: 700;
    color: #22d3ee;
    text-shadow: 0 1px 0 rgba(0,0,0,0.6);
    /* Subtle bluish backdrop used elsewhere but kept muted so labels remain legible */
    background: rgba(0, 44, 56, 0.28);
    padding: 2px 6px;
    border-radius: 6px;
    line-height: 1;
    white-space: nowrap;
    pointer-events: none;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-align: center;
}

.grid-quad-index {
    display: inline-block;
}

.grid-quad-count {
    display: none; /* hidden when zero */
    min-width: 18px;
    height: 18px;
    line-height: 18px;
    border-radius: 12px;
    padding: 0 6px;
    background: linear-gradient(180deg, #2ea04aff 0%, #237a2b 100%);
    color: #001916;
    font-weight: 700;
    font-size: 12px;
    box-shadow: 0 1px 0 rgba(0,0,0,0.4), 0 0 6px rgba(46,160,74,0.12) inset;
    text-align: center;
}

.layer-info {
    flex: 1;
}

.layer-name {
    font-size: 12px;
    font-weight: 500;
}

/* Use Orbitron for layer titles to test look-and-feel */
.layer-name {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    font-weight: 600;
}

.layer-name {
    color: #22d3ee;
}

/* Make the Local Storage (consent) toggle title cyan to match dev stats */
#saveDataToggle_label .layer-name {
    color: #22d3ee;
}

/* Center the title text inside the consent toggle */
#saveDataToggle_label .layer-info {
    display: flex;
    justify-content: center;
    align-items: center;
}
#saveDataToggle_label .layer-name {
    text-align: center;
}

/* Ensure the consent toggle button matches the Hints toggle width/spacing */
#saveDataToggle_label {
    width: calc(100% - 32px); /* same as .hints-toggle */
    padding: 10px 12px;
    margin: 6px 16px 6px 16px; /* match hints-toggle margins */
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Consent toggle: when storage consent is OFF, encourage action with dark background and a subtle pulse */
#saveDataToggle_label:not(.active) {
    background: linear-gradient(180deg, #04121a 0%, #021018 100%);
    border-color: #033747;
    color: #cfeff5;
    /* inline (inset) cyan border + outer glow placeholder (animated)
       The inset part keeps the "inline outline" look requested. */
    box-shadow: inset 0 0 0 2px #22d3ee, 0 0 0 rgba(34,211,238,0);
    animation: consentPulse 1800ms ease-in-out infinite;
}

@keyframes consentPulse {
    0% { box-shadow: inset 0 0 0 2px #22d3ee, 0 0 0 0px rgba(34,211,238,0.12); }
    50% { box-shadow: inset 0 0 0 2px #22d3ee, 0 0 20px 8px rgba(34,211,238,0.18); }
    100% { box-shadow: inset 0 0 0 2px #22d3ee, 0 0 0 0px rgba(34,211,238,0.00); }
}

/* When pressed (consent given), restore normal pressed styling (handled via .pressed rules) */
/* When pressed (consent given), remove pulse and inline border to match normal pressed styling */
#saveDataToggle_label.active {
    animation: none;
    box-shadow: none;
}

/* ===== Consent toggle - cloned styles for per-button adjustments ===== */
/* Base appearance for consent toggle when not emphasized (consent given or neutral) */
#saveDataToggle_label {
    /* clone of .control-toggle base but full-width like other sidebar toggles */
    width: calc(100% - 32px); /* account for 16px left + 16px right margin */
    padding: 10px 12px;
    /* margin inherited from earlier rule */
    box-sizing: border-box;
    background: linear-gradient(135deg, #0d4a6e 0%, #0a2f47 100%);
    border: 1px solid #269cdc;
    color: #22d3ee;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    transition: all 0.2s;
    touch-action: manipulation;
}

/* Pressed appearance for consent toggle (both emphasized and regular) */
#saveDataToggle_label.pressed,
#saveDataToggle_label:active {
    /* clone of .control-toggle.pressed */
    background: linear-gradient(135deg, #0e5a7d 0%, #0b3a54 100%);
    border-color: #22d3ee;
    color: #22d3ee;
    box-shadow: 0 0 8px rgba(34, 211, 238, 0.2);
}

/* Active appearance for consent toggle (consent given) - match danger/clear buttons base */
#saveDataToggle_label.active {
    /* use danger base background (not the pressed variant) so pressing can show pressed state */
    background: linear-gradient(135deg, #7f1d1d 0%, #5f0f0f 100%);
    border-color: #dc2626;
    color: #fca5a5;
    box-shadow: none !important; /* no glow for active consent */
}
#saveDataToggle_label.active .layer-name {
    color: #fca5a5;
}

/* Pressed appearance for consent toggle when active (match danger pressed) */
#saveDataToggle_label.active.pressed,
#saveDataToggle_label.active:active {
    /* match .control-btn.danger.pressed */
    background: linear-gradient(135deg, #991b1b 0%, #7f1d1d 100%) !important;
    border-color: #f87171 !important;
    color: #fca5a5 !important;
    /* do NOT add box-shadow for consent button even when pressed */
    box-shadow: none !important;
    animation: none !important; /* ensure any pulse is stopped */
}
#saveDataToggle_label.active.pressed .layer-name,
#saveDataToggle_label.active:active .layer-name {
    color: #fca5a5 !important;
}

/* Ensure emphasized (no consent) keeps its special look unless pressed */
#saveDataToggle_label:not(.active) {
    /* existing emphasized styling preserved above */
}

/* ===================================================================== */

/* Pressed state for emphasized consent toggle (when not consented) */
#saveDataToggle_label:not(.active).pressed,
#saveDataToggle_label:not(.active):active {
    /* Match the emphasized sidebar handle's background and remove glow */
    background: linear-gradient(180deg, #0d2137 0%, #091521 100%);
    border-color: #22d3ee;
    color: #22d3ee;
    animation: none;
    /* inset cyan outline + intense outer cyan glow */
    box-shadow: inset 0 0 0 2px #22d3ee, 0 0 14px rgba(34,211,238,0.95), 0 0 36px rgba(34,211,238,0.6);
}

.layer-count {
    font-size: 11px;
    color: #9fb9c9;
}

/* Try Orbitron for layer subtitles (counts/meta) */
.layer-count {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    font-weight: 500;
}

/* Data Miners section */
.dataminers-list {
    margin-top: 10px;
    background: rgba(255,255,255,0.02);
    border: 1px solid rgba(34,211,238,0.06);
    padding: 8px;
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 24px; /* ensure consistent spacing to next section */
}

.dataminer-row {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    align-items: center;
    padding: 6px 8px;
    border-radius: 4px;
    border: 1px solid rgba(34,211,238,0.1);
    transition: all 200ms ease;
}

.dataminer-label {
    color: #9fb9c9;
    font-size: 12px;
}
/* Use Orbitron for contributor names */
.dataminer-label {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Control buttons */
.control-btn {
    width: 100%;
    padding: 10px 12px;
    margin-bottom: 8px;
    background: linear-gradient(135deg, #0d4a6e 0%, #0a2f47 100%);
    border: 1px solid #269cdc;
    color: #22d3ee;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    transition: all 0.2s;
    /* Prevent browser double-tap zoom on touch devices */
    touch-action: manipulation;
}

/* Control toggles (same as buttons) */
.control-toggle {
    width: 100%;
    padding: 10px 12px;
    margin-bottom: 8px;
    background: linear-gradient(135deg, #0d4a6e 0%, #0a2f47 100%);
    border: 1px solid #269cdc;
    color: #22d3ee;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    transition: all 0.2s;
    /* Prevent browser double-tap zoom on touch devices */
    touch-action: manipulation;
}

/* Make the edit markers sidebar button icon slightly larger */
#editMarkersToggle {
    font-size: 16px; /* increase symbol size */
    padding: 12px 12px;
}

/* Make the edit route sidebar button match edit markers sizing */
#editRouteToggle {
    font-size: 16px;
    padding: 12px 12px;
}

.control-btn.pressed,
.control-btn:active {
    background: linear-gradient(135deg, #0e5a7d 0%, #0b3a54 100%);
    border-color: #22d3ee;
    box-shadow: 0 0 8px rgba(34, 211, 238, 0.2);
}

.control-toggle.pressed,
.control-toggle:active {
    background: linear-gradient(135deg, #0e5a7d 0%, #0b3a54 100%);
    border-color: #22d3ee;
    transform: scale(0.98);
}

.control-toggle.active {
    background: linear-gradient(135deg, #0e5a7d 0%, #0b3a54 100%);
    border-color: #22d3ee;
    box-shadow: 0 0 20px rgba(34, 211, 238, 0.6);
}

.control-toggle.active.pressed {
    box-shadow: none;
}

.control-btn:active {
    transform: scale(0.98);
}

.control-btn.danger {
    background: linear-gradient(135deg, #7f1d1d 0%, #5f0f0f 100%);
    color: #fca5a5;
    border-color: #dc2626;
}

.control-toggle.danger {
    background: linear-gradient(135deg, #7f1d1d 0%, #5f0f0f 100%);
    color: #fca5a5;
    border-color: #dc2626;
}

.control-btn.danger.pressed,
.control-btn.danger:active {
    background: linear-gradient(135deg, #991b1b 0%, #7f1d1d 100%);
    border-color: #f87171;
    box-shadow: 0 0 8px rgba(248, 113, 113, 0.2);
}

.control-toggle.danger.pressed,
.control-toggle.danger:active {
    background: linear-gradient(135deg, #991b1b 0%, #7f1d1d 100%);
    border-color: #f87171;
    transform: scale(0.98);
}

.control-toggle.active.danger {
    background: linear-gradient(135deg, #991b1b 0%, #7f1d1d 100%);
    border-color: #f87171;
    box-shadow: 0 0 20px rgba(248, 113, 113, 0.6);
}

.control-toggle.active.danger.pressed {
    box-shadow: none;
}

.control-toggle.danger.pressed,
.control-toggle.danger:active {
    background: linear-gradient(135deg, #991b1b 0%, #7f1d1d 100%);
    border-color: #f87171;
    box-shadow: 0 0 8px rgba(248, 113, 113, 0.2);
    transform: scale(0.98);
}

/* Ensure active toggles temporarily lose their glow when pressed
   and use the same pressed visuals as the idle->pressed transition.
   This covers both the JS-added `pressed` class and the browser
   `:active` pseudo-class. */
.control-toggle.active.pressed,
.control-toggle.active:active {
    box-shadow: none;
    background: linear-gradient(135deg, #0d4a6e 0%, #0a2f47 100%);
    border-color: #269cdc;
    color: #22d3ee;
    transform: scale(0.98);
}

.control-toggle.active.danger.pressed,
.control-toggle.active.danger:active {
    box-shadow: none;
    background: linear-gradient(135deg, #7f1d1d 0%, #5f0f0f 100%);
    border-color: #dc2626;
    color: #fca5a5;
    transform: scale(0.98);
}

/* Remove size change on pressed states for toggles so they don't shrink */
.control-toggle.pressed,
.control-toggle:active,
.control-toggle.danger.pressed,
.control-toggle.danger:active,
.control-toggle.active.pressed,
.control-toggle.active:active,
.control-toggle.active.danger.pressed,
.control-toggle.active.danger:active {
    transform: none !important;
}

/* Prevent sidebar buttons from resizing in pressed state */
.sidebar .control-btn.pressed,
.sidebar .control-btn:active,
.sidebar .control-btn.danger.pressed,
.sidebar .control-btn.danger:active {
    transform: none !important;
}

/* Status bar */
.status-bar {
    padding: 12px 16px;
    border-top: 1px solid #0e4a6e;
    display: flex;
    gap: 16px;
    font-size: 12px;
    color: #888;
}

.status-item {
    display: flex;
    gap: 6px;
}

.status-value {
    color: #22d3ee;
    font-weight: 600;
}

/* Map container */
.map-container {
    flex: 1;
    position: relative;
    overflow: hidden;
}

/* Stack canvases to fill the map area and avoid layout shifts (fixes blue bar) */
.map-container canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    background: transparent;
}

/* tile canvas beneath overlay (non-interactive) */
#mapTiles {
    z-index: 0;
    pointer-events: none;
}

/* heatmap canvas sits above tiles and below overlay */
#heatmapCanvas {
    z-index: 1;
    pointer-events: none;
    /* Use normal alpha blending so the heatmap composes via RGBA alpha only */
    mix-blend-mode: normal;
    will-change: opacity, transform;
}

/* overlay canvas (interactive) */
#mapCanvas {
    z-index: 2;
    cursor: grab;
    /* Disable browser pinch-to-zoom on the canvas so pointer events
       (including multi-touch pinch) are delivered to the app's JS
       which implements pinch-to-zoom handling. */
    touch-action: none;
}

#mapCanvas:active {
    cursor: grabbing;
}

/* Semi-transparent overlay shown during edit modes (markers/route) */
.edit-overlay {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 20; /* above canvas (1) and below zoom controls (50) */
    background: rgba(34, 238, 228, 0.347);
    pointer-events: none; /* allow map interactions through overlay */
    /* Blend with map tiles beneath for a lighter, screen-like effect */
    mix-blend-mode: screen;
    /* Hint to browser about properties that will change */
    will-change: opacity, background-color;
    opacity: 0;
    transition: opacity 160ms ease;
}
.edit-overlay.visible {
    opacity: 1;
}

/* Zoom controls */
.zoom-controls {
    position: absolute;
    bottom: 20px;
    right: 20px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    z-index: 50;
    /* Make only the actual buttons catch pointer events so empty space is click-through */
    pointer-events: none;
}

/* Re-enable pointer events on the individual buttons */
.zoom-controls .zoom-btn {
    pointer-events: auto;
}

.mini-row {
    position: absolute;
    /* place to the left of the sidebar handle; adjust if button size changes */
    right: 44px; /* moved closer to sidebar handle */
    bottom: 0;
    display: flex;
    flex-direction: row;
    gap: 4px;
    /* keep the container out of pointer flow so clicks between buttons hit the map */
    pointer-events: none;
}

/* Allow clicks through the empty areas of the mini-row so the map can be dragged
   when clicking between buttons. Buttons remain interactive via pointer-events:auto. */
.mini-row .zoom-btn {
    pointer-events: auto;
}

.zoom-btn {
    width: 40px;
    height: 40px;
    background: linear-gradient(180deg, #0d2137 0%, #091521 100%);
    background-color: #0b2236;
    border: 1px solid #0e4a6e;
    border-radius: 8px;
    color: #22d3ee;
    font-size: 20px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 150ms ease, transform 120ms ease, border-color 150ms;
    appearance: none;
    -webkit-appearance: none;
    /* Prevent browser double-tap zoom on touch devices */
    touch-action: manipulation;
}

/* Size and align inline SVG icons inside zoom buttons */
.zoom-btn .mini-icon {
    width: 18px;
    height: 18px;
    display: block;
    margin: 0;
    color: var(--edit-layer-icon, #22d3ee);
}

/* Nudge the expand-route mini icon slightly upward for visual centering */
#computeRouteNearbyMini .mini-icon {
    display: inline-block;
    transform: translateY(-2px);
    line-height: 18px;
    font-size: 16px;
}

/* Center the edit-route mini icon in the onscreen controls */
/* Center edit-route icon inside its mini-toggle */
#editRouteToggleMini .mini-icon {
    display: block;
    transform: none;
    margin: 0;
    width: 18px;
    height: 18px;
    line-height: 18px;
    font-size: 16px;
    text-align: center;
}

/* Also center the reverse-direction mini icon */
/* Center reverse-direction icon inside its mini-toggle */
#toggleRouteDirMini .mini-icon {
    display: block;
    transform: none;
    margin: 0;
    width: 18px;
    height: 18px;
    line-height: 18px;
    font-size: 16px;
    text-align: center;
}

/* Center edit-markers icon inside its mini-toggle */
#editMarkersToggleMini .mini-icon {
    display: block;
    transform: none;
    margin: 0;
    width: 18px;
    height: 18px;
    line-height: 18px;
    font-size: 16px;
    text-align: center;
}

/* Slight nudge for the reset-view mini icon (1px) */
#resetView .mini-icon {
    display: inline-block;
    transform: translateY(-1px);
    line-height: 20px;
    font-size: 20px;
}

.zoom-btn:active,
.zoom-btn.pressed {
    background: linear-gradient(180deg, var(--edit-layer-press1, #0891b2) 0%, var(--edit-layer-press2, #065666) 100%);
    border-color: var(--edit-layer-border, #0891b2);
    transform: scale(0.95);
    transition: transform 10ms ease;
}

/* Route-related mini toggles: keep normal background and border when pressed or active */
#editRouteToggleMini:active,
#editRouteToggleMini.pressed,
#computeRouteNearbyMini:active,
#computeRouteNearbyMini.pressed,
#toggleRouteDirMini:active,
#toggleRouteDirMini.pressed,
#editMarkersToggleMini:active,
#editMarkersToggleMini.pressed {
    background: linear-gradient(180deg, #0d2137 0%, #091521 100%);
    border-color: var(--edit-layer-border, #0e4a6e);
}

/* Unified mini buttons: no background change on press, keep normal background */
#sidebarHandle:active,
#sidebarHandle.pressed,
#resetView:active,
#resetView.pressed,
#zoomOut:active,
#zoomOut.pressed,
#zoomIn:active,
#zoomIn.pressed {
    background: linear-gradient(180deg, #0d2137 0%, #091521 100%);
}

/* Glow state for the mini edit-markers toggle in the zoom controls */
.zoom-btn.glow {
    box-shadow: 0 0 12px var(--edit-layer-glow1, rgba(34, 211, 238, 0.45)), 0 0 28px var(--edit-layer-glow2, rgba(34, 211, 238, 0.12));
    border-color: var(--edit-layer-border, #22d3ee);
}

/* Route edit sidebar button: allow per-layer outline/glow via CSS variables */
#editRouteToggle.pressed {
    border-color: var(--edit-route-border, #22d3ee);
    box-shadow: 0 0 12px var(--edit-route-glow1, rgba(34, 211, 238, 0.2));
}

/* Edit markers sidebar button: per-layer outline/glow via CSS variables */
#editMarkersToggle.pressed {
    border-color: var(--edit-markers-border, #22d3ee);
    box-shadow: 0 0 12px var(--edit-markers-glow1, rgba(34, 211, 238, 0.2));
}

/* Tooltip */
#tooltip {
    position: fixed;
    background: rgba(10, 25, 41, 0.95);
    border: 1px solid #22d3ee;
    border-radius: 6px;
    padding: 6px 10px;
    font-size: 13px;
    color: #e2e2e2;
    pointer-events: none;
    z-index: 199;
    display: none;
    white-space: nowrap;
}

/* Keyboard hints - in-flow list inside the footer (expands to push content) */
.hints-overlay {
    width: 100%;
    /* use the same base background as the sidebar so this list visually matches */
    background: var(--sidebar-bg);
    /* no border for a cleaner hints box */
    border-top: none;
    z-index: 250; /* sit above sidebar background but below footer buttons */
    display: block;
    overflow: hidden; /* collapse when closed */
    pointer-events: none;
    opacity: 0; /* visually hidden when closed */
    max-height: 0; /* collapsed */
    transition: max-height 260ms cubic-bezier(.2,.9,.18,1), opacity 150ms ease;
    will-change: max-height, opacity;
}

.hints-overlay.open,
.hints-overlay.visible {
    opacity: 1;
    pointer-events: auto;
    overflow-y: auto;
    /* limit to a comfortable size relative to viewport */
    max-height: min(60vh, calc(100vh - var(--sidebar-footer-height)));
    height: auto; /* fallback */
}

/* Footer container at bottom of sidebar — now in-flow so toggles push content */
.sidebar-footer {
    position: relative;
    width: 100%;
    min-height: var(--sidebar-footer-height);
    background: var(--sidebar-bg);
    border-top: 1px solid #0e4a6e;
    z-index: 300; /* keep above sidebar background */
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 12px 0; /* vertical spacing inside footer */
    box-sizing: border-box;
}

/* Ensure consent and hints buttons render above the overlay box and fit nicely inside footer */
.sidebar-footer .hints-toggle,
.sidebar-footer #saveDataToggle_label {
    position: relative;
    z-index: 310;
    width: calc(100% - 32px);
}

.hints-overlay.closed {
    /* Explicit closed state: collapse */
    max-height: 0;
    pointer-events: none;
    overflow: hidden;
}

/* When sidebar is collapsed, hint overlay is hidden entirely */
.app-container.sidebar-collapsed .hints-overlay {
    display: none;
    opacity: 0;
}


/* Hide native scrollbars but keep scrolling functional */
.hints-overlay {
    -ms-overflow-style: none; /* IE and Edge */
    scrollbar-width: none; /* Firefox */
}
.hints-overlay::-webkit-scrollbar {
    width: 0px;
    height: 0px;
}

.hints-list kbd {
    background: #0e4a6e;
    padding: 2px 6px;
    border-radius: 3px;
    font-family: 'Space Grotesk', monospace;
    color: #22d3ee; /* match pin/icon cyan */
}

/* Global keyboard key color to match UI cyan */
kbd {
    color: #22d3ee;
}

/* Group related hints so their label doesn't break across lines */
.hint-group {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    white-space: normal;
}

.hint-label {
    color: #a0c4d8;
    font-size: 11px;
}

/* Right-align hint text (labels) while keeping command keys on the left */
.hint-label {
    margin-left: auto;
    text-align: right;
}

/* Decorative connector line between key(s) and label */
.hint-group {
    position: relative;
}
.hint-group::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 1px;
    background: linear-gradient(90deg, rgba(160,196,216,0.06), rgba(160,196,216,0.14), rgba(160,196,216,0.06));
    transform: translateY(-50%);
    z-index: 0;
    pointer-events: none;
}

/* Ensure keys and labels sit above the connector and mask it where they overlap */
.hint-group kbd,
.hint-group .hint-label {
    position: relative;
    z-index: 1;
}

/* Give label a matching footer background so it masks the connector cleanly */
.hint-group .hint-label {
    background: var(--sidebar-bg);
    padding: 0 8px;
}

/* Small inline icon used inside hint-group (e.g. pin SVG) */
.hint-icon {
    width: 12px;
    height: 12px;
    display: inline-block;
    vertical-align: middle;
    margin: 0 -2px;
}

/* Hints toggle button (matches .control-btn exactly) */
.hints-toggle {
    width: calc(100% - 32px); /* account for 16px left + 16px right margin */
    padding: 10px 12px;
    margin: 20px 16px 6px 16px;
    background: linear-gradient(135deg, #0d4a6e 0%, #0a2f47 100%);
    border: 1px solid #269cdc;
    color: #22d3ee;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    transition: all 0.2s;
    touch-action: manipulation;
}

/* Ensure the hints toggle sits above the sidebar gradient overlay */
.hints-toggle {
    position: relative;
    z-index: 1005;
}

.hints-toggle.pressed,
.hints-toggle:active {
    background: linear-gradient(135deg, #0e5a7d 0%, #0b3a54 100%);
    border-color: #22d3ee;
    box-shadow: 0 0 8px rgba(34, 211, 238, 0.2);
}

/* (removed temporary adjacent-sibling hack during investigation) */

.hints-toggle:active {
    transform: scale(0.98);
}

/* Full-screen computing overlay to lock interactions during route computation */
.computing-overlay {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,0.35);
    z-index: 3000;
    pointer-events: auto;
}
.computing-overlay .computing-inner {
    background: rgba(6,12,20,0.9);
    padding: 14px 18px;
    border-radius: 8px;
    color: #22d3ee;
    font-weight: 600;
    box-shadow: 0 6px 24px rgba(0,0,0,0.6);
}

/* Collapsible hints list (fully hidden by default, expands when visible) */
.hints-list {
    padding: 6px 16px 16px; /* remove top padding; rely on footer spacing */
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-size: 11px;
    color: #a0c4d8;
    opacity: 0; /* contents hidden when collapsed */
    transition: opacity 180ms ease; /* fade in/out */
    pointer-events: none; /* disable interactions when hidden */
}

.hints-overlay.open .hints-list,
.hints-overlay.visible .hints-list {
    opacity: 1; /* fade contents in */
    pointer-events: auto; /* enable interactions once visible */
    transition-delay: 220ms; /* wait until container has finished revealing */
}

/* Dev-stats panel (compact rows under low-spec toggle) */
.dev-stats {
    margin-top: 10px;
    background: rgba(255,255,255,0.02);
    border: 1px solid rgba(34,211,238,0.06);
    padding: 8px;
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 12px; /* keep spacing consistent with other control content */
}

/* Settings slider styling */
.settings-row {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.settings-row label {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    font-size: 12px;
    color: #9fb9c9;
}
.settings-row #highlightScaleValue {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
    color: #22d3ee;
    font-size: 12px;
}
.settings-row input[type="range"] {
    -webkit-appearance: none;
    width: 100%;
    height: 4px;
    background: rgba(34, 211, 238, 0.2);
    border-radius: 2px;
    cursor: pointer;
}
.settings-row input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #22d3ee;
    cursor: pointer;
}
.settings-row input[type="range"]:focus { outline: none; }
.settings-row input[type="range"]::-moz-range-track {
    background: rgba(34, 211, 238, 0.2);
    border-radius: 2px;
}
.settings-row input[type="range"]::-moz-range-thumb {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #22d3ee;
    border: none;
    cursor: pointer;
}
.dev-row {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    align-items: center;
}
.dev-label {
    color: #9fb9c9;
    font-size: 12px;
}
.dev-label {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.dev-value {
    font-family: 'Orbitron', 'Space Grotesk', system-ui, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.dev-value {
    color: #22d3ee;
    font-weight: 600;
    font-size: 12px;
}

/* Decorative connector line between dev stat label and value (masked under label/value) */
.dev-row {
    position: relative;
}
.dev-row::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 1px;
    background: linear-gradient(90deg, rgba(160,196,216,0.06), rgba(160,196,216,0.14), rgba(160,196,216,0.06));
    transform: translateY(-50%);
    z-index: 0;
    pointer-events: none;
}
.dev-row .dev-label,
.dev-row .dev-value {
    position: relative;
    z-index: 1;
    background: var(--sidebar-bg);
    padding: 0 8px;
}

/* Mobile: smaller handle, adjust positioning */
/* Mobile: smaller handle, adjust positioning (small-screen breakpoint removed) */
/* Previously contained an @media (max-width: 720px) breakpoint that resized
   the sidebar and handle on narrow viewports. That behavior was removed to
   keep a consistent sidebar width across screen sizes. */

/* When the handle is placed inside the zoom controls, keep it static in the control column */
.zoom-controls #sidebarHandle {
    position: relative;
    left: auto;
    top: auto;
    /* match zoom control button shape: square and consistent radius */
    width: 40px;
    height: 40px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Ripple ring pulse effect */
.ripple-ring {
    position: fixed; /* fixed so it can sit above all stacking contexts */
    z-index: 200001; /* sit above everything (including loading fade) */
    transform: translate(-50%, -50%) scale(0.0);
    border-radius: 50%;
    pointer-events: none;
    border: 2px solid rgba(34,211,238,0.9);
    box-shadow: 0 0 14px rgba(34,211,238,0.35), inset 0 0 8px rgba(34,211,238,0.06);
    opacity: 1;
    will-change: transform, opacity;
    animation: rippleRing 600ms cubic-bezier(.2,.9,.18,1) forwards;
    max-width: var(--ripple-max-size);
    max-height: var(--ripple-max-size);
}

@keyframes rippleRing {
    0% { transform: translate(-50%, -50%) scale(0.0); opacity: 1; }
    70% { transform: translate(-50%, -50%) scale(1.0); opacity: 0.6; }
    100% { transform: translate(-50%, -50%) scale(1.12); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .ripple-ring { animation: none; opacity: 0; }
}

.zoom-controls .sidebar-handle .handle-icon {
    /* no rotation/animation on icon when inside controls */
    transition: none;
    /* small vertical nudge for tighter visual centering */
    transform: translateY(-1px);
}

/* Prevent the sidebar handle from jumping when the sidebar toggles
   (override the generic collapsed-state rule when the handle is inside
   the zoom control column). Use strong specificity and non-animated rules. */
.app-container.sidebar-collapsed .zoom-controls #sidebarHandle {
    position: relative !important;
    left: auto !important;
    top: auto !important;
}

/* When the hints overlay is collapsed, reduce the Hints button top
   margin so the footer doesn't leave a large empty gap. This is a
   conservative, local fix that only applies when the overlay is closed. */
.sidebar-footer .hints-overlay.closed + .hints-toggle {
    margin-top: 6px;
}
