/* =================================================================
   jl audio — theme v2
   Same selectors, same markup across every page — theme-v2.css is
   the site's single shared stylesheet.

   Source: design-system-v2.md + design-brief-v2.md (2026-09-21)
   Typeface: Inter.
   Palette: monochrome paper/black/grey, PLUS a sparing two-green accent
   system (2026-09-23 owner direction — "don't ban green, it's an
   important part of the brand... use it sparingly, don't go ham"):
   green is still never a background fill, only hover/focus/active
   states, underlines, borders and the one "currently active" signal
   (playing player, visible beat number). See DESIGN.md §1 for the
   full system + where each token is used.
   ================================================================= */

/* Self-hosted (2026-09-25 — was a Google Fonts @import; see CLAUDE.md /
   audit finding #23). Roboto's gstatic file is a variable font, so one
   file covers both 400 and 500 via two @font-face declarations. Latin
   subset only, matching the family/weight set actually used site-wide. */
@font-face{
  font-family:'Roboto';
  font-style:normal;
  font-weight:400 500;
  font-display:swap;
  src:url('/assets/fonts/roboto-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:'Inter';
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url('/assets/fonts/inter-700-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;
}

:root{
  /* ---------- colour tokens ---------- */
  --paper:      #F7F7F7;  /* light surface, body copy background — very light neutral grey (2026-09-23 owner direction) */
  --black:      #0B0B0A;  /* dark surface, primary text on paper */
  --grey-1:     #6E6C66;  /* muted/secondary text on paper */
  --grey-2:     #9C9A93;  /* hairlines, dividers, placeholder text */
  --grey-3:     #D8D6CF;  /* disabled states, subtle fills on paper */
  /* ---------- green accent system (2026-09-23) ----------
     Sampled straight from the brand icon files (Brand Collateral/Icon/
     Standard/): viridiandeep-on-white.png → --green-deep, black-on-
     viridianlight.png → --green-light. --green-ink is at-rest ink for
     labels/CTAs/prices (owner direction 2026-09-23: green should be
     present at rest, not just hover — small doses only, never fills,
     never display scale). --green-light stays reserved for focus
     outlines/accents. */
  --green-deep:   #085041;  /* sampled from viridiandeep-on-white.png — the darker brand green */
  --green-light:  #40826D;  /* focus rings / valid-input borders — viridian (2026-09-28: mint #9FE1CB retired site-wide) */
  /* dark-room accent pair (2026-09-29 — "Mono dark", owner direction:
     "in the DARK room there is NO green anywhere"): these two constants
     used to be green (viridian/emerald); they now hold the dark room's
     two mono accent values instead, same role split as before so every
     dark-room override below and viz.js's own read of --viridian keep
     working unchanged. --viridian = line-art accent (the single front
     trace in waveforms/motif bands/three.js story, dots on it) — pure
     white, read by viz.js as the constant "dark room signal colour" and
     by motif.js/instruments.js via --accent-line. --emerald = UI/text
     accent (nav links, current-page underline, labels/eyebrows, hovers,
     focus rings, valid-input borders, "enquire →"/"start →", step
     numbers) — soft off-white, same family as body text so emphasis
     reads by brightness/underline alone, not colour. Names kept as-is
     (still "Constants, read by viz.js") to avoid touching every call
     site; see the html[data-room="dark"] block below for where each
     applies. Light room is unaffected — --green-deep/--green-light are
     untouched and still drive the light room's real green. */
  --viridian:     #FFFFFF;
  --emerald:      #E8E8E6;
  --accent-text:  var(--green-deep); /* text accent — emerald in the dark room */
  --accent-line:  var(--green-deep); /* non-text accent (canvas traces/dots) — viridian in the dark room */
  --motif-back:   #282828;          /* signature motif back rows (fade toward --paper), motif.js — SPEC §6 */
  /* dark-room line-art fix (2026-09-29): --black doubles as dark-room ink
     by resolving to --paper's #F7F7F7 (see the html[data-room="dark"]
     block below) — correct for TEXT, but every neutral (non-accent)
     canvas hairline that borrowed --black for its stroke (instruments.js'
     INK(), the home/#work + /work/ waveform players' INK()) rendered
     literally in the paper hex, reading as cream against the near-black
     stage instead of matching the approved dark IG carousel's pure-white
     hairlines. --line-art is the dedicated stroke token those canvases
     now read instead: identical to --black in the light room (no visual
     change there), overridden to true white only in the dark room —
     never touches --paper/--black/text colour. */
  --line-art:     var(--black);
  --green-ink:    var(--accent-text); /* text/underline/icon/CTA/price accent — 8.8:1 on --paper, passes 4.5:1 */
  --accent:       var(--green-ink);  /* legacy alias — every existing hover/focus rule below already
                                         reads var(--accent), so this alone applies green-ink through
                                         nav/link/CTA/footer/form hover states unchanged */

  --hairline:      var(--grey-2);
  --hairline-inv:  rgba(243,241,236,.22);
  --on-dark-1:     rgba(243,241,236,.62);   /* muted text on black */
  --on-dark-2:     rgba(243,241,236,.4);    /* dimmer still, on black */

  /* ---------- typeface ---------- */
  --face: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --face-display: 'Inter', var(--face);

  /* ---------- 8px rhythm ---------- */
  --rhythm: 8px;
  --r1: calc(var(--rhythm) * 1);   /* 8   */
  --r2: calc(var(--rhythm) * 2);   /* 16  */
  --r3: calc(var(--rhythm) * 3);   /* 24  */
  --r4: calc(var(--rhythm) * 4);   /* 32  */
  --r5: calc(var(--rhythm) * 5);   /* 40  */
  --r6: calc(var(--rhythm) * 6);   /* 48  */
  --r8: calc(var(--rhythm) * 8);   /* 64  */
  --r12: calc(var(--rhythm) * 12); /* 96  */
  --r14: calc(var(--rhythm) * 14); /* 112 */

  /* ---------- fluid section rhythm ----------
     r10/r16/r24 are the three steps that only ever do section-level vertical
     separation (page-header top offset, sec-head/svcp-grid top gap, contact
     bookend top/bottom) — every use site is a top/bottom padding on a
     section, never a tight component gap. Fluid so the gap holds its
     proportion to the viewport instead of jumping at a fixed px value;
     each clamp's max matches the old fixed px so desktop is unchanged. */
  --r10: clamp(40px, 6vw, 80px);    /* was fixed 80  */
  --r16: clamp(48px, 8vw, 128px);   /* was fixed 128 */
  --r24: clamp(64px, 12vw, 192px);  /* was fixed 192 — the MONOE-style section-separation gap */

  /* ---------- nav height ---------- */
  --nav-h: 80px;
  --nav-h-mobile: 64px;

  /* ---------- grid ----------
     Single page margin at every width (MONOE / FWD / juliaborelli.com
     model) — content aligns to one edge, never centred inside a
     fixed-width column. Every layout wrapper below pads to this,
     with no max-width/margin:auto fighting it. */
  --gutter: clamp(20px, 4.5vw, 80px);
  --page-x: clamp(24px, 4vw, 72px);
  --pad-x: var(--page-x); /* kept as an alias — every existing rule below already reads var(--pad-x) */

  /* ---------- type scale: desktop → mobile via clamp() ---------- */
  --fs-display: clamp(56px, 9.4vw, 148px);  /* hero wordmark */
  --fs-h1:      clamp(36px, 6.4vw, 64px);   /* page/service titles */
  --fs-h2:      clamp(24px, 3.6vw, 32px);   /* section headers */
  --fs-body:    clamp(16px, 1.3vw, 18px);   /* weight 400 */
  --fs-small:   clamp(13px, 1vw, 14px);     /* captions/meta, weight 400 */
  --fs-label:   clamp(12px, .95vw, 13px);   /* nav/buttons/tags, weight 600, uppercase */

  /* ---------- type weight/tracking (2026-09-21: restored the heavier, tighter
     feel of the pre-v2 build — Jacob called the 300-weight display "no personality").
     Size/rhythm tokens above are untouched; only these got heavier + tighter. ---------- */
  --fw-display: 600; --ls-display: -.045em;  /* was 300 / -.02em */
  --fw-h1:      600; --ls-h1:      -.02em;   /* was 500 / -.01em */
  --fw-h2:      600; --ls-h2:      -.015em;  /* was 500 / -.01em */

  /* legacy alias so any inherited --sans/--mono usage still resolves to the one family */
  --sans: var(--face);
  --mono: var(--face);
}

/* =================================================================
   HIDDEN DARK ROOM (Easter egg) — double-click the "jl audio" nav mark
   (deploy/assets/room.js) toggles html[data-room="dark"], persisted in
   localStorage ("jla-room") and applied pre-paint by a tiny inline
   snippet in every page's <head> (no flash on load/reload).

   Full paper<->black token swap: since almost every rule on the site
   already reads var(--paper)/var(--black)/var(--grey-*)/var(--hairline)
   instead of a literal hex, overriding just these tokens at the root
   flips the whole page in one hard cut — no per-component dark theme
   to hand-maintain, no transition (instant, per the brief: "nothing
   fades"). --grey-2 (which --hairline is itself defined FROM, so it
   updates for free) goes to green-light: "every hairline becomes
   green" per the brief. --grey-3 (watermark/subtle-fill token) goes to
   a very dark green-grey. --green-ink (already the alias every
   hover/focus/CTA/price rule below reads via --accent) repoints to
   --green-light — --green-deep alone is too dark to read on a black
   surface.

   .footer is ALREADY a fixed black surface regardless of page theme —
   its own --black / --paper / --grey-N / --on-dark-N need to stay pinned
   to their ORIGINAL (non-swapped) values so its existing "light text
   on black" rules keep working, instead of quietly flipping to
   unreadable light-on-light. Re-pinned in its own nested block below
   (higher specificity than the html[data-room="dark"] rule above it,
   so it wins for its subtree only). world.css carries one further
   override for index.html only: that page's .footer is deliberately
   NOT a fixed-dark surface (it matches the one-white-page-surface
   design, "owner direction 2026-09-23") so it needs to keep following
   the swapped page tokens rather than this re-pin — see world.css.

   .dark (on .svc-panel/.bio-panel etc.) is DELIBERATELY NOT re-pinned
   here (2026-09-26 dark-room sweep fix): those panels are "already
   black" ONLY in the light theme. Re-pinning them the same way as
   .footer forced --paper back to the light F7F7F7 inside the panel,
   and since .svc-panel/.bio-panel's own background:var(--paper) rule
   (components.css, loads after this file) beats .dark's
   background:var(--black) at equal specificity, the panel rendered as
   a light island on an otherwise black dark-room page (confirmed on
   /about/ section#bio.bio-panel.dark). Left unpinned, --paper/--black
   simply follow the root swap above, so the panel's own
   background:var(--paper) rule resolves to the dark-room black
   (#000000) like the rest of the page, and its descendants' existing
   color:var(--black) text rules resolve to the dark-room light ink —
   both automatically correct with no extra selectors needed. */
html{ background:var(--paper); }
html[data-room="dark"]{
  --paper:      #121211;  /* soft black (2026-10-28 owner pick "D"; was #0B0B0A, before that pure #000) */
  --black:      #F2F1EE;  /* text on soft black: off-white, less glare than #F7F7F7 (2026-10-28) */
  /* greys go back to dimmed paper (2026-09-28): mirrors the light-room
     hierarchy — grey-1 ≈7.3:1 (AA body), grey-2 ≈2.6:1 like light's
     #9C9A93 (placeholders/borders), hairline quieter still. */
  --grey-1:     rgba(247,247,247,.62); /* muted/secondary text on black */
  --grey-2:     rgba(247,247,247,.32); /* dividers/placeholder/input borders */
  --grey-3:     #1A1A19;               /* disabled/subtle-fill + watermark */
  --hairline:   rgba(247,247,247,.14);
  --green-light: var(--emerald);       /* UI accent: focus rings, valid-input borders — mono off-white (2026-09-29), not the line-art white */
  --accent-line: var(--viridian);      /* line-art accent: canvas traces/dots — pure white (2026-09-29) */
  --motif-back: #FFFFFF;               /* motif back rows on black — pure white (2026-09-29: was #D2D2D2, read as dim/cream next to the approved dark IG carousel's white hairlines) */
  --accent-text: var(--emerald);       /* text accent — --green-ink/--accent follow this */
  --green-ink:  var(--accent-text);
  --line-art:   #FFFFFF;               /* dark-room neutral canvas-stroke token (2026-09-29) — pure white, NOT --black (which is #F7F7F7/paper here, correct for text but read as cream on line-art canvases). See :root comment. */
}
html[data-room="dark"] .footer{
  --paper:      #F7F7F7;
  --black:      #121211;  /* soft black (2026-10-28) — matches the rest of the dark-room ground instead of reading as a grey strip under it */
  --grey-1:     #6E6C66;
  --grey-2:     #9C9A93;
  --grey-3:     #D8D6CF;
  /* mono dark (2026-09-29): this whole rule only ever applies while
     html[data-room="dark"] is active (see selector) — it re-pins the
     footer's OWN fixed black band back to the light-room hex values so
     its "light text on black" rules stay legible regardless of the
     page room. Every other pinned value above is a neutral (grey/paper/
     black), so re-pinning to the light-room literal is invisible either
     way — but --green-ink was pinned to the real brand green
     (--green-deep, #085041), which put green text on the footer any
     time this rule's selector matched, i.e. only in the dark room. That
     is exactly the "no green in the dark room" bug: the light room's
     footer is styled by the plain (unscoped) .footer rules elsewhere,
     which still read --green-deep directly and are untouched. */
  --green-ink:  var(--emerald);
  --hairline-inv: rgba(243,241,236,.22);
  --on-dark-1:  rgba(243,241,236,.62);
  --on-dark-2:  rgba(243,241,236,.4);
  /* --black above now matches the dark-room page ground exactly (both
     pure #000000), so without a seam the band would vanish into the
     page. --hairline is NOT re-pinned in this block, so it keeps
     following the root dark-room value (rgba(247,247,247,.14)) — reuse
     it here as the separator, same hairline colour as the rest of the
     dark room (2026-09-29). */
  border-top:1px solid var(--hairline);
}

/* .sf-submit (footer contact form's submit button, components.css) is the
   one control on the site that fills with a literal --green-deep (never
   swaps with the room) while its text/icon read var(--paper) (which DOES
   swap — dark in the dark room). Left alone that's dark ink on a
   fixed dark-green fill in the dark room — unreadable. Pin its ink back
   to the dark room's light green so it stays legible; reuses the
   dark room's own --green-light token, no new colour (2026-09-26
   dark-room sweep fix). */
html[data-room="dark"] .sf-submit{ color:var(--accent-text); background:transparent; border-color:var(--accent-text); }
html[data-room="dark"] .sf-submit i{ color:var(--accent-text); }
/* hover/focus inverts like the light room (ink fill, paper label). The
   transparent background above out-ranks .sf-submit:hover's fill, so the
   old paper-coloured label sat on nothing — a blank emerald box (QA
   2026-09-28). */
html[data-room="dark"] .sf-submit:hover, html[data-room="dark"] .sf-submit:focus-visible{ background:var(--black); border-color:var(--black); color:var(--paper); }
html[data-room="dark"] .sf-submit:hover i, html[data-room="dark"] .sf-submit:focus-visible i{ color:var(--paper); }

/* room-flip (2026-09-27 fix): the brief says the room swap is "a hard,
   instant cut, not a fade" — but several unrelated components (.nav's
   background/border-color transition, .beat-hero .hero-cta's background/
   color/border-color transition, etc.) already carry their own short
   transitions for normal hover/scroll behaviour. Those same properties
   are exactly what the room swap repoints, so toggling the room made
   them fade instead of cut, and for the ~0.2s of that fade one element
   (already-swapped, no transition of its own) sits next to another still
   mid-fade on the old room's colour — the "half paper, half dark" glitch
   Jacob saw (nav still light while the hero was already black; the hero
   CTA label washed out grey mid-fade). room.js adds this class to <html>
   for one frame around the attribute flip so nothing transitions during
   the swap itself; normal hover/scroll transitions are unaffected once
   it's removed. */
html.room-flip, html.room-flip *, html.room-flip *::before, html.room-flip *::after{
  transition:none !important;
}

/* ================= reset / base ================= */
*{margin:0; padding:0; box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{overflow-x:hidden;}
body{
  background:var(--paper);
  color:var(--black);
  font-family:var(--face);
  font-weight:400;
  font-size:var(--fs-body);
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
a{color:inherit; text-decoration:none;}
::selection{background:var(--black); color:var(--paper);}
.mono{font-family:var(--face);}

/* grain overlay is a texture device from v1 that has no place in the
   restrained v2 system — neutralize it without touching markup */
.grain::before{content:none;}

/* ---------- micro labels (nav / buttons / tags) ---------- */
.lbl{
  font-family:var(--face);
  font-size:var(--fs-label);
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--green-ink);
}
.lbl.accent{color:var(--black);}
.dark .lbl{color:var(--on-dark-1);}
.dark .lbl.accent{color:var(--paper);}

@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
}

/* ================= NAV ================= */
.nav{
  position:fixed; top:0; left:0; right:0; z-index:200;
  display:flex; align-items:center; justify-content:space-between;
  padding:0 var(--pad-x);
  height:var(--nav-h);
  background:var(--paper);
  border-bottom:1px solid var(--hairline);
  transition:background .2s ease-out, border-color .2s ease-out;
}
.nav-mark{
  display:flex; align-items:center;
  font-family:var(--face); font-weight:500; font-size:18px; letter-spacing:-.01em;
  text-transform:lowercase;
  color:var(--black);
  transition:color .2s ease-out;
}
.nav-links{display:flex; align-items:stretch; list-style:none; gap:clamp(2px,1.2vw,8px); height:100%;}
.nav-links a, .nav-links .nav-link{
  display:flex; align-items:center; gap:8px; height:100%;
  padding:0 var(--r2);
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--black);
  background:none; border:none; cursor:pointer;
  position:relative;
  transition:color .2s ease-out;
}
.nav-links a i{font-style:normal; color:inherit; transition:color .2s ease-out;}
.nav-links a::after, .nav-links .nav-link::after{
  /* Sits tight under the label's own line-box (not floating mid-bar) so it
     reads as a normal underline coming up from the bottom on hover, never
     above the text. 2026-09-23. */
  content:''; position:absolute; left:var(--r2); right:var(--r2); bottom:28px; height:1px;
  background:var(--accent); transform:scaleX(0); transform-origin:left;
  transition:transform .2s ease-out;
}
.nav-links a:hover{color:var(--accent); background:none;}
.nav-links a:hover i{color:var(--accent);}
.nav-links a:hover::after{transform:scaleX(1);}
/* current-page label: green-ink, underline held open. nav.js does not
   currently set aria-current/is-current on the matching link — this rule
   is written ahead of that wiring (see DESIGN.md §1) so it activates the
   moment either attribute is added, with no further CSS work. */
.nav-links a[aria-current="page"], .nav-links a.is-current{color:var(--green-ink);}
.nav-links a[aria-current="page"]::after, .nav-links a.is-current::after{transform:scaleX(1); background:var(--green-ink);}
.nav-links .nav-link:hover,
.nav-links .nav-link:focus-visible,
.nav-item--has-menu:hover .nav-link,
.nav-item--has-menu:focus-within .nav-link,
.nav-item--has-menu.is-open .nav-link{color:var(--accent);}
.nav-links .nav-link:hover::after,
.nav-links .nav-link:focus-visible::after,
.nav-item--has-menu:hover .nav-link::after,
.nav-item--has-menu:focus-within .nav-link::after,
.nav-item--has-menu.is-open .nav-link::after{transform:scaleX(1);}

.nav-toggle{
  display:none;
  align-items:center; justify-content:center; gap:8px;
  height:100%; padding:0 2px 0 18px;
  background:none; border:none; cursor:pointer;
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--black);
}
.nav-toggle .ic{font-size:11px; transition:transform .2s ease-out;}
.nav-toggle[aria-expanded="true"] .ic{transform:rotate(180deg);}

