/* ═══ LATVERA — PERGOLA CATEGORY PAGES (batch 08c · tasks/088) ═══
   Shared by louvered / hardtop / glass / fabric / sides pages. Extends the main
   design system (main.css tokens loaded first). Light paper, one grammar:
   hero → fact rows → image sections → mini-diamond cross-nav → door.
   Ship-guard: every page is complete static; loops layer on top. */

.pg { background: var(--stone); color: var(--graphite); }

/* ── fixed page chrome (batch 09b · L4) ──────────────────────────────────────
   The sub pages no longer carry their OWN bar. They now mount the homepage
   component verbatim — `header.doc > .doc__panel` — driven by the same
   `js/nav.js`, which was already generic (it keys on .doc / .doc__prog /
   .doc__section[href^='#'], none of which are homepage-specific). So the float
   materialisation, the scroll-progress hairline, the retract-on-scroll-down and
   the focus-safety rescue all come free and can never drift from the homepage
   again. `.pg-doc` is now DELTAS ONLY — it must not re-declare position,
   background, padding or link geometry, or it re-forks the two bars.

   The category links ride in the `.doc__section-list` slot (the homepage's
   scrollspy slot). They are cross-page hrefs, so nav.js's `[href^='#']` filter
   correctly ignores them for spy purposes; `.is-current` is authored in the
   markup instead and paints the same lime underline via main.css. */
.pg-doc .doc__section { letter-spacing: .14em; }
/* [aria-current="location"] marks the category a GALLERY page belongs to —
   related but not the page itself, so it reads quieter than the page marker. */
.pg-doc .doc__section[aria-current="location"]::after { transform: scaleX(1); transform-origin: 0 50%; opacity: .45; }

/* second dropdown group — the side-system galleries (L5) */
.gdrop__h--2 { margin-top: 10px; border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); }

/* ── hero ── */
.pg-hero { padding: calc(var(--nav-h) + clamp(40px, 7vh, 80px)) var(--pad) 0; }
.pg-crumb { font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--ink-2); display: block; margin-bottom: 16px; }
.pg-crumb a { color: inherit; text-decoration: none; }
.pg-crumb a:hover { color: var(--graphite); }
.pg-t {
  font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 74;
  font-size: clamp(52px, 8.5vw, 140px); line-height: .88; letter-spacing: .005em;
}
.pg-lede {
  font-family: var(--body); font-size: clamp(15px, 1.3vw, 18px); line-height: 1.65;
  color: var(--ink-2); max-width: 62ch; margin: 20px 0 clamp(28px, 4vw, 48px);
}
.pg-lede b { color: var(--graphite); font-weight: 500; }
.pg-hero__fig { margin: 0; position: relative; border: 1px solid var(--hair); overflow: clip; background: oklch(14% 0.005 80); }
.pg-hero__fig img, .pg-hero__fig video { display: block; width: 100%; height: auto; aspect-ratio: 21 / 9; object-fit: cover; }
.pg-hero__fig .pg-loop { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pg-tick { position: absolute; width: 20px; height: 20px; border: 0 solid oklch(94% 0.004 120 / .55); z-index: 2; }
.pg-tick--tl { top: 14px; left: 14px; border-top-width: 1px; border-left-width: 1px; }
.pg-tick--tr { top: 14px; right: 14px; border-top-width: 1px; border-right-width: 1px; }
.pg-tick--bl { bottom: 14px; left: 14px; border-bottom-width: 1px; border-left-width: 1px; }
.pg-tick--br { bottom: 14px; right: 14px; border-bottom-width: 1px; border-right-width: 1px; }
@media (max-width: 860px) { .pg-hero__fig img, .pg-hero__fig video { aspect-ratio: 4 / 3; } }

/* ── shared band head ── */
.pg-band { padding: clamp(70px, 9vw, 120px) var(--pad) 0; }
.pg-band__head { border-top: 1px solid var(--hair); padding-top: 16px; margin-bottom: clamp(22px, 3vw, 36px); display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; }
.pg-band__k { font-family: var(--mono); font-size: 11px; letter-spacing: .2em; color: var(--ink-2); }
.pg-band__t { font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 92; font-size: clamp(24px, 2.6vw, 40px); letter-spacing: -0.01em; }
.pg-band__sub { font-family: var(--mono); font-size: 10px; letter-spacing: .16em; color: var(--ink-2); margin-left: auto; }

/* ── the system band: figure + fact rows ── */
.pg-sys { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(300px, 1fr); gap: clamp(24px, 3.5vw, 60px); align-items: start; }
.pg-sys__fig { margin: 0; border: 1px solid var(--hair); overflow: clip; }
.pg-sys__fig img { display: block; width: 100%; height: auto; }
.pg-rows { border-top: 1px solid var(--hair); }
.pg-rows > div { display: grid; grid-template-columns: minmax(130px, 40%) 1fr; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--hair); font-family: var(--mono); font-size: 11.5px; letter-spacing: .05em; }
.pg-rows dt { color: var(--ink-2); }
.pg-rows dd { color: var(--graphite); line-height: 1.65; }
.pg-rows a { color: oklch(49% 0.1 55); text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 1px; }
.pg-rows a:hover, .pg-rows a:focus-visible { color: var(--graphite); }
.pg-note { font-family: var(--mono); font-size: 10px; letter-spacing: .08em; line-height: 1.8; color: var(--ink-2); max-width: 74ch; margin-top: 16px; }
@media (max-width: 960px) { .pg-sys { grid-template-columns: 1fr; } }

/* ── split feature section (text | media) ── */
.pg-split { display: grid; grid-template-columns: minmax(280px, 1fr) minmax(0, 1.3fr); gap: clamp(24px, 3.5vw, 60px); align-items: center; }
.pg-split__copy p { font-family: var(--body); font-size: clamp(14px, 1.2vw, 16.5px); line-height: 1.7; color: var(--ink-2); max-width: 46ch; }
.pg-split__copy p b { color: var(--graphite); font-weight: 500; }
.pg-split__fig { margin: 0; border: 1px solid var(--hair); overflow: clip; position: relative; }
.pg-split__fig img { display: block; width: 100%; height: auto; }
@media (max-width: 960px) { .pg-split { grid-template-columns: 1fr; } }

/* ── the gallery (photo slots — drop files in, add a figure line) ── */
.pg-gal { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(12px, 1.6vw, 22px); }
.pg-gal figure { margin: 0; border: 1px solid var(--hair); overflow: clip; background: var(--bg-2); }
.pg-gal img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; transition: transform .8s var(--ease-out-expo); }
.pg-gal figure:hover img { transform: scale(1.02); }
.pg-gal figcaption { font-family: var(--mono); font-size: 9px; letter-spacing: .12em; color: var(--ink-2); padding: 8px 10px; border-top: 1px solid var(--hair); }
.pg-gal__note { font-family: var(--mono); font-size: 10px; letter-spacing: .1em; color: var(--ink-2); margin-top: 14px; }
@media (max-width: 860px) { .pg-gal { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .pg-gal { grid-template-columns: 1fr; } }

/* ── product cards (side attachments on roof pages) ─────────────────────────
   BATCH 09b · L2 — the cards were choking the imagery, and the cause was
   measurable rather than aesthetic: `aspect-ratio: 3/4` (PORTRAIT) was imposed
   on 900x604 LANDSCAPE sources inside a 4-column grid. Measured at 1440px each
   frame rendered 312x417 — a keyhole that centre-cropped ~50% of every image's
   width away, so no system could be read.

   Then: TWO columns, frames in the source's own 3:2, identity plate laid ON the
   image over a scrim instead of a text strip below it. Same content, ~2.9x the
   rendered image area (312x417 = 130k px^2 -> 649x433 = 281k px^2) and zero
   crop. The new imagery is authored 1600x1067 with an 800 rung.

   Now (2026-08-14): WIND BREAKERS was withdrawn, so the set is THREE, and three
   in a two-column grid orphans one. One row of three, side by side. Each frame
   measures ~430x287 at 1440px — smaller than the 2-col figure above but still
   well clear of the keyhole that caused the original fix, and the row reads as
   one deliberate set rather than 2+1. It collapses straight to a single column
   at 900px: three across a tablet would put the identity plate back under 270px
   and undo exactly what L2 fixed. */
.pg-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 1.8vw, 26px); }
.pg-card {
  position: relative; display: block; overflow: clip; text-decoration: none;
  background: var(--graphite); border: 1px solid var(--hair);
  transform: translateZ(0);
}
.pg-card img {
  display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover;
  transition: transform 1.1s var(--ease-out-expo), filter .5s ease;
}
.pg-card::after {            /* the scrim the identity plate sits on */
  content: ""; position: absolute; inset: 40% 0 0 0; pointer-events: none;
  background: linear-gradient(to bottom, transparent, oklch(16% 0.006 80 / .82));
  transition: opacity .45s var(--ease-magic); opacity: .9;
}
.pg-card:hover img, .pg-card:focus-visible img { transform: scale(1.045); }
.pg-card:hover::after, .pg-card:focus-visible::after { opacity: 1; }
.pg-card__id {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: clamp(14px, 1.6vw, 22px); display: block;
}
.pg-card__id b {
  display: block; font-family: var(--display); font-weight: 650;
  font-variation-settings: "wdth" 88; font-size: clamp(19px, 2.1vw, 30px);
  line-height: 1.02; color: var(--stone);
}
.pg-card__id span {
  display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .12em;
  color: oklch(88% 0.004 100 / .82); margin-top: 7px; line-height: 1.5;
}
/* house affordance language: lime 11x1 tick + 9px mono micro-label, one move */
.pg-card__go {
  display: flex; align-items: center; gap: 8px; margin-top: 11px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .2em;
  color: var(--stone); opacity: 0; transform: translateY(4px);
  transition: opacity .3s var(--ease-magic), transform .3s var(--ease-magic);
}
.pg-card__go::before { content: ""; width: 11px; height: 1px; background: var(--lime); flex: none; }
.pg-card:hover .pg-card__go, .pg-card:focus-visible .pg-card__go { opacity: 1; transform: none; }
/* keyboard users get the affordance without a pointer; touch has no hover at all */
@media (hover: none) { .pg-card__go { opacity: 1; transform: none; } }
.pg-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
@media (max-width: 900px) { .pg-cards { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) {
  .pg-card img, .pg-card__go, .pg-card::after { transition: none; }
  .pg-card:hover img, .pg-card:focus-visible img { transform: none; }
}

/* ── quiet control band ── */
.pg-quiet { font-family: var(--mono); font-size: 11px; letter-spacing: .14em; color: var(--ink-2); line-height: 2; border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); padding: 18px 0; }
.pg-quiet b { color: var(--graphite); font-weight: 500; letter-spacing: .18em; }

