/* ==========================================================================
   Wavify — design system
   Direction: photo-led warm. Cream ground, terracotta accent used once per
   screen, full-bleed photography, glass cards, 20px radii.
   Deliberately shares no tokens with the earlier sand/Instrument-Serif work.
   ========================================================================== */

/* --- 1. Tokens ---------------------------------------------------------- */

:root {
  /* ground */
  --cream:      #F7F4EF;
  --paper:      #FFFFFF;
  --sand:       #EFE9E0;
  --night:      #14100D;
  --night-2:    #211A15;

  /* ink */
  --ink:        #1A1714;
  --ink-70:     #57504A;
  --ink-45:     #8B837B;
  --ink-on-dark:#F4EFE8;

  /* line */
  --line:       #E4DDD3;
  --line-soft:  rgba(26, 23, 20, .09);
  --line-dark:  rgba(244, 239, 232, .16);

  /* accent — terracotta. One per screen. */
  --clay:       #C75B2C;
  --clay-700:   #A2451F;
  --clay-50:    #FAEDE5;

  /* semantic */
  --ok:         #4C7A5B;

  /* geometry */
  --r-xl:  28px;
  --r-lg:  20px;
  --r-md:  14px;
  --r-sm:  10px;
  --r-pill: 999px;

  /* elevation */
  --sh-1: 0 1px 2px rgba(26,23,20,.05), 0 8px 20px -14px rgba(26,23,20,.30);
  --sh-2: 0 2px 4px rgba(26,23,20,.05), 0 18px 44px -22px rgba(26,23,20,.42);
  --sh-glass: 0 8px 32px -12px rgba(0,0,0,.45);

  /* layout */
  --wrap: 1200px;
  --gut: 24px;

  /* type */
  --display: 'Bricolage Grotesque', 'Segoe UI', system-ui, sans-serif;
  --body: 'Figtree', 'Segoe UI', system-ui, -apple-system, sans-serif;
}

@media (min-width: 900px) { :root { --gut: 40px; } }

/* --- 2. Reset ----------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;          /* floor: this audience is 35–60 */
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2.5px solid var(--clay);
  outline-offset: 3px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

/* --- 3. Type ------------------------------------------------------------ */

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -.028em;
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: clamp(2.5rem, 6.2vw, 4.5rem); }
h2 { font-size: clamp(1.95rem, 3.9vw, 3rem); }
h3 { font-size: clamp(1.2rem, 1.7vw, 1.45rem); letter-spacing: -.02em; line-height: 1.18; }
h4 { font-size: 1.05rem; letter-spacing: -.015em; }

p { margin: 0; }

.lead {
  font-size: clamp(1.05rem, 1.5vw, 1.2rem);
  line-height: 1.55;
  color: var(--ink-70);
  max-width: 54ch;
}

.eyebrow {
  display: inline-block;
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-45);
}
.eyebrow--clay { color: var(--clay); }
.eyebrow--dark { color: rgba(244,239,232,.62); }

.muted { color: var(--ink-70); }
.small { font-size: .875rem; line-height: 1.55; }
.fine  { font-size: .8rem; line-height: 1.5; color: var(--ink-45); }

.num {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -.035em;
  font-variant-numeric: tabular-nums;
}

/* --- 4. Layout ---------------------------------------------------------- */

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gut); }

.section { padding-block: clamp(56px, 8vw, 104px); }
.section--tight { padding-block: clamp(40px, 5vw, 68px); }
.section--sand { background: var(--sand); }
.section--night { background: var(--night); color: var(--ink-on-dark); }
.section--night h2, .section--night h3 { color: var(--ink-on-dark); }
.section--night .lead, .section--night .muted { color: rgba(244,239,232,.68); }

.head {
  display: grid;
  gap: 18px;
  margin-bottom: clamp(28px, 4vw, 46px);
}
@media (min-width: 860px) {
  .head { grid-template-columns: minmax(0,1.15fr) minmax(0,.85fr); align-items: end; gap: 48px; }
  .head > .lead { justify-self: end; }
}