.nav-item{position:relative; display:flex; align-items:center; height:100%;}
/* every nav list item is a full-height flex row so the CTA (a plain <li>) centres
   vertically like the links — it was sitting at the top of the bar (owner 2026-09-24). */
.nav-links > li{display:flex; align-items:center; height:100%;}

.nav-links a.cta{
  height:auto; align-self:center; align-items:center;
  margin-left:clamp(4px,1vw,14px);
  padding:8px 18px;
  border:1px solid var(--green-ink);
  border-radius:2px;
  color:var(--black);
  transition:color .2s ease-out, border-color .2s ease-out;
}
.nav-links a.cta span{border-bottom:none; padding-bottom:0;}
.nav-links a.cta::after{content:none;}
.nav-links a.cta:hover, .nav-links a.cta:focus-visible{color:var(--green-ink); border-color:var(--green-ink); background:none;}

.nav-panel{
  position:fixed; inset:0; z-index:190;
  background:var(--paper);
  padding:calc(var(--nav-h-mobile) + var(--r6)) var(--pad-x) var(--r5);
  overflow-y:auto;
  transform:translateY(-100%);
  visibility:hidden;
  transition:transform .28s cubic-bezier(.4,0,.2,1), visibility 0s linear .28s;
  display:flex; flex-direction:column;
}
/* Fallback for browsers without `inert` support: keep the closed panel out
   of the accessibility tree and un-hoverable/un-clickable even though it's
   `position:fixed` and technically still painted during its slide-out. The
   `inert` attribute (set/cleared by nav.js) is the primary mechanism — this
   is belt-and-braces. */
.nav-panel:not(.is-open){visibility:hidden;}
.nav-panel.is-open{transform:translateY(0); visibility:visible; transition:transform .28s cubic-bezier(.4,0,.2,1), visibility 0s linear 0s;}
.nav-panel ul{list-style:none;}
.nav-panel a{
  display:flex; align-items:baseline; justify-content:space-between; gap:var(--r2);
  padding:var(--r2) 0;
  border-bottom:1px solid var(--hairline);
  font-family:var(--face); font-size:clamp(22px,6.4vw,28px); font-weight:500; letter-spacing:-.01em; text-transform:lowercase;
  color:var(--black);
}
.nav-panel li:last-child a{border-bottom:none;}
.nav-panel a i{
  font-style:normal;
  font-family:var(--face); font-size:var(--fs-label); letter-spacing:.08em; color:var(--grey-1); font-weight:600;
}
/* Indented sub-links shown under "services" in the open mobile panel —
   always visible, no extra tap. The parent row above still links straight
   to /services/. */
