/* Generated by KELNIVRA Site Factory. Do not edit: change core/, components/ or site.json and rebuild. */

/* ==========================================================================
   KELNIVRA Site Factory — base.css
   Shared foundation for every site: neutral token defaults, reset, typography,
   layout, buttons, skip link, demo notice and accessibility utilities.

   The build places the site's own tokens (generated from site.json "theme")
   right after this file's :root block, so every value here is only a default.
   Components use role tokens (--color-accent), never raw colours.

   Origin: adapted from Apex Auto Detailing (styles.css sections 1, 3–6, 16),
   without its palette, typeface, hero values or light-sweep effect.
   ========================================================================== */


/* 1. Default tokens (overridden by the site theme)
   ========================================================================== */

:root {
  /* Colour roles: a neutral light theme so an incomplete theme still renders legibly */
  --color-bg: #ffffff;
  --color-surface: #f3f4f6;
  --color-surface-raised: #e5e7eb;
  --color-border: #d1d5db;
  --color-control-border: #6b7280;
  --color-text: #111827;
  --color-text-soft: #374151;
  --color-text-muted: #4b5563;
  --color-accent: #1d4ed8;
  --color-accent-hover: #1e40af;
  --color-on-accent: #ffffff;
  --color-focus: #1d4ed8;

  /* Typography */
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-display: var(--font-body);
  --display-weight: 700;
  --display-leading: 1.05;
  --display-tracking: -0.02em;
  --display-stretch: 100%;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* Fluid sizes: minimum at a 320px viewport, maximum 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.375rem;
  --text-menu: 1.5rem;
  --text-h2: clamp(2rem, 1.643rem + 1.786vw, 3.25rem);
  --text-display: clamp(2.75rem, 1.821rem + 4.643vw, 6rem);
  --leading-snug: 1.15;
  --leading-body: 1.6;

  /* 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: 75rem;
  --gutter: clamp(1rem, 0.714rem + 1.429vw, 2rem);
  --section-padding: clamp(4rem, 2.857rem + 5.714vw, 8rem);
  --header-height: 4.5rem;

  /* Shape, sizing, motion */
  --radius-control: 4px;
  --border-thin: 1px;
  --border-thick: 2px;
  --tap-target: 2.75rem;
  --focus-ring-width: 2px;
  --focus-ring-offset: 3px;
  --duration-fast: 150ms;

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


/* 2. Reset and base
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Keeps anchor targets from hiding under a sticky header */
  scroll-padding-top: calc(var(--header-height) + var(--border-thin));
}

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

h1,
h2,
h3,
p,
ul,
ol,
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);
}


/* 3. Typography
   ========================================================================== */

/* Very long words break only when they cannot fit (large browser font sizes on
   narrow screens). "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;
}

.display-title,
.section-title {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-stretch: var(--display-stretch);
  letter-spacing: var(--display-tracking);
}

.display-title {
  font-size: var(--text-display);
  line-height: var(--display-leading);
}

.section-title {
  font-size: var(--text-h2);
  line-height: calc(var(--display-leading) + 0.05);
}

/* Short line above a title */
.eyebrow {
  margin-bottom: var(--space-4);
  color: var(--color-accent);
  font-size: var(--text-nav);
  font-weight: var(--weight-semibold);
}

/* Not-found page (404.html), generated for every site */
.not-found__text {
  max-width: 32rem;
  margin-block: var(--space-6) var(--space-8);
  color: var(--color-text-muted);
}


/* 4. 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);
}


/* 5. Shared components: buttons, skip link, demo notice
   ========================================================================== */

/* The transparent border keeps a visible edge in forced-colours 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;
}

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

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

/* A ring in the accent colour could disappear against the accent 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-control-border);
  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--compact {
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-nav);
}

/* 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);
}

/* Demo notice for fictional or preview sites, 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);
}


/* 6. 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 visitor has not asked to reduce it.
   Components put their transitions and animations inside this same query. */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  .button {
    transition:
      background-color var(--duration-fast) ease,
      border-color var(--duration-fast) ease;
  }
}


/* Site theme (from site.json) */

@font-face {
  font-family: "Bricolage Grotesque";
  src: url("../assets/fonts/bricolage-grotesque-latin-wght-normal.woff2") format("woff2");
  font-weight: 200 800;
  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;
}

