/* =========================================================
   Section redesign — PRODUCTS. See REDESIGN-BRIEF.md.

   Loads after pages.css so it can override the .tile/.g3 rules it
   replaces. Scoped to this page only; nothing here ships to the other six.

   Archetypes, in page order — no two adjacent are the same and there is
   no uniform grid left on the page:

     hero       0 · specimen rack — four staggered plates, never a grid
     range      5 · alternating full-bleed split
     alloys     7 · expanding rows            <- the page's one moment
     specs      8 · bespoke drawn schematic
     downloads  5 · compact split + hairline ledger
     why        3 · scroll-drawn spine (ported from .proc__ on the homepage)

   Colour comes entirely from tokens.css. Molten never appears as a CTA:
   the only filled buttons on this page are the shared white .btn--fill.
   ========================================================= */

/* =========================================================
   0 · HERO — the rack

   .phero and .phero__* live in pages.css, which is shared by all
   seven pages and is not editable from here. Everything below
   overrides it under `.phero--rack`, so it lands on this page and
   nowhere else.

   Geometry: the copy holds the left of the site grid; four plates
   stand in the right, each a different WIDTH and a different
   HEIGHT (grid-template-columns is deliberately not 1fr 1fr 1fr 1fr,
   and each slat spans its own rows). Two of them are cut by the top
   of the frame, all of them are cut by the seam below. That is what
   keeps it a composition rather than a row of four cards — which is
   the exact thing the redesign brief counted 91 of.

   Contrast: no text sits on a photograph here. The 01–04 labels sit
   on navy under each plate, which is why this hero needs no scrim
   over the imagery and the photographs can stay bright.
   ========================================================= */

.phero--rack { padding-bottom: clamp(2.4rem, 6vh, 4rem); }

/* The rack is absolutely positioned, so the copy has to be told not
   to run under it. Percentages of the wrap, not of the viewport. */
.prack__copy { max-width: 44%; }

.prack {
  /* z-index 3, above .phero__inner's 2. The copy container is a .wrap —
     a full-width box that covers the whole hero, transparent but very
     much present — so at z-index 1 the four plates were painted
     underneath it and it swallowed every click. They stayed
     keyboard-reachable, which is exactly why a focus test passed while
     the mouse did nothing. The plates never overlap the copy column
     visually, so painting above it costs nothing. */
  position: absolute; z-index: 3;
  /* Clear of the fixed header on purpose. The homepage runs its video
     under the nav because the footage is dark there; these plates are
     bright studio shots and white nav links on a lit ingot is a real
     contrast failure, not a stylistic preference. */
  top: calc(var(--nav-h) + 10px); bottom: 0;
  /* 49%, not 51% (round 2, item 2). The rack carries five plates now
     instead of four, and the two points bought back cover most of the
     width the extra column costs. */
  left: 49%;
  /* bleeds off the right edge — .phero{overflow:hidden} clips it, so
     this can never widen the document */
  right: calc(-1 * clamp(10px, 1.7vw, 34px));
  display: grid;
  /* Not four equal columns and not four equal heights. Billets leads
     because it is product 01 and because the plate that leads should
     be the one carrying fetchpriority. */
  grid-template-columns: 1.3fr .82fr 1fr .84fr 1.04fr;
  grid-template-rows: repeat(24, 1fr);
  column-gap: clamp(8px, .85vw, 15px);
  margin: 0; padding: 0; list-style: none;
}

/* Five different vertical extents — no two slats share a top edge or a
   bottom edge. Slats 2 and 4 run off the top of the frame; 1 and 3 hang
   lower and are cut by the seam; 5 sits between them and is cut by
   neither, which is what stops the new plate reading as a repeat of one
   of the four it joined. */
.prack__slat { position: relative; min-width: 0; }
.prack__slat:nth-child(1) { grid-row: 4 / 22; }
.prack__slat:nth-child(2) { grid-row: 1 / 14; }
.prack__slat:nth-child(3) { grid-row: 7 / 25; }
.prack__slat:nth-child(4) { grid-row: 2 / 17; }
.prack__slat:nth-child(5) { grid-row: 5 / 20; }

