/* ═══════════════════════════════════════════════════════════════════════
   CoreWeave — PDP, Dedicated Inference
   Figma: CW / node 2580:1376 "PDP" (1440 × 11226)

   Loaded after styles.css (tokens, base, nav), form.css (the button) and
   home.css. The frame is drawn in the landing page's system, not the old CPU
   page's: same #0541e9 / #02030b / #f5f5f5, same 60px gutter, same 40-between-
   rows header block, same 44px circled arrow, same 427px resource card. So
   home.css is not a reference here — it is the stylesheet, and this file adds
   only the sections it has no class for.

   What comes from home.css, unchanged: `.hp-h1/h2/h3/h4`, `.hp-body`,
   `.hp-eyebrow`, `.hp-head`, `.hp-actions`, `.cw-btn.hp-btn` with its rolling
   label, `.hp-arrow` with its growing ring, `.hp-carousel`, `.hp-post`,
   `.hp-band`, `.hf` (the footer) and the whole hover language — teal #c7ffff
   on every surface that can be hovered.

   Everything new is prefixed `pdp-`. Every size is a clamp() whose upper
   bound is the frame's number at 1440.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* the frame's three rules, all of them the ink at low alpha */
  --pdp-rule:      rgba(2, 3, 11, .20);   /* row and panel edges     */
  --pdp-rule-mid:  rgba(2, 3, 11, .30);   /* the FAQ list            */
  --pdp-dim:       rgba(2, 3, 11, .40);   /* spec keys, path labels  */
  --pdp-dim-light: rgba(255, 255, 255, .60);

  --pdp-fs-lg:  clamp(34px, 4.445vw, 64px);   /* 64 / 62 — the row titles */
  --pdp-fs-sub: clamp(18px, 1.667vw, 24px);   /* 24 / 34 — the hero lede  */
}

/* Every section but the hero opens with 60 of its own above the header
   block's 60 — 120 clear above the eyebrow — exactly as on the landing
   page, whose rule this joins. */
.pdp-why, .pdp-who, .pdp-paths, .pdp-helps,
.pdp-works, .pdp-faq, .pdp-close { padding-top: var(--hp-g60); }

/* ── type this page adds ─────────────────────────────────────────────
   Both are trimmed cap-to-baseline like everything in home.css, which is
   what keeps the sections on the frame's heights. */
.pdp-h-lg, .pdp-sub, .pdp-path__label,
.pdp-spec__k, .pdp-spec__v, .pdp-q__title {
  text-box: trim-both cap alphabetic;
}

.pdp-h-lg {
  margin: 0;
  font-weight: 500;
  font-size: var(--pdp-fs-lg);
  line-height: .969;                    /* 62 / 64 */
  letter-spacing: -.03em;
  color: var(--hp-ink);
}

.pdp-sub {
  margin: 0;
  font-weight: 400;
  font-size: var(--pdp-fs-sub);
  line-height: 1.417;                   /* 34 / 24 */
  letter-spacing: -.02em;
  color: var(--hp-ink);
  max-width: 984px;
}

/* ═════════════════════════════════════════ 1 — hero (2580:1377) ═════
   1000 tall: 500 of copy over a 500 band. The frame draws no header, so it
   starts its 60 of padding at the top of the page; the header here is 108
   and fixed, so the copy half grows by exactly that and its 60 begins
   underneath the bar — the same trade the landing page makes. The band
   keeps its 500.

   The copy half is the page's grey, not the frame's white: the landing page
   opens on the same #f5f5f5 and this one arrives from it, so a white first
   screen made the move between them read as two different sites. The band
   paints over the bottom half, so this colour is only ever the copy's. */
.pdp-hero { position: relative; background: var(--hp-grey); }

.pdp-hero__lead {
  min-height: calc(clamp(360px, 34.723vw, 500px) + var(--nav-h));
  padding: calc(var(--nav-h) + var(--hp-g60)) var(--hp-gutter) var(--hp-g60);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--hp-g60);
}
.pdp-hero__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hp-g40);
}

.pdp-crumb a { color: inherit; transition: color .2s var(--hp-ease); }
.pdp-crumb a:hover { color: var(--hp-blue); }

