/* ==========================================================================
   Apex Auto Detailing — styles.css

   Contents
   1. Design tokens
   2. Fonts
   3. Reset and base
   4. Typography
   5. Layout
   6. Components: buttons, checklist, notice, skip link, demo notice
   7. Header and navigation
   8. Hero
   9. Services
   10. Benefits
   11. Gallery and photo viewer
   12. Process
   13. FAQ
   14. Quote form
   15. Footer
   16. Accessibility: visually hidden text, reduced motion, forced colors

   Responsive approach: mobile first. Media queries sit next to the
   component they change, so each component can be read in one place.
   Breakpoints (custom properties cannot be used inside media queries):
     30rem (480px)  hero buttons switch from stacked to side by side
     40rem (640px)  benefits list and form fields in two columns
     48rem (768px)  Interior and Exterior services side by side, process steps
                    in three columns, footer about text beside the link columns
     60rem (960px)  desktop navigation (must match DESKTOP_NAV_QUERY in
                    js/main.js), Full Detail layout, 4-column benefits and gallery,
                    quote introduction beside the form
   ========================================================================== */


/* 1. Design tokens
   ========================================================================== */

:root {
  /* Palette */
  --color-graphite: #1c1e21;
  --color-carbon: #24272b;
  --color-carbon-raised: #2c3035;
  --color-steel: #383c42;
  --color-field-edge: #7a808a;
  --color-mist: #a9aeb5;
  --color-silver: #c9cdd2;
  --color-titanium: #dadde1;
  --color-chalk: #f4f5f6;
  --color-white: #fff;
  --color-black: #000;
  --color-signal: #f2792b;
  --color-signal-hover: #ff8f45;
  --color-coral: #ff9b8f;

  /* Roles: components use these, not the palette directly */
  --color-bg: var(--color-graphite);
  --color-surface: var(--color-carbon);
  --color-surface-raised: var(--color-carbon-raised);
  --color-border: var(--color-steel);
  --color-control-border: var(--color-field-edge);
  --color-text: var(--color-chalk);
  --color-text-soft: var(--color-silver);
  --color-text-muted: var(--color-mist);
  --color-accent: var(--color-signal);
  --color-accent-hover: var(--color-signal-hover);
  --color-on-accent: var(--color-graphite);
  --color-focus: var(--color-signal);
  --color-error: var(--color-coral);
  /* Background of the hero photo files (assets/images/hero-*): pure black */
  --color-photo-backdrop: var(--color-black);

  /* Typography */
  --font-sans: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --stretch-normal: 100%;
  --stretch-display: 125%;
  --stretch-menu: 120%;
  --stretch-heading: 112%;
  --weight-light: 300;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --weight-heavy: 800;

  /* Fluid sizes: min at 320px viewport, max at 1440px */
  --text-xs: 0.8125rem;
  --text-sm: 0.875rem;
  --text-nav: 0.9375rem;
  --text-base: clamp(1rem, 0.982rem + 0.089vw, 1.0625rem);
  --text-lead: clamp(1.0625rem, 0.991rem + 0.357vw, 1.3125rem);
  --text-brand: 1.5rem;
  --text-menu: 1.75rem;
  --text-h2: clamp(2.375rem, 1.982rem + 1.964vw, 3.75rem);
  --text-h3: clamp(1.6875rem, 1.5625rem + 0.625vw, 2.125rem);
  --text-h3-featured: clamp(2rem, 1.714rem + 1.429vw, 3rem);
  --text-h4: clamp(1.25rem, 1.214rem + 0.179vw, 1.375rem);
  --text-faq: clamp(1.0625rem, 1.009rem + 0.268vw, 1.25rem);
  --text-step: clamp(3.25rem, 2.607rem + 3.214vw, 5.5rem);
  --text-display: clamp(3.25rem, 1.821rem + 7.143vw, 8.25rem);

  /* Below ~0.95 the descender of "g" collides with the next line's "f" */
  --leading-display: 0.98;
  --leading-heading: 1;
  --leading-snug: 1.15;
  --leading-body: 1.6;
  --tracking-display: -0.025em;
  --tracking-heading: -0.02em;

  /* Spacing scale (8px rhythm, 4px half-steps) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-7: 1.75rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-24: 6rem;
  --space-32: 8rem;

  /* Layout */
  --container-max: 77.5rem;
  --gutter: clamp(1rem, 0.714rem + 1.429vw, 2rem);
  --section-padding: clamp(4rem, 2.857rem + 5.714vw, 8rem);
  --header-height: 4.5rem;
  --gallery-row: clamp(9rem, 7.91rem + 8.57vw, 15.625rem);

  /* Shape, sizing, motion */
  --radius-control: 2px;
  --border-thin: 1px;
  --border-thick: 2px;
  --tap-target: 2.75rem;
  --focus-ring-width: 2px;
  --focus-ring-offset: 3px;
  --duration-fast: 150ms;
  --duration-sweep: 1400ms;
  --delay-sweep: 300ms;
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* Elevation order */
  --z-header: 10;
  --z-skip-link: 100;
}


