/* ============================================================
   BROWARD MOBILE DETAILING — Wet Glass
   Identity: the moment water beads and runs off a fresh coat.
   Committed palette: hydro blue + graphite on white, amber for the ask.
   ============================================================ */

/* Fontshare drops every family after a weight it does not have, so only ask
   for weights that exist. Clash Display stops at 700; Satoshi has 900. */
@import url('https://api.fontshare.com/v2/css?f[]=clash-display@400,500,600,700&f[]=satoshi@400,500,700,900&display=swap');

/* ---------- Tokens ---------- */
:root {
  /* Ground — white. A detailing page is a before/after medium; every surface
     that is not the work itself stays out of the way. */
  --bg:          oklch(1 0 0);
  --surface:     oklch(0.966 0.005 250);   /* cool grey wash, never warm */
  --line:        oklch(0.900 0.008 250);

  /* Ink */
  --ink:         oklch(0.210 0.022 258);   /* 12.6:1 on white */
  --muted:       oklch(0.475 0.020 258);   /* 4.9:1 on white */
  --shell:       oklch(0.975 0.004 250);   /* text on dark grounds */
  --shell-dim:   oklch(0.830 0.012 250);

  /* Hydro — the brand */
  --gloss:       oklch(0.720 0.155 225);   /* bright: display type on dark, marks */
  --gloss-hi:    oklch(0.860 0.110 205);   /* highlight, water */
  --brand:       oklch(0.545 0.170 250);   /* fills + white text, 4.8:1 */
  --brand-d:     oklch(0.475 0.160 250);   /* pressed */

  /* Graphite — the anchor */
  --steel:       oklch(0.265 0.028 258);
  --steel-deep:  oklch(0.175 0.022 260);
  --steel-mid:   oklch(0.375 0.032 256);

  /* Flare — the ask. Used only on CTAs sitting on graphite, never as decoration. */
  --flare:       oklch(0.780 0.155 72);
  --flare-d:     oklch(0.700 0.150 68);

  /* Type */
  --font-display: 'Clash Display', 'Helvetica Neue', Arial, sans-serif;
  --font-body:    'Satoshi', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --step--1: clamp(0.83rem, 0.80rem + 0.15vw, 0.92rem);
  --step-0:  clamp(1rem, 0.96rem + 0.20vw, 1.13rem);
  --step-1:  clamp(1.27rem, 1.19rem + 0.38vw, 1.55rem);
  --step-2:  clamp(1.60rem, 1.45rem + 0.75vw, 2.13rem);
  --step-3:  clamp(2.02rem, 1.75rem + 1.35vw, 2.92rem);
  --step-4:  clamp(2.25rem, 1.80rem + 2.35vw, 4.00rem);
  --step-5:  clamp(3.05rem, 2.20rem + 4.25vw, 5.60rem);

  /* Space */
  --sp-1: 0.375rem; --sp-2: 0.75rem;  --sp-3: 1.25rem;
  --sp-4: 2rem;     --sp-5: 3.25rem;  --sp-6: clamp(3.5rem, 7vw, 6.5rem);
  --sp-7: clamp(5rem, 11vw, 10rem);
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --measure: 66ch;

  --radius: 3px;              /* near-square: this trade sells precision */
  --radius-lg: 6px;

  /* Semantic z-scale */
  --z-base: 0; --z-sticky: 100; --z-dropdown: 200;
  --z-backdrop: 300; --z-modal: 400; --z-toast: 500;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);   /* ease-out-expo */
  --ease-q: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.62;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0;
  /* Last resort only: a word that cannot fit its box breaks instead of
     overflowing the page. "Bachelorettes" at display size on a 375px phone
     is the case this exists for. */
  overflow-wrap: break-word;
  hyphens: auto;
}
h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); letter-spacing: -0.007em; }
h4 { font-size: var(--step-1); letter-spacing: -0.005em; }
p  { margin: 0; text-wrap: pretty; }

