/* Daylight Ledger. Photographs are the architecture, type is the signage.
   Palette sampled from the photographs (travertine wall in 03-ceramics, plaster in 05, brass fixtures in 03):
   the manifest names travertine, oak, concrete and brass, which is the brand-names-the-materials override of
   design-taste-frontend 4.2. Brass is used only for button fills, graphic accents and links, never as a ground.
   Display and body: Assistant (one family, display at weight 300). Wordmark only: Frank Ruhl Libre.
   Dials: VARIANCE 7, MOTION 5, DENSITY 3.
   Signature: the level line. One brass (or cream, over a photograph) 1px line that recurs at rest with a different
   job in each section: the stage divider reveals, the story's level line orders the stages, the active trade's
   underline selects, the footer's line annotates who is responsible. Hooks: [data-signature]. */

:root {
  color-scheme: light dark;
  --canvas: #e4e0d6;
  --surface: #f1efea;
  --ink: #23211d;
  --ink-soft: #4f4b42;
  --line: rgba(35, 33, 29, 0.16);
  --line-strong: rgba(35, 33, 29, 0.62);
  --accent: #6f5a33;          /* brass as text and links */
  --accent-fill: #b59a63;     /* brass as a button fill */
  --accent-ink: #1b1915;      /* text on brass */
  --accent-graphic: #8a7343;  /* brass as a rule or mark */
  --dark: #1e1d1a;
  --dark-ink: #f4efe4;
  --dark-soft: #b9b2a3;
  --cream: #f4efe4;
  --slab: #d3cdc0;
  --ground-3: #dcd6c9;      /* contact form ground, a third step between canvas and slab */
  --foot: #0a0a09;
  --danger: #a3241c;
  --field-bg: transparent;
  --f-display: 'Assistant', system-ui, sans-serif;
  --f-mark: 'Frank Ruhl Libre', 'Assistant', serif;
  --bar-bg: #1e1d1a;
  --bar-line: rgba(244, 239, 228, 0.14);
  --bar-ink: #f4efe4;
  --radius: 2px;
  --head-h: 64px;
  /* Type scale: 8 steps on desktop. 14 notes and labels | 16 small text and nav | 18 body (17 phone) |
     20 wordmark descriptor | 24 h3 and photo titles | 28 opener title and wordmark | 56 h2 (40 phone) | 91 stage (34 phone). */
  --t-note: 0.875rem;
  --t-small: 1rem;
  --t-body: 1.0625rem;
  --t-h3: 1.5rem;
  --t-lead: 1.75rem;
  --t-stage: clamp(2.5rem, 0.8rem + 5.4vw, 6rem);
  --t-h2: clamp(2.5rem, 0.9rem + 3vw, 3.5rem);
  --pad: clamp(64px, 7.5vw, 112px);   /* section padding: generous at boundaries, tight inside */
}
@media (prefers-color-scheme: dark) {
  :root {
    --canvas: #151412;
    --surface: #201f1b;
    --ink: #e9e4d8;
    --ink-soft: #ada698;
    --line: rgba(233, 228, 216, 0.14);
    --line-strong: rgba(233, 228, 216, 0.45);
    --accent: #cdb27a;
    --accent-graphic: #b59a63;
    --dark: #0f0f0d;
    --slab: #25231f;
    --ground-3: #2a2823;
    --foot: #070706;
    --danger: #ff8f84;
  }
}
/* Tablet: the stage headline steps down so each half sets on one line (the sentence reads across the divider). */
@media (min-width: 720px) and (max-width: 899px) { :root { --t-stage: 2.875rem; --t-h2: 3.25rem; } }
@media (max-width: 719px) { :root { --head-h: 56px; --t-h3: 1.25rem; --t-lead: 1.5rem; --t-h2: 3.1875rem; } }

.site { font-weight: 400; font-size: 1.125rem; caret-color: var(--accent-graphic); accent-color: var(--accent-fill); }
.site h1, .site h2, .site h3 { font-family: var(--f-display); font-weight: 300; letter-spacing: -0.015em; line-height: 1.08; }
.site h2 { font-size: var(--t-h2); }
.site h2 strong, .site h1 strong { font-weight: 600; }
@media (prefers-color-scheme: dark) { .site h1, .site h2, .site h3 { font-weight: 350; } }
@media (max-width: 719px) { .site { font-size: 1.0625rem; } }
.s-keep { white-space: nowrap; }
.s-note { font-size: var(--t-note); color: var(--ink-soft); }

