/* ==========================================================================
   CT Innovates — Components
   Reusable brand primitives. Reference tokens by name only.
   ========================================================================== */

/* --- Interaction spine: one focus ring for every interactive element ----- */
/* The ring must clear 3:1 against whatever sits behind it. --color-focus
   (blue-400) only does that on the dark bands; on white and on the mid-blue
   CTA panel it measured 1.4-2.3:1. Default to the deep brand blue and let the
   dark contexts opt back into the bright one. */
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2.5px solid var(--color-primary-deep);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.on-dark :where(a, button, summary, [tabindex]):focus-visible,
.cta :where(a, button, summary, [tabindex]):focus-visible {
  outline-color: var(--color-focus);
}

/* --- Eyebrow ------------------------------------------------------------- */
.eyebrow {
  --eb-color: var(--color-primary-deep);
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
  font-size: var(--text-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--eb-color);
}
@media (max-width: 480px) {
  .eyebrow { letter-spacing: 0.1em; }
}
.eyebrow::before {
  content: "";
  flex: none;
  width: 1.75rem;
  height: 2px;
  background: var(--grad-primary);
  border-radius: 2px;
}
.on-dark .eyebrow { --eb-color: var(--brand-blue-400); }

/* Entrance: the dash draws (like the card accent bar), then the label appears.
   JS-gated so it degrades to visible without JS; reduced-motion shows instantly. */
html.js .eyebrow { color: transparent; transition: color 260ms var(--ease-out) 300ms; }
html.js .eyebrow::before { width: 0; transition: width 380ms var(--ease-out); }
html.js .eyebrow.is-eb { color: var(--eb-color); }
html.js .eyebrow.is-eb::before { width: 1.75rem; }
@media (prefers-reduced-motion: reduce) {
  html.js .eyebrow { color: var(--eb-color); transition: none; }
  html.js .eyebrow::before { width: 1.75rem; transition: none; }
}
/* Centered eyebrow with a rule on BOTH sides. Each rule keeps its full width
   (so the group's layout never shifts) and draws via scaleX — a transform, so no
   reflow. Sequence: left line -> text -> right line, each drawing out from the text. */
.eyebrow--rule::after { content: ""; flex: none; width: 1.75rem; height: 2px; background: var(--grad-primary); border-radius: 2px; }
html.js .eyebrow--rule::before { width: 1.75rem; transform: scaleX(0); transform-origin: left; transition: transform 380ms var(--ease-out); }
html.js .eyebrow--rule::after  { width: 1.75rem; transform: scaleX(0); transform-origin: left;  transition: transform 380ms var(--ease-out) 560ms; }
html.js .eyebrow--rule.is-eb::before,
html.js .eyebrow--rule.is-eb::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  html.js .eyebrow--rule::before,
  html.js .eyebrow--rule::after { transform: none; transition: none; }
}

/* --- Keyword highlight (signature device) -------------------------------- */
/* Blue phrase whose FILL carries the dot motif (from the hero composition),
   with a light wave that sweeps across. Clipped to the text; clone so it wraps
   per-line. Falls back to flat blue where background-clip:text is unsupported. */
