/* =====================================================================
   Elevated Mobile Detailing
   Design system — dark, near-monochrome, red used as punctuation only.
   ===================================================================== */

:root {
  /* --- Surface ramp -------------------------------------------------
     Five steps instead of two. Depth comes from a controlled ramp plus
     hairline borders, not from drop shadows or glows. */
  --bg:        #000000;
  --bg-raised: #0E0E10;
  --bg-panel:  #121215;
  --line:      rgba(255, 255, 255, 0.09);
  --line-soft: rgba(255, 255, 255, 0.055);
  --line-hard: rgba(255, 255, 255, 0.18);

  /* --- Text ramp ---------------------------------------------------- */
  --text:   #F4F4F5;
  --text-2: #A2A2A9;
  /* Was #6E6E77 — measured 3.92:1, below the 4.5:1 WCAG AA floor for
     small text. Bumped Aug 7 2026 to 4.65:1. This is the single change
     that matters most for reading the page outdoors on a phone, which is
     where a detailing customer actually reads it. */
  --text-3: #7C7C85;

  /* --- Accent -------------------------------------------------------
     One red. Deliberately rationed: primary button, active nav, focus
     ring, and the featured package rule. Nowhere else. */
  --accent:       #D91E36;
  /* Hover was #F02742, which dropped white-on-red to 4.14:1 — the button
     got LESS readable on hover. Going darker instead of lighter keeps the
     "pressed/lit" read and lands at 5.76:1. */
  --accent-hover: #C81A30;
  --accent-dim:   rgba(217, 30, 54, 0.14);

  /* Red for SMALL TEXT only (eyebrows, inline links). The brand red is
     3.95:1 on the page background — fine as a fill behind white text,
     too low as text itself. This lightened red hits 4.75:1 and reads as
     the same colour at 0.72rem. Fills keep using --accent. */
  --accent-text:  #E8354C;

  /* --- Type --------------------------------------------------------- */
  --font-display: 'Archivo', system-ui, sans-serif;
  --font-body:    'Inter', system-ui, sans-serif;

  /* --- Radius: three values, used consistently ---------------------
     Kept small and near-square deliberately — heavy rounding is one of
     the fastest tells of a generic/AI-templated site. Automotive brand
     sites (Lexus, Porsche) run almost square. */
  --r-sm: 2px;
  --r-md: 3px;
  --r-lg: 4px;

  /* --- Motion ------------------------------------------------------- */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur:  0.5s;

  /* --- Rhythm ------------------------------------------------------- */
  --section-y: clamp(72px, 11vw, 150px);
  --gutter:    clamp(20px, 5vw, 40px);
  --shell:     1180px;
}

/* ============ Reset ============ */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  /* Offset anchor targets so the sticky header never covers a heading */
  scroll-padding-top: 88px;
  -webkit-text-size-adjust: 100%;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* legacy Edge/IE */
}
html::-webkit-scrollbar { display: none; } /* Chrome, Safari, new Edge */

body {
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--text-2);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }

/* ============ Accessibility ============ */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--accent);
  color: #fff;
  padding: 12px 20px;
  border-radius: 0 0 var(--r-sm) 0;
  font-size: 0.9rem;
}
.skip-link:focus { left: 0; }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* ============ Layout ============ */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section-y); }
.section--flush { padding-bottom: calc(var(--section-y) * 0.6); }

/* ============ Typography ============ */
h1, h2, h3 {
  font-family: var(--font-display);
  color: var(--text);
  line-height: 1.08;
  /* Negative tracking on large type is the single biggest cue that
     separates considered typography from default browser output. */
  letter-spacing: -0.028em;
  font-weight: 600;
  text-wrap: balance;
}

.eyebrow {
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  /* --accent-text, not --accent: this is 0.72rem type and needs the
     4.5:1 floor. Visually identical, measurably readable. */
  color: var(--accent-text);
  margin-bottom: 18px;
}

.section__head { max-width: 640px; margin-bottom: clamp(40px, 6vw, 72px); }

