/* ==========================================================================
   ELDERCARE MOBILE WEB — COMPONENTS
   --------------------------------------------------------------------------
   A mobile-web design system, not a narrow copy of the desktop one. The shapes
   here exist because of the phone: a fixed app frame, screens that stack and
   slide, a bottom tab bar, sticky action bars, bottom sheets, segmented
   controls, and lists built for a thumb.

   THREE RULES CARRIED OVER FROM THE DESKTOP THEME, UNCHANGED
   1. Every interactive target is at least 48x48px.
   2. Every icon has a visible text label or an aria-label. No bare glyphs.
   3. Two states that matter differ in LIGHTNESS as well as hue, because blue
      fades and yellow/green pairs are hard to separate for older eyes.

   ONE RULE THAT IS NEW, BECAUSE THIS IS A TOUCHSCREEN
   4. Nothing is discoverable only by hover. Hover styling is wrapped in
      @media (hover: hover); the feedback a phone actually gets is :active.
   ========================================================================== */

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

html {
  /* Never let iOS inflate our type on rotate — the rem scale already honours
     the user's own text-size preference, which is the control that matters. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  height: 100%;
}

body {
  margin: 0;
  height: 100%;
  overflow: hidden;              /* the screens scroll, the page never does */
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  /* Kill the 300ms tap delay and the double-tap zoom without disabling
     pinch-zoom, which must stay available. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3, h4 {
  margin: 0 0 var(--sp-3);
  line-height: var(--lh-tight);
  color: var(--color-heading);
  font-weight: var(--fw-bold);
  letter-spacing: -0.015em;
}
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-base); }

p { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }
a { color: var(--color-brand); }
img { max-width: 100%; }
button { font: inherit; color: inherit; }

.muted  { color: var(--color-text-muted); }
.faint  { color: var(--color-text-faint); }
.small  { font-size: var(--fs-sm); }
.tiny   { font-size: var(--fs-xs); }
.strong { font-weight: var(--fw-medium); }
.bold   { font-weight: var(--fw-bold); }
.center { text-align: center; }
.right  { text-align: right; }
.nowrap { white-space: nowrap; }
.mb-0   { margin-bottom: 0; }
.mt-2   { margin-top: var(--sp-2); }
.mt-3   { margin-top: var(--sp-3); }
.mt-4   { margin-top: var(--sp-4); }
.mt-5   { margin-top: var(--sp-5); }
.mt-6   { margin-top: var(--sp-6); }
.mt-8   { margin-top: var(--sp-8); }
.grow   { flex: 1; min-width: 0; }
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

:focus-visible {
  outline: 3px solid var(--green-500);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.skiplink {
  position: fixed; top: calc(var(--safe-t) + 4px); left: 50%;
  transform: translate(-50%, -160%);
  z-index: 3000; background: var(--color-surface); color: var(--color-brand);
  padding: var(--sp-3) var(--sp-5); border-radius: var(--radius-pill);
  box-shadow: var(--shadow-lg); font-weight: var(--fw-medium);
  text-decoration: none; transition: transform var(--dur) var(--ease-out);
}
.skiplink:focus { transform: translate(-50%, 0); }

/* Icons. Same set as the desktop prototype, always beside a label. */
.ico {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; line-height: 0; color: currentColor;
}
.ico svg { display: block; }

/* ==========================================================================
   0 · WIREFRAME SCAFFOLDING  (not product — navigation for reviewers)
   --------------------------------------------------------------------------
   The mobile counterpart of the desktop set's .wfbar (assets/theme.css):
   same left-to-right pattern — a way back to the journey map, this screen's
   review code, its title — built once by shell.js from data-code and the
   page <title>, so no screen carries this markup itself.

   Thinner than desktop's 44px because a phone has no width to spare, and the
   right-hand "eldercare.com · Customer Portal" label desktop shows is dropped
   below ~360px — the code pill plus title already say which surface and
   which screen this is.

   Sits ABOVE .app, at the true top of the viewport, and owns --safe-t itself
   (the dark strip runs into a notch rather than leaving a bare gap above it).
   .app is measured to start below it — see shell.js syncHeight().
   ========================================================================== */
.wfbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 950;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: calc(var(--wfbar-h) + var(--safe-t));
  padding: var(--safe-t) max(var(--sp-3), var(--safe-r)) 0 max(var(--sp-3), var(--safe-l));
  background: var(--petrol-900);
  color: #C9D6DE;
  font-size: var(--fs-xs);
  overflow: hidden;
  white-space: nowrap;
}
.wfbar a { color: var(--white); text-decoration: none; font-weight: var(--fw-medium); flex: 0 0 auto; }
.wfbar a:hover, .wfbar a:focus-visible { text-decoration: underline; }
.wfbar__sep { color: #4F6A78; flex: 0 0 auto; }
.wfbar__code {
  flex: 0 0 auto;
  background: rgba(255,255,255,.14);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  letter-spacing: .04em;
  font-weight: var(--fw-medium);
  font-size: 11px;
}
.wfbar__title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* The desktop context label. There is room for it on a wider phone or a
   rotated one; below that it would just crowd the title, so it goes. */
.wfbar__ctx { flex: 0 0 auto; color: #4F6A78; }
@media (max-width: 359px) {
  .wfbar__ctx { display: none; }
}

/* ==========================================================================
   1 · THE APP FRAME
   --------------------------------------------------------------------------
   position:fixed with an explicit height, rather than a flowing document.
   That is the one reliable way on mobile web to keep a bottom bar pinned to
   the bottom while browser toolbars grow and shrink and the keyboard opens.
   --app-h is driven by visualViewport in app.js; 100dvh covers us before the
   first measurement and if the API is missing.
   ========================================================================== */
.app {
  position: fixed;
  top: calc(var(--wfbar-h) + var(--safe-t));
  left: 0; right: 0;
  height: var(--app-h);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-bg);
  /* A phone-width frame, centred, when this is opened on a large display so
     the mobile design is judged at the size it was drawn for. */
  max-width: 100%;
}

/* ---------- APPBAR ------------------------------------------------------- */
/* No top safe-area padding here: .app now starts below the .wfbar strip
   above it, which already claims --safe-t. Padding it again here would leave
   a second, unwanted gap under the notch. */
.appbar {
  position: relative;
  z-index: 20;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 0 max(var(--sp-2), var(--safe-r)) 0 max(var(--sp-2), var(--safe-l));
  background: var(--color-surface);
  box-shadow: var(--shadow-bar);
}
.appbar[hidden] { display: none; }
.appbar__row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--appbar-h);
}
/* The bar grows a second row for a step indicator or a summary strip. Those
   belong to the chrome, not the screen, so they stay put while content
   scrolls underneath. */
.appbar--stacked { padding-bottom: 0; }
.appbar__title {
  flex: 1; min-width: 0;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  color: var(--color-heading);
  letter-spacing: -0.01em;
  line-height: 1.25;
  /* A long destination name truncates rather than wrapping the bar to two
     lines and shifting every screen below it. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.appbar__title span {
  display: block;
  font-size: var(--fs-xs);
  font-weight: var(--fw-normal);
  color: var(--color-text-muted);
  letter-spacing: 0;
}
.appbar__title--center { text-align: center; }
.appbar__actions { display: flex; align-items: center; gap: var(--sp-1); flex: 0 0 auto; }

/* Over a photograph or a map: no plate, white controls, a scrim for contrast. */
.appbar--over {
  position: absolute; top: 0; left: 0; right: 0;
  background: none; box-shadow: none; color: var(--white);
}
.appbar--over::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(6,48,31,.62), rgba(6,48,31,0));
}
.appbar--over .appbar__title { color: var(--white); }
.appbar--over .appbar__title span { color: var(--green-100); }
.appbar--over .iconbtn {
  background: rgba(12, 32, 24, .42);
  color: var(--white);
  backdrop-filter: blur(6px) saturate(140%);
  -webkit-backdrop-filter: blur(6px) saturate(140%);
}

/* Brand lock-up in the appbar on tab roots. */
.appbar__brand { display: flex; align-items: center; gap: var(--sp-2); text-decoration: none; }
.appbar__brand .brandmark { width: 32px; height: 32px; flex-basis: 32px; }
.appbar__brand .brandmark svg { width: 18px; height: 18px; }
.appbar__brand b { font-size: var(--fs-lg); color: var(--color-heading); letter-spacing: -0.02em; }
.appbar__brand b span { color: var(--color-brand); }

.brandmark {
  width: 44px; height: 44px; flex: 0 0 44px; border-radius: 50%;
  background: var(--color-brand); color: var(--color-on-brand);
  display: grid; place-items: center;
}
.brandmark svg { width: 24px; height: 24px; }

/* ---------- ICON BUTTON — 48px target, always aria-labelled ------------- */
.iconbtn {
  width: var(--tap-min); height: var(--tap-min);
  flex: 0 0 var(--tap-min);
  display: grid; place-items: center;
  border: none; background: none; padding: 0; margin: 0;
  border-radius: 50%;
  color: var(--color-heading);
  text-decoration: none; cursor: pointer;
  position: relative;
  transition: background var(--dur-fast), transform var(--dur-fast);
}
.iconbtn:active { background: var(--color-surface-alt); transform: scale(.94); }
.iconbtn svg { width: 22px; height: 22px; }
.iconbtn--filled { background: var(--color-surface-alt); }
.iconbtn--brand { background: var(--color-brand); color: var(--white); font-weight: var(--fw-bold); }
.iconbtn__dot {
  position: absolute; top: 4px; right: 4px;
  min-width: 18px; height: 18px; padding: 0 5px;
  background: var(--color-danger); color: var(--white);
  font-size: 11px; font-weight: var(--fw-bold); line-height: 18px;
  border-radius: var(--radius-pill);
  border: 2px solid var(--color-surface);
}
@media (hover: hover) {
  .iconbtn:hover { background: var(--color-surface-alt); }
}

/* ---------- VIEWPORT + SCREENS ------------------------------------------
   The viewport is the window; each .screen is an absolutely positioned layer
   inside it that scrolls on its own. Two consequences worth the complexity:
   scroll position is naturally per-screen, and a push/pop can animate two
   layers past each other the way a native stack does.
   ------------------------------------------------------------------------ */
.viewport {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}

