/* Shop pages on design system v2.
 *
 * Loaded after tokens.css and school.css for any page declaring
 * designSheet: "shop". Written from what check-unstyled-classes reported after
 * the markup was converted, so every rule here answers a class the page
 * actually uses, and the v1 class names are kept because the page's own
 * calculator script binds several of them.
 *
 * Nothing here redraws a device school.css already provides: the hero, the
 * closing band, the lane markers, the FAQ and the buttons all come from there.
 */

/* ---------- 1. Shop hero ---------- */

/* The stacked hero title, same construction as a town: a small service line
   over a large green place line. The third line is a sub-clause, not a third
   size jump, so it sits well under the place name. */
.sm-shop-headline {
  max-width: 18ch;
  margin-bottom: var(--space-10);
}
.sm-shop-headline__sub {
  display: block;
  margin-top: var(--space-6);
  font-size: clamp(20px, 2.2vw, 30px);
  font-weight: var(--fw-semi);
  line-height: 1.15;
  letter-spacing: var(--ls-display);
  color: var(--color-text-body);
}
.sm-shop-headline__sub strong { color: var(--color-accent); font-weight: var(--fw-black); }

/* Trust pills under the hero copy. The pack's chip shape, sheared on the right
   like the lane marker, so they read as part of the same furniture. */
.sm-shop-pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  margin-top: var(--space-12);
}
.sm-shop-pill {
  padding: var(--space-4) var(--space-10);
  background: var(--rsa-line-10);
  border: 1px solid var(--rsa-line-16);
  border-radius: var(--radius-xs);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--color-text-body);
}

/* ---------- 2. Price calculator ---------- */

.calc-subtitle {
  max-width: 54ch;
  margin-bottom: var(--space-16);
  font-size: var(--fs-body-lg);
  color: var(--color-text-muted);
}

/* Controls left, the answer right. The answer is the point of the page, so it
   takes the larger share and the lighter ground. */
.calc-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--space-16);
  align-items: start;
}

.calc-selector {
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-top: var(--rule-green-top);
  border-radius: var(--radius-xs);
}

.calc-step + .calc-step { margin-top: var(--space-14); }

.calc-step-label {
  margin-bottom: var(--space-6);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--color-eyebrow);
}

.calc-options { display: flex; flex-wrap: wrap; gap: var(--space-5); }

/* The same chip the town pricing switch uses, so one interaction looks the
   same everywhere on the site. 44px is the touch-target floor. */
.calc-btn {
  min-height: 44px;
  padding: var(--space-5) var(--space-12);
  background: transparent;
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius-xs);
  font-family: var(--font-display);
  font-size: var(--fs-label);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--color-text-body);
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.calc-btn:hover { border-color: var(--color-accent); color: var(--color-text); }
/* .active is the class the page's own script toggles. Do not rename it. */
.calc-btn.active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-on-accent);
}
.calc-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.calc-lessons { gap: var(--space-4); }

.calc-note {
  margin-top: var(--space-14);
  padding-top: var(--space-10);
  border-top: 1px solid var(--rsa-line-12);
  font-size: var(--fs-small);
  color: var(--color-text-faint);
}

/* The answer panel. Chalk paper on a dark page, the one light surface, the
   same treatment the lead form's stage gets and for the same reason: it is
   where the visitor is asked to act. */
.calc-result {
  position: relative;
  padding: var(--pad-card);
  background: var(--rsa-chalk);
  color: var(--rsa-road-black);
  border-top: 10px solid var(--color-action);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

.calc-badge {
  display: inline-block;
  margin-bottom: var(--space-8);
  padding: var(--space-4) var(--space-8);
  background: var(--color-accent);
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--color-on-accent);
}

.calc-total-wrap { display: flex; flex-direction: column; }

/* The pack's display numeral: the largest single source of contrast on the
   page, and the figure the whole calculator exists to produce. */
.calc-total {
  font-family: var(--font-display);
  font-size: clamp(56px, 7vw, 96px);
  font-weight: var(--fw-black);
  line-height: 0.86;
  letter-spacing: var(--ls-tighter);
}
.calc-total-label {
  margin-top: var(--space-4);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--rsa-slate);
}

.calc-per {
  margin-top: var(--space-8);
  padding-top: var(--space-8);
  border-top: 2px dashed rgba(11, 11, 12, 0.25);
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-bold);
}
.calc-per span {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-black);
}

.calc-savings {
  margin-top: var(--space-6);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-bold);
  color: var(--rsa-sign-green);
}

.calc-includes {
  margin: var(--space-12) 0;
  padding-top: var(--space-10);
  border-top: 1px solid rgba(11, 11, 12, 0.14);
}
/* A tick list. Hanging indent, not a grid: a grid puts every inline child of a
   row in its own cell. */
.calc-inc {
  padding-left: var(--space-10);
  text-indent: calc(var(--space-10) * -1);
  margin-bottom: var(--space-5);
  font-size: var(--fs-body-sm);
  color: var(--rsa-graphite);
}

.calc-cta {
  display: block;
  min-height: 48px;
  padding: var(--space-8) var(--space-14);
  background: var(--color-action);
  border-radius: var(--radius-xs);
  font-family: var(--font-display);
  font-size: var(--fs-label);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  color: var(--rsa-white);
  box-shadow: var(--shadow-red-glow);
  transition: background var(--dur-fast), transform var(--dur-fast) var(--ease-reveal);
}
.calc-cta:hover { background: var(--color-action-hover); transform: var(--lift-sm); }
.calc-cta:focus-visible { outline: 3px solid var(--rsa-road-black); outline-offset: 3px; }

/* Rule 5: a phone alternative beside every Book action. */
.calc-or {
  margin-top: var(--space-8);
  font-size: var(--fs-body-sm);
  text-align: center;
  color: var(--rsa-slate);
}
.calc-or a { color: var(--rsa-road-black); font-weight: var(--fw-bold); }

/* ---------- 3. The full price table ---------- */

/* A table stays a table: these are prices to compare down a column, and the
   heading cells are content. */
.price-table-wrap { overflow-x: auto; }

.price-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  min-width: 480px;
}
.price-table .col-pkg { width: 40%; }
.price-table .col-price { width: 30%; }

.price-table thead th {
  padding: var(--space-8) var(--space-10);
  background: var(--color-panel);
  border-bottom: 2px solid var(--rsa-chalk);
  font-family: var(--font-display);
  font-size: var(--fs-caption);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-align: left;
  color: var(--color-text);
}

.price-table tbody td,
.price-table tbody th {
  padding: var(--space-8) var(--space-10);
  border-bottom: 1px solid var(--rsa-line-08);
  text-align: left;
  font-weight: var(--fw-regular);
}
.price-table tbody tr:hover { background: var(--rsa-line-08); }

/* Best value, one row only, the same signal the green ticket carries. */
.price-table .best-row { background: rgba(142, 219, 79, 0.08); }
.price-table .best-row td,
.price-table .best-row th { border-bottom-color: var(--rsa-sign-light, var(--color-accent)); }

.pt-label { font-weight: var(--fw-bold); color: var(--color-text); }
.pt-price {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-tight);
  color: var(--color-text);
}
.pt-per { font-size: var(--fs-small); color: var(--color-text-muted); }

/* ---------- 4. Reading sections ---------- */

/* The page's own prose class. Same measure and rhythm as .sm-prose, which it
   predates. */
