:root {
  --bg: #14181c;
  --panel: #1d2329;
  --panel-2: #242b32;
  --text: #e8ecef;
  --text-dim: #9aa5ad;
  --accent: #ffb648;
  --shade-route: #3f8ad1;
  --sun-route: #ef7f37;
  --direct-route: #6b7885;
  --border: #2c333a;
  --panel-translucent: rgba(29, 35, 41, 0.82);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  height: 100dvh;
  overflow: hidden;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
}

body {
  display: flex;
}

#sidebar {
  width: 320px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  padding: 20px 20px calc(20px + env(safe-area-inset-bottom)) 20px;
  background: var(--panel);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
  touch-action: pan-y;
  height: 100vh;
  height: 100dvh;
}

#mapWrap {
  flex: 1;
  position: relative;
  height: 100vh;
  height: 100dvh;
}

#map {
  width: 100%;
  height: 100%;
}

#mapOverlay {
  position: absolute;
  top: calc(16px + env(safe-area-inset-top));
  right: calc(16px + env(safe-area-inset-right));
  z-index: 1000;
}

#mapCompass:empty {
  display: none;
}

#mapCompass .compass {
  margin: 0;
  padding: 10px 12px;
  background: var(--panel-translucent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
}

.sidebar-toggle {
  display: none;
}

/* Phones/small tablets: side-by-side squeezes the map to near-zero width,
   which is what breaks pinch-zoom and pan (the page scrolls instead of the
   Leaflet container getting the touch events). Stack instead, and let the
   panel collapse down to a header bar so it doesn't permanently cover the
   map — it was fixed at 45vh with no way to get it out of the way. */
@media (max-width: 680px) {
  body {
    flex-direction: column;
  }

  #sidebar {
    position: relative;
    width: 100%;
    height: auto;
    max-height: 45vh;
    max-height: 45dvh;
    border-right: none;
    border-bottom: 1px solid var(--border);
    padding-top: 52px;
    padding-bottom: calc(20px + env(safe-area-inset-bottom));
    transition: max-height 0.2s ease;
  }

  /* padding-bottom must be reset here: with box-sizing: border-box, a
     border-box can never shrink below its own padding sum, so the
     inherited 20px+ padding-bottom (meant for the expanded view) would
     otherwise force this collapsed bar past max-height regardless of
     overflow: hidden, pushing the title off-center. */
  #sidebar.collapsed {
    max-height: 82px;
    padding-bottom: 0;
    overflow: hidden;
  }

  #mapWrap {
    flex: 1;
    height: auto;
    min-height: 40vh;
    min-height: 40dvh;
  }

  #mapOverlay {
    top: calc(10px + env(safe-area-inset-top));
    right: calc(10px + env(safe-area-inset-right));
  }

  #legend {
    bottom: calc(10px + env(safe-area-inset-bottom));
    left: calc(10px + env(safe-area-inset-left));
    font-size: 10px;
    padding: 6px 8px;
    border-radius: 6px;
  }

  #legend div {
    gap: 6px;
    margin-bottom: 3px;
  }

  #legend .swatch {
    width: 13px;
  }

  /* Compass shrinks to match the legend's mobile footprint -- at full size
     it and the legend together cover a third of a phone screen's map. */
  #mapCompass .compass {
    padding: 6px 8px;
    border-radius: 6px;
  }

  #mapCompass .compass-ring {
    width: 46px;
    height: 46px;
  }

  #mapCompass .compass-n {
    top: 2px;
    font-size: 7px;
  }

  #mapCompass .compass-needle {
    height: 19px;
  }

  #mapCompass .compass-needle::after {
    border-left-width: 3px;
    border-right-width: 3px;
  }

  #mapCompass .compass-needle.sun::after {
    border-bottom-width: 5px;
  }

  #mapCompass .compass-needle.shadow::after {
    border-bottom-width: 5px;
  }

  #mapCompass .compass-legend {
    gap: 8px;
    margin-top: 4px;
    font-size: 9px;
  }

  #mapCompass .compass-legend .dot {
    width: 6px;
    height: 6px;
    margin-right: 3px;
  }

  .sidebar-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    position: absolute;
    top: calc(10px + env(safe-area-inset-top));
    left: 20px;
    right: 20px;
    width: auto;
    margin: 0;
    padding: 8px;
    font-size: 12.5px;
    font-weight: 600;
    background: var(--panel-2);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 6px;
  }
}