.nav-panel-item > a{border-bottom:none;}
.nav-panel-item{border-bottom:1px solid var(--hairline);}
.nav-panel-item:last-child{border-bottom:none;}
.nav-panel-sub{padding:0 0 var(--r2) var(--r4);}
.nav-panel-sub li a, .nav-panel-sub li:last-child a{border-bottom:none;}
.nav-panel-sub a{
  font-size:clamp(15px,4vw,17px); font-weight:400; color:var(--grey-1);
  padding:var(--r1) 0;
}
.nav-panel-sub a:hover, .nav-panel-sub a:focus-visible{color:var(--accent);}
.nav-panel .panel-cta{
  display:inline-flex; align-items:center; gap:10px;
  margin-top:auto; padding-top:var(--r4);
  font-family:var(--face); font-size:15px; letter-spacing:0; text-transform:lowercase;
  color:var(--black);
  transition:color .2s ease-out;
}
.nav-panel .panel-cta span{border-bottom:1px solid var(--hairline); padding-bottom:3px; transition:border-color .2s ease-out;}
.nav-panel .panel-cta:hover, .nav-panel .panel-cta:focus-visible{color:var(--accent);}
.nav-panel .panel-cta:hover span, .nav-panel .panel-cta:focus-visible span{border-color:var(--accent);}


/* Current page in the MOBILE PANEL (nav.js sets aria-current="page" by exact
   path match): green text only. No box, background, border or outline.
   Keyboard focus is shown as an underline, never a ring/box. */
.nav-panel a[aria-current="page"], .nav-panel .nav-panel-sub a[aria-current="page"]{color:var(--green-ink);}
.nav-panel a:focus, .nav-panel a:focus-visible{outline:none; background:none; box-shadow:none;}
.nav-panel a:focus-visible{text-decoration:underline; text-underline-offset:4px;}

/* Dark room: NO green. Current = full white, everything else dimmed. */
html[data-room="dark"] .nav-links a:not(.cta),
html[data-room="dark"] .nav-links .nav-link,
html[data-room="dark"] .nav-links .c-nav-menu a,
html[data-room="dark"] .nav-panel a:not(.panel-cta),
html[data-room="dark"] .nav-panel .nav-panel-sub a{color:rgba(255,255,255,.58);}
html[data-room="dark"] .nav-links a:not(.cta):hover,
html[data-room="dark"] .nav-links a:not(.cta):focus-visible,
html[data-room="dark"] .nav-item--has-menu:hover .nav-link,
html[data-room="dark"] .nav-item--has-menu:focus-within .nav-link,
html[data-room="dark"] .nav-panel a:hover,
html[data-room="dark"] .nav-panel a:focus-visible,
html[data-room="dark"] .nav-links a[aria-current="page"],
html[data-room="dark"] .nav-links .c-nav-menu a[aria-current="page"],
html[data-room="dark"] .nav-panel a[aria-current="page"],
html[data-room="dark"] .nav-panel .nav-panel-sub a[aria-current="page"]{color:#fff;}
html[data-room="dark"] .nav-links a::after,
html[data-room="dark"] .nav-links a[aria-current="page"]::after{background:#fff;}

@media (max-width:760px){
  .nav{height:var(--nav-h-mobile);}
  /* Full link list still hides on mobile (menu panel owns it), but the
     "start a project" CTA <li> is pulled out and kept visible in the
     header bar itself — it's the only way in on phones, not just a
     footer link (client-reported gap, 2026-09-27). order puts it between
     the wordmark and MENU regardless of its DOM position before nav-toggle. */
  .nav-links{display:flex; order:2; height:100%; gap:0; align-items:center; margin-left:auto;}
  .nav-links > li{display:none;}
  .nav-links > li:has(a.cta){display:flex;}
  .nav-links a.cta{
    margin-left:0;
    padding:0 10px;
    height:34px; min-height:0;
    font-size:11px;
    letter-spacing:.04em;
    white-space:nowrap;
  }
  .nav-toggle{display:flex; order:3; height:44px; align-self:center; padding:0 0 0 14px;}
}
/* very thin windows (a desktop window dragged narrow, small/zoomed phones):
   wordmark + "start a project" + MENU need ~320px on one line. Below that
   the bar keeps every item — tighter gaps, and the CTA label may break onto
   two short lines inside its box instead of running into the wordmark.
   Min-width:0 lets the flex items give way rather than overflow the bar.
   2026-09-28 robust pass. */
@media (max-width:319px){
  .nav{gap:6px; padding:0 max(14px, env(safe-area-inset-left));}
  .nav-mark{flex:0 0 auto; font-size:16px;}
  .nav-links{min-width:0;}
  .nav-links a.cta{
    padding:4px 10px; height:auto; min-height:34px;
    white-space:nowrap; text-align:center; line-height:1.15;
    font-size:11px; letter-spacing:0;
    max-width:124px;
  }
  .nav-toggle{padding-left:6px; gap:5px; letter-spacing:.04em;}
}

/* =================================================================
   HOME (MONOE PORT) — hero (2026-09-21 rebuild, replaces the
   "home composition" block)
   Structural refs, literal not "inspired by":
   - juliaborelli.com: the hero IS the name — a compact top-hugging
     lockup (name, one supporting line, marquee immediately under),
     never a forced full-viewport statement. That is why there is no
     dead band above it: nothing pushes it down.
   - MONOE: how the marquee/index rows below sit flush to one page
     margin, full-bleed, no centered wrapper.
   Page margin is --page-x (falls back locally if the shared shell
   hasn't defined it yet) — every element sits on this one edge,
   nothing centers itself in a max-width box.
   All spacing below is viewport-relative (clamp), not fixed rhythm
   tokens, so the measured reference proportions hold across screen
   sizes rather than reading as a fixed px gap on a wide monitor. ---- */
:root{
  --page-x: clamp(24px, 4vw, 72px);
  /* section-level separation: hairline, then one rhythm unit, then
     content — never an empty band before the heading */
  --sec-gap: clamp(16px, 2.5vw, 32px);
  --sec-pad: clamp(40px, 6vw, 96px);
  --hero-pad-top: clamp(40px, 7vw, 120px);
  --hero-pad-bottom: clamp(20px, 3vw, 48px);
  --row-pad: clamp(20px, 3.2vw, 44px);
  --row-pad-lead: clamp(24px, 4vw, 56px);
}

.hero{
  display:flex; flex-direction:column;
  position:relative;
  background:var(--black);
  color:var(--paper);
  border-bottom:1px solid var(--hairline-inv);
  padding-top:var(--nav-h);
}
.hero-top{padding:var(--hero-pad-top) var(--page-x) var(--hero-pad-bottom);}
.hero-name{
  display:block;
  font-family:var(--face);
  font-size:var(--fs-display);
  font-weight:var(--fw-display);
  letter-spacing:var(--ls-display);
  line-height:.94;
  text-transform:lowercase;
  color:var(--paper);
  user-select:none;
}
.hero-sub{
  margin-top:clamp(10px, 1.6vw, 20px);
  max-width:46ch;
  font-family:var(--face); font-size:var(--fs-body); font-weight:400; letter-spacing:0;
  color:var(--on-dark-1); line-height:1.5;
}
.hero-cta{
  display:inline-flex; align-items:center; gap:var(--r2);
  margin-top:clamp(20px, 3vw, 40px);
  padding:clamp(12px,1.4vw,16px) clamp(20px,2.6vw,32px);
  font-family:var(--face); font-weight:600; font-size:var(--fs-body); letter-spacing:0; text-transform:lowercase;
  color:var(--black); background:var(--paper);
  border-radius:2px;
  transition:background .2s ease-out, color .2s ease-out;
}
.hero-cta .arr{transition:transform .35s cubic-bezier(.22,1,.36,1);}
.hero-cta:hover, .hero-cta:focus-visible{background:var(--accent); color:var(--paper);}
.hero-cta:hover .arr{transform:translateX(5px);}
.hero-cta:focus-visible{outline:2px solid var(--green-light); outline-offset:2px;}

/* ---- juliaborelli.com-style marquee, tight under the lockup ---- */
.hero-marquee{
  overflow:hidden;
  border-top:1px solid var(--hairline-inv);
  padding:clamp(10px,1.4vw,16px) 0;
}
.hero-marquee:hover .marquee-track{animation-play-state:paused;}
.marquee-track{display:flex; width:max-content; animation:jl-marquee 40s linear infinite;}
.marquee-group{display:flex; flex:none;}
.marquee-group span{
  display:inline-flex; align-items:center;
  padding:0 clamp(20px,3vw,48px);
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--on-dark-1);
  white-space:nowrap;
}
.marquee-group span::after{content:'\2022'; margin-left:clamp(10px,1.6vw,24px); color:var(--on-dark-2);}
@keyframes jl-marquee{ from{transform:translateX(0);} to{transform:translateX(-50%);} }
@media (prefers-reduced-motion:reduce){
  .marquee-track{animation:none;}
  .hero-marquee{overflow-x:auto;}
}
@media (max-width:760px){
  .hero{padding-top:var(--nav-h-mobile);}
  .hero-sub{max-width:none;}
}

/* =================================================================
   HOME (MONOE PORT) — services index
   MONOE's own "Our latest arrivals/." index: a single flush-left
   column of rows, hairline between each, the lead item jumping to
   display weight/scale, a right-aligned meta glyph standing in for
   MONOE's right-aligned price (no prices here — arrow only). No
   floating aside column, no numbering. Section opens straight off
   its own hairline + --sec-gap — nothing empty above the heading.
   ================================================================= */
.svcp-head{
  display:flex; align-items:baseline; justify-content:space-between; gap:var(--r3);
  padding:var(--sec-pad) var(--page-x) var(--sec-gap);
  border-top:1px solid var(--hairline);
}
.svcp-head h2{
  font-family:var(--face); font-size:var(--fs-h2); font-weight:var(--fw-h2); letter-spacing:var(--ls-h2);
  text-transform:lowercase; color:var(--black);
}
.svcp-list{border-top:1px solid var(--hairline);}
.svcp-row{
  display:flex; align-items:center; justify-content:space-between; gap:var(--r3);
  padding:var(--row-pad) var(--page-x);
  border-bottom:1px solid var(--hairline);
  font-family:var(--face); font-size:var(--fs-h1); font-weight:var(--fw-h1); letter-spacing:var(--ls-h1);
  text-transform:lowercase; color:var(--black);
  transition:color .2s ease-out;
}
.svcp-row .svcp-meta{
  font-family:var(--face); font-size:var(--fs-h2); color:var(--grey-1);
  transition:color .2s ease-out, transform .35s cubic-bezier(.22,1,.36,1);
}
.svcp-row:hover{color:var(--accent);}
.svcp-row:hover .svcp-meta{color:var(--accent); transform:translateX(5px);}
.svcp-lead{
  padding-top:var(--row-pad-lead); padding-bottom:var(--row-pad-lead);
  font-size:clamp(34px,5vw,64px); font-weight:var(--fw-display); letter-spacing:var(--ls-display); line-height:.98;
}
@media (max-width:760px){
  .svcp-row{font-size:var(--fs-body);}
  .svcp-lead{font-size:clamp(30px,10vw,44px);}
}

/* ================= SECTION SCAFFOLD ================= */
.sec{border-bottom:none;}
.sec + .sec{border-top:none;}
/* MONOE separation rule: whitespace does the work; hairline only
   between two rows of the SAME surface (service rows, work rows,
   testimonial cards) — never between sections/surfaces. */
/* .sec-head is used ONLY on /services/ — ported 1:1 to the home
   section-head pattern (svcp-head / work-preview-head): small
   flush-left h2 + hairline-top, opening straight off --sec-pad/
   --sec-gap, no numbered idx box, no forced right-aligned link
   (this head has nothing to link out to). */
.sec-head{
  display:flex; align-items:baseline; justify-content:space-between; gap:var(--r3);
  padding:var(--sec-pad) var(--page-x) var(--sec-gap);
  border-top:1px solid var(--hairline);
}
.sec-head h2{
  font-family:var(--face);
  font-size:var(--fs-h2);
  font-weight:var(--fw-h2);
  letter-spacing:var(--ls-h2);
  line-height:1.15;
  text-transform:lowercase;
}
.sec-head h2 em{font-style:normal; color:var(--grey-1);}
.dark .sec-head{border-top:1px solid var(--hairline-inv);}
.dark .sec-head h2 em{color:var(--on-dark-1);}

/* ================= SERVICE ROWS (home svcp-row pattern: full-width,
   fluid --row-pad rhythm, --page-x edge) + price as right-aligned row
   meta ("from $X" / "by inquiry"), same place MONOE puts its price ================= */
.svc-rows{border-top:1px solid var(--hairline);}
.svc-row{
  display:grid;
  grid-template-columns:44px 1fr auto 24px;
  gap:clamp(14px,3vw,40px);
  align-items:center;
  padding:var(--row-pad) var(--page-x);
  border-bottom:1px solid var(--hairline);
  position:relative;
  transition:background .2s ease-out;
}
.svc-row:last-child{border-bottom:none;}
.svc-row .svc-idx{font-family:var(--face); font-size:var(--fs-small); letter-spacing:.08em; color:var(--grey-1); font-variant-numeric:tabular-nums;}
.svc-row .svc-name{display:flex; flex-direction:column; gap:var(--r1); min-width:0;}
.svc-row .svc-name b{
  font-family:var(--face);
  font-weight:var(--fw-h1); font-size:var(--fs-h1); letter-spacing:var(--ls-h1); text-transform:lowercase;
  color:var(--black); transition:color .2s ease-out;
}
.svc-row .svc-name small{
  font-family:var(--face); font-weight:400; font-size:var(--fs-body); letter-spacing:0; text-transform:none;
  color:var(--grey-1); max-width:480px; line-height:1.55;
}
.svc-row .svc-price{
  font-family:var(--face); font-weight:600; font-size:var(--fs-label); letter-spacing:.08em; text-transform:uppercase;
  color:var(--grey-1); text-align:right; white-space:nowrap; transition:color .2s ease-out;
}
.svc-row .svc-arr{font-family:var(--face); color:var(--black); justify-self:end; transition:color .2s ease-out, transform .35s cubic-bezier(.22,1,.36,1);}
.svc-row:hover{background:none;}
.svc-row:hover .svc-name b{color:var(--accent);}
.svc-row:hover .svc-price{color:var(--accent);}
.svc-row:hover .svc-arr{color:var(--accent); transform:translateX(5px);}
@media (max-width:640px){
  .svc-row{grid-template-columns:1fr auto; grid-template-areas:"name price" "idx idx"; row-gap:6px;}
  .svc-row .svc-idx{display:none;}
  .svc-row .svc-arr{display:none;}
  .svc-row .svc-name b{font-size:clamp(24px,7vw,36px);}
}

/* ================= RATES-style rows (service pages) ================= */
.rates{border-top:1px solid var(--hairline);}
.rate{
  display:grid;
  grid-template-columns:minmax(120px,1fr) 2fr auto;
  gap:clamp(16px,3vw,48px);
  align-items:center;
  padding:var(--r5) var(--pad-x);
  border-bottom:1px solid var(--hairline);
  position:relative;
  overflow:hidden;
  transition:background .2s ease-out;
}
.rate:last-child{border-bottom:none;}
.rate .meta{display:flex; flex-direction:column; gap:var(--r1);}
.rate .meta .n{font-family:var(--face); font-size:var(--fs-small); letter-spacing:.08em; color:var(--grey-1); font-weight:600;}
.rate .name h3{
  font-family:var(--face);
  font-size:var(--fs-h1);
  font-weight:var(--fw-h1); letter-spacing:var(--ls-h1); text-transform:lowercase;
  line-height:1.05;
}
.rate .name p{font-size:var(--fs-small); color:var(--grey-1); margin-top:var(--r1); max-width:460px; line-height:1.55;}
.rate .fig{text-align:right; display:flex; flex-direction:column; align-items:flex-end; gap:2px;}
.rate .fig .amount{
  font-family:var(--face); font-weight:500;
  font-size:clamp(36px,6vw,72px);
  letter-spacing:-.02em;
  line-height:1;
  color:var(--black);
  transition:color .2s ease-out;
  white-space:nowrap;
}
.rate .fig .amount sup{font-size:.42em; letter-spacing:0; vertical-align:.62em; color:var(--grey-1);}
.rate .fig .per{font-family:var(--face); font-size:var(--fs-label); letter-spacing:.08em; text-transform:uppercase; color:var(--grey-1);}
.rate .fig .amount.quote{
  font-family:var(--face);
  font-size:clamp(16px,2vw,22px);
  letter-spacing:0;
  text-transform:lowercase;
  color:var(--black);
  border:1px solid var(--black);
  border-radius:999px;
  padding:.35em .9em;
}
.rate:hover{background:none;}
.rate:hover .fig .amount sup{color:var(--accent);}
.rate:hover .fig .amount.quote{border-color:var(--accent); color:var(--accent);}
@media (max-width:760px){
  .rate{grid-template-columns:1fr; gap:var(--r2);}
  .rate .meta{flex-direction:row; justify-content:space-between;}
  .rate .fig{align-items:flex-start; text-align:left;}
}

/* ================= BLACK ZONE (hero + footer only — no mid-page alternation) ================= */
.dark{background:var(--black); color:var(--paper);}
.dark .sec-head .idx b{color:var(--paper);}
.dark .sec-head h2 em{color:var(--on-dark-1);}
.dark.sec{border-bottom:none;}

/* ================= STEPS (how it works — /services/ only) =================
   3 steps, not 4 — was repeat(4,1fr) with only 3 <div class="step"> in the
   markup, which left a dead 4th empty column (the numbering skipped 02
   entirely, same bug). Grid and numbering fixed together. */
.steps{display:grid; grid-template-columns:repeat(3,1fr); padding:0 var(--page-x); border-top:1px solid var(--hairline-inv);}
.step{
  padding:var(--r4) var(--r3) var(--r5);
  border-right:1px solid var(--hairline-inv);
  position:relative;
}
.step:last-child{border-right:none;}
.step .n{
  font-family:var(--face); font-weight:500;
  font-size:clamp(32px,4vw,48px);
  letter-spacing:-.02em; line-height:1;
  color:var(--paper);
  display:block; margin-bottom:var(--r2);
}
.step h3{
  font-family:var(--face);
  font-size:17px; font-weight:500; letter-spacing:0; text-transform:lowercase;
  margin-bottom:var(--r1); color:var(--paper);
}
.step p{font-size:var(--fs-small); color:var(--on-dark-1); line-height:1.6;}
.step::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:0;
  background:var(--accent);
  transition:height .2s ease-out;
  opacity:1;
}
.step:hover::after{height:2px;}
@media (max-width:640px){
  .steps{grid-template-columns:1fr;}
  .step{border-right:none !important; border-bottom:1px solid var(--hairline-inv);}
  .step:last-child{border-bottom:none;}
}

