/* ==========================================================================
   CT Innovates — Inner pages (shared hero + page layouts + contact form)
   Reuses the homepage component system; adds inner-page-only patterns.
   ========================================================================== */

/* ---------------- Inner-page hero --------------------------------------- */
.page-hero {
  position: relative;
  background: var(--grad-hero);
  color: var(--color-on-dark);
  /* slide up beneath the floating nav so the gap above the pill shows the hero */
  margin-top: calc(-1 * var(--header-h));
  padding-block: calc(var(--header-h) + clamp(3rem, 2rem + 6vw, 6rem)) clamp(3.5rem, 2.5rem + 7vw, 7rem);
  overflow: clip;
}
.page-hero__inner { position: relative; z-index: 1; max-width: 50rem; }
/* a section that declares an image gets the homepage hero's two-column shape */
.page-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 4vw, 4.5rem);
  align-items: stretch;
}
.page-hero__grid > * { min-width: 0; }
.page-hero__grid .hero__media { min-height: 320px; }
/* the namecard chip, anchored like the homepage founders composite */
.page-hero__grid .cred__namecard { bottom: 10%; left: -4%; }
.page-hero__actions { margin-top: var(--space-8); display: flex; flex-wrap: wrap; gap: var(--space-4); }
@media (max-width: 880px) {
  .page-hero__grid { grid-template-columns: 1fr; }
  .page-hero__grid .cred__namecard { left: 5%; right: auto; bottom: 6%; }
}
.page-hero h1 { font-size: var(--text-3xl); margin-block: var(--space-5) var(--space-5); }
.page-hero .lede { max-width: var(--measure-lede); }
.page-hero__crumbs {
  display: flex; gap: var(--space-2); align-items: center;
  font-size: var(--text-xs); color: var(--color-on-dark-soft);
  margin-bottom: var(--space-2);
}
.page-hero__crumbs a:hover { color: var(--brand-blue-400); }

/* ---------------- Generic prose / page body ---------------------------- */
.page-body { padding-block: var(--section-y); }
.prose { max-width: var(--measure-body); }
/* Centres the column without centring the sentences. Used by about-story,
   which carries no image, so the measure has to hold the section on its own. */
.prose--center { margin-inline: auto; }
.prose > * + * { margin-top: var(--space-5); }
.prose h2 { font-size: var(--text-2xl); margin-top: var(--space-12); letter-spacing: var(--tracking-tight); }
.prose h3 { font-size: var(--text-lg); margin-top: var(--space-8); }
.prose p, .prose li { color: var(--color-ink-soft); }
.prose ul { display: grid; gap: var(--space-3); }
.prose ul li { display: flex; gap: var(--space-3); }
.prose ul svg { width: 1.1em; height: 1.1em; color: var(--color-primary); flex: none; margin-top: 0.3em; }

/* ---------------- Two-column split (about story / approach) ------------- */
.split {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem); align-items: stretch;   /* media grows to the copy column's height */
}
.split--media-first .split__media { order: -1; }
.split__media { position: relative; }
.split .frame { aspect-ratio: 4 / 5; box-shadow: var(--shadow-lg); }

/* ---------------- Civic-context band (one honest fact, not a KPI grab-bag) */
.context-band {
  display: grid; grid-template-columns: auto 1fr;
  gap: clamp(1.75rem, 5vw, 4.5rem); align-items: center;
  padding: clamp(2rem, 4vw, 3.25rem) clamp(1.75rem, 4vw, 3.5rem);
  border-radius: var(--radius-lg);
  background: var(--grad-dark); color: var(--color-on-dark);
  position: relative; overflow: clip;
}
.context-band::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(rgba(157, 223, 255, 0.06) 1px, transparent 1.6px);
  background-size: 22px 22px;
}
.context-band__stat { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--space-3); }
.context-band__stat b { font-size: var(--mark-lg); font-weight: var(--fw-extra); line-height: 0.85; letter-spacing: var(--tracking-tight); color: var(--brand-blue-400); }
.context-band__stat span { font-size: var(--text-sm); line-height: 1.4; color: var(--color-on-dark-soft); max-width: 20ch; }
.context-band__body { position: relative; z-index: 1; }
.context-band__note { font-size: var(--text-lg); line-height: 1.55; color: var(--color-on-dark); max-width: 44ch; }
.context-band__source { margin-top: var(--space-3); font-size: var(--text-xs); letter-spacing: 0.01em; color: var(--color-on-dark-soft); }
.context-band__source em { font-style: italic; }
.context-band__source a { color: inherit; text-decoration: none; border-bottom: 1px solid rgba(157, 223, 255, 0.28); transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out); }
.context-band__source a:hover { color: var(--brand-blue-200); border-bottom-color: var(--brand-blue-200); }
/* stacked cards: same band design, one per stat, with gaps */
.context-stack { display: grid; gap: clamp(1rem, 2.5vw, 1.5rem); }
/* standardized stat column so all three notes start on the same line, even
   though 40% / 70% / 18% render at different widths (same idea as the homepage
   program ledger's fixed mark column). Desktop only; mobile stays stacked. */
@media (min-width: 881px) {
  .context-stack .context-band { grid-template-columns: 15rem 1fr; }
  .context-stack .context-band__stat span { max-width: none; }
}

/* ---- Why it matters: two-column with the hero's parallelogram composite,
   standardized like the Story/cred composites: media stretches to the copy
   column's height (no fixed aspect-ratio on desktop), and the photo + offset
   panel are ONE frame — both calc(100% - peek) anchored to opposite corners, so
   their union fills the stage with an EQUAL fixed peek on the two exposed sides. */