a { color: inherit; }
:focus-visible {
  outline: 3px solid var(--gloss);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- Layout ---------- */
.wrap { width: min(100% - var(--gutter) * 2, 1240px); margin-inline: auto; }
.wrap--narrow { width: min(100% - var(--gutter) * 2, 860px); margin-inline: auto; }
.band { padding-block: var(--sp-7); }
.band--tight { padding-block: var(--sp-6); }
.band--surface { background: var(--surface); }
.band--steel { background: var(--steel); color: var(--shell); }
.band--steel h2, .band--steel h3 { color: var(--shell); }
.band--drench { background: var(--brand); color: #fff; }
.band--drench h2, .band--drench h3 { color: #fff; }
.band--steel p, .band--drench p { line-height: 1.7; }  /* light-on-dark breathing room */

.lede { font-size: var(--step-1); line-height: 1.5; max-width: min(34ch, 100%); color: var(--muted); }
.band--steel .lede, .band--drench .lede { color: var(--shell-dim); }
.prose { max-width: var(--measure); }
.prose p + p { margin-top: var(--sp-3); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: var(--z-toast);
  background: var(--ink); color: #fff; padding: var(--sp-2) var(--sp-3);
}
.skip:focus { left: var(--sp-3); top: var(--sp-3); }

/* ---------- Section head ---------- */
/* min-width:0 on every grid child. Without it a grid item refuses to shrink
   below its min-content width and quietly pushes the whole page sideways
   on phones — which is exactly what it did here. */
.head > *, .split > *, .row > *, .pkg > *, .rows > *,
.stack-4 > *, .stack-3 > *, .cta-final > *, .dodont > *,
.specimen > *, .form-light > *, .foot-grid > * { min-width: 0; }

.head { display: grid; gap: var(--sp-3); margin-bottom: var(--sp-5); }
@media (min-width: 900px) {
  .head--split {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: end; gap: var(--sp-5);
  }
}

/* The one deliberate brand device: a Spanish phrase set in coral, inline with the heading.
   Not an eyebrow system — it appears where the Spanish IS the voice, and it is never
   a tiny tracked-out all-caps label. */
.said {
  font-family: var(--font-display);
  font-weight: 500;
  font-style: normal;
  font-size: var(--step-1);
  letter-spacing: -0.005em;
  color: var(--brand);
  display: block;
  margin-bottom: 0.15em;
}
.band--steel .said, .band--drench .said { color: var(--gloss-hi); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 0.55em;
  font-family: var(--font-display); font-weight: 600;
  font-size: var(--step-0); letter-spacing: -0.003em;
  padding: 0.95em 1.6em; min-height: 48px;
  border: 2px solid transparent; border-radius: var(--radius);
  text-decoration: none; cursor: pointer;
  transition: background-color .35s var(--ease), color .35s var(--ease),
              border-color .35s var(--ease), transform .35s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--brand); color: #fff; }
.btn--primary:hover { background: var(--brand-d); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--bg); }
.btn--light { background: #fff; color: var(--brand); }
.btn--light:hover { background: var(--gloss-hi); color: var(--steel-deep); }
.btn--outline-light { background: transparent; color: #fff; border-color: rgb(255 255 255 / 0.55); }
.btn--outline-light:hover { background: #fff; color: var(--steel-deep); border-color: #fff; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* ---------- Header ---------- */
.site-head {
  --head-row: 74px;   /* the logo/CTA row; the drawer hangs below it */
  position: sticky; top: 0; z-index: var(--z-sticky);
  background: rgb(255 255 255 / 0.94);
  border-bottom: 1px solid var(--line);
  backdrop-filter: saturate(1.4) blur(10px);
}
.site-head__in {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 74px;
}
.brand { display: inline-flex; align-items: center; gap: 0.6rem; text-decoration: none; margin-right: auto; }
.brand__mark { width: 34px; height: 34px; flex: none; }
.brand__type {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.28rem; letter-spacing: -0.012em; color: var(--ink);
  line-height: 1;
}
.brand__type em { font-style: normal; color: var(--brand); }

.nav { display: none; gap: clamp(1rem, 2vw, 1.9rem); }
.nav a {
  text-decoration: none; font-weight: 500; font-size: var(--step--1);
  color: var(--ink); padding-block: 0.6rem; position: relative;
}
.nav a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0.15rem; height: 2px;
  background: var(--brand); transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--ease);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
@media (min-width: 1000px) { .nav { display: flex; } }

/* ---------- Nav dropdowns ---------- */
/* Twelve pages used to sit behind two hubs. The panel opens on hover, on
   keyboard focus, and on a tap of the chevron — the parent link still goes to
   the hub, so the menu never blocks the obvious action. */
.nav__item { position: relative; display: flex; align-items: center; gap: 0.15rem; }
.nav__more {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border: 0; background: none;
  color: var(--muted); cursor: pointer; border-radius: 2px;
  transition: color .3s var(--ease), transform .3s var(--ease);
}
.nav__more svg { width: 10px; height: 7px; }
.nav__item:hover .nav__more, .nav__item:focus-within .nav__more { color: var(--brand); }
.nav__more[aria-expanded="true"] { transform: rotate(180deg); }

.nav__menu {
  position: absolute; top: calc(100% + 0.55rem); left: -0.85rem;
  min-width: max-content; display: grid; gap: 0.05rem;
  padding: 0.4rem; z-index: var(--z-dropdown);
  background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 18px 40px -22px oklch(0.22 0.035 210 / 0.55);
  opacity: 0; visibility: hidden; transform: translateY(-5px);
  transition: opacity .28s var(--ease), transform .28s var(--ease),
              visibility .28s var(--ease);
}
/* visibility:hidden also takes the links out of the tab order, so focus lands
   on the parent first, opens the panel, and then walks into it. */
.nav__item:hover .nav__menu,
.nav__item:focus-within .nav__menu,
.nav__item.is-open .nav__menu {
  opacity: 1; visibility: visible; transform: none;
}
/* A hover bridge across the gap, so the panel does not close mid-travel. */
.nav__item::after {
  content: ''; position: absolute; top: 100%; left: 0; right: 0; height: 0.6rem;
}
.nav__menu a {
  padding: 0.5rem 0.75rem; border-radius: 2px; white-space: nowrap;
  color: var(--ink); font-weight: 500;
}
.nav__menu a::after { content: none; }   /* no underline sweep in here */
.nav__menu a:hover, .nav__menu a:focus-visible { background: var(--surface); color: var(--brand); }

/* Mobile drawer: the children are simply listed, indented. No nested
   accordion to fight with on a phone. */
.mobile-nav__sub {
  display: grid; gap: 0.1rem;
  margin: 0.1rem 0 0.5rem; padding-left: var(--sp-3);
  border-left: 1px solid var(--line);
}
.mobile-nav__sub a {
  font-size: var(--step--1) !important; font-weight: 500;
  color: var(--muted); padding-block: 0.45rem;
}
.mobile-nav__sub a:hover { color: var(--brand); }

.head-tools { display: flex; align-items: center; gap: var(--sp-2); }
.lang {
  font-family: var(--font-display); font-weight: 600; font-size: var(--step--1);
  background: none; border: 1.5px solid var(--line); border-radius: var(--radius);
  color: var(--muted); cursor: pointer; padding: 0.5rem 0.7rem; min-height: 40px;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.lang:hover { border-color: var(--brand); color: var(--brand); }
.lang b { color: var(--ink); font-weight: 700; }
.head-tools .btn { padding: 0.7em 1.15em; min-height: 44px; font-size: var(--step--1); }
.head-tools .btn--ghost { display: none; }
@media (min-width: 640px) { .head-tools .btn--ghost { display: inline-flex; } }

.burger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border: 1.5px solid var(--line); background: none;
  border-radius: var(--radius); cursor: pointer; color: var(--ink);
}
@media (min-width: 1000px) { .burger { display: none; } }
.burger span { display: block; width: 18px; height: 2px; background: currentColor; position: relative; }
.burger span::before, .burger span::after {
  content: ''; position: absolute; left: 0; width: 18px; height: 2px; background: currentColor;
  transition: transform .35s var(--ease), top .35s var(--ease);
}
.burger span::before { top: -6px; } .burger span::after { top: 6px; }
.burger[aria-expanded="true"] span { background: transparent; }
.burger[aria-expanded="true"] span::before { top: 0; transform: rotate(45deg); }
.burger[aria-expanded="true"] span::after  { top: 0; transform: rotate(-45deg); }

.mobile-nav {
  display: none; border-top: 1px solid var(--line);
  background: var(--bg); padding: var(--sp-3) 0 var(--sp-4);
}
/* The header is sticky, so a drawer taller than the screen would simply run off
   the bottom with no way to reach it — the page scrolls instead. Cap it to what
   is left below the header row and let the drawer itself scroll. */
.mobile-nav.is-open {
  display: block;
  max-height: calc(100vh - var(--head-row));
  max-height: calc(100dvh - var(--head-row));
  overflow-y: auto;
  overscroll-behavior: contain;   /* do not hand the scroll back to the page */
}
@media (min-width: 1000px) { .mobile-nav.is-open { display: none; } }
.mobile-nav a {
  display: block; text-decoration: none; font-family: var(--font-display);
  font-weight: 600; font-size: var(--step-1); padding: 0.6rem 0;
  border-bottom: 1px solid var(--line);
}

/* Phones: the brand + language toggle + CTA + burger do not fit at 375px at
   full size. Compact the row rather than dropping the booking CTA — it is the
   whole point of the header. */
@media (max-width: 560px) {
  .site-head { --head-row: 64px; }
  .site-head__in { gap: 0.5rem; min-height: 64px; }
  /* Mark-only lockup. The wordmark is the widest thing in the row, and losing it
     is cheaper than losing either the language toggle or the booking CTA —
     both of which have to stay visible for this audience. */
  .brand__type { display: none; }
  .brand__mark { width: 32px; height: 32px; }
  .head-tools { gap: 0.4rem; }
  .lang { padding: 0.45rem 0.55rem; min-height: 38px; font-size: 0.8rem; }
  .head-tools .btn { padding: 0.6em 0.85em; min-height: 38px; font-size: 0.82rem; }
  .burger { width: 38px; height: 38px; flex: none; }
  .mobile-nav a { font-size: var(--step-0); }
}

/* ---------- Hero ---------- */
.hero { position: relative; isolation: isolate; background: var(--steel-deep); overflow: hidden; }
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img,
.hero__media video { width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%; }
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(185deg, oklch(0.175 0.022 260 / 0.60) 0%, oklch(0.175 0.022 260 / 0.16) 42%, oklch(0.175 0.022 260 / 0.86) 100%),
    radial-gradient(72% 58% at 76% 30%, oklch(0.62 0.15 248 / 0.34) 0%, transparent 68%);
}
/* Slow drift — atmosphere, not decoration.
   Cool, not the warm sun this was inherited from: the amber Call button is the
   only warm thing on the page, and that is exactly what makes it pull the eye.
   A warm glow behind it competes with the one element meant to be clicked. */
.hero__glow {
  position: absolute; z-index: -1; inset: auto -10% 22% auto;
  width: min(52vw, 620px); aspect-ratio: 1;
  background: radial-gradient(circle, oklch(0.66 0.16 245 / 0.38) 0%, transparent 62%);
  filter: blur(18px);
  animation: drift 26s var(--ease-q) infinite alternate;
}
@keyframes drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-5%, -7%, 0) scale(1.14); }
}
.hero__in {
  position: relative;
  padding-block: clamp(6rem, 17vh, 11rem) clamp(3.5rem, 9vh, 6rem);
  color: #fff;
  display: grid; gap: var(--sp-4);
}
.hero h1 { color: #fff; max-width: 15ch; letter-spacing: -0.013em; }
.hero h1 .sun { color: var(--gloss-hi); }
.hero__sub { font-size: var(--step-1); line-height: 1.5; max-width: 40ch; color: oklch(0.94 0.008 250); }
.hero__meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  font-size: var(--step--1); color: oklch(0.90 0.010 250);
  border-top: 1px solid rgb(255 255 255 / 0.25); padding-top: var(--sp-3);
  margin-top: var(--sp-2);
}
.hero__meta strong { font-family: var(--font-display); font-weight: 600; color: #fff; }

/* ---------- Quote strip ---------- */
.strip { background: var(--steel-deep); border-top: 1px solid oklch(0.345 0.052 203 / 0.5); }
.strip .wrap { padding-block: var(--sp-5); }
.strip__head { max-width: 52ch; margin-bottom: var(--sp-4); }
.strip__head h2 { font-size: var(--step-2); color: var(--shell); margin-bottom: 0.6rem; }
.strip__head p { color: var(--shell-dim); font-size: var(--step-0); }
.strip form { display: grid; gap: var(--sp-3); grid-template-columns: 1fr; }
@media (min-width: 860px) {
  .strip form { grid-template-columns: repeat(3, 1fr) auto; align-items: end; }
}

/* Shared by the dark strip and the light booking form on /contact. */
/* min-width:0 — a grid item defaults to min-width:auto, so a control with a wide
   intrinsic size (iOS date inputs have one) pushes straight out of its track. */
.field { display: grid; gap: 0.4rem; min-width: 0; }
.field label {
  font-family: var(--font-display); font-weight: 600; font-size: var(--step--1);
  color: var(--shell-dim); letter-spacing: -0.002em;
}
.field input, .field select, .field textarea {
  font: inherit; font-size: var(--step-0);
  /* One line-height for all three, or a text input, a select and a date each
     compute a different box and the row stops lining up. */
  line-height: 1.2;
  padding: 0.8rem 0.9rem; min-height: 48px; width: 100%;
  border: 1.5px solid oklch(0.345 0.052 203); border-radius: var(--radius);
  background: oklch(0.20 0.04 206); color: var(--shell);
  transition: border-color .3s var(--ease);
}
/* Single-line controls get one fixed box. min-height alone still leaves each
   browser's own inner box to break the tie, and the row reads as ragged. */
.field input, .field select { height: 48px; }
.field input:hover, .field select:hover { border-color: var(--gloss); }
.field ::placeholder { color: oklch(0.70 0.02 205); opacity: 1; }
/* Sits under the whole row, not in the fourth column beside the button. */
.strip__fine {
  grid-column: 1 / -1; margin: 0;
  color: var(--shell-dim); font-size: var(--step--1);
}
.strip .btn { width: 100%; justify-content: center; gap: 0.55em; }
@media (min-width: 860px) { .strip .btn { width: auto; } }
.btn__ico { width: 1.15em; height: 1.15em; flex: none; }

/* iOS Safari gives date inputs a native box that ignores width, sizes itself
   from its own shadow text and sits on a text baseline — so on a phone it came
   out wider than its column and taller than the fields beside it. Resetting the
   appearance and pinning the box makes it match the select and the number. */
.field input[type="date"] {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; min-width: 0;
}

/* The native picker glyph renders near-black, which is invisible on the bay
   ground. Inverting it is the only hook the control exposes. */
.strip input[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(1); opacity: 0.65; cursor: pointer;
}
.strip input[type="date"]:hover::-webkit-calendar-picker-indicator { opacity: 1; }

/* ---------- Quote form on a light ground ---------- */
.form-light { display: grid; gap: var(--sp-3); }
@media (min-width: 700px) {
  .form-light { grid-template-columns: 1fr 1fr; }
  .form-light .field--full, .form-light .form-foot { grid-column: 1 / -1; }
}
.form-light .field label { color: var(--ink); }
.form-light .field input,
.form-light .field select,
.form-light .field textarea {
  background: var(--bg); color: var(--ink); border-color: var(--line);
}
.form-light .field input:hover, .form-light .field select:hover,
.form-light .field textarea:hover { border-color: var(--brand); }
.form-light .field ::placeholder { color: var(--muted); }
.form-light textarea { min-height: 7.5rem; resize: vertical; line-height: 1.55; }
.form-foot { display: grid; gap: var(--sp-2); justify-items: start; }
.form-note { font-size: var(--step--1); color: var(--muted); max-width: 52ch; }
[data-status]:not(.vh) { font-size: var(--step--1); color: var(--brand); font-weight: 500; }

/* ---------- Contact rail ---------- */
.rail { display: grid; gap: var(--sp-4); align-content: start; }
.rail__item { display: grid; gap: 0.25rem; padding-block: var(--sp-3); border-top: 1px solid var(--line); }
.rail__item:first-child { border-top: 0; padding-top: 0; }
.rail__label { font-size: var(--step--1); color: var(--muted); }
.rail__value {
  font-family: var(--font-display); font-weight: 600; font-size: var(--step-1);
  letter-spacing: -0.007em; text-decoration: none;
}
a.rail__value:hover { color: var(--brand); }

/* ---------- Service rows (deliberately not a card grid) ---------- */
.pkg { display: grid; gap: var(--sp-4); align-items: center; }
.pkg + .pkg { margin-top: var(--sp-6); padding-top: var(--sp-6); border-top: 1px solid var(--line); }
@media (min-width: 900px) {
  .pkg { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--sp-6); }
  .pkg--flip > .pkg__media { order: 2; }
}
.pkg__media { position: relative; border-radius: var(--radius-lg); overflow: hidden; background: var(--surface); }
/* Square: real job photos come off a phone, mixed portrait and landscape.
   A 1:1 crop treats both fairly. */