.stack   { display: grid; gap: 14px; }
.stack-8 { display: grid; gap: 8px; }
.row     { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

.grid { display: grid; gap: 14px; }
@media (min-width: 700px)  { .grid--2 { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 700px)  { .grid--3 { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1000px) { .grid--3 { grid-template-columns: repeat(3, minmax(0,1fr)); } }

.rule { height: 1px; background: var(--line); border: 0; margin: 0; }

/* --- 5. Buttons --------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 48px;                 /* ≥44px hit target */
  padding: 12px 22px;
  border-radius: var(--r-pill);
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: -.01em;
  white-space: nowrap;
  border: 1.5px solid transparent;
  transition: background .18s ease, color .18s ease, border-color .18s ease, transform .18s ease;
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--ink); color: var(--cream); }
.btn--primary:hover { background: var(--clay); }

.btn--clay { background: var(--clay); color: #fff; }
.btn--clay:hover { background: var(--clay-700); }

.btn--ghost { border-color: var(--line); color: var(--ink); background: var(--paper); }
.btn--ghost:hover { border-color: var(--ink); }

.btn--onphoto {
  background: rgba(255,255,255,.94);
  color: var(--ink);
  backdrop-filter: blur(8px);
}
.btn--onphoto:hover { background: #fff; }

.btn--onnight { border-color: var(--line-dark); color: var(--ink-on-dark); }
.btn--onnight:hover { background: rgba(244,239,232,.1); }

.btn--sm { min-height: 40px; padding: 8px 16px; font-size: .875rem; }
.btn--block { width: 100%; justify-content: center; }

.link-arrow {
  display: inline-flex; align-items: center; gap: 7px;
  font-weight: 600; font-size: .92rem; color: var(--clay);
}
.link-arrow svg { transition: transform .2s ease; }
.link-arrow:hover svg { transform: translateX(3px); }

/* --- 6. Chips / tags ---------------------------------------------------- */

.chip {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px;
  padding: 9px 18px;
  border-radius: var(--r-pill);
  border: 1.5px solid var(--line);
  background: var(--paper);
  font-size: .92rem; font-weight: 500; color: var(--ink-70);
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.chip:hover { border-color: var(--ink-45); color: var(--ink); }
.chip[aria-pressed="true"], .chip[aria-selected="true"] {
  background: var(--ink); border-color: var(--ink); color: var(--cream); font-weight: 600;
}

.tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px;
  border-radius: var(--r-pill);
  background: var(--clay-50);
  color: var(--clay-700);
  font-size: .76rem; font-weight: 600; letter-spacing: .01em;
}
.tag--plain { background: rgba(26,23,20,.05); color: var(--ink-70); }
.tag--dark  { background: rgba(244,239,232,.12); color: rgba(244,239,232,.82); }

/* --- 7. Photo holders --------------------------------------------------- */
/* Images that have not been generated yet fall back to their LQIP gradient,
   so a missing file reads as an unlit room rather than a broken box.        */

.ph {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--lqip, linear-gradient(150deg, #C9B7A2, #6E5A47));
  isolation: isolate;
}
.ph > img {
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .6s ease;
}
.ph > img.is-loaded { opacity: 1; }
.ph--4x3  { aspect-ratio: 4 / 3; }
.ph--1x1  { aspect-ratio: 1 / 1; }
.ph--3x2  { aspect-ratio: 3 / 2; }
.ph--16x9 { aspect-ratio: 16 / 9; }
.ph--tall { aspect-ratio: 3 / 4; }

.ph__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(178deg, rgba(20,16,13,.42) 0%, rgba(20,16,13,0) 34%, rgba(20,16,13,.10) 58%, rgba(20,16,13,.78) 100%);
  pointer-events: none;
}
.ph__caption {
  position: absolute; left: 18px; right: 18px; bottom: 16px;
  color: #fff;
  text-shadow: 0 1px 12px rgba(0,0,0,.4);
}

/* Glass card floating on photography — the core reference gesture */
.glass {
  background: rgba(24, 19, 15, .52);
  backdrop-filter: blur(16px) saturate(1.2);
  -webkit-backdrop-filter: blur(16px) saturate(1.2);
  border: 1px solid rgba(255,255,255,.18);
  border-radius: var(--r-md);
  box-shadow: var(--sh-glass);
  color: #fff;
  padding: 16px 18px;
}
.glass--light {
  background: rgba(255,255,255,.86);
  border-color: rgba(255,255,255,.9);
  color: var(--ink);
}

/* --- 8. Cards ----------------------------------------------------------- */

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 22px;
  transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.card--hover:hover { border-color: var(--ink-45); box-shadow: var(--sh-1); transform: translateY(-2px); }
.card--flush { padding: 0; overflow: hidden; }
.card--flush .card__body { padding: 20px 22px 24px; }
.card--night { background: var(--night-2); border-color: var(--line-dark); color: var(--ink-on-dark); }
.card--clay  { background: var(--clay); border-color: var(--clay); color: #fff; }
.card--clay h3, .card--clay p { color: #fff; }

/* --- 9. Header ---------------------------------------------------------- */

.site-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(247,244,239,.88);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, background .2s ease;
}
.site-header.is-stuck { border-bottom-color: var(--line); }

.site-header__inner {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  min-height: 72px;
}

/* Lockup: the supplied artwork, background removed to alpha.
   Two colourways — wavify-lockup.png on light grounds, -light.png on dark.
   Sized by height only; width:auto keeps the artwork's own proportions.
   Source master: logo/new series/ (see README). */
.logo { display: inline-flex; align-items: center; flex: none; }
.logo img {
  height: 34px;
  width: auto;
  display: block;
}
.site-footer .logo img { height: 38px; }
.drawer .logo img { height: 30px; }
@media (max-width: 480px) { .site-header .logo img { height: 29px; } }

.nav { display: none; align-items: center; gap: 4px; }
@media (min-width: 1000px) { .nav { display: flex; } }
.nav a {
  padding: 9px 13px;
  border-radius: var(--r-pill);
  font-size: .93rem; font-weight: 500; color: var(--ink-70);
  transition: color .16s ease, background .16s ease;
}
.nav a:hover { color: var(--ink); background: rgba(26,23,20,.05); }
.nav a[aria-current="page"] { color: var(--ink); font-weight: 600; }

.header-cta { display: none; }
@media (min-width: 1000px) { .header-cta { display: inline-flex; } }

.burger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px;
  border-radius: var(--r-pill);
  border: 1.5px solid var(--line);
  background: var(--paper);
}
@media (min-width: 1000px) { .burger { display: none; } }

.drawer {
  position: fixed; inset: 0; z-index: 70;
  background: var(--cream);
  padding: 20px var(--gut) 40px;
  display: grid; align-content: start; gap: 4px;
  overflow-y: auto;
}
.drawer[hidden] { display: none; }
.drawer__top { display: flex; align-items: center; justify-content: space-between; min-height: 52px; margin-bottom: 18px; }
.drawer a.drawer__link {
  font-family: var(--display); font-size: 1.6rem; font-weight: 600; letter-spacing: -.03em;
  padding: 12px 0; border-bottom: 1px solid var(--line-soft);
}
.drawer .btn { margin-top: 22px; }

/* --- 10. Hero ----------------------------------------------------------- */

.hero { padding-top: 14px; }

.hero__frame {
  position: relative;
  border-radius: var(--r-xl);
  overflow: hidden;
  min-height: clamp(420px, 62vh, 620px);
  display: flex;
  align-items: flex-end;
  background: var(--lqip);
}
.hero__frame > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity .8s ease;
}
.hero__frame > img.is-loaded { opacity: 1; }
.hero__veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(96deg, rgba(20,16,13,.80) 0%, rgba(20,16,13,.52) 42%, rgba(20,16,13,.10) 78%),
    linear-gradient(0deg, rgba(20,16,13,.55) 0%, rgba(20,16,13,0) 45%);
}
.hero__content {
  position: relative;
  padding: clamp(28px, 4vw, 52px);
  /* clear the router shelf, which overlaps the frame by 34px */
  padding-bottom: calc(clamp(28px, 4vw, 52px) + 34px);
  color: #fff;
  max-width: 46rem;
}
.hero__content h1 { color: #fff; }
.hero__content .lead { color: rgba(255,255,255,.9); margin-top: 18px; }

.hero__status {
  position: absolute; right: 22px; top: 22px;
  width: 210px;
  display: none;
}
@media (min-width: 900px) { .hero__status { display: block; } }
.hero__status .num { font-size: 2rem; line-height: 1; }

/* Router shelf — the three-way qualifier, overlapping the photo */
.router {
  position: relative;
  z-index: 2;
  margin: -34px auto 0;
  max-width: calc(var(--wrap) - var(--gut) * 2 - 48px);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-2);
  padding: 20px;
}
.router__label { display: block; margin-bottom: 12px; }
.router__opts { display: flex; flex-wrap: wrap; gap: 8px; }
.router__out {
  margin-top: 16px; padding-top: 16px;
  border-top: 1px solid var(--line-soft);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px;
}
.router__out p { max-width: 52ch; color: var(--ink-70); font-size: .95rem; }

/* --- 11. Installs strip ------------------------------------------------- */

.install__meta {
  display: flex; flex-wrap: wrap; gap: 8px 14px;
  margin-top: 10px;
  font-size: .82rem; color: var(--ink-45); font-weight: 500;
}
.install__meta span { display: inline-flex; align-items: center; gap: 6px; }
.dot { width: 5px; height: 5px; border-radius: 50%; background: var(--clay); flex: none; }

/* --- 12. Before / after ------------------------------------------------- */

.ba {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 3 / 2;
  touch-action: pan-y;
  user-select: none;
  cursor: ew-resize;
  background: var(--lqip);
}
.ba__layer { position: absolute; inset: 0; }
.ba__layer img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .6s ease; }
.ba__layer img.is-loaded { opacity: 1; }
.ba__layer--after { clip-path: inset(0 0 0 var(--pos, 50%)); }
.ba__handle {
  position: absolute; top: 0; bottom: 0;
  left: var(--pos, 50%);
  width: 2px; background: #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.12);
  transform: translateX(-1px);
}
.ba__grip {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 52px; height: 52px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 4px 18px rgba(0,0,0,.28);
  display: grid; place-items: center;
  color: var(--ink);
}
.ba__tag {
  position: absolute; bottom: 16px;
  padding: 6px 13px;
  border-radius: var(--r-pill);
  background: rgba(20,16,13,.62);
  backdrop-filter: blur(8px);
  color: #fff; font-size: .78rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
}
.ba__tag--l { left: 16px; }
.ba__tag--r { right: 16px; }
.ba input[type="range"] {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: 0; margin: 0; cursor: ew-resize;
}
/* the range is invisible by design, so surface focus on the frame instead —
   otherwise keyboard users get no indication the slider is theirs to drive */