/* ── CHOOSE YOUR ROOF — the mini-diamond cross-nav ── */
.pg-x { padding: clamp(70px, 9vw, 120px) var(--pad) 0; }
.pg-x__wrap { display: grid; grid-template-columns: minmax(240px, 320px) 1fr; gap: clamp(30px, 4vw, 70px); align-items: center; border-top: 1px solid var(--hair); padding-top: clamp(30px, 4vw, 50px); }
.pg-dia { position: relative; width: 100%; max-width: 260px; aspect-ratio: 1; margin: 0 auto; }
.pg-dia__sq { position: absolute; inset: 15%; transform: rotate(45deg); border: 1px solid var(--graphite); background: oklch(94% 0.004 120 / .5); }
.pg-dia__sq::after { content: ""; position: absolute; inset: 8px; border: 1px solid var(--hair); }
.pg-dia__c { position: absolute; left: 50%; top: 50%; width: 96px; height: 72px; margin: -36px 0 0 -48px; display: grid; place-items: center; }
.pg-dia__c[data-i="0"] { transform: translateY(-120%); }
.pg-dia__c[data-i="1"] { transform: translateX(112%); }
.pg-dia__c[data-i="2"] { transform: translateY(120%); }
.pg-dia__c[data-i="3"] { transform: translateX(-112%); }
.pg-dia__c a {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--stone); border: 1px solid var(--hair); padding: 8px 11px;
  font-family: var(--mono); text-decoration: none; min-height: 44px; justify-content: center;
  transition: border-color .3s;
}
.pg-dia__c a b { font-size: 8.5px; letter-spacing: .16em; color: oklch(56% 0.1 55); font-weight: 500; }
.pg-dia__c a span { font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 86; font-size: 12.5px; color: var(--graphite); }
.pg-dia__c a:hover, .pg-dia__c a:focus-visible { border-color: var(--graphite); }
.pg-dia__c a[aria-current="page"] { background: var(--graphite); border-color: var(--graphite); }
.pg-dia__c a[aria-current="page"] b { color: oklch(62.5% 0.23 21); }
.pg-dia__c a[aria-current="page"] span { color: var(--stone); }
.pg-x__copy .pg-band__t { margin-bottom: 10px; }
.pg-x__copy p { font-family: var(--mono); font-size: 11px; letter-spacing: .1em; line-height: 1.9; color: var(--ink-2); max-width: 52ch; }
@media (max-width: 860px) { .pg-x__wrap { grid-template-columns: 1fr; } .pg-dia { max-width: 220px; } }

/* ── the door (film / flagship band) + close ── */
.pg-door { position: relative; display: block; overflow: clip; background: oklch(16% 0.006 80); border: 1px solid var(--hair); text-decoration: none; margin-top: clamp(24px, 3vw, 40px); }
.pg-door img { display: block; width: 100%; height: auto; aspect-ratio: 21 / 6.6; object-fit: cover; opacity: .85; transition: opacity .4s; }
.pg-door:hover img, .pg-door:focus-visible img { opacity: 1; }
.pg-door__id { position: absolute; left: clamp(18px, 2.6vw, 40px); bottom: clamp(14px, 2.2vw, 30px); font-family: var(--mono); color: var(--stone); }
.pg-door__id b { display: block; font-size: 9.5px; letter-spacing: .2em; font-weight: 500; color: oklch(78% 0.005 100); margin-bottom: 5px; }
.pg-door__id strong { font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 74; font-size: clamp(26px, 2.6vw, 42px); line-height: .9; }
.pg-door__go { position: absolute; right: clamp(18px, 2.6vw, 40px); bottom: clamp(14px, 2.2vw, 30px); font-family: var(--mono); font-size: 10.5px; letter-spacing: .2em; color: var(--stone); border-bottom: 1px solid currentColor; padding-bottom: 3px; }
.pg-door__go::after { content: " →"; }
@media (max-width: 860px) { .pg-door img { aspect-ratio: 16 / 9; } }
.pg-close { text-align: center; padding: clamp(60px, 8vw, 100px) var(--pad) clamp(70px, 9vw, 110px); }
.pg-close__line { font-family: var(--mono); font-size: 10.5px; letter-spacing: .22em; color: var(--ink-2); margin-bottom: 6px; }

/* ── footer ── */
.pg-foot { border-top: 1px solid var(--hair); padding: clamp(30px, 4vw, 50px) var(--pad); display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: center; }
.pg-foot a { color: var(--graphite); font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em; text-decoration: none; min-height: 44px; display: inline-flex; align-items: center; }
.pg-foot a:hover, .pg-foot a:focus-visible { color: oklch(49% 0.1 55); }

/* ── hardtop page: configurations + colour register ── */
.pg-configs { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(12px, 1.6vw, 22px); }
.pg-config { border: 1px solid var(--hair); background: var(--stone); }
.pg-config figure { margin: 0; overflow: clip; border-bottom: 1px solid var(--hair); }
.pg-config img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
.pg-config__body { padding: 16px clamp(14px, 1.8vw, 22px) 20px; }
.pg-config__no { display: inline-block; font-family: var(--mono); font-size: 10px; letter-spacing: .16em; font-weight: 500; background: var(--graphite); color: var(--brand-lift); padding: 3px 8px; margin-bottom: 10px; }
.pg-config__n { font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 90; font-size: clamp(18px, 1.9vw, 26px); margin-bottom: 8px; }
.pg-config__d { font-family: var(--body); font-size: 13px; line-height: 1.6; color: var(--ink-2); }
.pg-config__m { font-family: var(--mono); font-size: 10px; letter-spacing: .14em; color: var(--ink-2); border-top: 1px solid var(--hair); padding-top: 10px; margin-top: 12px; }
@media (max-width: 960px) { .pg-configs { grid-template-columns: 1fr; } }

