/* ============================================================================
   PhenomeTech Ring — the product page's own sheet

   AN ADDITION, NOT A RETHEME. `shared.css` is the captured mirror of the live
   store and `phenome-glass.css` is the token overlay that reskins all 82 pages;
   neither is touched here. Everything below is scoped to `.pdp` on <body>, the
   same way `devices/ring/ring.css` scopes itself to `.ph-flat`, so a rule that
   goes wrong goes wrong on ONE url.

   WHAT WAS ASKED FOR, and it is worth writing down because it is the whole
   brief: keep the page's layout, palette and type exactly as they are, and
   change what the page LETS YOU DO with them. So there is not one new colour
   here, not one new face, and not one section moved. Every value is a token
   that already existed — --phenome-blue-*, --ink-*, --gl-*, --ph-r*, --ph-fs-* —
   and where a surface is drawn it is drawn on one of the three tiers
   phenome-glass.css already defines:

       raised   --gl-tint-live  + --gl-shadow, --gl-inner
       recess   --gl-tint-sunk  + --gl-inner-sunk
       chip     --gl-tint-solid + --gl-shadow

   THE SECTIONS: a five-tile media mosaic under a buy column that
   sticks, accordions that compress the column instead of lengthening it, a
   dark glass panel laid over a photograph, a vertical progress rail against a
   video that holds still, a spec table that is an accordion with its numbers
   in a right-hand column, a comparison whose own side is raised out of the
   table, and a floating dock at the foot. Each of those is below, struck off
   this site's tokens.

   ONE FACE, TABULAR FIGURES. No mono for the metric column. This
   system says, in phenome-glass.css's own words, "There is no second face" —
   a column of numbers lines up because the figures are TABULAR. So the metric
   column below is `font-variant-numeric: tabular-nums` with a little tracking,
   which is the same mechanism and no new download.
   ========================================================================== */

.pdp {
  /* Local names only. Nothing here leaks past .pdp and nothing here invents a
     value: each is an alias so the rules below read as intent rather than as a
     var() chain three deep. */
  --pdp-hair:   var(--divider);
  --pdp-rule:   var(--border-strong);
  --pdp-dark:   #0f2350e6;          /* the site's dark glass — glass.css:621 */
  --pdp-ease:   var(--ease-frosted-out);
  --pdp-quick:  var(--ph-dur-fast);
  --pdp-slow:   var(--ph-dur-base);
  /* The buy column parks under the nav plus one gutter. Read off --ph-nav-h so
     the 900px media query in shared.css that shortens the bar cannot leave a
     16px gap here. */
  --pdp-stick:  calc(var(--ph-nav-h) + 18px);
}

/* ---------------------------------------------------------------------------
   1 · THE HERO · a mosaic on the left, a column that sticks on the right
   ------------------------------------------------------------------------ */

/* THE HEAD IS BACK IN THE COLUMN (2026-09-14, later the same day, by request).
   Nothing sits above `.buy` now, so the hero is two tracks and only two: the
   frame's top edge and the product's name start on the same line, and the
   right-hand track carries the whole read — name, promise, lede, then the
   three choices and the price. See the head's own block below for the sizes
   that come with the move.

   The tracks: the media is a fraction and the column is fixed, so the block
   reflows continuously instead of snapping. 448 is narrow enough to read as a
   column beside a large picture and wide enough for eight size chips on one
   line, which is what sets the floor. */
.pdp .buy {
  position: relative;
  grid-template-columns: minmax(0, 1fr) 448px;
  gap: clamp(40px, 4.4vw, 72px);
  margin-top: 0;
}
/* 84px of hero padding plus 34 of grid margin put 118px of empty grey between
   the nav and the film. shared.css:906 spends that 84 on every page because the
   nav is 80% white with no border and the grey at the top of the hero is what
   makes its bottom edge visible — the ramp is a BACKGROUND though, not the
   padding, so shortening the padding keeps the edge and gives back the air.
   40px is enough that the frame does not touch the bar. */
.pdp .hero { padding-top: 40px; }

/* ---- the head, INSIDE THE COLUMN -------------------------------------------
   MOVED BACK OFF THE TOP, 2026-09-14, by request: the hero is a left/right
   block again — the frame on the left, and on the right one column that opens
   with what the product is and runs straight down into how you buy it. The
   head above both tracks framed the product as one centred statement, but it
   also put 200px of centred type between the nav and everything, and it left
   the column starting cold on the word "Material".

   THE SIZES COME BACK DOWN WITH IT. A 56px display line is a line for a
   760px measure; in a 448px column it wraps to four lines and stops being a
   display. So the rungs are re-set for the column's width and the ORDER of
   the rungs is unchanged — name, promise, lede — with the name taking the
   weight again because at this scale it is the only one that can carry it.
   Left-aligned, no `buy-head`: shared.css:2023 centres that class and its
   lede, which is the one thing this arrangement must not do.

   AND THE SIZES CAME PART OF THE WAY BACK UP, once the three accordion panels
   at the foot of the column were removed. That removal took ~190px out of the
   column and left it 76px SHORTER than the frame beside it, which is the one
   proportion this arrangement cannot have: a right track that stops early
   leaves the picture hanging on its own. So the head absorbs the difference —
   a rung on the name, a rung on the promise, and the lede up to 16.5 where it
   takes a fourth line. That is deliberate rather than incidental: the head is
   the only block in the column whose height is free, because everything below
   it is a control whose size is set by what it has to be able to hit.
   The two tracks now finish level at any width where `.wrap-wide` is capped
   (~1400 and up). Between 1024 and there the frame is a fraction of a
   narrowing track and shortens while the column does not, so the column leads
   — unavoidable without capping the frame, and the frame is the hero. */
.pdp .buy-col > .pdp-head {
  margin: 0 0 clamp(30px, 3.7vw, 53px);
  padding-bottom: clamp(26px, 3.1vw, 44px);
  border-bottom: 1px solid var(--pdp-hair);
  text-align: left;
}
.pdp .pdp-head .pdp-name {
  margin: 0;
  font-size: clamp(32px, 3.3vw, 48px);
  line-height: 1.06;
  letter-spacing: var(--ph-tr-32-600, -0.02em);
  font-weight: var(--ph-w-600);
  color: var(--ink-900);
  text-wrap: balance;
}
.pdp .pdp-head .pdp-tagline {
  margin: 16px 0 0;
  /* UNITLESS LINE-HEIGHT, deliberately, where the rest of this sheet takes the
     kit's paired tokens. `--ph-lh-19` is a fixed 23px, and the two breakpoints
     below re-size this line — a fixed leading under a changed size is how the
     two lines of "Your data, on your finger." came to overlap at 420. */
  font-size: clamp(20px, 1.6vw, 23px); line-height: 1.25;
  letter-spacing: var(--ph-tr-19-400);
  font-weight: var(--ph-w-600);
  color: var(--ph-accent);
  text-wrap: balance;
}
.pdp .pdp-head .lede {
  margin: 18px 0 0; max-width: none;
  /* 16.5/1.6 written out: the kit's scale jumps 14 → 17 and neither is right
     here — 17 makes the lede argue with the promise above it, 14 reads as fine
     print. The half-pixel is what puts the paragraph on four lines rather than
     three, which is where the column's height comes from. */
  font-size: 17px; line-height: 1.6;
  letter-spacing: normal;
  color: var(--ph-text-2);
  text-wrap: pretty;
}
/* The column's first option opens with no rule and no padding above it — the
   head's own bottom rule is already the line between them. `:first-of-type`
   is gone with the head that made it true: both are <div>s, so the head is
   the first of its type now and the rule would have missed. */
.pdp .buy-col > .buy-opt:first-child,
.pdp .buy-col > .pdp-head + .buy-opt { border-top: 0; padding-top: 0; }
.pdp .buy-col > .pdp-head + .buy-opt .pdp-opt-k { margin-top: 0; }

/* `align-self: start` IS THE STICKY, and it took a measurement to find. The
   grid's computed `align-items` is `stretch`, not the `start` shared.css:2041
   asks for — something after it in the cascade wins — so the column was being
   stretched to the full 1,355px row height. A grid item that is exactly as tall
   as its row has ZERO sticky travel, which is why `position: sticky` appeared
   to do nothing at all rather than doing something wrong. Stated here, on this
   page's own selector, rather than by editing the shared sheet 82 pages read.

   THE COLUMN NO LONGER ACTUALLY TRAVELS, 2026-09-14, and that is worth saying
   out loud rather than leaving as a rule that looks live. The two tracks are
   the SAME HEIGHT now by construction — 922 against the frame's 923 at 1440,
   922 against 925 at 1920 — because the head above absorbs whatever the
   controls below it do not fill. Equal heights means zero sticky travel, so
   `sticky` does nothing today. It is kept, not deleted: it is correct the
   moment the column shortens or the frame grows, and two tracks finishing
   level is the right reading of a left/right block anyway. `align-self: start`
   stays for the same reason, and because without it the column would be
   stretched rather than measured — the bug this comment was written for.
   Note which way the stretch runs: `.pdp-gal` has no `align-self`, so it takes
   the row height, and below ~1400 (where the frame is a fraction of a
   narrowing track) the column is what sets that row. */
.pdp .buy-col { position: sticky; top: var(--pdp-stick); align-self: start; }

/* WHAT THIS DELIBERATELY DOES NOT DO, because the first attempt did and it was
   worse: cap the column's height and let it scroll inside itself. Measured at
   1440x900 the column is 968px against 838px of room, so the cap produced a
   scrollbar INSIDE a page column at rest — a second scroll region a reader has
   to discover, to fix 130px of overhang.
   Left uncapped, `sticky` does the honest thing instead: the column pins for
   the ~390px of travel the media column has on it, and the moment it releases
   the foot of the column comes into view with the page. The overhang is not
   the bug; the inner scrollbar
   was. */

/* ---- the gallery ---------------------------------------------------------
   ONE FRAME, SEVEN SLIDES, ROTATING (2026-09-14). The six-tile mosaic under the
   film is gone; its pictures are slides in the frame now, after the film: a
   sideways track, a glass pill in the
   bottom-right corner with previous / dots / next, and the current dot drawn
   long and filling over the slide's dwell so the reader can see the frame is
   about to move. The history below explains the 4:5 frame, which stays.

   THE BIG FRAME IS A FILM, 4:5, AND IT CHANGES WITH THE SWATCH. It held the
   edge-on studio stills through two passes and both were wrong for the same
   reason: a ring photographed side-on in a beige sweep is a specification, not
   a hero. The colourway footage in the shoot is five scenes with one ring in
   each — black over ink mountains, white over a cloud bank, gold in gold water,
   silver on dark drape — so the asset that makes this page look like a brand is
   also, exactly, the asset that answers "show me that colour". One decision
   covers both.
   4:5 because that is the orientation those shots were composed in. A 4:3
   landscape crop of a 9:16 frame throws away the scene, and the scene is the
   whole reason the footage is worth using. The stills are not thrown away
   either — they move to the first tile, where a plain-ground view of the actual
   product is one glance below the film and still follows the swatch.

   THE TILES ARE SQUARE AND THERE ARE THREE ACROSS. Square is the shape the
   product shots are composed in; three across rather than two is what keeps the
   media column from towering over the buy column now that the frame above them
   is 4:5 — at two across the mosaic alone was 999px and the sticky travel came
   out over 1,100, which stops reading as "the column follows you" and starts
   reading as "the column is stuck".

   The block is a <div>, not a <ul>: it is one control and the tiles are buttons
   inside it. */
.pdp .pdp-gal { display: grid; gap: 12px; }

.pdp .pdp-gal-main {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--ph-r18);
  overflow: hidden;
  /* The scenes are dark more often than not, so the frame waits on a deep
     navy rather than a pale recess: a light box that fills with a black
     mountain range flashes, and the flash is the first thing a reader sees. */
  background: var(--phenome-blue-900);
  box-shadow: var(--gl-inner);
  touch-action: pan-y;
}
/* Beside the column the frame keeps its 4:5 only up to what the screen shows
   under the bar: on a shorter screen it is held to that height at the track's
   full width, so its foot stays above the fold, and it rides along while the
   column beside it scrolls. */
@media (min-width: 1280px) {
  .pdp .pdp-gal-main {
    position: sticky; top: calc(var(--ph-nav-h, 44px) + 20px);
    width: 100%; max-height: calc(100vh - var(--ph-nav-h, 44px) - 60px);
  }
}

/* THE TRACK. Without the script it is a snap scroller, so every slide is
   reachable by swiping or shift-wheel. With it (`data-live`), the slides stack
   in one cell and each is translated by its offset from the current slide —
   pdp.js writes `--o` and decides which slides animate, so a wrap from the last
   slide to the first slides one step rather than rewinding through all seven. */