.ba:has(input[type="range"]:focus-visible) {
  outline: 2.5px solid var(--clay);
  outline-offset: 3px;
}
.ba:has(input[type="range"]:focus-visible) .ba__grip {
  box-shadow: 0 4px 18px rgba(0,0,0,.28), 0 0 0 3px var(--clay);
}

/* --- 13. Room tabs ------------------------------------------------------ */

.tabs { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }

.room {
  display: grid; gap: 16px;
  margin-top: 22px;
}
@media (min-width: 900px) {
  .room { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 22px; align-items: stretch; }
}
.room__photo { min-height: 300px; }
.room__panel { display: flex; flex-direction: column; gap: 16px; }
.room__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.room__list li { position: relative; padding-left: 22px; color: var(--ink-70); font-size: .95rem; line-height: 1.5; }
.room__list li::before {
  content: ""; position: absolute; left: 0; top: .52em;
  width: 7px; height: 7px; border-radius: 50%; background: var(--clay);
}
.room__foot { margin-top: auto; padding-top: 16px; border-top: 1px solid var(--line-soft); }

/* --- 14. Steps ---------------------------------------------------------- */

.step { display: grid; gap: 12px; }
.step__n {
  font-family: var(--display); font-weight: 600; font-size: 2.6rem; line-height: 1;
  letter-spacing: -.05em;
  color: var(--clay);
}
.step__rule { height: 1px; background: var(--line); }

