/* zpl-pdf — pricing page
 *
 * Split out of app.css on 2026-09-14. app.css was 1699 lines and every page loaded all of it;
 * the pages now load base.css plus their own file. The rules are UNCHANGED — this was a cut,
 * not a rewrite, so every measurement and every comment explaining it moved intact.
 *
 * The configurator: pinned detail pane, gallery and the tier chooser. Only pricing/ uses these.
 */

/* ─────────────── pricing ───────────────
   Modelled on apple.com's Mac Studio buy page: the thing you are choosing is described at length
   on the left, and the chooser sits on the right as a column of selectable rows. It suits a
   tiered API better than a row of equal cards, because the tiers differ only in four numbers —
   side-by-side cards make the reader compare nine copies of the same shape, while one detail
   pane plus a compact list lets them scan prices first and read only the one they care about. */

.studio {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 384px;
  gap: 56px;
  align-items: start;
}

/* ── left: the selected plan, pinned ──
   Measured on apple.com/shop/buy-mac/mac-studio: the product imagery on the left holds still
   while the configurator on the right scrolls past it. The pinned side is the one you keep
   *referring to* while you choose; the scrolling side is the one you work down. Here that maps
   to the plan you have selected (left, pinned) against the nine tiers you are choosing from
   (right, scrolling) — which is the opposite of the first version, where the chooser was pinned
   and the description scrolled away from under it. */
.studio-detail {
  position: sticky;
  top: calc(var(--nav-h) + 20px);
  background: var(--bg);
  border-radius: var(--r);
  padding: 38px 34px;
}


/* ── the gallery ──
   Apple's buy page runs a carousel of product photography on the pinned side. We have no
   photographs, so each slide is drawn as inline SVG showing what the engine actually does. The
   track slides horizontally; only one slide is in the accessibility tree and tab order at a time
   (off-screen siblings are marked `inert` plus `aria-hidden` — not `hidden`, which would drop
   them out of the flex row and collapse the track), so a keyboard user is not walked through
   five panels of content they cannot see. */
/* The gallery is the whole of the pinned pane now, so it carries no trailing margin. */
.plan-gallery { margin-bottom: 0; }
.plan-gallery-viewport {
  position: relative;
  overflow: hidden;
  border-radius: 14px;
  /* No background of its own. The pinned card is already --bg (#F5F5F7) against a white section,
     so painting --bg-white here put a white card inside a grey one — two edges saying the same
     thing, and the inner one fighting the separation the outer one had already made. */
}
.plan-gallery-track {
  display: flex;
  transition: transform var(--dur) var(--ease);
  will-change: transform;
}
.plan-slide {
  flex: 0 0 100%;
  min-width: 0;
  padding: 48px 46px;
  /* Every slide is the height of the tallest, so the pinned pane does not jump as you page
     through — the same reason Apple's own carousel is a fixed frame. Measured on
     apple.com/shop/buy-mac/mac-studio: their frame runs to roughly 780px against a viewport of
     ~950px, i.e. it dominates the pinned side rather than sitting in a corner of it. The frame
     is sized the same way here — a viewport-relative height capped at 640px, so it stays large on a
     laptop and does not outgrow a short window. */
  height: min(640px, calc(100vh - var(--nav-h) - 150px));
  height: min(640px, calc(100dvh - var(--nav-h) - 150px));
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* Type scales with the frame: at 640px the old 17/14 read as a caption stranded in a large
   empty box. These sit one step up the site's own ladder. */
.plan-slide h4 {
  margin: 0 0 8px;
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.1;
  color: var(--ink);
}
.plan-slide p {
  margin: 0;
  font-size: 17px;
  line-height: 1.47;
  color: var(--ink-dim);
  letter-spacing: -0.016em;
  max-width: 46ch;
}
.plan-slide svg { display: block; max-width: 100%; }
/* Fill the room below each slide's copy while keeping the drawing centred and the frame steady.
   The old 330–360px inline caps left the SVGs undersized inside the wider gallery. */
.plan-slide-art {
  flex: 1 1 auto;
  min-height: 0;
  margin-top: 34px;
  display: flex;
  align-items: center;
}
.plan-slide-art svg { width: 100%; height: auto; max-height: min(100%, 450px); }

/* Slide 1: the selected plan's four figures, big. */
.slide-figures {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 30px 32px;
  margin-top: 40px;
}
.slide-figure dt {
  font-size: 13px;
  color: var(--ink-faint);
  letter-spacing: -0.005em;
  margin-bottom: 6px;
}
.slide-figure dd {
  margin: 0;
  /* The four figures are the point of slide 1, so they take the display size the frame now has
     room for — the same 40px step the site uses for its own headline numbers. */
  font-size: 40px;
  font-weight: 600;
  letter-spacing: -0.032em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.plan-gallery-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 14px;
}
.gallery-arrow {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  /* Transparent, not white. These were white when the viewport above them was white; now the
     whole pinned pane is --bg, so a white circle would be the only white left in the card and
     would read as a chip stuck on top of it. They earn their edge on hover instead. */
  background: transparent;
  color: var(--ink-dim);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.gallery-arrow:hover { background: rgba(0, 0, 0, .06); color: var(--ink); }
.gallery-arrow svg { width: 15px; height: 15px; }

.gallery-dots { display: flex; align-items: center; gap: 7px; }
/* The active dot stretches into a pill rather than changing colour alone — the same treatment as
   the dotnav elsewhere on the site (ui-research/apple/measurements.md §3C.1), and it reads at a glance. */
.gallery-dot {
  width: 7px; height: 7px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--line);
  cursor: pointer;
  transition: width var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.gallery-dot[aria-selected="true"] { width: 20px; background: var(--ink-faint); }

/* ── right: the chooser, scrolls ── */
.picker-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.022em;
  margin: 0 0 16px;
}
.picker-title span { color: var(--ink-dim); font-weight: 400; }

/* Family headings: nine flat rows read as a list of numbers, three groups of three read as a
   range with a shape. */
.plan-fam {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-faint);
  margin: 18px 0 8px;
}
.plan-fam:first-child { margin-top: 0; }