/* The frame's still artwork, redrawn: the CPU page's ornament sketch with
   this frame's geometry (measured off the export — 74 × 44 rhombi, 79
   across and 100 down, on a 790 wave) and its two colours, black on the
   page's own teal.
   Without a canvas the band is that teal and nothing else, which is the
   ground the frame paints under the pattern anyway. */
.pdp-band {
  height: clamp(240px, 34.723vw, 500px);
  background: var(--hp-teal);
  overflow: hidden;
}
.pdp-band canvas { display: block; width: 100%; height: 100%; }

/* ══════════════════════════ 2 — why dedicated inference (2580:1390) ═
   Five cards and, in the sixth cell of the 3 × 2 grid, the closing note the
   frame puts there instead of a card. */
.pdp-why { background: var(--hp-grey); padding-bottom: var(--hp-g60); }

.pdp-feats {
  padding: 0 var(--hp-gutter) var(--hp-g60);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--hp-g20);
}

.pdp-feat {
  min-height: clamp(420px, 39.514vw, 569px);
  background: var(--hp-white);
  border-radius: var(--hp-tile-radius);
  padding: var(--hp-g40);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--hp-g40);
  color: inherit;
  overflow: hidden;
}
.pdp-feat__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hp-g40);
}
/* The five icons are inline SVG rather than <img> so the ink can be the
   card's own and the strokes can be animated — an <img> is opaque to both.
   Every stroke is currentColor; the halves the frame draws at 50% keep their
   own stroke-opacity. */
.pdp-feat__icon { display: block; width: 44px; height: 44px; color: var(--hp-ink); }

/* ── the icon draws itself in ──────────────────────────────────────
   These are line drawings, so the honest entrance is the line being drawn.
   `pathLength="1"` on every path is what makes that free: the length is
   normalised, so one dash of 1 is the whole stroke whatever its real length,
   and no script has to measure anything.

   A path holding several subpaths — the chip's twelve pins, the gateway's
   dotted spine — draws them one after another off the same dash, which is
   the stagger the eye reads inside a single icon.

   It hangs off the card's own `.is-in`, so the icon starts as the card
   lands rather than on a clock of its own. */
.pdp-feat__icon path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.pdp-feat.is-in .pdp-feat__icon path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--t-line) var(--e-out);
}
/* the outline first, then the detail hung on it */
.pdp-feat.is-in .pdp-feat__icon path:nth-child(2) { transition-delay: 140ms; }
.pdp-feat.is-in .pdp-feat__icon path:nth-child(3) { transition-delay: 240ms; }
.pdp-feat.is-in .pdp-feat__icon path:nth-child(4) { transition-delay: 340ms; }

/* ── the two arrows draw in two beats ──────────────────────────────
   Open runtimes is two arrows pointing away from each other, and it reads
   as one gesture rather than four strokes: the shafts grow out of the middle
   in opposite directions, and only once they are nearly out do the heads
   sprout at the two tips.

   The direction is in the path data, not here — a dash grows from a path's
   START, so the shafts are written from the middle outwards and each barb
   from its tip. Splitting the head into two strokes is what lets it grow
   from the point instead of sweeping across it; the round cap closes the
   1.5px notch the two would otherwise leave where they meet.

   Five classes and an element on purpose. The nth-child defaults above are
   (0,4,1); at (0,4,0) this would lose to them, and at (0,4,1) it would tie
   and win only on sheet order — the fragile kind of win this file has been
   caught by twice already. (0,5,1) settles it outright. */
.pdp-feat.is-in .pdp-feat__icon.pdp-feat__icon--arrows path.pdp-icon__shaft {
  transition: stroke-dashoffset .9s var(--e-out);
  transition-delay: 0s;
}
.pdp-feat.is-in .pdp-feat__icon.pdp-feat__icon--arrows path.pdp-icon__barb {
  transition: stroke-dashoffset .45s var(--e-out);
  /* 780 rather than 900: the head starts while the shaft is still arriving,
     so the two beats overlap instead of handing over */
  transition-delay: .78s;
}

@media (prefers-reduced-motion: reduce) {
  .pdp-feat__icon path,
  .pdp-feat.is-in .pdp-feat__icon path {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    transition: none;
  }
}

.pdp-feats__note {
  padding: var(--hp-g60);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-end;
  gap: var(--hp-g30);
  text-align: right;
}
.pdp-feats__note-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--hp-g40);
  width: 100%;
}
.pdp-feats__note .hp-h3   { max-width: 480px; }
.pdp-feats__note .hp-body { max-width: 390px; }