.pkg__media img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
@media (min-width: 900px) { .pkg__media img { aspect-ratio: 4 / 3.4; } }
.pkg__tag {
  position: absolute; left: 0; bottom: 0;
  background: var(--brand); color: #fff;
  font-family: var(--font-display); font-weight: 600; font-size: var(--step--1);
  padding: 0.5rem 0.9rem;
}
.pkg__body { display: grid; gap: var(--sp-3); }
.pkg__name { font-size: var(--step-3); }
.spec { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); margin: 0; padding: 0; }
.spec > div { display: grid; gap: 0.1rem; }
.spec dt { font-size: var(--step--1); color: var(--muted); }
.spec dd { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: var(--step-1); letter-spacing: -0.007em; }
.band--steel .spec dt { color: var(--shell-dim); }
/* The full spec list on a service page. Wrapping flex left six items ragged
   (four, then two); a grid keeps the columns true at 2 and 3 across. */
.spec--icons {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3) var(--sp-4);
}
@media (min-width: 700px) { .spec--icons { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.spec--icons dt { display: flex; align-items: center; gap: 0.42rem; }
.spec__ico { width: 17px; height: 17px; flex: none; color: var(--brand); }
.band--steel .spec__ico { color: var(--gloss-hi); }
.price { font-family: var(--font-display); font-weight: 700; font-size: var(--step-2); color: var(--brand); letter-spacing: -0.01em; }
.price small { font-family: var(--font-body); font-weight: 400; font-size: var(--step--1); color: var(--muted); letter-spacing: 0; }
.band--steel .price { color: var(--gloss-hi); }
.band--steel .price small { color: var(--shell-dim); }

/* ---------- Service tiles ---------- */
.tiles { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
@media (min-width: 900px) {
  .tiles { grid-template-columns: repeat(6, 1fr); grid-auto-rows: 15rem; }
  .tile--wide { grid-column: span 3; grid-row: span 2; }
  .tile { grid-column: span 3; }
  .tiles--six .tile { grid-column: span 2; }
  .tiles--six .tile--wide { grid-column: span 4; grid-row: span 2; }
  /* Closes the grid. Nine tiles fill four rows exactly, so a tenth two-column
     tile would leave a row four columns short; a full-width band does not. */
  .tiles--six .tile--full { grid-column: 1 / -1; min-height: 0; }
}

.tile {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--radius-lg); min-height: 14rem;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--sp-3); color: #fff; text-decoration: none;
  background: var(--steel);
}
.tile img {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.1s var(--ease);
}
.tile::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top, oklch(0.165 0.035 208 / 0.90) 8%, oklch(0.165 0.035 208 / 0.30) 55%, oklch(0.165 0.035 208 / 0.10) 100%);
}
.tile:hover img { transform: scale(1.06); }
.tile h3 { font-size: var(--step-2); color: #fff; }
.tile__es { color: var(--gloss-hi); font-family: var(--font-display); font-weight: 500; font-size: var(--step-0); }
.tile p { color: oklch(0.92 0.008 250); font-size: var(--step--1); margin-top: 0.35rem; max-width: 40ch; }
.tile--wide h3 { font-size: var(--step-3); }

/* ---------- What's included ----------
   Six short inclusions. Hairline separators rather than boxed cards: the site
   already sets its rhythm with rules (.row, .rail__item), and a grid of
   bordered icon cards is the one layout every competitor detailing site uses. */
.kit { display: grid; grid-template-columns: 1fr; column-gap: var(--sp-5); }
@media (min-width: 560px) { .kit { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .kit { grid-template-columns: repeat(3, 1fr); } }
.kit__item {
  display: grid; gap: 0.45rem; align-content: start;
  padding-block: var(--sp-4); border-top: 1px solid var(--line);
}
.kit__ico { width: 26px; height: 26px; color: var(--brand); margin-bottom: 0.15rem; }
.kit__item h3 { font-size: var(--step-0); margin: 0; letter-spacing: -0.004em; }
.kit__item p { margin: 0; color: var(--muted); font-size: var(--step--1); max-width: 34ch; }
/* Single column only. Once the items sit side by side they read as a grid and
   the left edge is doing the aligning; stacked full-width, it just looks adrift. */
@media (max-width: 559px) {
  .kit__item { justify-items: center; text-align: center; }
  .kit__item p { margin-inline: auto; }
}

/* ---------- Marks / value rows ---------- */
.rows { display: grid; gap: 0; }
.row {
  display: grid; gap: var(--sp-2); padding-block: var(--sp-4);
  border-top: 1px solid var(--line);
}
.band--drench .row, .band--steel .row { border-color: rgb(255 255 255 / 0.28); }
.rows .row:last-child { border-bottom: 1px solid var(--line); }
.band--drench .rows .row:last-child, .band--steel .rows .row:last-child { border-color: rgb(255 255 255 / 0.28); }
@media (min-width: 800px) {
  .row { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.4fr); gap: var(--sp-5); align-items: baseline; }
}
.row h3 { font-size: var(--step-2); }
.row p { color: var(--muted); }
.band--drench .row p { color: oklch(0.94 0.014 250); }
.band--steel .row p { color: var(--shell-dim); }

/* ---------- Coverage zones ---------- */
.zones { display: grid; gap: var(--sp-4); }
@media (min-width: 780px) { .zones { grid-template-columns: 1fr 1fr; gap: var(--sp-5); } }
.zone { display: grid; gap: var(--sp-2); }
.zone__name { font-size: var(--step-2); }
.zone address { font-style: normal; color: var(--muted); }
.band--steel .zone address { color: var(--shell-dim); }

/* ---------- FAQ ---------- */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; padding: var(--sp-3) 0;
  font-family: var(--font-display); font-weight: 600; font-size: var(--step-1);
  letter-spacing: -0.006em; display: flex; gap: var(--sp-3);
  align-items: baseline; justify-content: space-between;
  transition: color .3s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--brand); }
