/* Editorial principal landing — Onovo AI
   Calm, McKinsey-grade. No blur. No glow. No gradient text.
   Hairlines do the work. Type carries the weight. */

.principal-body { background: var(--paper); color: var(--ink); }

/* ──────────────── NAV ──────────────── */
.p-nav {
  position: sticky; top: 0; z-index: 50;
  background: rgba(251, 250, 247, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule);
}
.p-nav-inner {
  max-width: 68rem; margin: 0 auto;
  padding: 18px var(--sp-6);
  display: flex; align-items: center; gap: 32px;
}
@media (min-width: 768px) { .p-nav-inner { padding: 18px var(--sp-12); } }
.p-nav-logo {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 17px;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.01em;
}
.p-nav-logo img { width: 22px; height: 22px; object-fit: contain; }
.p-nav-links {
  display: flex; align-items: center;
  gap: 28px; margin-left: auto;
}
.p-nav-links a {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ink-mute);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.p-nav-links a:hover { color: var(--ink); }

/* ──────────────── HERO ──────────────── */
.p-hero { padding: 112px 0 var(--sp-32); }
@media (max-width: 768px) { .p-hero { padding: 64px 0 var(--sp-24); } }

.p-eyebrow-row {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: var(--sp-8);
  font-family: var(--font-body); font-size: var(--fs-2xs);
  text-transform: uppercase; letter-spacing: 0.18em;
  color: var(--ink-mute); font-weight: var(--fw-semibold);
}
.p-eyebrow-row .dot {
  width: 5px; height: 5px; background: var(--teal); border-radius: 50%;
}

.p-hero h1 {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: clamp(48px, 8vw, 96px);
  line-height: 1.02;
  letter-spacing: -0.025em;
  margin: 0 0 var(--sp-10);
  color: var(--ink);
  max-width: 18ch;
  text-wrap: balance;
}
.p-hero h1 em {
  font-style: italic;
  font-weight: var(--fw-regular);
  color: var(--teal-dark);
}

.p-hero-lede {
  font-family: var(--font-body);
  font-size: 20px;
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 56ch;
  margin: 0 0 var(--sp-12);
  text-wrap: pretty;
}

.p-hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: var(--sp-20); }

/* Editorial stat row — tabular, hairlines */
.p-stat-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
@media (max-width: 768px) {
  .p-stat-row { grid-template-columns: repeat(2, 1fr); }
}
.p-stat {
  padding: var(--sp-6) var(--sp-5);
  border-right: 1px solid var(--rule);
}
.p-stat:last-child { border-right: 0; }
@media (max-width: 768px) {
  .p-stat:nth-child(2) { border-right: 0; }
  .p-stat:nth-child(-n+2) { border-bottom: 1px solid var(--rule); }
}
.p-stat-num {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 40px;
  line-height: 1;
  color: var(--ink);
  letter-spacing: -0.02em;
  font-feature-settings: "tnum", "lnum";
}
.p-stat-label {
  margin-top: 8px;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  color: var(--ink-mute);
  line-height: 1.4;
}

.p-disclaimer {
  margin-top: var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--ink-faint);
  font-style: italic;
}

/* ──────────────── SECTION FRAME ──────────────── */
.p-section { padding: var(--sp-32) 0; border-top: 1px solid var(--rule); }
@media (max-width: 768px) { .p-section { padding: var(--sp-24) 0; } }

/* Tightened from --sp-16 (4rem / 64px) per Task 9 polish. The
   previous value left a visible gap between the section eyebrow
   and the four-steps list that other sections didn't have.
   --sp-10 (2.5rem) matches the rest of the page rhythm. */