.bracket {
  --bk-base: var(--brand-blue-500);
  --bk-dot: rgba(12, 24, 58, 0.34);    /* light bg: subtle darker dots */
  --bk-sheen: rgba(255, 255, 255, 0.4);
  color: var(--bk-base);
  background-color: var(--bk-base);
  /* The wave = light + dots together, moving as one band:
     1) window cover (blue, transparent only in a soft gap) hides everything
        outside the band; 2-3) diamond-lattice dots (half-tile offset); 4) a
        soft sheen band behind the dots, aligned to the same window. */
  background-image:
    linear-gradient(90deg,
      var(--bk-base) 0%, var(--bk-base) 42%,
      transparent 50%,
      var(--bk-base) 58%, var(--bk-base) 100%),
    radial-gradient(circle, var(--bk-dot) 11%, transparent 15%),
    radial-gradient(circle, var(--bk-dot) 11%, transparent 15%),
    linear-gradient(90deg, transparent 37%, var(--bk-sheen) 50%, transparent 63%);
  background-size: 280% 100%, 0.22em 0.22em, 0.22em 0.22em, 280% 100%;
  background-position: 0% 0, 0 0, 0.11em 0.11em, 0% 0;
  background-repeat: no-repeat, repeat, repeat, no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  animation: bracket-wave 3.4s linear infinite;
}
.on-dark .bracket { --bk-base: var(--brand-blue-400); --bk-dot: rgba(236, 249, 255, 0.6); --bk-sheen: rgba(255, 255, 255, 0.42); }
/* window + sheen sweep together, off the left to off the right, then loop */
@keyframes bracket-wave {
  from { background-position: 100% 0, 0 0, 0.11em 0.11em, 100% 0; }
  to   { background-position: 0% 0, 0 0, 0.11em 0.11em, 0% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .bracket {
    animation: none;
    background-image: none;
    -webkit-text-fill-color: var(--bk-base);
  }
}

/* --- Headings ------------------------------------------------------------ */
.h-display {
  font-size: var(--text-display);
  font-weight: var(--fw-extra);
  line-height: 1.1;   /* a hair more than tight so an underlined line clears the glyphs below */
  letter-spacing: var(--tracking-tight);
  overflow-wrap: break-word;
  /* balance, like every other heading (base.css). The old comment said this
     suppressed space-wraps inside the nested .bracket; it no longer does, and
     pretty was leaving one-word widows on the About and Contact heroes. */
  text-wrap: balance;
  min-width: 0;
}
.h-section {
  font-size: var(--text-3xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-tight);
}
.lede {
  font-size: var(--text-lg);
  color: var(--color-ink-soft);
  max-width: var(--measure-lede);
  line-height: var(--lh-base);
}
.on-dark .lede { color: var(--color-on-dark-soft); }

/* --- Spacing grammar: relationships, not per-instance magic numbers ------- */
.eyebrow + h1, .eyebrow + h2, .eyebrow + h3,
.eyebrow + .h-display, .eyebrow + .h-section { margin-top: var(--space-3); }
:is(h1, h2, .h-display, .h-section) + .lede { margin-top: var(--space-4); }
:is(h1, h2, .h-display, .h-section) + .prose,
:is(h1, h2, .h-display, .h-section) + .steps,
:is(h1, h2, .h-display, .h-section) + .triad,
:is(h1, h2, .h-display, .h-section) + .modules { margin-top: var(--space-6); }

/* Honeypot field — off-screen but not display:none (bots fill it) */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* --- Buttons ------------------------------------------------------------- */
.btn {
  --_bg: var(--grad-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.92rem 1.6rem;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.01em;
  line-height: 1;
  border: 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
  text-align: center;
  white-space: nowrap;
  color: var(--brand-white);
  background-image: var(--_bg);
  box-shadow: var(--shadow-blue);
  position: relative;
  isolation: isolate;
  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}
/* filled buttons: a deeper-gradient layer fades in on hover — a real, smooth
   colour shift (not just a lift). Ghost + cta buttons opt out below. */
.btn:not(.btn--ghost)::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  background-image: var(--grad-deep);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
}
.btn:hover, .btn.is-hover { transform: translateY(-2px); box-shadow: 0 24px 48px -16px rgba(49,143,253,0.66); }
.btn:not(.btn--ghost):hover::after, .btn:not(.btn--ghost).is-hover::after { opacity: 1; }
.btn:active, .btn.is-active { transform: translateY(0); box-shadow: var(--shadow-sm); }
.btn[disabled], .btn.is-disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; transform: none; }

.btn--ghost {
  color: var(--color-primary);
  background-image: none;
  background-color: transparent;
  box-shadow: inset 0 0 0 1.5px var(--color-line);
}
.btn--ghost:hover, .btn--ghost.is-hover { box-shadow: inset 0 0 0 1.5px var(--color-primary); transform: translateY(-2px); filter: none; }
.btn--ghost:active { box-shadow: inset 0 0 0 1.5px var(--color-primary); }
.on-dark .btn--ghost { color: var(--color-on-dark); box-shadow: inset 0 0 0 1.5px var(--color-line-dark); }
.on-dark .btn--ghost:hover { box-shadow: inset 0 0 0 1.5px var(--brand-blue-400); }

