/* ELEMENT PAGES — /pool /stair /systems /glazing /shell
   One shape, five instances. Reuses the spine's tokens, type and motion
   unchanged; this file only adds the sub-page shell, the spec block, the
   Elements index on the spine, and the ADC corner mark. */

/* ---------------- sub-page hero ---------------- */
.el-hero{position:relative;height:min(82svh,46rem);min-height:24rem;
  display:grid;align-items:end;overflow:clip;isolation:isolate}
.el-hero img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 45%;z-index:-2}
/* Stops are absolute lengths, not percentages, and that is the whole point.
   The crumb is the topmost copy and the binding constraint, and it sits a FIXED
   distance above the hero bottom — 191.5px at worst (gutter + h1 + leading, all
   width-driven; h1 caps at 6rem). The hero's height is svh-driven. So a
   percentage scrim slides out from under the crumb as the viewport shortens: at
   1920 wide the crumb moved from 36% to 54% of the old 72%-tall box between a
   1080px-tall and a 600px-tall viewport, and contrast fell to 2.43:1. Pinning
   the stops in rem locks the scrim to the copy at every viewport height.
   Depth is set by the crumb, never the title: over a dark photograph h1 (--ink)
   needs only α ≈ 0.51, the crumb needs α ≈ 0.89. --copper-ink (#8A5626,
   L=0.122) tops out at 5.76:1 on FULL paper, so over the near-black pixels
   these photos put behind the crumb it needs α ≥ 0.891 to clear 4.5:1. The .94
   stop at 12.5rem holds α ≈ 0.943 at the worst crumb position → 5.08:1.
   Measured across stair/academia/engineer/photographer/toshi × 15 viewports
   (1920x600 → 360x640): worst 5.08, best 5.73 — flat, because it no longer
   depends on viewport height.

   Measure the real glyph ink band, not the border box. The crumb's box carries
   ~4px of half-leading above the cap line (box 542.7-561.6 at 1440x900, ink only
   546.7-555.7), and sampling those empty rows understates the ratio by ~0.12.
   Both numbers still failed here, but a fix calibrated on the box overshoots.

   The last stop is 24rem, the hero's own min-height, so the fade always
   completes inside the box and never leaves a hard edge at the top.
   /pool /glazing /shell /systems and the --film heroes (architect, john, terry,
   leslie) override or suppress this rule and are unaffected. */
.el-hero::before{content:"";position:absolute;inset-inline:0;bottom:0;height:100%;z-index:-1;
  background:linear-gradient(to top,var(--paper) 0,rgba(250,248,244,.94) 12.5rem,
    rgba(250,248,244,.55) 17rem,transparent 24rem)}
.el-hero__copy{position:relative;padding:0 var(--gutter) clamp(2rem,1rem + 4vw,4rem);
  max-width:78rem;margin-inline:auto;width:100%}
.el-hero h1{font-size:clamp(2.5rem,1.4rem + 5vw,6rem);
  font-weight:600;letter-spacing:-.02em;color:var(--ink);margin:.1em 0 0}

/* ----------------------------------------------------------------
   HERO VARIANTS — four distinct above-the-fold treatments.
   All reuse the same token set and type scale; structure and weight
   differ. The default .el-hero is the fallback for pages not in the
   five-element set (academia, leslie, terry, etc.).
   ---------------------------------------------------------------- */

/* /pool — full-bleed hold. The parchment scrim is removed; the image
   reads at full value. The hook sentence overlays the photograph as a
   translucent legend. Taller than the default to give the vessel room. */
.el-hero--full-bleed{height:min(90svh,54rem);min-height:28rem}
/* No gradient: ::before is suppressed. */
.el-hero--full-bleed::before{content:none}
/* Dark veil anchored at the bottom so all copy reads on the photograph.
   Height 80% so the crumb — topmost element — sits in a genuinely dark zone.
   Gradient stays opaque (≥0.72) through the first 55% from the bottom where all
   three text elements land, then fades to transparent in the upper quarter.
   Minimum veil alpha at each element's worst pixel (topmost):
     fact  (bottom zone)  α≈0.95  → bg dark enough for 4.5:1 at .72 opacity text
     h1    (mid zone)     α≈0.75  → clears 4.5:1 for fully-opaque paper text
     crumb (upper zone)  α≈0.72  → clears 4.5:1 for fully-opaque paper text
   Calibrated against the measured photo luminance (rooftop sky, L≈0.47). */
.el-hero--full-bleed::after{content:"";position:absolute;inset-inline:0;bottom:0;
  height:80%;z-index:-1;
  background:linear-gradient(to top,
    rgba(21,23,27,.95) 0%,
    rgba(21,23,27,.88) 20%,
    rgba(21,23,27,.78) 40%,
    rgba(21,23,27,.72) 55%,
    rgba(21,23,27,.18) 80%,
    transparent 100%)}
/* Anchor the image: pool-08 has the vessel centre-frame, sky above. Keep
   the horizon up; object-position 50% 55% shows vessel + curved soffit. */
.el-hero--full-bleed img{object-position:50% 55%}
/* Copy overlays the dark veil — inverted palette */
.el-hero--full-bleed .el-hero__copy--overlay{color:var(--paper)}
.el-hero--full-bleed .el-hero__copy--overlay h1{color:var(--paper)}
/* Crumb back in paper on the dark field.
   Scoped to .el-hero--full-bleed to win the cascade over the base .el-back rule
   (which appears later in this file and would otherwise override the modifier). */
.el-hero--full-bleed .el-back--light{color:var(--paper)}
.el-hero--full-bleed .el-back--light:hover,
.el-hero--full-bleed .el-back--light:focus-visible{color:var(--paper)}
/* The audacious fact — the one sentence the pool IS */
.el-hero__fact{margin-top:.55em;font-family:var(--font-mono);font-size:var(--text-label);
  text-transform:uppercase;letter-spacing:.14em;color:rgba(250,248,244,.72);
  max-width:52ch;line-height:1.6}

/* /glazing — high-key, light and open. The drone shot shows the folded white
   roof planes from above. The page should feel lighter than shell and pool,
   contrasting the structural weight that follows — so this carries the thinnest
   scrim of any photographic hero here (65% vs the 72% default, 86% on shell).

   object-position is NOT a contrast lever on this hero, so do not reach for it:
   the poster is 1440x809 and the hero box is 1440x736 at desktop, which leaves
   0px of horizontal pan and 73px of vertical pan. Measured across 50% 0% →
   50% 100% and 0%/100% on x, the crumb never moves off 1.0:1 — the white mass
   is upper-RIGHT and the copy is lower-LEFT, over palm shadow that samples at
   literal rgb(0,0,0). The scrim is the only lever. */