.plan-opts { display: flex; flex-direction: column; gap: 8px; }

/* The six tiers the backend does not sell yet. Still selectable — the page is a catalogue of what
   exists — but visibly quieter, and their call to action is disabled rather than pointing at a
   signup that answers 403 tier_not_available. */
.plan-opt.is-soon .plan-opt-face { background: #FCFCFD; }
.plan-opt.is-soon .plan-opt-name { color: var(--ink-dim); }

/* A real radio, visually hidden, with the label as the hit target: keyboard and screen readers
   get a proper radiogroup, and the ring is drawn on the face rather than on the input. */
.plan-opt { position: relative; display: block; }
.plan-opt input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  margin: 0;
}
.plan-opt-face {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 13px 15px;
  cursor: pointer;
  background: var(--bg-white);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.plan-opt-face:hover { border-color: var(--ink-faint); }
.plan-opt input:checked + .plan-opt-face {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.plan-opt input:focus-visible + .plan-opt-face {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

.plan-opt-main { flex: 1; min-width: 0; }

/* Both are block, not inline: as inline spans the name and the figure ran together on one line
   ("Personal Normal350,000 labels") and wrapped mid-phrase, and the meta's margin-top did
   nothing because vertical margins do not apply to inline boxes. Block puts the name on its own
   line with the figure beneath it, at the sizes each already had. */
.plan-opt-name {
  display: block;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.015em;
}
.plan-opt-meta {
  display: block;
  font-size: 12px;
  color: var(--ink-dim);
  letter-spacing: -0.005em;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.plan-opt-price {
  text-align: right;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.plan-opt-price small {
  display: block;
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-faint);
}

.plan-badge.is-soon { background: #F0F0F2; color: var(--ink-faint); }
.plan-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: -0.005em;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  margin-left: 7px;
  vertical-align: 1px;
}

.picker-cta { margin-top: 20px; }
.picker-fine {
  margin: 10px 0 0;
  font-size: 12px;
  color: var(--ink-faint);
  text-align: center;
  letter-spacing: -0.005em;
}

.loading { color: var(--ink-faint); font-size: 17px; text-align: center; }

/* The sticky chooser only makes sense beside a tall column; stacked, it would pin over the
   content it belongs to. */
@media (max-width: 980px) {
  .studio { grid-template-columns: minmax(0, 1fr); gap: 30px; }
  /* Stacked, a pinned pane would cover the list it belongs to. */
  .studio-detail { position: static; }
}

