/* ========================================
   CATASTOSOLARE.EU - SOLAR CADASTRAL MAP
   Technical/Industrial Aesthetic
   ======================================== */

:root {
    /* Color Palette - Dark Technical */
    --bg-primary: #0a0e14;
    --bg-secondary: #131820;
    --bg-elevated: #1a1f29;
    --bg-input: #0f141b;
    /* Translucent background for floating panels (legend, header, coordinates).
       A CSS var so the light theme can flip it white — otherwise panels stay
       dark in light mode and their (now-dark) text is unreadable. */
    --bg-panel: rgba(19, 24, 32, 0.95);

    --text-primary: #e6edf3;
    --text-secondary: #8b949e;
    --text-muted: #6e7681;

    --accent-primary: #ff6b35;
    --accent-secondary: #f7931e;
    --accent-tertiary: #ffd23f;

    --border-subtle: #21262d;
    --border-default: #30363d;
    --border-emphasis: #484f58;

    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5);

    /* Typography */
    --font-display: 'Outfit', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-mono: 'JetBrains Mono', 'Courier New', monospace;

    /* Spacing */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;

    /* Transitions */
    --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-slow: 350ms cubic-bezier(0.4, 0, 0.2, 1);

    /* Sky background of the popup horizon dial — blue-tinted dusk sky. */
    --horizon-sky: #13335c;

    /* Horizon animation palette (read by horizon-anim.js via getComputedStyle) */
    --ha-profile: var(--accent-primary);   /* apparent-horizon line + sun path (orange) */
    --ha-ink: var(--text-primary);          /* labels */
    --ha-muted: var(--text-secondary);      /* legend / dim labels */
    --ha-sil: #2b313c;                      /* obstruction silhouette fill (dark theme) */
    --ha-zero: #5fd0c4;                     /* true 0° horizon (teal, dashed) */
    --ha-grid: var(--border-emphasis);      /* elevation rings / axis cross */
}

/* Light theme overrides — applied via [data-theme="light"] on <html>. */
:root[data-theme="light"] {
    --bg-primary: #f7f4ee;
    --bg-secondary: #ffffff;
    --bg-elevated: #ffffff;
    --bg-input: #ffffff;
    --bg-panel: rgba(255, 255, 255, 0.95);

    --text-primary: #1a1f29;
    --text-secondary: #4a5260;
    --text-muted: #6e7681;

    --border-subtle: #e3dfd6;
    --border-default: #cfc9bd;
    --border-emphasis: #b3ac9d;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.12);

    --horizon-sky: #cfe8ff;
    --ha-sil: #b9a986;   /* earthy silhouette on the light basemap */
}

/* Theme toggle button in the header. */
.theme-toggle {
    background: var(--bg-elevated);
    border: 1px solid var(--border-default);
    color: var(--text-primary);
    border-radius: 8px;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    margin-left: auto;
    margin-right: var(--spacing-md);
    transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}

.theme-toggle:hover {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

.theme-toggle svg {
    width: 18px;
    height: 18px;
}

/* Show sun in dark mode (click → go light), moon in light mode (click → go dark). */
.theme-toggle .icon-sun { display: block; }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

/* ========================================
   RESET & BASE
   ======================================== */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: var(--font-display);
    font-weight: 300;
    background: var(--bg-primary);
    color: var(--text-primary);
    overflow: hidden;
    height: 100vh;
    width: 100vw;
    position: relative;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

button {
    font-family: inherit;
    cursor: pointer;
    border: none;
    background: none;
    color: inherit;
}

/* ========================================
   HEADER
   ======================================== */

.app-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 72px;
    background: linear-gradient(180deg, var(--bg-secondary) 0%, var(--bg-panel) 100%);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border-default);
    z-index: 1000;
    box-shadow: var(--shadow-md);
}

/* Demo-version badge — fixed pill centred just under the header, shown only
   for tenants whose runtime-config sets `demoBanner: true`. Non-interactive so
   it never steals map clicks. */
.demo-banner {
    position: fixed;
    top: 84px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1001;
    pointer-events: none;
    padding: 0.3rem 1rem;
    border-radius: 999px;
    border: 1px solid var(--accent-primary);
    background: var(--accent-primary);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    box-shadow: var(--shadow-md);
}

.demo-banner[hidden] {
    display: none;
}

.header-content {
    height: 100%;
    padding: 0 var(--spacing-xl);
    display: flex;
    align-items: center;
    justify-content: space-between;
    max-width: 100vw;
}