/* ══════════════════════════════ 3 — who this is for (2580:1479) ═════
   660 of picture beside a column that carries a rule along its top — an
   inset shadow rather than a border, so the row still measures the frame's
   320. */
.pdp-who { background: var(--hp-white); padding-bottom: var(--hp-g60); }

.pdp-rows {
  padding: 0 var(--hp-gutter);
  display: flex;
  flex-direction: column;
  gap: var(--hp-g60);
}

.pdp-row { display: flex; align-items: stretch; color: inherit; }
.pdp-row__shot {
  flex: none;
  width: 660px;
  height: 320px;
  background: #000;
  overflow: hidden;
}
.pdp-row__shot img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.2s cubic-bezier(.22, 1, .36, 1);
}
.pdp-row:hover .pdp-row__shot img { transform: scale(1.05); }

.pdp-row__text {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--hp-g40);
  display: flex;
  flex-direction: column;
  gap: var(--hp-g40);
  box-shadow: inset 0 1px 0 var(--pdp-rule);
}
.pdp-row__head { display: flex; align-items: center; gap: var(--hp-g40); }
.pdp-row__head .pdp-h-lg { flex: 1 1 auto; min-width: 0; }
.pdp-row__text .hp-body { max-width: 383px; }

/* the "Ready to scale?" band again, but the frame rules it top and bottom
   here rather than filling it, and keeps the type in the ink */

/* ═══════════════════════════ 4 — inference paths (2580:1525) ════════
   Three cards, the middle one the page you are on.

   The frame fixes each at 427 and leaves 59 of the row unused; here they are
   thirds of the row instead, so the three fill the gutters at every width
   above 1024 rather than only at 1440. At 1440 that is 426.67 against the
   frame's 427 — a third of a pixel each, and the row lands on the gutter
   instead of a third of a pixel past it.

   Below 1024 thirds would leave 288 of card and 208 of copy inside it, so the
   row goes back to the frame's fixed width and becomes a rail: it scrolls
   natively on touch and pdp.js adds the pointer drag for everything else. */
.pdp-paths { background: var(--hp-grey); padding-bottom: var(--hp-g60); }

.pdp-paths__rail {
  padding: 0 var(--hp-gutter) var(--hp-g60);
  display: flex;
  align-items: stretch;
  gap: var(--hp-g20);
}
.pdp-paths__rail::-webkit-scrollbar { display: none; }
.pdp-paths__rail.is-grabbing { cursor: grabbing; scroll-behavior: auto; }

.pdp-path {
  flex: 1 1 0;
  min-width: 0;
  background: var(--hp-white);
  border-radius: var(--hp-tile-radius);
  display: flex;
  flex-direction: column;
  color: inherit;
  overflow: hidden;
  /* background-color is gone from this list with the teal fill; box-shadow
     stays for the dark variant's own hover below. */
  transition: box-shadow .25s var(--hp-ease);
}

.pdp-path__top {
  padding: var(--hp-g40);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hp-g40);
}
.pdp-path__label {
  font-weight: 500;
  font-size: var(--hp-fs-h4);
  line-height: 1.084;
  letter-spacing: -.03em;
  color: var(--pdp-dim);
}
/* the frame authors the break and gives the block three lines of room, so
   the three titles sit on one baseline whatever they say */
.pdp-path__title { min-height: clamp(62px, 6.181vw, 89px); }

.pdp-path__specs {
  margin-top: auto;
  padding: var(--hp-g40);
  display: flex;
  flex-direction: column;
  gap: var(--hp-g30);
}
.pdp-spec { display: flex; flex-direction: column; gap: var(--hp-g10); }
.pdp-spec__k {
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--hp-fs-mono);
  line-height: 1.429;
  text-transform: uppercase;
  color: var(--pdp-dim);
}
.pdp-spec__v {
  font-family: var(--mono);
  font-weight: 700;
  font-size: var(--hp-fs-mono);
  line-height: 1.572;
  color: var(--hp-ink);
}
.pdp-spec__v-reg { font-weight: 400; }