.prose { max-width: 68ch; }
.prose p { margin-bottom: var(--space-10); color: var(--color-text-body); }
.prose p:last-child { margin-bottom: 0; }
.prose strong { color: var(--color-text); font-weight: var(--fw-bold); }
.prose a { color: var(--color-accent); }

/* Three card grids with different names and the same job. Column count comes
   from the item count, not from the width, so no row is left short. */
.info-grid,
.edt-grid,
.factors-grid {
  display: grid;
  gap: var(--space-12);
  margin-top: var(--space-14);
}
@media (min-width: 769px) {
  .info-grid, .edt-grid, .factors-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .info-grid:has(> :nth-child(3):last-child),
  .edt-grid:has(> :nth-child(3):last-child),
  .factors-grid:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.info-card {
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-top: 3px solid var(--rsa-line-16);
  border-radius: var(--radius-xs);
  transition: transform var(--dur-fast) var(--ease-reveal), border-color var(--dur-fast);
}
/* Every third card takes the green edge, as the town card grids do. */
.info-grid > .info-card:nth-child(3n + 1),
.edt-grid > .info-card:nth-child(3n + 1),
.factors-grid > .info-card:nth-child(3n + 1) { border-top-color: var(--color-accent); }
.info-card:hover { transform: var(--lift-sm); border-color: var(--rsa-line-22); }
.info-card h3 { margin-bottom: var(--space-6); font-size: var(--fs-h4); }
.info-card p { font-size: var(--fs-body-sm); color: var(--color-text-body); }

/* ---------- 5. Pretest panel ---------- */

.pretest-box {
  margin-top: var(--space-14);
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-radius: var(--radius-xs);
}

.pretest-prices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: var(--space-10);
  margin-top: var(--space-12);
}

/* Each price on its own ticket, with the perforation between what it is and
   what it costs. The pack's rule: every price lives on a ticket. */
.pretest-item {
  padding: var(--space-12);
  background: var(--rsa-chalk);
  color: var(--rsa-road-black);
  border-top: 4px solid var(--color-action);
  border-radius: var(--radius-md);
}
.pretest-type {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-label);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
.pretest-cost {
  display: block;
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 2px dashed rgba(11, 11, 12, 0.25);
  font-family: var(--font-display);
  font-size: var(--fs-num-xs);
  font-weight: var(--fw-black);
  line-height: 1;
  letter-spacing: var(--ls-tighter);
}

/* ---------- 6. Responsive ---------- */

@media (max-width: 1100px) {
  .calc-grid { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
  .sm-shop-headline { max-width: none; }
  .calc-selector, .calc-result, .pretest-box { padding: var(--space-12); }
  .calc-options { gap: var(--space-4); }
  /* The table scrolls rather than crushing six columns into 350px. */
  .price-table { min-width: 520px; }
}

/* ---------- 7. Contact centre ---------- */

/* Four forms behind four cards. The page script swaps them by setting
   style.display directly and owns #ct-cards, so nothing here may hide or show
   anything: these rules describe appearance only. */

.ct-sub { max-width: 52ch; margin-top: var(--space-10); font-size: var(--fs-body-lg); color: var(--color-text-body); }
.ct-phone-link { color: var(--color-accent); font-weight: var(--fw-bold); }

/* The details strip: hairline-separated cells, the proof bar construction. */
.sm-ct-strip { border-top: 1px solid var(--rsa-line-16); }
.ct-strip-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }
.ct-strip-item { padding: var(--space-12) var(--space-14); border-left: 1px solid var(--rsa-line-12); }
.ct-strip-item:first-child { border-left: 0; padding-left: 0; }
.ct-strip-label {
  margin-bottom: var(--space-4);
  font-size: var(--fs-eyebrow); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-eyebrow);
}
.ct-strip-value {
  font-family: var(--font-display); font-size: var(--fs-h4);
  font-weight: var(--fw-black); color: var(--color-text); text-decoration: none;
}
a.ct-strip-value:hover { color: var(--color-accent); }
.ct-strip-address { font-size: var(--fs-body); font-weight: var(--fw-semi); }

.ct-wrapper { display: grid; gap: var(--space-14); }

/* The four choices. Count-aware, so no row is left short. */
.ct-cards { display: grid; gap: var(--space-12); grid-template-columns: 1fr; }
@media (min-width: 769px) { .ct-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .ct-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.ct-card {
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-top: 3px solid var(--rsa-line-16);
  border-radius: var(--radius-xs);
  text-align: left; cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-reveal), border-color var(--dur-fast);
}
.ct-cards > .ct-card:nth-child(odd) { border-top-color: var(--color-accent); }
.ct-card:hover { transform: var(--lift-sm); border-color: var(--rsa-line-22); }
.ct-card:focus-visible { outline: 3px solid var(--color-accent); outline-offset: 3px; }
.ct-card-icon { font-size: 30px; line-height: 1; margin-bottom: var(--space-8); }
.ct-card h3 { margin-bottom: var(--space-5); font-size: var(--fs-h4); }
.ct-card p { font-size: var(--fs-body-sm); color: var(--color-text-muted); }

/* The form panel is the one light surface on the page, like the lead form
   stage, and for the same reason: it is where the visitor is asked to act. */
.ct-form-panel {
  padding: var(--pad-card);
  background: var(--rsa-chalk); color: var(--rsa-road-black);
  border-top: 10px solid var(--color-action);
  border-radius: var(--radius-md); box-shadow: var(--shadow-card);
}
.ct-back {
  min-height: 44px; margin-bottom: var(--space-10); padding: 0;
  background: none; border: 0;
  font-size: var(--fs-body-sm); font-weight: var(--fw-bold);
  color: var(--rsa-slate); cursor: pointer;
}
.ct-back:hover { color: var(--rsa-road-black); }
.ct-form-header { margin-bottom: var(--space-12); }
.ct-form-header h2 { color: var(--rsa-road-black); }
.ct-form-header p { font-size: var(--fs-body-sm); color: var(--rsa-slate); }

.ct-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: var(--space-10); }
.ct-field { display: flex; flex-direction: column; }
.ct-full { grid-column: 1 / -1; }
.ct-field label, .ct-captcha-row label {
  margin-bottom: var(--space-4);
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--rsa-slate);
}
.ct-optional { font-weight: var(--fw-regular); text-transform: none; letter-spacing: 0; }

/* background-color, never the background shorthand: the select draws its arrow
   with two sized gradients and the shorthand resets background-size. */
