@charset "utf-8";
/* ==========================================================================
   Design system.

   Governing constraint: the product in every photograph on this site is warm
   brown oak, hue ~20-45deg. Any UI colour in that band competes with the
   photography and makes it look muddy -- which is exactly why almost every
   cheap flooring site, with its tan/terracotta/ochre accent, looks cheap.
   So the accent here is a deep eucalypt green, a hue maximally distant from
   oak, and it passes AA comfortably (9.0:1 on the page ground) where a warm
   tan like #A8834B would have failed at 3.2:1.

   Everything else follows from three rules:
     * colour is delegated to the photography; the chrome is achromatic
     * one display face, one text face, two weights total
     * line-height 1.0-1.15 on display type, tracking inverted (negative on
       large type, strongly positive on small type)
   ========================================================================== */

:root {
  /* ---- grounds. Never pure #fff: it makes oak read yellow and dirty ---- */
  --paper:        #F7F5F2;
  --paper-alt:    #EFEBE5;
  --paper-deep:   #E4DED5;
  --ground-ink:   #191817;

  /* ---- ink ---- */
  --ink:          #1A1A1A;   /* 16.0:1 on --paper  AAA */
  --ink-70:       #4A4844;
  --ink-50:       #6B6862;   /*  5.1:1 on --paper  AA  */
  --ink-30:       #9A968F;   /* decorative only        */
  --rule:         #DED9D2;
  --rule-strong:  #C8C2B9;

  /* ---- the one accent ---- */
  --accent:       #1F4B3F;   /*  9.0:1 on --paper; white on it 9.8:1 */
  --accent-hover: #17392F;
  --accent-wash:  #E9EFEB;

  /* ---- on dark ---- */
  --on-dark:      #F2EFEA;
  --on-dark-50:   #A5A099;
  --rule-dark:    #333130;

  /* ---- type ---- */
  --display: "Instrument Serif", "Instrument Fallback", Georgia, "Times New Roman", serif;
  --text: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;

  /* ---- 8px spacing scale ---- */
  --s1: 8px;   --s2: 16px;  --s3: 24px;  --s4: 32px;  --s5: 48px;
  --s6: 64px;  --s7: 96px;  --s8: 128px; --s9: 160px; --s10: 192px;

  --gutter: 24px;
  --max: 1440px;
  --measure: 66ch;
  --radius: 2px;
}

@media (min-width: 768px)  { :root { --gutter: 48px; } }
@media (min-width: 1200px) { :root { --gutter: 80px; } }
@media (min-width: 1600px) { :root { --gutter: 120px; } }

/* ==========================================================================
   Fonts. Metric-matched fallbacks eliminate the layout shift when the webfont
   swaps in -- which in 2026 is a bigger CLS problem than the load itself.
   size-adjust and the overrides below were computed from the actual font
   tables against Arial, not estimated.
   ========================================================================== */

@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Instrument Serif";
  src: url("/assets/fonts/instrument-serif-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  size-adjust: 109.7%; ascent-override: 88.3%; descent-override: 22.0%; line-gap-override: 0%;
}
@font-face {
  font-family: "Instrument Fallback";
  src: local("Times New Roman");
  size-adjust: 75.9%; ascent-override: 130.5%; descent-override: 40.9%; line-gap-override: 0%;
}

/* ========================================================================== */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--text);
  font-size: 1.0625rem;          /* 17px */
  line-height: 1.65;
  font-feature-settings: "ss01", "ss03", "cv05", "cv11";
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
a:focus-visible, button:focus-visible, summary:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius);
}

::selection { background: var(--accent-wash); color: var(--ink); }

/* ---------------------------------------------------------------- type --- */

h1, h2, h3, h4 { font-family: var(--display); font-weight: 400; margin: 0; }