.screen {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  /* No visible scrollbar. On a touch device the overlay bar auto-hides anyway;
     on a desktop browser previewing this phone frame it would otherwise sit in
     the gutter and read as a stray UI element beside the content. */
  scrollbar-width: none;
  /* Stop a scroll that reaches the end of a screen from turning into a
     browser-level pull-to-refresh or back-swipe. */
  overscroll-behavior: contain;
  background: var(--color-bg);
  padding-left: var(--safe-l);
  padding-right: var(--safe-r);
  /* Reserve room for whatever fixed furniture sits at the bottom. Set by the
     shell, so content can always be scrolled clear of it. */
  padding-bottom: var(--bottom-inset);
  /* No will-change here. It was needed when screens slid over each other in a
     client-routed shell; page transitions are now the browser's job. Left in,
     it would force a compositing layer and make this element a backdrop root,
     which constrains what the frosted cards inside can sample. */
}
.screen::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ---------- AMBIENT GROUND FOR GLASS SURFACES ---------------------------
   Frosted panes need something behind them, or the blur has nothing to pick up
   and the card just looks faded. Three very soft brand washes give the glass
   something to refract without becoming decoration in its own right — they sit
   at 9–15% alpha over the warm ground, so the page still reads as the same
   cream, and text contrast on top of it is unchanged.

   background-attachment defaults to scroll, which on a scroll container pins
   the wash to the element's own box. The washes therefore stay put while the
   content slides over them, which is what makes the glass feel like a pane
   moving across a lit surface rather than a sticker on the page.
   ------------------------------------------------------------------------ */
.screen--ambient {
  background-color: var(--color-bg);
  background-image:
    radial-gradient(58% 38% at 10%  2%, rgba(15, 110, 78, .15), transparent 70%),
    radial-gradient(52% 34% at 94% 14%, rgba(180, 83,  9, .12), transparent 72%),
    radial-gradient(66% 42% at 52% 92%, rgba(35,  72, 92, .09), transparent 70%);
  background-repeat: no-repeat;
}

.screen__inner { padding: var(--sp-6) var(--gutter) var(--sp-10); }
.screen__inner--flush { padding-left: 0; padding-right: 0; }
.screen__inner--tight { padding-top: var(--sp-4); }
.screen--plain { background: var(--color-surface); }

/* ---------- CROSS-DOCUMENT TRANSITIONS ----------------------------------
   Each screen is a separate document, so page-to-page motion is the browser's
   job, not a router's. Opting into cross-document view transitions gets the
   app-like part of a single-page shell without giving up static pages: the
   appbar and tab bar are named, so they are held still and morphed between
   documents while only the content cross-fades. That removes the white flash
   that makes multi-page mobile web feel like a website.

   Unsupported browsers ignore all of this and get a plain, fast page load,
   which is a perfectly good fallback.
   ------------------------------------------------------------------------ */
@view-transition { navigation: auto; }

.appbar   { view-transition-name: ec-appbar; }
.tabbar   { view-transition-name: ec-tabbar; }
.viewport { view-transition-name: ec-screen; }

::view-transition-group(ec-appbar),
::view-transition-group(ec-tabbar) {
  animation-duration: var(--dur);
  animation-timing-function: var(--ease-out);
}
/* The bars cross-fade their contents in place rather than sliding. */
::view-transition-old(ec-appbar), ::view-transition-new(ec-appbar),
::view-transition-old(ec-tabbar), ::view-transition-new(ec-tabbar) {
  animation-duration: var(--dur-fast);
}
::view-transition-old(ec-screen) {
  animation: ec-vt-out var(--dur) var(--ease-in) both;
}
::view-transition-new(ec-screen) {
  animation: ec-vt-in var(--dur) var(--ease-out) both;
}
@keyframes ec-vt-out { to { opacity: 0; transform: translateY(-6px) } }
@keyframes ec-vt-in  { from { opacity: 0; transform: translateY(10px) } }

/* Screens that lead with a photograph or a map get a softer, scale-led
   entrance instead — declared per page with data-vt="media". */
html[data-vt="media"] ::view-transition-new(ec-screen) {
  animation: ec-vt-media var(--dur-slow) var(--ease-out) both;
}
@keyframes ec-vt-media { from { opacity: 0; transform: scale(1.015) } }

/* ---------- STICKY ACTION BAR -------------------------------------------
   The commit control. It sits in the frame rather than in the scroller, so it
   cannot drift, and the scroller reserves its height so it never covers the
   last thing on the screen.
   ------------------------------------------------------------------------ */
.actionbar {
  flex: 0 0 auto;
  z-index: 25;
  padding: var(--sp-3) max(var(--gutter), var(--safe-r)) calc(var(--sp-3) + var(--safe-b)) max(var(--gutter), var(--safe-l));
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border-top: 1px solid var(--color-border-soft);
  box-shadow: var(--shadow-up);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.actionbar[hidden] { display: none; }
.actionbar__row { display: flex; gap: var(--sp-3); align-items: center; }
.actionbar__row > .btn { flex: 1; }
.actionbar__row > .btn--ghost,
.actionbar__row > .btn--back { flex: 0 0 auto; }
.actionbar__note {
  font-size: var(--fs-xs); color: var(--color-text-muted);
  text-align: center; line-height: 1.4;
}
.actionbar__price {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-3);
}
.actionbar__price dt { margin: 0; font-size: var(--fs-sm); color: var(--color-text-muted); }
.actionbar__price dd {
  margin: 0; font-size: var(--fs-xl); font-weight: var(--fw-bold);
  color: var(--color-heading);
}

/* ---------- TAB BAR -----------------------------------------------------
   Five destinations. Every one keeps its written label at all times — the
   desktop theme's note about older users and unlabelled icons applies twice
   over at phone scale, so nothing here is icon-only.
   ------------------------------------------------------------------------ */
.tabbar {
  flex: 0 0 auto;
  z-index: 30;
  display: flex;
  align-items: stretch;
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(14px) saturate(170%);
  -webkit-backdrop-filter: blur(14px) saturate(170%);
  border-top: 1px solid var(--color-border-soft);
  padding: 0 max(var(--sp-1), var(--safe-r)) var(--safe-b) max(var(--sp-1), var(--safe-l));
}
.tabbar[hidden] { display: none; }

.tabbar__item {
  flex: 1 1 0;
  min-width: 0;
  min-height: var(--tabbar-h);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 3px;
  padding: var(--sp-2) 2px;
  text-decoration: none;
  color: var(--color-text-muted);
  font-size: 11px;
  font-weight: var(--fw-medium);
  letter-spacing: -0.01em;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.tabbar__item svg { width: 23px; height: 23px; }
.tabbar__label {
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tabbar__item.is-active { color: var(--color-brand); }
/* Active state is carried by weight, fill and a marker as well as hue. */
.tabbar__item.is-active .tabbar__label { font-weight: var(--fw-bold); }
.tabbar__item.is-active::before {
  content: ""; position: absolute; top: 0; left: 50%;
  width: 26px; height: 3px; margin-left: -13px;
  border-radius: 0 0 3px 3px;
  background: var(--color-brand);
}
.tabbar__item:active { background: var(--color-surface-alt); }
.tabbar__badge {
  position: absolute; top: 6px; left: 50%; margin-left: 4px;
  min-width: 17px; height: 17px; padding: 0 4px;
  background: var(--color-danger); color: var(--white);
  font-size: 10px; font-weight: var(--fw-bold); line-height: 17px;
  text-align: center; border-radius: var(--radius-pill);
  border: 2px solid var(--color-surface);
}

/* The Book tab is the product's one primary action, so it is raised and
   filled rather than being a fourth grey glyph among five. */
.tabbar__item--primary { color: var(--color-brand); }
.tabbar__item--primary .tabbar__mark {
  width: 46px; height: 32px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--color-brand);
  color: var(--white);
  box-shadow: 0 3px 10px rgba(15, 110, 78, .34);
  transition: transform var(--dur-fast) var(--ease-out);
}
.tabbar__item--primary:active .tabbar__mark { transform: scale(.92); }
.tabbar__item--primary.is-active::before { display: none; }
.tabbar__item--primary.is-active .tabbar__mark { background: var(--color-brand-deep); }

/* ==========================================================================
   2 · BUTTONS
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap-min);
  padding: 0 var(--sp-5);
  border-radius: var(--radius);
  border: 1.5px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit; font-size: var(--fs-base); font-weight: var(--fw-medium);
  text-decoration: none; cursor: pointer;
  text-align: center; line-height: 1.2;
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-fast);
}
.btn:active { transform: scale(.975); }
.btn svg { width: 19px; height: 19px; }

.btn--primary {
  background: var(--color-brand); color: var(--color-on-brand);
  border-color: var(--color-brand);
  font-size: var(--fs-action);          /* spec floor for primary actions */
  min-height: 54px;
  box-shadow: 0 2px 8px rgba(15, 110, 78, .22);
}
.btn--primary:active { background: var(--color-brand-deep); }
.btn--accent {
  background: var(--color-accent); color: var(--white); border-color: var(--color-accent);
  min-height: 54px; font-size: var(--fs-action);
}
.btn--accent:active { background: var(--color-accent-deep); }
.btn--danger  { background: var(--color-surface); color: var(--color-danger); border-color: var(--color-danger); }
.btn--danger:active { background: var(--color-danger-soft); }
.btn--danger-solid {
  background: var(--color-danger); color: var(--white); border-color: var(--color-danger);
  min-height: 54px; font-size: var(--fs-action);
}
.btn--ghost { background: transparent; border-color: transparent; color: var(--color-brand); }
.btn--ghost:active { background: var(--color-brand-soft); }
.btn--soft { background: var(--color-brand-soft); border-color: var(--color-brand-edge); color: var(--color-brand-deep); }
.btn--onphoto {
  background: rgba(255,255,255,.96); color: var(--green-800); border-color: transparent;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.btn--glass {
  background: rgba(12,32,24,.4); color: var(--white); border-color: rgba(255,255,255,.34);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.btn--block { width: 100%; }
.btn--sm { min-height: 40px; font-size: var(--fs-sm); padding: 0 var(--sp-4); border-radius: var(--radius-sm); }
.btn--sm svg { width: 16px; height: 16px; }
.btn--back { width: var(--tap-min); padding: 0; flex: 0 0 var(--tap-min); }
.btn[disabled], .btn.is-disabled { opacity: .45; pointer-events: none; }
.btn-row { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.btn-row--fill > .btn { flex: 1; }
/* For rows of equal secondary actions that should read as separate choices
   rather than a segmented cluster. */
.btn-row--airy { gap: var(--sp-4); }
.btn-stack { display: flex; flex-direction: column; gap: var(--sp-3); }
@media (hover: hover) {
  .btn:hover { background: var(--color-surface-alt); }
  .btn--primary:hover { background: var(--color-brand-deep); }
  .btn--accent:hover { background: var(--color-accent-deep); }
  .btn--ghost:hover { background: var(--color-brand-soft); }
}

/* ==========================================================================
   3 · SURFACES
   ========================================================================== */
.card {
  background: var(--color-surface);
  border: 1px solid transparent;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--sp-5);
  overflow: hidden;
}
.card:last-child { margin-bottom: 0; }
.card--bordered { border-color: var(--color-border); box-shadow: none; }
.card--brand { background: var(--color-brand-soft); border-color: var(--color-brand-edge); box-shadow: none; }
.card--warm  { background: var(--color-accent-soft); border-color: var(--color-accent-edge); box-shadow: none; }
.card--info  { background: var(--color-info-soft); border-color: var(--color-info-edge); box-shadow: none; }
.card--flat  { box-shadow: none; }
.card--plain { box-shadow: none; background: transparent; }
.card__head {
  padding: var(--sp-5) var(--sp-5) 0;
  display: flex; align-items: center; gap: var(--sp-3);
}
.card__head h2, .card__head h3 { margin: 0; flex: 1; min-width: 0; }
.card__body { padding: var(--sp-5); }
.card__body > :last-child { margin-bottom: 0; }
.card__foot {
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--color-border-soft);
  background: var(--color-surface-alt);
  display: flex; gap: var(--sp-3); align-items: center;
}
.card__foot--stack { flex-direction: column; align-items: stretch; }

/* Section heading inside a screen. Icon in a soft tile, label beside it. */
.sect { margin: var(--sp-10) 0 var(--sp-4); display: flex; align-items: center; gap: var(--sp-3); }
.sect:first-child { margin-top: 0; }
.sect__icon {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: var(--radius-sm);
  background: var(--color-brand-soft); color: var(--color-brand);
  display: grid; place-items: center;
}
.sect__icon svg { width: 18px; height: 18px; }
.sect--warm .sect__icon { background: var(--color-accent-soft); color: var(--color-accent); }
.sect__text { flex: 1; min-width: 0; }
.sect__text h2, .sect__text h3 {
  margin: 0; font-size: var(--fs-lg); letter-spacing: -0.02em;
}
.sect__text p { margin: 0; font-size: var(--fs-sm); color: var(--color-text-muted); }
.sect__link {
  flex: 0 0 auto; font-size: var(--fs-sm); font-weight: var(--fw-medium);
  color: var(--color-brand); text-decoration: none;
  min-height: var(--tap-min); display: inline-flex; align-items: center;
  padding-left: var(--sp-2);
}

/* A screen-leading title block, used where the appbar stays compact. */
.pagetitle { margin-bottom: var(--sp-5); }
.pagetitle h1 { font-size: var(--fs-2xl); margin-bottom: var(--sp-2); }
.pagetitle p { color: var(--color-text-muted); margin: 0; }

/* ==========================================================================
   4 · LISTS — the workhorse of a phone UI
   ========================================================================== */
.list {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--sp-5);
}
.list--flush { border-radius: 0; box-shadow: none; margin-left: calc(var(--gutter) * -1); margin-right: calc(var(--gutter) * -1); }
.list--plain { background: none; box-shadow: none; }