.faq summary::after {
  content: '+'; font-weight: 500; color: var(--brand); flex: none;
  transition: transform .4s var(--ease); font-size: 1.3em; line-height: 1;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > div { padding-bottom: var(--sp-4); max-width: var(--measure); color: var(--muted); }

/* ---------- Split feature ---------- */
.split { display: grid; gap: var(--sp-5); align-items: center; }
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; gap: var(--sp-6); }
  .split--flip > .split__media { order: 2; }
}
.split__media { border-radius: var(--radius-lg); overflow: hidden; }
.split__media img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
@media (min-width: 900px) { .split__media img { aspect-ratio: 4 / 4.4; } }

/* ---------- CTA band ---------- */
.cta-final { text-align: center; display: grid; gap: var(--sp-4); justify-items: center; }
.cta-final h2 { max-width: 16ch; }
.cta-final p { max-width: 46ch; color: oklch(0.94 0.014 250); }

/* ---------- Footer ---------- */
.site-foot { background: var(--steel-deep); color: var(--shell-dim); padding-block: var(--sp-6) var(--sp-4); }
.foot-grid { display: grid; gap: var(--sp-5); }
@media (min-width: 800px) { .foot-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; } }
/* Nine services in a single column left the footer lopsided. Above 1040px the
   Services column takes the extra width and splits its list in two; below
   that there is not room for two readable columns, so it stays as one. */