.section__head--split {
  max-width: none;
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-items: flex-start;
}

.section__title {
  font-size: clamp(1.85rem, 4.4vw, 2.9rem);
  margin-bottom: 18px;
}

.section__lede {
  font-size: 1.02rem;
  color: var(--text-2);
  max-width: 52ch;
}

/* ============ Buttons & links ============ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.92rem;
  letter-spacing: 0.005em;
  padding: 12px 22px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.2s var(--ease),
              border-color 0.2s var(--ease),
              transform 0.2s var(--ease);
}

.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-hover); transform: translateY(-1px); }
.btn--primary:active { transform: translateY(0); }

.btn--lg { padding: 16px 30px; font-size: 1rem; }

/* Arrow link — the secondary action everywhere. The arrow travels on
   hover, which reads as forward motion without needing a second button
   competing with the primary CTA. */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.92rem;
  color: var(--text);
  padding-block: 4px;
  transition: color 0.2s var(--ease);
}
.link-arrow::after {
  content: "\2192";
  transition: transform 0.28s var(--ease);
}
.link-arrow:hover { color: var(--accent); }
.link-arrow:hover::after { transform: translateX(5px); }

/* ============ Header ============ */
.header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 0.35s var(--ease),
              border-color 0.35s var(--ease);
}

/* Solid, not glass — a frosted header reads as a UI trend, not a brand
   choice. It only activates once you scroll, so the hero stays clean. */
.header.is-scrolled {
  background: var(--bg);
  border-bottom-color: var(--line-soft);
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 68px;
}

.wordmark { display: flex; align-items: center; gap: 11px; }
.wordmark__mark { width: 30px; height: 30px; object-fit: contain; border-radius: 5px; }
.wordmark__text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  color: var(--text);
  white-space: nowrap;
}

.nav { display: none; gap: 30px; }
.nav a {
  font-size: 0.9rem;
  color: var(--text-2);
  position: relative;
  padding-block: 4px;
  transition: color 0.2s var(--ease);
}
/* Underline draws out from the left rather than fading in — cheaper to
   read at a glance, and it echoes the arrow links. */
.nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  height: 1px;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--ease);
}
.nav a:hover { color: var(--text); }
.nav a:hover::after { transform: scaleX(1); }

.header__cta { display: none; }