.brand {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
}

.brand-icon {
    width: 32px;
    height: 32px;
    color: var(--accent-primary);
    stroke-width: 2;
    animation: rotate-sun 30s linear infinite;
}

.brand-logo {
    height: 48px;
    width: auto;
}

@keyframes rotate-sun {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

.brand-text h1 {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    background: linear-gradient(135deg, var(--accent-primary) 0%, var(--accent-secondary) 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.brand-subtitle {
    display: block;
    font-size: 0.75rem;
    color: var(--text-muted);
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-top: -2px;
}

.header-stats {
    display: flex;
    gap: var(--spacing-xl);
}

.stat {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

.stat-value {
    font-size: 1.5rem;
    font-weight: 600;
    font-family: var(--font-mono);
    color: var(--accent-secondary);
    line-height: 1.2;
}

.stat-label {
    font-size: 0.7rem;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-top: 2px;
}

/* ========================================
   SEARCH BAR
   ======================================== */

.search-bar {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    padding: var(--spacing-md) var(--spacing-lg);
    border-bottom: 1px solid var(--border-default);
}

.search-input-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
}

.search-icon {
    width: 18px;
    height: 18px;
    color: var(--text-muted);
    flex-shrink: 0;
    margin-right: var(--spacing-sm);
}

.search-input {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    padding: var(--spacing-sm) var(--spacing-md);
    padding-right: 32px;
    font-family: var(--font-display);
    font-size: 0.875rem;
    color: var(--text-primary);
    outline: none;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.search-input::placeholder {
    color: var(--text-muted);
}

.search-input:focus {
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 2px rgba(255, 107, 53, 0.2);
}

.search-clear {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    color: var(--text-muted);
    transition: color var(--transition-fast), background var(--transition-fast);
}

.search-clear:hover {
    color: var(--text-primary);
    background: var(--bg-elevated);
}

.search-clear svg {
    width: 14px;
    height: 14px;
}

.search-results {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    background: var(--bg-elevated);
    border: 1px solid var(--border-default);
    border-radius: 8px;
    box-shadow: var(--shadow-lg);
    max-height: 240px;
    overflow-y: auto;
    display: none;
    z-index: 960;
}

.search-results.visible {
    display: block;
}

.search-result-item {
    padding: var(--spacing-sm) var(--spacing-md);
    cursor: pointer;
    transition: background var(--transition-fast);
    border-bottom: 1px solid var(--border-subtle);
}

.search-result-item:last-child {
    border-bottom: none;
}

.search-result-item:hover,
.search-result-item.active {
    background: rgba(255, 107, 53, 0.1);
}

.search-result-item .result-name {
    font-size: 0.875rem;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.search-result-item .result-type {
    font-size: 0.7rem;
    color: var(--text-muted);
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-top: 1px;
}

.search-no-results {
    padding: var(--spacing-md);
    font-size: 0.85rem;
    color: var(--text-muted);
    text-align: center;
}

.municipality-wrapper {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.municipality-label {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
}

.municipality-select {
    flex: 1;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    padding: var(--spacing-sm) var(--spacing-lg) var(--spacing-sm) var(--spacing-sm);
    font-family: var(--font-display);
    font-size: 0.875rem;
    color: var(--text-primary);
    outline: none;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b949e' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.municipality-select:focus {
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 2px rgba(255, 107, 53, 0.2);
}

.municipality-select option {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

/* ========================================
   MAP
   ======================================== */

#map {
    position: absolute;
    top: 72px;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--bg-primary);
}

/* Custom MapLibre Popup Styling */
.maplibregl-popup {
    z-index: 955; /* above the Deck.gl canvas and the legend panel (950) */
}

.maplibregl-popup-content {
    background: var(--bg-elevated);
    border: 1px solid var(--border-emphasis);
    border-radius: 8px;
    padding: 0;
    box-shadow: var(--shadow-lg);
    min-width: 280px;
    font-family: var(--font-display);
    color: var(--text-primary);
}

.maplibregl-popup-close-button {
    color: var(--text-secondary);
    font-size: 20px;
    padding: 8px;
    right: 4px;
    top: 4px;
    transition: color var(--transition-fast);
}

.maplibregl-popup-close-button:hover {
    color: var(--accent-primary);
    background: transparent;
}

.maplibregl-popup-tip {
    border-top-color: var(--bg-elevated);
}

.popup-header {
    padding: var(--spacing-md) var(--spacing-lg);
    border-bottom: 1px solid var(--border-default);
    background: linear-gradient(180deg, var(--bg-elevated) 0%, var(--bg-secondary) 100%);
    border-radius: 8px 8px 0 0;
}

.popup-header h3 {
    font-size: 1rem;
    font-weight: 600;
    color: var(--accent-secondary);
    font-family: var(--font-mono);
}

.popup-body {
    padding: var(--spacing-md) var(--spacing-lg);
}

.popup-table {
    width: 100%;
    border-collapse: collapse;
}

.popup-table tr {
    border-bottom: 1px solid var(--border-subtle);
}

.popup-table tr:last-child {
    border-bottom: none;
}

.popup-table td {
    padding: var(--spacing-sm) 0;
    font-size: 0.875rem;
}

.popup-table td:first-child {
    color: var(--text-secondary);
    font-weight: 400;
    padding-right: var(--spacing-md);
}

.popup-table td:last-child {
    color: var(--text-primary);
    font-weight: 500;
    text-align: right;
    font-family: var(--font-mono);
}

.popup-highlight {
    color: var(--accent-secondary) !important;
    font-weight: 600 !important;
}

/* ========================================
   LEGEND PANEL
   ======================================== */

.legend-panel {
    position: fixed;
    top: 80px;
    right: var(--spacing-lg);
    width: 320px;
    background: var(--bg-panel);
    backdrop-filter: blur(12px);
    border: 1px solid var(--border-default);
    border-radius: 12px;
    box-shadow: var(--shadow-lg);
    z-index: 950;
    transition: transform var(--transition-base);
}

.legend-panel.collapsed .legend-content,
.legend-panel.collapsed .search-bar {
    display: none;
}

.legend-panel.collapsed .toggle-btn svg {
    transform: rotate(180deg);
}

.legend-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--spacing-sm) var(--spacing-md);
    border-bottom: 1px solid var(--border-default);
}

.legend-header h3 {
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.toggle-btn {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    transition: all var(--transition-fast);
}

.toggle-btn:hover {
    background: var(--bg-input);
}

.toggle-btn svg {
    width: 20px;
    height: 20px;
    transition: transform var(--transition-base);
}

.legend-content {
    padding: var(--spacing-lg);
}

/* Per-layer gradient legends, rendered from LAYERS_CONFIG[].legend by
   buildLayerControls(). Colours and units come from config, so they always
   match what the map paints (irradiation kWh/m²/yr, tree height, etc.). */
.layer-legends:empty {
    display: none;
}

.legend-gradient-block {
    margin-bottom: var(--spacing-lg);
}

.legend-grad-title {
    font-size: 0.75rem;
    font-family: var(--font-mono);
    color: var(--text-secondary);
    margin-bottom: var(--spacing-sm);
}

.legend-gradient-bar {
    height: 24px;
    border-radius: 6px;
    border: 1px solid var(--border-default);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
}

.legend-gradient-labels {
    position: relative;
    height: 1.1rem;
    margin-top: var(--spacing-sm);
    font-size: 0.75rem;
    font-family: var(--font-mono);
    color: var(--text-secondary);
}

.legend-grad-label {
    position: absolute;
    top: 0;
    white-space: nowrap;
}

.legend-section {
    margin-top: var(--spacing-lg);
    padding-top: var(--spacing-lg);
    border-top: 1px solid var(--border-subtle);
}

.legend-section:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

.legend-section h4 {
    font-size: 0.875rem;
    font-weight: 500;
    margin-bottom: var(--spacing-md);
    color: var(--text-primary);
}

.layer-toggle {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) 0;
    cursor: pointer;
    transition: color var(--transition-fast);
}

.layer-toggle:hover {
    color: var(--accent-primary);
}

.layer-toggle input[type="checkbox"] {
    width: 18px;
    height: 18px;
    border: 2px solid var(--border-emphasis);
    border-radius: 4px;
    background: var(--bg-input);
    cursor: pointer;
    appearance: none;
    position: relative;
    transition: all var(--transition-fast);
}

.layer-toggle input[type="checkbox"]:checked {
    background: var(--accent-primary);
    border-color: var(--accent-primary);
}

.layer-toggle input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    left: 5px;
    top: 2px;
    width: 4px;
    height: 8px;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.layer-toggle span {
    font-size: 0.875rem;
}

.legend-info {
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--text-secondary);
}

/* ========================================
   LOADING INDICATOR
   ======================================== */

.loading-indicator {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-lg);
    background: var(--bg-elevated);
    padding: var(--spacing-xl);
    border-radius: 12px;
    border: 1px solid var(--border-default);
    box-shadow: var(--shadow-lg);
    z-index: 2000;
    opacity: 1;
    transition: opacity var(--transition-base);
}

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

.spinner {
    width: 48px;
    height: 48px;
    border: 3px solid var(--border-emphasis);
    border-top-color: var(--accent-primary);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

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

.loading-indicator p {
    font-size: 0.875rem;
    color: var(--text-secondary);
    font-family: var(--font-mono);
}

/* Shown in place of the spinner when initMap() fails (basemap/style/Map
   construction). Keeps the user out of an eternal-spinner dead end. */
.map-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-lg);
    max-width: 280px;
    text-align: center;
}

