/* ==========================================================================
   RenoFriend — INSTRUMENT
   Landing mockup stylesheet.
   Token block below is A9-1 verbatim. Do not fork it, do not "improve" it.
   Everything under TOKENS is composition built on top of those tokens only.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS — canonical, from Instrument Kit Rev 06 sheet A-9 §A9-1
   -------------------------------------------------------------------------- */
:root{
  /* dark grounds */
  --ink-black: #0C0F10;  --graphite: #161A1C;  --charcoal: #22272A;  --slate: #343A3E;
  --text-1: #F2F5F7;  --text-2: #A8B2BA;  --text-3: #8A939B;

  /* light grounds */
  --canvas: #E4E8EA;  --sheet: #EFF2F3;  --raised: #F8FAFA;
  --hairline: #D3D8DA;  --hairline-strong: #B9C0C3;
  --ink: #1A1F22;  --ink-2: #545E66;  --ink-3: #77828A;

  /* measurement */
  --datum: #5E9FBF;  --datum-active: #8FC3DA;  --datum-idle: #3E6E86;

  /* action — exactly one per screen */
  --action: #F97316;  --action-hover: #FB8A38;  --action-pressed: #DE650C;

  /* status */
  --warn-d: #E8C838;  --warn-l: #725B10;  --ok-d: #4AD07E;  --ok-l: #166534;
  --danger-d: #FF6B5E;  --danger-l: #B91C1C;

  /* space */
  --space-xs: 4px;  --space-sm: 8px;  --space-md: 16px;  --space-lg: 24px;
  --space-xl: 40px;  --space-2xl: 64px;  --space-section: clamp(64px, 10vw, 140px);

  /* radius */
  --r0: 0;  --r4: 4px;  --r10: 10px;  --r-full: 999px;

  /* type */
  --font: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --t-hero: clamp(34px, 4.6vw, 64px);    /* 700 / -0.035em / 1.06 */
  --t-display: clamp(28px, 3.2vw, 44px); /* 700 / -0.03em / 1.14 */
  --t-title: clamp(22px, 2.4vw, 32px);   /* 700 / -0.025em / 1.19 */
  --t-section: 24px;                     /* 600 / -0.02em */
  --t-body: 15px;                        /* 400 / 1.47 */
  --t-small: 13px;
  --t-label: 11px;                       /* 500 / +0.06em / UPPERCASE */

  /* motion */
  --dur-press: 120ms;  --dur-fast: 160ms;  --dur-base: 200ms;
  --dur-slow: 280ms;   --dur-scroll: 500ms;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);

  /* elevation */
  --hairline-up: inset 0 1px 0 rgba(255,255,255,.28);
  --cast: 0 18px 40px -18px rgba(12,15,16,.35);

  /* composition */
  --container: 1200px;
  --nav-h: 64px;
}

/* --------------------------------------------------------------------------
   2. RESET + BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after{ box-sizing: border-box; }
html{ -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 88px; }
body{
  margin: 0;
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: 1.47;
  color: var(--ink);
  background: var(--sheet);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'tnum' 1, 'ss01' 1;
  overflow-x: hidden;
}
img, svg, video{ max-width: 100%; display: block; }
h1,h2,h3,h4,h5,p,figure,blockquote{ margin: 0; }
ul,ol{ margin: 0; padding: 0; list-style: none; }
button{ font: inherit; color: inherit; }
a{ color: inherit; }

/* Focus — A9-4. Never removed, never browser default. */
:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }
[data-ground="ink-black"] :focus-visible,
[data-ground="graphite"] :focus-visible,
[data-ground="charcoal"] :focus-visible,
[data-ground="slate"] :focus-visible{ outline-color: var(--datum); }