.lang-select {
  width: auto;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 12px;
  cursor: pointer;
}

h1.wordmark {
  font-size: 26px;
  margin: 0;
  font-weight: 700;
  letter-spacing: -0.01em;
}

h1.wordmark .tld {
  color: var(--accent);
}

.citytag {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 7px 0 16px;
}

label {
  display: block;
  font-size: 12px;
  color: var(--text-dim);
  margin: 14px 0 6px;
}

input[type="datetime-local"],
input[type="range"],
input[type="text"] {
  width: 100%;
}

input[type="datetime-local"] {
  /* iOS Safari sizes its native date/time widget to its content and
     ignores width: 100% otherwise, leaving a gap on the right that the
     other full-width fields/buttons don't have. */
  -webkit-appearance: none;
  appearance: none;
}

input[type="datetime-local"],
input[type="text"] {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 8px;
  font-size: 13px;
}

input[type="text"]::placeholder {
  color: var(--text-dim);
}

/* Dropping the native appearance above also drops its built-in vertical
   sizing, shrinking the field well below the other inputs/buttons.
   min-height (rather than relying on padding + the field's own content
   box, which some WebKit builds size inconsistently) pins it back to
   match them regardless of that. Overrides the shared 8px padding rule
   above by coming after it in the cascade. */
input[type="datetime-local"] {
  padding: 10px 12px;
  min-height: 40px;
}

/* iOS Safari zooms the page in on focus for any input with a computed
   font-size below 16px. Bump it just for mobile so tapping an address
   field doesn't zoom the whole UI. Must come after the 13px rule above
   to win the cascade (equal specificity — source order decides). */
@media (max-width: 680px) {
  input[type="datetime-local"],
  input[type="text"] {
    font-size: 16px;
  }
}

.address-fields {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-top: 28px;
}

.address-inputs {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.swap-btn {
  flex-shrink: 0;
  width: 30px;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
}

.swap-btn:hover {
  color: var(--accent);
}

.addr-field {
  position: relative;
}

.addr-field input[type="text"] {
  padding: 10px 34px 10px 12px;
  border-radius: 10px;
}

.locate-btn {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: 5px;
  color: var(--text-dim);
  cursor: pointer;
}

.locate-btn:hover {
  color: var(--accent);
  background: var(--panel-2);
}

.locate-btn.loading {
  opacity: 0.5;
  pointer-events: none;
}

.locate-btn.loading svg {
  animation: locate-pulse 1s ease-in-out infinite;
}

@keyframes locate-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.suggestions {
  display: none;
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  z-index: 1000;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  max-height: 180px;
  overflow-y: auto;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
}

.suggestions.open {
  display: block;
}

.suggestion {
  padding: 8px 10px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--text);
  cursor: pointer;
  border-bottom: 1px solid var(--border);
}

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

.suggestion:hover,
.suggestion.active {
  background: var(--panel);
  color: var(--accent);
}

button {
  width: 100%;
  margin-top: 14px;
  padding: 10px;
  border-radius: 6px;
  border: none;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  background: var(--accent);
  color: #1a1200;
  transition: opacity 0.15s;
}

button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.secondary {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  font-weight: 500;
}

.panel {
  margin-top: 16px;
  font-size: 12.5px;
  line-height: 1.7;
}

.panel:empty {
  display: none;
}

.panel b {
  color: var(--text);
}

.panel .row {
  display: flex;
  justify-content: space-between;
  color: var(--text-dim);
}

.panel .row b {
  color: var(--text);
}

.capped-note {
  margin-top: 6px;
  color: var(--accent);
  font-size: 11.5px;
  line-height: 1.5;
}

#legend {
  position: absolute;
  bottom: calc(16px + env(safe-area-inset-bottom));
  left: calc(16px + env(safe-area-inset-left));
  z-index: 1000;
  max-width: calc(100% - 32px - env(safe-area-inset-left) - env(safe-area-inset-right));
  font-size: 12px;
  color: var(--text-dim);
  background: var(--panel-translucent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
  /* Shown briefly after a route renders (see showLegendBriefly() in app.js)
     rather than sitting on screen the whole time -- it only matters for the
     few seconds it takes to learn what the route colors mean. */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

#legend.visible {
  opacity: 1;
}

#legend div {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

#legend div:last-child {
  margin-bottom: 0;
}

.swatch {
  width: 18px;
  height: 4px;
  border-radius: 2px;
  display: inline-block;
}