.ct-input, .ct-select, .ct-textarea, .ct-captcha-input {
  width: 100%; min-height: 46px;
  padding: var(--space-5) var(--space-9);
  background-color: var(--rsa-white);
  border: 1px solid var(--rsa-graphite);
  border-radius: var(--radius-xs);
  color: var(--rsa-road-black);
  font-family: var(--font-body); font-size: var(--fs-body-sm);
}
.ct-textarea { min-height: 120px; padding-top: var(--space-6); resize: vertical; }
.ct-input:focus, .ct-select:focus, .ct-textarea:focus, .ct-captcha-input:focus {
  border-color: var(--rsa-sign-green); outline: none;
}
.ct-select {
  appearance: none; -webkit-appearance: none;
  padding-right: var(--space-24);
  background-image: linear-gradient(45deg, transparent 50%, var(--rsa-slate) 50%),
                    linear-gradient(135deg, var(--rsa-slate) 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.ct-radio-group { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.ct-radio {
  display: inline-flex; align-items: center; gap: var(--space-4);
  min-height: 44px; padding: var(--space-5) var(--space-10);
  background-color: var(--rsa-white);
  border: 1px solid var(--rsa-graphite); border-radius: 100px;
  font-size: var(--fs-body-sm); cursor: pointer;
}
.ct-radio:has(input:checked) { border-color: var(--rsa-sign-green); background-color: rgba(0, 112, 60, 0.08); }

.ct-captcha-row { margin-top: var(--space-12); }
.ct-captcha-input { max-width: 160px; }
.ct-captcha-error { margin-top: var(--space-4); font-size: var(--fs-body-sm); color: var(--rsa-red); }

.ct-submit {
  min-height: 48px; margin-top: var(--space-12);
  padding: var(--space-8) var(--space-16);
  background: var(--color-action); border: 0; border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--rsa-white); cursor: pointer;
  box-shadow: var(--shadow-red-glow);
  transition: background var(--dur-fast), transform var(--dur-fast) var(--ease-reveal);
}
.ct-submit:hover { background: var(--color-action-hover); transform: var(--lift-sm); }
.ct-submit:disabled { opacity: 0.6; cursor: default; transform: none; }
.ct-status { margin-top: var(--space-8); font-size: var(--fs-body-sm); color: var(--rsa-slate); }

.ct-success {
  padding: var(--space-20) var(--pad-card);
  background: var(--color-panel); border-top: var(--rule-green-top);
  border-radius: var(--radius-xs); text-align: center;
}
.ct-success-icon { font-size: 44px; line-height: 1; margin-bottom: var(--space-10); }
.ct-success-timeline {
  max-width: 44ch; margin: var(--space-10) auto 0;
  padding-top: var(--space-10); border-top: 1px solid var(--rsa-line-12);
  font-size: var(--fs-body-sm); color: var(--color-text-muted);
}
.ct-success-actions { display: flex; flex-wrap: wrap; gap: var(--space-8); justify-content: center; margin-top: var(--space-14); }
.ct-btn-solid, .ct-btn-outline {
  min-height: 48px; display: inline-flex; align-items: center;
  padding: var(--space-6) var(--space-14); border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; text-decoration: none;
}
.ct-btn-solid { background: var(--color-action); color: var(--rsa-white); }
.ct-btn-solid:hover { background: var(--color-action-hover); }
.ct-btn-outline { border: 1px solid var(--color-field-border); color: var(--color-text); }
.ct-btn-outline:hover { border-color: var(--color-accent); color: var(--color-accent); }

.ct-info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: var(--space-12); margin-top: var(--space-14); }
.ct-info-card {
  padding: var(--pad-card); background: var(--color-panel);
  border: 1px solid var(--rsa-line-12); border-top: 3px solid var(--color-accent);
  border-radius: var(--radius-xs);
}
.ct-info-card h3 { margin-bottom: var(--space-8); font-size: var(--fs-h4); }
.ct-hours { margin-top: var(--space-6); }
.ct-hour-row {
  display: flex; justify-content: space-between; gap: var(--space-8);
  padding: var(--space-5) 0; border-bottom: 1px solid var(--rsa-line-08);
  font-size: var(--fs-body-sm); color: var(--color-text-body);
}
.ct-hour-row:last-child { border-bottom: 0; }
.ct-hours-note { margin-top: var(--space-8); font-size: var(--fs-small); color: var(--color-text-faint); }

.ct-call-btn {
  display: inline-flex; align-items: center; min-height: 48px;
  margin-top: var(--space-10); padding: var(--space-6) var(--space-14);
  background: var(--color-action); border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-h4);
  font-weight: var(--fw-black); color: var(--rsa-white); text-decoration: none;
}
.ct-call-btn:hover { background: var(--color-action-hover); }
.ct-call-sub { margin-top: var(--space-6); font-size: var(--fs-small); color: var(--color-text-faint); }

@media (max-width: 768px) {
  .ct-form-panel, .ct-success { padding: var(--space-12); }
  .ct-strip-item { border-left: 0; border-top: 1px solid var(--rsa-line-12); padding-left: 0; }
  .ct-strip-item:first-child { border-top: 0; }
}

/* ---------- 8. Gift vouchers ---------- */

/* The hero object here is the voucher itself, so this is the route skin: copy
   left, the object right on an offset block, no full-bleed photograph. */
.voucher-hero-grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); align-items: center; }
.voucher-hero-text .hero-sub { max-width: 46ch; margin: var(--space-10) 0 var(--space-12); font-size: var(--fs-body-lg); color: var(--color-text-body); }

/* The voucher preview: chalk paper, tilted a little so it reads as a physical
   thing rather than a panel, straightening on hover like the road sign. */
.voucher-hero-preview { position: relative; isolation: isolate; }
.voucher-hero-preview::after {
  content: "";
  position: absolute;
  inset: var(--space-10) calc(var(--space-9) * -1) calc(var(--space-9) * -1) var(--space-10);
  z-index: -1;
  background: var(--color-accent);
}
.vh-voucher-card {
  padding: var(--space-14);
  background: var(--rsa-chalk);
  color: var(--rsa-road-black);
  border-top: 10px solid var(--color-action);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
  transform: var(--tilt-sign-l);
  transition: transform var(--dur-base) var(--ease-reveal);
}
.vh-voucher-card:hover { transform: rotate(0deg); }

.gv-voucher-topbar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-8);
  padding-bottom: var(--space-8);
  border-bottom: 2px dashed rgba(11, 11, 12, 0.25);
}
.gv-voucher-logo { display: flex; align-items: center; }
.gv-voucher-logo-img { width: 92px; height: auto; }
.gv-voucher-date { font-size: var(--fs-caption); color: var(--rsa-slate); }

.gv-voucher-title {
  margin: var(--space-10) 0 var(--space-8);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-tight);
  text-transform: uppercase;
}
.gv-voucher-recipient { margin-bottom: var(--space-8); }
.gv-voucher-for, .gv-voucher-pkg-label, .gv-voucher-val-label {
  display: block;
  font-size: var(--fs-micro); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--rsa-slate);
}
.gv-voucher-name {
  display: block;
  font-family: var(--font-display); font-size: var(--fs-h4);
  font-weight: var(--fw-black); color: var(--rsa-road-black);
}
.gv-voucher-message { font-size: var(--fs-body-sm); font-style: italic; color: var(--rsa-graphite); }
.vh-voucher-sender { display: block; margin-top: var(--space-5); font-size: var(--fs-body-sm); font-weight: var(--fw-bold); }

.gv-voucher-details {
  display: flex; flex-wrap: wrap; gap: var(--space-10);
  margin: var(--space-10) 0;
  padding: var(--space-10) 0;
  border-top: 2px dashed rgba(11, 11, 12, 0.25);
  border-bottom: 2px dashed rgba(11, 11, 12, 0.25);
}
.gv-voucher-package, .gv-voucher-value { flex: 1 1 0; min-width: 120px; }
.gv-voucher-pkg-name { display: block; font-weight: var(--fw-bold); }
/* The amount is the figure the voucher exists to carry, so it takes the
   display scale. */
.gv-voucher-val-amount {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-num-xs);
  font-weight: var(--fw-black);
  line-height: 1;
  letter-spacing: var(--ls-tighter);
}
.gv-voucher-footer { font-size: var(--fs-caption); color: var(--rsa-slate); }
.gv-voucher-ref { font-weight: var(--fw-bold); color: var(--rsa-graphite); }
.gv-voucher-redeem, .gv-voucher-validity { display: block; margin-top: var(--space-4); }

