/* Postvex marketing site | assets/css/site.css
   Color and radius tokens mirror the app palette (Phase 11.4).
   Space Grotesk is reserved for the wordmark; everything else is Inter. */

/* ------------------------------------------------------------------ */
/* Fonts. Self-hosted from /assets/fonts/.                            */
/* ------------------------------------------------------------------ */

@font-face {
  font-family: 'Space Grotesk';
  src: url('/assets/fonts/SpaceGrotesk-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Space Grotesk';
  src: url('/assets/fonts/SpaceGrotesk-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/Inter-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/Inter-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/Inter-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ------------------------------------------------------------------ */
/* Tokens                                                             */
/* ------------------------------------------------------------------ */

:root {
  --c-bg:         #FDFDFE;
  --c-ink-deep:   #0F172A;
  --c-ink:        #1E293B;
  --c-slate:      #334155;
  --c-slate-mid:  #475569;
  --c-slate-soft: #64748B;
  --c-slate-faint: #94A3B8;
  --c-slate-light: #CBD5E1;
  --c-primary:      #E8215D;
  --c-primary-deep: #D01450;
  --c-hairline:     #E2E8F0;
  --c-slate-pale:   #D6DEE8;
  --c-card:         #F1F5F9;

  --font-wordmark: 'Space Grotesk', system-ui, sans-serif;
  --font-body:     'Inter', system-ui, sans-serif;
}

/* ------------------------------------------------------------------ */
/* Base                                                               */
/* ------------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-slate);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; }

/* Text for assistive tech only: the plan names and included or not
   included states the pricing strip and grid show by position. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 3px;
}

::selection {
  background: var(--c-primary);
  color: #FFFFFF;
}

/* ------------------------------------------------------------------ */
/* Announcement banner                                                */
/* ------------------------------------------------------------------ */

.banner {
  background: var(--c-primary);
  color: #FFFFFF;
  text-align: center;
  padding: 8px 16px;
}

.banner p {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.5;
  white-space: nowrap;
}

/* ------------------------------------------------------------------ */
/* Header and navigation                                              */
/* ------------------------------------------------------------------ */

.site-header { border-bottom: 1px solid var(--c-hairline); }

.nav-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

/* 1fr auto 1fr keeps the center links on the page's vertical axis on
   wide screens and degrades gracefully when the sides get tight. */
.nav-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  column-gap: 20px;
  align-items: center;
  height: 68px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  justify-self: start;
  text-decoration: none;
}

.brand-word {
  font-family: var(--font-wordmark);
  font-weight: 600;
  font-size: 1.4375rem;
  letter-spacing: -0.01em;
  color: var(--c-slate);
}

.nav-links {
  display: flex;
  gap: 28px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-links a {
  font-size: 0.9375rem;
  color: var(--c-slate);
  text-decoration: none;
  padding: 6px 2px;
  white-space: nowrap;
  transition: color 0.15s ease;
}

.nav-links a:hover { color: var(--c-primary); }

.nav-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  justify-self: end;
}

/* ------------------------------------------------------------------ */
/* Buttons. One pill base, four variants.                             */
/* ------------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55em;
  font-family: var(--font-body);
  font-weight: 600;
  line-height: 1;
  border-radius: 999px;
  text-decoration: none;
  white-space: nowrap;
}

.btn svg {
  width: 1em;
  height: 1em;
  flex: none;
}

/* Nav primary: slate pill that warms to raspberry. */
.btn-nav {
  height: 40px;
  padding-inline: 19px;
  font-size: 0.9375rem;
  background: var(--c-slate);
  color: #FFFFFF;
  transition: background-color 0.18s ease;
}

.btn-nav:hover { background: var(--c-primary); }

/* Sign In: outline pill, transparent at rest and on hover. */
.btn-ghost {
  height: 40px;
  padding-inline: 19px;
  font-size: 0.9375rem;
  background: transparent;
  border: 1.5px solid var(--c-slate);
  color: var(--c-slate);
  transition: color 0.15s ease, border-color 0.15s ease;
}

.btn-ghost:hover {
  color: var(--c-primary);
  border-color: var(--c-primary);
}

/* Call to action: raspberry pill. Hover deepens the color and grows
   the whole button together. */
.btn-cta {
  font-size: 1.0625rem;
  padding: 1em 1.65em;
  background: var(--c-primary);
  color: #FFFFFF;
  transition: background-color 0.18s ease, transform 0.18s ease;
}

.btn-cta:hover {
  background: var(--c-primary-deep);
  transform: scale(1.05);
}

/* Secondary call to action: a smaller pill outlined in raspberry with
   no fill in any state. Hover and keyboard focus deepen the border,
   text, and arrow together and grow the button like the primary. */
.btn-secondary {
  padding: 10px 20px;
  font-size: 0.9375rem;
  background: transparent;
  border: 1.5px solid var(--c-primary);
  color: var(--c-primary);
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}

.btn-secondary:hover,
.btn-secondary:focus-visible {
  background: transparent;
  border-color: var(--c-primary-deep);
  color: var(--c-primary-deep);
  transform: scale(1.05);
}

/* ------------------------------------------------------------------ */
/* Mobile toggle and panel (hidden on desktop)                        */
/* ------------------------------------------------------------------ */

.nav-toggle {
  display: none;
  appearance: none;
  background: none;
  border: 0;
  padding: 10px;
  margin-right: -10px;
  color: var(--c-slate);
  line-height: 0;
  cursor: pointer;
  justify-self: end;
}

.nav-toggle svg { width: 24px; height: 24px; }

.nav-toggle .icon-close { display: none; }
.nav-toggle[aria-expanded="true"] .icon-menu  { display: none; }
.nav-toggle[aria-expanded="true"] .icon-close { display: block; }

/* Desktop never shows the panel. Below 768px no display property is
   set on it, so the div default applies and the [hidden] attribute
   alone controls visibility. */
@media (min-width: 768px) {
  .mobile-menu { display: none; }
}

/* ------------------------------------------------------------------ */
/* Hero                                                               */
/* ------------------------------------------------------------------ */

.hero {
  padding-top: clamp(4.25rem, 2.75rem + 5vw, 7.5rem);
  padding-bottom: clamp(5rem, 3.5rem + 6vw, 9rem);
  text-align: center;
}

/* Wide enough to clear the sub's measure at its 21px cap. */
.hero-shell {
  max-width: 1024px;
  margin-inline: auto;
  padding-inline: 24px;
}

/* One line from about 455px up. Narrower than that it wraps, and
   balance breaks it as "You need" over "better posts", the marked
   word leading the second line, rather than leaving "posts" alone. */
.hero h1 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: clamp(2.3125rem, 1.40625rem + 3.86vw, 4.5rem);
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--c-ink);
  text-wrap: balance;
  margin: 0;
}