.map-error-text {
    font-size: 0.875rem;
    color: var(--text-primary);
    line-height: 1.5;
}

.map-error-retry {
    background: var(--accent-primary);
    color: #fff;
    border-radius: 6px;
    padding: var(--spacing-sm) var(--spacing-lg);
    font-family: var(--font-display);
    font-size: 0.875rem;
    font-weight: 500;
    transition: background var(--transition-fast);
}

.map-error-retry:hover {
    background: var(--accent-secondary);
}

/* Top-of-viewport progress bar for in-flight 3D tile fetches.
   Indeterminate animation while at least one /geo3d/ request is pending;
   fades out 400ms after the last one resolves. */
.tile-progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    z-index: 1500;
    pointer-events: none;
    background: transparent;
    overflow: hidden;
    opacity: 1;
    transition: opacity 400ms ease;
}

.tile-progress.idle {
    opacity: 0;
}

.tile-progress .bar {
    position: absolute;
    top: 0;
    height: 100%;
    width: 30%;
    background: linear-gradient(
        90deg,
        transparent,
        var(--accent-primary, #ff8a3d) 30%,
        var(--accent-primary, #ff8a3d) 70%,
        transparent
    );
    animation: tile-progress-slide 1.1s linear infinite;
}

.tile-progress.idle .bar {
    animation-play-state: paused;
}

@keyframes tile-progress-slide {
    0%   { left: -30%; }
    100% { left: 100%; }
}

/* Inline placeholder for the lazily-loaded horizon dial */
.horizon-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 160px;
    font-size: 0.8rem;
    color: var(--text-secondary);
    font-family: var(--font-mono);
    opacity: 0.7;
}

/* Inline placeholder for popup fields awaiting the lazy /feature/<fid>
   fetch. Shown until the full property bag arrives. */
.popup-loading {
    display: inline-block;
    min-width: 1.5em;
    color: var(--text-secondary);
    opacity: 0.6;
    font-family: var(--font-mono);
}

/* ========================================
   RESPONSIVE
   ======================================== */

@media (max-width: 768px) {
    .header-content {
        padding: 0 var(--spacing-md);
    }

    .header-stats {
        display: none;
    }

    .brand-text h1 {
        font-size: 1.25rem;
    }

    .brand-subtitle {
        font-size: 0.65rem;
    }

    /* Tighten the flag row so the header doesn't overflow on tablets/phones. */
    .lang-switch {
        gap: 3px;
        margin-right: var(--spacing-sm, 0.5rem);
    }
    .lang-flag {
        width: 24px;
        height: 18px;
    }

    .legend-panel {
        width: 280px;
        right: var(--spacing-md);
        top: 68px;
    }

    /* The legend/search panels take over the top of the viewport on small
       screens, so dock the demo badge at the bottom instead. */
    .demo-banner {
        top: auto;
        bottom: var(--spacing-md);
        font-size: 0.7rem;
        padding: 0.25rem 0.75rem;
    }
}

@media (max-width: 480px) {
    .app-header {
        height: 60px;
    }

    #map {
        top: 60px;
    }

    .brand-icon {
        width: 24px;
        height: 24px;
    }

    .brand-text h1 {
        font-size: 1.1rem;
    }

    .legend-panel {
        width: calc(100vw - 2rem);
        right: var(--spacing-md);
        left: var(--spacing-md);
        top: 64px;
    }

    /* Clear the coordinates readout, which sits bottom-left. */
    .demo-banner {
        bottom: 2.5rem;
    }
}

