/* ═══════════════════════════════════════════════════════════════
   FLOWSYNERGY — service.css : category + comparison pages.
   Readout hero · two-column shell (prose + sticky index) · selection matrix ·
   comparison table with the winner lifted. Extends site.css; redefines no chrome.
   ═══════════════════════════════════════════════════════════════ */

/* ── hero: readout variant ─────────────────────────────────── */
.hero--svc{position:relative; overflow:hidden; isolation:isolate; padding:clamp(40px,7vh,84px) var(--gut) 0}
.hero--svc .hero__plot{position:absolute; inset:0; width:100%; height:100%; z-index:-2; color:var(--sig); opacity:.16}
.hero--svc .hero__vign{position:absolute; inset:0; z-index:-1; background:radial-gradient(110% 80% at 82% 0%, rgba(133,224,255,.09), transparent 56%), linear-gradient(to top, var(--bg) 0%, rgba(8,9,11,.55) 40%, rgba(8,9,11,.25) 100%)}
.hero__in{max-width:var(--wide); margin-inline:auto}
.hero__grid{display:grid; grid-template-columns:minmax(0,1.35fr) minmax(300px,420px); gap:clamp(28px,4vw,80px); align-items:end}
.hero--svc h1{font-size:clamp(2.6rem,5.6vw,5rem); font-weight:800; letter-spacing:-.045em; text-wrap:balance; margin-bottom:clamp(18px,3vh,30px)}
.hero--svc h1 .vs{font-family:var(--mono); font-weight:400; font-size:.42em; letter-spacing:.16em; color:var(--sig); vertical-align:middle; margin:0 .35em; text-transform:uppercase}
.hero--svc .crumbs{margin-bottom:clamp(20px,3vh,36px)}
.hero__meta{margin-top:18px; font-size:12px; letter-spacing:.04em; color:var(--dim); line-height:1.6; max-width:var(--measure)}
.hero__meta a{color:var(--sig); border-bottom:1px solid rgba(133,224,255,.35)}
.hero--svc .readout{align-self:end}
.hero--svc .readout .big{font-size:clamp(2.6rem,4.4vw,3.8rem)}
.hero--svc .readout .big i{font-size:12px}
.frame--wide{margin-top:clamp(32px,5vh,64px)}
.frame--wide img{aspect-ratio:21/8; object-fit:cover}

/* comparison hero: the two contenders as a split readout */
.hero--duel .hero__title--wide{max-width:none}
.hero--duel .lead{max-width:var(--exhibit)}
.hero__duelrow{display:grid; grid-template-columns:minmax(0,1.7fr) minmax(280px,1fr); gap:clamp(20px,2.4vw,40px); align-items:stretch; margin-top:clamp(32px,5vh,56px)}
.duel{display:grid; grid-template-columns:1fr 1fr; gap:1px; background:var(--line-struct); border:1px solid var(--line-struct); border-radius:var(--radius-frame); overflow:hidden}
.frame--side{display:flex; flex-direction:column}
.frame--side img{flex:1; min-height:0; height:100%; object-fit:cover; aspect-ratio:auto}
.duel__side{background:var(--bg-3); padding:clamp(20px,2.4vw,32px); display:flex; flex-direction:column; gap:14px; min-width:0}
.duel__side .k{display:block; font-family:var(--mono); font-size:12px; letter-spacing:.2em; text-transform:uppercase; color:var(--dim)}
.duel__side:first-child .k{color:var(--txt-2)}
.duel__side:last-child .k{color:var(--txt-2)}
/* B4-04: the last --line-2 boundary still doing structural work -- 1.34:1 against its own
   card, on the hero verdict of both comparison pages. --line-2 is texture; this is a border. */
.verdict--quiet{background:rgba(255,255,255,.04); border-color:var(--line-struct); color:var(--txt-2)}
.verdict--quiet .dot{box-shadow:0 0 0 4px rgba(255,255,255,.08)}
.duel__name{font-size:clamp(1.3rem,2.1vw,1.9rem); font-weight:700; letter-spacing:-.03em; line-height:1.05; color:var(--txt)}
.duel__what{font-size:15px; line-height:1.55; color:var(--txt-2); max-width:44ch}
.duel .verdict{align-self:flex-start}
.duel .taglist{margin-top:auto; padding-top:6px}

/* ── the two-column shell ──────────────────────────────────── */
.svc{max-width:var(--wide); margin-inline:auto; padding:clamp(48px,7vh,96px) var(--gut) clamp(56px,8vh,110px); display:grid; grid-template-columns:minmax(0,1fr) 236px; column-gap:clamp(36px,4.6vw,84px); align-items:start}
.svc__main{min-width:0}
.svc__side{position:sticky; top:calc(var(--rail-h) + 28px)}
.svc__side .index{position:static}
.index li a{white-space:nowrap; overflow:hidden; text-overflow:ellipsis}

/* chapters */
.chapter{scroll-margin-top:calc(var(--rail-h) + 24px)}
.chapter+.chapter{margin-top:clamp(40px,6vh,72px)}
.chapter .prose h2{margin-top:0}
.chapter:first-child .prose h2{border-top:0; padding-top:0}
.chapter:target .prose h2{border-top-color:var(--sig)}
.chapter .caveat{margin-top:1.6em}

/* exhibits break the measure: full main-column width */
.exhibit{margin:clamp(26px,4vh,44px) 0 0; max-width:none}
figure.exhibit{background:transparent; border:0; border-radius:0}
figure.exhibit>figcaption{padding:12px 0 0; border-top:1px solid var(--line-struct); margin-top:14px; font-family:var(--mono); font-size:12px; letter-spacing:.04em; color:var(--dim); line-height:1.6; max-width:var(--exhibit)}
/* A1-12: exhibits sat at three widths (measure / --exhibit / full column) so right edges
   stepped in and out three times a screen. Two widths only: prose at --measure, every
   exhibit at the full main column. --exhibit stays for .panel and for article.css. */