.display {
  font-size: clamp(3rem, 6.5vw, 5.5rem);
  line-height: 1.04; letter-spacing: -0.025em;
  max-width: 18ch;
}
h1, .h1 {
  font-size: clamp(2.25rem, 4.5vw, 3.5rem);
  line-height: 1.08; letter-spacing: -0.02em;
  max-width: 20ch;
}
h2, .h2 {
  font-size: clamp(1.625rem, 3vw, 2.25rem);
  line-height: 1.16; letter-spacing: -0.015em;
  max-width: 24ch;
}
/* Instrument Serif is a high-contrast DISPLAY face: its thin strokes hold up
   at 36px+ and go spindly and hard to read below about 24px. So everything at
   sub-heading size and under switches to the text face at 500. This is why
   card titles, FAQ questions and step headings read as solid rather than
   delicate. Do not "unify" these back onto the serif. */
h3, .h3 {
  font-family: var(--text); font-weight: 500;
  font-size: 1.375rem; line-height: 1.3; letter-spacing: -0.012em;
}

p { margin: 0 0 var(--s3); max-width: var(--measure); }

/* Headings reset their margins to zero so they can be positioned deliberately
   per section. That leaves a heading sitting flush on the paragraph beneath it
   wherever no explicit spacing was set, so put the gap back here. Inside
   .prose the heading already carries its own margin-bottom, so cancel it there
   rather than doubling up. */
h1 + p, h1 + .lede, h1 + .capsule,
h2 + p, h2 + .lede { margin-top: var(--s3); }
.prose h2 + p, .prose h2 + ul, .prose h2 + ol,
.prose h2 + .table-wrap, .prose h3 + p { margin-top: 0; }
.lede { font-size: 1.25rem; line-height: 1.55; color: var(--ink-70); max-width: 46ch; }

.eyebrow {
  font-family: var(--text);
  font-size: 0.6875rem; line-height: 1.2; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-50);
  margin: 0 0 var(--s3);
}
.eyebrow--dark { color: var(--on-dark-50); }

.caption { font-size: 0.8125rem; line-height: 1.5; letter-spacing: 0.06em; color: var(--ink-50); }
.small { font-size: 0.9375rem; line-height: 1.6; }

/* ------------------------------------------------------------- layout --- */

.wrap { max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--wide { max-width: 1760px; }

section { padding-block: var(--s7); }
@media (min-width: 900px) { section { padding-block: var(--s8); } }
section.breathe { padding-block: var(--s8); }
@media (min-width: 900px) { section.breathe { padding-block: var(--s10); } }

.band-alt  { background: var(--paper-alt); }
.band-dark { background: var(--ground-ink); color: var(--on-dark); }
.band-dark h1, .band-dark h2, .band-dark h3 { color: var(--on-dark); }
.band-dark p { color: var(--on-dark); }
.band-dark .lede { color: var(--on-dark); opacity: 0.85; }

.rule { border: 0; border-top: 1px solid var(--rule); margin: 0; }
.band-dark .rule { border-top-color: var(--rule-dark); }

.grid { display: grid; gap: var(--s3); }
@media (min-width: 900px) {
  .grid-12 { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--s3); }
  .col-2-7  { grid-column: 2 / 8; }
  .col-2-8  { grid-column: 2 / 9; }
  .col-7-12 { grid-column: 7 / 13; }
  .col-1-6  { grid-column: 1 / 7; }
  .col-1-5  { grid-column: 1 / 6; }
  .col-6-12 { grid-column: 6 / 13; }
}

/* Copy beside a figure. Asymmetric on purpose -- text narrower than image. */
.split { display: grid; gap: var(--s5); }
@media (min-width: 1000px) {
  .split { grid-template-columns: 1fr 1.15fr; gap: var(--s7); align-items: center; }
}
.split > div > :last-child { margin-bottom: 0; }

/* Map embed alongside suburb copy. */
.map-embed {
  position: relative; border: 1px solid var(--rule); border-radius: var(--radius);
  overflow: hidden; background: var(--paper-alt);
  aspect-ratio: 4 / 3;
}
.map-embed iframe { display: block; width: 100%; height: 100%; border: 0; }
.map-note { margin-top: var(--s2); margin-bottom: 0; }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5em;
  font-family: var(--text); font-size: 0.875rem; font-weight: 500;
  letter-spacing: 0.04em; line-height: 1;
  padding: 1.125rem 1.75rem;
  border: 1px solid var(--ink); border-radius: var(--radius);
  background: var(--ink); color: var(--paper);
  text-decoration: none; cursor: pointer;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease;
  min-height: 48px;
}
.btn:hover { background: var(--accent); border-color: var(--accent); }