.nav-toggle {
  width: 40px; height: 40px;
  display: grid;
  place-content: center;
  gap: 6px;
  background: none;
  border: none;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  width: 20px; height: 1.5px;
  background: var(--text);
  transition: transform 0.3s var(--ease), opacity 0.2s var(--ease);
}
.nav-toggle[aria-expanded="true"] span:first-child { transform: translateY(3.75px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:last-child  { transform: translateY(-3.75px) rotate(-45deg); }

/* Mobile menu panel */
@media (max-width: 899px) {
  .nav {
    position: fixed;
    inset: 68px 0 auto 0;
    display: flex;
    flex-direction: column;
    gap: 0;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
    padding: 8px var(--gutter) 24px;
    clip-path: inset(0 0 100% 0);
    opacity: 0;
    pointer-events: none;
    transition: clip-path 0.42s var(--ease), opacity 0.25s var(--ease);
  }
  .nav.is-open { clip-path: inset(0 0 0 0); opacity: 1; pointer-events: auto; }
  .nav a {
    font-family: var(--font-display);
    font-size: 1.28rem;
    font-weight: 500;
    letter-spacing: -0.015em;
    color: var(--text);
    padding-block: 15px;
    border-bottom: 1px solid var(--line-soft);
  }
  .nav a::after { display: none; }
}

/* ============ Hero ============ */
/* Full-bleed `cover`, not `contain` — the image fills the section edge
   to edge like a real hero banner instead of sitting letterboxed inside
   it. This is the deliberate trade Steven asked for (professional/
   stretched-to-fill over "whole car visible, no crop"), and it also
   removes the letterbox-blending problem from earlier revisions outright
   — there's no exposed edge left for the photo's backdrop to mismatch
   against, so none of that masking/fade machinery is needed any more. */
.hero {
  position: relative;
  min-height: min(90vh, 880px);
  display: flex;
  align-items: flex-end;
  padding-top: clamp(120px, 20vw, 180px);
  padding-bottom: clamp(52px, 8vw, 88px);
  /* Cheap insurance against any 1px layout rounding at the seam. Didn't
     turn out to be the actual cause of the hairline below (see the next
     comment) but it's harmless to leave in. */
  margin-bottom: -1px;
  background-color: var(--bg);
  /* The gradient used to only reach fully-opaque --bg at 100% — the very
     last pixel. That's fine when the photo's own bottom edge is already
     near-black (the BMW render, the Lamborghini), but this photo's bottom
     edge is a LIT CONCRETE FLOOR, sampled at ~140-150/255 brightness, not
     near-black. A sliver just above that final pixel was still letting
     some of that brightness through — that was the "white line", not a
     rendering seam. Reaching full opacity by 92% instead of 100% leaves a
     genuine solid-black band at the bottom regardless of what the source
     photo looks like there. */
  background-image:
    linear-gradient(180deg, rgba(10, 10, 11, 0.16) 0%, rgba(10, 10, 11, 0.24) 42%, rgba(10, 10, 11, 0.94) 78%, var(--bg) 92%),
    url("images/hero-bg-black-bmw.jpg");
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
}

/* Belt-and-suspenders: an explicit solid bar right at the bottom edge,
   on top of everything else, so the seam is unambiguously --bg no matter
   what the gradient math or the photo underneath happen to be doing. */
.hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 8px;
  background: var(--bg);
  z-index: 1;
}

.hero__title {
  font-size: clamp(2.5rem, 7.4vw, 4.4rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 0.99;
  margin-bottom: 26px;
  max-width: 15ch;
}

.hero__lede {
  font-size: clamp(1.02rem, 1.9vw, 1.16rem);
  max-width: 48ch;
  margin-bottom: 40px;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 28px;
}

/* ============ Proof strip ============ */
.proof {
  background: var(--bg);
}
.proof__grid {
  display: grid;
  grid-template-columns: 1fr;
}
.proof__item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-block: 26px;
  border-bottom: 1px solid var(--line-soft);
}
.proof__item:last-child { border-bottom: none; }

.proof__value {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--text);
}
.proof__star {
  color: var(--accent);
  font-size: 1.1rem;
  vertical-align: 2px;
}
.proof__label { font-size: 0.88rem; color: var(--text-3); }
.proof__label a { border-bottom: 1px solid var(--line-hard); transition: color 0.2s, border-color 0.2s; }
.proof__label a:hover { color: var(--text); border-color: var(--accent); }

/* ============ Packages ============ */
.packages {
  display: grid;
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  overflow: hidden;
}

/* Cards share hairline seams instead of floating separately. Reads as one
   considered object rather than three repeated boxes. Each leads with a
   photo, catalog-style, rather than being text-only. */
.package {
  background: var(--bg-raised);
  position: relative;
  transition: background-color 0.3s var(--ease);
}
.package:hover { background: var(--bg-panel); }

.package__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--bg-panel);
}
.package__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.88);
  transition: transform 0.7s var(--ease), filter 0.45s var(--ease);
}
.package:hover .package__media img { transform: scale(1.035); filter: saturate(1.02); }

.package__body { padding: clamp(24px, 3.6vw, 34px); }

.package__head { margin-bottom: 22px; }

.package__index {
  display: block;
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--accent);
  margin-bottom: 14px;
}

.package__name {
  font-size: 1.32rem;
  font-weight: 600;
  margin-bottom: 6px;
}

.package__meta { font-size: 0.86rem; color: var(--text-3); }

/* Flat solid tag pinned to the photo corner — the way a listing marks
   "New" or "Featured" on real automotive sites. No blur, no glow. */
.package__flag {
  position: absolute;
  z-index: 1;
  top: 14px;
  left: 14px;
  background: var(--accent);
  color: #fff;
  font-family: var(--font-display);
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  padding: 6px 10px;
  border-radius: var(--r-sm);
}