@media (min-width: 1040px) {
  /* The wide track is the SECOND one, because Services is the second column
     in the footer markup. Getting these out of step is what leaves the nine
     service links wrapping two words to a line. */
  .foot-grid { grid-template-columns: 1.35fr 1.9fr 1fr 1fr; }
  /* Column flow, not the row-major default: a reader going down the first
     column should get the first five services, not every other one. */
  .foot-col--wide ul {
    grid-auto-flow: column;
    grid-template-rows: repeat(5, auto);
    grid-auto-columns: minmax(0, 1fr);
    column-gap: var(--sp-4);
  }
}
.site-foot h4 { color: var(--shell); font-size: var(--step-0); margin-bottom: var(--sp-2); }
.site-foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.site-foot a { color: var(--shell-dim); text-decoration: none; font-size: var(--step--1); }
.site-foot a:hover { color: var(--gloss-hi); }
.site-foot .brand__type { color: var(--shell); }
.foot-note {
  margin-top: var(--sp-5); padding-top: var(--sp-3);
  border-top: 1px solid oklch(0.345 0.052 203 / 0.6);
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  justify-content: space-between; font-size: var(--step--1);
}

/* ---------- Work gallery ---------- */
.gallery{display:grid;gap:var(--sp-2);grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr))}
@media (min-width:900px){
  .gallery{grid-template-columns:repeat(4,1fr)}
  .gallery figure:nth-child(1){grid-column:span 2;grid-row:span 2}
}
.gallery figure{margin:0;position:relative;overflow:hidden;border-radius:var(--radius-lg);background:var(--surface)}
.gallery img{width:100%;height:100%;object-fit:cover;aspect-ratio:1;display:block;transition:transform 1s var(--ease)}
.gallery figure:nth-child(1) img{aspect-ratio:1}
.gallery figure:hover img{transform:scale(1.04)}
.gallery figcaption{
  position:absolute;inset:auto 0 0 0;padding:.85rem;color:#fff;font-size:var(--step--1);
  background:linear-gradient(to top,oklch(0.165 0.035 208/.86),transparent);
  opacity:0;transition:opacity .35s var(--ease)
}
.gallery figure:hover figcaption,.gallery figure:focus-within figcaption{opacity:1}
@media (prefers-reduced-motion:reduce){
  .gallery img{transition:none}
  .gallery figcaption{opacity:1}
}