/* Anchors the marker stroke so it tracks its word at every size: the
   hero's "better" and the statement's "bet". */
.bet {
  position: relative;
  display: inline-block;
}

/* One tapered marker stroke, drawn as a filled outline so the width
   can vary. Em units keep it proportional at every font size. The
   svg stretches to its word, so each mark's viewBox matches the
   word's proportions (120 units wide under "bet", 206 under
   "better") and the drawing units stay square: the same 3-unit
   stroke, the same bulge to 4.35 in the middle, round caps that stay
   round. */
.bet-mark {
  position: absolute;
  left: -0.15em;
  bottom: -0.02em;
  width: calc(100% + 0.3em);
  height: 0.3em;
  overflow: visible;
  pointer-events: none;
}

.bet-mark path { fill: var(--c-primary); }

/* Wipes in left to right once on load. The static state is the
   finished stroke, so reduced motion shows it immediately. */
@media (prefers-reduced-motion: no-preference) {
  .bet-mark { animation: mark-wipe 0.3s ease-out 0.1s backwards; }
}

@keyframes mark-wipe {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

.sub {
  font-size: clamp(1.0625rem, 0.957rem + 0.45vw, 1.3125rem);
  line-height: 1.65;
  color: var(--c-slate-soft);
  max-width: 70ch;
  text-wrap: balance;
  margin: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem) auto 0;
}

.hero .btn-cta { margin-top: clamp(2.25rem, 2rem + 1.5vw, 2.75rem); }

.proof {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--c-slate-faint);
  margin: 2.25rem auto 0;
}

.proof-icon {
  font-size: 17px;
  line-height: 1;
  flex: none;
}

/* ------------------------------------------------------------------ */
/* Better odds. Three flat slate cards under the hero. The gap above  */
/* the h2 is the hero's own bottom padding, so this section adds none */
/* of its own on top.                                                 */
/* ------------------------------------------------------------------ */

.better-odds {
  padding-bottom: clamp(5rem, 3.5rem + 6vw, 9rem);
  text-align: center;
}

/* Same width and gutter as .nav-shell. */
.odds-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

/* One section-heading style, shared by every h2, the comparison
   grid's title, and the stub h1. */
.better-odds h2,
.convexity h2,
.platforms h2,
.faq h2,
.pricing h2,
.cmp-title,
.page-title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: clamp(1.875rem, 1.51rem + 1.55vw, 2.75rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--c-ink);
  margin: 0;
}

.odds-cards {
  display: grid;
  gap: 20px;
  margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem);
  text-align: left;
}

/* Screen test: light surface. Revert to the dark cards by swapping
   each color below for the slate value commented beside it. Padding
   is the original 36px 40px trimmed a fifth. */
.odds-card {
  background: var(--c-card); /* slate: var(--c-slate) */
  border-radius: 28px;
  padding: 28px 32px;
}

/* Card icons: Phosphor Icons (phosphoricons.com), MIT license. */
.odds-icon {
  display: block;
  width: 56px;
  height: 56px;
  color: var(--c-primary);
}

.odds-card h3 {
  font-weight: 600;
  font-size: 1.75rem;
  line-height: 1.3;
  color: var(--c-ink); /* slate: #FFFFFF */
  margin: 28px 0 0;
}

/* Body copy at the page's base size and leading, one step tighter
   than the FAQ answers' 1.6. */
.odds-card p {
  font-size: 1rem;
  line-height: 1.5;
  color: var(--c-slate-soft); /* slate: var(--c-slate-pale) */
  text-wrap: pretty;
  margin: 16px 0 0;
}

/* Three across once each card is wide enough for the 16px body. */
@media (min-width: 960px) {
  .odds-cards {
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
  }
}

/* ------------------------------------------------------------------ */
/* Statement. One line of display type on the page's own ground      */
/* between the odds cards and the convexity card: no fill, border,   */
/* icon, or button, and the word "bet" wears the hero's marker       */
/* stroke. It sits the way the equation row sits under the FAQ, the  */
/* neighbour's standard gap plus a row's own padding on each side,   */
/* so the line reads as a pause between the two card groups. Above,  */
/* better-odds provides the standard gap and this section adds the   */
/* row padding; below, this section carries both, since the          */
/* convexity card expects its top gap from its predecessor.          */
/* ------------------------------------------------------------------ */

.statement {
  background: var(--c-bg);
  padding-top: clamp(1.875rem, 1.5rem + 1.5vw, 2.625rem);
  padding-bottom: calc(clamp(5rem, 3.5rem + 6vw, 9rem) + clamp(1.875rem, 1.5rem + 1.5vw, 2.625rem));
  text-align: center;
}

/* Same width and gutter as .nav-shell. */
.stmt-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

/* The h2 scale, weight, and tracking, one step darker than the
   headings so it reads as a line of type rather than a heading. One
   line from 768px up; below that, balance breaks it at the full stop
   into two lines, which fit down to 320px. */
.stmt {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: clamp(1.875rem, 1.51rem + 1.55vw, 2.75rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--c-ink-deep);
  text-wrap: balance;
  margin: 0;
}

/* ------------------------------------------------------------------ */
/* Convexity. One large slate card on the page's own ground, as wide  */
/* as the content container and rounded like the page's other cards, */
/* holding the h2 and two iconed columns (what kills you, what pays  */
/* you) with the article button closing the right column. The gaps   */
/* above and below the card are the neighbours' own section padding  */
/* (the statement's bottom, the platforms' top), so the section      */
/* itself adds none.                                                 */
/* ------------------------------------------------------------------ */

