/* ============================================================================
   cart.css - page styles for /cart/ only.

   prospira.css already carries .container, .card, .btn family, .eyebrow, .badge,
   the nav, the footer and the starfield. None of that is restated here.

   The page is one centred column, not the usual two-column checkout. There is
   only ever one item - the licence tiers are mutually exclusive and a session is
   booked one at a time - so a summary rail beside a basket would be a column
   holding a single line. A single 640px panel reads as a receipt to confirm, and
   640px is the width of the booking dialog the buyer just came out of.
   ========================================================================== */

/* Top: the nav is sticky (top:14px, ~64-66px tall), so its bottom edge sits at
   about y=80 and content passes UNDER it on scroll - this padding only decides how
   the page looks at rest. It was 112px of pure air on desktop and 104px on mobile,
   which pushed the thing you came here to do off the first screen (on a 375x812
   phone only 539px of a 686px card was visible).

   Bottom is 0: the whole gap below the panel is owned by the #site-footer override
   further down, so it is one number to read instead of two to add up. */
.ck {
  padding: clamp(48px, 5vw, 64px) 18px 0;
}
/* The shared sheet gives #site-footer margin-top: var(--section-gap) - 128px on a
   desktop - and that is right for the landing pages, where tall scrolling sections
   need a real break before the footer. On a single-panel task page it stacked with
   this page's own bottom padding into 160px of nothing, under a panel sitting just
   64px below the nav. Same expression as the top padding above, so the panel has
   equal air on both sides. This wins over the shared rule on load order rather
   than force: equal specificity (1,0,0), and this sheet is linked second. */
#site-footer { margin-top: clamp(48px, 5vw, 64px); }

/* --- footer at the bottom on a short page --------------------------------
   The shared sheet gives body { min-height: 100vh }. On a block-level body that
   slack piles up AFTER the last child, so an empty cart - about 400px of content
   in a 1000px window - left 122px of bare background sitting BELOW the footer,
   which reads as a broken page rather than a short one.

   Making the body a column and letting <main> absorb the slack puts the footer at
   the bottom of the window with nothing after it. Scoped to this page rather than
   done in the shared sheet: the landing pages are always taller than the viewport,
   so min-height never bites there, and turning body into a flex container on all
   19 pages to fix two of them is a much bigger blast radius than the bug.

   Sticky positioning on the header is unaffected - a sticky flex item still sticks
   to the scroll container - and this was re-measured after the change. */
.page-cart { display: flex; flex-direction: column; }
.page-cart > main { flex: 1 0 auto; }


.ck-wrap {
  width: min(640px, 100%);
  margin-inline: auto;
}
/* .eyebrow is inline-flex in the shared sheet, so it is only as wide as its own
   text and text-align on it does nothing - it has to be centred as a box. */
.ck > .ck-wrap > .eyebrow { display: flex; width: fit-content; margin-inline: auto; }
.ck-title {
  margin: 12px 0 26px;
  text-align: center;
  font-size: clamp(2rem, 5vw, 2.7rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.05;
  color: var(--text-hi);
}
/* Same treatment the section headings use across the site: serif italic with the
   royal gradient clipped to the text. Copied deliberately - it is the one type
   flourish the brand has, and inventing a second one here would break it. */
.ck-title em {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.012em;
  background: linear-gradient(115deg, #d4e2ff 8%, #7fa2ff 54%, var(--accent) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* Cancelled checkout. Deliberately not styled as an error: nothing was charged,
   and a red panel over a decision someone simply postponed reads as a fault. */
.ck-notice {
  margin: 0 0 18px;
  padding: 13px 16px;
  border-radius: 12px;
  border: 1px solid var(--border-mid);
  background: linear-gradient(180deg, rgba(16, 22, 44, 0.5), rgba(10, 14, 30, 0.4));
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--text-mid);
}

.ck-panel { padding: 0; overflow: hidden; }

/* --- name band -----------------------------------------------------------
   The same lit plate the pricing cards use, so the item on the receipt looks
   like the card that was clicked. */
.ck-band {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  padding: 24px 24px 18px;
  overflow: hidden;
  border-bottom: 1px solid rgba(120, 160, 255, 0.14);
  border-radius: 0 0 16px 16px;
  background:
    radial-gradient(78% 140% at 50% -12%, rgba(42, 91, 255, 0.3), transparent 66%),
    linear-gradient(180deg, rgba(20, 30, 66, 0.5), rgba(10, 14, 30, 0.14));
  box-shadow:
    inset 0 1px 0 rgba(120, 160, 255, 0.14),
    inset 0 -20px 30px -26px rgba(0, 0, 0, 0.5);
}
/* The light line along the top rim, as on the pricing cards. */
.ck-band::after {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 56%;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, rgba(120, 160, 255, 0.85) 20%, rgba(255, 255, 255, 0.95) 50%, rgba(120, 160, 255, 0.85) 80%, transparent);
  box-shadow: 0 0 12px 1px rgba(42, 91, 255, 0.7);
  pointer-events: none;
}
.ck-item {
  position: relative;
  margin: 0;
  font-size: clamp(1.25rem, 3.2vw, 1.5rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text-hi);
}
.ck-term {
  position: relative;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-low);
}