.p-section-head { margin-bottom: var(--sp-10); }
.p-section-head .eyebrow {
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  text-transform: uppercase; letter-spacing: 0.18em;
  font-weight: var(--fw-semibold);
  color: var(--teal-dark);
  margin-bottom: var(--sp-4);
}
.p-section-head h2 {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: clamp(32px, 5vw, 56px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0 0 var(--sp-5);
  max-width: 22ch;
  text-wrap: balance;
}
.p-section-head p {
  font-family: var(--font-body);
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 60ch;
  margin: 0;
  text-wrap: pretty;
}

/* ──────────────── HOW IT WORKS — numbered enum ──────────────── */
.p-steps {
  list-style: none; padding: 0; margin: 0;
  counter-reset: step;
}
.p-steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 5rem 1fr 1.2fr;
  gap: var(--sp-10);
  padding: var(--sp-12) 0;
  border-top: 1px solid var(--rule);
  align-items: start;
}
.p-steps li:last-child { border-bottom: 1px solid var(--rule); }
@media (max-width: 768px) {
  .p-steps li {
    grid-template-columns: 3rem 1fr;
    gap: var(--sp-5);
    padding: var(--sp-8) 0;
  }
  .p-steps li > .p-step-detail { grid-column: 1 / -1; }
}
.p-steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 32px;
  color: var(--teal-dark);
  line-height: 1;
}
.p-step-title {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 24px;
  line-height: 1.2;
  margin: 0 0 8px;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.p-step-body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0;
}
.p-step-detail {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink-mute);
  line-height: 1.55;
  border-left: 1px solid var(--rule);
  padding-left: var(--sp-6);
}
.p-step-detail strong {
  color: var(--ink);
  font-weight: var(--fw-semibold);
}

/* ──────────────── DEPED ALIGNMENT — three card columns ──────────────── */
.p-align-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 768px) {
  .p-align-grid { grid-template-columns: repeat(3, 1fr); }
}
.p-align-card {
  padding: var(--sp-10) var(--sp-8);
  border-right: 1px solid var(--rule);
}
.p-align-card:last-child { border-right: 0; }
@media (max-width: 768px) {
  .p-align-card { border-right: 0; border-bottom: 1px solid var(--rule); }
  .p-align-card:last-child { border-bottom: 0; }
}
.p-align-card .num {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 14px;
  color: var(--teal-dark);
  letter-spacing: 0.05em;
  margin-bottom: var(--sp-6);
}
.p-align-card h3 {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 22px;
  line-height: 1.2;
  margin: 0 0 var(--sp-4);
  letter-spacing: -0.01em;
  color: var(--ink);
}
.p-align-card p {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-6);
}

/* Rubric line — hairline rows */
.p-rubric {
  list-style: none; padding: 0; margin: 0;
}
.p-rubric li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--rule);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink);
}
.p-rubric li:last-child { border-bottom: 1px solid var(--rule); }
.p-rubric li .pts {
  color: var(--ink-mute);
  font-feature-settings: "tnum";
}

/* Band stack — five tiers, vertical, hairlines */
.p-bands {
  display: flex; flex-direction: column;
}
.p-band {
  display: grid;
  grid-template-columns: 14px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
  border-top: 1px solid var(--rule);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink);
}
.p-band:last-child { border-bottom: 1px solid var(--rule); }
.p-band .swatch {
  width: 14px; height: 14px; border-radius: 2px;
}
.p-band .range { color: var(--ink-mute); font-feature-settings: "tnum"; font-size: var(--fs-xs); }

/* Compliance check list */
.p-checks { list-style: none; padding: 0; margin: 0; }
.p-checks li {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 10px;
  padding: 8px 0;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-soft);
}
.p-checks li svg { margin-top: 3px; color: var(--teal-dark); }

/* ──────────────── RESULT EXAMPLE PANEL ──────────────── */
.p-result-panel {
  margin-top: var(--sp-16);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  display: grid;
  grid-template-columns: 1fr;
}
@media (min-width: 768px) {
  .p-result-panel { grid-template-columns: 320px 1fr; }
}
.p-result-meta {
  padding: var(--sp-10);
  border-right: 1px solid var(--rule);
  background: var(--paper);
  border-radius: var(--r-md) 0 0 var(--r-md);
}
@media (max-width: 768px) {
  .p-result-meta {
    border-right: 0;
    border-bottom: 1px solid var(--rule);
    border-radius: var(--r-md) var(--r-md) 0 0;
  }
}
.p-result-meta .label {
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: var(--fw-semibold);
  color: var(--ink-mute);
  margin-bottom: 14px;
}
.p-result-grade {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 88px;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--ink);
  font-feature-settings: "lnum", "tnum";
}
.p-result-grade-sub {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink-mute);
  margin-top: 8px;
}
.p-result-band-row {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--rule);
}
.p-result-meta-info {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--rule);
  display: flex; flex-direction: column; gap: 8px;
  font-size: var(--fs-xs);
  color: var(--ink-mute);
}
.p-result-meta-info .row { display: flex; justify-content: space-between; }
.p-result-meta-info .row strong { color: var(--ink); font-weight: var(--fw-medium); }