/* The three tiers. Each price on a ticket with its own CTA, per rule 4. */
.voucher-grid { display: grid; gap: var(--space-12); margin-top: var(--space-14); }
@media (min-width: 769px) { .voucher-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.voucher-card {
  display: flex; flex-direction: column;
  padding: var(--pad-card);
  background: var(--rsa-chalk);
  color: var(--rsa-road-black);
  border-top: 10px solid var(--color-action);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-fast) var(--ease-reveal);
}
.voucher-card:hover { transform: var(--lift-sm); }
/* One green card only, the pack rule: green means best value, never decoration. */
.voucher-green { background: var(--color-accent); border-top-color: var(--rsa-road-black); }
.voucher-amber { border-top-color: var(--color-star); }
.voucher-red { border-top-color: var(--color-action); }
/* The three cards are read across, price against price, so their rows have to
   line up. They did not: the MOST POPULAR pill is taller than a plain label and
   carries a margin under it, which pushed the green card's heading, price, body
   and button 25px below their counterparts on the other two cards. A featured
   card sitting LOWER than its neighbours is nobody's intention, it is just the
   badge shoving everything down, and it is invisible to every correctness gate
   because each card is independently valid.

   The cards are separate grid items, so no CSS can equalise their internal rows
   without subgrid. Instead the label row reserves the badge's height on all
   three, written once as --voucher-badge-h and used by both label variants, so
   the plain label occupies exactly the space the pill does. Same shape as
   --step-num-size: one number, not two that have to agree. */
.voucher-card { --voucher-badge-h: 35px; }
.voucher-label, .voucher-label-popular {
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label); text-transform: uppercase;
}
.voucher-label {
  display: flex; align-items: center;
  align-self: flex-start;
  min-height: var(--voucher-badge-h);
  margin-bottom: var(--space-6);
}
.voucher-label-popular {
  align-self: flex-start;
  min-height: var(--voucher-badge-h);
  margin-bottom: var(--space-6);
  padding: var(--space-4) var(--space-8);
  background: var(--rsa-road-black);
  border-radius: var(--radius-sm);
  font-size: var(--fs-micro);
  color: var(--rsa-chalk);
}
.voucher-price {
  margin: var(--space-6) 0 var(--space-10);
  padding-bottom: var(--space-8);
  border-bottom: 2px dashed rgba(11, 11, 12, 0.25);
  font-family: var(--font-display);
  font-size: var(--fs-num-xs);
  font-weight: var(--fw-black);
  line-height: 1;
  letter-spacing: var(--ls-tighter);
}
/* Headings inside a pale card must be told they are on a pale card. The sheet
   sets h1 to h4 to chalk globally, for a dark page, so an untreated heading on
   chalk paper came out chalk on chalk: measured 1:1 on two of these cards and
   1.54:1 on the green one. Same fault the price tickets had. */
/* Each pale card declares its own ink, and every text role inside reads from
   that, so there is one place per card deciding what dark means.

   Headings alone were not enough. These cards carry .info-card as well, whose
   `p` rule paints --color-text-body, and that token is #C4C4C7: "body copy on
   black". It measured 1.58:1 on the chalk cards and 1.03:1 on the green one,
   which is text you cannot read at all. A heading-only fix could never have
   caught it, because the fault was in the roles nobody had thought about: the
   paragraph, and the EDT link inside it. */
.voucher-card, .vh-voucher-card, .gv-voucher-card {
  --card-ink: var(--rsa-road-black);
  --card-ink-body: var(--rsa-graphite);
}
/* On Go Green the pack is explicit: text is ALWAYS road black, not a softened
   grey, so the green card overrides the body ink too. */
.voucher-green { --card-ink: var(--color-on-accent); --card-ink-body: var(--color-on-accent); }

.voucher-card :is(h2, h3, h4), .vh-voucher-card :is(h2, h3, h4),
.gv-voucher-card :is(h2, h3, h4) { color: var(--card-ink); }
.voucher-card :is(p, li, small, span), .vh-voucher-card :is(p, li, small),
.gv-voucher-card :is(p, li, small) { color: var(--card-ink-body); }
.voucher-card .voucher-label-popular { color: var(--rsa-chalk); }
.voucher-card p { font-size: var(--fs-body-sm); margin-bottom: var(--space-10); }
/* An inline link on a pale card cannot be told apart by colour once it is the
   same dark ink as the sentence around it, so it carries a real underline. */
.voucher-card p a, .vh-voucher-card p a, .gv-voucher-card p a {
  color: var(--card-ink);
  font-weight: var(--fw-bold);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  text-decoration-color: var(--color-action);
}
.voucher-card p a:hover, .vh-voucher-card p a:hover, .gv-voucher-card p a:hover {
  text-decoration-color: var(--card-ink);
}
/* Every card's CTA sits on the card's bottom edge, whichever button class the
   markup used. The rule named .btn only, but the first card's button is
   .sm-btn, so that one alone was never pushed down: it sat directly under its
   paragraph. At 1440 the three paragraphs happen to occupy equal height and it
   looked right, which is why it survived. At 1100 they wrap differently and the
   button stood 26px above the other two. */
.voucher-card :is(.btn, .sm-btn) { margin-top: auto; }

/* The page's own button classes, kept because its markup uses them. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: var(--space-6) var(--space-14);
  border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; text-decoration: none;
  transition: background var(--dur-fast), transform var(--dur-fast) var(--ease-reveal);
}
.btn:hover { transform: var(--lift-sm); }
.btn-green { background: var(--rsa-road-black); color: var(--rsa-chalk); }
.btn-red, .btn-amber-dark { background: var(--color-action); color: var(--rsa-white); }
.btn-red:hover, .btn-amber-dark:hover { background: var(--color-action-hover); }

/* Three numbered steps on the dashed road line. */
.steps { display: grid; gap: var(--space-12); margin-top: var(--space-14); }
@media (min-width: 769px) { .steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Every offset here is computed from the circle's own size plus a gap, so the
   two can never disagree. They did, on both axes: a separately typed 40px of
   left padding against a 44px circle put the heading 4px INSIDE the number at
   desktop, and a separately typed 32px of top padding overlapped it by 12px at
   phone width. The layout stacks below 769px, so the clearance moves from the
   left edge to the top, and only the axis in use is ever set. */
.step {
  position: relative;
  --step-num-size: 44px;
  --step-num-gap: var(--space-8);
  padding-top: calc(var(--step-num-size) + var(--step-num-gap));
}
@media (min-width: 769px) {
  .step { padding-top: 0; padding-left: calc(var(--step-num-size) + var(--step-num-gap)); }
  /* Beside the circle, the heading reads as its label, so it takes the
     circle's optical centre rather than sitting at its top edge. Stacked, the
     heading is below the circle and a min-height would only add dead space. */
  .step h3 { min-height: var(--step-num-size); display: flex; align-items: center; }
}
.step-num {
  position: absolute; left: 0; top: 0;
  display: grid; place-items: center;
  width: var(--step-num-size); height: var(--step-num-size);
  background: var(--color-accent);
  border-radius: var(--radius-round);
  font-family: var(--font-display); font-size: var(--fs-h4);
  font-weight: var(--fw-black); color: var(--color-on-accent);
}
.step h3 { margin-bottom: var(--space-5); font-size: var(--fs-h4); }
.step p { font-size: var(--fs-body-sm); color: var(--color-text-body); }

.occasions-grid, .voucher-trust-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: var(--space-10);
  margin-top: var(--space-14);
}
.voucher-trust-item {
  padding: var(--space-12);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-top: 3px solid var(--color-accent);
  border-radius: var(--radius-xs);
}
.voucher-trust-icon { font-size: 26px; line-height: 1; margin-bottom: var(--space-6); }