/* The featured package is marked with a 2px rule, not a coloured fill or a
   scale transform. Quieter, and it doesn't break the grid. */
.package--featured { background: var(--bg-panel); }
.package--featured::before {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--accent);
}

.spec { display: flex; flex-direction: column; gap: 11px; }
.spec li {
  position: relative;
  padding-left: 20px;
  font-size: 0.93rem;
  color: var(--text-2);
  line-height: 1.5;
}
.spec li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.62em;
  width: 9px; height: 1px;
  background: var(--text-3);
}

.note {
  margin-top: 30px;
  padding-left: 16px;
  border-left: 2px solid var(--accent);
  font-size: 0.93rem;
  color: var(--text-2);
  max-width: 60ch;
}

/* ============ Add-ons ============ */
.addons { margin-top: clamp(52px, 7vw, 80px); }

.addons__title {
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--accent);
  margin-bottom: 8px;
}

.addons__list { display: grid; grid-template-columns: 1fr; }

/* List rows rather than a grid of little cards. This is how a menu or a
   spec sheet is set, and it removes seven redundant boxes. No prices —
   pricing lives on the booking page, same as the packages above. */
.addon {
  padding-block: 15px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--text);
  font-size: 0.96rem;
}

/* ============ Work / gallery ============ */
.work-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.work-item {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 0;
  background: var(--bg-panel);
  cursor: pointer;
}
/* 16/9 is tall enough that a full car (roofline to wheels) fits without
   cropping into the vehicle itself, just trims sky/driveway margin. */
.work-item--wide { grid-column: span 2; aspect-ratio: 16 / 9; }

.work-item img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease), filter 0.45s var(--ease);
  /* Photos sit very slightly desaturated at rest and resolve on hover.
     Subtle, but it makes the grid feel curated rather than dumped. */
  filter: saturate(0.92);
}
/* These exterior shots have a lot of sky above the car — bias the crop
   down so the wheels don't get cut off before the sky does. */
.work-item--wide img { object-position: center 60%; }
.work-item:hover img { transform: scale(1.035); filter: saturate(1.06); }
.work-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Expand affordance, revealed on hover only */
.work-item::after {
  content: "";
  position: absolute;
  right: 12px; bottom: 12px;
  width: 30px; height: 30px;
  border-radius: var(--r-sm);
  background: rgba(10, 10, 11, 0.82) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round'%3E%3Cpath d='M9 4H4v5M15 4h5v5M9 20H4v-5M15 20h5v-5'/%3E%3C/svg%3E") center / 15px no-repeat;
  border: 1px solid var(--line);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.work-item:hover::after { opacity: 1; transform: translateY(0); }

/* ============ Reviews ============ */
.reviews { background: var(--bg-raised); border-block: 1px solid var(--line-soft); }

/* One bordered container divided by hairline seams — same pattern as the
   services packages, so each review gets its own scannable cell instead
   of one long stacked column of full-width sentences. */
.quotes {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.quote {
  background: var(--bg-raised);
  padding: clamp(28px, 4vw, 38px);
  transition: background-color 0.3s var(--ease);
}
.quote:hover { background: var(--bg-panel); }

.quote::before {
  content: "\201C";
  display: block;
  font-family: var(--font-display);
  font-size: 2.4rem;
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
  margin-bottom: 10px;
}

.quote p {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.7vw, 1.18rem);
  font-weight: 500;
  line-height: 1.44;
  letter-spacing: -0.018em;
  color: var(--text);
  margin-bottom: 16px;
  text-wrap: pretty;
}
.quote cite {
  font-style: normal;
  font-size: 0.84rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-2);
}

.reviews__more { margin-top: 30px; }

/* ============ About ============ */
/* Single column: heading on top, story stacked below it. */
.about__inner { display: grid; gap: 32px; }