.p-result-criteria {
  padding: var(--sp-10);
}
.p-criterion {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  padding: var(--sp-5) 0;
  border-top: 1px solid var(--rule);
}
.p-criterion:first-child { border-top: 0; padding-top: 0; }
.p-crit-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px;
}
.p-crit-name {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ink);
}
.p-crit-score {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 18px;
  color: var(--ink);
  font-feature-settings: "tnum", "lnum";
}
.p-crit-track {
  height: 4px; background: var(--paper-3); border-radius: 2px; overflow: hidden;
}
.p-crit-fill {
  height: 100%; background: var(--ink); border-radius: 2px;
}
.p-crit-quote {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: var(--fs-sm);
  color: var(--ink-mute);
  line-height: 1.5;
  margin-top: 4px;
  padding-left: 14px;
  border-left: 2px solid var(--teal);
}

/* ──────────────── QUOTE / TESTIMONIAL ROW ──────────────── */
.p-quote {
  padding: var(--sp-12) 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.p-quote blockquote {
  font-family: var(--font-heading);
  font-weight: var(--fw-regular);
  font-style: italic;
  font-size: clamp(22px, 3vw, 32px);
  line-height: 1.35;
  color: var(--ink);
  margin: 0;
  max-width: 32ch;
  letter-spacing: -0.005em;
}
.p-quote-cite {
  margin-top: var(--sp-6);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink-mute);
}
.p-quote-cite strong { color: var(--ink); font-weight: var(--fw-semibold); }

/* ──────────────── PILOT CTA ──────────────── */
.p-cta {
  padding: var(--sp-24) 0;
  border-top: 1px solid var(--rule);
}
.p-cta-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-10);
  align-items: end;
}
@media (min-width: 768px) {
  .p-cta-inner { grid-template-columns: 1.2fr 1fr; gap: var(--sp-16); }
}
.p-cta h2 {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: clamp(32px, 5vw, 56px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0;
  max-width: 18ch;
  text-wrap: balance;
}
.p-cta-side {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  line-height: 1.55;
}
.p-cta-side dl { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 14px var(--sp-6); }
.p-cta-side dt { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.14em; color: var(--ink-mute); margin-bottom: 4px; font-weight: var(--fw-semibold); }
.p-cta-side dd { margin: 0; font-family: var(--font-heading); font-weight: var(--fw-semibold); font-size: 22px; color: var(--ink); }
.p-cta-actions {
  margin-top: var(--sp-8);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--rule);
  display: flex; gap: 12px; flex-wrap: wrap;
}
@media (min-width: 768px) { .p-cta-actions { grid-column: 1 / -1; } }