/* ================= CONTACT / CTA ROWS (black bookend) ================= */
.contact-rows{border-top:1px solid var(--hairline-inv);}
.crow{
  display:grid;
  grid-template-columns:minmax(90px,1fr) 3fr auto;
  gap:clamp(14px,3vw,40px);
  align-items:center;
  padding:var(--r5) var(--pad-x);
  border-bottom:1px solid var(--hairline-inv);
  position:relative;
  overflow:hidden;
}
.crow::before{content:none;}
.crow > *{position:relative; z-index:1;}
.crow .k{font-family:var(--face); font-size:var(--fs-label); letter-spacing:.08em; text-transform:uppercase; color:var(--on-dark-1); transition:color .2s ease-out;}
.crow .v{
  font-family:var(--face);
  font-size:clamp(19px,3vw,34px);
  font-weight:500; letter-spacing:-.01em; text-transform:lowercase;
  color:var(--paper);
  line-height:1.15;
}
.crow .v small{display:block; font-family:var(--face); font-weight:400; font-size:var(--fs-small); letter-spacing:0; color:var(--on-dark-1); margin-top:var(--r1); text-transform:none;}
.crow .arr{font-family:var(--face); font-size:clamp(18px,2.4vw,26px); color:var(--on-dark-1); transition:color .2s ease-out;}
.crow:hover .k{color:var(--accent);}
.crow:hover .v{color:var(--paper);}
.crow:hover .v small{color:var(--on-dark-1);}
.crow:hover .arr{color:var(--accent);}
@media (max-width:640px){
  .crow{grid-template-columns:1fr auto; row-gap:var(--r1);}
  .crow .k{grid-column:1 / -1;}
}

.contact-bookend{padding:var(--r24) var(--pad-x) var(--r16);}
.contact-bookend .lbl{display:block; margin-bottom:var(--r2);}
.contact-email{
  display:inline-block;
  font-family:var(--face);
  font-size:clamp(30px,7vw,84px);
  font-weight:500;
  letter-spacing:-.01em;
  line-height:1.02;
  text-transform:lowercase;
  color:var(--paper);
  transition:color .2s ease-out;
}
.contact-email:hover, .contact-email:focus-visible{color:var(--accent);}

.contact-micro{display:flex; flex-wrap:wrap; gap:var(--r2) var(--r5); padding:var(--r4) var(--pad-x) var(--r10);}
.contact-micro a, .contact-micro span{font-family:var(--face); font-size:var(--fs-small); letter-spacing:0; color:var(--on-dark-1);}
.contact-micro a{border-bottom:1px solid var(--hairline-inv); padding-bottom:3px; transition:color .2s ease-out, border-color .2s ease-out;}
.contact-micro a:hover{color:var(--paper); border-color:var(--accent);}