::selection{ background: var(--action); color: #111417; }

/* --------------------------------------------------------------------------
   3. GROUNDS — A0·5: mid-grays are deleted. --ground never returns.
   -------------------------------------------------------------------------- */
/* --ground repeats the ground's own colour as a value a descendant can read.
   Anything that has to paint the ground back over itself — a scroller masking
   its own edge cue — needs the colour, and `background` is not readable. */
[data-ground]{ position: relative; }
[data-ground="ink-black"]{ background: var(--ink-black); color: var(--text-1); --ground: var(--ink-black); }
[data-ground="graphite"] { background: var(--graphite);  color: var(--text-1); --ground: var(--graphite); }
[data-ground="charcoal"] { background: var(--charcoal);  color: var(--text-1); --ground: var(--charcoal); }
[data-ground="slate"]    { background: var(--slate);     color: var(--text-1); --ground: var(--slate); }
[data-ground="canvas"]   { background: var(--canvas);    color: var(--ink); --ground: var(--canvas); }
[data-ground="sheet"]    { background: var(--sheet);     color: var(--ink); --ground: var(--sheet); }
[data-ground="raised"]   { background: var(--raised);    color: var(--ink); --ground: var(--raised); }

[data-ground="ink-black"] .dim, [data-ground="graphite"] .dim,
[data-ground="charcoal"] .dim,  [data-ground="slate"] .dim{ color: var(--text-2); }
.dim{ color: var(--ink-2); }

[data-ground="ink-black"] .dimmer, [data-ground="graphite"] .dimmer,
[data-ground="charcoal"] .dimmer,  [data-ground="slate"] .dimmer{ color: var(--text-3); }
.dimmer{ color: var(--ink-2); font-size: 18px; }
/* A raised panel lifts the ground one step toward the text. Step the ramp up with it,
   or tier 3 lands at 3.7:1 and stops being readable. */
[data-ground="ink-black"] .panel--raised .dimmer,
[data-ground="graphite"]  .panel--raised .dimmer,
[data-ground="charcoal"]  .panel--raised .dimmer{ color: var(--text-2); }

/* Hairline that flips with the ground */
[data-ground="ink-black"], [data-ground="graphite"],
[data-ground="charcoal"],  [data-ground="slate"]{ --rule: rgba(242,245,247,.13); --rule-strong: rgba(242,245,247,.24); }
[data-ground="canvas"], [data-ground="sheet"], [data-ground="raised"]{ --rule: var(--hairline); --rule-strong: var(--hairline-strong); }

/* --------------------------------------------------------------------------
   4. LAYOUT
   -------------------------------------------------------------------------- */
.wrap{ width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 24px; }
@media (max-width: 767px){ .wrap{ padding: 0 20px; } }

.band{ padding: var(--space-section) 0; }
.band--tight{ padding: var(--space-2xl) 0; }
.band--flush{ padding: 0; }

.grid{ display: grid; gap: var(--space-lg); }
/* Grid and flex children get min-width:auto, which resolves to min-content. A wide
   child (the estimate table) then forces its track past the container and the whole
   page scrolls sideways on a phone. The table already has .matrix__scroll around it —
   this lets that container actually do its job. */
.grid > *, .hero__grid > *, .foot__grid > *,
.numlist > li, .numlist > li > *, .stack > *{ min-width: 0; }
.g2{ grid-template-columns: repeat(2, 1fr); }
.g3{ grid-template-columns: repeat(3, 1fr); }
.g4{ grid-template-columns: repeat(4, 1fr); }
.g-auto{ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.g-7-5{ grid-template-columns: 7fr 5fr; align-items: center; gap: var(--space-2xl); }
.g-5-7{ grid-template-columns: 5fr 7fr; align-items: center; gap: var(--space-2xl); }
@media (max-width: 1023px){
  .g4{ grid-template-columns: repeat(2, 1fr); }
  .g-7-5, .g-5-7{ grid-template-columns: 1fr; gap: var(--space-xl); }
}
@media (max-width: 767px){
  .g2, .g3, .g4{ grid-template-columns: 1fr; }
}

.stack{ display: flex; flex-direction: column; }
.stack-xs > * + *{ margin-top: var(--space-xs); }
.stack-sm > * + *{ margin-top: var(--space-sm); }
.stack-md > * + *{ margin-top: var(--space-md); }
.stack-lg > * + *{ margin-top: var(--space-lg); }
.stack-xl > * + *{ margin-top: var(--space-xl); }
.row{ display: flex; align-items: center; gap: var(--space-md); flex-wrap: wrap; }
.measure{ max-width: 68ch; }
.measure-narrow{ max-width: 52ch; }

/* --------------------------------------------------------------------------
   5. TYPE
   -------------------------------------------------------------------------- */
/* Headlines are set at 41-54px in a 5-of-12 column, so the last word lands alone
   on its own line often enough to read as a habit rather than an accident — four
   of the thirty-one display headlines across the five pages, "written." and
   "going." and "touches." hanging by themselves under a full line of type. Let
   the browser even the lines out. Wrapping only: no size, colour or box changes,
   and Blink stops balancing past six lines, which no headline here reaches. */
.t-hero{ font-size: var(--t-hero); font-weight: 700; letter-spacing: -0.035em; line-height: 1.06; text-wrap: balance; }
.t-display{ font-size: var(--t-display); font-weight: 700; letter-spacing: -0.03em; line-height: 1.14; text-wrap: balance; }
.t-title{ font-size: var(--t-title); font-weight: 700; letter-spacing: -0.025em; line-height: 1.19; text-wrap: balance; }
.t-section{ font-size: var(--t-section); font-weight: 600; letter-spacing: -0.02em; line-height: 1.3; }
.t-body{ font-size: var(--t-body); font-weight: 400; line-height: 1.47; }
.t-lead{ font-size: 18px; font-weight: 400; line-height: 1.58; }
.t-small{ font-size: var(--t-small); line-height: 1.55; }
[data-ground="ink-black"] .t-lead, [data-ground="graphite"] .t-lead,
[data-ground="charcoal"] .t-lead{ line-height: 1.64; } /* light-on-dark reads lighter */

.t-label{
  font-size: var(--t-label); font-weight: 500; letter-spacing: 0.06em;
  text-transform: uppercase; line-height: 1.4;
}
.t-num{ font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }
.orange{ color: var(--action); }
.datum{ color: var(--datum); }
[data-ground="canvas"] .datum, [data-ground="sheet"] .datum,
[data-ground="raised"] .datum{ color: var(--datum-idle); } /* datum is NON-TEXT on light */

/* --------------------------------------------------------------------------
   6. SECTION MARKER — the drafting-sheet register. §NN / NAME on a hairline.
   -------------------------------------------------------------------------- */
.marker{
  display: flex; align-items: baseline; gap: 14px;
  margin-bottom: var(--space-xl);
}
/* Register numbers are MEASUREMENT, not action — datum, never orange. */
.marker__no{
  font-size: 13px; font-weight: 700; letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  color: var(--datum-idle);
}
[data-ground="ink-black"] .marker__no, [data-ground="graphite"] .marker__no,
[data-ground="charcoal"] .marker__no, [data-ground="slate"] .marker__no{ color: var(--datum); }
.marker__name{
  font-size: 13px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; line-height: 1.3;
  color: var(--ink);
}
[data-ground="ink-black"] .marker__name, [data-ground="graphite"] .marker__name,
[data-ground="charcoal"] .marker__name, [data-ground="slate"] .marker__name{ color: var(--text-1); }
.marker__rule{ flex: 1; background: var(--rule-strong); }
/* Meta is retired visually; the spans stay in markup. */
.marker__meta{ display: none; }

/* --------------------------------------------------------------------------
   7. BUTTONS — A-7 §2 ramps. Fill + inset hairline-up + press to 0.98.
   -------------------------------------------------------------------------- */
.btn{
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 20px;
  border: none; border-radius: var(--r4);
  font-size: 14px; font-weight: 600; letter-spacing: -0.005em;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition:
    background var(--dur-fast) var(--ease-out),
    transform var(--dur-press) var(--ease-out),
    box-shadow var(--dur-press) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}
.btn:active{ transform: scale(0.98); }
.btn--sm{ height: 38px; padding: 0 16px; font-size: 13px; }
.btn--lg{ height: 52px; padding: 0 26px; font-size: 15px; }

.btn--primary{ background: var(--action); color: #111417; box-shadow: var(--hairline-up); }
.btn--primary:hover{ background: var(--action-hover); }
.btn--primary:active{ background: var(--action-pressed); box-shadow: inset 0 1px 0 #9E4A08; }

.btn--secondary{ background: #E2E7E9; color: var(--ink); border: 1px solid var(--hairline-strong); box-shadow: inset 0 1px 0 #FFFFFF; }
.btn--secondary:hover{ background: #ECF0F1; }
.btn--secondary:active{ background: #CBD3D6; box-shadow: inset 0 1px 0 #9FA9AD; }
[data-ground="ink-black"] .btn--secondary,
[data-ground="graphite"] .btn--secondary,
[data-ground="charcoal"] .btn--secondary{
  background: #262C30; color: var(--text-1); border-color: #3C444C; box-shadow: inset 0 1px 0 #3A4247;
}
[data-ground="ink-black"] .btn--secondary:hover,
[data-ground="graphite"] .btn--secondary:hover,
[data-ground="charcoal"] .btn--secondary:hover{ background: #31383D; }

.btn--ghost{ background: transparent; color: inherit; }
.btn--ghost:hover{ background: #E2E7E9; }
[data-ground="ink-black"] .btn--ghost:hover,
[data-ground="graphite"] .btn--ghost:hover,
[data-ground="charcoal"] .btn--ghost:hover{ background: #262C30; }

/* Text link — underline, no orange. Orange is for the one action. */
.tlink{
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 14px; font-weight: 600; letter-spacing: -0.005em;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 1px; text-decoration-color: var(--rule-strong);
  transition: color var(--dur-fast) var(--ease-out), text-decoration-color var(--dur-fast) var(--ease-out);
}
.tlink:hover{ color: #AD3A08; text-decoration-color: currentColor; }
[data-ground="ink-black"] .tlink:hover,
[data-ground="graphite"] .tlink:hover,
[data-ground="charcoal"] .tlink:hover{ color: var(--datum-active); }
.tlink svg{ transition: transform var(--dur-base) var(--ease-out); }
.tlink:hover svg{ transform: translateX(3px); }

/* --------------------------------------------------------------------------
   8. PANEL — hairline box, never a rounded card with a drop shadow.
   Corner registration ticks are the Instrument signature.
   -------------------------------------------------------------------------- */
.panel{
  position: relative;
  border: 1px solid var(--rule);
  background: transparent;
  padding: var(--space-lg);
}
.panel--raised{ background: var(--raised); }
[data-ground="ink-black"] .panel--raised{ background: var(--graphite); }
[data-ground="graphite"]  .panel--raised{ background: var(--charcoal); }
[data-ground="charcoal"]  .panel--raised{ background: var(--slate); }
.panel--flush{ padding: 0; }
.panel--pad-lg{ padding: var(--space-xl); }

/* registration ticks: four L-corners drawn 1px, offset outside the box.
   Datum, not orange — a crop mark is measurement, not an action. */
.ticked{ position: relative; }
.ticked::before, .ticked::after{
  content: ''; position: absolute; width: 9px; height: 9px; pointer-events: none;
  border-color: var(--datum-idle); border-style: solid;
}
[data-ground="ink-black"] .ticked::before, [data-ground="graphite"] .ticked::before,
[data-ground="charcoal"] .ticked::before, [data-ground="ink-black"] .ticked::after,
[data-ground="graphite"] .ticked::after, [data-ground="charcoal"] .ticked::after{ border-color: var(--datum); }
.ticked::before{ top: -1px; left: -1px; border-width: 1px 0 0 1px; }
.ticked::after{ bottom: -1px; right: -1px; border-width: 0 1px 1px 0; }

/* --------------------------------------------------------------------------
   9. NAV — A9-3. Sticky 64px, transparent over hero, resolves on scroll.
   -------------------------------------------------------------------------- */
.nav{
  position: sticky; top: 0; z-index: 60; height: var(--nav-h);
  display: flex; align-items: center;
  background: transparent; border-bottom: 1px solid transparent;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.nav.is-resolved{ background: var(--sheet); border-bottom-color: var(--hairline); color: var(--ink); }
.nav.is-resolved .nav__links a{ color: var(--ink); }
.nav.is-resolved .lockup{ color: var(--ink); }
.nav__inner{ width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 24px;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-lg); }
@media (max-width: 767px){ .nav__inner{ padding: 0 20px; } }

.lockup{ display: inline-flex; align-items: center; gap: 9px; text-decoration: none; color: var(--text-1); }
.lockup__mark{ width: 24px; height: 24px; flex: none; }
.lockup__word{ font-size: 18px; font-weight: 600; letter-spacing: -0.02em; }

.nav__links{ display: flex; align-items: center; gap: 4px; }
.nav__links a{
  padding: 8px 12px; font-size: 13px; font-weight: 500; text-decoration: none;
  color: var(--text-1); border-radius: var(--r4);
  transition: background var(--dur-fast) var(--ease-out);
}
.nav__links a:hover{ background: rgba(242,245,247,.09); }
.nav.is-resolved .nav__links a:hover{ background: #E2E7E9; }
.nav__links a[aria-current="page"]{ box-shadow: inset 0 -1px 0 currentColor; }
.nav__cta{ display: flex; align-items: center; gap: 8px; }
/* One orange per screen: the hero owns the orange until the nav resolves. */
.nav[data-nav-over-hero]:not(.is-resolved) .nav__cta .btn--primary{
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.nav .nav__cta .btn--primary{ transition: opacity var(--dur-base) var(--ease-out), background var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out); }
.nav__burger{ display: none; }

@media (max-width: 1023px){
  .nav__links{ display: none; }
  .nav__burger{
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border: 1px solid var(--rule-strong);
    background: transparent; border-radius: var(--r4); cursor: pointer;
  }
  .nav.is-resolved .nav__burger{ border-color: var(--hairline-strong); }
}
.drawer{
  position: fixed; inset: var(--nav-h) 0 auto 0; z-index: 59;
  background: var(--raised); border-bottom: 1px solid var(--hairline);
  transform: translateY(-8px); opacity: 0; visibility: hidden;
  transition: transform var(--dur-slow) var(--ease-in-out), opacity var(--dur-slow) var(--ease-in-out), visibility var(--dur-slow);
}
.drawer.is-open{ transform: translateY(0); opacity: 1; visibility: visible; }
.drawer > a{
  display: block; padding: 16px 20px; text-decoration: none; color: var(--ink);
  font-size: 16px; font-weight: 500; border-bottom: 1px solid var(--hairline);
}
.drawer > a:last-of-type{ border-bottom: none; }
/* On phones the drawer is the whole nav, so the primary action can't be the
   sixth item in a list of destinations. Same button the desktop nav carries,
   run full-width so the thumb gets the entire row. */
.drawer__foot{ padding: 16px 20px; border-top: 1px solid var(--hairline); }
.drawer__foot .btn{ width: 100%; }

/* --------------------------------------------------------------------------
   10. HERO
   -------------------------------------------------------------------------- */
.hero{ position: relative; overflow: hidden; padding: clamp(56px, 9vw, 120px) 0 clamp(64px, 9vw, 128px); margin-top: calc(var(--nav-h) * -1); padding-top: calc(clamp(56px, 9vw, 120px) + var(--nav-h)); }
.hero__grid{ display: grid; grid-template-columns: 6.5fr 5.5fr; gap: var(--space-2xl); align-items: center; }
@media (max-width: 1023px){ .hero__grid{ grid-template-columns: 1fr; gap: var(--space-xl); } }

/* faint drafting grid, ink-black only. Not a gradient, not a glow. */
.hero::before{
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(242,245,247,.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(242,245,247,.045) 1px, transparent 1px);
  background-size: 96px 96px;
  mask-image: radial-gradient(120% 90% at 78% 40%, #000 0%, transparent 72%);
  -webkit-mask-image: radial-gradient(120% 90% at 78% 40%, #000 0%, transparent 72%);
}
.hero__inner{ position: relative; z-index: 1; }

.eyebrow{
  display: inline-flex; align-items: center; gap: 9px; width: fit-content;
  padding: 6px 11px 6px 9px; border: 1px solid var(--rule-strong); border-radius: var(--r-full);
  font-size: var(--t-label); font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase;
}
.eyebrow__dot{ width: 6px; height: 6px; background: var(--datum); flex: none; }
[data-ground="canvas"] .eyebrow__dot, [data-ground="sheet"] .eyebrow__dot,
[data-ground="raised"] .eyebrow__dot{ background: var(--datum-idle); }

/* --------------------------------------------------------------------------
   11. LEDGER — the pain list. Numbered rows on hairlines. No cards.
   -------------------------------------------------------------------------- */
.ledger{ border-top: 1px solid var(--rule); }
.ledger__row{
  display: grid; grid-template-columns: 56px 1fr auto; gap: var(--space-lg);
  align-items: start; padding: var(--space-lg) 0;
  border-bottom: 1px solid var(--rule);
}
.ledger__no{
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums; padding-top: 5px;
  color: var(--ink-2);
}
[data-ground="ink-black"] .ledger__no, [data-ground="graphite"] .ledger__no,
[data-ground="charcoal"] .ledger__no{ color: var(--text-3); }
.ledger__cost{
  text-align: right; font-variant-numeric: tabular-nums;
  font-size: 15px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--danger-l); white-space: nowrap; padding-top: 2px;
}
[data-ground="ink-black"] .ledger__cost, [data-ground="graphite"] .ledger__cost,
[data-ground="charcoal"] .ledger__cost{ color: var(--danger-d); }
@media (max-width: 767px){
  .ledger__row{ grid-template-columns: 40px 1fr; gap: var(--space-md); }
  .ledger__cost{ grid-column: 2; text-align: left; padding-top: 0; }
}

/* --------------------------------------------------------------------------
   12. STEP — how it works
   -------------------------------------------------------------------------- */
.step{ display: flex; flex-direction: column; gap: var(--space-md); }
.step__head{ display: flex; align-items: center; gap: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--rule); }
.step__no{
  width: 30px; height: 30px; flex: none; display: grid; place-items: center;
  border: 1px solid var(--rule-strong); font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.step__media{
  aspect-ratio: 4 / 3; border: 1px solid var(--rule); background: var(--canvas);
  display: grid; place-items: center; position: relative; overflow: hidden;
}
[data-ground="ink-black"] .step__media, [data-ground="graphite"] .step__media,
[data-ground="charcoal"] .step__media{ background: var(--charcoal); }

/* --------------------------------------------------------------------------
   13. MEDIA SLOT — labelled placeholder for the real photography (A9-5)
   -------------------------------------------------------------------------- */
.slot{
  position: relative; border: 1px solid var(--rule); background: var(--canvas);
  display: grid; place-items: center; overflow: hidden;
}
[data-ground="ink-black"] .slot, [data-ground="graphite"] .slot,
[data-ground="charcoal"] .slot{ background: #1B2023; }
.slot::after{
  content: attr(data-slot);
  position: absolute; left: 10px; bottom: 9px;
  font-size: 9px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3); pointer-events: none;
}
[data-ground="ink-black"] .slot::after, [data-ground="graphite"] .slot::after,
[data-ground="charcoal"] .slot::after{ color: var(--text-3); }
.slot__cross{ position: absolute; inset: 0; pointer-events: none; opacity: .28; }
.slot--16x9{ aspect-ratio: 16 / 9; }
.slot--4x3{ aspect-ratio: 4 / 3; }
.slot--3x4{ aspect-ratio: 3 / 4; }
.slot--1x1{ aspect-ratio: 1 / 1; }
/* Dropping the real photo in is one line — put an <img> or <video> inside the
   slot and the placeholder furniture gets out of the way on its own. The cross
   and the size stamp are scaffolding; once there is real media they would only
   print on top of it. Slot keeps its aspect ratio, so the crop is decided here
   and not by whatever the camera happened to shoot. */
.slot > img, .slot > video{
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.slot:has(> img)::after, .slot:has(> video)::after{ content: none; }
.slot:has(> img) .slot__cross, .slot:has(> video) .slot__cross{ display: none; }

/* --------------------------------------------------------------------------
   14. PHONE — the device frame used to show app screens
   -------------------------------------------------------------------------- */
.phone{
  width: 100%; max-width: 300px; aspect-ratio: 393 / 852;
  border: 1px solid var(--rule-strong); border-radius: 26px;
  background: var(--graphite); padding: 8px; position: relative;
  box-shadow: var(--cast);
}
/* Once the paired grids collapse the phone is alone on the row, so its 300px
   cap has to centre — left-flush leaves ~50px of dead air down one side. */
@media (max-width: 767px){ .phone{ margin-inline: auto; } }
.phone__screen{
  width: 100%; height: 100%; border-radius: 19px; overflow: hidden;
  background: var(--ink-black); display: flex; flex-direction: column;
  position: relative; /* containing block for the floating action bar */
}
.phone__notch{
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  width: 78px; height: 20px; border-radius: var(--r-full); background: var(--ink-black); z-index: 2;
}

/* Screen content — schematic app UI drawn inside .phone__screen.
   Hairlines are hard-coded here because the phone is always dark, whatever
   ground it is standing on. */
.scr__bar{ padding: 34px 14px 12px; border-bottom: 1px solid rgba(242,245,247,.13); }
.scr__eyebrow{ font-size: 10px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--text-3); }
.scr__title{ margin-top: 4px; font-size: 16px; font-weight: 600; letter-spacing: -.02em; color: var(--text-1); }
.scr__media{ position: relative; aspect-ratio: 4 / 3; background: #1B2023; display: grid; place-items: center;
  border-bottom: 1px solid rgba(242,245,247,.13); color: var(--text-3); }
.scr__rows{ padding: 4px 14px 10px; }
.scr__row{ display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid rgba(242,245,247,.09); }
.scr__row:last-child{ border-bottom: none; }
.scr__k{ font-size: 12px; color: var(--text-2); }
.scr__v{ font-size: 12px; font-weight: 600; color: var(--text-1); font-variant-numeric: tabular-nums; }
.scr__total{ padding: 11px 14px; border-top: 1px solid rgba(242,245,247,.24);
  display: flex; align-items: baseline; justify-content: space-between; }
.scr__total b{ font-size: 19px; font-weight: 700; letter-spacing: -.03em; color: var(--text-1); font-variant-numeric: tabular-nums; }
/* Floating action bar. The real iOS app has NO tab bar — it has one light
   capsule hovering over the content: a raised white [+] tile and an orange
   camera tile. The orange here is device chrome, not page accent, so it does
   not spend the one-orange budget of the band the phone stands in.
     <div class="scr__actionbar">
       <button class="scr__act" aria-label="New job"><svg><use href="#ic-plus"/></svg></button>
       <button class="scr__act scr__act--capture" aria-label="Capture"><svg><use href="#ic-camera"/></svg></button>
     </div> */
.scr__actionbar{
  position: absolute; left: 50%; bottom: 16px; z-index: 3;
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px;
  padding: 7px; border-radius: var(--r-full);
  background: var(--sheet);
  box-shadow: 0 12px 26px -10px rgba(12,15,16,.8), var(--cast), var(--hairline-up);
}
.scr__act{
  appearance: none; -webkit-appearance: none; border: none; padding: 0; margin: 0;
  width: 38px; height: 38px; border-radius: 12px; cursor: pointer;
  display: grid; place-items: center;
  background: var(--raised); color: var(--ink);
  box-shadow: 0 2px 5px -2px rgba(12,15,16,.38), var(--hairline-up);
  transition: transform var(--dur-press) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.scr__act svg{ width: 15px; height: 15px; }
.scr__act:active{ transform: scale(0.97); }

.scr__act--capture{ background: var(--action); color: #111417;
  box-shadow: 0 3px 8px -3px rgba(249,115,22,.6), var(--hairline-up); }
.scr__act--capture:hover{ background: var(--action-hover); }
.scr__act--capture:active{ background: var(--action-pressed); }

/* --------------------------------------------------------------------------
   14b. WINDOW — the desktop frame, sibling to PHONE

   The phone shows what happens on site. This shows what the same job looks
   like back at the office, and the two are meant to be composited: window
   behind, phone overlapping a corner in front.

   No traffic lights. Three coloured dots would import somebody else's brand
   palette into a page that spends exactly one accent, so the dots are drawn
   as hairline rings — enough signal to read "browser", nothing borrowed. The
   address pill is the only thing in the bar carrying information, so it is
   the only thing with contrast, and it is centred by an empty third column
   rather than by a spacer element.

     <div class="win">
       <div class="win__bar">
         <span class="win__dots" aria-hidden="true"><i></i><i></i><i></i></span>
         <span class="win__url"><svg><use href="#ic-lock"/></svg>app.renofriend.com/j/0412</span>
       </div>
       <div class="win__view slot slot--16x9" data-slot="…">…</div>
     </div>
   -------------------------------------------------------------------------- */
.win{
  border: 1px solid var(--rule-strong); border-radius: var(--r10);
  background: var(--raised); box-shadow: var(--cast);
  overflow: hidden;
}
[data-ground="ink-black"] .win, [data-ground="graphite"] .win,
[data-ground="charcoal"] .win{ background: var(--graphite); }
.win__bar{
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: var(--space-md); height: 38px; padding: 0 12px;
  border-bottom: 1px solid var(--rule);
}
.win__dots{ display: flex; gap: 6px; }
.win__dots i{
  width: 9px; height: 9px; border-radius: var(--r-full);
  border: 1px solid var(--rule-strong);
}
.win__url{
  display: flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 3px 12px; border: 1px solid var(--rule); border-radius: var(--r-full);
  background: var(--sheet); color: var(--ink-2);
  font-size: 11px; letter-spacing: .01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
[data-ground="ink-black"] .win__url, [data-ground="graphite"] .win__url,
[data-ground="charcoal"] .win__url{ background: var(--ink-black); color: var(--text-2); }
.win__url svg{ width: 10px; height: 10px; flex: none; color: var(--ink-3); }
[data-ground="ink-black"] .win__url svg, [data-ground="graphite"] .win__url svg,
[data-ground="charcoal"] .win__url svg{ color: var(--text-3); }
/* the viewport is a MEDIA SLOT — it keeps the label and the cross, but the
   frame already draws the border, so the slot must not draw a second one */
.win__view{ border: none; }

/* --------------------------------------------------------------------------
   15. TABLE — comparison matrix
   -------------------------------------------------------------------------- */
/* Capped, not stretched. At 100% of a wide wrap the four mark columns
   balloon until an 18px check floats in a county of whitespace and the
   whole thing reads as a spreadsheet, not an argument. ~880px keeps every
   mark within a glance of its row label; the leftover wrap width stays
   empty on the right, which is the kit's asymmetry, not a bug.
   table-layout:fixed hands the thead the column widths so no cell's
   content can wobble them. */
.matrix{
  width: 100%; max-width: 880px; margin-inline: auto; table-layout: fixed;
  border-collapse: collapse; font-variant-numeric: tabular-nums;
}
/* The caption names the table for assistive tech. It restates the headline
   sitting directly above it, so it is carried but not drawn. */
.matrix caption{
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.matrix th, .matrix td{
  padding: 14px 16px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--rule); font-size: 14px;
}
.matrix thead th{
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  border-bottom: 1px solid var(--rule-strong); white-space: nowrap;
  vertical-align: bottom;
}
/* The capability column reads, the four brand columns are scanned — so the
   labels stay left and everything else centers over its marks. 38% + 4 equal
   shares of the rest ≈ 334px of prose against ~136px per brand at full width. */
.matrix thead th:first-child{ width: 38%; }
.matrix thead th:not(:first-child){ text-align: center; }
/* Price sits under the name, not welded to it. */
.matrix thead th small{
  display: block; margin-top: 6px;
  font-size: 11px; font-weight: 500; letter-spacing: 0.02em; text-transform: none;
  color: var(--ink-3);
}
[data-ground="ink-black"] .matrix thead th small, [data-ground="graphite"] .matrix thead th small,
[data-ground="charcoal"] .matrix thead th small,  [data-ground="slate"] .matrix thead th small{ color: var(--text-3); }
.matrix tbody th{ font-weight: 500; font-size: 14px; letter-spacing: -0.005em; vertical-align: middle; }
/* Marks center under their brand and sit on the row's optical middle. A
   left-aligned check at the mouth of a wide cell is the loudest of the
   spreadsheet tells this block exists to kill. */
.matrix tbody td{ text-align: center; vertical-align: middle; }
.matrix tbody td .mark-y, .matrix tbody td .mark-n, .matrix tbody td .mark-p{ margin-inline: auto; }
/* Each mark gets a lane. A check 500px from its label floats in open
   whitespace unless the column it belongs to is drawn — one hairline on
   every data cell's leading edge fences the four brand columns without
   boxing the table. tbody only: the header row stays open above its
   columns, and the group rows (colspan) break the verticals into
   per-section runs, which is rhythm, not damage. --rule flips with the
   ground token, so the dark variants come along for free. */
.matrix tbody tr:not(.matrix__group) td{ border-inline-start: 1px solid var(--rule); }
/* The qualifier under a mark ("Photo measure", "Flex plan+") is a footnote,
   not a second answer — smaller, quieter, and allowed to wrap. */
.matrix__note{
  display: block; margin-top: 5px;
  font-size: 11px; line-height: 1.35; letter-spacing: 0.01em;
  font-variant-numeric: normal; white-space: normal; color: var(--ink-3);
}
[data-ground="ink-black"] .matrix__note, [data-ground="graphite"] .matrix__note,
[data-ground="charcoal"] .matrix__note,  [data-ground="slate"] .matrix__note{ color: var(--text-3); }
.matrix .col-us{ background: rgba(94,159,191,.09); }
.matrix thead .col-us{ color: var(--ink); box-shadow: inset 0 2px 0 var(--datum-idle); }
[data-ground="ink-black"] .matrix .col-us, [data-ground="graphite"] .matrix .col-us{ background: rgba(94,159,191,.13); }
[data-ground="ink-black"] .matrix thead .col-us, [data-ground="graphite"] .matrix thead .col-us{ color: var(--text-1); box-shadow: inset 0 2px 0 var(--datum); }
/* The thead opens the table on a strong rule; the last row closes it on
   the same weight. Without the close the tbody peters out into the legend
   and the whole object reads unfinished — the "floating" tell. */
.matrix tr:last-child th, .matrix tr:last-child td{ border-bottom: 1px solid var(--rule-strong); }
/* Close the highlight rail: the 2px datum line that opens the RenoFriend
   column at the header returns under its last row, so the tint reads as one
   deliberate object with a top and a bottom, not a wash that peters out. */
.matrix tbody tr:last-child .col-us{ box-shadow: inset 0 -2px 0 var(--datum-idle); }
[data-ground="ink-black"] .matrix tbody tr:last-child .col-us,
[data-ground="graphite"] .matrix tbody tr:last-child .col-us{ box-shadow: inset 0 -2px 0 var(--datum); }
/* The price row is the one row read as numbers, and ours is the answer. */
.matrix .t-num{ font-size: 15px; }
.matrix td.col-us.t-num{ font-weight: 700; }
/* Row hover keeps the eye on one line across five columns — a reading aid,
   not decoration, so it is subtle and desktop-only. */
@media (hover: hover) and (pointer: fine){
  .matrix tbody th, .matrix tbody td{ transition: background-color 120ms var(--ease-out, ease-out); }
  .matrix tbody tr:not(.matrix__group):hover th,
  .matrix tbody tr:not(.matrix__group):hover td{ background-color: color-mix(in srgb, var(--ink) 4%, transparent); }
  .matrix tbody tr:not(.matrix__group):hover td.col-us{ background-color: color-mix(in srgb, #5E9FBF 16%, transparent); }
}
/* Group labels align to the capability column they caption — without an
   explicit left, tbody's center rule (.matrix tbody td, 0-1-2) outguns a
   bare .matrix__group td and drifts them to the middle of a colspan-5
   cell, captioning nothing. The tr. spelling keeps the specificity above
   it. Space above outweighs space below so each label binds down to its
   own rows, not up to the previous run. */
.matrix tr.matrix__group td{
  padding: 26px 16px 8px; text-align: left;
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2);
  border-bottom: 1px solid var(--rule-strong);
}
[data-ground="ink-black"] .matrix__group td, [data-ground="graphite"] .matrix__group td,
[data-ground="charcoal"] .matrix__group td,  [data-ground="slate"] .matrix__group td{ color: var(--text-2); }
.matrix__scroll{ overflow-x: auto; -webkit-overflow-scrolling: touch; }
@media (max-width: 767px){
  .matrix th, .matrix td{ padding: 12px; font-size: 13px; }
  .matrix{ min-width: 720px; }
  /* THE PEEK. The desktop split (38% + four equal shares) lands the RenoFriend
     column's right edge at 385px of a 390px phone — five pixels shy of the cut,
     which reads as a finished table and nobody swipes. A comparison nobody
     scrolls is a page of our own checkmarks.
     So the mobile split is computed backwards from the cut instead of inherited:
     hold the table at 720 and solve label + one brand = 366 so that ~24px of the
     SECOND brand column is visibly on screen at 390 — an obviously severed column,
     not a hairline. 248 + 4x118 = 720 exactly, and the label column keeps ~216px
     of prose after its 20+12 padding. Widths, not percentages: table-layout is
     fixed, so the thead row alone decides all five. */
  .matrix thead th:first-child{ width: 248px; }
  .matrix thead th:not(:first-child){ width: 118px; }
  /* Bleed to the viewport edges so the cut happens at the glass, and mark it:
     the radial layer is attachment:scroll so it sits on the visible right edge,
     the flat layer is attachment:local so it travels with the content and covers
     the shadow exactly when there is nothing left to the right. The cue leaves on
     its own, no script and no permanent decoration at the end of the scroll. The
     radial is 22px/26% rather than 16px/20% — against a real severed column it is
     the second half of one signal, and a signal read at a glance on a phone in
     daylight can't be a whisper. */
  .matrix__scroll{
    margin-inline: -20px;
    background:
      linear-gradient(to left, var(--ground, var(--sheet)) 60%, transparent) right / 24px 100% no-repeat local,
      radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, currentColor 26%, transparent), transparent) right / 22px 100% no-repeat scroll;
  }
  /* The page gutter rides on the cells, not on the scroller. Inset the scroller
     instead and the pinned column below stops 20px shy of the screen edge, so
     the columns passing behind it resurface in the margin — and box-shadow
     can't patch that, Blink drops shadows on cells once borders are collapsed. */
  .matrix th:first-child, .matrix td:first-child{ padding-left: 20px; }
  .matrix th:last-child,  .matrix td:last-child { padding-right: 20px; }
  /* Scrolled to the far column the reader is looking at a stack of bare marks
     with nothing to attach them to. Pin the capability column so the row keeps
     its name the whole way across. */
  .matrix tbody th, .matrix thead th:first-child{
    position: sticky; left: 0; z-index: 1;
    /* The one vertical rule in the table, and it earns it: it says the column is
       pinned rather than the table merely being oddly aligned, and it gives the
       columns sliding underneath an edge to disappear behind. It has to be drawn
       in the background — Blink paints neither border-right nor box-shadow on a
       sticky cell once the table's borders are collapsed. */
    background: linear-gradient(to left, var(--rule) 0 1px, var(--ground, var(--sheet)) 1px);
  }
  /* A colspan cell is as wide as its own row, so it has no sticky travel — the
     label inside it does. Without this the group headings scroll away and the
     lower half of the table arrives with no section names. */
  .matrix__group td > span{ position: sticky; left: 20px; display: inline-block; }
}

/* Thirteen rows and two group breaks is ~1,100px of table — long enough that the
   brand names leave the screen while the marks keep coming, and a checkmark with
   no column name over it is a mark against nobody. Pin the head under the nav.
   Two Blink facts shape the whole block:
   1. overflow-x:auto computes overflow-y to auto as well, so .matrix__scroll is a
      scroll container on BOTH axes and a top-sticky cell inside it sticks to a box
      that never scrolls vertically — i.e. does nothing. The head can only pin where
      the scroller is allowed to stop being a scroll container, which is where the
      880px table no longer overflows: 880 + 2x24 of wrap gutter = 928, so 960 with
      a little air. Below that the scroller stays and these rules simply never
      apply — no conflict with the mobile sticky-column block above.
   2. A sticky cell in a border-collapse table paints neither its borders nor its
      box-shadow (same fact the pinned column's background trick documents). So the
      head's closing rule and the RenoFriend column's 2px datum rail are both
      redrawn as background layers here, and the ground colour underneath them is
      opaque because rows now pass behind the cells. --ground carries whichever
      ground the section declared, light or dark, so the dark variants come along;
      only the col-us tint needs a hand-written pair. */
@media (min-width: 960px){
  .matrix__scroll{ overflow: visible; }
  .matrix thead th{
    position: sticky; top: var(--nav-h); z-index: 2;
    background: linear-gradient(to top, var(--rule-strong) 0 1px, var(--ground, var(--sheet)) 1px);
  }
  .matrix thead th.col-us{
    background:
      linear-gradient(to top, var(--rule-strong) 0 1px, transparent 1px),
      linear-gradient(to bottom, var(--datum-idle) 0 2px, transparent 2px),
      linear-gradient(rgba(94,159,191,.09), rgba(94,159,191,.09)),
      var(--ground, var(--sheet));
  }
  [data-ground="ink-black"] .matrix thead th.col-us,
  [data-ground="graphite"]  .matrix thead th.col-us{
    background:
      linear-gradient(to top, var(--rule-strong) 0 1px, transparent 1px),
      linear-gradient(to bottom, var(--datum) 0 2px, transparent 2px),
      linear-gradient(rgba(94,159,191,.13), rgba(94,159,191,.13)),
      var(--ground, var(--sheet));
  }
  [data-ground="charcoal"] .matrix thead th.col-us,
  [data-ground="slate"]    .matrix thead th.col-us{
    background:
      linear-gradient(to top, var(--rule-strong) 0 1px, transparent 1px),
      linear-gradient(to bottom, var(--datum) 0 2px, transparent 2px),
      linear-gradient(rgba(94,159,191,.09), rgba(94,159,191,.09)),
      var(--ground, var(--sheet));
  }
}

/* Reading the marks off the table means reading the key, so the key has to
   separate: the glyph from its word, and each pair from the next. */
.legend{
  display: flex; flex-wrap: wrap; gap: 10px var(--space-lg);
  max-width: 880px; margin-inline: auto;
  margin-top: var(--space-md); font-size: 13px; color: var(--ink-2);
}
[data-ground="ink-black"] .legend, [data-ground="graphite"] .legend,
[data-ground="charcoal"] .legend,  [data-ground="slate"] .legend{ color: var(--text-2); }
.legend__item{ display: inline-flex; align-items: center; gap: 7px; }
/* The one place the price asterisk resolves. Sits on the legend line at
   desktop, wraps under it when the row runs out. */
.legend__foot{ font-size: 12px; color: var(--ink-3); }
[data-ground="ink-black"] .legend__foot, [data-ground="graphite"] .legend__foot,
[data-ground="charcoal"] .legend__foot,  [data-ground="slate"] .legend__foot{ color: var(--text-3); }

/* The marks carry no width/height of their own, and a bare <svg><use> with no
   intrinsic size falls back to the CSS replaced-element default of 300x150.
   Size them here, once, so every injected matrix and legend measures right. */
.mark-y, .mark-n, .mark-p{ display: block; width: 18px; height: 18px; flex: none; }
.legend__item .mark-y, .legend__item .mark-n, .legend__item .mark-p{ width: 15px; height: 15px; }
.mark-y{ color: var(--ok-l); }
.mark-n{ color: var(--ink-2); }
.mark-p{ color: var(--warn-l); }
/* The -l semantic pair is mixed for light grounds only; on dark it inverts to -d. */
[data-ground="ink-black"] .mark-y, [data-ground="graphite"] .mark-y,
[data-ground="charcoal"] .mark-y,  [data-ground="slate"] .mark-y{ color: var(--ok-d); }
[data-ground="ink-black"] .mark-n, [data-ground="graphite"] .mark-n,
[data-ground="charcoal"] .mark-n,  [data-ground="slate"] .mark-n{ color: var(--text-2); }
[data-ground="ink-black"] .mark-p, [data-ground="graphite"] .mark-p,
[data-ground="charcoal"] .mark-p,  [data-ground="slate"] .mark-p{ color: var(--warn-d); }

/* --------------------------------------------------------------------------
   16. PRICE
   -------------------------------------------------------------------------- */
.price{ display: flex; flex-direction: column; height: 100%; }
.price__amount{
  font-size: clamp(38px, 5vw, 56px); font-weight: 700; letter-spacing: -0.04em;
  line-height: 1; font-variant-numeric: tabular-nums;
}
.price__unit{ font-size: 15px; font-weight: 500; letter-spacing: -0.01em; }
.price__list{ display: flex; flex-direction: column; gap: 10px; }
.price__list li{ display: grid; grid-template-columns: 18px 1fr; gap: 10px; align-items: start; font-size: 14px; line-height: 1.5; }
.price__list svg{ width: 14px; height: 14px; margin-top: 4px; }

/* --------------------------------------------------------------------------
   17. QUOTE
   -------------------------------------------------------------------------- */
.quote{ display: flex; flex-direction: column; gap: var(--space-lg); height: 100%; }
.quote__body{ font-size: 17px; line-height: 1.6; letter-spacing: -0.011em; }
.quote__who{ display: flex; align-items: center; gap: 12px; margin-top: auto; padding-top: var(--space-md); border-top: 1px solid var(--rule); }
.quote__pic{ width: 40px; height: 40px; flex: none; background: var(--canvas); border: 1px solid var(--rule); }
[data-ground="ink-black"] .quote__pic, [data-ground="graphite"] .quote__pic{ background: var(--charcoal); }

/* --------------------------------------------------------------------------
   18. STAT STRIP — measurement context, datum blue, tabular
   -------------------------------------------------------------------------- */
.stats{ display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); border-top: 1px solid var(--rule); }
.stat{ padding: var(--space-lg) var(--space-md) var(--space-lg) 0; border-bottom: 1px solid var(--rule); }
.stat__n{ font-size: clamp(28px, 3.4vw, 40px); font-weight: 700; letter-spacing: -0.035em; line-height: 1; font-variant-numeric: tabular-nums; }
.stat__l{ margin-top: 10px; font-size: var(--t-label); font-weight: 500; letter-spacing: 0.09em; text-transform: uppercase; }

/* --------------------------------------------------------------------------
   19. TUTORIAL CARD
   -------------------------------------------------------------------------- */
.tut{ display: flex; flex-direction: column; text-decoration: none; color: inherit; border: 1px solid var(--rule); background: var(--raised); }
[data-ground="ink-black"] .tut, [data-ground="graphite"] .tut{ background: var(--graphite); }
.tut__thumb{ position: relative; aspect-ratio: 16/9; background: var(--canvas); display: grid; place-items: center; border-bottom: 1px solid var(--rule); }
[data-ground="ink-black"] .tut__thumb, [data-ground="graphite"] .tut__thumb{ background: #1B2023; }
.tut__play{ width: 46px; height: 46px; display: grid; place-items: center; border: 1px solid currentColor; border-radius: var(--r-full); transition: transform var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out); }
.tut:hover .tut__play{ transform: scale(1.06); background: var(--action); color: #111417; border-color: var(--action); }
.tut__meta{ padding: var(--space-md); display: flex; flex-direction: column; gap: 6px; }
.tut__time{ position: absolute; right: 8px; bottom: 8px; padding: 3px 6px; background: var(--ink-black); color: var(--text-1); font-size: 11px; font-weight: 500; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   20. FAQ — details/summary, no modals
   -------------------------------------------------------------------------- */
.faq{ border-top: 1px solid var(--rule); }
.faq details{ border-bottom: 1px solid var(--rule); }
.faq summary{
  list-style: none; cursor: pointer; padding: var(--space-lg) 0;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
  font-size: 17px; font-weight: 600; letter-spacing: -0.015em;
}
.faq summary::-webkit-details-marker{ display: none; }
.faq summary::after{
  content: ''; width: 12px; height: 12px; flex: none;
  border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
  transform: rotate(45deg) translate(-3px, -3px);
  transition: transform var(--dur-base) var(--ease-out);
}
.faq details[open] summary::after{ transform: rotate(225deg) translate(-3px, -3px); }
.faq__body{ padding-bottom: var(--space-lg); max-width: 68ch; }

/* --------------------------------------------------------------------------
   21. FOOTER
   -------------------------------------------------------------------------- */
.foot{ background: var(--graphite); color: var(--text-1); padding: var(--space-2xl) 0 var(--space-xl); }
.foot__grid{ display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--space-xl); }
@media (max-width: 1023px){ .foot__grid{ grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px){ .foot__grid{ grid-template-columns: 1fr; } }
.foot h4{ font-size: var(--t-label); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-3); margin-bottom: 14px; }
.foot li + li{ margin-top: 9px; }
.foot a{ font-size: 14px; text-decoration: none; color: var(--text-2); transition: color var(--dur-fast) var(--ease-out); }
.foot a:hover{ color: var(--text-1); }
.foot__legal{ margin-top: var(--space-xl); padding-top: var(--space-lg); border-top: 1px solid rgba(242,245,247,.13); display: flex; justify-content: space-between; gap: var(--space-md); flex-wrap: wrap; font-size: 13px; color: var(--text-3); }
/* .badge-slot is gone with the App Store / QR placeholders it framed — there is
   no listing to link, and an empty bordered box captioned in caps is the single
   loudest "this site isn't finished" tell a footer can carry. */

/* --------------------------------------------------------------------------
   22. MOTION — A9-4 scroll law
   -------------------------------------------------------------------------- */
[data-reveal]{ opacity: 0; transform: translateY(16px); }
[data-reveal].is-in{
  opacity: 1; transform: none;
  transition: opacity var(--dur-scroll) var(--ease-out), transform var(--dur-scroll) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *, *::before, *::after{
    animation-duration: 1ms !important; animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  [data-reveal]{ opacity: 1 !important; transform: none !important; }
}

/* --------------------------------------------------------------------------
   24. UTILITY
   -------------------------------------------------------------------------- */
.hr{ height: 1px; background: var(--rule); border: none; margin: 0; }
.center{ text-align: center; }
.sr{ position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.mt-auto{ margin-top: auto; }
.nowrap{ white-space: nowrap; }
.pill{
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px;
  border: 1px solid var(--rule-strong); border-radius: var(--r-full);
  font-size: 11px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase;
}
.pill--action{ border-color: var(--action); color: var(--action); }
.mx-auto{ margin-left: auto; margin-right: auto; }
.full{ width: 100%; }
@media (max-width: 1023px){ .hide-md{ display: none; } }
@media (min-width: 1024px){ .show-md{ display: none; } }

/* --------------------------------------------------------------------------
   25. SUBPAGE PARTS — masthead, tabs, spec list, note, numbered list.
   Added for product / compare / pricing / learn / crews. Same tokens, no forks.
   -------------------------------------------------------------------------- */

/* masthead: the index hero, shorter. Inherits .hero::before drafting grid. */
.hero--page{
  padding-top: calc(clamp(40px, 6vw, 76px) + var(--nav-h));
  padding-bottom: clamp(48px, 6vw, 84px);
}

/* tabs — progressive: they are buttons, the panes are plain sections */
.tabs{
  display: flex; gap: 0; overflow-x: auto; scrollbar-width: none;
  border-bottom: 1px solid var(--rule);
}
.tabs::-webkit-scrollbar{ display: none; }
.tabs__btn{
  position: relative; appearance: none; background: none; border: none;
  padding: 13px 18px; cursor: pointer; white-space: nowrap;
  font-size: 14px; font-weight: 500; letter-spacing: -0.01em; color: var(--ink-2);
  transition: color var(--dur-fast) var(--ease-out);
}
.tabs__btn::after{
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: transparent; transition: background var(--dur-fast) var(--ease-out);
}
.tabs__btn:hover{ color: var(--ink); }
.tabs__btn[aria-selected="true"]{ color: var(--ink); }
.tabs__btn[aria-selected="true"]::after{ background: var(--ink); }
[data-ground="ink-black"] .tabs__btn,
[data-ground="graphite"] .tabs__btn,
[data-ground="charcoal"] .tabs__btn{ color: var(--text-3); }
[data-ground="ink-black"] .tabs__btn:hover,
[data-ground="graphite"] .tabs__btn:hover,
[data-ground="charcoal"] .tabs__btn:hover,
[data-ground="ink-black"] .tabs__btn[aria-selected="true"],
[data-ground="graphite"] .tabs__btn[aria-selected="true"],
[data-ground="charcoal"] .tabs__btn[aria-selected="true"]{ color: var(--text-1); }
[data-ground="ink-black"] .tabs__btn[aria-selected="true"]::after,
[data-ground="graphite"] .tabs__btn[aria-selected="true"]::after,
[data-ground="charcoal"] .tabs__btn[aria-selected="true"]::after{ background: var(--datum); }

/* spec list — the back-of-the-manual table. dt on a hairline, dd beside it. */
.spec{ display: grid; grid-template-columns: 220px 1fr; margin: 0; }
.spec > dt, .spec > dd{ padding: 15px 0; border-top: 1px solid var(--rule); margin: 0; }
.spec > dt{
  font-size: var(--t-label); font-weight: 500; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-2);
}
[data-ground="ink-black"] .spec > dt, [data-ground="graphite"] .spec > dt,
[data-ground="charcoal"] .spec > dt{ color: var(--text-3); }
.spec > dd{ font-size: 15px; line-height: 1.5; }
@media (max-width: 767px){
  .spec{ grid-template-columns: 1fr; }
  .spec > dt{ padding-bottom: 4px; }
  .spec > dd{ border-top: none; padding-top: 0; }
}

/* note — a full-bordered aside. Never a side stripe. */
.note{
  display: grid; grid-template-columns: 18px 1fr; gap: 14px; align-items: start;
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--rule-strong); border-radius: var(--r4);
  font-size: 14px; line-height: 1.55; color: var(--ink-2);
}
[data-ground="ink-black"] .note, [data-ground="graphite"] .note,
[data-ground="charcoal"] .note{ color: var(--text-2); }
.note svg{ width: 16px; height: 16px; margin-top: 3px; flex: none; }

/* numbered list — steps that are prose, not cards */
.numlist{ display: grid; gap: var(--space-lg); }
.numlist li{ display: grid; grid-template-columns: 46px 1fr; gap: var(--space-md); align-items: start; }
.numlist__n{
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums; color: var(--datum-idle); padding-top: 5px;
}
[data-ground="ink-black"] .numlist__n, [data-ground="graphite"] .numlist__n,
[data-ground="charcoal"] .numlist__n{ color: var(--datum); }

/* chip — a hairline tag. Sits in a .row, never carries colour on its own. */
.chip{
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px;
  border: 1px solid var(--rule); border-radius: var(--r4);
  font-size: var(--t-label); font-weight: 500; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-2); white-space: nowrap;
}
[data-ground="ink-black"] .chip, [data-ground="graphite"] .chip,
[data-ground="charcoal"] .chip{ color: var(--text-2); }
.chip svg{ width: 13px; height: 13px; flex: none; color: var(--datum-idle); }
[data-ground="ink-black"] .chip svg, [data-ground="graphite"] .chip svg,
[data-ground="charcoal"] .chip svg{ color: var(--datum); }

/* pane switching for [data-tabs] */
[data-pane][hidden]{ display: none; }

/* ==========================================================================
   26. MOTION KIT — ported from Instrument Kit Rev 05 (sheet A-7) and
   Rev 04C (the JobTread flow mark). Keyframe VALUES are verbatim from the
   kits; only literal hexes were retokened per the porting rule, and the
   `linear` / `ease-in-out` shorthands were moved onto the project easing
   tokens. Do not retime these — the beats are choreographed against copy.

   Three animations live here. Page agents: use these class names.

     A. §5 CAPTURE -> FILE ..... .cc-scroll > .cc > (…)   9s loop
     B. §4 ROOM -> MARK ........ .la > svg.la__svg#…      10s loop, JS-driven
     C. JobTread flow mark ..... .k-flow / .k-flow--inline 2.2s loop

   Everything settles to its resting frame under prefers-reduced-motion —
   see §26e at the bottom of this file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   26a. §5 CAPTURE -> FILE — the photo-storage sequence. A-7 §5, verbatim.
   9.0s master: 0–6.0s three shutter flashes behind camera glass, 6.0–9.0s the
   frames fly into a job card that resolves from skeleton to real copy.

   MARKUP (paste as-is; the stage is a fixed 720x405 and scrolls on narrow
   viewports exactly as the kit does):

   <div class="cc-scroll">
     <div class="cc">
       <div class="cc__room"><div class="cc__pan"><img alt=""></div></div>
       <div class="cc__cam">
         <div class="cc__glass">
           <div class="cc__pan"><img alt=""></div>
           <div class="cc__flash cc__flash--1"></div>
           <div class="cc__flash cc__flash--2"></div>
           <div class="cc__flash cc__flash--3"></div>
         </div>
         <div class="cc__ctrl">
           <span class="cc__ctrl-sq"></span>
           <span class="cc__ctrl-shutter"></span>
           <span class="cc__ctrl-done">Done</span>
         </div>
       </div>
       <div class="cc__card">
         <div class="cc__rail">
           <svg class="cc__rail-mark" viewBox="0 0 96 96"><use href="#il-final"/></svg>
           <span class="cc__rail-bar"></span><span class="cc__rail-bar"></span>
           <span class="cc__rail-bar"></span><span class="cc__rail-bar"></span>
         </div>
         <div class="cc__body">
           <div class="cc__chip">Upload photos</div>
           <div class="cc__skel">
             <span class="cc__skel-bar"></span>
             <span class="cc__skel-bar cc__skel-bar--2"></span>
           </div>
           <div class="cc__head">
             <div class="cc__addr">214 Alder St</div>
             <div class="cc__sub">Kitchen remodel — Tuesday, Aug 4</div>
           </div>
           <div class="cc__seg"><b>PHOTOS</b><span>SCOPE</span><span>REPORTS</span></div>
           <div class="cc__stamp">TUE AUG 4 · 7:42 AM — 3 PHOTOS · M. ORTEGA</div>
           <div class="cc__slot cc__slot--1"></div>
           <div class="cc__slot cc__slot--2"></div>
           <div class="cc__slot cc__slot--3"></div>
         </div>
       </div>
       <div class="cc__thumb cc__thumb--1"></div>
       <div class="cc__thumb cc__thumb--2"></div>
       <div class="cc__thumb cc__thumb--3"></div>
     </div>
   </div>
   -------------------------------------------------------------------------- */

@keyframes ccPan{0%{transform:translateX(0)}66.7%,100%{transform:translateX(-22px)}}
@keyframes ccCam{0%,66.7%{opacity:1}73%,100%{opacity:0}}
@keyframes ccFlash1{0%,21.6%{opacity:0}22.4%{opacity:.9}23.8%,100%{opacity:0}}
@keyframes ccFlash2{0%,38.2%{opacity:0}39%{opacity:.9}40.4%,100%{opacity:0}}
@keyframes ccFlash3{0%,54.9%{opacity:0}55.7%{opacity:.9}57.1%,100%{opacity:0}}
@keyframes ccT1{0%,22.4%{opacity:0;transform:translate(0,8px) rotate(-2.5deg)}23.8%{opacity:1;transform:translate(0,0) rotate(-2.5deg)}70%{opacity:1;transform:translate(0,0) rotate(-2.5deg);animation-timing-function:cubic-bezier(0.77,0,0.175,1)}76%,96%{opacity:1;transform:translate(-37px,-63px) rotate(0deg) scale(2.4)}100%{opacity:0;transform:translate(-37px,-63px) scale(2.4)}}
@keyframes ccT2{0%,39%{opacity:0;transform:translate(0,8px) rotate(2deg)}40.4%{opacity:1;transform:translate(0,0) rotate(2deg)}71.5%{opacity:1;transform:translate(0,0) rotate(2deg);animation-timing-function:cubic-bezier(0.77,0,0.175,1)}77.5%,96%{opacity:1;transform:translate(99px,-59px) rotate(0deg) scale(2.4)}100%{opacity:0;transform:translate(99px,-59px) scale(2.4)}}
@keyframes ccT3{0%,55.7%{opacity:0;transform:translate(0,8px) rotate(-1.5deg)}57.1%{opacity:1;transform:translate(0,0) rotate(-1.5deg)}73%{opacity:1;transform:translate(0,0) rotate(-1.5deg);animation-timing-function:cubic-bezier(0.77,0,0.175,1)}79%,96%{opacity:1;transform:translate(247px,-67px) rotate(0deg) scale(2.4)}100%{opacity:0;transform:translate(247px,-67px) scale(2.4)}}
@keyframes ccCard{0%,66%{opacity:0;transform:translateY(14px)}73%,97%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(0)}}
@keyframes ccSkel{0%,82%{opacity:1}86%,100%{opacity:0}}
@keyframes ccText{0%,83%{opacity:0;filter:blur(3px)}87%,97%{opacity:1;filter:blur(0)}100%{opacity:0;filter:blur(3px)}}

/* A-7 §5/§6 skeleton breathe. Tone shift only — never a sweeping gradient. */
@keyframes kSkelL{0%{opacity:.55}50%{opacity:1}100%{opacity:.55}}
@keyframes kSkelD{0%{background:#1A1F23}50%{background:#22272A}100%{background:#1A1F23}}

.cc-scroll{
  background: var(--ink-black); overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.cc-scroll::-webkit-scrollbar{ display: none; }
.cc{
  --cc-dur: 9s;                       /* one master clock — never desync a part */
  position: relative; width: 720px; height: 405px; margin: 0 auto;
  overflow: hidden; background: var(--ink-black);
  font-family: var(--font);
}
/* The kit authors the stage at a fixed 720x405 and scrolls it when the page is
   narrower. Both ends of that are wrong here. On a laptop the sequence sat as a
   720px island inside a band that runs the full width of the page — small
   enough that the shutter, the stamp and the filing card read as a diagram
   rather than a demonstration. On a phone the kit's scroll silently hid the
   right 46%, where the shutter bar and the whole job card live.

   Scale the stage instead. One transform on the root leaves every choreographed
   keyframe value in the kit untouched, which is the point — the beats are timed
   against the copy and must not be re-authored to change size.

   The scale is one continuous expression, no breakpoint of its own:
     box >= 720   the stage grows to fill its box
     600 - 720    it holds at 1:1 and crops
     box <  600   it scales down, but never past a 600-column window
   600 is not a taste call: every drawn part of the sequence lives between x60
   and x660 — the card is exactly that box, and the shutter bar and viewfinder
   are centred inside it. Only the blurred room backdrop runs wider. So the
   stage is centred and the crop takes backdrop and nothing else, at any width.

   The box itself is the only breakpoint: from 768 up it is the 1200px text
   column, so the figure's edges line up with the headline above it; below that
   it runs the full width of the screen, because a phone has no width to spend
   on gutters.

   Ratio math and container units both have to be there or we fall back to the
   kit's own centred 720px stage and its scroller. */
@supports (transform: scale(calc(100cqw / 720px))){
  .cc-scroll{
    container-type: inline-size; overflow: hidden;
    display: flex; justify-content: center;
  }
  .cc{
    --cc-s: max(calc(100cqw / 720px), min(calc(100cqw / 600px), 1));
    flex: none;
    /* a transform does not lay out — reserve the rendered height by hand */
    margin: 0 auto calc(405px * (var(--cc-s) - 1));
    transform: scale(var(--cc-s)); transform-origin: top center;
  }
  @media (min-width: 768px){
    .cc-scroll{ max-width: var(--container); padding-inline: 24px; margin-inline: auto; }
  }
}

/* the room, blurred and dimmed outside the glass */
.cc__room{ position: absolute; left: 0; top: 0; width: 742px; height: 405px; filter: blur(10px) brightness(.5); }
.cc__room > .cc__pan{ inset: 0; }
.cc__pan{ position: absolute; animation: ccPan var(--cc-dur) linear infinite; }
.cc__pan > img, .cc__pan > .slot{ width: 100%; height: 100%; object-fit: cover; display: block; }

/* the camera layer — yields to the card at 6.0s */
.cc__cam{ position: absolute; inset: 0; opacity: 0; animation: ccCam var(--cc-dur) linear infinite; }
.cc__glass{
  position: absolute; left: 250px; top: 28px; width: 220px; height: 300px;
  border-radius: 12px; overflow: hidden; box-shadow: 0 0 0 1.5px var(--text-1);
}
.cc__glass > .cc__pan{ left: -250px; top: -28px; width: 742px; height: 405px; }
.cc__flash{ position: absolute; inset: 0; background: var(--text-1); opacity: 0; }
.cc__flash--1{ animation: ccFlash1 var(--cc-dur) linear infinite; }
.cc__flash--2{ animation: ccFlash2 var(--cc-dur) linear infinite; }
.cc__flash--3{ animation: ccFlash3 var(--cc-dur) linear infinite; }
.cc__ctrl{
  position: absolute; left: 288px; top: 344px; width: 144px; height: 42px;
  border-radius: var(--r-full); background: var(--graphite);
  box-shadow: inset 0 1px 0 #2E353C;
  display: flex; align-items: center; justify-content: space-between; padding: 0 9px;
}
.cc__ctrl-sq{ width: 22px; height: 22px; border-radius: 6px; background: var(--slate); }
.cc__ctrl-shutter{ width: 26px; height: 26px; border-radius: var(--r-full); box-shadow: inset 0 0 0 2.5px var(--text-1); }
.cc__ctrl-done{ font-size: 10px; font-weight: 600; color: var(--text-1); }

/* the job card — the only part on --ease-out, because it is the one entrance */
.cc__card{
  position: absolute; left: 60px; top: 48px; width: 600px; height: 308px;
  border-radius: var(--r10); background: var(--sheet);
  box-shadow: var(--hairline-up), 0 18px 40px -18px rgba(12,15,16,.55);
  display: flex; overflow: hidden;
  animation: ccCard var(--cc-dur) var(--ease-out) infinite;
}
.cc__rail{
  width: 116px; flex-shrink: 0; background: var(--graphite);
  box-shadow: inset -1px 0 0 #2E353C; padding: 14px 12px;
  display: flex; flex-direction: column; gap: 10px;
}
.cc__rail-mark{ width: 18px; height: 18px; color: var(--text-1); }
.cc__rail-bar{ display: block; height: 7px; background: var(--charcoal); animation: kSkelD 1.6s var(--ease-in-out) infinite; }
.cc__rail-bar:nth-of-type(1){ width: 70px; animation-delay: 0s; }
.cc__rail-bar:nth-of-type(2){ width: 54px; animation-delay: .1s; }
.cc__rail-bar:nth-of-type(3){ width: 62px; animation-delay: .2s; }
.cc__rail-bar:nth-of-type(4){ width: 44px; animation-delay: .3s; }

.cc__body{ flex: 1; position: relative; padding: 14px 16px; }
.cc__chip{
  position: absolute; right: 14px; top: 12px;
  background: var(--action); border-radius: var(--r4); padding: 7px 11px;
  font-size: 11px; font-weight: 600; color: #111417; box-shadow: var(--hairline-up);
}
.cc__skel{ position: absolute; left: 16px; top: 14px; opacity: 0; animation: ccSkel var(--cc-dur) linear infinite; }
.cc__skel-bar{ display: block; width: 150px; height: 13px; background: #DDE1E4; animation: kSkelL 1.6s var(--ease-in-out) infinite; }
.cc__skel-bar--2{ width: 216px; height: 8px; margin-top: 7px; animation-delay: .15s; }

.cc__text,
.cc__head,
.cc__stamp{ animation: ccText var(--cc-dur) linear infinite; }
.cc__head{ position: absolute; left: 16px; top: 10px; }
.cc__addr{ font-size: 17px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); }
.cc__sub{ font-size: 10px; color: var(--ink-2); margin-top: 1px; }
.cc__stamp{ position: absolute; left: 16px; top: 92px; font-size: 9px; font-weight: 500; letter-spacing: .08em; color: var(--ink-3); }
.cc__seg{ position: absolute; left: 16px; top: 60px; display: flex; gap: 14px; font-size: 9.5px; font-weight: 600; letter-spacing: .08em; }
.cc__seg span{ color: var(--ink-3); }
.cc__seg b{ color: var(--ink); border-bottom: 2px solid var(--ink); padding-bottom: 3px; }

.cc__slot{
  position: absolute; top: 157px; width: 120px; height: 120px; border-radius: 8px;
  background: var(--charcoal); box-shadow: 0 0 0 1px #C6CBCF; overflow: hidden;
}
.cc__slot--1{ left: 43px; }
.cc__slot--2{ left: 183px; }
.cc__slot--3{ left: 323px; }

/* the flying frames. transform-origin top-left is what makes 2.4x land square
   in a 120px slot from a 50px thumb. */
.cc__thumb{
  position: absolute; width: 50px; height: 50px; border-radius: 3.5px;
  background: var(--charcoal); box-shadow: 0 0 0 .8px var(--text-1);
  transform-origin: top left; opacity: 0; overflow: hidden;
}
.cc__thumb--1{ left: 256px; top: 268px; animation: ccT1 var(--cc-dur) linear infinite; }
.cc__thumb--2{ left: 260px; top: 264px; animation: ccT2 var(--cc-dur) linear infinite; }
.cc__thumb--3{ left: 252px; top: 272px; animation: ccT3 var(--cc-dur) linear infinite; }

/* --------------------------------------------------------------------------
   26b. §4 ROOM -> CONVERGENCE -> MARK. A-7 §4 is a rAF timeline, not CSS
   keyframes — the driver lives in instrument.js §7 and paints attributes.
   CSS here is stage + resting appearance only.

   CONTRACT: the driver looks up ELEMENT IDS, so there is exactly ONE of these
   per page. Required ids, all inside the svg:
     la2-tick · la2-floor · la2-verts · la2-ceil · la2-dots-f · la2-dots-c
     la2-str1 · la2-str2 · la2-sqft · la2-l1 · la2-l2 · la2-l3 · la2-l4
     la2-ga (with child path la2-pa) · la2-gb (with child path la2-pb)
     la2-pulse · la2-word
   Room paths carry pathLength="400" stroke-dasharray="400"
   stroke-dashoffset="400". The svg is viewBox="0 0 640 360".

   <div class="la">
     <svg class="la__svg" viewBox="0 0 640 360" aria-label="Room scan resolving into the mark">…</svg>
   </div>
   -------------------------------------------------------------------------- */
.la{
  position: relative; background: var(--graphite);
  border: 1px solid var(--rule-strong); border-radius: var(--r10); overflow: hidden;
}
.la__svg{ display: block; width: 100%; height: auto; }
.la-line{ fill: none; stroke: var(--datum-idle); stroke-width: 1; }
.la-dot{ fill: var(--datum); }
.la-tick{ fill: none; stroke: var(--datum); stroke-width: 1.5; }
.la-str{ fill: none; stroke: var(--datum); stroke-width: 1; }
.la-num{ fill: var(--text-1); font-family: var(--font); font-weight: 600; font-variant-numeric: tabular-nums; }
.la-label{ fill: var(--text-3); font-family: var(--font); font-weight: 500; letter-spacing: .1em; }
.la-word{ fill: var(--text-1); font-family: var(--font); font-weight: 600; letter-spacing: .16em; }
.la-mark{ fill: none; stroke: var(--datum-idle); stroke-width: 1; stroke-linecap: butt; stroke-linejoin: miter; }

/* --------------------------------------------------------------------------
   26c. JobTread flow mark — "blue electricity". Rev 04C §S10, retokened.
   A9-4 names the stroke-dash growth as the documented exception to the
   transform/opacity-only rule; this is that exception.

   INLINE USE (this is what the brief asks for — small, twice, inside an
   existing band; never its own card):

   <svg class="k-flow k-flow--inline" viewBox="0 0 232 34" role="img"
        aria-label="Scope and photos sync both ways with JobTread">
     <rect class="k-flow__tile" x="0.75" y="4.75" width="24.5" height="24.5" rx="6"/>
     <rect class="k-flow__tile" x="206.75" y="4.75" width="24.5" height="24.5" rx="6"/>
     <path class="k-flow__rail" d="M26 13 H206 M206 21 H26"/>
     <path class="k-flow__wire" d="M26 13 H206" pathLength="100" stroke-dasharray="8 92"/>
     <path class="k-flow__wire k-flow__wire--b" d="M206 21 H26" pathLength="100" stroke-dasharray="8 92"/>
     <rect class="k-flow__node" x="200" y="7" width="12" height="12"/>
     <rect class="k-flow__node k-flow__node--b" x="20" y="15" width="12" height="12"/>
   </svg>

   BAND USE is .k-flow--panel inside a .k-flow-panel scroller — see below.
   -------------------------------------------------------------------------- */
@keyframes kFlow{0%{stroke-dashoffset:100}100%{stroke-dashoffset:0}}
@keyframes kNode{0%{stroke:var(--k-idle)}84%{stroke:var(--k-idle)}88%{stroke:var(--datum)}96%{stroke:var(--datum)}100%{stroke:var(--k-idle)}}

.k-flow{ --k-idle: var(--hairline-strong); display: block; width: 100%; height: auto; }
[data-ground="ink-black"] .k-flow,
[data-ground="graphite"] .k-flow,
[data-ground="charcoal"] .k-flow{ --k-idle: var(--slate); }

.k-flow__tile{ fill: none; stroke: var(--rule-strong); stroke-width: 1; }
.k-flow__rail{ fill: none; stroke: var(--k-idle); stroke-width: 1.5; }
.k-flow__wire{
  fill: none; stroke: var(--datum); stroke-width: 2;
  animation: kFlow 2.2s linear infinite;
}
.k-flow__wire--b{ animation-delay: 1.1s; }
.k-flow__node{
  fill: var(--sheet); stroke: var(--k-idle); stroke-width: 1.5;
  animation: kNode 2.2s linear infinite;
}
.k-flow__node--b{ animation-delay: 1.1s; }
[data-ground="ink-black"] .k-flow__node{ fill: var(--ink-black); }
[data-ground="graphite"] .k-flow__node{ fill: var(--graphite); }
[data-ground="charcoal"] .k-flow__node{ fill: var(--charcoal); }
.k-flow__label{ fill: var(--ink-3); font-family: var(--font); font-weight: 500; letter-spacing: .08em; }
[data-ground="ink-black"] .k-flow__label,
[data-ground="graphite"] .k-flow__label,
[data-ground="charcoal"] .k-flow__label{ fill: var(--text-3); }

/* miniaturized: paragraph scale, sits on the baseline of a sentence.
   The 232x34 viewBox renders near 1:1 at this width, so the kit's stroke
   weights stay honest instead of shrinking to nothing. */
.k-flow--inline{
  display: inline-block; vertical-align: -0.5em;
  width: 208px; max-width: 100%; height: auto; margin: 0 4px;
}
.k-flow--inline .k-flow__label{ display: none; }
@media (max-width: 560px){ .k-flow--inline{ width: 168px; vertical-align: -0.45em; } }

/* band scale: the drawing the kit actually sheets, full container width.
   Two real lockups instead of two empty tiles, a lane each way with the lane
   labels the inline version has to drop, and the other party's logo as itself.
   Use this when the integration IS the passage; keep --inline for a product
   name dropped mid-sentence.

   Wire timing is untouched from the inline version — node A sits at 96.9% of
   its lane and kNode lights at 88%, so the dash arrives ~20ms after the node
   wakes. Do not retime. */
.k-flow-panel{ overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.k-flow-panel::-webkit-scrollbar{ display: none; }

/* Below ~700px the 860 viewBox would put the 12-unit lane labels under 5px —
   the exact failure the inline version already has. The drawing keeps its size
   and the finger moves instead, same deal as .matrix__scroll. */
.k-flow--panel{ min-width: 640px; }
.k-flow--panel .k-flow__label{ font-size: 12px; }

/* the RenoFriend lockup, nav ratios (24:18:9) scaled to 34:26:12.75 */
.k-flow__brand{ color: var(--ink); }
.k-flow__brandword{ fill: var(--ink); font-family: var(--font); font-weight: 600; letter-spacing: -.02em; }
[data-ground="ink-black"] .k-flow__brand,
[data-ground="graphite"] .k-flow__brand,
[data-ground="charcoal"] .k-flow__brand{ color: var(--text-1); }
[data-ground="ink-black"] .k-flow__brandword,
[data-ground="graphite"] .k-flow__brandword,
[data-ground="charcoal"] .k-flow__brandword{ fill: var(--text-1); }

/* JobTread ships one artwork, near-black on transparent, and its orange is the
   one sanctioned exception to the single-accent law. It gets a card of its own
   so it reads the same on sheet and on graphite rather than being recoloured. */
.k-flow__chip{ fill: var(--raised); stroke: var(--hairline); stroke-width: 1; }

.k-flow__arrow{ fill: none; stroke: var(--k-idle); stroke-width: 1.5; stroke-linecap: butt; stroke-linejoin: miter; }

/* --------------------------------------------------------------------------
   26d. kDrawOnce — the dimension-line wipe (Rev 04C). 500ms, --ease-out,
   60ms stagger. Pair it with an ancestor [data-reveal] and it waits for the
   scroll observer instead of firing on load.
   -------------------------------------------------------------------------- */
@keyframes kDrawOnce{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}

.k-draw{ animation: kDrawOnce 500ms var(--ease-out) both; }
[data-reveal] .k-draw{ animation-play-state: paused; }
[data-reveal].is-in .k-draw{ animation-play-state: running; }
.k-draw--seq > *{ animation: kDrawOnce 500ms var(--ease-out) both; }
.k-draw--seq > *:nth-child(2){ animation-delay: 60ms; }
.k-draw--seq > *:nth-child(3){ animation-delay: 120ms; }
.k-draw--seq > *:nth-child(4){ animation-delay: 180ms; }
.k-draw--seq > *:nth-child(5){ animation-delay: 240ms; }
[data-reveal] .k-draw--seq > *{ animation-play-state: paused; }
[data-reveal].is-in .k-draw--seq > *{ animation-play-state: running; }

/* --------------------------------------------------------------------------
   26e. REDUCED MOTION — every animation above ships its RESTING FRAME.
   This block must stay last: §22 already blankets `*` with
   animation-duration:1ms / iteration-count:1, which would land the capture
   sequence on its 100% keyframe — and 100% is opacity:0 for almost all of it,
   i.e. an empty black box. So each part is pinned explicitly.
   A-7 §5's own note: "Reduced motion: blurred footage + the resolved card."
   The §4 loader handles itself in JS by pinning its clock to t=9.2s.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  .cc__pan{ animation: none !important; transform: translateX(-22px) !important; }
  .cc__cam{ animation: none !important; opacity: 0 !important; }
  .cc__flash{ animation: none !important; opacity: 0 !important; }

  .cc__card{ animation: none !important; opacity: 1 !important; transform: none !important; }
  .cc__rail-bar{ animation: none !important; background: #1A1F23 !important; }
  .cc__skel{ animation: none !important; opacity: 0 !important; }
  .cc__skel-bar{ animation: none !important; opacity: .55 !important; }
  .cc__text, .cc__head, .cc__stamp{ animation: none !important; opacity: 1 !important; filter: none !important; }

  .cc__thumb{ animation: none !important; opacity: 1 !important; }
  .cc__thumb--1{ transform: translate(-37px, -63px) scale(2.4) !important; }
  .cc__thumb--2{ transform: translate(99px, -59px) scale(2.4) !important; }
  .cc__thumb--3{ transform: translate(247px, -67px) scale(2.4) !important; }

  .k-flow__wire{ animation: none !important; stroke-dashoffset: 0 !important; }
  .k-flow__node{ animation: none !important; stroke: var(--k-idle) !important; }

  .k-draw, .k-draw--seq > *{ animation: none !important; clip-path: inset(0 0 0 0) !important; }
}
