/* ───────────────────────────────────────────────────────────────
   SERVICE SECTIONS — v2

   One renderer for the nine section types the service content uses:
   features, list, process, offerings, comparison, claims, accordion,
   gallery, carousel.

   Every component is CLASS-scoped and initialised per instance. The
   existing service/home scripts bind by id (#procList, .where__list),
   which silently breaks the second instance on a page — several of
   these services have two "features" sections and the content may add
   more. Nothing here depends on there being only one.

   Spacing follows the homepage: clamp(60px,9vw,100px) section padding
   and --rhythm between a heading block and its content.
   ─────────────────────────────────────────────────────────────── */

:root { --accent-ink: #9a5200; }

.sx { padding: clamp(60px, 9vw, 100px) var(--pad); }
.sx--tint  { background: var(--g-svcs, #faf5f0); }
.sx--plain { background: var(--g-proc, #fff); }
.sx--warm  { background: var(--g-price, #fdfaf7); }
/* Headings and ledes now use the homepage's own .sec-title / .sec-sub, so the
   type matches everywhere. Only the spacing inside these containers is set
   here — never the size, colour or tracking. */
.sx__top .sec-title { margin: .36em 0 .4em; }
.sx__top .sec-sub { margin-block-start: 18px; }
.sx__top .sec-sub p { margin: 0 0 .85em; }
.sx__top .sec-sub p:last-child { margin-bottom: 0; }
.sx__outro { margin-block-start: clamp(22px, 2.4vw, 32px); font-size: clamp(15.5px, 1.35vw, 18px); line-height: 1.6; color: var(--heading, #3a2e26); max-inline-size: none; }
.sx__body { margin-block-start: var(--rhythm, 40px); }

/* ── features / claims: cards that stagger in and lift ──── */
.sfeat { display: grid; gap: clamp(16px, 2vw, 26px); grid-template-columns: 1fr; }
/* `1fr` tracks keep min-width:auto, so a card cannot shrink below its own
   content and the row runs past the page edge wherever the grid sits in a
   narrow container — .sfeat--3 inside .sx__col did exactly that at 1280,
   hanging 44px off the right. minmax(0,1fr) lets the tracks shrink; a
   .sfeat--3 in a split column also drops to two across, because three
   190px cards are not a layout. */
@media (min-width: 720px) { .sfeat { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .sfeat--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .sx__col .sfeat--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sfeat__c {
  padding: clamp(22px, 2.4vw, 30px); background: #fff; border: 1px solid #e7ded4; border-radius: 16px;
  transition: transform .45s cubic-bezier(.2,.7,.2,1), box-shadow .45s ease, border-color .45s ease;
}
.sx--plain .sfeat__c { background: var(--g-svcs, #faf5f0); }
.sfeat__c:hover { transform: translateY(-7px); box-shadow: 0 18px 38px rgba(33,26,22,.12); border-color: #ddd0c0; }
.sfeat__n { font-size: 12px; letter-spacing: .14em; font-weight: 700; color: var(--accent-ink); }
.sfeat__c h3 { font-size: clamp(17px, 1.7vw, 21px); margin: 11px 0 9px; letter-spacing: -.012em; color: var(--heading, #3a2e26); }
.sfeat__c p { margin: 0; font-size: 14.5px; line-height: 1.64; color: #6b6259; }
.sfeat__c a { color: var(--heading, #3a2e26); text-underline-offset: 3px; }
/* stagger only once JS marks the section */
.sx.anim .sfeat__c { opacity: 0; transform: translateY(20px); transition: opacity .7s cubic-bezier(.2,.7,.2,1), transform .7s cubic-bezier(.2,.7,.2,1), box-shadow .45s ease; }
.sx.anim.on .sfeat__c { opacity: 1; transform: none; }
.sx.anim.on .sfeat__c:nth-child(2) { transition-delay: .1s }
.sx.anim.on .sfeat__c:nth-child(3) { transition-delay: .2s }
.sx.anim.on .sfeat__c:nth-child(4) { transition-delay: .3s }
.sx.anim.on .sfeat__c:nth-child(5) { transition-delay: .4s }
.sx.anim.on .sfeat__c:nth-child(6) { transition-delay: .5s }
.sx.anim.on .sfeat__c:hover { transform: translateY(-7px); }

/* ── list: numbered rows, a rule draws across each ──────── */
.slist { list-style: none; margin: 0; padding: 0; border-block-start: 1px solid #e7ded4; }
.slist li { position: relative; display: grid; grid-template-columns: 54px 1fr; gap: 10px; align-items: baseline;
  padding: clamp(16px,1.8vw,22px) 0; border-block-end: 1px solid #e7ded4; }
.slist li::after { content: ''; position: absolute; inset-inline: 0; inset-block-end: -1px; block-size: 1px;
  background: var(--accent, #f78c1e); transform: scaleX(0); transform-origin: left;
  transition: transform .8s cubic-bezier(.2,.7,.2,1); }
.sx.anim.on .slist li::after { transform: scaleX(1); }
.sx.anim.on .slist li:nth-child(2)::after { transition-delay: .09s }
.sx.anim.on .slist li:nth-child(3)::after { transition-delay: .18s }
.sx.anim.on .slist li:nth-child(4)::after { transition-delay: .27s }
.sx.anim.on .slist li:nth-child(5)::after { transition-delay: .36s }
.sx.anim.on .slist li:nth-child(6)::after { transition-delay: .45s }
.slist b { font-size: 12.5px; letter-spacing: .12em; color: var(--accent-ink); font-weight: 700; }
.slist span { font-size: clamp(15.5px, 1.5vw, 18px); line-height: 1.5; color: var(--heading, #3a2e26); }

/* ── process: a rail that fills, steps that light ───────── */
.sproc { position: relative; list-style: none; margin: 0; padding: 0; }
.sproc::before, .sproc::after {
  content: ''; position: absolute; inset-inline-start: 7px; inset-block-start: 10px;
  inline-size: 2px; block-size: calc(100% - 20px); background: #e0d3c4;
}
.sproc::after { background: var(--accent, #f78c1e); transform-origin: top; transform: scaleY(var(--fill, 0)); transition: transform .25s linear; }
.sproc li { position: relative; padding: 0 0 clamp(22px, 2.6vw, 34px) 38px; }
.sproc li:last-child { padding-block-end: 0; }
.sproc li::before {
  content: ''; position: absolute; inset-inline-start: 0; inset-block-start: 5px; z-index: 1;
  inline-size: 16px; block-size: 16px; border-radius: 50%; background: #fff; border: 2px solid #cdbba6;
  transition: background .4s ease, border-color .4s ease, transform .4s cubic-bezier(.2,.7,.2,1);
}
.sproc li.is-lit::before { background: var(--accent, #f78c1e); border-color: var(--accent, #f78c1e); transform: scale(1.22); }
.sx.anim .sproc li { opacity: .45; transition: opacity .5s ease; }
.sx.anim .sproc li.is-lit { opacity: 1; }
.sproc__n { display: block; font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: #6b6259; font-weight: 700; }
.sproc__t { display: block; font-size: clamp(17px,1.7vw,22px); font-weight: 600; margin-block: 5px 6px; letter-spacing: -.012em; color: var(--heading,#3a2e26); }
.sproc__b { margin: 0; font-size: 15px; line-height: 1.62; color: #6b6259; max-inline-size: none; }

/* ── offerings: a selector and a panel ──────────────────── */
.soff { display: grid; gap: clamp(18px,2.4vw,34px); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .soff { grid-template-columns: 300px 1fr; } }
.soff__list { display: grid; gap: 8px; }
.soff__list button {
  appearance: none; border: 1px solid #e7ded4; background: #fff; cursor: pointer; font: inherit;
  text-align: start; padding: 15px 17px; border-radius: 12px; color: #6b6259; font-size: 15px; font-weight: 600;
  transition: background .35s ease, color .35s ease, border-color .35s ease, transform .35s ease;
}
.soff__list button:hover { transform: translateX(3px); border-color: #ddd0c0; }
.soff__list button[aria-selected="true"] { background: var(--dark, #211a16); color: #fff; border-color: var(--dark, #211a16); }
.soff__list button:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
.soff__panel { padding: clamp(22px,2.6vw,34px); background: #fff; border: 1px solid #e7ded4; border-radius: 16px; min-block-size: 190px; }
.sx--plain .soff__panel { background: var(--g-svcs,#faf5f0); }
.soff__panel h3 { margin: 0 0 10px; font-size: clamp(19px,1.9vw,24px); letter-spacing: -.015em; color: var(--heading,#3a2e26); }
.soff__panel p { margin: 0; font-size: 15.5px; line-height: 1.65; color: #6b6259; }
.soff__panel[data-anim] { animation: soffIn .45s cubic-bezier(.2,.7,.2,1); }
@keyframes soffIn { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
.soff__price { display: inline-block; margin-block-start: 14px; font-size: 13px; font-weight: 700; letter-spacing: .04em; color: var(--accent-ink); }

/* ── comparison: hover a column, it comes forward ───────── */
.scomp { inline-size: 100%; border-collapse: collapse; font-size: 15px; }
.scomp caption { text-align: start; font-size: 13px; color: #6b6259; padding-block-end: 12px; }
.scomp th, .scomp td { padding: 15px 16px; text-align: start; vertical-align: top; border-block-end: 1px solid #e7ded4; transition: background .3s ease; }
.scomp thead th { font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: #6b6259; font-weight: 700; border-block-end: 2px solid #ddd0c0; }
.scomp tbody th { font-weight: 600; color: var(--heading, #3a2e26); }
.scomp td { color: #6b6259; }
.scomp .is-us { background: #fff; color: var(--heading,#3a2e26); font-weight: 600; }
.scomp thead .is-us { color: var(--accent-ink); }
.scomp col.is-hot + col {} /* no-op, kept for clarity */
.scomp .col-hot { background: var(--g-dc, #faf5f0); }
@media (max-width: 720px) {
  .scomp, .scomp tbody, .scomp tr, .scomp td, .scomp th { display: block; }
  .scomp thead { display: none; }
  .scomp tr { border-block-end: 1px solid #e7ded4; padding-block: 10px; }
  .scomp td, .scomp th { border: 0; padding: 6px 0; }
  .scomp td::before { content: attr(data-l) ': '; font-weight: 700; color: #6b6259; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; }
}

/* ── accordion ──────────────────────────────────────────── */
.sacc { border-block-start: 1px solid #e7ded4; }
.sacc__i { border-block-end: 1px solid #e7ded4; }
.sacc__q {
  appearance: none; background: none; border: 0; cursor: pointer; font: inherit; inline-size: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: clamp(16px,1.8vw,22px) 0; text-align: start;
  font-size: clamp(16px,1.6vw,19px); font-weight: 600; color: var(--heading,#3a2e26); letter-spacing: -.01em;
}
.sacc__q:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
.sacc__q svg { flex: none; transition: transform .4s cubic-bezier(.2,.7,.2,1); color: var(--accent-ink); }
.sacc__i.is-open .sacc__q svg { transform: rotate(45deg); }
.sacc__a { overflow: hidden; max-block-size: 0; transition: max-block-size .5s cubic-bezier(.2,.7,.2,1); }
.sacc__a > div { padding-block-end: clamp(16px,1.8vw,22px); font-size: 15.5px; line-height: 1.66; color: #6b6259; max-inline-size: none; }
/* no-JS: everything open and readable */
.sacc:not([data-js]) .sacc__a { max-block-size: none; }

/* ── gallery / carousel ─────────────────────────────────── */
.sgal { position: relative; }
.sgal__win { overflow: hidden; border-radius: 16px; }
.sgal__track { display: flex; gap: 14px; transition: transform .65s cubic-bezier(.2,.7,.2,1); }
.sgal__s { flex: 0 0 100%; margin: 0; }
@media (min-width: 760px) { .sgal__s { flex-basis: calc((100% - 14px) / 2); } }
@media (min-width: 1100px) { .sgal__s { flex-basis: calc((100% - 28px) / 3); } }
.sgal__s img { inline-size: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; border-radius: 14px; background: #eee5da; }
.sgal__s figcaption { margin-block-start: 9px; font-size: 13px; color: #6b6259; }
.sgal__nav { display: flex; gap: 10px; justify-content: flex-end; margin-block-start: 16px; }
.sgal__nav button {
  appearance: none; cursor: pointer; inline-size: 44px; block-size: 44px; border-radius: 50%;
  border: 1px solid #ddd0c0; background: #fff; color: var(--heading,#3a2e26);
  display: grid; place-items: center; transition: background .3s ease, transform .3s ease, opacity .3s ease;
}
.sgal__nav button:hover { background: var(--g-dc,#faf5f0); transform: translateY(-2px); }
.sgal__nav button:disabled { opacity: .34; cursor: default; transform: none; }
.sgal__nav button:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }

/* ── links row ──────────────────────────────────────────── */
.slinks { display: flex; flex-wrap: wrap; gap: 10px; }
.slinks a {
  display: inline-block; padding: 11px 17px; border-radius: 999px; border: 1px solid #e7ded4;
  background: #fff; color: var(--heading,#3a2e26); font-size: 14.5px; text-decoration: none;
  transition: background .3s ease, transform .3s ease, border-color .3s ease;
}
.slinks a:hover { background: var(--dark,#211a16); color: #fff; border-color: var(--dark,#211a16); transform: translateY(-2px); }

@media (prefers-reduced-motion: reduce) {
  .sx.anim .sfeat__c, .sx.anim .sproc li { opacity: 1; transform: none; }
  .sx.anim.on .slist li::after { transform: scaleX(1); transition: none; }
  .sfeat__c, .soff__list button, .sgal__track, .sacc__a, .sacc__q svg, .slinks a { transition: none !important; }
  .soff__panel[data-anim] { animation: none; }
}

/* ── a section with a media column ──────────────────────── */
.sx__split { display: grid; gap: clamp(26px, 3.4vw, 56px); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 960px) {
  .sx__split { grid-template-columns: minmax(0,1fr) minmax(0,.86fr); }
  /* `side` names where the PICTURE goes; the column order follows it. */
  .sx__split[data-side="left"] > .sx__col   { order: 2; }
  .sx__split[data-side="left"] > .sx__media { order: 1; }
}
.sx__media { margin: 0; display: grid; gap: 12px; }
.sx__shot {
  inline-size: 100%; block-size: auto; display: block; border-radius: 16px; background: #eee5da;
  transition: transform .55s cubic-bezier(.2,.7,.2,1), box-shadow .55s ease;
}
.sx__media:hover .sx__shot { transform: translateY(-5px); box-shadow: 0 22px 46px rgba(33,26,22,.16); }
.sx__shot.is-contain { object-fit: contain; background: transparent; }
.sx__media--drawing .sx__shot, .sx__media--render .sx__shot { background: #fff; }
.sx__media figcaption { font-size: 13px; line-height: 1.55; color: #6b6259; }
@media (prefers-reduced-motion: reduce) { .sx__shot, .sx__media:hover .sx__shot { transition: none; transform: none; } }

/* Intro-only sections use the homepage's .split; the prose sits in the right
   half rather than under the heading, so the row is not half empty. */
.sx .split { align-items: flex-start; }
.sx__aside { flex: 1 1 46%; min-inline-size: 0; }
.sx__aside p + p { margin-block-start: .85em; }
@media (max-width: 860px) { .sx__aside { flex-basis: 100%; } }

/* The split header: title left, supporting line right, body full width below —
   the homepage's own arrangement (.work, .price, .faq, .guides). */
.sx .split, .sig .split, .pg .split, .hand .split, .pil .split, .dcx .split, .abr .split { align-items: flex-start; }
/* A lede is CONTENT: it belongs under the title, full width between the page
   padding, not in a 44% column beside it. The old rule parked the heading in
   62ch on the left, the lede in 56ch on the right, and left the rest of the
   row empty — which is what read as cluttered and left-pushed. A short .link
   or .btn may still sit beside a heading; that is the homepage's own pattern
   and the only thing .split is still doing here. */
.sx__aside, .sig__aside, .pg__aside, .ab-aside {
  flex: 1 0 100%; min-inline-size: 0; max-inline-size: none;
}
.sx__aside p + p, .ab-aside p + p { margin-block-start: .85em; }

/* A split header spans the row — the 62ch cap belongs to a stacked heading
   block, and left on the split it held the whole header at 48% with the
   right half empty, which is the thing the split exists to fix. */
.split.sx__top, .split.sig__top, .split.pg__top, .split.ab-top {
  max-inline-size: none;
  inline-size: 100%;
}

/* A heading block with no supporting line has nothing to pair with, so the
   62ch cap just parks a short title in a narrow column with the row empty
   beside it. Let it span; the body below is full width anyway. */
@supports selector(:has(*)) {
  .sx__top:not(:has(.sec-sub)), .pg__top:not(:has(.sec-sub)) { max-inline-size: none; }
}

/* The kitchen plan's zone tabs measured 38.8px — under the thumb minimum,
   and they are the control for the drawing above them. */
@media (max-width: 900px) {
  .plan__tabs button { min-block-size: 44px; }
}

/* Matches .svc__dur on the homepage cards — see v2-home.css. */
.scard__dur{display:block;margin-block:6px 10px;font-family:var(--fd,inherit);font-size:12.5px;
  letter-spacing:.08em;color:var(--accent-ink,#8a4b06)}

/* ── numbered cards: the number sits BESIDE the heading ────
   Rashi, 2026-10-28: the 01/02 markers and the ticks "come above the text
   and it looks very untidy ... they're very tiny". A 17px number on its own
   line reads as a stray mark rather than as a label for the heading under
   it. Two columns: the number, then the heading and the body sharing the
   second column so the copy stays in one measure. */
.sfeat__c {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 11px;
  align-items: baseline;
}
.sfeat__n { grid-column: 1; grid-row: 1; }
.sfeat__c h3 { grid-column: 2; grid-row: 1; margin: 0 0 9px; }
.sfeat__c p  { grid-column: 2; grid-row: 2; }

/* ── OTHER SERVICES: CARDS, NOT PILLS ──────────────────────────────────────
   Rashi, 2026-10-28: "do not put just buttons, maybe cards 5 in one row with
   thumbnail images and content?"

   Five across at desktop. There are ten services, so a page shows nine of
   them — five and four. The .slinks rules above are left in place: nothing
   renders with that class any more, but they are two lines and removing them
   is a separate tidy-up, not part of this change.

   The tagline is clamped to three lines. They run from eight words to two
   full sentences, and unclamped the tallest card set the height of the whole
   row, leaving a band of white under the short ones. */
.ogrid { display: grid; gap: clamp(14px,1.6vw,20px);
  grid-template-columns: repeat(5, minmax(0,1fr)); }
@media (max-width: 1200px) { .ogrid { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (max-width: 760px)  { .ogrid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 430px)  { .ogrid { grid-template-columns: 1fr; } }

.ocard { display: flex; flex-direction: column; overflow: hidden;
  background: #fff; border: 1px solid rgba(40,31,26,.10); border-radius: 14px;
  text-decoration: none; color: inherit;
  transition: transform .3s cubic-bezier(.2,.7,.2,1), box-shadow .3s ease, border-color .3s ease; }
.ocard:hover { transform: translateY(-5px); border-color: #ddd0c0;
  box-shadow: 0 18px 38px rgba(33,26,22,.13); }
.ocard:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 3px; }
.ocard__ph { overflow: hidden; background: #eee5da; }
.ocard__ph img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block;
  transition: transform .5s cubic-bezier(.2,.7,.2,1); }
.ocard:hover .ocard__ph img { transform: scale(1.06); }
.ocard__in { padding: 14px 15px 16px; }
.ocard__t { margin: 0; font-family: var(--fh); font-weight: 600; font-size: 16px;
  letter-spacing: -.015em; color: var(--heading,#3a2e26); }
.ocard__dur { display: block; margin-block-start: 5px; font-family: var(--fb);
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-600,#cb7319); }
.ocard__b { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: #6b6259;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  .ocard, .ocard__ph img { transition: none !important; }
  .ocard:hover { transform: none; }
}

/* ── A PORTRAIT DRAWING MUST NOT SET THE ROW HEIGHT ────────────────────────
   Rashi, 2026-10-29: "make this image smaller to fit against the text."

   On /services/design-and-permits/ the permits drawing is 718x1077 — taller
   than it is wide. .sx__shot is `inline-size: 100%`, so it filled the 680px
   media column and came out 1019px tall against a 737px text column: the
   image set the height of the row and left 300px of dead space beside the
   copy.

   Capping the HEIGHT and letting the width follow fixes the tall ones and
   leaves the other 30 sections alone — a landscape drawing in a 680px
   column is about 490px tall and never reaches this cap, so nothing it does
   today changes. The image keeps its own aspect ratio; it is scaled, not
   cropped and not letterboxed.

   ⚠ Do not "fix" this by setting a height on .sx__media instead. That boxes
   the figure and the caption with it, and object-fit would then crop a
   drawing — which on a floor plan means losing dimensions off the edge. */
/* ⚠ inline-size STAYS 100%. The obvious version of this rule sets
   `inline-size: auto` so the width follows the capped height — and it looks
   right, and it silently reintroduces layout shift. With auto, the browser
   stops reserving a box for a lazy image from its width/height attributes:
   measured on /custom-home-builder-leaside/, the figure was 44px tall (the
   caption alone) until the image scrolled into view and then jumped to
   729px. A 685px shift, three times on that page.

   Keeping the width at 100% keeps the aspect-ratio box, so the space is
   reserved before the file arrives; max-block-size then caps it and
   object-fit: contain scales the drawing inside rather than cropping it.
   The spare width shows the figure's own white, which is already what a
   drawing sits on, so the letterboxing is invisible. */
.sx__media--drawing .sx__shot,
.sx__media--render .sx__shot {
  max-block-size: min(72vh, 740px);
  object-fit: contain;
}