.prack__link {
  display: flex; flex-direction: column; height: 100%;
  text-decoration: none; color: var(--steel-dim);
  transition: transform var(--d-s) var(--e-out), color var(--d-s) var(--e-out);
}
.prack__link:hover, .prack__link:focus-visible { color: var(--chrome); transform: translateY(-5px); }

.prack__shot {
  position: relative; flex: 1 1 auto; min-height: 0;
  overflow: hidden; border-radius: var(--rad);
  background: var(--navy-800);
  border: 1px solid var(--rule-d);
  isolation: isolate;
}
/* The four product shots are studio work on grey seamless. Left
   ungraded they read as four grey blocks on a navy band; a navy
   multiply pushes the seamless towards the band's own colour and
   leaves the metal itself bright, which is what makes the objects
   read rather than their backgrounds. */
.prack__shot::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(178deg, rgba(10,30,60,.14) 0%, rgba(6,21,41,.40) 100%);
  mix-blend-mode: multiply;
  transition: opacity var(--d-s) var(--e-out);
}
.prack__link:hover .prack__shot::after,
.prack__link:focus-visible .prack__shot::after { opacity: .55; }

.prack__shot img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* Close to the .ph--live grade in main.css. Tuned against
     _qc/herolum-pim.js: at brightness(.94) under a heavier multiply the
     four plates painted 88-101, and photolum's floor for an unscrimmed
     photographic surface is 95. They now paint 106-121. */
  filter: saturate(.97) brightness(1) contrast(1.06);
  transition: transform var(--d-l) var(--e-out), filter var(--d-s) var(--e-out);
}
.prack__link:hover img, .prack__link:focus-visible img {
  transform: scale(1.05); filter: saturate(1) brightness(.98) contrast(1.06);
}

/* Each studio shot is centred in a wide frame, so a portrait crop has
   to be told where the object actually is. */
/* Framing belongs to the photograph, not to the slot. These were
   :nth-child(2)/(3)/(4) until the 2026-09-01 reorder, at which point each
   would have started cropping a different product's picture. The row spans
   above stay on :nth-child on purpose — those ARE the slot. */
.prack__slat--ingots   img { object-position: 50% 46%; }
.prack__slat--custom   img { object-position: 48% 56%; }
.prack__slat--recycled img { object-position: 40% 50%; }

/* The mould veil. Default state is FINISHED — retreated — so no JS,
   a thrown error or reduced motion all leave the photograph visible.
   js/sec-products.js writes the covering pre-state before it plays.
   Solid navy, so scaling it is invisible; the molten front below is a
   separate element travelling the same distance on the same ease. */