.btn--lg { padding: 1.05rem 2rem; font-size: var(--text-base); }

/* A button may never exceed the column it sits in.
 *
 * .btn sets white-space: nowrap, so a long label simply grew past its container.
 * That never produced a scrollbar, because html/body carry overflow-x: clip --
 * the end of the label was silently amputated instead. "Schedule a 30-Minute
 * Capacity Preview" measured 420px inside a 335px column at 375px wide, losing
 * the last word and the arrow, and every page uses this button.
 *
 * Order of preference: shrink to fit, then wrap, never truncate. */
.btn { max-width: 100%; }

@media (max-width: 560px) {
  .btn--lg {
    padding: 1rem 1.4rem;
    font-size: var(--text-sm);
    /* Fallback for labels too long to fit even shrunk. Two lines is worse than
       one and far better than a clipped word. */
    white-space: normal;
    text-wrap: balance;
    line-height: 1.25;
  }
}

.btn svg { width: 1.05em; height: 1.05em; flex: none; transition: transform var(--dur) var(--ease-out); }
.btn:hover svg { transform: translateX(3px); }

/* --- Cards --------------------------------------------------------------- */
.card {
  position: relative;
  background: var(--color-bg-card);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
/* Feature cards: inset top accent bar that grows on hover (brand signal) */
.card--feature::before {
  content: "";
  position: absolute;
  top: 0; left: var(--space-8);
  width: 2.25rem; height: 3px;
  background: var(--grad-primary);
  border-radius: 0 0 3px 3px;
  transition: width var(--dur) var(--ease-out);
}
.card--feature:hover::before { width: calc(100% - var(--space-8) * 2); }
.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: color-mix(in srgb, var(--brand-blue-400) 50%, var(--color-line));
}
.on-dark .card {
  background: rgba(255,255,255,0.035);
  border-color: var(--color-line-dark);
  box-shadow: none;
  backdrop-filter: blur(4px);
}
.on-dark .card:hover { border-color: rgba(157,223,255,0.4); transform: translateY(-4px); }

.card__icon {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 0;
  clip-path: var(--clip-notch);
  background: color-mix(in srgb, var(--brand-blue-400) 16%, transparent);
  color: var(--color-primary);
  margin-bottom: var(--space-5);
}
.on-dark .card__icon { background: rgba(157,223,255,0.1); color: var(--brand-blue-400); }
.card__icon svg { width: 1.4rem; height: 1.4rem; }

/* Icon + label on one row. The kicker names the move the card performs
   (LISTEN / EXPLAIN / ORGANIZE), using the site's standard uppercase-label
   idiom — same treatment as .extras__label, .cred__who and .journey__phase. */
.card__mark { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-5); }
.card__mark .card__icon { margin-bottom: 0; }
.card__kicker {
  font-size: var(--text-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--color-primary-deep);
}
.on-dark .card__kicker { color: var(--brand-blue-400); }

.card__num {
  font-size: var(--text-sm);
  font-weight: var(--fw-bold);
  letter-spacing: 0.12em;
  color: var(--brand-blue-400);
  margin-bottom: var(--space-3);
}
.card h3 { font-size: var(--text-xl); font-weight: var(--fw-bold); margin-bottom: var(--space-3); letter-spacing: var(--tracking-tight); overflow-wrap: break-word; }
.card > p { color: var(--color-ink-soft); font-size: var(--text-base); }
.on-dark .card h3 { color: var(--color-on-dark); }
.on-dark .card p  { color: var(--color-on-dark-soft); }

