/* Wave 1 UI fixes (owner's screenshots, Android ~390 px). Linked near the end of <head>, right before v141-install.css
   * (tests/install-banner.test.mjs requires that sheet last).
 * 1. Círculo map indicator: compact button + popover.   2. Startup: stable top card, no boot transitions.
 * 3. Trip mode: no "Menu" pill, GPS button.              4. Share-trip progress.   5. GPS button.   6. Stop cards. */

/* ---------- 1 · Círculo on the map: compact button + status popover (circle-ui.mjs pillMarkup) ---------- */
/* The pill ("👥 ● Compartilhando ≈ 500 m ||") took ~60 % of a phone's width above the zoom buttons. Now it is one
 * 44 px button in the right-hand control column (people icon + status dot, "≈ 500 m" only when approximate); a tap
 * opens a small popover with the full status, the precision, Pausar/Retomar and "Abrir Círculo". */
html body .map-panel .circle-pill { max-width: none; }
html body .map-panel .circle-pill .circle-pill-compact { position: relative; justify-content: center; gap: 6px; width: auto; min-width: 44px; padding: 0 12px 0 12px; border-radius: 22px; }
html body .map-panel .circle-pill .circle-pill-compact:not(:has(.circle-pill-approx)) { width: 44px; padding: 0; }
html body .map-panel .circle-pill .circle-pill-compact > .ui-icon { width: 20px; height: 20px; flex: 0 0 20px; color: var(--circle-accent); }
.circle-pill-dot { position: absolute; top: 7px; left: 28px; width: 10px; height: 10px; border-radius: 50%; background: var(--circle-muted); box-shadow: 0 0 0 2px var(--circle-surface); }
.circle-pill-dot[data-state="live"] { background: var(--circle-live); animation: wave1-circle-live 2.4s ease-out infinite; }
.circle-pill-dot[data-state="blocked"] { background: var(--circle-warn-ink); }
.circle-pill-dot[data-state="elsewhere"] { background: var(--circle-surface); box-shadow: inset 0 0 0 2px var(--circle-live), 0 0 0 2px var(--circle-surface); }
.circle-pill-dot[data-state="none"] { display: none; }
@keyframes wave1-circle-live { 0% { box-shadow: 0 0 0 2px var(--circle-surface), 0 0 0 2px color-mix(in srgb, var(--circle-live) 55%, transparent); } 70%, 100% { box-shadow: 0 0 0 2px var(--circle-surface), 0 0 0 8px transparent; } }
@media (prefers-reduced-motion: reduce) { .circle-pill-dot[data-state="live"] { animation: none; } }
body.reduce-motion .circle-pill-dot[data-state="live"] { animation: none; }
html body .map-panel .circle-pill .circle-pill-compact .circle-pill-approx { font-size: 11px; }
html body .map-panel .circle-pill[data-expanded="true"] .circle-pill-compact { background: var(--circle-accent-soft); }

/* Popover: below the button where the pill sits at the top (tablet, desktop, trip), above it in the phone's control
 * column (right edge aligned with the column). */