.pdp .pdp-gal-track {
  position: absolute; inset: 0;
  display: flex;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.pdp .pdp-gal-track::-webkit-scrollbar { display: none; }
.pdp .pdp-slide {
  position: relative; flex: 0 0 100%;
  scroll-snap-align: start;
  overflow: hidden;
  background: var(--gl-tint-sunk);
}
.pdp .pdp-slide--film { background: var(--phenome-blue-900); }
.pdp .pdp-slide > img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
/* `clip`, not `hidden`, and no snapping. The translated slides are scrollable
   overflow of the track, so with `hidden` + snap the browser scrolled the track
   to snap onto them and the whole row drifted a slide-width at a time. `clip`
   is not a scroll container at all. */
.pdp .pdp-gal-main[data-live] .pdp-gal-track { display: block; overflow: hidden; overflow: clip; scroll-snap-type: none; }
.pdp .pdp-gal-main[data-live] .pdp-slide {
  scroll-snap-align: none;
  position: absolute; inset: 0;
  transform: translate3d(calc(var(--o, 0) * 100%), 0, 0);
  transition: transform 760ms cubic-bezier(.65, 0, .25, 1);
}
.pdp .pdp-gal-main[data-live] .pdp-slide[data-snap] { transition: none; }
/* The picture inside eases a touch slower than its slide, so the move reads as
   a camera pan rather than a card being swapped. */
.pdp .pdp-gal-main[data-live] .pdp-slide > img,
.pdp .pdp-gal-main[data-live] .pdp-slide > video {
  transform: translate3d(calc(var(--o, 0) * -12%), 0, 0) scale(1.02);
  transition: transform 900ms cubic-bezier(.65, 0, .25, 1), opacity 520ms var(--pdp-ease);
}
.pdp .pdp-gal-main[data-live] .pdp-slide[data-snap] > img,
.pdp .pdp-gal-main[data-live] .pdp-slide[data-snap] > video { transition: opacity 520ms var(--pdp-ease); }

/* The studio stills stack inside their slide and crossfade with the swatch. */
.pdp .pdp-slide--still > img[data-finish] {
  position: absolute; inset: 0;
  opacity: 0;
}
.pdp .pdp-slide--still > img[data-finish].on { opacity: 1; }
/* THE PLATE, 2026-09-17. The nine finish stills are renders on transparency,
   not photographs of a scene, so they want the opposite of `cover`: contained,
   with air around them, on the recess wash the rest of the page uses for a
   product on a plain ground. Cropping a render to fill a 4:5 frame cuts the
   object the slide exists to show. */
.pdp .pdp-slide--still.is-plate { background: var(--gl-tint-sunk); }
.pdp .pdp-slide--still.is-plate > img[data-finish] {
  padding: clamp(18px, 3vw, 46px);
  object-fit: contain;
}
.pdp .pdp-gal-main:not([data-live]) .pdp-slide--still > img[data-finish]:first-of-type { opacity: 1; }

/* The finish tag belongs to the two slides that follow the swatch; on the
   product shots it would be naming a colour the picture is not showing. */
.pdp .pdp-gal-main[data-live] .pdp-gal-tag { transition: opacity var(--pdp-slow) var(--pdp-ease); }
.pdp .pdp-gal-main[data-live]:not([data-follow]) .pdp-gal-tag { opacity: 0; }

/* ---- the pagination pill ------------------------------------------------
   Same dark glass as the tools, so the frame's furniture is one family. The
   dots are 6px marks inside 20px buttons — the mark stays quiet, the target
   stays hittable. The current one is 32px long and fills over `--dwell`; the
   fill pauses with the slideshow, so it is always an honest countdown. */
.pdp .pdp-gal-nav {
  position: absolute; right: 16px; bottom: 16px; z-index: 2;
  display: flex; align-items: center; gap: 2px;
  height: 40px; padding: 0 6px; border-radius: var(--ph-r56);
  background: #0a1e5757;
  -webkit-backdrop-filter: blur(18px) saturate(130%); backdrop-filter: blur(18px) saturate(130%);
  box-shadow: inset 0 0 0 1px #ffffff2b;
  color: #fff;
}
.pdp .pdp-gal-arrow,
.pdp .pdp-gal-dot {
  display: flex; align-items: center; justify-content: center;
  padding: 0; border: 0; background: none; color: inherit; cursor: pointer;
  border-radius: var(--ph-r56);
}
.pdp .pdp-gal-arrow { width: 30px; height: 30px; opacity: .8; transition: opacity var(--pdp-quick) var(--pdp-ease), background var(--pdp-quick) var(--pdp-ease); }
.pdp .pdp-gal-arrow:hover { opacity: 1; background: #ffffff1f; }
.pdp .pdp-gal-arrow svg { width: 16px; height: 16px; display: block; }
.pdp .pdp-gal-dots { display: flex; align-items: center; padding: 0 4px; }
/* The current dot changes length instantly; only its fill (a transform) moves.
   A width transition here re-lays out the pill on every frame of the change. */
.pdp .pdp-gal-dot { width: 14px; height: 20px; }
.pdp .pdp-gal-dot i {
  position: relative; display: block; overflow: hidden;
  width: 6px; height: 6px; border-radius: 3px;
  background: #ffffff66;
  transition: background var(--pdp-quick) var(--pdp-ease);
}
.pdp .pdp-gal-dot:hover i { background: #ffffffb3; }
.pdp .pdp-gal-dot[aria-current="true"] { width: 40px; }
.pdp .pdp-gal-dot[aria-current="true"] i { width: 32px; background: #ffffff59; }
.pdp .pdp-gal-dot[aria-current="true"] i::after {
  content: ""; position: absolute; inset: 0;
  background: #fff; border-radius: inherit;
  transform-origin: left center; transform: scaleX(0);
  animation: pdp-dwell var(--dwell, 5s) linear forwards;
}
.pdp .pdp-gal-main[data-held] .pdp-gal-dot[aria-current="true"] i::after,
.pdp .pdp-gal-main[data-hover] .pdp-gal-dot[aria-current="true"] i::after { animation-play-state: paused; }
/* Held for good (the pause button or reduced motion): the countdown is not
   paused, it is not happening, so the bar reads full rather than frozen. */
.pdp .pdp-gal-main[data-held] .pdp-gal-dot[aria-current="true"] i::after { animation: none; transform: none; }
@keyframes pdp-dwell { to { transform: scaleX(1); } }
.pdp .pdp-gal-arrow:focus-visible,
.pdp .pdp-gal-dot:focus-visible { outline: var(--ph-focus-w) solid #fff; outline-offset: 1px; }
/* FOUR CLIPS, FIVE FINISHES. Graphite and Onyx share the black scene the same
   way they share the black still — the ring is black in both materials, so a
   fifth encode would be a second copy of one picture. The films are keyed by
   CLIP, the stills by FINISH, and pdp.js maps one to the other.
   All four ship in the markup and crossfade on opacity. Only the current one is
   playing: four simultaneously decoding videos is four decoders' worth of
   battery for three frames nobody can see. */
.pdp .pdp-gal-main video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 520ms var(--pdp-ease);
}
.pdp .pdp-gal-main video.on { opacity: 1; }
/* No `autoplay` attribute anywhere in this frame — the script starts the
   current clip. With the script off, every video sits on its own poster, which
   is a frame of itself rather than a studio still standing in for a cloud bank:
   the fallback is the same picture, held still. This rule is what makes the
   first one visible until the script takes over. */
.pdp .pdp-gal-main:not([data-live]) video:first-of-type { opacity: 1; }

/* THE FURNITURE SITS AT THE TOP OF THE FRAME, and that is a fold decision
   rather than a taste one. The frame is 923px tall at 1440 and the fold is at
   about 900, so anything parked along its foot — the colourway tag, the pause
   control — was 85px below the screen. The tag is the confirmation for the
   swatch that was just clicked, and a confirmation you have to scroll to is not
   one; the pause control is the mechanism WCAG 2.2.2 asks for, and a mechanism
   that has to be found is weak even when it is technically present.
   So the gradient runs from the top now, and both live under it. */
.pdp .pdp-gal-main::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 24%;
  background: linear-gradient(#0a1e5761, #0a1e5700);
  pointer-events: none;
}

/* The frame's two controls. THE HOLD BUTTON IS NOT OPTIONAL: the loops run from
   3.9 to 6.9 seconds and then repeat forever, and WCAG 2.2.2 asks for a way to
   stop anything that moves for more than five. It is also simply the right
   thing for a film that starts on its own.

   DARK GLASS, WHITE GLYPH — not .buy-arrow's light disc with dark ink, which is
   what these were first. shared.css can use a light disc because it sits on ONE
   photograph per page and states as much ("it has to read on both"); this frame
   plays four scenes and two of them are nearly black. A 42%-white disc over the
   ink mountains composites to about #6d6d6d, and --ink-900 on that measures
   1.9:1 — the glyph disappears exactly when the picture is at its most
   dramatic. Dark glass inverts the problem into one that has no failing case:
   the darkest ground it sits on is black, where it stays dark, and the lightest
   is the cloud bank, where 34% navy still holds white type at over 7:1. It is
   also how every video player on earth draws a control over film. */
.pdp .pdp-gal-tools {
  position: absolute; right: 14px; top: 14px; z-index: 2;
  display: flex; gap: 9px;
}
.pdp .pdp-gal-tool {
  width: 44px; height: 44px; border-radius: 50%; padding: 0;
  display: flex; align-items: center; justify-content: center;
  /* Light frosted glass with an ink glyph. The glyph sits on the near opaque
     disc, not on the photograph, so it keeps its contrast over dark scenes, and
     the soft shadow keeps the disc visible over light ones. */
  border: 1px solid rgba(0, 0, 0, .06);
  background: rgba(255, 255, 255, .82);
  -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%);
  box-shadow: 0 2px 12px rgba(0, 0, 0, .14);
  color: #1d1d1f; cursor: pointer;
  /* The HOLD button stays visible; the expand button waits for a pointer. A
     pause control a reader has to discover by hovering is not a mechanism. */
  opacity: 0;
  transition: opacity var(--pdp-quick) var(--pdp-ease),
              background var(--pdp-quick) var(--pdp-ease),
              transform var(--pdp-quick) var(--pdp-ease);
}
.pdp .pdp-gal-hold { opacity: 1; }
.pdp .pdp-gal-main:hover .pdp-gal-tool,
.pdp .pdp-gal-tool:focus-visible { opacity: 1; }
.pdp .pdp-gal-tool:hover { background: rgba(255, 255, 255, .96); }
.pdp .pdp-gal-tool:active { transform: scale(.95); }
.pdp .pdp-gal-tool:focus-visible {
  outline: var(--ph-focus-w) solid var(--ph-accent, #0071e3); outline-offset: 2px;
}
.pdp .pdp-gal-tool svg { width: 17px; height: 17px; display: block; }
/* One button, two glyphs, the state picks — the same mechanism the timeline's
   film control uses, so there is one pause button design on this page. */
.pdp .pdp-gal-hold .i-play { display: none; }
.pdp .pdp-gal-hold[data-paused] .i-play { display: block; }
.pdp .pdp-gal-hold[data-paused] .i-pause { display: none; }

/* The finish name, drawn on the photograph rather than only in the column.
   It is the confirmation for the swatch that was just clicked, at the place the
   eye went — which is the picture, not the label 600px to the right. */
.pdp .pdp-gal-tag {
  position: absolute; left: 16px; top: 20px; z-index: 2;
  display: inline-flex; align-items: center; gap: 9px;
  height: 32px; padding: 0 14px; border-radius: var(--ph-r56);
  /* NAVY glass, not white. Over a beige still 62% white was a pill; over a
     running film it is a sticker, and a WHITE glass pill carrying white type
     has no failing case only on the dark scenes — over the cloud bank the same
     fill composited to about #7d8ba5 and the label came in at 4.3:1, which is
     a label you can read rather than one you can see. 34% of the brand navy
     goes the other way: it darkens whatever is behind it, so one value holds
     across a cloud bank and an ink mountain in the same frame. */
  background: #0a1e5757;
  -webkit-backdrop-filter: blur(18px) saturate(130%); backdrop-filter: blur(18px) saturate(130%);
  box-shadow: inset 0 0 0 1px #ffffff33;
  font-size: var(--ph-fs-13); font-weight: var(--ph-w-600);
  letter-spacing: normal;
  color: #fff; white-space: nowrap;
  /* NO TEXT-SHADOW, 2026-09-09 — a site rule now. A glow behind type over a
     photograph is a legibility patch, and this tag already has the real fix
     two lines up: a 34% navy fill with an 18px blur behind it, which is a
     surface the label sits ON rather than a smear it sits in. With both, the
     shadow was doing nothing but softening its own glyph edges. */
}
/* The bead in the tag takes the same three sampled tones as the swatch below —
   one gloss treatment for the finish wherever the finish is named. */
.pdp .pdp-gal-tag i {
  /* Size and defaults only; the material is drawn by the shared disc block
     further down. The fallbacks matter here and nowhere else — the tag takes
     its tones from pdp.js as inline custom properties rather than from a
     data-tone, so before the script runs there is nothing to resolve against. */
  --rf-hi: #f8e4c4; --rf-body: #cfa878; --rf-sh: #7d5c3c; --rf-rim: #e6c99e;
  --rf-lift: 15%; --rf-hold: 36%; --rf-fall: 70%;
}


/* ---- the lightbox --------------------------------------------------------
   The one piece of chrome on this page that covers the page. It is a
   <dialog>-shaped thing without <dialog>: shared.js already owns the mega-menu
   overlay and two competing top-layer elements is a bug waiting for a slow
   connection. z-index 120 clears .ph-nav (100) and .ph-bar (99). */
.pdp .pdp-lb {
  position: fixed; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(16px, 4vw, 56px);
  background: #061029d1;
  -webkit-backdrop-filter: blur(18px) saturate(120%);
  backdrop-filter: blur(18px) saturate(120%);
  opacity: 0; visibility: hidden;
  transition: opacity var(--pdp-slow) var(--pdp-ease),
              visibility 0s linear var(--pdp-slow);
}
.pdp .pdp-lb.on { opacity: 1; visibility: visible; transition-delay: 0s; }
.pdp .pdp-lb-frame {
  position: relative;
  max-width: min(1080px, 100%); max-height: 100%;
  display: flex; align-items: center; justify-content: center;
  transform: scale(.985);
  transition: transform var(--pdp-slow) var(--pdp-ease);
}
.pdp .pdp-lb.on .pdp-lb-frame { transform: none; }
.pdp .pdp-lb-frame > img,
.pdp .pdp-lb-frame > video {
  max-width: 100%; max-height: calc(100vh - clamp(120px, 14vw, 190px));
  width: auto; height: auto; display: block;
  border-radius: var(--ph-r18);
  background: var(--gl-tint-sunk);
  box-shadow: 0 40px 90px -40px #02081be0;
}
.pdp .pdp-lb-cap {
  position: absolute; left: 0; right: 0; bottom: -38px;
  text-align: center;
  font-size: var(--ph-fs-14); line-height: var(--ph-lh-14);
  color: #ffffffb8;
}
/* Three controls, one shape: the same 44px glass disc as the gallery's zoom, so
   the overlay reads as the same object opened rather than a second design. */
.pdp .pdp-lb-btn {
  position: absolute; z-index: 1;
  width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid #ffffff2e; background: #ffffff1f;
  -webkit-backdrop-filter: var(--gl-blur-thin); backdrop-filter: var(--gl-blur-thin);
  color: #fff; cursor: pointer;
  transition: background var(--pdp-quick) var(--pdp-ease);
}
.pdp .pdp-lb-btn:hover { background: #ffffff33; }
.pdp .pdp-lb-btn svg { width: 18px; height: 18px; display: block; }
.pdp .pdp-lb-close { top: clamp(14px, 3vw, 26px); right: clamp(14px, 3vw, 26px); position: fixed; }
.pdp .pdp-lb-prev { left: clamp(10px, 2vw, 22px); top: 50%; transform: translateY(-50%); position: fixed; }
.pdp .pdp-lb-next { right: clamp(10px, 2vw, 22px); top: 50%; transform: translateY(-50%); position: fixed; }
html.pdp-lb-open, body.pdp-lb-open { overflow: hidden; }

/* ---- the option controls, which used to be pictures of themselves ---------
   .buy-choice, .buy-swatch and .buy-chips .tag all shipped with an `.on` class
   painted on and nothing behind it. They keep every one of shared.css's own
   values; what is added is the part that was missing — a cursor, a hover, a
   focus ring, and a pressed state that is a fifth of a second rather than
   instant. The elements become <button>s in the markup, so :disabled below is
   what greys a finish the chosen material does not come in. */
.pdp .buy-choice,
.pdp .buy-swatch,
.pdp .buy-chips .tag {
  cursor: pointer; -webkit-appearance: none; appearance: none;
  font: inherit; text-align: left;
  transition: border-color var(--pdp-quick) var(--pdp-ease),
              box-shadow var(--pdp-quick) var(--pdp-ease),
              transform var(--pdp-quick) var(--pdp-ease),
              color var(--pdp-quick) var(--pdp-ease),
              opacity var(--pdp-quick) var(--pdp-ease);
}
/* ---- THE MATERIAL CHOICE IS THE COLUMN'S BIGGEST DECISION AND WAS ITS
   QUIETEST CONTROL. Measured at 1440: 216x65 cards, a 17px name and a 14px
   grey price, sitting directly above 30px gloss swatches and 44px size chips.
   So the control that sets the price — £179 against £199, and the only choice
   on this page a reader cannot change later without returning the ring — was
   the least visible thing in the column, and the beads under it pulled the eye
   first. That is the hierarchy upside down.

   It is a real pair of cards now: 96px tall, the name at 21/600, and the price
   in primary ink at 19 rather than as grey supporting text, because the price
   IS the decision being made. Nothing is added to the markup — the same two
   spans, given the weight they were always carrying.

   AND THE CHOSEN ONE LIFTS. shared.css:2167 says the selected state must be a
   border colour and nothing else, under `tokens.elevation ELEVATION SISTEMI
   YOK` — but that is the old doctrine of the captured mirror, and
   phenome-glass.css replaced it wholesale with a system that draws --gl-shadow
   on every card, tile and panel including this page's own buy card, comparison
   columns and dock. The rule to follow is the live one. So unselected keeps
   glass.css's recess tone and the chosen card rises out of it to white with the
   accent ring — which is exactly how the comparison section marks its chosen
   material, so the page says "this one" the same way in both places. */
.pdp .buy-choices { grid-template-columns: 1fr 1fr; gap: 14px; }
/* THREE MATERIALS SINCE 2026-09-17. The gap comes in with the third column
   because 448 minus two 14px gaps leaves 140 a card, and "Brushed silver"
   never had to fit there — the name that does is "Ceramic", at 10px of
   padding either side. */
.pdp .buy-choices.is-three { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.pdp .buy-choices.is-three .buy-choice { padding-inline: 12px; }
/* BOTH CARDS ARE WHITE PANES; only the state differs. The first attempt left
   the unselected one on glass.css's recess tone and it disappeared outright —
   `--gl-tint-sunk` is #f4f6fb and the hero's ground ramp is the same value, so
   "Ceramic £199" floated on the page with no card around it at all. A recess
   only reads as a recess against something lighter than itself.
   The ladder is three steps on one white ground instead: hairline at rest, a
   soft drop on hover, the lift and the accent ring when chosen. */
.pdp .buy-choice {
  padding: 19px 20px 17px;
  border-radius: var(--ph-r14);
  border-color: transparent;
  background: var(--gl-tint-live);
  box-shadow: var(--gl-inner);
  display: grid; align-content: center; gap: 5px;
  min-height: 96px;
}
.pdp .buy-choice .n {
  font-size: var(--ph-fs-21); line-height: var(--ph-lh-21);
  letter-spacing: var(--ph-tr-21-600);
  color: var(--ink-900);
}
.pdp .buy-choice .p {
  font-size: var(--ph-fs-19); line-height: var(--ph-lh-19);
  font-weight: var(--ph-w-400); letter-spacing: var(--ph-tr-19-400);
  color: var(--ph-text-2); font-variant-numeric: tabular-nums;
}
.pdp .buy-choice:hover:not(.on) { box-shadow: var(--gl-shadow), var(--gl-inner); }
.pdp .buy-choice:active { transform: scale(.99); }
.pdp .buy-choice.on { box-shadow: var(--gl-shadow-lift), inset 0 0 0 2px var(--ph-accent); }
.pdp .buy-choice.on .p { color: var(--ink-900); }
/* THE ARCTIC WHITE SWATCH WAS INVISIBLE. #EFEFF2 on a #ffffff page has no edge
   and shared.css draws the swatch as a bare `background: var(--sw)` — so one of
   the five controls simply was not there. The hairline goes on all five rather
   than on the pale one: it is the same 6% ink `--gl-inner` uses to give every
   other rimless surface on this site a boundary, it is invisible on graphite
   and onyx, and a per-swatch exception would be a rule that has to be revisited
   every time a colourway is added. */
.pdp .buy-swatch {
  border: 0; padding: 0;
  box-shadow: inset 0 0 0 1px #10214b1f;
}
.pdp .buy-swatch:hover { transform: scale(1.08); }
.pdp .buy-swatch:active { transform: scale(1.01); }
/* There is deliberately no `[disabled]` rule here. An earlier version dimmed
   the three finishes the chosen material does not come in, and pdp.js explains
   at length why that was wrong: a disabled swatch can never reach the code that
   makes choosing a finish also choose its material, so it was a control that
   looked live and was not. All five are live. */

/* ---- THE SWATCHES ARE THE FINISHES, gloss included ----------------------
   shared.css draws them as `background: var(--sw)` — one flat hex per ring, so
   Gold was a mustard disc and Arctic White was a hole in the page. A swatch
   whose entire job is to stand for a polished object cannot be flat.

   The treatment is lifted WHOLE from devices/ring/ring.css's `.ringfam-dot`,
   including its sampled values, because the sibling page already solved this
   and two answers to one question is one answer too many. Its reasoning, kept
   verbatim: each dot is asked to look like the ring it stands for, and the
   three tones it takes are sampled off that ring's own photograph rather than
   named from memory — a highlight, the body, and the shaded side, with the
   gradient putting them where the light puts them: lit from the upper left,
   body through the middle, shade falling away bottom-right. Two of the five are
   black and they are not the same black — the ceramic is a deep gloss with a
   soft sheen, the titanium is near-graphite with a hard chrome highlight.

   WHAT IS ADDED HERE, and only because these are 30px where the ring page's are
   12: a second, tighter radial for the specular — at 12px the body gradient IS
   the highlight, at 30px it needs an actual catchlight or the bead looks matte —
   and one short drop so it sits ON the page rather than in it. The drop is
   allowed here and is not on the ring page because that page's §1 strips every
   shadow; this one is under phenome-glass.css, which draws them. */
.pdp .buy-swatches { gap: 15px; margin-top: 18px; }

/* ============================ THE FINISH DISCS ============================
   PORTED WHOLE FROM /devices/ring/ (ring.css § 4, .ringfam-dot), 2026-09-09,
   because two pages were drawing the same five finishes two different ways and
   only one of them was drawing a material.

   WHAT WAS HERE: a radial-gradient bead — a sphere with a catchlight at 31%/23%
   and a white specular blob over it. That is a snooker ball. It says "this
   swatch is gold" and nothing else, and the whole question these controls exist
   to ask is which of two MATERIALS you would wear, which a bead cannot answer
   because a brushed metal and a fired glaze return light in completely
   different ways.

   WHAT REPLACES IT:

     · a BROAD SPECULAR BAND on a 128deg axis with a fairly crisp upper edge —
       a rolled surface catching a window, not a point light on a sphere;
     · a thin DARKER SLIVER outboard of it at the top-left, which is what makes
       the band read as a reflection rather than as the object being paler;
     · a soft BOUNCE along the lower edge, light coming back off whatever the
       ring is sitting on;
     · four stops that MOVE PER FAMILY rather than four colours per swatch:
       ceramic lifts at 7% and falls by 51% (the wet line a glaze gives),
       titanium takes 15% to arrive and 70% to leave (the same light smeared
       along a grain).

   And for titanium:
   THE TITANIUM IS BRUSHED. ::after lays a real grain in `overlay`, so each
   groove lightens or darkens in proportion to what is under it — bright where
   the specular band crosses, nearly gone in the shaded corner. The hard stops
   at 4px are not a style choice; a soft repeating gradient under about 3px gets
   dithered by the rasteriser and comes out looking like woven fabric. The full
   derivation is in ring.css beside the original and is not repeated here.

   ONE BLOCK, THREE COMPONENTS. The buy column's swatches, the comparison's
   colourway dots and the bead inside the film's tag are the same object at
   three sizes, so they share the construction and differ only in diameter.

   THE DROP STAYS AND THE RING PAGE'S DOES NOT: that page's § 1 strips every
   shadow on itself; this one lives under phenome-glass.css, which draws them.
   The inset hairline goes, though — with the bounce along the lower edge doing
   the silhouette, a drawn outline around a rendered material is an interface
   element sitting on top of an object.
   ======================================================================== */
.pdp .buy-swatch,
.pdp .pdp-vs-dot,
.pdp .pdp-gal-tag i {
  position: relative;
  isolation: isolate;          /* keeps the grain's blend inside the disc */
  border-radius: 50%;
  background:
    /* the bounce, under the lower edge */
    radial-gradient(58% 42% at 62% 102%, var(--rf-rim) 0%, transparent 68%),
    /* the specular band, and the dark sliver outboard of it */
    linear-gradient(128deg,
      var(--rf-sh)   0%,
      var(--rf-hi)   var(--rf-lift),
      var(--rf-hi)   var(--rf-hold),
      var(--rf-body) var(--rf-fall),
      var(--rf-body) 80%,
      var(--rf-sh)   100%);
}
.pdp .buy-swatch    { width: 30px; height: 30px; box-shadow: 0 2px 5px -2px #10214b47; }
.pdp .pdp-vs-dot    { width: 26px; height: 26px; box-shadow: 0 2px 5px -2px #10214b47; }
.pdp .pdp-gal-tag i { width: 11px; height: 11px; box-shadow: none; }

/* CERAMIC — a glaze. The band lifts almost immediately off the edge, holds
   narrow, and falls away early into a large untroubled body. */
.pdp [data-tone^="c-"] { --rf-lift: 7%;  --rf-hold: 23%; --rf-fall: 51%; }
/* METAL — the band takes 15% to arrive and 70% to leave, which is the same
   light spread along the grain instead of returned as a line. */
.pdp [data-tone^="m-"] { --rf-lift: 15%; --rf-hold: 36%; --rf-fall: 70%; }
/* MATTE — no specular band at all: a diffuse surface returns the room as a
   wide slow ramp rather than a line, so the highlight arrives late, never holds
   and falls away across almost the whole disc. It carries no grain either, and
   that pair is what lets you tell it from Metal with the colour removed. */
.pdp [data-tone^="x-"] { --rf-lift: 30%; --rf-hold: 34%; --rf-fall: 92%; }

.pdp .buy-swatch[data-tone^="m-"]::after,
.pdp .pdp-vs-dot[data-tone^="m-"]::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  pointer-events: none;
  mix-blend-mode: overlay;
  opacity: var(--rf-brush);
  background:
    repeating-linear-gradient(122deg,
      rgba(255, 255, 255, .26) 0, rgba(255, 255, 255, .26) 1.2px,
      rgba(0, 0, 0, .14)     1.2px, rgba(0, 0, 0, .14)     2.6px,
      rgba(255, 255, 255, 0) 2.6px, rgba(255, 255, 255, 0) 4px),
    repeating-linear-gradient(122deg,
      rgba(255, 255, 255, .15) 0,
      rgba(255, 255, 255, 0)   6px,
      rgba(0, 0, 0, .12)       12px);
  /* The grain turns away from the eye at the rim of a curved surface. */
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 46%, rgba(0, 0, 0, .3) 86%, transparent 100%);
          mask-image: radial-gradient(circle at 50% 50%, #000 46%, rgba(0, 0, 0, .3) 86%, transparent 100%);
}

/* THE TONE TABLE IS KEYED ON THE ATTRIBUTE, NOT ON THE COMPONENT, so one table
   feeds every bead on the page. Values are ring.css's — sampled off each ring's
   own photograph rather than named from memory.

   Two of them are called Black and they are not the same black. The ceramic is
   a deep gloss with no warmth in it; the titanium is graphite, a lighter body
   with a paler and much wider reflection, because a brushed dark metal never
   gets as close to black as a fired glaze does. The highlight tints with the
   metal on the titaniums and does not on the ceramics — a glaze reflects the
   room, a metal reflects the room through its own colour, which is why the
   gold's highlight is cream rather than white. */
.pdp [data-tone="m-black"] {
  /* Overlay doubles a dark base under a white line, so the black metal takes
     the lightest hand or the grain becomes the object. */
  --rf-hi: #b4b3b2; --rf-body: #4a4b4a; --rf-sh: #101110; --rf-rim: #6d6e6d;
  --rf-brush: .5;
}
/* Silver and brushed silver are the same pigment, so the only thing that can
   tell them apart at 30px is the LIGHT: polished returns a hard bright line off
   a darker body and carries almost no grain, brushed spreads the same light
   along the pass and carries all of it. */
.pdp [data-tone="m-silver"] {
  --rf-hi: #ffffff; --rf-body: #b4b5b9; --rf-sh: #4e5055; --rf-rim: #e8e8ea;
  --rf-brush: .3;
}
.pdp [data-tone="m-brushed"] {
  /* The one finish whose NAME is the texture, so it carries it hardest. */
  --rf-hi: #dfdee0; --rf-body: #9d9c9f; --rf-sh: #5c5d61; --rf-rim: #c6c5c7;
  --rf-brush: 1;
}
/* Gold is polished, so it takes silver's light hand of grain. */
.pdp [data-tone="m-gold"] {
  --rf-hi: #fff8e1; --rf-body: #d9b87a; --rf-sh: #5c4822; --rf-rim: #f1e0ad;
  --rf-brush: .3;
}
.pdp [data-tone="x-rose"] {
  --rf-hi: #fbd3cf; --rf-body: #d3aba6; --rf-sh: #8f6560; --rf-rim: #eec4bf;
}
.pdp [data-tone="x-stealth"] {
  --rf-hi: #82817f; --rf-body: #484948; --rf-sh: #151614; --rf-rim: #5e5f5d;
}
.pdp [data-tone="c-black"] {
  --rf-hi: #7e8996; --rf-body: #15171b; --rf-sh: #000000; --rf-rim: #3d444e;
}
.pdp [data-tone="c-pink"] {
  --rf-hi: #fff7f9; --rf-body: #f0c8ce; --rf-sh: #b4868f; --rf-rim: #f6dade;
}
.pdp [data-tone="c-white"] {
  --rf-hi: #ffffff; --rf-body: #dbe0e8; --rf-sh: #98a1b0; --rf-rim: #e4e9f1;
}
/* The chosen one is RINGED, not recoloured and not grown: a swatch whose job is
   to be the ring's colour cannot be dimmed or tinted to show its state. The
   outline replaces shared.css's accent one — navy ink at 2px reads on all five
   beads where the accent blue disappeared into Silver. */
.pdp .buy-swatch.on {
  outline: 2px solid var(--ink-900); outline-offset: 3px;
}

/* The same three tones feed the bead in the film's tag, so the label on the
   picture and the control in the column are visibly one object. The tag gets
   them as inline custom properties from pdp.js rather than from a second table
   of hexes here — one source for the finish's colour, five lines above. */

/* ---- the option groups, retitled ----------------------------------------
   WHAT WAS CUT, and it is most of what made this column feel long:

     "They track exactly the same health data — it's purely a matter of feel
      and finish."                     the line above it already says "same
                                       continuous sensing"
     "Three in titanium, two in ceramic. Picking one picks its material."
                                       instructions for a control, not a fact
                                       about a ring
     "Not sure? Order a free sizing kit and choose later."
                                       the button underneath it is that sentence

   And what replaced the three remaining labels. They were 17px sentences —
   "Material. Titanium or ceramic, same continuous sensing." / "Finish. Choose
   your look: Gold." / "Size. Find your fit — US 8." — three lines of prose
   doing the work of three field names. They are the site's own 12px tracked
   overline now, with the chosen value beside the name in the primary ink, so
   the label is also the confirmation and no line is spent saying so. */
.pdp .pdp-opt-k {
  display: flex; align-items: baseline; gap: 14px;
  margin: 0 0 2px;
  /* BRAND BLUE AND A RUNG LARGER, 2026-09-09. "Material", "Finish" and "Size"
     are the three questions this column asks, and at 12px in --ph-tertiary
     they were the quietest type in it — quieter than the answer beside them.
     They take the accent now, which is also what the eyebrow above them uses,
     so the column reads as one voice asking and the ink answering. 14, not 12:
     with the capitals gone (phenome-glass.css §2c) a 12px label loses the
     width capitals gave it, and a rung up puts it back. */
  font-size: var(--ph-fs-14); line-height: var(--ph-lh-14);
  font-weight: var(--ph-w-600); letter-spacing: normal;
  color: var(--ph-accent);
}
.pdp .pdp-opt-k span {
  color: var(--ink-900); letter-spacing: normal;
  margin-left: auto; text-align: right;
}
.pdp .buy-opt + .buy-opt { margin-top: clamp(20px, 2vw, 26px); }
.pdp .buy-choices { margin-top: 14px; }
/* EIGHT SIZES, ONE ROW. shared.css gives each chip `min-width: 56px` and a 10px
   gap, which is 8x56 + 7x10 = 518 — it fitted the 600px column this page used
   to have and wraps 12 and 13 onto a second row in a 448px one. A size run that
   breaks in the middle reads as two groups of sizes rather than one scale.
   44px still clears the 44px touch floor on its height, and the widest label is
   two digits. */
.pdp .buy-chips { margin-top: 14px; gap: 8px; }
.pdp .buy-chips .tag { min-width: 44px; padding-inline: 8px; }
/* The alternative is a link's worth of type, not a pill's. A full-width bordered
   capsule for "free sizing kit instead" gave a secondary action the same weight
   as the eight chips above it and left a 44px empty box in the column. */
.pdp .buy-alt {
  width: auto; justify-content: flex-start; margin-top: 12px;
  height: auto; min-height: 36px; padding: 0;
  border: 0; background: none; box-shadow: none;
  font-size: var(--ph-fs-14); text-decoration: none;
  /* THE HALF SHADOW, 2026-09-14. Two layers were still drawing behind the
     words: phenome-glass.css gives every `.tag` a blur(14px) backdrop-filter,
     which on a 36px box with no fill paints a soft edge where it meets the
     column, and the 28%-navy underline sat under the baseline like a cast
     shadow. Both go; the chevron carries "this is an action" instead. */
  -webkit-backdrop-filter: none; backdrop-filter: none;
  transition: color var(--ph-dur-base) var(--ease-frosted-out);
  gap: 4px; align-items: center;
}
.pdp .buy-alt::after {
  content: ""; width: 6px; height: 6px; margin-left: 2px;
  border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--ph-dur-base) var(--ease-frosted-out);
}
.pdp .buy-alt:hover::after { transform: translateX(2px) rotate(45deg); }
/* It is a link, so it hovers like one. Being a `.tag` underneath, it was
   picking up the size chips' filled navy hover — and with this rule's 0 padding
   that pill hugged the letters and ran flush into the column's left edge, so it
   read as half a shadow cut off. The background and ink are pinned here. */
.pdp .buy-alt:hover,
.pdp .buy-alt:active {
  border: 0; background: none; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  color: var(--ph-accent-hover);
}
.pdp .buy-alt.on {
  border: 0; color: var(--ink-900); font-weight: var(--ph-w-600);
}

/* The price block loses a line and some air. "or from £16.58/mo. Free shipping
   & sizing kit." said free shipping, and the tick list under it says "Free
   next-day delivery & returns" — the same promise, eleven pixels apart. */
.pdp .buy-price { margin-top: clamp(22px, 2.2vw, 30px); padding: 20px 22px; }
.pdp .buy-price .buy-sub { font-size: var(--ph-fs-12); line-height: var(--ph-lh-12); }
.pdp .buy-price .btn { min-height: 54px; font-size: 18px; font-weight: 600; }
.pdp .buy-col .ticks { margin-top: 20px; }

.pdp .buy-chips .tag:hover:not(.on) { border-color: var(--ph-accent); }
.pdp .buy-chips .tag:active { transform: scale(.97); }
/* The sizing-kit alternative was an <a href="#"> and is a <button> now, which
   costs it the link ink a <button> does not inherit — a full-width pill with no
   colour in it reads as an empty box rather than an offer. `.buy-alt` keeps
   shared.css's own width and centring; only the ink and the chosen state are
   added, and the chosen state is the same accent-border-and-ink the size chips
   beside it already use. */
.pdp .buy-alt { color: var(--ph-accent-link); }
.pdp .buy-alt.on { border-color: var(--ph-accent); color: var(--ph-accent); background: none; }
.pdp .buy-swatch:focus-visible,
.pdp .buy-choice:focus-visible,
.pdp .buy-chips .tag:focus-visible {
  outline: var(--ph-focus-w) solid var(--ph-focus);
  outline-offset: var(--ph-focus-offset);
}
/* The price in the buy block and in the dock change together, and a number that
   changes without moving is a number a reader misses. 140ms, one direction. */
.pdp [data-price] { transition: opacity 140ms var(--pdp-ease); }
.pdp [data-price].swap { opacity: .25; }

/* ---- the column's accordion: REMOVED 2026-09-14, with the markup it drew.
   Three <details> panels — what's in the box, what it measures, what it works
   with — sat at the foot of the column to give it enough height to have sticky
   travel. They are gone by request, and the rules that styled them (.pdp-col-acc
   and the .pdp-mini list inside it) are deleted rather than left behind: no
   element on this page carries either class now, and a stylesheet that dresses
   nothing is a thing the next reader has to prove is dead.
   The content is not lost. Every line was already set out in full in § 7's
   Technical Specifications — In the Box, Sensors, Connectivity, Compatibility —
   which is where the panels had copied it from in the first place. */

/* ---------------------------------------------------------------------------
   2 · THE SIGNAL BAND · a photograph, a frosted panel, and no tabs

   WHAT THIS REPLACES: a navy section with five chips in a `role="tablist"` and
   five panes behind them, of which four were always hidden. It worked, and it
   was the wrong shape for what it holds. A tablist is right when the options
   are alternatives — pick titanium OR ceramic — and these five are not
   alternatives, they are five things the ring does AT THE SAME TIME. The
   section's own headline says so ("more signal"), and then the interface made
   the reader press four times to be told it, while showing 20% of the answer
   at any moment. Four fifths of a section behind a click that nobody asked for.

   THE CONSTRUCTION:

     ground     one full-bleed photograph, no scrim over the whole frame
     panel      a frosted panel, radius 16, padding 32 / 48, no border
     columns    flex, gap 48, five equal cells
     glyph      a line drawing, no fill, no container, sat above the title
     heading    over the picture and outside the panel

   THE CONSTRAINTS, and each is a system constraint rather than taste:

     · THE FROST IS DARK, NOT LIGHT. The photograph is sunlit water —
       the brightest picture in the shoot — and a white frost over it composited
       to about #dfe6ee, which cannot hold white type at any weight. So the
       panel is the brand navy at 34%, which darkens whatever is behind it
       instead of lightening it. Measured on the four brightest frames: 8.9:1
       for the title, 6.1:1 for the body.
     · THE WEIGHTS ARE 400 AND 600. This kit has 400 and 500 only
       (phenome-glass.css maps --ph-w-600 to 500), so no weight is invented.
     · FIVE COLUMNS, because there are five signals and dropping one
       to fit a grid is letting the layout edit the product.

   THE COPY IS THE PANES', SHORTENED. Each cell keeps the sentence that says
   what the sensor actually does and loses the second clause; the "Optical
   sensor · continuous" metric lines are gone with the panes, because a caption
   under a caption is what a tab pane had room for and a five-up does not.
   ------------------------------------------------------------------------ */
/* THE RING STAYS CLEAR, 2026-09-14. The band used to stack the heading, the
   lede and a five-column panel of descriptions straight down the middle of the
   photograph, and the ring — the one thing the picture exists to show — sat
   under the panel. Now the photograph is read as three zones: the copy takes
   the empty tiles and water in the upper right, the five signals (icon and
   name only, the descriptions are gone) run along the foot as one frosted
   strip, and the middle, where the hand and the ring are, carries no type at
   all. The ring is at 47% / 49% of the frame, so a right-hand copy column and a
   bottom strip can never reach it at any desktop width.
   Below 1024 there is no right-hand side to use, so the photograph drops into
   the flow between the copy and the strip instead of sitting behind both. */
/* THE FRAME GROWS, 2026-09-21 (supplements/nad "Feel the difference").
   Everything this screen draws now lives on
   .pdp-sig-box, which pdp.js scales from .86 to 1 while the track's top climbs
   from 80% down the window to its top; the stage is sticky, so the box then
   holds full screen for most of a screen. The section itself is only the
   scroll room: no padding, and no overflow hidden, which would make it a
   scroll container and leave the sticky stage stuck to nothing. */
.pdp .pdp-sig { padding: 0; overflow: visible; }
.pdp .pdp-sig-track { position: relative; height: calc(100svh + 70vh); }
.pdp .pdp-sig-stage { position: sticky; top: 0; height: 100svh; overflow: clip; }
.pdp .pdp-sig-box {
  position: relative;
  isolation: isolate;
  overflow: clip;
  display: flex;
  height: 100svh;
  min-height: 620px;
  padding-block: clamp(88px, 8vw, 120px) clamp(40px, 4vw, 64px);
  border-radius: var(--sig-rad, 0px);
  transform: scale(var(--sig-s, 1)); transform-origin: 50% 50%;
}
/* the photograph keeps its size while the frame grows: only the crop changes */
.pdp .pdp-sig-bg { scale: calc(1 / var(--sig-s, 1)); }
.pdp .pdp-sig-bg { position: absolute; inset: 0; z-index: -2; }
.pdp .pdp-sig-bg img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  object-position: 40% 50%;
}
/* Two washes, each seating one zone and leaving the middle alone: a navy bloom
   behind the copy in the upper right, where the tiles are near-white, and a
   floor under the strip. The ring sits between them in untouched light. */
.pdp .pdp-sig-box::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  /* Under both washes, a flat near-black veil over the whole photograph: the
     tiles and water were bright enough to fight the white type everywhere,
     not just behind the copy. */
  background:
    linear-gradient(rgba(4, 7, 14, .52), rgba(4, 7, 14, .52)),
    radial-gradient(ellipse 58% 62% at 88% 18%, rgba(10, 30, 87, .70) 0%, rgba(10, 30, 87, .44) 48%, rgba(10, 30, 87, 0) 100%),
    linear-gradient(0deg, rgba(10, 30, 87, .50) 0%, rgba(10, 30, 87, 0) 34%);
}

.pdp .pdp-sig-in {
  flex: 1;
  display: flex; flex-direction: column; justify-content: space-between;
  gap: clamp(40px, 5vw, 72px);
}
/* THE COPY IS ON THE LEFT NOW, which is the side nad's hero states from and the
   side every two tone display on this site is set against. The ring sits at 47%
   of the frame, so a column that stops at 620px still clears it at 1024 and up. */
/* RIGHT AGAIN, 2026-09-22: the running photograph puts the hand and ring at
   ~37% of the frame, under a left column, and gives the right half a black
   tank top, which is the quietest ground on the picture for white type. */
.pdp .pdp-sig-copy {
  margin-left: auto;
  width: min(100%, 620px);
}
.pdp .pdp-sig-frame { display: none; }

/* The display pair itself lives in phenome-glass.css § 3; what belongs here is
   only how large it is on this photograph. nad sets its own at
   clamp(32px, 3.8vw, 62px) over a portrait; this frame is wider and emptier at
   the top left, so it takes a step more. */
.pdp .pdp-sig-h { max-width: 15ch; font-size: clamp(38px, 4.6vw, 76px); }
.pdp .pdp-sig-lede {
  margin: 24px 0 0;
  font-size: clamp(19px, 1.5vw, 23px); line-height: 1.5;
  letter-spacing: var(--ph-tr-19-400);
  color: #e3eaf6;
  text-wrap: pretty;
}

/* ---- the strip. Five signals, a glyph and a name each. Without the
   descriptions a cell is two lines tall, so it becomes one row: the glyph to
   the left of the name, hairlines between cells, and the strip reads as a
   legend along the foot of the picture rather than a block of cards. */
.pdp .pdp-sig-glass {
  padding: clamp(30px, 3vw, 46px) clamp(26px, 3vw, 48px);
  min-height: clamp(180px, 15vw, 232px);
  border-radius: var(--ph-r24, 24px);
  /* NAD'S PANE, 2026-09-16 (supplements/nad/nad.css § 2). It was a navy tint at
     36% with an inset hairline, which is a darker piece of the same photograph;
     this is a pane of WHITE at 12% with a real 20% border and a heavier blur,
     so it reads as glass laid on the picture rather than as a hole cut in it. */
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .2);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
          backdrop-filter: blur(22px) saturate(140%);
  display: grid;
  /* CONTENT-SIZED, NOT FIFTHS (2026-09-14, by request): every signal name has to
     sit on ONE line. Five equal columns give each name 180px of text width and
     "Heart rate variability" wants 239px at this size, so two of the five broke
     to a second line and the strip read as a ragged block. The five names
     measure 857px together against 1174px of strip, so max-content columns fit
     them all at full size with room to spare; `space-between` spends what is
     left on the gaps, which is also what keeps the hairlines evenly placed. */
  grid-auto-flow: column;
  grid-auto-columns: max-content;
  justify-content: space-between;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pdp .pdp-sig-glass { background: rgba(10, 30, 87, .82); border-color: rgba(255, 255, 255, .16); }
}
/* Taller cells: the glyph rides the top edge and the name sits on the
   baseline, so each signal reads as a small plate rather than a legend entry. */
.pdp .pdp-sig-cell {
  display: flex; flex-direction: column; justify-content: space-between;
  align-items: flex-start; gap: 24px;
  padding-inline: clamp(14px, 1.8vw, 28px);
  min-width: 0;
}
.pdp .pdp-sig-cell:first-child { padding-left: 0; }
.pdp .pdp-sig-cell:last-child { padding-right: 0; }
.pdp .pdp-sig-cell + .pdp-sig-cell { box-shadow: inset 1px 0 0 rgba(255, 255, 255, .18); }
.pdp .pdp-sig-cell svg {
  width: clamp(40px, 3.2vw, 52px); height: clamp(40px, 3.2vw, 52px);
  flex: none; display: block;
  color: #fff;
}
.pdp .pdp-sig-t {
  margin: 0;
  font-size: clamp(21px, 1.9vw, 29px); line-height: 1.12;
  font-weight: var(--ph-w-600); letter-spacing: -0.018em;
  color: #fff;
  /* `balance` is what was here, and balancing is the wrong instruction for a
     name that must not wrap at all. nowrap says the thing directly, and the
     column sizing above is what makes it safe at every width. */
  white-space: nowrap;
}

@media (max-width: 1180px) {
  .pdp .pdp-sig-cell svg { width: 32px; height: 32px; }
}
@media (max-width: 1023px) {
  .pdp .pdp-sig-track { height: auto; }
  .pdp .pdp-sig-stage { position: static; height: auto; overflow: visible; }
  .pdp .pdp-sig-box {
    height: auto; min-height: 0; display: block; transform: none; border-radius: 0;
    padding-block: clamp(64px, 6vw, 96px);
    background: var(--phenome-blue-900);
  }
  .pdp .pdp-sig-bg, .pdp .pdp-sig-box::before { display: none; }
  .pdp .pdp-sig-in { gap: 28px; }
  .pdp .pdp-sig-copy { margin-right: 0; width: auto; max-width: 62ch; }
  .pdp .pdp-sig-frame {
    display: block;
    aspect-ratio: 4 / 3;
    border-radius: var(--ph-r18);
    background: url("/site/assets/store/phenometech-ring/signature-frame.webp") 50% 50% / cover no-repeat;
  }
  .pdp .pdp-sig-glass {
    background: rgba(255, 255, 255, .07);
    -webkit-backdrop-filter: none; backdrop-filter: none;
    /* Back to rows here: `grid-auto-flow: column` would keep laying the five
       out sideways past the three declared columns instead of wrapping. */
    grid-auto-flow: row;
    justify-content: normal;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 28px 0;
    min-height: 0;
  }
  .pdp .pdp-sig-cell { gap: 14px; }
  .pdp .pdp-sig-cell:nth-child(4) { padding-left: 0; box-shadow: none; }
}
/* ONE PER ROW UNDER 720px. Two columns gave the longest name about 130px of
   text width against the 178px it needs at the floor of the type ramp, so it
   was the one place left where a name could still have broken. Turning each
   cell on its side — glyph beside the name rather than above it — buys the
   whole column width back, and the strip reads as a list, which is what a
   five-item legend wants to be on a phone anyway. */
@media (max-width: 719px) {
  .pdp .pdp-sig-glass { grid-template-columns: minmax(0, 1fr); gap: 20px 0; }
  .pdp .pdp-sig-cell {
    flex-direction: row; align-items: center; justify-content: flex-start;
    gap: 14px;
    padding-inline: 0;
    box-shadow: none !important;
  }
  .pdp .pdp-sig-cell svg { width: 34px; height: 34px; }
  .pdp .pdp-sig-t { font-size: 21px; }
}

/* ---------------------------------------------------------------------------
   3 · THE TIMELINE · a rail that fills, against a film that holds still
   ------------------------------------------------------------------------ */

/* ---- 3b · WHEN IT STARTS WORKING · the kit timeline, phenome-glass.css § 9.

   WHAT WAS HERE: 116 lines drawing a stepper — .pdp-tl, .pdp-tl-steps with two
   absolutely positioned rules, .pdp-tl-step as a button at 38% opacity with a
   hover state and a focus ring, a .pdp-tl-when chip that inverted on the
   current step, and a sticky 4:5 film beside it. All of it drew, differently,
   the thing supplements/nad already had. The component is the kit's now and
   both pages take it, so what is left here is only what is true of THIS page.

   Two things are: the section's head, and the phone. -------------------- */

/* The section's own head, centred over the grid the way nad's is. */
.pdp .pdp-when-head { text-align: center; }
.pdp .pdp-when-h { font-size: clamp(34px, 4.4vw, 68px); }
.pdp .pdp-when-sub {
  margin: 20px auto 0; max-width: 62ch;
  font-size: clamp(19px, 1.4vw, 21px); line-height: 1.55;
  color: var(--ph-text-2);
}
.pdp .pdp-when-head .link-more { margin-top: 18px; display: inline-block; }

/* THE PHONE, NOT A FILM (2026-09-29, by request). The screen recording is
   gone; the app's own screens stand on the 3D phone (apple/phone3d.js) on the
   section's white, one screen per stage, and pdp.js turns to the next as the
   kit's timeline lights it. The tile drops its ground and its clip, because
   the phone's canvas reaches past its host, and the caption sits under the
   phone rather than over it. Where the 3D phone cannot run, the host keeps
   its screen image. */
.pdp .pdp-when .ph-tl-media { display: flex; justify-content: center; }
.pdp .ph-tl-big.pdp-when-fig {
  display: flex; flex-direction: column; align-items: center; gap: 32px;
  width: min(100%, 540px); aspect-ratio: auto; overflow: visible;
  background: none; border-radius: 0;
}
.pdp .pdp-when-phone { position: relative; width: 300px; height: 623px; }
.pdp .pdp-when-phone > img { border-radius: 44px; }
.pdp .ph-tl-big.pdp-when-fig figcaption {
  position: static; translate: none; width: auto; max-width: 32ch; padding: 0;
  background: none; -webkit-backdrop-filter: none; backdrop-filter: none;
  color: var(--ph-text-2); font-size: 17px; font-weight: 500;
}
@media (max-width: 640px) {
  .pdp .pdp-when-phone { width: min(260px, 64vw); height: auto; aspect-ratio: 300 / 623; }
  .pdp .pdp-when-phone > img { border-radius: 36px; }
}

.pdp .pdp-when-ic { width: 32px; height: 32px; flex: none; color: var(--ph-accent); }

/* ---------------------------------------------------------------------------
   4 · THE HIGHLIGHTS · devices/band's coach and insight marquee
   ------------------------------------------------------------------------ */
/* Taken from devices/band/band.css § 2 and § 3 (2026-09-17, by request), so
   the ring and the band present their highlights one way. The headline is the
   kit's two tone pair on white; pdp.js grows a navy circle up from below the
   stage until it is the ground, and the second pair rides in on it. The card
   row then slides up over the stage's empty lower third on a ground that is
   transparent where the two overlap, so there is no seam. */
.pdp { --pdp-night: #070c24; --pdp-mq-ease: cubic-bezier(.16, 1, .3, 1); }
.pdp .pdp-coach { position: relative; height: 230vh; background: #fff; }
.pdp .pdp-coach-stage { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: clip; }
.pdp .pdp-coach-h {
  position: absolute; left: 50%; top: 42%; width: min(92vw, 980px); margin: 0;
  transform: translate(-50%, calc(-50% - var(--c-lift, 0px)));
  font-size: clamp(46px, 7.6vw, 118px);
}
.pdp .pdp-orb {
  position: absolute; inset: 0; background: var(--pdp-night);
  clip-path: circle(var(--orb-r, 0px) at 50% calc(100% + var(--orb-drop, 30vh)));
  will-change: clip-path;
}
.pdp .pdp-orb-in {
  position: absolute; left: 50%; top: 50%; width: 92vw;
  transform: translate(-50%, calc(-50% + var(--orb-copy, 40px)));
}
.pdp .pdp-orb-t { margin: 0; font-size: clamp(50px, 8vw, 118px); }

.pdp .pdp-apps {
  position: relative; z-index: 1; margin-top: -34vh; padding: 0 0 clamp(90px, 10vw, 150px); overflow: clip; color: #fff;
  background: linear-gradient(180deg, transparent 0, var(--pdp-night) 34vh);
}
.pdp .pdp-mq { overflow: hidden; }
.pdp .pdp-mq-row {
  list-style: none; margin: 0; padding: 0; display: flex; gap: 16px; width: max-content;
  animation: pdp-mq var(--mq-s, 80s) linear infinite;
}
.pdp .pdp-mq:hover .pdp-mq-row { animation-play-state: paused; }
@keyframes pdp-mq { to { transform: translateX(calc(-50% - 8px)); } }
.pdp .pdp-mq-card {
  position: relative; flex: none; width: clamp(260px, 27.8vw, 400px); aspect-ratio: 400 / 560;
  border-radius: 16px; overflow: hidden; background: #1a2140;
}
.pdp .pdp-mq-card img { width: 100%; height: 100%; object-fit: cover; display: block; transition: scale 1.2s var(--pdp-mq-ease); }
.pdp .pdp-mq-card:hover img { scale: 1.04; }
.pdp .pdp-mq-card::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(6, 12, 34, 0) 45%, rgba(6, 12, 34, .55) 100%);
}
.pdp .pdp-mq-chip {
  position: absolute; z-index: 1; left: 14px; right: 14px; bottom: 14px;
  padding: 18px 20px 20px; border-radius: 14px;
  background: rgba(10, 30, 87, .42);
  -webkit-backdrop-filter: blur(18px) saturate(140%); backdrop-filter: blur(18px) saturate(140%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
}
.pdp .pdp-mq-chip p { margin: 0; }
.pdp .pdp-mq-k { display: flex; align-items: center; gap: 8px; font-size: 15px; line-height: 1.3; color: rgba(255, 255, 255, .78); }
.pdp .pdp-mq-k i { width: 8px; height: 8px; border-radius: 50%; background: #8fb4ff; box-shadow: 0 0 0 4px rgba(143, 180, 255, .25); }
.pdp .pdp-mq-chip .pdp-mq-t { margin-top: 10px; font-size: clamp(20px, 1.6vw, 24px); line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; color: #fff; }
.pdp .pdp-mq-chip .pdp-mq-d { margin-top: 6px; font-size: 16px; line-height: 1.4; color: rgba(255, 255, 255, .82); }
.pdp .pdp-mq-chip .pdp-mq-v { display: flex; align-items: baseline; gap: 10px; margin-top: 14px; color: #fff; }
.pdp .pdp-mq-v b { font-size: clamp(30px, 2.6vw, 38px); line-height: 1; font-weight: 600; letter-spacing: -0.02em; }
.pdp .pdp-mq-v span { font-size: 16px; color: rgba(255, 255, 255, .72); }

/* Over the navy the product bar turns to ink, so it never floats as a white slab. */
.pdp.is-dark-bar .ph-bar { background: rgba(7, 12, 36, .66); border-bottom-color: rgba(255, 255, 255, .08); }
.pdp.is-dark-bar .ph-bar-name { color: #fff; }
.pdp.is-dark-bar .ph-bar-meta { color: rgba(255, 255, 255, .62); }

@media (max-width: 760px) {
  .pdp .pdp-coach { height: 190vh; }
}
@media (prefers-reduced-motion: reduce) {
  .pdp .pdp-mq-row { animation: none; }
  .pdp .pdp-mq { overflow-x: auto; }
}

/* ---------------------------------------------------------------------------
   5 · TITANIUM OR CERAMIC · two columns, compare structure
   ------------------------------------------------------------------------ */

/* THE THIRD ARRANGEMENT THIS SECTION HAS HAD, and each one failed at a
   different level.

     two cards      the values were not on the same line, so "4 grams" sat
                    level with "a soft, warm feel" and compared nothing
     a key table    attribute on the left, two answers beside it. It compared,
                    but it read as a datasheet — no product in it, no colour in
                    it, and eight identical-looking rows of which three said the
                    same thing twice

   This structure is the argument: NO KEY COLUMN. Each column is a self-contained
   pitch — picture, colourways, price, buy — and then its own facts, each group
   led by a value set large enough to be read across the room. The reader
   compares by looking left and right at the same height, not by tracking a row
   back to a label at the far edge.

   AND NO REPEATED SPECS. Repeating every spec in every column only makes sense
   when products genuinely differ down the list. Ours do not — the sensors, the water rating, the
   battery and the radio are identical, and the section's own lede says so
   ("Identical sensors, identical insight"). Repeating them twice would spend
   two columns denying the sentence above them. So the columns carry only what
   differs, and everything shared is stated once, full width, underneath. The
   layout makes the argument instead of contradicting it. */

.pdp .pdp-vs {
  margin-top: clamp(40px, 4.4vw, 64px);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(20px, 2.4vw, 34px);
  align-items: start;
}
/* Three materials since 2026-09-17. The subgrid below does the real work and is
   written in rows, not columns, so a third column needs nothing from it. */
.pdp .pdp-vs.is-three { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(14px, 1.6vw, 24px); }

/* ---- THE ROWS HAVE TO LINE UP ACROSS THE TWO COLUMNS, and by default they do
   not. Each column is its own formatting context, so "Grade-5 aerospace
   titanium" (one line of description) and "High-density zirconia ceramic" (two)
   pushed the group under them to different heights — 437px against 458px at
   1440, measured. Twenty-one pixels is enough that the eye stops reading across
   and starts reading down each column separately, which is the one thing a
   comparison must not let happen.

   `subgrid` is the fix and it is the only one that does not involve guessing.
   The parent owns seven rows — picture, dots, colour name, buy block, and one
   per fact group — and each column adopts them instead of generating its own,
   so every row is as tall as the taller of the two columns' content and the
   pairs are level by construction. No reserved line-heights to maintain, no
   copy written to a length, nothing to re-tune when a description changes.

   Row gap is zero on purpose: with subgrid the parent's row gap would fall
   between the picture and the dots as well as between the fact groups, so the
   spacing stays where it already was — on each element's own margin.

   Wrapped in @supports because a browser without subgrid must not get seven
   collapsed rows. It falls through to the block flow above, which is the
   layout this section had before and is merely unaligned rather than broken. */
@supports (grid-template-rows: subgrid) {
  .pdp .pdp-vs {
    grid-template-rows: repeat(7, auto);
    row-gap: 0;
  }
  .pdp .pdp-vs-col {
    grid-row: 1 / -1;
    display: grid;
    grid-template-rows: subgrid;
    row-gap: 0;
  }
  .pdp .pdp-vs-facts {
    grid-row: span 3;
    grid-template-rows: subgrid;
    row-gap: 0;
    gap: 0;
  }
  .pdp .pdp-vs-g + .pdp-vs-g { margin-top: clamp(26px, 2.6vw, 36px); }
}

/* The column. It is a real card rather than an absolutely-positioned pane
   sliding behind cells — the old table's trick, which needed measured
   arithmetic in script and could not survive the mobile stack. A card per
   column is the same idea stated in one property, and `[data-on]` is the
   chosen one. */
.pdp .pdp-vs-col {
  padding: clamp(26px, 2.6vw, 38px) clamp(20px, 2.2vw, 32px) clamp(24px, 2.4vw, 34px);
  border-radius: var(--ph-r27);
  text-align: center;
  box-shadow: inset 0 0 0 1px transparent;
  transition: background 420ms var(--pdp-ease),
              box-shadow 420ms var(--pdp-ease),
              transform 420ms var(--pdp-ease);
}
.pdp .pdp-vs-col[data-on] {
  background: var(--gl-tint-live);
  box-shadow: var(--gl-shadow-lift), var(--gl-inner);
}
/* The unchosen column is not dimmed. Both are products this page sells and one
   of them is about to be chosen; greying it out would be selling against it.
   It simply does not have the card. */

/* ---- the picture. Follows the swatch, like everything else that shows a ring:
   the titanium column shows whichever titanium finish is current, the ceramic
   column whichever ceramic one. A column that always showed gold while the
   reader had silver selected would be the one place on the page where the
   product stopped agreeing with the control. */
/* SEVENTY PER CENT, IN BOTH DIMENSIONS, 2026-09-09.

   It was the column's full width at 4:3 — about 600 x 450 at 1440 — which made
   the photograph the largest object in a section whose subject is a CHOICE
   between two of them. Two 600px pictures side by side is a gallery; the
   comparison starts below them and the reader has to scroll to reach it.

   The aspect stays 4:3 so the reduction is a true 0.7 on both axes rather than
   0.7 wide and 0.93 tall, which is what a square would have made it — and a
   picture that only narrows reads as a cropped picture rather than a smaller
   one. 420 x 315 against 600 x 450.

   THE CROP IS IN THE FILE, NOT IN THE BOX. The ceramic column now carries the
   three-quarter shots (9 and 10 in the shoot — the ring tilted with its sensor
   face toward the camera) and the masters are 4:5 portraits. Two ways to get a
   4:5 picture into a 4:3 frame and both were tried: `contain` letterboxes, and
   the bars showed, because the studio ground is a soft gradient and no single
   flat fill matches it at both edges; `cover` crops a fifth off the top and
   bottom and the ring then touches the frame. So the window is cut in the
   ENCODER instead — the ring's own bounding box was measured in each master
   (about 1690 x 1725px, centred near 1669, 2130) and a 3000 x 2250 window taken
   around it, which leaves the object 1.3x its own size in air on every side.
   That is the same headroom the existing gold, graphite and silver renders
   carry, so the two columns match. The files are 4:3 and `cover` is then doing
   nothing at all. */
.pdp .pdp-vs-fig {
  position: relative;
  width: 70%;
  margin-inline: auto;
  aspect-ratio: 4 / 3;
  border-radius: var(--ph-r18);
  overflow: hidden;
  /* The photography's own studio ground, sampled off the frames themselves,
     rather than the recess tone — what shows for the instant before a lazy
     image decodes, and behind any future render whose crop is not exact. */
  background: #d5cac4;
}
.pdp .pdp-vs-col[data-on] .pdp-vs-fig { background: #f7f4f1; }
/* THE PLATE, 2026-09-17: the columns carry the same nine renders the hero does,
   so the studio ground the frame was painted for is gone and the transparent
   plate sits on the page's own wash, contained rather than cropped. The white
   ceramic is the reason the chosen column does NOT go lighter here: a white
   ring on a white card is a ring with no silhouette. */
/* NO PLATE, 2026-09-22 (by request): the cut out rings stand straight on the
   column, no tinted panel behind them. The soft floor shadow is what keeps the
   white ceramic's silhouette on a white column now that the panel is gone. */
.pdp .pdp-vs-fig.is-plate,
.pdp .pdp-vs-col[data-on] .pdp-vs-fig.is-plate { background: transparent; border-radius: 0; overflow: visible; }
.pdp .pdp-vs-fig.is-plate img {
  object-fit: contain; padding: 2%;
  filter: drop-shadow(0 14px 18px rgba(10, 30, 87, .12));
}
.pdp .pdp-vs-fig img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0;
  transition: opacity var(--pdp-slow) var(--pdp-ease);
}
.pdp .pdp-vs-fig img.on { opacity: 1; }
.pdp .pdp-vs-fig:not([data-live]) img:first-of-type { opacity: 1; }

/* ---- the colourways. The same gloss treatment as the buy column's swatches,
   at 26px, and they are LIVE: clicking one here sets the finish and the
   material exactly as the hero's do. That is what keeps this section part of
   the decision rather than a description of it. */
.pdp .pdp-vs-sw {
  display: flex; justify-content: center; gap: 13px;
  margin-top: clamp(20px, 2vw, 26px);
}
/* Geometry and behaviour only — the material itself is drawn by the shared
   disc block above, which this and the buy column's swatches both feed from. */
.pdp .pdp-vs-dot {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  padding: 0; border: 0;
  transition: transform var(--pdp-quick) var(--pdp-ease);
}
.pdp .pdp-vs-dot:hover { transform: scale(1.1); }
.pdp .pdp-vs-dot:active { transform: scale(1.01); }
.pdp .pdp-vs-dot.on { outline: 2px solid var(--ink-900); outline-offset: 3px; }
.pdp .pdp-vs-dot:focus-visible {
  outline: var(--ph-focus-w) solid var(--ph-focus); outline-offset: var(--ph-focus-offset);
}
/* The name under the dots: a row
   of coloured beads with no names makes the reader guess what "the pale one" is
   called. Fixed height so the row does not jog when the name changes length. */
.pdp .pdp-vs-swname {
  margin: 12px 0 0; min-height: 24px;
  font-size: 15px; line-height: 1.5;
  color: var(--ph-text-2);
}

/* ---- price and action, under a hairline. Order: rule, price,
   filled button. */
.pdp .pdp-vs-buy {
  margin-top: clamp(20px, 2vw, 26px);
  padding-top: clamp(18px, 1.8vw, 24px);
  border-top: 1px solid var(--pdp-hair);
}
.pdp .pdp-vs-name {
  margin: 0;
  font-size: var(--ph-fs-21); line-height: var(--ph-lh-21);
  font-weight: var(--ph-w-600); letter-spacing: var(--ph-tr-21-600);
  color: var(--ink-900);
}
.pdp .pdp-vs-price {
  margin: 6px 0 0;
  font-size: var(--ph-fs-28); line-height: var(--ph-lh-28);
  font-weight: var(--ph-w-600); letter-spacing: var(--ph-tr-28-600);
  color: var(--ink-900); font-variant-numeric: tabular-nums;
}
.pdp .pdp-vs-pick {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  margin-top: 16px; font: inherit;
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--ph-btn-h); padding: 0 22px; border-radius: var(--ph-r56);
  border: 0; background: var(--ph-accent); color: #fff;
  font-size: var(--ph-fs-17); letter-spacing: var(--ph-tr-17-400);
  transition: background var(--pdp-quick) var(--pdp-ease),
              color var(--pdp-quick) var(--pdp-ease),
              transform var(--pdp-quick) var(--pdp-ease);
}
.pdp .pdp-vs-pick:hover { background: var(--ph-accent-hover); }
.pdp .pdp-vs-pick:active { transform: scale(.98); }
.pdp .pdp-vs-pick:focus-visible {
  outline: var(--ph-focus-w) solid var(--ph-focus); outline-offset: var(--ph-focus-offset);
}
/* The chosen column's button becomes a statement rather than an offer. Not
   removed: a column with a button and a column without would be two different
   components, and the row's rhythm would break every time the reader chose. */
.pdp .pdp-vs-col[data-on] .pdp-vs-pick {
  background: var(--gl-tint-sunk); color: var(--ph-text-2); cursor: default;
}
.pdp .pdp-vs-col[data-on] .pdp-vs-pick:hover { background: var(--gl-tint-sunk); }

/* ---- the facts. Rhythm: a value large enough to read at a glance,
   then short centred lines under it, and generous air between groups. No
   labels down the left, because there is no left. */
.pdp .pdp-vs-facts {
  margin-top: clamp(26px, 2.6vw, 38px);
  padding-top: clamp(22px, 2.2vw, 30px);
  border-top: 1px solid var(--pdp-hair);
  display: grid; gap: clamp(26px, 2.6vw, 36px);
}
.pdp .pdp-vs-g > * { margin: 0; }
.pdp .pdp-vs-v {
  font-size: clamp(40px, 4.2vw, 60px); line-height: 1;
  font-weight: var(--ph-w-600); letter-spacing: var(--ph-tr-64-600);
  color: var(--ink-900); font-variant-numeric: tabular-nums;
}
.pdp .pdp-vs-v small {
  font-size: .42em; letter-spacing: var(--ph-tr-24-600); margin-left: .12em;
}
.pdp .pdp-vs-t {
  margin-top: 12px;
  font-size: var(--ph-fs-19); line-height: var(--ph-lh-19);
  font-weight: var(--ph-w-600); letter-spacing: var(--ph-tr-21-600);
  color: var(--ink-900); text-wrap: balance;
}
.pdp .pdp-vs-s {
  margin-top: 7px;
  font-size: var(--ph-fs-17); line-height: var(--ph-lh-17);
  color: var(--ph-text-2); text-wrap: balance;
}
/* The group's mark, for the two groups that have no number to lead with. Line
   art at 34px, the same weight as the badge marks in Tech Specs. */
.pdp .pdp-vs-m {
  width: 34px; height: 34px; margin: 0 auto 4px;
  display: block; color: var(--ph-accent);
}


/* ---------------------------------------------------------------------------
   6 · TECHNICAL SPECIFICATIONS · the plate runs off the page

   THE REFERENCE IS THE COMPANY'S OWN PREVIOUS PAGE,
   phenomelongevity.com/products/phenometech-ring, asked for 2026-09-14. What
   was taken from it, and what could not be:

     the plate     the charging dock shot side-on, its cable running straight
                   out through the right edge of the PAGE rather than stopping
                   at the edge of a box. That is the whole idea of the section:
                   the one long line in the composition is the product's own
                   cable, and it leaves the frame instead of being framed.
     the title     two lines, very large, set bottom-left against the plate so
                   the words and the dock share a baseline zone.
     the cards     an icon, a quiet label in the secondary ink, the value in
                   the primary ink, outlined, and What's Included as the one
                   tinted card. Kept exactly.

     the grid      NOT kept. The reference has eight cards of ONE value each,
                   so a uniform 3 × 3 works for it. This page carries eleven
                   groups and most hold three to five lines, and at uniform
                   heights the short ones would stretch into boxes of air. So
                   each card now leads with one headline value — the thing a
                   reader scanning for "how long does the battery last" is
                   looking for — and the supporting lines sit under it in a
                   smaller, quieter voice. The two heavy groups span two rows,
                   the short ones stack beside them, and the warranty closes
                   the section as a full-width strip.

   THE LABELS ARE FULL NAMES AND SENTENCE-WEIGHT, NOT EYEBROWS. 15px in the
   secondary ink, no tracking and no capitals: a label here names a card, it
   is not a kicker above a headline.
   ------------------------------------------------------------------------ */
.pdp .pdp-specs {
  /* The plate is allowed past the wrapper to the right edge of the viewport,
     and 100vw includes the scrollbar, so the section clips the overhang rather
     than letting it scroll the page sideways. `clip`, not `hidden`: hidden
     would make the section a scroll container and break sticky descendants. */
  overflow-x: clip;
}

/* ---- the head. The title takes the narrow column and sits at the foot of it;
   the plate takes the rest and runs on past the wrapper. */
.pdp .pdp-specs-head {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: end;
  gap: clamp(20px, 3vw, 48px);
}
/* THE TITLE IS ONE STATEMENT IN ONE INK, 2026-09-16, by request, on
   devices/band's `.bd-h2`. It used to set "Technical" in the ink and
   "Specifications" in the accent on the line under it, which is the two tone
   display's gesture worn by a heading that is not the display — and the system
   rule (phenome-glass.css § 3) is explicit that a section's NAME is set solid,
   because a colour shift across two words reads as an error rather than as
   emphasis. Same size band the Band uses, same weight, same ink. */
.pdp .pdp-specs-h {
  margin: 0;
  padding-bottom: clamp(8px, 1.4vw, 22px);
  font-size: clamp(34px, 4.4vw, 60px);
  line-height: 1.05;
  font-weight: var(--ph-w-600);
  letter-spacing: -0.02em;
  color: var(--ink-900);
}

/* THE BLEED. The wrapper is centred at --ph-content-max with --ph-margin either
   side, so the distance from the plate's column edge to the viewport's edge is
   that margin plus half of whatever the viewport has beyond the wrapper. The
   plate's right margin is that distance, negative. The image's own right edge
   is the end of the cable — the PNG was cut there — so the cable meets the
   viewport edge and the dock stays in the column. */
.pdp .pdp-specs-plate {
  --bleed: calc(var(--ph-margin) + max(0px, (100vw - var(--ph-content-max) - var(--ph-margin) * 2) / 2));
  margin-right: calc(var(--bleed) * -1);
  min-width: 0;
}
.pdp .pdp-specs-plate img {
  display: block;
  width: 100%;
  height: auto;
}

/* ---- the grid. EIGHT CARDS, FOUR BY TWO, 2026-09-14.

   The content was handed over as eight fixed groups, each a short list of
   equal lines with no single headline figure among them, which is the
   reference's own shape: a label and the values, nothing ranked above
   anything else. What's Included went because In the Box says the same four
   things. Eight in threes leaves a row of two; eight in fours is two full
   rows, so the grid is four across and the cards follow the given order. */
.pdp .pdp-specs-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-top: clamp(28px, 3vw, 44px);
}

/* ALL EIGHT ARE TINTED BLOCKS, 2026-09-14, on In the Box's treatment: the
   recess tint, no outline. Eight outlined white cards on a white page were
   eight boxes; eight tinted blocks are one surface cut into eight. */
.pdp .pdp-spec {
  margin: 0;
  padding: clamp(22px, 2vw, 30px);
  border-radius: var(--ph-r21);
  border: 1px solid transparent;
  background: var(--gl-tint-sunk);
}

/* THE LABEL LEADS, 2026-09-16, by request, on devices/band's specification grid
   (band.css § 5). It was 15px at 400 in the secondary ink — a caption over its
   own values, and the smallest type on a block whose whole job is to be read.
   The Band settled this: the label is the heading of its card, 19 to 23 at 600
   in the heading ink with the mark beside it in the brand blue, and the values
   under it step DOWN into the body ink. Same two rungs, same icon colour, same
   blue bullet. The card, its tint and its radius are unchanged — they already
   matched. */
.pdp .pdp-spec-k {
  display: flex; align-items: center; gap: 12px;
  margin: 0;
  font-size: clamp(19px, 1.6vw, 23px); line-height: 1.2;
  font-weight: var(--ph-w-600);
  color: var(--ink-900);
}
.pdp .pdp-spec-k svg { width: 26px; height: 26px; flex: none; color: var(--ph-accent); }

.pdp .pdp-spec-l {
  margin: 18px 0 0; padding: 0; list-style: none;
  display: grid; gap: 10px;
}
.pdp .pdp-spec-l li {
  position: relative; padding-left: 18px;
  font-size: var(--ph-fs-17); line-height: 1.45;
  color: var(--ink-600);
}
.pdp .pdp-spec-l li::before {
  content: ""; position: absolute; left: 0; top: .6em;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--phenome-blue-300);
}


/* ---- narrower. Four across holds to 1180px, where the longest lines start
   wrapping to three; then two across, which pairs the eight exactly. */
@media (max-width: 1180px) {
  .pdp .pdp-specs-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1023px) {
  .pdp .pdp-specs-head { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .pdp .pdp-specs-h { padding-bottom: 0; }
  .pdp .pdp-specs-plate { margin-left: 18%; }
}
@media (max-width: 719px) {
  .pdp .pdp-specs-plate { margin-left: 8%; }
  .pdp .pdp-specs-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------------------------------------------------------------------
   7 · THE SWAP · the nav leaves, the product bar takes the top
   ------------------------------------------------------------------------ */

/* THE SAME CHANGE devices/ring/ring.css § 3b makes, asked for by name
   (2026-09-14): past the hero the global nav slides up and out, and
   shared.js's product bar rises into the space it left — name and Buy, one
   row, the only chrome on screen. It replaces the floating capsule this
   section used to draw at the foot of the viewport: two bars carrying the same
   product and the same button, one at each edge, would be saying it twice.

   "Past the hero" is the moment the sticky buy column scrolls away with the
   section it lives in, so the bar arrives exactly when the column's own
   Add-to-cart stops being on screen.

   THIS PAGE'S VERSION OF THE SWAP IS GONE, and that is the point: it worked
   here and on four other pages that had each copied it, while the forty product
   pages without a bespoke stylesheet went on stacking the nav and the bar. The
   rules were promoted verbatim to shared.css § "the swap", and shared.js — not
   pdp.js — now sets `.is-past-hero`, from the very observer that already owned
   `.on`, the aria-hidden toggle and the tabindex handoff. One source for both
   halves, so they cannot disagree. What is left below is the PDP's material. */

/* The glass material ring.css uses on both bars: 72% white,
   saturate(180%) blur(20px), a hairline instead of a drop. The same substance
   either side of the swap, so only the contents appear to change. */
.pdp .ph-bar,
.pdp .ph-bar.on {
  background: rgba(255, 255, 255, .72);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  box-shadow: none;
  border-bottom: 1px solid var(--pdp-rule, rgba(0, 0, 0, .07));
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pdp .ph-bar { background: var(--gl-tint-overlay); }
}
.pdp .ph-bar-inner { gap: 14px; justify-content: flex-start; }
/* pdp.js adds a thumbnail and a meta line; in a 56px bar they sit on one
   baseline with the name instead of stacking into a capsule. */
.pdp .ph-bar-thumb {
  width: 32px; height: 32px; border-radius: 50%;
  object-fit: cover; flex: none; display: block;
  background: var(--gl-tint-sunk);
  box-shadow: inset 0 0 0 1px #10214b14;
}
.pdp .ph-bar-txt {
  min-width: 0; flex: 1 1 auto;
  display: flex; align-items: baseline; gap: 12px;
}
.pdp .ph-bar-meta {
  font-size: 16px; line-height: 1.4;
  color: var(--ph-text-2); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pdp .ph-bar .btn.small { flex: none; }
@media (max-width: 560px) {
  .pdp .ph-bar-meta { display: none; }
}

/* ---------------------------------------------------------------------------
   8 · NARROW WIDTHS
   ------------------------------------------------------------------------ */

/* 1024 is where shared.css's own two-column gestures stand down (see its note
   at 755: "a 32-point heading beside a 24-point paragraph in 300px is not a
   composition, it is a squeeze"). Everything that is two columns here stacks at
   the same place, and every sticky thing stops being sticky — a sticky element
   in a single column is just an element that covers the thing under it. */
@media (max-width: 1024px) {
  /* THE HERO HAS TO BE STACKED HERE BY NAME. shared.css already stacks `.buy`
     at ≤1279, but its rule is `.buy` and this page's is `.pdp .buy` — two
     classes beat one, so the two-column grid would have survived all the way
     down to 320px and the film would have been 130px wide. The site's own rule
     losing to a page's is exactly the risk a page-scoped sheet carries, and the
     only defence is to restate every layout the base sheet was going to undo.
     Stacked, the film comes first and the column follows it: media over the
     decision, which is the order shared.css:2589 chose for the same block and
     the order every product page on the site already uses. */
  .pdp .buy { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  /* SQUARE ONCE IT HAS THE WHOLE WIDTH, and `max-height` is the wrong tool for
     saying so. A 4:5 frame at 886px wide is 1,107px tall, which is a monolith;
     capping it with `max-height: 76vh` does not shorten it, it SHRINKS THE
     WIDTH — aspect-ratio holds the ratio and gives up the other axis — so the
     film came out 547px wide sitting in an 886px track with 339px of nothing
     beside it. 1:1 keeps the frame full-width and its height in the same
     neighbourhood as the screen, and a square crop of a 9:16 source still holds
     the scene where a 4:3 one throws it away. */
  .pdp .pdp-gal-main { aspect-ratio: 1 / 1; }
  .pdp .buy-col {
    position: static; max-height: none; overflow: visible;
    padding-right: 0; margin-right: 0;
  }
  /* Stacked, the head still sits at the top of the column but the column is the
     whole width now, so the name takes a rung back — and only the name. The
     promise stays a supporting line under it rather than becoming the display
     it used to be when the head lived above both tracks: the rungs keep their
     order at every width, and only their scale moves. */
  .pdp .buy-col > .pdp-head { margin-bottom: 30px; padding-bottom: 26px; }
  .pdp .pdp-head .pdp-name { font-size: clamp(32px, 4.2vw, 44px); }
  .pdp .pdp-head .pdp-tagline { font-size: var(--ph-fs-21); }
  .pdp .pdp-head .lede { font-size: var(--ph-fs-17); line-height: var(--ph-lh-17-loose); max-width: 56ch; }
}

@media (max-width: 860px) {
  /* THE TWO COLUMNS STAY TWO COLUMNS, all the way to 320. This is the one thing
     the section cannot give up: it exists to be compared, and stacking the
     answers puts "4 g" above "6 g" where they read as two facts about one ring
     rather than one fact about two. The old key-table version was collapsed to
     one column at this width and that was exactly the failure.
     The columns stay side by side on a phone and narrow, which works because
     every value in the column is short. What gives instead is the padding, the card and the display sizes
     — the structure holds. */
  .pdp .pdp-vs { gap: 12px; }
  .pdp .pdp-vs-col { padding: 16px 12px 20px; border-radius: var(--ph-r18); grid-template-columns: minmax(0, 1fr); }
  .pdp .pdp-vs-sw { gap: 9px; flex-wrap: wrap; }
  .pdp .pdp-vs-dot { width: 22px; height: 22px; }
  /* Three columns on a phone: a price such as "SEK 2,350.00" cannot wrap (its
     space is non-breaking), so the columns give up side padding and the price
     steps down until it fits its column. */
  .pdp .pdp-vs:has(> .pdp-vs-col:nth-child(3)) { gap: 6px; }
  .pdp .pdp-vs:has(> .pdp-vs-col:nth-child(3)) .pdp-vs-col { padding-inline: 6px; }
  .pdp .pdp-vs:has(> .pdp-vs-col:nth-child(3)) .pdp-vs-price { font-size: clamp(13px, 3.6vw, 21px); line-height: 1.4; }
  .pdp .pdp-vs-pick { width: 100%; padding: 0 10px; font-size: var(--ph-fs-14); }
  .pdp .pdp-vs-v { font-size: clamp(30px, 8vw, 40px); }
  .pdp .pdp-vs-t { font-size: var(--ph-fs-17); line-height: var(--ph-lh-17); }
  .pdp .pdp-vs-s { font-size: var(--ph-fs-14); line-height: var(--ph-lh-14); }
}

@media (max-width: 560px) {
  /* On a phone the head is back at the column's own scale — the 1024 rule's
     44px name is a line for an 886px measure, not a 372px one. */
  .pdp .pdp-head .pdp-name { font-size: clamp(26px, 7.4vw, 32px); }
  .pdp .pdp-head .pdp-tagline { font-size: var(--ph-fs-19); }
  .pdp .pdp-head .lede { font-size: var(--ph-fs-17); line-height: var(--ph-lh-17-loose); }
  .pdp .pdp-gal-nav { right: 10px; bottom: 10px; }
  .pdp .buy-swatches { gap: 13px; }
  /* Portrait again on a phone. The reason square works at 768 is that the width
     is large; at 390 a square is 332px tall and the film stops being the hero.
     4:5 gives it back 83px and the source is portrait anyway. */
  .pdp .pdp-gal-main { aspect-ratio: 4 / 5; }
  /* THE CARDS KEEP THEIR TYPE AND GIVE UP THEIR PADDING. Measured at 320: the
     content box was 83px against "Titanium" at 84px — one pixel of overflow,
     which the wrap test missed because the word does not break, it just sits
     over its own edge. 13px of side padding gives it 99px and eleven of slack.
     The type is what makes this control findable and it is the last thing that
     should shrink; the padding is not doing any work at this width. */
  .pdp .buy-choice { padding: 15px 13px 14px; min-height: 88px; }
  .pdp .buy-choices { gap: 10px; }
  /* FOUR AND FOUR, not five-and-three. Eight chips at 44px need 408px and the
     content box is 372 at 430 and 262 at 320, so they wrap — and a flex wrap
     leaves 5+3 at one width and 4+4 at another, which reads as a ragged list
     rather than a scale. An explicit four-column grid wraps the same way at
     every width and the chips share the row evenly. */
  .pdp .buy-chips { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .pdp .buy-chips .tag { min-width: 0; }
  .pdp .ph-bar-inner { gap: 10px; }
  .pdp .pdp-lb-cap { display: none; }
}

/* ---------------------------------------------------------------------------
   9 · STILLNESS
   ------------------------------------------------------------------------ */

/* A reader who asked for less motion gets the whole page, all at once, with
   nothing moving. Note what is NOT withdrawn: the fades on the option controls
   and the accordions stay as instant state changes rather than being removed,
   because the state itself is the information. What goes is everything that
   travels — the crossfade, the rail fill, the lift's slide, the unfold, the
   pulse on the film dot. shared.js's own reduced-motion branches already hand
   the pinned band every point at once and stop the films. */
@media (prefers-reduced-motion: reduce) {
  .pdp *,
  .pdp *::before,
  .pdp *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .pdp .pdp-gal-main img { transition: none; }
  .pdp .pdp-gal-zoom { opacity: 1; }
  .pdp .ph-bar { transform: none; }
}

/* Where the script never runs, nothing below it is reachable and the page is the
   page it was: a photograph, a column of options, four figures, a navy band, a
   film, two materials and a table. Every enhancement above is additive and every
   control that needs script is a <button> that shows its state in the markup. */

/* ===========================================================================
   10 · THE BUY COLUMN, REBALANCED (2026-09-15, by request)

   What was wrong, measured at 1440x900:
     · ~100px of empty ground between the lede and "Material": a 53px margin
       under a 44px padding under the head's hairline;
     · the three field names at 14px and the chosen value shoved to the far
       right edge, 300px from the name it answers;
     · "or £14.92/mo" at 12px, the smallest type in the column;
     · the chosen size ringed by a 0.67px line, which at 44px reads as no
       ring at all.

   The column still finishes level with the frame beside it, which is the one
   proportion this hero keeps. The height comes back from the controls rather
   than from air: bigger type, bigger targets, one even rhythm between groups.

   Placed last and wrapped in the desktop query, so the stacked layouts below
   1024 keep the sizes their own blocks already give them. The few rules that
   are right at every width (the ring on the chosen size, the value beside its
   field name) sit outside it.
   ======================================================================== */

/* `hidden` on a swatch has to win over the flex display the row gives it */
.pdp .buy-swatch[hidden] { display: none; }

/* The value sits beside its name, not across the column from it. */
.pdp .pdp-opt-k {
  justify-content: flex-start; align-items: baseline; gap: 10px;
  font-size: 16px; line-height: 22px; font-weight: var(--ph-w-600);
  color: var(--ink-900);
}
.pdp .pdp-opt-k span {
  margin-left: 0; text-align: left;
  font-weight: var(--ph-w-400); color: var(--ph-text-2);
}

/* THE CHOSEN SIZE IS RINGED IN THE ACCENT AT 2.5PX. An inset shadow rather
   than a thicker border, so the chip does not grow by 4px and push its row. */
.pdp .buy-chips .tag.on {
  border-color: var(--ph-accent);
  box-shadow: inset 0 0 0 2px var(--ph-accent), 0 8px 22px -16px rgba(32, 58, 133, .55);
  color: var(--ph-accent); font-weight: var(--ph-w-600);
}
/* Under the cursor every chip takes the shared pill's accent fill; the chosen
   one's accent ink would vanish into it, so it takes the fill's white as the
   others do. */
.pdp .buy-chips .tag.on:hover { color: var(--ph-white); }
.pdp .buy-price .buy-sub { font-size: 15px; line-height: 1.4; color: var(--ph-text-2); }

@media (min-width: 1025px) {
  .pdp .buy { gap: clamp(40px, 4vw, 64px); grid-template-columns: minmax(0, 1fr) 470px; }

  /* head: the name, the promise and the lede, then straight into the choices */
  .pdp .buy-col > .pdp-head { margin: 0 0 30px; padding-bottom: 28px; }
  .pdp .pdp-head .pdp-name { font-size: clamp(38px, 3.2vw, 48px); line-height: 1.04; }
  .pdp .pdp-head .pdp-tagline { margin-top: 12px; font-size: clamp(21px, 1.6vw, 24px); }
  .pdp .pdp-head .lede { margin-top: 14px; font-size: 17px; line-height: 1.58; }

  /* one rhythm between the groups */
  .pdp .buy-opt + .buy-opt { margin-top: 34px; }
  .pdp .pdp-opt-k { margin-bottom: 0; }

  /* material: a pair of wide rows, name left and price right */
  .pdp .buy-choices { margin-top: 12px; gap: 12px; }
  .pdp .buy-choice {
    min-height: 74px; padding: 0 22px;
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
  }
  .pdp .buy-choice .n { font-size: 20px; line-height: 26px; font-weight: var(--ph-w-600); }
  .pdp .buy-choice .p { font-size: 18px; line-height: 24px; }

  /* finish: three discs you can actually aim at */
  .pdp .buy-swatches { margin-top: 14px; gap: 18px; }
  .pdp .buy-swatch { width: 40px; height: 40px; }
  .pdp .buy-swatch.on { outline-offset: 4px; }

  /* size: eight equal chips across the column */
  .pdp .buy-chips { margin-top: 12px; display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 8px; }
  .pdp .buy-chips .tag { min-width: 0; height: 50px; padding-inline: 0; justify-content: center; font-size: 17px; border-radius: 14px; }
  .pdp .buy-alt { margin-top: 14px; font-size: 16px; }

  /* price: the number and the monthly line both readable */
  .pdp .buy-price { margin-top: 32px; padding: 22px 24px; border-radius: 16px; }
  .pdp .buy-price .stat-num { font-size: 42px; line-height: 48px; }
  .pdp .buy-price .buy-sub { margin-top: 2px; font-size: 15px; line-height: 20px; color: var(--ph-text-2); }
  .pdp .buy-price .btn { height: 58px; padding: 0 44px; font-size: 18px; font-weight: 600; }

  /* the three promises */
  .pdp .buy-col .ticks { margin-top: 22px; gap: 10px; }
  .pdp .buy-col .ticks li { font-size: 16px; line-height: 22px; grid-template-columns: 18px 1fr; }
  .pdp .buy-col .ticks svg { width: 17px; height: 17px; margin-top: 3px; }
}

/* ---------------------------------------------------------------------------
   11 · THE BAND'S HEADLINE LADDER (2026-09-17, by request)
   A statement that runs to two lines takes the kit's two tone pair; a glance
   length label is set solid in the Band's Specifications ink and size.
   ------------------------------------------------------------------------ */
.pdp .pdp-vs-h { font-size: clamp(40px, 5.6vw, 84px); margin: 0 0 clamp(18px, 2vw, 28px); }
.pdp .pdp-vs-h + .lede { margin-left: 0; }
.pdp .pdp-specs-h {
  font-size: clamp(34px, 4.4vw, 60px); line-height: 1.05; font-weight: 600;
  letter-spacing: -0.02em; color: var(--ink-900);
}

/* ---------------------------------------------------------------------------
   12 · THE BUY COLUMN'S TYPE, SET TO THE BAND'S (2026-09-20, by request)

   The two product columns are the same object at 470 and 480 pixels wide, and
   a reader who moves between them should not be able to tell that two people
   set the type. They could: the head agreed — 46/48 for the name, 23 for the
   promise, 17 for the lede, at 1440 — and then every line under it drifted.

   WHAT DRIFTED, measured at 1440 against devices/band's own column:

     field name        16 / 22 / 500   ->   17 / 24 / 600
     field value       16 / 22         ->   16 / 24
     choice name       20 / 26 / 500   ->   17 / 23 / 600
     choice price      18 / 24         ->   16 / 23
     price             42 / 48 / 500   ->   36 / 42 / 600
     price sub         15 / 20         ->   15 / 21
     the three ticks   16 / 22         ->   16 / 24

   The material names were the loudest of these: at 20px over a 17px field name
   the answer was shouting over its own question, and three of them across a
   470px column left "Ceramic £199" with nowhere to go. At 17 they sit level
   with "Sport silicone" on the Band, which is the same control doing the same
   job. The price came down the other way, 42 to 36, for the same reason in
   reverse — the Band's £149 is the largest thing in its column without being
   the largest thing on the page.

   THE WEIGHTS COME WITH THE SIZES and are written as literals, which is not an
   oversight. `--ph-w-600` resolves to 500 site wide; devices/band/band.css asks
   for 600 by hand on every one of these lines, so a column set through the
   token reads a full step lighter than the column it is meant to match. The
   token is left alone — 82 pages read it — and this column says 600 the way
   the Band's does.

   NO BREAKPOINT OF ITS OWN. These are unconditional, so they also replace the
   two phone sizes further up the sheet, whose formulas were this column's own
   rather than the Band's. Every clamp below is copied from band.css verbatim,
   so the two columns now agree at every width rather than only at 1440.
   ------------------------------------------------------------------------ */
.pdp .buy-col .pdp-name {
  font-size: clamp(32px, 3.2vw, 48px); line-height: 1.04; font-weight: 600;
  letter-spacing: -0.02em;
}
.pdp .buy-col .pdp-tagline {
  font-size: clamp(20px, 1.6vw, 24px); line-height: 1.3; font-weight: 600;
}
.pdp .buy-col .pdp-head .lede { font-size: 17px; line-height: 1.55; }

.pdp .buy-col .pdp-opt-k {
  font-size: 17px; line-height: 24px; font-weight: 600; color: var(--ink-900);
}
/* The value still sits beside its name rather than under it, which is this
   column's arrangement and not a size: "Finish Black" and "Size 8" are two
   words where the Band's "Colour / Onyx" is a word and a menu. Only the
   leading is taken from the Band, so the pair sits on one baseline grid. */
.pdp .buy-col .pdp-opt-k span { font-size: 16px; line-height: 24px; font-weight: 400; }

.pdp .buy-col .buy-choice .n { font-size: 17px; line-height: 23px; font-weight: 600; }
.pdp .buy-col .buy-choice .p { font-size: 16px; line-height: 23px; font-weight: 400; }

.pdp .buy-col .buy-price .stat-num {
  font-size: 36px; line-height: 42px; font-weight: 600; letter-spacing: -0.02em;
}
.pdp .buy-col .buy-price .buy-sub { font-size: 15px; line-height: 21px; }

.pdp .buy-col .ticks li { font-size: 16px; line-height: 24px; }

/* ==========================================================================
   SIZE GUIDE (2026-10-08) · the link on the Size row and its <dialog>
   pdp.js sizeGuide() adds both. The link is the "Sizing kit instead" link a
   rung larger, pushed to the right end of the label row. The dialog is a
   centred white card on desktop and a bottom sheet below 640px.
   ======================================================================== */
.pdp .buy-col .pdp-opt-k .buy-guide {
  margin-left: auto; padding: 0; border: 0; background: none;
  display: inline-flex; align-items: center; gap: 4px;
  font: inherit; font-size: 16px; line-height: 24px; font-weight: 500;
  color: var(--ph-accent-link); cursor: pointer;
  transition: color var(--ph-dur-base) var(--ease-frosted-out);
}
.pdp .buy-col .pdp-opt-k .buy-guide::after,
.pdp .pdp-sg-kit::after {
  content: ""; width: 6px; height: 6px; margin-left: 2px;
  border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--ph-dur-base) var(--ease-frosted-out);
}
.pdp .buy-col .pdp-opt-k .buy-guide:hover { color: var(--ph-accent-hover); }
.pdp .buy-col .pdp-opt-k .buy-guide:hover::after,
.pdp .pdp-sg-kit:hover::after { transform: translateX(2px) rotate(45deg); }
.pdp .buy-guide:focus-visible,
.pdp .pdp-sg button:focus-visible {
  outline: var(--ph-focus-w) solid var(--ph-focus);
  outline-offset: var(--ph-focus-offset);
  border-radius: 6px;
}
@media (min-width: 1025px) {
  .pdp .buy-col .pdp-opt-k .buy-guide { font-size: 17px; }
}

html.pdp-sg-open, html.pdp-sg-open body { overflow: hidden; }

.pdp .pdp-sg {
  width: min(480px, calc(100vw - 32px)); max-width: none;
  max-height: calc(100dvh - 48px);
  margin: auto; padding: 0; border: 0; border-radius: 20px;
  background: #fff; color: var(--ink-900);
  box-shadow: 0 30px 80px -24px rgba(10, 30, 87, .45);
  overflow: auto; overscroll-behavior: contain;
}
.pdp .pdp-sg::backdrop { background: rgba(10, 30, 87, .38); }
.pdp .pdp-sg[open] { animation: pdp-sg-in .22s var(--ease-frosted-out, ease-out); }
@keyframes pdp-sg-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .pdp .pdp-sg[open] { animation: none; } }

.pdp .pdp-sg-card { padding: 26px 26px 24px; }
.pdp .pdp-sg-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.pdp .pdp-sg-eyebrow {
  margin: 0 0 4px; font-size: 13px; line-height: 18px; font-weight: 600; color: #203a85;
}
.pdp .pdp-sg h2 {
  margin: 0; font-size: 28px; line-height: 32px; font-weight: 600;
  letter-spacing: -0.02em; color: #0a1e57;
}
.pdp .pdp-sg-x {
  flex: none; width: 40px; height: 40px; margin: -4px -8px 0 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; background: #f1f3f8; color: #0a1e57; cursor: pointer;
  transition: background-color .2s ease, transform .2s ease;
}
.pdp .pdp-sg-x:hover { background: #e4e8f2; transform: rotate(90deg); }
.pdp .pdp-sg-x svg { width: 18px; height: 18px; display: block; }

/* How to measure: three numbered steps, each with its drawing, and the one
   rule that matters said on its own. */
.pdp .pdp-sg-measure {
  margin-top: 20px; padding: 18px 18px 16px; border-radius: 16px; background: #f5f7fb;
}
.pdp .pdp-sg h3 {
  margin: 0; font-size: 15px; line-height: 20px; font-weight: 600; color: #0a1e57;
}
.pdp .pdp-sg-steps { display: grid; gap: 12px; margin: 14px 0 0; padding: 0; list-style: none; }
.pdp .pdp-sg-steps li {
  display: grid; grid-template-columns: 40px minmax(0, 1fr); align-items: center; gap: 12px;
  font-size: 14px; line-height: 20px; color: #3b4566;
}
.pdp .pdp-sg-ic {
  position: relative; display: grid; place-items: center; width: 40px; height: 40px;
  border-radius: 12px; background: #fff; color: #203a85;
  box-shadow: inset 0 0 0 1px rgba(32, 58, 133, .1);
}
.pdp .pdp-sg-ic svg { width: 22px; height: 22px; }
.pdp .pdp-sg-ic b {
  position: absolute; top: -5px; right: -5px;
  display: grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
  background: #203a85; color: #fff; font-size: 11px; line-height: 1; font-weight: 700;
}
.pdp .pdp-sg-tip {
  display: inline-flex; align-items: center; gap: 8px; margin: 14px 0 0;
  padding: 6px 12px; border-radius: 99px; background: #fff;
  font-size: 13px; line-height: 18px; font-weight: 600; color: #203a85;
  box-shadow: inset 0 0 0 1px rgba(32, 58, 133, .12);
}
.pdp .pdp-sg-tip::before {
  content: ""; width: 7px; height: 7px; border-top: 1.6px solid currentColor; border-left: 1.6px solid currentColor;
  transform: translateY(2px) rotate(45deg);
}

/* The chart: short headings with their unit beneath, the size as a chip; the
   size picked on the page is the filled chip on a tinted row. */
.pdp .pdp-sg-chart { margin-top: 20px; }
.pdp .pdp-sg-table {
  width: 100%; border-collapse: separate; border-spacing: 0;
  font-size: 15px; line-height: 20px; font-variant-numeric: tabular-nums;
}
.pdp .pdp-sg-table th,
.pdp .pdp-sg-table td { padding: 7px 10px; text-align: left; }
.pdp .pdp-sg-table thead th {
  padding-top: 0; padding-bottom: 10px; border-bottom: 1px solid #e6e9f1;
  font-size: 12px; line-height: 16px; font-weight: 600; color: #203a85; vertical-align: bottom;
}
.pdp .pdp-sg-table thead small { display: inline; margin-left: 4px; font-size: 11px; font-weight: 500; color: #6e6e73; }
.pdp .pdp-sg-table thead th { white-space: nowrap; }
.pdp .pdp-sg-table tbody tr + tr th,
.pdp .pdp-sg-table tbody tr + tr td { border-top: 1px solid #f0f2f7; }
.pdp .pdp-sg-table tbody th { padding-left: 6px; white-space: nowrap; }
.pdp .pdp-sg-chip {
  display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  background: #f1f3f8; font-size: 14px; font-weight: 600; color: #0a1e57;
  transition: background-color .2s ease, color .2s ease;
}
.pdp .pdp-sg-yours {
  display: none; margin-left: 8px; padding: 2px 8px; border-radius: 99px;
  background: #fff; font-size: 11px; line-height: 16px; font-weight: 600; color: #203a85;
  vertical-align: middle;
}
.pdp .pdp-sg-table tbody td { color: #1d1d1f; font-weight: 500; }
.pdp .pdp-sg-table tbody td.pdp-sg-uk { color: #6e6e73; }
.pdp .pdp-sg-table tbody tr.on th,
.pdp .pdp-sg-table tbody tr.on td { background: #eef1f9; border-top-color: transparent; }
.pdp .pdp-sg-table tbody tr.on + tr th,
.pdp .pdp-sg-table tbody tr.on + tr td { border-top-color: transparent; }
.pdp .pdp-sg-table tbody tr.on th { border-radius: 12px 0 0 12px; }
.pdp .pdp-sg-table tbody tr.on td:last-child { border-radius: 0 12px 12px 0; color: #0a1e57; }
.pdp .pdp-sg-table tbody tr.on .pdp-sg-chip { background: #203a85; color: #fff; }
.pdp .pdp-sg-table tbody tr.on .pdp-sg-yours { display: inline-block; }
.pdp .pdp-sg-table tbody tr.on td { color: #0a1e57; font-weight: 600; }

.pdp .pdp-sg-note {
  display: flex; align-items: flex-start; gap: 8px; margin: 16px 0 0;
  font-size: 12px; line-height: 17px; color: #6e6e73;
}
.pdp .pdp-sg-note svg { flex: none; width: 15px; height: 15px; margin-top: 1px; color: #6e6e73; }
.pdp .pdp-sg-kit {
  width: 100%; margin-top: 18px; min-height: 48px; padding: 0 20px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 1.5px solid #203a85; border-radius: 99px; background: #fff;
  font: inherit; font-size: 15px; line-height: 20px; font-weight: 600; color: #203a85; cursor: pointer;
  transition: background-color .2s ease, color .2s ease;
}
.pdp .pdp-sg-kit:hover { background: #203a85; color: #fff; }

/* ONE SCREEN (2026-10-08): the whole guide shows without scrolling. From
   900px wide it is a wide card in two columns, the steps, note and kit
   button on the left, the chart on the right; below that the sheet is set
   tighter so all eight sizes fit. */
@media (min-width: 900px) {
  .pdp .pdp-sg { width: min(920px, calc(100vw - 48px)); }
  .pdp .pdp-sg-card {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
    grid-template-areas: "head head" "measure chart" "note chart" "kit chart";
    grid-template-rows: auto auto 1fr auto;
    column-gap: 44px; padding: 36px 40px 40px;
  }
  .pdp .pdp-sg-head { grid-area: head; }
  .pdp .pdp-sg-measure { grid-area: measure; margin-top: 24px; padding: 22px 22px 20px; }
  .pdp .pdp-sg-chart { grid-area: chart; margin-top: 24px; }
  .pdp .pdp-sg-note { grid-area: note; align-self: end; }
  .pdp .pdp-sg-kit { grid-area: kit; }
  .pdp .pdp-sg-table th, .pdp .pdp-sg-table td { padding-block: 6px; }
}
@media (max-width: 899px) {
  .pdp .pdp-sg-card { padding: 26px 24px 24px; }
  .pdp .pdp-sg h2 { font-size: 24px; line-height: 28px; }
  .pdp .pdp-sg-measure { margin-top: 16px; padding: 14px 16px; }
  .pdp .pdp-sg-steps { gap: 8px; margin-top: 10px; }
  .pdp .pdp-sg-steps li { grid-template-columns: 32px minmax(0, 1fr); gap: 10px; font-size: 13px; line-height: 17px; }
  .pdp .pdp-sg-ic { width: 32px; height: 32px; border-radius: 10px; }
  .pdp .pdp-sg-ic svg { width: 18px; height: 18px; }
  .pdp .pdp-sg-ic b { width: 16px; height: 16px; font-size: 10px; top: -4px; right: -4px; }
  .pdp .pdp-sg-tip { margin-top: 10px; padding: 4px 10px; font-size: 12px; }
  .pdp .pdp-sg-chart { margin-top: 12px; }
  .pdp .pdp-sg-table { font-size: 14px; line-height: 18px; }
  .pdp .pdp-sg-table thead th { padding-bottom: 6px; }
  .pdp .pdp-sg-table th, .pdp .pdp-sg-table td { padding-block: 3px; }
  .pdp .pdp-sg-chip { width: 28px; height: 28px; font-size: 13px; }
  .pdp .pdp-sg-note { margin-top: 10px; }
  .pdp .pdp-sg-kit { margin-top: 12px; min-height: 44px; }
}

/* Short phones (an iPhone SE): tighter still, so it still fits. */
@media (max-width: 899px) and (max-height: 760px) {
  .pdp .pdp-sg-eyebrow { display: none; }
  .pdp .pdp-sg h2 { font-size: 22px; line-height: 26px; }
  .pdp .pdp-sg-x { width: 34px; height: 34px; }
  .pdp .pdp-sg-measure { margin-top: 10px; padding: 10px 12px; }
  .pdp .pdp-sg-steps { gap: 6px; margin-top: 8px; }
  .pdp .pdp-sg-steps li { grid-template-columns: 26px minmax(0, 1fr); font-size: 12px; line-height: 16px; }
  .pdp .pdp-sg-ic { width: 26px; height: 26px; border-radius: 8px; }
  .pdp .pdp-sg-ic svg { width: 16px; height: 16px; }
  .pdp .pdp-sg-ic b { display: none; }
  .pdp .pdp-sg-tip { margin-top: 8px; }
  .pdp .pdp-sg-chart { margin-top: 8px; }
  .pdp .pdp-sg-table th, .pdp .pdp-sg-table td { padding-block: 2px; }
  .pdp .pdp-sg-chip { width: 24px; height: 24px; font-size: 12px; }
  .pdp .pdp-sg-note { margin-top: 8px; }
  .pdp .pdp-sg-kit { margin-top: 8px; min-height: 40px; }
}

/* Phones: a bottom sheet the width of the screen. */
@media (max-width: 640px) {
  .pdp .pdp-sg {
    width: 100%; max-height: 94dvh;
    margin: auto 0 0; border-radius: 20px 20px 0 0;
  }
  .pdp .pdp-sg[open] { animation-name: pdp-sg-up; }
  @keyframes pdp-sg-up { from { transform: translateY(100%); } to { transform: none; } }
  .pdp .pdp-sg-card { padding: 24px 22px calc(20px + env(safe-area-inset-bottom)); }
  .pdp .pdp-sg-table th, .pdp .pdp-sg-table td { padding-inline: 6px; }
  .pdp .pdp-sg-yours { display: none !important; }
}