.el-hero--high-key img{object-position:50% 15%}
/* Scrim depth is set by the crumb, not the title. Over black, the alpha each
   element needs to clear 4.5:1 was measured at 1440x900:
     h1    (--ink #15171B, 8.8–21.9% up)   needs α ≥ 0.513
     crumb (--copper-ink #8A5626, →26.4%)  needs α ≥ 0.890
   The crumb is the binding constraint and it is not close: copper-ink tops out
   at 5.75:1 on FULL paper, so it needs a near-opaque ground, and alpha only
   falls as you go up. Hence the near-opaque plateau (≥0.96) held to 56% of the
   gradient box before the fade to transparent begins.

   Calibrate against a SHORT viewport, not a tall one. The copy is bottom-
   anchored with fixed padding, so a shorter hero pushes the crumb to a higher
   FRACTION of the gradient box, where alpha is lower. 1366x768 gives a 629px
   hero and is the worst case in the ladder 1920/1440/1366/1024/768/390 — an
   earlier .94-to-44% version measured a comfortable 5.18:1 at 1440x900 and a
   hair-thin 4.51:1 here. Worst case now: crumb 5.42:1, h1 16.23:1. */
.el-hero--high-key::before{height:65%;
  background:linear-gradient(to top,var(--paper) 0%,rgba(250,248,244,.98) 40%,rgba(250,248,244,.96) 56%,rgba(250,248,244,.36) 78%,transparent 100%)}

/* /systems — data-first. No image. Ink ground, paper type.
   The page's argument is density; leading with infrastructure prose rather
   than a photograph is the correct register for an infrastructure page.
   The hero IS the register — colour-inverted, full width, spare. */
.el-hero--data{
  height:auto;min-height:0;
  background:var(--ink);
  /* No image, no pseudo gradient. */
  overflow:visible;
}
.el-hero--data::before{content:none}
.el-hero__copy--data{
  padding:clamp(3rem,2rem + 5vw,7rem) var(--gutter) clamp(2.5rem,1.5rem + 4vw,5.5rem);
  max-width:78rem;margin-inline:auto;width:100%;
}
.el-hero--data h1{color:var(--paper);font-size:clamp(2.5rem,1.4rem + 5vw,6rem);font-weight:600;letter-spacing:-.02em;margin:.1em 0 0}
/* The hook — a single infrastructure claim, set in mono under the title. */
.el-hero__hook{margin-top:clamp(.75rem,.5rem + 1vw,1.5rem);
  font-family:var(--font-mono);font-size:var(--text-label);
  text-transform:uppercase;letter-spacing:.14em;
  color:rgba(250,248,244,.55);max-width:52ch;line-height:1.6}
/* Crumb in a readable but muted paper on the dark ground */
.el-hero--data .el-back--light{color:rgba(250,248,244,.55)}
.el-hero--data .el-back--light:hover,
.el-hero--data .el-back--light:focus-visible{color:var(--paper)}

/* /shell — mass and sequence. Tallest, heaviest opening.
   The aerial at construction stage shows the full constrained footprint —
   buildings hard against both sides, the blue tarp on the concrete shell.
   Image anchors MID-LOW so the building mass occupies the lower two-thirds.
   The gradient runs deeper and the copy sits in denser parchment than any
   other page. The extra height (96svh / 62rem) makes the opening feel like
   the building is filling the screen before you scroll. */
.el-hero--shell{height:min(96svh,62rem);min-height:32rem}
.el-hero--shell img{object-position:50% 58%}
/* Deep gradient — the title reads against near-paper at the base.
   Compared to the default (height 82%, stops at 0/30/58/100%):
   this runs taller and the mid stops are more opaque — heavier. */
.el-hero--shell::before{height:86%;
  background:linear-gradient(to top,var(--paper) 0%,rgba(250,248,244,.99) 24%,rgba(250,248,244,.82) 46%,rgba(250,248,244,.3) 70%,transparent 100%)}

/* ---------------------------------------------------------------- */

/* ---------------- film hero (/stair) ----------------
   The stair film is 9:16, shot on a phone. Cover-cropping it into the wide
   still-hero band would show about a third of each frame and cut the top and
   bottom off the stair — the one thing the film is of. So the film keeps its
   own aspect and the title sits beside it: edge to edge, no letterbox bars,
   nothing of the subject lost. Below 60rem it stacks and the film fills the
   width, which is the shape it was shot in. */
.el-hero--film{height:auto;min-height:0;display:block;overflow:visible;
  background:var(--paper-2);border-bottom:1px solid var(--rule)}
.el-hero--film::before{content:none}
.el-hero__film{position:relative;display:grid;place-items:center;background:var(--ink)}
/* Portrait hero. Deliberately NOT the film variant's absolute fill: that relies on
   the column having a definite height, and when it does not the image collapses to
   zero (measured 901x0 on /leslie). Here the image sizes itself and the column
   sizes to the image, capped so it cannot run past the viewport. Paper behind it,
   not ink — it is a photograph of a person, not a film still. */
.el-hero--portrait .el-hero__film{display:grid;place-items:center;position:static;
  height:auto;background:var(--paper-2);padding:var(--sp-md) 0}
.el-hero--portrait .el-film{position:static;display:block;
  width:auto;max-width:100%;height:auto;max-height:min(78svh,44rem);
  object-fit:contain;margin:0 auto}
.el-film{display:block;width:100%;height:auto}
.el-hero--film .el-hero__copy{padding:var(--sp-lg) var(--gutter)}
.el-hero__filmcap{margin-top:var(--sp-sm);max-width:46ch;
  font-size:var(--text-caption);color:var(--muted);line-height:1.55}

/* The film autoplays muted, so a visible control is not optional: a looping
   video the visitor cannot stop is a nuisance and an accessibility failure. */
.el-film__toggle{position:absolute;right:var(--sp-sm);bottom:var(--sp-sm);
  font-family:var(--font-mono);font-size:var(--text-label);text-transform:uppercase;
  letter-spacing:.14em;color:var(--paper);background:rgba(21,23,27,.55);
  border:1px solid rgba(250,248,244,.35);border-radius:2px;
  padding:.5em .9em;cursor:pointer;backdrop-filter:blur(6px)}
.el-film__toggle:hover,.el-film__toggle:focus-visible{background:rgba(21,23,27,.85)}

@media (min-width:60rem){
  .el-hero--film{display:grid;grid-template-columns:minmax(0,44%) minmax(0,1fr);
    align-items:stretch;height:min(94svh,58rem)}
  .el-hero--portrait{height:auto;align-items:center}
  /* block + absolute, NOT a centred grid: a centred grid item is not stretched,
     so height:100% has no definite height to resolve against and the 9:16 film
     overflows its column at its natural aspect (measured 634x1126 in an 846px
     hero). Absolute positioning gives the crop a definite box. */
  .el-hero__film{display:block;position:relative;height:100%;overflow:clip}
  /* the column is already close to 9:16, so this crop is slight */
  /* SCOPED to the hero. Unscoped, this matched every .el-film on the page - including
     the films inside .film-band__stage, whose own rule overrides display/width/height
     but never position. position:absolute leaked through, those videos left the flow,
     their stages collapsed to zero height, and consecutive film bands rendered on top
     of one another. Reported from a desktop screenshot of /es/toshi with two clips
     overlapping and a title sitting over the wrong film. */
  .el-hero__film .el-film{position:absolute;inset:0;width:100%;height:100%;
    object-fit:cover;object-position:50% 50%}
  /* contain, not cover: the column is 44% of the viewport and these frames are 3:4,
     so covering would crop a head or a foot. Override the film variant's absolute
     fill here too. */
  .el-hero--portrait .el-hero__film{position:static;height:auto;align-self:center}
  .el-hero--portrait .el-film{position:static;width:auto;max-width:100%;
    height:auto;max-height:min(82svh,48rem);object-fit:contain}
  .el-hero--film .el-hero__copy{align-self:end;max-width:none;margin:0;
    padding:var(--sp-lg) var(--sp-xl) var(--sp-xl) var(--sp-lg)}
}

