/* EdgeRift: product pages (templates/pages/product.twig + partials/product/*).
   Page CSS only: loaded after the shared kit, inside @layer pages, tokens only (no colour values).
   The <img sizes> in product.twig follow the --w values here and in components.css; change both together. */
@layer pages {

  /* ---------- Hero: NAME [pill] (H1) + red bar / tagline (owner, 2026-10-14: as the home page's features) ----------
     The pill sits on the right of the name at the home titles' scale (components.css: .42 of the title, centred on its
     caps), and the red bar under the name. The name shrinks to fit one line (--chars = the name's length; Rajdhani
     caps run ~.43em a character); where the pill doesn't fit beside it, it drops under the whole name. Taglines up
     to ~31 characters fit one line at 21px down to 320px; longer ones (iPad: 42) wrap, balanced. */
  .product-hero__name {
    font-size: min(clamp(40px, 4.4vw + 23px, 88px), calc((100vw - 2 * var(--gutter)) / (var(--chars) * .46)));
  }
  .product-hero__tagline { text-wrap: balance; }   /* longer lines wrap evenly on phones ("The ultimate solitaire. / Designed for iPad.") */

  /* ---------- Proof strip: rating, ratings, since (snapshot) ----------
     One row of three at every width. On phones it is a compact strip (~130px at 390: 26–28px values, 13px labels,
     tighter padding) instead of three stacked 48px figures (~420px). */
  .proof { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px; max-width: var(--w-content); margin-inline: auto; text-align: center; }
  @media (min-width: 768px) { .proof { gap: 24px; } }
  .proof__value {
    display: block; font-family: var(--f-display); font-weight: 600; line-height: 1; white-space: nowrap;
    font-size: clamp(26px, 4.6vw + 10px, 72px); font-variant-numeric: tabular-nums; letter-spacing: -.5px;
  }
  .proof__unit { font-size: .5em; font-weight: 700; letter-spacing: 0; margin-right: .08em; }
  .proof__label { display: block; margin-top: 6px; font-size: var(--t-fine); line-height: 1.3; color: var(--c-muted); }
  @media (min-width: 768px) { .proof__label { margin-top: 10px; font-size: var(--t-body); line-height: 1.47; } }
  .proof .stars { display: inline-block; margin: 0 0 0 .3em; vertical-align: .14em; --star: clamp(11px, 1.3vw + 6px, 24px); }
  @media (max-width: 767px) { .band--proof { padding-block: 28px 32px; } }
  @media (max-width: 374px) { .proof .stars { display: block; margin: 5px auto 0; } }   /* 320: the stars under the 4.6 */

  /* ---------- Headlines in phrases (pm.phrases): lines break between phrases, never inside one ---------- */
  .phrase { display: inline-block; }

  /* ---------- Type bands: Gameplay modes; Pro: why Pro (items), optional app icon (band.icon) ---------- */
  .type-band__icon { width: clamp(104px, 2.3vw + 95px, 128px); margin: 0 auto 28px; }
  .type-band__icon img, .closing__icon img { display: block; width: 100%; height: auto; border-radius: 22.37%; }
  .type-band__icon img { box-shadow: var(--shadow-device); }
  .modes { display: grid; grid-template-columns: 1fr 1fr; gap: 44px 16px; max-width: var(--w-content); margin: var(--gap-cta-media) auto 0; }
  @media (min-width: 768px) { .modes { grid-template-columns: repeat(4, 1fr); gap: 24px; } }
  /* Three items (Why Pro since "No tracking" left it, owner 2026-10-13): stacked on phones, then three columns as wide
     as the four above (.75 of the row less one 24px gap), centred */
  .modes:has(> :nth-child(3):last-child) { grid-template-columns: minmax(0, 360px); justify-content: center; }
  @media (min-width: 768px) { .modes:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, 1fr); max-width: calc(var(--w-content) * .75 - 6px); } }
  .modes__item .icon { width: 44px; height: 44px; margin: 0 auto 18px; }
  .modes__item p { margin-top: 6px; font-size: var(--t-body); line-height: 1.4; color: var(--c-muted); }
  .band--dark .modes__item p { color: var(--c-on-dark-muted); }
  /* Why Pro: two-word item titles ("Family Sharing") at title size, so all four sit on one line at 768+ */
  .type-band--why-pro .modes__title { font-size: var(--t-title); }

  /* ---------- Stage: centred text over a large device (XL Print) ---------- */
  /* Device sizes as Apple sizes them on a product page (owner, 2026-10-13: "can we make the iphone and screenshots
     larger", "what about ipad sizing"): the hero and the stage's device about 60% of a 1440 window for the iPad Pro
     (860px; nearly the full width on phones) and 29% for the iPhone 18 Pro (420px); in a split the iPad fills its
     column (640px) and the iPhone is 380px. <img sizes> in product.twig follow these; change both together. */
  .bleed--hero, .bleed--stage { --w: min(88vw, clamp(320px, 45vw + 212px, 860px)); }
  .bleed--stage { --show: .84; }
  .split .bleed { --w: clamp(300px, 32vw + 179px, 640px); }
  .bleed--stage.bleed--phone { --w: clamp(280px, 13.33vw + 228px, 420px); --show: 1.4; }

  /* ---------- What's new in {version}: a calm light split after the feature bands ----------
     Small title (.tile-title), the release date and note in small type, and a device about 80% of a feature
     split's (sizes.whatsNew in product.twig follows these --w values). */
  .whats-new__note { max-width: 34em; margin: 16px auto 0; font-size: var(--t-small); line-height: 1.45; color: var(--c-muted); }
  @media (min-width: 1024px) { .whats-new__note { margin-inline: 0; } }
  .split .whats-new__media { --w: clamp(280px, 21vw + 198px, 500px); }
  .split .whats-new__media.bleed--phone { --w: clamp(230px, 8.57vw + 197px, 320px); --show: 1.4; }

  /* ---------- Highlights: the rest of the feature list as tiles ---------- */
  .highlights { display: grid; gap: var(--tile-gap); margin-top: var(--gap-cta-media); }
  @media (min-width: 640px) { .highlights { grid-template-columns: 1fr 1fr; } }
  @media (min-width: 1024px) { .highlights { grid-template-columns: repeat(3, 1fr); } }
  .highlight { padding: 28px 24px 32px; border-radius: 18px; background: var(--c-band); }
  .band--grey .highlight { background: var(--c-bg); }
  @media (min-width: 1024px) { .highlight { padding: 36px 32px 40px; } }
  .highlight .icon { width: 36px; height: 36px; margin-bottom: 18px; }
  .highlight__title { font-size: clamp(21px, .38vw + 19.5px, 24px); }
  .highlight p { margin-top: 8px; font-size: var(--t-body); line-height: 1.47; color: var(--c-muted); }
  /* Phones: a list (icon beside the text, hairlines between) instead of nine stacked tiles */
  @media (max-width: 639px) {
    .highlights { gap: 0; }
    .highlight { display: grid; grid-template-columns: 32px 1fr; column-gap: 16px; padding: 20px 0; border-radius: 0; background: none; border-top: 1px solid var(--c-hairline); }
    .band--grey .highlight { background: none; }
    .highlight:last-child { border-bottom: 1px solid var(--c-hairline); }
    .highlight .icon { grid-row: span 2; width: 30px; height: 30px; margin: 0; }
    .highlight__title { font-size: 21px; }
    .highlight p { margin-top: 4px; }
  }

  /* Feature icons (macros/product.twig): line drawings in the text colour */
  .icon { display: block; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
  /* A "no" mark's gap: the same shape, filled and stroked wider in the band's background, under the mark, so the
     mark cuts cleanly through the drawing */
  .icon .icon__gap { fill: var(--c-bg); stroke: var(--c-bg); stroke-width: 3.5; }
  .band--grey .icon .icon__gap { fill: var(--c-band); stroke: var(--c-band); }
  .band--dark .icon .icon__gap { fill: var(--c-surface-dark); stroke: var(--c-surface-dark); }

  /* ---------- Themes: a large device and every theme (partials/product/themes.twig) ----------
     The band is always dark (ProductService::sections). .theme-show holds the stage and the picker: each theme's
     panel (device, text) is position:absolute against it, and .theme-show reserves the stage around it.
     Without the script the panels sit in their <li>s inside the rail, which they escape only while nothing between
     .theme-show and them is positioned, transformed or masked (rail, groups, <li>); the script moves them out.
     Two layouts:
     - stacked (below 1024px): the device, its name and caption under it, then a rail of tiles (scroller);
       .theme-show reserves the stage with padding-top (frame height + gap + --text-h);
     - two columns (1024px and up): the device on the left; on the right the name and caption, then every theme at
       once as a grid of swatches (names show on hover), vertically centred on the device (--col-top).
     The device fits the screen with the picker: --w is the width rule (--w-max) capped by the height left under the
     sticky local nav (100svh less --chrome), never below --w-min. assets/js/pages/product-themes.js measures the
     tallest name and caption (--text-h), the rail (--rail-h) and the right column's offset (--col-top).
     The devices are the home page's (owner, 2026-10-13: "use actual iPhone and iPad device frame"): the iPad Pro
     upright around a 2064×2752 capture (.039w bezels: --ratio 1.3073) and the iPhone 18 Pro around a 1206×2622 one
     (.037w: 2.0872), so the phone is narrower than the old frame for the same height. <img sizes> in the partial
     follow --w and the tiles; change both together. */
  .band--themes > .headline, .band--themes > .body-lg { position: relative; z-index: 1; }   /* above the stage's light */
  .theme-show {
    --ratio: 1.3073;
    --w-max: clamp(260px, 22vw + 212px, 460px);
    --w-min: 240px;
    --w: var(--w-max);
    --frame-h: calc(var(--w) * var(--ratio));
    --tile: clamp(62px, 2.2vw + 54px, 84px);
    --opt: calc(var(--tile) + 14px);   /* a tile's column: the square and its name */
    --text-h: 100px;
    --rail-h: 176px;
    --stage-gap: clamp(20px, .8vw + 17px, 28px);
    --picker-gap: clamp(24px, 1.5vw + 18px, 40px);
    --chrome: calc(var(--localnav-h) + 1px + 16px + var(--stage-gap) + var(--text-h) + var(--picker-gap) + var(--rail-h));
    --fade: clamp(16px, 2vw + 8px, 48px);
    position: relative; isolation: isolate; display: flow-root;   /* flow-root: the picker's margin stays inside */
    margin-top: var(--gap-cta-media);
    padding-top: calc(var(--frame-h) + var(--stage-gap) + var(--text-h));
  }
  @supports (height: 100svh) {
    .theme-show { --w: clamp(var(--w-min), (100svh - var(--chrome)) / var(--ratio), var(--w-max)); }
  }
  @media (min-width: 768px) { .theme-show { --text-h: 112px; } }
  .theme-show--phone { --ratio: 2.0872; --w-max: clamp(230px, 6vw + 207px, 290px); --w-min: 154px; }
  @media (max-height: 700px) and (max-width: 1023px) {   /* short phones: a tighter stage and rail, so the device stays as large as it can */
    .theme-show { --stage-gap: 16px; --picker-gap: 18px; --tile: 56px; --w-min: 220px; }
    .theme-show--phone { --w-min: 137px; }
  }

  /* Panels: hidden until selected; the selected one (CSS :has without the script, .is-shown with it) shows */
  .theme-panel {
    position: absolute; top: 0; left: 0; right: 0; z-index: 1;
    display: flex; flex-direction: column; align-items: center;
    visibility: hidden; opacity: 0; text-align: center; touch-action: pan-y; pointer-events: none;
  }
  .theme-panel__device { pointer-events: auto; }   /* swipe; the rest of the panel never covers the tiles */
  .theme-show:not(.is-live) .theme-opt:has(:checked) .theme-panel { visibility: visible; opacity: 1; animation: fade-in var(--d-theme) var(--ease); }
  .theme-show.is-live .theme-panel { transition: opacity .6s var(--ease), visibility 0s linear .6s; }
  .theme-show.is-live .theme-panel:is(.is-shown, .is-leaving) { visibility: visible; opacity: 1; transition-delay: 0s; }
  .theme-show.is-live .theme-panel.is-shown { z-index: 2; }
  .theme-show.is-live .theme-show__picker { position: relative; z-index: 3; }   /* the panels are in the stage now */
  /* Pictures load only once their panel is selected (or warmed by the script): display:none keeps lazy images unloaded */
  .theme-wall__fill, .theme-wall__card, .theme-panel__screen { display: none; }
  .theme-show:not(.is-live) .theme-opt:has(:checked) :is(.theme-wall__fill, .theme-wall__card, .theme-panel__screen),
  .theme-panel.is-warm :is(.theme-wall__fill, .theme-wall__card, .theme-panel__screen) { display: block; }
  @supports not selector(:has(a)) {   /* no :has(): the theme shown first stays (the script switches the rest) */
    .theme-show:not(.is-live) .theme-group:first-child .theme-opt:first-child .theme-panel { visibility: visible; opacity: 1; }
    .theme-show:not(.is-live) .theme-group:first-child .theme-opt:first-child :is(.theme-wall__fill, .theme-wall__card, .theme-panel__screen) { display: block; }
  }

  /* One soft light behind the device, the same for every theme (owner, 2026-10-13: the theme's own glow "gets bright
     and dims" as the themes change): the device changes, the stage stays still, as on Apple's colour pickers */
  .theme-show::before {
    content: ""; position: absolute; z-index: -1; top: calc(var(--frame-h) * -.1); left: 50%;
    width: calc(var(--w) * 2); height: calc(var(--frame-h) * 1.2); transform: translateX(-50%); pointer-events: none;
    background: radial-gradient(closest-side, var(--glow-stage-dark), transparent);
  }

  /* The frame: the screen sits on a "wall", the theme's tile blurred to fill the screen, which shows while the
     capture loads (a theme without one shows its tile across the screen, with "Wallpaper preview" in the eyebrow).
     The wall and the capture have the device's screen shape and corners (iPad Pro .021w, iPhone 18 Pro .127w); the
     iPhone's Dynamic Island (the frame's ::before) sits over the capture. */
  .theme-panel__device { position: relative; flex: none; }
  .theme-wall { position: relative; display: block; overflow: hidden; aspect-ratio: 2064 / 2752; border-radius: calc(var(--w) * .021); background: var(--c-device); }
  .theme-show--phone .theme-wall { aspect-ratio: 1206 / 2622; border-radius: calc(var(--w) * .127); }
  .theme-panel__device.device--iphone-pro::before { z-index: 3; }
  .theme-wall__fill { position: absolute; inset: -8%; max-width: none; }   /* past the screen's edges, so the blur stays even */
  .theme-panel .theme-wall img { width: 100%; height: 100%; border-radius: 0; object-fit: cover; }
  .theme-wall__fill img { filter: blur(calc(var(--w) * .05)) saturate(1.15); }
  .theme-wall--only .theme-wall__fill { inset: -8% -16%; }
  .theme-wall--only .theme-wall__fill img { filter: blur(calc(var(--w) * .07)) saturate(1.1); }
  .theme-wall__card { position: absolute; z-index: 1; top: 50%; left: 0; width: 100%; transform: translateY(-50%); }
  .theme-panel .theme-wall__card img {
    height: auto; aspect-ratio: 1;
    -webkit-mask-image: linear-gradient(transparent, #000 20%, #000 80%, transparent);
    mask-image: linear-gradient(transparent, #000 20%, #000 80%, transparent);
  }
  /* inside the frame's aluminium edge (a border), so the bezel less the edge */
  .theme-panel__screen { position: absolute; z-index: 1; top: calc(var(--bezel) - var(--edge, 0px)); left: calc(var(--bezel) - var(--edge, 0px)); right: calc(var(--bezel) - var(--edge, 0px)); }
  .theme-show.is-live .theme-panel__screen img { opacity: 0; transition: opacity .45s var(--ease); }
  .theme-show.is-live .theme-panel__screen.is-loaded img { opacity: 1; }

  /* Name and caption under the frame; the leaving panel's text fades out quickly while the frames crossfade */
  .theme-panel__text { width: 100%; max-width: 34em; margin-top: var(--stage-gap); padding-inline: 8px; }
  .theme-panel__eyebrow { margin-bottom: 6px; }
  .theme-panel__name { font-family: var(--f-display); font-weight: 700; font-size: var(--t-title); line-height: 1.15; color: var(--c-on-dark); }
  .theme-show.is-live .theme-panel__text { transition: opacity .3s var(--ease) .1s; }
  .theme-show.is-live .theme-panel.is-leaving .theme-panel__text { opacity: 0; transition-delay: 0s; transition-duration: .15s; }

  /* The rail: full bleed, the first tile on the wide column's edge; scroll-snap; the edge fades are sticky
     pseudo-elements at both ends (no padding-inline: ::before and ::after make the end space). A group's label waits
     (.is-ahead, set by the script) until it fits inside the rail, so it never shows cut at the right edge. */
  .theme-show__picker { min-inline-size: 0; margin: var(--picker-gap) 0 0; padding: 0; border: 0; }
  .theme-rail {
    --pad: max(var(--gutter), (100% - var(--w-wide)) / 2);   /* % = the rail's width (scroll-padding, ::before/::after margins) */
    display: flex; margin-inline: calc(-1 * var(--gutter)); padding-block: 2px 8px;
    overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scroll-padding-inline: var(--pad);
    scrollbar-width: thin; text-align: left;
  }
  .theme-show.has-paddles .theme-rail { scrollbar-width: none; }
  .theme-show.has-paddles .theme-rail::-webkit-scrollbar { display: none; }
  .theme-rail::before, .theme-rail::after { content: ""; position: sticky; z-index: 2; flex: none; width: var(--fade); pointer-events: none; }
  .theme-rail::before { left: 0; margin-right: calc(var(--pad) - var(--fade)); background: linear-gradient(90deg, var(--c-surface-dark), transparent); }
  .theme-rail::after { right: 0; margin-left: calc(var(--pad) - var(--fade)); background: linear-gradient(270deg, var(--c-surface-dark), transparent); }
  .theme-group { flex: none; }
  .theme-group + .theme-group { margin-left: clamp(20px, 3.4vw + 7px, 56px); }
  .theme-group__label { position: sticky; z-index: 1; left: var(--fade); width: max-content; margin: 0 0 14px; transition: opacity var(--d-base) var(--ease); }
  .theme-group.is-ahead .theme-group__label { opacity: 0; }
  .theme-group__list { display: flex; gap: 6px; margin: 0; padding: 0; list-style: none; }
  .theme-opt { flex: none; width: var(--opt); scroll-snap-align: start; }
  @media (min-width: 768px) {   /* phones show four and a half tiles, so the rail visibly goes on */
    .theme-show { --opt: calc(var(--tile) + 20px); }
    .theme-group__list { gap: 8px; }
  }

  /* A tile: the wallpaper square (ring when selected, like Apple's finish swatches), the name, the months. Every name
     keeps two lines, so the months and the tiles' bottoms line up whether a name wraps or not. */
  .theme-tile { position: relative; display: flex; flex-direction: column; align-items: center; padding-top: 6px; text-align: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .theme-tile__radio { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; -webkit-appearance: none; appearance: none; }
  .theme-tile__art {
    position: relative; display: block; width: var(--tile); aspect-ratio: 1; overflow: hidden; border-radius: 24%;
    background: var(--c-device-dark); transition: box-shadow var(--d-base) var(--ease);
  }
  .theme-tile__art::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--c-device-edge-dark); }
  .theme-tile__art img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--d-theme) var(--ease); }
  .theme-tile__radio:checked ~ .theme-tile__art { box-shadow: 0 0 0 3px var(--c-surface-dark), 0 0 0 5px var(--c-on-dark); }
  .theme-tile__radio:focus-visible ~ .theme-tile__art { outline: 2px solid var(--c-red-on-dark); outline-offset: 7px; }
  @media (hover: hover) {
    .theme-tile:hover .theme-tile__art img { transform: scale(1.06); }
    .theme-tile:hover .theme-tile__name { color: var(--c-on-dark); }
  }
  .theme-tile__name { min-height: 2.5em; margin-top: 12px; font-size: 12px; line-height: 1.25; color: var(--c-on-dark-muted); transition: color var(--d-fast) var(--ease); }
  .theme-tile__radio:checked ~ .theme-tile__name { color: var(--c-on-dark); }
  .theme-tile__when { margin-top: 2px; font-size: 11px; line-height: 1.25; color: var(--c-on-dark-muted); }
  .theme-tile__when--now { font-weight: 500; color: var(--c-red-on-dark); }
  /* Seasonal leads the picker as cards (owner, 2026-10-13): each theme's whole scene, the app's own 16:10 preview
     (realsolitaire-ipad-v7), 1.75 tiles wide, its name and months under it; Everyday stays compact squares */
  .theme-group--seasonal { --card: calc(var(--tile) * 1.75); }
  .theme-group--seasonal .theme-opt { width: calc(var(--card) + 14px); }
  .theme-group--seasonal .theme-tile__art { width: var(--card); aspect-ratio: 16 / 10; border-radius: calc(var(--tile) * .18); }
  .theme-group--seasonal .theme-tile:hover .theme-tile__art img { transform: scale(1.04); }
  @media (min-width: 768px) { .theme-tile__name { font-size: 13px; } .theme-tile__when { font-size: 12px; } }
  @media (max-height: 700px) and (max-width: 1023px) { .theme-tile__name { margin-top: 8px; } .theme-group__label { margin-bottom: 10px; } }

  /* Under the rail: the note, and the paddles (pointer devices, with the script) at the wide column's right edge */
  .theme-show__foot { display: flex; align-items: center; justify-content: center; gap: 16px 24px; max-width: var(--w-wide); margin: 20px auto 0; }
  .theme-show.has-paddles .theme-show__foot { justify-content: flex-end; }   /* the paddles, on the right */
  .theme-show__paddles { display: flex; flex: none; gap: 12px; }
  .theme-show__paddles[hidden] { display: none; }
  .theme-paddle {
    display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%;
    background: var(--c-device-dark); color: var(--c-on-dark); cursor: pointer; transition: opacity var(--d-fast) var(--ease), filter var(--d-fast) var(--ease);
  }
  .theme-paddle svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
  .theme-paddle:hover:not(:disabled) { filter: brightness(1.3); }
  .theme-paddle:disabled { opacity: .36; cursor: default; }
  .theme-paddle:focus-visible { outline: 2px solid var(--c-red-on-dark); outline-offset: 3px; }

  /* Two columns (1024px and up): the device on the left; the name, caption and every theme on the right, as a grid of
     nine swatches a row (all 32 or 27 at once, no paddles). The right column is --col-top from the device's top, so
     it sits centred on the device (0 without the script: top-aligned). A tile's name is a tooltip on hover and keyboard
     focus (still the radio's label); seasonal tiles keep their months. */
  @media (min-width: 1024px) {
    .theme-show {
      --w-max: clamp(380px, 33.65vw + 35px, 520px);
      --w-min: 320px;
      --chrome: calc(var(--localnav-h) + 1px + 48px);
      --col-gap: clamp(48px, 5vw, 80px);
      --col-max: 640px;
      --g-gap: 12px;
      --picker-gap: 28px;
      max-width: calc(var(--w) + var(--col-gap) + var(--col-max)); min-height: var(--frame-h); margin-inline: auto;
      padding-top: 0; padding-left: calc(var(--w) + var(--col-gap)); text-align: left;
    }
    .theme-show--phone { --w-max: clamp(290px, 12vw + 167px, 340px); --w-min: 205px; }
    .theme-panel { display: grid; grid-template-columns: var(--w) minmax(0, 1fr); column-gap: var(--col-gap); align-items: start; text-align: left; }
    .theme-show::before { left: calc(var(--w) / 2); }
    .theme-panel__text { max-width: none; margin-top: var(--col-top, 0px); padding-inline: 0; }
    .theme-panel__eyebrow { margin-bottom: 8px; }
    .theme-panel__name { font-size: clamp(30px, 1.2vw + 18px, 36px); }
    .theme-show__picker { margin-top: calc(var(--col-top, 0px) + var(--text-h) + var(--picker-gap)); }
    .theme-rail { display: block; margin-inline: 0; padding: 0; overflow: visible; scroll-snap-type: none; scroll-padding-inline: 0; }
    .theme-rail::before, .theme-rail::after { display: none; }
    .theme-group + .theme-group { margin: 24px 0 0; }
    .theme-group__label { position: static; margin: 0 0 12px; }
    .theme-group__list { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: var(--g-gap); }
    .theme-opt { width: auto; }
    .theme-tile { padding-top: 0; }
    .theme-tile__art { width: 100%; border-radius: 22%; }
    .theme-tile__name {
      position: absolute; z-index: 4; bottom: calc(100% + 10px); left: 50%; width: max-content; min-height: 0; margin: 0;
      padding: 5px 10px; border-radius: 6px; background: var(--c-device-dark); box-shadow: 0 6px 16px -6px rgba(0, 0, 0, .5);
      font-size: 13px; line-height: 1.3; color: var(--c-on-dark); white-space: nowrap; pointer-events: none;
      opacity: 0; transform: translate(var(--tx, -50%), 4px); transition: opacity .15s var(--ease), transform .15s var(--ease);
    }
    .theme-opt:nth-child(9n + 1) .theme-tile__name { left: 0; --tx: 0; }   /* the outer columns' tooltips stay inside the column */
    .theme-opt:nth-child(9n) .theme-tile__name { left: auto; right: 0; --tx: 0; }
    .theme-tile__radio:focus-visible ~ .theme-tile__name { opacity: 1; transform: translate(var(--tx, -50%), 0); }
    .theme-tile__radio:focus-visible ~ .theme-tile__art { outline-offset: 5px; }
    .theme-tile__when { margin-top: 9px; font-size: clamp(11px, .2vw + 9px, 12px); white-space: nowrap; }
    /* Seasonal: four cards a row, each with its name and months under it (no tooltip) */
    .theme-group--seasonal .theme-group__list { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px var(--g-gap); }
    .theme-group--seasonal .theme-opt { width: auto; }
    .theme-group--seasonal .theme-tile { align-items: flex-start; text-align: left; }
    .theme-group--seasonal .theme-tile__art { width: 100%; border-radius: 12px; }
    .theme-group--seasonal .theme-tile__name {
      position: static; width: auto; margin: 10px 0 0; padding: 0; border-radius: 0; background: none; box-shadow: none;
      font-size: 14px; line-height: 1.25; color: var(--c-on-dark-muted); opacity: 1; transform: none; transition: color var(--d-fast) var(--ease);
    }
    .theme-group--seasonal .theme-tile__radio:checked ~ .theme-tile__name { color: var(--c-on-dark); }
    .theme-group--seasonal .theme-tile__when { margin-top: 2px; }
    .theme-group--seasonal .theme-tile__radio:focus-visible ~ .theme-tile__name { transform: none; }
    .theme-show__foot { max-width: none; margin: 24px 0 0; justify-content: flex-start; }
  }
  @media (min-width: 1024px) and (hover: hover) {
    .theme-tile:hover .theme-tile__name { opacity: 1; transform: translate(var(--tx, -50%), 0); }
    .theme-group--seasonal .theme-tile:hover .theme-tile__name { color: var(--c-on-dark); transform: none; }
  }

  @media (forced-colors: active) {
    .theme-tile__radio:checked ~ .theme-tile__art { outline: 3px solid Highlight; outline-offset: 3px; }
    .theme-rail::before, .theme-rail::after { display: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .theme-show.is-live .theme-panel, .theme-show.is-live .theme-panel__text, .theme-show.is-live .theme-panel__screen img, .theme-tile__art img, .theme-tile__name, .theme-group__label { transition: none; }
    .theme-show:not(.is-live) .theme-opt:has(:checked) .theme-panel { animation: none; }
  }

  /* ---------- Card sets (partials/product/cardsets.twig; owner, 2026-10-13) ----------
     Each deck as a fanned hand on a rounded tile, its name and line under it. Everyday: three across from 1024, Royal
     two columns wide; Seasonal: four across, centred, so a short last row sits in the middle. Tiles are the band's
     contrast colour (grey on white, white on grey); a night deck's tile is the dark surface. */
  .cardsets .body-lg { max-width: 36em; margin-inline: auto; }
  .cardsets__label { margin: clamp(40px, 1.9vw + 33px, 60px) 0 18px; }
  .cardsets__label:first-of-type { margin-top: var(--gap-cta-media); }
  .cardsets__grid { --gap: clamp(12px, .76vw + 9px, 20px); display: grid; gap: var(--gap); max-width: 1140px; margin: 0 auto; padding: 0; list-style: none; text-align: left; }
  @media (min-width: 640px) { .cardsets__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (min-width: 1024px) {
    .cardsets__grid--everyday { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .cardset--feature { grid-column: span 2; }
  }
  .cardsets__grid--seasonal { display: flex; flex-wrap: wrap; justify-content: center; }
  .cardsets__grid--seasonal > li { flex: 0 0 100%; }
  @media (min-width: 640px) { .cardsets__grid--seasonal > li { flex-basis: calc((100% - var(--gap)) / 2); } }
  @media (min-width: 1024px) { .cardsets__grid--seasonal > li { flex-basis: calc((100% - 3 * var(--gap)) / 4); } }
  .cardset { display: flex; flex-direction: column; padding: clamp(18px, .76vw + 15px, 26px) clamp(18px, .76vw + 15px, 26px) clamp(20px, .76vw + 17px, 28px); border-radius: 24px; background: var(--c-band); }
  .band--grey .cardset { background: var(--c-bg); }
  .cardset--dark, .band--grey .cardset--dark { background: var(--c-surface-dark); color: var(--c-on-dark); }
  /* the art fills the tile above the text, so in a row of uneven tiles every name and line sits at the foot */
  .cardset__art { display: flex; flex: 1 0 auto; align-items: center; justify-content: center; min-height: 0; aspect-ratio: 2 / 1; margin-bottom: 18px; }
  .cardset--feature .cardset__art { aspect-ratio: auto; max-height: 340px; }
  /* a real width before the image loads (its width and height give the aspect), so lazy loading fires */
  .cardset__art picture { display: block; width: 100%; }
  .cardset__art img { display: block; width: 100%; height: auto; }
  .cardset--feature .cardset__art img { max-height: 300px; object-fit: contain; }
  .cardset__name { font-size: clamp(19px, .38vw + 17.5px, 22px); }
  .cardsets__grid--seasonal .cardset__art { margin-bottom: 14px; }
  .cardsets__grid--seasonal .cardset__name { font-size: 18px; }

  /* ---------- Reviews (partials/product/reviews.twig; owner, 2026-10-13) ----------
     Three pull quotes as cards (the band's contrast colour), stars in red, the quote in the display size of a tile
     title, the nickname and month under it; one column on phones, three from 900. */
  .reviews__list { display: grid; gap: clamp(12px, .76vw + 9px, 20px); max-width: 1140px; margin: var(--gap-cta-media) auto 0; padding: 0; list-style: none; text-align: left; }
  @media (min-width: 900px) { .reviews__list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
  .reviews__list > li { display: flex; }
  .review { display: flex; flex-direction: column; width: 100%; margin: 0; padding: clamp(24px, .95vw + 20px, 34px); border-radius: 24px; background: var(--c-band); }
  .band--grey .review { background: var(--c-bg); }
  .review__stars { --star: 18px; margin: 0 0 18px; }
  .review__stars::after { background: var(--c-red); }
  .review__quote { flex: 1; margin: 0; }
  .review__quote p { font-family: var(--f-display); font-weight: 700; font-size: clamp(21px, .57vw + 19px, 27px); line-height: 1.22; text-wrap: balance; }
  .review__by { margin-top: 20px; font-size: var(--t-small); font-weight: 500; color: var(--c-ink); }
  .review__when { font-weight: 400; color: var(--c-muted); }
  .reviews .cta-row { margin-top: clamp(28px, 1.14vw + 24px, 40px); }

  /* ---------- Compare ---------- */
  /* A lone link sits level with the first link of a pair. */

  /* ---------- Specs: the privacy policy link ---------- */
  .specs__link { color: var(--c-red-text); text-decoration: underline; text-underline-offset: .2em; text-decoration-thickness: 1px; }

  /* ---------- Closing lockup: NAME [pill], like the hero ---------- */
  .closing__icon { width: clamp(104px, 2.3vw + 95px, 128px); margin: 0 auto 24px; }
  .closing .tile-title + .sub { margin-top: 12px; }

  /* ---------- iPhone apps: the iPhone 18 Pro (components.css .device--iphone-pro) ----------
     Its screens are the creatives' in the 18 Pro's shape (images/devices/iphone18pro-*, a clean 9:41 status bar over
     the old notch strip). In the splits the phone shows about as much screen as the tablet does (~420 px tall at
     1440), so the iPad and iPhone pages keep the same band rhythm. */
  .bleed--hero.bleed--phone { --w: clamp(280px, 13.33vw + 228px, 420px); --show: 1.3; }
  .split .bleed--phone { --w: clamp(250px, 12.38vw + 202px, 380px); --show: 1.4; }
  /* frame 'full': the whole screenshot (its subject sits low). On iPad the whole device, above the band's foot with
     room for its shadow (owner, 2026-10-13: the iPad Pro frame is taller than the old one, so a fixed cut landed in
     its bottom bezel) */
  .split .bleed--full:not(.bleed--phone) { height: auto; padding-bottom: clamp(40px, 2.5vw + 30px, 72px); }
  /* the 18 Pro's screen is taller than the screenshots, so 'full' cuts where the screenshot ends (its foot is filler) */
  .split .bleed--phone.bleed--full { --show: 1.72; }
}
