:root {
  --bg: #10171c;
  --panel: #182229;
  --border: #2a3540;
  --text: #ece7da;
  --sub: #8b98a1;
  --ink: #10171c;
  --cat-drive: #3fa34d;
  --cat-ferry: #2d6fe0;
  --cat-stay: #e3b23a;
  --cat-utility: #e0573d;
  --cat-endpoint: #5b6670;
  /* Kept in sync with SELECT_COLOR in mapView.js. */
  --select: #a855f7;
  /* Distinct from both --bg and --panel (used by various inputs) so
     buttons read as buttons rather than blending in with text fields. */
  --btn-bg: #232e36;
}

* { box-sizing: border-box; }

/* App-shell layout: header and the view-toggle are fixed-height flex
   children that never scroll themselves; only the active pane (list or
   map) scrolls, inside its own fixed-height region. This avoids the
   overlap bugs that sticky positioning caused when the header's height
   changes (e.g. a <details> opening) — sticky elements don't reserve
   space for themselves, so a scrolling sibling can ride up underneath. */
html, body {
  height: 100%;
}

body {
  margin: 0;
  display: flex;
  flex-direction: column;
  height: 100vh; /* fallback for browsers without dvh support */
  height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.01em;
  overflow: hidden;
}

.error-banner[hidden] {
  display: none;
}

.error-banner {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--cat-utility);
  color: var(--ink);
  padding: 8px 14px;
  font-size: 0.85rem;
  font-weight: 700;
}

.error-banner button {
  background: none;
  border: none;
  color: var(--ink);
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
}

.app-header {
  flex-shrink: 0;
  padding: 16px;
  border-bottom: 2px solid var(--text);
  background: var(--bg);
  overflow-y: auto;
}

.app-header h1 {
  margin: 0 0 10px;
  font-size: 1.3rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.trip-settings {
  margin-bottom: 10px;
}

.trip-settings summary {
  cursor: pointer;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--sub);
  padding: 4px 0;
}

.trip-settings summary:hover {
  color: var(--text);
}

.trip-settings[open] summary {
  margin-bottom: 8px;
}

.trip-bar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}

.trip-bar select,
.trip-bar button {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 5px 9px;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
}

.trip-bar select {
  text-transform: none;
  width: 100%;
}

.trip-bar-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.trip-bar-actions button {
  flex: 1;
}

/* Matches the List view's destructive-action color (chip--warn) — this is
   the one trip-bar action that can't be undone. */
#delete-trip-btn {
  border-color: var(--cat-utility);
  color: var(--cat-utility);
}

#delete-trip-btn:hover {
  background: var(--cat-utility);
  color: var(--ink);
}

.target-row,
.preset-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--sub);
  flex-wrap: wrap;
}

.target-row input,
.preset-row input {
  width: 56px;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 4px 8px;
  font-size: 0.95rem;
  text-transform: none;
  letter-spacing: normal;
}

.preset-row label {
  display: flex;
  align-items: center;
  gap: 4px;
}

.target-row--stacked {
  flex-direction: column;
  align-items: stretch;
}

.target-row--stacked textarea {
  width: 100%;
  box-sizing: border-box;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 6px 8px;
  font-size: 0.85rem;
  font-family: inherit;
  text-transform: none;
  letter-spacing: normal;
  resize: vertical;
}

.preset-row input[type="text"] {
  width: 110px;
}

.preset-range-input {
  width: 60px !important;
}

.variant-bar {
  margin-bottom: 12px;
}

.variant-pills-row,
.variant-actions-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.variant-pills-row {
  margin-bottom: 6px;
}

.variant-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 4px 8px;
  font-size: 0.75rem;
  background: var(--panel);
  cursor: pointer;
}

.variant-pill.active {
  border-color: var(--text);
}

.variant-pill.preferred {
  border-left: 3px solid var(--cat-stay);
}

.variant-pill button {
  background: none;
  border: none;
  color: var(--sub);
  cursor: pointer;
  font-size: 0.75rem;
  padding: 0;
}

.variant-pill button:hover {
  color: var(--text);
}

.variant-action {
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 4px 8px;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: var(--btn-bg);
  color: var(--sub);
  cursor: pointer;
}

.variant-action:hover {
  color: var(--text);
  border-color: var(--text);
}

.totals, .save-status {
  font-size: 0.8rem;
  color: var(--sub);
}

.totals-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.totals-row .totals {
  flex: 1;
}

.totals-row .chip {
  flex-shrink: 0;
}

