/* ==========================================================================
   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.
   ========================================================================== */

/* --- 0. Fonts ------------------------------------------------------------
   Self-hosted. These are Google's own subset files, served from our origin
   instead of fonts.gstatic.com: the same bytes the site shipped before, so
   nothing renders differently, but without the third-party DNS lookup, TLS
   handshake and stylesheet round trip that used to sit in front of first
   paint. 95.8 KB across four files, cached for a year under hashed-content
   names — if a font file is ever replaced, give it a NEW filename.

   Two subsets per family, split exactly as Google splits them. Latin-ext is
   fetched only when a character in its range appears, which on this site
   means the rupee sign (U+20B9) — so any priced page pulls both, and a page
   without a price pulls one. Licences ship alongside as *-OFL.txt.

   Both faces are variable across the weight range the stylesheet uses, so a
   single file per subset covers every weight. No italic is hosted: the four
   <em> tags on the site synthesise an oblique, which is what the Google
   version did too. Add an italic file if that ever stops being acceptable. */

@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/figtree-latin.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/figtree-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url('/assets/fonts/schibsted-grotesk-latin.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url('/assets/fonts/schibsted-grotesk-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- 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: 'Schibsted Grotesk', 'Segoe UI', system-ui, sans-serif;
  --body: 'Figtree', 'Segoe UI', system-ui, -apple-system, sans-serif;
  /* Figures ride the body face, not the display face. Both faces carry real
     tabular figures, so this is a legibility call rather than a technical one:
     Figtree's digits are the quieter of the two at price sizes, and it keeps
     every number on the page — hero stats, estimator output, table columns —
     in one voice. Switch this to var(--display) to put them back. */
  --num: var(--body);
}

@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; }

/* Size utilities, so heading LEVEL is chosen for document structure and SIZE
   for the design, independently.

   Card and callout titles were marked up by how big they should look, which
   put an h4 directly under an h2 on fourteen pages and, on /cost/estimator, an
   h4 directly under the h1. Screen-reader users navigating by heading landed
   in a level that skipped a rung, and the outline a model reads had holes.

   The tag now says where a thing sits in the document. The class says how big
   it renders. One class beats the bare element selectors above. */
.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; line-height: 1.08; }

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(--num);
  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(--num); 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; }

/* The rung titles are paragraphs, not headings: they are link labels on a CTA
   block that repeats on all 21 pages, and as headings they drowned every
   page's real outline. See src/partials/survey.html.

   This reproduces the h3 rule plus .section--night h3, so the change is
   invisible. Both selectors are two classes deep on purpose: .rung p and
   .rung--final p are (0,1,1) and would otherwise win and shrink these to
   body copy. */
.rung .rung__h {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.2rem, 1.7vw, 1.45rem);
  letter-spacing: -.02em;
  line-height: 1.18;
  margin: 0;
  text-wrap: balance;
  color: var(--ink-on-dark);
}
.rung--final .rung__h { color: var(--ink-on-dark); }

/* --- 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; }

/* Same visual language as .spec, but a real table with a header row.
   Used on /cost, where the three breakdowns are comparative price data.
   A definition list gives a parser the labels but never says what the values
   ARE: the numbers sat there with nothing declaring them price bands in
   rupees. A th scope="col" says it once, in a place a machine reads. */
.spec-table { width: 100%; border-collapse: collapse; border-top: 1px solid var(--line); }
.spec-table caption { text-align: left; color: var(--ink-45); font-size: .875rem; line-height: 1.55; padding-bottom: 14px; }
.spec-table thead th {
  font-size: .74rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-45); text-align: left; padding: 0 0 12px; border-bottom: 1px solid var(--line);
}
.spec-table thead th + th { text-align: right; }
.spec-table tbody th { color: var(--ink-45); font-size: .9rem; font-weight: 400; text-align: left; padding: 15px 20px 15px 0; border-bottom: 1px solid var(--line); }
.spec-table tbody td { font-weight: 600; font-size: .95rem; text-align: right; padding: 15px 0; border-bottom: 1px solid var(--line); }
.spec-table tbody tr { transition: background .18s ease; }
.spec-table tbody tr:hover { background: var(--clay-50); }

.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. */
/* The failures table is 689px wide on a 375px screen, so two of its five
   columns start out of sight. It always scrolled correctly — the page itself
   never moves sideways — but nothing announced that, because mobile browsers
   draw no scrollbar until a finger is already on the glass. On the one table
   the whole page is built around, that is the difference between a reader
   seeing three columns and seeing five.

   Three fixes, no JavaScript:

   1. Scrolling shadows. Four gradients: two the colour of the page painted
      with background-attachment:local so they travel with the content, and
      two dark ones painted with scroll so they stay pinned to the edges. The
      travelling pair covers the pinned pair exactly when that end is reached,
      so a shadow appears only while there is more table in that direction —
      and never appears at all on a screen wide enough to fit the whole thing.
      The rgba() stops must stay in step with --cream; a gradient fading to
      the keyword `transparent` greys out through transparent-black.

   2. tabindex and role. A scroll container that cannot take focus cannot be
      scrolled from a keyboard, so those two columns were genuinely
      unreachable without a mouse or a touchscreen. That was the real defect
      here; the missing shadow was only the visible half of it.

   3. A hint line, shown at the width where the table stops fitting. It reads
      as a sentence rather than an arrow because U+2192 is in neither font
      subset and would silently fall back to whatever the OS offers. */
.tbl-block { display: block; }

.tbl-hint { display: none; }
@media (max-width: 780px) {
  .tbl-hint {
    display: block;
    margin: 0 0 10px;
    font-size: .82rem; line-height: 1.5; color: var(--ink-45);
    max-width: 46ch;
  }
}

.tbl-wrap {
  overflow-x: auto;
  margin: 0 0 30px;
  -webkit-overflow-scrolling: touch;
  background:
    linear-gradient(to right, var(--cream) 42%, rgba(247, 244, 239, 0)) left center,
    linear-gradient(to left,  var(--cream) 42%, rgba(247, 244, 239, 0)) right center,
    radial-gradient(farthest-side at 0 50%,    rgba(26, 23, 20, .15), rgba(26, 23, 20, 0)) left center,
    radial-gradient(farthest-side at 100% 50%, rgba(26, 23, 20, .15), rgba(26, 23, 20, 0)) right center;
  background-repeat: no-repeat;
  background-size: 46px 100%, 46px 100%, 16px 100%, 16px 100%;
  background-attachment: local, local, scroll, scroll;
}
.tbl-wrap:focus-visible {
  outline: 2.5px solid var(--clay);
  outline-offset: 4px;
  border-radius: 6px;
}
.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); }