.pg-paint { margin: 0; position: relative; isolation: isolate; border: 1px solid var(--hair); overflow: clip; }
.pg-paint__coat { position: absolute; inset: 0; background: var(--paint, #373C41); z-index: 0; }
.pg-paint__base { display: block; position: relative; width: 100%; height: auto; mix-blend-mode: luminosity; z-index: 1; }
.pg-paint::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; background: var(--paint, #373C41); mix-blend-mode: multiply; opacity: var(--shade, 0); }
.pg-paint__tag { position: absolute; right: 10px; top: 10px; z-index: 3; font-family: var(--mono); font-size: 9px; letter-spacing: .14em; background: var(--graphite); color: var(--stone); padding: 4px 8px; }
.pg-paint__cap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px 20px; border: 1px solid var(--hair); border-top: 0; padding: 12px clamp(12px, 1.8vw, 20px); font-family: var(--mono); }
.pg-paint__cap span:nth-child(1) { font-size: 13px; letter-spacing: .12em; font-weight: 500; color: var(--graphite); }
.pg-paint__cap span:nth-child(2) { font-family: var(--display); font-weight: 600; font-variation-settings: "wdth" 96; font-size: clamp(17px, 1.8vw, 24px); color: var(--graphite); }
.pg-paint__cap span:nth-child(3), .pg-paint__cap span:nth-child(4) { font-size: 9.5px; letter-spacing: .18em; color: var(--ink-2); }
.pg-paint__cap span:nth-child(4) { margin-left: auto; }
.pg-wallrow { width: 100%; display: grid; grid-template-columns: minmax(170px, 250px) 1fr; gap: 16px; align-items: center; padding: 13px 0; border-top: 1px solid var(--graphite); border-bottom: 1px solid var(--hair); background: none; border-left: 0; border-right: 0; margin-top: clamp(20px, 2.5vw, 32px); text-align: left; font-family: var(--mono); font-size: 11.5px; letter-spacing: .05em; min-height: 44px; cursor: default; }
.pg-wallrow > span:first-child { color: var(--graphite); font-weight: 500; letter-spacing: .18em; }
.pg-wallrow > span:last-child { color: var(--ink-2); letter-spacing: .14em; }
.pg.pg-armed button.pg-wallrow:not(:disabled) { cursor: pointer; }
.pg.pg-armed button.pg-wallrow:not(:disabled) > span:last-child::after { content: " · OPEN THE WALL"; }
.pg.pg-armed button.pg-wallrow[aria-expanded="true"] > span:last-child::after { content: " · CLOSE"; }
button.pg-wallrow:disabled { color: inherit; opacity: 1; }
.pg-wall { border-bottom: 1px solid var(--hair); padding: 6px 0 22px; }
.pg.pg-armed .pg-wall { display: none; }
.pg.pg-armed .pg-wall.is-open { display: block; }
.pg-wall:focus-visible { outline: 2px solid var(--lime); outline-offset: 4px; }
.pg-wall .px-fam { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--ink-2); margin: 22px 0 10px; }
.pg-wall .px-chips { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 10px; padding: 0; }
.pg-wall .pxchip { min-width: 0; cursor: pointer; }
.pg-wall .pxchip__s { display: block; aspect-ratio: 4 / 3; background: var(--c); border: 1px solid var(--hair); }
.pg-wall .pxchip.is-sel .pxchip__s { outline: 2px solid var(--brand); outline-offset: 2px; }
.pg-wall .pxchip.is-kb .pxchip__s { outline: 2px dashed var(--graphite); outline-offset: 2px; }
.pg-wall .pxchip__c { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .08em; margin-top: 7px; color: var(--graphite); }
.pg-wall .pxchip__n { display: block; font-family: var(--body); font-size: 11px; color: var(--ink-2); line-height: 1.35; }
.pg-wall .px-range__foot, .pg-wall__sub { font-family: var(--mono); font-size: 10px; letter-spacing: .06em; line-height: 1.7; color: var(--ink-2); max-width: 78ch; margin-top: 14px; }

/* ── the flagship film — pinned scrub (batch 09, owner order 2: the films
   live HERE now, off the homepage). Ship-guard: the base markup is a plain
   framed figure holding the poster frame + the beats list — complete with
   no JS. The inline driver ARMS the runway (.pg-film--armed) only when
   motion is allowed, then scrubs the frame sequence by scroll. ── */
.pg-film { position: relative; margin-top: clamp(24px, 3vw, 40px); }
.pg-film--armed { height: 300svh; }
.pg-film__pin { display: grid; gap: 12px; }
.pg-film--armed .pg-film__pin { position: sticky; top: 0; height: 100svh; align-content: center; overflow: clip; }
.pg-film__fig { margin: 0; position: relative; border: 1px solid var(--hair); overflow: clip; background: oklch(16% 0.006 80); }
.pg-film__fig img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
@media (min-aspect-ratio: 7/5) {
  /* wide viewports: cap the plate so the HUD always shares the pin */
  .pg-film--armed .pg-film__fig img { height: min(78svh, 56.25vw); width: 100%; }
}
.pg-film__hud {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .18em; color: var(--ink-2);
}
.pg-film__phase { color: var(--graphite); font-weight: 500; min-height: 16px; }
.pg-film__count { font-variant-numeric: tabular-nums; }
.pg-film__bar { flex: 1 1 auto; max-width: 240px; height: 2px; background: var(--hair); overflow: hidden; }
.pg-film__fill { display: block; height: 100%; width: 100%; background: oklch(59.5% 0.23 21); transform: scaleX(0); transform-origin: left; }
.pg-film__load { font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; color: var(--ink-2); }
.pg-film__load[hidden] { display: none; }
.pg-beats { list-style: none; margin: clamp(28px, 4vw, 48px) 0 0; padding: 0; counter-reset: beat; max-width: 760px; }
.pg-beats li {
  counter-increment: beat; display: grid; grid-template-columns: 56px 1fr; gap: 14px;
  padding: 13px 0; border-top: 1px solid var(--hair); align-items: baseline;
}
.pg-beats li::before {
  content: "B0" counter(beat); font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .16em; color: var(--ink-2);
}
.pg-beats b { display: block; font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 92; font-size: clamp(15px, 1.5vw, 19px); letter-spacing: .01em; }
.pg-beats span { display: block; margin-top: 3px; font-family: var(--mono); font-size: 10px; letter-spacing: .12em; color: var(--ink-2); line-height: 1.7; }
@media (max-width: 860px) {
  /* phones: the plate takes a taller 4:3 window of the same frames — both
     films are center-composed, so the side walls give way, not the subject */
  .pg-film__fig img { aspect-ratio: 4 / 3; }

  /* ── 10a · THE PLATE TAKES THE PIN ───────────────────────────────────────
     Measured on louvered.html at 393x852 before this rule: 151px dead above
     the plate and 151px below the HUD, constant at every scroll position —
     302px, 35% of the screen. `align-content: center` was centring a 532px
     block in an 852px pin, and the plate was capped at `min(62svh, 118vw)`.

     Note which half of that cap was actually binding: at 393 wide, 118vw =
     463.7 and 62svh = 528, so the 4:3 WIDTH term governed. Raising 62svh
     toward 76svh — the obvious reading — would have moved nothing at all on
     the phone the owner is holding. So the plate takes the row instead: the
     pin is an explicit `1fr auto` grid, the plate fills the free space, and
     there is no free space left to centre.

     It also takes the page gutter. The frames are 16:9 behind an
     `object-fit: cover` window, so height alone buys pixels by CROPPING more
     of the shot — the bleed buys the same height back at a gentler crop
     (0.62 rather than 0.56 at 393x852) and +11% of plate area with it. */
  .pg-film--armed .pg-film__pin {
    grid-template-rows: 1fr auto;
    align-content: stretch;
    padding-block: calc(var(--nav-h) + 8px) max(16px, env(safe-area-inset-bottom));
  }
  .pg-film--armed .pg-film__fig {
    min-height: 0;
    margin-inline: calc(-1 * var(--pad));
  }
  .pg-film--armed .pg-film__fig img { height: 100%; }
}

/* ═══ THE GALLERIES (batch 09f) ═══════════════════════════════════════════
   gallery-louvered / -glass / -fabric. The organising idea: this is a
   REGISTER OF INSTALLATIONS, not a wall of tiles. One place = one record =
   one framed assembly, so photographs of the same job can never read as
   several different jobs. Everything here is project photography; renders
   stay on the product pages and keep their own tag. */
.gx-head { padding: calc(var(--nav-h) + clamp(40px, 7vh, 80px)) var(--pad) 0; }
.gx-lede {
  font-family: var(--body); font-size: clamp(15px, 1.3vw, 18px); line-height: 1.65;
  color: var(--ink-2); max-width: 60ch; margin: 20px 0 clamp(20px, 3vw, 30px);
}
.gx-lede b { color: var(--graphite); font-weight: 500; }

/* the index strip: every record on the page, one jump each */
.gx-ix {
  display: flex; flex-wrap: wrap; gap: 8px;
  border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair);
  padding: 12px 0; margin-bottom: clamp(30px, 5vw, 56px);
}
.gx-ix__k { font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--ink-2); align-self: center; margin-right: 6px; }
.gx-ix a {
  display: inline-flex; align-items: center; gap: 7px; min-height: 44px; padding: 6px 12px;
  border: 1px solid var(--hair); text-decoration: none; color: var(--graphite);
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
  transition: border-color .3s, background .3s;
}
.gx-ix a:hover, .gx-ix a:focus-visible { border-color: var(--graphite); background: oklch(94% 0.004 120 / .6); }
.gx-ix a b { color: var(--ink-2); font-weight: 400; }

/* one record = one place */
.gx-set { padding: 0 var(--pad) clamp(56px, 8vw, 96px); scroll-margin-top: calc(var(--nav-h) + 14px); }
.gx-set__head {
  border-top: 1px solid var(--graphite); padding-top: 14px; margin-bottom: 16px;
  display: grid; grid-template-columns: auto 1fr auto; gap: 8px 18px; align-items: baseline;
}
.gx-set__no { font-family: var(--mono); font-size: 11px; letter-spacing: .2em; color: var(--ink-2); }
.gx-set__place {
  font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 92;
  font-size: clamp(20px, 2.2vw, 32px); letter-spacing: -0.01em; color: var(--graphite);
}
.gx-set__tag { font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; color: var(--ink-2); justify-self: end; }
.gx-set__read {
  grid-column: 2 / -1; font-family: var(--body); font-size: clamp(13.5px, 1.15vw, 15.5px);
  line-height: 1.65; color: var(--ink-2); max-width: 68ch;
}
.gx-set__read b { color: var(--graphite); font-weight: 500; }
@media (max-width: 640px) {
  .gx-set__head { grid-template-columns: auto 1fr; }
  .gx-set__tag { grid-column: 1 / -1; justify-self: start; }
  .gx-set__read { grid-column: 1 / -1; }
}

/* the framed assembly — one border around the whole place, hairlines between
   the frames. The 1px gap over a --hair background paints the dividers, so a
   two-photo and a three-photo record read as the same object. */
.gx-frame {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
  border: 1px solid var(--hair); background: var(--hair);
}
.gx-frame > figure { margin: 0; background: var(--stone); overflow: clip; min-width: 0; }
.gx-frame img { display: block; width: 100%; height: auto; background: var(--stone-2); }
/* lead plate: full width at its own proportion, but capped in height — at
   1440 an uncropped 4:3 plate ran 840px and swallowed the whole viewport, so
   every record read as one photo. The cap keeps a record legible as a record. */
.gx-frame--lead > figure:first-child { grid-column: 1 / -1; }
.gx-frame--lead > figure:first-child img,
.gx-frame--one img { max-height: 70svh; object-fit: cover; object-position: center 42%; }
/* supporting frames share one window so the row sits level */
.gx-frame--lead > figure:not(:first-child) img { aspect-ratio: 4 / 3; object-fit: cover; }
.gx-frame--pair > figure img { aspect-ratio: 4 / 3; object-fit: cover; }
.gx-frame--one { grid-template-columns: 1fr; }
/* upright pairs keep their own proportion — nothing worth cropping here */
.gx-frame--tall > figure img { aspect-ratio: auto; }
.gx-cap {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; line-height: 1.6;
  color: var(--ink-2); padding: 9px 12px; border-top: 1px solid var(--hair);
}
.gx-cap b { color: var(--graphite); font-weight: 500; }
@media (max-width: 640px) {
  .gx-frame, .gx-frame--lead, .gx-frame--pair, .gx-frame--tall { grid-template-columns: 1fr; }
  .gx-frame--lead > figure:not(:first-child) img, .gx-frame--pair > figure img { aspect-ratio: 3 / 2; }
}