/* ================= CONTACT FORM (site-wide, sits directly above the footer) ================= */
.contact-cta{
  padding:var(--r6) var(--pad-x);
  border-top:1px solid var(--hairline);
}
.contact-cta .cta-inner{
  display:grid;
  grid-template-columns:minmax(200px,1fr) 3fr;
  gap:var(--r6);
  align-items:stretch;
  text-align:left;
}
.cta-info{display:flex; flex-direction:column; gap:0;}
.cta-info .lbl{display:block; margin-bottom:var(--r1);}
.contact-cta h2{
  font-family:var(--face);
  font-size:var(--fs-h2);
  font-weight:500; letter-spacing:-.01em; line-height:1.15; text-transform:lowercase;
}
.gform{text-align:left;}
.gfield{margin-bottom:var(--r1);}
.gfield label{
  display:block;
  font-family:var(--face); font-size:var(--fs-label); font-weight:500; letter-spacing:.14em;
  text-transform:lowercase; color:var(--grey-1); margin-bottom:6px;
}
.gfield input, .gfield textarea{
  display:block; width:100%;
  font-family:var(--face); font-size:16px; color:var(--black);
  background:transparent; border:none; border-bottom:1px solid var(--grey-2);
  border-radius:0; padding:9px 2px 10px; min-height:44px;
  transition:border-color .2s ease-out;
}
.gfield textarea{resize:vertical; min-height:72px; line-height:1.5;}
.gfield input:focus, .gfield textarea:focus{outline:none; border-bottom:1.5px solid var(--accent);}
.gfield input:valid:not(:placeholder-shown):not(:focus),
.gfield textarea:valid:not(:placeholder-shown):not(:focus){border-bottom-color:var(--green-light);}
/* footer contact form inline errors (footer-form.js, novalidate) — same
   pattern as the intake's .field.has-error */
.gfield.has-error input, .gfield.has-error textarea{border-bottom-color:var(--error);}
.gfield .err-msg{display:none; font-family:var(--face); font-size:var(--fs-label); letter-spacing:.04em; text-transform:none; color:var(--error); margin-top:6px;}
.gfield.has-error .err-msg{display:block;}
.sf-error{font-family:var(--face); font-size:var(--fs-small); font-weight:500; line-height:1.5; color:var(--error); margin-top:var(--r2);}
.gform-submit{
  display:inline-block; width:auto;
  margin-top:var(--r2);
  padding:12px 39px;
  border:1px solid var(--green-ink); border-radius:2px;
  background:transparent; color:var(--black);
  font-family:var(--face); font-weight:600; font-size:15px; letter-spacing:-.01em;
  text-transform:lowercase; cursor:pointer;
  transition:background .2s ease-out, color .2s ease-out, border-color .2s ease-out;
}
.gform-submit:hover, .gform-submit:focus-visible{background:none; color:var(--green-ink); border-color:var(--green-ink);}
.gform-submit:focus-visible{outline:2px solid var(--green-light); outline-offset:2px;}
@media (max-width:900px){
  .contact-cta .cta-inner{grid-template-columns:1fr; gap:var(--r4);}
  .cta-info{gap:var(--r3);}
  .gform-submit{display:block; width:100%;}
}

/* ================= FOOTER — black surface, single line: copyright + icons ================= */
.footer{background:var(--black); overflow:hidden; position:relative;}
.footer-meta{
  display:flex; align-items:center; justify-content:space-between; gap:var(--r3);
  padding:var(--r2) var(--pad-x);
  min-height:56px;
}
.footer-meta span, .footer-meta a{font-family:var(--face); font-size:var(--fs-small); letter-spacing:0; color:var(--on-dark-1);}
.footer-meta a{transition:color .2s ease-out;}
.footer-meta a:hover, .footer-meta a:focus-visible{color:var(--accent);}
.footer-social{display:flex; align-items:center; gap:var(--r2);}
.footer-social a{
  display:flex; align-items:center; justify-content:center;
  width:24px; height:24px; flex:none;
  color:var(--paper);
  opacity:.7;
  transition:opacity .2s ease-out, color .2s ease-out;
}
.footer-social a svg{width:20px; height:20px; display:block;}
.footer-social a:hover, .footer-social a:focus-visible{opacity:1; color:var(--accent);}
.footer-word{
  font-family:var(--face);
  font-weight:300;
  font-size:clamp(60px,22vw,360px);
  letter-spacing:-.02em;
  line-height:.9;
  text-transform:lowercase;
  color:var(--on-dark-2);
  text-align:center;
  transform:translateY(.14em);
  user-select:none;
  white-space:nowrap;
}

/* .preview-all is a shared component (also used on /work/) — kept here,
   unrelated to the svcp-* rebuild above. */
.preview-all{
  display:inline-block;
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--grey-1); border-bottom:1px solid var(--hairline); padding-bottom:3px; width:fit-content;
  transition:color .2s ease-out, border-color .2s ease-out;
}
.preview-all:hover{color:var(--accent); border-color:var(--accent);}

/* ================= SINGLE TESTIMONIAL PULL (home) ================= */
/* order: label, then stars, then attribution (name + track/service), then the quote itself.
   Top/bottom padding + hairline match the services/work preview sections' own rhythm
   (row inset r4, closing gap r8) instead of the section's old standalone r6. */
.testi-pull{padding:var(--r4) var(--pad-x) var(--r8); border-top:1px solid var(--hairline);}
.testi-pull .words-label{display:block; margin-bottom:var(--r2);}
.testi-pull .words-stars{display:flex; gap:4px; margin-bottom:var(--r2);}
/* default unfilled — same rule shape as the #words grid on /work/, so a star only
   reads as "rated" once JS (or a correctly-authored fallback) adds .is-filled to it */
.testi-pull .words-stars .star{width:14px; height:14px; fill:none; stroke:var(--grey-2); stroke-width:1.4; flex:none;}
.testi-pull .words-stars .star.is-filled{fill:var(--black); stroke:var(--black);}
.testi-pull .words-attr{display:flex; flex-direction:column; gap:4px; margin-bottom:var(--r2);}
.testi-pull .words-attr b{font-family:var(--face); font-weight:500; font-size:14.5px; color:var(--black); text-transform:lowercase;}
.testi-pull .words-quote{
  font-family:var(--face); font-size:var(--fs-h2); font-weight:400; font-style:italic;
  line-height:1.4; letter-spacing:0; color:var(--black); max-width:44ch; margin-bottom:var(--r1);
}
.testi-pull .words-toggle{
  display:inline-block; background:none; border:none; padding:0; cursor:pointer;
  margin-bottom:var(--r2); transition:color .2s ease-out;
}
.testi-pull .words-toggle:hover{color:var(--accent);}
.testi-pull .words-more{
  display:inline-block; margin-top:var(--r1);
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--black); border-bottom:1px solid var(--hairline); padding-bottom:2px;
  transition:color .2s ease-out, border-color .2s ease-out;
}
.testi-pull .words-more:hover{color:var(--accent); border-color:var(--accent);}

/* ================= WORK INDEX HERO (/work/) ================= */
.work-index-hero{
  padding:calc(var(--nav-h) + var(--r10)) var(--pad-x) var(--r6);
  border-bottom:1px solid var(--hairline);
}
.work-index-hero .lbl{display:block; margin-bottom:var(--r2);}
.work-index-hero h1{
  font-family:var(--face);
  font-size:var(--fs-h1);
  font-weight:var(--fw-h1);
  letter-spacing:var(--ls-h1);
  line-height:1.05;
  text-transform:lowercase;
}

/* ================= SECTION HEADING (mid-page — e.g. "testimonials.") =================
   same treatment as .work-index-hero h1, scaled for a section that isn't the page hero */
.words-head{padding:var(--r10) var(--pad-x) var(--r4);}
.words-head h2{
  font-family:var(--face);
  font-size:var(--fs-h1);
  font-weight:var(--fw-h1);
  letter-spacing:var(--ls-h1);
  line-height:1.05;
  text-transform:lowercase;
}

/* ================= SELECTED WORK — paper, static waveform, no colour ================= */
#work .work-rows, .work-rows{border-top:1px solid var(--hairline);}
#work .work-row, .work-row{
  display:grid;
  grid-template-columns:40px minmax(180px,240px) 1fr auto;
  grid-template-areas:"idx meta wave time";
  column-gap:clamp(16px,2.6vw,32px);
  align-items:center;
  padding:var(--r4) var(--pad-x);
  border-bottom:1px solid var(--hairline);
}
#work .work-row:last-child, .work-row:last-child{border-bottom:none;}
#work .work-idx, .work-idx{grid-area:idx; align-self:start; padding-top:3px; font-family:var(--face); font-weight:600; font-size:var(--fs-small); letter-spacing:.04em; font-variant-numeric:tabular-nums; color:var(--grey-1);}
#work .work-meta, .work-meta{grid-area:meta; display:flex; flex-direction:column; gap:var(--r1); min-width:0;}
#work .work-meta .k, .work-meta .k{font-family:var(--face); font-size:var(--fs-label); letter-spacing:.08em; text-transform:uppercase; color:var(--green-ink); order:2;}
#work .work-meta a.k:hover, .work-meta a.k:hover,
#work .work-meta a.k:focus-visible, .work-meta a.k:focus-visible{color:var(--accent);}
#work .work-meta .v, .work-meta .v{
  font-family:var(--face);
  font-size:clamp(16px,1.6vw,20px);
  font-weight:500; letter-spacing:-.01em; text-transform:lowercase;
  color:var(--black); line-height:1.3; order:1;
}
#work .work-meta .v .dash, .work-meta .v .dash{color:var(--grey-1); font-weight:400;}
#work .player, .player{grid-area:wave; display:flex; align-items:center; gap:clamp(10px,2vw,18px); min-width:0;}
#work .play-btn, .play-btn{
  flex:none; width:40px; height:40px; border-radius:50%;
  border:1px solid var(--grey-2);
  background:transparent;
  color:var(--black);
  font-family:var(--face);
  display:flex; align-items:center; justify-content:center;
  cursor:pointer;
  transition:border-color .2s ease-out;
  padding:0;
}
#work .play-btn:hover, .play-btn:hover,
#work .play-btn:focus-visible, .play-btn:focus-visible{border-color:var(--accent); background:none;}
#work .play-btn:focus-visible, .play-btn:focus-visible{outline:1px solid var(--accent); outline-offset:2px;}
#work .play-btn .ic-play{font-size:11px; margin-left:2px;}
#work .play-btn .ic-pause{font-size:11px; display:none;}
#work .play-btn[aria-pressed="true"] .ic-play{display:none;}
#work .play-btn[aria-pressed="true"] .ic-pause{display:inline;}
/* playing state — icon + ring go green-ink while a track is actually
   playing (the canvas waveform playhead itself is drawn by instruments.js,
   which does not yet read a CSS var for its stroke colour — see DESIGN.md §1). */
