/* Onsyte — marketing site.
   One stylesheet, no build step: these pages change when the pitch changes,
   which is far more often than the product, and a copy edit should not need
   npm.

   Two pages, one design system:
     · index.html   — the customer page: the booker, then why to use it
     · vendors.html — the pitch to service companies (B2B)

   The system is shared because the two pages are the same company, and a
   visitor who crosses from one to the other should not feel the seam. What
   differs is only the components each page needs.

   ── Where the look comes from ────────────────────────────────────────────
   Uber      · monochrome authority. Black chrome, black CTAs, type that is
               big and tight and unhedged, a map that fills its frame.
   Airbnb    · warmth. Nothing is pure black or pure grey — everything is
               warmed a few degrees. Surfaces lift on hover instead of just
               changing colour. Corners are generous. Space is not scarce.

   The rule throughout: Uber's *structure*, Airbnb's *surface*. The decisions
   are black and confident; the material they are made of is warm. */


/* ══════════════════════════════ tokens ══════════════════════════════ */

:root {
  /* Warm near-black. #000 is free and reads cheap; a black with a little red
     and blue left in it is what expensive brands actually print. */
  --ink: #17161a;
  --ink-2: #5c5966;
  --ink-3: #8c8896;
  --ink-4: #b5b1bc;

  --surface: #ffffff;
  --surface-2: #f7f6f4;   /* warm off-white, not blue-grey */
  --surface-3: #efedea;
  --line: #e6e3de;
  --line-strong: #d5d1ca;

  /* Ink, inverted — for the dark bands. */
  --on-dark: #ffffff;
  --on-dark-2: rgba(255, 255, 255, 0.62);
  --on-dark-3: rgba(255, 255, 255, 0.40);
  --dark-line: rgba(255, 255, 255, 0.14);
  --dark-raise: #211f26;  /* a card sitting on the black band */

  /* One accent, spent sparingly — an eyebrow, a map pin, an error, the icons
     on the dark band. Every button stays black. Restraint is the whole trick:
     an accent that appears four times reads as a decision, an accent that
     appears forty times reads as a template. */
  --accent: #e2563a;
  --accent-dark: #c4441f;

  /* Airbnb's real contribution to web design: shadows in two layers, a tight
     contact shadow plus a wide ambient one. One-layer shadows look pasted on. */
  --e1: 0 1px 2px rgba(23, 22, 26, 0.04), 0 2px 8px rgba(23, 22, 26, 0.04);
  --e2: 0 2px 4px rgba(23, 22, 26, 0.05), 0 8px 24px rgba(23, 22, 26, 0.08);
  --e3: 0 8px 16px rgba(23, 22, 26, 0.08), 0 24px 48px rgba(23, 22, 26, 0.12);

  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;

  /* Uber's own easing. Fast out of the gate, long settle — motion that feels
     decided rather than springy. */
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --dur: 240ms;

  --wrap: 1140px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font: 16px/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  letter-spacing: -0.011em;
}

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 28px; }
.narrow { max-width: 60ch; }
.narrow-block { max-width: 60ch; }

/* Prices, counts and yardages line up column-wise instead of jittering as
   digits change width. Nobody notices this and everybody feels it. */
.tnum, .trust-stat, .svc-price, .bk-price, .bk-chip { font-variant-numeric: tabular-nums; }


/* ══════════════════════════════ nav ══════════════════════════════ */