/* foot of a gallery: back to the product, on to the next roof */
.gx-foot { padding: clamp(10px, 2vw, 20px) var(--pad) 0; }
.gx-foot__wrap {
  border-top: 1px solid var(--hair); padding-top: clamp(24px, 3.5vw, 40px);
  display: flex; flex-wrap: wrap; gap: 14px 26px; align-items: center;
}
.gx-foot__wrap a {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em; color: var(--graphite);
  text-decoration: none; min-height: 44px; display: inline-flex; align-items: center;
  border-bottom: 1px solid var(--hair); transition: border-color .3s;
}
.gx-foot__wrap a:hover, .gx-foot__wrap a:focus-visible { border-color: var(--graphite); }
.gx-foot__k { font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--ink-2); margin-right: auto; }

/* ── the GALLERY walls, once real photography lands on them ── */
.pg-gal figcaption b { color: var(--graphite); font-weight: 500; }
.pg-gal__more {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px;
  margin-top: 14px; padding: 9px 15px; border: 1px solid var(--graphite);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .18em;
  color: var(--graphite); text-decoration: none;
  transition: background .3s, color .3s;
}
.pg-gal__more:hover, .pg-gal__more:focus-visible { background: var(--graphite); color: var(--stone); }
.pg-gal__more::after { content: " →"; }

/* the GALLERY control keeps its place in the pergola bar at every width —
   the category list drops at 820, this must not go with it */
.pg-doc .gdrop > summary { font-size: 10px; padding: 9px 12px; }
@media (max-width: 420px) {
  .pg-doc .gdrop > summary { padding: 9px 10px; letter-spacing: .12em; }
  /* CATALOG yields first at phone width; GALLERY + CALL US are the two that matter */
  .pg-doc .doc__cta:not(.doc__cta--call) { display: none; }
}
/* `.pg-doc__end` and the `.pg-doc a { display:inline-flex }` override it existed
   to repair are both GONE with the old bar (batch 09b · L4) — the dropdown rows
   now inherit main.css's own `.gdrop__p a` geometry, unforked. */

/* ═══════════════════════════════════════════════════════════════════════════
   BATCH 09b · L8 + L15 — THE SUB PAGES GET A MOTION LANGUAGE
   ═══════════════════════════════════════════════════════════════════════════
   Until now these pages loaded one script (gallery-nav.js) and had no entrance,
   scroll or hover grammar at all — they were static documents next to a
   choreographed homepage. This block + js/pg-motion.js closes that gap without
   importing GSAP: the pages stay dependency-free inline-JS islands, which is
   the contract that keeps them working under iCloud eviction.

   SHIP-GUARD (the rule that has bitten this codebase before): nothing is hidden
   by default. Every hidden state below is scoped to `html.pgm`, a class
   js/pg-motion.js adds ONLY after its IntersectionObserver is live — and a
   2.5s watchdog force-reveals everything if anything goes wrong. No-JS, ?static
   and reduced-motion each keep a complete, legible page.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── entrance reveals ── */
html.pgm [data-rev] {
  opacity: 0; transform: translateY(20px);
  transition: opacity .85s var(--ease-magic), transform .85s var(--ease-magic);
  transition-delay: calc(var(--ri, 0) * 70ms);
}
html.pgm [data-rev].is-in { opacity: 1; transform: none; }

/* masked rise — the homepage's heading grammar, ported */
.pgm-mask { display: block; overflow: hidden; }
html.pgm .pgm-rise {
  display: block; transform: translateY(105%);
  transition: transform .95s var(--ease-out-expo);
  transition-delay: calc(var(--ri, 0) * 85ms);
}
html.pgm .is-in .pgm-rise, html.pgm .pgm-mask.is-in .pgm-rise { transform: none; }

/* seam hairline that draws itself under each band head */
.pgm-seam {
  display: block; height: 1px; background: var(--graphite);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 1.1s var(--ease-out-expo);
}
html.pgm .pg-band__head { border-top-color: transparent; position: relative; }
html.pgm .pg-band__head .pgm-seam { position: absolute; left: 0; right: 0; top: -1px; }
html.pgm .pg-band__head.is-in .pgm-seam { transform: scaleX(1); }

/* ── page transition veil (created by JS, so it cannot exist without JS) ── */
/* Every state below is CLASS-driven and the lift state carries the highest
   specificity of the set. This is load-bearing: the covered state was once
   written as an INLINE transform and cleared with a class, which cannot win
   the cascade — the veil stayed at scaleY(1) forever and every pergola→pergola
   navigation landed on an opaque graphite screen until a manual refresh.
   Never express a veil state as an inline style. */
.pgm-veil {
  position: fixed; inset: 0; z-index: 200; background: var(--graphite);
  transform: scaleY(0); transform-origin: 50% 100%; pointer-events: none;
  transition: transform .44s var(--ease-magic);
}
.pgm-veil.is-out { transform: scaleY(1); transform-origin: 50% 100%; }

/* The incoming lift is a CSS ANIMATION, not a class toggle, and that is the
   whole point: an animation starts the moment the element renders, with no
   second frame and no requestAnimationFrame. The rAF version measured
   `lift: null` on all eleven sub pages — under any rAF throttling (background
   tab, an iframe, low-power) the callback never ran and the veil sat opaque
   until the failsafe. Nothing here depends on JS after the class is set. */
.pgm-veil.is-cover {
  transform-origin: 50% 0%;
  animation: pgm-lift .42s var(--ease-magic) both;
}
@keyframes pgm-lift {
  from { transform: scaleY(1); }
  to   { transform: scaleY(0); }
}

/* ── L15 micro-interactions — one move per surface ── */
/* gallery frames: the image breathes, the caption rises to meet it */
.gx-frame figure { position: relative; overflow: clip; }
.gx-frame figure img { transition: transform 1.2s var(--ease-out-expo); }
.gx-frame figure:hover img { transform: scale(1.035); }
.gx-cap { transition: color .3s var(--ease-magic), transform .4s var(--ease-magic); }
.gx-frame figure:hover .gx-cap { transform: translateX(6px); color: var(--graphite); }

/* record index: the house tick, and a live "you are here" from the spy */
.gx-ix a { position: relative; transition: color .28s var(--ease-magic); }
.gx-ix a::before {
  content: ""; position: absolute; left: -14px; top: 50%; width: 9px; height: 1px;
  background: var(--lime); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .3s var(--ease-magic);
}
.gx-ix a:hover::before, .gx-ix a:focus-visible::before, .gx-ix a.is-here::before { transform: scaleX(1); }
.gx-ix a.is-here { color: var(--graphite); }

/* configuration cards: image breathes, number plate warms */
.pg-config figure { overflow: clip; }
.pg-config img { transition: transform 1.2s var(--ease-out-expo); }
.pg-config:hover img { transform: scale(1.04); }
.pg-config { transition: border-color .35s var(--ease-magic); }
.pg-config:hover { border-color: var(--graphite); }

/* split figures on sides.html */
.pg-split__fig { overflow: clip; }
.pg-split__fig img { transition: transform 1.2s var(--ease-out-expo); }
.pg-split__fig:hover img { transform: scale(1.03); }

/* the closing CTA earns an arrow that leans out */
.pg-close .btn, .pg-foot a { position: relative; }
.pg-close .btn::after {
  content: " →"; display: inline-block; transition: transform .32s var(--ease-magic);
}
.pg-close .btn:hover::after { transform: translateX(5px); }

/* hero image parallax is driven by JS as a custom property — transform only */
.pg-hero__fig img, .pg-hero__fig video { will-change: auto; }
html.pgm .pg-hero__fig { overflow: clip; }
html.pgm .pg-hero__fig img { transform: translate3d(0, var(--pgm-par, 0px), 0) scale(1.06); }

/* ── every tier keeps a complete page ── */
@media (prefers-reduced-motion: reduce) {
  html.pgm [data-rev],
  html.pgm .pgm-rise { opacity: 1 !important; transform: none !important; transition: none !important; }
  html.pgm .pg-band__head { border-top-color: var(--hair); }
  html.pgm .pg-band__head .pgm-seam { display: none; }
  html.pgm .pg-hero__fig img { transform: none; }
  .gx-frame figure img, .pg-config img, .pg-split__fig img, .gx-cap { transition: none; }
  .gx-frame figure:hover img, .pg-config:hover img, .pg-split__fig:hover img { transform: none; }
  .pgm-veil { display: none; }
}
@media print {
  html.pgm [data-rev], html.pgm .pgm-rise { opacity: 1 !important; transform: none !important; }
  .pgm-veil { display: none; }
}

/* ═══ THE COUPON — colour register preview (2026-08-14, order 07) ═══════════
   Replaces `.pg-paint`, which tinted ONE photograph per swatch. That approach
   could not tell a solid from a metallic from a wood, went muddy on every dark
   code, and — the owner's word — died. A coil-coated panel is a material, so
   this draws the material: a slab that holds the colour, an anisotropic sheen
   that sweeps as the pointer moves (metal turns in the light; paint does not),
   a grain layer that only wood finishes switch on, and an exposed edge showing
   the true 4 mm sandwich. All CSS, so all 88 codes render identically well and
   nothing needs an asset. Colour changes WIPE across the slab rather than
   cross-fade — the swap is the point of the section, so it should be seen.
   ═══════════════════════════════════════════════════════════════════════════ */