/* breadcrumb back to the spine — the only navigation on a sub-page */
.el-back{display:inline-block;font-family:var(--font-mono);font-weight:500;
  font-size:var(--text-label);text-transform:uppercase;letter-spacing:.16em;
  color:var(--copper-ink);text-decoration:none;margin-bottom:.4em}
.el-back:hover,.el-back:focus-visible{color:var(--ink)}
/* 44px where the pointer is a thumb. Measured at 390x844: this rendered 16px
   tall — and since Task 2 it is not just a breadcrumb but the way back to the
   exact chapter the reader came from, on every one of the 52 sub-pages. The
   comment above already calls it "the only navigation on a sub-page"; a 16px
   target is not that. Gated on pointer:coarse so the desktop breadcrumb keeps
   its tight setting, matching how .rail and .sitenav hold the same floor.

   Width OR coarse pointer, not coarse alone: pointer:coarse is a hint the UA
   may not report — it read false on an emulated 390x844 touch viewport while
   testing this — so the width clause is the one that is guaranteed to fire on
   a phone, and .sitenav already holds its own 44px floor at this same 40rem
   breakpoint. The pointer clause then picks up touch tablets above it. */
@media (max-width:40rem), (pointer:coarse){
  .el-back{display:inline-flex;align-items:center;min-height:44px;margin-bottom:0}
}

/* ---------------- lede ---------------- */
.el-lede{max-width:78rem;margin:0 auto;padding:var(--sp-xl) var(--gutter) 0}
.el-lede p{font-family:var(--font-display);font-weight:400;
  font-size:var(--text-display);line-height:1.45;color:var(--ink);
  max-width:34ch;letter-spacing:-.004em}

/* ---------------- spec block ----------------
   A measurement register, not a table. Hairline rows, mono, tabular figures.
   .is-attested marks values sourced to the builder rather than a document. */
.el-spec{max-width:78rem;margin:var(--sp-xl) auto 0;padding:0 var(--gutter)}
.el-spec dl{margin:0;border-top:1px solid var(--rule)}
.el-spec div{display:grid;grid-template-columns:1fr;gap:.15rem;
  padding:var(--sp-sm) 0;border-bottom:1px solid var(--paper-3)}
.el-spec dt{font-family:var(--font-mono);font-weight:500;font-size:var(--text-label);
  text-transform:uppercase;letter-spacing:.14em;color:var(--muted)}
.el-spec dd{margin:0;font-family:var(--font-mono);color:var(--ink);
  font-variant-numeric:tabular-nums;max-width:56ch}
@media (min-width:48rem){
  .el-spec div{grid-template-columns:minmax(10rem,18rem) minmax(0,1fr);gap:var(--sp-md);align-items:baseline}
}
.el-spec__note{margin-top:var(--sp-md);font-size:var(--text-caption);color:var(--muted);max-width:60ch}
.is-attested::after{content:"·  builder-attested";font-size:.72em;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);margin-left:.75em;white-space:nowrap}

/* ---------------- close + ADC mark ---------------- */
.el-close{max-width:78rem;margin:var(--sp-2xl) auto 0;padding:var(--sp-lg) var(--gutter) var(--sp-xl);
  border-top:1px solid var(--rule);display:grid;gap:var(--sp-md);align-items:center}
.el-close__mark{width:clamp(7rem,14vw,9.5rem);height:auto;opacity:.9}
.el-close__built{font-size:var(--text-caption);color:var(--muted);max-width:44ch}
@media (min-width:48rem){
  .el-close{grid-template-columns:auto 1fr auto;gap:var(--sp-lg)}
  .el-close__return{justify-self:end}
}

/* ---------------- INDEX (The Elements / The People) ----------------
   NOT a card grid. A uniform grid of identical crops is the template look the
   whole site is trying to avoid — and with five items in three columns it also
   orphans two. This is a monograph plate-list instead: a numbered rule-separated
   index, full width, that reads down and scales to any count. */

.elements{border-top:1px solid var(--rule);padding:var(--sp-xl) var(--gutter) var(--sp-2xl)}
.elements__head{max-width:78rem;margin:0 auto var(--sp-lg)}
.elements__grid{max-width:78rem;margin:0 auto;counter-reset:idx;
  border-top:1px solid var(--ink)}

.element-card{counter-increment:idx;display:grid;gap:var(--sp-sm) var(--sp-md);
  grid-template-columns:auto 1fr;grid-template-areas:"num name" "num hook" "img img";
  align-items:start;padding:var(--sp-lg) 0;border-bottom:1px solid var(--paper-3);
  text-decoration:none;color:inherit;position:relative}
.element-card::before{content:counter(idx,decimal-leading-zero);grid-area:num;
  font-family:var(--font-display);font-weight:400;
  font-size:clamp(1.5rem,1.1rem + 1.6vw,2.6rem);line-height:1;color:var(--copper-ink);
  font-variant-numeric:tabular-nums lining-nums;padding-top:.1em;min-width:2.4ch}
.element-card__name{grid-area:name;font-family:var(--font-display);
  font-weight:400;
  font-size:clamp(1.9rem,1.2rem + 3.4vw,4.25rem);line-height:1;
  color:var(--ink);letter-spacing:-.022em;margin:0}
.element-card__hook{grid-area:hook;font-size:var(--text-caption);color:var(--ink-2);
  max-width:46ch;line-height:1.6;margin:0}
.element-card__spec{display:block;margin-top:.85em;font-family:var(--font-mono);
  font-weight:500;font-size:var(--text-label);text-transform:uppercase;
  letter-spacing:.16em;color:var(--copper-ink);font-variant-numeric:tabular-nums}
.element-card picture{grid-area:img;display:block;overflow:clip;margin-top:var(--sp-sm)}
/* `height:auto` is load-bearing, not tidiness. Every <img> here carries width and
   height attributes, which map to a presentational `height:1012px`. CSS
   `aspect-ratio` is ignored whenever height is anything but auto — so without
   this the card box became 347x1012 on a phone and object-fit:cover blew a 16:9
   aerial up ~4.6x to crop a narrow vertical sliver out of the middle of it.
   Any rule that sets aspect-ratio on one of these images must set height:auto too. */