/* the card for the page you are on: the frame inverts it and rules it white */
.pdp-path--dark {
  background: var(--hp-ink);
  box-shadow: inset 0 0 0 1px var(--hp-white);
}
.pdp-path--dark .hp-h3,
.pdp-path--dark .hp-body,
.pdp-path--dark .pdp-spec__v { color: var(--hp-white); }
.pdp-path--dark .pdp-path__label,
.pdp-path--dark .pdp-spec__k   { color: var(--pdp-dim-light); }
/* it cannot take the teal as a fill without stopping being the dark card,
   so it takes it as the rule instead */
.pdp-path--dark:hover {
  background: var(--hp-ink);
  box-shadow: inset 0 0 0 1.5px var(--hp-teal);
}

/* ══════════════════════════════ 5 — how it helps (2580:1579) ════════ */
.pdp-helps { background: var(--hp-white); padding-bottom: var(--hp-g60); }

.pdp-helps__grid {
  padding: 0 var(--hp-gutter) var(--hp-g60);
  display: flex;
  align-items: center;
  gap: var(--hp-g20);
}
/* The frame gives the picture the row's height, not its own: it is a fill
   on a box that is `h-full` beside the claims. So the image is taken out of
   flow — left in it, its 975px of intrinsic height would set the flex line
   and the row would be twice the height the frame draws. */
.pdp-helps__shot {
  position: relative;
  flex: none;
  width: 650px;
  align-self: stretch;
  background: #000;
  overflow: hidden;
}
.pdp-helps__shot img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.2s cubic-bezier(.22, 1, .36, 1);
}
/* the picture answers the claims, so it moves when one of them is pointed
   at rather than when the picture itself is */
/* The canvas is named alongside the <img> because once the lattice is running
   the <img> is hidden, and this push into the picture — the thing that ties a
   claim to the photograph — would have quietly stopped happening. */
.pdp-helps__grid:has(.pdp-helps__item:hover) .pdp-helps__shot :is(img, canvas.hp-mesh) {
  transform: scale(1.05);
}
.pdp-helps__shot canvas.hp-mesh {
  transition: transform 1.2s cubic-bezier(.22, 1, .36, 1);
}

.pdp-helps__list {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: inset 0 1px 0 var(--pdp-rule);
}
.pdp-helps__item {
  padding: var(--hp-g40);
  display: flex;
  flex-direction: column;
  gap: var(--hp-g40);
  box-shadow: inset 0 -1px 0 var(--pdp-rule);
  /* an <a> now, so the pointer says the claim can be followed. The reset is
     what keeps that from also changing how it looks — the anchor would
     otherwise bring the browser's underline and link colour, and the two
     paragraphs inside are already coloured by their own rules. */
  color: inherit;
  text-decoration: none;
}

/* ═══════════════════════════════ 6 — how it works (2580:1587) ═══════
   1080 with a header block in the top third and nothing under it, because
   that is what the frame draws. The landing page's Forge section makes the
   same call for the same reason. */
.pdp-works { background: var(--hp-grey); min-height: 1080px; }

/* ═══════════════════════════════════════ 7 — FAQs (2580:1589) ═══════
   The frame absolutely positions two blocks in a 1365 box: the heading at
   the left edge, the list starting 245 down and 618 across. Here that is a
   two-track grid — 366 and 762 of the 1320 between the gutters, 192 of air
   between them — so it reflows instead of overlapping on a narrow window. */
.pdp-faq {
  background: var(--hp-white);
  /* The frame's 1365 was holding 163 of empty page under the last answer:
     the content ends at 1202 and the min-height forced the rest. The section
     now ends where it ends, with the same 60 of padding under it as before. */
  padding: 0 var(--hp-gutter) var(--hp-g60);
  display: grid;
  grid-template-columns: 366fr 762fr;
  column-gap: clamp(24px, 13.334vw, 192px);
  align-content: start;
}

.pdp-faq__head {
  padding-top: var(--hp-g60);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hp-g40);
}

.pdp-faq__list {
  margin-top: clamp(40px, 12.848vw, 185px);
  padding: var(--hp-g30) 0;
  display: flex;
  flex-direction: column;
  gap: var(--hp-g30);
  box-shadow: inset 0 1px 0 var(--pdp-rule-mid);
}