.prack__cast {
  position: absolute; inset: 0; z-index: 2;
  background: var(--navy-900);
  transform: scaleY(0); transform-origin: 50% 0;
}
.prack__front {
  position: absolute; left: 0; right: 0; top: 0; z-index: 3;
  height: 2px; opacity: 0;
  background: linear-gradient(90deg, transparent, var(--molten) 22%, #ffd9a8 50%, var(--molten) 78%, transparent);
  box-shadow: 0 0 16px 3px var(--glow);
}

.prack__meta {
  display: block; margin-top: .62rem;
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.prack__meta b {
  color: var(--molten); font-weight: 500; margin-right: .35rem;
}

/* --- narrower: the rack lies down under the copy ------------------
   Below 1024 there is no room for a column of copy AND a rack beside
   it, so the rack becomes a full-bleed strip: same four plates, same
   staggered heights, now read left to right. */
@media (max-width: 1023px) {
  .prack__copy { max-width: none; }
  .prack {
    position: static; margin-top: clamp(1.8rem, 4vh, 2.6rem);
    /* Half the copy's gutter: the strip still reads as running past
       the frame, but no plate or label is welded to the screen edge. */
    padding: 0 calc(var(--gutter) * .5);
    grid-template-rows: repeat(12, 1fr);
    height: clamp(190px, 34vw, 280px);
  }
  .prack__slat:nth-child(1) { grid-row: 2 / 12; }
  .prack__slat:nth-child(2) { grid-row: 1 / 10; }
  .prack__slat:nth-child(3) { grid-row: 3 / 13; }
  .prack__slat:nth-child(4) { grid-row: 1 / 11; }
  .prack__slat:nth-child(5) { grid-row: 2 / 11; }
}
@media (max-width: 560px) {
  .prack { grid-template-columns: 1.06fr .88fr 1.08fr .84fr .98fr; column-gap: 6px; height: clamp(160px, 40vw, 230px); }
  /* Five columns at 360px leaves roughly 62px a slat, and one nowrap line
     of "05 PROFILES" cannot live in that — it ellipsised to "05 PRO…".
     The index moves onto its own line instead, which is how a mono index
     wants to be set anyway. */
  .prack__meta {
    font-size: .62rem; letter-spacing: .08em;
    white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.3;
  }
  .prack__meta b { display: block; margin-right: 0; }
}

/* Reduced motion: the CSS above already IS the end state — the veil
   is retreated and the front is invisible — and js/sec-products.js
   returns before touching either. Nothing to undo here; the hover
   transitions are neutralised globally by base.css. */

/* ---------------------------------------------------------
   1 · RANGE — alternating full-bleed split.

   The four product cards keep their .prod class, because that is the
   contract transitions.js cast()/settle()/ignite() read. Everything that
   made them look like cards is undone here: no white plate, no border,
   no lift-on-hover, no ring around the whole row. The mould-fill reveal
   and the counting index survive intact.
   --------------------------------------------------------- */

.prange {
  /* Aligns a full-bleed row's copy with the .wrap column above it. */
  --edge: max(var(--gutter), calc((100vw - var(--maxw)) / 2 + var(--gutter)));
  margin-top: clamp(1rem, 3vh, 2.2rem);
  overflow: hidden;   /* the figures run to the viewport edge */
}

.prange__row {
  display: grid;
  grid-template-columns: 54fr 46fr;
  align-items: center;
  column-gap: clamp(1.5rem, 4vw, 4rem);
  background: none;
  border: 0;
  border-radius: 0;
  overflow: visible;
  transition: none;
}
.prange__row + .prange__row { margin-top: clamp(2.6rem, 8vh, 6rem); }

.prange__row--r { grid-template-columns: 46fr 54fr; }
.prange__row--r .prange__fig  { order: 2; }
.prange__row--r .prange__body { order: 1; }

/* Kill the card lift and the whole-row ignition ring — a 1px ring around
   a 600px-wide band reads as a stray border, not as heat. */
.prange__row:hover { transform: none; border-color: transparent; box-shadow: none; }
.prange__row::before { display: none; }

.prange__fig {
  aspect-ratio: 4 / 3;
  border-radius: 0;
  align-self: stretch;
  min-height: clamp(230px, 42vh, 520px);
}

/* The cast counter moves to the figure's INNER corner. Left at 0 it sat
   flush against the viewport edge, which read as a clipped element rather
   than a stamp. */
.prange__fig .prod__no { left: auto; right: 0; }
.prange__row--r .prange__fig .prod__no { left: 0; right: auto; }

/* The ignition moves onto the figure instead. --ignite is set on .prod by
   transitions.js and inherits down, so the photograph's edge warms as the
   row crosses the ignition line. */
.prange__fig::after {
  content: ''; position: absolute; inset: 0; z-index: 4; pointer-events: none;
  opacity: var(--ignite, 0);
  box-shadow: inset 0 0 0 1px rgba(194, 65, 12, .75), inset 0 0 26px -8px rgba(194, 65, 12, .5);
}

.prange__body {
  display: block;
  flex: none;
  padding: 0 var(--edge) 0 0;
  max-width: calc(46ch + var(--edge));
}
.prange__row--r .prange__body { padding: 0 0 0 var(--edge); }

.prange__body h3 {
  font-size: clamp(1.35rem, 1.05rem + 1.1vw, 2.1rem);
  line-height: 1.1;
  margin-bottom: clamp(.7rem, 1.6vh, 1rem);
  max-width: 16ch;
}
.prange__body p:not(.label) {
  font-size: var(--fs-body);
  flex: none;
  max-width: 42ch;
}
.prange__body .arrowlink { margin-top: clamp(1.2rem, 3vh, 1.9rem); }

@media (max-width: 900px) {
  .prange__row,
  .prange__row--r { grid-template-columns: 1fr; row-gap: clamp(1.2rem, 3vh, 1.8rem); }
  .prange__row--r .prange__fig  { order: 0; }
  .prange__row--r .prange__body { order: 0; }
  .prange__fig { aspect-ratio: 16 / 10; min-height: 0; }
  .prange__body,
  .prange__row--r .prange__body { padding: 0 var(--gutter); max-width: none; }
  .prange__body h3 { max-width: 20ch; }
}

/* ---------------------------------------------------------
   2 · ALLOYS — expanding rows. The one moment.

   Progressive enhancement matters here: with CSS only, every drawer is
   open and the page reads exactly like the table it replaced. js adds
   `.is-live` and only then does anything collapse.
   --------------------------------------------------------- */

.alloy__lede {
  max-width: 56ch;
  color: var(--steel);
  margin: 0 0 clamp(1.8rem, 4.5vh, 2.8rem);
}

.alloy { border-top: 1px solid var(--rule-d); }

.alloy__row { position: relative; border-bottom: 1px solid var(--rule-d); }

/* The row's hairline warms — the .tile::after language, moved onto a rule
   that is 1200px wide instead of a box that is 320px wide. */
.alloy__row::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--molten);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform var(--d-s) var(--e-out);
}
.alloy__row:hover::after,
.alloy__row:focus-within::after,
.alloy__row.is-open::after { transform: scaleX(1); }