/* ---------- Sticky call bar ----------
   Phones and tablets only: the desktop header already keeps Call and Get a
   quote on screen, and a second fixed bar there would just eat the viewport. */
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
  padding: 0.65rem var(--sp-3);
  padding-bottom: calc(0.65rem + env(safe-area-inset-bottom));  /* clears the iPhone home bar */
  background: rgb(255 255 255 / 0.94);
  backdrop-filter: saturate(1.4) blur(10px);
  border-top: 1px solid var(--line);
  animation: cta-rise .34s var(--ease) both;
}
.sticky-cta .btn { width: 100%; justify-content: center; gap: 0.55em; }
@keyframes cta-rise { from { transform: translateY(100%); } to { transform: none; } }
/* Keep the last of the page clear of the bar rather than under it. */
body.has-sticky-cta { padding-bottom: 4.75rem; }
/* While the drawer is open the visitor is navigating, not booking — and a tall
   drawer runs under the bar at the bottom of the screen. */
body.nav-open .sticky-cta { display: none; }
@media (min-width: 900px) {
  .sticky-cta { display: none; }
  body.has-sticky-cta { padding-bottom: 0; }
}
@media (prefers-reduced-motion: reduce) { .sticky-cta { animation: none; } }

/* ---------- Motion: enhance what is already visible ---------- */
.rise { transition: opacity .9s var(--ease), transform .9s var(--ease); }
.js .rise { opacity: 0; transform: translate3d(0, 22px, 0); }
.js .rise.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .rise { opacity: 1 !important; transform: none !important; transition: none; }
  .hero__glow { animation: none; }
  .tile img, .btn, .nav a::after { transition: none; }
}