#work .play-btn[aria-pressed="true"], .play-btn[aria-pressed="true"]{border-color:var(--accent); color:var(--accent);}
#work .wave, .wave{flex:1; height:52px; min-width:0; cursor:pointer; position:relative;}
#work .wave canvas, .wave canvas{display:block; width:100%; height:100%;}
#work .wave:focus-visible, .wave:focus-visible{outline:1px solid var(--accent); outline-offset:3px;}
#work .work-tail, .work-tail{grid-area:time; flex:none; display:flex; flex-direction:column; align-items:flex-end; gap:6px;}
#work .time, .time{flex:none; font-size:var(--fs-small); letter-spacing:.04em; color:var(--grey-1); font-variant-numeric:tabular-nums; white-space:nowrap; min-width:74px; text-align:right;}
#work .listen-slot:empty, .listen-slot:empty{display:none;}
#work .listen-slot, .listen-slot{font-family:var(--face); font-size:var(--fs-small); letter-spacing:0; text-transform:lowercase; color:var(--black); border-bottom:1px solid var(--hairline); padding-bottom:2px; transition:color .2s ease-out, border-color .2s ease-out;}
#work .listen-slot:hover, .listen-slot:hover{color:var(--accent); border-color:var(--accent);}
#work .player.player-soon, .player.player-soon{height:52px;}
#work .soon-label, .soon-label{font-family:var(--face); font-size:var(--fs-small); letter-spacing:0; text-transform:lowercase; color:var(--grey-1);}
@media (max-width:760px){
  #work .work-row, .work-row{
    grid-template-columns:auto 1fr auto;
    grid-template-areas:"idx meta time" "wave wave wave";
    row-gap:var(--r2);
  }
  #work .wave, .wave{height:48px;}
}

/* ================= TESTIMONIAL CARDS — paper, no border/shadow, black stars ================= */
#words .words-grid, .words-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(360px,1fr));
  gap:1px;
  background:var(--hairline);
  border-top:1px solid var(--hairline);
  border-bottom:1px solid var(--hairline);
}
#words .words-card, .words-card{
  background:var(--paper);
  padding:var(--r5);
  display:flex; flex-direction:column; gap:var(--r2);
}
#words .words-stars, .words-stars{display:flex; gap:4px;}
#words .words-stars .star, .words-stars .star{
  width:14px; height:14px;
  fill:none;
  stroke:var(--grey-2);
  stroke-width:1.4;
  flex:none;
}
#words .words-stars .star.is-filled, .words-stars .star.is-filled{fill:var(--black); stroke:var(--black);}
/* order: stars, then attribution (name + track/service), then the quote itself */
#words .words-attr, .words-attr{display:flex; flex-direction:column; gap:var(--r1);}
#words .words-attr b, .words-attr b{
  font-family:var(--face); font-weight:500; font-size:14.5px; letter-spacing:-.01em;
  color:var(--black); text-transform:lowercase; font-style:normal;
}
#words .words-attr .lbl, .words-attr .lbl{font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase; color:var(--grey-1);}
#words .words-quote, .words-quote{
  font-family:var(--face);
  font-size:var(--fs-body);
  font-weight:400;
  font-style:italic;
  line-height:1.6;
  letter-spacing:0;
  color:var(--black);
  max-width:68ch;
}
#words .words-toggle, .words-toggle{
  align-self:flex-start;
  display:inline-block; background:none; border:none; padding:0; cursor:pointer;
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--grey-1);
  transition:color .2s ease-out;
}
#words .words-toggle:hover, .words-toggle:hover{color:var(--accent);}
#words .words-listen, .words-listen{
  align-self:flex-start;
  margin-top:auto;
  font-family:var(--face); font-size:var(--fs-small); letter-spacing:0; text-transform:lowercase;
  color:var(--black); border-bottom:1px solid var(--hairline); padding-bottom:2px;
  transition:color .2s ease-out, border-color .2s ease-out;
}
#words .words-listen:hover, .words-listen:hover{color:var(--accent); border-color:var(--accent);}
@media (max-width:480px){
  #words .words-grid, .words-grid{grid-template-columns:1fr;}
}

/* ================= ABOUT (MONOE) — label column left, measured copy offset right ================= */
.about-hero{padding:calc(var(--nav-h) + var(--r10)) var(--pad-x) var(--r6); border-bottom:1px solid var(--hairline);}
.about-hero h1{
  font-family:var(--face);
  font-size:var(--fs-h1);
  font-weight:var(--fw-h1);
  letter-spacing:var(--ls-h1);
  line-height:1.05;
  text-transform:lowercase;
}
.about-bio{padding:var(--r24) var(--pad-x) var(--r16); border-bottom:1px solid var(--hairline);}
.about-grid{
  display:grid;
  grid-template-columns:minmax(120px,1fr) minmax(0,2fr);
  gap:var(--r3);
  align-items:start;
}
.about-grid > .lbl{padding-top:.3em;}
.bio-copy{display:flex; flex-direction:column; gap:var(--r4); max-width:60ch;}
.bio-copy p{
  font-family:var(--face);
  font-size:var(--fs-body);
  line-height:1.65;
  letter-spacing:0;
  color:var(--black);
}
.bio-copy p.lead{
  font-size:clamp(19px, 1.7vw, 23px);
  line-height:1.5;
  letter-spacing:-.005em;
}
@media (max-width:640px){
  .about-grid{grid-template-columns:1fr; gap:var(--r3);}
  .bio-copy{max-width:none;}
}

/* ================= FAQ ACCORDION (STEEL) — +/× glyph, hairline every row ================= */
.faq-hero{padding:calc(var(--nav-h) + var(--r10)) var(--pad-x) var(--r5);}
.faq-hero .lbl{display:block; margin-bottom:var(--r2);}
.faq-hero h1{
  font-family:var(--face);
  font-size:var(--fs-h1);
  font-weight:var(--fw-h1);
  letter-spacing:var(--ls-h1);
  line-height:1.05;
  text-transform:lowercase;
  margin-bottom:var(--r2);
}
.faq-hero .dek{
  font-family:var(--face);
  font-size:var(--fs-body);
  font-weight:400;
  color:var(--grey-1);
  max-width:560px;
}
.faq-group{padding:var(--r2) var(--pad-x) 0;}
.faq-group:last-of-type{padding-bottom:var(--r2);}
.faq-group .grp-lbl{
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--grey-1);
  padding:var(--r4) 0 var(--r2);
}
.faq-list{border-top:1px solid var(--hairline);}
.faq-row{border-bottom:1px solid var(--hairline);}
.faq-q{
  width:100%;
  display:flex; align-items:center; justify-content:space-between; gap:var(--r3);
  padding:var(--r3) 0;
  background:none; border:none;
  text-align:left;
  cursor:pointer;
  -webkit-appearance:none; appearance:none;
}
.faq-q .qt{
  font-family:var(--face);
  font-size:var(--fs-body);
  font-weight:500;
  letter-spacing:0;
  color:var(--black);
  line-height:1.35;
  transition:color .2s ease-out;
}
.faq-q .ic{position:relative; flex:none; width:22px; height:22px;}
.faq-q .ic::before,
.faq-q .ic::after{
  content:'';
  position:absolute; left:50%; top:50%;
  background:var(--black);
  transform:translate(-50%,-50%);
  transition:transform .28s cubic-bezier(.4,0,.2,1), background .2s ease-out;
}
.faq-q .ic::before{width:14px; height:1.5px;}
.faq-q .ic::after{width:1.5px; height:14px;}
.faq-row[data-open="true"] .faq-q .ic::after{transform:translate(-50%,-50%) rotate(90deg); opacity:0;}
.faq-q:hover .qt,
.faq-q:focus-visible .qt{color:var(--accent);}
.faq-q:hover .ic::before,
.faq-q:hover .ic::after,
.faq-q:focus-visible .ic::before,
.faq-q:focus-visible .ic::after{background:var(--accent);}
.faq-q:focus-visible{outline:2px solid var(--accent); outline-offset:4px;}
.faq-a{
  display:grid;
  grid-template-rows:0fr;
  opacity:0;
  transition:grid-template-rows .28s cubic-bezier(.4,0,.2,1), opacity .2s ease-out;
}
.faq-row[data-open="true"] .faq-a{grid-template-rows:1fr; opacity:1;}
.faq-a-inner{overflow:hidden;}
.faq-a p{
  font-family:var(--face);
  font-size:var(--fs-body);
  line-height:1.65;
  color:var(--grey-1);
  max-width:640px;
  padding-bottom:var(--r3);
}
@media (max-width:640px){
  .faq-q{gap:var(--r2);}
}

/* ================= SERVICE HERO (h1 + dek) ================= */
.svc-hero{padding:calc(var(--nav-h) + var(--r10)) var(--pad-x) var(--r6); border-bottom:1px solid var(--hairline);}
.svc-hero .lbl{display:block; margin-bottom:var(--r2);}
.svc-hero h1{
  font-family:var(--face);
  font-size:var(--fs-h1);
  font-weight:var(--fw-h1);
  letter-spacing:var(--ls-h1);
  line-height:1.05;
  text-transform:lowercase;
  margin-bottom:var(--r2);
}
.svc-hero .dek{
  font-family:var(--face);
  font-size:var(--fs-body);
  font-weight:400;
  color:var(--grey-1);
  max-width:560px;
  margin-bottom:var(--r4);
}
.svc-hero .price-row{display:flex; align-items:baseline; gap:var(--r2); flex-wrap:wrap;}
.svc-hero .price{
  font-family:var(--face); font-weight:500;
  font-size:clamp(40px,7vw,80px);
  letter-spacing:-.02em;
  line-height:1;
  color:var(--black);
  white-space:nowrap;
}
.svc-hero .price sup{font-size:.4em; letter-spacing:0; vertical-align:.62em; color:var(--grey-1);}
.svc-hero .price.quote{
  font-size:clamp(18px,2.4vw,26px);
  text-transform:lowercase;
  color:var(--black);
  border:1px solid var(--black);
  border-radius:999px;
  padding:.3em .85em;
}
.svc-hero .per{font-family:var(--face); font-size:var(--fs-label); letter-spacing:.08em; text-transform:uppercase; color:var(--grey-1);}

/* ---------- generic content section ---------- */
.blk{padding:var(--r5) var(--pad-x); border-bottom:1px solid var(--hairline);}
.blk.dark{border-bottom:1px solid var(--hairline-inv);}
.blk h2{
  font-family:var(--face);
  font-size:var(--fs-h2);
  font-weight:var(--fw-h2); letter-spacing:var(--ls-h2); text-transform:lowercase;
  margin-bottom:var(--r3);
}
.blk .sub{font-family:var(--face); font-size:var(--fs-small); color:var(--grey-1); max-width:560px; margin-bottom:var(--r3); line-height:1.6;}
.dark .blk .sub{color:var(--on-dark-1);}

/* ---------- checklist ---------- */
.chk-list{display:grid; gap:0; border-top:1px solid var(--hairline);}
.dark .chk-list{border-top:1px solid var(--hairline-inv);}
.chk-item{
  display:flex; align-items:baseline; gap:var(--r2);
  padding:var(--r2) 0;
  border-bottom:1px solid var(--hairline);
  font-family:var(--face);
  font-size:var(--fs-body);
  line-height:1.5;
}
.dark .chk-item{border-bottom:1px solid var(--hairline-inv);}
.chk-item:last-child{border-bottom:none;}
.chk-item .mk{font-family:var(--face); font-size:var(--fs-small); color:var(--black); flex:none;}
.dark .chk-item .mk{color:var(--paper);}

/* ---------- two-column layout for content sections ---------- */
.blk-grid{display:grid; grid-template-columns:1fr 1fr; gap:clamp(28px,5vw,64px);}
@media (max-width:760px){ .blk-grid{grid-template-columns:1fr;} }