.alloy__head { margin: 0; font-weight: inherit; font-size: inherit; }

.alloy__btn {
  display: grid;
  grid-template-columns: minmax(4.5rem, 7.5rem) minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(.9rem, 3vw, 2.8rem);
  width: 100%;
  padding: clamp(1rem, 2.4vh, 1.65rem) 0;
  background: none; border: 0; text-align: left; cursor: pointer;
  font: inherit; color: inherit;
}

.alloy__series {
  display: block;
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(1.5rem, 1.15rem + 1.35vw, 2.5rem);
  line-height: 1; letter-spacing: -.02em;
  color: var(--molten);
  transition: transform var(--d-s) var(--e-out);
}
.alloy__row:hover .alloy__series,
.alloy__row.is-open .alloy__series { transform: translateX(4px); }

.alloy__base {
  font-family: var(--f-display); font-weight: 300;
  font-size: clamp(1rem, .95rem + .35vw, 1.28rem);
  line-height: 1.25; letter-spacing: -.01em;
  color: var(--chrome);
}

.alloy__mark {
  position: relative; display: block;
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--rule-d2);
  transition: border-color var(--d-s) var(--e-out);
}
.alloy__mark i {
  position: absolute; left: 50%; top: 50%;
  width: 12px; height: 1px; background: var(--steel);
  transform: translate(-50%, -50%);
  transition: transform var(--d-s) var(--e-out), background-color var(--d-s) var(--e-out);
}
.alloy__row:hover .alloy__mark { border-color: var(--molten); }
.alloy.is-live .alloy__row:not(.is-open) .alloy__mark i:last-child {
  transform: translate(-50%, -50%) rotate(90deg);
}
.alloy__row.is-open .alloy__mark { border-color: var(--molten); }
.alloy__row.is-open .alloy__mark i { background: var(--ember); }

/* Open by default. Height is written by js only once .is-live is on, so a
   visitor with no JS still gets all six properties. */
.alloy__drawer { overflow: hidden; }
.alloy.is-live .alloy__drawer { height: 0; visibility: hidden; }
.alloy.is-live .alloy__row.is-open .alloy__drawer { visibility: visible; }

.alloy__panel {
  max-width: 62ch;
  border-left: 2px solid var(--molten);
  padding: .15rem 0 clamp(1.4rem, 3.4vh, 2.2rem) clamp(1rem, 2.4vw, 1.8rem);
}
.alloy__prop {
  font-family: var(--f-display); font-weight: 300;
  font-size: clamp(1.1rem, .95rem + .8vw, 1.7rem);
  line-height: 1.28; letter-spacing: -.012em;
  color: var(--white); margin: 0;
}
/* Grade codes, added 2026-08-20 from the client's written confirmation.
   Mono and tabular-nums because these are part numbers a buyer scans and
   compares, not prose: 6005A above 6060 has to align to read as a list.
   Size is .78rem: above --fs-label (.72rem), because the label scale is for
   furniture and these are the most-searched content on the page — but at the
   top of DESIGN-SPEC §mono (.68–.78rem) rather than outside it. It was .8rem
   briefly, which would have made this the largest mono on the site and left
   the spec silently wrong. */
