/* Dotsie design system — components v14.0.0
 * Requires tokens.css. Every color, font, radius and duration comes from a token; no literal colors.
 * Naming: .wt-<component>, .wt-<component>__<part>, .wt-<component>--<variant>, .is-<state>. */

/* ---------- Base ---------- */
.wt-base {
  margin: 0;
  font: var(--wt-type-body);
  color: var(--wt-text-primary);
  background: var(--wt-surface-page);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
.wt-base *, .wt-base *::before, .wt-base *::after { box-sizing: border-box; }
.wt-icon { flex: none; display: block; }
/* Bold in running text is semibold, never 700: emphasis without the glare. Components set their own weights. */
.wt-base :where(b, strong) { font-weight: 600; }
.wt-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:where(.wt-btn, .wt-icon-btn, .wt-avatar-stack, .wt-toast__action, .wt-sheet__grab, .wt-picker, .wt-option, .wt-search__clear, .wt-search-bar__cancel, .wt-link-add) {
  font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; text-align: left;
}
:where(.wt-btn, .wt-icon-btn, .wt-tl-drive, .wt-tl-day, .wt-trip-card, .wt-avatar-stack, .wt-sheet__grab, .wt-picker, .wt-option, .wt-search__clear, .wt-search-bar__cancel):focus-visible {
  outline: 2px solid var(--wt-border-focus);
  outline-offset: 2px;
  border-radius: var(--wt-radius-md);
}
:where(.wt-btn, .wt-icon-btn):disabled { opacity: .35; cursor: default; }
a:where(.wt-btn, .wt-icon-btn, .wt-trip-card) { color: inherit; text-decoration: none; }

/* ---------- Button ---------- */
.wt-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--wt-size-touch); padding: 0 18px;
  border-radius: var(--wt-radius-pill);
  font: var(--wt-type-label); font-size: 15px; white-space: nowrap;
}
/* The one main action in a view is the only button in semibold; every other button is medium. */
.wt-btn--primary { background: var(--wt-action-primary); color: var(--wt-action-primary-text); font-weight: 600; }
/* Every other button is the same white, outlined button: Copy, Make a new link, Sign out, Delete trip.
   --danger is that button with a red label, for an action that destroys something. */
.wt-btn--secondary, .wt-btn--danger {
  background: var(--wt-action-secondary); color: var(--wt-action-secondary-text);
  border-radius: var(--wt-radius-md); box-shadow: 0 0 0 1px var(--wt-border-subtle), var(--wt-shadow-hairline);
}
.wt-btn--danger { color: var(--wt-text-danger); }
.wt-btn--secondary:active, .wt-btn--danger:active { background: var(--wt-surface-hover); }
.wt-btn--block { width: 100%; }
/* Icon only: a round button as tall as the others, like Edit stop and the + beside Open in Maps. Give it an aria-label. */
.wt-btn--icon { width: var(--wt-size-touch); padding: 0; flex: none; border-radius: var(--wt-radius-round); }
.wt-btn .wt-icon { width: 18px; height: 18px; }
/* Unavailable for now, such as adding a stop while offline: grey, with no shadow, but still tappable, so a tap can say why.
   Use aria-disabled="true", not disabled, which would swallow the tap. */
.wt-btn[aria-disabled="true"], .wt-btn[aria-disabled="true"]:active { background: var(--wt-surface-sunken); color: var(--wt-text-tertiary); box-shadow: none; font-weight: 500; cursor: default; }

/* ---------- Icon button ---------- */
.wt-icon-btn {
  width: var(--wt-size-icon-btn); height: var(--wt-size-icon-btn); flex: none;
  display: grid; place-items: center; border-radius: var(--wt-radius-round);
}
.wt-icon-btn:active { background: var(--wt-surface-hover); }
.wt-icon-btn:focus-visible { border-radius: var(--wt-radius-round); }

/* ---------- Avatar ---------- */
.wt-avatar {
  position: relative; overflow: hidden;
  width: var(--wt-size-avatar); height: var(--wt-size-avatar); flex: none;
  display: grid; place-items: center; border-radius: var(--wt-radius-round);
  background: var(--wt-avatar-color, var(--wt-identity-1)); color: var(--wt-identity-text);
  font: var(--wt-type-micro); font-weight: 600;
}
/* A photo covers the initial; the initial stays underneath as the fallback. */
.wt-avatar__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* "+2": the rest of a stack that's out of room */
.wt-avatar--more { --wt-avatar-color: var(--wt-surface-hover); color: var(--wt-text-secondary); }
.wt-avatar-stack { display: flex; align-items: center; padding: 6px var(--wt-space-1); flex: none; }
.wt-avatar-stack .wt-avatar { margin-left: -6px; box-shadow: 0 0 0 2px var(--wt-avatar-ring, var(--wt-surface-sheet)); }
.wt-avatar-stack .wt-avatar:first-child { margin-left: 0; }

/* ---------- Form ---------- */
.wt-field { display: block; margin-top: var(--wt-space-3); }
.wt-field[hidden] { display: none; } /* display: block would otherwise show a field marked hidden */
.wt-field__label { display: block; margin-bottom: var(--wt-space-1); font: var(--wt-type-caption); color: var(--wt-text-secondary); }
.wt-input {
  display: block; width: 100%; padding: var(--wt-space-3);
  font: var(--wt-type-input); color: var(--wt-text-primary);
  background: var(--wt-surface-sunken); border: 1px solid var(--wt-border-default); border-radius: var(--wt-radius-md);
  outline: none; transition: border-color var(--wt-duration-fast), background var(--wt-duration-fast);
}
.wt-input::placeholder { color: var(--wt-text-placeholder); }
.wt-input:focus { border-color: var(--wt-border-focus); background: var(--wt-surface-raised); }
textarea.wt-input { resize: none; }
/* Date and time fields: iPhone Safari draws them its own way, centred and wider than width: 100% allows, so they run
   off the sheet's edge. Drawn like any other field, they fit, read from the left, and keep the field height when empty. */
input.wt-input:is([type="date"], [type="time"], [type="datetime-local"]) { min-width: 0; max-width: 100%; min-height: 50px; }
@supports (-webkit-touch-callout: none) {
  input.wt-input:is([type="date"], [type="time"], [type="datetime-local"]) { -webkit-appearance: none; appearance: none; }
}
.wt-input::-webkit-date-and-time-value { text-align: left; margin: 0; }
/* A stop's links in its sheet (.wt-link-list): a row each, drawn like an input, with the link's label over its address
   and a remove button, then Add link under them. Both inputs are the input's 16px, so a phone doesn't zoom in on them. */
.wt-link-list { display: grid; gap: var(--wt-space-2); margin-bottom: var(--wt-space-1); }
.wt-link-list:empty { display: none; }
.wt-link-edit {
  display: flex; align-items: center; gap: var(--wt-space-1); padding: 0 var(--wt-space-1) 0 var(--wt-space-3);
  background: var(--wt-surface-sunken); border: 1px solid var(--wt-border-default); border-radius: var(--wt-radius-md);
  transition: border-color var(--wt-duration-fast), background var(--wt-duration-fast);
}
.wt-link-edit:focus-within { border-color: var(--wt-border-focus); background: var(--wt-surface-raised); }
.wt-link-edit__fields { flex: 1; min-width: 0; display: grid; gap: 2px; padding: 9px 0; }
.wt-link-edit input { display: block; width: 100%; min-width: 0; padding: 0; border: 0; background: none; outline: none; font: var(--wt-type-input); }
.wt-link-edit__label { color: var(--wt-text-primary); }
.wt-link-edit__url { color: var(--wt-text-secondary); }
.wt-link-edit input::placeholder { color: var(--wt-text-placeholder); }
.wt-link-edit__remove { color: var(--wt-text-secondary); }
.wt-link-add { display: inline-flex; align-items: center; gap: 6px; height: var(--wt-size-touch); padding: 0 var(--wt-space-1) 0 0; font: var(--wt-type-label); font-size: 15px; color: var(--wt-text-link); border-radius: var(--wt-radius-md); }
.wt-link-add[hidden] { display: none; }
.wt-link-add .wt-icon { width: 18px; height: 18px; }
.wt-link-add:focus-visible { outline: 2px solid var(--wt-border-focus); outline-offset: 2px; }

/* A field with a fixed part before its input, like check-out's day before its time. The whole box is a label, so
   tapping anywhere in it opens the input. */
.wt-input-group { display: flex; align-items: center; gap: var(--wt-space-2); min-height: 50px; padding-top: 0; padding-bottom: 0; cursor: text; }
.wt-input-group:focus-within { border-color: var(--wt-border-focus); background: var(--wt-surface-raised); }
.wt-input-group > input {
  flex: 1; min-width: 0; width: 100%; min-height: 48px; padding: 0; margin: 0;
  font: inherit; color: inherit; background: none; border: 0; outline: none; -webkit-appearance: none; appearance: none;
}
/* On a touch screen, tapping the field opens the picker, so its icon only takes room from the time */
@media (pointer: coarse) { .wt-input-group > input::-webkit-calendar-picker-indicator { display: none; } }
/* ---------- Search field: a search icon, the input, then a spinner while it looks and a clear button ---------- */
/* An .wt-input-group, so tapping anywhere in it focuses the input. It heads a search page (.wt-search-bar). */
.wt-search { padding-left: var(--wt-space-3); padding-right: var(--wt-space-1); }
/* The icon sits over the results' markers, and the typed text starts where their names do: the icon's centre is the
   marker's (half a 30px marker in from the row's padding), and 9px more than the group's gap clears it the way a marker's gap does. */
.wt-search > .wt-icon:first-child { width: 20px; height: 20px; margin-right: 9px; color: var(--wt-text-secondary); }
.wt-search__clear { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: var(--wt-radius-round); color: var(--wt-text-secondary); }
.wt-search__clear .wt-icon { width: 18px; height: 18px; }
@media (hover: hover) { .wt-search__clear:hover { background: var(--wt-surface-hover); color: var(--wt-text-primary); } }
.wt-search__clear[hidden], .wt-spinner[hidden] { display: none; }
.wt-spinner {
  flex: none; display: block; width: 18px; height: 18px; margin: 0 11px; border-radius: var(--wt-radius-round);
  border: 2px solid var(--wt-border-default); border-top-color: var(--wt-text-secondary); animation: wt-spin .7s linear infinite;
}
@keyframes wt-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .wt-spinner { animation-duration: 2.4s; } }