.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--paper); }

.band-dark .btn { background: var(--on-dark); border-color: var(--on-dark); color: var(--ground-ink); }
.band-dark .btn:hover { background: var(--accent); border-color: var(--accent); color: var(--on-dark); }
.band-dark .btn--ghost { background: transparent; color: var(--on-dark); border-color: var(--on-dark); }
.band-dark .btn--ghost:hover { background: var(--on-dark); color: var(--ground-ink); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }

/* Text link with a rule that grows on hover -- the whole hover vocabulary. */
.link-arrow {
  display: inline-block; font-size: 0.9375rem; font-weight: 500;
  letter-spacing: 0.02em; text-decoration: none;
  border-bottom: 1px solid var(--rule-strong); padding-bottom: 2px;
  transition: border-color .18s ease, color .18s ease;
}
.link-arrow:hover { border-color: var(--accent); color: var(--accent); }
.link-arrow::after { content: " \2192"; }

/* ------------------------------------------------------------- header --- */

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--paper); padding: 1rem 1.5rem;
}
.skip:focus { left: 0; }

.site-header {
  position: sticky; top: 0; z-index: 40;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.header-in {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3); min-height: 72px;
}
.brand {
  font-family: var(--display); font-size: 1.375rem; letter-spacing: -0.01em;
  text-decoration: none; white-space: nowrap;
}
.brand span { display: block; font-family: var(--text); font-size: 0.625rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-50); margin-top: 2px; }

.nav { display: none; }
@media (min-width: 1000px) {
  .nav { display: flex; align-items: center; gap: var(--s4); }
  .nav a {
    font-size: 0.9375rem; text-decoration: none; color: var(--ink-70);
    padding-block: 0.5rem; border-bottom: 1px solid transparent;
    transition: color .18s ease, border-color .18s ease;
  }
  .nav a:hover, .nav a[aria-current="page"] { color: var(--ink); border-color: var(--accent); }
}
.header-cta { display: none; }
@media (min-width: 1000px) { .header-cta { display: inline-flex; } }

.menu-btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  background: none; border: 1px solid var(--rule-strong); border-radius: var(--radius);
  font-family: var(--text); font-size: 0.8125rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink);
  padding: 0.75rem 1rem; cursor: pointer; min-height: 44px;
}
@media (min-width: 1000px) { .menu-btn { display: none; } }

.mobile-nav { border-top: 1px solid var(--rule); background: var(--paper); }
.mobile-nav ul { list-style: none; margin: 0; padding: var(--s2) 0 var(--s4); }
.mobile-nav a {
  display: block; padding: 0.875rem 0; text-decoration: none;
  border-bottom: 1px solid var(--rule); font-size: 1.0625rem;
}
.mobile-nav .sub a { padding-left: var(--s2); color: var(--ink-70); font-size: 0.9375rem; }

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

/* ---- full-bleed hero (home) ---------------------------------------------
   One photograph, a flat veil for legibility, copy bottom-left. The veil is a
   flat tint rather than a gradient: gradients read cheap, and a flat tint is
   also predictable to contrast-check.

   Measured, not guessed: compositing this veil over the actual photograph and
   sampling only the column the text occupies gives #F2EFEA a WORST-CASE
   contrast of 5.25:1 (median 9.6:1). At 0.62 the worst case was 4.56:1 — over
   the 4.5:1 AA floor, but with no margin against a brighter frame. If the hero
   image is ever swapped, re-measure rather than assuming. */

/* Height is driven by content, not the viewport. A vh-based hero looked right
   on a large monitor and forced a laptop user to scroll past a near-empty
   screen before reaching anything. The cap keeps it from ballooning on very
   tall windows. */
.hero-full {
  position: relative;
  display: flex; align-items: center;
  overflow: hidden;
  background: var(--ground-ink);
  /* This is a <section>, so it inherits the global 128px block padding. The
     hero manages its own spacing via .hero-inner -- leaving the inherited
     padding in place silently added 256px and made the hero far taller than
     its content. */
  padding-block: 0;
}

