/* styles.css — Fuelstops Telegram Mini App design system.
   Recreated from design-handoff/design_handoff_fuelstops (screens A–E). Fixed light theme on a
   #F4F6FA surface; Hanken Grotesk for UI, Space Mono for numbers/prices/codes (.mono). Telegram theme
   params are still applied at runtime (app.js applyTheme) but the bespoke design tokens drive the look.
   prefers-reduced-motion disables the motion at the bottom of this file. */

:root {
  /* Fixed light design (per the handoff): keep the UA from dark-rendering form controls,
     scrollbars and the canvas under dark Telegram themes — the tokens below are light-locked. */
  color-scheme: light;
  /* primary */
  --c-primary: #0b5fff;
  --c-primary-dark: #0a3fb0;
  --c-primary-tint: #eef3ff;
  --c-primary-tint2: #f5f9ff;
  --c-primary-border2: #d5e1ff;
  /* ink / dark surfaces */
  --c-ink: #0e1525;
  --c-ink2: #172033;
  /* text */
  --c-body: #33425c;
  --c-secondary: #5b6473;
  --c-muted: #7a8496;
  --c-faint: #9aa4b4;
  /* success */
  --c-success: #0e9e6e;
  --c-success-dark: #0a7d56;
  --c-success-bright: #1fe08a;
  --c-success-soft: #5be3b0;
  --c-success-bg: #e7f7f0;
  /* warn / def */
  --c-warn: #e8853a;
  --c-warn-soft: #ffb877;
  --c-warn-bg: #fff3e9;
  /* danger / pins */
  --c-danger: #e5484d;
  /* surfaces / borders */
  --c-app-bg: #f4f6fa;
  --c-border: #e6eaf1;
  --c-border2: #eef1f6;
  --c-border3: #dce2ec;
  --c-hairline-dark: #283248;

  --r-card: 16px;
  --r-input: 12px;
  --r-pill: 20px;

  /* Spacing scale (FS-189 / 3.19 follow-up): ONE 4px-base scale for the screen-level rhythm —
     shell padding, section gaps and card-to-card margins on the compose/empty and routes screens
     (was a 12/14/16px mix). Component-INTERNAL paddings keep their bespoke values, and the
     app-header's 14px design pad (--header-pad-top below) is the 3.19 device-measured fullscreen
     collapse value — intentionally not on this scale. Token name = rung × 4px; only the rungs the
     rhythm actually uses (12/16/20) are declared — add 4/8px rungs here if a later screen needs them. */
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;

  /* App-header vertical box. In fullscreen the combined Telegram inset (--safe-top, below) IS the
     header's top padding — the 14px design pad must NOT stack on top of it (measured on-device: the
     inset already ends at the clearance line under Telegram's floating controls, and 14px more just
     grows the dead band). Sheet mode (inset 0) keeps the plain 14px pad via max().
     --header-bottom = top pad + 38px avatar row + 14px bottom pad + 1px border: the header's true
     bottom edge, which the full-screen overlays start below (see .overlay). */
  --header-pad-top: max(14px, var(--safe-top));
  --header-bottom: calc(var(--header-pad-top) + 53px);

  /* Top safe-area. In TRUE fullscreen (app.js initViewport → tg.requestFullscreen, Bot API 8.0+)
     Telegram's chrome (status bar + close/more controls) overlays the top of the webview and the
     device's env() inset alone under-reports the offset. --safe-top therefore takes the LARGEST of:
       - env(safe-area-inset-top): the device notch when the webview owns the screen edge;
       - the SDK-set --tg-safe-area-inset-top + --tg-content-safe-area-inset-top CSS vars (device
         inset + Telegram's own controls — Telegram reports them separately, so they ADD);
       - --app-safe-top: the same sum written by app.js applySafeArea() from tg.safeAreaInset /
         tg.contentSafeAreaInset on the safeAreaChanged / contentSafeAreaChanged / fullscreenChanged
         events, covering clients that fire the events before/without setting the CSS vars.
     In sheet mode (older clients, or fullscreen denied → fullscreenFailed) every source is 0 and
     the layout is exactly the pre-fullscreen one. */
  --app-safe-top: 0px;
  --safe-top: max(
    env(safe-area-inset-top, 0px),
    calc(var(--tg-safe-area-inset-top, 0px) + var(--tg-content-safe-area-inset-top, 0px)),
    var(--app-safe-top)
  );

  --font-ui: "Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
    sans-serif;
  --font-mono: "Space Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Telegram theme fallbacks (applyTheme overrides at runtime; bespoke tokens above take priority). */
  --tg-link: var(--c-primary);
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--c-app-bg);
  color: var(--c-ink);
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* ---------- in-app header (gradient avatar + brand + bot-online) ---------- */
.app-header {
  display: flex;
  align-items: center;
  gap: 11px;
  background: #fff;
  padding: 14px 18px;
  /* Respect the device notch AND Telegram's fullscreen chrome: the header owns the top inset
     (--header-pad-top collapses the inset and the design pad into ONE value — never both), so
     --header-bottom is always the header's true bottom edge (the .overlay top offset reuses it). */
  padding-top: var(--header-pad-top);
  border-bottom: 1px solid #eaeef4;
  min-height: var(--header-bottom);
  /* Sticky so the header row stays visible above scrolled content AND above the fixed overlays,
     which start exactly at its bottom edge. Below the sheet scrim (50) / overlay (60) is fine —
     they begin below or dim it by design. */
  position: sticky;
  top: 0;
  z-index: 40;
}

/* Runtime inset changes (fullscreen exit/re-enter, rotation) glide instead of snapping — but ONLY
   once .insets-live is armed. applySafeArea() (app.js) adds the class one frame AFTER the first
   nonzero inset write: the fullscreen insets land asynchronously right after launch (post first
   paint), and animating that first application read as the whole header sliding ~90px down the
   page. The global prefers-reduced-motion block zeroes this transition. */
