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

/* Saved to the iOS home screen, the page runs edge-to-edge: the status bar
   sits over the top and the home indicator over the bottom. These insets
   keep the chrome clear of both. Held in variables so they can be overridden
   for testing on a desktop browser, where env() resolves to 0. */
:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

html, body {
  height: 100%;
  background: #101010;
  color: #eee;
  font-family: -apple-system, "Segoe UI", Roboto, sans-serif;
  overflow: hidden;
}

body {
  display: flex;
  flex-direction: column;
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
}

#disclaimer {
  font-size: 0.65rem;
  text-align: center;
  color: #888;
  background: #000;
  padding: 3px 6px;
  letter-spacing: 0.02em;
}

/* Routine state: quiet countdown, reads as chrome not alarm. */
#status-banner {
  font-size: 0.7rem;
  text-align: center;
  padding: 4px;
  background: #141414;
  color: #6a6a6a;
  letter-spacing: 0.03em;
}
/* Reserved for an actual failure to reach the server. */
#status-banner.error {
  background: #7a2a2a;
  color: #fff;
  font-size: 0.8rem;
  padding: 6px;
}
#status-banner.hidden { display: none; }

#rows {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.row {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 5vw;
  border-bottom: 1px solid #000;
  transition: background-color 0.3s ease, opacity 0.3s ease;
}

.row:last-child { border-bottom: none; }

.row.linkable { cursor: pointer; }
.row.linkable .value { text-decoration: underline; text-decoration-style: dotted; }

.row .label {
  font-size: 5vw;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  opacity: 0.85;
}

.row .value-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.05;
}