/* Top padding matches the band's bottom padding above: the two straddle the
   band's border, and 22+22 made 44px of air around a 1px line. */
.ck-body { padding: 18px 24px 24px; }

/* --- money ---------------------------------------------------------------- */
.ck-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  font-size: 0.94rem;
  color: var(--text-mid);
}
.ck-row + .ck-row { margin-top: 10px; }
/* The total is the one number that decides, so it is the only one at scale.
   A rule above it separates "what it costs" from "what you pay now". */
.ck-row-total {
  padding-top: 14px;
  border-top: 1px solid var(--border-soft);
  align-items: center;
}
/* Equal air on both sides of that line - and it needs the compound selector to
   get it. `.ck-row + .ck-row` above is (0,2,0) and beats a bare `.ck-row-total`
   (0,1,0), so the intended 14px was silently pulled back to 10px: 10 above the
   line, 14 below. Only the margin is scoped this way; the line and its padding
   stay on the element, so they survive if the row above is ever hidden. */
.ck-row + .ck-row-total { margin-top: 14px; }
.ck-row-total strong {
  font-size: clamp(1.7rem, 4.2vw, 2.1rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--text-hi);
  font-variant-numeric: tabular-nums;
}

/* --- the spec, read back before a person acts on it ---------------------- */
.ck-spec {
  margin-top: 20px;
  padding: 15px 16px 16px;
  border-radius: 13px;
  border: 1px solid var(--border-soft);
  background: rgba(150, 180, 255, 0.035);
}
.ck-spec-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.ck-spec-title {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-low);
}
.ck-spec-edit {
  font-size: 0.86rem;
  color: #8ea8ff;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.ck-spec-edit:hover { border-bottom-color: currentColor; }
.ck-spec-rows { margin: 0; display: grid; gap: 9px; }
/* Label left, value right, on one line each: this is data to scan for a wrong
   graphics card, not prose to read. */
.ck-spec-row {
  display: grid;
  grid-template-columns: 128px 1fr;
  gap: 14px;
  align-items: baseline;
  font-size: 0.89rem;
  line-height: 1.5;
}
.ck-spec-row dt { color: var(--text-low); }
.ck-spec-row dd { margin: 0; color: var(--text-mid); overflow-wrap: anywhere; }
@media (max-width: 460px) {
  .ck-spec-row { grid-template-columns: 1fr; gap: 2px; }
}

/* --- the one action ------------------------------------------------------- */
.ck-pay {
  width: 100%;
  margin-top: 20px;   /* the card's one block gap - was 22px, which read as the
                         same separation as .ck-spec's 20px while not being it */
  font-size: 1rem;
}
.ck-pay.is-busy { opacity: 0.72; cursor: progress; }
.ck-pay:disabled { cursor: not-allowed; }

/* What happens after paying. Sits under the button because that is where the
   question is asked, and quiet because it is reassurance, not a claim. */
.ck-after {
  margin: 12px 0 0;
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--text-low);
}

.ck-error {
  margin: 18px 0 0;
  padding: 12px 14px;
  border-radius: 11px;
  border: 1px solid rgba(255, 120, 120, 0.34);
  background: rgba(255, 80, 80, 0.07);
  font-size: 0.89rem;
  line-height: 1.55;
  color: #ffc2c2;
}

.ck-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 18px;
  padding-top: 18px;   /* equal air either side of the line, as on .ck-row-total */
  border-top: 1px solid var(--border-soft);
}
.ck-secure {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.83rem;
  color: var(--text-low);
}
.ck-secure svg { color: rgba(150, 180, 255, 0.65); flex-shrink: 0; }
/* Removing the item is a real action but not one to invite, so it is a link in
   weight even though it is a button in behaviour. */
.ck-remove {
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 0.83rem;
  color: var(--text-low);
  cursor: pointer;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-1) var(--ease-out);
}
.ck-remove:hover { color: #ffb4b4; border-bottom-color: currentColor; }

/* --- empty and paid ------------------------------------------------------- */
.ck-empty .ck-body,
.ck-paid .ck-body { text-align: center; padding: 34px 24px 30px; }
.ck-empty-title,
.ck-paid-title {
  margin: 0 0 10px;
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text-hi);
}
.ck-empty-note,
.ck-paid-body {
  margin: 0 auto;
  max-width: 46ch;
  font-size: 0.94rem;
  line-height: 1.65;
  color: var(--text-mid);
}
.ck-empty-cta {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 24px;
}
.ck-paid-cta { margin-top: 24px; }