.why__grid { display: grid; grid-template-columns: 1fr 0.82fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: stretch; }
.why__grid > * { min-width: 0; }
.why__media { position: relative; isolation: isolate; height: 100%; }
.why__stage { position: relative; height: 100%; --peek: 1.75rem; }
.why__stage .frame--main,
.why__stage .frame--ghost { position: absolute; width: calc(100% - var(--peek)); height: calc(100% - var(--peek)); aspect-ratio: auto; }
.why__stage .frame--main { z-index: 2; top: 0; left: 0; clip-path: var(--clip-parallelogram); border-radius: 0; filter: drop-shadow(0 6px 10px rgba(4, 10, 30, 0.4)) drop-shadow(0 20px 30px rgba(4, 10, 30, 0.5)); }
.why__stage .frame--main::after { box-shadow: none; }
.why__stage .frame--ghost { inset: auto; bottom: 0; right: 0; transform: none; }
/* cursor-pan inside the mask, same as the hero (JS sets --img-*); slightly
   zoomed so the pan has slack, slow settle back on leave. */
.why__stage .frame--main > img {
  transform: scale(1.12) translate(var(--img-x, 0%), var(--img-y, 0%));
  transition: transform 200ms var(--ease-out);
  will-change: transform;
}
.why__stage .frame--main.is-returning > img {
  transition: transform 650ms cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .why__stage .frame--main > img { transition: none; }
}
/* Entrance: same choreographed assembly as the homepage composites — photo lands,
   then the panel slides out from behind it. Scroll-triggered via .is-in. */
@media (prefers-reduced-motion: no-preference) {
  html.js .why__media[data-reveal] { opacity: 1; transform: none; }
  html.js .why__media[data-reveal] .frame--main,
  html.js .why__media[data-reveal] .frame--ghost { opacity: 0; }
  html.js .why__media.is-in .frame--main { animation: hero-rise 0.7s var(--ease-out) both; animation-delay: 0.05s; }
  html.js .why__media.is-in .frame--ghost { animation: hero-panel 0.66s var(--ease-out) both; animation-delay: 0.24s; }
}
@media (max-width: 880px) {
  /* stacked: no copy column to stretch against, so give the stage its own ratio */
  .why__grid { grid-template-columns: 1fr; gap: clamp(2rem, 6vw, 3rem); }
  .why__media { max-width: none; width: 100%; height: auto; }
  .why__stage { aspect-ratio: 3 / 2; height: auto; }
}

/* ---------------- Module table (services) ------------------------------ */
.section--flush-top { padding-top: 0; }
/* Photo + offset back-plane, standardized exactly like the hero/cred composites:
   both layers are calc(100% - peek) anchored to opposite corners, so the panel
   shows an EQUAL fixed peek on the two exposed sides (right + bottom) and their
   union precisely fills the frame — no uneven % offset, no overflow. The stage
   has no fixed aspect-ratio: it fills the stretched grid row, so the composite
   grows to the copy column's height. Notch clip (cut bottom-right corner) reads
   cleanest against a bottom-right offset — the arrow pennant's centre point
   fought the peek. Ghost shares the mask (ghost == clip); drop-shadow (not
   box-shadow, which the clip-path would eat) grounds the photo on the light page. */
.split__media { height: 100%; --peek: 1.75rem; }
.split__media .frame,
.split__media .frame--ghost {
  position: absolute;
  width: calc(100% - var(--peek));
  height: calc(100% - var(--peek));
  aspect-ratio: auto;
}
.split__media .frame {
  z-index: 1; top: 0; left: 0;
  box-shadow: none;
  border-radius: 0;                 /* sharp corners to match the notch clip */
  clip-path: var(--clip-notch);
  filter: drop-shadow(0 6px 10px rgba(4, 10, 30, 0.16)) drop-shadow(0 18px 30px rgba(4, 10, 30, 0.2));
}
.split__media .frame--ghost {
  z-index: 0; inset: auto; bottom: 0; right: 0;
  transform: none; clip-path: var(--clip-notch);
}
/* cursor-pan inside the mask (same as the hero): always slightly zoomed so the
   pan has slack on both axes; JS sets --img-*; slow settle back on leave. */
.split__media .frame > img {
  transform: scale(1.12) translate(var(--img-x, 0%), var(--img-y, 0%));
  transition: transform 200ms var(--ease-out);
  will-change: transform;
}
.split__media .frame.is-returning > img {
  transition: transform 650ms cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .split__media .frame > img { transition: none; }
}
/* Entrance: the same choreographed assembly as the homepage composites — the
   photo lands, then the panel slides out from behind it. Scroll-triggered via the
   reveal observer's .is-in (this composite is below the fold). Reuses the hero
   keyframes (defined in home.css, which loads on every page). */
@media (prefers-reduced-motion: no-preference) {
  /* the container is only the observer hook — it must not fade/rise as a block */
  html.js .split__media[data-reveal] { opacity: 1; transform: none; }
  html.js .split__media[data-reveal] .frame,
  html.js .split__media[data-reveal] .frame--ghost { opacity: 0; }
  html.js .split__media.is-in .frame { animation: hero-rise 0.7s var(--ease-out) both; animation-delay: 0.05s; }
  html.js .split__media.is-in .frame--ghost { animation: hero-panel 0.66s var(--ease-out) both; animation-delay: 0.24s; }
}


/* ---------------- Contact form ----------------------------------------- */
.contact__grid { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.contact__aside .h-section { margin-bottom: var(--space-8); }
.contact__aside .cred__item { margin-bottom: var(--space-6); }
.contact__aside .mailcard { margin-top: var(--space-8); }
.contact__card {
  background: var(--color-bg-card);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: clamp(1.5rem, 3vw, 2.5rem);
}
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); align-items: start; }
.field { display: flex; flex-direction: column; gap: var(--space-2); }
.field--full { grid-column: 1 / -1; }
.field label { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--color-ink); min-height: 1.25em; }