.item {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 64px;
  padding: var(--sp-3) var(--sp-4);
  text-decoration: none; color: inherit;
  border: none; background: none; width: 100%; text-align: left;
  font: inherit; cursor: pointer;
  position: relative;
}
.item + .item::before {
  content: ""; position: absolute; top: 0; left: var(--sp-4); right: 0;
  height: 1px; background: var(--color-border-soft);
}
.item:active { background: var(--color-brand-soft); }
.item__icon {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: var(--radius-sm);
  background: var(--color-brand-soft); color: var(--color-brand);
  display: grid; place-items: center;
}
.item__icon svg { width: 19px; height: 19px; }
.item__icon--warm { background: var(--color-accent-soft); color: var(--color-accent); }
.item__icon--danger { background: var(--color-danger-soft); color: var(--color-danger); }
.item__icon--support { background: var(--color-support-soft); color: var(--color-support); }
.item__body { flex: 1; min-width: 0; }
.item__title {
  font-weight: var(--fw-medium); color: var(--color-heading);
  line-height: 1.3;
}
.item__meta {
  font-size: var(--fs-sm); color: var(--color-text-muted);
  margin-top: 1px; line-height: 1.35;
}
.item__side {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--sp-2);
  color: var(--color-text-faint);
}
.item__side svg { width: 18px; height: 18px; }
.item__value { font-weight: var(--fw-medium); color: var(--color-heading); font-size: var(--fs-sm); }
.item--stack { align-items: flex-start; }
.item--stack .item__icon { margin-top: 2px; }

/* Key/value rows. The desktop <dl> gave dt a fixed 210px column; at phone
   width that leaves nothing for the value, so the label sits above instead. */
.kv { margin: 0; }
.kv__row {
  display: flex; gap: var(--sp-4); align-items: baseline;
  padding: var(--sp-3) 0;
  border-bottom: 1px dashed var(--color-border);
}
.kv__row:last-child { border-bottom: none; }
.kv__row:first-child { padding-top: 0; }
.kv dt { margin: 0; flex: 0 0 38%; color: var(--color-text-muted); font-size: var(--fs-sm); }
.kv dd {
  margin: 0; flex: 1; min-width: 0; text-align: right;
  font-weight: var(--fw-medium); color: var(--color-heading);
}
.kv dd .small { font-weight: var(--fw-normal); }
/* Long values get their own line rather than being squeezed into 60%. */
.kv--stacked .kv__row { display: block; }
.kv--stacked dt { margin-bottom: 2px; }
.kv--stacked dd { text-align: left; }

/* ==========================================================================
   5 · SEGMENTED CONTROL
   ========================================================================== */
.seg {
  display: flex;
  padding: 3px;
  background: var(--color-surface-alt);
  border-radius: var(--radius);
  gap: 2px;
  margin-bottom: var(--sp-4);
  /* More than three options scroll horizontally instead of shrinking below a
     legible width. */
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.seg::-webkit-scrollbar { display: none; }
.seg__btn {
  flex: 1 1 0;
  min-width: max-content;
  min-height: 42px;
  padding: 0 var(--sp-4);
  border: none; background: none;
  border-radius: calc(var(--radius) - 3px);
  font: inherit; font-size: var(--fs-sm); font-weight: var(--fw-medium);
  color: var(--color-text-muted);
  cursor: pointer; white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  transition: background var(--dur-fast), color var(--dur-fast);
}
.seg__btn.is-active {
  background: var(--color-surface);
  color: var(--color-brand);
  font-weight: var(--fw-bold);
  box-shadow: var(--shadow-sm);
}
.seg__btn:active { transform: scale(.97); }
.seg__count {
  font-size: var(--fs-xs); font-weight: var(--fw-normal);
  color: var(--color-text-faint);
}
.seg__btn.is-active .seg__count { color: var(--color-brand); }
/* Sticky under the appbar so switching views never needs a scroll back up. */
.seg--sticky {
  position: sticky; top: 0; z-index: 12;
  margin: 0 calc(var(--gutter) * -1) var(--sp-4);
  padding: var(--sp-3) var(--gutter);
  background: var(--color-bg);
  border-radius: 0;
  box-shadow: 0 1px 0 var(--color-border-soft);
}
.seg--sticky .seg__inner {
  display: flex; gap: 2px; padding: 3px;
  background: var(--color-surface-alt); border-radius: var(--radius);
  width: 100%;
}

/* Horizontally scrolling filter chips. */
.chiprow {
  display: flex; gap: var(--sp-2);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  margin: 0 calc(var(--gutter) * -1) var(--sp-4);
  padding: 0 var(--gutter);
}
.chiprow::-webkit-scrollbar { display: none; }
.chip {
  flex: 0 0 auto;
  min-height: var(--tap-min);
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 0 var(--sp-4);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit; font-size: var(--fs-sm); font-weight: var(--fw-medium);
  cursor: pointer; white-space: nowrap; text-decoration: none;
}
.chip svg { width: 16px; height: 16px; }
.chip.is-on {
  background: var(--color-brand-soft);
  border-color: var(--color-brand);
  color: var(--green-800);
}
.chip:active { transform: scale(.96); }

/* ==========================================================================
   6 · PILLS · ALERTS · STATUS
   ========================================================================== */
.pill {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 3px var(--sp-3);
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: var(--fw-medium);
  background: var(--color-surface-alt); color: var(--color-text-muted);
  border: 1px solid var(--color-border-soft);
  white-space: nowrap; line-height: 1.5;
}
.pill svg { width: 13px; height: 13px; }
.pill--brand  { background: var(--color-brand-soft);  color: var(--green-800);  border-color: var(--color-brand-edge); }
.pill--accent { background: var(--color-accent-soft); color: var(--amber-800);  border-color: var(--color-accent-edge); }
.pill--info   { background: var(--color-info-soft);   color: var(--color-info); border-color: var(--color-info-edge); }
.pill--danger { background: var(--color-danger-soft); color: var(--color-danger); border-color: var(--color-danger-edge); }
.pill--solid  { background: var(--color-brand); color: var(--white); border-color: var(--color-brand); }
.pill--onphoto {
  background: rgba(255,255,255,.2); color: var(--white); border-color: rgba(255,255,255,.4);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.pill--live::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; display: inline-block;
  animation: ec-blink 1.4s ease-in-out infinite;
}
.pillrow { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.alert {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: var(--sp-4);
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
  background: var(--color-surface-alt);
  margin-bottom: var(--sp-4);
}
.alert__icon { flex: 0 0 auto; line-height: 0; margin-top: 2px; }
.alert__icon svg { width: 22px; height: 22px; }
.alert__body { flex: 1; min-width: 0; }
.alert__body > :last-child { margin-bottom: 0; }
.alert__body b { display: block; margin-bottom: 2px; color: var(--color-heading); }
.alert__body p { font-size: var(--fs-sm); }
.alert--info    { background: var(--color-info-soft);    border-color: var(--color-info-edge); }
.alert--info    .alert__icon { color: var(--color-info); }
.alert--success { background: var(--color-success-soft); border-color: var(--color-brand-edge); }
.alert--success .alert__icon { color: var(--color-brand); }
.alert--warning { background: var(--color-warning-soft); border-color: var(--color-accent-edge); }
.alert--warning .alert__icon { color: var(--color-accent); }
.alert--danger  { background: var(--color-danger-soft);  border-color: var(--color-danger-edge); }
.alert--danger  .alert__icon { color: var(--color-danger); }

.sos {
  background: var(--color-danger-soft);
  border: 2px solid var(--color-danger);
  color: var(--color-danger);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  text-align: center;
  margin-bottom: var(--sp-4);
}
.sos h3 { color: var(--color-danger); margin-bottom: var(--sp-2); }
.sos p { font-size: var(--fs-sm); margin-bottom: var(--sp-4); }
.sos .btn {
  background: var(--color-danger); color: var(--white);
  border-color: var(--color-danger); width: 100%;
  min-height: 54px; font-size: var(--fs-action);
}

/* Demo scaffolding banner — clearly not product. */
.simbar {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px dashed var(--color-support);
  border-radius: var(--radius);
  background: var(--color-support-soft);
  color: var(--color-support);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-4);
}
.simbar__icon { flex: 0 0 auto; line-height: 0; }
.simbar__icon svg { width: 18px; height: 18px; }
.simbar b { color: var(--petrol-900); }
.simbar .btn { flex: 0 0 auto; }

/* ==========================================================================
   7 · HERO / MEDIA
   ========================================================================== */
.hero {
  position: relative;
  margin: calc(var(--sp-5) * -1) calc(var(--gutter) * -1) var(--sp-5);
  min-height: 260px;
  display: flex; align-items: flex-end;
  overflow: hidden;
  isolation: isolate;
}
.hero__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 38%;
  z-index: -2;
}
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(6,48,31,.42) 0%, rgba(6,48,31,.72) 52%, rgba(6,48,31,.94) 100%);
}
.hero__body { padding: var(--sp-6) var(--gutter) var(--sp-5); color: var(--white); width: 100%; }
.hero__body h1 {
  color: var(--white); font-size: var(--fs-3xl);
  margin: var(--sp-3) 0 var(--sp-2); letter-spacing: -0.025em;
}
.hero__body p { color: var(--green-100); margin-bottom: var(--sp-4); }
.hero--tall { min-height: 340px; }
.hero--short { min-height: 190px; }
/* Under an --over appbar, the copy needs clearing room at the top. */
.hero--underbar { padding-top: calc(var(--appbar-h) + var(--safe-t)); }