/* ---------- Search page: a field picked by searching, as in a maps app ---------- */
/* The form shows the choice as a row (.wt-picker--text); tapping it opens a page in the sheet: the search bar
   (field, then Cancel) stays at the top, and the results fill the page under it. Picking one comes back.
   While it's open, the sheet takes the whole screen on a phone (.wt-modal.is-full), so the results show above
   the keyboard. */
.wt-search-bar {
  position: sticky; z-index: 1; top: calc(-1 * var(--wt-modal-pad-top));
  display: flex; align-items: center; gap: var(--wt-space-2);
  margin: calc(-1 * var(--wt-modal-pad-top)) calc(-1 * var(--wt-modal-pad-x)) 0;
  padding: calc(var(--wt-modal-pad-top) + var(--wt-space-2)) var(--wt-modal-pad-x) var(--wt-space-2);
  background: var(--wt-surface-raised);
}
.wt-search-bar > .wt-search { flex: 1; min-width: 0; }
.wt-search-bar__cancel { flex: none; padding: var(--wt-space-2) 0 var(--wt-space-2) var(--wt-space-1); font: var(--wt-type-label); color: var(--wt-text-primary); }
/* Results: options (.wt-option), or one message saying what happened and what to try. The rows share the field's
   edges, so each marker sits under the search icon and each name starts where the typed text does. */
.wt-results__msg { padding: var(--wt-space-3) 0; font: var(--wt-type-caption); color: var(--wt-text-secondary); }
.wt-results__msg b { display: block; font: var(--wt-type-body); font-weight: 500; color: var(--wt-text-primary); }
/* Before anything's typed, a page can suggest places under a heading that says why (On the way to Las Vegas) */
.wt-results__head { padding: var(--wt-space-3) 0 var(--wt-space-1); font: var(--wt-type-caption-strong); color: var(--wt-text-secondary); }
.wt-copy-row { display: flex; gap: var(--wt-space-2); }
.wt-copy-row .wt-input { font-size: 14px; color: var(--wt-text-secondary); min-width: 0; }

/* ---------- People list ---------- */
.wt-people { list-style: none; margin: var(--wt-space-4) 0 0; padding: 0; }
.wt-people__item { display: flex; align-items: center; gap: var(--wt-space-3); padding: 6px 0; }
.wt-people__meta { color: var(--wt-text-secondary); }

/* ---------- Section: a settings sheet is a column of sections ---------- */
/* Trip settings and Account. Each section is one thing: a title, then a line on what it does (__text), then its
   controls, then a hint under a control (__hint) or a text button. Hairlines divide the sections, and every section
   has the same rhythm, so the sheet reads top to bottom with nothing to tell apart but the words. A section can be
   the <form> of its field, with its title as the field's <label>. */
.wt-section { padding: var(--wt-space-5) 0; }
.wt-section + .wt-section { border-top: 1px solid var(--wt-border-default); }
.wt-modal__head + .wt-section { padding-top: var(--wt-space-2); }
.wt-section > * { margin: var(--wt-space-3) 0 0; }
.wt-section > :first-child { margin-top: 0; }
.wt-section[hidden], .wt-section > [hidden] { display: none; }
.wt-section__title { display: block; font: var(--wt-type-heading); color: var(--wt-text-primary); }
.wt-section > .wt-section__text { margin-top: var(--wt-space-1); }
.wt-section__text { color: var(--wt-text-secondary); }
.wt-section > .wt-section__hint { margin-top: var(--wt-space-2); }
.wt-section__hint { font: var(--wt-type-caption); color: var(--wt-text-secondary); }
.wt-section > .wt-btn { display: flex; width: fit-content; }
.wt-section > .wt-btn--block { width: 100%; }
.wt-section > .wt-people { margin-top: var(--wt-space-2); }
.wt-section > .wt-field { margin-top: var(--wt-space-3); }
.wt-section > .wt-section__title + .wt-field, .wt-section > .wt-section__title + .wt-input, .wt-section > .wt-section__title + .wt-copy-row { margin-top: var(--wt-space-2); }

/* ---------- Marker: a stop's type icon on its type's color ---------- */
/* A stop's marker and pin are shaded from their own color (--wt-marker-fill), as a maps app's are: lighter and a touch
   richer at the top, darker at the bottom, one hue throughout (OKLCH relative colors). No white or black overlay, which
   greys the color. Where relative colors aren't supported, the marker is its flat color. */
.wt-marker, .wt-pin {
  --wt-marker-fill: var(--wt-kind-color, var(--wt-kind-place));
  --wt-marker-shade: linear-gradient(to bottom in oklab,
    oklch(from var(--wt-marker-fill) calc(l + var(--wt-marker-lift)) calc(c * var(--wt-marker-boost)) h),
    var(--wt-marker-fill) 50%,
    oklch(from var(--wt-marker-fill) calc(l - var(--wt-marker-sink)) c h));
}
/* The same marker in the list, on the map and in the day list, at different sizes. Set --wt-kind-color. */
.wt-marker {
  display: grid; place-items: center; flex: none; width: 30px; height: 30px; border-radius: var(--wt-radius-round);
  background-color: var(--wt-marker-fill); background-image: var(--wt-marker-shade); color: var(--wt-marker-ink);
}
.wt-marker .wt-icon { width: 16px; height: 16px; }
.wt-marker--sm { width: 20px; height: 20px; }
.wt-marker--sm .wt-icon { width: 12px; height: 12px; }
/* A way of getting there (Drive, Walk, Bike, Transit, Flight), as the list of them shows it: flat grey like a drive's car */
.wt-marker--travel { background-color: var(--wt-kind-drive); background-image: none; }

/* ---------- Timeline: rail · stop · time, with drives on the rail ---------- */
/* Rows touch and have no padding of their own, so the rail is one solid hairline down the day. Every line is a
   border (--wt-tl-line), never a background, so every line is the same width. It's a
   whole number of pixels: browsers round a 1.5px border down to 1px but snap a 1.5px background to 2px on a 3x screen. */
/* --wt-tl-pad: space above and below a stop's text. The marker sits on the name's first line. */
.wt-tl { --wt-tl-rail: 40px; --wt-tl-line: 2px; --wt-tl-pad: 12px; --wt-tl-mark-y: calc(var(--wt-tl-pad) + 10px); }
.wt-tl-rail { position: relative; align-self: stretch; }
.wt-tl-rail::before { content: ''; position: absolute; box-sizing: border-box; left: calc(50% - var(--wt-tl-line) / 2); top: 0; bottom: 0; width: var(--wt-tl-line); border-left: var(--wt-tl-line) solid var(--wt-border-rail); }
.wt-tl > :first-child .wt-tl-rail::before { top: var(--wt-tl-mark-y); }
.wt-tl > :last-child .wt-tl-rail::before { bottom: auto; height: var(--wt-tl-mark-y); }
.wt-tl > :only-child .wt-tl-rail::before { display: none; }

/* Stop: marker · name · time, and its notes on the next row, across the name and time columns, so a long note
   wraps to the row's full width and its right edge lines up with the times. The name is one line, cut off with an ellipsis. A hotel at either end of the day is the
   same row, with no time. The last row is the bottom padding, inside the grid so the rail runs through it. */