/* ---------- inline spec list (file prep) ---------- */
.spec-list{border-top:1px solid var(--hairline);}
.spec-item{
  display:flex; gap:var(--r2);
  padding:var(--r2) 0;
  border-bottom:1px solid var(--hairline);
  font-family:var(--face); font-size:var(--fs-small); color:var(--grey-1); line-height:1.55;
}
.spec-item:last-child{border-bottom:none;}
.spec-item .k{
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--black); flex:none; width:112px;
}
.spec-link{
  display:inline-flex; align-items:center; gap:8px;
  margin-top:var(--r3);
  font-family:var(--face); font-size:var(--fs-label); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--black);
  border-bottom:1px solid var(--hairline);
  padding-bottom:4px;
  transition:border-color .2s ease-out, color .2s ease-out;
}
.spec-link:hover{border-color:var(--accent); color:var(--accent);}

/* ---------- CTA block ---------- */
.cta-block{padding:var(--r5) var(--pad-x) var(--r6);}
.cta-main{
  display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap;
  gap:var(--r2);
  padding:var(--r4) var(--r4);
  border:1px solid var(--hairline-inv);
  transition:background .2s ease-out, border-color .2s ease-out;
}
.dark .cta-main{border-color:var(--hairline-inv);}
.cta-main:hover{background:none; border-color:var(--accent);}
.cta-main:focus-visible{outline:2px solid var(--green-light); outline-offset:2px;}
.cta-main .lbl-txt{
  font-family:var(--face);
  font-size:clamp(19px,3vw,30px);
  font-weight:500; letter-spacing:-.01em; text-transform:lowercase;
  color:var(--paper);
  transition:color .2s ease-out;
}
.cta-main:hover .lbl-txt{color:var(--accent);}
.cta-main .arr{font-family:var(--face); font-size:clamp(18px,2.2vw,26px); color:var(--paper); transition:color .2s ease-out;}
.cta-main:hover .arr{color:var(--accent);}
.cta-secondary{display:flex; flex-wrap:wrap; gap:var(--r2) var(--r4); margin-top:var(--r3);}
.cta-secondary a{
  font-family:var(--face); font-size:var(--fs-small); letter-spacing:0; text-transform:lowercase;
  color:var(--on-dark-1);
  border-bottom:1px solid var(--hairline-inv);
  padding-bottom:3px;
  transition:color .2s ease-out, border-color .2s ease-out;
}
.cta-secondary a:hover{color:var(--paper); border-color:var(--accent);}

/* ---------- back-to-work link ---------- */
.back-link{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--face); font-size:var(--fs-small); letter-spacing:0; text-transform:lowercase;
  color:var(--grey-1);
  border-bottom:1px solid var(--hairline);
  padding-bottom:3px;
  transition:color .2s ease-out, border-color .2s ease-out;
}
.back-link:hover{color:var(--black); border-color:var(--accent);}
.dark .back-link{color:var(--on-dark-1); border-color:var(--hairline-inv);}
.dark .back-link:hover{color:var(--paper); border-color:var(--accent);}

/* ================= FORM FIELDS — underline only, uppercase label ================= */
.fset-title, .required-note, .submit-note, .status-eyebrow,
.field label, .rating-field > label, .check-group .opt label, .kind-change{
  font-family:var(--face);
  font-size:var(--fs-label);
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--grey-1);
}
.fset-title{padding-bottom:var(--r2); margin-bottom:var(--r3); border-bottom:1px solid var(--hairline);}
fieldset{border:none; padding:0; margin:0 0 var(--r5);}

.field{margin-bottom:var(--r3);}
.field label, .rating-field > label{display:block; color:var(--black); margin-bottom:var(--r1);}
.field label .req, .rating-field > label .req{display:inline-block; width:4px; height:4px; border-radius:50%; background:var(--black); margin-left:5px; vertical-align:middle;}
.required-note .req-dot{display:inline-block; width:4px; height:4px; border-radius:50%; background:var(--black); vertical-align:middle;}
.field .help{font-family:var(--face); font-size:var(--fs-small); color:var(--grey-1); line-height:1.55; margin-bottom:var(--r1);}
.field .help a{color:var(--black); text-decoration:underline; text-underline-offset:2px;}
.field .help a:hover{color:var(--accent);}

.field input[type="text"],
.field input[type="email"],
.field input[type="url"],
.field textarea,
.field select{
  width:100%;
  font-family:var(--face);
  font-size:var(--fs-body);
  color:var(--black);
  background:transparent;
  border:none;
  border-bottom:1px solid var(--grey-2);
  border-radius:0;
  padding:9px 2px 10px;
  min-height:44px;
  transition:border-color .2s ease-out;
}
.field select{
  font-family:var(--face);
  appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 7l5 6 5-6' fill='none' stroke='%236E6C66' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 2px center;
  padding-right:26px;
}
.field textarea{resize:vertical; min-height:88px; line-height:1.5;}
.field input:focus,
.field textarea:focus,
.field select:focus{outline:none; border-bottom:1.5px solid var(--green-ink);}
/* green "valid" underline only once the field actually holds a value —
   footer-form.js toggles .is-filled on every form control (2026-09-28 QA:
   empty optional fields matched :valid and sat green at rest, since
   :placeholder-shown never matches an input with no placeholder). */
.field input.is-filled:valid:not(:focus),
.field textarea.is-filled:valid:not(:focus),
.field select.is-filled:valid:not(:focus){border-bottom-color:var(--green-light);}
.field.has-error input,
.field.has-error textarea,
.field.has-error select{border-bottom-color:var(--error);}
.field .err-msg{display:none; font-family:var(--face); font-size:var(--fs-label); letter-spacing:.04em; text-transform:none; color:var(--error); margin-top:6px;}
.field.has-error .err-msg{display:block;}
/* failed "next"/"send" scrolls the first bad field into view — clear the
   fixed nav (+ the sticky step bar on /start/ desktop). */
.field, .rating-field, .gfield{scroll-margin-top:calc(var(--nav-h) + var(--r3));}
@media (min-width:900px){ .field, .rating-field, .gfield{scroll-margin-top:calc(var(--nav-h) + 72px);} }

.check-field{display:flex; align-items:flex-start; gap:var(--r2); min-height:44px; margin-bottom:var(--r3);}
.check-field label, .check-group .opt label{
  font-family:var(--face); font-size:var(--fs-small); font-weight:400; letter-spacing:0; text-transform:none;
  line-height:1.5; color:var(--black);
}
.check-field label a{color:var(--black); text-decoration:underline; text-underline-offset:2px;}
.check-field label a:hover{color:var(--accent);}
.check-group{display:flex; flex-wrap:wrap; gap:var(--r2) var(--r3); margin-top:var(--r1);}
.check-group .opt{display:flex; align-items:center; gap:9px; min-height:44px;}

.check-field input[type="checkbox"],
.check-group .opt input[type="checkbox"]{
  appearance:none; -webkit-appearance:none;
  width:16px; height:16px; flex:none; margin-top:3px;
  border:1.5px solid var(--grey-2);
  border-radius:2px;
  background:transparent;
  position:relative;
  cursor:pointer;
  transition:border-color .2s ease-out, background .2s ease-out;
}
.check-group .opt input[type="checkbox"]{margin-top:0;}
.check-field input[type="checkbox"]:hover,
.check-group .opt input[type="checkbox"]:hover{border-color:var(--accent);}
.check-field input[type="checkbox"]:checked,
.check-group .opt input[type="checkbox"]:checked{border-color:var(--black); background:var(--black);}
.check-field input[type="checkbox"]:checked::after,
.check-group .opt input[type="checkbox"]:checked::after{
  content:'';
  position:absolute; left:4px; top:1px;
  width:4px; height:8px;
  border:solid var(--paper);
  border-width:0 1.5px 1.5px 0;
  transform:rotate(45deg);
}
.check-field input[type="checkbox"]:focus-visible,
.check-group .opt input[type="checkbox"]:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}

/* mobile/desktop audit 2026-09-27 (#2): every checkbox on /start/ sits
   inside a .field.c-field wrapper (the per-field error/label shell) as
   well as .check-field — .c-field's own input rule in components.css
   (`.c-field input{padding:var(--r2) 0}`, meant for text inputs) still
   applies to the checkbox too since it sets a property this rule never
   touches, inflating the box from 16px square to ~16x34. Zero it back
   out here, and size up to 18px per the brand-collateral checkbox scale
   used elsewhere — box-sizing:border-box (inherited from the sitewide
   `*{box-sizing:border-box}`) keeps the border inside that 18px, and
   aspect-ratio is a belt-and-braces backstop against any future rule
   that sets only one axis. Same fix for both light and dark room since
   it's a box-model bug, not a color one. */
.field.c-field .check-field input[type="checkbox"],
.field.c-field .check-group .opt input[type="checkbox"]{
  padding:0; margin-top:3px; width:18px; height:18px; aspect-ratio:1; flex:none;
}
.field.c-field .check-group .opt input[type="checkbox"]{margin-top:0;}

.hp{position:absolute !important; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;}

/* ---------- chooser (production tab) ---------- */
.kind-chooser{margin-bottom:var(--r5);}
.kind-prompt{
  font-family:var(--face);
  font-size:var(--fs-h2);
  font-weight:var(--fw-h2); letter-spacing:var(--ls-h2); text-transform:lowercase;
  margin-bottom:var(--r3);
}
.kind-options{display:grid; grid-template-columns:1fr 1fr; gap:var(--r2);}
@media (max-width:640px){ .kind-options{grid-template-columns:1fr;} }
.kind-opt{
  display:flex; flex-direction:column; gap:var(--r1); align-items:flex-start; text-align:left;
  padding:var(--r3) var(--r3);
  border:1px solid var(--grey-2);
  background:transparent;
  font-family:var(--face); font-size:var(--fs-body);
  cursor:pointer;
  transition:border-color .2s ease-out;
}
.kind-opt:hover{border-color:var(--accent); background:none;}
.kind-opt:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}
.kind-opt-title{font-family:var(--face); font-size:var(--fs-body); font-weight:500; letter-spacing:0; text-transform:lowercase; color:var(--black);}
.kind-opt-desc{font-family:var(--face); font-size:var(--fs-small); color:var(--grey-1); line-height:1.55;}
.kind-change{
  display:inline-flex; align-items:center; gap:6px;
  background:none; border:none; padding:0 0 3px; cursor:pointer;
  color:var(--grey-1);
  border-bottom:1px solid var(--hairline);
  margin-bottom:var(--r4);
  transition:color .2s ease-out, border-color .2s ease-out;
}
.kind-change:hover{color:var(--accent); border-color:var(--accent);}

