/* THE PHRASE METHOD / global type scale.
   Loaded after main.css and hero.css, so it is the last word on these selectors.

   WHY THIS FILE EXISTS
   main.css is a hand-authored stylesheet with ~120 hard-coded font sizes across
   four breakpoints. There is no CSS mechanism that scales a hard-coded px or vw
   value from a single variable -- em resolves against the parent, not the element,
   and rem cannot reach a clamp() built from vw. So a global "type scale" setting
   has to re-declare the sizes it wants to control.

   This file does exactly that for the text a merchant would ever resize: section
   headings, section body copy, the animated stamp, the price, the coach block,
   the module and FAQ rows, the reviews, the final call, and the hero. Micro labels
   -- 9px eyebrows, badges, barcodes, the "VS" chip -- are deliberately left alone,
   because scaling them breaks the layouts they sit in.

   Every value below is copied verbatim from main.css / hero.css and wrapped in a
   calc(). With both scales at their 100% default, calc(X * 1) computes to X, so
   this file is a mathematical no-op until somebody moves a slider.

   THE BREAKPOINTS ARE NOT OPTIONAL. main.css overrides these same selectors inside
   @media blocks. Because this file loads later at equal specificity, an unqualified
   rule here would beat main.css's mobile rule and desktop sizes would leak onto
   phones. Every breakpoint main.css declares for a scaled selector is repeated
   here, in main.css's own source order (620 before 700, so the coach block keeps
   the 700 values it has today at narrow widths). */

.sec-head h2 { font-size: calc(clamp(52px, 6.25vw, 78px) * var(--pm-heading-scale, 1)); }
.sec-head p { font-size: calc(16px * var(--pm-body-scale, 1)); }

.stamp { font-size: calc(clamp(72px, 11.1vw, 150px) * var(--pm-heading-scale, 1)); }
.stamp.phrase-long { font-size: calc(clamp(65px, 9.7vw, 128px) * var(--pm-heading-scale, 1)); }
.stamp.phrase-xl { font-size: calc(clamp(58px, 8.7vw, 114px) * var(--pm-heading-scale, 1)); }
.hero-line { font-size: calc(16.5px * var(--pm-body-scale, 1)); }

.math-card .big { font-size: calc(clamp(92px, 10vw, 132px) * var(--pm-heading-scale, 1)); }
.math-card p:not(.way) { font-size: calc(14.5px * var(--pm-body-scale, 1)); }

.ledger .row { font-size: calc(14px * var(--pm-body-scale, 1)); }
.hangtag .wasnum { font-size: calc(37px * var(--pm-heading-scale, 1)); }
.hangtag .price { font-size: calc(88px * var(--pm-heading-scale, 1)); }

.chris h2 { font-size: calc(clamp(56px, 6vw, 82px) * var(--pm-heading-scale, 1)); }
.chris .coach-deck { font-size: calc(16px * var(--pm-body-scale, 1)); }
.chris .chris-quote { font-size: calc(clamp(17px, 1.75vw, 21px) * var(--pm-body-scale, 1)); }
.chris p.coach-body { font-size: calc(13.8px * var(--pm-body-scale, 1)); }

.phase > button { font-size: calc(17px * var(--pm-body-scale, 1)); }
.mod { font-size: calc(14px * var(--pm-body-scale, 1)); }

.quote p { font-size: calc(15px * var(--pm-body-scale, 1)); }

.qa > button { font-size: calc(15px * var(--pm-body-scale, 1)); }
.qa .a { font-size: calc(13.5px * var(--pm-body-scale, 1)); }

.final h2 { font-size: calc(clamp(68px, 9vw, 118px) * var(--pm-heading-scale, 1)); }
.final p { font-size: calc(15px * var(--pm-body-scale, 1)); }

.pmh__title { font-size: calc(clamp(64px, 5.5vw, 116px) * var(--pm-heading-scale, 1)); }
.pmh__copy { font-size: calc(clamp(17px, 1.2vw, 24px) * var(--pm-body-scale, 1)); }
.pmh__cta { font-size: calc(clamp(17px, 1.15vw, 22px) * var(--pm-body-scale, 1)); }