/* --- 15. Estimator ------------------------------------------------------ */

.est { display: grid; gap: 18px; }
@media (min-width: 940px) { .est { grid-template-columns: minmax(0,1.15fr) minmax(0,.85fr); gap: 22px; align-items: start; } }

.field { display: grid; gap: 10px; padding-block: 18px; border-top: 1px solid var(--line-soft); }
.field:first-of-type { border-top: 0; padding-top: 0; }
.field__label { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.field__label b { font-size: .98rem; font-weight: 600; }
.field__label span { font-size: .85rem; color: var(--ink-45); font-variant-numeric: tabular-nums; }

.slider {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 34px; background: transparent; cursor: pointer;
}
.slider::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: var(--line); }
.slider::-moz-range-track { height: 6px; border-radius: 999px; background: var(--line); }
.slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 26px; height: 26px; margin-top: -10px;
  border-radius: 50%; background: var(--clay);
  border: 3px solid #fff; box-shadow: 0 2px 8px rgba(26,23,20,.3);
}
.slider::-moz-range-thumb {
  width: 26px; height: 26px; border: 3px solid #fff;
  border-radius: 50%; background: var(--clay); box-shadow: 0 2px 8px rgba(26,23,20,.3);
}

.toggle {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 15px;
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper);
  cursor: pointer;
  transition: border-color .16s ease, background .16s ease;
}
.toggle:hover { border-color: var(--ink-45); }
.toggle:has(input:checked) { border-color: var(--clay); background: var(--clay-50); }
.toggle:has(input:focus-visible) { outline: 2.5px solid var(--clay); outline-offset: 3px; }
.toggle input { width: 20px; height: 20px; accent-color: var(--clay); flex: none; margin: 0; cursor: pointer; }
.toggle__name { font-size: .93rem; font-weight: 500; }
/* The unit each band is quoted in. Sits under the name rather than beside the
   price, because .toggle__price is nowrap and a unit like "whole home, however
   many sensors that takes" would force the row wide on a phone. */
.toggle__unit {
  display: block;
  font-size: .78rem; font-weight: 400; line-height: 1.35;
  color: var(--ink-45);
  margin-top: 3px;
}
.toggle__price { margin-left: auto; font-size: .84rem; color: var(--ink-45); white-space: nowrap; }

.result {
  position: sticky; top: 96px;
  background: var(--night); color: var(--ink-on-dark);
  border-radius: var(--r-lg);
  padding: 26px;
  display: grid; gap: 16px;
}
.result__range {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1.85rem, 3.6vw, 2.6rem);
  line-height: 1.05; letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}
.result__bar { height: 6px; border-radius: 999px; background: rgba(244,239,232,.16); overflow: hidden; }
.result__bar i { display: block; height: 100%; background: var(--clay); border-radius: 999px; transition: width .35s ease, margin-left .35s ease; }
.result__lines { display: grid; gap: 9px; font-size: .86rem; color: rgba(244,239,232,.68); }
.result__lines div { display: flex; justify-content: space-between; gap: 14px; }
.result__lines b { font-weight: 600; color: var(--ink-on-dark); font-variant-numeric: tabular-nums; }