.hero-bg { position: absolute; inset: 0; }
.hero-bg img { width: 100%; height: 100%; object-fit: cover; }

.hero-veil { position: absolute; inset: 0; background: rgba(20, 19, 18, 0.66); }

.hero-inner {
  position: relative; z-index: 1; width: 100%;
  padding-block: var(--s6);
}
@media (min-width: 1000px) {
  .hero-inner {
    padding-block: var(--s5);
    display: grid; grid-template-columns: minmax(0,1fr) 480px; gap: var(--s5);
    align-items: center;
  }
}
@media (min-width: 1240px) { .hero-inner { grid-template-columns: minmax(0,1fr) 540px; gap: var(--s6); } }

.hero-inner .display {
  max-width: 15ch;
  /* Slightly tighter than the global display scale: the hero now shares its
     row with the quote form, so the headline cannot run to 88px. */
  font-size: clamp(2.25rem, 3.9vw, 3.25rem);
}
.hero-inner .lede { max-width: 40ch; margin-bottom: 0; font-size: 1.0625rem; }
.hero-inner .btn-row { margin-top: var(--s3); }

/* Compact single-step form living in the hero. The full four-step version is
   still at the foot of the page for people who scroll. */
.hero-form {
  background: rgba(17, 16, 15, 0.90);
  border: 1px solid var(--rule-dark);
  border-radius: var(--radius);
  padding: var(--s3);
  margin-top: var(--s5);
}
@media (min-width: 1000px) { .hero-form { margin-top: 0; } }
.hero-form h2 {
  font-family: var(--text); font-weight: 500; font-size: 1.0625rem;
  letter-spacing: -0.01em; color: var(--on-dark); max-width: none;
  margin-bottom: var(--s2);
}
.hero-form .field { margin-bottom: 12px; }
.hero-form .field label {
  font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--on-dark-50); margin-bottom: 5px;
}
.hero-form input, .hero-form select, .hero-form textarea {
  background: #121110; border-color: #3A3735; color: var(--on-dark);
  min-height: 42px; padding: 0.5rem 0.75rem; font-size: 0.9375rem;
}
.hero-form textarea { min-height: 4.375rem; }   /* 70px; was 53px from rows=2 */
.hero-form .btn { width: 100%; margin-top: 6px; min-height: 46px; padding-block: 0.875rem; }
.hero-form .form-note { color: var(--on-dark-50); font-size: 0.75rem; text-align: center; }
.hero-form .duo { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }

/* Credentials strip directly beneath the hero. */
.assurance { padding-block: var(--s4); }
@media (min-width: 900px) { .assurance { padding-block: var(--s5); } }
.assurance-grid {
  display: grid; gap: var(--s3) var(--s4); margin: 0;
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 760px) { .assurance-grid { grid-template-columns: repeat(4, 1fr); } }
.assurance-grid dt {
  font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-50);
}
.assurance-grid dd { margin: 6px 0 0; font-size: 1rem; font-weight: 500; }

.band-dark .hero-facts { border-top-color: var(--rule-dark); }
.band-dark .hero-facts dt { color: var(--on-dark-50); }
.band-dark .hero-facts dd { color: var(--on-dark); }

/* ---- split hero (service and inner pages) ------------------------------- */

.hero { padding-block: var(--s6) var(--s7); }
@media (min-width: 900px) {
  .hero { padding-block: var(--s7) var(--s8); }
  .hero-in { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s6); align-items: center; }
}
@media (min-width: 1200px) {
  .hero-in { grid-template-columns: 1.05fr 0.95fr; gap: var(--s7); }
}
.hero-copy { max-width: 34rem; }
.hero .display { margin-bottom: var(--s3); }
.hero-media { margin-top: var(--s5); }
@media (min-width: 900px) { .hero-media { margin-top: 0; } }
.hero-media img { width: 100%; border-radius: var(--radius); }

.hero-facts {
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5);
  margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--rule);
}
.hero-facts div { min-width: 8rem; }
.hero-facts dt { font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-50); }
.hero-facts dd { margin: 4px 0 0; font-size: 0.9375rem; font-weight: 500; }

/* ------------------------------------------------------------ figures --- */