@media (max-width: 1199px) {
  .pmh__title-mobile { font-size: calc(clamp(24px, 6.3vw, 34px) * var(--pm-heading-scale, 1)); }
  .pmh__copy { font-size: calc(clamp(16px, 3.35vw, 20px) * var(--pm-body-scale, 1)); }
  .pmh__cta { font-size: calc(clamp(16px, 3.45vw, 21px) * var(--pm-body-scale, 1)); }
}

@media (max-width: 620px) {
  .sec-head h2,
  .mathsec .sec-head h2,
  .offer .sec-head h2,
  .proof .sec-head h2,
  .faqsec .sec-head h2 { font-size: calc(43px * var(--pm-heading-scale, 1)); }
  .sec-head p { font-size: calc(13.6px * var(--pm-body-scale, 1)); }

  .stamp { font-size: calc(15vw * var(--pm-heading-scale, 1)); }
  .stamp.phrase-long { font-size: calc(13.3vw * var(--pm-heading-scale, 1)); }
  .stamp.phrase-xl { font-size: calc(11.8vw * var(--pm-heading-scale, 1)); }
  .hero-line { font-size: calc(13.4px * var(--pm-body-scale, 1)); }

  .math-card .big { font-size: calc(76px * var(--pm-heading-scale, 1)); }
  .math-card p:not(.way) { font-size: calc(12.7px * var(--pm-body-scale, 1)); }

  .ledger .row { font-size: calc(12px * var(--pm-body-scale, 1)); }
  .hangtag .wasnum { font-size: calc(30px * var(--pm-heading-scale, 1)); }
  .hangtag .price { font-size: calc(72px * var(--pm-heading-scale, 1)); }

  .phase > button { font-size: calc(14.5px * var(--pm-body-scale, 1)); }
  .mod { font-size: calc(12.5px * var(--pm-body-scale, 1)); }

  .quote p { font-size: calc(13.8px * var(--pm-body-scale, 1)); }

  .qa > button { font-size: calc(13.5px * var(--pm-body-scale, 1)); }
  .qa .a { font-size: calc(12.2px * var(--pm-body-scale, 1)); }

  .final h2 { font-size: calc(14.1vw * var(--pm-heading-scale, 1)); }
  .final p { font-size: calc(12.7px * var(--pm-body-scale, 1)); }
}

/* main.css declares the coach block's narrow sizes at 700px, after its 620px
   block. Same order kept here so the 700px values still win below 620px. */
@media (max-width: 700px) {
  .chris h2 { font-size: calc(48px * var(--pm-heading-scale, 1)); }
  .chris .coach-deck { font-size: calc(14px * var(--pm-body-scale, 1)); }
  .chris .chris-quote { font-size: calc(15.5px * var(--pm-body-scale, 1)); }
  .chris p.coach-body { font-size: calc(12.6px * var(--pm-body-scale, 1)); }
}

@media (max-width: 390px) {
  .stamp { font-size: calc(14.7vw * var(--pm-heading-scale, 1)); }
  .stamp.phrase-long { font-size: calc(12.9vw * var(--pm-heading-scale, 1)); }
  .stamp.phrase-xl { font-size: calc(11.4vw * var(--pm-heading-scale, 1)); }
  .hero-line { font-size: calc(13px * var(--pm-body-scale, 1)); }
  .sec-head h2,
  .mathsec .sec-head h2,
  .offer .sec-head h2,
  .faqsec .sec-head h2 { font-size: calc(40px * var(--pm-heading-scale, 1)); }

  .pmh__title-mobile { font-size: calc(6.3vw * var(--pm-heading-scale, 1)); }
  .pmh__copy { font-size: calc(3.25vw * var(--pm-body-scale, 1)); }
  .pmh__cta { font-size: calc(3.25vw * var(--pm-body-scale, 1)); }
}

@media (max-height: 700px) and (max-width: 1199px) {
  .pmh__title-mobile { font-size: calc(clamp(22px, 6vw, 27px) * var(--pm-heading-scale, 1)); }
  .pmh__copy { font-size: calc(clamp(12px, 3.1vw, 15px) * var(--pm-body-scale, 1)); }
}

/* ---------------------------------------------------------------------------
   Editor affordances.

   Sections render at their real size in the editor, but a section whose every
   setting has been cleared would otherwise be an invisible strip that cannot be
   clicked. A minimum height only in design mode keeps it selectable without
   affecting the live page. */
