/* Preview band that blends into the hero title; expands to fullscreen. isolation:isolate contains the map + fade + open-button z-indices (which must beat Leaflet's internal panes) so they don't leak out and outrank the header's Compare button. */ .wrapper { position: relative; width: 100%; height: 210px; background: var(--bg-secondary); isolation: isolate; } @media (max-width: 640px) { .wrapper { height: 150px; } } /* Preview: move the OSM attribution off the bottom edge, where the school title slides up under the fade — top-left is the band's only quiet corner (Compare floats top-right). Fullscreen keeps Leaflet's default bottom-right, since the zoom control occupies the top-left there. */ .wrapper:not([data-fullscreen]) :global(.leaflet-bottom.leaflet-right) { top: 0; left: 0; right: auto; bottom: auto; } /* Fullscreen: the Fullscreen API promotes this element to fill the viewport. */ .wrapper[data-fullscreen] { height: 100vh; height: 100dvh; background: #fff; } /* Fallback fullscreen (iOS Safari — no Element.requestFullscreen): the API can't promote the element, so pin it over the page ourselves. Above the comparison toast (3000) and everything else except modals (9999+). */ .wrapper[data-fs-fallback] { position: fixed; inset: 0; z-index: 5000; } .skeleton { width: 100%; height: 100%; background: /* Sweeps toward the card colour, which is a shade lighter than this ground in both themes. Hardcoded white was a bright flash across a dark page every 1.4s while the tiles loaded. */ linear-gradient(100deg, rgba(var(--bg-card-rgb), 0) 40%, rgba(var(--bg-card-rgb), .5) 50%, rgba(var(--bg-card-rgb), 0) 60%) var(--bg-secondary); background-size: 200% 100%; animation: shimmer 1.4s infinite; } @keyframes shimmer { to { background-position: -200% 0; } } /* Full-band click target. Transparent so the map shows through; reveals a hint pill on hover/focus. Sits above the map but below the header's fade and Compare button (which carry higher stacking in the header). */ .openBtn { position: absolute; inset: 0; /* Above Leaflet's marker pane (600) so the whole band — pin included — is one click target. Transparent, so map + pin still show through. */ z-index: 800; width: 100%; height: 100%; padding: 0; border: 0; background: transparent; cursor: pointer; display: flex; align-items: flex-end; justify-content: center; } /* * Controls that float ON the map. * * The map tiles are light in both themes, so these deliberately do NOT follow * the theme — they follow the map. The literal ink below is the point: paired * with a hardcoded white background, `color: var(--text-primary)` resolved to * #E9EEF0 in the dark theme and put near-white text on a near-white button. * A themed token is the wrong tool for a surface that never changes. */ .openHint { display: inline-flex; align-items: center; gap: 7px; margin-bottom: 16px; padding: 8px 14px; border-radius: 999px; font-size: 13px; font-weight: 600; /* See "Controls that float ON the map" above. */ color: #1C2731; background: rgba(255, 255, 255, .85); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); box-shadow: 0 2px 10px rgba(var(--shadow-rgb), .16); opacity: 0; transform: translateY(4px); transition: opacity .16s ease, transform .16s ease; } .openBtn:hover .openHint, .openBtn:focus-visible .openHint { opacity: 1; transform: none; } /* Diffuse fade: map dissolves to the card background before the title. */ .fade { position: absolute; left: 0; right: 0; bottom: 0; top: 33%; /* Above Leaflet's tile (200) and overlay (400) panes so the gradient is actually visible, but below the marker pane (600) so the pin stays crisp on top of the blend. */ z-index: 450; pointer-events: none; /* The card colour, not white. This ramp was hardcoded white and ended at var(--bg-card). In the light theme that is white into white and invisible, as intended. In the dark theme it climbed to 95% WHITE and then met a near-black card — a bright band across the full width, right where the map is supposed to dissolve into the header. Fading to the same colour the gradient lands on is the whole trick, and it only works if that colour is a token. */ background: linear-gradient(to bottom, rgba(var(--bg-card-rgb), 0) 0%, rgba(var(--bg-card-rgb), .35) 35%, rgba(var(--bg-card-rgb), .75) 62%, rgba(var(--bg-card-rgb), .95) 82%, var(--bg-card) 100%); } .closeBtn { position: absolute; top: 0.75rem; right: 0.75rem; z-index: 1000; display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border: none; border-radius: 8px; background: rgba(255, 255, 255, .92); /* See "Controls that float ON the map" above. */ color: #1C2731; cursor: pointer; box-shadow: 0 2px 10px rgba(var(--shadow-rgb), .2); } .closeBtn:hover { background: #fff; }