/* The tick is the whole confirmation, so it gets the one bright moment on the
   page - green, because it reports success rather than the brand. */
.ck-tick {
  display: inline-grid;
  place-items: center;
  width: 54px;
  height: 54px;
  margin-bottom: 16px;
  border-radius: 50%;
  border: 1px solid rgba(74, 222, 128, 0.4);
  background: radial-gradient(120% 120% at 50% 0%, rgba(74, 222, 128, 0.2), transparent 70%);
  box-shadow: 0 0 26px -8px rgba(74, 222, 128, 0.5);
  color: #7ee2a8;
}

/* --- already-on-this-plan dialog ----------------------------------------- */
/* Self-contained rather than borrowed from services.css, which this page does
   not load. One dialog, one place. */
.ck-modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px;
  background: rgba(2, 3, 10, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.ck-modal-panel {
  width: min(460px, 100%);
  max-height: calc(100dvh - 32px);
  display: flex;
  flex-direction: column;
  border-radius: var(--r-panel);
  border: 1px solid var(--border-strong);
  background:
    radial-gradient(120% 90% at 10% 0%, rgba(42, 91, 255, 0.16), transparent 58%),
    linear-gradient(180deg, rgba(13, 18, 38, 0.86), rgba(8, 11, 24, 0.9));
  /* No backdrop-filter here on purpose: the overlay behind it already blurs the
     page, and this panel is 86-90% opaque, so a second 22px readback would cost a
     composited layer to show almost nothing. */
  box-shadow: 0 40px 90px -40px rgba(0, 0, 0, 0.9);
}
.ck-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 16px 18px 14px;
  border-bottom: 1px solid var(--border-soft);
}
/* Stands alone rather than extending .badge: it wanted a different face, size,
   weight, case and spacing, so nine of the eleven declarations existed only to
   undo the shared ones. */
.ck-modal-badge {
  display: inline-flex;
  align-items: center;
  padding: 5px 13px 6px;
  border-radius: 10px;
  border: 1px solid rgba(120, 160, 255, 0.55);
  background: rgba(42, 91, 255, 0.14);
  box-shadow: 0 0 20px -6px rgba(42, 91, 255, 0.6);
  font-size: 0.9rem;
  font-weight: 600;
  color: #dbe7ff;
}
.ck-modal-x {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 9px;
  border: 1px solid var(--border-mid);
  background: rgba(150, 180, 255, 0.05);
  color: var(--text-mid);
  cursor: pointer;
}
.ck-modal-x:hover { color: var(--text-hi); border-color: var(--border-strong); }
.ck-modal-body { padding: 18px; overflow-y: auto; }
.ck-modal-note { margin: 0; font-size: 0.94rem; line-height: 1.65; color: var(--text-mid); }
.ck-modal-foot {
  display: grid;
  gap: 10px;
  padding: 14px 18px 18px;
  border-top: 1px solid var(--border-soft);
}
.ck-modal-foot .btn { width: 100%; }

/* --- phone ---------------------------------------------------------------- */
@media (max-width: 560px) {
  /* No padding-top override here any more. It used to be
     clamp(104px, 26vw, 132px), which was a much steeper curve than the base rule -
     harmless while the base started at 120px, but once the base came down to clear
     the dead space it left a 48px jump at this breakpoint. The base clamp is now
     flat enough (104-112px) to cover phones and desktop with one value. */
  /* Band bottom and body top stay equal here too - they straddle the band's
     border, and 18/20 put the line off centre on every phone. */
  .ck-band { padding: 20px 18px 18px; }
  .ck-body { padding: 18px 18px 22px; }
  .ck-foot { gap: 10px; }
}

/* -- Panel entrance -------------------------------------------------------
   Every checkout panel is swapped in by JS once the API answers, so the scroll reveal
   cannot drive it. An IntersectionObserver never fires for a display:none
   element, and by the time the script un-hides one the observer has already
   disconnected - the panel would sit at opacity 0 permanently. Keying the
   animation to :not([hidden]) runs it exactly when the panel appears, whenever
   that is, and something already on screen can never be left waiting on a
   script. Same keyframe and same tokens as .reveal-item and .hero-item: one
   system, a third trigger for content that arrives on its own schedule. */
.ck-panel:not([hidden]),
.ck-notice:not([hidden]) {
  animation: flow-card-in var(--reveal-dur) var(--reveal-ease) both;
}
@media (prefers-reduced-motion: reduce) {
  .ck-panel:not([hidden]), .ck-notice:not([hidden]) { animation: none; }
}