/* 2. Fonts
   Archivo (SIL OFL 1.1), instanced to wght 300–800 and wdth 100–125,
   Latin subset. Source and license: CREDITS.md, assets/fonts/OFL.txt.
   ========================================================================== */

@font-face {
  font-family: "Archivo";
  src: url("../assets/fonts/archivo-variable-latin.woff2") format("woff2");
  font-weight: 300 800;
  font-stretch: 100% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* 3. Reset and base
   ========================================================================== */

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

html {
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Keeps anchor targets from hiding under the sticky header */
  scroll-padding-top: calc(var(--header-height) + var(--border-thin));
  /* Reserves the scrollbar's space so hiding it (open photo viewer) causes no shift */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
p,
ul,
figure {
  margin: 0;
}

img,
picture,
svg {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
}

button {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus);
  outline-offset: var(--focus-ring-offset);
}


/* 4. Typography
   ========================================================================== */

/* Very long words break only if they cannot fit on a line (large browser font
   sizes on narrow screens); at normal sizes this changes nothing. "anywhere"
   rather than "break-word" because only "anywhere" also lowers the heading's
   minimum width, which is what flex and grid containers size themselves by. */
h1,
h2,
h3 {
  overflow-wrap: anywhere;
}

h1,
h2 {
  text-wrap: balance;
}

.section-title {
  font-size: var(--text-h2);
  font-weight: var(--weight-heavy);
  font-stretch: var(--stretch-display);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
}


/* 5. Layout
   ========================================================================== */

.container {
  width: min(100% - 2 * var(--gutter), var(--container-max));
  margin-inline: auto;
}

.section {
  padding-block: var(--section-padding);
}

.section--surface {
  background-color: var(--color-surface);
}

/* Follows a section with the same background: no second top padding */
.section--continued {
  padding-top: 0;
}

.section--divided {
  border-top: var(--border-thin) solid var(--color-border);
}

/* Section title with a short introduction beside it (below it on narrow screens) */
.section-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6) var(--space-8);
  margin-bottom: clamp(var(--space-10), 1.5rem + 3vw, var(--space-16));
}

.section-header .section-title {
  max-width: 40rem;
}

.section-header__intro {
  max-width: 28rem;
  color: var(--color-text-muted);
}

.section-header__intro--small {
  font-size: var(--text-nav);
}


/* 6. Components
   ========================================================================== */