.wt-tl-stop {
  font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; text-align: left;
  width: 100%; display: grid; grid-template-columns: var(--wt-tl-rail) 1fr auto; grid-template-rows: auto auto auto var(--wt-tl-pad);
  border-radius: var(--wt-radius-md); transition: background var(--wt-duration-fast);
}
.wt-tl-stop:active { background: var(--wt-surface-hover); }
@media (hover: hover) { .wt-tl-stop:hover { background: var(--wt-surface-sunken); } }
.wt-tl-stop:focus-visible { outline: 2px solid var(--wt-border-focus); outline-offset: 2px; }
.wt-tl-stop.is-flash { animation: wt-flash var(--wt-duration-flash) ease-out; }
@keyframes wt-flash { from { background: var(--wt-highlight); } to { background: transparent; } }
.wt-tl-marker { position: absolute; z-index: 1; left: 50%; top: var(--wt-tl-mark-y); transform: translate(-50%, -50%); box-shadow: 0 0 0 3px var(--wt-tl-row, var(--wt-surface-raised)); }
.wt-tl-stop > .wt-tl-rail { grid-column: 1; grid-row: 1 / -1; }
.wt-tl-name {
  grid-column: 2; grid-row: 1; min-width: 0; padding: var(--wt-tl-pad) var(--wt-space-2) 0 0; font: var(--wt-type-name); line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wt-tl-notes { grid-column: 2 / -1; grid-row: 2; min-width: 0; display: grid; gap: 2px; padding: 3px var(--wt-space-3) 0 0; }
.wt-tl-note { font: var(--wt-type-caption); line-height: 19px; color: var(--wt-text-secondary); white-space: pre-line; overflow-wrap: anywhere; }
/* A link in a note: its site's name in blue, the one thing in the row that isn't the row's own tap. Regular weight:
   the blue says it's a link (see the README's rule on weight) */
.wt-tl-note a { color: var(--wt-text-link); text-decoration: none; }
/* A stop's links: a row of buttons under its notes, each its label (or the page's site) and an arrow that says it
   leaves the app. Outlined pills in link blue, 34px tall so a finger hits the one it means; they wrap onto more rows. */
.wt-tl-links { grid-column: 2 / -1; grid-row: 3; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; padding: var(--wt-space-2) var(--wt-space-3) 0 0; }
.wt-tl-link {
  display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; height: 34px; padding: 0 10px 0 12px;
  border-radius: var(--wt-radius-pill); background: var(--wt-surface-raised); box-shadow: 0 0 0 1px var(--wt-border-subtle), var(--wt-shadow-hairline);
  font: var(--wt-type-caption-strong); color: var(--wt-text-link); text-decoration: none; white-space: nowrap;
  transition: background var(--wt-duration-fast);
}
.wt-tl-link__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.wt-tl-link .wt-icon { flex: none; width: 13px; height: 13px; opacity: .8; }
.wt-tl-link:active { background: var(--wt-surface-hover); }
@media (hover: hover) { .wt-tl-link:hover { background: var(--wt-surface-sunken); } }
.wt-tl-link:focus-visible { outline: 2px solid var(--wt-border-focus); outline-offset: 2px; }
/* A link icon at the start of the notes' line, saying a stop has links: shown only where its buttons aren't (below). */
.wt-tl-links-hint { display: none; height: 19px; align-items: center; margin-right: 6px; vertical-align: top; color: var(--wt-text-tertiary); }
.wt-tl-links-hint .wt-icon { width: 14px; height: 14px; }
/* On a phone (the wt-trip container under 768px) a stop's notes are one line, run together with " · " and cut off
   with an ellipsis, so the half sheet fits a stop with its neighbors. The selected stop shows them in full. Its links
   too: the others show only a link icon, on the notes' line. */
@container wt-trip (max-width: 767px) {
  .wt-tl-stop:not(.is-selected) .wt-tl-notes { display: block; font: var(--wt-type-caption); line-height: 19px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .wt-tl-stop:not(.is-selected) .wt-tl-note { display: inline; white-space: nowrap; }
  .wt-tl-stop:not(.is-selected) .wt-tl-note + .wt-tl-note::before { content: ' · '; }
  .wt-tl-stop:not(.is-selected) .wt-tl-links { display: none; }
  .wt-tl-stop:not(.is-selected) .wt-tl-links-hint { display: inline-flex; }
}
.wt-tl-time { grid-column: 3; grid-row: 1; padding: calc(var(--wt-tl-pad) + 1px) var(--wt-space-3) 0 0; text-align: right; white-space: nowrap; font: var(--wt-type-time); font-variant-numeric: tabular-nums; color: var(--wt-text-secondary); }
.wt-tl-meridiem { font: var(--wt-type-micro); margin-left: 2px; color: var(--wt-text-tertiary); }
/* A stop's time zone ("EST"), after its time, only where the clocks change from the stop before */
.wt-tl-zone { font: var(--wt-type-micro); margin-left: 3px; color: var(--wt-text-tertiary); }
.wt-tl-time__day { display: block; font: var(--wt-type-caption); color: var(--wt-text-tertiary); }

/* Drive: a small grey car marker on the rail and "1 hr 49 min drive". Tapping it shows the route, and the add bar
   offers Directions.
   No top or bottom padding: it would leave a gap in the rail. Compact, about two-thirds of a stop, so a half sheet
   fits the selected stop with the stops before and after it: the stops are what you read, the drives join them. */
.wt-tl-drive {
  display: grid; grid-template-columns: var(--wt-tl-rail) 1fr auto; align-items: center;
  min-height: 32px; padding: 0 var(--wt-space-1) 0 0; border-radius: var(--wt-radius-md); cursor: pointer;
  transition: background var(--wt-duration-fast);
}
/* The car is a marker like a stop's, smaller and grey, sitting on the rail. */
.wt-tl-car {
  position: absolute; z-index: 1; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 20px; height: 20px; display: grid; place-items: center; border-radius: var(--wt-radius-round);
  background-color: var(--wt-kind-drive); color: var(--wt-marker-ink);   /* flat: no gloss, so a drive stays quieter than a stop */
}
.wt-tl-car .wt-icon { width: 13px; height: 13px; }
/* The row itself takes no hover or press look: only its Directions button reads as a control. */
.wt-tl-drive__body { min-width: 0; display: grid; gap: 1px; }
.wt-tl-drive__what, .wt-tl-drive__late { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The quietest text in the list: tertiary ink, the duration a step darker and medium. Stop names stay the strongest. */
.wt-tl-drive__what { font: var(--wt-type-caption); color: var(--wt-text-tertiary); }
.wt-tl-drive__what b { font-weight: 500; color: var(--wt-text-secondary); }
.wt-tl-drive__late { font: var(--wt-type-caption-strong); color: var(--wt-text-danger); }
.wt-tl-drive.is-late .wt-tl-drive__what b { color: var(--wt-text-danger); }

/* The list ranks what it shows by ink and color, loudest first: what needs fixing (red), where you are now (the
   blackest ink), what kind of place a stop is (its type color), then the rest by ink, and what's over (grey). No blue:
   blue is the map's routes, and links. --wt-tl-row is the row's background, which the marker's ring matches so the
   marker sits cleanly on the rail.

   One highlighted row at most, a grey background the same for stops and drives: the selected row (a stop tapped or
   picked on the map, or a drive whose route is shown), or, when nothing is selected, the row happening now. Its text
   steps up one ink: tertiary turns secondary, which also keeps it at 4.5:1 on the darker grey. */
.wt-tl :is(.is-selected, .is-active),
.wt-tl:not(:has(.is-selected, .is-active)) .is-now { --wt-tl-row: var(--wt-surface-current); background: var(--wt-tl-row); --wt-text-tertiary: var(--wt-text-secondary); }
.wt-tl-stop:active { --wt-text-tertiary: var(--wt-text-secondary); }
/* Selected: its time or drive time turns primary, and a drive's car a darker grey. */
.wt-tl .wt-tl-stop.is-selected .wt-tl-time { color: var(--wt-text-primary); }
.wt-tl .wt-tl-drive.is-active { --wt-kind-drive: var(--wt-kind-drive-current); }
.wt-tl .wt-tl-drive.is-active .wt-tl-drive__what b { color: var(--wt-text-primary); }

/* Now: on today, the row you're in takes the blackest ink (--wt-now), whether or not something else is selected, so you
   can always find where the day is: a black ring around the stop's marker, or a black car on the drive, and its time or
   drive time in primary ink. */
.wt-tl .is-now :is(.wt-tl-time, .wt-tl-drive__what b) { color: var(--wt-text-primary); }
.wt-tl .wt-tl-stop.is-now .wt-tl-marker { box-shadow: 0 0 0 3px var(--wt-tl-row, var(--wt-surface-raised)), 0 0 0 5px var(--wt-now); }
.wt-tl .wt-tl-drive.is-now { --wt-kind-drive: var(--wt-now); }

/* Doesn't fit: louder than anything else in the list. The car turns red as well as the text, so a drive that won't make
   it shows on the rail when you run your eye down it. */
.wt-tl .wt-tl-drive.is-late { --wt-kind-drive: var(--wt-danger); }
.wt-tl .wt-tl-drive.is-late .wt-tl-drive__what b { color: var(--wt-text-danger); }

/* What's over: the color drains out. Every ink in the row becomes the fourth, --wt-text-past (links too), and markers
   and cars turn grey (--wt-kind-past), solid so the rail doesn't show through them. Inks from the scale rather than
   opacity, so a faded row is the same grey on any background. A late drive that's over isn't red any more: there's
   nothing left to fix. The drive whose route is on show keeps its blue car. */
.wt-tl .is-past {
  color: var(--wt-text-past);
  --wt-text-primary: var(--wt-text-past); --wt-text-secondary: var(--wt-text-past); --wt-text-tertiary: var(--wt-text-past); --wt-text-link: var(--wt-text-past);
}
.wt-tl .is-past .wt-tl-marker { background: var(--wt-kind-past); }   /* flat: what's over isn't shaded */
.wt-tl .is-past:not(.is-active) .wt-tl-car { background-color: var(--wt-kind-past); }
.wt-tl .wt-tl-drive.is-past.is-late :is(.wt-tl-drive__what b, .wt-tl-drive__late) { color: var(--wt-text-secondary); }

/* Day heading: the overview (every day on one page) puts each day's stops under the day's name. It's a label, not a
   name: small grey capitals from the list's left edge (where the markers start), so it never reads as a stop.
   Tapping it opens the day. It isn't on the rail: each day's rail runs from its first stop to its last. */
.wt-tl-day {
  font: inherit; color: var(--wt-text-secondary); background: none; border: 0; margin: 0; cursor: pointer; text-align: left;
  width: 100%; min-height: var(--wt-size-touch); display: grid; grid-template-columns: 1fr auto; align-items: end; gap: var(--wt-space-2);
  /* The text starts where the markers do; "View day" ends where the times do. */
  padding: 0 var(--wt-space-4) var(--wt-space-1) calc((var(--wt-tl-rail) - 30px) / 2);
  border-radius: var(--wt-radius-md); transition: background var(--wt-duration-fast);
}
.wt-tl > * + .wt-tl-day { margin-top: var(--wt-space-2); }
.wt-tl-day__name { min-width: 0; font: var(--wt-type-overline); letter-spacing: var(--wt-tracking-caps); text-transform: uppercase; overflow-wrap: anywhere; }
/* Said in words, in link blue, rather than with a ›, so it isn't one more arrow under the day bar's ‹ › */
.wt-tl-day__open { font: var(--wt-type-caption); color: var(--wt-text-link); white-space: nowrap; }
.wt-tl .wt-tl-day.is-past .wt-tl-day__open { color: var(--wt-text-secondary); }
.wt-tl-day:active { background: var(--wt-surface-hover); }
@media (hover: hover) { .wt-tl-day:hover { background: var(--wt-surface-sunken); } }
.wt-tl .wt-tl-day.is-past { color: var(--wt-text-past); }
.wt-tl-day + * .wt-tl-rail::before { top: var(--wt-tl-mark-y); }
.wt-tl > :has(+ .wt-tl-day) .wt-tl-rail::before { bottom: auto; height: var(--wt-tl-mark-y); }
.wt-tl-day + :is(:last-child, :has(+ .wt-tl-day)) .wt-tl-rail::before { display: none; }

/* ---------- Day tabs: Overview, then every day, at the top of the sheet ---------- */
/* Quiet on purpose: the day says where you are, so it stays below the plan. Each tab is --wt-type-context in tertiary ink;
   the open one is primary, with a short bar under it that slides to the next tab as the list is swiped. The row scrolls
   sideways (no scrollbar) and fades out at either edge with more days past it; the calendar button at its end stays put. */
.wt-day-bar { display: flex; align-items: center; }
.wt-day-bar[hidden] { display: none; }
.wt-day-tabs {
  position: relative; flex: 1; min-width: 0; display: flex; overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain;
  touch-action: pan-x; padding: 0 var(--wt-space-1);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--wt-space-3), #000 calc(100% - var(--wt-space-5)), transparent);
  mask-image: linear-gradient(to right, transparent, #000 var(--wt-space-3), #000 calc(100% - var(--wt-space-5)), transparent);
}
.wt-day-tabs::-webkit-scrollbar { display: none; }
.wt-day-tab {
  flex: none; height: var(--wt-size-touch); padding: 0 var(--wt-space-3); margin: 0; border: 0; background: none; cursor: pointer;
  font: var(--wt-type-context); color: var(--wt-text-tertiary); white-space: nowrap; transition: color var(--wt-duration-fast);
}
.wt-day-tab[aria-selected="true"] { color: var(--wt-text-primary); }
.wt-day-tab:focus-visible { outline: 2px solid var(--wt-border-focus); outline-offset: -4px; border-radius: var(--wt-radius-md); }
.wt-day-tabs__bar {
  position: absolute; left: 0; bottom: 0; width: 24px; height: 2px; border-radius: 1px; background: var(--wt-text-primary);
  pointer-events: none; transition: transform var(--wt-duration-base) var(--wt-ease-out);
}
.wt-day-bar__cal { flex: none; color: var(--wt-text-secondary); }
.wt-day-bar__cal[aria-expanded="true"] { color: var(--wt-text-primary); background: var(--wt-surface-hover); }

/* ---------- Day calendar: jump to any day of the trip ---------- */
/* Between the tabs and the list, when the calendar button is on. Its days are .wt-cal's: the open one black, today
   ringed, a dot under a day with stops. Days that aren't on the trip are spans in --wt-text-past. It takes the room it
   needs, up to all of the list's, and scrolls past that. */
.wt-day-cal { flex: 0 1 auto; min-height: 0; overflow-y: auto; padding: var(--wt-space-1) var(--wt-space-4) var(--wt-space-2); border-bottom: 1px solid var(--wt-border-default); }
.wt-day-cal[hidden] { display: none; }
.wt-day-cal__head { display: flex; align-items: center; justify-content: space-between; gap: var(--wt-space-2); min-height: var(--wt-size-touch); padding-left: var(--wt-space-2); }
.wt-day-cal__overview {
  height: var(--wt-size-touch); padding: 0 var(--wt-space-2); margin: 0 calc(-1 * var(--wt-space-2)) 0 0; border: 0; background: none;
  cursor: pointer; font: var(--wt-type-body); color: var(--wt-text-link); border-radius: var(--wt-radius-md);
}
.wt-day-cal__overview[aria-pressed="true"] { color: var(--wt-text-primary); font-weight: 600; }
.wt-day-cal__month { grid-column: 1 / -1; padding: var(--wt-space-2) 0 var(--wt-space-1) var(--wt-space-2); font: var(--wt-type-caption); color: var(--wt-text-secondary); }
.wt-day-cal .wt-cal__day { --wt-cal-size: 36px; }
.wt-day-cal span.wt-cal__day { color: var(--wt-text-past); cursor: default; }

/* ---------- Picker: a field that shows the current choice and opens the options on a page of their own ---------- */
/* Every choice from a list is one: a stop's Type (marker · Hotel · ›), Account's Maps app (--text: Google Maps · ›).
   On a phone, tapping it slides the sheet to the options, with a back button in the sheet's head (.wt-modal__head--sub);
   picking one applies it and comes back. On a computer the options drop down as a menu (.wt-menu, below).
   Never inline radios, selects or segmented controls between named choices. */
.wt-picker {
  /* 7px + the 1px border puts the marker and the chevron on the options' columns, so the row and the page it opens line up. */
  display: flex; align-items: center; gap: var(--wt-space-3); width: 100%; min-height: 50px; padding: 9px calc(var(--wt-space-2) - 1px);
  font: var(--wt-type-input); color: var(--wt-text-primary);
  background: var(--wt-surface-sunken); border: 1px solid var(--wt-border-default); border-radius: var(--wt-radius-md);
}
.wt-picker:active { background: var(--wt-surface-hover); }
.wt-picker__value { flex: 1; min-width: 0; }
/* A picker with no marker, whose value can have a second line: the place's name over its address */
.wt-picker--text { padding-left: var(--wt-space-3); }
.wt-picker--text .wt-picker__value { display: grid; }
.wt-picker__name, .wt-picker__detail { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wt-picker__detail { font: var(--wt-type-caption); color: var(--wt-text-secondary); }
.wt-picker > .wt-icon:last-child { width: 18px; height: 18px; color: var(--wt-text-tertiary); }

/* Menu: on a computer (768px and up), a picker's options drop down under it instead of taking over the sheet.
   The options page itself becomes the menu: it moves into the field, under the picker, and gets .wt-menu. Its
   Back head goes; a one-line intro stays, smaller. Rows are 36px, a mouse's size, not a finger's. */
.wt-field:has(> .wt-menu) { position: relative; }
.wt-menu {
  position: absolute; z-index: 2; top: calc(100% + var(--wt-space-1)); left: 0; right: 0;
  max-height: 360px; overflow-y: auto; padding: var(--wt-space-1);
  background: var(--wt-surface-raised); border-radius: var(--wt-radius-md);
  box-shadow: var(--wt-shadow-hairline), var(--wt-shadow-card);
}
.wt-menu[hidden] { display: none; }
.wt-menu > .wt-modal__head { display: none; }
.wt-menu > .wt-modal__text { margin: 0; padding: var(--wt-space-1) var(--wt-space-2) var(--wt-space-2); font: var(--wt-type-caption); }
.wt-menu .wt-option { min-height: 36px; padding-top: 4px; padding-bottom: 4px; }
.wt-menu .wt-option .wt-marker { transform: scale(.85); }
/* A picker that drops a menu down points down there: its › turns to ⌄ (the Place row, which opens a search page, keeps ›) */
@media (min-width: 768px) {
  .wt-picker[aria-haspopup] > .wt-icon:last-child { transform: rotate(90deg); }
}

/* ---------- When: a day and a time, picked in that order, as in a calendar app ---------- */
/* The row: two pickers side by side, the day taking the room and the time after it, with no chevrons
   ("Fri, Nov 20" · "1:00 PM"). Tapping the day opens the month (.wt-cal); picking a day goes on to the time (.wt-wheels),
   which Done sets. On a phone each is a page of the sheet (.wt-when-page), on a computer a menu under the row. */
.wt-when { display: flex; gap: var(--wt-space-2); }
.wt-when > .wt-picker { width: auto; font-variant-numeric: tabular-nums; }
.wt-when__date { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wt-when__time { flex: none; }
.wt-when > .wt-picker[aria-expanded="true"] { border-color: var(--wt-border-focus); background: var(--wt-surface-raised); }
/* Under the row, the clock its times are on: "Local time · Mountain Standard Time", quiet, with a › to change it.
   It opens a picker page (or menu) of every zone, searched by city or name (.wt-zone-search over its options). */
.wt-when__zone {
  display: flex; align-items: center; gap: 2px; min-height: 36px; margin: 2px 0 -6px; padding: 0 var(--wt-space-1) 0 0;
  font: var(--wt-type-caption); color: var(--wt-text-secondary); background: none; border: 0; cursor: pointer; text-align: left;
}
.wt-when__zone .wt-icon { flex: none; width: 14px; height: 14px; color: var(--wt-text-tertiary); }
@media (hover: hover) { .wt-when__zone:hover { color: var(--wt-text-primary); } }
.wt-when__zone:focus-visible { outline: 2px solid var(--wt-border-focus); outline-offset: 2px; border-radius: var(--wt-radius-sm); }
.wt-zone-search { margin: 0 0 var(--wt-space-2); }
.wt-menu .wt-zone-search { min-height: 40px; }
/* A label with something on its right: a hotel's nights beside Check-out */
.wt-field__label--split { display: flex; justify-content: space-between; gap: var(--wt-space-3); }
.wt-field__aside { color: var(--wt-text-secondary); }
.wt-when-page[hidden] { display: none; }
.wt-when-page__done { margin-top: var(--wt-space-4); }
/* As a page, it takes the bottom padding the stop sheet's sticky actions would, home indicator and all */
.wt-when-page:not(.wt-menu) { padding-bottom: calc(var(--wt-space-4) + env(safe-area-inset-bottom, 0px)); }
.wt-menu.wt-when-page { max-height: none; overflow: visible; padding: var(--wt-space-2); }
.wt-menu .wt-when-page__done { margin-top: var(--wt-space-2); min-height: 40px; }

/* Month: its name with ‹ › after it, the weekdays' letters, then its days. The day set is black, like the main
   button; today has a ring, like now in the timeline; a day with stops has a dot under its number. Days that can't be
   picked (a check-out more than 30 nights on) are light grey. */
.wt-cal__head { display: flex; align-items: center; gap: var(--wt-space-1); padding: 0 0 var(--wt-space-1) var(--wt-space-2); }
.wt-cal__month { flex: 1; font: var(--wt-type-name); }
.wt-cal__head .wt-icon-btn:disabled { opacity: .35; cursor: default; }
.wt-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.wt-cal__wd { height: 28px; display: grid; place-items: center; font: var(--wt-type-caption); color: var(--wt-text-tertiary); }
.wt-cal__day {
  --wt-cal-size: 40px;
  position: relative; display: grid; place-items: start center; height: calc(var(--wt-cal-size) + 8px); margin: 0; padding: 2px 0 0;
  font: var(--wt-type-body); font-variant-numeric: tabular-nums; color: var(--wt-text-primary);
  background: none; border: 0; cursor: pointer;
}
.wt-cal__n {
  display: grid; place-items: center; width: var(--wt-cal-size); height: var(--wt-cal-size); border-radius: var(--wt-radius-round);
  transition: background var(--wt-duration-fast);
}
.wt-cal__day:active .wt-cal__n { background: var(--wt-surface-hover); }
@media (hover: hover) { .wt-cal__day:hover:not(:disabled) .wt-cal__n { background: var(--wt-surface-sunken); } }
.wt-cal__day.has-stops::after {
  content: ''; position: absolute; left: 50%; bottom: 1px; width: 4px; height: 4px; margin-left: -2px;
  border-radius: var(--wt-radius-round); background: var(--wt-text-tertiary);
}
.wt-cal__day[aria-current="date"] .wt-cal__n { box-shadow: inset 0 0 0 1.5px var(--wt-now); }
.wt-cal__day[aria-pressed="true"] .wt-cal__n { background: var(--wt-surface-inverse); color: var(--wt-text-inverse); font-weight: 600; }
.wt-cal__day:disabled { color: var(--wt-text-past); cursor: default; }
.wt-cal__day:focus-visible { outline: none; }
.wt-cal__day:focus-visible .wt-cal__n { outline: 2px solid var(--wt-border-focus); outline-offset: 1px; }
.wt-menu .wt-cal__day { --wt-cal-size: 34px; }

/* Wheels: hour, minute and AM/PM, each a column that scrolls and snaps, the one set in the grey band across the
   middle (the grey of a selected row). Tap a value to bring it to the band; ↑ ↓ step it. */
.wt-wheels {
  --wt-wheel-item: 44px;
  position: relative; display: flex; justify-content: center; gap: var(--wt-space-2); height: calc(5 * var(--wt-wheel-item));
}
.wt-wheels::before {
  content: ''; position: absolute; left: 0; right: 0; top: calc(2 * var(--wt-wheel-item)); height: var(--wt-wheel-item);
  border-radius: var(--wt-radius-md); background: var(--wt-surface-current); pointer-events: none;
}
.wt-wheel {
  position: relative; width: 72px; height: 100%; overflow-y: auto; overscroll-behavior: contain;
  padding: calc(2 * var(--wt-wheel-item)) 0; scroll-snap-type: y mandatory; scrollbar-width: none; border-radius: var(--wt-radius-md);
}
.wt-wheel::-webkit-scrollbar { display: none; }
.wt-wheel:focus-visible { outline: 2px solid var(--wt-border-focus); outline-offset: -2px; }
.wt-wheel__item {
  height: var(--wt-wheel-item); display: grid; place-items: center; scroll-snap-align: center;
  font: var(--wt-type-input); font-size: 20px; font-variant-numeric: tabular-nums; color: var(--wt-text-tertiary);
  cursor: pointer; user-select: none; -webkit-user-select: none; transition: color var(--wt-duration-fast);
}
.wt-wheel__item.is-on { color: var(--wt-text-primary); font-weight: 500; }
.wt-menu .wt-wheels { --wt-wheel-item: 36px; }
.wt-menu .wt-wheel__item { font-size: 17px; }

/* ---------- Option: one row for every choice in a list, a place to go as much as a type to be ---------- */
/* marker · label over detail · check. Search results and the type list are both made of it, so a place and its
   type read the same everywhere: a result's marker is the type it will get. The grey row is "this one", as in
   the timeline: the one Return picks in a listbox (aria-selected), the one that's set in a radiogroup
   (aria-checked, with its check). Rows are at least a touch target tall. */
.wt-options { list-style: none; margin: 0; padding: 0; }
.wt-options__sep { height: 1px; margin: var(--wt-space-1) var(--wt-space-2); background: var(--wt-border-default); }
.wt-option {
  display: flex; align-items: center; gap: var(--wt-space-3); width: 100%; min-height: var(--wt-size-touch);
  padding: 6px var(--wt-space-2); border-radius: var(--wt-radius-md); font: var(--wt-type-body); color: var(--wt-text-primary);
  cursor: pointer; text-align: left; transition: background var(--wt-duration-fast);
}
.wt-option:active { background: var(--wt-surface-hover); }
@media (hover: hover) { .wt-option:hover { background: var(--wt-surface-sunken); } }
.wt-option__text { flex: 1; min-width: 0; display: grid; }
.wt-option__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wt-option__detail { font: var(--wt-type-caption); color: var(--wt-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A short value on the right, before the check: how long a way of getting there takes */
.wt-option__meta { flex: none; font: var(--wt-type-body); color: var(--wt-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The part of a result's name that matches what was typed */
.wt-option__match { background: none; color: inherit; font-weight: 600; }
/* Under suggestions, a link to more in another app (Places to eat nearby, in the maps app), in link blue */
.wt-results__more { display: inline-flex; align-items: center; gap: 4px; height: var(--wt-size-touch); margin-top: var(--wt-space-1); font: var(--wt-type-label); font-size: 15px; color: var(--wt-text-link); text-decoration: none; }
.wt-results__more[hidden] { display: none; }
.wt-results__more .wt-icon { width: 14px; height: 14px; }
@media (hover: hover) { .wt-results__more:hover { text-decoration: underline; } }
/* A word at the start of the detail that sets a result apart (On the way): in the name's ink, not a color */
.wt-option__tag { font-weight: 500; color: var(--wt-text-primary); }
.wt-option[aria-selected="true"], .wt-option[aria-checked="true"] { background: var(--wt-surface-current); }
.wt-option > .wt-icon:last-child { width: 18px; height: 18px; visibility: hidden; }
.wt-option[aria-checked="true"] > .wt-icon:last-child { visibility: visible; }

/* ---------- Trip header: home · trip name · settings ---------- */
/* A full row at the top of the trip screen, so the trip's name is always in view. On a phone it's a card floating
   over the map, like a maps app's from/to card; with the whole day showing (.is-docked) it spans the top, flat, and
   joins the list. Its bottom edge stays put either way. From 768px wide (the wt-trip container, below) it tops the side panel.
   It stays quiet, since the plan is what you read: 44px, a smaller name, grey icons, and floating, a frosted card
   with a light shadow that lets the map show through. */
.wt-trip-head {
  position: absolute; z-index: calc(var(--wt-z-sheet) + 1);
  top: calc(env(safe-area-inset-top, 0px) + var(--wt-space-2)); left: var(--wt-space-3); right: var(--wt-space-3);
  /* Home and settings are centred on the timeline's rail and Directions column, and the name starts where stop names do.
     Docked or in the side panel, the header loses its inset and gains it back as padding, so nothing in it moves. */
  height: var(--wt-size-trip-head); padding: 0 var(--wt-space-1) 0 0;
  display: flex; align-items: center; gap: 0;
  background: color-mix(in srgb, var(--wt-surface-raised) 80%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.4); backdrop-filter: blur(14px) saturate(1.4);
  border-radius: var(--wt-radius-lg); box-shadow: var(--wt-shadow-float);
  transition: top var(--wt-duration-base) var(--wt-ease-out), left var(--wt-duration-base) var(--wt-ease-out), right var(--wt-duration-base) var(--wt-ease-out),
    height var(--wt-duration-base) var(--wt-ease-out), padding var(--wt-duration-base) var(--wt-ease-out), border-radius var(--wt-duration-base), box-shadow var(--wt-duration-base);
}
.wt-trip-head.is-docked {
  top: 0; left: 0; right: 0; height: calc(var(--wt-size-trip-head) + var(--wt-space-2) + env(safe-area-inset-top, 0px));
  padding: calc(var(--wt-space-2) + env(safe-area-inset-top, 0px)) var(--wt-space-4) 0 var(--wt-space-3); border-radius: 0; box-shadow: 0 1px 0 var(--wt-border-default);
  background: var(--wt-surface-raised);
}
.wt-trip-head .wt-icon-btn { color: var(--wt-text-secondary); }
.wt-trip-head .wt-icon-btn .wt-icon { width: 20px; height: 20px; }
.wt-trip-head__name { flex: 1; min-width: 0; margin: 0; padding-right: var(--wt-space-1); font: var(--wt-type-context); color: var(--wt-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Offline status, between the name and settings: saved on this device or saving (quiet), or no connection (louder).
   Hidden when there's nothing to say. A tap explains it in a toast. */
.wt-trip-head .wt-trip-head__status { width: 36px; color: var(--wt-text-tertiary); }
.wt-trip-head .wt-trip-head__status .wt-icon { width: 18px; height: 18px; }
.wt-trip-head .wt-trip-head__status.is-offline { color: var(--wt-text-secondary); }
@media (hover: hover) { .wt-trip-head .wt-icon-btn:hover { background: var(--wt-surface-hover); } }

/* ---------- Bottom sheet (the list over the map) ---------- */
/* Two heights on a phone: half, the default, and full (.is-full: docked under the trip header). It never hides.
   Drag the top or the list to move it; tap the grab handle to switch. */
.wt-sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: var(--wt-z-sheet);
  display: flex; flex-direction: column;
  background: var(--wt-surface-raised); border-radius: var(--wt-radius-lg) var(--wt-radius-lg) 0 0; box-shadow: var(--wt-shadow-sheet);
  overflow: hidden;
  transition: height var(--wt-duration-base) var(--wt-ease-out), border-radius var(--wt-duration-base);
}
.wt-sheet.is-dragging { transition: none; }
/* Full: square and flush under the header, so the two read as one page: the trip, then the whole day. */
.wt-sheet.is-full { border-radius: 0; box-shadow: none; }
/* Below full, dragging the list moves the sheet (up first, then it scrolls once full), and the list can't be scrolled
   by hand at all, not by a finger, a wheel or a trackpad: the app scrolls it, to keep the focused row in the middle. */
.wt-sheet:not(.is-full) .wt-sheet__body { touch-action: none; overflow: hidden; }
/* Sideways is the app's at every height: a swipe turns the page (.wt-sheet__peek is the page coming in). */
.wt-sheet.is-full .wt-sheet__body { touch-action: pan-y; }
.wt-sheet__peek {
  position: absolute; left: 0; right: 0; overflow: hidden; pointer-events: none;
  padding: 0 var(--wt-space-3) var(--wt-space-3); background: var(--wt-surface-raised);
}
/* The grab handle sits in the top margin, over the day bar's top edge, rather than on a row of its own, as in a maps app's sheet.
   A hairline under the day bar divides it from the list (not when there's no day bar: an empty trip). */
.wt-sheet__top {
  position: relative; flex: none; min-height: 22px; touch-action: none; padding: 14px var(--wt-space-3) var(--wt-space-2) var(--wt-space-1);
  border-bottom: 1px solid var(--wt-border-default);
}
.wt-sheet__top:has(> .wt-day-bar[hidden]) { border-bottom: 0; padding-bottom: 0; }
/* The tabs' bar sits on the hairline under them */
.wt-sheet__top:has(> .wt-day-bar:not([hidden])) { padding-bottom: 0; }
/* The grab handle is a button as wide as the sheet, so it's easy to hit and nothing else on the sheet's top resizes it.
   The day tabs sit over its lower part, so a tap on a tab or the calendar is theirs. */
.wt-sheet__grab { position: absolute; top: 0; left: 0; right: 0; display: block; width: 100%; height: 16px; cursor: grab; }
/* Above the handle, but only its buttons take taps: a tap between them is the handle's. */
.wt-sheet__top .wt-day-bar { position: relative; pointer-events: none; }
.wt-sheet__top .wt-day-bar > * { pointer-events: auto; }
.wt-sheet__grab::before {
  content: ''; position: absolute; left: 50%; top: 6px; width: 36px; height: 4px; transform: translateX(-50%);
  border-radius: 2px; background: var(--wt-border-strong);
}
.wt-sheet__grab:focus-visible { border-radius: var(--wt-radius-md); }
.wt-sheet__body { flex: 1; min-height: 0; overflow: auto; padding: 0 var(--wt-space-3) var(--wt-space-3); overscroll-behavior: contain; }
/* More of the day above or below what's showing: the list fades out at that edge (.is-more-above, .is-more-below,
   set from the list's scroll position), so it's clear there are stops to scroll to. */
@property --wt-fade-top { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --wt-fade-bottom { syntax: '<length>'; inherits: false; initial-value: 0px; }
.wt-sheet__body {
  --wt-fade-top: 0px; --wt-fade-bottom: 0px;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--wt-fade-top), #000 calc(100% - var(--wt-fade-bottom)), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 var(--wt-fade-top), #000 calc(100% - var(--wt-fade-bottom)), transparent);
  transition: --wt-fade-top var(--wt-duration-fast), --wt-fade-bottom var(--wt-duration-fast);
}
.wt-sheet__body.is-more-above { --wt-fade-top: 24px; }
.wt-sheet__body.is-more-below { --wt-fade-bottom: 24px; }
/* The sheet's main action, below the list: Add stop, or, with a stop selected, Open in Maps, a round Edit stop and a round +,
   so adding is always one tap away. Static, not sticky: a sticky bar pinned itself to the screen's bottom and covered a pulled-down sheet's top. */
.wt-add-bar {
  flex: none; display: flex; gap: var(--wt-space-2);
  padding: var(--wt-space-2) var(--wt-space-3) max(var(--wt-space-2), env(safe-area-inset-bottom, 0px)); background: var(--wt-surface-raised);
}
.wt-add-bar .wt-btn--block { flex: 1; min-width: 0; }
/* Every button in the bar is a pill (a round 44px one is a circle either way): one shape along the bar, and one that can
   stretch from a circle to the whole row while the set changes */
.wt-add-bar .wt-btn { border-radius: var(--wt-radius-pill); }
/* Changing set (Add stop, a stop, a drive): while the buttons morph, the app places each one (left, top, width) and keeps
   the bar's height. .is-ghost is a button's old look fading out, or a button that's gone; it takes no taps. */
.wt-add-bar.is-morphing { position: relative; }
.wt-add-bar.is-morphing > .wt-btn { position: absolute; overflow: hidden; }
.wt-add-bar > .is-ghost { pointer-events: none; }

/* ---------- Map buttons: round icon buttons floating over the map, such as Whole day ---------- */
.wt-map-btn { pointer-events: auto; width: var(--wt-size-touch); height: var(--wt-size-touch); background: var(--wt-surface-raised); color: var(--wt-text-primary); box-shadow: var(--wt-shadow-float); }
.wt-map-btn:active:not(:disabled) { background: var(--wt-surface-hover); }
.wt-map-btn[hidden] { display: none; }
/* Disabled, it stays solid over the map; only the icon greys out. */
.wt-map-btn:disabled { opacity: 1; color: var(--wt-text-tertiary); }
.wt-map-btn:disabled svg { opacity: .45; }
@media (hover: hover) { .wt-map-btn:hover:not(:disabled) { background: var(--wt-surface-hover); } }

/* ---------- Wide screens: the sheet becomes a side panel ---------- */
/* Opt in by making the element that holds the map and the sheet a size container named wt-trip:
   `container: wt-trip / inline-size`. From 768px wide, the header and the sheet stack into a full-height panel
   on the left, and there's nothing to drag or toggle. Without the container, the sheet stays a bottom sheet at every width. */
@container wt-trip (min-width: 768px) {
  .wt-trip-head {
    top: 0; left: 0; right: auto; width: var(--wt-size-panel); height: calc(var(--wt-size-trip-head) + env(safe-area-inset-top, 0px));
    padding: env(safe-area-inset-top, 0px) var(--wt-space-4) 0 var(--wt-space-3); border-radius: 0; box-shadow: 1px 0 0 var(--wt-border-default); transition: none;
    background: var(--wt-surface-raised);
  }
  .wt-sheet {
    top: calc(var(--wt-size-trip-head) + env(safe-area-inset-top, 0px)); right: auto; width: var(--wt-size-panel);
    border-radius: 0; box-shadow: 1px 0 0 var(--wt-border-default); transition: none;
  }
  .wt-sheet__top { touch-action: auto; min-height: 0; padding-top: var(--wt-space-1); }
  .wt-sheet .wt-sheet__body, .wt-sheet:not(.is-full) .wt-sheet__body { touch-action: pan-y; overflow: auto; }
  .wt-sheet__grab { display: none; }
}
@media (hover: hover) {
  .wt-day-tab:hover { color: var(--wt-text-primary); }
}

/* ---------- Modal sheet ---------- */
.wt-modal-root .wt-modal__backdrop {
  position: fixed; inset: 0; z-index: var(--wt-z-modal);
  background: var(--wt-overlay); opacity: 0; transition: opacity var(--wt-duration-base);
}
.wt-modal {
  --wt-modal-pad-x: var(--wt-space-4); --wt-modal-pad-top: var(--wt-space-2);
  position: fixed; left: 50%; bottom: 0; z-index: calc(var(--wt-z-modal) + 1);
  width: 100%; max-width: var(--wt-size-column); max-height: 92dvh; overflow: auto;
  padding: var(--wt-modal-pad-top) var(--wt-modal-pad-x) calc(var(--wt-space-5) + env(safe-area-inset-bottom, 0px));
  background: var(--wt-surface-raised); color: var(--wt-text-primary);
  border-radius: var(--wt-radius-lg) var(--wt-radius-lg) 0 0;
  transform: translate(-50%, 100%); transition: transform var(--wt-duration-base) var(--wt-ease-out);
}
.wt-modal-root.is-open .wt-modal__backdrop { opacity: 1; }
.wt-modal-root.is-open .wt-modal { transform: translate(-50%, 0); }
/* --in-place: a phone's sheet that opens where it'll stay, fading in instead of sliding up. For one that opens on a
   search page with its field focused: on an iPhone, a field focused below the screen pans the page down to it. */
@media (max-width: 767px) {
  .wt-modal.wt-modal--in-place { transform: translate(-50%, 0); opacity: 0; transition: opacity var(--wt-duration-fast); }
  .wt-modal-root.is-open .wt-modal--in-place { opacity: 1; }
}
/* Panel: a sheet that leaves the map in view and usable, with no backdrop. The stop sheet is one, so you can
   watch the place on the map as you edit it. On a phone it's a shorter bottom sheet; from 768px it covers
   the trip's side panel (with --side), and the map beside it stays clear. */
.wt-modal-root--panel .wt-modal { max-height: 62dvh; box-shadow: var(--wt-shadow-sheet); }
/* .is-full: the whole screen, for a search page in the sheet, as a maps app's sheet rises when you search */
.wt-modal-root--panel .wt-modal.is-full { height: 92dvh; max-height: 92dvh; }
/* From 768px wide: a dialog in the middle of the screen. With --side (set by script when the trip's side
   panel is showing), it covers the panel instead, so the map stays in view beside it. */
@media (min-width: 768px) {
  .wt-modal {
    --wt-modal-pad-x: var(--wt-space-5); --wt-modal-pad-top: var(--wt-space-3);
    top: 50%; bottom: auto; max-width: 440px; max-height: min(720px, 88dvh);
    padding: var(--wt-modal-pad-top) var(--wt-modal-pad-x) var(--wt-space-5);
    border-radius: var(--wt-radius-lg); box-shadow: var(--wt-shadow-float);
    opacity: 0; transform: translate(-50%, calc(-50% + 16px));
    transition: transform var(--wt-duration-base) var(--wt-ease-out), opacity var(--wt-duration-base);
  }
  .wt-modal-root.is-open .wt-modal { opacity: 1; transform: translate(-50%, -50%); }
  .wt-modal-root--side .wt-modal {
    top: 0; bottom: 0; left: 0; width: var(--wt-size-panel); max-width: none; max-height: none;
    --wt-modal-pad-top: calc(var(--wt-space-3) + env(safe-area-inset-top, 0px));
    border-radius: 0; box-shadow: 1px 0 0 var(--wt-border-default); transform: translateX(-24px);
  }
  .wt-modal-root--side.is-open .wt-modal { transform: none; }
  .wt-modal-root--side.wt-modal-root--panel .wt-modal { max-height: none; box-shadow: 1px 0 0 var(--wt-border-default); }
  .wt-modal-root--side.wt-modal-root--panel .wt-modal.is-full { height: auto; max-height: none; }
}
/* A sheet's icons sit in two columns, measured from the content edge: the left one through the options' markers
   (8px padding + half a 30px marker = 23px), the right one through their checks (8px + half an 18px icon = 17px).
   Close sits on the right one, a sub-page's back button on the left one with its title over the options' names. */
.wt-modal__head { display: flex; align-items: center; justify-content: space-between; margin: 0 calc(17px - var(--wt-size-icon-btn) / 2) var(--wt-space-1) 0; }
/* A page inside a sheet (a picker's options): back on the left, then the title */
.wt-modal__head--sub { justify-content: flex-start; gap: 0; margin-left: calc(23px - var(--wt-size-icon-btn) / 2); }
.wt-modal__head--sub .wt-modal__title { margin-left: calc(15px + var(--wt-space-3) - var(--wt-size-icon-btn) / 2); }
.wt-modal__title { margin: 0; font: var(--wt-type-title); }
.wt-modal__text { margin: 0 0 var(--wt-space-3); color: var(--wt-text-secondary); }
.wt-modal__actions { display: flex; align-items: center; gap: var(--wt-space-3); margin-top: var(--wt-space-5); }
.wt-modal__actions .wt-btn--primary { margin-left: auto; min-width: 110px; }
/* A long form in a short sheet (the stop sheet): its head and actions stay put while the fields scroll between
   them, so Close and Save are always in reach. Put --sticky on the head and the actions; the actions take over
   the sheet's bottom padding. */
.wt-modal:has(.wt-modal__actions--sticky) { padding-bottom: 0; }
/* It sticks at the sheet's very top, over its top padding, so nothing scrolls by above it */
.wt-modal__head--sticky {
  position: sticky; top: calc(-1 * var(--wt-modal-pad-top)); z-index: 1;
  margin-top: calc(-1 * var(--wt-modal-pad-top)); padding-top: var(--wt-modal-pad-top);
  background: var(--wt-surface-raised);
}
.wt-modal__actions--sticky {
  position: sticky; bottom: 0; z-index: 1;
  margin: var(--wt-space-4) calc(-1 * var(--wt-modal-pad-x)) 0;
  padding: var(--wt-space-3) var(--wt-modal-pad-x) calc(var(--wt-space-3) + env(safe-area-inset-bottom, 0px));
  background: var(--wt-surface-raised); box-shadow: 0 -1px 0 var(--wt-border-default);
}

/* ---------- Toast ---------- */
.wt-toast {
  /* --wt-toast-top: where it shows, below anything that must stay in reach (the trip header). --wt-toast-drag: how far
     a swipe has moved it up, set by the app while a finger is on it. */
  position: fixed; left: 50%; top: calc(var(--wt-toast-top, var(--wt-space-3)) + env(safe-area-inset-top, 0px)); z-index: var(--wt-z-toast);
  max-width: calc(100% - 2 * var(--wt-space-4));
  display: flex; align-items: center; gap: var(--wt-space-4); padding: 10px 18px;
  border-radius: var(--wt-radius-pill); background: var(--wt-surface-inverse); color: var(--wt-text-inverse);
  font: var(--wt-type-body); font-size: 14px; cursor: default; touch-action: none; user-select: none; -webkit-user-select: none;
  opacity: 0; pointer-events: none; transform: translate(-50%, -12px);
  transition: opacity var(--wt-duration-base), transform var(--wt-duration-base);
}
.wt-toast.is-visible { opacity: 1; pointer-events: auto; transform: translate(-50%, var(--wt-toast-drag, 0px)); }
.wt-toast.is-dragging { transition: none; }
.wt-toast__action { flex: none; color: var(--wt-text-inverse-action); font-weight: 500; }
/* A notice that needs a second line: an icon, a short heading (what happened), and a detail line (what still works, or
   how to fix it). A card rather than a pill, so two lines sit well in it. */
.wt-toast--rich {
  align-items: flex-start; gap: var(--wt-space-3); width: max-content; max-width: min(360px, calc(100% - 2 * var(--wt-space-4)));
  padding: 12px 16px 12px 14px; border-radius: var(--wt-radius-lg); box-shadow: var(--wt-shadow-float);
}
.wt-toast__icon { flex: none; display: grid; padding-top: 1px; }
.wt-toast__icon .wt-icon { width: 18px; height: 18px; }
.wt-toast__text { display: grid; gap: 2px; min-width: 0; }
.wt-toast__title { font-weight: 600; }
.wt-toast__detail { font: var(--wt-type-caption); color: var(--wt-text-inverse-secondary); }
.wt-toast--rich .wt-toast__action { align-self: center; }
/* Something went wrong: the alert icon in red, and screen readers hear it at once (role="alert") */
.wt-toast--error .wt-toast__icon { color: var(--wt-text-inverse-danger); }

/* ---------- Dialog: a question before an action that can't be undone ---------- */
/* Small, in the middle of the screen, over everything, sheets included, so a sheet can ask without closing.
   The safe choice is on the left and has the focus; the action says what happens ("Delete trip", not "OK"). */
.wt-dialog-root { position: fixed; inset: 0; z-index: var(--wt-z-dialog); display: grid; place-items: center; padding: var(--wt-space-4); pointer-events: none; }
.wt-dialog-root.is-open { pointer-events: auto; }
.wt-dialog__backdrop { position: absolute; inset: 0; background: var(--wt-overlay); opacity: 0; transition: opacity var(--wt-duration-base); }
.wt-dialog {
  position: relative; width: min(100%, 340px); padding: var(--wt-space-5) var(--wt-space-5) var(--wt-space-4);
  border-radius: var(--wt-radius-lg); background: var(--wt-surface-raised); color: var(--wt-text-primary); box-shadow: var(--wt-shadow-card);
  opacity: 0; transform: scale(.96); transition: opacity var(--wt-duration-base), transform var(--wt-duration-base) var(--wt-ease-out);
}
.wt-dialog-root.is-open .wt-dialog__backdrop, .wt-dialog-root.is-open .wt-dialog { opacity: 1; }
.wt-dialog-root.is-open .wt-dialog { transform: none; }
.wt-dialog__title { margin: 0; font: var(--wt-type-title); overflow-wrap: anywhere; }
.wt-dialog__text { margin: var(--wt-space-2) 0 0; color: var(--wt-text-secondary); }
.wt-dialog__actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--wt-space-2); margin-top: var(--wt-space-5); }
.wt-dialog__actions .wt-btn { justify-content: center; padding: 0 var(--wt-space-3); }
/* The confirm button of a dialog that destroys something: filled red. Only here; elsewhere Delete is --danger. */
.wt-btn--destructive { background: var(--wt-action-danger); color: var(--wt-action-danger-text); font-weight: 600; }

/* ---------- Trip card (Home) ---------- */
/* Where the trip goes across the top, then its name, dates and people. Set apart from the page by its surface alone, as
   the list's rows are. Across the top: photos of its places when they have them (__photos), else a sketch of its
   route (the svg) that draws routes and pins as the trip's map does. */
.wt-trip-card {
  --wt-avatar-ring: var(--wt-surface-raised);
  display: flex; flex-direction: column; overflow: hidden;
  border-radius: var(--wt-radius-md); background: var(--wt-surface-raised);
  transition: background var(--wt-duration-fast);
}
.wt-trip-card:hover, .wt-trip-card:active { background: var(--wt-surface-sunken); --wt-avatar-ring: var(--wt-surface-sunken); }
.wt-trip-card__map {
  position: relative; display: grid; place-items: center; aspect-ratio: 5 / 2;
  background: var(--wt-surface-map); overflow: hidden;
}
.wt-trip-card__map svg { display: block; width: 100%; height: 100%; }
/* Drawn in the sketch's own units, but every line and dot keeps its width in pixels at any card size. A dot is a
   path of no length, so its round cap draws it. */
.wt-trip-card__map path { fill: none; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.wt-trip-card__casing { stroke: var(--wt-route-casing); stroke-width: 7px; }
.wt-trip-card__route { stroke: var(--wt-route); stroke-width: 4px; }
/* A drive not looked up yet: dotted, as on the map */
.wt-trip-card__casing.is-estimate, .wt-trip-card__route.is-estimate { stroke-dasharray: 0 9; }
.wt-trip-card.is-past .wt-trip-card__route { stroke: var(--wt-route-done); }
/* Pins, as on the map: a dot in the type's color (--wt-kind-past once the trip is over) in a ring, standing off the map */
.wt-trip-card__ring { stroke: var(--wt-pin-fill); stroke-width: 14px; filter: drop-shadow(var(--wt-shadow-pin)); }
.wt-trip-card__stop { stroke: var(--wt-kind-color, var(--wt-kind-place)); stroke-width: 10px; }
.wt-trip-card__map--empty { font: var(--wt-type-caption); color: var(--wt-text-tertiary); }
/* Up to three photos side by side, each cut to fill its share, with a hairline of the card between them. The map's
   color holds their place while they load. A trip that's over drains of color, as its sketch does. */
.wt-trip-card__photos { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 2px; aspect-ratio: 5 / 2; overflow: hidden; }
.wt-trip-card__photo { display: block; width: 100%; height: 100%; min-width: 0; object-fit: cover; background: var(--wt-surface-map); }
.wt-trip-card.is-past .wt-trip-card__photo { filter: saturate(0.25); }
.wt-trip-card__body { display: flex; align-items: center; gap: var(--wt-space-3); padding: var(--wt-space-3) var(--wt-space-3) var(--wt-space-3) var(--wt-space-4); }
.wt-trip-card__text { flex: 1; min-width: 0; display: grid; gap: 2px; }
.wt-trip-card__name { font: var(--wt-type-name); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wt-trip-card__dates {
  font: var(--wt-type-caption); font-size: 14px; color: var(--wt-text-secondary); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Under way: which day it is reads first, in primary ink, like the row happening now */
.wt-trip-card.is-now .wt-trip-card__when { color: var(--wt-text-primary); }
.wt-trip-card__people { padding: 0; }
/* Under way, what the trip is at now and what's next, under a hairline at the foot of the card, each like a row of
   the timeline: a small marker in its type's color, the place, and on the right when it is, "Now" for the first. The
   row happening now is in primary ink, as in the timeline; what's next stays secondary. */
.wt-trip-card__now {
  display: grid; gap: var(--wt-space-1); margin: 0 var(--wt-space-3) 0 var(--wt-space-4);
  padding: var(--wt-space-3) 0; border-top: 1px solid var(--wt-border-subtle);
}
.wt-trip-card__step { display: flex; align-items: center; gap: var(--wt-space-2); min-width: 0; font: var(--wt-type-caption); font-size: 14px; color: var(--wt-text-secondary); }
.wt-trip-card__step .wt-marker { flex: none; }
.wt-trip-card__step-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wt-trip-card__step.is-now :is(.wt-trip-card__step-name, .wt-trip-card__step-time) { color: var(--wt-text-primary); }
.wt-trip-card__step.is-now .wt-trip-card__step-time { font-weight: 600; }
.wt-trip-card__step-time { flex: none; margin-left: auto; padding-left: var(--wt-space-2); font-variant-numeric: tabular-nums; }

/* ---------- Map pin ---------- */
/* A round dot centered on its place, like a stop on a transit map: the stop's type color, shaded like a marker, in a
   --wt-pin-fill ring that keeps it apart from the route under it, with its number inside (.wt-pin__num). Every pin
   has one: its row's in the list (the first one's, for several rows at one place). Nothing else: names and times are
   in the list. Pins merged where they crowd (--cluster) are the
   first one's pin in front, with its number, and the next ones' pins stacked behind it, in their colors. Selected: larger, with a deeper shadow, and the other pins in
   the same .wt-pins (the element that holds them) fade, still in their colors. Muted (over, the day before's last
   stop, or off the route on show): smaller and grey, as what's over is grey in the list. Placed by its center, at the
   marker's position on the map. --wt-pin-size is the pin's whole width, ring included. */
.wt-pin {
  --wt-pin-size: 24px;
  position: absolute; box-sizing: border-box; width: var(--wt-pin-size); height: var(--wt-pin-size);
  display: grid; place-items: center; transform: translate(-50%, -50%);
  border: 2px solid var(--wt-pin-fill); border-radius: var(--wt-radius-round);
  background-color: var(--wt-marker-fill); background-image: var(--wt-marker-shade); box-shadow: var(--wt-shadow-pin);
  transition: width var(--wt-duration-base), height var(--wt-duration-base), opacity var(--wt-duration-base), box-shadow var(--wt-duration-base), background-color var(--wt-duration-base);
}
/* A tap target larger than a small pin, centered on it */
.wt-pin::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 36px; height: 36px; border-radius: var(--wt-radius-round);
  transform: translate(-50%, -50%);
}
.wt-pin--muted { --wt-pin-size: 20px; opacity: .85; box-shadow: none; background: var(--wt-kind-past); }   /* flat grey, as in the list */
.wt-pin--selected { --wt-pin-size: 32px; box-shadow: var(--wt-shadow-pin-selected); }
/* The others step back, still solid and in their colors (grey means over): flat, in a lighter version of their color
   (--wt-pin-faded-mix of it over the ring's), with the number in their own color. Not see-through, so the route and
   the map don't show through them. A pin that's over stays as it is. */
.wt-pins:has(.wt-pin--selected) .wt-pin:not(.wt-pin--selected, .wt-pin--muted) {
  --wt-marker-fill: color-mix(in oklab, var(--wt-kind-color, var(--wt-kind-place)) var(--wt-pin-faded-mix), var(--wt-pin-fill));
  background-image: none;
}
.wt-pins:has(.wt-pin--selected) .wt-pin:not(.wt-pin--selected, .wt-pin--muted) > .wt-pin__num {
  color: oklch(from var(--wt-kind-color, var(--wt-kind-place)) calc(l + var(--wt-pin-faded-ink-lift)) c h);
}
.wt-pin__num {
  color: var(--wt-marker-ink); font: 700 12px/1 var(--wt-font-sans); font-variant-numeric: tabular-nums; letter-spacing: -.02em;
  transition: opacity var(--wt-duration-base), color var(--wt-duration-base);
}
.wt-pin--muted .wt-pin__num { font-size: 11px; }
.wt-pin--selected .wt-pin__num { font-size: 15px; }
/* A stop not saved yet, which has no row and so no number */
.wt-pin__dot { width: 8px; height: 8px; border-radius: var(--wt-radius-round); background: var(--wt-marker-ink); transition: opacity var(--wt-duration-base); }
.wt-pin--muted .wt-pin__dot { width: 6px; height: 6px; }
.wt-pin--selected .wt-pin__dot { width: 10px; height: 10px; }
/* Pins merged where they crowd (--cluster): round, like every pin. The first one's pin is in front, as it is, with its
   number; the next ones' pins are stacked behind it, up and to the right, each in its own color in its own
   --wt-pin-fill ring, like a fanned deck: one behind when two merge, two when more (--deep). Set their colors in
   --wt-pin-behind-1 and -2. Behind, they're flat and faded, half their color over the ring's (--wt-pin-behind-soft), so
   the pin in front leads; one shadow goes around the whole stack. */
.wt-pin--cluster {
  --wt-pin-behind-soft: 50%;
  filter: drop-shadow(var(--wt-shadow-pin));
  box-shadow: 4px -4px 0 -2px color-mix(in oklab, var(--wt-pin-behind-1) var(--wt-pin-behind-soft), var(--wt-pin-fill)), 4px -4px 0 0 var(--wt-pin-fill);
}
.wt-pin--cluster.wt-pin--deep {
  box-shadow: 4px -4px 0 -2px color-mix(in oklab, var(--wt-pin-behind-1) var(--wt-pin-behind-soft), var(--wt-pin-fill)), 4px -4px 0 0 var(--wt-pin-fill),
    8px -8px 0 -2px color-mix(in oklab, var(--wt-pin-behind-2) var(--wt-pin-behind-soft), var(--wt-pin-fill)), 8px -8px 0 0 var(--wt-pin-fill);
}
.wt-pin--cluster.wt-pin--muted { filter: none; }

/* ---------- Sight: a place worth seeing, on the map ---------- */
/* What a maps app shows of its places, zoomed in: a marker with the type's icon, centered on the place. It's part of
   the map, not of the plan, so it's the plan's pin turned inside out: a 22px disc in the pin ring's color, the icon in
   the type's color, a ring of it around the edge, and the pin's light shadow, so it reads over any map. A stop's pin is
   a solid color with a white number, so the plan still reads first. Pointed at, focused or selected, it becomes a
   solid marker in the type's color, like the card's.
   Its name, to its right in secondary ink with a halo in the pin ring's color so it reads over any map, shows only
   while a mouse is on it: the map's own names stay readable, and tapping it says the rest. Selected, its card says
   its name, so the map doesn't repeat it. Set --wt-kind-color.
   On its own (in a sight's card), .wt-sight__marker is the solid 20px marker. */
.wt-sight {
  position: absolute; display: flex; align-items: center; gap: 4px; transform: translate(-11px, -50%);
  cursor: pointer; animation: wt-sight-in var(--wt-duration-base) var(--wt-ease-out);
  transition: opacity var(--wt-duration-base);
}
.wt-sight__marker {
  display: grid; place-items: center; flex: none; box-sizing: border-box; width: 20px; height: 20px;
  border: 1.5px solid var(--wt-pin-fill); border-radius: var(--wt-radius-round);
  background: var(--wt-kind-color, var(--wt-kind-place)); color: var(--wt-marker-ink); box-shadow: var(--wt-shadow-pin);
}
.wt-sight__marker .wt-icon { width: 12px; height: 12px; }
.wt-sight .wt-sight__marker {
  width: 22px; height: 22px; border: 0;
  background: var(--wt-pin-fill);
  color: var(--wt-kind-color, var(--wt-kind-place));
  box-shadow: inset 0 0 0 1.5px var(--wt-kind-color, var(--wt-kind-place)), var(--wt-shadow-pin);
  transition: width var(--wt-duration-fast), height var(--wt-duration-fast), margin var(--wt-duration-fast);
}
.wt-sight .wt-sight__marker .wt-icon { width: 14px; height: 14px; }
/* Focused (it, or the element holding it, as the map's marker), or selected: the solid marker, 24px about the same center */
.wt-sight:is(:focus-visible, .is-selected) .wt-sight__marker, :focus-visible > .wt-sight .wt-sight__marker {
  width: 24px; height: 24px; margin-left: -1px; border: 1.5px solid var(--wt-pin-fill);
  background: var(--wt-kind-color, var(--wt-kind-place)); color: var(--wt-marker-ink); box-shadow: var(--wt-shadow-pin);
}
.wt-sight:focus-visible .wt-sight__marker .wt-icon, :focus-visible > .wt-sight .wt-sight__marker .wt-icon { width: 14px; height: 14px; }
/* Pointed at with a mouse: the same, with its name */
@media (hover: hover) {
  .wt-sight:hover .wt-sight__marker {
    width: 24px; height: 24px; margin-left: -1px; border: 1.5px solid var(--wt-pin-fill);
    background: var(--wt-kind-color, var(--wt-kind-place)); color: var(--wt-marker-ink); box-shadow: var(--wt-shadow-pin);
  }
  .wt-sight:hover .wt-sight__marker .wt-icon { width: 14px; height: 14px; }
}
.wt-sight__name {
  display: none; max-width: 160px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font: 500 12px/16px var(--wt-font-sans); color: var(--wt-text-secondary);
  text-shadow: 0 0 2px var(--wt-pin-fill), 0 0 2px var(--wt-pin-fill), 0 0 3px var(--wt-pin-fill);
}
/* A tap target bigger than the marker (42px square), and over the name while it shows */
.wt-sight::after { content: ''; position: absolute; inset: -10px; }
@media (hover: hover) { .wt-sight:not(.is-selected):hover .wt-sight__name { display: block; } }
@keyframes wt-sight-in { from { opacity: 0; } }
/* Selected: its card is open. The marker grows to 32px about its center, solid, with no name beside it. */
.wt-sight.is-selected .wt-sight__marker { width: 32px; height: 32px; margin-left: -5px; box-shadow: var(--wt-shadow-pin-selected); }
.wt-sight.is-selected .wt-sight__marker .wt-icon { width: 18px; height: 18px; }
/* While a pin is selected, the other pins step back to a lighter solid color: the sights step back to 70%, so none
   outshines the plan, and they still read, since a selected stop is where you look around. For the sights inside the
   element that holds the .wt-pins element (in the app, the map, which holds the pins and the sights). */
:has(> .wt-pins .wt-pin--selected) .wt-sight:not(.is-selected) { opacity: .7; }

/* ---------- About a place: a photo, a few lines, and where they're from ---------- */
/* As in a sight's card: the photo across the top, then the lines (at most four), then the photo's credit and a link
   to the article. --compact puts a small square photo beside them, three lines in caption type: the top of a stop's
   sheet. --loading holds the place with grey blocks. */
.wt-about { margin-bottom: var(--wt-space-4); }
.wt-about__photo {
  display: block; width: 100%; height: 144px; object-fit: cover;
  border-radius: var(--wt-radius-md); background: var(--wt-surface-sunken);
}
.wt-about__text {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; line-clamp: 4; overflow: hidden;
  margin: var(--wt-space-3) 0 0; color: var(--wt-text-secondary);
}
.wt-about__src {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--wt-space-3);
  margin-top: var(--wt-space-2); font: var(--wt-type-caption); color: var(--wt-text-tertiary);
}
.wt-about__credit { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: inherit; text-decoration: none; }
.wt-about__more { display: inline-flex; align-items: center; gap: 2px; flex: none; margin-left: auto; color: var(--wt-text-link); text-decoration: none; }
.wt-about__more .wt-icon { width: 12px; height: 12px; }
@media (hover: hover) { .wt-about__credit:hover, .wt-about__more:hover { text-decoration: underline; } }
.wt-about--compact { display: flex; align-items: flex-start; gap: var(--wt-space-3); }
.wt-about--compact .wt-about__photo { flex: none; width: 72px; height: 72px; }
.wt-about--compact .wt-about__body { flex: 1; min-width: 0; }
.wt-about--compact .wt-about__text { margin: 0; -webkit-line-clamp: 3; line-clamp: 3; font: var(--wt-type-caption); }
.wt-about--compact .wt-about__src { margin-top: var(--wt-space-1); }
.wt-about--loading .wt-about__line { display: block; height: 12px; margin-top: var(--wt-space-2); border-radius: var(--wt-radius-sm); background: var(--wt-surface-sunken); }
.wt-about--loading:not(.wt-about--compact) .wt-about__line:first-child { margin-top: var(--wt-space-3); }
.wt-about--loading .wt-about__line:last-child { width: 60%; }
.wt-about--compact.wt-about--loading .wt-about__line:first-child { margin-top: 0; }

/* ---------- Wordmark: the app's name, "Dotsie", with a stop for the i's dot ----------
   The i is a dotless ı, and its dot an orange stop, the logo's, a little bigger than a letter's dot (30% of the cap
   height), where Inter Bold has its own: centered over the stem (.136em in) and .69em over the baseline. The dot is
   an empty inline-block before the ı, so its bottom margin edge sits on the baseline whatever the font's metrics; the
   right margin gives its width back. Sized in em, it follows whatever bold type the name is set in. */
.wt-wordmark { white-space: nowrap; }
.wt-wordmark__i::before { content: ''; display: inline-block; vertical-align: baseline; width: .213em; height: .213em; margin: 0 -.242em .586em .029em; border-radius: var(--wt-radius-round); background: var(--wt-brand-dot-i); }

/* ---------- Empty state ---------- */
.wt-empty { margin: 0; padding: var(--wt-space-10) var(--wt-space-6); text-align: center; color: var(--wt-text-secondary); }
.wt-empty a { color: var(--wt-text-link); }

/* ---------- Credit: the map's credits, at the bottom of trip settings ---------- */
.wt-credit { margin: var(--wt-space-5) 0 0; font: var(--wt-type-caption); color: var(--wt-text-tertiary); }
.wt-section + .wt-credit { margin-top: var(--wt-space-2); }
.wt-credit a { color: inherit; }