.element-card img{width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;background:var(--paper-3);
  transition:transform 700ms var(--ease-out-expo),filter 700ms var(--ease-out-expo)}

/* People, not buildings: a 16:9 cut through a photograph of a group lands on
   torsos at 50%. Lifting the window keeps faces in the frame. */
.people .element-card img{object-position:50% 35%}

/* Mark cards — the architect, the builder, the photographer. These three are
   practices, not people, so the card carries an identity mark on a neutral
   panel instead of a photograph. Same box, same rhythm as the rest of the list.
   SOOP and Kahu Visionworks are set typographically rather than as logo files:
   neither mark is in this repo, and republishing another firm's logo is theirs
   to approve, not ours to assume. */
.mark-plate{grid-area:img;display:grid;place-items:center;margin-top:var(--sp-sm);
  aspect-ratio:16/9;background:var(--paper-2);
  border:1px solid var(--paper-3);padding:var(--sp-md)}
/* min-height:0 on the item, or the logo's intrinsic size becomes the grid's
   automatic minimum and the panel grows past its 16:9 box — measured 347x214
   against the 347x195 the wordmark panels sit at, so the three cards no longer
   lined up. */
.mark-plate>*{min-height:0;min-width:0}
/* Scoped to .element-card on purpose: `.element-card img` is (0,1,1) and would
   otherwise win, forcing the logo to width:100% / aspect-ratio:16/9 /
   object-fit:cover — which cropped the wordmark to "ACADE / DEVELOPMENT CO". */
/* The mark is close to square, so bound it by HEIGHT — bounding by width put a
   774px-tall logo into a 143px-tall panel. */
/* background:none is the point. `.element-card img` sets background:var(--paper-3)
   as a letterbox fill for photographs — behind a transparent logo that painted a
   visible #E7E0D4 rectangle on the #F2EDE4 panel. The logo is transparent; the
   BOX around it was the element's own background, not the file. */
.element-card .mark-plate__logo{height:min(78%,8rem);width:auto;max-width:80%;
  aspect-ratio:auto;object-fit:contain;background:none;opacity:.92}
.mark-plate__word{font-family:var(--font-display);font-weight:400;
  font-size:clamp(1.5rem,1rem + 2.4vw,2.6rem);line-height:1;color:var(--ink);
  letter-spacing:.16em;text-align:center}
.mark-plate__word small{display:block;margin-top:.9em;font-family:var(--font-mono);
  font-size:var(--text-label);letter-spacing:.2em;text-transform:uppercase;
  color:var(--muted)}
.element-card:hover .mark-plate,
.element-card:focus-visible .mark-plate{background:var(--paper-3)}
.mark-plate,.mark-plate__logo{transition:background var(--dur-normal) linear,
  opacity var(--dur-normal) linear}
@media (min-width:56rem){
  .mark-plate{margin-top:0;align-self:stretch;aspect-ratio:auto;min-height:9rem}
}
@media (prefers-reduced-motion: reduce){ .mark-plate,.mark-plate__logo{transition:none} }

@media (min-width:56rem){
  /* the image moves into its own column and the row reads as one line of a list */
  .element-card{grid-template-columns:auto minmax(0,1fr) minmax(11rem,20rem);
    grid-template-areas:"num name img" "num hook img";
    gap:var(--sp-sm) var(--sp-lg);align-items:center}
  .element-card picture{margin-top:0;align-self:stretch}
  .element-card img{height:100%;aspect-ratio:auto;min-height:9rem}
}

.element-card:hover img,.element-card:focus-visible img{transform:scale(1.04)}
.element-card:hover .element-card__name,
.element-card:focus-visible .element-card__name{color:var(--copper-ink)}
@media (prefers-reduced-motion: reduce){ .element-card img{transition:none} }

/* ---------------- THE OWNERS ---------------- */
.owners{border-top:1px solid var(--rule);padding:var(--sp-xl) var(--gutter) var(--sp-2xl)}
.owners__grid{max-width:78rem;margin:0 auto;display:grid;gap:var(--sp-lg);align-items:start}
.owners__portrait{margin:0}
.owners__portrait img{width:100%;height:auto;background:var(--paper-3)}
.owners__portrait figcaption{margin-top:var(--sp-sm);font-size:var(--text-caption);
  color:var(--muted);max-width:34ch}
.owners__name{font-family:var(--font-display);font-size:var(--text-section);
  font-weight:500;color:var(--ink);
  letter-spacing:-.018em;margin:0 0 var(--sp-md);max-width:12ch}
.owners__body p{margin-bottom:.9em;color:var(--ink-2);max-width:52ch}
.owners__kicker{font-family:var(--font-display);font-style:italic;font-weight:400;
  font-size:var(--text-display);line-height:1.4;color:var(--ink);
  max-width:26ch;letter-spacing:-.005em;margin-top:var(--sp-md)!important}
@media (min-width:60rem){
  .owners__grid{grid-template-columns:minmax(0,22rem) minmax(0,1fr);gap:var(--sp-xl)}
}

/* ---------------- persistent ADC corner mark ----------------
   Constant, never competing. Sits above the paper, below any focus ring, and
   is hidden on short viewports where it would collide with content. */
.adc-corner{position:fixed;right:clamp(.75rem,2vw,1.5rem);bottom:clamp(.75rem,2vw,1.5rem);
  z-index:20;opacity:.42;pointer-events:auto;transition:opacity var(--dur-fast) linear}
.adc-corner:hover,.adc-corner:focus-visible{opacity:.9}
.adc-corner img{width:clamp(4.25rem,7vw,5.75rem);height:auto;display:block}
@media (max-height:30rem){ .adc-corner{display:none} }
@media print{ .adc-corner{display:none} }

/* No verified portrait on file — the owners section runs as a single column so
   the absence reads as deliberate rather than as a missing image. Remove this
   rule and restore the two-column grid once a confirmed photograph exists. */
.owners__grid--noportrait{grid-template-columns:minmax(0,1fr)!important;max-width:62rem}
.owners__grid--noportrait .owners__name{max-width:18ch}

/* ---------------- CONTACT (GHL embed) ----------------
   The form is a GoHighLevel iframe so the workflows bound to it keep firing —
   a hand-rolled form posting to a webhook would bypass them. The surround is
   ours; the iframe is given paper to sit on rather than being dropped in raw. */
.contact{border-top:1px solid var(--rule);background:var(--paper-2);
  padding:var(--sp-xl) var(--gutter) var(--sp-2xl)}
.contact__grid{max-width:78rem;margin:0 auto;display:grid;gap:var(--sp-lg);align-items:start}
.contact__title{max-width:14ch}
.contact__lede{margin-top:var(--sp-md);color:var(--ink-2);max-width:44ch}
.contact__meta{margin-top:var(--sp-lg);padding-top:var(--sp-md);
  border-top:1px solid var(--paper-3);font-size:var(--text-caption);color:var(--muted);max-width:40ch}