:root {
  color-scheme: light;
  --color-bg: #f7f8fc;
  --color-surface: #e9edf8;
  --color-surface-raised: #dbe1f3;
  --color-border: #cfd6ea;
  --color-control-border: #5f6b8a;
  --color-text: #111a3a;
  --color-text-soft: #28345a;
  --color-text-muted: #475274;
  --color-accent: #4338ca;
  --color-accent-hover: #3730a3;
  --color-on-accent: #ffffff;
  --color-focus: #4338ca;
  --color-error: #b42318;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-display: "Bricolage Grotesque", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --display-weight: 700;
  --display-leading: 0.98;
  --display-tracking: -0.035em;
  --display-stretch: 100%;
  --radius-control: 0.75rem;
  --container-max: 76rem;
  --radius-media: 1.25rem;
}

/* Shared: section */
/* Shared section styles: header (title + introduction) and checklist.
   Included once when any Delivery 2 content section is on the page.
   Origin: Apex styles.css sections 5 and 6 (.section-header, .checklist).
   ========================================================================== */

.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__text {
  max-width: 40rem;
}

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

/* Checklist: included items, each marked with a check drawn in CSS (no icon files) */
.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);
}


/* Component: header */
/* 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 (header.js only flips it).

   58rem is replaced at build time with site.json header.breakpoint
   (default 60rem). The same value reaches header.js through the button's
   data-desktop-query attribute, so CSS and JavaScript cannot drift apart.
   Origin: Apex styles.css section 7, without its logo and type settings.
   ========================================================================== */

.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);
}

.site-header--static {
  position: relative;
}

/* flex-wrap: with a very large browser font size the toggle (or the desktop
   links) moves to a second row instead of pushing the page sideways. */
.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);
}

/* flex-wrap and overflow-wrap: with a very large text size on a narrow screen
   the descriptor moves under the name, and a long name may break, instead of
   pushing the page sideways. At normal sizes nothing wraps. */
.brand {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-2);
  min-width: 0;
  min-height: var(--tap-target);
  color: var(--color-text);
  text-decoration: none;
}

/* The logo is inlined, so it can use currentColor and the accent token. */
.brand__mark {
  flex: none;
  width: auto;
  height: 1.75rem;
  color: var(--color-accent);
}

.brand__name {
  min-width: 0;
  overflow-wrap: anywhere;
  font-family: var(--font-display);
  font-size: var(--text-brand);
  font-weight: var(--display-weight);
  font-stretch: var(--display-stretch);
  line-height: 1;
}

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

/* On very narrow screens (or 400% zoom) only the name stays visible, so the
   brand and the menu button fit on one row. The accessible name is unchanged:
   in the header it comes from a .visually-hidden copy. */
@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-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
   header.js while the menu is open (it changes as anything above the header,
   such as the demo notice, scrolls away). The fallback assumes the header is
   at the top. overscroll-behavior keeps panel scrolling 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-family: var(--font-display);
  font-size: var(--text-menu);
  font-weight: var(--display-weight);
  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;
  }
}

@media (min-width: 58rem) {
  .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-family: var(--font-body);
    font-size: var(--text-nav);
    font-weight: var(--weight-medium);
  }
}


/* Component: hero */
/* Hero
   Shared parts first, then the two layouts. Photo-specific values (focal
   point, scrim strength, minimum height) come from site.json and are written
   as per-instance rules by the build; nothing here assumes a particular photo.
   Origin: Apex styles.css section 8, keeping only the general mechanisms
   (media layer behind the text, scrim, art direction, button row).
   ========================================================================== */

.hero {
  --hero-scrim: 85%;
  --hero-min-height: clamp(32rem, 85svh, 52rem);
}

.hero__title {
  max-width: 18ch;
  margin-bottom: var(--space-6);
}

.hero__lead {
  max-width: 34rem;
  margin-bottom: var(--space-8);
  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);
  }
}

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


/* Split: text and image side by side from 52rem, stacked below it.
   ========================================================================== */

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

.hero--split .hero__inner {
  display: grid;
  gap: var(--space-10);
  align-items: center;
}

.hero--split .hero__media {
  overflow: hidden;
  border-radius: var(--radius-media, 0);
}

.hero--split .hero__image {
  height: auto;
}

@media (min-width: 52rem) {
  .hero--split .hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-12);
  }

  .hero--text-only .hero__inner {
    grid-template-columns: minmax(0, 1fr);
  }
}