figure.frame.exhibit{background:var(--bg-2); border:1px solid var(--line-struct); border-radius:var(--radius-frame)}
figure.frame.exhibit>figcaption{padding:12px 16px; margin-top:0; max-width:none}
.exhibit .tbl{font-size:15px}
.exhibit .tbl th{padding-bottom:14px}
.exhibit .tbl td{padding:16px 20px 16px 0}
.exhibit .tbl td:first-child{font-size:15px; color:var(--txt); font-weight:500}
.exhibit .tbl--wrap td:first-child{min-width:12ch; max-width:22ch}
.exhibit .tbl td:last-child{text-align:right}
.exhibit .tbl td:last-child .chip{margin-left:auto}
.exhibit .tbl td a{color:var(--sig); border-bottom:1px solid rgba(133,224,255,.35)}

/* ── the selection matrix ──────────────────────────────────── */
.matrix .cell{gap:14px; padding:clamp(20px,2.2vw,28px)}
.matrix .cell h3{font-size:clamp(1.2rem,1.6vw,1.5rem); font-weight:700}
.spec{margin:0; display:grid; gap:12px}
.spec div{display:grid; grid-template-columns:5.5ch 1fr; gap:12px; align-items:start}
.spec dt{font-family:var(--mono); font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--dim); padding-top:.3em}
.spec div:nth-child(2) dt{color:var(--warn)}
.spec dd{margin:0; font-size:13px; line-height:1.6; color:var(--txt-2); text-wrap:pretty}
.matrix .cell__foot .ok{letter-spacing:.06em}

/* ── comparison table: the winner lifted per row ───────────── */
.tbl--duel th{font-size:12px}
.tbl--duel th:not(:first-child){font-family:var(--disp); font-size:1.05rem; letter-spacing:-.02em; text-transform:none; color:var(--txt); font-weight:700; width:38%}
.tbl--duel td{text-align:left !important; color:var(--dim)}
.tbl--duel td:first-child{color:var(--txt); font-size:13px; white-space:normal; width:auto; min-width:14ch; max-width:20ch}
.tbl--duel td:not(:first-child){padding-left:14px; border-left:2px solid transparent}
.tbl--duel td.hi{color:var(--txt); border-left-color:var(--sig); background:linear-gradient(90deg, rgba(133,224,255,.07), transparent 70%)}
/* C1-16: this used to be `::before{content:'winner'}`. The verdict -- which device wins
   each row -- is the whole point of a comparison page, and it existed only as generated
   content, a colour and a border: nothing in the markup distinguished a winning cell.
   It is a real element now. Same word, same place, same style, but it is text. */
.tbl td.hi .win,.tbl--duel td.hi .win,.tbl--dec td.hi .win{display:block; font-family:var(--mono); font-size:12px; letter-spacing:.18em; text-transform:uppercase; color:var(--txt); font-weight:400; margin-bottom:6px}

/* ── steps: reading size lifted a notch on service pages ───── */

/* ── focus ─────────────────────────────────────────────────── */
.index a:focus-visible,.hero__meta a:focus-visible,.exhibit a:focus-visible{outline:2px solid var(--sig); outline-offset:2px}

/* ── responsive ────────────────────────────────────────────── */
@media (max-width:1180px){
  .svc{grid-template-columns:1fr; row-gap:0}
  .svc__side{position:static; order:-1; margin-bottom:clamp(36px,5vh,56px); padding-bottom:clamp(24px,3vh,36px); border-bottom:1px solid var(--line-struct)}
  .svc__side .index ol{border-left:0; display:flex; flex-wrap:wrap; gap:8px}
  /* C2-02: this was two rules, and the second stripped the border-left and padding-left off
     the box the first had just drawn -- three-sided brackets with the numeral flush on the
     missing edge. One rule now. */
  .svc__side .index li a{border:1px solid var(--line-struct); border-radius:var(--radius);
    padding:13px 14px; margin-left:0; white-space:normal}
  .hero__grid{grid-template-columns:1fr}
  .hero__duelrow{grid-template-columns:1fr}
  .frame--side img{aspect-ratio:21/9; height:auto; flex:none}
  .hero--svc .readout{max-width:560px}
  .matrix.cells--3{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:720px){
  .hero--svc h1{font-size:clamp(2.4rem,11vw,3.4rem)}
  .duel{grid-template-columns:1fr}
  .frame--side img{aspect-ratio:16/10; height:auto}
  .frame--wide img{aspect-ratio:16/10}
  .matrix.cells--3{grid-template-columns:1fr}
  .spec div{grid-template-columns:5.5ch 1fr}
  .exhibit .tbl{font-size:13px}
  .exhibit .tbl td{padding:12px 14px 12px 0}
  .tbl--duel thead{display:none}
  .tbl--duel tr{display:grid; grid-template-columns:1fr 1fr; gap:0 12px; border-bottom:1px solid var(--line-struct); padding:14px 0}
  .tbl--duel td{border-bottom:0; padding:6px 0}
  .tbl--duel td:first-child{grid-column:1/-1; max-width:none; padding:0 0 6px}
  .tbl--duel td:not(:first-child){display:flex; flex-direction:column; padding-left:10px}
  .tbl--duel td:not(:first-child)::after{content:attr(data-c); order:-1; font-family:var(--mono); font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--txt-2); margin-bottom:6px}
  .tbl--duel td.hi .win{order:-2}
  .tbl--wrap.stds{min-width:560px}
}
@media (max-width:480px){
  .tbl--duel tr{grid-template-columns:1fr}
  .tbl--duel td:first-child{grid-column:auto}
  /* R1-02: the standards ledger restacks as cards — designation + kind chip on one line,
     description under. Overrides the ≤720 min-width and exhibit paddings above. */
  .exhibit .tbl--wrap.stds{min-width:0; font-size:13px}
  .exhibit .tbl.stds thead{display:none}
  .exhibit .tbl.stds tr{display:grid; grid-template-columns:minmax(0,1fr) auto; gap:4px 14px; padding:14px 0; border-bottom:1px solid var(--line-struct); align-items:baseline}
  .exhibit .tbl.stds td{display:block; border-bottom:0; padding:0}
  .exhibit .tbl.stds td:first-child{white-space:normal; width:auto; max-width:none; font-size:13px}
  .exhibit .tbl.stds td:nth-child(2){grid-column:1 / -1; grid-row:2}
  .exhibit .tbl.stds td:last-child{grid-column:2; grid-row:1; text-align:right}
}