/* ──────────────── FOOTER ──────────────── */
.p-footer {
  border-top: 1px solid var(--rule);
  padding: var(--sp-12) 0 var(--sp-16);
  background: var(--paper);
}
.p-footer-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-8);
}
@media (min-width: 768px) {
  .p-footer-inner { grid-template-columns: 1.2fr repeat(3, 1fr); }
}
.p-footer-brand {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: 17px;
  color: var(--ink);
}
.p-footer-brand img { width: 22px; height: 22px; object-fit: contain; }
.p-footer-tagline {
  margin-top: 12px;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink-mute);
  max-width: 32ch;
  line-height: 1.55;
}
.p-footer-col h4 {
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-mute);
  margin: 0 0 14px;
}
.p-footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.p-footer-col a {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.p-footer-col a:hover { color: var(--teal-dark); }

.p-footer-legal {
  margin-top: var(--sp-12);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; gap: 12px var(--sp-6); justify-content: space-between;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  color: var(--ink-faint);
}

/* Subtle reveal — opacity only, no slide */
@keyframes p-reveal { from { opacity: 0; } to { opacity: 1; } }
.reveal { animation: p-reveal var(--dur-slow) var(--ease-out) both; }

/* ───────────────────────────────────────────────────────────────
 * Mobile pass · 2026-05-05 audit (320–600 px)
 * The landing was designed desktop-first; the only mobile-ish
 * coverage was a `max-width: 768px` tablet block. iPhone widths
 * inherited those rules and broke in predictable ways (h1 too
 * big, nav links overflowing, quote cite cramped, CTA dl crammed
 * into 2 cols at 320 px). This single block scopes every mobile-
 * only fix; nothing here fires above 600 px viewport, so iPad +
 * desktop render byte-for-byte identical.
 * ─────────────────────────────────────────────────────────── */
@media (max-width: 600px) {

  /* ─── Hero ──────────────────────────────────────────────── */
  .p-hero { padding: 28px 0 32px; }

  .p-hero h1 {
    font-size: 32px;
    line-height: 1.05;
    max-width: none;            /* drops the desktop 18ch cap */
    letter-spacing: -0.012em;
  }
  .p-hero-lede { font-size: 14px; max-width: none; }
  .p-hero-lede.p-hero-lede-tech { font-size: 13px; }

  /* CTAs stack full-width — each its own 48 px-tall touch target. */
  .p-hero-ctas { flex-direction: column; gap: 10px; }
  .p-hero-ctas .btn { width: 100%; justify-content: center; }

  /* Stat row — already 2-col below 768 px (existing rule); just
   * tighten the chip contents so 167 px cells don't overflow. */
  .p-stat { padding: 16px 12px; }
  .p-stat-num { font-size: 26px; }
  .p-stat-sub { font-size: 11px; }
  .p-stat-label { font-size: 11px; line-height: 1.35; }

  /* ─── Nav · hide anchor links + bump Log in hit area ──── */
  /* Mobile keeps brand mark + Log in + Get started only. The
   * three in-page anchor links (How it works / Curriculum
   * alignment / Programme) hide because they don't fit and
   * scroll-to-section beats menu-to-section on a short single-
   * page landing. */
  .p-nav-links { display: none; }
  .p-nav-inner {
    padding: 12px var(--sp-6);
    gap: 12px;
    justify-content: space-between;
  }

  /* Log in anchor — uses [data-mobile-cta="link"] in the HTML so
   * we don't fight the inline `style=` with [href="/login"]. */
  [data-mobile-cta="link"] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 8px;
    margin-right: 0 !important;
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* Stop the three surviving nav items (brand, Log in, Get started)
   * from line-breaking on a 393 px viewport. Without nowrap +
   * flex-shrink: 0, the flex container squeezes each child until its
   * text wraps — "Onovo AI" → "Onovo" / "AI", "Log in" → "Log" /
   * "in", "Get started — free" → "Get started —" / "free". */
  .p-nav-logo { flex-shrink: 0; }
  .p-nav-logo span { white-space: nowrap; }
  .p-nav-inner .btn-primary {
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* ─── Quote · tighten + stack cite vertically ─────────── */
  .p-quote blockquote { font-size: 18px; line-height: 1.45; }
  .p-quote-cite {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  /* ─── CTA section · single-column dl ──────────────────── */
  .p-cta-side dl {
    grid-template-columns: 1fr;
    gap: 14px;
  }

  /* ─── How it works · tighten step type + markbook list ── */
  .p-steps li::before { font-size: 26px; }
  .p-step-title { font-size: 18px; }
  .p-step-body { font-size: 14px; }
  .p-markbook li { padding: 10px 14px; }
  .p-markbook .name { font-size: 13px; }
  .p-markbook .score { font-size: 12px; }

  /* ─── Disclaimer · methodology link 44 px hit area ────── */
  /* Padding + negative margin expands the click target to 44 px
   * tall while keeping the visible text inline at its original
   * position — no layout shift. */
  .p-disclaimer a {
    display: inline-block;
    padding: 8px 6px;
    margin: -8px -6px;
    border-radius: 4px;
  }

  /* ─── Curriculum alignment cards ──────────────────────── */
  .p-align-card { padding: 22px 18px; }
  .p-align-card h3 { font-size: 19px; line-height: 1.25; }
  .p-align-card p { font-size: 14px; }
  .p-band { font-size: 13px; }

  /* ─── Footer · tighter so the new UK address fits ─────── */
  .p-footer-col h4 { font-size: 12px; margin-bottom: 8px; }
  .p-footer-col li { font-size: 13px; line-height: 1.5; }
  .p-footer-tagline { font-size: 14px; }
}

/* iPhone SE / very narrow (≤ 380 px) — one extra pinch on the
 * h1 + a tighter Get started button so the 3-element nav row
 * (brand · Log in · Get started) fits in 320 px. */
@media (max-width: 380px) {
  .p-hero h1 { font-size: 28px; }
  .p-hero { padding: 24px 0 28px; }
  .p-nav-inner .btn-primary { font-size: 13px; padding: 10px 14px; }
}

/* ─── STEP DECK · scroll-triggered narrative · 2026-05-06 ─────────
 * Sits below the How-it-works section. Five horizontal cards on
 * desktop, stacked on mobile. Sticky header echoes the active step;
 * progress line draws as the reader scrolls; per-card mask reveal
 * + word-stagger title; ornament drifts behind each card.
 *
 * Reduced-motion users: every animation block below is wrapped in
 * `.js-anim` so without JS it renders as a static deck. The
 * @media (prefers-reduced-motion) override flips opacity / transform
 * to neutral and stretches the progress fill to 100%.
 * ─────────────────────────────────────────────────────────────── */

.p-step-deck { padding: var(--sp-14) 0 var(--sp-20); position: relative; overflow-x: clip; }
@media (max-width: 768px) { .p-step-deck { padding: var(--sp-10) 0 var(--sp-14); } }

.p-deck-head {
  /* No `position: sticky` here — the page nav (.p-nav) is already
   * sticky at top: 0 with z-index: 50, and a second sticky at the
   * same anchor caused the deck title to half-clip under the nav
   * while scrolling. Sticky was a hangover from the carousel era
   * (it tracked the active step); the static 3+2 grid has no need
   * for it. The header scrolls with the section like any other
   * section heading on the page. */
  background: var(--paper);
  padding: var(--sp-6) 0 var(--sp-4);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--sp-10);
}

.p-deck-title {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: clamp(28px, 4vw, 40px);
  letter-spacing: -0.018em;
  line-height: 1.05;
  color: var(--ink);
  margin: var(--sp-2) 0 var(--sp-5);
}

.p-deck-progress {
  height: 2px; width: 100%;
  background: var(--rule);
  border-radius: 1px;
  overflow: hidden;
}
.p-deck-progress-fill {
  display: block; height: 100%; width: 100%;
  background: var(--teal);
  transform: scaleX(0); transform-origin: left;
  transition: transform 240ms ease;
}

/* ── Carousel wrapper + chrome ────────────────────────────────────
 * The deck used to be a snap carousel; it is now a 3+2 grid (≥1024px)
 * or a vertical stack (<1024px). The .p-deck-carousel wrapper, the
 * prev / next .p-deck-nav buttons, and the .p-deck-progress bar all
 * stay in the DOM (they're rendered by teacher.html and would need a
 * separate HTML edit to remove) but are display:none everywhere so
 * they have no visual or interaction effect. The carousel JS in
 * setupStepDeck() also early-bails — see MarketingReveal.tsx. */
.p-deck-carousel { position: relative; }
.p-deck-nav,
.p-deck-progress { display: none !important; }

/* ── Track layout ─────────────────────────────────────────────────
 * Two layouts, one breakpoint:
 *
 *   ≥1024px → 3 + 2 GRID. A 6-column grid where every card spans 2
 *   columns. Cards 1-3 fill row 1 (cols 1-2, 3-4, 5-6). Cards 4 + 5
 *   sit centred in row 2 (cols 2-3 and 4-5), with col 1 and col 6
 *   left empty so the second row is symmetrically inset. All five
 *   cards are the same width — no asymmetric sizing.
 *
 *   <1024px → vertical stack (1-column grid). Cards take the full
 *   container width, top-to-bottom scroll. Editorial reading flow.
 *
 * No carousel, no scroll snap, no prev / next chrome anywhere. The
 * existing data-deck-track / data-deck-card hooks stay so the
 * setupStepDeck() reveal animation (word-stagger on title) still
 * fires per card, but the carousel-only wiring early-bails.
 * ────────────────────────────────────────────────────────────── */
.p-deck-track {
  list-style: none; padding: 0; margin: 0;
  display: grid;
  grid-template-columns: 1fr;       /* mobile / tablet default */
  gap: var(--sp-5);
}

@media (min-width: 1024px) {
  .p-step-deck > .container-prose {
    max-width: min(96rem, 95vw);    /* widen the stage so cards breathe */
  }
  .p-deck-track {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    /* Both rows the same height. minmax(420px, 1fr) means each row
     * is at least 420 px tall; if either row's natural content
     * exceeds that, both rows lift together via 1fr. Row 1 (cards
     * 1-3 with chunky bottom blocks) and Row 2 (cards 4-5 with
     * lighter blocks) now always match — the equalisation is
     * structural at the grid level, not a per-card min-height that
     * leaves dead air below shorter content. */
    grid-auto-rows: minmax(420px, 1fr);
    gap: var(--sp-5);
  }
  .p-deck-card { grid-column: span 2; }
  /* Cards 4 + 5 sit centred in row 2: cols 2-3 and 4-5. Col 1 and
   * col 6 stay empty as half-card visual padding on each side. */
  .p-deck-card:nth-child(4) { grid-column: 2 / span 2; }
  .p-deck-card:nth-child(5) { grid-column: 4 / span 2; }
  /* Cards 4 + 5 carry less natural content than cards 1-3. With the
   * row equalisation above they inherit row 1's height; centring
   * the body splits the extra height evenly above and below the
   * content rather than pooling it as a single bottom void. */
  .p-deck-card:nth-child(4) .p-deck-card-body,
  .p-deck-card:nth-child(5) .p-deck-card-body {
    justify-content: center;
  }
  .p-deck-nav { display: none; }
  .p-deck-progress { display: none; }
}

.p-deck-card {
  position: relative;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: 14px;
  /* Mobile / vertical-stack default: 40 / 40 px gives the title,
   * body, and bottom block generous editorial breathing room from
   * the card border (was 36 / 32 px — still felt packed per
   * iPhone live-preview review). Matches the desktop value so the
   * editorial rhythm stays consistent across viewports. */
  padding: var(--sp-10) var(--sp-10);
  overflow: hidden;
  transition:
    transform 320ms cubic-bezier(0.22,0.61,0.36,1),
    box-shadow 320ms cubic-bezier(0.22,0.61,0.36,1),
    border-color 320ms cubic-bezier(0.22,0.61,0.36,1);
  display: flex; flex-direction: column;
  /* No min-height — cards size to their natural content. The grid
   * default `align-items: stretch` already matches every card in a
   * row to the tallest sibling, so the two rows stay uniformly tall
   * without a hard-coded floor leaving dead air below the body /
   * chip / criteria / reason / meta block. */
}
/* Desktop padding override removed — the base .p-deck-card rule
 * above now uses sp-10 / sp-10 for both mobile and desktop, so the
 * previous @media (min-width: 1024px) block was redundant. The
 * editorial rhythm is identical across viewports. */
.p-deck-card[aria-current="step"] {
  border-color: var(--rule-strong);
  box-shadow: 0 14px 32px -22px rgba(15,20,25,0.28);
}
.p-deck-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 32px -22px rgba(15,20,25,0.22);
  border-color: var(--rule-strong);
}

/* Body content stacks top-down with editorial rhythm. The last block
 * (chip-row, criteria, reason, meta) lives at its natural position
 * directly below the body text — no `margin-top: auto` pushing it to
 * the floor and leaving a void. Cards look full and consistent. */
.p-deck-card-body {
  position: relative; z-index: 1;
  flex: 1 1 auto;
  display: flex; flex-direction: column;
  gap: var(--sp-2);
}

.p-deck-num {
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--teal-dark);
}