/* --- Clipped image frame (angular mask + dot decor) ---------------------- */
.frame {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  clip-path: var(--clip-arrow);
  aspect-ratio: 4 / 5;
  background-image:
    radial-gradient(rgba(157, 223, 255, 0.16) 1.2px, transparent 1.4px),
    linear-gradient(150deg, var(--navy-700), var(--navy-900));
  background-size: 15px 15px, cover;
}
.frame--portrait { aspect-ratio: 4 / 5; }
.frame > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.frame::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  box-shadow: inset 0 0 0 1px rgba(157, 223, 255, 0.14);
  /* subtle brand-tinted depth over photography */
  background: linear-gradient(180deg, transparent 55%, rgba(6, 15, 42, 0.28) 100%);
}
/* placeholder content label */
.frame__ph {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: var(--space-2);
  text-align: center;
  color: var(--brand-blue-200);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.frame__ph svg { width: 2.4rem; height: 2.4rem; margin-inline: auto; opacity: 0.8; }

/* --- Dot decoration ------------------------------------------------------ */
.halftone {
  position: absolute;
  pointer-events: none;
  background-image: radial-gradient(currentColor 1.4px, transparent 1.5px);
  background-size: 16px 16px;
  color: var(--brand-blue-400);
  opacity: 0.16;
}

/* --- Pill / chip --------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.45rem 0.9rem;
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.04em;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--brand-blue-400) 12%, transparent);
  color: var(--color-primary-deep);
}
.on-dark .chip { background: rgba(157,223,255,0.12); color: var(--brand-blue-200); }

/* --- Accordion (FAQ) ----------------------------------------------------- */
.accordion { display: grid; gap: var(--space-3); }
.acc {
  border: 1px solid var(--color-line-dark);
  border-radius: var(--radius-md);
  background: rgba(255,255,255,0.04);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
}
.acc:hover { border-color: rgba(157,223,255,0.42); background: rgba(255,255,255,0.06); }
.acc.is-open { border-color: rgba(157,223,255,0.34); }
.acc__btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--fw-semibold);
  color: var(--color-on-dark);
  transition: color var(--dur) var(--ease-out);
}
.acc__btn:hover { color: var(--brand-blue-400); }
.acc__btn:focus-visible { outline: 3px solid var(--color-focus); outline-offset: -3px; border-radius: var(--radius-md); }
.acc__ico {
  flex: none;
  display: grid; place-items: center;
  width: 2rem; height: 2rem;
  border-radius: var(--radius-pill);
  background: rgba(157,223,255,0.12);
  color: var(--brand-blue-400);
  transition: transform var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
}
.acc[open] .acc__ico, .acc.is-open .acc__ico { transform: rotate(45deg); background: var(--grad-primary); color: var(--brand-white); }
.acc__panel {
  display: grid;
  grid-template-rows: 0fr;
  /* visibility, not just height: a 0fr row still exposes its text to screen
     readers, which contradicted aria-expanded="false". Unlike [hidden] it is
     animatable, so the panel keeps its motion -- delayed out, instant in. */
  visibility: hidden;
  transition: grid-template-rows var(--dur-slow) var(--ease-in-out),
              visibility 0s linear var(--dur-slow);
}
.acc.is-open .acc__panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--dur-slow) var(--ease-in-out),
              visibility 0s;
}
.acc__panel > div { overflow: hidden; }
.acc__panel p {
  padding: 0 var(--space-6) var(--space-6);
  color: var(--color-on-dark-soft);
  max-width: var(--measure-body);
}

/* --- Reveal animation (one choreography, grouped stagger via --reveal-delay) */
/* Original cascade, untouched — the enhancement path is proven. */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease-out) var(--reveal-delay, 0ms),
              transform var(--dur-slow) var(--ease-out) var(--reveal-delay, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}
/* Safety net (added 2026-07-31): if main.js never runs, html.js is absent and
   nothing may stay hidden. Additive on purpose — scoping the rules above would
   invert specificity against .is-in and hide the page permanently. */
html:not(.js) [data-reveal] { opacity: 1; transform: none; transition: none; }