.about__lead {
  font-family: var(--font-display);
  font-size: clamp(1.85rem, 4.4vw, 2.9rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.026em;
  color: var(--text);
  max-width: 20ch;
}

.about__content { max-width: 60ch; }

.about__body {
  font-size: clamp(1rem, 1.35vw, 1.08rem);
  line-height: 1.7;
  color: var(--text-2);
}

.about__body + .about__body { margin-top: 3.4em; }

/* ============ FAQ ============ */
.faq { border-top: 1px solid var(--line-soft); max-width: 780px; }

.faq__item { border-bottom: 1px solid var(--line-soft); }

.faq__item summary {
  list-style: none;
  cursor: pointer;
  padding-block: 20px;
  padding-right: 40px;
  position: relative;
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--text);
  transition: color 0.2s var(--ease);
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary:hover { color: var(--accent); }

/* Plus that rotates into a minus. One glyph, built from two rules, so
   there's no icon font or SVG to load. */
.faq__item summary::before,
.faq__item summary::after {
  content: "";
  position: absolute;
  right: 4px;
  top: 50%;
  background: var(--text-3);
  transition: transform 0.35s var(--ease), background-color 0.2s var(--ease);
}
.faq__item summary::before { width: 13px; height: 1px; transform: translateY(-50%); }
.faq__item summary::after  { width: 1px; height: 13px; right: 10px; transform: translateY(-50%); }
.faq__item[open] summary::after { transform: translateY(-50%) rotate(90deg); }
.faq__item[open] summary { color: var(--text); }
.faq__item summary:hover::before,
.faq__item summary:hover::after { background: var(--accent); }

.faq__body { padding-bottom: 22px; padding-right: 40px; max-width: 62ch; }
.faq__body p { font-size: 0.95rem; color: var(--text-2); }

.faq__item[open] .faq__body { animation: faqOpen 0.4s var(--ease); }
@keyframes faqOpen {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ============ Closing CTA ============ */
.cta {
  padding-block: clamp(84px, 13vw, 168px);
  text-align: center;
  border-top: 1px solid var(--line-soft);
  position: relative;
  overflow: hidden;
}
.cta__inner { position: relative; }

.cta__title {
  font-size: clamp(2.1rem, 6vw, 3.5rem);
  font-weight: 700;
  letter-spacing: -0.038em;
  margin-bottom: 16px;
}
.cta__lede { max-width: 42ch; margin: 0 auto 34px; }

.cta__contacts {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px 32px;
  margin-top: 40px;
}
.cta__contacts a {
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--text);
  border-bottom: 1px solid var(--line-hard);
  padding-bottom: 2px;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.cta__contacts a:hover { color: var(--accent); border-color: var(--accent); }

.cta__fineprint { margin-top: 26px; font-size: 0.83rem; color: var(--text-3); }

/* ============ Footer ============ */
.footer { border-top: 1px solid var(--line-soft); padding-block: 44px; }
.footer__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
}
.footer__meta, .footer__copy { font-size: 0.85rem; color: var(--text-3); }
.footer__meta a:hover { color: var(--text); }

/* ============ Scroll reveal ============ */
[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.62s var(--ease), transform 0.62s var(--ease);
  will-change: opacity, transform;
}
[data-reveal].is-visible { opacity: 1; transform: none; }
[data-reveal-delay="1"] { transition-delay: 0.07s; }
[data-reveal-delay="2"] { transition-delay: 0.14s; }
[data-reveal-delay="3"] { transition-delay: 0.21s; }

/* ============ Lightbox ============ */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(6, 6, 7, 0.97);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 56px 20px;
  opacity: 0;
  transition: opacity 0.28s var(--ease);
}
.lightbox[hidden] { display: none; }
.lightbox.is-open { opacity: 1; }

.lightbox__figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-width: 100%;
  max-height: 100%;
}
.lightbox__img {
  max-width: 100%;
  max-height: calc(100vh - 150px);
  object-fit: contain;
  border-radius: var(--r-md);
  transform: scale(0.985);
  transition: transform 0.32s var(--ease);
}
.lightbox.is-open .lightbox__img { transform: scale(1); }