.app-header.insets-live {
  transition: padding-top 0.12s ease-out;
}

.app-header__avatar {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--c-primary), var(--c-primary-dark));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.app-header__title {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
}

/* Dimmed ".io" wordmark suffix — mirrors the web Wordmark (opacity-60 on ".io"). */
.brand-io {
  opacity: 0.6;
}

.app-header__sub {
  font-size: 12px;
  color: var(--c-muted);
  display: flex;
  align-items: center;
  gap: 5px;
}

.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-success);
  flex-shrink: 0;
}

/* ---------- app shell ---------- */
.app {
  max-width: 480px;
  margin: 0 auto;
  /* Bottom padding clears the sticky CTA bar / Telegram MainButton plus any home-indicator
     safe-area inset, so the last card is never hidden under the button. */
  padding: var(--sp-3) var(--sp-4) calc(120px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: 0;
  /* Opacity-only — NEVER a transform animation here. `scIn` with fill-mode `both` left a permanent
     `transform: translateY(0)` on the shell, which made #app the containing block for its
     position:fixed children: every full-screen overlay (sending/sent) collapsed into #app's small
     box and became a tiny inner scroller showing a clipped text fragment. Per-screen entrance
     motion stays on .screen (a non-fixed subtree, where a lingering transform is harmless). */
  animation: fadeIn 0.35s ease both;
}

/* Entrance motion is KEYED by render() (parity.screenKey): .screen--enter is added only when the
   top-level screen actually changed, so a same-screen re-render (checkbox, radio, add-stop,
   expander taps) never replays the fade/slide — only real navigation does. An unconditional
   animation here made every full render look like a page reload. */
.screen--enter {
  animation: scIn 0.3s ease both;
}

.step-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-faint);
  margin: 0 0 10px;
}

.step-label--mt {
  margin-top: var(--sp-5);
}

/* ---------- group selector ---------- */
.group-empty {
  width: 100%;
  text-align: left;
  background: #fff;
  border: 1.5px dashed #b9c4d4;
  border-radius: var(--r-card);
  padding: 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  cursor: pointer;
  font-family: inherit;
  transition: 0.15s;
}

.group-empty:hover {
  border-color: var(--c-primary);
  background: #f7faff;
}

.group-empty__icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--c-primary-tint);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.group-empty__title {
  font-size: 16px;
  font-weight: 700;
}

.group-empty__sub {
  font-size: 13px;
  color: var(--c-muted);
}

.group-card {
  width: 100%;
  text-align: left;
  background: #fff;
  border: 1.5px solid var(--c-primary);
  border-radius: var(--r-card);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 13px;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 4px 16px -6px rgba(11, 95, 255, 0.3);
}

/* Pop only when the SELECTED GROUP changed (render keys it, same discipline as .screen--enter) —
   not on every re-render of the compose/load screens. */
.group-card--enter {
  animation: scIn 0.3s ease both;
}

.unit-badge {
  width: 42px;
  height: 42px;
  border-radius: 11px;
  background: linear-gradient(135deg, var(--c-primary), var(--c-primary-dark));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #fff;
  font-weight: 800;
  font-size: 13px;
}

.group-card__body {
  flex: 1;
  min-width: 0;
}

.group-card__title {
  font-size: 15px;
  font-weight: 700;
}

.group-card__sub {
  font-size: 12px;
  color: var(--c-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.group-card__change {
  font-size: 12px;
  font-weight: 700;
  color: var(--c-primary);
  flex-shrink: 0;
}

/* ---------- live truck status (dark) ---------- */
.live-card {
  margin-top: var(--sp-3);
  background: linear-gradient(165deg, var(--c-ink), var(--c-ink2));
  border-radius: 18px;
  padding: 18px;
  color: #fff;
  position: relative;
  overflow: hidden;
}

/* 3.29b layout-shift reserve: while the live read is in flight, hold (approximately) the resolved
   card's height so the 1–3 s resolve doesn't shove the form fields below it mid-tap/mid-type.
   216px = card padding + eyebrow + main row (108px fuel ring) + GPS row at one address line; a
   two-line address grows the card a few px, and the rare error state collapses it. Loading only —
   fillLiveCard toggles the class off the moment the resolve lands. */
.live-card--reserve {
  min-height: 216px;
}

.live-card__live {
  position: absolute;
  top: 14px;
  right: 16px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 700;
  color: var(--c-success-soft);
}

.live-card__live .dot {
  background: var(--c-success-bright);
  box-shadow: 0 0 8px var(--c-success-bright);
  animation: pulse 1.6s infinite;
}

.live-card__eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #7e8aa3;
  text-transform: uppercase;
}

.live-card__main {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: 14px;
}

.live-card__stats {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 13px;
  min-width: 0;
}

.live-stat__label {
  font-size: 11px;
  color: #8995ad;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.live-stat__value {
  font-size: 20px;
  font-weight: 800;
}

.live-stat__value .unit {
  font-size: 13px;
  color: #8995ad;
  font-weight: 600;
}

.def-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.def-pct {
  font-size: 13px;
  font-weight: 700;
}

.def-track {
  margin-top: 5px;
  height: 7px;
  background: var(--c-hairline-dark);
  border-radius: 6px;
  overflow: hidden;
}

.def-fill {
  height: 100%;
  border-radius: 6px;
  transition: width 0.9s ease;
}

.def-advise {
  margin-top: 6px;
  font-size: 11px;
  font-weight: 700;
  color: var(--c-warn-soft);
  display: flex;
  align-items: center;
  gap: 5px;
}

.live-card__gps {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--c-hairline-dark);
  display: flex;
  align-items: center;
  gap: 9px;
}