.cpn { margin: 0 0 clamp(20px, 2.6vw, 30px); }
.cpn__stage {
  position: relative; margin: 0;
  display: grid; place-items: center;
  padding: clamp(20px, 3.4vw, 44px) 0 clamp(26px, 3vw, 38px);
  background:
    radial-gradient(120% 90% at 50% 0%, oklch(99% 0.002 120) 0%, transparent 70%),
    var(--stone-2, oklch(92% 0.004 120));
  border: 1px solid var(--hair); overflow: clip;
}
.cpn__slab {
  position: relative; display: block;
  width: min(62%, 520px); aspect-ratio: 5 / 3;
  border-radius: 2px; overflow: clip;
  /* the slab sits on the ground rather than floating on it */
  box-shadow: 0 1px 0 oklch(100% 0 0 / .5) inset,
              0 18px 34px -18px oklch(20% 0.01 80 / .45),
              0 3px 8px -4px oklch(20% 0.01 80 / .3);
}
.cpn__face {
  position: absolute; inset: 0; background: var(--c);
  clip-path: inset(0 100% 0 0);
  transition: clip-path .52s var(--ease-out-expo);
}
.cpn__face.is-on { clip-path: inset(0 0 0 0); }
/* wood codes get a grain; everything else leaves this off */
.cpn__grain {
  position: absolute; inset: 0; opacity: 0; pointer-events: none;
  transition: opacity .4s var(--ease-magic);
  background: repeating-linear-gradient(92deg,
    oklch(0% 0 0 / .10) 0 1px, transparent 1px 3px,
    oklch(100% 0 0 / .06) 3px 4px, transparent 4px 9px);
}
.cpn.is-wood .cpn__grain { opacity: .85; }
/* the specular band — position follows the pointer via --mx */
.cpn__sheen {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg,
    transparent calc(var(--mx, 50%) - 34%),
    oklch(100% 0 0 / .16) calc(var(--mx, 50%) - 10%),
    oklch(100% 0 0 / .30) var(--mx, 50%),
    oklch(100% 0 0 / .16) calc(var(--mx, 50%) + 10%),
    transparent calc(var(--mx, 50%) + 34%));
  mix-blend-mode: soft-light;
  transition: background-position .2s linear;
}
/* metallics take a tighter, brighter sweep than solids do */
.cpn.is-metallic .cpn__sheen { mix-blend-mode: overlay; filter: contrast(1.25); }
/* the exposed edge: skin / core / skin, to scale */
.cpn__edge { position: absolute; left: 0; right: 0; bottom: 0; height: 9px; display: grid;
  grid-template-rows: 2px 1fr 2px; }
.cpn__edge i { display: block; }
.cpn__edge i:nth-child(1) { background: color-mix(in oklch, var(--c) 78%, white); }
.cpn__edge i:nth-child(2) { background: oklch(28% 0.01 80); }
.cpn__edge i:nth-child(3) { background: color-mix(in oklch, var(--c) 62%, black); }
.cpn__scale {
  position: absolute; right: clamp(12px, 2vw, 22px); bottom: clamp(10px, 1.4vw, 16px);
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em; color: var(--ink-2);
}
.cpn__read {
  display: grid; grid-template-columns: auto 1fr; align-items: baseline;
  column-gap: clamp(14px, 1.8vw, 26px); row-gap: 2px;
  border-top: 1px solid var(--hair); padding-top: 12px; margin-top: 12px;
}
.cpn__code {
  font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 78;
  font-size: clamp(30px, 4.4vw, 58px); line-height: .9; letter-spacing: .002em;
  grid-row: span 2;
}
.cpn__name { font-family: var(--body); font-size: clamp(15px, 1.5vw, 20px); color: var(--graphite); }
.cpn__meta { font-family: var(--mono); font-size: 10px; letter-spacing: .16em; color: var(--ink-2); }
.cpn__meta b { font-weight: 400; color: var(--graphite); }
.cpn__meta i { font-style: normal; }
.cpn__meta b::after { content: " · "; color: var(--ink-2); }
@media (max-width: 620px) {
  .cpn__slab { width: 82%; }
  .cpn__read { grid-template-columns: 1fr; }
  .cpn__code { grid-row: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .cpn__face { transition: none; }
  .cpn__sheen { transition: none; }
}

/* ═══ CINEMATIC SUB-PAGE HERO (2026-08-14) ═════════════════════════════════
   The sub pages used to open with crumb → title → lede → picture, so the first
   thing on screen was a paragraph and the image arrived below the fold. Now the
   IMAGE is the page opening and the title sits ON it, and the scroll behaves
   like the homepage hero: the title leaves left, the tag leaves right, the
   supporting line lifts and fades, the picture pushes in to 1.12.

   Driven by ONE custom property, --hp (hero progress, 0 → 1), written by
   pg-motion.js. CSS owns every transform, so there is no per-frame layout and
   the whole thing is compositor-only. --hp defaults to 0, so with JS absent or
   reduced-motion set the hero simply sits at its resting state, fully legible.
   ═══════════════════════════════════════════════════════════════════════════ */
.pg-hero--film {
  position: relative; padding: 0; margin: 0;
  height: min(88svh, 760px); min-height: 420px;
  overflow: clip; isolation: isolate;
  background: oklch(14% 0.005 80);
}
.pg-hero--film .pg-hero__fig {
  position: absolute; inset: 0; margin: 0; border: 0; overflow: clip;
}
.pg-hero--film .pg-hero__fig img,
.pg-hero--film .pg-hero__fig video {
  width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover;
  transform: scale(calc(1 + var(--hp, 0) * .12));
  transform-origin: 50% 55%;
}
/* the scrim is what makes the overlaid type legible — it is a contrast
   device, not decoration, so it is authored here rather than left to luck */
.pg-hero--film .pg-hero__scrim {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(to top, oklch(12% 0.006 80 / .82) 0%, oklch(12% 0.006 80 / .38) 34%, transparent 62%),
    linear-gradient(to right, oklch(12% 0.006 80 / .45) 0%, transparent 46%);
}
.pg-hero--film .pg-hero__over {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 0 var(--pad) clamp(28px, 5vh, 64px);
  color: oklch(97% 0.004 120);
}
.pg-hero--film .pg-crumb { color: oklch(88% 0.006 100 / .9); margin-bottom: 10px; }
.pg-hero--film .pg-crumb a { color: inherit; }
.pg-hero--film .pg-crumb a:hover { color: oklch(100% 0 0); }
.pg-hero--film .pg-t {
  color: oklch(98% 0.003 120); margin: 0;
  transform: translateX(calc(var(--hp, 0) * -110%));
  will-change: transform;
}
.pg-hero__tag {
  display: block; margin-top: 12px;
  font-family: var(--mono); font-size: clamp(10px, 1vw, 12px);
  letter-spacing: .24em; color: oklch(90% 0.006 100 / .92);
  transform: translateX(calc(var(--hp, 0) * 110%));
  will-change: transform;
}
.pg-hero--film .pg-crumb {
  opacity: calc(1 - var(--hp, 0) * 1.7);
  transform: translateY(calc(var(--hp, 0) * -40px));
}
.pg-hero--film .pg-tick { border-color: oklch(96% 0.004 120 / .5); z-index: 3; }
@media (max-width: 620px) {
  .pg-hero--film { height: min(78svh, 560px); }
}
/* Motion is the only thing that stops — the hero stays exactly as legible. */
@media (prefers-reduced-motion: reduce) {
  .pg-hero--film .pg-hero__fig img,
  .pg-hero--film .pg-hero__fig video,
  .pg-hero--film .pg-t,
  .pg-hero__tag { transform: none; }
  .pg-hero--film .pg-crumb { opacity: 1; transform: none; }
}

/* ── hero scrub: cascade corrections ─────────────────────────────────────────
   The reveal system (`html.pgm [data-rev].is-in { transform: none }`) and the
   hero parallax (`html.pgm .pg-hero__fig img`) both carry an `html` element in
   their selector, so they out-specify a plain `.pg-hero--film .pg-t`. Measured:
   the title computed `transform: none` and the picture stayed at the parallax's
   own scale(1.06) — the scrub was being written to --hp and then thrown away.
   These rules match that specificity and come later, and the picture rule
   COMPOSES the two transforms rather than replacing one with the other. */
html.pgm .pg-hero--film .pg-t {
  transform: translateX(calc(var(--hp, 0) * -110%));
}
html.pgm .pg-hero--film .pg-hero__tag {
  transform: translateX(calc(var(--hp, 0) * 110%));
}
html.pgm .pg-hero--film .pg-crumb {
  opacity: calc(1 - var(--hp, 0) * 1.7);
  transform: translateY(calc(var(--hp, 0) * -40px));
}
html.pgm .pg-hero--film .pg-hero__fig img,
html.pgm .pg-hero--film .pg-hero__fig video {
  transform: translate3d(0, var(--pgm-par, 0px), 0) scale(calc(1.06 + var(--hp, 0) * .12));
}
@media (prefers-reduced-motion: reduce) {
  html.pgm .pg-hero--film .pg-t,
  html.pgm .pg-hero--film .pg-hero__tag { transform: none; }
  html.pgm .pg-hero--film .pg-crumb { opacity: 1; transform: none; }
  html.pgm .pg-hero--film .pg-hero__fig img,
  html.pgm .pg-hero--film .pg-hero__fig video { transform: none; }
}

/* ═══ MODEL SERIES — fabric configurations (2026-08-14) ═════════════════════
   Not three abstract "ways to stand" any more: SIX real models in two series,
   each with the projection it is actually rated to. The series heading is the
   organising line, so the grid can stay a plain three-up and the reader still
   sees LINEAR and ARCH as two different things rather than one list of six. */
.pg-series { margin: clamp(26px, 3.4vw, 44px) 0 clamp(14px, 1.8vw, 22px); }
.pg-series:first-of-type { margin-top: 0; }
.pg-series__t {
  display: flex; align-items: baseline; gap: clamp(12px, 1.6vw, 22px); flex-wrap: wrap;
  font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 88;
  font-size: clamp(17px, 1.7vw, 24px); letter-spacing: .01em;
  border-bottom: 1px solid var(--hair); padding-bottom: 10px;
}
.pg-series__note {
  font-family: var(--body); font-weight: 400; font-size: clamp(12px, 1.05vw, 14px);
  color: var(--ink-2); letter-spacing: 0;
}
.pg-models { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 1.8vw, 26px); }
.pg-model { border: 1px solid var(--hair); background: var(--stone-2, oklch(92% 0.004 120)); transition: border-color .35s var(--ease-magic); }
.pg-model:hover { border-color: var(--graphite); }
.pg-model figure { margin: 0; overflow: clip; }
.pg-model img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; transition: transform 1.2s var(--ease-out-expo); }
.pg-model:hover img { transform: scale(1.04); }
.pg-model__body { padding: clamp(12px, 1.4vw, 18px); }
.pg-model__code {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 80;
  font-size: clamp(22px, 2.2vw, 32px); line-height: 1; margin-bottom: 8px;
}
.pg-model__proj { font-family: var(--mono); font-size: 9.5px; font-weight: 400; letter-spacing: .16em; color: var(--ink-2); }
.pg-model__d { font-family: var(--body); font-size: clamp(13px, 1.05vw, 14.5px); line-height: 1.6; color: var(--ink-2); }
.pg-model__m { font-family: var(--mono); font-size: 9px; letter-spacing: .14em; color: var(--ink-2); margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--hair); }
@media (max-width: 900px) { .pg-models { grid-template-columns: 1fr; } }