/* ---------- Utility ---------- */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.stack-4 { display: grid; gap: var(--sp-4); }
.stack-3 { display: grid; gap: var(--sp-3); }
.credit { font-size: 0.75rem; color: var(--muted); margin-top: var(--sp-2); }
.band--steel .credit, .site-foot .credit { color: oklch(0.62 0.02 205); }

/* ---------- Trust strip ----------
   Four claims directly under the hero. Every one of them is checkable, which
   is the point: this trade is full of sites that say "premium" and stop. */
.trust { display: grid; gap: 0; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 820px) { .trust { grid-template-columns: repeat(4, 1fr); } }
.trust__i {
  display: grid; gap: 0.3rem; align-content: start;
  padding: var(--sp-3) var(--sp-3) var(--sp-3) 0;
}
.trust__n {
  font-family: var(--font-display); font-weight: 600; font-size: var(--step-2);
  letter-spacing: -0.01em; color: var(--gloss-hi); line-height: 1;
}
.trust__l { font-size: var(--step--1); color: var(--shell-dim); max-width: 22ch; }

/* ---------- Package cards ----------
   Prices are shown, and that is a lead-quality decision: a visitor who sees
   "from $149" and still fills the form is a lead worth paying for, and one who
   bounces at the number was never going to book. */
.plans { display: grid; gap: var(--sp-3); }
@media (min-width: 800px) { .plans { grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); } }
.plan {
  display: grid; gap: var(--sp-3); align-content: start;
  padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--bg);
}
.plan--pick { border-color: var(--brand); border-width: 2px; padding: calc(var(--sp-4) - 1px); }
.plan__tag {
  justify-self: start; font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.08em; font-weight: 700; color: #fff;
  background: var(--brand); padding: 0.3rem 0.55rem; border-radius: 2px;
}
.plan h3 { font-size: var(--step-2); }
.plan__from { display: grid; gap: 0.1rem; }
.plan__price {
  font-family: var(--font-display); font-weight: 700; font-size: var(--step-3);
  color: var(--ink); letter-spacing: -0.02em; line-height: 1;
}
.plan__unit { font-size: var(--step--1); color: var(--muted); }
.plan ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.plan li { padding-left: 1.55em; position: relative; font-size: var(--step--1); }
.plan li::before {
  content: ''; position: absolute; left: 0; top: 0.42em;
  width: 0.85em; height: 0.45em; border-left: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand); transform: rotate(-45deg);
}
.plan .btn { width: 100%; justify-content: center; }

/* ---------- Service-area grid ----------
   Thirty-one municipalities. A dense link grid, not tiles: this block exists
   for the visitor checking their city is on the list, and for the crawler. */