/* ================= BUTTONS — black/paper at rest, viridian on hover only ================= */
.submit-row{display:flex; align-items:center; gap:var(--r2); flex-wrap:wrap; margin-top:var(--r1);}
.btn-primary{
  display:inline-flex; align-items:center; gap:14px;
  padding:16px 30px;
  border:none; border-radius:999px;
  background:var(--black);
  color:var(--paper);
  font-family:var(--face);
  font-weight:600;
  font-size:15px;
  letter-spacing:0;
  cursor:pointer;
  box-shadow:none;
  transition:background .2s ease-out;
}
.btn-primary .arr{color:var(--paper); font-size:16px; transition:transform .2s ease-out;}
.btn-primary:hover{background:var(--accent); transform:none; box-shadow:none;}
.btn-primary:hover .arr{transform:translateX(6px);}
.btn-primary:active{background:var(--black);}
.btn-primary:disabled{opacity:.5; cursor:default; transform:none; box-shadow:none;}
.submit-note{font-family:var(--face); font-size:var(--fs-label); letter-spacing:.08em; text-transform:uppercase; color:var(--grey-1);}
/* the note only ever carries the "check the highlighted fields." error */
.submit-note[data-submit-note]{font-size:var(--fs-small); font-weight:500; letter-spacing:0; text-transform:none; color:var(--error);}

/* secondary button: paper fill, 1px black border, inverts on hover */
.btn-secondary{
  display:inline-flex; align-items:center; gap:14px;
  padding:15px 29px;
  border:1px solid var(--black); border-radius:999px;
  background:var(--paper);
  color:var(--black);
  font-family:var(--face);
  font-weight:600;
  font-size:15px;
  letter-spacing:0;
  cursor:pointer;
  transition:background .2s ease-out, color .2s ease-out, border-color .2s ease-out;
}
.btn-secondary:hover{background:var(--black); color:var(--paper); border-color:var(--black);}
.btn-secondary:focus-visible, .btn-primary:focus-visible{outline:2px solid var(--green-light); outline-offset:2px;}

.status-panel{
  display:none;
  padding:var(--r4) var(--r3);
  background:var(--paper);
  border-top:2px solid var(--black);
  box-shadow:inset 0 -1px 0 var(--hairline), inset -1px 0 0 var(--hairline), inset 1px 0 0 var(--hairline), inset 0 -1px 0 var(--hairline);
}
/* form result panels (/testimonial/, /start/ intake). The page scripts add
   .show; that rule was dropped with the per-page styles on 2026-09-21
   (e9ed75c), so neither "received" nor "not sent" ever appeared. */
.status-panel.show{display:block; margin-bottom:var(--r5); scroll-margin-top:calc(var(--nav-h) + var(--r3));}
@media (min-width:900px){ .status-panel.show{scroll-margin-top:calc(var(--nav-h) + 72px);} } /* clears /start/'s sticky step bar */
/* focused only so screen readers read it — not an interactive target */
.status-panel:focus, .status-panel[tabindex]:focus-visible{outline:none;}
.status-panel.success{border-top-color:var(--green-ink);}
.status-panel.error{border-top-color:var(--error);}
.status-panel .status-eyebrow{display:block; margin-bottom:var(--r2); color:var(--green-ink);}
.status-panel.error .status-eyebrow{color:var(--error);}
.status-panel h3{
  font-family:var(--face-display, var(--face)); font-size:var(--fs-h2); font-weight:var(--fw-h2);
  letter-spacing:var(--ls-h2); line-height:1.15; text-transform:lowercase; color:var(--black); margin:0;
}
.status-panel p{font-family:var(--face); font-size:var(--fs-body); color:var(--grey-1); line-height:1.55; max-width:56ch; margin-top:var(--r2);}
.status-panel p.status-detail{color:var(--black);}
.status-panel a{color:var(--black); text-decoration:underline; text-underline-offset:2px;}
.status-panel a:hover, .status-panel a:focus-visible{color:var(--accent);}
.status-panel .fallback{margin-top:var(--r3); font-family:var(--face); font-size:var(--fs-small);}

/* error ink: #b0392f is 5.6:1 on paper but only 3.3:1 on the dark room's
   black, so the dark room gets a lighter red (6.6:1). */
:root{--error:#b0392f;}
html[data-room="dark"]{--error:#E0776C;}

/* ================= PAGE HEADER — shared inner-page title band =================
   Used on every inner page (about, services, work, faq, start, pricing, prep,
   testimonial, links, 404, thanks — never home). Two parts:
   1. .ph-watermark — full-bleed "jl audio" ghost type behind the title. Plain
      text (not SVG) sized with clamp(min, vw, max); the max is measured so it
      never exceeds the header band's own max content width (1280px), so the
      word scales proportionally and is never stretched/squashed or clipped.
   2. .ph-crumbs — a single breadcrumb label at the top-left corner (architect
      title-block spirit): ancestors are links, the current page is plain
      text. No top-right label, no "↓" — removed 2026-09-21 to stop the
      corner-label duplication (e.g. "FILE PREP" / "FILE PREP — MIXING").
   ================================================================= */
.page-header{
  position:relative;
  overflow:hidden;
}
.page-header > *{position:relative; z-index:1;}

.ph-watermark{
  position:absolute;
  inset:0;
  z-index:0;
  display:flex;
  align-items:center;
  padding:0 var(--pad-x);
  pointer-events:none;
  user-select:none;
  overflow:hidden;
}
.ph-watermark span{
  display:block;
  font-family:var(--face);
  font-weight:700;
  font-size:clamp(140px, 20vw, 350px); /* max measured against the header band's
                       1280px max content width at real "jl audio" glyph metrics,
                       so it never overflows past 1440/1760; true proportional
                       scaling, no textLength distortion. */
  line-height:1;
  letter-spacing:-.02em;
  color:var(--black);
  opacity:.06;
  white-space:nowrap;
}

/* .nav is position:fixed (out of flow), so .page-header's own box starts at the
   very top of the page, not below the visual nav bar — top offsets here have to
   clear var(--nav-h) themselves or they render underneath the fixed nav. */
.ph-crumbs{
  position:absolute;
  top:calc(var(--nav-h) + var(--r3));
  left:var(--pad-x);
  right:var(--pad-x);
  z-index:2;
  display:flex;
  align-items:flex-start;
  pointer-events:none;
}
.ph-crumbs .lbl{margin:0; pointer-events:auto; min-width:0; overflow-wrap:break-word; max-width:100%;}
.ph-crumbs .lbl a{text-decoration:none; color:inherit;}
.ph-crumbs .lbl a:hover, .ph-crumbs .lbl a:focus-visible{color:var(--black);}
.dark .ph-crumbs .lbl a:hover, .dark .ph-crumbs .lbl a:focus-visible{color:var(--paper);}

@media (max-width:640px){
  .ph-crumbs{top:calc(var(--nav-h-mobile) + var(--r2)); left:var(--pad-x); right:var(--pad-x);}
  .ph-watermark span{font-size:clamp(70px, 24vw, 140px);}
}

/* prep-download — a titled PDF row inside the "file prep" .c-detail section (services
   pages, #prep). 2026-09-27: was the same small-caps label style as .c-detail-label
   itself, so "file prep" read as two orphan labels stacked between dividers with no
   visible content. Now matches the body-style rhythm of the "what to send" list right
   above it (fs-body, --grey-1, line-height 1.55, block/li layout via .c-detail-list) so
   the PDF's real title reads as content under a heading, not a second heading. The
   trailing arrow is the only label-style/green accent left, giving a clear download
   affordance without shouting the whole line. */
.prep-download{
  display:block;
  font-family:var(--face); font-size:var(--fs-body); font-weight:400; color:var(--grey-1);
  line-height:1.55;
}
.prep-download:hover, .prep-download:focus-visible{ text-decoration:underline; }
.prep-download .prep-download__arrow{ color:var(--green-ink); margin-left:var(--r1); }

/* faq-prep-links — compact stacked list of per-service PDF links under the FAQ's first answer.
   Padding matches .c-acc-a p's `0 var(--page-x) var(--row-pad)` since this list is a sibling of
   that p, not a descendant, so it doesn't inherit the answer's own horizontal padding.
   2026-09-27: link text was the short small-caps label style ("mixing (PDF)") — same
   all-caps-orphan-label problem as .prep-download on the service pages. Now uses each
   PDF's real title at body style (matches .prep-download), with the same trailing-arrow
   accent as the only green/label-style touch. max-width widened from 320 to fit the
   longer real titles without cramping. */
.faq-prep-links{ list-style:none; margin:0; padding:0 var(--page-x) var(--row-pad); max-width:calc(480px + 2 * var(--page-x)); }
.faq-prep-links li{ border-top:1px solid var(--hairline); padding:var(--r2) 0; }
.faq-prep-links a{
  display:block;
  font-family:var(--face); font-size:var(--fs-body); font-weight:400; color:var(--grey-1); line-height:1.55;
  text-decoration:none;
}
.faq-prep-links a:hover, .faq-prep-links a:focus-visible{ text-decoration:underline; }
.faq-prep-links a .prep-download__arrow{ color:var(--green-ink); margin-left:var(--r1); }

/* ================= FIRST-VISIT ROOM NOTE (room.js, 2026-09-28) =================
   Passive margin note, bottom-right: tells a first-time visitor the room
   switch exists. Never takes a click (pointer-events:none), never an
   overlay, no close button — fades in, fades out on its own. Fixed, so no
   layout shift. Solid paper backing + hairline so it stays legible over the
   home three.js stage; accent rule on the left is the brand non-text accent
   (green-deep light / viridian dark). Sits under the mobile nav panel (190). */
.room-hint{
  position:fixed; z-index:180;
  left:0; right:0;
  bottom:0;
  display:flex; align-items:center; justify-content:center; gap:var(--r1);
  padding:8px var(--page-x) calc(8px + env(safe-area-inset-bottom, 0px));
  background:var(--paper);
  border:0; border-top:1px solid var(--hairline);
  color:var(--black);
  font-family:var(--face); font-size:var(--fs-small); font-weight:500; line-height:1.3;
  letter-spacing:.005em;
  pointer-events:none;
  opacity:0; transform:translateY(6px);
  transition:opacity .5s ease-out, transform .5s cubic-bezier(.22,1,.36,1);
}
.room-hint.is-on{ opacity:1; transform:none; }
.room-hint__glyph{ flex:none; width:20px; height:20px; fill:none; stroke:var(--accent-line); stroke-width:1; }
.room-hint__glyph circle:first-child{ fill:var(--accent-line); stroke:none; }
.room-hint__glyph circle:last-child{ opacity:.45; }
@media (max-width:760px){
  .room-hint{ padding-left:16px; padding-right:16px; }
}
@media (prefers-reduced-motion: reduce){
  .room-hint{ transition:none; transform:none; }
}
@media print{ .room-hint{ display:none !important; } }

/* ================= ROBUST PASS — odd window sizes (2026-09-28) =================
   Jacob dragged a desktop window very thin and saw pieces collide / drop out.
   These rules only engage where something would otherwise overflow, so the
   normal 1440 / 390 renders are unchanged. Guarded by
   tools/responsive-check.mjs (npm run check:responsive).
   - long words / emails / URLs break instead of pushing the page sideways
     (break-word never changes layout unless a word genuinely can't fit)
   - media never wider than its column
   - the room note never sits over content on a very short or very thin
     window (it's a first-visit nicety, not content) */
body{overflow-wrap:break-word;}
a[href^="mailto:"]{overflow-wrap:anywhere;}
img, video{max-width:100%;}
@media (max-height:460px), (max-width:319px){
  .room-hint{display:none !important;}
}