.hero--catalogue { margin: 0 0 var(--sp-6); text-align: center; }
.hero--catalogue .hero__body {
  max-width: 38rem;
  margin: 0 auto;
  padding: var(--sp-8) var(--gutter);
}
.hero--catalogue .hero__body h1 { margin: 0 0 var(--sp-3); }

.mediaband {
  margin: 0 calc(var(--gutter) * -1) var(--sp-5);
  height: 190px; overflow: hidden; background: var(--color-surface-alt);
  position: relative;
}
.mediaband img { width: 100%; height: 100%; object-fit: cover; }
.mediaband--auth { height: clamp(160px, 30vh, 260px); }
.mediaband__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(6,48,31,.25), rgba(6,48,31,.8));
  display: flex; align-items: flex-end;
  padding: var(--sp-5) var(--gutter);
  color: var(--white);
}

/* Horizontally snapping carousel — service shortcuts, vehicle photos. */
.carousel {
  display: flex; gap: var(--sp-3);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  margin: 0 calc(var(--gutter) * -1) var(--sp-4);
  padding: 0 var(--gutter) var(--sp-1);
}
.carousel::-webkit-scrollbar { display: none; }
.carousel > * { scroll-snap-align: start; flex: 0 0 auto; }
.carousel--cards > * { width: min(78%, 300px); }

/* Keep a page gutter to the left, including when cards snap into place. */
[data-code="E-01"] #soon-slot {
  margin-left: 0;
  padding-left: 0;
}

/* A service card, redrawn for a phone: wide image, one line of purpose. */
.svc {
  display: flex; flex-direction: column;
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden; text-decoration: none; color: inherit;
  box-shadow: var(--shadow-sm);
}
.svc:active { transform: scale(.985); border-color: var(--color-brand); }
.svc__media { position: relative; height: 128px; background: var(--color-surface-alt); }
.svc__media img { width: 100%; height: 100%; object-fit: cover; }
.svc__flag {
  position: absolute; top: var(--sp-3); left: var(--sp-3);
  padding: 3px var(--sp-3); border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  background: var(--color-brand); color: var(--white);
  letter-spacing: .02em;
}
.svc__flag--soon { background: rgba(28,26,23,.8); font-weight: var(--fw-medium); }
.svc__body { padding: var(--sp-4); flex: 1; display: flex; flex-direction: column; gap: var(--sp-2); }
.svc__name {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-lg); font-weight: var(--fw-bold);
  color: var(--color-heading); line-height: 1.25;
}
.svc__name .ico { color: var(--color-accent); }
.svc__name svg { width: 19px; height: 19px; }
.svc__tagline { font-size: var(--fs-sm); color: var(--color-text-muted); margin: 0; flex: 1; }
.svc__foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--color-border-soft);
  background: var(--color-surface-alt);
  font-size: var(--fs-sm);
}
.svc__price { font-weight: var(--fw-bold); color: var(--color-brand); }
.svc__go { display: inline-flex; align-items: center; gap: var(--sp-1); font-weight: var(--fw-medium); color: var(--color-brand); }
.svc__go svg { width: 15px; height: 15px; }
/* Coming soon: dimmed by lightness as well as colour. */
.svc--soon { background: var(--color-surface-alt); }
.svc--soon .svc__media img { filter: grayscale(.72) contrast(.94) brightness(1.04); }
.svc--soon .svc__name { color: var(--color-text-muted); }
.svc--soon .svc__name .ico { color: var(--color-text-faint); }
.svc--soon .svc__go { color: var(--color-text-muted); }

/* ==========================================================================
   8 · PEOPLE
   ========================================================================== */
.avatar {
  width: 48px; height: 48px; flex: 0 0 48px; border-radius: 50%;
  background: var(--color-support-soft); color: var(--color-support);
  display: grid; place-items: center; overflow: hidden;
  font-weight: var(--fw-bold); font-size: var(--fs-base);
  box-shadow: 0 0 0 1px var(--color-border);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--xs { width: 32px; height: 32px; flex-basis: 32px; font-size: var(--fs-xs); }
.avatar--sm { width: 40px; height: 40px; flex-basis: 40px; font-size: var(--fs-sm); }
.avatar--lg { width: 68px; height: 68px; flex-basis: 68px; font-size: var(--fs-xl); }
.avatar--xl { width: 96px; height: 96px; flex-basis: 96px; font-size: var(--fs-2xl); }
/* Amber marks the Warrior wherever they appear, so families learn to scan for it. */
.avatar--warrior { background: var(--color-accent-soft); color: var(--amber-800); }
.avatar--ring { box-shadow: 0 0 0 1px var(--color-border), 0 0 0 5px var(--color-accent-soft); }
.avatar--brand { background: var(--color-brand); color: var(--white); }

.person { display: flex; gap: var(--sp-3); align-items: center; }
.person__body { min-width: 0; flex: 1; }
.person__name { font-weight: var(--fw-bold); font-size: var(--fs-lg); color: var(--color-heading); line-height: 1.25; }
.person__meta { font-size: var(--fs-sm); color: var(--color-text-muted); line-height: 1.4; }
.person--center { flex-direction: column; text-align: center; gap: var(--sp-3); }
.person--center .person__body { text-align: center; }

.stars { color: var(--color-accent); letter-spacing: 1px; }

/* A stacked avatar row — "3 Warriors know her". */
.facepile { display: flex; align-items: center; }
.facepile .avatar { margin-left: -12px; box-shadow: 0 0 0 2px var(--color-surface); }
.facepile .avatar:first-child { margin-left: 0; }

/* ==========================================================================
   9 · FORMS
   ========================================================================== */
.field { margin-bottom: var(--sp-4); }
.field:last-child { margin-bottom: 0; }
.label {
  display: block; font-weight: var(--fw-medium);
  margin-bottom: var(--sp-2); color: var(--color-heading);
}
.label .req { color: var(--color-danger); }
.hint { font-size: var(--fs-sm); color: var(--color-text-muted); margin-top: var(--sp-2); line-height: 1.45; }

.input, .select, .textarea {
  width: 100%;
  min-height: 52px;
  padding: var(--sp-3) var(--sp-4);
  font-family: inherit;
  /* 17px is above the 16px threshold that makes iOS Safari zoom the page on
     focus, so an input never hijacks the viewport. */
  font-size: var(--fs-base);
  color: var(--color-text);
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius);
  appearance: none; -webkit-appearance: none;
}
.textarea { min-height: 100px; resize: none; line-height: var(--lh-body); }
.input::placeholder, .textarea::placeholder { color: var(--color-text-faint); }
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--color-brand); outline: none;
  box-shadow: 0 0 0 3px var(--color-brand-edge);
}
.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B6459' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-4) center;
  background-size: 20px;
  padding-right: var(--sp-10);
}
.field-pair { display: flex; gap: var(--sp-3); }
.field-pair > .field { flex: 1; min-width: 0; }

/* Selectable option card — the mobile replacement for the desktop .choice.
   The native radio is hidden and a ring/tick carries the state, because a
   14px system radio is not a 48px target. */