/* custom select chevron (replaces the native OS arrow) */
.field select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.75rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23475069' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 1.05rem;
  cursor: pointer;
}
.field select:invalid { color: var(--color-ink-faint); }
.field .req { color: var(--color-primary); }
.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.8rem 1rem;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-ink);
  transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.field textarea { resize: vertical; min-height: 7rem; }
.field input::placeholder, .field textarea::placeholder { color: var(--color-ink-faint); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--color-ink-faint); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-blue-400) 30%, transparent);
}
.field--check { flex-direction: row; align-items: flex-start; gap: var(--space-3); }
.field--check input { width: 1.15rem; height: 1.15rem; flex: none; margin-top: 0.15rem; accent-color: var(--color-primary); }
.field--check label { font-weight: var(--fw-regular); color: var(--color-ink-soft); }
.form-actions { margin-top: var(--space-6); display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; }
.form-note { font-size: var(--text-xs); color: var(--color-ink-faint); }
/* Helper text under a control. Darker than the note beside the button, because
   this one carries an instruction rather than a reassurance. */
.form-note--field { color: var(--color-ink-soft); margin-top: calc(-1 * var(--space-1)); }

/* ---------------- Responsive ------------------------------------------- */
@media (max-width: 880px) {
  .split, .contact__grid { grid-template-columns: 1fr; }
  /* Stacked: no copy column to stretch against, so the stage carries its own
     ratio. It fills the column (the old 460px cap left dead space at tablet). */
  .split__media { aspect-ratio: 3 / 2; height: auto; max-width: none; width: 100%; }
  .context-band { grid-template-columns: 1fr; gap: var(--space-5); }
}
@media (max-width: 560px) {
  .form-grid { grid-template-columns: 1fr; }
  /* narrow enough now that the portrait crop reads better than the landscape one */
  .why__stage, .split__media { aspect-ratio: 4 / 5; }
}

/* ==========================================================================
   Pricing page
   Hallmark · page: pricing · system: CT Innovates (locked tokens)
   pre-emit critique: P5 H4 E4 S5 R4 V4
   A sequence (Step 1 -> Step 2) + an a-la-carte menu + a glance table.
   Real rates only; not a good/better/best tier ladder.
   ========================================================================== */

/* ---- the catalog: the homepage program ledger, extended ----------------- */
/* One connected panel (see .program in home.css): row 01 is the foundation,
   then three rows share the big "02" with Option 1/2/3 labels, so the menu
   reads as one step with three doors, never a ladder. */
/* (.program-step__n--word lives in home.css so the front page gets it too) */
/* the three options sit side by side under the START row, inside the same
   connected panel: hairline top from START, hairlines between columns */
.program-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--color-line); }
.program-option { display: flex; flex-direction: column; padding: clamp(1.75rem, 3vw, 2.5rem) clamp(1.5rem, 3vw, 2rem); }
.program-option + .program-option { border-left: 1px solid var(--color-line); }
.program-option .program-step__n--word { display: block; margin-bottom: var(--space-4); }
.program-option__name { margin-top: var(--space-1); font-size: var(--text-xl); font-weight: var(--fw-bold); letter-spacing: var(--tracking-tight); color: var(--color-ink); }
/* meta pins to the bottom so all three feet align */
.program-option__meta { margin-top: auto; padding-top: var(--space-5); border-top: 1px solid var(--color-line); display: grid; gap: var(--space-3); }
.program-option .program-step__tags { margin-bottom: var(--space-6); }
.program-option .program-step__price { white-space: normal; flex-wrap: wrap; }
.program-option .program-step__format { align-items: flex-start; }
/* squeeze zone (881-1100px): three columns get narrow, so the long module
   names step down a size instead of wrapping to four uneven lines */
@media (max-width: 1100px) and (min-width: 881px) {
  .program-option__name { font-size: var(--text-lg); }
}
.program-option .program-step__format svg { margin-top: 0.2em; }
@media (max-width: 880px) {
  .program-options { grid-template-columns: 1fr; }
  .program-option + .program-option { border-left: 0; border-top: 1px solid var(--color-line); }
}

/* ---- pricing at a glance: a real table -------------------------------- */
.price-table { overflow-x: auto; border: 1px solid var(--color-line); border-radius: var(--radius-lg); background: var(--color-bg-card); box-shadow: var(--shadow-sm); }
.price-table table { width: 100%; border-collapse: collapse; min-width: 480px; }
.price-table th, .price-table td { padding: var(--space-4) var(--space-5); text-align: left; }
.price-table thead th { font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-ink-faint); border-bottom: 1px solid var(--color-line); }
.price-table thead th span { font-weight: var(--fw-regular); letter-spacing: 0.04em; }
/* second line in a rate cell: the self-paced figure under the live one */
.price-table td span:not(.na) { display: block; margin-top: 0.15rem; font-size: var(--text-xs); font-weight: var(--fw-regular); color: var(--color-ink-faint); }
.on-dark .price-table td span:not(.na) { color: var(--color-on-dark-soft); }
.price-table tbody tr { border-top: 1px solid var(--color-line); transition: background var(--dur) var(--ease-out); }
.price-table tbody tr:hover { background: var(--color-bg-soft); }
/* group label rows (Core path / Add-ons) give the flat rate list real structure */
.price-table__group th { padding-top: var(--space-3); padding-bottom: var(--space-3); font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.12em; color: var(--color-primary-deep); background: var(--color-bg-soft); }
.price-table tbody tr.price-table__group:hover { background: var(--color-bg-soft); }
.price-table tbody th[scope="row"] { font-size: var(--text-base); font-weight: var(--fw-semibold); color: var(--color-ink); }
.price-table tbody th[scope="row"] span { display: block; margin-top: 2px; font-size: var(--text-xs); font-weight: var(--fw-regular); color: var(--color-ink-faint); }
.price-table tbody td { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--color-ink); white-space: nowrap; }
.price-table tbody td span { font-weight: var(--fw-regular); color: var(--color-ink-faint); }
/* "not offered at this rate" mark — a muted rule, so an empty cell reads as an
   intentional N/A rather than missing data */