figure { margin: 0; }
figure img { border-radius: var(--radius); background: var(--paper-alt); }
figcaption {
  margin-top: var(--s3); padding-top: var(--s2); border-top: 1px solid var(--rule);
}
figcaption .t { display: block; font-size: 0.9375rem; color: var(--ink); }
figcaption .m {
  display: block; margin-top: 4px;
  font-size: 0.8125rem; letter-spacing: 0.06em; color: var(--ink-50);
}
figcaption .i {
  display: block; margin-bottom: 6px;
  font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-30);
}

/* -------------------------------------------------------- card grids --- */

.cards { display: grid; gap: var(--s5) var(--s3); grid-template-columns: 1fr; }
@media (min-width: 620px)  { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .cards { grid-template-columns: repeat(4, 1fr); } }
.cards--3 { grid-template-columns: 1fr; }
@media (min-width: 620px)  { .cards--3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .cards--3 { grid-template-columns: repeat(3, 1fr); } }

.card { display: flex; flex-direction: column; }
.card a.card-link { text-decoration: none; display: block; }
.card img { width: 100%; }
.card h3 { margin-top: var(--s3); }
.card p { max-width: none; }
.card p { font-size: 0.9375rem; color: var(--ink-70); margin-top: var(--s1); }
.card .link-arrow { margin-top: auto; align-self: flex-start; }
.card-link:hover h3 { color: var(--accent); }

/* ------------------------------------------------------- testimonials --- */
/* Sits on the warm band, so the cards take the lighter page ground to stand
   off it. The home page alternates white and beige section by section. */
.testimonial {
  margin: 0; display: flex; flex-direction: column;
  background: var(--paper); border-radius: var(--radius);
  padding: var(--s4);
}
.testimonial blockquote { margin: 0; flex: 1; }
.testimonial blockquote p { font-size: 1.0625rem; line-height: 1.65; color: var(--ink); max-width: none; margin: 0; }
.testimonial figcaption { margin-top: var(--s4); }
.stars { display: flex; gap: 3px; margin: 0 0 var(--s3); color: var(--ink); }
.stars svg { display: block; fill: currentColor; }

/* Testimonial carousel.

   Content first: all five reviews are real DOM nodes inside the track, so with
   JavaScript off this degrades to a normal horizontally scrollable strip --
   swipe, trackpad and keyboard all still reach every review. That is the only
   thing the no-JS rule asks for. The looping itself is unashamedly JS.

   site.js clones the set twice and parks the view on the middle copy, so
   clicking right forever just keeps revealing reviews. Nothing here needs to
   know about that -- the clones are ordinary children of the same flex row. */
.tcar { position: relative; }
.tcar-track {
  display: flex; gap: var(--s3);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  padding: 2px;  margin: -2px;
  scrollbar-width: none;            /* Firefox */
  -ms-overflow-style: none;
}
.tcar-track::-webkit-scrollbar { display: none; }
.tcar-track > .testimonial { flex: 0 0 100%; scroll-snap-align: start; }
@media (min-width: 620px)  { .tcar-track > .testimonial { flex-basis: calc((100% - var(--s3)) / 2); } }
@media (min-width: 1000px) { .tcar-track > .testimonial { flex-basis: calc((100% - 2 * var(--s3)) / 3); } }
.tcar-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* Arrows flank the cards, vertically centred. They start life inside the page
   gutter on wide screens and only overlap the cards once the gutter is too
   narrow to hold them -- so on desktop they never cover a word of a review. */
.tcar-btn {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 44px; height: 44px;          /* 44px: comfortable touch target */
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule-strong); border-radius: 50%;
  cursor: pointer; padding: 0;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.tcar-btn[data-tcar="prev"] { left: 2px; }
.tcar-btn[data-tcar="next"] { right: 2px; }
@media (min-width: 768px) {
  .tcar-btn[data-tcar="prev"] { left: -22px; }
  .tcar-btn[data-tcar="next"] { right: -22px; }
}
@media (min-width: 1200px) {
  .tcar-btn[data-tcar="prev"] { left: -56px; }
  .tcar-btn[data-tcar="next"] { right: -56px; }
}
.tcar-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.tcar-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .tcar-btn { transition: none; } }