.opt {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: var(--sp-4);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  margin-bottom: var(--sp-3);
  cursor: pointer;
  position: relative;
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.opt:last-child { margin-bottom: 0; }
.opt input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.opt.is-on { border-color: var(--color-brand); background: var(--color-brand-soft); }
.opt:active { transform: scale(.99); }
.opt__body { flex: 1; min-width: 0; }
.opt__title {
  font-weight: var(--fw-medium); font-size: var(--fs-lg);
  color: var(--color-heading); line-height: 1.3;
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
}
.opt__desc { font-size: var(--fs-sm); color: var(--color-text-muted); margin-top: var(--sp-1); }
.opt__price {
  font-weight: var(--fw-bold); color: var(--color-brand);
  white-space: nowrap; font-size: var(--fs-base); flex: 0 0 auto;
}
.opt__tick {
  width: 26px; height: 26px; flex: 0 0 26px; margin-top: 2px;
  border-radius: 50%; border: 2px solid var(--color-border);
  background: var(--color-surface);
  display: grid; place-items: center; color: transparent;
}
.opt__tick svg { width: 15px; height: 15px; }
.opt.is-on .opt__tick {
  background: var(--color-brand); border-color: var(--color-brand); color: var(--white);
}
.opt__thumb {
  width: 76px; height: 60px; flex: 0 0 76px;
  border-radius: var(--radius-sm); overflow: hidden;
  background: var(--color-surface-alt);
}
.opt__thumb img { width: 100%; height: 100%; object-fit: cover; }
.opt--person { align-items: center; }
.opt--focus { border-color: var(--color-accent); background: var(--color-accent-soft); }

/* Photo-led vehicle choices with pricing separated from the description. */
.vehicle-options { display: grid; gap: var(--sp-4); }
.vehicle-option {
  display: flex; flex-direction: column; gap: 0;
  padding: 0; margin: 0;
  border-radius: var(--radius-lg); overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.vehicle-option:focus-within { outline: 3px solid var(--green-500); outline-offset: 3px; }
.vehicle-option__media {
  display: block; position: relative; width: 100%; height: 156px;
  background: var(--color-surface-alt);
}
.vehicle-option__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.vehicle-option .opt__tick {
  position: absolute; top: var(--sp-3); right: var(--sp-3); margin: 0;
  width: 30px; height: 30px; box-shadow: var(--shadow-sm);
}
.vehicle-option__selected {
  display: none; position: absolute; top: var(--sp-3); left: var(--sp-3);
  padding: var(--sp-1) var(--sp-3); border-radius: var(--radius-pill);
  background: var(--color-brand); color: var(--white);
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
}
.vehicle-option.is-on .vehicle-option__selected { display: block; }
.vehicle-option__body { display: grid; gap: var(--sp-2); padding: var(--sp-5); }
.vehicle-option__title { font-size: var(--fs-lg); font-weight: var(--fw-bold); color: var(--color-heading); line-height: 1.3; }
.vehicle-option__desc { font-size: var(--fs-sm); line-height: 1.6; color: var(--color-text-muted); }
.vehicle-option__footer {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-2); width: 100%; padding: var(--sp-3) var(--sp-5);
  border-top: 1px solid var(--color-border-soft);
  font-size: var(--fs-xs); color: var(--color-text-muted);
}
.vehicle-option__price {
  padding: var(--sp-1) var(--sp-2); border-radius: var(--radius-sm);
  background: var(--color-brand-soft); color: var(--color-brand-deep);
  font-size: var(--fs-sm); font-weight: var(--fw-bold);
}

/* Checkbox row. */
.check {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  min-height: var(--tap-min);
  padding: var(--sp-3) var(--sp-4);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  margin-bottom: var(--sp-3);
  cursor: pointer;
}
.check:last-child { margin-bottom: 0; }
.check input {
  width: 24px; height: 24px; flex: 0 0 24px; margin: 1px 0 0;
  accent-color: var(--color-brand);
}
.check__text { flex: 1; min-width: 0; font-size: var(--fs-sm); line-height: 1.5; }
.check__text b { display: block; font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--color-heading); }
.check--consent { background: var(--color-accent-soft); border-color: var(--color-accent-edge); }
.check--plain { border: none; background: none; padding: var(--sp-2) 0; min-height: 0; }
.check.is-on { border-color: var(--color-brand); background: var(--color-brand-soft); }

/* Toggle row — settings. */
.toggle {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 64px; padding: var(--sp-3) var(--sp-4);
  position: relative; cursor: pointer;
}
.toggle + .toggle::before {
  content: ""; position: absolute; top: 0; left: var(--sp-4); right: var(--sp-4);
  height: 1px; background: var(--color-border-soft);
}
.toggle__body { flex: 1; min-width: 0; }
.toggle__title { font-weight: var(--fw-medium); color: var(--color-heading); }
.toggle__meta { font-size: var(--fs-sm); color: var(--color-text-muted); line-height: 1.4; }
.toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle__switch {
  flex: 0 0 52px; width: 52px; height: 32px;
  border-radius: var(--radius-pill);
  background: var(--ink-200);
  position: relative;
  transition: background var(--dur-fast);
}
.toggle__switch::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--white); box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-out);
}
.toggle input:checked + .toggle__switch { background: var(--color-brand); }
.toggle input:checked + .toggle__switch::after { transform: translateX(20px); }
.toggle input:disabled + .toggle__switch { opacity: .5; }
.toggle input:focus-visible + .toggle__switch { outline: 3px solid var(--green-500); outline-offset: 2px; }

/* Six-box OTP entry. */
.otp { display: flex; gap: var(--sp-2); justify-content: space-between; }
.otp input {
  flex: 1 1 0; min-width: 0; width: 100%;
  height: 62px; padding: 0;
  text-align: center;
  font-size: var(--fs-xl); font-weight: var(--fw-bold);
  font-family: var(--font-mono);
  color: var(--color-heading);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  appearance: none; -webkit-appearance: none;
}
.otp input:focus { border-color: var(--color-brand); outline: none; box-shadow: 0 0 0 3px var(--color-brand-edge); }
.otp input.is-filled { border-color: var(--color-brand); background: var(--color-brand-soft); }

/* Star rating picker. */
.ratepick { display: flex; gap: var(--sp-2); justify-content: center; }
.ratepick button {
  width: 52px; height: 52px;
  border: 2px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-surface); color: var(--color-text-faint);
  font-size: var(--fs-xl); cursor: pointer;
  display: grid; place-items: center;
  transition: transform var(--dur-fast) var(--ease-out);
}
.ratepick button.is-on {
  border-color: var(--color-accent); color: var(--color-accent);
  background: var(--color-accent-soft);
}
.ratepick button:active { transform: scale(.9); }

/* ==========================================================================
   10 · BOOKING FLOW CHROME
   ========================================================================== */
/* A thin segmented progress bar under the appbar. Step count is also written
   out, because a bar alone does not say "2 of 5". */
.stepbar { display: flex; gap: 4px; padding: 0 var(--gutter) var(--sp-3); background: var(--color-surface); }
.stepbar__seg {
  flex: 1; height: 5px; border-radius: 3px;
  background: var(--color-border);
  overflow: hidden;
}
.stepbar__seg.is-done { background: var(--green-500); }
.stepbar__seg.is-current { background: var(--color-brand); }

/* The persistent booking summary. Replaces the desktop's sticky right rail:
   one line of what is being booked, tappable to open the full summary sheet. */
.summarystrip {
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%; text-align: left;
  padding: var(--sp-3) var(--gutter);
  background: var(--color-brand-soft);
  border: none; border-bottom: 1px solid var(--color-brand-edge);
  font: inherit; cursor: pointer;
  color: var(--green-800);
}
.summarystrip__thumb {
  width: 40px; height: 40px; flex: 0 0 40px; border-radius: var(--radius-sm);
  overflow: hidden; background: var(--color-surface);
}
.summarystrip__thumb img { width: 100%; height: 100%; object-fit: cover; }
.summarystrip__body { flex: 1; min-width: 0; }
.summarystrip__title {
  font-size: var(--fs-sm); font-weight: var(--fw-bold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.summarystrip__meta {
  font-size: var(--fs-xs); color: var(--green-800); opacity: .8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.summarystrip__more { flex: 0 0 auto; display: flex; align-items: center; gap: 2px; font-size: var(--fs-xs); font-weight: var(--fw-medium); }
.summarystrip__more svg { width: 16px; height: 16px; }
.summarystrip:active { background: var(--color-brand-edge); }

/* Price breakdown. */
.priceline {
  display: flex; justify-content: space-between; gap: var(--sp-4);
  padding: var(--sp-3) 0;
  border-bottom: 1px dashed var(--color-border);
  font-size: var(--fs-sm);
}
.priceline:last-of-type { border-bottom: none; }
.priceline > span:first-child { flex: 1; min-width: 0; color: var(--color-text-muted); }
.priceline b { color: var(--color-heading); white-space: nowrap; }
.pricetotal {
  display: flex; justify-content: space-between; gap: var(--sp-4);
  padding-top: var(--sp-4); margin-top: var(--sp-2);
  border-top: 2px solid var(--color-heading);
  font-size: var(--fs-xl); font-weight: var(--fw-bold);
  color: var(--color-heading);
}

/* Accordion — how secondary detail hides on a phone. */
.acc {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--sp-4);
  overflow: hidden;
}
.acc > summary {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 58px; padding: var(--sp-3) var(--sp-4);
  cursor: pointer; list-style: none;
  font-weight: var(--fw-medium); color: var(--color-heading);
}
.acc > summary::-webkit-details-marker { display: none; }
.acc > summary::after {
  content: ""; flex: 0 0 auto; width: 20px; height: 20px; margin-left: auto;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230F6E4E' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat;
  transition: transform var(--dur-fast) var(--ease-out);
}
.acc[open] > summary::after { transform: rotate(180deg); }
.acc__body { padding: 0 var(--sp-4) var(--sp-4); }
.acc__body > :last-child { margin-bottom: 0; }
.acc__side { flex: 0 0 auto; font-size: var(--fs-sm); color: var(--color-text-muted); }
.acc--flush { border-radius: 0; box-shadow: none; margin: 0; border-bottom: 1px solid var(--color-border-soft); }

/* ==========================================================================
   11 · BOTTOM SHEET
   ========================================================================== */
.sheet {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: flex-end; justify-content: center;
  pointer-events: none;
}
.sheet[hidden] { display: none; }
.sheet__scrim {
  position: absolute; inset: 0;
  background: rgba(20, 44, 58, .5);
  opacity: 0; pointer-events: auto;
  transition: opacity var(--dur) var(--ease-out);
  border: none; padding: 0; margin: 0;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.sheet__panel {
  position: relative;
  width: 100%;
  max-width: 560px;
  max-height: var(--sheet-max);
  display: flex; flex-direction: column;
  background: var(--color-surface);
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  box-shadow: 0 -8px 40px rgba(20, 44, 58, .28);
  transform: translate3d(0, 100%, 0);
  transition: transform var(--dur-slow) var(--ease-sheet);
  pointer-events: auto;
  padding-bottom: var(--safe-b);
  overscroll-behavior: contain;
}
.sheet.is-open .sheet__scrim { opacity: 1; }
.sheet.is-open .sheet__panel { transform: none; }
.sheet.is-dragging .sheet__panel { transition: none; }

.sheet__grab {
  flex: 0 0 auto; padding: var(--sp-3) 0 var(--sp-1);
  display: grid; place-items: center; cursor: grab;
  touch-action: none;
}
.sheet__grab::after {
  content: ""; width: 44px; height: 5px; border-radius: 3px;
  background: var(--ink-200);
}
.sheet__head {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-1) var(--sp-4) var(--sp-3);
}
.sheet__head h2 { margin: 0; flex: 1; min-width: 0; font-size: var(--fs-xl); }
.sheet__body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0 var(--sp-4) var(--sp-5);
}
.sheet__body > :last-child { margin-bottom: 0; }
.sheet__foot {
  flex: 0 0 auto;
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--color-border-soft);
  background: var(--color-surface);
  display: flex; flex-direction: column; gap: var(--sp-2);
}