.price-table .na { display: inline-flex; align-items: center; color: var(--color-ink-faint); }
.price-table .na svg { width: 1.4rem; height: auto; }
/* Hallmark · variant: price-table--start · system: CT Innovates (locked tokens)
   pre-emit critique: P5 H4 E5 S5 R5 V4
   The routing table, on the same chassis as the rate card so it inherits the
   hairlines, the hover, and the 600px stacked-card collapse. Two differences,
   both because the right-hand cell holds a phrase rather than a figure: it may
   wrap (the base cell is nowrap, for rates), and it carries the deep-blue of a
   destination while the situation on the left stays quiet body text. */
/* No max-width: a 72rem cap left this 48px short of the container while every
   other block on the page runs to it, and the table's own frame is faint enough
   that the shortfall reads as a mistake rather than as a measure. */
.price-table--start thead th:first-child { width: 56%; }
.price-table--start tbody th[scope="row"] { font-size: var(--text-base); font-weight: var(--fw-regular); color: var(--color-ink-soft); }
.price-table--start tbody td { white-space: normal; color: var(--color-primary-deep); }
.on-dark .price-table--start tbody th[scope="row"] { color: var(--color-on-dark-soft); }
.on-dark .price-table--start tbody td { color: var(--brand-blue-400); }
/* stacked view: the repeated column name is a label, so it stays on one line
   and the long answer wraps instead */
@media (max-width: 600px) {
  .price-table--start tbody td::before { white-space: nowrap; }
}

.price-note { margin-top: var(--space-6); max-width: var(--measure-body); font-size: var(--text-sm); line-height: 1.6; color: var(--color-ink-soft); }
.price-note a { color: var(--color-primary-deep); font-weight: var(--fw-semibold); }
.price-note a:hover { text-decoration: underline; }

/* ---- pricing: readiness spotlight + three module cards ------------------ */
/* One idea per view: the entry product gets a full-width spotlight (it is the
   only thing anyone buys first), the modules are three small equal cards, and
   the platform lives in its own dark band so it never reads as a fourth module. */
.spotlight {
  position: relative;
  display: grid; grid-template-columns: 1.5fr 1fr; gap: clamp(1.5rem, 3vw, 3rem);
  /* start, not end: the two spotlights differ a lot in body height, and
     bottom-aligning stranded the taller card's price in dead space. */
  align-items: start;
  padding: var(--space-8);
  background: var(--color-bg-card);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
/* One accent, identical on all five pricing cards: same offset, same length,
   same at every viewport. Deliberately not responsive. */
.spotlight::before {
  content: ""; position: absolute; top: 0; left: var(--space-8);
  width: 3.5rem; height: 3px;
  background: var(--grad-primary);
  border-radius: 0 0 3px 3px;
}
.spotlight__body h3 { font-size: var(--text-2xl); font-weight: var(--fw-bold); line-height: 1.1; letter-spacing: var(--tracking-tight); color: var(--color-ink); }
.spotlight__body p { margin-top: var(--space-3); font-size: var(--text-sm); line-height: 1.55; color: var(--color-ink-soft); max-width: var(--measure-lede); }
.spotlight__body .program-step__tags { margin-top: var(--space-4); }
/* price block mirrors the homepage ledger: one baseline row, no odd wrapping,
   with the sub-rate and the format line stacked beneath it */
/* layout only; the price anatomy itself is the shared .price component */
.spotlight__price { --price-align: end; --price-size: clamp(2rem, 1.5rem + 1.6vw, 2.75rem); justify-self: end; align-self: end; }

/* Hallmark · component: price-formats · system: CT Innovates (locked tokens)
   pre-emit critique: P5 H4 E4 S5 R5 V4

   ONE product, sold three ways. Deliberately NOT a tier ladder: no cards, no
   emphasis on any row, no per-row action — three identical hairline rows, so
   the eye reads "which format" rather than "which plan". It borrows the .price
   anatomy's own language (uppercase deep-blue label, tabular extrabold figure,
   faint unit) at a smaller --price-size, because three display-sized numbers
   stacked would out-shout the product name they belong to.

   Layout: label left, figure right, unit tucked under the figure. That keeps
   the widest row ("Private DTC cohort" / "$1,000 / up to 12 participants")
   inside the spotlight's narrow right column without a breakpoint hack; below
   560px the row stacks so nothing can be squeezed. */
/* .spotlight wins the specificity race against the 880px rule that pulls the
   single-price block back to justify-self:start — this list is a full-width
   ledger at every size, or its hairlines stop short of the card edge. */
.spotlight .spotlight__price--formats { --price-size: var(--text-xl); justify-self: stretch; min-width: 0; }
.price-formats { display: grid; list-style: none; margin: 0; padding: 0; }
.price-formats li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: var(--space-4);
  padding: var(--space-3) 0;
}
.price-formats li:first-child { padding-top: 0; }
.price-formats li:last-child { padding-bottom: 0; }
.price-formats li + li { border-top: 1px solid var(--color-line); }
.price-formats__label {
  font-size: var(--text-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  line-height: 1.35;
  color: var(--color-primary-deep);
}
.price-formats__rate { text-align: end; }
.price-formats__rate strong {
  display: block;
  font-size: var(--price-size, var(--text-xl));
  font-weight: var(--fw-extra);
  line-height: 1;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
}
.price-formats__unit { display: block; margin-top: var(--space-1); font-size: var(--text-xs); line-height: 1.35; color: var(--color-ink-faint); }
.on-dark .price-formats li + li { border-top-color: var(--color-line-dark); }
.on-dark .price-formats__label { color: var(--brand-blue-400); }
.on-dark .price-formats__rate strong { color: var(--color-on-dark); }
.on-dark .price-formats__unit { color: var(--color-on-dark-soft); }
@media (max-width: 560px) {
  .price-formats li { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-1); }
  .price-formats__rate { text-align: start; }
}