.p-deck-card-title {
  font-family: var(--font-heading);
  font-weight: 600;
  /* Title scaled up for the wider 3+2 grid cards (~440-480 px wide
   * on a 1440 px viewport, vs ~250 px in the old flex-row). */
  font-size: clamp(22px, 1.6vw, 28px);
  letter-spacing: -0.012em;
  line-height: 1.15;
  color: var(--ink);
  margin: 0;
}
.p-deck-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 700ms cubic-bezier(0.22,0.61,0.36,1),
    transform 700ms cubic-bezier(0.22,0.61,0.36,1);
}
.p-deck-word.in { opacity: 1; transform: none; }

.p-deck-card-body-text {
  font-family: var(--font-body);
  /* Body bumped from var(--fs-sm) ≈ 14 px to 15.5 px. The wider
   * cards leave the smaller size visually under-weight against the
   * larger title and the surrounding editorial paragraphs. */
  font-size: 15.5px;
  color: var(--ink-soft);
  line-height: 1.62;
  margin: var(--sp-1) 0 var(--sp-2);
}

.p-deck-chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--sp-2); }
.p-deck-chip {
  font-family: var(--font-body); font-size: var(--fs-2xs);
  color: var(--ink-mute);
  border: 1px solid var(--rule);
  padding: 4px 10px; border-radius: 999px;
  background: var(--paper-2);
}