/* ═══ THE DIAMOND STAGE (2026-08-14, order 01) ═══════════════════════════════
   Was: a pale panel with the wheel on the left and a paragraph on the right,
   sitting on the same light paper as everything above it — so the one moment
   on the page where the reader CHOOSES looked like another content block.

   Now it is the only dark thing on the page: a full-bleed stage, the heading
   and the diamond centred on one axis, nothing else in the frame. The light is
   doing the work — a warm pool behind the diamond, a slow sweep travelling the
   bezel, a vignette closing the edges. Depth comes from three stacked layers
   rather than a shadow: glow (behind), plate (the square), sweep (in front).
   ═══════════════════════════════════════════════════════════════════════════ */
.pg-x--stage {
  position: relative;
  margin-top: clamp(70px, 9vw, 120px);
  padding: clamp(72px, 10vw, 130px) var(--pad) clamp(80px, 11vw, 140px);
  background: oklch(15% 0.006 80);
  overflow: clip; isolation: isolate;
}
/* the pooled light + the vignette that closes the frame */
.pg-x--stage::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(58% 62% at 50% 54%, oklch(42% 0.03 75 / .55) 0%, transparent 68%),
    radial-gradient(120% 100% at 50% 50%, transparent 42%, oklch(9% 0.006 80 / .85) 100%);
}
.pg-x--stage .pg-x__wrap {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: clamp(38px, 6vw, 76px);
  text-align: center;
}
.pg-x--stage .pg-band__t {
  color: oklch(97% 0.004 120); max-width: 18ch; margin: 0;
  font-size: clamp(26px, 3.4vw, 52px); line-height: 1.02;
}
.pg-x--stage .pg-dia { max-width: clamp(240px, 30vw, 340px); }

/* the warm pool that sits BEHIND the plate and gives the object its depth */
.pg-dia__glow {
  position: absolute; inset: -18%; z-index: 0; pointer-events: none;
  background: radial-gradient(closest-side, oklch(72% 0.09 72 / .30), transparent 74%);
  filter: blur(6px);
}
.pg-x--stage .pg-dia__sq {
  inset: 15%; z-index: 1;
  border-color: oklch(78% 0.02 90 / .55);
  background: linear-gradient(148deg, oklch(26% 0.008 80 / .92), oklch(18% 0.006 80 / .92));
  box-shadow: 0 30px 60px -30px oklch(0% 0 0 / .8), 0 0 0 1px oklch(100% 0 0 / .05) inset;
}
.pg-x--stage .pg-dia__sq::after { inset: 9px; border-color: oklch(80% 0.02 90 / .16); }

/* the sweep: one bright arc travelling the bezel, masked to the rim only */
/* The travelling light is the GRADIENT's start angle, not the element's
   rotation. Rotating the element composes with its base rotate(45deg) and
   swings the whole square off the diamond's axis — measured at 351deg, i.e. a
   second misaligned square orbiting the first. Registering the angle as a
   custom property lets it animate while the square stays locked at 45deg. */