/* ── R3 additions (build_service3): the ladder · the line ledger · the demand grid ── */

/* the enquiry-worked ladder (technical-support-testing) */
.ladder{list-style:none; margin:0; padding:0; counter-reset:lr; display:grid; gap:1px; background:var(--line-struct); border:1px solid var(--line-struct); border-radius:var(--radius-frame); overflow:hidden}
.ladder>li{counter-increment:lr; background:var(--bg-2); display:grid; grid-template-columns:minmax(0,1.15fr) minmax(0,1fr) minmax(0,1fr); gap:clamp(16px,2.2vw,36px); padding:clamp(18px,2.2vw,28px) clamp(18px,2.4vw,32px)}
.ladder .step{display:grid; grid-template-columns:4ch 1fr; gap:14px; align-items:start}
.ladder .step::before{content:counter(lr,decimal-leading-zero); font-family:var(--mono); font-size:12px; letter-spacing:.12em; color:var(--txt-2); padding-top:.42em}
.ladder .step h3{font-size:clamp(1.05rem,1.4vw,1.3rem); font-weight:600; letter-spacing:-.02em; line-height:1.15; color:var(--txt); margin-bottom:6px}
.ladder .step p{font-size:13px; line-height:1.55; color:var(--dim)}
.ladder .hand .k{display:block; font-family:var(--mono); font-size:12px; letter-spacing:.18em; text-transform:uppercase; color:var(--dim); margin-bottom:8px}
.ladder .hand p{font-size:13px; line-height:1.62; color:var(--txt-2); text-wrap:pretty}
.ladder .hand--fss{border-left:2px solid var(--sig); padding-left:clamp(14px,1.6vw,22px)}
.ladder .hand--fss .k{color:var(--txt-2)}

/* the line ledger (product-lines) */
.chapter--line+.chapter--line{margin-top:clamp(28px,4vh,48px)}
.line{display:grid; grid-template-columns:minmax(0,1.45fr) minmax(0,.85fr) minmax(0,1fr); gap:1px; background:var(--line-struct); border:1px solid var(--line-struct); border-radius:var(--radius-frame); overflow:hidden}
.line>div{background:var(--bg-2); padding:clamp(18px,2.2vw,28px); min-width:0}
.line .k{display:block; font-family:var(--mono); font-size:12px; letter-spacing:.2em; text-transform:uppercase; color:var(--dim); margin-bottom:10px}
.line p{font-size:15px; line-height:1.64; color:var(--txt-2); text-wrap:pretty}
.line .feeds{list-style:none; margin:0; padding:0; display:grid; gap:8px}
.line .feeds a{font-family:var(--mono); font-size:13px; letter-spacing:.04em; color:var(--sig); border-bottom:1px solid rgba(133,224,255,.35)}
.line .feeds a:hover{border-bottom-color:var(--sig)}
.line__foot{margin-top:16px; padding-top:12px; border-top:1px solid var(--line-struct)}
.line__foot .k{margin-bottom:8px}

/* the industry × demand grid (industries) */
.dcell dl{margin:0; display:grid; gap:10px}
.dcell dl div{display:grid; grid-template-columns:8.5ch 1fr; gap:10px; align-items:start}
.dcell dt{font-family:var(--mono); font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--dim); padding-top:.25em}
.dcell dd{margin:0; font-size:13px; line-height:1.58; color:var(--txt-2); text-wrap:pretty}
.dcell dd a{color:var(--sig); border-bottom:1px solid rgba(133,224,255,.35)}
.dcell dd a:hover{border-bottom-color:var(--sig)}
.dcell .cell__foot{white-space:normal}

/* responsive */
@media (max-width:1180px){
  .dgrid.cells--3{grid-template-columns:repeat(2,1fr)}
  .ladder>li{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr) minmax(0,1fr); gap:clamp(14px,2vw,24px)}
}
@media (max-width:980px){
  .ladder>li{grid-template-columns:1fr; gap:14px}
  .ladder .hand{padding-left:calc(4ch + 14px)}
  .ladder .hand--fss{border-left:0; padding-left:calc(4ch + 14px)}
  .ladder .hand--fss p{border-left:2px solid var(--sig); padding-left:14px}
  .line{grid-template-columns:1fr}
}
@media (max-width:720px){
  .dgrid.cells--3{grid-template-columns:1fr}
  .ladder .hand,.ladder .hand--fss{padding-left:0}
}

/* ═══════════════════════════════════════════════════════════════
   Phase 3 additions — ladder (hvac) · chain (steam) ·
   decision table (actuators) · trio comparison (gate/ball/butterfly).
   Extends the service sheet; redefines no chrome.
   ═══════════════════════════════════════════════════════════════ */