/* Buttons. The transparent border keeps a visible edge in forced-colors mode. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--tap-target);
  padding: var(--space-4) var(--space-7);
  border: var(--border-thin) solid transparent;
  border-radius: var(--radius-control);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  text-align: center;
  text-decoration: none;
  transition:
    background-color var(--duration-fast) ease,
    border-color var(--duration-fast) ease;
}

.button--primary {
  background-color: var(--color-accent);
  color: var(--color-on-accent);
}

.button--primary:hover {
  background-color: var(--color-accent-hover);
}

/* An orange ring would disappear against the orange button */
.button--primary:focus-visible {
  outline-color: var(--color-text);
}

/* Explicit transparent background: on a <button> the browser default would show */
.button--secondary {
  border-color: var(--color-text-muted);
  background-color: transparent;
  color: var(--color-text);
  font-weight: var(--weight-semibold);
}

.button--secondary:hover {
  border-color: var(--color-text);
  background-color: var(--color-surface-raised);
}

.button--primary:disabled {
  background-color: var(--color-surface-raised);
  color: var(--color-text-muted);
  cursor: not-allowed;
}

.button--compact {
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-nav);
}

.button__icon {
  flex: none;
  width: 0.875rem;
  height: 0.875rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
}

/* Checklist: list of included items, each marked with a check drawn in CSS */
.checklist {
  display: grid;
  gap: var(--space-3);
  padding: 0;
  list-style: none;
}

.checklist li {
  position: relative;
  padding-left: var(--space-7);
}

.checklist li::before {
  content: "";
  position: absolute;
  top: 0.45em;
  left: var(--space-1);
  width: 0.75rem;
  height: 0.375rem;
  border-bottom: var(--border-thick) solid var(--color-accent);
  border-left: var(--border-thick) solid var(--color-accent);
  transform: rotate(-45deg);
}

/* Skip link: off screen until it receives keyboard focus */
.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--gutter);
  z-index: var(--z-skip-link);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-control);
  background-color: var(--color-accent);
  color: var(--color-on-accent);
  font-weight: var(--weight-bold);
  text-decoration: none;
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
  outline-color: var(--color-text);
}

/* Fictional business notice, always visible above the header */
.demo-notice {
  padding: var(--space-2) var(--gutter);
  border-bottom: var(--border-thin) solid var(--color-border);
  background-color: var(--color-surface);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: 1.5;
  text-align: center;
}

.demo-notice strong {
  color: var(--color-text);
  font-weight: var(--weight-semibold);
}

/* Notice: a bordered message box. Default border is the accent (information);
   --error is for validation problems. An empty notice is not shown. */
.notice {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-5);
  border: var(--border-thin) solid var(--color-accent);
  border-radius: var(--radius-control);
  font-size: var(--text-nav);
  line-height: 1.55;
}

.notice:empty {
  display: none;
}

/* .notice sets display, which would otherwise override the hidden attribute */
.notice[hidden] {
  display: none;
}

.notice--error {
  border-color: var(--color-error);
}

.notice__icon {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.15em;
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 1.7;
}

.notice--error .notice__icon {
  stroke: var(--color-error);
}

.notice__title {
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
}

/* The gap keeps consecutive links far enough apart to be easy targets (WCAG 2.5.8) */
.notice__list {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-left: var(--space-5);
}

.notice__list a {
  color: var(--color-text);
}


/* 7. Header and navigation
   Mobile: a disclosure button shows the navigation as a panel below the bar.
   The panel's visibility follows the button's aria-expanded value, so the
   ARIA state is the single source of truth (js/main.js only flips it).
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  border-bottom: var(--border-thin) solid var(--color-border);
  background-color: var(--color-bg);
}

/* The gap is only a minimum: space-between spreads the items on wider
   screens. At 320px the brand and the toggle leave about 4px to spare,
   so check that width after changing either of them.
   flex-wrap: with a large browser font size the toggle (or the desktop links)
   moves to a second row instead of pushing the page sideways. At normal sizes
   everything fits on one row and the padding is absorbed by the min-height. */
.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  min-height: var(--header-height);
  padding-block: var(--space-3);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap-target);
  color: var(--color-text);
  text-decoration: none;
}