/* ------------------------------------------------------------ gallery --- */

.gal { display: grid; gap: var(--s5) var(--s3); grid-template-columns: 1fr; }
@media (min-width: 620px)  { .gal { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .gal { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 620px)  { .gal .wide { grid-column: span 2; } }

.filters { display: flex; flex-wrap: wrap; gap: var(--s1); margin-bottom: var(--s5); }
.filters button {
  font-family: var(--text); font-size: 0.8125rem; letter-spacing: 0.04em;
  padding: 0.625rem 1rem; min-height: 40px;
  background: transparent; color: var(--ink-70);
  border: 1px solid var(--rule-strong); border-radius: var(--radius); cursor: pointer;
  transition: background-color .18s, color .18s, border-color .18s;
}
.filters button:hover { border-color: var(--ink); color: var(--ink); }
.filters button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* ------------------------------------------------------------- process --- */

.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.steps > li {
  counter-increment: step;
  display: grid; gap: var(--s1) var(--s4); align-items: start;
  padding-block: var(--s4); border-top: 1px solid var(--rule);
}
.steps > li:last-child { border-bottom: 1px solid var(--rule); }
@media (min-width: 760px) { .steps > li { grid-template-columns: 5rem 18rem 1fr; gap: var(--s5); } }
.steps > li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--display); font-size: 1.5rem; color: var(--ink-30); line-height: 1;
}
.steps h3 { margin: 0; }
.steps p { margin: 0; font-size: 0.9375rem; color: var(--ink-70); }
.band-dark .steps > li { border-color: var(--rule-dark); }
.band-dark .steps p { color: var(--on-dark); opacity: .8; }
.band-dark .steps > li::before { color: var(--on-dark-50); }

/* --------------------------------------------------------------- lists --- */

.ticks { list-style: none; margin: 0 0 var(--s3); padding: 0; max-width: var(--measure); }
.ticks li { position: relative; padding-left: 1.75rem; margin-bottom: var(--s2); }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: 0.7em;
  width: 10px; height: 1px; background: var(--accent);
}
.band-dark .ticks li::before { background: var(--on-dark-50); }

ol.numbered { margin: 0 0 var(--s3); padding-left: 1.4rem; max-width: var(--measure); }
ol.numbered li { margin-bottom: var(--s2); padding-left: 0.4rem; }
ol.numbered li::marker { color: var(--ink-30); font-family: var(--display); }

/* -------------------------------------------------------------- tables --- */

.table-wrap { overflow-x: auto; margin: 0 0 var(--s3); -webkit-overflow-scrolling: touch; }
table { border-collapse: collapse; width: 100%; min-width: 34rem; font-size: 0.9375rem; }
caption {
  caption-side: top; text-align: left; padding-bottom: var(--s3);
  font-size: 0.8125rem; letter-spacing: 0.04em; color: var(--ink-50); max-width: var(--measure);
}
th, td { text-align: left; padding: 0.875rem var(--s2) 0.875rem 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
thead th { font-weight: 500; font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-50); }
tbody th { font-weight: 500; }

.specs { width: 100%; min-width: 0; }
.specs th { width: 34%; color: var(--ink-50); font-weight: 400; }

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

.faq { border-top: 1px solid var(--rule); max-width: 54rem; }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  cursor: pointer; list-style: none;
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3);
  padding: var(--s4) 0;
  font-family: var(--text); font-weight: 500; font-size: 1.125rem; line-height: 1.4;
  letter-spacing: -0.01em;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font-family: var(--text); font-size: 1.25rem; color: var(--ink-50); flex: none; }
.faq details[open] summary::after { content: "\2212"; }
.faq details[open] summary { color: var(--accent); }
.faq .a { padding: 0 0 var(--s3); }
.faq .a p { margin: 0; color: var(--ink-70); }

/* ---------------------------------------------------------------- form --- */

