*, *::before, *::after { box-sizing: border-box; }

:root {
  --app-width:             480px;
  --color-hairline:        #e0e0e0; /* dividers */
  --color-hover-bg:        rgba(0, 0, 0, 0.07);
  --color-muted:           #888; /* secondary text + control borders */
  --color-page-bg:         #e0e0e0; /* same value as hairline, different semantics */
  --color-panel:           #f5f5f5;
  --color-bus:             #ffc72c;
  --color-green-line:      #00843d;
  --color-red-line:        #da291c;
  --color-orange-line:     #ed8b00;
  --color-blue-line:       #003da5;
  --color-silver-line:     #7c878e;
  --color-commuter-rail:   #80276c;
  --color-mattapan:        #da291c;
  --color-ferry:           #008eaa;
  --chip-opacity-min:      0.6;
  --radius:                4px;
}

#progress-bar {
  height: 2px;
  left: 50%;
  max-width: var(--app-width);
  overflow: hidden;
  position: fixed;
  top: 0;
  transform: translateX(-50%);
  width: 100%;
  z-index: 1000;
}

#progress-bar.loading::after {
  animation: progress-slide 1.2s ease-in-out infinite;
  background: var(--color-bus);
  content: "";
  height: 100%;
  position: absolute;
  top: 0;
  width: 40%;
}

@keyframes progress-slide {
  0%   { left: -40%; }
  100% { left: 100%; }
}

.overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  backdrop-filter: blur(6px) grayscale(80%);
  -webkit-backdrop-filter: blur(6px) grayscale(80%);
  background: rgba(0, 0, 0, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
}

body {
  font-family: 'Inter', system-ui, sans-serif;
  margin: 0;
  background: var(--color-page-bg);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.panel {
  background: var(--color-panel);
  display: flex;
  flex-direction: column;
  max-width: var(--app-width);
  min-height: 100dvh;
  width: 100%;
}

.app-footer {
  color: #aaa;
  font-size: 0.7rem;
  margin-top: auto;
  padding: 1rem 0.75rem;
  text-align: center;
}

.app-footer a {
  border-bottom: 1px solid var(--color-hairline);
  color: #999;
  text-decoration: none;
}

.app-footer a:hover {
  color: #777;
}

#toast {
  width: 100%;
  max-width: var(--app-width);
  background: #fde8e8;
  color: #7f1d1d;
  border-bottom: 1px solid #fca5a5;
  padding: 0.6rem 0.75rem;
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

#toast[hidden] { display: none; }

#dismiss-toast {
  align-items: center;
  color: #991b1b;
  display: flex;
  height: 1rem;
  flex-shrink: 0;
  padding-left: 1rem;
}

.error { color: red; margin: 1rem; }

.app-header {
  align-items: center;
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem 0.75rem 0.5rem;
}

.app-title {
  flex-shrink: 0;
  margin: 0;
}

.app-title, .overlay-label {
  background: white;
  border-radius: 8px;
  border: 1px solid black;
  cursor: pointer;
  font-size: 1.2rem;
  font-weight: 800;
  padding: 0 0.35rem;
}

.app-info {
  font-size: 0.7rem;
  color: var(--color-muted);
}

.icon {
  height: 1em;
  width: 1em;
}

.routes-page {
  display: flex;
  flex-direction: column;
  margin-bottom: 4rem;
}

.route-cards {
  display: flex;
  flex-direction: column;
  transition: opacity 0.2s ease;

  &.stale {
    opacity: 0.5;
  }
}

.destination-control {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.25rem 0.75rem;
}

.destination-input-row {
  align-items: center;
  border: 1px solid var(--color-muted);
  border-radius: var(--radius);
  display: flex;
  gap: 0.5rem;
  padding: 0.25rem 0.5rem;

  /* Lift to white while the user is actually typing; quiet panel grey otherwise */
  &:focus-within {
    background: white;
  }
}

.destination-input {
  background: transparent;
  border: none;
  flex-grow: 1;
  font-size: 16px; /* anything smaller and iOS Safari zooms on focus */
  outline: none;
  padding: 0;
}

.destination-input-spinner {
  animation: spinner-rotate 0.8s linear infinite;
  border: 2px solid var(--color-muted);
  border-radius: 50%;
  border-top-color: transparent;
  flex-shrink: 0;
  height: 0.7rem;
  width: 0.7rem;

  &[data-hidden] {
    visibility: hidden;
  }
}