/* Phone popup: dock near bottom, centered, full-width with safe margins.
   The popup carries `popup-docked popup-docked--phone`; the --phone variant
   opts out of the top-right docked card below and keeps this bottom dock. */
@media (max-width: 600px) {
    .maplibregl-popup.popup-docked--phone {
        left: 50% !important;
        right: auto !important;
        top: auto !important;
        bottom: var(--spacing-md) !important;
        transform: translateX(-50%) !important;
        max-width: calc(100vw - 2rem) !important;
        width: calc(100vw - 2rem) !important;
    }
    .maplibregl-popup.popup-docked--phone .maplibregl-popup-tip {
        display: none;
    }
    .maplibregl-popup.popup-docked--phone .maplibregl-popup-content {
        max-width: 100%;
        max-height: 60vh;
        overflow-y: auto;
    }
}

/* Placed popup (not phones): fixed at the screen position chosen by placePopup()
   or set by dragging, so it stays put while the map moves. Width comes from JS
   and is shared with the docked card, so undocking on drag doesn't resize it. */
.maplibregl-popup.popup-placed {
    position: fixed !important;
    top: var(--popup-top, 0) !important;
    left: var(--popup-left, 0) !important;
    right: auto !important;
    bottom: auto !important;
    transform: none !important;
    width: var(--popup-width, 360px) !important;
    max-width: calc(100vw - 2rem) !important;
}
.maplibregl-popup.popup-placed .maplibregl-popup-tip {
    display: none; /* the leader line replaces the tip */
}
/* Only the body scrolls, so the title bar and the close button stay reachable
   in a height-capped popup. */