.quote { background: var(--paper-alt); border: 1px solid var(--rule); border-radius: var(--radius); padding: var(--s4); }
@media (min-width: 760px) { .quote { padding: var(--s5); } }
.band-dark .quote { background: #221F1E; border-color: var(--rule-dark); }

.field { margin-bottom: var(--s3); }
.field label, .fieldset-label {
  display: block; font-size: 0.8125rem; letter-spacing: 0.06em;
  color: var(--ink-50); margin-bottom: var(--s1);
}
.band-dark .field label, .band-dark .fieldset-label { color: var(--on-dark-50); }
.field .opt { text-transform: none; letter-spacing: 0.02em; color: var(--ink-30); }

input[type="text"], input[type="email"], input[type="tel"], input[type="number"], select, textarea {
  width: 100%; font-family: var(--text); font-size: 1rem; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule-strong); border-radius: var(--radius);
  padding: 0.875rem 1rem; min-height: 48px;
}
textarea { min-height: 7rem; resize: vertical; }
.band-dark input, .band-dark select, .band-dark textarea {
  background: #191817; border-color: #3A3735; color: var(--on-dark);
}
input::placeholder, textarea::placeholder { color: var(--ink-30); }

/* Card-style radio group: zero typing on the first step. */
.choices { display: grid; gap: var(--s1); grid-template-columns: 1fr; }
@media (min-width: 560px) { .choices { grid-template-columns: repeat(2, 1fr); } }
.choice { position: relative; }
.choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choice label {
  display: block; margin: 0; padding: 1rem 1.125rem; min-height: 56px;
  border: 1px solid var(--rule-strong); border-radius: var(--radius);
  background: var(--paper); cursor: pointer;
  font-size: 0.9375rem; letter-spacing: 0; color: var(--ink); text-transform: none;
  transition: border-color .15s, background-color .15s;
}
.choice input:checked + label { border-color: var(--accent); background: var(--accent-wash); }
.choice input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 3px; }
.band-dark .choice label { background: #191817; border-color: #3A3735; color: var(--on-dark); }
.band-dark .choice input:checked + label { border-color: var(--on-dark); background: #2A2725; }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-note { font-size: 0.8125rem; color: var(--ink-50); margin-top: var(--s2); }
.band-dark .form-note { color: var(--on-dark-50); }

.form-msg { margin-top: var(--s3); padding: var(--s2) 0 0; border-top: 1px solid var(--rule); font-size: 0.9375rem; }
/* Empty until JS writes into it -- without this the rule and its spacing show
   as a stray hairline under every form. */
.form-msg:empty { display: none; }
.form-msg[data-state="error"] { color: #8C2F1F; }
.band-dark .form-msg[data-state="error"] { color: #E9A08F; }

/* Multi-step. Steps beyond the first are hidden ONLY once JS confirms it can
   drive them -- see site.js. Without JS every step renders and the form still
   submits, which is the whole point. */
.steps-form fieldset { border: 0; margin: 0 0 var(--s3); padding: 0; }
.steps-form legend { padding: 0; margin-bottom: var(--s3); font-family: var(--text); font-weight: 500; font-size: 1.25rem; letter-spacing: -0.01em; }
html.js-form .steps-form .step { display: none; }
html.js-form .steps-form .step.is-active { display: block; }

/* Without JS the wizard collapses to one long form, so Continue/Back would be
   inert clutter -- they only exist once JS can act on them. The row itself is
   hidden too unless it holds the submit button, otherwise an empty flex row
   leaves a phantom gap in the no-JS form. */
.step-nav { display: none; }
.step-nav:has([type="submit"]) { display: flex; }
html.js-form .step-nav { display: flex; }
.step-nav [data-next], .step-nav [data-prev] { display: none; }
html.js-form .step-nav [data-next],
html.js-form .step-nav [data-prev] { display: inline-flex; }
.progress { font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-50); margin-bottom: var(--s3); }
.band-dark .progress { color: var(--on-dark-50); }
/* Sits to the right of the panel, clear of the choice grid above it, with a
   hairline separating the answer from the action. */
.step-nav {
  display: flex; gap: var(--s2); flex-wrap: wrap; justify-content: flex-end;
  margin-top: var(--s5); padding-top: var(--s3);
  border-top: 1px solid var(--rule);
}
.band-dark .step-nav { border-top-color: var(--rule-dark); }

/* Result panel produced by the scope builder. */
.scope-out { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px solid var(--rule); }
.band-dark .scope-out { border-color: var(--rule-dark); }
.scope-out h3 { font-size: 1.125rem; margin-bottom: var(--s2); }

/* ------------------------------------------------------------- footer --- */

.site-footer { background: var(--ground-ink); color: var(--on-dark); padding-block: var(--s7) var(--s5); }
.footer-grid { display: grid; gap: var(--s5); grid-template-columns: 1fr; }
@media (min-width: 760px)  { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr; } }
@media (min-width: 1100px) { .footer-grid { grid-template-columns: 1.6fr 1fr 1fr 1fr; } }
.site-footer h2 { font-size: 0.6875rem; font-family: var(--text); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--on-dark-50); margin-bottom: var(--s3); }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 0.625rem; }
.site-footer a { color: var(--on-dark); text-decoration: none; font-size: 0.9375rem; opacity: .85; }
.site-footer a:hover { opacity: 1; text-decoration: underline; }
.footer-legal {
  margin-top: var(--s6); padding-top: var(--s3); border-top: 1px solid var(--rule-dark);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4);
  font-size: 0.8125rem; color: var(--on-dark-50);
}