.contact__frame{background:var(--paper);border:1px solid var(--paper-3);min-height:44rem}
.contact__frame iframe{width:100%;min-height:44rem;border:0;display:block}
@media (min-width:64rem){
  .contact__grid{grid-template-columns:minmax(0,22rem) minmax(0,1fr);gap:var(--sp-xl)}
}

/* ---------------- spec variants ----------------
   el-spec--dense: /systems. The spec IS the content — full column, tighter
   rows, ink-ground paper-2 background so it reads as a register, not a sidebar.
   Loaded only when specClass "el-spec--dense" is set in elements.json. */
.el-spec--dense {
  background: var(--paper-2);
  border-block: 1px solid var(--rule);
  margin-inline: 0;
  max-width: none;
  padding: var(--sp-xl) var(--gutter);
}
.el-spec--dense dl {
  max-width: 78rem;
  margin: 0 auto;
}
.el-spec--dense .el-spec__note {
  max-width: 78rem;
  margin: var(--sp-md) auto 0;
}
/* Tighter row padding — this is a dense register, not a spaced list. */
.el-spec--dense div {
  padding: .6rem 0;
}
@media (min-width: 48rem) {
  .el-spec--dense div {
    grid-template-columns: minmax(14rem, 22rem) minmax(0, 1fr);
  }
}

/* work--continued: /shell seq-split second half.
   No repeated label/title — the reader is already in the sequence. A
   hairline continues the rhythm without re-heading the section. */
.work--continued {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* ---------------- SYSTEMS emphasis ----------------
   Three headline systems get their own weight rather than sitting as rows in
   the spec list. Used on /systems via bodyHtml. */
.sys-tri{max-width:78rem;margin:var(--sp-xl) auto 0;padding:0 var(--gutter);
  display:grid;gap:var(--sp-lg)}
@media (min-width:56rem){ .sys-tri{grid-template-columns:repeat(3,1fr);gap:var(--sp-lg)} }
.sys-card{border-top:2px solid var(--copper-ink);padding-top:var(--sp-md)}
.sys-card h3{font-size:clamp(1.35rem,1.1rem + 1vw,2rem);margin-bottom:.45em;
  }
.sys-card p{color:var(--ink-2);max-width:38ch}
.sys-card__fig{display:block;font-family:var(--font-display);font-style:normal;
  font-weight:600;
  font-size:clamp(2.75rem,2rem + 3.5vw,4.5rem);line-height:.95;
  color:var(--copper);opacity:.55;margin-bottom:.1em;font-variant-numeric:tabular-nums}
.sys-card__unit{display:block;font-family:var(--font-mono);font-weight:500;
  font-size:var(--text-label);text-transform:uppercase;letter-spacing:.14em;
  color:var(--muted);margin-top:.9em}

/* ---------------- TRIBUTE ----------------
   A first-person account from the people who were on the job. Set on the paper-2
   stock so it reads as a held aside inside the document rather than another
   section, and at display size because it is the most human copy on the site. */
.tribute{background:var(--paper-2);border-block:1px solid var(--rule);
  padding:var(--sp-xl) var(--gutter)}
.tribute__inner{max-width:46rem;margin:0 auto}
.tribute__inner .overline{margin-bottom:var(--sp-sm)}
.tribute__quote{margin:0;padding:0;border:0}
.tribute__quote p{font-family:var(--font-display);font-weight:400;
  font-size:var(--text-display);line-height:1.5;color:var(--ink);
  max-width:38ch;margin:0 0 .6em;letter-spacing:-.004em}
.tribute__quote p:first-of-type::before{content:"\201C";
  color:var(--copper-ink);margin-left:-.42em}
.tribute__quote p:last-of-type::after{content:"\201D";color:var(--copper-ink)}
.tribute__quote cite{display:block;margin-top:var(--sp-md);font-style:normal;
  font-family:var(--font-mono);font-size:var(--text-label);text-transform:uppercase;
  letter-spacing:.18em;color:var(--muted-2)}

/* ---------------- FILM BAND (a film in the body, not the hero) ---------------- */
.film-band{margin:var(--sp-2xl) 0;background:var(--paper-2);
  border-block:1px solid var(--rule);padding:var(--sp-xl) 0 var(--sp-lg)}
.film-band__head{max-width:78rem;margin:0 auto var(--sp-lg);padding:0 var(--gutter)}
.film-band__title{font-size:var(--text-section);max-width:16ch;margin:.1em 0 0}
/* width:fit-content so the ink field HUGS the film. Held at a fixed column width it
   was 544px wide around a 253px portrait clip, and the bars either side read as
   letterboxing rather than as a frame. Now the dark ground is the film's own edge. */
.film-band__stage{position:relative;display:flex;justify-content:center;
  width:fit-content;margin-inline:auto;background:var(--ink)}
/* Explicit position:static is load-bearing, not redundancy: a hero rule once leaked
   position:absolute onto these and collapsed every band. State the geometry here so
   the component cannot be un-flowed from a distance.
   max-height caps a clip at roughly one screen - a 9:16 film in a 34rem column runs
   ~960px tall, and four of them consecutively on /systems read as a wall. */
/* PORTRAIT is the default here: most films on this site are 9:16 phone clips.
   aspect-ratio, not width:auto - these carry preload="none", so videoWidth is 0 until
   a clip is actually played and the element has NO intrinsic size to lay out from.
   Sizing from `auto` therefore collapsed every film to one arbitrary shape, landscape
   included. Declaring the ratio makes the box correct before a single byte loads.
   height:auto is mandatory alongside it - the w/h attributes are a presentational
   height and aspect-ratio is ignored without it (assets/css/element.css:144). */
.film-band__stage .el-film{position:static;inset:auto;display:block;
  width:auto;height:auto;aspect-ratio:9/16;
  max-width:100%;max-height:min(78svh,44rem);margin-inline:auto}
/* Landscape films state their own ratio and take the width. */
/* No max-height on the landscape variant: the stage is already held to 78rem, so a
   16:9 clip resolves to about 1248x702 and needs no cap. Capping height while width
   is 100% squeezed the box to 3.09:1 and object-fit:cover then cropped the top and
   bottom out of the frame. */
.film-band--wide .film-band__stage .el-film{aspect-ratio:16/9;width:100%;
  height:auto;max-height:none}
.film-band__cap{margin:var(--sp-md) auto 0;padding:0 var(--gutter);
  font-size:var(--text-caption);color:var(--muted);line-height:1.55;max-width:46rem}
@media (min-width:60rem){
  /* 9:16 at full width is absurdly tall on desktop — hold it to a column. */
  .film-band__stage{max-width:34rem}
  /* Align the caption's left edge with the 78rem content column, using MARGIN.
     This was padding, and padding is fatal here: with border-box, max-width caps
     the border box, so once the two paddings exceed 46rem the content box has
     nowhere to go and collapses to zero — the text then wraps one word per line
     in a 42-line column. It grew with the viewport, so it was invisible up to
     about 1824px and unmissable on any wide desktop. Margin cannot eat the
     content box in either box model, and max() keeps the small end sane. */
  .film-band__cap{padding-inline:0;
    margin-left:max(var(--gutter), calc((100% - 78rem)/2 + var(--gutter)));
    margin-right:var(--gutter)}
}

/* Landscape film band. Every other film on the site is a 9:16 phone clip that has
   to be held narrow or it dominates the page; a 16:9 piece is the opposite — it
   needs the width to read. Same component, one modifier. */
.film-band--wide .film-band__stage{max-width:none;background:var(--ink)}
@media (min-width:60rem){
  .film-band--wide .film-band__stage{max-width:78rem;margin-inline:auto}
}

/* ---------------- SUBCONTRACTOR CREDIT ----------------
   A named trade gets a block, not a footnote. Same paper-2 ground as the film
   bands so it reads as part of the page's structure rather than an ad. */
.sub-credit{border-top:1px solid var(--rule);background:var(--paper-2);
  padding:var(--sp-xl) var(--gutter)}
.sub-credit__inner{max-width:78rem;margin:0 auto;display:grid;gap:var(--sp-md)}
.sub-credit__name{font-size:var(--text-section);margin:.1em 0 0;max-width:14ch}
.sub-credit__lede{color:var(--ink);font-family:var(--font-display);
  font-size:var(--text-display);line-height:1.45;max-width:46ch}
.sub-credit__body{color:var(--ink-2);max-width:56ch}
@media (min-width:60rem){
  .sub-credit__inner{grid-template-columns:minmax(0,22rem) minmax(0,1fr);
    column-gap:var(--sp-2xl);align-items:start}
  .sub-credit__name{grid-column:1}
  .sub-credit__lede,.sub-credit__body{grid-column:2}
  .sub-credit .overline{grid-column:1}
}

/* ============================================================
   PEOPLE FILMSTRIP — #people only.
   All selectors are prefixed with #people so the identical
   .elements__grid and .element-card rules on #elements remain
   completely untouched.

   DEVICE 1 from 2026-08-08-interaction-upgrade.md:
   Horizontal portrait filmstrip, Fort Vega "KEY PEOPLE" reference.
   Portrait crops come in a later step; this layout works correctly
   with the current landscape images — it just sets a fixed aspect
   on the image box without distorting anything.
   ============================================================ */

/* ---- Section chrome ---- */
#people, #elements{
  /* Remove the gutter-constrained padding that the .elements rule sets;
     the filmstrip row needs to run edge-to-edge of the viewport. The
     heading stays guttered via .elements__head. */
  padding-bottom:var(--sp-2xl);
}