.brand__mark {
  flex: none;
  width: 1.875rem;
  height: 1.25rem;
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 3.5;
}

.brand__name {
  font-size: var(--text-brand);
  font-weight: var(--weight-heavy);
  font-stretch: var(--stretch-display);
  line-height: 1;
  letter-spacing: -0.01em;
}

.brand__descriptor {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
}

/* Below 22rem (352px at the default font size) the header brand and the menu
   button do not fit on one row once a desktop-style scrollbar takes its 15px,
   e.g. at 400% browser zoom, so the visible "Auto Detailing" is dropped there.
   The link's accessible name does not change: in the header it comes from a
   .visually-hidden copy, and the visible descriptor is aria-hidden. The demo
   notice above the header still names the business in full. */
@media (max-width: 22rem) {
  .site-header .brand__descriptor {
    display: none;
  }
}

.menu-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--tap-target);
  padding: 0 var(--space-3);
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius-control);
  background-color: transparent;
  font-size: var(--text-nav);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}

.menu-toggle__icon {
  flex: none;
  width: 1.125rem;
  height: 0.875rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
}

/* Icon and visible label follow aria-expanded: "Menu" when closed,
   "Close" (accessible name "Close menu") when open. */
.menu-toggle__icon--close,
.menu-toggle__label--open,
.menu-toggle[aria-expanded="true"] .menu-toggle__icon--open,
.menu-toggle[aria-expanded="true"] .menu-toggle__label--closed {
  display: none;
}

.menu-toggle[aria-expanded="true"] .menu-toggle__icon--close,
.menu-toggle[aria-expanded="true"] .menu-toggle__label--open {
  display: block;
}

/* --menu-top is the panel's distance from the top of the viewport, measured
   by js/main.js while the menu is open. It varies because the demo notice
   above the header scrolls away. The fallback assumes the header is at the top.
   overscroll-behavior stops scrolling inside the panel from moving the page. */
.site-nav {
  display: none;
  position: absolute;
  top: 100%;
  inset-inline: 0;
  max-height: calc(100svh - var(--menu-top, var(--header-height)));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-4) var(--gutter) var(--space-8);
  border-bottom: var(--border-thin) solid var(--color-border);
  background-color: var(--color-bg);
}

.menu-toggle[aria-expanded="true"] + .site-nav {
  display: block;
}

.site-nav__list {
  display: flex;
  flex-direction: column;
  padding: 0;
  list-style: none;
}

.site-nav__item {
  border-bottom: var(--border-thin) solid var(--color-border);
}

.site-nav__item--cta {
  margin-top: var(--space-8);
  border-bottom: 0;
}

.site-nav__item--cta .button {
  width: 100%;
}

.site-nav__link {
  display: block;
  padding-block: var(--space-4);
  font-size: var(--text-menu);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-menu);
  line-height: var(--leading-snug);
  text-decoration: none;
}

.site-nav__link:hover {
  color: var(--color-accent);
}

/* Without JavaScript the toggle cannot work, so show the links inline instead */
@media (scripting: none) {
  .site-header {
    position: static;
  }

  .menu-toggle {
    display: none;
  }

  .site-nav {
    display: block;
    position: static;
    width: 100%;
    max-height: none;
    overflow: visible;
    padding-inline: 0;
    border-bottom: 0;
  }
}

/* Desktop navigation breakpoint. Keep in sync with DESKTOP_NAV_QUERY in js/main.js:
   if they differ, the script resets the menu at the wrong width. */
@media (min-width: 60rem) {
  .menu-toggle {
    display: none;
  }

  .site-nav {
    display: block;
    position: static;
    max-height: none;
    overflow: visible;
    padding: 0;
    border-bottom: 0;
    background-color: transparent;
  }

  .site-nav__list {
    flex-direction: row;
    align-items: center;
    gap: var(--space-8);
  }

  .site-nav__item {
    border-bottom: 0;
  }

  .site-nav__item--cta {
    margin-top: 0;
  }

  .site-nav__link {
    padding-block: var(--space-3);
    font-size: var(--text-nav);
    font-weight: var(--weight-medium);
    font-stretch: var(--stretch-normal);
  }
}