/* ── the system ladder: plant → distribution → terminal ─────── */
/* B1-06: scoped with :has(), NOT deleted. `.ladder` is two different objects -- an <ol> of
   rungs on technical-support-testing (hairline grid, gap:1px) and this level stack on
   hvac. The bare re-declaration used to win on `gap` alone while leaving the grid's
   --line-struct ground in place, so 16-26px of it painted through as solid slabs. The
   ground has to be reset here as well as the gap. */
.ladder:has(.ladder__level){display:grid; gap:clamp(16px,2.2vh,26px); background:transparent; border:0; border-radius:0; overflow:visible}
.ladder__level{display:grid; grid-template-columns:minmax(210px,280px) minmax(0,1fr); gap:clamp(14px,1.5vw,22px); align-items:stretch}
.ladder__head{background:var(--bg-3); border:1px solid var(--line-struct); border-left:2px solid var(--sig); border-radius:var(--radius-frame); padding:clamp(18px,2vw,26px); display:flex; flex-direction:column; gap:10px}
.ladder__head .n{font-family:var(--mono); font-size:12px; letter-spacing:.2em; text-transform:uppercase; color:var(--txt-2)}
.ladder__head h3{font-size:clamp(1.15rem,1.5vw,1.42rem); font-weight:700; letter-spacing:-.02em; color:var(--txt); line-height:1.15}
.ladder__head p{font-size:13px; line-height:1.6; color:var(--txt-2); text-wrap:pretty}
.ladder .cell{padding:clamp(16px,1.8vw,24px); gap:10px}
.ladder .cell h3{font-size:1.05rem}
.ladder .spec dd{font-size:13px}
/* A1-07: three cells inside a level left ~137px for the definition column -- about 17
   characters per line -- while each level's head cell ran out of text and left 200-260px of
   empty panel beside them.
   The first attempt at this was two columns, and render_gate was right to reject it: a level
   holds exactly THREE cards, so two columns orphans one at every width. (INNER-PAGE-DESIGN
   §3: compute a grid's column count from its CHILD COUNT. It is the most repeated defect in
   this whole exercise and it caught me too.)
   What actually buys the measure is removing the 210-280px head column from the row: the head
   becomes a full-width band ABOVE its three cards, so each card gains ~80px and the head's
   dead space disappears because it is now short and wide rather than tall and empty. Three
   cards, three columns, no orphan. */
.ladder__level{grid-template-columns:1fr; gap:clamp(12px,1.4vh,18px)}
.ladder__head{flex-direction:row; align-items:baseline; flex-wrap:wrap; gap:8px 16px}
.ladder__head p{flex:1 1 380px; min-width:0}
.ladder .spec div{grid-template-columns:1fr; gap:5px}
.ladder .spec dt{padding-top:0}
@media (max-width:900px){ .ladder .cells--3{grid-template-columns:1fr} }

/* ── the protection chain: reduce → protect → trap → strain ──── */
.chain .cell h3{font-size:1.08rem}
/* B1-05: an 8ch label column inside a 250px cell left ~122px for the value -- one to three
   words a line. A key/value pair cannot be side-by-side at quarter width; it stacks. */
.chain .spec div{grid-template-columns:1fr; gap:5px}
.chain .spec dt{padding-top:0}
.chain .spec dd{font-size:13px}
@media (max-width:1180px){ .chain.cells--4{grid-template-columns:repeat(2,1fr)} }
@media (max-width:720px){ .chain.cells--4{grid-template-columns:1fr} }

/* ── the actuation decision table: four inputs → a choice ────── */
.tbl--dec th{font-size:12px}
.tbl--dec th:last-child{color:var(--sig)}
.tbl--dec td{text-align:left !important; color:var(--dim); font-size:13px; white-space:normal}
.tbl--dec td:first-child{font-family:var(--body); font-weight:600; font-size:13px; color:var(--txt); width:auto; min-width:13ch; max-width:17ch; white-space:normal; overflow-wrap:break-word}
.tbl--dec td:not(:first-child){padding-left:14px; border-left:2px solid transparent}
.tbl--dec td.hi{color:var(--txt); border-left-color:var(--sig); background:linear-gradient(90deg, rgba(133,224,255,.07), transparent 70%)}

@media (max-width:720px){
  .tblwrap:has(.tbl--dec){-webkit-mask-image:none; mask-image:none}
  .tblwrap:has(.tbl--dec)::before{content:none}
  .tbl--dec thead{display:none}
  .tbl--dec tr{display:grid; grid-template-columns:1fr; border-bottom:1px solid var(--line-struct); padding:14px 0}
  .tbl--dec td{border-bottom:0; padding:6px 0 6px 10px; display:flex; flex-direction:column}
  .tbl--dec td:first-child{padding:0 0 6px; max-width:none; font-size:15px}
  .tbl--dec td:not(:first-child)::after{content:attr(data-c); order:-1; font-family:var(--mono); font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--txt-2); margin-bottom:4px}
  .tbl--dec td.hi .win{order:-2}
}

/* ── trio comparison: three contenders in hero and table ─────── */
.duel--trio{grid-template-columns:repeat(3,1fr)}
.duel--trio .duel__side .k{color:var(--dim)}
/* B5: on a page whose own lede says there is no single winner, one contender's chip must
   not be the only lit thing in the hero. All three read as statements, not as a verdict. */