@property --sweep { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
.pg-dia__sweep {
  position: absolute; inset: 15%; z-index: 2; pointer-events: none;
  transform: rotate(45deg); border-radius: 1px;
  background: conic-gradient(from var(--sweep),
    transparent 0deg, oklch(97% 0.03 85 / .75) 22deg, transparent 68deg,
    transparent 180deg, oklch(97% 0.03 85 / .38) 202deg, transparent 244deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  padding: 1.5px;
  animation: pg-dia-sweep 9s linear infinite;
}
@keyframes pg-dia-sweep { to { --sweep: 360deg; } }

/* the four corners, on dark */
.pg-x--stage .pg-dia__c a {
  background: oklch(26% 0.008 80 / .96);
  border-color: oklch(85% 0.02 90 / .45);
  transition: transform .32s var(--ease-magic), border-color .32s var(--ease-magic), background .32s var(--ease-magic);
}
.pg-x--stage .pg-dia__c a span { color: oklch(95% 0.004 120); }
.pg-x--stage .pg-dia__c a b { color: oklch(78% 0.13 68); }
.pg-x--stage .pg-dia__c a:hover,
.pg-x--stage .pg-dia__c a:focus-visible {
  transform: translateY(-3px);
  border-color: oklch(92% 0.03 85 / .8);
  background: oklch(24% 0.008 80 / .92);
}
.pg-x--stage .pg-dia__c a[aria-current="page"] {
  background: oklch(93% 0.006 100); border-color: oklch(93% 0.006 100);
}
.pg-x--stage .pg-dia__c a[aria-current="page"] span { color: oklch(17% 0.006 80); }
.pg-x--stage .pg-dia__c a[aria-current="page"] b { color: oklch(52% 0.19 25); }

@media (prefers-reduced-motion: reduce) {
  .pg-dia__sweep { animation: none; }
}

/* The four corners must sit ABOVE the decorative layers. `.pg-dia__sq` (z-1)
   and `.pg-dia__sweep` (z-2) were painting over them: computed background on
   the active tile read oklch(93%) while the rendered pixel measured rgb(45,42,39),
   because the semi-opaque plate was covering it. Corners are the interface —
   they go on top, and they are the only thing here that is interactive. */
.pg-x--stage .pg-dia__c { z-index: 3; }

/* ═══ FILM PROGRESS — HERO GRADE (2026-08-14, order 17) ═════════════════════
   The films used to explain themselves twice: a small mono HUD under the frame
   AND a five-item beat list repeating the same facts in prose. Both gone. What
   is left is the film and the reading of the film, at the scale of the homepage
   hero — a giant beat numeral, the phase in display type that RISES on each
   change (the same masked line the hero uses), and one rule running the full
   width. The captions were already in `data-phases`; nothing was lost, it just
   stopped being said twice.
   ═══════════════════════════════════════════════════════════════════════════ */
.pg-film__hud--big {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "no phase" "bar bar";
  align-items: end; column-gap: clamp(18px, 2.6vw, 40px); row-gap: clamp(14px, 1.8vw, 22px);
  margin-top: clamp(18px, 2.4vw, 30px);
}
.pg-film__no {
  grid-area: no; display: flex; align-items: baseline; gap: 8px;
  font-family: var(--display); font-variation-settings: "wdth" 76; line-height: .82;
}
.pg-film__no i {
  font-style: normal; font-weight: 700; font-size: clamp(46px, 8vw, 118px);
  font-variant-numeric: tabular-nums; color: var(--graphite);
}
.pg-film__no em {
  font-style: normal; font-weight: 500; font-size: clamp(12px, 1.3vw, 18px);
  color: var(--ink-2); letter-spacing: .04em;
}
/* the mask the phase line rises out of — same device as the homepage hero */
.pg-film__phasewrap { grid-area: phase; display: block; overflow: hidden; padding-bottom: .12em; }
.pg-film__phase {
  display: block;
  font-family: var(--display); font-weight: 650; font-variation-settings: "wdth" 84;
  font-size: clamp(15px, 2.1vw, 34px); line-height: 1.04; letter-spacing: -0.005em;
  color: var(--graphite); text-transform: none;
}
.pg-film__phase.is-rise { animation: pg-phase-rise .62s var(--ease-out-expo) both; }
@keyframes pg-phase-rise {
  from { transform: translateY(105%); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
.pg-film__hud--big .pg-film__bar {
  grid-area: bar; max-width: none; width: 100%; height: 2px; background: var(--hair);
}
.pg-film__hud--big .pg-film__load {
  grid-area: phase; align-self: start; justify-self: end;
}
@media (prefers-reduced-motion: reduce) {
  .pg-film__phase.is-rise { animation: none; }
}

/* ═══ NIRVANA — THE FLAGSHIP STAGE (2026-08-14, order 15) ═══════════════════
   NIRVANA was a band head like any other, three quarters down the page, its
   name buried inside a sentence ("NIRVANA — A DAY, HELD") at the same size as
   CONFIGURATIONS and GALLERY. It is the flagship, so it now gets the only
   full-bleed dark stage on this page and the name alone at wordmark scale —
   everything else in the head demoted to a kicker and one line beneath it.
   The film, its giant counter and the phase line all invert onto the dark.
   ═══════════════════════════════════════════════════════════════════════════ */
.pg-flag {
  position: relative;
  margin-top: clamp(70px, 9vw, 120px);
  padding: clamp(56px, 7vw, 96px) var(--pad) clamp(64px, 8vw, 110px);
  background: oklch(13% 0.006 80);
  overflow: clip; isolation: isolate;
}
.pg-flag::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(70% 55% at 50% 0%, oklch(40% 0.04 70 / .5) 0%, transparent 70%);
}
.pg-flag > * { position: relative; z-index: 1; }
.pg-flag__head { text-align: center; margin-bottom: clamp(28px, 4vw, 52px); }
.pg-flag__k {
  display: block; font-family: var(--mono); font-size: 10.5px; letter-spacing: .3em;
  color: oklch(78% 0.12 68); margin-bottom: clamp(10px, 1.4vw, 18px);
}
.pg-flag__t {
  font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 72;
  font-size: clamp(54px, 12vw, 190px); line-height: .86; letter-spacing: .006em;
  color: oklch(97% 0.004 120); margin: 0;
}
.pg-flag__sub {
  display: block; margin-top: clamp(12px, 1.6vw, 20px);
  font-family: var(--mono); font-size: 10px; letter-spacing: .2em;
  color: oklch(84% 0.008 100 / .75);
}
/* the film and its HUD invert onto the dark stage */
.pg-flag .pg-film__fig { border-color: oklch(80% 0.02 90 / .22); }
.pg-flag .pg-film__no i { color: oklch(97% 0.004 120); }
.pg-flag .pg-film__no em { color: oklch(84% 0.008 100 / .7); }
.pg-flag .pg-film__phase { color: oklch(96% 0.004 120); }
.pg-flag .pg-film__bar { background: oklch(100% 0 0 / .16); }
.pg-flag .pg-film__load { color: oklch(84% 0.008 100 / .7); }
.pg-flag .pg-tick { border-color: oklch(96% 0.004 120 / .45); }

/* ═══ DISCLOSURE (2026-08-14, orders 06 + 18) ═══════════════════════════════
   The technical record — footing sign-off, swatch caveats, panel datasheet
   strings, printed footnotes — was set as running body text at full volume,
   so a page about a roof opened with legal small print in the reader's face.
   None of it is deleted; it is one tap away and clearly marked as a control.

   Built on native <details>, so keyboard, screen-reader semantics and the
   no-JS case all come free — nothing here can hide content if a script fails.
   The summary is styled to look like the button it is: full-width hit area,
   pointer cursor, hover and focus states, and a + that becomes a −.
   ═══════════════════════════════════════════════════════════════════════════ */
.disc { border-top: 1px solid var(--hair); margin-top: clamp(14px, 1.8vw, 22px); }
.disc__s {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 12px 0; cursor: pointer; list-style: none;
  font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--ink-2);
  transition: color .28s var(--ease-magic);
  min-height: 44px;                       /* touch target */
}
.disc__s::-webkit-details-marker { display: none; }
.disc__s:hover { color: var(--graphite); }
.disc__s:focus-visible { outline: 2px solid oklch(52% 0.19 25); outline-offset: 3px; }
/* the +/− is drawn, so it needs no glyph and can animate */
.disc__i { position: relative; width: 11px; height: 11px; flex: none; }
.disc__i::before, .disc__i::after {
  content: ""; position: absolute; left: 0; top: 5px; width: 11px; height: 1px;
  background: currentColor; transition: transform .3s var(--ease-magic);
}
.disc__i::after { transform: rotate(90deg); }
.disc[open] .disc__i::after { transform: rotate(0deg); }
.disc[open] .disc__s { color: var(--graphite); }
.disc__b { padding-bottom: 14px; }
.disc__b > p { margin: 0; }
@media (prefers-reduced-motion: reduce) {
  .disc__i::before, .disc__i::after { transition: none; }
}
/* on the dark colour-register stage the disclosure inverts */
.pg-flag .disc, .pg-x--stage .disc { border-top-color: oklch(100% 0 0 / .14); }
.pg-flag .disc__s, .pg-x--stage .disc__s { color: oklch(84% 0.008 100 / .7); }
.pg-flag .disc__s:hover, .pg-x--stage .disc__s:hover { color: oklch(96% 0.004 120); }

/* ═══ NAV OVER THE FILM HERO (2026-08-14) ═══════════════════════════════════
   Regression from the full-bleed hero: the doc panel only paints its surface
   once it floats (past 80px), so at the top of a sub page the dark nav text
   was sitting straight on the photograph. On hard top that photograph is a
   sunlit roof soffit and the labels vanished.

   Fixed by guaranteeing the contrast rather than hoping the frame is dark:
   a top scrim inside the hero (the header is fixed, so it reads as behind the
   bar), plus light nav ink while the bar is unfloated. Once it floats its own
   opaque surface takes over and the ink returns to normal — the same handover
   the homepage already uses via .page--hero. */
.pg--film .pg-hero--film .pg-hero__scrim {
  background:
    linear-gradient(to bottom, oklch(10% 0.006 80 / .62) 0%, oklch(10% 0.006 80 / .22) 12%, transparent 26%),
    linear-gradient(to top, oklch(12% 0.006 80 / .82) 0%, oklch(12% 0.006 80 / .38) 34%, transparent 62%),
    linear-gradient(to right, oklch(12% 0.006 80 / .45) 0%, transparent 46%);
}
.pg--film .doc:not(.is-float) .doc__panel { color: oklch(97% 0.004 120); }
.pg--film .doc:not(.is-float) .doc__section { color: oklch(94% 0.006 100 / .92); }
.pg--film .doc:not(.is-float) .doc__section.is-current { color: oklch(99% 0.002 120); }
.pg--film .doc:not(.is-float) .doc__cta { border-color: oklch(96% 0.006 100 / .5); color: oklch(97% 0.004 120); }
.pg--film .doc:not(.is-float) .doc__cta:hover { border-color: oklch(99% 0.002 120); }
.pg--film .doc:not(.is-float) .gdrop > summary { color: oklch(97% 0.004 120); }

/* ═══ THE COLOUR WALL, ALIVE (2026-08-14) ═══════════════════════════════════
   The register was 88 flat rectangles arriving as one slab — a wall, not an
   instrument. Three changes, all cheap:
     · chips CASCADE in when their range opens, on a per-chip delay, so the
       range unfolds instead of appearing;
     · each chip is a physical sample — it lifts, tilts toward the pointer and
       catches a specular band, the same material logic as the coupon above;
     · the selected chip stays lifted and lit, so the wall always shows where
       you are.
   The tilt is pointer-only and transform-only, so it stays on the compositor,
   and every state degrades to a plain legible swatch without JS.
   ═══════════════════════════════════════════════════════════════════════════ */
.pg-wall .px-chips { perspective: 620px; }
.pg-wall .pxchip {
  transform-style: preserve-3d;
  transition: transform .38s var(--ease-magic);
}
.pg-wall .pxchip__s {
  position: relative; overflow: hidden;
  border-radius: 2px;
  box-shadow: 0 1px 2px oklch(20% 0.01 80 / .16);
  transition: transform .38s var(--ease-magic), box-shadow .38s var(--ease-magic);
  transform: rotateX(calc(var(--ty, 0) * -7deg)) rotateY(calc(var(--tx, 0) * 7deg)) translateZ(0);
}
/* the specular band that tracks the pointer across the swatch */
.pg-wall .pxchip__s::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent calc(var(--mx, 50%) - 30%),
    oklch(100% 0 0 / .34) var(--mx, 50%), transparent calc(var(--mx, 50%) + 30%));
  opacity: 0; transition: opacity .3s var(--ease-magic);
  mix-blend-mode: soft-light;
}
.pg-wall .pxchip:hover .pxchip__s,
.pg-wall .pxchip:focus-within .pxchip__s {
  box-shadow: 0 14px 26px -10px oklch(20% 0.01 80 / .45), 0 2px 5px oklch(20% 0.01 80 / .2);
}
.pg-wall .pxchip:hover .pxchip__s::after { opacity: 1; }
.pg-wall .pxchip:hover { transform: translateY(-4px); }
.pg-wall .pxchip.is-sel { transform: translateY(-5px); }
.pg-wall .pxchip.is-sel .pxchip__s {
  box-shadow: 0 16px 30px -12px oklch(20% 0.01 80 / .5), 0 0 0 2px var(--brand);
  outline: none;
}
.pg-wall .pxchip__c, .pg-wall .pxchip__n { transition: color .28s var(--ease-magic); }
.pg-wall .pxchip:hover .pxchip__c, .pg-wall .pxchip.is-sel .pxchip__c { color: var(--graphite); }
.pg-wall .pxchip:hover .pxchip__n { color: var(--graphite); }