/* --- 16. Answers accordion ---------------------------------------------- */

.qa { border-top: 1px solid var(--line); }
.qa__item { border-bottom: 1px solid var(--line); }
.qa__q {
  width: 100%;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
  padding: 22px 0;
  text-align: left;
  font-family: var(--display); font-size: clamp(1.05rem, 1.6vw, 1.25rem); font-weight: 600;
  letter-spacing: -.02em; line-height: 1.3;
}
.qa__q:hover { color: var(--clay); }
.qa__icon {
  flex: none; width: 30px; height: 30px; margin-top: 1px;
  border-radius: 50%; border: 1.5px solid var(--line);
  display: grid; place-items: center;
  transition: transform .25s ease, background .2s ease, border-color .2s ease, color .2s ease;
}
.qa__q[aria-expanded="true"] .qa__icon { transform: rotate(45deg); background: var(--ink); border-color: var(--ink); color: var(--cream); }
.qa__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s ease; }
.qa__a > div { overflow: hidden; }
.qa__item.is-open .qa__a { grid-template-rows: 1fr; }
.qa__a p { padding-bottom: 24px; max-width: 68ch; color: var(--ink-70); }
.qa__a p + p { padding-top: 12px; }

/* --- 17. Commitment ladder ---------------------------------------------- */