.cities {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 0.1rem var(--sp-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 190px), 1fr));
}
.cities a {
  display: block; padding: 0.55rem 0; text-decoration: none; color: var(--ink);
  border-bottom: 1px solid var(--line); font-size: var(--step--1);
  transition: color .25s var(--ease), padding-left .25s var(--ease);
}
.cities a:hover { color: var(--brand); padding-left: 0.3rem; }
.band--steel .cities a { color: var(--shell-dim); border-color: rgb(255 255 255 / 0.18); }
.band--steel .cities a:hover { color: var(--gloss-hi); }

/* ---------- Numbered steps ---------- */
.steps { display: grid; gap: 0; counter-reset: step; }
.step {
  display: grid; gap: var(--sp-2); padding-block: var(--sp-4);
  border-top: 1px solid var(--line); counter-increment: step;
}
.steps .step:last-child { border-bottom: 1px solid var(--line); }
@media (min-width: 800px) {
  .step { grid-template-columns: 4.5rem minmax(0, 1fr) minmax(0, 1.3fr); gap: var(--sp-4); align-items: baseline; }
}
.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-display); font-weight: 600; font-size: var(--step-2);
  color: var(--gloss); line-height: 1; letter-spacing: -0.01em;
}
.step h3 { font-size: var(--step-1); }
.step p { color: var(--muted); }
.band--steel .step { border-color: rgb(255 255 255 / 0.22); }
.band--steel .step p { color: var(--shell-dim); }

/* ---------- Before / after ----------
   Slots, not decoration. Until real photos land these render as a labelled
   graphite panel — an empty frame is more honest than a stock car. */
.ba { display: grid; gap: var(--sp-3); }
@media (min-width: 700px) { .ba { grid-template-columns: 1fr 1fr; } }
.ba figure { margin: 0; display: grid; gap: 0.55rem; }
.ba__frame {
  aspect-ratio: 4 / 3; border-radius: var(--radius-lg); overflow: hidden;
  background: var(--steel); display: grid; place-items: center;
  border: 1px solid var(--line);
}
.ba__frame img { width: 100%; height: 100%; object-fit: cover; }
.ba__ph { color: var(--shell-dim); font-size: var(--step--1); letter-spacing: 0.04em; text-transform: uppercase; }
.ba figcaption { font-size: var(--step--1); color: var(--muted); }
.ba__label {
  font-family: var(--font-display); font-weight: 600; color: var(--ink);
  text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.72rem;
}

/* ---------- Quote form status ---------- */
.quote-ok {
  display: grid; gap: var(--sp-2); padding: var(--sp-4);
  border: 2px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface);
}
.quote-ok h3 { font-size: var(--step-2); }
.quote-ok p { color: var(--muted); margin: 0; }
[data-status].is-error { color: var(--flare-d); font-weight: 600; }

/* ---------- Flare button ----------
   Amber on graphite only. On white it drops under 4.5:1 and stops being a
   button you can read. */
.btn--flare { background: var(--flare); color: var(--steel-deep); }
.btn--flare:hover { background: var(--flare-d); color: var(--steel-deep); }

/* ---------- Artwork ----------
   Vector, not photography. An SVG is a few KB, stays sharp on any display,
   and — unlike a stock photo of somebody else's car — is honestly ours.
   Real job photographs replace this the day they exist; see
   assets/media/README.md, and note the before/after frames stay empty until
   those photographs are real.

   Paths resolve relative to THIS stylesheet, so /es/ pages need no second set
   of rules. Every rule degrades to the flat graphite ground if a file is
   missing. */
.hero {
  background-image:
    linear-gradient(to right,
      oklch(0.175 0.022 260 / 0.93) 0%,
      oklch(0.175 0.022 260 / 0.68) 42%,
      oklch(0.175 0.022 260 / 0.22) 100%),
    url('assets/media/hero-beads.svg');
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat;
}
/* The stock scrim would stack with the gradient above and flatten the beads. */
.hero__scrim { opacity: 0.28; }

/* Tile marks: oversized line art, bottom-right, cropped by the tile edge so it
   reads as a watermark rather than a centred icon. Sits under the gradient and
   therefore under the copy. */
.tile {
  background-repeat: no-repeat;
  /* Top-right, because the tile's copy is bottom-aligned. Anchoring the mark
     opposite the text is what keeps it from crossing the heading — which is
     exactly what it did when it sat bottom-right. */
  background-position: right -14px top -12px;
  background-size: auto 58%;
  transition: background-size .7s var(--ease), background-position .7s var(--ease);
}
@media (min-width: 900px) {
  /* The wide tile has room the others do not, so its mark can be larger and
     sit in the open middle-right rather than tucked in a corner. */
  .tile--wide { background-size: auto 56%; background-position: right 6% center; }
}
.tile:hover { background-size: auto 64%; background-position: right -6px top -8px; }
@media (min-width: 900px) {
  .tile--wide:hover { background-size: auto 60%; background-position: right 5% center; }
}
@media (prefers-reduced-motion: reduce) { .tile { transition: none; } }
.tile::after {
  background: linear-gradient(to top,
    oklch(0.175 0.022 260 / 0.93) 4%,
    oklch(0.175 0.022 260 / 0.55) 52%,
    oklch(0.175 0.022 260 / 0.18) 100%);
}