/* Hallmark · component: preview-link · system: CT Innovates (locked tokens)
   pre-emit critique: P5 H5 E4 S5 R5 V4
   The site's inline arrow-link idiom (.extras__link, .mailcard__addr, .price-note a):
   deep-blue semibold text with a 1em arrow that slides 3px on hover. Used where a
   section hands off to something you can go and look at rather than buy, so it sits
   on its own line under the card instead of being buried in the body copy. */
.preview-link { margin-top: var(--space-4); font-size: var(--text-sm); }
.preview-link a { display: inline-flex; align-items: center; gap: var(--space-2); font-weight: var(--fw-semibold); color: var(--color-primary-deep); }
.preview-link a svg { width: 1em; height: 1em; flex: none; transition: transform var(--dur) var(--ease-out); }
.preview-link a:hover { text-decoration: underline; }
.preview-link a:hover svg { transform: translateX(3px); }
.on-dark .preview-link a { color: var(--brand-blue-400); }

/* ---- email card: the site's standard box + top accent, entirely clickable -- */
.mailcard {
  position: relative; display: block; overflow: hidden;
  padding: var(--space-5) var(--space-6);
  background: var(--color-bg-card);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
/* same inset top accent as .card--feature, grown on hover */
.mailcard::before {
  content: ""; position: absolute; top: 0; left: var(--space-6);
  width: 2.25rem; height: 3px;
  background: var(--grad-primary);
  border-radius: 0 0 3px 3px;
  transition: width var(--dur) var(--ease-out);
}
.mailcard:hover { box-shadow: var(--shadow-md); border-color: color-mix(in srgb, var(--brand-blue-400) 50%, var(--color-line)); }
.mailcard:hover::before { width: calc(100% - var(--space-6) * 2); }
.mailcard__label { display: block; font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.12em; color: var(--color-primary-deep); }
.mailcard__addr { display: inline-flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); font-size: var(--text-base); font-weight: var(--fw-bold); letter-spacing: var(--tracking-tight); color: var(--color-primary-deep); }
.mailcard__addr svg { width: 1em; height: 1em; flex: none; transition: transform var(--dur) var(--ease-out); }
.mailcard:hover .mailcard__addr svg { transform: translateX(3px); }

/* the extras strip opens the soft section, so its own top margin would stack
   on the section padding and make the block look top-heavy */
.section > .container > .extras:first-child { margin-top: 0; }
/* the "Prices" label owns the gap; the toggle sits straight under it */
.rates-label + .rates { margin-top: 0; }
/* the as-of line: same job as .price-note, but it belongs to the label above
   the toggle rather than to the table inside it */
.rates-note { margin-top: calc(-1 * var(--space-2)); margin-bottom: var(--space-4); max-width: var(--measure-body); font-size: var(--text-sm); line-height: 1.6; color: var(--color-ink-soft); }
.rates-note + .rates { margin-top: 0; }
.on-dark .rates-note { color: var(--color-on-dark-soft); }

/* ---- also-available strip: door-openers as a highlighted card strip ------ */
.extras { margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.extras__head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: var(--space-3) var(--space-4); margin-bottom: var(--space-4); }
.extras__label { display: block; font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.14em; color: var(--color-primary-deep); }
/* label + the one line that says what the strip is for; the "point me at the
   right one" link stays on the opposite edge, aligned to the label's baseline */
.extras__intro { min-width: 0; }
.extras__blurb { margin-top: var(--space-2); font-size: var(--text-sm); line-height: 1.5; color: var(--color-ink-soft); }
.on-dark .extras__blurb { color: var(--color-on-dark-soft); }
.extras__link { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--color-primary-deep); }
.extras__link svg { width: 1em; height: 1em; transition: transform var(--dur) var(--ease-out); }
.extras__link:hover { text-decoration: underline; }
.extras__link:hover svg { transform: translateX(3px); }
.extras__list {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); list-style: none;
  background: var(--color-bg-card);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
/* Hallmark - component: extras item. Two rows, so the name and its meta never
   compete for horizontal space (the old single flex row split "$1,500 /" from
   "yr"). Icon anchors the name; meta hangs beneath, aligned to the name. */
.extras__list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-content: start;
  column-gap: var(--space-3);
  padding: var(--space-5);
}
.extras__ico  { grid-area: 1 / 1; display: flex; }
.extras__name { grid-area: 1 / 2; font-size: var(--text-sm); font-weight: var(--fw-semibold); line-height: 1.3; color: var(--color-ink); }
.extras__meta { grid-area: 2 / 2; margin-top: var(--space-2); font-size: var(--text-xs); line-height: 1.4; color: var(--color-ink-faint); }
.extras__list li + li { border-left: 1px solid var(--color-line); }
.extras__list svg { width: 1.2rem; height: 1.2rem; flex: none; color: var(--color-primary); }
@media (max-width: 980px) {
  .extras__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .extras__list li { border-left: 0; }
  .extras__list li:nth-child(even) { border-left: 1px solid var(--color-line); }
  .extras__list li:nth-child(n+3) { border-top: 1px solid var(--color-line); }
}
@media (max-width: 520px) {
  .extras__list { grid-template-columns: 1fr; }
  .extras__list li:nth-child(even) { border-left: 0; }
  .extras__list li + li { border-top: 1px solid var(--color-line); }
}