/* ---- Row ---- */
#people .elements__grid, #elements .elements__grid{
  /* Filmstrip: flex, not grid. Full viewport width, scrolls off the right
     edge — that overflow IS the affordance. counter-reset on the base rule
     still fires; we suppress the generated content below. */
  display:flex;
  flex-direction:row;
  /* No max-width — runs wall-to-wall so cards visibly bleed right. */
  max-width:none;
  /* Left gutter aligns the first card with the section heading. */
  padding-inline:var(--gutter);
  padding-bottom:var(--sp-md);   /* room for the scrollbar on desktop */
  gap:clamp(.875rem,.6rem + 1.25vw,1.5rem);
  overflow-x:auto;
  /* Momentum scrolling on iOS Safari. */
  -webkit-overflow-scrolling:touch;
  scroll-snap-type:x mandatory;
  /* Right padding so the last card does not sit flush against the edge
     and visitors can see there is nothing more. */
  padding-right:var(--gutter);
  /* A thin visible scrollbar is the desktop affordance.
     We tint it to the copper palette rather than hiding it. */
  scrollbar-width:thin;
  scrollbar-color:var(--copper-ink) var(--paper-3);
  /* border-top from the base rule stays — keeps the section ruled. */
}

/* WebKit scrollbar tint — mirrors the scrollbar-color above. */
#people .elements__grid::-webkit-scrollbar{height:.35rem}
#people .elements__grid::-webkit-scrollbar-track{background:var(--paper-3)}
#people .elements__grid::-webkit-scrollbar-thumb, #elements .elements__grid::-webkit-scrollbar-thumb{
  background:var(--copper-ink);border-radius:0;opacity:.6}

/* ---- Card ---- */
#people .element-card, #elements .element-card{
  /* Column, not grid. Image on top; name + hook beneath. */
  display:flex;
  flex-direction:column;
  gap:0;
  /* Fixed width — wide enough to read, narrow enough to signal overflow. */
  flex:0 0 clamp(15rem,62vw,22rem);
  width:clamp(15rem,62vw,22rem);
  /* Override the base grid template areas so they have no effect. */
  grid-template-areas:none;
  grid-template-columns:none;
  /* Snap the leading edge of each card. */
  scroll-snap-align:start;
  /* Reset base rule padding — card stacks vertically, no top/bottom space. */
  padding:0;
  border-bottom:none;
  /* Separate cards visually with a right rule instead of the bottom rule. */
  border-right:none;
  /* Keyboard: already a real <a>, so tab-reachable. No extra work needed. */
  position:relative;
  /* Keep hover lift from the base rule. */
}

/* Kill the CSS counter numeral — the column layout has no place for it
   as a sidebar, and a large numeral over the image reads as decoration,
   not navigation. The name already identifies each card. */
#people .element-card::before{content:none}

/* ---- Image box ---- */
/* ⚠️ THE TRAP: every <img> carries width/height attributes → presentational
   height. aspect-ratio is IGNORED unless height:auto is also set. Setting
   only aspect-ratio without height:auto caused a 347x1012 card box on a
   phone with object-fit:cover cropping a vertical sliver. BOTH rules are
   required together. See the comment at line 144 of this file. */
#people .element-card picture, #elements .element-card picture{
  display:block;
  overflow:clip;
  /* Override grid-area:img — meaningless in a flex column. */
  grid-area:auto;
  margin-top:0;
  /* Let the picture element grow to fill the card width. */
  width:100%;
}
#people .element-card img:not(.mark-plate__logo), #elements .element-card img:not(.mark-plate__logo){
  width:100%;
  height:auto;           /* load-bearing — see trap note above */
  aspect-ratio:3/4;      /* portrait frame; landscape images fill with cover */
  object-fit:cover;
  object-position:50% 35%; /* inherited from .people rule; faces stay in frame */
  /* Transition from base rule stays. */
}

/* ---- Mark-plate cards (architect, builder, photographer) ----
   These three have no photograph: a neutral identity panel sits in the
   image slot. Inherit the portrait frame for visual rhythm. */
#people .mark-plate, #elements .mark-plate{
  grid-area:auto;
  margin-top:0;
  aspect-ratio:3/4;
  min-height:0;          /* override the 56rem media query min-height:9rem */
  /* width fills the card naturally as a flex child */
  width:100%;
  align-self:auto;
}
/* At 56rem+ the base rule set align-self:stretch on .element-card picture
   and height:100% on the img. Override both for the filmstrip context. */