.p-deck-bandrow { display: flex; flex-direction: column; gap: 4px; margin-top: var(--sp-2); font-family: var(--font-body); font-size: var(--fs-xs); color: var(--ink-soft); }
.p-deck-bandrow strong { color: var(--ink); margin-right: 6px; }

.p-deck-criteria { margin-top: var(--sp-3); display: grid; gap: 6px; font-family: var(--font-body); font-size: var(--fs-xs); }
.p-deck-criteria > div { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; border-bottom: 1px dashed var(--rule); color: var(--ink-soft); }
.p-deck-criteria > div:last-child { border-bottom: 0; }
.p-deck-criteria strong { color: var(--ink); font-weight: var(--fw-semibold); }

/* Desktop-only typography uplift — at ≥1024 px the 3+2 grid produces
 * substantially wider cards (~440-480 px), so the eyebrow / body /
 * chip / criteria / reason / meta sizes all bump ~10-15 % to fill
 * the additional horizontal real estate. Mobile keeps the smaller
 * tokens since cards are full-container-width and don't need uplift. */
@media (min-width: 1024px) {
  .p-deck-num            { font-size: 12px; }
  .p-deck-card-body-text { font-size: 16.5px; line-height: 1.62; }
  .p-deck-chip           { font-size: 12px; padding: 5px 12px; }
  .p-deck-bandrow        { font-size: 13px; }
  .p-deck-criteria       { font-size: 13.5px; }
  .p-deck-criteria > div { padding: 5px 0; }
}