.convexity {
  background: var(--c-bg);
  text-align: center;
  /* The nav's Convexity link lands here: a strip of white above the
     card so its rounded top corners read, not a flush dark edge. */
  scroll-margin-top: 2rem;
}

/* Same width and gutter as .nav-shell. */
.cvx-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

/* Flat slate, no border or shadow. Vertical padding is the old band's
   edge, 56px on phones up to 80px, so the h2 and columns keep their
   breathing room; horizontal padding is the page gutter on phones
   growing to 64px, and the centered columns never reach it on wide
   screens anyway. */
.cvx-card {
  background: var(--c-slate);
  border-radius: 28px;
  padding: clamp(3.5rem, 2.8rem + 2.8vw, 5rem) clamp(24px, 5vw, 64px);
}

.convexity h2 { color: #FFFFFF; }

/* The wrapper shrink-wraps its two columns and centers as a block,
   so the composition is symmetric even though the text inside is
   ragged right. One stacked column until both fit side by side; the
   left column (what kills you) reads first either way. */
.cvx-columns {
  display: flex;
  flex-direction: column;
  gap: 40px 80px;
  width: fit-content;
  margin: clamp(2.5rem, 2rem + 2vw, 3.5rem) auto 0;
  text-align: left;
}

/* Side by side, top-aligned: the button lengthens the right column
   without stretching the left one. */
@media (min-width: 960px) {
  .cvx-columns {
    flex-direction: row;
    align-items: flex-start;
  }
}

/* Each column takes its width from the flex layout: its capped body
   side by side, the wrapper's full width when stacked. Either way
   the icon, label, and body share one left edge. It must not be
   max-content: the wrapper is fit-content, so a percentage max-width
   here is cyclic and ignored while the wrapper measures itself, and a
   max-content column would hold the wrapper at 42ch on any phone,
   spilling the copy past the card's right edge. */
.cvx-col { width: auto; }

/* Column icons: Phosphor skull (fill) and currency-dollar-simple
   (bold), same license as the card icons above. */
.cvx-icon {
  display: block;
  width: 48px;
  height: 48px;
  color: var(--c-primary);
}

.cvx-label {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.2;
  color: #FFFFFF;
  margin: 20px 0 0;
}

/* Slate-pale on the card measures 7.6:1. */
.cvx-body {
  font-size: 1.1875rem;
  line-height: 1.6;
  color: var(--c-slate-pale);
  text-wrap: pretty;
  max-width: 42ch;
  margin: 16px 0 0;
}

/* Flex so the paragraph is exactly the button's height and the pill
   sits on the column's left edge under the body. */
.cvx-cta {
  display: flex;
  margin: 28px 0 0;
}

/* On the card the pill rests in white and turns raspberry on hover
   and keyboard focus. Scale, transparent fill, and the reduced-motion
   behavior come from the shared secondary variant. */
.convexity .btn-secondary {
  border-color: #FFFFFF;
  color: #FFFFFF;
}

.convexity .btn-secondary:hover,
.convexity .btn-secondary:focus-visible {
  border-color: var(--c-primary);
  color: var(--c-primary);
}

/* ------------------------------------------------------------------ */
/* Platforms. A heading and one line of subhead over two flat tiles  */
/* on the page's own ground: the X app icon, then a quiet placeholder */
/* for what comes next. Same rhythm and tile treatment as better-odds. */
/* The band above gives no light space, so this section pads both    */
/* edges.                                                            */
/* ------------------------------------------------------------------ */

.platforms {
  background: var(--c-bg);
  padding-block: clamp(5rem, 3.5rem + 6vw, 9rem);
  text-align: center;
}

/* Same width and gutter as .nav-shell. */
.plat-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

/* The subhead: the hero's headline to subhead lockup at the h2's
   scale. The hero's gap is about 0.8em of its h1, so this one runs
   20px under the 30px h2 on phones to 24px under the 44px h2 at the
   cap. Slate-mid at 18px, balanced so its two desktop lines match. */
.plat-sub {
  font-size: 1.125rem;
  font-weight: 400;
  line-height: 1.6;
  color: var(--c-slate-mid);
  max-width: 60ch;
  text-wrap: balance;
  margin: clamp(1.25rem, 1rem + 0.8vw, 1.5rem) auto 0;
}

/* Stacked and centered below the better-odds breakpoint, then a
   centered pair. */
.plat-cards {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem);
}

@media (min-width: 960px) {
  .plat-cards {
    flex-direction: row;
    justify-content: center;
  }
}

/* A true 140px square whatever it holds: fixed on both axes, exempt
   from flex sizing, and border-box so the hairline sits inside the
   140px. Contents center as one unit. */
.plat-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex: none;
  width: 140px;
  height: 140px;
  background: var(--c-card);
  border: 1px solid var(--c-hairline);
  border-radius: 28px;
}

/* The X app icon: the brand glyph in white on a black rounded
   square, drawn in the markup on a 96-unit viewBox and rendered at
   60px, so its 20-unit corner comes out at 12.5px. */
.plat-x {
  display: block;
  width: 60px;
  height: 60px;
}

/* The placeholder plus, small and faint, subordinate to the icon. */
.plat-plus {
  display: block;
  width: 30px;
  height: 30px;
  color: var(--c-slate-faint);
}

.plat-label {
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--c-slate-soft);
  margin: 0;
}

/* ------------------------------------------------------------------ */
/* FAQ. Eyebrow and h2 on the left, eleven hairline rows on the       */
/* right, on the page's own ground with no cards or fills. Each row  */
/* is one button that opens its answer in place: question and plus   */
/* turn raspberry, the plus rotates into a cross, and the answer     */
/* track grows from 0fr to 1fr while the copy fades in, all on one   */
/* 300ms clock. The gap above is the platforms section's bottom      */
/* padding, so like better-odds this section pads the bottom only.   */
/* ------------------------------------------------------------------ */

.faq {
  background: var(--c-bg);
  padding-bottom: clamp(5rem, 3.5rem + 6vw, 9rem);
  /* The nav's FAQ link lands here. Same headroom the band gives its
     h2, so the eyebrow never sits flush against the viewport top. */
  scroll-margin-top: clamp(3.5rem, 2.8rem + 2.8vw, 5rem);
}