.nav {
  display: block;                 /* the flex row lives on .nav-inner so the
                                     black bar spans the full width while its
                                     contents stay on the page grid */
  position: sticky; top: 0; z-index: 30;
  background: var(--ink);
}
.nav-inner {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  max-width: var(--wrap); margin: 0 auto; padding: 16px 28px;
}
.brand {
  color: var(--on-dark); font-size: 22px; font-weight: 800;
  letter-spacing: -0.03em; text-decoration: none;
}
.nav nav { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.nav nav a:not(.btn) {
  color: var(--on-dark-2); text-decoration: none;
  font-size: 15px; font-weight: 500;
  transition: color var(--dur) var(--ease);
}
.nav nav a:not(.btn):hover { color: var(--on-dark); }
.nav nav a.btn { text-decoration: none; }

/* On the black bar the primary action inverts to white — the highest-contrast
   thing available, which is what a primary action is for. */
.nav .btn-primary, .nav .btn-ghost {
  background: var(--on-dark); color: var(--ink); border-color: transparent;
  border-radius: var(--r-pill); font-weight: 600; font-size: 14px;
  padding: 11px 20px;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.nav .btn-primary:hover, .nav .btn-ghost:hover {
  background: #f0eeeb; transform: translateY(-1px);
}
.nav .btn-primary:active, .nav .btn-ghost:active { transform: translateY(0); }

@media (max-width: 940px) {
  /* On a narrow screen what matters is the action, not the section index. */
  .nav nav a:not(.btn) { display: none; }
}


/* ════════════════════════════ buttons ════════════════════════════ */

.btn {
  display: inline-block; text-decoration: none;
  font-weight: 600; font-size: 15.5px; letter-spacing: -0.012em;
  padding: 13px 24px; border-radius: var(--r-md);
  border: 1.5px solid transparent; white-space: nowrap;
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn-primary { background: var(--ink); color: var(--on-dark); }
.btn-primary:hover { background: #2b2930; transform: translateY(-2px); box-shadow: var(--e2); }
.btn-primary:active { transform: translateY(0); box-shadow: none; }

.btn-ghost { border-color: var(--line-strong); color: var(--ink); background: var(--surface); }
.btn-ghost:hover { border-color: var(--ink); transform: translateY(-2px); box-shadow: var(--e1); }
.btn-ghost:active { transform: translateY(0); box-shadow: none; }

.btn-lg { padding: 17px 34px; font-size: 16.5px; }


/* ═══════════════════════ sections & typography ═══════════════════════ */

.section { padding: 88px 0; border-top: 1px solid var(--line); }
.section.alt { background: var(--surface-2); }
.section h2 {
  margin: 0; font-size: clamp(28px, 3.8vw, 42px); font-weight: 800;
  letter-spacing: -0.035em; line-height: 1.1; text-wrap: balance;
}
.lede {
  margin: 14px 0 0; font-size: 18px; color: var(--ink-2);
  line-height: 1.55; max-width: 60ch;
}
.eyebrow {
  margin: 0 0 18px; color: var(--accent);
  font-size: 12px; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase;
}
.note { margin-top: 22px; font-size: 14px; color: var(--ink-3); }

/* --- the stat row, used by both pages ---------------------------------- */

.trust-stats { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 30px; }
.trust-stat {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 10px 18px; border-radius: var(--r-pill);
  background: var(--surface-2); border: 1px solid transparent;
  font-size: 13.5px; color: var(--ink-2);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.trust-stat:hover { background: var(--surface); border-color: var(--line); }
.trust-stat strong {
  color: var(--ink); font-size: 15px; font-weight: 700; letter-spacing: -0.02em;
}


/* ════════════════════════════ footer ════════════════════════════ */

.foot { padding: 52px 0 64px; border-top: 1px solid var(--line); }
.foot p { margin: 0 0 4px; }
.foot strong { letter-spacing: -0.02em; }
.small { color: var(--ink-3); font-size: 14px; }


/* ═══════════════════════════════════════════════════════════════════════
   index.html — the pitch to vendors
   ═══════════════════════════════════════════════════════════════════════ */

.hero { padding: 92px 0 96px; }
.hero h1 {
  margin: 0; font-size: clamp(40px, 6.4vw, 72px); line-height: 0.98;
  letter-spacing: -0.045em; font-weight: 800; max-width: 16ch;
  text-wrap: balance;
}
.hero .lede { margin-top: 24px; font-size: 19.5px; max-width: 54ch; }
.cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; }

/* --- the day, end to end ------------------------------------------------ */

/* A sequence, so it is numbered. The cards lift toward the cursor — the one
   gesture most responsible for Airbnb's listings feeling touchable. */
.flow {
  display: grid; gap: 18px; margin-top: 44px;
  grid-template-columns: 1fr;
}
@media (min-width: 620px) { .flow { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .flow { grid-template-columns: repeat(4, 1fr); } }

.flow article {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 26px;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.flow article:hover {
  transform: translateY(-4px); box-shadow: var(--e2); border-color: transparent;
}
.flow-num {
  display: block; margin-bottom: 16px;
  font-size: 13px; font-weight: 800; letter-spacing: 0.06em;
  color: var(--ink-4); font-variant-numeric: tabular-nums;
  transition: color var(--dur) var(--ease);
}
.flow article:hover .flow-num { color: var(--accent); }
.flow h3 { margin: 0 0 8px; font-size: 18.5px; font-weight: 700; letter-spacing: -0.025em; }
.flow p { margin: 0; color: var(--ink-2); font-size: 14.5px; line-height: 1.6; }

/* --- who it's for ------------------------------------------------------- */

.trades { list-style: none; padding: 0; margin: 44px 0 0; display: grid; gap: 10px; }
.trades li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 16px;
  padding: 20px 24px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.trades li:hover {
  transform: translateX(4px); box-shadow: var(--e1); border-color: var(--line-strong);
}
.trades strong { font-size: 16.5px; font-weight: 700; letter-spacing: -0.022em; }
.trades span { color: var(--ink-2); font-size: 14.5px; }

/* --- the widget section, on black --------------------------------------- */

/* The one dark band on this page. It lands where the pitch turns technical,
   which is exactly where a change of ground helps the reader notice they have
   moved from why to how. */
.band-dark {
  background: var(--ink); color: var(--on-dark);
  padding: 88px 0; border-top: none;
}
.band-dark h2 { color: var(--on-dark); }
.band-dark .lede { color: var(--on-dark-2); }
.band-dark .note { color: var(--on-dark-3); }

.snippet {
  margin: 36px 0 0; padding: 22px 24px; overflow-x: auto;
  background: var(--dark-raise); color: #e9e6ef;
  border: 1px solid var(--dark-line); border-radius: var(--r-md);
  font: 13.5px/1.8 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0;
}

/* --- product screenshots ------------------------------------------------ */

/* Shots of the real product, taken against a demo company whose every row is
   invented. Never the live panel: a screenshot of that is a screenshot of
   somebody's customers, their addresses and their revenue. */

.shot {
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-2);
  box-shadow: var(--e2);
  overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.shot:hover { transform: translateY(-3px); box-shadow: var(--e3); }

/* The window bar. Three dots and nothing else — enough to read as an app
   without pretending to be a specific browser. */
.shot-bar {
  display: flex; align-items: center; gap: 6px;
  padding: 11px 14px;
  background: var(--surface-3);
  border-bottom: 1px solid var(--line);
}
.shot-bar span {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--line-strong);
}

.shot img {
  display: block; width: 100%; height: auto;
  background: var(--surface);
}

/* `aspect-ratio` and explicit dimensions so the page does not jump as each
   one loads. */
.shot img { aspect-ratio: 1440 / 900; object-fit: cover; object-position: top; }

.shot-caption {
  padding: 16px 18px;
  border-top: 1px solid var(--line);
  background: var(--surface);
}
.shot-caption strong {
  display: block; font-size: 15px; font-weight: 700; letter-spacing: -0.022em;
}
.shot-caption span {
  display: block; margin-top: 3px;
  font-size: 13.5px; color: var(--ink-2); line-height: 1.5;
}

/* One big one, then a grid of the rest. */
.shot-lead { margin-top: 40px; }
.shot-grid {
  display: grid; gap: 18px; margin-top: 18px;
  grid-template-columns: 1fr;
}
@media (min-width: 760px) { .shot-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .shot-grid.three { grid-template-columns: repeat(3, 1fr); } }

/* On the dark band the frame has to invert or it glows. */
.band-dark .shot { border-color: var(--dark-line); background: var(--dark-raise); }
.band-dark .shot-bar { background: #2b2930; border-bottom-color: var(--dark-line); }
.band-dark .shot-bar span { background: rgba(255, 255, 255, 0.22); }
.band-dark .shot-caption { background: var(--dark-raise); border-top-color: var(--dark-line); }
.band-dark .shot-caption span { color: var(--on-dark-2); }

.shot-note {
  margin-top: 22px; font-size: 13px; color: var(--ink-3);
}
.band-dark .shot-note { color: var(--on-dark-3); }

/* --- closing cta -------------------------------------------------------- */

.closer { padding: 104px 0; text-align: center; border-top: 1px solid var(--line); }
.closer h2 { margin: 0 auto; max-width: 18ch; }
.closer .lede { margin: 16px auto 0; }
.contact { margin-top: 30px; font-size: 20px; font-weight: 700; letter-spacing: -0.025em; }
.contact a {
  color: var(--ink); text-decoration: none;
  border-bottom: 2px solid var(--line-strong); padding-bottom: 2px;
  transition: border-color var(--dur) var(--ease);
}
.contact a:hover { border-color: var(--accent); }


/* ═══════════════════════════════════════════════════════════════════════
   The customer page — the booker and its neighbours (body.mkt)
   ═══════════════════════════════════════════════════════════════════════ */

/* --- hero --------------------------------------------------------------- */

.mkt .trust-bar { padding: 68px 0 8px; }
.mkt .trust-bar h1 {
  margin: 0; font-size: clamp(38px, 6.2vw, 68px); line-height: 0.98;
  letter-spacing: -0.045em; font-weight: 800; max-width: 15ch;
  text-wrap: balance;
}
.mkt .trust-bar .lede { margin-top: 22px; font-size: 19px; max-width: 52ch; }

/* ═══════════════════════════ the booker ═══════════════════════════ */

/* The map fills the frame and the panel floats over it, Uber-style. The
   address comes first because without it there is no price — the rate card
   charges by distance, so until the ZIP is known there is no honest number
   to show. Watching the map fly to the right place is what tells the
   customer we understood where. */

.mkt .booking { padding: 34px 0 0; }

.mkt .bk {
  position: relative;
  margin-top: 26px;
  min-height: max(600px, calc(100vh - 210px));
  background: var(--surface-2);
  overflow: hidden;
}

/* The fusion, made literal: Uber puts the map edge-to-edge, Airbnb puts
   everything in a rounded card. On a wide screen it gets to be both — inset,
   with corners, so the page still has a margin to breathe in. */
@media (min-width: 1000px) {
  .mkt .bk {
    max-width: var(--wrap); margin: 26px auto 0;
    border-radius: var(--r-xl);
    box-shadow: var(--e2);
  }
}

.mkt #bk-map { position: absolute; inset: 0; z-index: 0; filter: saturate(0.92); }

/* A whisper of a scrim down the left edge so the white panel always has
   something to sit against, whatever the map happens to be showing. */
.mkt .bk::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(100deg, rgba(23, 22, 26, 0.14) 0%, rgba(23, 22, 26, 0) 42%);
}

/* --- the dropped pin ---------------------------------------------------- */

/* Leaflet's stock marker is a blue PNG from its CDN; booking.js swaps in a
   divIcon so the pin is drawn here instead. No `position` on .bk-pin — the
   marker element is already absolutely positioned by Leaflet and overriding
   that detaches the pin from its coordinates. */
.mkt .bk-pin-dot,
.mkt .bk-pin-pulse {
  position: absolute; left: 50%; top: 50%;
  width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border-radius: 50%; background: var(--accent);
}
.mkt .bk-pin-dot {
  border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(23, 22, 26, 0.35);
}
.mkt .bk-pin-pulse { animation: bk-pulse 2.4s var(--ease) infinite; }

@keyframes bk-pulse {
  0%   { transform: scale(1);   opacity: 0.5; }
  70%  { transform: scale(3.4); opacity: 0; }
  100% { transform: scale(3.4); opacity: 0; }
}

/* --- the panel ---------------------------------------------------------- */

.mkt .bk-panel {
  position: relative; z-index: 2;
  width: min(444px, calc(100% - 36px));
  margin: 30px 0 30px 30px;
  max-height: min(600px, calc(100vh - 260px));
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--e3);
  padding: 28px;
  scrollbar-width: thin;
}

@media (max-width: 720px) {
  /* On a phone the panel leads and the map is context, not decoration. */
  .mkt .bk { min-height: 0; }
  .mkt #bk-map { position: relative; height: 230px; }
  .mkt .bk-panel {
    width: auto; margin: -44px 16px 20px; max-height: none; padding: 24px 22px;
  }
}

.mkt .bk-panel h3 {
  margin: 0 0 20px; font-size: 23px; font-weight: 800;
  letter-spacing: -0.032em; line-height: 1.15;
}

.mkt .bk-progress { display: flex; gap: 5px; margin-bottom: 22px; }
.mkt .bk-progress span {
  height: 3px; flex: 1; border-radius: var(--r-pill); background: var(--surface-3);
  transition: background var(--dur) var(--ease);
}
.mkt .bk-progress span.on { background: var(--ink); }

/* --- fields ------------------------------------------------------------- */

.mkt .bk-field { display: block; margin-bottom: 12px; }
.mkt .bk-field > span {
  display: block; margin-bottom: 7px;
  font-size: 11px; font-weight: 700; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: 0.07em;
}
.mkt .bk-field input {
  width: 100%; padding: 15px 16px;
  font-size: 16px;                /* 16px so iOS does not zoom on focus */
  font-family: inherit; color: var(--ink);
  border: 1.5px solid transparent; border-radius: var(--r-md);
  background: var(--surface-2);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.mkt .bk-field input::placeholder { color: var(--ink-4); }
.mkt .bk-field input:hover { background: var(--surface-3); }
.mkt .bk-field input:focus {
  outline: none; background: var(--surface);
  border-color: var(--ink); box-shadow: var(--e1);
}

.mkt .bk-suggestions { display: grid; gap: 5px; margin-bottom: 14px; }
.mkt .bk-suggestion {
  display: block; width: 100%; text-align: left; cursor: pointer;
  font-family: inherit; padding: 13px 15px;
  border: 1.5px solid transparent; border-radius: var(--r-md);
  background: var(--surface-2);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.mkt .bk-suggestion:hover {
  background: var(--surface); border-color: var(--line-strong); transform: translateX(2px);
}
.mkt .bk-suggestion strong {
  display: block; font-size: 15px; font-weight: 600; letter-spacing: -0.015em;
}
.mkt .bk-suggestion span {
  display: block; font-size: 13px; color: var(--ink-3); margin-top: 1px;
}

.mkt .bk-label {
  margin: 20px 0 9px; font-size: 11px; font-weight: 700; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: 0.07em;
}

/* --- tiles and chips ---------------------------------------------------- */

/* Selection is an inset ring, not a thicker border: a border that grows
   reflows every neighbour by a pixel and the whole grid twitches. */
.mkt .bk-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.mkt .bk-chips { display: flex; flex-wrap: wrap; gap: 7px; }

.mkt .bk-tile,
.mkt .bk-chip {
  text-align: left; cursor: pointer; font-family: inherit;
  border: none; border-radius: var(--r-md); background: var(--surface-2);
  box-shadow: inset 0 0 0 1.5px transparent;
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.mkt .bk-tile { padding: 15px; }
.mkt .bk-chip { padding: 11px 15px; }

.mkt .bk-tile:hover,
.mkt .bk-chip:hover {
  background: var(--surface);
  box-shadow: inset 0 0 0 1.5px var(--line-strong), var(--e1);
  transform: translateY(-1px);
}
.mkt .bk-tile.on,
.mkt .bk-chip.on {
  background: var(--surface);
  box-shadow: inset 0 0 0 2px var(--ink), var(--e1);
  transform: none;
}
.mkt .bk-tile strong,
.mkt .bk-chip strong {
  display: block; font-size: 14.5px; font-weight: 700; letter-spacing: -0.018em;
}
.mkt .bk-tile span,
.mkt .bk-chip span {
  display: block; font-size: 12.5px; color: var(--ink-3); line-height: 1.45;
}
.mkt .bk-tile span { margin-top: 3px; }
.mkt .bk-chip span { margin-top: 1px; }

/* --- price -------------------------------------------------------------- */

.mkt .bk-price {
  margin-top: 18px; padding: 17px 19px; border-radius: var(--r-md);
  background: var(--surface-2); font-size: 14px; color: var(--ink-2);
  line-height: 1.5;
  transition: opacity var(--dur) var(--ease);
}
.mkt .bk-price strong {
  font-size: 30px; font-weight: 800; color: var(--ink);
  letter-spacing: -0.038em; line-height: 1;
}
.mkt .bk-price span { margin-left: 9px; color: var(--ink-3); font-size: 13.5px; }
.mkt .bk-price.loading { opacity: 0.45; }

.mkt .bk-note { margin: 7px 0 0; font-size: 12.5px; color: var(--ink-3); }
.mkt .bk-error {
  margin: 10px 0 0; min-height: 1em;
  font-size: 13.5px; color: var(--accent-dark); font-weight: 500;
}

/* --- buttons ------------------------------------------------------------ */

.mkt .bk-nav { display: flex; gap: 9px; margin-top: 24px; }
.mkt .bk-btn {
  flex: 1; cursor: pointer; font-family: inherit;
  font-weight: 600; font-size: 15.5px; letter-spacing: -0.012em;
  padding: 16px 20px; border-radius: var(--r-md); border: none;
  background: var(--ink); color: var(--on-dark);
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.mkt .bk-btn:hover:not(:disabled) {
  background: #2b2930; transform: translateY(-1px); box-shadow: var(--e2);
}
.mkt .bk-btn:active:not(:disabled) { transform: translateY(0); box-shadow: none; }
.mkt .bk-btn:disabled { opacity: 0.26; cursor: default; }
.mkt .bk-btn.ghost {
  flex: 0 0 auto; background: var(--surface-2); color: var(--ink);
  padding-left: 24px; padding-right: 24px;
}
.mkt .bk-btn.ghost:hover:not(:disabled) { background: var(--surface-3); box-shadow: none; }
.mkt #bk-address-next { width: 100%; }

/* --- done --------------------------------------------------------------- */

.mkt .bk-done { text-align: center; padding: 26px 0 12px; }
.mkt .bk-check {
  width: 56px; height: 56px; line-height: 56px; margin: 0 auto 18px;
  border-radius: 50%; font-size: 25px;
  background: var(--ink); color: var(--on-dark);
}
.mkt .bk-done h3 { margin-bottom: 10px; }
.mkt .bk-done p { color: var(--ink-2); font-size: 15px; line-height: 1.55; }

/* --- service cards ------------------------------------------------------ */

/* Explicit columns rather than auto-fit. With exactly four cards, auto-fit
   lands on three-plus-an-orphan for a whole band of widths, which looks like
   a mistake. 1 → 2 → 4 always divides evenly. */
.mkt .services-grid {
  display: grid; gap: 18px; margin-top: 40px; grid-template-columns: 1fr;
}
@media (min-width: 620px) { .mkt .services-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .mkt .services-grid { grid-template-columns: repeat(4, 1fr); } }

.mkt .svc-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 26px;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.mkt .svc-card:hover {
  transform: translateY(-4px); box-shadow: var(--e2); border-color: transparent;
}
.mkt .svc-icon {
  display: grid; place-items: center;
  width: 48px; height: 48px; border-radius: var(--r-md); margin-bottom: 20px;
  background: var(--surface-2); color: var(--ink);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.mkt .svc-card:hover .svc-icon { background: var(--ink); color: var(--on-dark); }
.mkt .svc-icon svg { width: 23px; height: 23px; }
.mkt .svc-card h3 {
  margin: 0 0 8px; font-size: 18.5px; font-weight: 700; letter-spacing: -0.025em;
}
.mkt .svc-card p {
  margin: 0 0 16px; color: var(--ink-2); font-size: 14.5px; line-height: 1.55;
}
.mkt .svc-price { margin: 0; font-size: 13.5px; color: var(--ink-3); }
.mkt .svc-price strong {
  color: var(--ink); font-weight: 700; font-size: 15px; letter-spacing: -0.02em;
}

/* --- steps -------------------------------------------------------------- */

.mkt .steps { display: grid; gap: 32px; margin-top: 44px; grid-template-columns: 1fr; }
@media (min-width: 820px) { .mkt .steps { grid-template-columns: repeat(3, 1fr); } }

.mkt .step-num {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: var(--r-pill); margin-bottom: 18px;
  background: var(--ink); color: var(--on-dark); font-size: 15px; font-weight: 700;
}
.mkt .step h3 {
  margin: 0 0 8px; font-size: 18px; font-weight: 700; letter-spacing: -0.025em;
}
.mkt .step p { margin: 0; color: var(--ink-2); font-size: 14.5px; line-height: 1.6; }

/* --- why band ----------------------------------------------------------- */

.mkt .why-band { background: var(--ink); color: var(--on-dark); padding: 88px 0; }
.mkt .why-band h2 { color: var(--on-dark); }
.mkt .why-band .lede { color: var(--on-dark-2); }
.mkt .why-grid { display: grid; gap: 34px 28px; margin-top: 44px; grid-template-columns: 1fr; }
@media (min-width: 620px) { .mkt .why-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .mkt .why-grid { grid-template-columns: repeat(4, 1fr); } }

.mkt .why-item h3 {
  display: flex; align-items: flex-start; gap: 10px; margin: 0 0 9px;
  font-size: 16px; font-weight: 700; letter-spacing: -0.02em;
}
.mkt .why-item h3 svg {
  width: 19px; height: 19px; flex: none; margin-top: 1px; color: var(--accent);
}
.mkt .why-item p { margin: 0; font-size: 14.5px; color: var(--on-dark-2); line-height: 1.6; }

/* --- faq ---------------------------------------------------------------- */

/* An accordion, not a wall: somebody who came for a dumpster should be able to
   skim four questions in two seconds and open only the one that worries them. */
.mkt .faq { margin-top: 36px; border-top: 1px solid var(--line); }
.mkt .faq-item { border-bottom: 1px solid var(--line); }
.mkt .faq-item summary {
  list-style: none; cursor: pointer; position: relative;
  padding: 24px 44px 24px 0;
  font-size: 17px; font-weight: 600; letter-spacing: -0.022em;
  transition: color var(--dur) var(--ease);
}
.mkt .faq-item summary::-webkit-details-marker { display: none; }
.mkt .faq-item summary:hover { color: var(--ink-2); }
.mkt .faq-item summary::after {
  content: ''; position: absolute; right: 6px; top: 50%;
  width: 9px; height: 9px; margin-top: -6px;
  border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}
.mkt .faq-item[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.mkt .faq-item p {
  margin: 0; padding: 0 56px 26px 0;
  color: var(--ink-2); font-size: 15.5px; line-height: 1.65;
}

/* --- sticky mobile bar -------------------------------------------------- */

/* On a phone the booker scrolls away and the page keeps going. This is the way
   back to it — it appears only once the booker is off screen, and only on a
   touch-sized viewport. */
.mkt .sticky-book {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--line);
  transform: translateY(110%);
  transition: transform 320ms var(--ease);
}
.mkt .sticky-book.show { transform: translateY(0); }
.mkt .sticky-book a {
  display: block; text-align: center; text-decoration: none;
  background: var(--ink); color: var(--on-dark); font-weight: 600; font-size: 16px;
  padding: 16px; border-radius: var(--r-md);
}
@media (max-width: 860px) { .mkt .sticky-book { display: block; } }

/* --- coverage map ------------------------------------------------------- *
   Where work has actually gone out. Sits inside a normal section rather than
   bleeding full-width: it is evidence next to the prose that explains it, not
   a hero. The fixed height keeps the page from reflowing when the JSON lands.  */
.cv-map-wrap {
  margin-top: 28px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--e1);
  background: var(--surface-2);
}
#cv-map {
  height: 460px;
  width: 100%;
  /* Until the data arrives this is an empty panel, not a grey void with a
     spinner nobody asked for. */
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
#cv-map.ready { opacity: 1; }

/* No data, no canvas. The section keeps its sentence and loses the hole. */
#coverage.no-map .cv-map-wrap { display: none; }

.cv-map-wrap .leaflet-container { background: var(--surface-2); font: inherit; }
.cv-map-wrap .leaflet-popup-content { margin: 10px 12px; font-size: 13px; line-height: 1.5; }
.cv-map-wrap .leaflet-popup-content-wrapper { border-radius: var(--r-md); box-shadow: var(--e2); }

@media (max-width: 700px) {
  #cv-map { height: 340px; }
}

/* --- service states ------------------------------------------------------ *
   The four states a service actually moves through. Four, not the seven a
   marketing deck would like: the board has SCHEDULED, EN_ROUTE, COMPLETED and
   CANCELLED, and inventing "Arriving" for a page would promise a status the
   customer would then never see change.                                       */
.states {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: st;
}
.states li {
  position: relative;
  padding: 0 12px 0 0;
}
/* The rail, drawn behind the dots and stopping at the last one. */
.states li::before {
  content: '';
  position: absolute;
  left: 7px; right: 0; top: 6px;
  height: 2px;
  background: var(--line);
}
.states li:last-child::before { display: none; }
.states .dot {
  position: relative;
  z-index: 1;
  display: block;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent);
}
.states li.live .dot { background: var(--accent); box-shadow: 0 0 0 5px rgb(226 86 58 / 0.16); }
.states strong { display: block; margin-top: 14px; font-size: 15px; letter-spacing: -0.01em; }
.states span { display: block; margin-top: 4px; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }

@media (max-width: 760px) {
  .states { grid-template-columns: 1fr; gap: 22px; }
  .states li { padding: 0 0 0 26px; }
  .states li::before { left: 6px; top: 14px; bottom: -22px; right: auto; width: 2px; height: auto; }
  .states .dot { position: absolute; left: 0; top: 3px; }
  .states strong { margin-top: 0; }
}

/* --- proof slots --------------------------------------------------------- */
.proof {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-top: 32px;
  padding: 0;
  list-style: none;
}
.proof li {
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--e1);
}
.proof strong { display: block; font-size: 16px; letter-spacing: -0.01em; }
.proof span { display: block; margin-top: 8px; font-size: 14.5px; line-height: 1.6; color: var(--ink-2); }
@media (max-width: 760px) { .proof { grid-template-columns: 1fr; } }

/* --- reviews carousel ---------------------------------------------------- */
/* Photo on top, quote under it, attribution last — read in that order, the
   picture is what makes the sentence believable rather than decoration beside
   it.

   The track is a plain scrolling row with snap points. A phone swipes it and a
   trackpad flicks it before a line of JavaScript runs; the arrows and dots are
   an addition, not the mechanism. */
.rv-carousel { position: relative; margin-top: 34px; }

.rv-track {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Room for the card shadow and the hover lift, pulled back out again so the
     row still lines up with the text above it. */
  padding: 6px 6px 10px;
  margin: -6px -6px -10px;
  scrollbar-width: none;
}
.rv-track::-webkit-scrollbar { display: none; }

.rv-track > .rv { flex: 0 0 calc((100% - 40px) / 3); scroll-snap-align: start; }
@media (max-width: 1000px) { .rv-track > .rv { flex-basis: calc((100% - 20px) / 2); } }
@media (max-width: 640px)  { .rv-track > .rv { flex-basis: 100%; } }

.rv {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--e1);
  overflow: hidden;
  transition: box-shadow 160ms ease, transform 160ms ease;
}
.rv:hover { box-shadow: var(--e2); transform: translateY(-2px); }

.rv-photo {
  aspect-ratio: 4 / 3;
  background: var(--surface-3);
  overflow: hidden;
}
.rv-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* No picture yet, or a broken path: keep the words, drop the grey hole. */
.rv.no-photo .rv-photo { display: none; }

.rv-body { padding: 20px 20px 22px; display: flex; flex-direction: column; gap: 12px; flex: 1; }

.rv-stars { margin: 0; font-size: 14px; letter-spacing: 2px; line-height: 1; }
.rv-stars .on  { color: var(--accent); }
.rv-stars .off { color: var(--line-strong); }

.rv blockquote {
  margin: 0;
  font-size: 15px;
  line-height: 1.62;
  color: var(--ink);
}
.rv blockquote::before { content: '\201C'; }
.rv blockquote::after  { content: '\201D'; }

/* Pushed to the bottom so the attributions line up across cards of one height,
   however long the quotes above them run. */
.rv-by { margin: auto 0 0; padding-top: 4px; }
.rv-by strong { display: block; font-size: 14px; letter-spacing: -0.01em; }
.rv-by span   { display: block; margin-top: 2px; font-size: 13px; color: var(--ink-3); }

.rv-controls { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 26px; }

.rv-arrow {
  display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink);
  font: inherit; font-size: 19px; line-height: 1;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, opacity 140ms ease;
}
.rv-arrow:hover:not(:disabled) { background: var(--surface-2); border-color: var(--ink-4); }
.rv-arrow:disabled { opacity: 0.28; cursor: default; }

.rv-dots { display: flex; align-items: center; gap: 9px; }
.rv-count { font-size: 14px; color: var(--ink-2); font-variant-numeric: tabular-nums; min-width: 58px; text-align: center; }
.rv-dot {
  width: 8px; height: 8px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--line-strong);
  cursor: pointer;
  transition: background 140ms ease, transform 140ms ease;
}
.rv-dot:hover { background: var(--ink-4); }
.rv-dot.on { background: var(--accent); transform: scale(1.3); }

/* --- centred call to action ---------------------------------------------- */
/* `.cta` is a flex row, and a flex row does not inherit the `text-align:
   center` its parent sets — which is why the closing button sat against the
   left edge under a heading that was centred. */
.closer .cta { justify-content: center; }

/* --- consentimiento de SMS ----------------------------------------------- */
/* Letra pequeña de verdad: legible, no escondida. Una casilla que la gente no
   puede leer no es un permiso, y es justo la que un operador te va a pedir que
   le enseñes. */
.mkt .bk-consent {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 18px;
  cursor: pointer;
}
.mkt .bk-consent input {
  margin-top: 2px;
  width: 16px; height: 16px;
  flex: 0 0 auto;
  accent-color: var(--ink);
  cursor: pointer;
}
.mkt .bk-consent span {
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-3);
}