.live-card__gps-text {
  font-size: 13px;
  color: #c4cddd;
  font-weight: 500;
  line-height: 1.3;
}

.live-card__msg {
  margin: 14px 0 0;
  font-size: 13px;
  color: #c4cddd;
}

.live-card__msg--error {
  color: var(--c-warn-soft);
}

/* fuel ring */
.fuel-ring {
  position: relative;
  width: 108px;
  height: 108px;
  flex-shrink: 0;
}

.fuel-ring__svg {
  transform: rotate(-90deg);
}

.fuel-ring__fg {
  animation: ring 0.9s cubic-bezier(0.4, 0, 0.2, 1) both;
  transition: stroke-dashoffset 0.9s cubic-bezier(0.4, 0, 0.2, 1);
}

.fuel-ring__center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.fuel-ring__pct {
  font-size: 30px;
  font-weight: 800;
  line-height: 1;
}

.fuel-ring__pct .sign {
  font-size: 15px;
}

.fuel-ring__cap {
  font-size: 11px;
  color: #8995ad;
  font-weight: 600;
}

/* ---------- route card (compose) ---------- */
.route-card {
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  overflow: hidden;
}

.route-line {
  padding: 14px 16px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.route-line + .route-line {
  border-top: 1px solid var(--c-border2);
}

.route-line__rail {
  width: 26px;
  display: flex;
  justify-content: center;
  padding-top: 2px;
  flex-shrink: 0;
}

.start-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 3px solid var(--c-primary);
}

.route-line__body {
  flex: 1;
  min-width: 0;
}

.route-line__label {
  font-size: 11px;
  color: var(--c-faint);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.route-line__value {
  font-size: 14px;
  font-weight: 600;
  margin-top: 1px;
}

.route-line__gps {
  font-size: 11px;
  color: var(--c-success);
  font-weight: 600;
  margin-top: 1px;
}

/* Middle-stop rows (web RouteStops parity): numbered dark node in the rail, a trash remove button,
   and a full-width dashed "Add another stop" affordance. Destination keeps the red pin. */
.stop-node {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--c-ink);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.route-line__remove {
  appearance: none;
  width: 40px;
  height: 42px;
  margin-top: 8px; /* sits beside the input, below the row label */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--c-border3);
  border-radius: var(--r-input);
  background: #fff;
  color: var(--c-faint);
  cursor: pointer;
  flex-shrink: 0;
}

.route-line__remove:hover {
  border-color: var(--c-danger);
  color: var(--c-danger);
  background: #fdf1f2;
}

.route-line--add {
  padding-top: 4px;
}

.add-stop-btn {
  appearance: none;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 11px 14px;
  border: 1px dashed #c2cede;
  border-radius: var(--r-input);
  background: #fff;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--c-secondary);
  cursor: pointer;
}

.add-stop-btn:hover {
  border-color: var(--c-primary);
  background: var(--c-primary-tint2);
  color: var(--c-primary);
}

.route-line__remove:focus-visible,
.add-stop-btn:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

.linkbtn {
  appearance: none;
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  color: var(--c-primary);
  cursor: pointer;
  flex-shrink: 0;
  /* >=44px touch target (a11y) without growing the visible text run */
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
}

.load-row {
  margin-top: var(--sp-3);
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: 14px;
  padding: 11px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.load-row__label {
  font-size: 14px;
  color: var(--c-muted);
}

.load-row__label .req {
  font-weight: 700;
  color: #c0353a;
}

.field-error {
  margin: 6px 2px 0;
  font-size: 12.5px;
  color: #c0353a;
}

/* ---------- optimizer parameters (collapsed expander) ---------- */
.params-card {
  margin-top: var(--sp-3);
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: 14px;
  padding: 13px 14px;
}

.params-head {
  appearance: none;
  border: none;
  background: none;
  padding: 0;
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
}

.params-head:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
  border-radius: 6px;
}

.params-head__text {
  display: block;
  min-width: 0;
}

.params-head__titlerow {
  display: flex;
  align-items: center;
  gap: 8px;
}

.params-head__title {
  font-size: 14px;
  font-weight: 800;
  color: var(--c-ink);
}

.params-head__sub {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--c-muted);
}

.params-head__chev {
  flex-shrink: 0;
  display: flex;
  transition: transform 0.15s ease;
}

.params-head__chev--open {
  transform: rotate(180deg);
}

.params-badge {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--c-primary);
  background: var(--c-primary-tint);
  padding: 2px 8px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}

.params-badge--sm {
  padding: 1px 7px;
  font-size: 10px;
}

/* "from Samsara" provenance tag beside the Avg mpg label (Req 33). Sits right after the label
   (margin-right: auto absorbs the row's free space so the Edited badge stays pinned right). */
.params-tag {
  margin-right: auto;
  font-size: 10px;
  font-weight: 600;
  color: var(--c-success);
  white-space: nowrap;
}

.params-body {
  margin-top: 13px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 12px;
}

.params-field__labelrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 6px;
}

.params-field__label {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-faint);
}

.params-field__inputwrap {
  position: relative;
}

.params-field__input {
  height: 40px;
  padding-right: 40px;
  font-size: 14px;
  font-weight: 700;
}

.params-field__input::placeholder {
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 12.5px;
  color: var(--c-faint);
}

.params-field__input[aria-invalid="true"] {
  border-color: #c0353a;
}

.params-field__unit {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12px;
  font-weight: 600;
  color: var(--c-faint);
  pointer-events: none;
}