.p-deck-reason {
  margin-top: var(--sp-3);
  padding: 8px 12px; border-radius: 6px;
  background: var(--paper-2);
  border: 1px dashed var(--rule-strong);
  display: flex; flex-direction: column; gap: 2px;
  font-family: var(--font-body);
}
.p-deck-reason-label { font-size: var(--fs-2xs); color: var(--ink-mute); letter-spacing: 0.12em; text-transform: uppercase; }
.p-deck-reason-value { font-size: var(--fs-sm); color: var(--ink); font-weight: var(--fw-medium); }

.p-deck-meta { display: flex; flex-direction: column; gap: 4px; margin-top: var(--sp-3); font-family: var(--font-body); font-size: var(--fs-2xs); color: var(--ink-mute); letter-spacing: 0.04em; }

@media (min-width: 1024px) {
  .p-deck-reason-value { font-size: 15px; }
  .p-deck-reason       { padding: 10px 14px; }
  .p-deck-meta         { font-size: 12px; gap: 6px; }
}

/* ── Reveal animation (resilient) ───────────────────────────────
 * Cards are visible by default — the previous version held them
 * at opacity 0 plus a teal-light gradient overlay (`::before`,
 * z-index 2) and only released both states when revealIO fired
 * `.p-deck-in`. On desktop's horizontal grid, all 5 cards share
 * the same vertical position so per-card thresholding was
 * unreliable; cards stayed blank-teal-covered. The word-stagger
 * on `.p-deck-word` (still wired) handles the entrance flourish
 * without risking total invisibility if the observer flakes. */
.js-anim .p-deck-card.p-deck-in .p-deck-ornament {
  /* legacy placeholder — kept so the cascade ordering doesn't
   * shift other rules; ornament parallax stays scoped below. */
}
.js-anim .p-deck-card.p-deck-in::before {
  transform: scaleX(0);
}

/* ── Per-card ornaments ─────────────────────────────────────── */
.p-deck-ornament {
  position: absolute; inset: 0;
  z-index: 0; pointer-events: none;
  opacity: 0.55;
  display: flex; align-items: flex-end; justify-content: flex-end;
  padding: var(--sp-4);
}
/* Desktop tone-down. The ornaments were calibrated for the original
 * 280 px-wide cards; on the 3+2 grid each card is now ~440-480 px,
 * and at 0.55 opacity the ornaments started competing with foreground
 * content (most visibly the .p-deck-quote bleeding across card 03's
 * criteria list). 0.32 reads as the faint background pattern the
 * design originally intended. Inset bumped from sp-4 → sp-6 so the
 * ornament tracks the card's new sp-10 inner padding instead of
 * sitting on the new 40 px content edge. */
@media (min-width: 1024px) {
  .p-deck-ornament { opacity: 0.32; padding: var(--sp-6); }
}