/* 8. Hero
   The media layer sits behind the content. A two-direction scrim keeps the
   text readable over the photo; contrast is measured over the real photo
   (see README, "Tested"). Re-measure it if the photo or the scrim changes.
   ========================================================================== */

.hero {
  /* Also the photo layer's height in landscape (see the end of this section) */
  --hero-height: clamp(36rem, 88svh, 54rem);

  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  min-height: var(--hero-height);
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--color-photo-backdrop);
}

.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, transparent 15%, color-mix(in srgb, var(--color-bg) 90%, transparent) 80%, var(--color-bg) 100%),
    linear-gradient(90deg, color-mix(in srgb, var(--color-bg) 65%, transparent) 0%, transparent 70%);
}

/* The composition is baked into two files (see the <picture> in index.html):
   a wide one with the car at the upper right and a tall one for portrait
   screens with the car at the top, both clear of the headline. The image is
   anchored to the top (raised slightly in landscape, see the end of this
   section). */
.hero__media picture {
  height: 100%;
}

.hero__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0%;
}

.hero__content {
  padding-block: var(--space-32) clamp(var(--space-10), 1.5rem + 4vw, var(--space-24));
}

/* Portrait: the image scales with the width only (contain), so the car's
   position is predictable, and the text starts below it. In the tall image the
   car spans 88% of the width and the car with its lit floor ends at 46% of the
   image width; the rest of the image is the same black as
   --color-photo-backdrop, so no edge shows. */
@media (orientation: portrait) {
  .hero__image {
    object-fit: contain;
  }

  .hero__content {
    padding-top: max(var(--space-32), calc(46vw + var(--space-8)));
  }
}

.hero__title {
  max-width: 62rem;
  margin-bottom: var(--space-7);
  color: var(--color-text);
  font-size: var(--text-display);
  font-weight: var(--weight-heavy);
  font-stretch: var(--stretch-display);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
}

/* Inspection-light sweep: a bright band passes through the letters once,
   leaving them lit (titanium) behind it and dim (mist) ahead of it.
   Applied only where background-clip: text works, so other browsers keep
   the solid color above. The resting position (0%) is the fully lit fill,
   which is also what reduced-motion visitors see. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .hero__title {
    background-image: linear-gradient(
      100deg,
      var(--color-titanium) 0% 42%,
      var(--color-white) 50%,
      var(--color-text-muted) 58% 100%
    );
    background-size: 300% 100%;
    background-position: 0% 0%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.hero__lead {
  max-width: 34rem;
  margin-bottom: var(--space-10);
  color: var(--color-text-soft);
  font-size: var(--text-lead);
  line-height: 1.5;
}

.hero__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

@media (min-width: 30rem) {
  .hero__actions {
    flex-flow: row wrap;
    gap: var(--space-4);
  }
}

/* Landscape: keeps the headline clear of the car and, on 1280×720 and
   1366×768 screens, the buttons inside the first screen. Placed after the
   hero rules above because it overrides some of them.
   - The photo layer keeps the hero's minimum height even when the text makes
     the hero taller, so the photo's scale (and the car's position) never
     depends on the text. Below it the page background continues the scrim's
     last color.
   - The photo is raised by 1.8vw, and the gaps between the text and the
     bottom of the hero are tighter than in portrait.
   - The text never starts above the car's lit floor. The floor ends at 16.5%
     of the wide image's width, or 33% of its height when the image is scaled
     to the hero's height (object-fit: cover picks the larger scale), minus
     the 1.8vw raise. On short browser windows this moves the buttons below
     the first screen (see README, Known limitations).
   Re-measure contrast and overlap if any of these values or the photo change. */