/* Universal block reveal (2026-08-13). Coverage used to run from 0 to 10 tagged
   elements per section, so some blocks rose in and others simply appeared. This
   extends the SAME choreography above to every block that was never tagged --
   one transition, one stagger, one easing, everywhere.

   Selector-driven rather than tagged in JS on purpose: a JS pass would add the
   attribute after first paint, so above-fold blocks would flash visible and
   then hide. Matching in CSS means they start hidden on the very first frame.

   Three guards:
   :not([data-reveal])        authored intent wins; never doubled up
   :not(:has([data-reveal]))  a wrapper whose children already reveal is left
                              alone, or the child fades inside a fading parent
                              (pricing-catalog's card grid is exactly this)
   :not(.paragrid):not(.halftone)  decorative backdrops, not content

   The guards sit inside :where() so they carry NO specificity. Written bare,
   the four :not()s pushed the hide rule to (0,7,1) against the .is-in rule's
   (0,4,1) -- the block could never un-hide and would have stayed invisible on
   the live site. :where() keeps the hide rule at (0,3,1), safely below it.

   Heroes are excluded for free -- they carry .hero / .page-hero, never
   .section, so their on-load cascade is untouched. */
html.js .section > .container > *:where(:not([data-reveal]):not(:has([data-reveal])):not(.paragrid):not(.halftone)) {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease-out) var(--reveal-delay, 0ms),
              transform var(--dur-slow) var(--ease-out) var(--reveal-delay, 0ms);
}
html.js .section > .container > .is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js .section > .container > * { opacity: 1; transform: none; transition: none; }
}


/* ==========================================================================
   404 — wayfinding, not a dead end
   Lives here (not pages.css) because pages.css doesn't load on is_404().
   ========================================================================== */
/* The 404 is a hero, so it has to behave like one.
 *
 * .page-hero slides up under the floating nav pill with a negative margin, so
 * the gap around the pill shows the dark band. .e404 did not, so it began below
 * the sticky header and the white <body> painted an 84px bar across the top of
 * the page. Same pull-up, same padding compensation as .page-hero.
 *
 * 100svh, not vh: on mobile browsers vh includes the retractable URL bar, which
 * pushes the footer into view on load and then leaves a gap when the bar hides. */
.e404 {
  display: flex;
  align-items: center;
  margin-top: calc(-1 * var(--header-h));
  padding-block: calc(var(--header-h) + var(--section-y)) var(--section-y);
  min-height: 100svh;
}
.e404__grid { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(2rem, 6vw, 5rem); align-items: center; }
.e404__title { margin-top: var(--space-3); }
.e404 .lede { margin-top: var(--space-5); }
.e404__head .btn { margin-top: var(--space-8); }
.e404__nav { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.e404__link { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-5); border: 1px solid var(--color-line-dark); border-radius: var(--radius-lg); background: rgba(255, 255, 255, 0.03); transition: transform var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out); }
.e404__link:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--brand-blue-400) 55%, var(--color-line-dark)); background: rgba(157, 223, 255, 0.07); }
.e404__link-name { display: flex; align-items: center; gap: var(--space-2); font-weight: var(--fw-bold); color: var(--color-on-dark); }
.e404__link-name svg { width: 0.9em; height: 0.9em; flex: none; transition: transform var(--dur) var(--ease-out); }
.e404__link:hover .e404__link-name svg { transform: translateX(3px); }
.e404__link-desc { font-size: var(--text-sm); color: var(--color-on-dark-soft); }
@media (max-width: 860px) {
  /* Stacked, a forced full viewport strands the copy at the top with dead
     space beneath it. Let the content set the height; the pull-up and its
     padding stay, so the band still runs behind the nav. */
  .e404 { min-height: 0; }
  .e404__grid { grid-template-columns: 1fr; gap: var(--space-10); }
}
@media (max-width: 460px) {
  .e404__nav { grid-template-columns: 1fr; }
}

/* --- Price block ---------------------------------------------------------
   Hallmark · component: price · genre: editorial · theme: project tokens
   states: n/a (static text, not interactive)
   contrast: pass (46-50)

   ONE anatomy for every price on the site:
     1. what you are buying   2. how much   3. the one other way to buy it
   Context sets ONLY --price-size and --price-align. Previously this existed as
   three separate implementations (.spotlight__amount, .mod-foot__amount,
   .program-step__price), which is exactly why they drifted apart. */