/* ---- the dark closer: prices label, on-dark notes, keep-strip spacing ---- */
.rates-label { margin: clamp(2.5rem, 5vw, 3.5rem) 0 var(--space-4); font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.14em; color: var(--color-primary-deep); }
.on-dark .rates-label { color: var(--brand-blue-400); }
.on-dark .price-note { color: var(--color-on-dark-soft); }
.on-dark .price-note a { color: var(--brand-blue-400); }
.price-note + .keep-strip { margin-top: var(--section-y); }

/* on the dark closer the rate card goes glass, like the contact FAQ accordion:
   translucent card, dark hairlines, on-dark text — no white slab on navy */
.on-dark .rates { background: rgba(255, 255, 255, 0.04); border-color: var(--color-line-dark); box-shadow: none; -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.on-dark .rates summary { color: var(--color-on-dark); }
.on-dark .rates summary:hover { color: var(--brand-blue-200); }
.on-dark .rates summary svg { color: var(--brand-blue-400); }
.on-dark .price-table--flat { border-top-color: var(--color-line-dark); }
.on-dark .price-table { background: transparent; }
.on-dark .price-table thead th { color: var(--color-on-dark-soft); border-bottom-color: var(--color-line-dark); }
.on-dark .price-table tbody tr { border-top-color: var(--color-line-dark); }
.on-dark .price-table tbody tr:hover { background: rgba(255, 255, 255, 0.04); }
.on-dark .price-table__group th { color: var(--brand-blue-400); background: rgba(157, 223, 255, 0.06); }
.on-dark .price-table tbody tr.price-table__group:hover { background: rgba(157, 223, 255, 0.06); }
.on-dark .price-table tbody th[scope="row"] { color: var(--color-on-dark); }
.on-dark .price-table tbody th[scope="row"] span { color: var(--color-on-dark-soft); }
.on-dark .price-table tbody td { color: var(--color-on-dark); }
.on-dark .price-table tbody td span { color: var(--color-on-dark-soft); }

/* stage markers — the Learn / Apply / Operationalize spine */
.stage { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-3); margin: clamp(2.5rem, 5vw, 4rem) 0 var(--space-6); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.14em; color: var(--color-ink-faint); }
/* the rule carries each marker across the page, so 01/02/03 read as one
   continuous document rather than three orphaned captions */
.stage::after { content: ""; flex: 1; align-self: center; height: 1px; min-width: 3rem; background: var(--color-line); }
.stage strong { font-weight: var(--fw-bold); color: var(--color-primary-deep); }
.stage span:not(.stage__n) { text-transform: none; letter-spacing: 0.01em; }
.stage__n { font-size: var(--text-2xl); font-weight: var(--fw-extra); line-height: 1; letter-spacing: var(--tracking-tight); background: var(--grad-primary); -webkit-background-clip: text; background-clip: text; color: transparent; font-variant-numeric: tabular-nums; }
.stage--head { margin-top: 0; }
.pricing-triad .card { display: flex; flex-direction: column; }
/* The module cards sit between the two spotlights, so they read as the same family:
   no icon, no lift on hover, and the accent bar fixed at the spotlight's 3.5rem
   instead of the feature-card 2.25rem that grows to full width. */
.pricing-triad .card--feature::before,
.pricing-triad .card--feature:hover::before { width: 3.5rem; }
.pricing-triad .card:hover { transform: none; box-shadow: var(--shadow-sm); border-color: var(--color-line); }
.mod-tags { margin-top: var(--space-4); margin-bottom: var(--space-5); }
/* The courses ARE the product, so they lead with a real labelled list rather than
   the pill treatment, which reads as metadata. The pills follow, carrying what the
   module produces. */
.pricing-triad .card .mod-courses__label { margin-top: var(--space-5); font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.14em; color: var(--color-primary-deep); }
.mod-courses { margin-top: var(--space-3); margin-bottom: 0; display: grid; gap: var(--space-2); list-style: none; }
.pricing-triad .card .mod-courses li { position: relative; padding-left: var(--space-4); font-size: var(--text-sm); line-height: 1.45; color: var(--color-ink); }
.mod-courses li::before { content: ""; position: absolute; left: 0; top: 0.5em; width: 5px; height: 5px; border-radius: 50%; background: var(--color-primary); }
.mod-foot { --price-size: var(--text-xl); margin-top: auto; padding-top: var(--space-4); border-top: 1px solid var(--color-line); }
/* The bootcamp is the module's price; the single workshop is the entry point
   below it. They are deliberately NOT a like-for-like pair (v3: a bootcamp is
   an integrated program, not a discounted bundle). */

/* .mods-note lives in home.css so the homepage (which never loads pages.css) can use it */

/* match the spotlight body size so 01/02/03 read as one family */
.pricing-triad .card > p { font-size: var(--text-sm); line-height: 1.55; }
@media (max-width: 880px) {
  .spotlight { grid-template-columns: 1fr; align-items: start; }
  .spotlight__price { --price-align: start; justify-self: start; }
}


/* ---- the full rate card, tucked behind a native <details> toggle -------- */
.rates {
  margin-top: clamp(2rem, 4vw, 3rem);
  border: 1px solid var(--color-line); border-radius: var(--radius-lg);
  background: var(--color-bg-card); box-shadow: var(--shadow-sm);
  overflow: clip;
}
.rates summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  font-weight: var(--fw-bold); color: var(--color-ink);
  cursor: pointer; list-style: none;
  transition: color var(--dur) var(--ease-out);
}
.rates summary::-webkit-details-marker { display: none; }
.rates summary:hover { color: var(--color-primary-deep); }
.rates summary svg { width: 1.1rem; height: 1.1rem; flex: none; color: var(--color-primary); transition: transform var(--dur) var(--ease-out); }
.rates[open] summary svg { transform: rotate(45deg); }
/* inside the toggle the table drops its own card chrome */
.price-table--flat { border: 0; border-radius: 0; box-shadow: none; border-top: 1px solid var(--color-line); }