/* ==========================================================================
   12 · TOASTS — how simulated actions report back
   ========================================================================== */
.toasts {
  position: fixed; left: 0; right: 0; z-index: 400;
  bottom: calc(var(--safe-b) + var(--sp-4));
  display: flex; flex-direction: column-reverse; align-items: center;
  gap: var(--sp-2); padding: 0 var(--gutter);
  pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: var(--sp-3);
  max-width: 460px; width: 100%;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  background: var(--petrol-900); color: var(--white);
  font-size: var(--fs-sm); line-height: 1.4;
  box-shadow: var(--shadow-lg);
  animation: toast-in var(--dur) var(--ease-out) both;
}
.toast.is-out { animation: toast-out var(--dur-fast) var(--ease-in) both; }
.toast__icon { flex: 0 0 auto; line-height: 0; color: var(--green-200); }
.toast__icon svg { width: 19px; height: 19px; }
.toast--warn .toast__icon { color: var(--amber-200); }
@keyframes toast-in  { from { opacity: 0; transform: translateY(18px) scale(.96) } to { opacity: 1; transform: none } }
@keyframes toast-out { to { opacity: 0; transform: translateY(10px) } }

/* ==========================================================================
   13 · TIMELINE · MAP · CHAT
   ========================================================================== */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li {
  position: relative;
  padding: 0 0 var(--sp-5) var(--sp-6);
  border-left: 2px solid var(--color-border);
  margin-left: 7px;
}
.timeline li:last-child { border-left-color: transparent; padding-bottom: 0; }
.timeline li::before {
  content: ""; position: absolute; left: -8px; top: 3px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--color-surface); border: 2px solid var(--color-border);
}
.timeline li.is-done { border-left-color: var(--color-brand); }
.timeline li.is-done::before { background: var(--color-brand); border-color: var(--color-brand); }
.timeline li.is-current::before {
  background: var(--color-accent); border-color: var(--color-accent);
  box-shadow: 0 0 0 4px var(--color-accent-soft);
}
.timeline li.is-current { border-left-color: var(--color-border); }
.timeline__title { font-weight: var(--fw-medium); color: var(--color-heading); line-height: 1.35; }
.timeline__time { font-size: var(--fs-sm); color: var(--color-text-muted); line-height: 1.4; }

/* Map stand-in. Same grid-paper treatment as the desktop prototype, sized to
   fill a phone screen and carry a sheet over it. */
.map {
  position: absolute; inset: 0;
  background:
    repeating-linear-gradient(0deg, var(--petrol-100) 0 1px, transparent 1px 46px),
    repeating-linear-gradient(90deg, var(--petrol-100) 0 1px, transparent 1px 46px),
    var(--color-support-soft);
  overflow: hidden;
}
.map__route {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
.map__route path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.map__pin {
  position: absolute; transform: translate(-50%, -100%);
  display: flex; align-items: center; gap: var(--sp-1);
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-pill); padding: 4px var(--sp-3);
  font-size: var(--fs-xs); font-weight: var(--fw-medium);
  color: var(--color-heading);
  box-shadow: var(--shadow); white-space: nowrap;
}
.map__pin svg { width: 13px; height: 13px; }
.map__pin--live { background: var(--color-accent); color: var(--white); border-color: var(--color-accent); }
.map__car {
  position: absolute; transform: translate(-50%, -50%);
  width: 44px; height: 44px; border-radius: 50%;
  border: 3px solid var(--white); overflow: hidden;
  box-shadow: 0 0 0 4px rgba(180, 83, 9, .28), var(--shadow);
  animation: ec-pulse 2.6s ease-in-out infinite;
}
.map__car img { width: 100%; height: 100%; object-fit: cover; }
.map__note {
  position: absolute; left: 50%; top: var(--sp-4); transform: translateX(-50%);
  background: rgba(255,255,255,.94); border: 1px dashed var(--color-support);
  color: var(--color-support); border-radius: var(--radius-pill);
  padding: var(--sp-2) var(--sp-4); font-size: var(--fs-xs);
  white-space: nowrap; box-shadow: var(--shadow);
}
/* An immersive screen: media fills the viewport, content rides over it. */
.stage { position: absolute; inset: 0; overflow: hidden; }
.stage__over {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--sp-5) var(--gutter) calc(var(--sp-4) + var(--safe-b));
}

/* Chat. */
.chat {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4) var(--gutter) var(--sp-5);
  min-height: 100%;
  background: var(--color-surface-alt);
  justify-content: flex-end;
}
.bubble {
  max-width: 82%;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-lg);
  font-size: var(--fs-base); line-height: 1.45;
}
.bubble__meta { font-size: var(--fs-xs); margin-top: var(--sp-1); opacity: .85; }
.bubble--them {
  background: var(--color-surface); border: 1px solid var(--color-border);
  align-self: flex-start; border-bottom-left-radius: var(--radius-sm);
  color: var(--color-text);
}
.bubble--them .bubble__meta { color: var(--color-text-muted); }
.bubble--me {
  background: var(--color-brand); color: var(--white);
  align-self: flex-end; border-bottom-right-radius: var(--radius-sm);
}
.bubble--me .bubble__meta { color: var(--green-200); }
.bubble--system {
  align-self: center; max-width: 92%; text-align: center;
  background: var(--color-warning-soft); color: var(--amber-800);
  border: 1px dashed var(--color-accent-edge);
  font-size: var(--fs-sm); border-radius: var(--radius);
}
.bubble__photo {
  background: rgba(255,255,255,.2); border-radius: var(--radius-sm);
  padding: var(--sp-6) var(--sp-4); text-align: center; font-size: var(--fs-sm);
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
}
.bubble__day {
  align-self: center; font-size: var(--fs-xs); color: var(--color-text-muted);
  padding: var(--sp-1) var(--sp-3); background: var(--color-surface);
  border-radius: var(--radius-pill);
}

/* The composer lives in the frame, not the scroller, so the keyboard shrinks
   the frame and the composer rides up with it. */
.composer {
  display: flex; align-items: flex-end; gap: var(--sp-2);
  padding: var(--sp-2) max(var(--sp-3), var(--safe-r)) calc(var(--sp-2) + var(--safe-b)) max(var(--sp-3), var(--safe-l));
  background: var(--color-surface);
  border-top: 1px solid var(--color-border-soft);
}
.composer__input {
  flex: 1; min-width: 0;
  min-height: var(--tap-min); max-height: 120px;
  padding: var(--sp-3) var(--sp-4);
  font: inherit; font-size: var(--fs-base);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: var(--color-bg);
  resize: none; overflow-y: auto;
  line-height: 1.4;
}
.composer__input:focus { outline: none; border-color: var(--color-brand); background: var(--color-surface); }
.composer__send {
  width: var(--tap-min); height: var(--tap-min); flex: 0 0 var(--tap-min);
  border-radius: 50%; border: none;
  background: var(--color-brand); color: var(--white);
  display: grid; place-items: center; cursor: pointer;
}
.composer__send svg { width: 20px; height: 20px; }
.composer__send:active { transform: scale(.92); }
.composer__send[disabled] { background: var(--ink-200); color: var(--ink-500); }

/* ==========================================================================
   14 · MATCHING RADAR
   --------------------------------------------------------------------------
   The one screen where the family is genuinely anxious, so it earns motion.
   Every animation is switched off under prefers-reduced-motion at the bottom
   of this file — not boilerplate, since reduced motion is specifically
   recommended when designing for older users.
   ========================================================================== */
.radar {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background:
    repeating-linear-gradient(0deg,  rgba(35,72,92,.06) 0 1px, transparent 1px 44px),
    repeating-linear-gradient(90deg, rgba(35,72,92,.06) 0 1px, transparent 1px 44px),
    radial-gradient(circle at 50% 46%, #EEF6F1 0%, #DFEDE5 58%, #CFE0D6 100%);
  overflow: hidden;
}
.radar__field {
  position: relative;
  width: min(86vw, 340px);
  aspect-ratio: 1;
  display: grid; place-items: center;
}
.radar__sweep {
  position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg, rgba(15,110,78,.22), rgba(15,110,78,0) 38%);
  animation: ec-sweep 3.6s linear infinite;
}
.radar__ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid var(--color-brand); opacity: 0;
  animation: ec-ping 2.8s var(--ease-out) infinite;
}
.radar__ring:nth-of-type(2) { animation-delay: .7s; }
.radar__ring:nth-of-type(3) { animation-delay: 1.4s; }
.radar__home {
  position: relative; z-index: 3;
  width: 76px; height: 76px; border-radius: 50%; overflow: hidden;
  border: 4px solid var(--white); box-shadow: var(--shadow-lg);
  animation: ec-pulse 2.8s ease-in-out infinite;
}
.radar__home img { width: 100%; height: 100%; object-fit: cover; }
.radar__dot {
  position: absolute; z-index: 2; left: var(--x); top: var(--y);
  transform: translate(-50%, -50%);
  width: 42px; height: 42px; border-radius: 50%; overflow: hidden;
  border: 3px solid var(--white); box-shadow: var(--shadow);
  opacity: .26; filter: grayscale(1);
  transition: opacity .5s, filter .5s, transform .5s, box-shadow .5s;
}
.radar__dot img { width: 100%; height: 100%; object-fit: cover; }
.radar__dot.is-asked {
  opacity: 1; filter: none;
  transform: translate(-50%, -50%) scale(1.1);
  box-shadow: 0 0 0 4px var(--color-accent-soft), var(--shadow);
  animation: ec-pop .45s var(--ease-out);
}
.radar__dot.is-accepted {
  transform: translate(-50%, -50%) scale(1.26);
  box-shadow: 0 0 0 5px var(--color-brand-soft), var(--shadow-lg);
}
.radar__scope {
  position: absolute; bottom: var(--sp-5); left: 50%; transform: translateX(-50%);
  background: rgba(255,255,255,.94); border-radius: var(--radius-pill);
  padding: var(--sp-2) var(--sp-4); font-size: var(--fs-xs);
  font-weight: var(--fw-medium); color: var(--color-heading);
  box-shadow: var(--shadow); white-space: nowrap;
}

