diff --git a/accispace/HANDOFF.md b/accispace/HANDOFF.md
new file mode 100644
index 0000000..b9362d3
--- /dev/null
+++ b/accispace/HANDOFF.md
@@ -0,0 +1,106 @@
+# ACCI Handoff
+
+Last updated: 2026-07-19
+
+## Current state
+
+ACCI, the Austin Crash Context Interface, is live at [acci.handprotocol.org](https://acci.handprotocol.org). It is a standalone static Netlify app that renders recent fatal and suspected serious-injury crashes from the City of Austin Vision Zero crash-level dataset.
+
+The production Netlify project is `acci-handprotocol`, project ID `92b38e69-7254-4e2d-aed6-4f6795379b22`. The custom domain is managed through the existing `handprotocol.org` Netlify DNS zone and is covered by its wildcard TLS certificate.
+
+## Product behavior
+
+- The initial map loads the latest five calendar years of fatal and suspected serious-injury crashes.
+- WebGL terrain, point markers, and severity-weighted hexagonal columns show spatial concentrations of harm.
+- Year, travel mode, severity, and terrain controls update the map and totals.
+- Address and landmark search is bounded to Austin through Photon.
+- A selected address summarizes matching crashes within 80 meters.
+- “Show accidents near location” expands the investigation radius to one kilometer.
+- Double-clicking the map reverse-searches the selected point and shows a five-second “Search this pin” confirmation.
+- Top-harm arrows step through the 20 highest severity-weighted concentrations under the active filters.
+- The target control selects a random crash under the active filters.
+- Tapping a crash opens its date, harm, speed, involved units, location, and source-record link.
+
+## Mobile interaction rules
+
+Mobile uses one active surface at a time. Search results, Explore Data, location summaries, crash details, about content, and pin confirmation must not stack.
+
+- Explore Data opens from the bottom-left settings control.
+- Explore Data has an internal X close control.
+- Crash and location details open as bottom sheets with safe-area padding.
+- Crash markers retain their small visual dots but have 36 to 44 pixel invisible hit regions.
+- Opening a new surface closes competing surfaces.
+- Closing crash details restores the active location summary when one exists.
+
+## Files
+
+- `index.html`: semantic application shell, controls, summaries, prompts, and source notes.
+- `style.css`: full visual system, responsive layout, bottom sheets, and reduced-motion behavior.
+- `app.js`: map setup, City data query, filtering, spatial aggregation, search, reverse lookup, hotspot navigation, random targeting, and overlay state.
+- `netlify.toml`: static publish configuration, security headers, and revalidated asset caching.
+- `favicon.svg`: ACCI application mark.
+- `README.md`: short local-development and data-source guide.
+
+## External services
+
+- Crash data: `https://data.austintexas.gov/resource/y2wy-tgr5.geojson`
+- Geocoding and reverse lookup: `https://photon.komoot.io`
+- Basemap: `https://tiles.openfreemap.org/styles/dark`
+- Terrain tiles: AWS Terrain Tiles, Terrarium encoding
+- Map runtime: MapLibre GL JS 5.24.0 from unpkg
+- Fonts: Inter and JetBrains Mono from Google Fonts
+
+The app has no build step and no stored API secrets. External-service availability is a runtime dependency.
+
+## Local development
+
+```bash
+cd accispace
+python3 -m http.server 4173
+```
+
+Open `http://localhost:4173`.
+
+## Validation
+
+Run before deployment:
+
+```bash
+node --check app.js
+npx --yes html-validate@10 index.html
+git diff --check -- .
+```
+
+The latest browser verification covered:
+
+- Loading 2,063 live crash records
+- Ranked hotspot navigation
+- Random crash targeting
+- Address and nearby-crash summaries
+- Double-click reverse lookup and countdown dismissal
+- Real crash-marker pointer selection
+- Exclusive mobile overlays at 390 by 844 pixels
+- Mobile Explore Data open and close behavior
+- No browser exceptions during the verified flows
+
+## Deploy
+
+The directory is linked locally to the Netlify project through `.netlify/state.json`, which is intentionally ignored by git. Deploy manually with:
+
+```bash
+netlify deploy --prod --dir . --message "Describe the ACCI update"
+```
+
+After deployment, verify both `https://acci.handprotocol.org` and the browser-level live data load. JavaScript and CSS use `max-age=0, must-revalidate` because the filenames are not content-hashed.
+
+## Known constraints and next moves
+
+- There is no bundled crash-data fallback if the City API is unavailable.
+- Photon, OpenFreeMap, terrain tiles, fonts, and MapLibre are external runtime dependencies.
+- The word “accident” appears in user-facing discovery controls because that is the requested language. City data and explanatory copy otherwise use “crash.”
+- A future reliability pass could vendor MapLibre, self-host fonts, and create a scheduled crash-data snapshot.
+- A future analysis pass could add accessible crash lists and permalinked filter state.
+
+## Repository safety
+
+ACCI work is confined to `accispace/`. The adjacent `wxl/` working changes belong to a separate workstream and must not be staged or modified as part of ACCI work.
diff --git a/accispace/README.md b/accispace/README.md
new file mode 100644
index 0000000..4aff589
--- /dev/null
+++ b/accispace/README.md
@@ -0,0 +1,17 @@
+# ACCI
+
+Austin Crash Context Interface is an experimental spatial view of fatal and serious-injury crashes in Austin. It reads the City of Austin's public Vision Zero crash-level dataset directly in the browser and renders severity-weighted harm cells over a WebGL terrain map.
+
+## Run locally
+
+```bash
+python3 -m http.server 4173
+```
+
+Open `http://localhost:4173`.
+
+## Data
+
+Source: [Austin Crash Report Data, Crash Level Records](https://data.austintexas.gov/Transportation-and-Mobility/Austin-Crash-Report-Data-Crash-Level-Records/y2wy-tgr5)
+
+The app requests fatal and suspected serious-injury records for the latest five calendar years. Data can be delayed, revised, incomplete, or imprecisely located. Recent totals are especially likely to change.
diff --git a/accispace/app.js b/accispace/app.js
new file mode 100644
index 0000000..097ba77
--- /dev/null
+++ b/accispace/app.js
@@ -0,0 +1,808 @@
+const DATASET_ID = "y2wy-tgr5";
+const DATASET_URL = `https://data.austintexas.gov/resource/${DATASET_ID}.geojson`;
+const SOURCE_PAGE = `https://data.austintexas.gov/resource/${DATASET_ID}`;
+const DEFAULT_VIEW = { center: [-97.7431, 30.2672], zoom: 10.35, pitch: 57, bearing: -18 };
+const CURRENT_YEAR = new Date().getFullYear();
+const FIRST_YEAR = Math.max(2016, CURRENT_YEAR - 4);
+const ADDRESS_RADIUS_METERS = 80;
+const NEARBY_RADIUS_METERS = 1000;
+
+const state = {
+ features: [],
+ firstYear: FIRST_YEAR,
+ mode: "all",
+ showFatal: true,
+ showSerious: true,
+ terrain: true,
+ selectedLocation: null,
+ locationRadius: null,
+ hotspots: [],
+ hotspotIndex: -1,
+ hotspotSignature: "",
+ navigationFeatures: [],
+};
+
+const elements = {
+ dataStatus: document.querySelector("#data-status"),
+ loading: document.querySelector("#loading-screen"),
+ loadingDetail: document.querySelector("#loading-detail"),
+ yearRange: document.querySelector("#year-range"),
+ yearOutput: document.querySelector("#year-output"),
+ statCrashes: document.querySelector("#stat-crashes"),
+ statLives: document.querySelector("#stat-lives"),
+ statInjuries: document.querySelector("#stat-injuries"),
+ showFatal: document.querySelector("#show-fatal"),
+ showSerious: document.querySelector("#show-serious"),
+ detailCard: document.querySelector("#detail-card"),
+ controls: document.querySelector("#controls"),
+ mobileToggle: document.querySelector("#mobile-toggle"),
+ aboutPanel: document.querySelector("#about-panel"),
+ placeSearch: document.querySelector("#place-search"),
+ placeQuery: document.querySelector("#place-query"),
+ searchResults: document.querySelector("#search-results"),
+ locationCard: document.querySelector("#location-card"),
+ pinPrompt: document.querySelector("#pin-prompt"),
+ pinConfirm: document.querySelector("#pin-confirm"),
+ hotspotPosition: document.querySelector("#hotspot-position"),
+ hotspotPrev: document.querySelector("#hotspot-prev"),
+ hotspotNext: document.querySelector("#hotspot-next"),
+ randomTarget: document.querySelector("#random-target"),
+};
+
+let searchMarker;
+let candidateMarker;
+let searchTimer;
+let searchAbortController;
+let pinCountdownTimer;
+let pendingPin;
+
+elements.yearRange.min = FIRST_YEAR;
+elements.yearRange.max = CURRENT_YEAR;
+elements.yearRange.value = FIRST_YEAR;
+
+const map = new maplibregl.Map({
+ container: "map",
+ style: "https://tiles.openfreemap.org/styles/dark",
+ ...DEFAULT_VIEW,
+ maxPitch: 72,
+ minZoom: 8,
+ maxZoom: 17,
+ hash: false,
+ attributionControl: false,
+ antialias: true,
+});
+
+map.doubleClickZoom.disable();
+
+map.addControl(new maplibregl.NavigationControl({ visualizePitch: true }), "bottom-right");
+map.addControl(new maplibregl.AttributionControl({ compact: true }), "bottom-right");
+
+map.on("load", async () => {
+ softenBaseMap();
+ addTerrain();
+ addDataLayers();
+ await loadCrashData();
+});
+
+function softenBaseMap() {
+ const style = map.getStyle();
+ style.layers.forEach((layer) => {
+ if (layer.type === "background") map.setPaintProperty(layer.id, "background-color", "#070604");
+ if (layer.type === "symbol" && layer.layout?.["text-field"]) {
+ map.setPaintProperty(layer.id, "text-color", "#ad9270");
+ map.setPaintProperty(layer.id, "text-halo-color", "#070604");
+ map.setPaintProperty(layer.id, "text-halo-width", 1);
+ }
+ if (layer.type === "line") {
+ const id = layer.id.toLowerCase();
+ if (id.includes("road") || id.includes("street") || id.includes("highway")) {
+ map.setPaintProperty(layer.id, "line-color", id.includes("motorway") ? "#74501e" : "#392812");
+ map.setPaintProperty(layer.id, "line-opacity", 0.72);
+ }
+ }
+ });
+ if (typeof map.setFog === "function") {
+ map.setFog({ color: "#070604", "high-color": "#2a1806", "horizon-blend": 0.16, "space-color": "#020201", "star-intensity": 0.14 });
+ }
+}
+
+function addTerrain() {
+ map.addSource("terrain", {
+ type: "raster-dem",
+ tiles: ["https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"],
+ tileSize: 256,
+ encoding: "terrarium",
+ maxzoom: 15,
+ });
+ map.setTerrain({ source: "terrain", exaggeration: 1.65 });
+}
+
+function addDataLayers() {
+ map.addSource("harm-cells", { type: "geojson", data: emptyCollection() });
+ map.addSource("crashes", { type: "geojson", data: emptyCollection() });
+
+ map.addLayer({
+ id: "harm-cell-glow",
+ source: "harm-cells",
+ type: "fill-extrusion",
+ paint: {
+ "fill-extrusion-color": ["interpolate", ["linear"], ["get", "score"], 1, "#ffd36a", 8, "#ff9f1a", 20, "#ff573b"],
+ "fill-extrusion-height": ["interpolate", ["linear"], ["get", "score"], 1, 80, 25, 1350],
+ "fill-extrusion-base": 10,
+ "fill-extrusion-opacity": 0.18,
+ "fill-extrusion-vertical-gradient": true,
+ },
+ });
+
+ map.addLayer({
+ id: "harm-cells",
+ source: "harm-cells",
+ type: "line",
+ paint: {
+ "line-color": ["interpolate", ["linear"], ["get", "score"], 1, "#ffe6a8", 8, "#ffb000", 20, "#ff573b"],
+ "line-width": ["interpolate", ["linear"], ["zoom"], 9, 0.5, 13, 1.4],
+ "line-opacity": 0.72,
+ },
+ });
+
+ map.addLayer({
+ id: "crash-halo",
+ source: "crashes",
+ type: "circle",
+ paint: {
+ "circle-radius": ["interpolate", ["linear"], ["zoom"], 9, 3, 14, 10],
+ "circle-color": ["case", [">", ["to-number", ["get", "death_cnt"]], 0], "#ff573b", "#ffd05a"],
+ "circle-opacity": 0.12,
+ "circle-blur": 0.85,
+ },
+ });
+
+ map.addLayer({
+ id: "crash-points",
+ source: "crashes",
+ type: "circle",
+ paint: {
+ "circle-radius": ["interpolate", ["linear"], ["zoom"], 9, 1.4, 14, 4.5],
+ "circle-color": ["case", [">", ["to-number", ["get", "death_cnt"]], 0], "#ff573b", "#ffd05a"],
+ "circle-stroke-color": "#fff6e8",
+ "circle-stroke-width": ["interpolate", ["linear"], ["zoom"], 10, 0, 14, 0.8],
+ "circle-opacity": 0.92,
+ },
+ });
+
+ map.addLayer({
+ id: "crash-hit-targets",
+ source: "crashes",
+ type: "circle",
+ paint: {
+ "circle-radius": ["interpolate", ["linear"], ["zoom"], 9, 18, 14, 22],
+ "circle-color": "#ffffff",
+ "circle-opacity": 0.001,
+ },
+ });
+
+ map.on("mouseenter", "crash-hit-targets", () => { map.getCanvas().style.cursor = "pointer"; });
+ map.on("mouseleave", "crash-hit-targets", () => { map.getCanvas().style.cursor = "grab"; });
+ map.on("click", "crash-hit-targets", (event) => showCrashDetail(event.features[0]));
+ map.on("click", (event) => {
+ const hits = map.queryRenderedFeatures(event.point, { layers: ["crash-hit-targets"] });
+ if (!hits.length && !elements.detailCard.hidden) closeCrashDetail();
+ });
+ map.on("dblclick", handleMapDoubleClick);
+}
+
+async function loadCrashData() {
+ const fields = [
+ "id", "crash_timestamp_ct", "latitude", "longitude", "crash_sev_id", "death_cnt",
+ "sus_serious_injry_cnt", "units_involved", "rpt_block_num", "rpt_street_name",
+ "rpt_street_sfx", "crash_speed_limit", "pedestrian_death_count",
+ "pedestrian_serious_injury_count", "bicycle_death_count", "bicycle_serious_injury_count",
+ "motorcycle_death_count", "motorcycle_serious_injury_count", "micromobility_death_count",
+ "micromobility_serious_injury_count", "point",
+ ].join(",");
+ const where = `is_deleted=false AND crash_timestamp_ct >= '${FIRST_YEAR}-01-01T00:00:00' AND (crash_sev_id=1 OR crash_sev_id=4) AND point IS NOT NULL`;
+ const params = new URLSearchParams({ "$select": fields, "$where": where, "$limit": "5000", "$order": "crash_timestamp_ct DESC" });
+
+ try {
+ elements.loadingDetail.textContent = "Mapping fatal and serious-injury records";
+ const response = await fetch(`${DATASET_URL}?${params}`);
+ if (!response.ok) throw new Error(`Data request returned ${response.status}`);
+ const data = await response.json();
+ state.features = data.features.filter(isAustinCoordinate);
+ renderData();
+ elements.dataStatus.textContent = `${state.features.length.toLocaleString()} records synced`;
+ window.setTimeout(() => elements.loading.classList.add("done"), 500);
+ } catch (error) {
+ console.error(error);
+ elements.dataStatus.textContent = "Live data unavailable";
+ elements.loadingDetail.textContent = "The City data service did not respond. Please refresh to try again.";
+ elements.loading.querySelector("p").textContent = "Connection interrupted";
+ }
+}
+
+function isAustinCoordinate(feature) {
+ const [lng, lat] = feature.geometry?.coordinates || [];
+ return lng > -98.05 && lng < -97.45 && lat > 30.05 && lat < 30.58;
+}
+
+function renderData() {
+ const scopeFiltered = state.features.filter(matchesFilters);
+ const filtered = state.selectedLocation && state.locationRadius
+ ? scopeFiltered.filter((feature) => distanceMeters(feature.geometry.coordinates, state.selectedLocation.geometry.coordinates) <= state.locationRadius)
+ : scopeFiltered;
+ const scopeCells = buildHexCells(scopeFiltered);
+ const filterSignature = `${state.firstYear}:${state.mode}:${state.showFatal}:${state.showSerious}`;
+ if (filterSignature !== state.hotspotSignature) {
+ state.hotspotIndex = -1;
+ state.hotspotSignature = filterSignature;
+ }
+ state.navigationFeatures = scopeFiltered;
+ state.hotspots = [...scopeCells.features].sort((a, b) => b.properties.score - a.properties.score).slice(0, 20);
+ map.getSource("crashes").setData({ type: "FeatureCollection", features: filtered });
+ map.getSource("harm-cells").setData(filtered === scopeFiltered ? scopeCells : buildHexCells(filtered));
+
+ const totals = filtered.reduce((sum, feature) => {
+ sum.deaths += number(feature.properties.death_cnt);
+ sum.injuries += number(feature.properties.sus_serious_injry_cnt);
+ return sum;
+ }, { deaths: 0, injuries: 0 });
+
+ animateNumber(elements.statCrashes, filtered.length);
+ animateNumber(elements.statLives, totals.deaths);
+ animateNumber(elements.statInjuries, totals.injuries);
+ elements.yearOutput.textContent = `${state.firstYear} to present`;
+ updateLocationCard(scopeFiltered, filtered);
+ updateDiscoveryControls();
+}
+
+function matchesFilters(feature) {
+ const p = feature.properties;
+ const year = new Date(p.crash_timestamp_ct).getFullYear();
+ const isFatal = number(p.death_cnt) > 0 || number(p.crash_sev_id) === 4;
+ const severityMatches = (isFatal && state.showFatal) || (!isFatal && state.showSerious);
+ if (year < state.firstYear || !severityMatches) return false;
+ if (state.mode === "walking") return number(p.pedestrian_death_count) + number(p.pedestrian_serious_injury_count) > 0;
+ if (state.mode === "bicycle") return number(p.bicycle_death_count) + number(p.bicycle_serious_injury_count) > 0;
+ if (state.mode === "motorcycle") return number(p.motorcycle_death_count) + number(p.motorcycle_serious_injury_count) > 0;
+ return true;
+}
+
+function buildHexCells(features) {
+ const radius = 0.0062;
+ const vertical = radius * Math.sqrt(3);
+ const cells = new Map();
+
+ features.forEach((feature) => {
+ const [lng, lat] = feature.geometry.coordinates;
+ const row = Math.round((lat - 30.05) / vertical);
+ const offset = row % 2 ? radius * 0.75 : 0;
+ const column = Math.round((lng + 98.05 - offset) / (radius * 1.5));
+ const key = `${column}:${row}`;
+ const score = Math.max(1, number(feature.properties.death_cnt) * 4 + number(feature.properties.sus_serious_injry_cnt));
+ const existing = cells.get(key) || { lng: column * radius * 1.5 - 98.05 + offset, lat: row * vertical + 30.05, score: 0, crashes: 0 };
+ existing.score += score;
+ existing.crashes += 1;
+ cells.set(key, existing);
+ });
+
+ return {
+ type: "FeatureCollection",
+ features: [...cells.values()].map((cell) => ({
+ type: "Feature",
+ properties: { score: cell.score, crashes: cell.crashes, lng: cell.lng, lat: cell.lat },
+ geometry: { type: "Polygon", coordinates: [hexagon(cell.lng, cell.lat, radius * 0.83)] },
+ })),
+ };
+}
+
+function hexagon(lng, lat, radius) {
+ const points = [];
+ for (let i = 0; i < 6; i += 1) {
+ const angle = (Math.PI / 180) * (60 * i + 30);
+ points.push([lng + radius * Math.cos(angle), lat + radius * Math.sin(angle) * 0.86]);
+ }
+ points.push(points[0]);
+ return points;
+}
+
+function showCrashDetail(feature) {
+ setExploreOpen(false);
+ closeSearchResults();
+ if (!elements.aboutPanel.hidden) toggleAbout(false);
+ if (!elements.pinPrompt.hidden) dismissPinPrompt(true, false);
+ const p = feature.properties;
+ const date = new Date(p.crash_timestamp_ct);
+ const deaths = number(p.death_cnt);
+ const injuries = number(p.sus_serious_injry_cnt);
+ const address = [p.rpt_block_num, p.rpt_street_name, p.rpt_street_sfx].filter(Boolean).join(" ");
+ document.querySelector("#detail-severity").textContent = deaths ? "Fatal crash" : "Serious-injury crash";
+ document.querySelector("#detail-severity").style.color = deaths ? "var(--coral)" : "var(--amber)";
+ document.querySelector("#detail-location").textContent = address || "Location recorded in Austin";
+ document.querySelector("#detail-date").textContent = date.toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
+ document.querySelector("#detail-harm").textContent = [deaths ? `${deaths} ${deaths === 1 ? "death" : "deaths"}` : "", injuries ? `${injuries} serious ${injuries === 1 ? "injury" : "injuries"}` : ""].filter(Boolean).join(", ") || "Not specified";
+ document.querySelector("#detail-speed").textContent = number(p.crash_speed_limit) ? `${p.crash_speed_limit} mph` : "Not recorded";
+ document.querySelector("#detail-mode").textContent = p.units_involved || "Not recorded";
+ document.querySelector("#detail-source").href = `${SOURCE_PAGE}/${p.id}`;
+ elements.locationCard.hidden = true;
+ elements.detailCard.hidden = false;
+}
+
+function closeCrashDetail() {
+ elements.detailCard.hidden = true;
+ if (state.selectedLocation && elements.aboutPanel.hidden && elements.pinPrompt.hidden && !elements.controls.classList.contains("open")) {
+ elements.locationCard.hidden = false;
+ }
+}
+
+function updateLocationCard(scopeFeatures, visibleFeatures) {
+ if (!state.selectedLocation || !state.locationRadius) {
+ elements.locationCard.hidden = true;
+ return;
+ }
+ const properties = state.selectedLocation.properties || {};
+ const isNearby = state.locationRadius === NEARBY_RADIUS_METERS;
+ const nearbyCount = scopeFeatures.filter((feature) => distanceMeters(feature.geometry.coordinates, state.selectedLocation.geometry.coordinates) <= NEARBY_RADIUS_METERS).length;
+ const totals = visibleFeatures.reduce((sum, feature) => {
+ sum.deaths += number(feature.properties.death_cnt);
+ sum.injuries += number(feature.properties.sus_serious_injry_cnt);
+ return sum;
+ }, { deaths: 0, injuries: 0 });
+ document.querySelector("#location-scope").textContent = isNearby ? "Near this location" : "At this location";
+ document.querySelector("#location-name").textContent = placeName(properties);
+ document.querySelector("#location-context").textContent = placeContext(properties);
+ document.querySelector("#location-crashes").textContent = visibleFeatures.length.toLocaleString();
+ document.querySelector("#location-deaths").textContent = totals.deaths.toLocaleString();
+ document.querySelector("#location-injuries").textContent = totals.injuries.toLocaleString();
+ document.querySelector("#location-note").textContent = isNearby
+ ? "Showing records within 1 kilometer of this point. Current year, mode, and severity filters still apply."
+ : visibleFeatures.length
+ ? "Showing records located within 80 meters of this address. Current filters still apply."
+ : "No severe crashes match within 80 meters. Widen the view to inspect the surrounding area.";
+ document.querySelector("#show-nearby").textContent = `Show ${nearbyCount.toLocaleString()} accidents near location`;
+ document.querySelector("#show-nearby").hidden = isNearby;
+ document.querySelector("#show-address").textContent = properties.name === "Top harm concentration" ? "Narrow to this point" : "Return to this address";
+ document.querySelector("#show-address").hidden = !isNearby;
+ elements.locationCard.hidden = false;
+ elements.detailCard.hidden = true;
+}
+
+function placeName(properties = {}) {
+ const streetAddress = properties.housenumber && properties.street ? `${properties.housenumber} ${properties.street}` : "";
+ return streetAddress || properties.name || properties.street || properties.district || "Selected Austin location";
+}
+
+function placeContext(properties = {}) {
+ return [properties.street, properties.city || "Austin", properties.state || "Texas"]
+ .filter((value, index, values) => value && value !== placeName(properties) && values.indexOf(value) === index)
+ .join(", ") || "Austin, Texas";
+}
+
+function distanceMeters([lngA, latA], [lngB, latB]) {
+ const toRadians = (degrees) => degrees * Math.PI / 180;
+ const earthRadius = 6371000;
+ const latDelta = toRadians(latB - latA);
+ const lngDelta = toRadians(lngB - lngA);
+ const a = Math.sin(latDelta / 2) ** 2
+ + Math.cos(toRadians(latA)) * Math.cos(toRadians(latB)) * Math.sin(lngDelta / 2) ** 2;
+ return earthRadius * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+}
+
+function updateDiscoveryControls() {
+ const ready = state.hotspots.length > 0 && state.navigationFeatures.length > 0;
+ elements.hotspotPrev.disabled = !ready;
+ elements.hotspotNext.disabled = !ready;
+ elements.randomTarget.disabled = !ready;
+ if (!ready) {
+ elements.hotspotPosition.textContent = "No harm sites";
+ } else if (state.hotspotIndex >= 0) {
+ elements.hotspotPosition.textContent = `Top ${String(state.hotspotIndex + 1).padStart(2, "0")} / ${state.hotspots.length}`;
+ } else {
+ elements.hotspotPosition.textContent = "Top harm sites";
+ }
+}
+
+function navigateHotspot(direction) {
+ if (!state.hotspots.length) return;
+ if (state.hotspotIndex < 0) state.hotspotIndex = direction > 0 ? 0 : state.hotspots.length - 1;
+ else state.hotspotIndex = (state.hotspotIndex + direction + state.hotspots.length) % state.hotspots.length;
+ const hotspot = state.hotspots[state.hotspotIndex];
+ const coordinates = [number(hotspot.properties.lng), number(hotspot.properties.lat)];
+ const nearest = nearestCrash(coordinates, state.navigationFeatures);
+ const street = nearest ? crashAddress(nearest.properties) : "Austin street network";
+ const feature = {
+ type: "Feature",
+ geometry: { type: "Point", coordinates },
+ properties: { name: "Top harm concentration", street, city: "Austin", state: "Texas" },
+ };
+ selectPlace(feature, NEARBY_RADIUS_METERS, 13.35);
+ updateDiscoveryControls();
+}
+
+function targetRandomCrash() {
+ if (!state.navigationFeatures.length) return;
+ const randomIndex = Math.floor(Math.random() * state.navigationFeatures.length);
+ const crash = state.navigationFeatures[randomIndex];
+ const feature = {
+ type: "Feature",
+ geometry: crash.geometry,
+ properties: {
+ name: "Random crash target",
+ street: crashAddress(crash.properties),
+ city: "Austin",
+ state: "Texas",
+ },
+ };
+ state.hotspotIndex = -1;
+ selectPlace(feature, ADDRESS_RADIUS_METERS, 15.3);
+ elements.hotspotPosition.textContent = "Random target";
+}
+
+function nearestCrash(coordinates, features) {
+ return features.reduce((nearest, feature) => {
+ const distance = distanceMeters(coordinates, feature.geometry.coordinates);
+ return !nearest || distance < nearest.distance ? { feature, distance } : nearest;
+ }, null)?.feature;
+}
+
+function crashAddress(properties = {}) {
+ const address = [properties.rpt_block_num, properties.rpt_street_name, properties.rpt_street_sfx].filter(Boolean).join(" ");
+ return address && !address.toLowerCase().includes("not reported") ? address : "Recorded Austin location";
+}
+
+function number(value) { return Number(value) || 0; }
+function emptyCollection() { return { type: "FeatureCollection", features: [] }; }
+
+function animateNumber(element, value) {
+ const start = Number(element.textContent.replace(/\D/g, "")) || 0;
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
+ element.textContent = value.toLocaleString();
+ return;
+ }
+ const started = performance.now();
+ const duration = 350;
+ function frame(now) {
+ const progress = Math.min(1, (now - started) / duration);
+ const eased = 1 - Math.pow(1 - progress, 3);
+ element.textContent = Math.round(start + (value - start) * eased).toLocaleString();
+ if (progress < 1) requestAnimationFrame(frame);
+ }
+ requestAnimationFrame(frame);
+}
+
+elements.yearRange.addEventListener("input", (event) => {
+ state.firstYear = Number(event.target.value);
+ renderData();
+});
+
+document.querySelectorAll("#mode-filter button").forEach((button) => {
+ button.addEventListener("click", () => {
+ document.querySelectorAll("#mode-filter button").forEach((item) => {
+ item.classList.toggle("active", item === button);
+ item.setAttribute("aria-pressed", String(item === button));
+ });
+ state.mode = button.dataset.mode;
+ renderData();
+ });
+});
+
+elements.showFatal.addEventListener("change", () => {
+ state.showFatal = elements.showFatal.checked;
+ if (!state.showFatal && !state.showSerious) {
+ elements.showSerious.checked = true;
+ state.showSerious = true;
+ }
+ renderData();
+});
+
+elements.showSerious.addEventListener("change", () => {
+ state.showSerious = elements.showSerious.checked;
+ if (!state.showFatal && !state.showSerious) {
+ elements.showFatal.checked = true;
+ state.showFatal = true;
+ }
+ renderData();
+});
+
+document.querySelector("#reset-view").addEventListener("click", () => map.flyTo({ ...DEFAULT_VIEW, duration: 900, essential: true }));
+document.querySelector("#toggle-terrain").addEventListener("click", (event) => {
+ state.terrain = !state.terrain;
+ map.setTerrain(state.terrain ? { source: "terrain", exaggeration: 1.65 } : null);
+ event.currentTarget.classList.toggle("active", state.terrain);
+ event.currentTarget.setAttribute("aria-pressed", String(state.terrain));
+ event.currentTarget.lastChild.textContent = state.terrain ? " Terrain on" : " Terrain off";
+});
+
+document.querySelector("#detail-close").addEventListener("click", closeCrashDetail);
+
+document.querySelector("#show-nearby").addEventListener("click", () => {
+ state.locationRadius = NEARBY_RADIUS_METERS;
+ renderData();
+ map.flyTo({ center: state.selectedLocation.geometry.coordinates, zoom: 13.35, pitch: 57, duration: 700, essential: true });
+});
+
+document.querySelector("#show-address").addEventListener("click", () => {
+ state.locationRadius = ADDRESS_RADIUS_METERS;
+ renderData();
+ map.flyTo({ center: state.selectedLocation.geometry.coordinates, zoom: 15.3, pitch: 62, duration: 700, essential: true });
+});
+
+document.querySelector("#location-close").addEventListener("click", clearSelectedLocation);
+
+elements.hotspotPrev.addEventListener("click", () => navigateHotspot(-1));
+elements.hotspotNext.addEventListener("click", () => navigateHotspot(1));
+elements.randomTarget.addEventListener("click", targetRandomCrash);
+
+function setExploreOpen(open) {
+ if (open) {
+ closeSearchResults();
+ elements.detailCard.hidden = true;
+ elements.locationCard.hidden = true;
+ if (!elements.aboutPanel.hidden) toggleAbout(false);
+ if (!elements.pinPrompt.hidden) dismissPinPrompt(true, false);
+ }
+ elements.controls.classList.toggle("open", open);
+ elements.mobileToggle.setAttribute("aria-expanded", String(open));
+ elements.mobileToggle.querySelector("span").textContent = "Explore data";
+}
+
+elements.mobileToggle.addEventListener("click", () => setExploreOpen(!elements.controls.classList.contains("open")));
+document.querySelector("#controls-close").addEventListener("click", () => setExploreOpen(false));
+
+function toggleAbout(open) {
+ if (open) {
+ setExploreOpen(false);
+ closeSearchResults();
+ elements.detailCard.hidden = true;
+ elements.locationCard.hidden = true;
+ if (!elements.pinPrompt.hidden) dismissPinPrompt(true, false);
+ }
+ elements.aboutPanel.hidden = !open;
+ document.querySelector("#about-toggle").setAttribute("aria-expanded", String(open));
+ if (open) document.querySelector("#about-close").focus();
+}
+
+document.querySelector("#about-toggle").addEventListener("click", () => toggleAbout(elements.aboutPanel.hidden));
+document.querySelector("#about-close").addEventListener("click", () => toggleAbout(false));
+
+elements.placeSearch.addEventListener("submit", async (event) => {
+ event.preventDefault();
+ await searchPlaces(elements.placeQuery.value, true);
+});
+
+elements.placeQuery.addEventListener("input", () => {
+ window.clearTimeout(searchTimer);
+ const query = elements.placeQuery.value.trim();
+ if (query.length < 3) {
+ closeSearchResults();
+ return;
+ }
+ searchTimer = window.setTimeout(() => searchPlaces(query, false), 260);
+});
+
+elements.placeQuery.addEventListener("keydown", (event) => {
+ if (event.key === "ArrowDown") {
+ const first = elements.searchResults.querySelector("button");
+ if (first) {
+ event.preventDefault();
+ first.focus();
+ }
+ }
+});
+
+document.addEventListener("click", (event) => {
+ if (!elements.placeSearch.contains(event.target)) closeSearchResults();
+});
+
+async function searchPlaces(rawQuery, selectFirst) {
+ const query = rawQuery.trim();
+ if (query.length < 2) return;
+ setExploreOpen(false);
+ elements.detailCard.hidden = true;
+ elements.locationCard.hidden = true;
+ if (!elements.aboutPanel.hidden) toggleAbout(false);
+ if (!elements.pinPrompt.hidden) dismissPinPrompt(true, false);
+ if (searchAbortController) searchAbortController.abort();
+ searchAbortController = new AbortController();
+ elements.searchResults.hidden = false;
+ elements.searchResults.replaceChildren(makeStatusItem("Searching Austin..."));
+ elements.placeQuery.setAttribute("aria-expanded", "true");
+
+ try {
+ const params = new URLSearchParams({
+ q: `${query}, Austin, Texas`,
+ limit: "6",
+ bbox: "-98.05,30.05,-97.45,30.58",
+ lang: "en",
+ });
+ const response = await fetch(`https://photon.komoot.io/api/?${params}`, { signal: searchAbortController.signal });
+ if (!response.ok) throw new Error(`Location search returned ${response.status}`);
+ const data = await response.json();
+ const results = data.features.filter(isAustinCoordinate).slice(0, 6);
+ if (selectFirst && results[0]) {
+ selectPlace(results[0]);
+ return;
+ }
+ renderSearchResults(results);
+ } catch (error) {
+ if (error.name === "AbortError") return;
+ console.error(error);
+ const localResults = findCrashStreets(query);
+ if (selectFirst && localResults[0]) selectPlace(localResults[0]);
+ else renderSearchResults(localResults, "Location service unavailable. Showing crash streets.");
+ }
+}
+
+function findCrashStreets(query) {
+ const needle = query.toLowerCase();
+ const seen = new Set();
+ return state.features.filter((feature) => {
+ const street = [feature.properties.rpt_street_name, feature.properties.rpt_street_sfx].filter(Boolean).join(" ");
+ if (!street.toLowerCase().includes(needle) || seen.has(street)) return false;
+ seen.add(street);
+ feature.properties.name = street;
+ feature.properties.city = "Austin";
+ feature.properties.state = "Texas";
+ return true;
+ }).slice(0, 6);
+}
+
+function renderSearchResults(results, note = "") {
+ elements.searchResults.replaceChildren();
+ if (note) elements.searchResults.append(makeStatusItem(note));
+ if (!results.length) {
+ elements.searchResults.append(makeStatusItem("No Austin location found. Try a street, park, or landmark."));
+ return;
+ }
+ results.forEach((feature) => {
+ const properties = feature.properties || {};
+ const name = properties.name || properties.street || properties.district || "Austin location";
+ const context = [properties.street, properties.city, properties.state].filter((value, index, values) => value && value !== name && values.indexOf(value) === index).join(", ");
+ const item = document.createElement("li");
+ const button = document.createElement("button");
+ const strong = document.createElement("strong");
+ const span = document.createElement("span");
+ button.type = "button";
+ strong.textContent = name;
+ span.textContent = context || "Austin, Texas";
+ button.append(strong, span);
+ button.addEventListener("click", () => selectPlace(feature));
+ button.addEventListener("keydown", (event) => {
+ if (event.key === "ArrowDown") item.nextElementSibling?.querySelector("button")?.focus();
+ if (event.key === "ArrowUp") (item.previousElementSibling?.querySelector("button") || elements.placeQuery).focus();
+ });
+ item.append(button);
+ elements.searchResults.append(item);
+ });
+}
+
+function makeStatusItem(text) {
+ const item = document.createElement("li");
+ item.className = "search-empty";
+ item.textContent = text;
+ return item;
+}
+
+function selectPlace(feature, initialRadius = ADDRESS_RADIUS_METERS, zoom = 15.3) {
+ const coordinates = feature.geometry.coordinates;
+ const name = placeName(feature.properties);
+ setExploreOpen(false);
+ elements.detailCard.hidden = true;
+ if (!elements.aboutPanel.hidden) toggleAbout(false);
+ elements.placeQuery.value = name;
+ closeSearchResults();
+ if (searchMarker) searchMarker.remove();
+ if (candidateMarker) {
+ candidateMarker.remove();
+ candidateMarker = null;
+ }
+ const markerElement = document.createElement("div");
+ markerElement.style.cssText = "width:18px;height:18px;border:2px solid #ffe0a3;border-radius:2px;background:#070604;box-shadow:0 0 0 6px rgba(255,176,0,.18),0 0 24px #ffb000;transform:rotate(45deg)";
+ searchMarker = new maplibregl.Marker({ element: markerElement }).setLngLat(coordinates).addTo(map);
+ state.selectedLocation = feature;
+ state.locationRadius = initialRadius;
+ renderData();
+ map.flyTo({ center: coordinates, zoom, pitch: 62, bearing: -12, duration: 1100, essential: true });
+}
+
+function clearSelectedLocation() {
+ state.selectedLocation = null;
+ state.locationRadius = null;
+ elements.locationCard.hidden = true;
+ elements.detailCard.hidden = true;
+ elements.placeQuery.value = "";
+ if (searchMarker) {
+ searchMarker.remove();
+ searchMarker = null;
+ }
+ renderData();
+}
+
+function closeSearchResults() {
+ elements.searchResults.hidden = true;
+ elements.placeQuery.setAttribute("aria-expanded", "false");
+}
+
+async function handleMapDoubleClick(event) {
+ event.originalEvent.preventDefault();
+ setExploreOpen(false);
+ closeSearchResults();
+ elements.detailCard.hidden = true;
+ elements.locationCard.hidden = true;
+ if (!elements.aboutPanel.hidden) toggleAbout(false);
+ const coordinates = [event.lngLat.lng, event.lngLat.lat];
+ if (candidateMarker) candidateMarker.remove();
+ const markerElement = document.createElement("div");
+ markerElement.style.cssText = "width:20px;height:20px;border:1px solid #ffb000;background:rgba(7,6,4,.78);box-shadow:0 0 0 8px rgba(255,176,0,.12),0 0 28px #ffb000;transform:rotate(45deg)";
+ candidateMarker = new maplibregl.Marker({ element: markerElement }).setLngLat(coordinates).addTo(map);
+ pendingPin = {
+ type: "Feature",
+ geometry: { type: "Point", coordinates },
+ properties: { name: "Selected map point", city: "Austin", state: "Texas" },
+ };
+ window.clearInterval(pinCountdownTimer);
+ elements.pinPrompt.hidden = false;
+ elements.pinConfirm.disabled = true;
+ document.querySelector("#pin-prompt-label").textContent = "Locating this point";
+ document.querySelector("#pin-prompt-context").textContent = `${coordinates[1].toFixed(5)}, ${coordinates[0].toFixed(5)}`;
+ document.querySelector("#pin-countdown").textContent = "...";
+
+ try {
+ const params = new URLSearchParams({ lon: coordinates[0], lat: coordinates[1], lang: "en" });
+ const response = await fetch(`https://photon.komoot.io/reverse?${params}`);
+ if (!response.ok) throw new Error(`Reverse location search returned ${response.status}`);
+ const data = await response.json();
+ const result = data.features?.[0];
+ if (result) pendingPin.properties = result.properties || pendingPin.properties;
+ } catch (error) {
+ console.error(error);
+ }
+
+ document.querySelector("#pin-prompt-label").textContent = placeName(pendingPin.properties);
+ document.querySelector("#pin-prompt-context").textContent = placeContext(pendingPin.properties);
+ elements.pinConfirm.disabled = false;
+ startPinCountdown();
+}
+
+function startPinCountdown() {
+ let seconds = 5;
+ const countdown = document.querySelector("#pin-countdown");
+ countdown.textContent = seconds;
+ countdown.setAttribute("aria-label", `Closes in ${seconds} seconds`);
+ window.clearInterval(pinCountdownTimer);
+ pinCountdownTimer = window.setInterval(() => {
+ seconds -= 1;
+ countdown.textContent = seconds;
+ countdown.setAttribute("aria-label", `Closes in ${seconds} seconds`);
+ if (seconds <= 0) dismissPinPrompt();
+ }, 1000);
+}
+
+function dismissPinPrompt(removeCandidate = true, restoreLocation = true) {
+ window.clearInterval(pinCountdownTimer);
+ elements.pinPrompt.hidden = true;
+ if (removeCandidate && candidateMarker) {
+ candidateMarker.remove();
+ candidateMarker = null;
+ }
+ if (removeCandidate) pendingPin = null;
+ if (restoreLocation && state.selectedLocation && elements.detailCard.hidden && elements.aboutPanel.hidden && !elements.controls.classList.contains("open")) {
+ elements.locationCard.hidden = false;
+ }
+}
+
+elements.pinConfirm.addEventListener("click", () => {
+ if (!pendingPin) return;
+ const selectedPin = pendingPin;
+ dismissPinPrompt(false);
+ selectPlace(selectedPin);
+ pendingPin = null;
+});
+
+document.addEventListener("keydown", (event) => {
+ if (event.key === "Escape") {
+ elements.detailCard.hidden = true;
+ if (!elements.pinPrompt.hidden) dismissPinPrompt();
+ if (!elements.aboutPanel.hidden) toggleAbout(false);
+ setExploreOpen(false);
+ }
+});
diff --git a/accispace/favicon.svg b/accispace/favicon.svg
new file mode 100644
index 0000000..4a5d8d5
--- /dev/null
+++ b/accispace/favicon.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/accispace/index.html b/accispace/index.html
new file mode 100644
index 0000000..c47c49e
--- /dev/null
+++ b/accispace/index.html
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+
+
+
+ ACCI | Austin Crash Context Interface
+
+
+
+
+
+
+
+
+ Skip to controls
+
+
+
+
+
+
+
+
+
+
+ Close
+
+
+
+
A public-safety lens
+
The street remembers.
+
+ Each column gathers nearby fatal and serious-injury crashes. Height reflects the human cost recorded at that place.
+
+
+
+
+
+ ...
+ severe crashes
+
+
+ ...
+ lives lost
+
+
+ ...
+ serious injuries
+
+
+
+
+
+
+ People traveling by
+
+ All
+ Walk
+ Bike
+ Moto
+
+
+
+
+ Show
+
+
+
+ Fatal crashes
+
+
+
+
+ Serious-injury crashes
+
+
+
+
+
+
+ Reset view
+
+
+
+ Terrain on
+
+
+
+ ↗ Drag to orbit. Scroll or pinch to zoom. Select a point for context.
+
+
+
+ ×
+ Crash record
+ Austin, Texas
+
+
Date
+
People harmed
+
Posted speed
+
Units involved
+
+ View source record ↗
+
+
+
+ ×
+ At this location
+ Selected Austin location
+ Austin, Texas
+
+
Severe crashes 0
+
Lives lost 0
+
Serious injuries 0
+
+ Crash locations within 80 meters of this point.
+
+ Show accidents near location
+ Return to this address
+
+
+
+
+
+
+
Locating this point
+
Double-click selection
+
+
Search this pin
+
5
+
+
+
+ LOWER HARM
+
+ HIGHER HARM
+
+
+
+ About this view
+ City of Austin Vision Zero data
+
+
+
+ ×
+ How to read ACCI
+ A map is a question, not a verdict.
+
+
+
What you are seeing
+
+ Crash records from the City of Austin Vision Zero crash-level dataset. ACCI includes crashes coded as fatal or suspected serious injury, within the selected years. Columns combine records in nearby map cells. Their height weights a death more heavily than a serious injury.
+
+
+
+
What the data cannot say
+
+ Reports can be delayed, revised, incomplete, or imprecisely located. A concentration shows where harm was recorded, not why it happened or who is at fault. Recent totals are especially likely to change.
+
+
+
+
Why this exists
+
+ Safety data can feel abstract in a spreadsheet. This experimental view makes spatial patterns legible while keeping individual records available for inspection.
+
+
+
+
+
+
+
+
+
Reading Austin's street-safety record
+
Opening the public dataset
+
+
+
+
+
+
+
diff --git a/accispace/netlify.toml b/accispace/netlify.toml
new file mode 100644
index 0000000..dd70fbe
--- /dev/null
+++ b/accispace/netlify.toml
@@ -0,0 +1,20 @@
+[build]
+ publish = "."
+
+[[headers]]
+ for = "/*"
+ [headers.values]
+ X-Frame-Options = "DENY"
+ X-Content-Type-Options = "nosniff"
+ Referrer-Policy = "strict-origin-when-cross-origin"
+ Permissions-Policy = "camera=(), microphone=(), geolocation=()"
+
+[[headers]]
+ for = "/*.css"
+ [headers.values]
+ Cache-Control = "public, max-age=0, must-revalidate"
+
+[[headers]]
+ for = "/*.js"
+ [headers.values]
+ Cache-Control = "public, max-age=0, must-revalidate"
diff --git a/accispace/style.css b/accispace/style.css
new file mode 100644
index 0000000..7145c21
--- /dev/null
+++ b/accispace/style.css
@@ -0,0 +1,464 @@
+:root {
+ color-scheme: dark;
+ --bg: #070604;
+ --panel: rgba(13, 10, 6, 0.94);
+ --panel-soft: rgba(24, 17, 8, 0.86);
+ --line: rgba(255, 194, 82, 0.2);
+ --line-strong: rgba(255, 194, 82, 0.5);
+ --text: #fff8e9;
+ --muted: #c6bca8;
+ --faint: #8f8675;
+ --mint: #ffb000;
+ --mint-bright: #ffe0a3;
+ --amber: #ffd05a;
+ --coral: #ff573b;
+ --font-sans: "Inter", system-ui, sans-serif;
+ --font-mono: "JetBrains Mono", ui-monospace, monospace;
+}
+
+* { box-sizing: border-box; }
+
+html, body { height: 100%; margin: 0; overflow: hidden; }
+
+body {
+ background: var(--bg);
+ color: var(--text);
+ font-family: var(--font-sans);
+ -webkit-font-smoothing: antialiased;
+}
+
+button, input { font: inherit; }
+button, a { -webkit-tap-highlight-color: transparent; }
+
+button:focus-visible, a:focus-visible, input:focus-visible {
+ outline: 2px solid var(--mint-bright);
+ outline-offset: 3px;
+}
+
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+.skip-link {
+ position: fixed;
+ z-index: 1000;
+ top: 0.75rem;
+ left: 0.75rem;
+ padding: 0.7rem 1rem;
+ border-radius: 999px;
+ background: var(--mint-bright);
+ color: #070604;
+ font-weight: 700;
+ transform: translateY(-180%);
+ transition: transform 150ms ease;
+}
+
+.skip-link:focus { transform: translateY(0); }
+
+.app-shell, #map { position: fixed; inset: 0; }
+
+#map { background: radial-gradient(circle at 60% 45%, #2a1806, var(--bg) 58%); }
+
+.scan-lines, .map-vignette {
+ position: fixed;
+ inset: 0;
+ pointer-events: none;
+ z-index: 2;
+}
+
+.scan-lines {
+ opacity: 0.08;
+ background-image: repeating-linear-gradient(to bottom, transparent 0, transparent 3px, rgba(255, 190, 69, 0.15) 4px);
+ background-size: 100% 4px;
+}
+
+.map-vignette {
+ background: radial-gradient(circle at 60% 48%, transparent 25%, rgba(7, 4, 1, 0.2) 62%, rgba(3, 2, 1, 0.82) 100%);
+}
+
+.topbar {
+ position: fixed;
+ z-index: 10;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 76px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 1rem;
+ padding: 0 1.5rem;
+ border-bottom: 1px solid var(--line);
+ background: linear-gradient(to bottom, rgba(9, 7, 4, 0.96), rgba(9, 7, 4, 0.76));
+ backdrop-filter: blur(14px);
+}
+
+.brand { display: flex; align-items: center; gap: 0.8rem; color: var(--text); text-decoration: none; }
+.brand__mark { width: 40px; height: 40px; color: var(--mint); }
+.brand__mark svg { width: 100%; height: 100%; stroke: currentColor; stroke-width: 1.25; }
+.brand strong { display: block; font-size: 1.02rem; letter-spacing: 0.18em; }
+.brand small { display: block; margin-top: 0.2rem; color: var(--muted); font: 0.61rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; }
+
+.topbar__status {
+ display: flex;
+ align-items: center;
+ gap: 0.55rem;
+ color: var(--muted);
+ font: 0.67rem/1 var(--font-mono);
+ letter-spacing: 0.04em;
+ text-transform: uppercase;
+}
+
+.topbar__tools { display: flex; align-items: center; gap: 1rem; margin-left: auto; }
+.hotspot-nav { display: flex; align-items: center; height: 42px; overflow: hidden; border: 1px solid var(--line); border-radius: 2px; background: rgba(12, 9, 5, 0.86); }
+.hotspot-nav button { height: 100%; min-width: 40px; display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem; padding: 0 0.65rem; border: 0; border-left: 1px solid var(--line); background: transparent; color: var(--muted); cursor: pointer; }
+.hotspot-nav button:first-child { border-left: 0; }
+.hotspot-nav button:hover:not(:disabled) { background: rgba(255, 176, 0, 0.1); color: var(--mint-bright); }
+.hotspot-nav button:disabled { cursor: wait; opacity: 0.35; }
+.hotspot-nav svg { width: 17px; height: 17px; flex: 0 0 auto; stroke: currentColor; stroke-width: 1.5; }
+.hotspot-nav__rank { min-width: 122px !important; justify-content: space-between !important; }
+.hotspot-nav__rank span { color: var(--mint-bright); font: 0.57rem/1 var(--font-mono); text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }
+
+.place-search {
+ position: absolute;
+ left: 50%;
+ top: 15px;
+ width: min(380px, 32vw);
+ height: 46px;
+ display: flex;
+ align-items: center;
+ gap: 0.55rem;
+ padding: 0 0.35rem 0 0.85rem;
+ border: 1px solid var(--line);
+ border-radius: 999px;
+ background: rgba(12, 9, 5, 0.9);
+ transform: translateX(-50%);
+}
+
+.place-search:focus-within { border-color: var(--line-strong); box-shadow: 0 0 0 3px rgba(255, 176, 0, 0.09); }
+.place-search > svg { width: 17px; flex: 0 0 auto; stroke: var(--muted); stroke-width: 1.6; }
+.place-search input { min-width: 0; flex: 1; border: 0; outline: 0; background: transparent; color: var(--text); font-size: 0.72rem; }
+.place-search input::placeholder { color: var(--faint); }
+.place-search > button { min-width: 54px; height: 34px; border: 0; border-radius: 2px; background: rgba(255, 176, 0, 0.14); color: var(--mint-bright); font-size: 0.62rem; font-weight: 600; cursor: pointer; }
+.place-search > button:hover { background: rgba(255, 176, 0, 0.24); }
+
+.search-results {
+ position: absolute;
+ z-index: 20;
+ top: calc(100% + 0.5rem);
+ left: 0;
+ right: 0;
+ max-height: 300px;
+ overflow: auto;
+ margin: 0;
+ padding: 0.4rem;
+ list-style: none;
+ border: 1px solid var(--line-strong);
+ border-radius: 2px;
+ background: #120d06;
+ box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
+}
+.search-results[hidden] { display: none; }
+.search-results li { margin: 0; }
+.search-results button { width: 100%; display: block; padding: 0.7rem 0.75rem; border: 0; border-radius: 9px; background: transparent; color: var(--text); text-align: left; cursor: pointer; }
+.search-results button:hover, .search-results button:focus-visible { background: rgba(255, 176, 0, 0.1); }
+.search-results strong { display: block; overflow: hidden; color: var(--text); font-size: 0.7rem; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
+.search-results span { display: block; margin-top: 0.25rem; overflow: hidden; color: var(--faint); font: 0.55rem var(--font-mono); text-overflow: ellipsis; white-space: nowrap; }
+.search-results .search-empty { padding: 0.8rem; color: var(--muted); font-size: 0.66rem; }
+
+.signal {
+ width: 7px;
+ height: 7px;
+ border-radius: 50%;
+ background: var(--mint);
+ box-shadow: 0 0 0 5px rgba(255, 176, 0, 0.1), 0 0 18px var(--mint);
+}
+
+.icon-button, .mobile-toggle {
+ border: 1px solid var(--line-strong);
+ background: rgba(18, 12, 5, 0.85);
+ color: var(--text);
+ border-radius: 999px;
+ min-height: 44px;
+ padding: 0 0.9rem;
+ cursor: pointer;
+}
+
+.mobile-toggle { display: none; align-items: center; gap: 0.5rem; font-size: 0.75rem; font-weight: 600; }
+.mobile-toggle svg { width: 18px; stroke: currentColor; stroke-width: 1.5; }
+
+.control-panel {
+ position: fixed;
+ z-index: 8;
+ left: 1.5rem;
+ top: 100px;
+ bottom: 50px;
+ width: min(330px, calc(100vw - 3rem));
+ display: flex;
+ flex-direction: column;
+ overflow: auto;
+ padding: 1.4rem;
+ border: 1px solid var(--line);
+ border-radius: 2px;
+ background: var(--panel);
+ box-shadow: 10px 12px 0 rgba(0, 0, 0, 0.24), 0 28px 70px rgba(0, 0, 0, 0.42);
+ scrollbar-width: thin;
+ scrollbar-color: var(--line-strong) transparent;
+}
+
+.controls-close { display: none; }
+
+.eyebrow {
+ margin: 0 0 0.65rem;
+ color: var(--mint);
+ font: 600 0.62rem/1.3 var(--font-mono);
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+}
+
+.panel-heading h1 {
+ margin: 0;
+ max-width: 10ch;
+ font-size: clamp(1.8rem, 3vw, 2.55rem);
+ line-height: 0.98;
+ letter-spacing: -0.045em;
+}
+
+.panel-heading > p:last-child { margin: 0.85rem 0 0; color: var(--muted); font-size: 0.78rem; line-height: 1.55; }
+
+.stats {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ margin: 1.35rem 0;
+ padding: 1rem 0;
+ border-top: 1px solid var(--line);
+ border-bottom: 1px solid var(--line);
+}
+
+.stats div + div { border-left: 1px solid var(--line); padding-left: 0.85rem; }
+.stats span { display: block; font: 600 1.22rem/1 var(--font-mono); color: var(--mint-bright); }
+.stats small { display: block; margin-top: 0.42rem; color: var(--faint); font: 0.56rem/1.35 var(--font-mono); text-transform: uppercase; }
+
+.filter-group { margin: 0 0 1.15rem; padding: 0; border: 0; }
+.filter-group legend, .filter-label { width: 100%; margin-bottom: 0.65rem; color: var(--muted); font: 500 0.64rem/1 var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; }
+.filter-label { display: flex; justify-content: space-between; }
+.filter-label output { color: var(--mint); text-transform: none; }
+
+input[type="range"] { width: 100%; height: 18px; margin: 0; accent-color: var(--mint); cursor: pointer; }
+.range-labels { display: flex; justify-content: space-between; color: var(--faint); font: 0.55rem var(--font-mono); }
+
+.segment-control { display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px; padding: 3px; border: 1px solid var(--line); border-radius: 10px; background: rgba(0, 0, 0, 0.18); }
+.segment-control button { min-height: 34px; padding: 0.35rem; border: 0; border-radius: 7px; background: transparent; color: var(--muted); font-size: 0.65rem; cursor: pointer; }
+.segment-control button:hover { color: var(--text); }
+.segment-control button.active { background: rgba(255, 176, 0, 0.14); color: var(--mint-bright); box-shadow: inset 0 0 0 1px rgba(255, 176, 0, 0.18); }
+
+.severity-filter { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
+.severity-filter legend { grid-column: 1 / -1; }
+.severity-filter label { display: flex; align-items: center; gap: 0.45rem; color: var(--muted); font-size: 0.68rem; cursor: pointer; }
+.severity-filter input { position: absolute; opacity: 0; pointer-events: none; }
+.legend-dot { width: 9px; height: 9px; flex: 0 0 auto; border-radius: 50%; box-shadow: 0 0 9px currentColor; }
+.legend-dot--fatal { color: var(--coral); background: var(--coral); }
+.legend-dot--serious { color: var(--amber); background: var(--amber); }
+.severity-filter input:not(:checked) + .legend-dot { background: transparent; box-shadow: inset 0 0 0 1px currentColor; opacity: 0.45; }
+
+.view-actions { display: flex; gap: 0.5rem; margin-top: auto; padding-top: 0.35rem; }
+.text-button { display: inline-flex; align-items: center; gap: 0.4rem; min-height: 40px; padding: 0 0.7rem; border: 1px solid var(--line); border-radius: 999px; background: transparent; color: var(--muted); font-size: 0.65rem; cursor: pointer; }
+.text-button:hover, .text-button.active { border-color: var(--line-strong); color: var(--mint-bright); background: rgba(255, 176, 0, 0.07); }
+.text-button svg { width: 15px; stroke: currentColor; stroke-width: 1.5; }
+.interaction-hint { display: flex; gap: 0.45rem; margin: 0.85rem 0 0; color: var(--faint); font-size: 0.61rem; line-height: 1.45; }
+
+.detail-card {
+ position: fixed;
+ z-index: 9;
+ right: 1.5rem;
+ top: 100px;
+ width: min(320px, calc(100vw - 3rem));
+ padding: 1.35rem;
+ border: 1px solid var(--line-strong);
+ border-radius: 2px;
+ background: var(--panel);
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
+}
+
+.detail-card[hidden] { display: none; }
+.detail-card__close, .about-panel__close { position: absolute; top: 0.8rem; right: 0.9rem; width: 36px; height: 36px; border: 0; background: transparent; color: var(--muted); font-size: 1.5rem; cursor: pointer; }
+.detail-card h2 { max-width: 13ch; margin: 0 0 1rem; font-size: 1.35rem; letter-spacing: -0.025em; }
+.detail-card dl { margin: 0; border-top: 1px solid var(--line); }
+.detail-card dl div { display: grid; grid-template-columns: 0.9fr 1.2fr; gap: 0.75rem; padding: 0.7rem 0; border-bottom: 1px solid var(--line); }
+.detail-card dt { color: var(--faint); font: 0.59rem var(--font-mono); text-transform: uppercase; }
+.detail-card dd { margin: 0; color: var(--text); font-size: 0.7rem; line-height: 1.35; text-align: right; }
+.detail-card a { display: inline-block; margin-top: 1rem; color: var(--mint); font-size: 0.68rem; text-decoration: none; }
+.detail-card a:hover { color: var(--mint-bright); }
+
+.location-card {
+ position: fixed;
+ z-index: 9;
+ right: 1.5rem;
+ top: 100px;
+ width: min(330px, calc(100vw - 3rem));
+ padding: 1.35rem;
+ border: 1px solid var(--line-strong);
+ border-radius: 2px;
+ background: var(--panel);
+ box-shadow: 10px 12px 0 rgba(0, 0, 0, 0.24), 0 24px 60px rgba(0, 0, 0, 0.42);
+}
+
+.location-card[hidden] { display: none; }
+.location-card__close { position: absolute; top: 0.8rem; right: 0.9rem; width: 36px; height: 36px; border: 0; background: transparent; color: var(--muted); font-size: 1.5rem; cursor: pointer; }
+.location-card h2 { max-width: 15ch; margin: 0; font-size: 1.35rem; letter-spacing: -0.025em; }
+.location-card__context { margin: 0.4rem 0 1rem; color: var(--faint); font: 0.57rem/1.4 var(--font-mono); text-transform: uppercase; letter-spacing: 0.04em; }
+.location-summary { display: grid; grid-template-columns: repeat(3, 1fr); margin: 0; padding: 1rem 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
+.location-summary div { padding: 0 0.65rem; }
+.location-summary div:first-child { padding-left: 0; }
+.location-summary div + div { border-left: 1px solid var(--line); }
+.location-summary dt { color: var(--faint); font: 0.52rem/1.35 var(--font-mono); text-transform: uppercase; }
+.location-summary dd { margin: 0.45rem 0 0; color: var(--mint-bright); font: 600 1.15rem/1 var(--font-mono); }
+.location-card__note { margin: 0.85rem 0; color: var(--muted); font-size: 0.65rem; line-height: 1.5; }
+.location-card__actions { display: grid; gap: 0.5rem; }
+.location-card__actions button { min-height: 42px; padding: 0.65rem 0.8rem; border: 1px solid var(--line-strong); border-radius: 2px; background: rgba(255, 176, 0, 0.13); color: var(--mint-bright); font-size: 0.66rem; font-weight: 600; text-align: left; cursor: pointer; }
+.location-card__actions button:hover { background: rgba(255, 176, 0, 0.22); }
+.location-card__actions button[hidden] { display: none; }
+
+.pin-prompt {
+ position: fixed;
+ z-index: 24;
+ left: 50%;
+ bottom: 3.25rem;
+ width: min(520px, calc(100vw - 3rem));
+ min-height: 70px;
+ display: grid;
+ grid-template-columns: auto minmax(0, 1fr) auto auto;
+ align-items: center;
+ gap: 0.85rem;
+ padding: 0.65rem 0.7rem 0.65rem 0.9rem;
+ border: 1px solid var(--line-strong);
+ border-radius: 2px;
+ background: #120d06;
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.56);
+ transform: translateX(-50%);
+}
+
+.pin-prompt[hidden] { display: none; }
+.pin-prompt__target { position: relative; width: 28px; height: 28px; border: 1px solid var(--mint); transform: rotate(45deg); }
+.pin-prompt__target::before, .pin-prompt__target::after { content: ""; position: absolute; background: var(--mint); opacity: 0.5; }
+.pin-prompt__target::before { top: 50%; left: -7px; right: -7px; height: 1px; }
+.pin-prompt__target::after { left: 50%; top: -7px; bottom: -7px; width: 1px; }
+.pin-prompt__target i { position: absolute; inset: 9px; background: var(--mint-bright); box-shadow: 0 0 12px var(--mint); }
+.pin-prompt p { margin: 0; overflow: hidden; color: var(--text); font-size: 0.7rem; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
+.pin-prompt > div:nth-child(2) span { display: block; margin-top: 0.25rem; overflow: hidden; color: var(--faint); font: 0.53rem var(--font-mono); text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
+.pin-prompt button { min-height: 42px; padding: 0 0.85rem; border: 1px solid var(--line-strong); border-radius: 2px; background: var(--mint); color: #171005; font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; cursor: pointer; }
+.pin-prompt button:disabled { cursor: wait; opacity: 0.55; }
+.pin-prompt__countdown { display: grid; place-items: center; width: 32px; height: 32px; border: 1px solid var(--line); border-radius: 50%; color: var(--muted); font: 0.65rem var(--font-mono); }
+
+.map-key { position: fixed; z-index: 7; right: 1.5rem; bottom: 3.2rem; display: flex; align-items: center; gap: 0.55rem; color: var(--faint); font: 0.52rem var(--font-mono); letter-spacing: 0.06em; }
+.map-key i { display: block; width: 90px; height: 4px; border-radius: 999px; background: linear-gradient(90deg, var(--mint), var(--amber), var(--coral)); box-shadow: 0 0 12px rgba(242, 169, 59, 0.28); }
+
+.source-note { position: fixed; z-index: 8; left: 1.5rem; right: 1.5rem; bottom: 0; min-height: 42px; display: flex; align-items: center; justify-content: flex-end; gap: 1rem; color: var(--faint); font: 0.55rem var(--font-mono); text-transform: uppercase; letter-spacing: 0.05em; }
+.source-note button { min-height: 32px; padding: 0; border: 0; border-bottom: 1px solid var(--line-strong); background: transparent; color: var(--muted); font: inherit; text-transform: inherit; cursor: pointer; }
+.source-note button:hover { color: var(--mint-bright); }
+
+.about-panel {
+ position: fixed;
+ z-index: 30;
+ left: 50%;
+ bottom: 1.5rem;
+ width: min(920px, calc(100vw - 3rem));
+ max-height: calc(100vh - 3rem);
+ overflow: auto;
+ padding: clamp(1.5rem, 4vw, 3rem);
+ border: 1px solid var(--line-strong);
+ border-radius: 2px;
+ background: #120d06;
+ box-shadow: 0 30px 100px rgba(0, 0, 0, 0.65);
+ transform: translateX(-50%);
+}
+.about-panel[hidden] { display: none; }
+.about-panel h2 { margin: 0 0 2rem; font-size: clamp(1.8rem, 4vw, 3rem); letter-spacing: -0.04em; }
+.about-grid { display: grid; grid-template-columns: 1.1fr 1fr 1fr; gap: clamp(1.2rem, 3vw, 2.5rem); }
+.about-grid h3 { margin: 0 0 0.6rem; font-size: 0.8rem; }
+.about-grid p { margin: 0; color: var(--muted); font-size: 0.76rem; line-height: 1.65; }
+.about-links { display: flex; gap: 1.5rem; margin-top: 2rem; padding-top: 1.2rem; border-top: 1px solid var(--line); }
+.about-links a { color: var(--mint); font-size: 0.7rem; text-decoration: none; }
+
+.loading-screen { position: fixed; z-index: 50; inset: 0; display: grid; place-content: center; justify-items: center; background: #070604; transition: opacity 400ms ease, visibility 400ms ease; }
+.loading-screen.done { opacity: 0; visibility: hidden; }
+.loading-screen p { margin: 1.5rem 0 0.35rem; font-size: 0.82rem; font-weight: 600; }
+.loading-screen span { color: var(--faint); font: 0.58rem var(--font-mono); text-transform: uppercase; letter-spacing: 0.08em; }
+.loader-orbit { position: relative; width: 76px; height: 76px; border: 1px solid var(--line-strong); border-radius: 50%; animation: orbit 3s linear infinite; }
+.loader-orbit::before, .loader-orbit::after { content: ""; position: absolute; inset: 12px; border: 1px solid var(--line); border-radius: 50%; }
+.loader-orbit::after { inset: 27px; background: var(--mint); box-shadow: 0 0 25px var(--mint); }
+.loader-orbit i { position: absolute; top: 50%; left: 50%; width: 5px; height: 5px; border-radius: 50%; background: var(--amber); box-shadow: 0 0 12px var(--amber); }
+.loader-orbit i:first-child { transform: translate(28px, -2px); }
+.loader-orbit i:nth-child(2) { transform: translate(-33px, 8px); }
+.loader-orbit i:nth-child(3) { transform: translate(10px, 31px); }
+@keyframes orbit { to { transform: rotate(360deg); } }
+
+.maplibregl-ctrl-group { overflow: hidden; border: 1px solid var(--line) !important; border-radius: 12px !important; background: var(--panel) !important; box-shadow: none !important; }
+.maplibregl-ctrl-group button { width: 38px; height: 38px; }
+.maplibregl-ctrl-group button + button { border-top-color: var(--line) !important; }
+.maplibregl-ctrl-icon { filter: invert(92%) sepia(12%) saturate(315%); opacity: 0.75; }
+.maplibregl-ctrl-bottom-right { right: 0.65rem; bottom: 4.35rem; }
+.maplibregl-ctrl-attrib { background: rgba(7, 6, 4, 0.82) !important; color: var(--faint) !important; font-size: 9px !important; }
+.maplibregl-ctrl-attrib a { color: var(--muted) !important; }
+.maplibregl-canvas { cursor: grab; }
+.maplibregl-canvas:active { cursor: grabbing; }
+
+@media (max-width: 760px) {
+ .topbar { height: 64px; padding: 0 0.85rem; }
+ .brand__mark { width: 34px; height: 34px; }
+ .brand small, .topbar__status { display: none; }
+ .place-search { top: 76px; width: calc(100vw - 1.4rem); height: 44px; }
+ .topbar__tools { position: fixed; z-index: 9; top: 128px; right: 0.7rem; margin: 0; }
+ .hotspot-nav { height: 40px; }
+ .hotspot-nav__rank { min-width: 112px !important; }
+ .mobile-toggle { position: fixed; z-index: 18; left: 0.7rem; bottom: max(0.7rem, env(safe-area-inset-bottom)); min-height: 48px; display: flex; border-radius: 2px; background: #120d06; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.48); }
+ .control-panel { z-index: 23; top: auto; left: 0.7rem; right: 0.7rem; bottom: max(0.7rem, env(safe-area-inset-bottom)); width: auto; max-height: min(72vh, 640px); padding: 1.15rem; transform: translateY(calc(100% + 1rem)); transition: transform 250ms ease; }
+ .control-panel.open { transform: translateY(0); }
+ .controls-close { align-self: flex-end; min-height: 38px; display: inline-flex; align-items: center; gap: 0.4rem; margin: -0.35rem -0.3rem 0.55rem 0; padding: 0 0.7rem; border: 1px solid var(--line); border-radius: 2px; background: transparent; color: var(--muted); font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; }
+ .controls-close:hover { border-color: var(--line-strong); color: var(--mint-bright); }
+ .controls-close svg { width: 16px; stroke: currentColor; stroke-width: 1.5; }
+ .panel-heading h1 { font-size: 1.9rem; }
+ .stats { margin: 1rem 0; }
+ .source-note { left: 8.8rem; right: 5.5rem; justify-content: flex-start; bottom: 0.4rem; }
+ .source-note span { display: none; }
+ .map-key { right: 0.8rem; bottom: 1rem; }
+ .map-key span { display: none; }
+ .map-key i { width: 62px; }
+ .detail-card, .location-card { z-index: 23; top: auto; left: 0.7rem; right: 0.7rem; bottom: max(0.7rem, env(safe-area-inset-bottom)); width: auto; max-height: calc(100dvh - 190px); overflow: auto; padding: 1.25rem 1.2rem calc(1.2rem + env(safe-area-inset-bottom)); animation: sheet-in 250ms ease both; }
+ .detail-card::before, .location-card::before { content: ""; display: block; width: 42px; height: 3px; margin: -0.55rem auto 1rem; border-radius: 999px; background: var(--line-strong); }
+ .detail-card__close, .location-card__close { top: 0.65rem; right: 0.7rem; width: 44px; height: 44px; }
+ .detail-card h2, .location-card h2 { max-width: calc(100% - 3rem); font-size: 1.25rem; }
+ .detail-card dl div { min-height: 44px; align-items: center; }
+ .detail-card a { min-height: 44px; display: inline-flex; align-items: center; }
+ .pin-prompt { bottom: 0.7rem; width: calc(100vw - 1.4rem); grid-template-columns: auto minmax(0, 1fr) auto; gap: 0.65rem; }
+ .pin-prompt button { grid-column: 2 / 4; width: 100%; }
+ .pin-prompt__countdown { grid-row: 1; grid-column: 3; }
+ .about-panel { bottom: 0.7rem; width: calc(100vw - 1.4rem); max-height: calc(100vh - 1.4rem); padding: 1.5rem 1.2rem; }
+ .about-grid { grid-template-columns: 1fr; }
+ .about-links { flex-direction: column; gap: 0.8rem; }
+ .maplibregl-ctrl-bottom-right { bottom: 4rem; }
+}
+
+@keyframes sheet-in {
+ from { opacity: 0; transform: translateY(18px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+@media (min-width: 761px) and (max-width: 1120px) {
+ .topbar__status { display: none; }
+ .place-search { width: min(360px, 38vw); }
+ .hotspot-nav__rank { min-width: 110px !important; }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ *, *::before, *::after { scroll-behavior: auto !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
+ .scan-lines { display: none; }
+}