.ladder { display: grid; gap: 12px; }
@media (min-width: 780px)  { .ladder { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1080px) { .ladder { grid-template-columns: repeat(4, minmax(0,1fr)); } }

.rung {
  display: flex; flex-direction: column; gap: 10px;
  padding: 22px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-dark);
  background: var(--night-2);
  color: var(--ink-on-dark);
  min-height: 210px;
  transition: border-color .2s ease, transform .2s ease;
}
.rung:hover { border-color: rgba(244,239,232,.4); transform: translateY(-2px); }
.rung p { color: rgba(244,239,232,.66); font-size: .9rem; line-height: 1.55; }
.rung__cta { margin-top: auto; font-weight: 600; font-size: .9rem; color: var(--clay); display: inline-flex; gap: 7px; align-items: center; }
.rung--final { background: var(--clay); border-color: var(--clay); }
.rung--final p { color: rgba(255,255,255,.85); }
.rung--final .rung__cta { color: #fff; }
.rung--final .tag { background: rgba(255,255,255,.2); color: #fff; }

/* --- 18. Footer --------------------------------------------------------- */

.site-footer { background: var(--night); color: var(--ink-on-dark); padding-block: clamp(48px, 6vw, 76px) 32px; }
.site-footer__grid { display: grid; gap: 32px; }
@media (min-width: 820px) { .site-footer__grid { grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 40px; } }
.site-footer h4 {
  font-family: var(--body); font-size: .74rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgba(244,239,232,.5); margin-bottom: 14px;
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.site-footer a { color: rgba(244,239,232,.82); font-size: .93rem; }
.site-footer a:hover { color: var(--clay); }
.site-footer__base {
  margin-top: 44px; padding-top: 22px;
  border-top: 1px solid var(--line-dark);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 14px;
  font-size: .84rem; color: rgba(244,239,232,.5);
}

/* --- 19. Sticky mobile action bar --------------------------------------- */

.actionbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--line);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
@media (min-width: 1000px) { .actionbar { display: none; } }
.actionbar a {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 56px;
  background: var(--paper);
  font-weight: 600; font-size: .95rem;
}
.actionbar a:last-child { background: var(--clay); color: #fff; }
body:has(.actionbar) { padding-bottom: 58px; }
@media (min-width: 1000px) { body:has(.actionbar) { padding-bottom: 0; } }

/* --- 20. Service page --------------------------------------------------- */

.svc-hero { display: grid; gap: 24px; align-items: center; }
@media (min-width: 940px) { .svc-hero { grid-template-columns: minmax(0,1fr) minmax(0,1.1fr); gap: 48px; } }

.spec { display: grid; gap: 0; border-top: 1px solid var(--line); }
.spec div { display: flex; justify-content: space-between; gap: 20px; padding: 15px 0; border-bottom: 1px solid var(--line); }
.spec dt { color: var(--ink-45); font-size: .9rem; margin: 0; }
.spec dd { margin: 0; font-weight: 600; font-size: .95rem; text-align: right; }

.callout {
  border-left: 3px solid var(--clay);
  background: var(--clay-50);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  padding: 20px 22px;
  display: grid; gap: 8px;
}

/* --- 21. Utilities ------------------------------------------------------ */

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.mt-auto { margin-top: auto; }
.center { text-align: center; }
[hidden] { display: none !important; }

/* ═══ Rebuild additions — breadcrumbs, gap markers, cluster links ═══════ */

.crumbs{border-bottom:1px solid var(--line);background:var(--paper)}
.crumbs .wrap{display:flex;flex-wrap:wrap;align-items:center;gap:2px;
  padding-top:14px;padding-bottom:14px;font-size:.86rem;color:var(--ink-45)}
.crumbs a{color:var(--ink-45);text-decoration:none}
.crumbs a:hover{color:var(--clay);text-decoration:underline}
.crumbs i{font-style:normal;opacity:.4;padding:0 8px}
.crumbs [aria-current]{color:var(--ink)}

/* Content gaps that need Malay's input. Deliberately loud — these must be
   impossible to miss in a browser, and must all be gone before launch.
   Search the built site for "needs-input" to find every remaining one. */
.needs{border:2px dashed #C2410C;background:#FFF7ED;border-radius:var(--r-sm);
  padding:18px 20px;margin:22px 0}
.needs::before{content:"⚠ NEEDS INPUT — not publishable yet";display:block;
  font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;
  font-weight:700;color:#C2410C;margin-bottom:8px}
.needs p{font-size:.93rem;color:#7C2D12;margin:0 0 6px}
.needs ul{margin:8px 0 0 18px;font-size:.93rem;color:#7C2D12}
.needs li{margin-bottom:4px}

/* A price band carried over as a market estimate rather than Wavify's own. */
.price-draft{border-bottom:1px dashed #C2410C;cursor:help}

/* Cluster navigation — the sibling/child links that carry topical authority. */
.cluster{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  margin-top:26px}
.cluster a{display:block;padding:18px 20px;border:1px solid var(--line);
  border-radius:var(--r-sm);text-decoration:none;background:var(--paper);
  transition:border-color .18s ease,transform .18s ease}
.cluster a:hover{border-color:var(--clay);transform:translateY(-2px)}
.cluster b{display:block;color:var(--ink);font-size:1rem;margin-bottom:5px}
.cluster span{display:block;color:var(--ink-45);font-size:.88rem;line-height:1.5}

/* Answer blocks written for passage extraction: a real heading, then a direct
   answer in the first sentence. This is what AI Overviews and Perplexity lift. */
.answer{padding:26px 0;border-top:1px solid var(--line)}
.answer h3{font-size:1.18rem;margin-bottom:10px}
.answer p{color:var(--ink-70);margin-bottom:10px}
.answer p:last-child{margin-bottom:0}

/* ═══ Responsive fixes ═════════════════════════════════════════════════════
   Found by an automated overflow pass across all 21 pages at 360, 375 and
   768px (Playwright, 24 Aug 2026). Three real bugs, root causes below.
   Deliberately NOT fixed with "body { overflow-x: hidden }" — that hides the
   symptom, keeps the broken layout, and blinds the test that found it.      */

/* 1. Grid and flex children default to min-width:auto, so they refuse to
      shrink below their min-content width. On /cost/estimator a single
      nowrap button label was setting a 357px floor on both grid columns,
      pushing the page 12px past a 360px viewport. */
.est > *,
.grid > *,
.svc-hero > *,
.room > *,
.ladder > *,
.cluster > * { min-width: 0; }

/* 2. A full-width button should wrap its own label rather than dictate the
      width of everything around it. */
.btn--block { white-space: normal; }

/* 3. Add-on rows keep the price on one line, but let it drop under the label
      when there is not room for both on a narrow phone. */
.toggle { flex-wrap: wrap; }
.toggle__name { flex: 1 1 auto; min-width: 0; }

/* 4. File paths and code fragments have no spaces to break at, so they ran
      past the right edge on the two newest service pages. */
code { overflow-wrap: anywhere; word-break: break-word; }

/* 5. Long unbroken strings anywhere in body copy (URLs, part numbers). */
p, li, dd, .lead, .small, .fine { overflow-wrap: break-word; }

/* --- 20. Long-form reading --------------------------------------------- */
/* Added 2026-08-24. Content-heavy pages had no rhythm: 79 always-open FAQ
   blocks, no entrance motion, no way to scan a 1,700-word guide. Everything
   here is driven by classes JS adds at runtime, so with JS off the page stays
   a flat readable document and nothing is hidden. No new colours: this is the
   existing clay/sand/ink system, used with more intention.                  */

/* Accordion. Reuses the grid-template-rows 0fr -> 1fr technique already
   proven in .qa__a, which animates height without measuring anything. */
.answer--collapsible { padding: 0; }
.answer__h { margin: 0; font-size: inherit; }
.answer__q {
  width: 100%;
  display: flex; align-items: flex-start; gap: 20px;
  padding: 22px 0;
  background: none; border: 0; cursor: pointer;
  font-family: var(--display); font-size: 1.18rem; font-weight: 600;
  line-height: 1.35; color: var(--ink); text-align: left;
  transition: color .2s ease;
}
.answer__q:hover { color: var(--clay); }
.answer__icon {
  flex: none; margin-left: auto; margin-top: 2px;
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--line); color: var(--ink-45);
  transition: transform .3s cubic-bezier(.2,.7,.3,1), background .2s ease,
              border-color .2s ease, color .2s ease;
}
.answer__q:hover .answer__icon { border-color: var(--clay); color: var(--clay); }
.answer--collapsible.is-open .answer__icon {
  transform: rotate(135deg);
  background: var(--clay); border-color: var(--clay); color: #fff;
}
.answer__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .34s cubic-bezier(.2,.7,.3,1); }
.answer__a > div { overflow: hidden; }
.answer--collapsible.is-open .answer__a { grid-template-rows: 1fr; }
.answer__a p { max-width: 68ch; padding-bottom: 4px; }
.answer__a > div > :last-child { padding-bottom: 24px; }

/* Entrance. One system, one curve, capped stagger. */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .6s cubic-bezier(.2,.7,.3,1), transform .6s cubic-bezier(.2,.7,.3,1);
  transition-delay: calc(var(--reveal-i, 0) * 60ms);
  will-change: opacity, transform;
}
.reveal.is-in { opacity: 1; transform: none; will-change: auto; }

/* On this page. Guides and blog articles only - see initToc() for the gate.
   Presented as a contained panel on the page grid rather than a loose list
   between two section bands, which is how it first shipped and read as
   something dropped in by accident. */
.toc-band { padding-top: 0; }
.toc {
  display: block;
  padding: 22px 24px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--clay);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--sand);
  max-width: 74ch;
}
.toc__label {
  display: block;
  font-size: .72rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--clay-700);
  margin-bottom: 12px;
}
.toc ol {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1px;
  counter-reset: toc;
}
.toc li { margin: 0; counter-increment: toc; }
.toc a {
  display: flex; gap: 12px; align-items: baseline;
  padding: 7px 0;
  color: var(--ink-70); font-size: .95rem; line-height: 1.4;
  text-decoration: none;
  transition: color .2s ease, transform .2s ease;
}
.toc a::before {
  content: counter(toc);
  flex: none; width: 1.3em;
  font-size: .78rem; font-weight: 700; color: var(--ink-45);
  font-variant-numeric: tabular-nums;
  transition: color .2s ease;
}
.toc a:hover { color: var(--ink); transform: translateX(3px); }
.toc a:hover::before { color: var(--clay); }
.toc a.is-active { color: var(--clay-700); font-weight: 600; }
.toc a.is-active::before { color: var(--clay); }

/* Reading progress. Two pixels, accent only, no chrome. */
.progress {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 60;
  pointer-events: none; background: transparent;
}
.progress i {
  display: block; height: 100%; background: var(--clay);
  transform: scaleX(0); transform-origin: 0 50%;
}

/* --- 21. Ambient ground ------------------------------------------------- */
/* Two effects, both nearly invisible on their own. The grain stops large flat
   cream areas reading as dead screen space; the wash gives sand and night
   bands a light source instead of a flat fill. Neither is decoration standing
   in for content, and both sit behind everything at z-index 0.              */

.section--sand, .section--night { position: relative; isolation: isolate; }
.section--sand::before, .section--night::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
}
.section--sand::before {
  background:
    radial-gradient(70% 55% at 12% 0%, rgba(199,91,44,.055), transparent 60%),
    radial-gradient(60% 50% at 92% 100%, rgba(199,91,44,.04), transparent 62%);
}
.section--night::before {
  background:
    radial-gradient(65% 55% at 84% 6%, rgba(199,91,44,.16), transparent 62%),
    radial-gradient(55% 45% at 6% 96%, rgba(244,239,232,.05), transparent 60%);
}
.section--sand > .wrap, .section--night > .wrap { position: relative; z-index: 1; }