.alloy__codes {
  display: flex; flex-wrap: wrap; gap: .45rem;
  list-style: none; margin: clamp(.95rem, 2.2vh, 1.35rem) 0 0; padding: 0;
}
.alloy__codes li {
  font-family: var(--f-mono); font-size: .78rem; font-weight: 500;
  font-variant-numeric: tabular-nums; letter-spacing: .05em;
  color: var(--white);
  padding: .32rem .6rem;
  border: 1px solid var(--rule-d2); border-radius: var(--rad);
  background: rgba(255, 255, 255, .04);
}
.alloy__panel .arrowlink { margin-top: clamp(.9rem, 2.2vh, 1.35rem); }

/* Ingot grade codes on the product range, added 2026-08-24 on the client
   team's instruction. Same pill idiom as .alloy__codes, but the range sits
   on the LIGHT band (#range is sec--light) so the drawer pills' white-on-
   dark values cannot be reused. Two labelled groups: trade/international
   grades, then GLD's own codes — see the provenance comment beside the
   markup in build/pages/products.html. */
.pgrades {
  margin: clamp(.95rem, 2.2vh, 1.3rem) 0 0;
  display: flex; flex-direction: column; gap: .85rem;
}
.pgrades__set { display: flex; flex-direction: column; gap: .45rem; }
.pgrades__label {
  font-family: var(--f-mono); font-size: .66rem; font-weight: 600;
  letter-spacing: .15em; text-transform: uppercase;
  color: var(--slate);
}
.pgrades__codes {
  display: flex; flex-wrap: wrap; gap: .45rem;
  list-style: none; margin: 0; padding: 0;
}
.pgrades__codes li {
  font-family: var(--f-mono); font-size: .78rem; font-weight: 500;
  font-variant-numeric: tabular-nums; letter-spacing: .05em;
  color: var(--ink);
  padding: .32rem .6rem;
  border: 1px solid var(--rule-l2); border-radius: var(--rad);
  background: rgba(15, 27, 45, .04);
}
/* "etc." is not a grade. It stands for the rest of the trade list, which the
   client took off the page on 2026-09-01. Held a step back from the codes it
   sits beside — body face rather than mono, muted ink, dashed edge, no fill —
   so it reads as a continuation and can never be mistaken for a designation. */
.pgrades__codes li.pgrades__etc {
  font-family: var(--f-body); font-style: italic; font-weight: 400;
  letter-spacing: 0;
  color: var(--slate);
  border-style: dashed;
  background: transparent;
}

/* The catch-all sits outside the accordion, so it reads as a statement about
   the whole range rather than a footnote on whichever row happens to be open. */
.alloy__note {
  max-width: 62ch;
  margin: clamp(1.6rem, 3.6vh, 2.4rem) 0 0;
  color: var(--steel-dim);
  font-size: .92rem;
}