.voucher-cta { text-align: center; }
.cta-phone { margin-top: var(--space-8); font-size: var(--fs-body-sm); color: var(--color-text-muted); }
.cta-phone a { color: var(--color-text); font-weight: var(--fw-bold); }
/* This sits in a red band, where the band's `.sm-band p` rule puts body copy on
   white. It is a div, so that rule never reached it and the muted grey above
   stood at 2:1 on red, the worst real contrast fault on the site. The link
   beside it was 4.385:1 as chalk. Both take the band's documented ink. */
.sm-band .cta-phone,
.sm-band .cta-phone a { color: var(--color-on-red-muted); }

@media (max-width: 1100px) {
  .voucher-hero-grid { grid-template-columns: 1fr; }
  .vh-voucher-card { transform: none; }
  .voucher-hero-preview::after { display: none; }
}
@media (max-width: 768px) {
  .vh-voucher-card { padding: var(--space-12); }
}

/* ---------- 9. Pay now ---------- */

/* Generated from the inline style attributes this page carried, so that a
   stylesheet can reach them. Any `display` stayed inline, because the page
   script sets .style.display on six of these elements and an inline value
   there is behaviour, not presentation. v1 token names are mapped onto
   their v2 equivalents. */

.pn-s1 {
  padding: 6rem 0 2rem;
}

.pn-s2 {
  padding: 3rem 0;
}

.pn-s3 {
  max-width: 1200px;
  margin: 0 auto;
}

.pn-s4 {
  justify-content: center;
  gap: 2rem;
}

.pn-s5 {
  font-family: var(--font-display);
  font-size: var(--fs-h1);
  font-weight: var(--fw-black);
  color: var(--color-text);
  margin: 1.5rem 0 1rem;
  letter-spacing: var(--ls-display);
}

.pn-s6 {
  font-size: 1.1rem;
  color: var(--color-text-body);
  line-height: 1.6;
  max-width: 600px;
}

.pn-s7 {
  margin-bottom: 2rem;
  padding: 1.25rem;
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-radius: 10px;
}

.pn-s8 {
  color: var(--color-text-body);
  font-size: 0.9rem;
  margin: 0;
}

.pn-s9 {
  color: var(--color-text);
}

.pn-s10 {
  margin-bottom: 2rem;
  text-align: center;
}

.pn-s11 {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 0.75rem;
}

.pn-s12 {
  min-height: 200px;
}

.pn-s13 {
  text-align: center;
  color: var(--color-text-muted);
}

.pn-s14 {
  margin-bottom: 1.5rem;
}

.pn-s15 {
  background: none;
  border: none;
  color: var(--color-accent);
  cursor: pointer;
  font-size: 0.95rem;
  padding: 0;
}

.pn-s16 {
  color: var(--accent-red, #e53e3e);
  font-size: 0.85rem;
  margin-top: 0.5rem;
}

.pn-s17 {
  text-align: center;
  margin-top: 1rem;
  font-size: 0.9rem;
}

.pn-s18 {
  text-align: center;
  padding: 3rem 1rem;
}

.pn-s19 {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--color-accent);
  align-items: center;
  justify-content: center;
  margin: 0 auto 1.5rem;
}

.pn-s20 {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  color: var(--color-text);
  margin-bottom: 1rem;
}

.pn-s21 {
  color: var(--color-text-body);
  font-size: 1.05rem;
  max-width: 480px;
  margin: 0 auto 1.5rem;
}

.pn-s22 {
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.pn-s23 {
  margin-top: 2rem;
  text-align: center;
  padding: 1.5rem;
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-radius: 10px;
}

.pn-s24 {
  color: var(--color-text-body);
  margin: 0 0 1rem;
}

.pn-s25 {
  color: var(--color-accent);
  font-weight: 600;
  font-size: 1.1rem;
  text-decoration: none;
}

/* ---------- 10. Pay now checkout ---------- */

/* The shop. Every class name here is the one the page script already uses, so
   none may be renamed: .pn-product-card carries data-product-id, .pn-select-btn
   is bound by a click handler, and #pn-card-element is the Stripe mount point.
   These rules describe appearance only; showing and hiding stays with the
   script, which sets style.display directly. */

.pn-checkout-container { display: grid; gap: var(--space-16); align-items: start; }
@media (min-width: 1100px) {
  .pn-checkout-container { grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.9fr); }
}
.pn-checkout-main { display: grid; gap: var(--space-14); }

/* The product grid. Column count follows the item count so the last row is
   never short; the catalogue returns five to nine packages. */
.pn-products-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  gap: var(--space-10);
}
.pn-product-card {
  display: flex; flex-direction: column; gap: var(--space-6);
  padding: var(--space-12);
  background: var(--rsa-chalk);
  color: var(--rsa-road-black);
  border-top: 6px solid var(--color-action);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-fast) var(--ease-reveal);
}
.pn-product-card:hover { transform: var(--lift-sm); }
.pn-product-name {
  /* Two lines' worth of room whether the name needs it or not, so the
     perforation and the price land on the same line across the row. The
     pretest name wraps and the lesson packages do not, which left the prices
     stepping down the row. */
  min-height: 2.5em;
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label); text-transform: uppercase;
  line-height: 1.25;
}
/* Every price on a ticket, with the perforation between what it is and what it
   costs. */
.pn-product-price {
  padding-top: var(--space-6);
  border-top: 2px dashed rgba(11, 11, 12, 0.25);
  font-family: var(--font-display);
  font-size: var(--fs-num-xs);
  font-weight: var(--fw-black);
  line-height: 1;
  letter-spacing: var(--ls-tighter);
}
.pn-product-btn, .pn-select-btn {
  margin-top: auto; min-height: 44px;
  padding: var(--space-5) var(--space-10);
  background: var(--color-action); border: 0; border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-caption);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--rsa-white); cursor: pointer;
}
.pn-product-btn:hover, .pn-select-btn:hover { background: var(--color-action-hover); }
.pn-product-btn:focus-visible, .pn-select-btn:focus-visible { outline: 3px solid var(--rsa-road-black); outline-offset: 2px; }

/* A numbered step in the checkout, the lane marker applied to a form. */
.pn-form-section {
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-radius: var(--radius-xs);
}
.pn-section-header { display: flex; align-items: center; gap: var(--space-6); margin-bottom: var(--space-12); }
.pn-section-number {
  display: grid; place-items: center;
  width: 30px; height: 30px; flex: 0 0 auto;
  background: var(--color-accent); border-radius: var(--radius-round);
  font-family: var(--font-display); font-size: var(--fs-caption);
  font-weight: var(--fw-black); color: var(--color-on-accent);
}
.pn-section-title { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: var(--fw-black); color: var(--color-text); }

.pn-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: var(--space-10); }
.pn-form-row-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: var(--space-10); }
.pn-field { display: flex; flex-direction: column; }
.pn-label {
  margin-bottom: var(--space-4);
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-text-muted);
}
.pn-input {
  width: 100%; min-height: 46px;
  padding: var(--space-5) var(--space-9);
  background-color: var(--color-bg);
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius-xs);
  color: var(--color-text);
  font-family: var(--font-body); font-size: var(--fs-body-sm);
}
.pn-input:focus { border-color: var(--color-accent); outline: none; }
/* A select drawn by the browser is the one control that still reads unstyled.
   background-color, never the shorthand: it would reset background-size and
   tile the arrow gradients across the whole control. */