.params-foot {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.params-foot__hint {
  margin: 0;
  font-size: 11px;
  color: var(--c-faint);
}

/* ---------- special instructions (dispatcher note) ---------- */
.note-card {
  margin-top: var(--sp-3);
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: 14px;
  padding: 13px 14px;
}

.note-card__label {
  font-size: 14px;
  font-weight: 800;
  color: var(--c-ink);
}

.note-card__optional {
  font-weight: 600;
  color: var(--c-faint);
}

.note-card__sub {
  margin: 2px 0 10px;
  font-size: 12px;
  color: var(--c-muted);
}

.note-card__input {
  width: 100%;
  padding: 10px 12px;
  font-size: 14px;
  font-family: inherit;
  line-height: 1.45;
  color: var(--c-ink);
  background: #fff;
  border: 1.5px solid var(--c-border3);
  border-radius: var(--r-input);
  resize: vertical;
}

.note-card__input:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

.note-card__count {
  margin-top: 4px;
  text-align: right;
  font-size: 11px;
  color: var(--c-faint);
}

/* Dispatcher-note block on the review screen (matches the web review's note panel). */
.note-block {
  background: #f0f4ff;
  border: 1px solid var(--c-primary-border2);
  border-radius: var(--r-card);
  padding: 12px 14px;
  margin-top: 14px;
}

.note-block__label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-primary);
}

.note-block__text {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--c-body);
  white-space: pre-line;
}

/* Best-effort disclaimer under the note text (mirrors the web review caption). */
.note-block__caption {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--c-muted);
}

/* Zero-stop success notice on the review screen (FS-222): replaces the fuel-stop list when the
   plan's stops array is empty — current fuel already covers the route. */
.zero-stop {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--c-success-bg);
  border: 1px solid var(--c-success-soft);
  border-radius: var(--r-card);
  padding: 12px 14px;
  margin-top: 14px;
}

.zero-stop__text {
  font-size: 13px;
  font-weight: 700;
  color: var(--c-success-dark);
}

/* Visually-hidden live-region text for screen readers. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- fields / inputs ---------- */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: relative;
}

.field--inline {
  flex: 1;
  gap: 3px;
}

.input {
  width: 100%;
  height: 42px;
  padding: 8px 12px;
  font-size: 15px;
  font-family: inherit;
  color: var(--c-ink);
  background: #fff;
  border: 1.5px solid var(--c-border3);
  border-radius: var(--r-input);
}

/* Number inputs (the optimizer-parameter fields — the app's only type=number inputs): remove the
   native spinner arrows app-wide. They overlapped the unit suffix ("mpg"/"gal") and a tap on the
   arrow of an EMPTY field stepped it to 0 — instantly a phantom "1 edited" plus a bound error
   ("Avg mpg must be greater than 0"). Dispatchers type values; there's no stepping use case. */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

.input--bare {
  height: 30px;
  padding: 0;
  border: none;
  border-radius: 0;
  font-size: 14px;
  font-weight: 600;
  background: transparent;
}

.input--load {
  height: 32px;
  border: none;
  padding: 0;
  /* Conventional field: left-aligned with a normal in-input placeholder ("LD-12345") that clears on
     typing — not the old right-aligned decorative hint. */
  text-align: left;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 14px;
  background: transparent;
  flex: 1;
  min-width: 0;
}

.input--load::placeholder {
  color: var(--c-faint);
  font-weight: 400;
}

.input:focus-visible,
.linkbtn:focus-visible,
.btn:focus-visible,
.cta-btn:focus-visible,
a:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

.input--bare:focus-visible,
.input--load:focus-visible {
  outline-offset: 4px;
}

/* HERE autosuggest list */
.ac-list {
  list-style: none;
  margin: 6px 0 0;
  padding: 4px 0;
  border: 1px solid var(--c-border);
  border-radius: var(--r-input);
  background: #fff;
  max-height: 220px;
  overflow: auto;
  box-shadow: 0 12px 28px -16px rgba(11, 30, 80, 0.4);
}

.ac-item {
  padding: 9px 12px;
  font-size: 14px;
  cursor: pointer;
}

.ac-item:hover {
  background: var(--c-primary-tint2);
}

/* ---------- routes screen ---------- */
.screen-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}