/* One clock moves this row, and it is the panel's height. `--dur` is set
   here rather than on each piece so the panel, the ring and the bar inside
   it all land on the same frame.

   The frame gives an open row 40 of bottom padding and a shut one 30. Taken
   literally that is a second transition on the same bottom edge, running to
   a different length on a different curve — and two clocks arriving 50ms
   apart is exactly what a judder is. So the row keeps 30 at all times and
   the extra 10 lives *inside* the panel, where the one animating height
   already carries it. The open row still measures the frame's 40. */
.pdp-q {
  --dur: .4s;
  padding-bottom: var(--hp-g30);
  box-shadow: inset 0 -1px 0 var(--pdp-rule-mid);
}

.pdp-q__row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--hp-g40);
  padding: 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.pdp-q__title {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 600;
  font-size: 18px;
  line-height: 1.556;                   /* 28 / 18 */
  letter-spacing: -.02em;
  color: var(--hp-ink);
  transition: color .25s var(--hp-ease);
}
.pdp-q__row:hover .pdp-q__title,
.pdp-q__row:focus-visible .pdp-q__title { color: var(--hp-blue); }

/* the plus is two bars in a ring; opening drops the upright one and turns
   the ring through a half circle, so the two states are one movement.

   Like every other ring in the build it darkens under the pointer and does
   not grow — see the note on the arrows in the README. */
.pdp-q__mark {
  position: relative;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px var(--pdp-rule-mid);
  transition: box-shadow var(--dur) var(--hp-ease),
              transform var(--dur) var(--hp-ease);
}
.pdp-q__mark i {
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  background: var(--hp-ink);
  border-radius: 1px;
}
.pdp-q__mark i:first-child { width: 20px; height: 2px; transform: translate(-50%, -50%); }
.pdp-q__mark i:last-child  {
  width: 2px; height: 20px;
  transform: translate(-50%, -50%);
  transform-origin: 50% 50%;
  transition: transform var(--dur) var(--hp-ease), opacity var(--dur) var(--hp-ease);
}
.pdp-q.is-open .pdp-q__mark            { transform: rotate(180deg); }
.pdp-q.is-open .pdp-q__mark i:last-child { transform: translate(-50%, -50%) scaleY(0); opacity: 0; }
/* the whole row is the control, so it is the row that darkens the ring — the
   same trade `.hp-hit` makes for the cards on the landing page. No fill:
   a ring is not a surface, and the teal is for surfaces. */
.pdp-q__row:hover .pdp-q__mark,
.pdp-q__row:focus-visible .pdp-q__mark {
  box-shadow: inset 0 0 0 1.5px var(--hp-ring-hover);
}

/* the panel's height is set in pdp.js — `auto` cannot be transitioned, and
   a max-height guess either clips a long answer or coasts through empty
   space on a short one */
.pdp-q__panel {
  height: 0;
  overflow: hidden;
  opacity: 0;
  transition: height var(--dur) var(--hp-ease), opacity var(--dur) var(--hp-ease);
}
.pdp-q.is-open .pdp-q__panel { opacity: 1; }
/* the bottom half of this padding is the row's own 40 − 30, moved inside the
   box that animates — see the note on `.pdp-q` above */
.pdp-q__panel > p {
  padding-top: var(--hp-g20);
  padding-bottom: calc(var(--hp-g40) - var(--hp-g30));
}

/* ═════════════════════════ 8 — related resources (2580:1640) ════════
   `.hp-res` from home.css is this section already — same 427 card, same
   two-up grouping, same clamp on the last page, same dots, and the frame
   gives it the same 60 / 120 header block. Nothing to add. */

/* ══════════════════════════════════════ 9 — closing (2580:1719) ═════
   The frame opens this one 40 below its own 60 rather than the 60 the rest
   of the page uses, and closes it with both. */
.pdp-close {
  background: var(--hp-white);
  padding-top: calc(var(--hp-g60) + var(--hp-g40));
  padding-bottom: var(--hp-g60);
}