@media (orientation: landscape) {
  .hero__media {
    bottom: auto;
    height: var(--hero-height);
  }

  .hero__image {
    object-position: 50% -1.8vw;
  }

  .hero__content {
    padding-block:
      max(var(--space-32), calc(14.7vw + var(--space-2)), calc(var(--hero-height) * 0.33 - 1.8vw + var(--space-2)))
      var(--space-10);
  }

  .hero__title {
    margin-bottom: var(--space-5);
  }

  .hero__lead {
    margin-bottom: var(--space-6);
  }
}


/* 9. Services
   ========================================================================== */

.services__grid {
  display: grid;
  gap: var(--space-16) var(--space-8);
}

@media (min-width: 48rem) {
  .services__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.service {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}

.service__image {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background-color: var(--color-surface);
}

.service__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.service__title {
  font-size: var(--text-h3);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-heading);
  line-height: var(--leading-snug);
}

.service__summary {
  max-width: 32.5rem;
  margin-block: var(--space-3) var(--space-6);
  color: var(--color-text-soft);
}

.service__body .checklist {
  margin-bottom: var(--space-8);
}

/* Full Detail Package: the featured service, set apart by an accent rule */
.service--featured {
  gap: 0;
  margin-top: clamp(var(--space-12), 2rem + 4vw, var(--space-24));
  border-top: var(--border-thick) solid var(--color-accent);
  background-color: var(--color-surface);
}

.service--featured .service__image {
  aspect-ratio: 16 / 10;
}

.service--featured .service__body {
  padding: clamp(var(--space-8), 1.25rem + 3vw, var(--space-16)) clamp(var(--space-6), 1rem + 2.5vw, var(--space-12));
}

.service--featured .service__title {
  font-size: var(--text-h3-featured);
  font-weight: var(--weight-heavy);
  font-stretch: var(--stretch-display);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
}

.service__eyebrow {
  margin-bottom: var(--space-4);
  color: var(--color-accent);
  font-size: var(--text-nav);
  font-weight: var(--weight-semibold);
}

@media (min-width: 60rem) {
  /* Text on the left, photo on the right; the photo fills the row height */
  .service--featured {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  }

  .service--featured .service__image {
    grid-column: 2;
    grid-row: 1;
    height: 100%;
    aspect-ratio: auto;
  }

  .service--featured .service__body {
    grid-column: 1;
    grid-row: 1;
    justify-content: center;
  }
}


/* 10. Benefits
   ========================================================================== */

.benefits__list {
  display: grid;
  gap: var(--space-10) var(--space-12);
  padding: 0;
  list-style: none;
}

@media (min-width: 40rem) {
  .benefits__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 60rem) {
  .benefits__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-8);
  }
}

.benefit {
  padding-top: var(--space-6);
  border-top: var(--border-thin) solid var(--color-border);
}

.benefit__title {
  font-size: var(--text-h4);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-heading);
  line-height: var(--leading-snug);
}

.benefit__text {
  margin-top: var(--space-3);
  color: var(--color-text-muted);
}


/* 11. Gallery and photo viewer
   ========================================================================== */

.gallery__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: var(--gallery-row);
  gap: var(--space-3);
  padding: 0;
  list-style: none;
}

@media (min-width: 60rem) {
  .gallery__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-4);
  }
}

.gallery__item--featured {
  grid-column: span 2;
  grid-row: span 2;
}

.gallery__link {
  display: block;
  position: relative;
  height: 100%;
  cursor: zoom-in;
}

/* Enlarge icon: tells pointer and touch users the photo opens larger */
.gallery__link::after {
  content: "";
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: var(--space-8);
  height: var(--space-8);
  border-radius: var(--radius-control);
  background: color-mix(in srgb, var(--color-bg) 80%, transparent) url("../assets/icons/expand.svg") center / var(--space-4) no-repeat;
}