/* Same width and gutter as .nav-shell. Heading block over the list
   until the page's other side by side layouts go to two columns,
   then a 40/60 split with the heading pinned to the top. */
.faq-shell {
  display: grid;
  gap: clamp(2.5rem, 2rem + 2vw, 3.5rem) clamp(48px, 7.5vw, 96px);
  align-items: start;
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

@media (min-width: 960px) {
  .faq-shell { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
}

/* The band's caps label, one size down. Shared with pricing. */
.faq-eyebrow,
.price-eyebrow {
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-primary);
  margin: 0;
}

.faq h2 { margin-top: 10px; }

/* Hairlines: one above each row, one closing the list. */
.faq-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-bottom: 1px solid var(--c-hairline);
}

.faq-item { border-top: 1px solid var(--c-hairline); }

/* The heading exists for assistive tech; the button is the row. */
.faq-h { margin: 0; }

.faq-q {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  appearance: none;
  background: none;
  border: 0;
  margin: 0;
  padding: 24px 0;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.125rem;
  line-height: 1.4;
  text-align: left;
  color: var(--c-ink-deep);
  cursor: pointer;
  transition: color 0.3s ease-in-out;
}

/* Phosphor plus (bold), centered on the question's first line
   however many lines the question wraps to. */
.faq-icon {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: calc((1.4em - 20px) / 2);
  color: var(--c-slate-mid);
  transition: transform 0.3s ease-in-out, color 0.3s ease-in-out;
}

@media (hover: hover) {
  .faq-q:hover,
  .faq-q:hover .faq-icon { color: var(--c-primary); }
}

.faq-item.is-open .faq-q,
.faq-item.is-open .faq-icon { color: var(--c-primary); }

.faq-item.is-open .faq-icon { transform: rotate(45deg); }

/* Closed: a 0fr track and an overflow-hidden cell clip the answer to
   nothing; the markup's inert attribute keeps its links out of the
   tab order and visibility backs that up. Open: the track grows to
   the answer's height. Visibility flips at the start when opening
   and at the end when closing, so the copy is visible for the whole
   of either transition. */
.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows 0.3s ease-in-out, visibility 0.3s;
}

.faq-item.is-open .faq-a {
  grid-template-rows: 1fr;
  visibility: visible;
}

.faq-a-inner {
  min-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.3s ease-in-out;
}

.faq-item.is-open .faq-a-inner { opacity: 1; }

/* The bottom padding lives on the paragraph, inside the clipped cell,
   so a closed row collapses to exactly zero. */
.faq-a p {
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--c-slate-mid);
  text-wrap: pretty;
  margin: 0;
  padding-bottom: 28px;
}

/* In-copy links: raspberry, underlined, deeper on hover. */
.faq-a a {
  color: var(--c-primary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
  transition: color 0.15s ease;
}

.faq-a a:hover { color: var(--c-primary-deep); }

/* ------------------------------------------------------------------ */
/* Pricing. Eyebrow and h2 centered, the billing toggle under them,  */
/* three cards in a row on the page's own ground, then the Compare   */
/* plans grid and the button under it that appends the rest.        */
/* Starter and Ultra are the flat pale card from                     */
/* better-odds; Pro wears a raspberry gradient and the badge, so it  */
/* reads as the default. The gradient is one modifier class,        */
/* price-card-gradient, at the end of this block, and the ringed     */
/* pale card it replaces is what the Pro article shows without that  */
/* class. The lists run 11, 14, and 17 rows; the row stretches every */
/* card to Ultra's height and each card pins its button to the       */
/* bottom, so the three buttons share one line. The gap above is the */
/* FAQ section's bottom padding, so like the FAQ this section pads   */
/* the bottom only.                                                  */
/* ------------------------------------------------------------------ */

.pricing {
  background: var(--c-bg);
  padding-bottom: clamp(5rem, 3.5rem + 6vw, 9rem);
  text-align: center;
  /* The nav's Pricing link lands here, with the FAQ's headroom. */
  scroll-margin-top: clamp(3.5rem, 2.8rem + 2.8vw, 5rem);
}

/* Same width and gutter as .nav-shell. */
.price-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

/* Balanced so phones break the h2 at its comma, "Pick your plan,"
   over "publish winners", instead of stranding "winners". */
.pricing h2 {
  margin-top: 10px;
  text-wrap: balance;
}

/* The line under the h2, the platforms sub's type, color, and gap,
   centered by the section; the toggle keeps its own gap below it. */
.price-sub {
  font-size: 1.125rem;
  font-weight: 400;
  line-height: 1.6;
  color: var(--c-slate-mid);
  margin: clamp(1.25rem, 1rem + 0.8vw, 1.5rem) auto 0;
}

/* Billing toggle: a pale track holding two pills. The pressed one is
   the nav's slate pill with white text; the other is quiet text that
   darkens on hover. Yearly carries its tag at the button's own size,
   which puts the whole track at 284px with 16px side padding; under
   360px the padding drops to 12px and the tag gap to 5px, 267px in
   the 272px a 320px phone allows. Flex-wrap on the buttons is the
   fallback, wrapping the tag under Yearly rather than overflowing. */
.price-toggle {
  display: inline-flex;
  max-width: 100%;
  padding: 4px;
  margin-top: clamp(1.5rem, 1.2rem + 1.2vw, 2rem);
  background: var(--c-card);
  border-radius: 999px;
}

.toggle-btn {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 2px 6px;
  min-height: 40px;
  padding: 6px 16px;
  appearance: none;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.9375rem;
  line-height: 1.2;
  color: var(--c-slate-mid);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.toggle-btn:hover { color: var(--c-ink-deep); }

.toggle-btn[aria-pressed="true"],
.toggle-btn[aria-pressed="true"]:hover {
  background: var(--c-slate);
  color: #FFFFFF;
}

/* The Yearly button's tag, the button's own size. Deep raspberry on
   the pale track measures 4.9:1; raspberry on the pressed slate pill
   would be 2.6:1, so there it goes slate-pale. */
.toggle-note {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--c-primary-deep);
  white-space: nowrap;
}

.toggle-btn[aria-pressed="true"] .toggle-note { color: var(--c-slate-pale); }

@media (max-width: 359.98px) {
  .toggle-btn {
    gap: 2px 5px;
    padding-inline: 12px;
  }
}

/* One column until 960px, then three across, in document order:
   Starter, Pro, Ultra. Same top margin as the odds cards. Every
   card is capped at 360px and centered in its column, so the
   stacked cards sit centered in the shell, and the row stretches
   all three to the tallest, Ultra, with the buttons pinned level.
   Across, the columns are the cap wide with 32px between, 1144px
   in all, and the shell centers the trio: at 1280px the row sits
   36px in from each gutter, close to the gaps between the cards.
   Under 1204px the columns shrink together, 283px at 960px, and
   the row fills the shell as before. */
.price-cards {
  display: grid;
  align-items: stretch;
  justify-items: center;
  gap: 20px;
  margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem);
  text-align: left;
}