@media (min-width:56rem){
  #people .element-card picture{margin-top:0}
  /* :not(.mark-plate__logo) is load-bearing, not tidiness.
     `#people .element-card img` is (1,1,1) and an id outranks the two classes in
     `.element-card .mark-plate__logo` (0,2,0), so this rule was also capturing the
     LOGO — forcing height:auto and aspect-ratio:3/4 onto a 900x774 mark. With
     width:auto that resolves to about 900x1200 inside a ~350px plate, which then
     clips it to its middle slice: "ACADEMIA" shipped to production reading "ЗADEM".
     A portrait frame is for photographs. A logo is bounded by height and CONTAINED,
     never cropped. */
  #people .element-card img:not(.mark-plate__logo){height:auto;aspect-ratio:3/4;min-height:0}
  #people .mark-plate{aspect-ratio:3/4;align-self:auto;min-height:0}
  /* Restated at (1,2,0) so no later id-scoped rule can quietly capture the logo again. */
  #people .element-card .mark-plate__logo{
    height:min(58%,7rem);width:auto;max-width:78%;
    aspect-ratio:auto;object-fit:contain}
}

/* ---- Text block beneath the image ---- */
#people .element-card__name, #elements .element-card__name{
  /* Override grid-area:name — meaningless in flex column context. */
  grid-area:auto;
  margin-top:var(--sp-sm);
  /* Tighter size than the list — the card is narrow. */
  font-size:clamp(1.35rem,.95rem + 1.8vw,2.25rem);
  /* Keep the rest: Garamond, color:ink, letter-spacing from base rule. */
}
#people .element-card__hook, #elements .element-card__hook{
  grid-area:auto;
  margin-top:.3em;
  /* Override max-width — cards are narrower than the full-row list items. */
  max-width:none;
}

/* ---- Hover lift — scoped so #elements cards are unaffected. ---- */
#people .element-card:hover img,
#people .element-card:focus-visible img, #elements .element-card:focus-visible img{
  transform:scale(1.04);   /* base rule value — explicit here for clarity */
}
/* ---- Hover state: card text block signals the full card is active.
   A hairline that appears under the hook line gives the card a closed
   boundary on hover without adding a box-shadow or background card,
   which would look like a component library default. The transition is
   compositor-friendly (opacity on a ::after, not layout). ---- */
#people .element-card{outline:none} /* suppress default; focus ring via :focus-visible below */
#people .element-card__hook{position:relative;padding-bottom:var(--sp-sm)}
#people .element-card__hook::after, #elements .element-card__hook::after{
  content:"";position:absolute;left:0;bottom:0;
  width:100%;height:1px;
  background:var(--copper-ink);
  opacity:0;
  transition:opacity var(--dur-fast) linear;
}
#people .element-card:hover .element-card__hook::after,
#people .element-card:focus-visible .element-card__hook::after{opacity:.55}
/* Focus ring on the whole card (not just image) — the global :focus-visible
   rule covers this, but the filmstrip card is position:relative and the
   outline-offset:3px default doesn't read well against the narrow column.
   Tighten to 0 so the ring hugs the card boundary. */
#people .element-card:focus-visible, #elements .element-card:focus-visible{
  outline:2px solid var(--copper-ink);
  outline-offset:0;
}

/* ---- Keyboard scrollability.
   The row is focusable so arrow keys scroll it when the row has focus.
   We add tabindex="0" in HTML. The outline follows the standard :focus-visible
   rule already defined in base.css. ---- */
#people .elements__grid:focus-visible, #elements .elements__grid:focus-visible{
  outline:2px solid var(--copper-ink);
  outline-offset:-2px;
}


/* ---- Desktop: filmstrip becomes a wrapped grid ----
   On touch the horizontal swipe is the natural gesture and the correct
   affordance — the strip stays exactly as it is. On a pointer device
   (mouse) the overflow is nearly invisible: the owner, who reads on a
   desktop, reported the cards as simply missing.

   min-width:60rem matches the gutter inflection already used elsewhere
   on this site. Above that threshold: overflow resets to visible, flex
   is released, and a responsive auto-fit grid takes over. The phone
   strip is completely untouched — the media query is the whole guard.

   Card width: minmax(14rem,1fr) is wide enough to show the portrait
   and the name at a glance, and auto-fit will pack as many as the row
   allows before wrapping — so on a 1512px display the ~48 people cards
   fill a comfortable grid of 5–6 columns rather than a 6-screen strip.

   gap: the same clamp the filmstrip uses, so card spacing is identical
   to the mobile experience. */
@media (min-width:60rem){
  #people .elements__grid, #elements .elements__grid{
    display:grid;
    grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));
    gap:clamp(.875rem,.6rem + 1.25vw,1.5rem);
    overflow:visible;
    /* Remove padding-right that was only needed to signal "more cards". */
    padding-right:var(--gutter);
    /* Remove padding-bottom that was only needed for the scrollbar track. */
    padding-bottom:0;
    /* Restore max-width so the grid aligns with the heading above it. */
    max-width:78rem;
    /* The scrollbar hints belong to the scroll-container only. */
    scrollbar-width:auto;
  }

  /* On desktop the card needs to flex like a real grid cell, not a
     fixed-width filmstrip column. Release the fixed width and let the
     grid column drive sizing. Portrait aspect-ratio and image rules stay
     untouched — they are set on the image, not the card. */
  #people .element-card, #elements .element-card{
    flex:none;
    width:100%;
    scroll-snap-align:none;
  }
}

/* ---- Reduced-motion: no scroll-snap animation jank. ----
   Snap itself stays (it is a layout affordance, not animation),
   but we kill any momentum-scroll overshoot animation. The global
   brake in motion.css already sets scroll-behavior:auto — this is
   belt-and-suspenders for the scroll container specifically. */
@media (prefers-reduced-motion:reduce){
  #people .elements__grid{
    scroll-behavior:auto;
  }
  #people .element-card img:not(.mark-plate__logo){
    transition:none;
  }
}

/* ---- Print: revert to a stacked list so cards do not vanish off-page. ---- */
@media print{
  #people .elements__grid{
    display:block;overflow:visible;padding:0;
  }
  #people .element-card{
    width:auto;display:block;break-inside:avoid;
    border-bottom:1px solid var(--paper-3);padding:var(--sp-sm) 0;
  }
  #people .element-card img:not(.mark-plate__logo){aspect-ratio:16/9}
}


/* ---------------------------------------------------------------------------
   THE LOGO IS NOT A PHOTOGRAPH. Last word in the file so nothing can outrank it.

   `#people .element-card img` is (1,1,1) - an id beats the two classes in
   `.element-card .mark-plate__logo` (0,2,0) - so every portrait rule in the
   filmstrip was also capturing the mark, forcing height:auto and
   aspect-ratio:3/4 onto a 900x774 logo. With width:auto that resolves to about
   900x1200 inside a ~350px plate, the plate clips it, and "ACADEMIA" ships
   reading "ЗADEM". It has now done so twice: once from the base rule and once
   from the >=56rem rule after only the desktop path was fixed.

   Fixed by excluding .mark-plate__logo from all three portrait rules AND by
   restating the logo's own sizing here at (1,2,0) with !important on the two
   properties that caused it. A photograph fills its frame and is cropped; a
   logo is bounded by height and contained. --------------------------------- */