.maplibregl-popup.popup-placed .maplibregl-popup-content,
.maplibregl-popup.popup-docked:not(.popup-docked--phone) .maplibregl-popup-content {
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 96px);
    overflow: hidden;
}
.popup-placed .popup-body,
.popup-docked:not(.popup-docked--phone) .popup-body {
    overflow-y: auto;
}
/* Title bar is the drag handle. */
.popup-placed .popup-header,
.popup-docked:not(.popup-docked--phone) .popup-header {
    flex: none;
    cursor: grab;
    user-select: none;
    touch-action: none;
}
.popup-dragging .popup-header {
    cursor: grabbing;
}

/* Docked popup card (not phones): pin into the legend's top-right slot, hide
   the legend beneath it, cap its height with an internal scroll, and keep the
   close button always reachable. A leader line (drawn in JS) connects the card
   back to the roof. Applied unconditionally — JS decides *when* to add the
   `popup-docked` class (small/short viewport, and the popup can't clear the
   roof), so this must not be gated behind a media query. */
.maplibregl-popup.popup-docked:not(.popup-docked--phone) {
    position: fixed !important;
    top: 80px !important;
    right: var(--spacing-lg) !important;
    left: auto !important;
    bottom: auto !important;
    transform: none !important;
    width: var(--popup-width, 320px) !important;
    max-width: calc(100vw - 2rem) !important;
    z-index: 975; /* above legend (950), search results (960) & placed popups (955), below header (1000) */
}
.maplibregl-popup.popup-docked:not(.popup-docked--phone) .maplibregl-popup-tip {
    display: none; /* the leader line replaces the tip */
}
.maplibregl-popup.popup-docked:not(.popup-docked--phone) .maplibregl-popup-content {
    max-height: min(70vh, calc(100vh - 96px));
}
/* While a docked card is open it supersedes the legend; visibility (not
   display / the collapsed class) so the legend's collapse state survives. */
body.popup-docked-open #legend-panel {
    visibility: hidden;
}

/* Leader line overlay: full map-container overlay, click-through, sitting above
   the Deck canvas but below the docked card. Created & toggled from JS. */
.leader-overlay {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 960;
}
.leader-overlay line {
    stroke: var(--accent-secondary);
    stroke-width: 2;
    stroke-dasharray: 4 3;
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}
.leader-overlay circle {
    fill: var(--accent-secondary);
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}

/* ========================================
   ANIMATIONS
   ======================================== */

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

.legend-panel {
    animation: fadeIn 0.4s ease-out;
}

/* ========================================
   ACCESSIBILITY
   ======================================== */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 2px;
}