@media (max-width: 620px) {
  .alloy__btn {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: .3rem;
  }
  .alloy__series { grid-column: 1; }
  .alloy__base   { grid-column: 1; }
  .alloy__mark   { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
}

/* ---------------------------------------------------------
   3 · SPECS — a drawn engineering plate beside a callout ledger.

   Default state is FINISHED: every path sits at dashoffset 0. js only
   ever winds them back to draw them, so no-JS and reduced-motion both
   land on a complete plate.
   --------------------------------------------------------- */

.pspec {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

.pspec__plate { margin: 0; }
.pspec__svg { width: 100%; height: auto; }

.pspec__reg path,
.pspec__thin { fill: none; stroke: var(--rule-d); stroke-width: 1.3; stroke-linecap: square; }
.pspec__reg path { stroke: var(--rule-d2); }
.pspec__rule { fill: none; stroke: var(--rule-d2); stroke-width: 1.4; }
.pspec__hot  { fill: none; stroke: var(--ember); stroke-width: 1.8; }
.pspec__dim  { fill: none; stroke: var(--ember); stroke-width: 2.2; stroke-linecap: round; }

.pspec__txt text {
  font-family: var(--f-mono); font-size: 17px; letter-spacing: .05em;
  fill: var(--steel);
}
.pspec__txt .pspec__lab { fill: var(--ember); font-size: 15px; letter-spacing: .18em; }

.pspec__plate figcaption {
  margin-top: clamp(.9rem, 2.2vh, 1.3rem);
  font-size: var(--fs-small);
  color: var(--steel);
  max-width: 46ch;
}

.pspec__list {
  display: grid; margin: 0; padding: 0; list-style: none;
  border-top: 1px solid var(--rule-d);
}
.pspec__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(.9rem, 2vw, 1.6rem);
  padding: clamp(1rem, 2.6vh, 1.6rem) 0;
  border-bottom: 1px solid var(--rule-d);
}
.pspec__no {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .16em; color: var(--ember); padding-top: .4rem;
}
.pspec__item h3 {
  font-family: var(--f-display); font-weight: 600; font-size: var(--fs-h3);
  letter-spacing: -.015em; color: var(--white); margin: 0 0 .35rem;
}
.pspec__item p { font-size: var(--fs-small); color: var(--steel); margin: 0; }

@media (max-width: 900px) {
  .pspec { grid-template-columns: 1fr; gap: clamp(1.8rem, 5vh, 2.8rem); }
  .pspec__plate { max-width: 34rem; }
}

/* ---------------------------------------------------------
   4 · DOWNLOADS — compact split, hairline ledger.
   Four bordered boxes became four ruled lines, on a band that runs
   tight so it reads as an index rather than another full section.
   --------------------------------------------------------- */

.pdocs {
  display: grid;
  grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr);
  gap: clamp(1.6rem, 5vw, 4.5rem);
  align-items: start;
}
.pdocs__intro > p {
  margin-top: clamp(1rem, 2.4vh, 1.5rem);
  max-width: 40ch;
  font-size: var(--fs-small);
  color: var(--slate);
}

.pdocs__list {
  list-style: none; margin: 0; padding: 0;
  border-top: 1px solid var(--rule-l2);
}
.pdocs__item { position: relative; border-bottom: 1px solid var(--rule-l2); }
.pdocs__item::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--molten-ink);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform var(--d-s) var(--e-out);
}
.pdocs__item:hover::after,
.pdocs__item:focus-within::after { transform: scaleX(1); }

.pdocs__item a {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(.85rem, 2.4vw, 2rem);
  padding: clamp(.9rem, 2.2vh, 1.35rem) 0;
  color: var(--ink);
}
.pdocs__no {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .16em; color: var(--molten-ink);
}
.pdocs__name {
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(1rem, .94rem + .4vw, 1.22rem);
  letter-spacing: -.012em;
}
.pdocs__act {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--slate); white-space: nowrap;
  transition: color var(--d-xs) var(--e-quad);
}
.pdocs__act svg { transition: transform var(--d-s) var(--e-out); }
.pdocs__item a:hover .pdocs__act { color: var(--molten-ink); }
.pdocs__item a:hover .pdocs__act svg { transform: translateX(4px); }

@media (max-width: 860px) {
  .pdocs { grid-template-columns: 1fr; }
  .pdocs__list { margin-top: clamp(1.4rem, 4vh, 2rem); }
}
@media (max-width: 480px) {
  .pdocs__item a { grid-template-columns: auto minmax(0, 1fr); row-gap: .35rem; }
  .pdocs__act { grid-column: 2; }
}

/* ---------------------------------------------------------
   5 · WHY — the homepage spine, ported. The component lives in
   main.css; all this band needs is the intro paragraph's colour.
   --------------------------------------------------------- */

.proc__intro > p:not(.label) {
  margin-top: clamp(1.1rem, 2.6vh, 1.6rem);
  max-width: 40ch;
  font-size: var(--fs-small);
  color: var(--steel);
}

/* ---------------------------------------------------------
   Reduced motion — every device on this page already defaults to its
   finished state, so this block only has to stop the hairline sweeps
   and the two hover nudges.
   --------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .alloy__row::after,
  .pdocs__item::after,
  .alloy__series,
  .alloy__mark,
  .alloy__mark i,
  .pdocs__act,
  .pdocs__act svg { transition: none; }
  .alloy__row:hover .alloy__series,
  .alloy__row.is-open .alloy__series { transform: none; }
}