#people .element-card .mark-plate__logo, #elements .element-card .mark-plate__logo{
  height:min(58%,7rem)!important;
  width:auto;
  max-width:78%;
  aspect-ratio:auto!important;
  object-fit:contain;
  background:none}

/* --- Adjacent pages -----------------------------------------------------
   The record was hub-and-spoke: every element and person page dead-ended back
   to the spine, so a reader following the build had to return to the index
   between each one. These carry the two chains — the build sequence and the
   people — and nothing else. Both chains are cyclic, so there is no dead end
   and no page is more than one click from its neighbours.

   Deliberately NOT cards, NOT "related", NOT a third suggested link. This is
   navigation for someone already reading, not a recommendation engine. Same
   caption register as .el-close__built above it. ------------------------- */
.el-adjacent{max-width:78rem;margin:var(--sp-xl) auto 0;padding:0 var(--gutter);
  display:flex;justify-content:space-between;align-items:baseline;
  gap:var(--sp-md);flex-wrap:wrap}
.el-adjacent__link{display:inline-flex;align-items:baseline;gap:.5em;
  color:var(--muted);text-decoration:none;
  transition:color var(--dur-fast) var(--ease-out-expo)}
.el-adjacent__link:hover,.el-adjacent__link:focus-visible{color:var(--ink)}
.el-adjacent__link--next{margin-left:auto;text-align:right}
.el-adjacent__dir{font-family:var(--font-mono);font-size:var(--text-label)}
.el-adjacent__title{font-size:var(--text-caption);
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.25em;
  text-decoration-color:var(--rule)}
.el-adjacent__link:hover .el-adjacent__title{text-decoration-color:currentColor}

/* ---------------- EXPLAINER PAGES — the depth cluster ----------------
   /hvhz /structural-glass /rooftop-pools /infill /cast-in-place
   /roof-waterproofing /owner-builder /little-havana /trades

   The answer paragraph is deliberately the largest text on the page. It is
   what a reader skims and what an answer engine extracts, so it carries
   display scale and leads — there is no separate lede, because on these pages
   the answer IS the lede and printing both would put the same sentence on
   screen twice.

   Measure is held at 44rem. NOTE for anyone tempted to align this to the wider
   content column with padding: do not. `padding-inline: calc((100% - Nrem)/2
   + gutter)` is what collapsed the film captions to one word per line on any
   display over ~1824px — with border-box, once the two paddings exceed
   max-width the content box goes to zero. Use margin. */
.explainer{padding:var(--sp-xl) 0 var(--sp-lg)}
.explainer__inner{max-width:50rem;margin-inline:auto;padding-inline:var(--gutter)}
/* Sized DOWN from --text-display. At display scale (44px at 1920) this
   paragraph ran about five words to the line inside its own measure — the type
   was fighting the column instead of leading it. It still has to be the most
   prominent text on the page, but prominence here comes from being first and
   set wider than the body, not from being enormous. */
/* The question, posed above the answer.

   These pages are named poetically — "A Pool On The Roof", "Glass That Carries
   People" — which is right for the h1 and wrong for how anyone actually types a
   search. So the question people DO ask is stated here, in the small mono
   register, and the h1 keeps the voice.

   It is deliberately quieter than the answer beneath it, not louder. The answer
   is display type at up to 1.9rem; a question set at the same weight would turn
   the page into a FAQ card and flatten the hierarchy. Asked quietly, answered
   plainly.

   The string is not authored here twice: build-elements.py renders it from the
   SAME faq[0][0] value that feeds the FAQPage JSON-LD, so the visible question
   and the structured-data question cannot drift apart. */
.explainer__inner h2.explainer__q{font-family:var(--font-mono);font-weight:500;
  font-size:var(--text-caption);line-height:1.5;letter-spacing:.01em;
  color:var(--muted);margin:0 0 var(--sp-sm);max-width:44ch;
  text-transform:none}

.explainer__answer{font-family:var(--font-display);font-weight:400;
  font-size:clamp(1.35rem,1.05rem + .95vw,1.9rem);line-height:1.4;
  letter-spacing:-.004em;color:var(--ink);margin:0 0 var(--sp-lg);max-width:38ch}

/* Documentation hero. Explainer pages reuse posters that were tuned for OTHER
   scrims — /glazing's poster expects the thin --high-key wash, /pool's expects
   the dark --full-bleed veil — so the default gradient met them badly and left
   a hard dark wedge across the frame. This is shorter and its scrim is a plain
   paper wash that behaves over any poster, because these pages are
   documentation and the photograph is context, not the argument. */
.el-hero--doc{height:min(54svh,30rem);min-height:17rem}
.el-hero--doc::before{height:100%;
  background:linear-gradient(to top,var(--paper) 0,rgba(250,248,244,.97) 7rem,
    rgba(250,248,244,.72) 12rem,rgba(250,248,244,.22) 18rem,transparent 24rem)}
.el-hero--doc h1{font-size:clamp(2rem,1.2rem + 3.2vw,3.9rem)}
.explainer__inner h2{font-size:var(--text-section);margin:var(--sp-lg) 0 .5em;max-width:24ch}
.explainer__inner h3{margin:var(--sp-md) 0 .4em}
.explainer__inner p{color:var(--ink-2);margin-bottom:.85em}
.explainer__inner p:last-child{margin-bottom:0}
/* The single attribution link out. One per page is the ceiling and the
   compliance gate enforces it — this is a legacy record, not a funnel. */
/* Related questions. The twelve explainer pages had no links between them at
   all before this — each was an island off the spine. The list is deliberately
   plain: real questions in the reader's own language, set in the mono register
   so it reads as an index rather than as a promoted-content rail. */
.related{padding:var(--sp-xl) 0 var(--sp-xl);margin-top:var(--sp-lg);
  border-top:1px solid var(--rule)}
.related__inner{max-width:50rem;margin-inline:auto;padding-inline:var(--gutter)}
.related__h{font-family:var(--font-mono);font-weight:500;font-size:var(--text-label);
  text-transform:uppercase;letter-spacing:.18em;color:var(--copper-ink);
  margin:0 0 var(--sp-sm)}
.related__list{list-style:none;margin:0;padding:0}
.related__list li{border-bottom:1px solid var(--rule)}
.related__list a{display:block;padding:.85em 0;text-decoration:none;
  font-family:var(--font-mono);font-size:var(--text-caption);line-height:1.5;
  color:var(--ink-2);transition:color var(--dur-fast,150ms) ease}
.related__list a:hover,.related__list a:focus-visible{color:var(--copper-ink)}

.explainer__built{margin-top:var(--sp-xl);padding-top:var(--sp-md);
  border-top:1px solid var(--rule);font-size:var(--text-caption);color:var(--muted)}