/* the cascade — armed by JS when a range opens, so it plays on OPEN, not load */
.pg-wall.is-live .pxchip { animation: px-in .5s var(--ease-out-expo) both; animation-delay: calc(var(--i, 0) * 14ms); }
@keyframes px-in { from { opacity: 0; transform: translateY(14px) scale(.94); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .pg-wall.is-live .pxchip { animation: none; }
  .pg-wall .pxchip, .pg-wall .pxchip__s { transition: none; }
  .pg-wall .pxchip__s { transform: none; }
}

/* ── hero scrub: the title must not carry the reveal's transition ────────────
   The reveal system puts `transition: transform .85s` on every [data-rev], and
   the hero title is one. So every frame of the scrub was being re-eased through
   an 850ms transition on top of the JS damping — the line lagged the scroll and
   never reached its endpoint. Measured at --hp:1 the tag (no transition) sat at
   exactly +110% of its width while the title was still short of it: 1457px vs
   1096px. The scrub owns transform on this element; the reveal keeps opacity. */
html.pgm .pg-hero--film .pg-t {
  transition: opacity .85s var(--ease-magic);
}

/* ═══ THE RANGE SWITCH + THE RAILS (2026-08-14) ═════════════════════════════
   The register used to be two hairline rows reading "OPEN THE WALL", which the
   owner could barely see, and opening one dumped 28 or 60 flat swatches as a
   slab. Two changes:

     · the ranges become a real SEGMENTED SWITCH — always one range on screen,
       never a closed drawer, the manufacturer and the count legible at a glance;
     · each family becomes a horizontal RAIL rather than a wrapping grid, so 60
       codes read as something you browse instead of a wall you face. The rails
       scroll-snap, and the chips are large enough to actually judge a colour.
   The two ranges still never merge — switching swaps the whole panel. */
.rng {
  display: flex; gap: 0; margin: clamp(22px, 3vw, 34px) 0 clamp(16px, 2vw, 24px);
  border-top: 1px solid var(--graphite); border-bottom: 1px solid var(--hair);
}
.rng__t {
  flex: 1 1 0; min-width: 0; min-height: 64px;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 16px 18px 16px 0; background: none; border: 0; cursor: pointer;
  text-align: left; font-family: var(--mono); color: var(--ink-2);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .28s var(--ease-magic), border-color .28s var(--ease-magic);
}
.rng__t b {
  font-family: var(--display); font-weight: 700; font-variation-settings: "wdth" 84;
  font-size: clamp(17px, 1.9vw, 26px); letter-spacing: .005em; color: var(--ink-2);
  transition: color .28s var(--ease-magic);
}
.rng__t i { font-style: normal; font-size: 10px; letter-spacing: .2em; }
.rng__t em { font-style: normal; font-size: 10px; letter-spacing: .16em; margin-left: auto; }
.rng__t:hover b, .rng__t:hover { color: var(--graphite); }
.rng__t:focus-visible { outline: 2px solid oklch(52% 0.19 25); outline-offset: 3px; }
.rng__t.is-on { color: var(--graphite); border-bottom-color: oklch(52% 0.19 25); }
.rng__t.is-on b { color: var(--graphite); }

/* the panel is now always present for the selected range */
.pg.pg-armed .pg-wall { display: none; }
.pg.pg-armed .pg-wall.is-open { display: block; }
.pg-wall { border-bottom: 0; padding: 2px 0 8px; }

/* families as rails, not a wall */
.pg-wall .px-fam {
  display: flex; align-items: baseline; gap: 10px;
  margin: clamp(18px, 2.2vw, 26px) 0 10px;
  font-size: 10px; letter-spacing: .2em; color: var(--ink-2);
}
.pg-wall .px-chips {
  display: flex; flex-wrap: nowrap; gap: 12px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; padding: 4px 2px 14px;
  scrollbar-width: thin;
}
.pg-wall .px-chips::-webkit-scrollbar { height: 5px; }
.pg-wall .px-chips::-webkit-scrollbar-thumb { background: var(--hair); border-radius: 3px; }
.pg-wall .pxchip {
  flex: 0 0 auto; width: clamp(112px, 12vw, 148px); scroll-snap-align: start;
}
.pg-wall .pxchip__s { aspect-ratio: 1; }
.pg-wall .pxchip__c { font-size: 10.5px; margin-top: 9px; }
.pg-wall .pxchip__n { font-size: 11.5px; }
@media (max-width: 620px) {
  .rng { flex-direction: column; }
  .rng__t { min-height: 56px; padding: 12px 0; }
  .pg-wall .pxchip { width: 116px; }
}

/* ═══ GALLERY PAGES — SAME OPENING AS THE PRODUCT PAGES (2026-08-14) ════════
   The galleries opened on light paper with a crumb, a title and a paragraph,
   while every product page now opens on a full-bleed picture with the title
   laid over it. Same site, two different front doors. They now share one:
   the gallery's own lead frame becomes the hero, the title sits on it, and the
   scrub carries it out exactly as it does elsewhere. The records index, which
   used to be buried under the paragraph, becomes its own strip directly under
   the hero — the first thing you can act on. */
.gx-hero .pg-t { font-size: clamp(46px, 7.4vw, 118px); }
.gx-rec {
  padding: clamp(22px, 3vw, 34px) var(--pad) 0;
}
.gx-rec .gx-ix {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px clamp(16px, 2.2vw, 30px);
  border-bottom: 1px solid var(--hair); padding-bottom: clamp(16px, 2vw, 22px);
}
.gx-rec .gx-ix__k {
  font-family: var(--mono); font-size: 10px; letter-spacing: .24em; color: var(--ink-2);
  margin-right: 4px;
}
/* the index inherits a boxed-chip style from the old stacked layout — in a
   single strip those borders read as a row of empty buttons, so they are
   cleared here and the affordance becomes a rule that draws under the label */
.gx-rec .gx-ix a {
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em;
  color: var(--ink-2); text-decoration: none;
  border: 0; background: none; padding: 4px 0; min-height: 44px;
  display: inline-flex; align-items: center; gap: 6px;
  position: relative; transition: color .26s var(--ease-magic);
}
.gx-rec .gx-ix a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 2px; height: 1px;
  background: var(--graphite); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .3s var(--ease-magic);
}
.gx-rec .gx-ix a:hover::after,
.gx-rec .gx-ix a:focus-visible::after,
.gx-rec .gx-ix a.is-here::after { transform: scaleX(1); }
.gx-rec .gx-ix a:hover, .gx-rec .gx-ix a:focus-visible, .gx-rec .gx-ix a.is-here { background: none; }
/* the leading lime tick belongs to the old vertical list; it collides in a row */
.gx-rec .gx-ix a::before { display: none; }
.gx-rec .gx-ix a b { color: var(--graphite); font-weight: 500; margin-right: 5px; }
.gx-rec .gx-ix a:hover, .gx-rec .gx-ix a:focus-visible { color: var(--graphite); }
/* the first set should not collide with the strip above it */
.gx-rec + .gx-set { padding-top: clamp(30px, 4vw, 52px); }

/* ── the keyboard cursor is for KEYBOARD users ───────────────────────────────
   `.is-kb` paints a dashed marker so an arrow-key user can see where the
   cursor sits. But clicking a swatch also focuses the wall, so a mouse user
   got a dashed black box around the first chip — on a white swatch it looked
   like a rendering fault. Gating on :focus-visible means the marker appears
   only when focus actually arrived from the keyboard. */
.pg-wall .pxchip.is-kb .pxchip__s { outline: none; }
.pg-wall:focus-visible .pxchip.is-kb .pxchip__s {
  outline: 2px dashed var(--graphite); outline-offset: 2px;
}

/* ═══ 10a · PHONE TYPE FLOOR (2026-08-15) ═══════════════════════════════════
   Same contract as the block at the end of main.css: phone-gated, last in the
   file so source order settles ties, written at the specificity of the rule
   each line lifts, and split 11px (read) / 10.5px (glance). Measured on
   louvered.html at 393x852, this sheet alone held 34 rules under 10.5px —
   including the gallery captions at 9px, which are the only description a
   photograph of a finished job ever gets. */
@media (max-width: 860px) {
  /* ── 11px · read ───────────────────────────────────────────────────────── */
  .pg-note,
  .pg-gal figcaption,
  .pg-gal__note,
  .pg-beats span,
  .pg-config__m,
  .pg-wall__sub,
  .pg-wall .px-fam,
  .pg-wall .pxchip__c,
  .pg-wall .px-range__foot,
  .gx-cap,
  .gx-ix a,
  .pg-doc .gdrop > summary,
  .cpn__meta,
  .pg-model__proj,
  .pg-model__m,
  .pg-flag__sub,
  .disc__s,
  .pg-card__id span,
  /* clamp(10px, 1vw, 12px) — the vw term is 3.9px on a phone, so 10px renders */
  .pg-hero__tag { font-size: 11px; }

  /* ── 10.5px · glance ───────────────────────────────────────────────────── */
  .pg-crumb,
  .pg-band__sub,
  .pg-card__go,
  .pg-dia__c a b,
  .pg-door__id b,
  .pg-config__no,
  .pg-paint__tag,
  .pg-paint__cap span:nth-child(3),
  .pg-paint__cap span:nth-child(4),
  .pg-film__load,
  .gx-ix__k,
  .gx-rec .gx-ix__k,
  .gx-set__tag,
  .gx-foot__k,
  .cpn__scale,
  .rng__t i,
  .rng__t em { font-size: 10.5px; }

  /* ── 44px hit areas ─────────────────────────────────────────────────────
     These are inline links sitting in running text — the breadcrumb pair and
     two "read on" links, measured at 14px tall. They are grown with
     padding-block, not font-size: padding on an INLINE box expands the border
     box, which is what gets hit-tested, while leaving the line box alone, so
     nothing around them reflows and the type keeps the size it was designed
     at. The crumb's padding is asymmetric on purpose — the nearest control
     above it is only 10px away, so it takes 8px up and 22px down rather than
     15/15, which would have overlapped that control's hit area by 5px. */
  .pg-crumb a { padding-block: 8px 23px; }
  .pg-quiet a,
  .pg-rows dd a { padding-block: 15px; }
}