select.pn-input {
  appearance: none; -webkit-appearance: none;
  padding-right: var(--space-24);
  background-image: linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
                    linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

/* The transmission toggle. The same chip the town pricing switch uses, so one
   interaction looks the same across the site. */
.pn-toggle-group { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.pn-toggle { display: inline-flex; }
.pn-toggle-btn {
  display: inline-flex; align-items: center; gap: var(--space-4);
  min-height: 44px; padding: var(--space-5) var(--space-12);
  background-color: var(--color-bg);
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--color-text-body); cursor: pointer;
}
.pn-toggle-btn:has(input:checked) {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-on-accent);
}
.pn-toggle-btn:focus-within { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* The Stripe card mount. #pn-card-element is Stripe's: give it room and a
   field surface, and never style its innards. */
.pn-card-element {
  min-height: 46px;
  padding: var(--space-6) var(--space-9);
  background-color: var(--color-bg);
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius-xs);
}
.pn-card-brands { display: flex; gap: var(--space-4); margin-bottom: var(--space-6); font-size: var(--fs-caption); color: var(--color-text-faint); }

.pn-terms-row { display: flex; align-items: flex-start; gap: var(--space-6); margin-top: var(--space-12); }
.pn-terms-label { font-size: var(--fs-body-sm); color: var(--color-text-body); }
.pn-terms-label a { color: var(--color-accent); }

.pn-pay-button {
  width: 100%; min-height: 52px;
  margin-top: var(--space-12);
  padding: var(--space-8) var(--space-16);
  background: var(--color-action); border: 0; border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-body-lg);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--rsa-white); cursor: pointer;
  box-shadow: var(--shadow-red-glow);
  transition: background var(--dur-fast);
}
.pn-pay-button:hover { background: var(--color-action-hover); }
.pn-pay-button:disabled { opacity: 0.6; cursor: default; }
.pn-stripe-badge { margin-top: var(--space-6); font-size: var(--fs-small); text-align: center; color: var(--color-text-faint); }

/* The order summary, sticky beside the form on a wide screen. */
.pn-checkout-sidebar { position: sticky; top: 24px; }
.pn-order-card {
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-top: var(--rule-green-top);
  border-radius: var(--radius-xs);
}
.pn-order-card-header {
  margin-bottom: var(--space-10); padding-bottom: var(--space-8);
  border-bottom: 1px solid var(--rsa-line-12);
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--color-text);
}
.pn-order-product { margin-bottom: var(--space-10); }
.pn-order-product-name { display: block; font-weight: var(--fw-bold); color: var(--color-text); }
.pn-order-product-meta { display: block; margin-top: var(--space-4); font-size: var(--fs-body-sm); color: var(--color-text-muted); }
.pn-order-total {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-8);
  padding-top: var(--space-10);
  border-top: 2px dashed var(--rsa-line-22);
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-text-muted);
}
/* The amount being paid: the largest figure on the page, because it is the one
   thing the visitor must be certain of. */
.pn-order-total-price {
  font-family: var(--font-display);
  font-size: clamp(34px, 4vw, 52px);
  font-weight: var(--fw-black);
  line-height: 1;
  letter-spacing: var(--ls-tighter);
  color: var(--color-text);
}
.pn-order-trust { margin-top: var(--space-12); padding-top: var(--space-10); border-top: 1px solid var(--rsa-line-12); }
.pn-trust-item {
  padding-left: var(--space-10);
  text-indent: calc(var(--space-10) * -1);
  margin-bottom: var(--space-5);
  font-size: var(--fs-body-sm);
  color: var(--color-text-muted);
}

.pn-spinner {
  display: inline-block; width: 16px; height: 16px;
  border: 2px solid var(--rsa-line-25);
  border-top-color: var(--color-text);
  border-radius: var(--radius-round);
  animation: pn-spin 0.7s linear infinite;
}
@keyframes pn-spin { to { transform: rotate(360deg); } }
/* Rule 14: motion is opt-out, sitewide and unconditionally. */
@media (prefers-reduced-motion: reduce) {
  .pn-spinner { animation: none; }
}

@media (max-width: 1100px) {
  .pn-checkout-sidebar { position: static; }
}
@media (max-width: 768px) {
  .pn-form-section { padding: var(--space-12); }
}

/* ---------- 11. Create gift voucher ---------- */

/* Generated from the inline style attributes this page carried. Any
   `display` stayed inline: the wizard script sets style.display on the
   five gv-step panels, so an inline value there is behaviour. v1 token
   names are mapped onto their v2 equivalents, including the four that
   CLAUDE.md records as used-but-never-defined. */

.gvx-s1 {
  padding: 6rem 0 2rem;
}

.gvx-s2 {
  padding: 3rem 0;
}

.gvx-s3 {
  max-width: 1200px;
  margin: 0 auto;
}

.gvx-s4 {
  justify-content: center;
  gap: 2rem;
}

.gvx-s5 {
  text-align: center;
  padding: 4rem 1rem;
}

.gvx-s6 {
  text-decoration: none;
}

.gvx-s7 {
  text-decoration: none;
  padding: 0.85rem 1.5rem;
  border: 1px solid var(--rsa-line-12);
  border-radius: 10px;
  color: var(--color-text-body);
}

.gvx-s8 {
  font-family: var(--font-display);
  font-size: var(--fs-h1);
  font-weight: 700;
  color: var(--color-text);
  margin: 1.5rem 0 1rem;
  letter-spacing: -0.02em;
}

.gvx-s9 {
  font-size: 1.1rem;
  color: var(--color-text-body);
  line-height: 1.6;
  max-width: 600px;
}

.gvx-s10 {
  margin-bottom: 2rem;
  text-align: center;
}

.gvx-s11 {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 0.75rem;
}

.gvx-s12 {
  color: var(--accent-red, #e53e3e);
  font-size: 0.85rem;
  margin-top: 0.5rem;
}

.gvx-s13 {
  text-align: center;
  margin-top: 1rem;
  font-size: 0.9rem;
}

.gvx-s14 {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--color-accent);
  align-items: center;
  justify-content: center;
  margin: 0 auto 1.5rem;
}

.gvx-s15 {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  color: var(--color-text);
  margin-bottom: 0.75rem;
}

.gvx-s16 {
  color: var(--color-text-body);
  font-size: 1.05rem;
  max-width: 500px;
  margin: 0 auto 1rem;
}

.gvx-s17 {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  margin-bottom: 2rem;
}

.gvx-s18 {
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}

/* ---------- 12. Gift voucher wizard ---------- */

/* A five-step wizard. Every class name is the one the page script already
   binds, so none may be renamed: gv-step-1 to gv-step-5 are shown and hidden by
   style.display, .gv-input-error is toggled on invalid fields, and
   #gv-card-element is the Stripe mount. These rules are appearance only. */

/* The v1 chrome classes this page still carries. */
.hero-section { padding: var(--space-28) 0 var(--space-16); }
.breadcrumb { font-size: var(--fs-body-sm); color: var(--color-text-muted); }
.breadcrumb a { color: var(--color-text-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--color-text); }
.breadcrumb-sep { margin: 0 var(--space-4); color: var(--rsa-slate); }