/* ---- Header: wordmark, three anchors, one CTA ---- */
.s-head {
  position: sticky; inset-block-start: 0; z-index: 50; height: var(--head-h); display: flex; align-items: center; gap: var(--s6);
  padding-inline: var(--gutter); background: var(--canvas); border-block-end: 1px solid var(--line);
}
.s-mark { display: inline-flex; align-items: center; gap: 14px; min-height: 44px; color: var(--ink); text-decoration: none; }
.s-mark__a { font: 700 28px/1 var(--f-mark); letter-spacing: 0.06em; }
.s-mark__a i { font-style: normal; color: var(--accent-graphic); }
.s-mark__rule { width: 1px; height: 22px; background: currentColor; opacity: 0.3; }
.s-mark__b { font: 300 20px/1 var(--f-body); letter-spacing: 0.04em; }
.s-nav { display: flex; gap: var(--s6); margin-inline-start: auto; }
.s-nav a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; font-size: var(--t-small); font-weight: 600; text-decoration: none; color: var(--ink); }
@media (hover: hover) and (pointer: fine) { .s-nav a:hover { color: var(--accent); } }
.s-head__cta { min-height: 44px; padding-inline: var(--s5); }
.s-head.is-contact .s-head__cta, .s-head.is-contact .s-head__tel { visibility: hidden; }
.s-head__tel { font-weight: 600; font-size: var(--t-small); color: var(--ink); text-decoration: none; letter-spacing: 0.02em; }
@media (max-width: 899px) { .s-head__tel { display: none; } .s-nav { gap: var(--s5); } }
@media (max-width: 719px) {
  .s-head { gap: var(--s3); }
  .s-head__cta { display: none; }
  .s-nav { gap: var(--s3); }
  .s-nav a { font-size: 0.9375rem; }
  .s-mark { gap: 10px; }
  .s-mark__a { font-size: 24px; }
  .s-mark__b { font-size: 16px; }
}