.chip:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.view-toggle {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 12px 16px;
  max-width: 640px;
  width: 100%;
  margin: 0 auto;
}

.active-variant-label {
  margin-left: 6px;
  font-size: 0.8rem;
  color: var(--sub);
}

.view-toggle button {
  background: var(--panel);
  color: var(--sub);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 5px 12px;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
}

.view-toggle button.active {
  color: var(--text);
  border-color: var(--text);
}

/* The app-body holds whichever pane (list or map) is active — it's the
   one region that actually scrolls, sized to fill whatever's left of the
   viewport after the header and view-toggle. */
.app-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  position: relative;
}

.pane {
  height: 100%;
  overflow-y: auto;
}

.list-controls {
  display: flex;
  gap: 14px;
  padding: 12px 16px 0;
  max-width: 640px;
  margin: 0 auto;
  font-size: 0.8rem;
  color: var(--sub);
}

.list-controls label {
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}

.leg-list {
  padding: 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 640px;
  margin: 0 auto;
}

.map-view {
  display: flex;
  flex-direction: column;
  height: 100%;
  max-width: 640px;
  margin: 0 auto;
  padding: 12px 16px;
  position: relative;
}

.map-controls {
  flex-shrink: 0;
  display: flex;
  gap: 14px;
  margin-bottom: 8px;
  font-size: 0.8rem;
  color: var(--sub);
}

.map-controls label {
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}

.map-canvas {
  flex: 1;
  min-height: 240px;
  border: 1px solid var(--border);
  border-radius: 2px;
}

.map-marker {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Matches List view's .icon-badge (sharp corners, not a full circle) so
     a node reads as the same kind of "place marker" the card icons do. */
  border-radius: 4px;
  border: 2px solid var(--ink);
  cursor: pointer;
}

.map-marker svg {
  opacity: 0.7;
}

.map-edge-label {
  font-size: 0.7rem;
  font-weight: 400;
  text-align: left;
  white-space: nowrap;
  background: rgba(16, 23, 28, 0.8);
  padding: 1px 6px;
  border-radius: 8px;
  pointer-events: none;
  /* Higher than .map-edge-arrow — labels were getting drawn over by
     direction arrows whenever an arrow happened to land later in marker
     DOM order than the label at the same point along the route. */
  z-index: 2;
}

.map-edge-arrow {
  font-size: 0.7rem;
  line-height: 1;
  pointer-events: none;
  text-shadow: 0 0 2px var(--bg), 0 0 2px var(--bg);
  z-index: 1;
}

.map-loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 8px 14px;
  font-size: 0.8rem;
  color: var(--sub);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  pointer-events: none;
}

.map-detail {
  position: absolute;
  bottom: 16px;
  left: 16px;
  right: 16px;
  /* MapLibre's own canvas/marker/control layers each establish their own
     stacking context with z-index values scoped inside the map — without
     an explicit value here, those could still end up rendered on top of
     this popup despite being earlier in the DOM. */
  z-index: 10;
  background: var(--panel);
  border: 1px solid var(--border);
  /* Matches the purple highlight on whatever node/edge this popup is
     describing, so the two visibly belong together. */
  border-left: 4px solid var(--select);
  border-radius: 2px;
  padding: 12px 14px;
  font-size: 0.85rem;
  line-height: 1.5;
}

.map-detail p {
  margin: 0 0 4px;
}

.map-detail p:last-child {
  margin-bottom: 0;
}

.map-detail #map-detail-close {
  float: right;
}

.map-detail-form {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}

.map-detail-form .mini-input {
  flex: 1;
}

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 2px;
  border-left: 5px solid var(--accent);
  padding: 12px 14px;
}

/* Travel legs (drive/ferry) are connectors between stops, not destinations
   themselves — visually lighter (no panel fill) than anchor cards. */
.card--travel {
  padding: 9px 14px;
  background: transparent;
}

.card--travel .title-input {
  font-size: 0.9rem;
  color: var(--sub);
}

/* EV charge stops are brief functional waypoints, not places to linger. */
.card--compact {
  padding: 9px 14px;
}

/* Start/Finish are structural bookends, but styled like a stay card (see
   card--anchor) so they read as real places — only the icon badge differs. */

.icon-badge {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: var(--ink);
  border-radius: 2px;
}

.card__row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.card__title {
  flex: 1;
  font-weight: 700;
}

.card__endpoint-label {
  font-weight: 700;
  flex-shrink: 0;
  white-space: nowrap;
}