.price {
  display: grid;
  gap: var(--space-2);
  justify-items: var(--price-align, start);
  text-align: var(--price-align, start);
}
/* names what the number buys; the site's established label idiom */
.price .price__what {
  font-size: var(--text-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-primary-deep);
}
.price__amount {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35rem;
  justify-content: var(--price-align, start);
}
/* lowercase on purpose: an uppercase "FROM" under an uppercase label reads as
   two competing kickers rather than a prefix */
.price .price__from { font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--color-ink-faint); }
.price__amount strong {
  font-size: var(--price-size, var(--text-2xl));
  font-weight: var(--fw-extra);
  line-height: 1;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
}
.price .price__unit { font-size: var(--text-sm); color: var(--color-ink-faint); }
.price .price__alt { font-size: var(--text-xs); line-height: 1.45; color: var(--color-ink-faint); }

.on-dark .price .price__what { color: var(--brand-blue-400); }
.on-dark .price__amount strong { color: var(--color-on-dark); }
.on-dark .price__from,
.on-dark .price__unit,
.on-dark .price .price__alt { color: var(--color-on-dark-soft); }

/* --- Mantra --------------------------------------------------------------
   The site thesis. It has now been a bordered callout, a notched slab and a
   parallelogram panel, and every one of those was decoration applied to a
   sentence that did not need a container. It is a statement, so it is set as
   one: a hairline, then the words. Structure from rules and space, not fills. */
/* Carries the site's thesis, so it is marked with the site's own signal: the
   same short gradient bar that leads every feature card, and statement-scale
   text. A hairline plus small grey type made the most important sentence on
   the site read like a footnote. No box -- every boxed version competed with
   the card family. */
.mantra {
  position: relative;
  margin-top: var(--space-8);
  padding-left: var(--space-5);
  max-width: var(--measure-lede);
  font-size: var(--text-lg);
  line-height: 1.5;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink-soft);
}
/* Left, not top: the card's bar sits ON the card's edge, which is what makes
   it read as a mark. There is no edge here, so a floating bar above the text
   would be arbitrary. Down the left it does real typographic work -- it sets
   the statement apart -- using the same 3px gradient the cards use.
   Inset to the optical text block: a bar run to the full line box reads too
   tall, because line-height adds space above the caps and below the baseline. */
.mantra::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.22em;
  bottom: 0.22em;
  width: 3px;
  border-radius: 3px;
  background: var(--grad-primary);
}
.mantra b { font-weight: var(--fw-bold); color: var(--color-ink); }
.on-dark .mantra { color: var(--color-on-dark-soft); }
.on-dark .mantra b { color: var(--color-on-dark); }
/* Spacing grammar: copy that resumes after the thesis (About's "why it matters"
   closes on one after it). Smaller than the gap that sets the mantra apart. */
.mantra + .lede { margin-top: var(--space-6); }

/* --- Claim -------------------------------------------------------------
   A section's closing statement: who is accountable for what the section just
   showed. Rule + larger ink text so it reads as a statement, not the muted
   footnote treatment of .mods-note. */
.claim {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-line);
  max-width: var(--measure-body);
  font-size: var(--text-lg);
  line-height: 1.5;
  color: var(--color-ink-soft);
}
.claim b { font-weight: var(--fw-bold); color: var(--color-ink); }
.on-dark .claim { border-top-color: var(--color-line-dark); color: var(--color-on-dark-soft); }
.on-dark .claim b { color: var(--color-on-dark); }

/* --- Hero second paragraph + pricing scope notice ------------------------ */
/* Chris's hero copy is two paragraphs: the positioning statement, then a
   narrower note about who the first program is for. The note steps down in size
   and weight so the hero still reads as one statement with a qualifier, rather
   than two competing paragraphs. */
.lede--note {
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  max-width: 48ch;
  color: var(--color-on-dark-soft);
}

/* Scope notice above the pricing stages. Same pale band as .form-notice and no
   left rule, so the two callouts on the site read as one component family. */
.scope-note {
  margin-bottom: var(--space-10);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-md);
  background: var(--color-bg-soft);
}
.scope-note__head {
  font-size: var(--text-base);
  font-weight: var(--fw-semibold);
  color: var(--color-ink);
  margin-bottom: var(--space-2);
}
.scope-note p {
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--color-ink-soft);
  max-width: var(--measure-body);
}