.duel--trio .verdict{background:rgba(255,255,255,.04); border-color:var(--line-struct); color:var(--txt-2)}
.duel--trio .verdict .dot{box-shadow:0 0 0 4px rgba(255,255,255,.08)}
.duel--trio .duel__name{font-size:clamp(1.15rem,1.7vw,1.6rem)}
.hero__duelrow--trio{grid-template-columns:minmax(0,2fr) minmax(260px,1fr)}
.tbl--trio th:not(:first-child){width:27%}
.tbl--duel.tbl--trio td:first-child{min-width:12ch; max-width:20ch}
@media (max-width:1180px){
  .hero__duelrow--trio{grid-template-columns:1fr}
  .exhibit .tbl--trio{font-size:13px}
}
@media (max-width:900px){ .duel--trio{grid-template-columns:1fr} }
@media (max-width:720px){
  .tbl--duel.tbl--trio tr{grid-template-columns:1fr}
  .tbl--duel.tbl--trio td:first-child{grid-column:auto; max-width:none}
}

/* named exhibits: the object gets its own label (and its own rhythm segment) */
.exhibit__h{max-width:var(--wide); font-family:var(--disp); font-size:clamp(1.05rem,1.5vw,1.32rem); font-weight:600; letter-spacing:-.02em; color:var(--txt); margin:clamp(28px,3.6vh,44px) 0 14px}
.exhibit__h + .exhibit{margin-top:0}

/* ══ design review round 1 ═══════════════════════════════════════ */
/* B1-09: the four rungs (17 / 15 / 13 / 12). These override the sizes declared above. */
.exhibit.steps p{font-size:15px}
/* A3-§5b: this cap, not the chapter panel, is why long designations ('CIBSE Commissioning
   Code W', 'ASHRAE Handbook - HVAC Systems and Equipment') wrapped to three mono lines
   against a one-line description. */
.exhibit .tbl--wrap td:first-child{max-width:34ch}
/* B1-16: the two (or three) contenders are one instrument, so their names, descriptions,
   verdict chips and tag lists have to sit on shared baselines. Subgrid does it with no
   markup change and degrades to today's behaviour where it is unsupported. */
@supports (grid-template-rows:subgrid){
  /* FIVE rows, not four: a .duel__side holds k, name, what, verdict AND taglist. Spanning four
     put the last two children in one row and printed the verdict chip on top of the tag list on
     both comparison pages. Count the children before you span them. */
  .duel{grid-template-rows:auto auto 1fr auto auto}
  .duel__side{display:grid; grid-template-rows:subgrid; grid-row:span 5; align-content:start; gap:14px}
  .duel .taglist{margin-top:0}
}
/* B1-04 / B1-11: a numeric field reads as a field -- mono, tabular, right-aligned. */
.tbl--num td:not(:first-child),.tbl--num th:not(:first-child){text-align:right}
.tbl--num td:not(:first-child){font-family:var(--mono); font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1; color:var(--txt)}

/* ══ A1-01: three hero shapes, one markup ═════════════════════════════════
   Nine pages rendered the same hero because the layout was welded to the markup. `display:contents`
   dissolves .hero__grid so title, readout and figure become siblings the hero can place three
   different ways -- no per-page markup, no new copy, and design_gate's composition check now
   measures three values instead of one. ───────────────────────────────────────── */

/* ── variant: SPLIT — tall portrait image holding the right column ───── */
[data-hero="readout-split"] .hero__in{
  display:grid; grid-template-columns:minmax(0,1.45fr) minmax(290px,.92fr);
  column-gap:clamp(28px,4vw,72px); align-items:start;
}
[data-hero="readout-split"] .hero__grid{display:contents}
[data-hero="readout-split"] .hero__title{grid-column:1; grid-row:1}
[data-hero="readout-split"] .readout{grid-column:1; grid-row:2; margin-top:clamp(22px,3vh,36px)}
[data-hero="readout-split"] .frame--wide{
  grid-column:2; grid-row:1 / span 2; margin-top:0;
  display:flex; flex-direction:column; align-self:stretch;
}
[data-hero="readout-split"] .frame--wide img{
  flex:1; min-height:min(560px,58vh); height:100%; aspect-ratio:auto; object-fit:cover;
}

/* ── variant: BAND — the readout as a horizontal spec strip ──────── */
[data-hero="readout-band"] .hero__grid{grid-template-columns:minmax(0,1fr)}
[data-hero="readout-band"] .hero__title{max-width:none}
[data-hero="readout-band"] .hero--svc h1,[data-hero="readout-band"] h1{max-width:18ch}
[data-hero="readout-band"] .readout{
  flex-direction:row; flex-wrap:wrap; align-items:stretch; gap:1px; padding:0;
  background:var(--line-struct); border:1px solid var(--line-struct);
  margin-top:clamp(24px,3.4vh,44px);
}
[data-hero="readout-band"] .readout > *{
  flex:1 1 210px; min-width:0; background:var(--bg-3); padding:clamp(15px,1.7vw,22px);
  display:flex; flex-direction:column; justify-content:flex-start; gap:8px;
}
[data-hero="readout-band"] .readout .row{
  display:flex; flex-direction:column; gap:12px; padding-bottom:0; border-bottom:0;
}
[data-hero="readout-band"] .readout .big{font-size:clamp(2rem,3.2vw,2.8rem)}
/* The verdict is a CHIP everywhere else -- a small box with its own ground. As a band cell
   it was stretched to fill the cell, so the chip's translucent signal ground became a
   filled slab and the quietest statement on the page became its loudest object. In the
   band it keeps the cell ground and gives up its own box: signal text, not a signal panel. */
[data-hero="readout-band"] .readout > .verdict{
  flex:1 1 210px; align-items:center; justify-content:flex-start; flex-direction:row; gap:10px;
  background:var(--bg-3); border:0; border-radius:0; color:var(--sig);
}
[data-hero="readout-band"] .frame--wide img{aspect-ratio:24/7}