@media (min-width: 960px) {
  .price-cards {
    grid-template-columns: repeat(3, minmax(0, 360px));
    justify-content: center;
    gap: 32px;
  }
}

/* The odds card's fill, radius, and vertical padding. Side padding
   is the page gutter on phones, growing to the odds card's 32px, so
   a 320px phone keeps 224px inside for the longest feature rows.
   The card fills its column up to the 360px cap; the min() lets
   the cap yield to the column on phones under 408px, where the
   shell's inside is narrower than 360px. A column flex layout runs
   name, tagline, price, and list from the top, and the CTA block's
   auto margin takes whatever height the stretched row adds, so a
   shorter list leaves empty space above its button rather than
   spreading its rows. */
.price-card {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: min(360px, 100%);
  min-width: 0;
  padding: 28px clamp(24px, 6vw, 32px);
  background: var(--c-card);
  border-radius: 28px;
  color: var(--c-ink-deep);
}

/* Pro's fallback: the same pale card with a 2px raspberry ring,
   drawn as an inset shadow so it follows the radius and takes no
   layout space; the three cards keep identical padding, width, and
   height, with no border box to throw the stretched row off. 4.3:1
   against the page. The Pro article also carries
   price-card-gradient, which switches this ring off under the
   gradient; drop that class and this ring is what shows. Pro's
   earlier slate-900 treatment is kept dormant at the end of this
   block under price-card-dark. */
.price-card-pro { box-shadow: inset 0 0 0 2px var(--c-primary); }

/* Name on the left, badge (Pro only) on the right, so the three
   names share one baseline across the row. */
.plan-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 12px;
}

.plan-name {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.2;
  margin: 0;
}

/* Raspberry pill, white caps, the announcement banner's pairing. A
   faint diagonal light crosses it every 3 seconds: a pseudo-element
   the pill's own size carrying a narrow white band at 22% opacity,
   clipped by the pill, sliding from one side to the other in the
   first 1.2s of each cycle and resting for the remaining 1.8s. The
   pseudo-element exists only when motion is welcome, so reduced
   motion gets the plain pill. */
.plan-badge {
  position: relative;
  display: inline-block;
  overflow: hidden;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--c-primary);
  color: #FFFFFF;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

@media (prefers-reduced-motion: no-preference) {
  .plan-badge::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(110deg, transparent 38%, rgba(255, 255, 255, 0.22) 50%, transparent 62%);
    transform: translateX(-100%);
    animation: badge-shimmer 3s ease-in-out infinite;
    pointer-events: none;
  }
}

@keyframes badge-shimmer {
  from { transform: translateX(-100%); }
  40%, to { transform: translateX(100%); }
}

.plan-tagline {
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--c-slate-mid);
  margin: 6px 0 0;
}

/* Price block: the amount at 48px with the period beside it on the
   baseline. The yearly state adds a 20px line beneath plus 4px, and
   the block reserves that height in both states (48 + 24 = 72px),
   so the list and button below never move when the toggle flips. */
.plan-price {
  min-height: 4.5rem;
  margin-top: 24px;
}

.price-monthly,
.price-yearly {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 4px;
  margin: 0;
}

/* The toggle script hides the off-period block with the hidden
   attribute, which the flex display above would otherwise override. */
.plan-price > [hidden] { display: none; }

.price-amount {
  font-size: 3rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
}

.price-per {
  font-size: 1rem;
  font-weight: 400;
  line-height: 1;
  color: var(--c-slate-mid);
}

.price-saving {
  flex-basis: 100%;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 20px;
  color: var(--c-primary-deep);
  margin-top: 4px;
}

/* Feature rows. */
.plan-features {
  list-style: none;
  margin: 24px 0 0;
  padding: 0;
}

.plan-features li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
}

.plan-features li + li { margin-top: 10px; }

/* Phosphor check (bold), raspberry: 4.0:1 on the pale card, past the
   3:1 icons need. 2px down centers the 20px glyph on the 24px first
   line. */
.feat-check {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  color: var(--c-primary);
}

/* Phosphor x (bold), slate-400: the grid's mark for a feature a
   plan lacks, gray by design, never red. */
.feat-none { color: var(--c-slate-faint); }

.feat-text { min-width: 0; }

/* Info icon and tooltip. The markup glues the icon to the last word
   with a non-breaking space, so the pair wraps together. The button
   is a 24px target around the 16px glyph, pulled in by negative
   margins so it sits on the line like a character and adds nothing
   to the line height. The tooltip hangs off the icon, centered and
   6px above; the script shifts it sideways into the viewport
   (--tip-shift) and flips it below the icon when there is no room
   above. It ignores the pointer, so leaving the icon closes it. */
.info {
  position: relative;
  display: inline-block;
}

.info-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  margin: -4px -4px -4px 0;
  padding: 0;
  appearance: none;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--c-slate-soft);
  vertical-align: middle;
  cursor: pointer;
  transition: color 0.15s ease;
}

.info-btn:hover,
.info.is-open .info-btn { color: var(--c-ink-deep); }

.info-icon {
  width: 16px;
  height: 16px;
}

/* width: max-content sidesteps shrink-to-fit inside the tiny anchor,
   which would otherwise stack the copy one word per line. */
.tip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 6px);
  z-index: 5;
  width: max-content;
  max-width: 260px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--c-ink-deep);
  color: #FFFFFF;
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  text-wrap: pretty;
  transform: translateX(calc(-50% + var(--tip-shift, 0px)));
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease, visibility 0.12s;
}