/* ---- what you keep (dark) --------------------------------------------- */
.keep-strip { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
.keep-strip__head .lede { margin-bottom: 0; }
.keep-strip__list { display: grid; gap: var(--space-4); }
.keep-strip__list li { display: flex; gap: var(--space-3); align-items: flex-start; font-size: var(--text-base); color: var(--color-on-dark); }
.keep-strip__list svg { width: 1.15em; height: 1.15em; flex: none; margin-top: 0.14em; color: var(--brand-blue-400); }

@media (max-width: 880px) {
  .keep-strip { grid-template-columns: 1fr; gap: var(--space-8); }
}
/* table collapses to stacked cards (no horizontal scroll) on phones */
@media (max-width: 640px) {
  .price-table { overflow: visible; border: 0; background: transparent; box-shadow: none; }
  .price-table table { min-width: 0; }
  .price-table table, .price-table tbody, .price-table tr, .price-table th, .price-table td { display: block; }
  .price-table thead { display: none; }
  .price-table tbody tr { border: 1px solid var(--color-line); border-radius: var(--radius-md); background: var(--color-bg-card); padding: var(--space-4); margin-bottom: var(--space-3); }
  .price-table tbody tr:hover { background: var(--color-bg-card); }
  .price-table tbody th[scope="row"] { padding: 0 0 var(--space-3); margin-bottom: var(--space-2); border-bottom: 1px solid var(--color-line); }
  .price-table tbody td { display: flex; justify-content: space-between; gap: var(--space-4); padding: var(--space-1) 0; white-space: normal; text-align: right; }
  .price-table tbody td::before { content: attr(data-label); font-weight: var(--fw-medium); color: var(--color-ink-faint); text-align: left; }
  /* group labels stay plain labels in the stacked view, not cards */
  .price-table tbody tr.price-table__group { border: 0; background: transparent; padding: var(--space-4) 0 var(--space-1); margin: 0; }
  .price-table__group th { padding: 0; }
  /* dark context: stacked row cards go glass, matching the desktop treatment */
  .on-dark .price-table tbody tr { border-color: var(--color-line-dark); background: rgba(255, 255, 255, 0.05); }
  .on-dark .price-table tbody tr:hover { background: rgba(255, 255, 255, 0.05); }
  .on-dark .price-table tbody th[scope="row"] { border-bottom-color: var(--color-line-dark); }
  .on-dark .price-table tbody td::before { color: var(--color-on-dark-soft); }
  .on-dark .price-table tbody tr.price-table__group { background: transparent; }
}

/* ==========================================================================
   Framework page — guardrails ("the lines that never move")
   Two-column: sticky-feeling head + a vertical list of fixed commitments.
   ========================================================================== */
/* ---- where it runs: the homepage triad, carrying the three modules ------ */
/* Hallmark · component: domain-triad · system: CT Innovates (locked tokens)
 * pre-emit critique: P5 H5 E4 S4 R5 V4
 * The site's established "three parallel kinds of work" component (icon feature
 * cards + paragrid). Cards stay deliberately light: kicker, job, one line. */
/* framework's module panel has no START row above its options, so no seam */
.domains-panel { margin-top: clamp(2rem, 4vw, 3rem); }
.domains-panel .program-options { border-top: 0; }
/* This panel's kicker is "Workflow area 1", not the two-word "Module 1" the
   display word was drawn for: at three-column widths the nowrap version runs
   straight through the column hairline. Scoped here so the homepage ledger
   keeps its full-size, single-line word. */
/* --mark-sm already sizes this; only the wrap behaviour is panel-specific */
.domains-panel .program-step__n--word { white-space: normal; }
/* a full-width row following the options columns (the RUN row) gets its seam */
.program-options + .program-step { border-top: 1px solid var(--color-line); }
.domains__note { margin-top: var(--space-8); font-size: var(--text-sm); color: var(--color-ink-soft); }
.domains__note a { color: var(--color-primary-deep); font-weight: var(--fw-semibold); }
.domains__note a:hover { text-decoration: underline; }

.guards { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
/* left head stays in view while the (growable) list of rules scrolls past */
.guards__head { position: sticky; top: calc(var(--header-h) + var(--space-5)); align-self: start; }
.guards__head .h-section { margin-top: var(--space-3); }
.guards__head .lede { margin-top: var(--space-4); margin-bottom: 0; }
/* a divided ledger of rules — a hairline between each "line", scales as it grows */
.guards__list { display: grid; }
.guards__item { display: flex; gap: var(--space-4); align-items: flex-start; padding-block: var(--space-5); border-top: 1px solid var(--color-line); }
.guards__item:first-child { padding-top: 0; border-top: 0; }
.guards__item:last-child { padding-bottom: 0; }
.guards__item .card__icon { flex: none; }
.guards__item h3 { font-size: var(--text-lg); font-weight: var(--fw-bold); line-height: 1.25; letter-spacing: var(--tracking-tight); color: var(--color-ink); }
.guards__item p { margin-top: var(--space-1); font-size: var(--text-sm); line-height: 1.55; color: var(--color-ink-soft); }
/* the section runs dark: hairlines and text flip to the dark palette */
.on-dark .guards__item { border-top-color: var(--color-line-dark); }
.on-dark .guards__item h3 { color: var(--color-on-dark); }
.on-dark .guards__item p { color: var(--color-on-dark-soft); }
@media (max-width: 880px) {
  .guards { grid-template-columns: 1fr; gap: var(--space-8); }
  .guards__head { position: static; }
}

/* ==========================================================================
   Framework page — the practice, folded into the Principle as a concise, value-
   based reference (the full walkthrough lives on the homepage). A compact 5-up
   strip below the split; a divider + label separate it from the philosophy above.
   ========================================================================== */
/* flows straight out of the lede above it: no divider, no label */
.moves { margin-top: clamp(2rem, 4vw, 3rem); }
/* the second lede paragraph (the "picture the workflow" setup) */
.lede + .lede { margin-top: var(--space-4); }
.moves__steps { list-style: none; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: clamp(1rem, 2.5vw, 1.75rem); }
.moves__steps li { min-width: 0; }
.moves__n { display: block; margin-bottom: var(--space-3); font-size: var(--text-2xl); font-weight: var(--fw-extra); line-height: 1; letter-spacing: var(--tracking-tight); color: var(--color-primary-deep); font-variant-numeric: tabular-nums; }
.moves__steps h3 { font-size: var(--text-base); font-weight: var(--fw-bold); letter-spacing: var(--tracking-tight); color: var(--color-ink); margin-bottom: var(--space-1); }
.moves__steps p { font-size: var(--text-sm); line-height: 1.5; color: var(--color-ink-soft); }
@media (max-width: 880px) {
  .moves__steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
}
@media (max-width: 460px) {
  .moves__steps { grid-template-columns: 1fr; }
}

/* ---- Working together: the engagement journey — CENTERED. Phase content is
   centered; nodes sit centered above each phase, connected by a rail. ---------- */
.journey { list-style: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(1.25rem, 2.5vw, 2rem); text-align: center; }
.journey__step { position: relative; padding-top: calc(12px + var(--space-5)); }
/* node centered at the top of each phase */
.journey__step::before { content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 12px; height: 12px; border-radius: 50%; background: var(--brand-blue-500); box-shadow: 0 0 0 4px var(--color-bg); z-index: 1; transition: transform 0.25s ease, background-color 0.25s ease, box-shadow 0.25s ease; }
/* rail from this centered node across to the next centered node */
.journey__step::after { content: ""; position: absolute; top: 5px; left: 50%; right: calc(-50% - clamp(1.25rem, 2.5vw, 2rem)); height: 2px; background: var(--color-line); }
.journey__step:last-child::after { display: none; }
.journey__phase { display: block; margin-bottom: var(--space-2); font-size: var(--text-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.12em; color: var(--color-primary-deep); }
.journey__step h3 { font-size: var(--text-lg); font-weight: var(--fw-bold); letter-spacing: var(--tracking-tight); color: var(--color-ink); margin-bottom: var(--space-2); }
.journey__step p { font-size: var(--text-sm); line-height: 1.55; color: var(--color-ink-soft); max-width: var(--measure-narrow); margin-inline: auto; }
/* hover microinteraction: the node lifts + glows (motion is gentle enough to keep
   ungated; the transform/color transition is on the base rule) */
.journey__step:hover::before {
  transform: translateX(-50%) scale(1.4);
  background: var(--brand-blue-400);
  box-shadow: 0 0 0 4px var(--color-bg), 0 0 0 9px color-mix(in srgb, var(--brand-blue-400) 22%, transparent);
}
@media (max-width: 760px) {
  /* Stacked, the centred version broke down: four floating nodes with a stub of
     rail in each gap, so the sequence never read as one run. Turned on its side
     it becomes the rail the rest of the site already uses -- node in a left
     gutter, one continuous line through all four, copy ranged left beside it.
     Each step's rail spans its own box including the bottom padding, so
     consecutive steps join with no seam and no extra element. */
  .journey { grid-template-columns: minmax(0, 1fr); gap: 0; text-align: left; }
  .journey__step {
    padding: 0 0 var(--space-8) var(--space-8);
  }
  .journey__step:last-child { padding-bottom: 0; }
  /* node to the left gutter, no longer centred */
  .journey__step::before { top: 0.15em; left: 0; transform: none; }
  .journey__step:hover::before { transform: scale(1.4); }
  /* the run: left 5px centres a 2px rail under the 12px node */
  .journey__step::after {
    top: 0; bottom: 0; left: 5px; right: auto;
    width: 2px; height: auto; transform: none;
  }
  .journey__step:last-child::after { display: none; }
  .journey__step p { margin-inline: 0; max-width: none; }
}
/* closing CTA folded into the section above it (like the homepage offer): its top
   gap matches the section's bottom padding so it reads as its own sub-section */
.journey + .cta,
.why__grid + .cta,
.keep-strip + .cta { margin-top: var(--section-y); }

/* Submission result. Rendered above the form after the redirect, and the target
   of that redirect's #form-status fragment -- hence scroll-margin-top, which
   keeps the message clear of the sticky header instead of tucked beneath it.

   No left rule. The two states read from their ground alone: the same pale blue
   band used everywhere else on success, its danger-toned twin on failure. */
.form-notice {
  margin-bottom: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  background: var(--color-bg-soft);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-ink);
  scroll-margin-top: calc(var(--header-h) + var(--space-4));
}
.form-notice:focus { outline: none; } /* focused only so screen readers land on it */
/* On the hero the notice sits on navy, so it follows the .on-dark contract:
   translucent white, hairline, never a solid slab. */
.on-dark .form-notice {
  margin-bottom: var(--space-6);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--color-line-dark);
  color: var(--color-on-dark);
  font-size: var(--text-base);
}
.on-dark .form-notice--bad {
  background: rgba(179, 38, 30, 0.18);
  border-color: rgba(255, 138, 128, 0.45);
  color: #ffd9d6;
}
.form-notice--bad {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}