.lightbox__close,
.lightbox__nav {
  position: absolute;
  display: grid;
  place-content: center;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line);
  color: var(--text);
  cursor: pointer;
  border-radius: 50%;
  line-height: 1;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.lightbox__close:hover,
.lightbox__nav:hover { background: var(--accent); border-color: var(--accent); }

.lightbox__close { top: 18px; right: 18px; width: 42px; height: 42px; font-size: 1.5rem; }
.lightbox__nav { top: 50%; transform: translateY(-50%); width: 44px; height: 44px; font-size: 1.6rem; }
.lightbox__nav--prev { left: 14px; }
.lightbox__nav--next { right: 14px; }

/* =====================================================================
   Responsive — mobile-first, three breakpoints only
   ===================================================================== */

@media (min-width: 620px) {
  .proof__grid { grid-template-columns: repeat(3, 1fr); gap: 1px; }
  .proof__item {
    border-bottom: none;
    padding-inline-end: 24px;
  }
  .addons__list { grid-template-columns: repeat(2, 1fr); column-gap: 48px; }
  .work-grid { gap: 12px; }
}

@media (min-width: 900px) {
  .nav { display: flex; }
  .header__cta { display: inline-flex; }
  .nav-toggle { display: none; }
  .header__inner { height: 76px; }

  .section__head--split {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-end;
  }

  .packages { grid-template-columns: repeat(3, 1fr); }
  .quotes { grid-template-columns: repeat(3, 1fr); }

  .work-grid { grid-template-columns: repeat(3, 1fr); }
  /* Wide tile is 2 columns wide (~2x a normal tile) but keeps the same
     16/9 ratio as mobile, so its row height no longer matches a normal
     4/3 tile beside it — work-item--pair marks the single normal tile
     sharing a row with a wide tile at this breakpoint and matches it. */
  .work-item--pair { aspect-ratio: 8 / 9; }

  .addons__list { grid-template-columns: repeat(3, 1fr); column-gap: 56px; }

  .footer__inner {
    flex-direction: row;
    justify-content: space-between;
    text-align: left;
  }
}


/* =====================================================================
   =====================================================================
   ADDITIONS — Aug 7 2026, updated same day (de-glow / re-organize pass)

   The ambient drifting-blob background and the button sheen/glow are
   gone — they read as generic "AI site" signatures, not a considered
   brand choice, and they fought the near-monochrome discipline above.
   Depth now comes only from the surface ramp, hairline borders, and
   real photography (packages now carry a photo each, hero is a proper
   full-bleed image). See DESIGN_NOTES.md for the full rationale.

   Remaining blocks:
     B. Micro-interactions (restrained: colour/position only)
     C. Before/after slider
     D. Mobile sticky CTA bar

   PERFORMANCE RULE followed throughout: animate ONLY transform and
   opacity. Those two are composited on the GPU and never trigger layout
   or paint. Animating background-position, filter, width, or top would
   force work on the main thread on every frame and tank INP on a mid-
   range Android — which is most of your traffic.
   =====================================================================
   ===================================================================== */


/* <picture> is an inline element by default. Without this the wrapped
   gallery images lose their 100% height and the tiles collapse. */
.work-item picture {
  display: block;
  width: 100%;
  height: 100%;
}


/* ---------------------------------------------------------------------
   B. MICRO-INTERACTIONS
   Deliberately restrained: colour and position change on hover, nothing
   that paints a shadow or a sweeping highlight. Glow/bloom/sheen on
   buttons is one of the fastest tells of a templated site.
   --------------------------------------------------------------------- */

/* Package cards: just the background shift already defined at the base
   rule. No lift, no shadow — the grid stays perfectly flat and aligned. */