.circle-pill-pop { display: none; }
html body .map-panel .circle-pill[data-expanded="true"] .circle-pill-pop {
  position: absolute; z-index: 5; top: calc(100% + 8px); right: 0;
  display: grid; gap: 10px; width: min(284px, calc(100vw - 24px)); padding: 12px;
  border: 1px solid var(--circle-line); border-radius: 18px; background: var(--circle-surface); color: var(--circle-ink); box-shadow: var(--circle-shadow);
  font-family: 'DM Sans', system-ui, sans-serif; white-space: normal; cursor: default;
}
.circle-pill-pop-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.circle-pill-pop-head .circle-stack { flex: none; }
.circle-pill-pop-icon { display: grid; flex: 0 0 36px; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: var(--circle-accent-soft); color: var(--circle-accent); }
.circle-pill-pop-icon .ui-icon { width: 20px; height: 20px; }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-text { display: grid; gap: 2px; min-width: 0; overflow: visible; white-space: normal; color: var(--circle-ink); }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-text strong { font-size: 14px; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-text strong[data-live] { color: var(--circle-live-ink); }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-text strong[data-live="blocked"] { color: var(--circle-warn-ink); }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-text strong[data-live="elsewhere"] { color: var(--circle-muted); }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-with { display: inline; color: var(--circle-ink); font-weight: 600; }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-text small { color: var(--circle-muted); font-size: 12px; font-weight: 500; line-height: 1.4; }
.circle-pill-pop-actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; }
html body .map-panel .circle-pill .circle-pill-pop button {
  justify-content: center; gap: 6px; width: auto; min-width: 0; height: auto; min-height: 44px; padding: 0 12px;
  border: 1px solid var(--circle-line); border-radius: 12px; background: var(--circle-surface); color: var(--circle-accent); font-size: 13px;
}
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-toggle svg { width: 16px; height: 16px; }
html body .map-panel .circle-pill .circle-pill-pop .circle-pill-sheet { border-color: transparent; background: var(--circle-button); color: var(--circle-on-button); }
@media (hover: hover) { html body .map-panel .circle-pill .circle-pill-pop .circle-pill-toggle:hover { background: var(--circle-raised); } }
@media (max-width: 600px) {
  html body.map-shell:not(.travel-active, .journey-navigation-active) .map-panel .circle-pill[data-expanded="true"] .circle-pill-pop { top: auto; bottom: calc(100% + 8px); }
}
html body.map-shell:is(.travel-active, .journey-navigation-active) .map-panel .circle-pill[data-expanded="true"] .circle-pill-pop { right: auto; left: 0; }
html body.map-shell:is(.travel-active, .journey-navigation-active) .map-panel .circle-pill .circle-pill-pop .circle-stack { display: inline-flex; }
/* During a trip the compact button sits in the top-left corner like before (v140-circle.css), now 44 px wide. */
html body.map-shell:is(.travel-active, .journey-navigation-active) .map-panel .circle-pill { max-width: none; }

/* ---------- 2 · Startup: the top card has its final shape from the first paint ---------- */
/* Before initMapShell moves the tabs out of the panel, the panel's rounded clip cut the fixed tabs in half and the
 * menu trigger showed as a dark square in the corner. */