.swatch.shade { background: var(--shade-route); height: 3px; }
.swatch.sun { background: var(--sun-route); height: 3px; }
.swatch.direct { background: var(--direct-route); height: 3px; border-top: 2px dashed var(--direct-route); background: none; }

.export-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.export-actions:empty {
  display: none;
}

.export-actions button,
.export-actions a {
  margin-top: 0;
  flex: 1;
  font-size: 12px;
  padding: 8px 6px;
  border-radius: 6px;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.export-actions svg {
  flex-shrink: 0;
}

.error {
  margin-top: 14px;
  font-size: 12.5px;
  color: #ff6b6b;
}

.error:empty { display: none; }

.bottom-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: auto;
  padding-top: 20px;
}

.app-version {
  font-size: 11px;
  color: var(--text-dim);
  opacity: 0.6;
}

.app-version a {
  color: inherit;
}

.app-version a:hover {
  color: var(--accent);
  opacity: 1;
}

.lang-switch {
  display: flex;
  gap: 4px;
}

.lang-switch .lang-opt {
  width: auto;
  margin: 0;
  padding: 3px 7px;
  font-size: 11px;
  font-weight: 600;
  background: transparent;
  color: var(--text-dim);
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
  opacity: 1;
}

.lang-switch .lang-opt:hover {
  color: var(--text);
}

.lang-switch .lang-opt.active {
  color: var(--accent);
  border-color: var(--border);
  background: var(--panel-2);
}

.leaflet-container {
  background: #dfe4e8;
}

/* Popup shown when tapping a route line -- see app.js openRoutePopup().
   Built as a plain element (not Leaflet's L.popup()) because Leaflet's own
   popup pane lives inside .leaflet-map-pane, which gets a CSS transform for
   panning -- that transform creates its own stacking context, so any
   z-index set on the popup pane only ever competes with Leaflet's *other*
   internal panes, never with #mapOverlay/#legend outside it (confirmed via
   elementFromPoint: the compass painted on top regardless of the popup
   pane's z-index). Being a sibling of #mapOverlay/#legend here means its
   z-index is compared against theirs directly, so it can actually win. */
/* Padding, blur, radius, shadow and font-size below are the same values
   #legend and #mapCompass .compass use -- the three floating map boxes
   share one visual standard rather than each having their own tuning. */
.route-popup-el {
  position: absolute;
  z-index: 1200;
  transform: translate(-50%, calc(-100% - 14px));
  min-width: 205px;
  background: var(--panel-translucent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
  color: var(--text);
  font-size: 12px;
  line-height: 1.5;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}

.route-popup-el.open {
  opacity: 1;
  pointer-events: auto;
}

.route-popup-el::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -6px;
  transform: translateX(-50%);
  width: 12px;
  height: 12px;
  background: var(--panel-2);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  clip-path: polygon(0 0, 100% 0, 100% 100%);
}

.route-popup-el .hdr {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 8px;
}

.route-popup-el .hdr b {
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
}

.route-popup-el .row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  color: var(--text-dim);
}

.route-popup-el .row + .row {
  margin-top: 4px;
}

.route-popup-el .row b {
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.route-popup-el .row.arrival {
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px solid var(--border);
}

.route-popup-el .row.arrival b {
  color: var(--accent);
  font-size: 13.5px;
}

.compass {
  margin-top: 10px;
  text-align: center;
}

.compass-ring {
  position: relative;
  width: 64px;
  height: 64px;
  margin: 0 auto;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--panel-2);
}

.compass-ring--night {
  background: #10141a;
  border-color: #1a1f26;
}

.compass-n {
  position: absolute;
  top: 3px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 9px;
  font-weight: 600;
  color: var(--text-dim);
}

.compass-needle {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2px;
  height: 27px;
  transform-origin: 50% 100%;
}

.compass-needle::after {
  content: "";
  position: absolute;
  top: -3px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
}

.compass-needle.sun {
  background: var(--accent);
}
.compass-needle.sun::after {
  border-bottom: 6px solid var(--accent);
}

.compass-needle.shadow {
  background: #5b6b7a;
}
.compass-needle.shadow::after {
  border-bottom: 6px solid #5b6b7a;
}

.compass-legend {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-dim);
}

.compass-legend .dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;
}

.compass-legend .dot.sun { background: var(--accent); }
.compass-legend .dot.shadow { background: #5b6b7a; }