.iconbtn {
  /* >=44px touch target (a11y) */
  min-width: 44px;
  min-height: 44px;
  border-radius: 8px;
  border: 1px solid #e2e7ef;
  background: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.screen-head__title {
  font-size: 17px;
  font-weight: 800;
  line-height: 1.1;
}

.screen-head__sub {
  font-size: 12px;
  color: var(--c-muted);
}

.map-frame {
  border-radius: 14px;
  overflow: hidden;
  position: relative;
  border: 1px solid var(--c-border);
  margin: var(--sp-3) 0;
}

.here-map {
  width: 100%;
  height: 150px;
  background: linear-gradient(160deg, #e9eef5, #dce3ee);
}

.here-map--review {
  height: 188px;
}

/* Classified route/review pin (HERE DomMarker inner node — see here.js markerNode). Size, background
   and pop-in delay are set inline per pin; HERE's positioning transform lives on the marker ROOT, so
   this inner node carries the centering margins and the scale animation. */
.map-pin {
  border-radius: 50%;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 12px;
  border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  animation: popIn 0.4s ease both;
}

.map-chip {
  position: absolute;
  top: 8px;
  left: 9px;
  background: #fff;
  border: 1px solid var(--c-border3);
  border-radius: 8px;
  padding: 5px 9px;
  font-size: 11px;
  font-weight: 700;
  color: var(--c-ink);
}

.map-chip--dark {
  top: 12px;
  left: 14px;
  background: rgba(14, 21, 37, 0.7);
  border: none;
  border-radius: var(--r-pill);
  padding: 5px 12px;
  color: #fff;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.route-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.route-opt {
  width: 100%;
  text-align: left;
  background: #fff;
  border: 1.5px solid var(--c-border);
  border-radius: 14px;
  padding: 13px 14px;
  cursor: pointer;
  font-family: inherit;
  margin-bottom: 9px;
}

.route-opt--selected {
  background: var(--c-primary-tint2);
  border-color: var(--c-primary);
}

.route-opt__top {
  display: flex;
  align-items: center;
  gap: 11px;
}

.radio {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid #c2ccda;
  background: #fff;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The dot follows the ROW's selected class — one source of truth, so the route-tap patch only
   toggles .route-opt--selected (no per-element radio class to keep in sync). */
.route-opt--selected .radio {
  border-color: var(--c-primary);
  background: var(--c-primary);
}

.radio__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #fff;
  opacity: 0;
}

.route-opt--selected .radio__dot {
  opacity: 1;
}

.route-opt__name {
  flex: 1;
  font-size: 15px;
  font-weight: 800;
}

.tag-best {
  font-size: 10px;
  font-weight: 700;
  color: var(--c-success-dark);
  background: var(--c-success-bg);
  border-radius: var(--r-pill);
  padding: 2px 8px;
  margin-left: 7px;
}

.route-opt__miles {
  font-size: 15px;
  font-weight: 800;
}

.route-opt__miles .unit {
  font-size: 10px;
  color: var(--c-faint);
}

.route-opt__meta {
  display: flex;
  gap: 14px;
  margin-top: 8px;
  padding-left: 31px;
}

.route-opt__meta span {
  font-size: 11.5px;
  color: var(--c-muted);
}

.route-opt__meta .k {
  color: var(--c-faint);
}

.route-opt__meta .v {
  color: var(--c-body);
  font-weight: 700;
}

/* ---------- full-screen overlays (sending / sent) ---------- */
.overlay {
  position: fixed;
  inset: 0;
  /* Contain the overlay BELOW the app header (true bottom edge incl. any safe-area inset) so the
     content never overlaps the header row. */
  top: var(--header-bottom);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  /* NOT justify-content:center — a flex-centered column CLIPS its overflow at BOTH ends (the
     unreachable-scroll fragment bug on the sending/sent screens). The single .overlay__center child
     centers via margin:auto instead, which degrades to a normal scroll when content is taller. */
  align-items: center;
  padding: 24px 20px calc(24px + env(safe-area-inset-bottom, 0px));
  background: var(--c-app-bg);
  z-index: 60;
  animation: fadeIn 0.2s ease;
  text-align: center;
}

.overlay__center {
  margin: auto 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
}

.spinner {
  position: relative;
  width: 84px;
  height: 84px;
}

.spinner__svg {
  animation: spin 1s linear infinite;
}

.spinner__bolt {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.overlay__title {
  font-size: 18px;
  font-weight: 800;
}

.overlay__sub {
  font-size: 14px;
  color: var(--c-muted);
  margin-top: 4px;
}

/* ---------- optimizing screen (branded in-flow card + skeleton stop list) ---------- */
.opt-card {
  margin-top: 4px;
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: 24px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  text-align: center;
}

.route-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  background: var(--c-primary-tint);
  border: 1px solid var(--c-primary-border2);
  border-radius: var(--r-pill);
  padding: 6px 13px;
  font-size: 12px;
  font-weight: 700;
  color: var(--c-primary);
}

.route-chip__text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skel-card {
  background: #fff;
  border: 1px solid var(--c-border2);
  border-radius: var(--r-card);
  padding: 14px;
  margin-bottom: 10px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.skel-card__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding-top: 2px;
}

.skel {
  display: block;
  background: linear-gradient(90deg, #eef1f6 25%, #f7f9fc 45%, #eef1f6 65%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
}

.skel-num {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  flex-shrink: 0;
}

.skel-line {
  height: 11px;
  border-radius: 6px;
}

.skel-line--lg {
  height: 16px;
  margin-top: 3px;
}

/* ---------- sending card ---------- */
.sending-spin {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 5px solid #dcf0e7;
  border-top-color: var(--c-success);
  animation: spin 0.8s linear infinite;
}

.send-card {
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: 30px 22px;
  width: 100%;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.send-card__title {
  font-size: 17px;
  font-weight: 800;
  color: var(--c-ink);
}

/* One truncated line — the full (often very long) group label lives in the title attribute. */
.send-card__group {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-muted);
}

.send-card__hint {
  font-size: 12px;
  color: var(--c-faint);
}

/* ---------- sent screen ---------- */
.sent-check {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: var(--c-success-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: pop 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

.sent-check__inner {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--c-success);
  display: flex;
  align-items: center;
  justify-content: center;
}

.sent-title {
  font-size: 21px;
  font-weight: 800;
  color: var(--c-ink);
}

/* One truncated line for the (long) group label; full label via the title attribute. */
.sent-group {
  max-width: 300px;
  margin: 4px auto 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-muted);
}

.savings-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 14px;
  background: var(--c-success-bg);
  color: var(--c-success-dark);
  border-radius: var(--r-pill);
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 700;
}

.sent-note {
  margin: 0;
  max-width: 300px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--c-faint);
}

.summary-card {
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: 14px;
  padding: 14px 18px;
  /* Spacing comes from .overlay__center's gap. */
  width: 100%;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.summary-row {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
}

.summary-row .k {
  color: var(--c-muted);
}

.summary-row .v {
  font-weight: 700;
}

.summary-row .v--ok {
  color: var(--c-success);
}

/* ---------- review ---------- */
.review-map {
  height: 188px;
  background: linear-gradient(160deg, #1b2740, #0e1525);
  position: relative;
  overflow: hidden;
  border-radius: var(--r-card);
}

.review-body {
  padding: 16px 0 0;
  display: flex;
  flex-direction: column;
}

.savings-hero {
  background: linear-gradient(135deg, var(--c-success), var(--c-success-dark));
  border-radius: 18px;
  padding: 16px 18px;
  color: #fff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0 10px 24px -10px rgba(14, 158, 110, 0.6);
}

.savings-hero__eyebrow {
  font-size: 12px;
  font-weight: 600;
  opacity: 0.85;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.savings-hero__big {
  font-size: 30px;
  font-weight: 800;
  line-height: 1.1;
}

.savings-hero__note {
  font-size: 12px;
  opacity: 0.85;
}

.savings-hero__total {
  font-size: 22px;
  font-weight: 800;
}

/* Whole-journey rows (Starting point / route Stop / Destination) bracketing and interleaving the
   rich fuel-stop cards — simple rows (web BookendCard parity), never full cards. */
.jrow {
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: 11px 14px;
  margin-bottom: 10px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.jrow__num {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--c-primary-tint);
  color: var(--c-primary);
  font-weight: 800;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Green-tinted start badge (the truck's onboard state lives here). */
.jrow--start .jrow__num {
  background: var(--c-success-bg);
  color: var(--c-success-dark);
}

.jrow__body {
  flex: 1;
  min-width: 0;
}

.jrow__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.jrow__title {
  font-size: 14px;
  font-weight: 700;
}

.jrow__mi {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--c-muted);
  flex-shrink: 0;
}

.jrow__addr {
  font-size: 12px;
  color: var(--c-muted);
  margin-top: 1px;
}

.jrow__onboard {
  font-size: 11.5px;
  color: var(--c-faint);
  margin-top: 2px;
}

.stop-card {
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: 14px;
  margin-bottom: 10px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.stop-num {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--c-ink);
  color: #fff;
  font-weight: 800;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.stop-card__body {
  flex: 1;
  min-width: 0;
}

.stop-card__name {
  font-size: 15px;
  font-weight: 700;
}

.stop-card__store {
  color: var(--c-faint);
  font-weight: 600;
  font-size: 13px;
}

.stop-card__loc {
  font-size: 12.5px;
  color: var(--c-muted);
  margin-top: 1px;
}

.stop-card__figs {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-top: 11px;
  gap: 8px;
}

.fig__label {
  font-size: 11px;
  color: var(--c-faint);
  font-weight: 700;
  text-transform: uppercase;
}

.fig__value {
  font-size: 17px;
  font-weight: 800;
}

.fig__value .unit {
  font-size: 12px;
  color: var(--c-muted);
  font-weight: 600;
}

.fig__value--price {
  color: var(--c-primary);
}

.fig__value--price .per {
  font-size: 11px;
  color: var(--c-faint);
}

.fig--right {
  text-align: right;
}

.save-badge {
  margin-top: 9px;
  display: flex;
  align-items: center;
  gap: 7px;
  background: var(--c-success-bg);
  border-radius: 8px;
  padding: 6px 10px;
}

.save-badge__text {
  font-size: 12px;
  font-weight: 700;
  color: var(--c-success-dark);
}

.stop-card__tank {
  margin-top: 8px;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--c-success-dark);
}

.stop-card__tank-label {
  opacity: 0.75;
}

.stop-card__reason {
  margin-top: 9px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--c-muted);
}

.stop-card__maps {
  margin-top: 9px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 700;
  color: var(--c-primary);
  text-decoration: none;
}

.stop-card__maps:active {
  opacity: 0.7;
}

.reasoning {
  background: #f0f4ff;
  border: 1px solid var(--c-primary-border2);
  border-radius: var(--r-card);
  padding: 15px;
  margin-top: 4px;
}

.reasoning__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.reasoning__title {
  font-size: 13px;
  font-weight: 800;
  color: #0b3fb0;
}

.reasoning__text {
  font-size: 13px;
  color: var(--c-body);
  line-height: 1.5;
  white-space: pre-line;
  margin: 0;
}

.confidential {
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--c-faint);
  justify-content: center;
  text-align: center;
}

.demo-banner {
  padding: 12px 14px;
  border-radius: var(--r-input);
  background: var(--c-warn-bg);
  color: #a9701a;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: var(--sp-3);
}

/* ---------- errors / hints ---------- */
.error {
  margin: var(--sp-3) 0 0;
  padding: 10px 12px;
  border-radius: var(--r-input);
  background: #fff5f5;
  color: #c0353a;
  font-size: 13px;
  border: 1px solid #f3d3d3;
}

.warn-note {
  margin: 10px 0 0;
  padding: 10px 12px;
  border-radius: var(--r-input);
  background: var(--c-warn-bg);
  color: #a9701a;
  font-size: 13px;
}

/* Tier upsell (403 upgrade_required): inline blocking notice on the routes step. Warn-toned like
   .warn-note but with room for the web-billing link, which must wrap inside the narrow column. */
.upgrade-note {
  margin: 12px 0 0;
  padding: 12px 14px;
  border-radius: var(--r-input);
  background: var(--c-warn-bg);
  color: #a9701a;
  font-size: 13px;
  line-height: 1.5;
}

.upgrade-note__link {
  color: var(--c-primary);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  overflow-wrap: anywhere; /* the URL-shaped label must wrap inside the notice */
}

.hint-center {
  font-size: 13px;
  color: var(--c-muted);
  text-align: center;
  margin: 12px 0 0;
}

.gate-hint {
  font-size: 12.5px;
  color: var(--c-muted);
  text-align: center;
  margin: 0 0 8px;
}

/* In-flow "next step" pill (Telegram path): anchored guidance at the end of the compose form, in
   normal document flow — NEVER fixed (the fixed .cta-bar floats mid-screen inside Telegram, where
   the bottom belongs to the native MainButton). The .screen bottom padding keeps it above the
   MainButton / home indicator. Muted while a field is missing; green the moment the form is ready. */
.next-pill {
  display: block;
  margin: var(--sp-3) auto 0;
  max-width: 480px;
  padding: 10px 16px;
  border: 1px solid var(--c-border);
  border-radius: var(--r-pill);
  background: #fff;
  color: var(--c-muted);
  font-size: 13px;
  text-align: center;
}

.next-pill--ready {
  border-color: var(--c-success);
  background: var(--c-success-bg);
  color: var(--c-success-dark);
  font-weight: 700;
}

/* ---------- buttons ---------- */
.btn {
  appearance: none;
  border: 1.5px solid transparent;
  border-radius: var(--r-input);
  padding: 11px 16px;
  font-size: 14px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
}

.btn[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--c-primary);
  color: #fff;
}

/* sticky bottom CTA */
.cta-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 14px 16px calc(26px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(to top, var(--c-app-bg) 70%, rgba(244, 246, 250, 0));
  z-index: 30;
}

.cta-inner {
  max-width: 480px;
  margin: 0 auto;
}

.cta-btn {
  width: 100%;
  background: var(--c-primary);
  color: #fff;
  border: none;
  border-radius: 14px;
  padding: 16px;
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  box-shadow: 0 10px 24px -8px rgba(11, 95, 255, 0.6);
}

.cta-btn--success {
  background: var(--c-success);
  box-shadow: 0 10px 24px -8px rgba(14, 158, 110, 0.6);
}

.cta-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.btn-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 320px;
}

/* ---------- full-screen blocking states (outside Telegram / missing carrier / not authorized) ---------- */
.blocking {
  max-width: 420px;
  min-height: 65vh;
  margin: 0 auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 8px;
}

.blocking__logo {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: linear-gradient(135deg, var(--c-primary), var(--c-primary-dark));
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 24px -8px rgba(11, 95, 255, 0.6);
  margin-bottom: 2px;
}

.blocking__name {
  font-size: 15px;
  font-weight: 800;
  color: var(--c-ink);
}

.blocking__title {
  margin: 8px 0 0;
  font-size: 19px;
  font-weight: 800;
  color: var(--c-ink);
}

.blocking__text {
  margin: 0;
  max-width: 300px;
  font-size: 14px;
  color: var(--c-muted);
}

.blocking .btn {
  margin-top: 12px;
  min-width: 160px;
}

/* Inline link inside a blocking message (billing_locked → web billing settings). Primary-colored
   (unlike the muted legal footer) so the one actionable path out of the lock reads as a link. */
.blocking__link {
  color: var(--c-primary);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  overflow-wrap: anywhere; /* the URL-shaped label must wrap inside the 300px text column */
}

a {
  color: var(--c-primary);
}

/* ---------- keyframes ---------- */
@keyframes scIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes sheetUp {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes ring {
  from {
    stroke-dashoffset: 327;
  }
}
@keyframes pop {
  0% {
    transform: scale(0.5);
    opacity: 0;
  }
  60% {
    transform: scale(1.08);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}
@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes shimmer {
  0% {
    background-position: 100% 0;
  }
  100% {
    background-position: -100% 0;
  }
}
@keyframes popIn {
  0% {
    transform: scale(0);
    opacity: 0;
  }
  70% {
    transform: scale(1.15);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* ---------- group picker bottom sheet ---------- */
.sheet-scrim {
  position: fixed;
  inset: 0;
  background: rgba(8, 12, 20, 0.45);
  z-index: 50;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.sheet {
  background: #fff;
  border-radius: 24px 24px 0 0;
  max-height: 78%;
  display: flex;
  flex-direction: column;
}

/* Entrance motion is KEYED by render() (same discipline as .screen--enter): the scrim fade and the
   slide-up play only on the render where the sheet OPENS — a full render while it's already open
   (e.g. an async resolve) must not replay the slide from the bottom under the user's finger. */
.sheet-scrim--enter {
  animation: fadeIn 0.2s ease;
}

.sheet--enter {
  animation: sheetUp 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.sheet__handle-wrap {
  padding: 14px 0 6px;
  display: flex;
  justify-content: center;
}

.sheet__handle {
  width: 38px;
  height: 4px;
  border-radius: 3px;
  background: #d3dae5;
}

.sheet__head {
  padding: 4px 20px 12px;
}

.sheet__title {
  font-size: 18px;
  font-weight: 800;
}

.sheet__sub {
  font-size: 13px;
  color: var(--c-muted);
}

/* Live filter for the group picker (matches group name or unit). Reuses .input styling. */
.sheet__search {
  padding: 0 20px 12px;
}

.sheet__list {
  overflow-y: auto;
  padding: 0 12px 24px;
}

.sheet-row {
  width: 100%;
  text-align: left;
  background: #fff;
  border: 1.5px solid var(--c-border);
  border-radius: 14px;
  padding: 13px 14px;
  display: flex;
  align-items: center;
  gap: 13px;
  cursor: pointer;
  font-family: inherit;
  margin-bottom: 8px;
}

.sheet-row--disabled {
  cursor: default;
  opacity: 0.85;
}

.sheet-row__badge {
  width: 40px;
  height: 40px;
  border-radius: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-weight: 800;
  font-size: 12px;
}

.sheet-row__badge--mapped {
  background: var(--c-primary-tint);
  color: var(--c-primary);
}

.sheet-row__badge--unmapped {
  background: var(--c-warn-bg);
  color: var(--c-warn);
}

.sheet-row__body {
  flex: 1;
  min-width: 0;
}

.sheet-row__name {
  font-size: 15px;
  font-weight: 700;
}

.sheet-row__sub {
  font-size: 12px;
  color: var(--c-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row-tag {
  font-size: 11px;
  font-weight: 700;
  padding: 4px 9px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  flex-shrink: 0;
}

.row-tag--mapped {
  color: var(--c-success);
  background: var(--c-success-bg);
}

.row-tag--unmapped {
  color: var(--c-warn);
  background: var(--c-warn-bg);
}

/* ---------- legal footer (compose) ---------- */
/* One muted line linking the landing-site Terms/Privacy pages (opened outside the webview). */
.legal-foot {
  margin: var(--sp-3) 0 0;
  text-align: center;
  font-size: 11.5px;
  color: var(--c-muted);
}
.legal-foot__link {
  color: var(--c-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .map-route-draw {
    stroke-dashoffset: 0 !important;
  }
}

/* ---------- Send load (load-formatter view) ---------- */
/* Mode tabs — Fuel plan | Send load, top-level screens only. Rendered INSIDE the padded .app shell,
   so no extra horizontal margin: the tabs align flush with the cards below them (they used to be
   double-inset — 16px shell padding + 16px own margin — and read as a floating stray element). */
.view-tabs {
  display: flex;
  gap: 6px;
  margin: 0 0 var(--sp-4);
  padding: 4px;
  background: #fff;
  border: 1.5px solid var(--c-border2);
  border-radius: var(--r-input);
}
.view-tab {
  appearance: none;
  border: none;
  flex: 1;
  padding: 9px 10px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  color: var(--c-secondary);
  background: transparent;
  border-radius: 9px;
  cursor: pointer;
}
.view-tab--active {
  background: var(--c-primary-tint);
  color: var(--c-primary);
}
.view-tab:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

.load-form-card {
  background: #fff;
  border: 1.5px solid var(--c-border2);
  border-radius: var(--r-card);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.load-field__label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-faint);
}
.load-field__label .req {
  color: var(--c-danger);
}

/* Stop cards */
.ls-stop {
  background: #fff;
  border: 1.5px solid var(--c-border2);
  border-radius: var(--r-card);
  padding: 12px 14px 14px;
  margin-bottom: 10px;
}
.ls-stop__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.ls-stop__num {
  font-weight: 700;
  font-size: 13px;
  color: var(--c-muted);
}
.ls-stop__kind-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--c-faint);
}
.ls-stop__remove {
  appearance: none;
  border: none;
  background: none;
  margin-left: auto;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border-radius: 10px;
}
.ls-stop__remove:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}
.ls-stop__grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ls-row2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.kind-toggle {
  display: inline-flex;
  border: 1.5px solid var(--c-border3);
  border-radius: 9px;
  overflow: hidden;
}
.kind-btn {
  appearance: none;
  border: none;
  background: #fff;
  padding: 6px 12px;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--c-secondary);
  cursor: pointer;
}
.kind-btn--on.kind-btn--pu {
  background: var(--c-primary);
  color: #fff;
}
.kind-btn--on.kind-btn--del {
  background: var(--c-success);
  color: #fff;
}
.kind-btn:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: -2px;
}

/* Micro-QoL chips (Send load): one tap fills the field's text; the field stays free text.
   Same visual family as .kind-btn (bordered white pill, small bold label). */
.qol-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.qol-chip {
  appearance: none;
  border: 1.5px solid var(--c-border3);
  border-radius: 999px;
  background: #fff;
  padding: 4px 10px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--c-secondary);
  cursor: pointer;
}
.qol-chip:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

/* Operational rules */
.rules-card {
  background: #fff;
  border: 1.5px solid var(--c-border2);
  border-radius: var(--r-card);
  padding: 14px;
  margin-top: 14px;
}
.rules-card__title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-faint);
  margin-bottom: 8px;
}
.rules-card__note {
  font-size: 12.5px;
  color: var(--c-muted);
  margin: 4px 0;
}
.rules-card__hint {
  font-size: 11.5px;
  color: var(--c-faint);
}
.rule-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.rule-row__check {
  width: 17px;
  height: 17px;
  accent-color: var(--c-primary);
  flex-shrink: 0;
}
.rule-row__text {
  height: 38px;
  font-size: 13.5px;
  flex: 1;
  min-width: 0;
}
.rule-row__text--off {
  color: var(--c-faint);
  text-decoration: line-through;
}
.rule-row__remove {
  appearance: none;
  border: none;
  background: none;
  min-width: 38px;
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border-radius: 10px;
  flex-shrink: 0;
}
.rule-row__remove:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}
.rule-add {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.rule-add__input {
  height: 38px;
  font-size: 13.5px;
  flex: 1;
  min-width: 0;
}
.rule-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  flex-wrap: wrap;
}