html body.map-shell:not(.map-shell-ready) .app-shell .control-panel { clip-path: none; }
html body.map-shell:not(.map-shell-ready) :is(#mobile-nav-trigger, #mobile-nav) { visibility: hidden; }
/* No transitions while the startup states replace each other (index.html sets the class, app.js endBoot() removes it). */
html body.map-shell.map-shell-booting :is(.workspace-tabs, .control-panel, .map-shell-navigation, .map-panel) :is(*, *::before, *::after) { transition: none !important; }
/* The departure card switches from the violet call to action to the light "Partida" card: an all-properties transition
 * faded white text over the light background (the title looked empty for a moment). Only feedback properties animate. */
html body #location-button { transition: box-shadow .2s ease, transform .2s ease; }

/* Placeholder shaped like "Escolha seu ponto" (app.js stopListLoadingMarkup, index.html). Same classes as the cards,
 * so heights match; the words are transparent and bars are drawn instead. */
.stop-list-loading { --sk-bar: var(--flow-skeleton, #e9e5f3); --sk-shine: var(--flow-skeleton-shine, #f6f4fc); }
.stop-list-loading .nearby-stop-heading h2 { display: flex; align-items: center; gap: 8px; }
.stop-list-loading .nearby-stop-heading h2::before {
  content: ''; flex: 0 0 12px; width: 12px; height: 12px; border: 2px solid var(--sk-bar); border-top-color: var(--shell-accent, var(--navy)); border-radius: 50%;
  animation: wave1-spin .8s linear infinite;
}
.stop-list-loading .nearby-stop-heading > b:empty { display: none; }
.nearby-stop-choice.is-skeleton { pointer-events: none; cursor: default; }
.nearby-stop-choice.is-skeleton .nearby-stop-icon { background: var(--sk-bar) !important; box-shadow: none !important; }
.nearby-stop-choice.is-skeleton :is(strong, small, i) { position: relative; color: transparent !important; }
.nearby-stop-choice.is-skeleton :is(strong, small, i)::before {
  content: ''; position: absolute; left: 0; top: 50%; width: 72%; height: .78em; border-radius: 6px; transform: translateY(-50%);
  background: linear-gradient(90deg, var(--sk-bar) 20%, var(--sk-shine) 50%, var(--sk-bar) 80%) 0 0 / 250% 100%;
  animation: wave1-shimmer 1.6s ease-in-out infinite;
}
.nearby-stop-choice.is-skeleton small::before { width: 46%; }
.nearby-stop-choice.is-skeleton i { width: 58px; }
.nearby-stop-choice.is-skeleton i::before { width: 100%; }
@keyframes wave1-spin { to { transform: rotate(360deg); } }
@keyframes wave1-shimmer { to { background-position: -150% 0; } }
@media (prefers-reduced-motion: reduce) {
  .stop-list-loading .nearby-stop-heading h2::before, .nearby-stop-choice.is-skeleton :is(strong, small, i)::before { animation: none; }
}
body.reduce-motion :is(.stop-list-loading .nearby-stop-heading h2, .nearby-stop-choice.is-skeleton :is(strong, small, i))::before { animation: none; }
/* The transport view's entrance animation (opacity + 6 px slide, product.css) also ran on the first load, under the fixed
 * top card. In the map shell this view is the full-screen map itself: it stays still (other views keep their animation).
 * Not tied to map-shell-booting: removing that class would restart the animation. */
html body.map-shell .app-shell.product-view { animation: none; }

/* ---------- 6 · "Escolha seu ponto": a card never rests half-scrolled ---------- */
/* With "proximity" snapping, a medium swipe left the carousel between two cards: the first card showed only its right
 * edge ("Ver ônibus", no icon, name or distance) while the second looked fine. Phones always settle on a card start. */
@media (max-width: 900px) {
  html body .nearby-stop-list { scroll-snap-type: x mandatory; }
}

/* ---------- 5 · GPS button: "Você está aqui" + "Usar como partida" (app.js showGpsOffer) ---------- */
.gps-offer {
  position: fixed;
  z-index: 640;
  left: max(var(--shell-gap, 12px), env(safe-area-inset-left, 0px));
  right: calc(max(var(--shell-gap, 12px), env(safe-area-inset-right, 0px)) + var(--v138-ctrl, 44px) + var(--v138-ctrl-gap, 8px));
  bottom: calc(var(--v138-ctrl-base, var(--shell-bottom, 104px)) + var(--v138-ctrl, 44px) + var(--v138-ctrl-gap, 8px));
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) 40px;
  align-items: center;
  column-gap: 10px;
  row-gap: 8px;
  max-width: 420px;
  padding: 8px 6px 8px 10px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--v138-shadow, 0 8px 28px #0f1a2e1f);
}
.gps-offer[hidden] { display: none; }
.gps-offer-icon { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: var(--shell-accent, var(--navy)); color: #fff; }
.gps-offer-icon svg { width: 16px; height: 16px; fill: currentColor; }
.gps-offer[data-precision="approximate"] .gps-offer-icon { background: var(--paper); color: var(--shell-accent, var(--navy)); box-shadow: inset 0 0 0 2px var(--shell-accent, var(--navy)); }
.gps-offer-copy { min-width: 0; }
.gps-offer-copy strong { display: block; font-size: 13.5px; line-height: 1.3; }
.gps-offer-copy small { display: block; margin-top: 2px; color: var(--muted); font-size: 12px; line-height: 1.4; }
.gps-offer-close { grid-column: 3; grid-row: 1; display: grid; place-items: center; width: 40px; height: 44px; margin: -6px 0; padding: 0; border: 0; border-radius: 12px; background: transparent; color: var(--muted); cursor: pointer; }
.gps-offer-close svg { width: 18px; height: 18px; }
.gps-offer-use { grid-column: 1 / -1; grid-row: 2; min-height: 44px; margin-right: 4px; border: 0; border-radius: 12px; background: var(--shell-accent, var(--navy)); color: #fff; font: 700 14px/1.2 'DM Sans', system-ui, sans-serif; cursor: pointer; }
.gps-offer-use[hidden] { display: none; }
:root[data-theme="dark"] .gps-offer-use { background: var(--l360-button, #7c4dff); }
.gps-offer :is(button):focus-visible { outline: 3px solid var(--shell-accent, var(--navy)); outline-offset: 2px; }
/* Out of the way whenever something else owns the screen. */
html body.map-shell:is(.map-shell-arrivals-open, .map-shell-menu-open, .origin-picking, .travel-active, .journey-navigation-active) .gps-offer,
html body.map-shell:has(dialog[open]) .gps-offer { display: none; }
@media (max-width: 600px) {
  html body.map-shell.map-shell-planner-open .gps-offer { display: none; }
}
@media (min-width: 601px) {
  .gps-offer { left: auto; width: min(380px, calc(100vw - 2 * var(--shell-gap, 20px) - var(--shell-panel-width, 366px) - 80px)); }
}
/* The blue "you are here" next to an address departure; dashed and without the pulse when it is only approximate. */
.map-pin.user.gps-here { z-index: 2; }
.map-pin.user.gps-here.is-approximate { opacity: .92; }
.map-pin.user.gps-here.is-approximate::before { inset: -12px; border: 2px dashed color-mix(in srgb, var(--shell-accent, #6d28d9) 70%, transparent); background: color-mix(in srgb, var(--shell-accent, #6d28d9) 10%, transparent); animation: none; }
/* The trip GPS button (item 3) shows the same working ring as the map's GPS button (v139-gps.css). */
html body .travel-gps-button.is-locating { pointer-events: none; }
html body .travel-gps-button.is-locating::after {
  content: ''; position: absolute; inset: 6px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: wave1-spin .8s linear infinite; pointer-events: none;
}
@media (prefers-reduced-motion: reduce) { html body .travel-gps-button.is-locating::after { animation-duration: 2.4s; } }

/* ---------- 3 · Trip mode: no "Menu" pill, GPS button beside the trip panel ---------- */
/* While the trip summary ("Embarque confirmado", Desembarque, Finalizar) is on the map, the "^ Menu" pill took a whole
 * row under it. It leaves; the same toggle is a small icon inside the summary (#travel-mini-menu, app.js
 * mountTripControls: menu icon to reopen the navigation, chevron to fold it) and, with the navigation folded, the
 * summary drops to the footer band (logo + credits stay). */
html body.map-shell.map-shell-dock-collapsed:has(#travel-mini-dock:not([hidden])) { --shell-bottom: calc(var(--shell-footer) + 8px); }
html body.map-shell:has(#travel-mini-dock:not([hidden])) .map-shell-navigation .map-shell-dock-toggle { display: none; }
html body.map-shell .travel-mini-dock #travel-mini-menu {
  display: grid; place-items: center; align-self: center; justify-self: end; z-index: 1751; /* #travel-mini carries z-index 1750 (travel.css) */
  width: 44px; height: 44px; margin-right: 2px; padding: 0;
  border: 1px solid var(--travel-line); border-radius: 14px; background: var(--travel-paper); color: var(--journey-accent, var(--navy)); cursor: pointer;
}
.travel-mini-dock #travel-mini-menu svg { width: 20px; height: 20px; }
/* Phones: the icon shares the summary row (same grid cell, at its right end); the summary keeps its full width. */
@media (max-width: 719px) {
  html body.map-shell .travel-mini-dock #travel-mini-confirm { grid-row: 1; }
  html body.map-shell .travel-mini-dock :is(#travel-mini, #travel-mini-menu) { grid-column: 1 / -1; grid-row: 1; }
  html body.map-shell .travel-mini-dock.has-confirm :is(#travel-mini, #travel-mini-menu) { grid-row: 2; }
  html body.map-shell .travel-mini-dock #travel-mini { padding-right: 54px; }
}
@media (min-width: 720px) {
  html body.map-shell .travel-mini-dock { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) auto auto auto; }
  html body.map-shell .travel-mini-dock #travel-mini { grid-column: 1; }
  html body.map-shell .travel-mini-dock #travel-mini-menu { grid-column: 5; grid-row: 2; }
  html body.map-shell .travel-mini-dock #travel-mini-confirm { grid-column: 1 / -1; }
}
@media (hover: hover) { .travel-mini-dock #travel-mini-menu:hover { background: var(--travel-soft); } }

/* "Centralizar no meu GPS" (#travel-gps): the map's GPS button, right above the trip panel (summary or sheet). */
.travel-gps-button { display: none; }
html body.map-shell:has(#travel-mini-dock:not([hidden])) .map-panel .travel-gps-button,
html body.map-shell.travel-active:has(#travel-sheet:not([hidden])) .map-panel .travel-gps-button {
  position: fixed;
  z-index: 1760;
  right: max(var(--shell-gap, 12px), env(safe-area-inset-right, 0px));
  bottom: calc(var(--shell-bottom) + var(--travel-sheet-height, 150px) + 12px);
  display: grid;
  place-items: center;
  width: var(--v138-ctrl, 44px);
  height: var(--v138-ctrl, 44px);
  margin: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--v138-radius, 14px);
  background: var(--paper);
  color: var(--shell-accent, var(--navy));
  box-shadow: var(--v138-shadow, 0 8px 28px #0f1a2e1f);
  cursor: pointer;
}
.travel-gps-button svg { width: 21px; height: 21px; }
.travel-gps-button:focus-visible { outline: 3px solid var(--shell-accent, var(--navy)); outline-offset: 2px; }
@media (hover: hover) { .travel-gps-button:hover { background: var(--v138-soft, var(--travel-soft)); } }
html body.map-shell:is(.map-shell-menu-open, .map-shell-planner-open, .origin-picking) .travel-gps-button,
html body.map-shell:has(dialog[open]) .travel-gps-button { display: none !important; }
/* Desktop and tablets: the trip summary is a centred bar; the button sits at the right edge, clear of it. */
@media (min-width: 720px) {
  html body.map-shell:has(#travel-mini-dock:not([hidden])) .map-panel .travel-gps-button { bottom: calc(var(--shell-bottom) + 12px); }
}

/* ---------- 4 · Compartilhar viagem: GPS progress in the dialog (journey-share.mjs renderGps) ---------- */
.journey-share-dialog { --share-ok: var(--l360-live-strong, #067647); --share-ok-soft: var(--l360-live-soft, #e7f8ef); --share-warn: var(--l360-warning-strong, #b54708); --share-warn-soft: var(--l360-warning-soft, #fff4e0); }
:root[data-theme="dark"] .journey-share-dialog { --share-ok: var(--l360-live-text, #5fe3a1); --share-ok-soft: #12352a; --share-warn: #fbbf6a; --share-warn-soft: #3a2a12; }
.share-gps { display: grid; grid-template-columns: 22px minmax(0, 1fr); align-items: start; gap: 6px 10px; margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 14px; background: var(--cream); color: var(--ink); font-size: 13px; line-height: 1.45; }
.share-gps:empty { display: none; }
.share-gps strong { font-weight: 700; }
.share-gps[data-state="precise"] { border-color: color-mix(in srgb, var(--share-ok) 35%, transparent); background: var(--share-ok-soft); }
.share-gps:is([data-state="approximate"], [data-state="timeout"], [data-state="denied"], [data-state="unsupported"]) { border-color: color-mix(in srgb, var(--share-warn) 35%, transparent); background: var(--share-warn-soft); }
.share-gps-icon { display: grid; place-items: center; width: 22px; height: 22px; }
.share-gps-icon svg { width: 20px; height: 20px; }
.share-gps-icon.is-ok { color: var(--share-ok); }
.share-gps-icon.is-warn { color: var(--share-warn); }
.share-gps-spinner { width: 16px; height: 16px; margin: 3px; border: 2px solid var(--flow-skeleton, #e9e5f3); border-top-color: var(--night-link, var(--navy)); border-radius: 50%; animation: wave1-spin .8s linear infinite; }
@media (prefers-reduced-motion: reduce) { .share-gps-spinner { animation-duration: 2.4s; } }
.share-gps-steps { grid-column: 2; margin: 0; padding-left: 18px; color: var(--ink); font-size: 12.5px; }
.share-gps-steps li + li { margin-top: 4px; }
.journey-share-dialog .share-gps .share-gps-retry { grid-column: 2; justify-self: start; min-height: 44px; background: var(--paper); }
.journey-share-dialog [data-start-share]:disabled { cursor: not-allowed; }
/* In a trip every user pin is labelled "Você" (travel.css); the rough GPS reading says it is only the area. */
body.travel-active .map-pin.user.gps-here.is-approximate::after { content: "Por aqui"; }
/* Dark theme: the consent screen's route card and authorization box used the light lavender (--blue-soft) under
 * light text (≈1.1:1); they take the dark "selected" surface like the rest of the dialog. */
:root[data-theme="dark"] .journey-share-dialog :is(.share-route, .share-consent, .shared-step > i) { background: var(--l360-selected, var(--night-selected, #203f59)); color: var(--ink); }