.gallery__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background-color: var(--color-surface);
}

/* Photo viewer, a native modal <dialog>. The browser provides the modal
   behavior: focus moves inside, the page behind is inert, Escape closes it. */
.lightbox {
  width: min(100% - 2 * var(--gutter), 75rem);
  max-width: none;
  max-height: calc(100svh - 2 * var(--gutter));
  padding: 0;
  border: var(--border-thin) solid var(--color-border);
  background-color: var(--color-bg);
  color: var(--color-text);
}

.lightbox::backdrop {
  background-color: color-mix(in srgb, var(--color-bg) 92%, transparent);
}

.lightbox__bar {
  display: flex;
  justify-content: flex-end;
  padding: var(--space-3);
}

.lightbox__figure {
  display: grid;
  gap: var(--space-3);
  padding: 0 var(--space-3) var(--space-4);
}

/* 9rem leaves room for the close bar and the caption inside the dialog */
.lightbox__image {
  width: 100%;
  height: auto;
  max-height: calc(100svh - 2 * var(--gutter) - 9rem);
  object-fit: contain;
}

.lightbox__caption {
  display: grid;
  gap: var(--space-1);
}

.lightbox__description {
  color: var(--color-text-soft);
}

.lightbox__credit {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Stop the page behind the open viewer from scrolling. scrollbar-gutter
   (section 3) keeps the layout from shifting when the scrollbar is hidden. */
html:has(.lightbox[open]) {
  overflow: hidden;
}


/* 12. Process
   The step numbers come from a CSS counter, so the markup stays a plain <ol>.
   ========================================================================== */

.steps {
  display: grid;
  gap: var(--space-10);
  padding: 0;
  list-style: none;
  counter-reset: step;
}

@media (min-width: 48rem) {
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-8);
  }
}

.step {
  padding-top: var(--space-7);
  border-top: var(--border-thin) solid var(--color-border);
  counter-increment: step;
}

.step::before {
  content: counter(step);
  display: block;
  margin-bottom: var(--space-5);
  color: var(--color-accent);
  font-size: var(--text-step);
  font-weight: var(--weight-light);
  font-stretch: var(--stretch-display);
  line-height: 1;
}

.step__title {
  font-size: var(--text-h4);
  font-weight: var(--weight-bold);
  font-stretch: var(--stretch-heading);
  line-height: var(--leading-snug);
}

.step__text {
  max-width: 24rem;
  margin-top: var(--space-3);
  color: var(--color-text-muted);
}


/* 13. FAQ
   Native <details>/<summary>. The plus/minus sign is two CSS gradients; the
   vertical bar collapses to zero height when the item is open.
   ========================================================================== */

.faq {
  max-width: 52rem;
  border-top: var(--border-thin) solid var(--color-border);
}

.faq__item {
  border-bottom: var(--border-thin) solid var(--color-border);
}

.faq__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding-block: var(--space-6);
  font-size: var(--text-faq);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
  list-style: none;
  cursor: pointer;
}

.faq__question::-webkit-details-marker {
  display: none;
}

.faq__question:hover {
  color: var(--color-accent);
}

.faq__question::after {
  content: "";
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  background:
    linear-gradient(var(--color-accent), var(--color-accent)) center / 100% var(--border-thick) no-repeat,
    linear-gradient(var(--color-accent), var(--color-accent)) center / var(--border-thick) 100% no-repeat;
}

.faq__item[open] > .faq__question::after {
  background-size: 100% var(--border-thick), var(--border-thick) 0;
}

.faq__answer {
  max-width: 42rem;
  padding-bottom: var(--space-7);
  color: var(--color-text-muted);
}


/* 14. Quote form
   ========================================================================== */

.quote {
  display: grid;
  gap: var(--space-10);
}

@media (min-width: 60rem) {
  .quote {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    gap: var(--space-16);
    align-items: start;
  }
}