/* Paper grain. One tiny inline SVG, tiled, fixed so it does not swim on
   scroll. Kept under 3% or it reads as a dirty screen. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: .028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --- 22. Micro-interactions -------------------------------------------- */

.link-arrow svg { transition: transform .22s cubic-bezier(.2,.7,.3,1); }
.link-arrow:hover svg { transform: translateX(4px); }

.cluster a { transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease; }
.cluster a:hover { box-shadow: var(--sh-1); }
.cluster b { transition: color .2s ease; }
.cluster a:hover b { color: var(--clay-700); }

/* Spec rows are pure data; a wash on hover helps the eye track across. */
.spec div { transition: background .18s ease, padding-left .18s ease; }
.spec div:hover { background: var(--clay-50); padding-left: 10px; }

.tag { transition: transform .18s ease; }
.card--hover:hover .tag { transform: translateY(-1px); }

.chip { transition: background .18s ease, border-color .18s ease, color .18s ease, transform .18s ease; }
.chip:hover { transform: translateY(-1px); }

.step__n { transition: color .25s ease; }
.step:hover .step__n { color: var(--clay); }

/* The site already ships a global prefers-reduced-motion clamp that kills
   durations. Reveal needs one extra rule: with transitions disabled, an
   element left at opacity 0 would never appear at all. */
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1 !important; transform: none !important; }
  body::after { display: none; }
}