/* The matching screen owns the whole viewport under a transparent appbar,
   rather than sitting inside a card the way the desktop radar did. A bottom
   sheet carries the live status, progress and wave list over it, so the
   radar itself stays uncluttered. */
.stage-fill { position: absolute; inset: 0; overflow: hidden; }

.livestatus { display: flex; align-items: center; gap: var(--sp-3); }
.livestatus__dot {
  width: 10px; height: 10px; flex: 0 0 10px; border-radius: 50%;
  background: var(--color-accent);
  animation: ec-blink 1.2s ease-in-out infinite;
}
.livestatus__text {
  font-size: var(--fs-lg); font-weight: var(--fw-medium);
  color: var(--color-heading); line-height: 1.35;
}
.progress { height: 8px; border-radius: 4px; background: var(--ink-100); overflow: hidden; }
.progress__bar {
  height: 100%; width: 0; border-radius: 4px;
  background: linear-gradient(90deg, var(--color-brand), var(--green-500));
  transition: width .6s var(--ease-out);
}

.wave { display: flex; flex-direction: column; gap: var(--sp-2); }
.wave__item {
  display: flex; gap: var(--sp-3); align-items: center;
  padding: var(--sp-3);
  border: 1px solid var(--color-border); border-radius: var(--radius);
  transition: opacity var(--dur), border-color var(--dur), background var(--dur);
}
.wave__item.is-pending { opacity: .5; }
.wave__item.is-active { border-color: var(--color-brand); background: var(--color-brand-soft); }
.wave__dot {
  width: 11px; height: 11px; flex: 0 0 11px; border-radius: 50%;
  background: var(--color-border);
  transition: background var(--dur);
}
.wave__item.is-done .wave__dot { background: var(--color-brand); }
.wave__item.is-active .wave__dot { background: var(--color-accent); animation: ec-pulse 1.3s ease-in-out infinite; }

.tick { width: 76px; height: 76px; }
.tick circle { fill: none; stroke: var(--color-brand); stroke-width: 4; opacity: .24; }
.tick path {
  fill: none; stroke: var(--color-brand); stroke-width: 5;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 44; stroke-dashoffset: 44;
  animation: ec-draw .5s .2s ease-out forwards;
}
.rise { animation: ec-rise .5s var(--ease-out) both; }
.rise--d1 { animation-delay: .06s } .rise--d2 { animation-delay: .13s }
.rise--d3 { animation-delay: .2s }  .rise--d4 { animation-delay: .27s }

.plate {
  display: inline-block; font-family: var(--font-mono);
  font-weight: var(--fw-bold); font-size: var(--fs-base); letter-spacing: .06em;
  background: var(--petrol-900); color: var(--white);
  padding: 4px var(--sp-3); border-radius: var(--radius-sm);
}
.platecard {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-3); border-radius: var(--radius);
  background: var(--color-surface-alt);
}
.platecard__img {
  width: 104px; height: 70px; flex: 0 0 104px;
  border-radius: var(--radius-sm); overflow: hidden;
}
.platecard__img img { width: 100%; height: 100%; object-fit: cover; }

.eta {
  display: flex; align-items: baseline; gap: var(--sp-3);
  padding: var(--sp-4); border-radius: var(--radius);
  background: var(--color-brand-soft); border: 1px solid var(--color-brand-edge);
}
.eta__big { font-size: var(--fs-3xl); font-weight: var(--fw-bold); color: var(--green-800); line-height: 1; }

.review { padding: var(--sp-3) 0; border-bottom: 1px dashed var(--color-border); }
.review:last-child { border-bottom: none; }
.review__head {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  font-size: var(--fs-sm); color: var(--color-text-muted); margin-bottom: var(--sp-1);
}

/* ==========================================================================
   15 · STATS · EMPTY · MISC
   ========================================================================== */
.statrow {
  display: flex; gap: var(--sp-3);
  background: var(--color-surface); border-radius: var(--radius-lg);
  padding: var(--sp-5) var(--sp-3);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--sp-5);
}
.stat { flex: 1; min-width: 0; text-align: center; position: relative; }
.stat + .stat::before {
  content: ""; position: absolute; left: 0; top: 10%;
  width: 1px; height: 80%; background: var(--color-border-soft);
}
.stat__value {
  font-size: var(--fs-xl); font-weight: var(--fw-bold);
  color: var(--color-heading); line-height: 1.1;
}
.stat__label {
  font-size: var(--fs-xs); color: var(--color-text-muted);
  margin-top: 2px; line-height: 1.3;
}

.empty { text-align: center; padding: var(--sp-10) var(--sp-5); }
.empty__mark {
  width: 72px; height: 72px; margin: 0 auto var(--sp-4); border-radius: 50%;
  background: var(--color-accent-soft); color: var(--color-accent);
  display: grid; place-items: center;
}
.empty__mark svg { width: 32px; height: 32px; }
.empty h3 { margin-bottom: var(--sp-2); }
.empty p { color: var(--color-text-muted); font-size: var(--fs-sm); margin-bottom: var(--sp-5); }

.quickrow {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-3); margin-bottom: var(--sp-7);
}
.quick {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  padding: var(--sp-5) var(--sp-2);
  background: var(--color-surface); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  text-decoration: none; color: var(--color-heading);
  font-size: var(--fs-xs); font-weight: var(--fw-medium);
  text-align: center; line-height: 1.25;
  min-height: 96px; justify-content: center;
}
.quick__icon {
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--color-brand-soft); color: var(--color-brand);
  display: grid; place-items: center;
}
.quick__icon svg { width: 19px; height: 19px; }
.quick--warm .quick__icon { background: var(--color-accent-soft); color: var(--color-accent); }
.quick--support .quick__icon { background: var(--color-support-soft); color: var(--color-support); }
.quick:active { transform: scale(.97); background: var(--color-brand-soft); }

.dash { border: none; border-top: 1px dashed var(--color-border); margin: var(--sp-4) 0; }

/* A booking card. The desktop's 7-column table cannot survive a phone, so each
   booking becomes a card.

   There is no coloured left edge. An earlier draft carried the status on a 4px
   border, which duplicated the status pill in the top row for no gain — and the
   pill is the better carrier, because it states the status in words as well as
   colour, which is the rule this product follows everywhere.

   GLASS, WITH THE ACCESSIBILITY FLOOR INTACT
   The fill is frosted, but it is kept at high opacity on purpose. Glassmorphism
   usually buys its look by letting the background bleed through the text, and
   this product cannot spend contrast that way — the theme's rule is that warmth
   comes from layout and imagery, never from lightening type. At .82 the
   effective surface behind body text is still near-white, so ink stays around
   15:1 and muted text around 5.6:1: both clear WCAG AA with room to spare.
   Nothing inside the card was lightened to make the glass work.

   Needs something behind it to refract — see .screen--ambient below. */
.bcard {
  display: block; text-decoration: none; color: inherit;
  position: relative;
  border-radius: var(--radius-lg);
  margin-bottom: var(--sp-5);
  overflow: hidden;

  background: linear-gradient(152deg,
    rgba(255, 255, 255, .84) 0%,
    rgba(255, 255, 255, .66) 100%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  backdrop-filter: blur(20px) saturate(150%);

  /* The glass edge: a bright hairline catching the light on top, a soft
     ambient shadow underneath to lift the pane off the page. */
  border: 1px solid rgba(255, 255, 255, .7);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .8),
    0 6px 22px rgba(28, 26, 23, .07),
    0 1px 3px rgba(28, 26, 23, .04);
  transition: box-shadow var(--dur-fast), transform var(--dur-fast);
}
.bcard:active {
  transform: scale(.99);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .8),
    0 2px 10px rgba(28, 26, 23, .09);
}

/* Browsers without backdrop-filter get a plain opaque card rather than a
   washed-out translucent one. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .bcard { background: var(--color-surface); border-color: var(--color-border-soft); }
}

/* Some people turn transparency off at the OS level. Honour it. */
@media (prefers-reduced-transparency: reduce) {
  .bcard {
    background: var(--color-surface);
    border-color: var(--color-border-soft);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
.bcard__top {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4) var(--sp-2);
}
.bcard__when {
  flex: 1; min-width: 0;
  font-size: var(--fs-sm); font-weight: var(--fw-bold);
  color: var(--color-heading);
}
.bcard__when span { display: block; font-weight: var(--fw-normal); color: var(--color-text-muted); font-size: var(--fs-xs); }
.bcard__body { display: flex; gap: var(--sp-3); align-items: flex-start; padding: 0 var(--sp-4) var(--sp-3); }
.bcard__dest { flex: 1; min-width: 0; }
/* Each of these is its own line. They are spans inside a flex item, so without
   an explicit display they would run together as one wrapped paragraph. */
.bcard__title {
  display: block;
  font-weight: var(--fw-medium); color: var(--color-heading); line-height: 1.3;
}
.bcard__meta {
  display: block;
  font-size: var(--fs-sm); color: var(--color-text-muted);
  margin-top: 3px; line-height: 1.4;
}
/* Translucent, so the frosted pane reads as one continuous piece of glass
   rather than a clear card with an opaque strip stuck on the bottom. */
.bcard__foot {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid rgba(28, 26, 23, .07);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55);
  background: rgba(255, 255, 255, .28);
  font-size: var(--fs-sm);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .bcard__foot { background: var(--color-surface-alt); box-shadow: none; }
}
@media (prefers-reduced-transparency: reduce) {
  .bcard__foot { background: var(--color-surface-alt); box-shadow: none; }
}
.bcard__price { font-weight: var(--fw-bold); color: var(--color-heading); }
.bcard__cta {
  margin-left: auto; display: inline-flex; align-items: center; gap: var(--sp-1);
  font-weight: var(--fw-medium); color: var(--color-brand);
}
.bcard__cta svg { width: 15px; height: 15px; }