/* Overlay: the image fills the hero behind the text. The scrim mixes the
   theme's background colour into the photo, strongest under the text.
   Re-measure the text contrast over the real photo whenever the photo,
   --hero-scrim or the colours change (see TESTING.md).
   ========================================================================== */

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

.hero--overlay .hero__media {
  position: absolute;
  inset: 0;
  z-index: -1;
}

.hero--overlay .hero__media picture {
  height: 100%;
}

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

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

/* Windows high contrast and similar modes: drop the decorative scrim */
@media (forced-colors: active) {
  .hero--overlay .hero__media::after {
    display: none;
  }
}


/* Component: services */
/* Services
   auto-fit columns: one, two, three or more services fill the row without
   empty slots or fixed counts. The featured service always takes a full row.
   Origin: Apex styles.css section 9, generalised.
   ========================================================================== */

/* Card image proportion; site.json "imageAspect" overrides it per section */
.services {
  --service-image-aspect: 4 / 3;
}

.services__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
  gap: var(--space-12) var(--space-8);
  padding: 0;
  list-style: none;
}

.service__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  height: 100%;
}

.service__media {
  overflow: hidden;
  border-radius: var(--radius-media, 0);
}

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

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

.service__title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.4rem + 0.5vw, 1.875rem);
  font-weight: var(--display-weight);
  line-height: var(--leading-snug);
}

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

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

/* The button sits at the bottom of the card, so buttons line up across a row */
.service__action {
  margin-top: auto;
}

/* Featured service: full row, set apart by an accent rule and the surface colour */
.service--featured {
  grid-column: 1 / -1;
}

.service--featured .service__card {
  gap: 0;
  border-top: var(--border-thick) solid var(--color-accent);
  background-color: var(--color-surface);
}

.section--surface .service--featured .service__card {
  background-color: var(--color-bg);
}

.service--featured .service__media {
  border-radius: 0;
}

.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-h2);
  letter-spacing: var(--display-tracking);
}

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

  .service--featured .service__media {
    grid-column: 2;
    grid-row: 1;
  }

  .service--featured .service__image {
    height: 100%;
    aspect-ratio: auto;
  }

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


/* Component: benefits */
/* Benefits
   Origin: Apex styles.css section 10; columns now follow the number of items.
   ========================================================================== */

.benefits__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: var(--space-10) var(--space-8);
  padding: 0;
  list-style: none;
}

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

.benefit__icon {
  width: 2.25rem;
  height: 2.25rem;
  margin-bottom: var(--space-5);
  color: var(--color-accent);
}

.benefit__title {
  font-size: clamp(1.1875rem, 1.15rem + 0.18vw, 1.3125rem);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
}

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


/* Component: process */
/* Process
   The step numbers come from a CSS counter, so the markup stays a plain <ol>.
   Origin: Apex styles.css section 12.
   ========================================================================== */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: var(--space-10) var(--space-8);
  padding: 0;
  list-style: none;
  counter-reset: step;
}

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

/* Decorative: the list already conveys the order to assistive technology */
.step::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  margin-bottom: var(--space-5);
  color: var(--color-accent);
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 2.3rem + 2.2vw, 4.5rem);
  font-weight: var(--display-weight);
  line-height: 1;
}

.step__title {
  font-size: clamp(1.1875rem, 1.15rem + 0.18vw, 1.3125rem);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
}

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


/* Component: gallery */
/* Gallery and photo viewer
   Origin: Apex styles.css section 11, adapted: thumbnails keep one proportion
   (site.json "imageAspect"), captions are visible under each photo, the
   featured photo takes a full row, and the enlarge icon is inline SVG that
   follows the theme instead of a file with a fixed colour.
   ========================================================================== */

/* Reserves the scrollbar's space so hiding it (open viewer) causes no shift.
   Here rather than in base.css so pages without a gallery are unchanged. */
html {
  scrollbar-gutter: stable;
}

.gallery {
  --gallery-image-aspect: 4 / 3;
}

.gallery__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(16rem, 100%), 1fr));
  gap: var(--space-8) var(--space-4);
  padding: 0;
  list-style: none;
}

.gallery__item--featured {
  grid-column: 1 / -1;
}

.gallery__figure {
  display: grid;
  gap: var(--space-3);
}

.gallery__link {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-media, 0);
  cursor: zoom-in;
}

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

.gallery__item--featured .gallery__image {
  aspect-ratio: 21 / 9;
}