.quote__text {
  max-width: 26rem;
  margin-block: var(--space-6) var(--space-8);
  color: var(--color-text-muted);
}

.quote__intro .notice {
  max-width: 26rem;
}

.quote-form {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 40rem) {
  .quote-form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Full-width rows inside the two-column form */
.quote-form__summary,
.quote-form__actions,
.quote-form__status,
.field--full {
  grid-column: 1 / -1;
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--text-nav);
  font-weight: var(--weight-semibold);
}

.field__optional {
  color: var(--color-text-muted);
  font-weight: var(--weight-regular);
}

.field__control {
  width: 100%;
  min-height: 3.25rem;
  padding: var(--space-3) var(--space-4);
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: var(--radius-control);
  background-color: var(--color-bg);
  color: var(--color-text);
  font: inherit;
}

.field__control--multiline {
  min-height: 8rem;
  resize: vertical;
}

.field__control:focus-visible {
  border-color: var(--color-focus);
  outline-offset: 0;
}

/* Invalid fields get a thicker error-colored edge. The inset shadow adds the
   second pixel without changing the border width, so nothing shifts. */
.field__control[aria-invalid="true"] {
  border-color: var(--color-error);
  box-shadow: inset 0 0 0 1px var(--color-error);
}

.field__error {
  color: var(--color-error);
  font-size: var(--text-sm);
}

.field__error:empty {
  display: none;
}

.quote-form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-6);
}

.quote-form__note,
.quote-form__no-script {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* Shown only when scripts cannot run, next to the disabled submit button */
.quote-form__no-script {
  display: none;
}

@media (scripting: none) {
  .quote-form__no-script {
    display: block;
  }
}

.quote-form__status {
  border-color: var(--color-text-muted);
}


/* 15. Footer
   ========================================================================== */

.site-footer {
  padding-block: var(--space-16) var(--space-10);
  border-top: var(--border-thin) solid var(--color-border);
  font-size: var(--text-nav);
}

.site-footer__top {
  display: grid;
  gap: var(--space-12);
}

@media (min-width: 48rem) {
  .site-footer__top {
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  }
}

.site-footer__text {
  max-width: 24rem;
  margin-top: var(--space-5);
  color: var(--color-text-muted);
}

.footer-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--space-10) var(--space-8);
}

.footer-column__title {
  margin-bottom: var(--space-4);
  font-size: var(--text-nav);
  font-weight: var(--weight-bold);
}

.footer-column__list {
  display: grid;
  gap: var(--space-1);
  padding: 0;
  color: var(--color-text-soft);
  list-style: none;
}

/* Block padding gives each link a tap area of at least 24px (WCAG 2.5.8) */
.footer-column__list a,
.site-footer__link {
  display: inline-block;
  padding-block: var(--space-1);
}

.footer-column__list a {
  text-decoration: none;
}

.footer-column__list a:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

.footer-column__note {
  margin-top: var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-4) var(--space-8);
  margin-top: var(--space-12);
  padding-top: var(--space-7);
  border-top: var(--border-thin) solid var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.site-footer__link {
  color: var(--color-text-soft);
}


/* 16. Accessibility
   ========================================================================== */

/* Text for screen readers only (it stays in the accessible name) */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Motion is opt-in: it only runs when the user has not asked to reduce it */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  @supports (background-clip: text) or (-webkit-background-clip: text) {
    .hero__title {
      animation: light-sweep var(--duration-sweep) var(--ease-in-out) var(--delay-sweep) both;
    }
  }
}

@keyframes light-sweep {
  from {
    background-position: 100% 0%;
  }

  to {
    background-position: 0% 0%;
  }
}

/* Windows high contrast and similar modes: drop decorative effects, keep text */
@media (forced-colors: active) {
  .hero__title {
    background: none;
    color: CanvasText;
  }

  .hero__media::after {
    display: none;
  }
}