.row .value {
  font-size: 7vw;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Secondary line under a value (e.g. the raw count behind a percentage).
   Deliberately quiet -- it's context, not the number being glanced at. */
.row .subvalue {
  font-size: 3.4vw;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
  margin-top: 0.6vw;
}

/* Trend rows: a line over the last miles driven, the county band behind
   it. The line carries the color, so the row itself stays dark. */
.row.trend { gap: 3vw; background: transparent; }
.row.trend .trend-chart { position: relative; flex: 1; align-self: stretch; margin: 1.5vw 0; }
.row.trend canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.row.trend .trend-label {
  position: absolute; left: 0; top: 0;
  font-size: 3.4vw; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.03em; opacity: 0.7;
}
.row.trend .value { font-size: 6vw; min-width: 18vw; text-align: right; color: #fff; }

/* State: empty row slot (row assignment has null) */
.row.empty {
  background: transparent;
}

/* State: value present -- background color comes from field catalog,
   set inline via style.backgroundColor. Text stays high-contrast. */
.row.ok .value { color: #fff; }

/* State: no data for this hex -- visually distinct from stale/disconnected.
   Muted, dashed underline on the value, no color-scale fill. */
.row.no_data {
  background: #262626;
}
.row.no_data .value {
  color: #777;
  font-size: 4.5vw;
  border-bottom: 2px dashed #555;
  padding-bottom: 2px;
}
.row.no_data .value::after {
  content: "";
}

/* State: stale / disconnected -- overrides whatever was last shown.
   Strikethrough + grayscale so a stale number is never mistaken for live. */
.row.stale {
  filter: grayscale(1);
  opacity: 0.5;
}
.row.stale .value {
  text-decoration: line-through;
  text-decoration-thickness: 3px;
}
.row.stale .subvalue {
  text-decoration: line-through;
}

#controls {
  flex: none;
  border-top: 1px solid #000;
  background: #1a1a1a;
}

.control-row {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid #000;
}
.control-row:last-child { border-bottom: none; }

.control-label {
  display: flex;
  align-items: center;
  padding: 0 3vw;
  font-size: 2.9vw;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #666;
  flex: none;
  white-space: nowrap;
}

.toggle-group { display: flex; }

.toggle-option {
  border: none;
  border-right: 1px solid #000;
  background: #1a1a1a;
  color: #777;
  font: inherit;
  font-size: 3.2vw;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2.2vw 3vw;
  /* Don't let a tight row compress these into two lines ("1 / MI"). */
  flex: none;
  white-space: nowrap;
}
.toggle-option.active {
  background: #333;
  color: #fff;
}



/* Pushes the action buttons to the right, so the left of each row is
   filters ("what am I looking at") and the right is actions ("do something").
   Previously every control shared one look and one strip, which gave no clue
   that Variables was the way to change the display. */
.control-spacer { flex: 1; }

.action-btn {
  flex: none;
  border: none;
  border-left: 1px solid #000;
  background: #222;
  color: #bbb;
  font: inherit;
  font-size: 3.2vw;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2.2vw 3.5vw;
  white-space: nowrap;
}
.action-btn:active { background: #3a3a3a; color: #fff; }
.action-btn.hidden { visibility: hidden; }
/* The one control most people need to find first. */
.action-btn.primary-action { background: #2f4a6d; color: #fff; }
.action-btn.primary-action:active { background: #3d5f8a; }
/* Held while a fresh GPS fix and refetch are in flight. */
.action-btn.busy { background: #3a3a3a; color: #fff; opacity: 0.7; }

#detail-modal.hidden, #fields-modal.hidden, #note-modal.hidden, #compare-modal.hidden,
#compare-detail-modal.hidden { display: none; }
#detail-modal, #fields-modal, #note-modal, #compare-modal, #compare-detail-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  /* Fixed positioning ignores the body padding, so the modal needs the
     insets too -- otherwise its close button lands under the status bar. */
  padding: calc(var(--safe-top) + 2vw) calc(var(--safe-right) + 2vw)
           calc(var(--safe-bottom) + 2vw) calc(var(--safe-left) + 2vw);
}
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
}
#detail-modal-content, .modal-content {
  position: relative;
  background: #181818;
  border-radius: 8px;
  width: 100%;
  max-width: 90vw;
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8vw 5vw 5vw;
}
#detail-modal-close, .modal-close {
  position: absolute;
  top: 2vw;
  right: 3vw;
  border: none;
  background: none;
  color: #ccc;
  font-size: 7vw;
  line-height: 1;
  padding: 2vw;
}

.detail-section-title {
  font-size: 3.5vw;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #888;
  margin: 4vw 0 1.5vw;
}
.detail-section-title:first-child { margin-top: 0; }

.detail-item {
  display: flex;
  justify-content: space-between;
  padding: 1.2vw 0;
  border-bottom: 1px solid #262626;
  font-size: 3.8vw;
}
.detail-item .detail-label { color: #aaa; }
.detail-item .detail-value { font-weight: 600; font-variant-numeric: tabular-nums; }

#debug-bar {
  font-size: 0.65rem;
  font-family: ui-monospace, monospace;
  color: #666;
  background: #000;
  padding: 3px 8px;
  display: flex;
  justify-content: space-between;
}
#debug-bar.hidden { display: none; }

/* Field picker */

.field-slot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 3vw;
  padding: 2vw 0;
  border-bottom: 1px solid #262626;
}
.field-slot-label {
  font-size: 3.4vw;
  color: #888;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.field-select {
  flex: 1;
  min-width: 0;
  background: #262626;
  color: #eee;
  border: 1px solid #3a3a3a;
  border-radius: 4px;
  font: inherit;
  font-size: 3.8vw;
  padding: 2vw;
}

#fields-reset {
  width: 100%;
  margin-top: 5vw;
  border: 1px solid #3a3a3a;
  border-radius: 4px;
  background: #262626;
  color: #aaa;
  font: inherit;
  font-size: 3.4vw;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2.5vw;
}
#fields-reset:active { background: #333; color: #fff; }

.modal-note {
  margin-top: 3vw;
  font-size: 3vw;
  color: #666;
  text-align: center;
}

/* Methodology notes: prose, not a figure, so they stack instead of trying to
   right-align a paragraph against its label. */
.detail-item.detail-note {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.8vw;
  padding: 2.2vw 0;
}
.detail-item.detail-note .detail-label {
  color: #ddd;
  font-weight: 600;
}
.detail-item.detail-note .detail-value {
  font-weight: 400;
  font-size: 3.3vw;
  color: #9a9a9a;
  line-height: 1.4;
  text-align: left;
}

/* Tap target explaining how a figure is derived -- e.g. that "Avg Home Value"
   averages block group medians rather than being a median itself. */