/* Message preview — dark Telegram-ish block (mirror of the web TelegramPreview's bubble look). */
.load-preview {
  background: linear-gradient(165deg, #101a2e, #0b1322);
  border-radius: var(--r-card);
  padding: 14px;
  color: #edf1f5;
  font-size: 13.5px;
  line-height: 1.5;
}
.load-preview__empty {
  color: #708499;
  font-style: italic;
  font-size: 13px;
  margin: 4px 0;
}
.load-preview__line {
  white-space: pre-wrap;
  word-break: break-word;
}
.load-preview__divider {
  color: #3a4a5f;
  user-select: none;
}
.load-preview__chip {
  appearance: none;
  border: none;
  display: block;
  width: 100%;
  text-align: left;
  margin: 4px 0;
  padding: 8px 10px;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 8px;
  cursor: pointer;
  position: relative;
}
.load-preview__chip:focus-visible {
  outline: 2px solid #2aabee;
  outline-offset: 2px;
}
.load-preview__chip-text {
  display: block;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.45;
  color: #5ca8eb;
}
.load-preview__chip--copied::after {
  content: "Copied";
  position: absolute;
  top: 6px;
  right: 8px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #4fae4e;
}

/* Sent screen */
.load-sent {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 8px;
  padding: 26px 18px;
}
.load-sent__check {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--c-success-bg);
  display: flex;
  align-items: center;
  justify-content: center;
}
.load-sent__title {
  font-size: 17px;
  font-weight: 800;
  color: var(--c-ink);
}
.load-sent__note {
  font-size: 13px;
  color: var(--c-body);
}
.cta-btn--inflow {
  margin-top: 10px;
  position: static;
  width: auto;
  padding: 10px 18px;
}
.linkbtn--add {
  gap: 6px;
}