/* ══ A1-03: chapters, not one scroll
   NOTE the `body:has(...)` scope. The variant lives on the hero <section> and .svc__main is
   its SIBLING, so `[data-hero=x] .svc__main` matches nothing -- which is exactly how the
   first version of this block shipped silently doing nothing. ════════════════════════════════════
   Panels come in PAIRS -- two chapters on the raised ground, two off. Alternating every single
   chapter reads as stripes; pairs read as chapters. The phase is offset per hero variant, so the
   same section number sits on a different ground on different pages and no two service pages
   scroll alike. Everything stays inside the column: no negative margins, because render_gate
   checks that nothing escapes its container. ────────────────────────────────── */
/* Uniform horizontal padding on EVERY chapter, panelled or not. Without it the panelled ones
   inset their text by ~26px and the numbered spine jogged sideways every other chapter -- the
   rhythm device drawing attention to itself instead of to the chapters.
   And a panel only runs the full column width when the chapter actually has an exhibit in it:
   a prose-only chapter's panel used to extend far past the 68ch measure, so a third of it was
   visibly empty raised ground. `:has()` lets the box hug what is in it. */
.svc__main > .chapter{
  padding:0 clamp(18px,2.2vw,32px); border:1px solid transparent;
  border-radius:var(--radius-frame);
}
/* A7-01: `.steps` is capped at the measure, so a chapter holding nothing but a ledger has no
   object that needs the full column -- and a panel drawn to the full column around it reads
   as a table that ran out of rows. Such a chapter hugs, like a prose one. */
.svc__main > .chapter:not(:has(.exhibit)),
.svc__main > .chapter:has(.exhibit.steps):not(:has(.exhibit:not(.steps))){
  max-width:calc(var(--measure) + 2 * clamp(18px,2.2vw,32px) + 2px);
}
body:has([data-hero="readout-aside"]) .svc__main > .chapter:nth-of-type(4n+2),
body:has([data-hero="readout-aside"]) .svc__main > .chapter:nth-of-type(4n+3),
body:has([data-hero="readout-band"])  .svc__main > .chapter:nth-of-type(4n+3),
body:has([data-hero="readout-band"])  .svc__main > .chapter:nth-of-type(4n+4),
body:has([data-hero="readout-split"]) .svc__main > .chapter:nth-of-type(4n+1),
body:has([data-hero="readout-split"]) .svc__main > .chapter:nth-of-type(4n+4),
body:has([data-hero="readout-duel"])  .svc__main > .chapter:nth-of-type(4n+2),
body:has([data-hero="readout-duel"])  .svc__main > .chapter:nth-of-type(4n+3){
  background:var(--bg-2); border-color:var(--line-struct);
  padding-block:clamp(24px,3.4vh,44px);
}
/* inside a panel the panel edge IS the chapter rule, so the h2 drops its own */
body:has([data-hero="readout-aside"]) .svc__main > .chapter:nth-of-type(4n+2) .prose h2,
body:has([data-hero="readout-aside"]) .svc__main > .chapter:nth-of-type(4n+3) .prose h2,
body:has([data-hero="readout-band"])  .svc__main > .chapter:nth-of-type(4n+3) .prose h2,
body:has([data-hero="readout-band"])  .svc__main > .chapter:nth-of-type(4n+4) .prose h2,
body:has([data-hero="readout-split"]) .svc__main > .chapter:nth-of-type(4n+1) .prose h2,
body:has([data-hero="readout-split"]) .svc__main > .chapter:nth-of-type(4n+4) .prose h2,
body:has([data-hero="readout-duel"])  .svc__main > .chapter:nth-of-type(4n+2) .prose h2,
body:has([data-hero="readout-duel"])  .svc__main > .chapter:nth-of-type(4n+3) .prose h2{
  border-top:0; padding-top:0;
}
/* and a framed exhibit steps up a ground so its border still reads against the panel */
body:has([data-hero="readout-aside"]) .svc__main > .chapter:nth-of-type(4n+2) figure.frame.exhibit,
body:has([data-hero="readout-aside"]) .svc__main > .chapter:nth-of-type(4n+3) figure.frame.exhibit,
body:has([data-hero="readout-band"])  .svc__main > .chapter:nth-of-type(4n+3) figure.frame.exhibit,
body:has([data-hero="readout-band"])  .svc__main > .chapter:nth-of-type(4n+4) figure.frame.exhibit,
body:has([data-hero="readout-split"]) .svc__main > .chapter:nth-of-type(4n+1) figure.frame.exhibit,
body:has([data-hero="readout-split"]) .svc__main > .chapter:nth-of-type(4n+4) figure.frame.exhibit,
body:has([data-hero="readout-duel"])  .svc__main > .chapter:nth-of-type(4n+2) figure.frame.exhibit,
body:has([data-hero="readout-duel"])  .svc__main > .chapter:nth-of-type(4n+3) figure.frame.exhibit{
  background:var(--bg-3);
}

@media (max-width:1180px){
  [data-hero="readout-split"] .hero__in{grid-template-columns:1fr}
  [data-hero="readout-split"] .frame--wide{grid-column:1; grid-row:auto; margin-top:clamp(26px,4vh,44px)}
  [data-hero="readout-split"] .frame--wide img{min-height:0; aspect-ratio:21/9; flex:none; height:auto}
  [data-hero="readout-split"] .readout{max-width:560px}
}
@media (max-width:720px){
  [data-hero="readout-band"] .readout{flex-direction:column}
  [data-hero="readout-band"] .frame--wide img{aspect-ratio:16/10}
  [data-hero="readout-split"] .frame--wide img{aspect-ratio:16/10}
  /* padding-BLOCK only. `padding:0` also zeroed the inline inset, which put a panel's own
     border one pixel from its first text. */
  .svc__main > .chapter{padding-block:0}
}

/* A1-09: the appointment caveat is stated ONCE, in section 01. Printing the warn chip
   in all six line blocks read as six error states and spent the warn colour -- which has
   exactly one job on this site -- six times on one screen. Each block keeps a quiet
   pointer so no entry looks like it is claiming an appointment by staying silent. */