/* Proof strip numbers: subtle count-up feel via a scale settle. */
.proof__item.is-visible .proof__value {
  animation: settle 0.7s var(--ease) both;
}
@keyframes settle {
  from { opacity: 0; transform: translateY(8px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}


/* ---------------------------------------------------------------------
   C. BEFORE / AFTER SLIDER
   Touch, mouse, and keyboard driven. Single CSS variable --pos (0-100)
   is the only thing JS touches.

   CLS protection: .ba is given a fixed aspect-ratio, so the box reserves
   its full height before either image decodes. Without this the slider
   is the worst CLS offender on a page like this.
   --------------------------------------------------------------------- */
.ba {
  position: relative;
  --pos: 50%;
  aspect-ratio: 4 / 3;
  width: 100%;
  overflow: hidden;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--bg-panel);
  touch-action: pan-y;          /* let vertical page scroll through */
  user-select: none;
  -webkit-user-select: none;
  cursor: ew-resize;
}

.ba__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

/* The "after" image is clipped to the slider position. clip-path on a
   pseudo-free element is GPU-composited in every current browser. */
.ba__img--after {
  clip-path: inset(0 0 0 var(--pos));
}

.ba__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--pos);
  width: 2px;
  margin-left: -1px;
  background: rgba(255, 255, 255, 0.9);
  pointer-events: none;
}

.ba__grip {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid rgba(255, 255, 255, 0.92);
  box-shadow: 0 4px 20px -4px rgba(0, 0, 0, 0.7);
  display: grid;
  place-content: center;
  color: #fff;
  font-size: 0.85rem;
  letter-spacing: -0.1em;
  transition: transform 0.18s var(--ease);
}
.ba:hover .ba__grip { transform: translate(-50%, -50%) scale(1.08); }
.ba:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.ba:focus-visible .ba__grip { transform: translate(-50%, -50%) scale(1.12); }

.ba__tag {
  position: absolute;
  bottom: 12px;
  font-family: var(--font-display);
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text);
  background: rgba(10, 10, 11, 0.88);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 5px 11px;
  pointer-events: none;
}
.ba__tag--before { left: 12px; }
.ba__tag--after  { right: 12px; }

.ba-wrap { max-width: 780px; margin-inline: auto; }
.ba-caption {
  margin-top: 14px;
  font-size: 0.86rem;
  color: var(--text-3);
  text-align: center;
}


/* ---------------------------------------------------------------------
   D. MOBILE STICKY CTA BAR
   Hidden at the top of the page, slides up once the hero is scrolled
   past, hides again over the closing CTA so it never covers the real
   Book button.

   No CLS: position:fixed is out of flow. The body gets bottom padding
   at first paint (not on scroll), so nothing shifts later.
   --------------------------------------------------------------------- */
.mobile-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 900;
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  gap: 10px;
  padding: 10px 14px;
  /* iOS home-indicator inset. Without this the bar sits under the swipe
     bar on every iPhone since the X. */
  padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--bg-raised);
  border-top: 1px solid var(--line);
  transform: translateY(110%);
  transition: transform 0.34s var(--ease);
  will-change: transform;
}
.mobile-bar.is-visible { transform: translateY(0); }

.mobile-bar__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  /* 48px min height — Google's tap-target threshold. Anything under 48
     is flagged in the mobile usability report. */
  min-height: 48px;
  padding-inline: 16px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-hard);
  color: var(--text);
  transition: background-color 0.2s var(--ease);
}
.mobile-bar__btn:active { background: rgba(255, 255, 255, 0.07); }

.mobile-bar__btn--book {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.mobile-bar__btn--book:active { background: var(--accent-hover); }

.mobile-bar__icon { width: 17px; height: 17px; flex: none; }

/* Desktop already has a Book button in the header — a second one would
   be noise. Hard-hide above 900px so it can never render. */
@media (min-width: 900px) {
  .mobile-bar { display: none; }
}

/* Reserve room so the bar never covers the footer's last line. */
@media (max-width: 899px) {
  body { padding-bottom: calc(70px + env(safe-area-inset-bottom, 0px)); }
}


/* ---------------------------------------------------------------------
   REDUCED MOTION
   The rule at line ~96 already clamps animation/transition duration.
   These add the pieces that rule cannot reach: infinite keyframes still
   "run" at 0.001ms and can pin a blob mid-drift, so stop them outright.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .proof__item.is-visible .proof__value { animation: none !important; }
  .mobile-bar { transition: none; }
}