.note-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4.4vw;
  height: 4.4vw;
  margin-left: 1.8vw;
  padding: 0;
  border: 1px solid #888;
  border-radius: 50%;
  background: transparent;
  color: #bbb;
  font: inherit;
  font-size: 3vw;
  font-style: italic;
  font-weight: 700;
  line-height: 1;
  vertical-align: middle;
}
.note-icon:active { background: #555; color: #fff; }

.note-modal-content { max-width: 85vw; }
.note-body {
  font-size: 3.9vw;
  line-height: 1.5;
  color: #ccc;
}

/* County comparison: legend strip above the controls, and its settings. */
#compare-legend {
  background: #1a1a1a;
  padding: 1.5vw 3vw;
  border-top: 1px solid #000;
  cursor: pointer;
}
#compare-legend.hidden { display: none; }
#compare-legend.stale { filter: grayscale(1); opacity: 0.5; }
#compare-legend-bar { height: 2.2vw; border-radius: 4px; }
#compare-legend-labels {
  display: flex;
  justify-content: space-between;
  gap: 2vw;
  margin-top: 0.8vw;
  font-size: 2.9vw;
  font-weight: 600;
  color: #bbb;
  white-space: nowrap;
}
#compare-legend-mid { overflow: hidden; text-overflow: ellipsis; }
#compare-legend-message { font-size: 3vw; font-weight: 600; color: #f0a030; text-align: center; }
#compare-legend-message:empty { display: none; }

.compare-switch {
  display: flex;
  align-items: center;
  gap: 2vw;
  font-size: 3.8vw;
  padding: 2vw 0;
}
.compare-option {
  display: block;
  width: 100%;
  text-align: left;
  background: #222;
  color: #ddd;
  border: 1px solid #222;
  border-radius: 6px;
  padding: 2.4vw 3vw;
  margin: 1.5vw 0;
  font: inherit;
  font-size: 3.6vw;
  cursor: pointer;
}
.compare-option.active { border-color: #4a7cb8; background: #1d2633; }
.compare-option-desc { display: block; font-size: 3vw; color: #888; margin-top: 1vw; }
.compare-swatch { display: block; height: 3.6vw; border-radius: 4px; margin-top: 1.5vw; }

/* "Why these colors": per row, here vs the county's spread. */
.cmp-item { border-top: 1px solid #2a2a2a; padding: 3vw 0; }
.cmp-head { display: flex; align-items: baseline; gap: 2vw; }
.cmp-here { font-size: 5.5vw; font-weight: 700; padding: 0 2vw; border-radius: 6px; font-variant-numeric: tabular-nums; }
.cmp-score { margin-left: auto; font-size: 3.6vw; font-weight: 600; }
.cmp-rank { font-size: 3.6vw; margin: 1.5vw 0; }
.cmp-strip { position: relative; display: flex; height: 3.6vw; border-radius: 4px; overflow: visible; margin: 4vw 0 1vw; }
.cmp-strip span { flex: 1; }
.cmp-strip span:first-child { border-radius: 4px 0 0 4px; }
.cmp-strip span:last-child { border-radius: 0 4px 4px 0; }
.cmp-marker { position: absolute; top: -2.5vw; bottom: -1vw; width: 2px; background: #fff; transform: translateX(-1px); }
.cmp-marker::before { content: "\25BC"; position: absolute; top: -3vw; left: -1.4vw; font-size: 3vw; color: #fff; }
.cmp-ticks { position: relative; height: 8vw; font-size: 2.8vw; color: #999; }
.cmp-ticks div { position: absolute; transform: translateX(-50%); text-align: center; white-space: nowrap; }
.cmp-ticks small { display: block; color: #666; }
.cmp-stat { display: flex; justify-content: space-between; font-size: 3.6vw; padding: 0.6vw 0; }
.cmp-stat span:first-child { color: #999; }
.cmp-note { font-size: 3.2vw; color: #999; margin: 1.5vw 0 0; }
.cmp-section-body { font-size: 3.3vw; color: #999; line-height: 1.45; }

/* Alternate screen (Market area): marks rows that aren't the user's own. */
#screen-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #2f4a6d;
  color: #fff;
  padding: 1.6vw 3vw;
  font-size: 3.4vw;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
#screen-banner.hidden { display: none; }

/* What the area figures cover, while drive time is chosen: the drive, or
   the radius they fell back to where there's no drive time. */
#area-note {
  flex: none;
  padding: 1.2vw 3vw;
  font-size: 3vw;
  color: #bbb;
  background: #1a1a1a;
  border-top: 1px solid #000;
}
#area-note.fallback { color: #f0c040; }
#area-note.hidden { display: none; }
#drive-row.hidden { display: none; }
#screen-back {
  background: none;
  border: none;
  color: #fff;
  font: inherit;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  cursor: pointer;
}