/* Mobile / tablet: ornaments are hidden entirely. On the vertical
 * stack the cards are full container width (~340-380 px), so the
 * absolute-positioned ornament occupies a much larger fraction of
 * card real-estate than on the original 280 px-wide design and
 * visually collides with the bottom-anchored content blocks
 * (bandrow on card 02, criteria + quote on card 03). They're
 * decorative — removing them on small screens preserves the primary
 * informational hierarchy without sacrificing anything functional. */
@media (max-width: 768px) {
  .p-deck-ornament { display: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .p-deck-ornament {
    transition: transform 700ms cubic-bezier(0.22,0.61,0.36,1);
    will-change: transform;
  }
  .p-deck-card.p-deck-in .p-deck-ornament {
    transform: translateY(-4px);
  }
}

/* 1 — rubric grid */
.p-deck-grid { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 14px; gap: 6px; width: 132px; }
.p-deck-grid span { background: var(--teal-light); border-radius: 3px; }
.p-deck-grid span:nth-child(7) { background: var(--teal); }
.p-deck-grid span:nth-child(2) { background: var(--teal-dark); }

/* 2 — band ramp */
.p-deck-bands { display: flex; gap: 4px; width: 200px; height: 12px; align-items: stretch; }
.p-deck-bands span { flex: 1; border-radius: 3px; }
.p-deck-bands span[data-band="beginning"]  { background: var(--band-beginning); }
.p-deck-bands span[data-band="developing"] { background: var(--band-developing); }
.p-deck-bands span[data-band="proficient"] { background: var(--band-proficient); }
.p-deck-bands span[data-band="advanced"]   { background: var(--band-advanced); }
.p-deck-bands span[data-band="exemplary"]  { background: var(--band-exemplary); }

/* 3 — quote */
.p-deck-quote {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-faint);
  max-width: 200px;
  line-height: 1.45;
  border-left: 2px solid var(--teal);
  padding-left: 8px;
}
/* Tighter cap at desktop so the quote stays in the bottom-right
 * corner of the wider 3+2 card and stops bleeding across the
 * .p-deck-criteria rows above it. */
@media (min-width: 1024px) {
  .p-deck-quote { max-width: 180px; }
}

/* 4 — teacher edit (4 → 5) */
.p-deck-edit { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-heading); font-size: 28px; color: var(--ink-faint); }
.p-deck-edit-from { text-decoration: line-through; color: var(--ink-faint); }
.p-deck-edit-arrow { color: var(--teal-dark); font-size: 22px; }
.p-deck-edit-to { color: var(--teal-dark); font-weight: 600; }

/* 5 — markbook row */
.p-deck-row {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 8px 12px;
  font-family: var(--font-body); font-size: var(--fs-xs);
  box-shadow: 0 4px 14px -10px rgba(15,20,25,0.18);
}
.p-deck-row-code  { font-family: var(--font-heading); font-weight: 600; color: var(--ink); letter-spacing: 0.04em; }
.p-deck-row-band  { padding: 2px 8px; border-radius: 999px; background: var(--band-advanced); color: #fff; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; }
.p-deck-row-grade { font-family: var(--font-heading); font-weight: 600; color: var(--ink); }

/* ── Cambridge coat-of-arms lockup ─────────────────────────────
 * Flex column with the eyebrow, coat of arms, and sub-paragraph as
 * direct children. 24 px gap; asymmetric vertical padding because
 * the previous .p-section already provides 128 px of bottom
 * breathing room above this block — duplicating with another 96 px
 * top stacked to a ~224 px visual void. Top trimmed to 24 px
 * (visual closure of the eyebrow without compounding); bottom kept
 * at 80 px so the transition into the .p-quote block stays calm.
 * Image caps at 144 px wide and scales down via 100% width +
 * max-width. */
.cambridge-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  padding-block: 24px 80px;
  text-align: center;
}
.cambridge-section img {
  width: 100%;
  max-width: 144px;
  height: auto;
  margin: 0;
  display: block;
}

/* ── Reduced motion ──────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .js-anim .p-deck-card,
  .js-anim .p-deck-card::before,
  .p-deck-progress-fill,
  .p-deck-card,
  .p-deck-ornament,
  .p-deck-track,
  .p-deck-nav {
    transition: none !important;
    animation: none !important;
  }
  .p-deck-track { scroll-behavior: auto !important; }
  .js-anim .p-deck-card { opacity: 1 !important; transform: none !important; }
  .js-anim .p-deck-card::before { transform: scaleX(0) !important; }
  .p-deck-word { opacity: 1 !important; transform: none !important; }
}