@keyframes spinner-rotate {
  to { transform: rotate(360deg); }
}

.destination-input-clear {
  color: var(--color-muted);
  cursor: pointer;
  line-height: 1;

  &[data-hidden] {
    visibility: hidden;
  }
}

.destination-suggestions {
  background: white;
  border: 1px solid var(--color-muted);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.destination-suggestion {
  cursor: pointer;
  padding: 0.25rem 0.5rem;

  & + .destination-suggestion {
    border-top: 1px solid var(--color-hairline);
  }
}

.destination-suggestion-name {
  font-size: 0.8rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.destination-suggestion-detail {
  color: var(--color-muted);
  font-size: 0.7rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.destination-chip {
  align-items: center;
  border: 1px solid var(--color-muted);
  border-radius: var(--radius);
  cursor: pointer;
  display: flex;
  font-size: 0.8rem;
  gap: 0.5rem;
  padding: 0.25rem 0.5rem;
}

.destination-chip::after {
  color: var(--color-muted);
  content: "×";
}

.destination-chip-label {
  flex-grow: 1;
  /* let the name/detail lines inside ellipsize */
  min-width: 0;
}

.bucket-header {
  align-items: center;
  color: var(--color-muted);
  display: flex;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  padding: 0.2rem 0.75rem;
}

.route-card + .bucket-header {
  margin-top: 0.5rem;
}

.route-card + .route-card {
  margin-top: 0.5rem;
}

.route-card {
  border: 1px solid black;
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  margin: 0 0.75rem;
  overflow: hidden;
}

.route-card-cols {
  background: color-mix(in srgb, var(--line-bg-color) 20%, white);
  display: flex;
}

.route-card-col {
  display: flex;
  flex-basis: 0;
  flex-direction: column;
  flex-grow: 1;
  min-width: 0;

  & + .route-card-col {
    border-left: 1px solid var(--line-bg-color);
  }
}

.route-card-id {
  align-items: center;
  background: var(--line-bg-color);
  color: var(--line-fg-color);
  display: flex;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 0.05rem 0.25rem;
}

/* data-class carries the transit-line color wherever it appears (route cards, destination rows) */
[data-class="blue-line"]        { --line-bg-color: var(--color-blue-line);     --line-fg-color: #ffffff; }
[data-class="bus"]              { --line-bg-color: var(--color-bus);           --line-fg-color: #000000; }
[data-class="commuter-rail"]    { --line-bg-color: var(--color-commuter-rail); --line-fg-color: #ffffff; }
[data-class="ferry"]            { --line-bg-color: var(--color-ferry);         --line-fg-color: #ffffff; }
[data-class="green-line"]       { --line-bg-color: var(--color-green-line);    --line-fg-color: #ffffff; }
[data-class="mattapan-trolley"] { --line-bg-color: var(--color-mattapan);      --line-fg-color: #ffffff; }
[data-class="orange-line"]      { --line-bg-color: var(--color-orange-line);   --line-fg-color: #ffffff; }
[data-class="red-line"]         { --line-bg-color: var(--color-red-line);      --line-fg-color: #ffffff; }
[data-class="silver-line"]      { --line-bg-color: var(--color-silver-line);   --line-fg-color: #ffffff; }

/* A single button showing the current sort's icon (walking man = least walking, clock = arrive soonest); tapping
   switches modes. First child of .route-cards in destination mode; its margins keep the page's 0.5rem rhythm
   against the control above and the table below. */
.destination-sort {
  display: flex;
  margin: 0.25rem 0.75rem 0.5rem 0.75rem;
}

.destination-sort-button {
  align-items: center;
  border: 1px solid var(--color-muted);
  border-radius: var(--radius);
  color: var(--color-muted);
  cursor: pointer;
  display: inline-flex;
  font-size: 0.9rem;
  gap: 0.25rem;
  padding: 0.15rem 0.5rem;
}

.destination-sort-button:hover {
  background: var(--color-hover-bg);
  color: #111;
}

.destination-sort-label {
  font-size: 0.8rem;
}

/* One shared grid for the whole table, so the metric columns size to content and line up down the page (even
   across the separated cards). The two metric columns are auto (sized to their widest value); identity grows.
   row-gap matches the 0.5rem spacing between route cards on the non-destination page. */
.destination-table {
  column-gap: 0.4rem;
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  margin: 0 0.75rem;
  row-gap: 0.5rem;
}

/* Each row is its own card - 1px black border + radius, like a route card - washed the same light shade of its
   route color as .route-row. It's a subgrid spanning all three columns, so its cells align with every other
   row's. */
.destination-row {
  align-items: center;
  background: color-mix(in srgb, var(--line-bg-color) 20%, white);
  border: 1px solid black;
  border-radius: var(--radius);
  cursor: pointer;
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  /* The card's left/right edge inset. Inter-column spacing is the grid's column-gap; cells carry only vertical
     padding - so edges and all column gaps are one uniform 0.4rem instead of paddings that sum into gaps. */
  padding-inline: 0.4rem;
}

/* Metric cells take only their column's width, content centered */
.destination-cell {
  color: var(--color-muted);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  padding-block: 0.3rem;
  text-align: center;
  white-space: nowrap;
}

/* The first cell is the active sort key (the Elm orders it first) - normal text color so it reads as primary */
.destination-cell:first-child {
  color: inherit;
}

.destination-metric-walk {
  align-items: center;
  display: inline-flex;
  justify-content: center;
}

/* Route identity: a strong route-colored id badge, the headsign (which ellipsizes), then the chip right after it -
   like a .route-row, not right-aligned */
.destination-route {
  align-items: center;
  display: flex;
  gap: 0.3rem;
  min-width: 0;
  padding-block: 0.3rem;
}

.destination-route-id {
  background: var(--line-bg-color);
  border-radius: var(--radius);
  color: var(--line-fg-color);
  font-size: 0.8rem;
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  padding: 0 0.25rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Expanded trip flow. Spans the full row under the cells; only shown when expanded. A vertical list alternating
   leg durations (walk/ride) with stop and destination names. Two columns: a clock-time gutter (blank on duration
   rows) and the main content. */
.destination-timeline {
  display: none;
  grid-column: 1 / -1;
}

.destination-row[data-expanded] .destination-timeline {
  align-items: center;
  border-top: 1px solid var(--color-muted);
  color: var(--color-muted);
  column-gap: 0.5rem;
  display: grid;
  /* Time gutter (auto, sized to a stable "HH:MM") then the main column. The spine rail lives at the *start* of the
     main column, so it sits at a constant x regardless of name lengths; minmax min of 0 lets long names ellipsize. */
  grid-template-columns: auto minmax(0, 1fr);
  padding: 0.35rem 0;
  row-gap: 0.05rem;
}

.tl-time {
  color: var(--color-muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.tl-main {
  align-items: center;
  display: flex;
  font-size: 0.8rem;
  min-width: 0;
}

/* Fixed-width spine rail: every row centers its marker/bar here, so the spine is a vertical line at a constant x. */
.tl-rail {
  align-items: center;
  display: flex;
  flex: none;
  justify-content: center;
  width: 1rem;
}

/* Node marker (circleIcon is 1em, so font-size sets its diameter). */
.tl-node {
  display: flex;
  font-size: 0.6rem;
}

/* The gap from the rail to the label lives on the label, because it depends on the marker's width: a name must
   clear the fatter circle, while a duration can tuck right up against the thin bar. */
.tl-main > .tl-name {
  margin-left: 0.4rem;
}

.tl-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The stop count trails the ride's icon+minutes in a smaller font. */
.tl-stops {
  font-size: 0.7rem;
  padding-left: 0.3rem;
  white-space: nowrap;
}

/* Connector bars on the spine: route-colored around the ride, muted around the walk legs. The height spans taller
   than a node marker so the spine reads as one continuous line between node names. */
.tl-bar {
  border-radius: 1px;
  height: 3rem;
  width: 2px;
}

.tl-bar--route {
  background: var(--line-bg-color);
}

.tl-bar--muted {
  background: radial-gradient(var(--color-muted) 60%, transparent 65%);
  background-size: 100% 0.2rem; /* one dot every 0.2rem of height */
  background-repeat: repeat-y;
}

.route-row {
  align-items: center;
  background: color-mix(in srgb, var(--line-bg-color) 20%, white);
  cursor: pointer;
  display: flex;
  flex-direction: row;
  flex-grow: 0;
  gap: 0.3rem;
  padding: 0.25rem;

  &[data-expanded] {
    align-items: stretch;
    flex-direction: column;

    & .headsign {
      white-space: normal;
    }
  }

  & + .route-row {
    border-top: 1px solid var(--line-bg-color);
  }
}

.headsign {
  /* same height as chip */
  border-bottom-color: transparent;
  border-bottom-style: solid;
  border-bottom-width: 1px;
  border-top-color: transparent;
  border-top-style: solid;
  border-top-width: 1px;
  font-size: 0.8rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.route-stop {
  color: var(--color-muted);
  display: none;
  font-size: 0.8rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.route-row[data-expanded] .route-stop {
  display: block;
  white-space: normal;

  & .route-stop-name {
    vertical-align: middle;
  }

  & .walk-time {
    vertical-align: middle;
  }
}

.route-alight {
  color: var(--color-muted);
  display: none;
  font-size: 0.8rem;

  & .route-alight-name {
    vertical-align: middle;
  }

  & .walk-time {
    vertical-align: middle;
  }
}

.route-row[data-expanded] .route-alight {
  display: block;
}

.route-times {
  display: contents;
}

.route-times > .chip {
  order: 1;
}

.chips-extra {
  display: flex;
  flex: 1 0 0;
  gap: 0.3rem;
  mask-image: linear-gradient(to right, black calc(100% - 2rem), transparent 100%);
  order: 2;
  overflow: hidden;
}

.route-row[data-expanded] .route-times {
  display: flex;
  flex-wrap: wrap;
  flex: 0 0 auto;
  gap: 0.3rem;
  margin-top: 0.15rem;
  overflow: visible;
}

.route-row[data-expanded] .route-times > .chip {
  order: 0;
}

.route-row[data-expanded] .chips-extra {
  display: contents;
}

.chip {
  align-items: center;
  background: color-mix(in srgb, var(--line-bg-color) 10%, white);
  border-radius: var(--radius);
  border: 1px solid var(--color-muted);
  display: inline-flex;
  flex-shrink: 0;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  justify-content: center;
  min-width: 3ch;
  padding: 0 0.15rem;
  white-space: nowrap;

  &[data-state="urgent"] .chip-relative {
    font-weight: 300;
  }
}

.chip-absolute {
  display: none;
}

.route-row[data-expanded] .chip-absolute {
  display: inline;
}

.route-row[data-expanded] .chip-absolute,
.trip-stop-time {
  color: #999;
  font-size: 0.8em;
}

.route-row[data-expanded] .chip {
  gap: 0.25rem;
}

.trip-stops {
  display: grid;
  grid-template-columns: 1fr auto auto;
  margin: 0.5rem 0.75rem 4rem 0.75rem;
}

.trip-stop {
  align-items: center;
  border-bottom: 1px solid var(--color-hairline);
  column-gap: 0.5rem;
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  padding: 0.25rem;
}

.trip-stop--past {
  opacity: 0.35;
}

.trip-stop--mine {
  & .trip-stop-name, & .trip-stop-wait {
    font-weight: 600;
  }
}

.trip-stop-left {
  align-items: center;
  display: flex;
  gap: 0.25rem;
  min-width: 0;
}

.trip-stop-name {
  flex: 0 1 auto;
  font-size: 0.9rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.trip-stop-expander {
  border-bottom: 1px solid var(--color-hairline);
  color: #aaa;
  cursor: pointer;
  font-size: 0.8rem;
  grid-column: 1 / -1;
  padding: 0.35rem 0.25rem;
  text-align: center;
}

.trip-stop-expander:hover {
  background: var(--color-hover-bg);
  color: #111;
}

.trip-stop-wait {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.trip-stop-time {
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.walk-speed-control {
  align-items: center;
  color: var(--color-muted);
  display: flex;
  font-size: 0.7rem;
  gap: 0.25rem;
  margin-left: auto;
}

.walk-speed-btn {
  cursor: pointer;
  display: flex;
  font-size: 1rem;
  user-select: none;
  border: 1px solid var(--color-muted);
  width: 1.4rem;
  height: 1.4rem;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
}

.walk-speed-btn:hover:not(.walk-speed-btn--disabled) {
  background: var(--color-hover-bg);
  color: #111;
}

.walk-speed-btn--disabled {
  color: #ccc;
  cursor: default;
}

.walk-speed-value {
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.walk-time {
  align-items: center;
  color: var(--color-muted);
  display: inline-flex;
  font-size: 0.8rem;
  vertical-align: middle;
  white-space: nowrap;
}

.cursor-pointer {
  cursor: pointer;
}

.display-none {
  display: none;
}

.invisible {
  visibility: hidden;
}
