Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/components/layout/NotForNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const KNOWN_DIFFERENCES: { heading: string; items: string[] }[] = [
items: [
'Only aircraft broadcasting ADS-B appear — non-equipped, blocked, or non-transmitting traffic (including some military) is invisible.',
'Positions are polled every few seconds and dead-reckoned between polls, so a target on screen is an estimate that lags reality by seconds.',
'No separation, TCAS, conflict, or wake information of any kind is shown or implied.',
'Though traffic is depicted with advisory conflict indicators, separation, wake turbulence, and deconfliction is not guaranteed or implied.',
'Callsign-to-route (origin → destination) is best-effort crowd-sourced data and is frequently missing or wrong.',
],
},
Expand Down
88 changes: 88 additions & 0 deletions src/components/map/AircraftOverlay.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

/* ── Mini data label — three centered lines below the icon ───────────────── */

/* transform is the base position; AircraftOverlay.tsx's rAF loop may set an
inline style.transform on this element (or .dataLabelWrap below) to push a
conflicting pair's labels apart, repeating this translate(-50%, 22px) since
an inline style fully replaces the rule below rather than composing with
it. Cleared back to '' once the pair-separation eases out to rest. */
.dataLabel {
position: absolute;
left: 0;
Expand Down Expand Up @@ -168,3 +173,86 @@
.selected .altspd {
color: #cbd5e1;
}

/* ── Traffic/terrain alert chrome (src/store/usePathStore.ts) ─────────────
Only rendered when the hex has an AircraftAlert — see AircraftOverlay.tsx.
.dataLabelWrap replaces the plain .dataLabel as the positioned element (same
translate(-50%, 22px) as the non-alerted .dataLabel, so the callsign line
doesn't shift when an alert appears/disappears) and stacks, top to bottom:
the unboxed callsign row, the .alertBox/.warnBox border around just the
data rows (altitude/speed/track + type/route/TIS-B), the chip, and — red
tier only — the blinking bar. The nested .dataLabel (now wrapping only the
data rows, inside the box) goes back to static/no-transform since
.dataLabelWrap carries the positioning. */

/* See the .dataLabel comment above — same inline pair-separation override
applies to this element when it's the alerted variant. */
.dataLabelWrap {
position: absolute;
left: 0;
top: 0;
transform: translate(-50%, 22px);
display: flex;
flex-direction: column;
align-items: center;
}

.dataLabelWrap .dataLabel {
position: static;
transform: none;
}

/* Amber tier ('alert' | 'ta'): 1px amber outline around the data rows only
(callsign row sits above, unboxed), no fill. */
.alertBox {
border: 1px solid #fbbf24; /* ALERT_AMBER */
border-radius: 2px;
padding: 2px 5px;
background: transparent;
}

/* Red tier ('warning' | 'ra'): pairs with the blinking bar below (.warnBar);
the outline itself stays amber like .alertBox. */
.warnBox {
}

.chip {
margin-top: 3px;
padding: 1px 5px;
border-radius: 2px;
font-family: 'Roboto Mono', 'DejaVu Sans Mono', monospace;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.04em;
white-space: nowrap;
}

.alertChip {
background: #fbbf24; /* ALERT_AMBER */
color: #1a1406;
}

.warnChip {
background: #ef4444; /* WARNING_RED */
color: #ffffff;
}

.warnBar {
align-self: stretch;
height: 5px;
margin-top: 3px;
border-radius: 1px;
background: #ef4444; /* WARNING_RED */
}

/* Blink is applied only to the red fill bar (not text elements), so labels
and chip text stay legible while the bar flashes. */
.blink {
animation: blink 1s steps(2, jump-none) infinite;
}

@keyframes blink {
50% {
opacity: 0.15;
}
}
Loading
Loading