/* Step indicator: numbered chips on a connecting line. */
.gv-progress { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-16); flex-wrap: wrap; }
.gv-progress-step { display: flex; align-items: center; gap: var(--space-5); }
.gv-progress-num {
  display: grid; place-items: center;
  width: 32px; height: 32px; flex: 0 0 auto;
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-16);
  border-radius: var(--radius-round);
  font-family: var(--font-display); font-size: var(--fs-caption);
  font-weight: var(--fw-black); color: var(--color-text-muted);
}
.gv-progress-label { font-size: var(--fs-caption); font-weight: var(--fw-bold); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-text-muted); }
/* .gv-progress-active is toggled by the script. */
.gv-progress-active .gv-progress-num { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-on-accent); }
.gv-progress-active .gv-progress-label { color: var(--color-text); }
.gv-progress-line { flex: 1 1 24px; min-width: 16px; height: 1px; background: var(--rsa-line-16); }

/* The wizard panel itself. No display here: the script sets style.display on
   gv-step-1 to gv-step-5 and an inline value there is behaviour, not style. */
.gv-step { animation: none; }
.gv-step-header { margin-bottom: var(--space-14); }
.gv-step-title { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: var(--fw-black); line-height: 0.98; letter-spacing: -0.035em; color: var(--color-text); }
.gv-step-sub { margin-top: var(--space-6); max-width: 52ch; font-size: var(--fs-body-lg); color: var(--color-text-muted); }

/* Step 1: the packages. Each price on a ticket with its own CTA. */
.gv-products-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: var(--space-10); }
.gv-product-card {
  position: relative;
  display: flex; flex-direction: column; gap: var(--space-6);
  padding: var(--space-12);
  background: var(--rsa-chalk); color: var(--rsa-road-black);
  border-top: 6px solid var(--color-action);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-fast) var(--ease-reveal);
}
.gv-product-card:hover { transform: var(--lift-sm); }
.gv-product-card h3, .gv-product-card h4 { color: var(--rsa-road-black); }
.gv-product-badge {
  align-self: flex-start;
  padding: var(--space-4) var(--space-8);
  background: var(--color-accent); border-radius: var(--radius-sm);
  font-family: var(--font-display); font-size: var(--fs-micro);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--color-on-accent);
}
.gv-product-name {
  min-height: 2.5em; line-height: 1.25;
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label); text-transform: uppercase;
}
.gv-product-price {
  padding-top: var(--space-6);
  border-top: 2px dashed rgba(11, 11, 12, 0.25);
  font-family: var(--font-display); font-size: var(--fs-num-xs);
  font-weight: var(--fw-black); line-height: 1; letter-spacing: var(--ls-tighter);
}
.gv-select-btn, .gv-continue-btn, .gv-pay-button {
  min-height: 48px;
  padding: var(--space-6) var(--space-14);
  background: var(--color-action); border: 0; border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--rsa-white); cursor: pointer;
  transition: background var(--dur-fast);
}
.gv-select-btn { margin-top: auto; }
.gv-pay-button { width: 100%; min-height: 52px; margin-top: var(--space-12); box-shadow: var(--shadow-red-glow); }
.gv-select-btn:hover, .gv-continue-btn:hover, .gv-pay-button:hover { background: var(--color-action-hover); }
.gv-pay-button:disabled, .gv-continue-btn:disabled { opacity: 0.6; cursor: default; }
.gv-select-btn:focus-visible, .gv-continue-btn:focus-visible, .gv-pay-button:focus-visible { outline: 3px solid var(--color-accent); outline-offset: 3px; }

.gv-back-btn {
  min-height: 44px; margin-bottom: var(--space-10); padding: 0;
  background: none; border: 0;
  font-size: var(--fs-body-sm); font-weight: var(--fw-bold);
  color: var(--color-text-muted); cursor: pointer;
}
.gv-back-btn:hover { color: var(--color-text); }

/* Step 2: the message, with the voucher previewing beside it. */
.gv-personalise-layout, .gv-details-layout { display: grid; gap: var(--space-16); align-items: start; }
@media (min-width: 1100px) {
  .gv-personalise-layout { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); }
  .gv-details-layout { grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.9fr); }
}
.gv-personalise-form, .gv-details-form { display: grid; gap: var(--space-12); }
.gv-form-section {
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-radius: var(--radius-xs);
}
.gv-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: var(--space-10); }
.gv-field { display: flex; flex-direction: column; }
.gv-label {
  margin-bottom: var(--space-4);
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-text-muted);
}
.gv-field-hint { margin-top: var(--space-4); font-size: var(--fs-small); color: var(--color-text-faint); }

/* background-color, never the shorthand: the shorthand resets background-size
   and the select arrow gradients would tile across the control. */
.gv-input, .gv-textarea {
  width: 100%; min-height: 46px;
  padding: var(--space-5) var(--space-9);
  background-color: var(--color-bg);
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius-xs);
  color: var(--color-text);
  font-family: var(--font-body); font-size: var(--fs-body-sm);
}
.gv-textarea { min-height: 130px; padding-top: var(--space-6); resize: vertical; }
.gv-input:focus, .gv-textarea:focus { border-color: var(--color-accent); outline: none; }
/* .gv-input-error is toggled by the validation script. */
.gv-input-error, .gv-input-error:focus { border-color: var(--rsa-red); }
select.gv-input {
  appearance: none; -webkit-appearance: none;
  padding-right: var(--space-24);
  background-image: linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
                    linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.gv-char-count { margin-top: var(--space-4); font-size: var(--fs-small); text-align: right; color: var(--color-text-faint); }

/* The live voucher preview: chalk paper, the object the page is building. */
.gv-preview-panel { position: sticky; top: 24px; }
.gv-preview-label {
  margin-bottom: var(--space-8);
  font-size: var(--fs-eyebrow); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-eyebrow);
}
.gv-voucher-preview { position: relative; }
.gv-voucher-card {
  padding: var(--space-14);
  background: var(--rsa-chalk); color: var(--rsa-road-black);
  border-top: 10px solid var(--color-action);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
}
.gv-voucher-from { margin-top: var(--space-8); font-size: var(--fs-body-sm); font-weight: var(--fw-bold); }

/* Steps 3 and 4: the numbered form sections and the order summary. */
.gv-section-header { display: flex; align-items: center; gap: var(--space-6); margin-bottom: var(--space-12); }
.gv-section-number {
  display: grid; place-items: center;
  width: 30px; height: 30px; flex: 0 0 auto;
  background: var(--color-accent); border-radius: var(--radius-round);
  font-family: var(--font-display); font-size: var(--fs-caption);
  font-weight: var(--fw-black); color: var(--color-on-accent);
}
.gv-section-title { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: var(--fw-black); color: var(--color-text); }