/* --- Lignano deployment: comune brand (right side of header) --- */
.app-header .header-content { display: flex; align-items: center; justify-content: space-between; }
.app-header .header-stats:empty { display: none; }
.municipality-brand { display: flex; align-items: center; gap: 0.75rem; margin-left: auto; }
.municipality-brand .municipality-logo { height: 48px; width: auto; }
.municipality-brand .municipality-text { display: flex; flex-direction: column; line-height: 1.1; text-align: right; }
.municipality-brand .municipality-kicker { font-size: 0.75rem; opacity: 0.75; }
.municipality-brand strong { font-weight: 700; font-size: 1rem; }

/* --- Horizon dial inside feature popup --- */
.horizon-wrap { margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid rgba(255,255,255,0.08); display: flex; flex-direction: column; align-items: center; }
.horizon-title { font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: #94a3b8; margin-bottom: 0.4rem; }
.horizon-dial { display: block; }
.horizon-sky  { fill: var(--horizon-sky); }
.horizon-grid { fill: none; stroke: #334155; stroke-width: 0.5; stroke-dasharray: 2 2; }
.horizon-fill { fill: #f59e0b; fill-opacity: 0.55; stroke: #d97706; stroke-width: 1; }
.horizon-tick { fill: #94a3b8; font-size: 10px; font-family: 'JetBrains Mono', monospace; }

/* Deck.gl's MapboxOverlay is added via map.addControl(overlay) with no
   position arg → MapLibre injects its wrapper into .maplibregl-ctrl-top-right.
   The deck canvas inside that wrapper is sized to span the whole map, so it
   paints over the other corners (zoom + compass in top-left, scale in
   bottom-left). All four corners default to z-index:2, and top-right wins
   over its siblings by DOM order. Bump the corners that hold real controls
   above top-right so their buttons render on top of the deck canvas. */
.maplibregl-ctrl-top-left,
.maplibregl-ctrl-bottom-left,
.maplibregl-ctrl-bottom-right {
    z-index: 3;
}

/* Compass: paint the north (top) triangle red so the cardinal direction is
   readable once the map is rotated. Default MapLibre SVG renders north at
   #333 and south at #ccc — both read as gray against this UI's button bg. */
.maplibregl-ctrl button.maplibregl-ctrl-compass .maplibregl-ctrl-icon {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 29 29'%3E%3Cpath fill='%23e84545' d='m10.5 14 4-8 4 8h-8z'/%3E%3Cpath fill='%23888' d='m10.5 16 4 8 4-8h-8z'/%3E%3C/svg%3E");
}

/* Info/guide button: mirrors .theme-toggle, sits beside it (no auto margin). */
.info-toggle {
    background: var(--bg-elevated);
    border: 1px solid var(--border-default);
    color: var(--text-primary);
    border-radius: 8px;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    margin-right: var(--spacing-md);
    transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}

.info-toggle:hover {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

.info-toggle svg {
    width: 18px;
    height: 18px;
}

/* ---- Language switcher (inline flag row) ---- */
.lang-switch {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-right: var(--spacing-md);
}

.lang-flag {
    padding: 0;
    width: 30px;
    height: 22px;
    border: 1px solid var(--border-default);
    border-radius: 4px;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity var(--transition-fast), border-color var(--transition-fast), transform var(--transition-fast);
}

.lang-flag img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    pointer-events: none;
}

.lang-flag:hover {
    opacity: 0.9;
    border-color: var(--accent-primary);
}

.lang-flag.active {
    opacity: 1;
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 1px var(--accent-primary);
}

/* ---- Guida & Informazioni modal ---- */
.info-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--spacing-lg);
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(4px);
}

.info-modal-overlay[hidden] {
    display: none;
}

.info-modal {
    background: var(--bg-secondary);
    border: 1px solid var(--border-default);
    border-radius: 12px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
    width: min(640px, 100%);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.info-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--spacing-md) var(--spacing-lg);
    border-bottom: 1px solid var(--border-default);
    background: linear-gradient(180deg, var(--bg-elevated) 0%, var(--bg-secondary) 100%);
}

.info-modal-header h2 {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--accent-secondary);
}

.info-close {
    background: transparent;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.info-close:hover {
    color: var(--accent-primary);
    background: var(--bg-elevated);
}

.info-close svg {
    width: 20px;
    height: 20px;
}

.info-modal-body {
    padding: var(--spacing-lg);
    overflow-y: auto;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--text-primary);
}

.info-modal-body p {
    margin: 0 0 var(--spacing-md);
}