.info.is-open .tip {
  visibility: visible;
  opacity: 1;
}

.info.tip-below .tip {
  bottom: auto;
  top: calc(100% + 6px);
}

/* CTA block: the button and its fine print, pinned to the card's
   bottom. The auto margin absorbs the height the stretched row adds
   above it, and the padding keeps the list's 28px clearance as the
   minimum, which is all Ultra, the tallest card, gets. */
.plan-cta {
  margin-top: auto;
  padding-top: 28px;
}

/* Plan button: the hero's raspberry pill. The markup carries btn-cta,
   so the fill, the deepening and 1.05 scale on hover, and the
   reduced-motion exemption are all the hero's; this only makes it
   full width at 16px. White on raspberry measures 4.4:1, the same as
   every raspberry pill on the site. The arrow is the shared header
   fragment, sized by .btn. */
.btn-plan {
  width: 100%;
  min-height: 48px;
  padding: 0.875em 1.25em;
  font-size: 1rem;
}

/* Slate-mid on the pale card is 7:1. */
.plan-fine {
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--c-slate-mid);
  text-align: center;
  margin: 12px 0 0;
}

/* Comparison grid. A centered title in the section heading style,
   then one table 840px wide, about seven tenths of the card row,
   centered: a label column on the page's ground and three plan
   columns of tiles, the plan names heading them. Six rows show by
   default, the three ladders, the two agent rows, and the edge map
   row; the button under the grid shows the other eleven card rows,
   a second table body that sits hidden until then, and reads
   Minimize while they show. Cells are tiles: each td pads 4px and
   the tile inside carries the pale card fill and a 12px radius, so
   tiles sit 8px apart both ways, the first column of tiles 16px off
   the labels, and the last flush with the row's right edge. Pro's
   tiles take the faintest raspberry tint, the one echo of the card
   above. Labels are semibold and tile values regular, 16px, the
   plan names bold, the icons 24px. Tooltips sit on the labels only,
   their icons in one column at the label column's right edge, each
   pinned there by the sticky cell and centered on its row. The
   label column from 768px up is 200px of text, enough for the
   longest label, "Press-when-ahead alerts", 197px semibold, on one
   line, then 8px, the 24px icon column, and the 16px gap, 248px in
   all, and the tiles come out 189px. Under 768px the text drops to
   15px, the icons to 22px, and the text area to 130px, where the
   long labels wrap to two lines, and the table keeps a 448px floor
   so every tile is at least 86px wide, 74px inside its padding,
   which holds "12 months"; under 496px, where the 448px floor no
   longer fits the shell, the wrapper scrolls sideways with the label
   column stuck to the left edge, on the page's ground so tiles slide
   under it. With a mouse, resting on a row washes its label cell and
   darkens its tiles a step, 100ms each way; touch gets none of that.
   A row of trial buttons follows the wrapper as its own block, shown
   and hidden with the appended body. The gap above the title is one
   and a half times the cards' gap under their heading, so the grid
   reads as its own moment. */
.price-compare {
  max-width: 840px;
  margin: clamp(3.75rem, 3rem + 3vw, 5.25rem) auto 0;
  text-align: left;
  /* The Minimize script keeps the button in place itself. */
  overflow-anchor: none;
}

/* The shared heading rule above sets the type; this centers it. */
.cmp-title {
  text-align: center;
  text-wrap: balance;
}

/* The cards' own gap under their heading. */
.cmp-scroll {
  margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem);
  overflow-x: auto;
}

/* Separate borders, since collapsed ones do not travel with a sticky
   cell in every browser. The 3px cell padding is half the phone gap. */
.cmp-table {
  width: 100%;
  min-width: 448px;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--c-ink-deep);
}

.cmp-table th,
.cmp-table td {
  padding: 3px;
  vertical-align: middle;
}

.cmp-table td:last-child { padding-right: 0; }

/* Plan names over their columns. */
.cmp-table thead th {
  padding-top: 0;
  padding-bottom: 6px;
  font-weight: 700;
  text-align: center;
}

/* The label column: its width covers the text, the icon column,
   and the 12px it keeps off the tiles, the right padding holding
   the icon column and its 6px lead clear of the text. Sticky for
   the sideways scroll, on the page's ground with a shadow the
   width of the next cell's padding so nothing shows through the
   gap. */
.cmp-table th:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  width: 172px;
  padding-inline: 0 42px;
  background: var(--c-bg);
  box-shadow: 3px 0 0 var(--c-bg);
  text-align: left;
}

/* Rounded on the outer side like the tiles, for the hover wash. */
.cmp-table tbody th {
  font-weight: 600;
  border-radius: 12px 0 0 12px;
  transition: background-color 0.1s ease, box-shadow 0.1s ease;
}

/* The icon column: the sticky cell positions it, so the icon sits
   at the text area's right edge, centered on the row by the auto
   margins around its fixed height. No transform here, since one
   would pull the fixed tooltip out of the viewport's frame. The
   button drops the inline nudge it uses on the cards. */
.cmp-table th .info {
  position: absolute;
  top: 0;
  right: 12px;
  bottom: 0;
  display: flex;
  align-items: center;
  height: 24px;
  margin: auto 0;
}

.cmp-table th .info-btn { margin: 0; }

/* The tile. Flex centers the value both ways. */
.tile {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: 6px;
  border-radius: 12px;
  background: var(--c-card);
  text-align: center;
  transition: background-color 0.1s ease;
}