.pdp-close__grid {
  padding: 0 var(--hp-gutter) var(--hp-g60);
  display: flex;
  align-items: center;
  gap: var(--hp-g20);
}
.pdp-close__text {
  flex: 1 1 auto;
  min-width: 0;
  box-shadow: inset 0 1px 0 var(--pdp-rule);
}
.pdp-close__inner {
  padding: var(--hp-g60) var(--hp-g40);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hp-g40);
  box-shadow: inset 0 -1px 0 var(--pdp-rule);
}
/* out of flow for the same reason as the picture in "how it helps" above */
.pdp-close__shot {
  position: relative;
  flex: none;
  width: 650px;
  align-self: stretch;
  background: #000;
  overflow: hidden;
}
.pdp-close__shot img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.2s cubic-bezier(.22, 1, .36, 1);
}
.pdp-close__grid:hover .pdp-close__shot img { transform: scale(1.04); }

/* ═══════════════════════════════════════════════════ responsive ═════
   One 1440 layout that scales, with the same four places the landing page
   changes shape rather than shrinking. */

@media (max-width: 1180px) {
  .pdp-row__shot { width: 40%; height: auto; min-height: 260px; }
  .pdp-helps__shot, .pdp-close__shot { width: 42%; }
  .pdp-faq { min-height: 0; grid-template-columns: minmax(0, 1fr); }
  .pdp-faq__list { margin-top: var(--hp-g60); }
}

@media (max-width: 1024px) {
  /* thirds of this row would leave 288 of card and 208 of copy inside it, so
     the three go back to the frame's own width and the row becomes a rail */
  .pdp-paths__rail {
    overflow-x: auto;
    scrollbar-width: none;
    touch-action: pan-x pan-y;
  }
  .pdp-path { flex: none; width: 427px; max-width: 82vw; }

  .pdp-feats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pdp-feat  { min-height: 0; }
  .pdp-feats__note { padding: var(--hp-g40); }
  .pdp-works { min-height: 0; padding-bottom: var(--hp-g120); }

  .pdp-row { flex-direction: column; }
  .pdp-row__shot { width: 100%; height: 260px; }

  .pdp-helps__grid, .pdp-close__grid { flex-direction: column; align-items: stretch; }
  .pdp-helps__shot, .pdp-close__shot { width: 100%; height: 320px; }
}

@media (max-width: 760px) {
  .pdp-feats { grid-template-columns: minmax(0, 1fr); }
  .pdp-feats__note { align-items: flex-start; text-align: left; }
  .pdp-feats__note-copy { align-items: flex-start; }
  .pdp-row__head { gap: var(--hp-g20); }
  .pdp-q__row { gap: var(--hp-g20); }
  .pdp-close__inner { padding: var(--hp-g40) var(--hp-g30); }
}

@media (prefers-reduced-motion: reduce) {
  .pdp-row__shot img,
  .pdp-helps__shot img,
  .pdp-close__shot img { transition: none; }
  .pdp-q__panel { transition: none; }
  .pdp-q__mark, .pdp-q__mark i:last-child { transition: none; }
}


/* ══════════════════════════════════ hover, as the home page does it ═══
   These four boxes filled with teal under the cursor. The home page dropped
   that treatment at the client's request and answers a pointer with two
   things only: the title turns blue, and a 1px stroke fades in around the
   box. Nothing moves, nothing fills, nothing lifts.

   The stroke itself is not written here — it is the shared overlay in
   home.css (which this page loads), extended to these selectors, so there is
   one definition of what that line is rather than a second copy drifting
   from the first. What is here is the part that is this page's own: which
   element in each box is the title.

   `position: relative` is what that overlay is positioned against; these
   four had no positioning of their own. */
/* they position their own contents; the hover stroke is an outset shadow on
   the element now and needs nothing from this */
.pdp-feat,
.pdp-path { position: relative; }

.pdp-feat .hp-h3,
.pdp-row__text .pdp-h-lg,
.pdp-path .pdp-path__title,
.pdp-helps__item .hp-h3 { transition: color .25s var(--e-out); }

.pdp-feat:is(:hover, :focus-visible) .hp-h3,
.pdp-row:is(:hover, :focus-visible) .pdp-row__text .pdp-h-lg,
.pdp-path:is(:hover, :focus-visible) .pdp-path__title,
.pdp-helps__item:hover .hp-h3 { color: var(--hp-blue); }

/* The dark path card keeps its own hover and is the one deliberate exception.
   Blue on near-black is unreadable and a 12.5%-black stroke on it is
   invisible, so the home treatment does not survive the change of ground.
   It answers with the ink fill and the teal edge it always had. */
.pdp-path--dark:is(:hover, :focus-visible) .pdp-path__title { color: inherit; }