.info-modal-body h3 {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--accent-secondary);
    margin: var(--spacing-lg) 0 var(--spacing-sm);
}

.info-modal-body ul {
    margin: 0;
    padding-left: 1.2em;
}

.info-modal-body li {
    margin-bottom: var(--spacing-sm);
}

.info-modal-body strong {
    color: var(--accent-secondary);
}

.info-modal-body .info-note {
    margin-top: var(--spacing-md);
    margin-bottom: 0;
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-elevated);
    border-left: 3px solid var(--accent-primary);
    border-radius: 4px;
    color: var(--text-secondary);
    font-size: 0.82rem;
}

/* Orizzonte apparente animation embedded in the info modal */
.horizon-anim {
    margin: var(--spacing-md) 0;
}

.horizon-anim canvas {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    height: auto;
    border: 1px solid var(--border-default);
    border-radius: 8px;
    background: var(--bg-input);
}

.horizon-anim-controls {
    display: flex;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-sm);
}

.horizon-anim-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    cursor: pointer;
    color: var(--text-secondary);
    background: var(--bg-elevated);
    border: 1px solid var(--border-default);
    border-radius: 8px;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}

.horizon-anim-btn:hover {
    color: var(--accent-primary);
    border-color: var(--border-emphasis);
}

.horizon-anim-btn svg {
    width: 18px;
    height: 18px;
}

.info-contact {
    margin-top: var(--spacing-md);
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--border-default);
}

.info-contact-email {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--accent-primary);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
}

.info-contact-email:hover {
    text-decoration: underline;
}

.info-contact-email svg {
    flex-shrink: 0;
}

.info-contact .info-credit {
    margin-top: var(--spacing-sm);
    margin-bottom: 0;
    color: var(--text-secondary);
    font-size: 0.82rem;
}

.info-contact .info-credit a {
    color: var(--accent-primary);
    text-decoration: none;
}

.info-contact .info-credit a:hover {
    text-decoration: underline;
}

/* Roof "solar" popup: grouped multi-column layout (Area/tilt/azimuth, the
   irradiation triplet with a merged header, and the four on-the-fly solar
   estimates). Overrides the generic 2-column table rules above. */
.popup-solar {
    table-layout: fixed;
}

.popup-solar tr {
    border-bottom: none;
}

.popup-solar th,
.popup-solar td {
    padding: 2px 4px;
    text-align: center;
    font-size: 0.8rem;
}

/* Neutralize the generic first/last-child label/value styling so every grid
   column is treated equally. */
.popup-solar td:first-child,
.popup-solar td:last-child {
    color: inherit;
    text-align: center;
    font-weight: 500;
    padding-right: 4px;
}

/* Group headers and sub-headers read as muted labels. */
.popup-solar .psr-head th,
.popup-solar .psr-subhead th,
.popup-solar .psr-inline-label {
    color: var(--text-secondary);
    font-weight: 400;
    line-height: 1.2;
}

.popup-solar .psr-subhead th {
    font-size: 0.7rem;
    opacity: 0.8;
    padding-top: 0;
}

.popup-solar .psr-inline-label {
    text-align: left;
}

/* Value cells: monospace numbers; the accent colour comes from .popup-highlight. */
.popup-solar .psr-val td {
    font-family: var(--font-mono);
    padding-bottom: 4px;
}

/* Thin separator line between groups. */
.popup-solar .psr-gap td {
    padding: 0;
    height: 5px;
    border-bottom: 1px solid var(--border-subtle);
}

/* ========================================
   TOAST (non-blocking notification)
   ======================================== */

.app-toast {
    position: fixed;
    bottom: var(--spacing-lg);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    max-width: calc(100vw - 2rem);
    background: var(--bg-elevated);
    border: 1px solid var(--border-emphasis);
    border-left: 3px solid var(--accent-primary);
    border-radius: 8px;
    padding: var(--spacing-sm) var(--spacing-md);
    box-shadow: var(--shadow-lg);
    z-index: 2100;
    animation: fadeIn 0.3s ease-out;
}

.app-toast-msg {
    font-size: 0.85rem;
    color: var(--text-primary);
}

.app-toast-close {
    flex-shrink: 0;
    font-size: 1.1rem;
    line-height: 1;
    color: var(--text-secondary);
    padding: 0 var(--spacing-xs);
    transition: color var(--transition-fast);
}

.app-toast-close:hover {
    color: var(--accent-primary);
}