/* -------------------------------------------------- sticky mobile bar --- */
/* Not present in the DOM until JS adds it, and only below 1000px. A fixed
   element is never an anchor target -- see the #quote target at the end of
   main, which is in flow and therefore actually scrollable. */

.callbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  display: grid; grid-template-columns: 1fr 1fr;
  background: var(--ground-ink); border-top: 1px solid var(--rule-dark);
  padding-bottom: env(safe-area-inset-bottom);
  transform: translateY(101%);
  transition: transform .25s ease;
}
.callbar.is-in { transform: none; }
@media (prefers-reduced-motion: reduce) { .callbar { transition: none; } }
.callbar a {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  min-height: 56px; padding: 0.75rem 1rem;
  color: var(--on-dark); text-decoration: none;
  font-size: 0.9375rem; font-weight: 500; letter-spacing: 0.02em;
}
.callbar a + a { border-left: 1px solid var(--rule-dark); }
.callbar a.primary { background: var(--accent); }
@media (min-width: 1000px) { .callbar { display: none; } }
body.has-callbar { padding-bottom: 0; }
@media (max-width: 999px) { body.has-callbar { padding-bottom: 56px; } }

/* --------------------------------------------------------- breadcrumb --- */

.crumbs { font-size: 0.8125rem; letter-spacing: 0.04em; color: var(--ink-50); padding-block: var(--s3) 0; }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; }
.crumbs li:not(:last-child)::after { content: "/"; margin-left: 0.5rem; color: var(--ink-30); }
.crumbs a { text-decoration: none; }
.crumbs a:hover { color: var(--accent); }

/* ------------------------------------------------------------- prose --- */

.prose h2 { margin-top: var(--s6); margin-bottom: var(--s3); }
.prose h3 { margin-top: var(--s5); margin-bottom: var(--s2); }
.prose > :first-child { margin-top: 0; }
.capsule {
  font-size: 1.1875rem; line-height: 1.6; color: var(--ink);
  border-left: 2px solid var(--accent); padding-left: var(--s3);
  max-width: 52ch; margin-bottom: var(--s5);
}

.callout {
  background: var(--paper-alt); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: var(--s4); margin-block: var(--s5);
}
.callout > :last-child { margin-bottom: 0; }

/* ------------------------------------------------------------ reveal --- */
/*
  The hidden state exists ONLY inside html.js-anim, which site.js adds at
  runtime after confirming IntersectionObserver is present. If JS runs but the
  observer never fires -- a bot, a screenshot tool, a print -- a timer in
  site.js reveals everything anyway. Content must never depend on JS to exist.
*/
html.js-anim .reveal > * {
  opacity: 0; transform: translateY(14px);
  transition: opacity .7s ease, transform .7s ease;
}
html.js-anim .reveal.is-in > * { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js-anim .reveal > * { opacity: 1; transform: none; transition: none; }
}

/* ------------------------------------------------------------- print --- */

@media print {
  .site-header, .callbar, .filters, .skip, .quote { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .reveal > * { opacity: 1 !important; transform: none !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #555; }
}