.line__see{font-family:var(--mono); font-size:12px; letter-spacing:.04em; color:var(--dim);
  border-bottom:1px solid var(--line-struct)}
.line__see:hover{color:var(--sig); border-bottom-color:var(--sig)}
.prose > .panel--warn .k{margin-bottom:8px}

/* ══ design review round 2 ════════════════════════════════════════════ */

/* A2-07 / A2-15: a chapter that is one member of a homogeneous series opts OUT of the panel
   rhythm. product-lines is six maker ledgers built to be identical; lighting two of the six and
   insetting them made them narrower than their siblings for no reason a reader could name, and
   at 390 it nested three hairline boxes and cost ~40px of measure. Rhythm marks chapters that
   differ; it must not mark members of a set that deliberately do not. */
.svc__main > .chapter:has(.line){
  background:none !important; border-color:transparent !important;
  padding-block:0 !important; max-width:none !important;
}
/* ...and its COUNTERPART. The panel rule removes the h2's own border-top because the panel
   edge does that job; opting a chapter out of the panel without also opting it out of that
   removal left three of the six makers with no separator at all. */
/* !important, because this is (0,4,1) and the panel rule it has to beat is (0,5,2) -- so
   without it the rule was present, correct, and overridden on exactly the chapters it was
   written for. The opt-out block above carries !important for the same reason. */
.svc__main > .chapter:has(.line) .prose h2{border-top:1px solid var(--line-struct) !important; padding-top:.9em !important}

/* A2-14: an exhibit inside a panel used to lose the panel's horizontal padding from its own
   width, so the same standards table was narrower on hvac than on valves and its designation
   column wrapped to three mono lines. Exhibits break back out to the column's own edge. */
/* `.steps` is capped at the measure now, so breaking it out of the chapter's padding only
   hangs it 33px left of its own chapter. Exhibits that USE the extra width still break out. */
.svc__main > .chapter > .exhibit.steps{margin-inline:0}
.svc__main > .chapter > .exhibit:not(.steps),
.svc__main > .chapter > figure.exhibit,
.svc__main > .chapter > .exhibit__h{
  margin-inline:calc(-1 * clamp(18px,2.2vw,32px));
}
.svc__main > .chapter > figure.frame.exhibit > figcaption{padding-inline:clamp(18px,2.2vw,32px)}

/* A2-13: cell three of the band strip held nothing but the verdict chip -- ~197x145px of panel
   around one 30px chip, and five cells at five different content heights. The verdict becomes
   the foot of the cell before it, so the strip runs four. */
[data-hero="readout-band"] .readout{align-items:stretch}
/* `align-self:center` shrank this cell vertically and exposed the STRIP'S OWN background --
   which is --line-struct, the hairline showing through the 1px gaps -- as a 356x220px slab of
   raw grey. A cell in a hairline grid must always stretch; only its WIDTH may shrink to its
   content, which is what fixes the empty-panel complaint this rule was written for. */
[data-hero="readout-band"] .readout > .verdict{flex:0 1 auto; align-self:stretch; justify-content:flex-start}
/* B6-04: the chip sat centred in a cell 60% empty. It reads as the cell's statement when it
   sits on the same top line as every other cell's label. */
[data-hero="readout-band"] .readout > .verdict{align-items:flex-start; padding-top:clamp(15px,1.7vw,22px)}
@media (max-width:720px){
  /* B6-03: stacked at 390 the cells were floored at 211px by the flex-basis, leaving 85-121px
     of empty panel each. Stacked cells size to their content. */
  [data-hero="readout-band"] .readout > *{flex:0 0 auto; padding:clamp(13px,3.4vw,18px)}
}
[data-hero="readout-band"] .readout .big{align-items:baseline}
/* No nowrap here. It was written for the numeral and inherited by the unit phrase beside it,
   which then truncated mid-word: "4 stages · reduce to strai". */
[data-hero="readout-band"] .readout .big i{white-space:normal}

/* A2-03: the last two screens of a service page were pixel-identical everywhere. Both closing
   objects now take their shape from the hero variant, so no two service pages end alike.
   On BAND pages the standards ledger restacks -- designation on its own line, description under
   it, kind chip right -- which is the treatment this sheet already ships at <=480, promoted to
   all widths rather than invented. Table rows restacking, so no grid-orphan risk. */
body:has([data-hero="readout-band"]) .exhibit .tbl.stds{font-size:15px}
body:has([data-hero="readout-band"]) .exhibit .tbl.stds thead{display:none}
body:has([data-hero="readout-band"]) .exhibit .tbl.stds tr{
  display:grid; grid-template-columns:minmax(0,1fr) auto; gap:6px 18px;
  padding:16px 0; border-bottom:1px solid var(--line-struct); align-items:baseline;
}
body:has([data-hero="readout-band"]) .exhibit .tbl.stds td{display:block; border-bottom:0; padding:0}
body:has([data-hero="readout-band"]) .exhibit .tbl.stds td:first-child{
  white-space:normal; width:auto; max-width:none; font-family:var(--mono); font-size:15px; color:var(--txt);
}
body:has([data-hero="readout-band"]) .exhibit .tbl.stds td:nth-child(2){grid-column:1 / -1; grid-row:2; color:var(--txt-2); max-width:var(--measure)}
body:has([data-hero="readout-band"]) .exhibit .tbl.stds td:last-child{grid-column:2; grid-row:1; text-align:right}

/* ...and the enquiry band, which closed every page identically. Four across on band pages, and
   on split pages the readout column leads instead of following. */