/* ---- Stage: a full-bleed photograph, pinned; scroll tips the divider ---- */
.s-stage { position: relative; --pin-h: calc(100svh - var(--head-h) - var(--bar-h)); height: calc(var(--pin-h) + 170svh); }
.s-stage.is-static { height: auto; }
.s-stage__pin { position: sticky; inset-block-start: var(--head-h); height: var(--pin-h); max-width: 1680px; margin-inline: auto; }
.s-stage.is-static .s-stage__pin { position: relative; inset-block-start: 0; }
.s-cmp { position: absolute; inset: 0; aspect-ratio: auto; border-radius: 0; background: #171512; --cmp-line: var(--cream); }
@media (prefers-reduced-motion: no-preference) {
  .s-cmp:not(.is-dragging):not(.is-keying) { transition: --p 110ms linear; }
}
.s-cmp .cmp__divider::before { width: 1px; inset-inline-start: -0.5px; box-shadow: none; }
.s-cmp .cmp__handle {
  width: 48px; height: 48px; inset-inline-start: -24px; margin-block-start: -24px; border: 0;
  background: var(--accent-fill); color: var(--accent-ink); box-shadow: 0 6px 18px rgba(20, 16, 10, 0.35);
  transition: opacity 200ms var(--e-out), transform 140ms var(--e-out);
}
.s-cmp .cmp__handle::before { right: 12px; }
.s-cmp .cmp__handle::after { left: 12px; }
.s-cmp.is-edge .cmp__handle:not(:focus-visible) { opacity: 0; pointer-events: none; }

/* Captions: borderless type over a scrim that is a SIBLING of the text, never a child of it, and every scrim sits
   below every caption (z-index 2 vs 3), so one side's scrim never veils the other side's words. Each side shows only
   while it holds enough of the frame. */
.s-capwrap { position: absolute; inset-block: 0; width: min(62%, 48rem); pointer-events: none; }
.s-capwrap--before { inset-inline-start: 0; --cx: 100%; }
.s-capwrap--after { inset-inline-end: 0; --cx: 0%; }
.s-scrim, .s-cap { transition: opacity 220ms var(--e-out); }
.s-stage:not(.show-b) .s-capwrap--before :is(.s-scrim, .s-cap), .s-stage:not(.show-a) .s-capwrap--after :is(.s-scrim, .s-cap) { opacity: 0; }
/* Each scrim fades out toward the divider, so its band never ends in a hard vertical edge mid-photograph. Physical
   sides on purpose: d-0003 fixes BEFORE on the right and AFTER on the left in every direction. */
.s-capwrap--before .s-scrim { -webkit-mask-image: linear-gradient(to left, #000 62%, transparent); mask-image: linear-gradient(to left, #000 62%, transparent); }
.s-capwrap--after .s-scrim { -webkit-mask-image: linear-gradient(to right, #000 62%, transparent); mask-image: linear-gradient(to right, #000 62%, transparent); }
.s-scrim { position: absolute; inset: 0; z-index: 2; background: linear-gradient(to top, rgba(22, 20, 17, 0.72), transparent 34%), radial-gradient(ellipse 90% 60% at var(--cx) 100%, rgba(22, 20, 17, 0.9), rgba(22, 20, 17, 0.5) 55%, transparent 100%); }
.s-cap { position: absolute; z-index: 3; inset-block-end: max(clamp(28px, 4.5vw, 64px), 72px); display: flex; flex-direction: column; align-items: flex-start; max-width: calc(50vw - 2 * var(--gutter) - 24px); color: var(--cream); }
.s-capwrap--before .s-cap { inset-inline-start: var(--gutter); }
.s-capwrap--after .s-cap { inset-inline-end: var(--gutter); }
.s-cap__h { margin: 0; font-size: var(--t-stage); font-weight: 400; line-height: 1.04; letter-spacing: -0.02em; text-wrap: balance; text-shadow: 0 1px 24px rgba(15, 12, 8, 0.35); }
/* Out of flow under the headline (like the link), so both headlines keep one baseline. */
.s-cap__note { position: absolute; inset-block-start: 100%; inset-inline-start: 0; white-space: nowrap; margin-block-start: var(--s2); min-height: 44px; display: inline-flex; align-items: flex-end; line-height: 1.3; padding-block-end: 6px; gap: var(--s2); font-size: 0.875rem; font-weight: 600; letter-spacing: 0.02em; color: var(--cream); text-shadow: 0 1px 10px rgba(10, 8, 5, 0.85); }
.s-cap__note::before { content: ''; width: 16px; height: 1px; background: currentColor; align-self: flex-end; margin-block-end: 0.62em; }
/* One disclosure at a time: the before caption carries it while it shows; the after caption takes over at the collapse. */
.s-capwrap--after .s-cap__note { display: none; }
.s-stage:not(.show-b) .s-capwrap--after .s-cap__note { display: inline-flex; }
.s-cap__link {
  position: absolute; inset-block-start: 100%; inset-inline-start: 0; display: inline-flex; align-items: flex-end; line-height: 1.3; padding-block-end: 6px; min-height: 44px; margin-block-start: var(--s2); white-space: nowrap; color: var(--cream); font-weight: 700; font-size: 1.25rem; text-shadow: 0 1px 12px rgba(10, 8, 5, 0.9); pointer-events: auto;
  text-underline-offset: 0.3em; text-decoration-thickness: 2px; text-decoration-color: var(--accent-fill); opacity: 0; visibility: hidden; transition: opacity 320ms var(--e-out), visibility 0s linear 320ms;
}
.is-won .s-cap__link, .is-static .s-cap__link { opacity: 1; visibility: visible; transition-delay: 0s; }
/* At the collapse the after caption shows the disclosure and, below it, the link. */
/* At the collapse the after caption carries both: the link at the inline-start end, the disclosure at the inline-end end of one row. */
.s-stage:not(.show-b) .s-capwrap--after .s-cap__note { inset-inline-start: auto; inset-inline-end: 0; }
/* The link sits under the after headline, so the after scrim is deepest there once the link shows. */
.s-stage.is-won .s-capwrap--after .s-scrim, .s-stage.is-static .s-capwrap--after .s-scrim { background: linear-gradient(to top, rgba(22, 20, 17, 0.8), transparent 30%), radial-gradient(ellipse 95% 70% at var(--cx) 100%, rgba(22, 20, 17, 0.94), rgba(22, 20, 17, 0.6) 55%, transparent 100%); }
@media (max-width: 719px) {
  .s-capwrap { width: 100%; inset-block-start: auto; height: 50%; }
  .s-scrim, .s-stage.is-won .s-capwrap--after .s-scrim, .s-stage.is-static .s-capwrap--after .s-scrim { background: linear-gradient(to top, rgba(22, 20, 17, 0.86), rgba(22, 20, 17, 0.42) 56%, transparent 100%); }
  .s-capwrap .s-scrim { -webkit-mask-image: none; mask-image: none; }
  /* Only one full-width scrim band at a time on phones: while BEFORE shows, its scrim carries both bottom captions so
     the two full-width gradients never compound over the lower half of the room. */
  .s-stage.show-b .s-capwrap--after .s-scrim { opacity: 0; }
  .s-cap, .s-capwrap--before .s-cap, .s-capwrap--after .s-cap { max-width: calc(50% - 32px); inset-block-end: 40px; }
  .s-capwrap--before .s-cap { inset-inline-start: 16px; inset-inline-end: auto; }
  .s-capwrap--after .s-cap { inset-inline-end: 16px; inset-inline-start: auto; }
  .s-stage.is-won .s-capwrap--after .s-cap { max-width: calc(100% - 32px); }
  /* One line per side: "מהבטון החשוף | עד הגימור האחרון" reads as one sentence across the divider, neither side wraps.
     The size follows the half width (the longer phrase is about 6.2 em wide). */
  .s-cap__h { font-size: min(1.75rem, calc((50vw - 32px) / 6.3)); line-height: 1.1; white-space: nowrap; font-weight: 500; }
  .s-stage.is-won .s-capwrap--after .s-cap__h { font-size: min(2.125rem, calc((100vw - 32px) / 6.3)); }
  .s-cap__note, .s-stage:not(.show-b) .s-capwrap--after .s-cap__note { font-size: 0.8125rem; margin-block-start: 0; min-height: 36px; inset-inline-start: 0; inset-inline-end: auto; }
  .s-cap__link { display: none; }
  /* Portrait crop at native scale: the seam lands on the bare concrete wall between the two windows (source x about 551
     of 1376), so each half shows a full slice of the room without enlargement softness. Both layers share the crop. */
  .s-cmp .cmp__img { object-position: 37% 50%; transform: none; }
}

/* ---- Story: the stage's room walked through in the order of work. Grid "Split with a live element": inline-start
   6 columns hold the heading and the six stages on their level line; inline-end 6 columns hold one sticky view that
   re-crops the registered hero pair to the detail of the stage being read (desktop). Under 900px every stage carries
   its own crop. The level line (brass, the laser line of the trade) marks the detail in every crop. ---- */
.s-story { padding: clamp(56px, 6vw, 88px) var(--gutter); background: var(--surface); }
.s-story__grid {
  display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); grid-template-areas: 'head view' 'list view';
  gap: var(--s6) clamp(32px, 4.5vw, 72px); max-width: 1360px; margin-inline: auto; align-items: start;
}
.s-story__head { grid-area: head; display: grid; gap: var(--s4); }
.s-story__lede { max-width: 60ch; color: var(--ink-soft); }
.s-story__list { grid-area: list; display: grid; gap: 0; padding-inline-start: var(--s6); border-inline-start: 1px solid var(--accent-graphic); }
.s-story__list li { position: relative; padding-block: var(--s4); }
/* A level mark on the line at each stage; the stage being read gets the long mark. */
.s-story__list li::before { content: ''; position: absolute; inset-inline-start: calc(-1 * var(--s6)); inset-block-start: calc(var(--s4) + 0.75rem); width: 14px; height: 1px; background: var(--accent-graphic); transition: width 240ms var(--e-out), height 240ms var(--e-out); }
.s-story__list li.is-active::before { width: 24px; height: 2px; }
.s-story__list h3 { font-size: var(--t-h3); font-weight: 500; letter-spacing: -0.01em; line-height: 1.2; }
.s-story__list p { margin-block-start: var(--s1); max-width: 62ch; font-size: var(--t-body); line-height: 1.6; color: var(--ink-soft); }
.s-story__list .s-story__detail { display: none; font-size: var(--t-note); color: var(--ink-soft); }
.s-story__list .s-story__detail span { color: var(--ink); font-weight: 600; }
.s-story__list .s-story__check { display: flex; align-items: baseline; gap: var(--s2); color: var(--ink); }
/* The check is confirmed by a level mark, not a bold label. */
.s-tick { flex: none; width: 12px; height: 2px; background: var(--accent-graphic); transform: translateY(-0.3em); }

/* Crop box: the photograph at source size, placed by one transform (page.js fit()); image-space, so physical left/top. */
.s-crop { position: relative; overflow: hidden; background: var(--slab); }
.s-crop__img { position: absolute; left: 0; top: 0; width: 1376px; max-width: none; height: 768px; transform-origin: 0 0; transform: translate(var(--tx, 0px), var(--ty, 0px)) scale(var(--k, 0.3)); }
/* The level line across the photograph at the marked detail, with a ring on the detail. Image-space coordinates,
   so physical left/top here (conventions: sanctioned for image space). The line stops at the outer rim of the ring
   so the construction detail inside the ring stays unobstructed. */
.s-crop__mark { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; transform: translateY(calc(var(--my, 0.5) * 100%)); }
.s-crop__mark::before {
  content: ''; position: absolute; left: 0; right: 0; top: -0.5px; height: 1px; background: #c9ad74; box-shadow: 0 0 4px rgba(20, 16, 10, 0.5);
  -webkit-mask-image: radial-gradient(circle at calc(var(--mx, 0.5) * 100%) 50%, transparent 10px, #000 11px);
  mask-image: radial-gradient(circle at calc(var(--mx, 0.5) * 100%) 50%, transparent 10px, #000 11px);
}
.s-crop__tick { position: absolute; left: 0; top: 0; width: 100%; height: 0; transform: translateX(calc(var(--mx, 0.5) * 100%)); }
.s-crop__tick::before { content: ''; position: absolute; left: -10px; top: -10px; width: 20px; height: 20px; border: 1.5px solid #c9ad74; border-radius: 50%; box-shadow: 0 0 0 1px rgba(20, 16, 10, 0.4), inset 0 0 0 1px rgba(20, 16, 10, 0.4); }

/* Desktop: one sticky view. */
.s-crop--inline { display: none; }
.s-story__view { grid-area: view; position: sticky; inset-block-start: calc(var(--head-h) + 24px); margin: 0; }
.s-crop--view { aspect-ratio: 4 / 3; }
/* Desktop: a reserve under the last stage, so every stage is read while the view is still pinned beside it. */
@media (min-width: 900px) { .s-story__list { padding-block-end: 24svh; } }
.s-crop--view .s-crop__img { opacity: 0; }
.s-crop--view .s-crop__img.is-on { opacity: 1; }
/* A stage change fades the view out, re-crops it, and fades it back: no pan, so the mark is never between details. */
.s-crop--view { transition: opacity 160ms var(--e-out); }
.s-crop--view.is-swapping { opacity: 0; }
.s-story__view figcaption { padding-block-start: var(--s3); font-size: var(--t-small); color: var(--ink-soft); }
.s-story__look { color: var(--ink); font-weight: 600; }
@media (prefers-reduced-motion: reduce) {
  .s-crop--view, .s-story__list li::before { transition: none; }
}
@media (max-width: 899px) {
  .s-story__grid { grid-template-columns: 1fr; grid-template-areas: 'head' 'list'; gap: var(--s5); }
  .s-story__view { display: none; }
  .s-crop--inline { display: block; }
  .s-story__list { padding-inline-start: var(--s5); }
  .s-story__list li::before { inset-inline-start: calc(-1 * var(--s5)); }
  .s-story__list .s-story__detail { display: block; }
}
/* Tablet: one ordered column on the line; each stage is text beside its crop. */
@media (min-width: 600px) and (max-width: 899px) {
  .s-story { padding-block: var(--s7); }
  .s-story__list li { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--s5); align-items: center; padding-block: var(--s3); }
  .s-story__list p { max-width: none; }
  .s-crop--inline { order: 2; aspect-ratio: 16 / 10; }
}
/* Phone: a compact band per stage, above its words. */
@media (max-width: 599px) {
  .s-story__list li { display: grid; gap: var(--s2); padding-block: var(--s3); }
  .s-crop--inline { aspect-ratio: 12 / 5; }
  .s-story__list li::before { inset-block-start: calc(var(--s3) + 8px); }
}

/* ---- Gallery: large photographs, captions below them (two levels: title, specification) ---- */
.s-gallery { padding-block: var(--pad); }
.s-gallery__head {
  padding-inline: var(--gutter); max-width: 1440px; margin-inline: auto;
  display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); align-items: end; gap: var(--s5) var(--s7);
}
.s-gallery__title { display: grid; gap: var(--s4); }
.s-lede { max-width: 46ch; color: var(--ink-soft); }
.s-tabs { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s1) var(--s5); }
.s-tab {
  min-width: 44px; min-height: 44px; padding: 0; text-align: center; border: 0; border-block-end: 2px solid transparent; background: transparent; cursor: pointer; font-size: var(--t-small); font-weight: 600; color: var(--ink-soft);
  transition: color 140ms var(--e-out), border-color 140ms var(--e-out);
}
.s-tab[aria-pressed='true'] { color: var(--ink); border-block-end-color: var(--accent-graphic); }
@media (hover: hover) and (pointer: fine) { .s-tab:hover { color: var(--ink); } }

.s-t { margin: 0; }
.s-t__img { position: relative; overflow: hidden; background: var(--slab); aspect-ratio: var(--ar, 3 / 2); transition: opacity 240ms var(--e-out), filter 240ms var(--e-out); }
.s-t__img img { width: 100%; height: 100%; object-fit: cover; object-position: var(--pos, 50% 50%); }
.s-t figcaption { display: grid; gap: var(--s1); padding-block-start: var(--s3); transition: opacity 240ms var(--e-out); }
.s-t__title { font-size: var(--t-h3); font-weight: 500; line-height: 1.2; letter-spacing: -0.01em; text-wrap: balance; }
.s-t__spec { max-inline-size: 52ch; font-size: var(--t-body); line-height: 1.5; color: var(--ink-soft); text-wrap: balance; }

@media (prefers-reduced-motion: no-preference) {
  .s-t[data-reveal] .s-t__img img { transform: scale(1.06); transition: transform 900ms var(--e-out); }
  .s-t[data-reveal].in .s-t__img img { transform: none; }
}

.s-open { margin-block-start: var(--s6); }
.s-open .s-t__img { --ar: auto; height: clamp(360px, 43vw, 620px); }
.s-open figcaption { padding-inline: var(--gutter); max-width: 1440px; margin-inline: auto; padding-block-start: var(--s4); }
.s-open .s-t__title { font-size: var(--t-lead); font-weight: 300; }

.s-mosaic { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--s7) 24px; max-width: 1440px; margin: var(--s7) auto 0; padding-inline: var(--gutter); }
.s-t--plumb { grid-column: span 5; --ar: 533 / 600; --pos: 23% 50%; }
.s-t--cer { grid-column: span 7; --ar: 755 / 600; --pos: 17% 50%; }
.s-t--dry { grid-column: span 7; --ar: 755 / 424; --pos: 50% 50%; }
.s-t--paint { grid-column: span 5; --ar: 533 / 424; --pos: 90% 60%; }
.s-open .s-t__img { --pos: 50% 22%; }
/* Filtered (desktop): only the chosen trade remains; any match becomes a full-width feature right under the tabs with
   a two-column caption ledger below it (title on inline-start, specification on inline-end), so both flanks are held. */
.s-gallery.is-filtered .s-mosaic { margin-block-start: var(--s6); }
.s-gallery.is-filtered .s-mosaic:not(:has(.s-t:not([hidden]))) { display: none; }
@media (min-width: 900px) {
  .s-gallery.is-filtered .s-mosaic .s-t,
  .s-gallery.is-filtered .s-open { grid-column: 1 / -1; --ar: 2 / 1; }
  .s-gallery.is-filtered .s-open { max-width: 1440px; margin: var(--s6) auto 0; padding-inline: var(--gutter); }
  .s-gallery.is-filtered .s-open .s-t__img { height: auto; }
  .s-gallery.is-filtered .s-mosaic .s-t figcaption,
  .s-gallery.is-filtered .s-open figcaption {
    display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s3) var(--s7); align-items: baseline;
    padding: var(--s4) 0 0; margin: 0; max-width: none;
  }
  .s-gallery.is-filtered .s-t__spec { max-inline-size: none; }
}
@media (max-width: 899px) {
  .s-gallery__head { grid-template-columns: 1fr; }
  .s-tabs { justify-content: flex-start; }
  .s-mosaic { display: grid; grid-template-columns: 1fr; gap: var(--s7); margin-block-start: var(--s6); }
  .s-t--plumb, .s-t--cer, .s-t--dry, .s-t--paint { grid-column: 1 / -1; }
  .s-mosaic .s-t__img { margin-inline: calc(var(--gutter) * -1); }
  .s-t--plumb { --ar: 1 / 1; --pos: 30% 50%; }
  .s-t--cer { --ar: 4 / 3; --pos: 17% 50%; }
  .s-t--dry { --ar: 4 / 3; --pos: 31% 40%; }
  .s-t--paint { --ar: 4 / 5; --pos: 70% 60%; }
  .s-open .s-t__img { --ar: 4 / 5; height: auto; --pos: 60% 40%; }
  .s-open { margin-block-start: var(--s5); }
}
/* Tablet pacing: two detail shots side by side, then two wide bands, so each caption arrives in the same view as
   its photograph and the reading task changes between overview and detail. */
@media (min-width: 600px) and (max-width: 899px) {
  .s-mosaic { grid-template-columns: 1fr 1fr; column-gap: var(--s4); }
  .s-t--plumb, .s-t--cer { grid-column: span 1; }
  .s-mosaic .s-t--plumb .s-t__img, .s-mosaic .s-t--cer .s-t__img { margin-inline: 0; }
  .s-t--plumb { --ar: 4 / 5; --pos: 25% 50%; }
  .s-t--cer { --ar: 4 / 5; --pos: 12% 50%; }
  .s-t--dry { --ar: 16 / 9; --pos: 40% 45%; }
  .s-t--paint { --ar: 21 / 9; --pos: 70% 55%; }
  .s-open .s-t__img { --ar: 3 / 2; --pos: 55% 45%; }
  /* Filtered: the match takes the whole row. */
  .s-gallery.is-filtered .s-mosaic .s-t { grid-column: 1 / -1; --ar: 16 / 10; }
}
/* Phones: every trade stays visible (two wrapped rows, no hidden chips), so the active one is always on screen.
   Pacing: one column, each photograph directly above its own caption, ratios varied (3:2, 16:10, 16:9, 4:3) and
   kept within three viewports so the section never drags. */
@media (max-width: 599px) {
  /* The first photograph arrives sooner: tighter head, same 17px body and 51px heading. */
  .s-gallery { padding-block: var(--s7); }
  .s-gallery__head { gap: var(--s3); }
  .s-gallery__title { gap: var(--s2); }
  .s-open { margin-block-start: var(--s4); }
  .s-open .s-t__img { --ar: 3 / 2; }
  .s-tabs { gap: 0 var(--s4); }
  .s-mosaic { gap: var(--s5); margin-block-start: var(--s5); }
  .s-t--plumb { --ar: 3 / 2; }
  .s-t--cer { --ar: 16 / 10; }
  .s-t--dry { --ar: 16 / 9; --pos: 31% 40%; }
  .s-t--paint { --ar: 4 / 3; --pos: 70% 60%; }
}

/* ---- Contact: two grounds (ruled: the contact contract; scroll-craft "Colour" allows hard cuts). The dark ground
   carries the decision: headline and why, then who is responsible, the one brass action and the call link. The light
   ground says what the form is for, then the form. ---- */
.s-contact__grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.s-contact__dark { display: grid; align-content: center; gap: var(--s6); padding: var(--pad) var(--gutter); background: var(--dark); color: var(--dark-ink); --accent: #cdb27a; }
.s-contact__intro, .s-contact__act { display: grid; gap: var(--s4); justify-items: start; align-content: start; }
.s-contact__dark h2 { font-size: var(--t-h2); text-wrap: balance; }
.s-contact__dark p { max-width: 34ch; color: var(--dark-soft); }
.s-contact__dark .btn { min-height: 56px; padding-inline: var(--s6); }
.s-owner { display: grid; gap: var(--s1); padding-inline-start: var(--s4); border-inline-start: 1px solid #b59a63; }
.s-contact__dark .s-owner p { max-width: none; }
.s-owner__who { color: var(--dark-ink) !important; font-weight: 600; }
.s-owner__who span { font-weight: 400; color: var(--dark-soft); }
.s-owner__creds { font-size: var(--t-small); }
.s-contact__phone { display: inline-flex; align-items: baseline; flex-wrap: wrap; column-gap: 0.6em; min-height: 44px; padding-block: var(--s2); font-size: var(--t-h3); font-weight: 600; color: var(--dark-ink); text-decoration: none; }
.s-contact__phone span { font-weight: 400; color: var(--dark-soft); }
.s-contact__phone bdi { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.3em; text-decoration-color: var(--accent-fill); }
.s-contact__light { display: grid; align-content: center; gap: var(--s5); padding: var(--pad) var(--gutter); background: var(--ground-3); color: var(--ink); }
.lead__intro { max-width: 44rem; font-size: var(--t-h3); font-weight: 300; line-height: 1.3; color: var(--ink); text-wrap: balance; }
.s-contact__light .lead { max-width: 44rem; gap: var(--s5) var(--s6); }
.s-contact .field label { font-size: var(--t-note); font-weight: 600; color: var(--ink-soft); }
.s-contact .field input, .s-contact .field select, .s-contact .field textarea {
  min-height: 56px; padding-inline: 0; border: 0; border-block-end: 1px solid var(--line-strong); border-radius: 0; background: transparent; font-size: 1.125rem;
}
.s-contact .field textarea { resize: none; min-height: 88px; padding-block-start: var(--s3); }
.s-contact .field select {
  appearance: none; padding-inline-end: 0; padding-inline-start: 24px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: 6px 52%, 12px 52%; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat;
}
.s-contact .field input:focus-visible, .s-contact .field select:focus-visible, .s-contact .field textarea:focus-visible { outline: 0; border-block-end-color: var(--accent-graphic); box-shadow: 0 1px 0 var(--accent-graphic); }
.s-contact .field [aria-invalid='true'] { border-block-end: 2px solid var(--danger); box-shadow: none; }
/* Invalid and focused: the error colour wins, with a matching focus line (danger on its ground passes 3:1 in both schemes). */
.s-contact .field input[aria-invalid='true']:focus-visible, .s-contact .field select[aria-invalid='true']:focus-visible, .s-contact .field textarea[aria-invalid='true']:focus-visible,
.s-contact .field input[aria-invalid='true']:focus, .s-contact .field select[aria-invalid='true']:focus, .s-contact .field textarea[aria-invalid='true']:focus { border-block-end-color: var(--danger); box-shadow: 0 2px 0 var(--danger); outline: 0; }
.field__error { margin: 0; font-size: var(--t-small); font-weight: 600; color: var(--danger); }
.s-contact .lead .btn { min-height: 56px; padding-inline: var(--s7); background: transparent; color: var(--ink); border: 1px solid var(--line-strong); }
@media (hover: hover) and (pointer: fine) { .s-contact .lead .btn:hover { background: var(--ink); border-color: var(--ink); color: var(--surface); } }
/* Outcome of a submit: a block under the button, marked on the level line (brass) or in the error colour. */
.lead__actions { display: grid; justify-items: start; gap: var(--s4); }
.lead__status { width: 100%; min-height: 0; font-size: var(--t-body); color: var(--ink); }
.lead__status:empty { display: none; }
.lead__status[data-state] { display: grid; gap: var(--s2); padding-block: var(--s2); padding-inline-start: var(--s4); border-inline-start: 2px solid var(--accent-graphic); }
.lead__status[data-state='error'] { border-inline-start-color: var(--danger); }
.lead__status[data-state='error'] p { color: var(--danger); font-weight: 600; }
.lead__status[data-state='ok'] p { font-weight: 400; }
.lead__status a { justify-self: start; display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; color: var(--accent); }
@media (max-width: 899px) {
  .s-contact__grid { grid-template-columns: 1fr; }
  .s-contact__dark, .s-contact__light { padding-block: var(--s8); }
}
/* Tablet: the dark panel is two columns, so both flanks carry content: the why on the inline-start side, the
   responsible contractor and the actions on the inline-end side. */
@media (min-width: 600px) and (max-width: 899px) {
  .s-contact__dark { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s7); align-items: center; }
  .s-contact__act { justify-items: stretch; }
  .s-contact__dark .btn { width: 100%; }
}
@media (max-width: 599px) {
  .s-contact__dark, .s-contact__light { padding-block: var(--s7); }
  .s-contact__dark { gap: var(--s5); }
  .s-contact__intro, .s-contact__act { justify-items: stretch; }
  .s-contact__dark p { max-width: none; }
  .s-contact__dark .btn { width: 100%; }
  .s-contact__light .lead { gap: var(--s4); }
  .lead__intro { font-size: 1.25rem; }
}

/* ---- Footer: who is responsible for the work. Grid "Index": identity 4 | facts on the level line 5 | back link
   and disclosure 3. Optional owner facts (site.config.js) appear as extra rows only when set. ---- */
.s-foot {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 6fr) minmax(0, 2fr); gap: var(--s5) var(--s7); align-items: start;
  padding: clamp(36px, 3.4vw, 48px) var(--gutter); background: var(--foot); color: var(--dark-soft); font-size: var(--t-small);
}
.s-foot__id { display: grid; gap: var(--s2); justify-items: start; }
.s-foot .s-mark { color: var(--cream); }
.s-foot .s-mark__a i { color: #cdb27a; }
.s-foot h2 { font-size: var(--t-h3); font-weight: 500; letter-spacing: -0.01em; color: var(--dark-ink); }
.s-foot__id p { max-width: 34ch; }
.s-facts { display: grid; gap: var(--s2); margin: 0; padding-inline-start: var(--s5); border-inline-start: 1px solid #b59a63; }
.s-facts__row { display: grid; grid-template-columns: minmax(7.5rem, auto) minmax(0, 1fr); gap: var(--s4); align-items: baseline; }
.s-facts dt { font-size: var(--t-note); font-weight: 600; color: var(--dark-soft); }
.s-facts dd { margin: 0; color: var(--dark-ink); text-wrap: balance; }
.s-foot__end { display: grid; gap: var(--s2); justify-items: start; }
.s-foot a { color: var(--dark-ink); display: inline-flex; align-items: center; min-height: 44px; }
.s-foot__note { font-size: var(--t-note); }
@media (max-width: 1099px) { .s-foot { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); } .s-foot__end { grid-column: 1 / -1; grid-auto-flow: column; justify-content: space-between; align-items: center; } }
/* No bar reserve under the footer: the bar steps aside while the footer is on screen (main.js watchBar). */
@media (max-width: 599px) { .s-foot { grid-template-columns: 1fr; } .s-foot__end { grid-auto-flow: row; } .s-facts__row { grid-template-columns: max-content minmax(0, 1fr); gap: var(--s3); } }