/* 6. Tap targets. Measured at 375px: footer heading links were 18px tall,
      footer list links 18px, breadcrumb links 22px and the header logo 29px.
      Google's guidance is roughly 48px with 8px clearance. Padding grows the
      hit area without moving anything visually. */
@media (max-width: 900px) {
  .crumbs .wrap { padding-top: 3px; padding-bottom: 3px; }
  .crumbs a { padding-block: 11px; }
  .site-footer h4 a { display: inline-block; padding-block: 13px; }
  .site-footer li a { display: inline-block; padding-block: 9px; }
  .site-header .logo,
  .drawer__top .logo { display: inline-flex; align-items: center; min-height: 44px; }
}

/* --- 23. Guide media ---------------------------------------------------- */
/* Guides teach; service pages sell. The existing .ph__caption is always an
   OVERLAY on the photograph, which is right for atmosphere and wrong for
   explanation: it covers the thing it describes and it cannot run to two
   lines. Everything here exists so a guide can show evidence rather than
   decoration. See 2026-08-24-guide-media-spec.md.                          */

.figure { margin: 0 0 30px; max-width: 78ch; }
.figure .ph { border-radius: var(--r-md); }

/* Caption BELOW the image. Explanatory, can wrap, never covers the subject. */
.figure__cap {
  margin-top: 11px;
  font-size: .88rem; line-height: 1.6; color: var(--ink-45);
}
.figure__cap b, .figure__cap strong { color: var(--ink-70); font-weight: 600; }

/* Numbered markers laid over a photograph, keyed to the list beneath it.
   Position with inline --x / --y percentages:
     <span class="anno" style="--x:38%;--y:62%">1</span>                     */
.anno {
  position: absolute;
  left: var(--x, 50%); top: var(--y, 50%);
  transform: translate(-50%, -50%);
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--clay); color: #fff;
  font-family: var(--body); font-size: .78rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 3px rgba(255,255,255,.92), 0 2px 8px rgba(26,23,20,.35);
  z-index: 2;
}

/* The key that pairs with those markers. */
.figure__keys {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: grid; gap: 7px; counter-reset: anno;
}
.figure__keys li {
  counter-increment: anno;
  display: flex; gap: 10px; align-items: baseline;
  font-size: .88rem; line-height: 1.55; color: var(--ink-70);
}
.figure__keys li::before {
  content: counter(anno);
  flex: none; width: 19px; height: 19px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--clay-50); color: var(--clay-700);
  font-size: .7rem; font-weight: 700; font-variant-numeric: tabular-nums;
  transform: translateY(2px);
}

/* Tables. There were none anywhere in the guides and no styling for them,
   which is why the failures guide has no failure table. Wrap every table in
   .tbl-wrap so a wide one scrolls itself instead of the page. */
.tbl-wrap { overflow-x: auto; margin: 0 0 30px; -webkit-overflow-scrolling: touch; }
.tbl {
  width: 100%; border-collapse: collapse;
  font-size: .92rem; min-width: 520px;
}
.tbl caption {
  caption-side: bottom; margin-top: 11px;
  font-size: .84rem; color: var(--ink-45); text-align: left; line-height: 1.55;
}
.tbl th, .tbl td {
  text-align: left; padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.tbl thead th {
  font-family: var(--display); font-size: .78rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--clay-700);
  border-bottom: 1.5px solid var(--line);
  white-space: nowrap;
}
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr { transition: background .16s ease; }
.tbl tbody tr:hover { background: var(--clay-50); }
.tbl td b { color: var(--ink); }
.tbl .num { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- 24. Inline diagrams ------------------------------------------------ */
/* SVG rather than image files: scales, weighs nothing, and the labels stay
   real selectable text that a crawler and a screen reader can both read.    */

.dg { width: 100%; height: auto; display: block; }
.dg-wire   { fill: none; stroke-width: 2; stroke-linecap: round; }
.dg-live   { stroke: var(--clay); }
.dg-neutral{ stroke: var(--ink-45); }
.dg-box    { fill: none; stroke: var(--ink-45); stroke-width: 1.5; stroke-dasharray: 5 4; }
.dg-lamp   { fill: var(--paper); stroke: var(--ink-70); stroke-width: 1.8; }
.dg-node   { fill: var(--clay); }
.dg-label  { font-family: var(--body); font-size: 13px; fill: var(--ink-70); }
.dg-label--key { font-weight: 700; fill: var(--ink); }
.dg-cap    { font-family: var(--body); font-size: 12.5px; fill: var(--ink-45); }