.shopline-design-mode .pm-page:empty,
.shopline-design-mode .pm-section-empty { min-height: 120px; }

/* The site header is fixed. Anchor links land under it without this. main.css
   sets scroll-margin-top on a hard-coded list of ids; sections here carry the
   class instead, so a merchant-renamed anchor still lands correctly. */
.pm-anchor { scroll-margin-top: 94px; }

/* ---------------------------------------------------------------------------
   Support for the JS ports. Each rule below exists because a script needed it,
   not because the design changed. */

/* The carousel track is a mandatory snap container, which ignores a scripted
   smooth scroll. The easing lives here instead, where snapping honours it, and
   carousel.js only assigns scrollLeft. */
.car-track { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  .car-track { scroll-behavior: auto; }
}

/* carousel.js builds the dots as <button> so they are reachable by keyboard and
   announced by a screen reader. The design styled bare <i>, so the same styling is
   matched here rather than restyled. */
.car-dots .car-dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #c0b9ae;
  transition: transform .2s ease, background .2s ease;
}

.car-dots .car-dot.on { transform: scale(1.35); background: var(--blue, #72a0ee); }
.car-dots .car-dot:focus-visible { outline: 2px solid var(--blue, #72a0ee); outline-offset: 3px; }

/* Tap target. The dot itself stays 7px to match the design; the hit area does not. */
.car-dots { gap: 7px; }
.car-dots .car-dot { position: relative; }
.car-dots .car-dot::after { content: ""; position: absolute; inset: -14px; }

/* accordion.js writes a measured max-height onto an open panel so long merchant
   copy is never clipped by the design's fixed 680px / 300px caps. Nothing to add
   visually -- these just make the transition target the same property. */
.phase .body,
.qa .a { will-change: auto; }

/* Drawer states the original markup carried inline. */
.cart[hidden],
.cart-scrim[hidden] { display: none; }

.cart-error {
  margin: 0 0 10px;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(240, 73, 73, .10);
  color: #b3261e;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.45;
}

.cart-error[hidden] { display: none; }

.cart-go.is-loading { pointer-events: none; opacity: .68; }

.cart-go.is-loading::after {
  content: "";
  position: absolute;
  right: 16px;
  top: calc(50% - 7px);
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: pm-spin .7s linear infinite;
}

@keyframes pm-spin { to { transform: rotate(1turn); } }

@media (prefers-reduced-motion: reduce) {
  .cart-go.is-loading::after { animation-duration: 2s; }
}

/* The checkout handoff submits a real cart form. It is never seen. */
.cart-checkout-form { display: none; }

/* Every interactive control reaches the 44px minimum on touch, without changing
   the visual size the design specifies. */
.nav__menu, .car-btn, .cart-x { min-width: 44px; min-height: 44px; }

/* The $5 card's mark row, drawn from its count rather than from one element per
   mark. SLINE's loop takes a list and not a number, and inventing a range filter
   that may not exist is worse than drawing this in CSS. Values match the design's
   .tests i and .tests i.dead exactly. */
.math-card .tests { --pm-mark-size: 10px; --pm-mark-gap: 6px; }

.math-card .tests--dots::before {
  content: "";
  display: block;
  height: var(--pm-mark-size);
  width: calc(var(--pm-marks, 25) * (var(--pm-mark-size) + var(--pm-mark-gap)) - var(--pm-mark-gap));
  max-width: 100%;
  background-image: radial-gradient(
    circle at calc(var(--pm-mark-size) / 2) 50%,
    var(--sage) calc(var(--pm-mark-size) / 2 - .5px),
    transparent calc(var(--pm-mark-size) / 2 + .5px)
  );
  background-size: calc(var(--pm-mark-size) + var(--pm-mark-gap)) 100%;
  background-repeat: repeat-x;
}

.math-card .tests--bar::before {
  content: "";
  display: block;
  width: 100%;
  height: var(--pm-mark-size);
  opacity: .55;
  background: repeating-linear-gradient(90deg, #51514f 0 8px, transparent 8px 15px);
}

/* Brand name standing in for a logo the merchant has not set yet. */
.pmh__brand-text {
  display: block;
  color: var(--ink);
  font-size: clamp(15px, 1.1vw, 20px);
  font-weight: 900;
  letter-spacing: -.03em;
  line-height: 1.1;
  text-transform: uppercase;
}

/* Editor-only selling-plan table. Never rendered on the live page -- the section
   wraps it in a design-mode check -- so it is styled for legibility, not for brand. */
.pm-plan-helper {
  display: block;
  margin: 0 0 32px;
  padding: 16px 18px;
  border: 1px solid rgba(114, 160, 238, .45);
  border-radius: 14px;
  background: rgba(114, 160, 238, .08);
  color: var(--paper);
}

.pm-plan-helper__note {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.5;
}

.pm-plan-helper__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.pm-plan-helper__table th,
.pm-plan-helper__table td {
  padding: 7px 10px;
  border-bottom: 1px solid rgba(245, 242, 234, .16);
  text-align: left;
  vertical-align: top;
  word-break: break-word;
}

.pm-plan-helper__table th {
  font-weight: 900;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-size: 10px;
}

.pm-plan-helper__table tbody tr:last-child td { border-bottom: 0; }

@media (max-width: 620px) {
  .pm-plan-helper__table { display: block; overflow-x: auto; }
}

/* The original markup had the Included heading and list inside .cart-plans, which
   is a role="radiogroup" -- so a screen reader announced five bullet points as
   payment options. They are siblings now. .cart-plans is a grid with an 11px gap,
   so this restores the exact spacing the grid was contributing. */
.cart-plans + .cart-sub { margin-top: 27px; }

/* The drawer thumbnail as a real image rather than the monogram. */
img.cart-thumb { object-fit: cover; }

/* ---------------------------------------------------------------------------
   The .section collision.

   SHOPLINE's renderer wraps EVERY section, on every template, in
   <div id="shopline-section-..." class="section">. main.css independently uses
   .section as the design's own content-section class, carrying 118px of vertical
   padding (94px under 980, 74px under 620). The two meet and every section gets
   that padding twice -- once on the wrapper, once on the section itself -- which
   put roughly 236px of dead cream above the hero and between every band on the
   page, and did the same to the stock cart and account templates.

   Resetting the wrapper is the surgical fix: it is matched by its id prefix and by
   being a div, and the design's own <section class="section ..."> elements are
   neither, so they keep the padding they are supposed to have. Renaming .section
   throughout main.css would have been the alternative, and a far bigger diff over
   a file that is meant to stay a faithful copy. */
div[id^="shopline-section-"].section { padding: 0; }

/* ---------------------------------------------------------------------------
   aspect-ratio versus the width/height attributes.

   Every image in this theme carries intrinsic width and height attributes so the
   browser reserves the right box before the file arrives. Those attributes are
   presentational hints -- effectively `width: Wpx; height: Hpx` at the bottom of the
   cascade -- and aspect-ratio only computes a dimension that is `auto`. The design
   sets `.sold-card img { width: 100%; aspect-ratio: 1 }` and never sets a height,
   because its plain HTML had no attributes for anything to inherit. Add the
   attributes and the height hint wins, aspect-ratio is ignored, and every product
   tile renders at its full intrinsic height: 800px tall in a 155px column.

   Restoring `height: auto` is what lets aspect-ratio do its job again, and keeps the
   reserved box. Anywhere else in this theme that pairs attributes with a CSS ratio
   already sets height explicitly. */
.sold-card img { height: auto; }

/* ===========================================================================
   CONTENT PAGES  (.pm-legal)  — Terms, Privacy, Support

   These reuse the site's own furniture: .section for the vertical rhythm, .wrap
   for the 1220px measure, .sec-head for the yellow accent rule and the heading
   block. Only what is genuinely page-specific lives here: a readable prose
   measure, list and link styling inside the rich text, and the contact rows.

   THE PAGE TITLE. main.css styles .sec-head h2, and a content page's title has to
   be an h1 -- one per page, and it is the page's real heading. So the h2's
   declarations are mirrored onto .pm-legal .sec-head h1 below, including the
   scaleX width treatment main.css currently uses in place of Archivo's width axis.
   If that approach is ever replaced (see the font note in NOTES.md), this rule has
   to change with it, or the page title will be the one heading on the site that
   does not match.
   =========================================================================== */

.pm-legal { background: var(--paper); }

.pm-legal .sec-head {
  max-width: 860px;
  margin-bottom: 12px;
}

.pm-legal .sec-head h1 {
  font-size: calc(clamp(52px, 6.25vw, 78px) * var(--pm-heading-scale, 1));
  letter-spacing: -.055em;
  line-height: .91;
  word-spacing: .1em;
  transform: scaleX(.72);
  transform-origin: left center;
}

.pm-legal__eyebrow {
  margin: 0 0 14px;
  color: var(--sage-deep);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.pm-legal__updated {
  margin: 0 0 44px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* The prose measure. Long legal text at the full 1220px is unreadable, so the body
   is capped at a comfortable line length while the heading above it keeps the
   section's own width. */
.pm-legal__body {
  max-width: 72ch;
}

.pm-legal__section + .pm-legal__section {
  margin-top: 40px;
  padding-top: 36px;
  border-top: 1px solid var(--line);
}

.pm-legal__heading {
  margin: 0 0 14px;
  font-size: calc(22px * var(--pm-heading-scale, 1));
  font-weight: 900;
  letter-spacing: -.03em;
  line-height: 1.18;
}

/* Rich text. The merchant's editor emits plain p, ul, ol, strong, em, a and
   headings, so each one is given a sensible default here.

   SPACING IS DONE IN ONE PLACE, and only one: the owl rule below. Every gap between
   paragraphs, lists and headings comes from it.

   That matters because the obvious-looking additions are the thing that breaks it.
   An earlier version of this file also carried `p { margin: 0 }` and
   `ul, ol { margin: 0 }` as tidy-up resets. Both are one class more specific than
   the owl rule and both sit after it, so they won, every gap computed to 0, and the
   prose ran together. Asking the engine which rules matched is what found it -- from
   the page it looked exactly like a stock !important winning, and it was not.

   The resets are not needed anyway: the base stylesheet already zeroes margins on p,
   ul and ol at element specificity, which the owl rule beats comfortably. So if a
   gap ever needs changing, change the 16px. Do not add a margin to an element here.

   This prose also deliberately does not carry the stock .rte class. Nothing here
   needs it, and keeping it off means none of the stock rich-text rules are in the
   cascade to reason about. */
.pm-legal__prose {
  color: var(--ink);
  font-size: calc(15px * var(--pm-body-scale, 1));
  line-height: 1.72;
}

.pm-legal .pm-legal__prose > * + * { margin-top: 16px; }

.pm-legal .pm-legal__prose h2,
.pm-legal .pm-legal__prose h3 {
  margin: 28px 0 10px;
  font-size: calc(17px * var(--pm-heading-scale, 1));
  font-weight: 900;
  letter-spacing: -.02em;
  line-height: 1.3;
}

/* No margin here on purpose -- see the note above. Padding and list-style only,
   because the bullets are drawn as pseudo-elements. */
.pm-legal .pm-legal__prose ul,
.pm-legal .pm-legal__prose ol {
  padding-left: 0;
  list-style: none;
}

.pm-legal .pm-legal__prose li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 9px;
}

.pm-legal .pm-legal__prose li:last-child { margin-bottom: 0; }

/* The same dot the enrolment drawer uses for its included list, so a bullet means
   the same thing everywhere on the site. */
.pm-legal .pm-legal__prose ul > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sage);
}

.pm-legal .pm-legal__prose ol { counter-reset: pm-legal-item; }

.pm-legal .pm-legal__prose ol > li { counter-increment: pm-legal-item; }

.pm-legal .pm-legal__prose ol > li::before {
  content: counter(pm-legal-item) ".";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--sage-deep);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.pm-legal .pm-legal__prose strong, .pm-legal .pm-legal__prose b { font-weight: 900; }

.pm-legal .pm-legal__prose a {
  color: var(--sage-deep);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color .2s ease;
}

.pm-legal .pm-legal__prose a:hover { color: var(--ink); }
.pm-legal .pm-legal__prose a:focus-visible { outline: 2px solid var(--sage); outline-offset: 3px; }

/* Contact rows, for the support page. Label and value sit side by side and stack
   on a phone, where a two-column row would crush an email address. */
.pm-legal__contact {
  display: grid;
  grid-template-columns: minmax(120px, 200px) minmax(0, 1fr);
  gap: 6px 24px;
  align-items: baseline;
  padding: 17px 0;
  border-bottom: 1px solid var(--line);
}

.pm-legal__contact:first-child { border-top: 1px solid var(--line); }

.pm-legal__contact-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: .13em;
  text-transform: uppercase;
}

.pm-legal__contact-value {
  color: var(--ink);
  font-size: calc(15.5px * var(--pm-body-scale, 1));
  font-weight: 800;
  letter-spacing: -.02em;
  overflow-wrap: anywhere;
}

a.pm-legal__contact-value {
  text-decoration: underline;
  text-underline-offset: 3px;
}

a.pm-legal__contact-value:hover { color: var(--sage-deep); }

.pm-legal__contact-note {
  grid-column: 2;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
}

@media (max-width: 620px) {
  .pm-legal .sec-head h1 { font-size: calc(43px * var(--pm-heading-scale, 1)); letter-spacing: -.052em; }
  .pm-legal .sec-head { margin-bottom: 10px; }
  .pm-legal__updated { margin-bottom: 32px; }
  .pm-legal__body { max-width: none; }

  .pm-legal__section + .pm-legal__section { margin-top: 30px; padding-top: 28px; }
  .pm-legal__heading { font-size: calc(19px * var(--pm-heading-scale, 1)); }
  .pm-legal .pm-legal__prose { font-size: calc(14px * var(--pm-body-scale, 1)); line-height: 1.68; }

  /* One column: an email address next to a label at 375px leaves about 150px for
     the address, which is not enough for a real one. */
  .pm-legal__contact { grid-template-columns: minmax(0, 1fr); gap: 5px; padding: 15px 0; }
  .pm-legal__contact-note { grid-column: 1; }
}

@media (max-width: 390px) {
  .pm-legal .sec-head h1 { font-size: calc(40px * var(--pm-heading-scale, 1)); }
}

/* ---------------------------------------------------------------------------
   Footer links.

   These were decorative before -- every one pointed at "#" -- and now they are the
   site's only navigation to Terms, Privacy and Support. Measured on the rendered
   page they were computing to #3D3819, a dark olive inherited from the stock colour
   scheme, against the footer's #0C131A. That is roughly 1.2:1: invisible, and about
   as far from the 4.5:1 minimum as a colour pair gets.

   main.css does set .footer .links { color: #96928a }, but the anchors take their
   colour from a stock rule instead of inheriting it, so the colour has to be set on
   the anchor itself. Stated here, where this stylesheet loads last. */
.footer .links a {
  color: var(--muted-dark);
  text-decoration: none;
}

.footer .links a:hover,
.footer .links a:focus-visible {
  color: var(--paper);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.footer .links a:focus-visible {
  outline: 2px solid var(--sage);
  outline-offset: 3px;
  border-radius: 2px;
}

/* The footer sits on a dark ground, and its links are 10.5px. A touch target that
   small needs help on a phone without changing how the row looks. */
@media (max-width: 620px) {
  .footer .links { gap: 14px 18px; }
  .footer .links a { display: inline-block; padding: 6px 0; }
}

/* ---------------------------------------------------------------------------
   Single payment mode.

   The store sells one thing, one way. The drawer's payment chooser is off, but its
   radio input still has to exist: the script reads the selected option to find the
   variant and to see whether a selling plan is attached, so deleting the input would
   break checkout rather than tidy the UI. It is taken out of sight and out of the
   accessibility tree instead, the standard visually-hidden treatment, with the
   section marking the wrapper aria-hidden.

   Nothing here is needed once a second payment option exists -- the chooser setting
   turns the real UI back on and these rules stop matching. */
.cart-plans--single {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* "Your price: one payment" repeats the total directly below it when there is only
   one way to pay. Hidden, not removed: the script writes into it. */
.cart-line--hidden { display: none; }

/* With the chooser gone the included list is the first thing under the item, so it
   does not need the extra gap that separated it from the radio cards. */
.cart-plans--single + .cart-sub { margin-top: 16px; }