/* Elder card — photo-led, with the two things you do to it. */
.ecard {
  background: var(--color-surface); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); overflow: hidden; margin-bottom: var(--sp-4);
}
.ecard__media { height: 150px; position: relative; background: var(--color-surface-alt); }
.ecard__media img { width: 100%; height: 100%; object-fit: cover; }
.ecard__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(6,48,31,0) 30%, rgba(6,48,31,.86) 100%);
  display: flex; align-items: flex-end; padding: var(--sp-4);
  color: var(--white);
}
.ecard__name { font-size: var(--fs-xl); font-weight: var(--fw-bold); color: var(--white); line-height: 1.2; }
.ecard__rel { font-size: var(--fs-sm); color: var(--green-100); }
.ecard__body { padding: var(--sp-4); }

/* ==========================================================================
   16 · KEYFRAMES
   ========================================================================== */
@keyframes ec-ping   { 0% { transform: scale(.3); opacity: .5 } 70% { opacity: 0 } 100% { transform: scale(1); opacity: 0 } }
@keyframes ec-pulse  { 0%, 100% { transform: scale(1) } 50% { transform: scale(1.06) } }
@keyframes ec-rise   { from { opacity: 0; transform: translateY(16px) } to { opacity: 1; transform: none } }
@keyframes ec-pop    { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.4) } 100% { opacity: 1; transform: translate(-50%,-50%) scale(1.1) } }
@keyframes ec-draw   { to { stroke-dashoffset: 0 } }
@keyframes ec-blink  { 50% { opacity: .3 } }
@keyframes ec-sweep  { to { transform: rotate(360deg) } }

/* ==========================================================================
   17 · LARGE SCREENS
   --------------------------------------------------------------------------
   This surface is mobile web. If it is opened on a desktop browser — which a
   reviewer will do — it presents as a phone-width frame on a neutral ground
   rather than stretching a one-column layout across 1400px. The design is
   then judged at the size it was drawn for.
   ========================================================================== */
@media (min-width: 620px) and (min-height: 560px) {
  body { background: #E7E2D8; display: grid; place-items: center; }
  .app {
    position: relative;
    top: 0;
    width: 412px;
    height: min(920px, calc(var(--app-h) - 48px));
    max-height: 920px;
    border-radius: 34px;
    box-shadow: 0 30px 70px rgba(20, 44, 58, .3), 0 0 0 1px rgba(20,44,58,.12);
    overflow: hidden;
  }
  .toasts, .sheet {
    position: absolute;
    left: 50%; transform: translateX(-50%);
    width: 412px; max-width: 412px;
  }
  .sheet { top: 50%; height: min(920px, calc(var(--app-h) - 48px)); transform: translate(-50%, -50%); }
  .toasts { bottom: max(calc((100vh - 920px) / 2 + 24px), 40px); }
  .skiplink { position: absolute; }
}

/* ==========================================================================
   18 · REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  /* Opt out of page transitions entirely rather than shortening them. */
  @view-transition { navigation: none; }

  .radar__sweep, .radar__ring, .radar__home, .radar__dot.is-asked,
  .livestatus__dot, .pill--live::before, .rise, .tick path,
  .wave__item.is-active .wave__dot, .map__car, .toast {
    animation: none !important;
  }
  .tick path { stroke-dashoffset: 0; }
  .rise, .toast { opacity: 1; transform: none; }
  .btn:active, .iconbtn:active, .opt:active, .quick:active,
  .bcard:active, .svc:active, .composer__send:active, .ratepick button:active {
    transform: none;
  }
  .sheet__panel { transition-duration: 1ms; }
}

/* ==========================================================================
   19 · THE LIVE JOURNEY CARD
   --------------------------------------------------------------------------
   The reason an adult child opens this app mid-morning. On desktop this was a
   300px hero across a 1120px column. On a phone that much photograph pushes
   everything else below the fold, so the picture is cropped to a band, the
   headline sits in it, and the facts that change — ETA, distance, how far
   along the journey is — move into a solid strip underneath where they stay
   legible against any image.
   ========================================================================== */
.livecard {
  /* The whole card is one link, so it has to opt out of link styling for its
     descendants — otherwise every label, endpoint and statistic inside renders
     underlined and in link blue. */
  display: block;
  text-decoration: none;
  color: inherit;
  background: var(--color-surface);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: var(--shadow);
  margin-bottom: var(--sp-5);
}
.livecard:active { transform: scale(.995); }
.journey-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  margin: var(--sp-4) 0 var(--sp-6);
}
.journey-actions__button {
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
  min-height: 100px;
  padding: var(--sp-4) var(--sp-3);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.journey-actions__icon { color: var(--color-brand); }
.journey-actions__icon svg { width: 22px; height: 22px; }
.journey-actions__label { font-size: var(--fs-sm); line-height: 1.4; }
.livecard__media { display: block; position: relative; height: clamp(172px, 28vh, 224px); background: var(--green-800); }
.livecard__media img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 36%; }
/* The scrim carries only the status pill and the headline. An earlier draft
   also put the supporting sentence here, which meant three stacked text blocks
   crowding the bottom third of the photograph — and it duplicated the facts
   strip underneath. The sentence moved onto white, so the picture can breathe
   and the gradient can be lighter. */
.livecard__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(6,48,31,.20) 0%, rgba(6,48,31,.50) 58%, rgba(6,48,31,.88) 100%);
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: var(--sp-3);
  padding: var(--sp-5);
  color: var(--white);
}
.livecard__title {
  font-size: var(--fs-xl); font-weight: var(--fw-bold); color: var(--white);
  line-height: 1.25; letter-spacing: -0.02em; margin: 0;
  max-width: 24ch;
}
/* The human line — who has her, and since when. Sits on white, where a small
   size is still comfortably legible. The Warrior's face lives here rather than
   riding the progress bar: on the bar it overlapped this line and hung off the
   card's left edge at low progress values. */
.livecard__note {
  display: flex; align-items: center; gap: var(--sp-3);
  margin: 0;
  font-size: var(--fs-sm); color: var(--color-text-muted); line-height: 1.4;
}
.livecard__note .avatar { box-shadow: 0 0 0 1px var(--color-border); }
.livecard__body { display: block; padding: var(--sp-5); }
.livecard__facts { display: flex; gap: var(--sp-3); margin-bottom: var(--sp-6); }
.livecard__fact { flex: 1; min-width: 0; position: relative; }
.livecard__fact + .livecard__fact { padding-left: var(--sp-3); }
.livecard__fact + .livecard__fact::before {
  content: ""; position: absolute; left: 0; top: 8%; width: 1px; height: 84%;
  background: var(--color-border-soft);
}
.livecard__fact b {
  display: block; font-size: var(--fs-lg); font-weight: var(--fw-bold);
  color: var(--color-heading); line-height: 1.15;
}
.livecard__fact span { font-size: var(--fs-xs); color: var(--color-text-muted); line-height: 1.25; display: block; }

/* Journey progress — origin to destination, as a plain bar. */
.jprog { display: block; margin: var(--sp-5) 0; }
.jprog__track {
  display: block;
  position: relative; height: 6px; border-radius: 3px;
  background: var(--ink-100); margin: 0 0 var(--sp-2);
  overflow: hidden;
}
.jprog__fill {
  position: absolute; inset: 0 auto 0 0; border-radius: 3px;
  background: linear-gradient(90deg, var(--color-brand), var(--green-500));
  transition: width .8s var(--ease-out);
}
.jprog__ends {
  display: flex; justify-content: space-between; gap: var(--sp-4);
  font-size: var(--fs-xs); color: var(--color-text-muted);
}
.jprog__ends span:last-child { text-align: right; }

/* A compact Warrior row — used on cards where the person matters but the
   profile does not need to be opened. */
.wstrip {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3);
  background: var(--color-accent-soft);
  border: 1px solid var(--color-accent-edge);
  border-radius: var(--radius);
  text-decoration: none; color: inherit;
}
.wstrip__body { flex: 1; min-width: 0; }
.wstrip__name { font-weight: var(--fw-bold); color: var(--amber-900); line-height: 1.25; }
.wstrip__meta { font-size: var(--fs-sm); color: var(--amber-800); }
.wstrip__go { flex: 0 0 auto; color: var(--amber-800); display: flex; }
.wstrip__go svg { width: 18px; height: 18px; }

/* Two-up grid, only once the phone is wide enough to keep each cell legible. */
.pair { display: grid; grid-template-columns: 1fr; gap: var(--sp-3); }
@media (min-width: 400px) { .pair--wide { grid-template-columns: 1fr 1fr; } }

/* An inline note, quieter than an alert. */
.notice {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  font-size: var(--fs-sm); color: var(--color-text-muted);
  line-height: 1.5;
}
.notice__icon { flex: 0 0 auto; line-height: 0; margin-top: 2px; color: var(--color-text-faint); }
.notice__icon svg { width: 17px; height: 17px; }

/* The reviewer's screen index. Not product. */
.maplane { margin-bottom: var(--sp-6); }
.maplane__head {
  display: flex; align-items: baseline; gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}
.maplane__head h3 { margin: 0; font-size: var(--fs-base); }
.maplane__head span { font-size: var(--fs-xs); color: var(--color-text-muted); }
.maplinks { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.maplink {
  display: inline-flex; align-items: center; min-height: 40px;
  padding: 0 var(--sp-3);
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-sm); text-decoration: none;
  color: var(--color-heading); font-size: var(--fs-sm);
}
.maplink code {
  font-family: var(--font-mono); font-size: 11px;
  color: var(--color-brand); margin-right: var(--sp-2);
}