.title-input {
  flex: 1;
  font-weight: 700;
  background: none;
  border: none;
  border-bottom: 1px solid transparent;
  color: var(--text);
  font-size: 1rem;
  padding: 2px 0;
}

.title-input:focus {
  outline: none;
  border-bottom-color: var(--border);
}

.card__route-title {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.card__route-title .title-input {
  flex: 1;
  min-width: 0;
}

.card__route-arrow {
  color: var(--sub);
  flex-shrink: 0;
}

.card__icon-btn {
  background: none;
  border: none;
  color: var(--sub);
  cursor: pointer;
  font-size: 0.9rem;
}

.card__sub {
  color: var(--sub);
  font-size: 0.85rem;
  margin-top: 4px;
}

.location-warning {
  color: var(--cat-utility);
  font-size: 0.7rem;
  margin-top: 2px;
}

.card__vibe {
  margin-top: 8px;
}

.card__vibe-text {
  display: block;
  width: 100%;
  font-style: italic;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
  font-size: 0.95rem;
  line-height: 1.4;
  margin: 0 0 6px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 2px;
  resize: vertical;
}

/* Reserves the title row's height when the description is toggled off,
   so the card doesn't visually jump as the global show/hide checkboxes
   are flipped. */
.card__title-spacer {
  flex: 1;
  min-height: 1.4em;
}

.card__notes {
  display: block;
  width: 100%;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
  font-size: 0.85rem;
  margin-top: 10px;
  padding: 5px 8px;
  border: 1px solid var(--border);
  border-radius: 2px;
  resize: vertical;
}

.card__add-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.card__grid {
  display: grid;
  /* minmax(0, 1fr), not plain 1fr — grid columns otherwise refuse to
     shrink below their content's intrinsic width (a number input's
     default min-content size), which is what was pushing fields past
     the edge of the screen on mobile. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 6px;
  margin-top: 10px;
}

.mini-input--full {
  display: block;
  width: 100%;
  margin-top: 10px;
}

.mini-input {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 4px 6px;
  font-size: 0.85rem;
}

.mini-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--sub);
}

.chip {
  background: var(--btn-bg);
  border: 1px solid var(--border);
  color: var(--sub);
  border-radius: 2px;
  padding: 4px 9px;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
}

.chip:hover {
  border-color: var(--text);
  color: var(--text);
}

.chip--active {
  background: var(--cat-stay);
  color: var(--ink);
  border-color: var(--cat-stay);
}

/* Needs the user's action, not just informational — "recalculate route"
   and "recalculate all routes". Same neutral background as a plain chip
   (e.g. "+ stay here") rather than a solid fill, so it doesn't shout —
   just the drive icon's own green for text/outline marks it as the one
   that needs attention. */
.chip--warn {
  background: var(--btn-bg);
  color: var(--cat-drive);
  border-color: var(--cat-drive);
  font-weight: 700;
}

.chip--warn:hover {
  background: var(--cat-drive);
  color: var(--ink);
}

.nights-stepper {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
}

.step-btn {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 2px;
  width: 22px;
  height: 22px;
  cursor: pointer;
}

.nights-label {
  font-size: 0.8rem;
  color: var(--sub);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.nights-number {
  color: var(--cat-stay);
  font-size: 1.05rem;
  font-weight: 800;
}

.chat-panel {
  max-width: 640px;
  margin: 0 auto 24px;
  padding: 0 16px;
}

.chat-messages {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 10px;
  margin-bottom: 8px;
  background: var(--panel);
}

.chat-message {
  font-size: 0.85rem;
  padding: 6px 10px;
  border-radius: 2px;
  max-width: 80%;
}

.chat-message--user {
  align-self: flex-end;
  background: var(--text);
  color: var(--ink);
}

.chat-message--assistant {
  align-self: flex-start;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
}

.chat-message--assistant p {
  margin: 0 0 6px;
}

.chat-message--assistant p:last-child {
  margin-bottom: 0;
}

.chat-message--assistant ul,
.chat-message--assistant ol {
  margin: 0 0 6px;
  padding-left: 1.2em;
}

.chat-message--assistant li {
  margin-bottom: 2px;
}

.chat-form {
  display: flex;
  gap: 8px;
}

.chat-form input {
  flex: 1;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 8px 10px;
}

.chat-form button {
  background: var(--text);
  color: var(--ink);
  border: none;
  border-radius: 2px;
  padding: 8px 14px;
  text-transform: uppercase;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  cursor: pointer;
}