/* Raspberry at 7% over the page, next to the neutral tiles. */
.cell-pro .tile { background: #FBEEF3; }

/* Row hover, pointers that can hover only: the label cell takes a
   faint slate wash, its gap shadow with it, and the tiles go one
   step darker, the Pro tint by the same step. No border, no move. */
@media (hover: hover) {
  .cmp-table tbody tr:hover th {
    background: #F5F7FA;
    box-shadow: 3px 0 0 #F5F7FA;
  }

  .cmp-table tbody tr:hover .tile { background: #E7ECF2; }

  .cmp-table tbody tr:hover .cell-pro .tile { background: #F2E5EB; }
}

/* The card's check and the absent cross, 22px here and 24px from
   768px up, without the list row's top nudge. */
.tile .feat-check,
.tile .feat-none {
  flex: none;
  width: 22px;
  height: 22px;
  margin: 0;
}

/* The appended rows fade in as they appear; reduced motion cuts the
   animation to nothing along with the rest. */
.cmp-more tr { animation: cmp-row-in 0.25s ease-out both; }

@keyframes cmp-row-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (min-width: 768px) {
  .cmp-table { font-size: 1rem; }

  .cmp-table th,
  .cmp-table td { padding: 4px; }

  .cmp-table thead th { padding-bottom: 8px; }

  .cmp-table th:first-child {
    width: 248px;
    padding-inline: 0 48px;
    box-shadow: 4px 0 0 var(--c-bg);
  }

  .cmp-table th .info { right: 16px; }

  .tile {
    min-height: 52px;
    padding: 8px 12px;
  }

  .tile .feat-check,
  .tile .feat-none {
    width: 24px;
    height: 24px;
  }

  @media (hover: hover) {
    .cmp-table tbody tr:hover th { box-shadow: 4px 0 0 #F5F7FA; }
  }
}

/* The trial row: its own block under the scroll wrapper, shown and
   hidden with the appended body by the same button, so it never
   rides the sideways scroll and nothing clips it. From 496px up it
   is a grid on the table's geometry: the label column's width as
   empty lead space, 172px and 248px from 768px, then three equal
   columns, each button stretching across its column inside the
   side margins the tiles keep, 3px and 4px from 768px with none on
   the right of the last, so every button sits exactly under its
   plan column. From 768px up the buttons are the card CTA's size,
   16px type at 48px tall, with 8px side padding so "Start Starter
   trial", 129px, holds one line in the 153px columns at 768px;
   in the narrower columns below that they are 13px and 44px, where
   "Start Starter" wraps to two lines. Hover is the card CTA's own
   from btn-cta, the deeper fill and the 1.05 scale on its 0.18s
   transition, and touch gets none of it. Under 496px, where the
   grid scrolls sideways, the buttons stack instead: full width of
   the content area, 48px tall, 12px apart, in plan order. The
   hidden rule restates the attribute, since the display here would
   otherwise beat it. */
.cmp-actions {
  display: grid;
  gap: 12px;
  margin-top: 12px;
  animation: cmp-row-in 0.25s ease-out both;
}

.cmp-actions[hidden] { display: none; }

.btn-grid {
  min-height: 48px;
  padding: 0.875em 8px;
  font-size: 1rem;
  line-height: 1.25;
  white-space: normal;
  text-align: center;
}

@media (hover: none) {
  .btn-grid:hover {
    background: var(--c-primary);
    transform: none;
  }
}

@media (min-width: 496px) {
  .cmp-actions {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0;
    padding-left: 172px;
  }

  .btn-grid {
    margin: 0 3px;
    min-height: 44px;
    padding: 8px 4px;
    font-size: 0.8125rem;
  }

  .btn-grid:last-child { margin-right: 0; }
}

@media (min-width: 768px) {
  .cmp-actions { padding-left: 248px; }

  .btn-grid {
    margin: 0 4px;
    min-height: 48px;
    padding: 0.875em 8px;
    font-size: 1rem;
  }
}

/* The toggle: the convexity card's outlined pill, centered under
   the grid at a 44px touch height, full width on phones, with a
   caret that turns while the rows show. */
.cmp-toggle {
  display: flex;
  width: fit-content;
  min-height: 44px;
  margin: 20px auto 0;
}

@media (max-width: 599.98px) {
  .cmp-toggle { width: 100%; }
}

.cmp-toggle svg { transition: transform 0.3s ease-in-out; }

.cmp-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

/* Inside the grid the tooltip is fixed to the viewport, anchored to
   its icon by the script (--tip-x above, --tip-below beneath), since
   the wrapper's sideways scroll on phones would cut off a panel
   positioned inside it. The sideways shift and the flip below work
   as they do on the cards. */
.cmp-scroll .tip {
  position: fixed;
  left: var(--tip-x, 0px);
  top: var(--tip-y, 0px);
  bottom: auto;
  transform: translate(calc(-50% + var(--tip-shift, 0px)), calc(-100% - 6px));
}

.cmp-scroll .info.tip-below .tip {
  top: var(--tip-below, 0px);
  transform: translate(calc(-50% + var(--tip-shift, 0px)), 6px);
}

/* Pro, gradient. The whole raspberry treatment hangs off one
   modifier, price-card-gradient, beside price-card-pro on the Pro
   article; nothing else references it, so removing that one class
   returns the pale ringed card. The fill is one raspberry lit from
   the top right: a radial gradient centered on that corner runs
   from a hot pink at the corner to the accent's own brightness
   140px out, then slides across the card to a deeper raspberry
   that lands on the bottom left corner, since the ending shape is
   the default farthest corner. The flare is sized to the text: the
   badge sits inside it, 44px to 169px from the corner, and the
   nearest 16px text, the tagline's last letter, is 149px out on a
   320px phone and 223px on desktop, so every row sits on the body
   or deeper. The body stop is the accent with three units less
   green, which is where white 16px text reaches 4.5:1; the accent
   itself measures 4.4:1. White measures 3.2:1 at the corner, 4.5:1
   on the body, and 6.0:1 at the deep corner. The ring goes; the
   fill carries the emphasis. */
.price-card-gradient {
  background: radial-gradient(circle at 100% 0%, #FF4D7D 0, #E6185B 140px, #C0184C 100%);
  color: #FFFFFF;
  box-shadow: none;
}

/* Badge: a frosted pill, white at 22% over the fill, white caps,
   sitting in the flare. The caps measure 2.8:1 at the pill's
   bright end and 3.6:1 at its far end, under the 4.5:1 that 12px
   text asks for; that is the cost of the lit corner. The shimmer
   keeps the base rule's timing and reduced-motion exemption, with
   its band cut from 22% to 10% white so it barely registers on a
   pill that is already a fifth white. */
.price-card-gradient .plan-badge {
  background: rgba(255, 255, 255, 0.22);
  color: #FFFFFF;
}

.price-card-gradient .plan-badge::after {
  background: linear-gradient(110deg, transparent 38%, rgba(255, 255, 255, 0.1) 50%, transparent 62%);
}

/* Every text color on the card flips to white: the tagline, the
   period and saving beside the price, and the check. The name, the
   amount, and the rows inherit it from the card. */
.price-card-gradient .plan-tagline,
.price-card-gradient .price-per,
.price-card-gradient .price-saving,
.price-card-gradient .feat-check { color: #FFFFFF; }

/* Info icons at three-quarter white, 3.0:1 on the body and better
   down the slide, full white on hover and while open. */
.price-card-gradient .info-btn { color: rgba(255, 255, 255, 0.75); }

.price-card-gradient .info-btn:hover,
.price-card-gradient .info.is-open .info-btn { color: #FFFFFF; }

/* Tooltips invert to a white panel with slate-900 text, and carry
   a soft shadow so the panel keeps an edge where it overhangs the
   card onto the page's near-white ground. */
.price-card-gradient .tip {
  background: #FFFFFF;
  color: var(--c-ink-deep);
  box-shadow: 0 4px 16px rgba(15, 23, 42, 0.18);
}

/* The button inverts: white pill, deep raspberry text and arrow,
   5.4:1. Hover tints the pill the faintest pink, 4.9:1, and the
   1.05 scale and its reduced-motion exemption come from btn-cta. */
.price-card-gradient .btn-plan {
  background: #FFFFFF;
  color: var(--c-primary-deep);
}

.price-card-gradient .btn-plan:hover { background: #FFF0F4; }

/* The fine print at 85% white. It sits at the bottom of the card,
   well down the slide, where it measures 4.5:1; on the body it
   would measure 3.6:1. */
.price-card-gradient .plan-fine { color: rgba(255, 255, 255, 0.85); }

/* The raspberry focus ring and selection would vanish on the fill,
   so both go white here. */
.price-card-gradient :focus-visible { outline-color: #FFFFFF; }

.price-card-gradient ::selection {
  background: #FFFFFF;
  color: var(--c-primary-deep);
}

/* Pro's previous treatment, dormant: slate-900 with white text, the
   convexity card's move, ring off. Nothing in the markup applies
   price-card-dark; add it to the Pro article beside price-card-pro
   to bring the whole treatment back in one edit. */
.price-card-dark {
  background: var(--c-ink-deep);
  color: #FFFFFF;
  box-shadow: none;
}

.price-card-dark .plan-tagline,
.price-card-dark .price-per { color: var(--c-slate-light); }

.price-card-dark .price-saving { color: #FFFFFF; }

.price-card-dark .info-btn { color: var(--c-slate-faint); }

.price-card-dark .info-btn:hover,
.price-card-dark .info.is-open .info-btn { color: #FFFFFF; }

.price-card-dark .tip {
  background: #FFFFFF;
  color: var(--c-ink-deep);
}

.price-card-dark .plan-fine { color: var(--c-slate-faint); }

/* ------------------------------------------------------------------ */
/* Equation. A modest strip on the page's own ground holding the     */
/* centered lockup equation and the primary CTA, then the page ends. */
/* The equation markup keeps its cvx- classes, so their rules live   */
/* here.                                                             */
/* ------------------------------------------------------------------ */

.equation {
  background: var(--c-bg);
  padding-block: clamp(1.875rem, 1.5rem + 1.5vw, 2.625rem);
  text-align: center;
}

/* Same width and gutter as .nav-shell. */
.eq-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

/* The nav lockup at 1.5x, continued as live text. Em units on the
   mark and gaps keep the lockup proportional as the equation clamps
   down on small screens. */
.cvx-equation {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.3em;
  font-family: var(--font-wordmark);
  font-weight: 600;
  font-size: clamp(1.625rem, 1.32rem + 1.31vw, 2.15625rem);
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--c-ink);
  margin: 0;
}

.cvx-lockup {
  display: inline-flex;
  align-items: center;
  gap: 0.464em;
}

/* Inline SVG carrying the mark file's own colors, slate tile and
   white curve, the same as the nav. Only its size is set here. */
.cvx-mark {
  width: 1.478em;
  height: 1.478em;
  flex: none;
}

.cvx-op { color: var(--c-primary); }

/* Two centered lines: the lockup, then the rest of the equation. */
@media (max-width: 599.98px) {
  .cvx-equation { flex-direction: column; gap: 12px; }
}

/* The hero CTA again, centered by the section, 40px under the lockup. */
.equation .btn-cta { margin-top: 40px; }

/* ------------------------------------------------------------------ */
/* Article stub (/convexity/)                                         */
/* ------------------------------------------------------------------ */

.stub {
  padding-top: clamp(4.25rem, 2.75rem + 5vw, 7.5rem);
  padding-bottom: clamp(5rem, 3.5rem + 6vw, 9rem);
  text-align: center;
}

.stub-shell {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(24px, 2.5vw, 32px);
}

.stub p {
  font-size: 1.1875rem;
  color: var(--c-slate-soft);
  margin: 1.25rem 0 0;
}

/* ------------------------------------------------------------------ */
/* Mobile                                                             */
/* ------------------------------------------------------------------ */

@media (max-width: 767.98px) {
  .nav-links,
  .nav-actions { display: none; }

  .nav-bar {
    grid-template-columns: 1fr auto;
    height: 60px;
  }

  .nav-toggle { display: inline-flex; }

  /* Sits outside .nav-shell for a full-bleed hairline. */
  .mobile-menu {
    border-top: 1px solid var(--c-hairline);
    padding: 10px 24px 24px;
  }

  .menu-link {
    display: block;
    padding: 13px 0;
    font-size: 1.0625rem;
    color: var(--c-slate);
    text-decoration: none;
  }

  .menu-signin { font-weight: 600; }

  .menu-divider {
    border: 0;
    border-top: 1px solid var(--c-hairline);
    margin: 10px 0;
  }

  .mobile-menu .btn-cta {
    width: 100%;
    margin-top: 14px;
  }
}

/* ------------------------------------------------------------------ */
/* Reduced motion                                                     */
/* ------------------------------------------------------------------ */

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

  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
  }

  .btn-cta:hover,
  .btn-secondary:hover,
  .btn-secondary:focus-visible { transform: none; }
}