body:has([data-hero="readout-band"]) .enquire__in{grid-template-columns:1fr}
body:has([data-hero="readout-band"]) .enquire__fields{grid-template-columns:repeat(4,1fr); margin-top:clamp(24px,3vh,36px)}
body:has([data-hero="readout-split"]) .enquire__in{grid-template-columns:minmax(0,1fr) minmax(0,1.2fr)}
body:has([data-hero="readout-split"]) .enquire__fields{order:-1}
@media (max-width:900px){
  body:has([data-hero="readout-band"]) .enquire__fields{grid-template-columns:repeat(2,1fr)}
  body:has([data-hero="readout-split"]) .enquire__in{grid-template-columns:1fr}
  body:has([data-hero="readout-split"]) .enquire__fields{order:0}
}
@media (max-width:720px){
  body:has([data-hero="readout-band"]) .enquire__fields{grid-template-columns:1fr}
  /* A2-15: below 900 the panel keeps its ground as the rhythm cue but drops the inset, so the
     boxes stop nesting on a phone. */
  .svc__main > .chapter > .exhibit,
  .svc__main > .chapter > figure.exhibit,
  .svc__main > .chapter > .exhibit__h{margin-inline:0}
}

/* A2-10: a readout headline that is a PHRASE rather than a numeral needs its own size -- the
   .big rung is tuned for two or three tabular digits and a word set at it overruns the card. */
.hero--svc .readout .big:not(.mono){font-size:clamp(1.5rem,2.2vw,2.1rem); line-height:1.1; letter-spacing:-.03em}

/* ══ A4-04: the third closing object varies too ═══════════════════════════════════════════
   §08 (the standards ledger) and the enquiry band already take their shape from the hero
   variant. §09 -- the numbered ledger of documents to request -- did not, so valves and hvac
   still closed table → ledger → maker cells → band in one identical sequence. Three
   arrangements of the same <li> children. Rows, not a card grid, so nothing can orphan. */
/* A6-01: aside and split were separated by nine pixels of number track, which is not a
   variant, it is a rounding error. The aside ledger puts its counter in a ruled left rail --
   a different object at a glance, not a different measurement. */
body:has([data-hero="readout-aside"]) .svc__main .steps li{
  grid-template-columns:minmax(0,7ch) minmax(0,1fr); gap:0 clamp(18px,2.2vw,32px);
}
body:has([data-hero="readout-aside"]) .svc__main .steps li::before{
  font-size:15px; color:var(--txt); padding-top:0; align-self:stretch;
  border-right:1px solid var(--line-struct); padding-right:clamp(14px,1.8vw,24px);
}
body:has([data-hero="readout-split"]) .svc__main .steps li{
  grid-template-columns:4.6ch minmax(0,1fr); align-items:start;
}
body:has([data-hero="readout-split"]) .svc__main .steps li::before{
  font-size:15px; color:var(--txt); padding-top:0;
}
/* the three-column band row is the one arrangement that needs more than the measure */
body:has([data-hero="readout-band"]) .svc__main .steps{max-width:var(--exhibit)}
body:has([data-hero="readout-band"]) .svc__main .steps li{
  grid-template-columns:3.2ch minmax(0,20ch) minmax(0,1fr); gap:16px clamp(16px,2vw,28px);
}
body:has([data-hero="readout-band"]) .svc__main .steps li > div{display:contents}
body:has([data-hero="readout-band"]) .svc__main .steps .steps__h,
body:has([data-hero="readout-band"]) .svc__main .steps h3{margin-bottom:0; align-self:start}
@media (max-width:900px){
  /* A7-04: every ledger variant collapses to one counter column on a phone. A 7ch ruled rail
     is a desktop device; at 390 it cost the copy nine characters a line against the prose
     directly above it. */
  body:has([data-hero="readout-aside"]) .svc__main .steps li{grid-template-columns:3.2ch minmax(0,1fr); gap:0 16px}
  body:has([data-hero="readout-aside"]) .svc__main .steps li::before{border-right:0; padding-right:0; font-size:12px; color:var(--txt-2)}
  body:has([data-hero="readout-split"]) .svc__main .steps li{grid-template-columns:3.2ch minmax(0,1fr)}
  body:has([data-hero="readout-band"]) .svc__main .steps li{grid-template-columns:3.2ch minmax(0,1fr)}
  body:has([data-hero="readout-band"]) .svc__main .steps li > div{display:block}
  body:has([data-hero="readout-band"]) .svc__main .steps .steps__h,
  body:has([data-hero="readout-band"]) .svc__main .steps h3{margin-bottom:6px}
}

@media (max-width:480px){
  /* render_gate @360: the band-page standards restack is a 2-column grid (label | chip), and at
     360px the chip's `auto` track left 111px for a 117px word -- "Thermodynamic" is one word and
     cannot wrap. Below 480 the row stacks fully, so the designation gets the whole width and the
     chip sits under it. */
  body:has([data-hero="readout-band"]) .exhibit .tbl.stds tr{grid-template-columns:minmax(0,1fr)}
  body:has([data-hero="readout-band"]) .exhibit .tbl.stds td:nth-child(2){grid-row:auto}
  body:has([data-hero="readout-band"]) .exhibit .tbl.stds td:last-child{grid-column:1; grid-row:auto; text-align:left; padding-top:6px}
}

/* A6-03: on industries the sector table's figcaption and the caveat under it stacked at two
   different left edges with two different rule widths, because the figure breaks out to the
   column edge and the .prose that carries the caveat does not. A note about an exhibit lines up
   with the exhibit. */
.svc__main > .chapter > .prose:has(> .caveat:only-child){
  margin-inline:calc(-1 * clamp(18px,2.2vw,32px));
  max-width:none;
}
.svc__main > .chapter > .prose:has(> .caveat:only-child) > .caveat{max-width:var(--exhibit)}