@media (max-width: 40rem) {
  .gallery__item--featured .gallery__image {
    aspect-ratio: var(--gallery-image-aspect);
  }
}

/* Enlarge icon: tells pointer and touch users the photo opens larger */
.gallery__zoom {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  display: grid;
  place-items: center;
  width: var(--space-8);
  height: var(--space-8);
  border-radius: var(--radius-control);
  background-color: color-mix(in srgb, var(--color-bg) 85%, transparent);
  color: var(--color-text);
}

.gallery__zoom svg {
  width: var(--space-4);
  height: var(--space-4);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}

.gallery__caption {
  display: grid;
  gap: var(--space-1);
  font-size: var(--text-sm);
  line-height: 1.5;
}

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

.gallery__credit {
  color: var(--color-text-muted);
}

/* Photo viewer, a native modal <dialog> */
.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-text) 80%, transparent);
}

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

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

.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__image[hidden],
.lightbox__error[hidden] {
  display: none;
}

.lightbox__error {
  padding: var(--space-8) var(--space-4);
  border: var(--border-thin) dashed var(--color-control-border);
  color: var(--color-text);
  text-align: center;
}

.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 */
html:has(.lightbox[open]) {
  overflow: hidden;
}


/* Component: faq */
/* FAQ
   Native <details>/<summary>. The plus/minus sign is two CSS gradients; the
   vertical bar collapses to zero height when the item is open.
   Origin: Apex styles.css section 13.
   ========================================================================== */

.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: clamp(1.0625rem, 1.009rem + 0.268vw, 1.25rem);
  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 {
  display: grid;
  gap: var(--space-4);
  max-width: 42rem;
  padding-bottom: var(--space-7);
  color: var(--color-text-muted);
}

/* High contrast mode drops background images, so draw the sign as text instead */
@media (forced-colors: active) {
  .faq__question::after {
    content: "+" / "";
    background: none;
    text-align: center;
  }

  .faq__item[open] > .faq__question::after {
    content: "−" / "";
  }
}


/* Component: contact-form */
/* Contact form and status notices
   Origin: Apex styles.css sections 6 (.notice) and 14 (quote form).
   Requires the theme colour "error" (checked by the build).
   ========================================================================== */

/* minmax(0, 1fr): long option texts or a date picker must not widen the page */
.contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-10);
}

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

.contact__text {
  max-width: 26rem;
  margin-top: var(--space-6);
  color: var(--color-text-muted);
}

.contact__intro .notice {
  max-width: 26rem;
  margin-top: var(--space-8);
}

/* 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: min(var(--radius-control), 0.75rem);
  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--quiet {
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

.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--quiet .notice__icon {
  stroke: currentColor;
}

.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);
}

/* Form layout: one column, two from 40rem */
.contact-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
}

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

.contact-form__summary,
.contact-form__actions,
.contact-form__status,
.contact-form__failure,
.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-width: 0;
  min-height: 3.25rem;
  padding: var(--space-3) var(--space-4);
  border: var(--border-thin) solid var(--color-control-border);
  border-radius: min(var(--radius-control), 0.75rem);
  background-color: var(--color-bg);
  color: var(--color-text);
  font: inherit;
}

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

.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-coloured 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);
  font-weight: var(--weight-medium);
}

.field__error:empty {
  display: none;
}

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

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

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

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

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

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

/* Spam trap: off screen and out of the accessibility tree (aria-hidden in the HTML) */
.contact-form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}


/* Component: footer */
/* Footer
   Origin: Apex styles.css section 15, unchanged in structure.
   ========================================================================== */

.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;
  /* min(): a column never asks for more than the available width (large text sizes) */
  grid-template-columns: repeat(auto-fit, minmax(min(10rem, 100%), 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;
  overflow-wrap: anywhere;
}

/* Block padding gives each link a target 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);
}


/* Per-section settings (from site.json) */
#welcome { --hero-scrim: 70%; --hero-min-height: clamp(34rem, 86svh, 50rem); }
#welcome .hero__image { object-position: 100% 50%; }
@media (orientation: portrait) {
  #welcome .hero__media { bottom: auto; aspect-ratio: 1200 / 1600; }
  #welcome .hero__content { padding-top: max(var(--space-32), 64vw); }
}
@media (orientation: landscape) {
  #welcome .hero__title, #welcome .hero__lead { max-width: 62%; }
}
@media (orientation: portrait) {
  #welcome .hero__image { object-position: 50% 0%; }
}