.gv-sidebar { position: sticky; top: 24px; }
.gv-order-card {
  padding: var(--pad-card);
  background: var(--color-panel);
  border: 1px solid var(--rsa-line-12);
  border-top: var(--rule-green-top);
  border-radius: var(--radius-xs);
}
.gv-order-header {
  margin-bottom: var(--space-10); padding-bottom: var(--space-8);
  border-bottom: 1px solid var(--rsa-line-12);
  font-family: var(--font-display); font-size: var(--fs-label);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--color-text);
}
.gv-order-product { margin-bottom: var(--space-10); }
.gv-order-product-name { display: block; font-weight: var(--fw-bold); color: var(--color-text); }
.gv-order-product-meta, .gv-order-recipient { display: block; margin-top: var(--space-4); font-size: var(--fs-body-sm); color: var(--color-text-muted); }
.gv-order-message-preview {
  margin-top: var(--space-8); padding: var(--space-8);
  background: var(--color-bg); border-left: 3px solid var(--color-accent);
  font-size: var(--fs-body-sm); font-style: italic; color: var(--color-text-body);
}
.gv-order-total {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-8);
  padding-top: var(--space-10);
  border-top: 2px dashed var(--rsa-line-22);
  font-size: var(--fs-caption); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-text-muted);
}
/* The amount being paid, the one figure the buyer must be certain of. */
.gv-order-total-price {
  font-family: var(--font-display);
  font-size: clamp(34px, 4vw, 52px);
  font-weight: var(--fw-black); line-height: 1; letter-spacing: var(--ls-tighter);
  color: var(--color-text);
}
.gv-order-trust { margin-top: var(--space-12); padding-top: var(--space-10); border-top: 1px solid var(--rsa-line-12); }
.gv-trust-item {
  padding-left: var(--space-10); text-indent: calc(var(--space-10) * -1);
  margin-bottom: var(--space-5); font-size: var(--fs-body-sm); color: var(--color-text-muted);
}

/* The Stripe mount. Give it a field surface and never style its innards. */
.gv-card-brands { display: flex; gap: var(--space-4); margin-bottom: var(--space-6); font-size: var(--fs-caption); color: var(--color-text-faint); }
.gv-card-element, .gv-card-placeholder {
  min-height: 46px;
  padding: var(--space-6) var(--space-9);
  background-color: var(--color-bg);
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius-xs);
}
.gv-card-placeholder { color: var(--color-text-faint); font-size: var(--fs-body-sm); }
.gv-terms-row { display: flex; align-items: flex-start; gap: var(--space-6); margin-top: var(--space-12); }
.gv-terms-label { font-size: var(--fs-body-sm); color: var(--color-text-body); }
.gv-terms-label a { color: var(--color-accent); }
.gv-stripe-badge { margin-top: var(--space-6); font-size: var(--fs-small); text-align: center; color: var(--color-text-faint); }
.gv-fallback-cta {
  margin-top: var(--space-14); padding: var(--space-12);
  background: var(--color-panel); border: 1px solid var(--rsa-line-12);
  border-radius: var(--radius-xs); text-align: center;
}

/* The first-run coach marks. */
/* The coachmark tour. Five rules were lost when this page's inline <style>
   block was converted: the text rules below survived and the positioning ones
   did not. The JavaScript sets top/left/right in document coordinates and
   expects an absolutely positioned tooltip, so without them the tooltip fell
   into normal flow and rendered at the foot of the document, below the footer,
   while the backdrop still dimmed the page.

   check-unstyled-classes could not catch this. Every class here is created by
   JavaScript at runtime, and that gate strips <script> blocks before reading
   class names, which it has to do or every JS string literal becomes a false
   positive. Runtime-injected markup is outside what it can see. */
.gv-coach-overlay {
  position: absolute; top: 0; left: 0;
  width: 100%; height: 100%;
  z-index: 60;
  pointer-events: none;
}
/* The backdrop only catches the click that dismisses the tour. Dimming is the
   spotlight's job below, so the highlighted field is genuinely clear instead of
   merely less dim than everything else, which is what two stacked 0.55 layers
   gave before. */
.gv-coach-backdrop { position: fixed; inset: 0; z-index: 60; background: transparent; pointer-events: auto; cursor: pointer; }
.gv-coach-spotlight {
  position: absolute;
  z-index: 61;
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 4000px rgba(0, 0, 0, 0.62), inset 0 0 0 2px var(--color-accent);
  pointer-events: none;
  transition: top var(--dur-base) var(--ease-reveal), left var(--dur-base) var(--ease-reveal),
              width var(--dur-base) var(--ease-reveal), height var(--dur-base) var(--ease-reveal);
}
.gv-coach-tooltip {
  position: absolute;
  z-index: 62;
  max-width: 280px;
  padding: var(--space-10) var(--space-12);
  background: var(--color-panel);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-50%);
  pointer-events: auto;
  animation: gv-coach-in var(--dur-base) var(--ease-reveal);
}
/* tokens.css disables every animation under prefers-reduced-motion, so this
   needs no guard of its own. */
@keyframes gv-coach-in {
  from { opacity: 0; transform: translateY(-50%) scale(0.96); }
  to   { opacity: 1; transform: translateY(-50%) scale(1); }
}
/* The arrow is drawn twice. The outer triangle takes the border colour and the
   inner one sits a pixel in and takes the panel colour, so the tooltip's border
   appears to carry on around the point. */
.gv-coach-right::before, .gv-coach-right::after,
.gv-coach-left::before,  .gv-coach-left::after {
  content: ""; position: absolute; top: 50%;
  transform: translateY(-50%);
  border: 8px solid transparent;
}
.gv-coach-right::before { left: -8px;  border-right-color: var(--color-accent); }
.gv-coach-right::after  { left: -6px;  border-width: 7px; border-right-color: var(--color-panel); }
.gv-coach-left::before  { right: -8px; border-left-color: var(--color-accent); }
.gv-coach-left::after   { right: -6px; border-width: 7px; border-left-color: var(--color-panel); }
/* Where the field leaves no room beside it, the tooltip goes underneath and
   spans the column instead. The JS adds this class and writes left and right
   inline, so the side arrows have to go and the vertical centring with them:
   the shared rule above translates the tooltip up by half its height, which is
   right beside a field and wrong below one. */
.gv-coach-tooltip.gv-coach-below {
  max-width: none;
  transform: none;
  animation-name: gv-coach-in-below;
}
.gv-coach-tooltip.gv-coach-below::before,
.gv-coach-tooltip.gv-coach-below::after { content: none; }
@keyframes gv-coach-in-below {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.gv-coach-step-count { font-size: var(--fs-caption); font-weight: var(--fw-bold); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-eyebrow); }
.gv-coach-title { margin: var(--space-5) 0; font-family: var(--font-display); font-size: var(--fs-h4); font-weight: var(--fw-black); color: var(--color-text); }
.gv-coach-text { font-size: var(--fs-body-sm); color: var(--color-text-body); }
.gv-coach-actions { display: flex; gap: var(--space-6); justify-content: flex-end; margin-top: var(--space-10); }
.gv-coach-skip, .gv-coach-next {
  min-height: 44px; padding: var(--space-5) var(--space-10);
  border-radius: var(--radius-xs);
  font-family: var(--font-display); font-size: var(--fs-caption);
  font-weight: var(--fw-black); letter-spacing: var(--ls-label);
  text-transform: uppercase; cursor: pointer;
}
.gv-coach-skip { background: none; border: 1px solid var(--color-field-border); color: var(--color-text-muted); }
.gv-coach-next { background: var(--color-accent); border: 0; color: var(--color-on-accent); }

.gv-spinner {
  display: inline-block; width: 16px; height: 16px;
  border: 2px solid var(--rsa-line-25);
  border-top-color: var(--color-text);
  border-radius: var(--radius-round);
  animation: gv-spin 0.7s linear infinite;
}
@keyframes gv-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .gv-spinner { animation: none; } }

@media (max-width: 1100px) {
  .gv-preview-panel, .gv-sidebar { position: static; }
}
@media (max-width: 768px) {
  .gv-form-section { padding: var(--space-12); }
  .gv-voucher-card { padding: var(--space-12); }
  .gv-progress-label { display: none; }
}
