/* IPR Design System v1.2 — generated by build/build_css.py, do not hand-edit. */

.ipr-2026 {
  --color-ink: #1F4760;
  --color-ink-10: rgba(31, 71, 96, .10);
  --color-ink-20: rgba(31, 71, 96, .20);
  --color-ink-06: rgba(31, 71, 96, .06);
  --color-accent: #CC6844;
  --color-accent-dark: #A8502F;
  --color-accent-12: rgba(204, 104, 68, .12);
  --color-blue: #3C6A79;
  --color-blue-tint: #E4EDF0;
  --color-blue-12: rgba(60, 106, 121, .12);
  --color-blue-card: #CFE0E6;
  --color-positive: #51845A;
  --color-positive-dark: #406B49;
  --color-positive-12: rgba(81, 132, 90, .12);
  --color-sand: #EAC885;
  --color-sand-20: rgba(234, 200, 133, .20);
  --color-sand-30: rgba(234, 200, 133, .30);
  --color-paper: #FEFBEC;
  --color-white: #FFFFFF;
  --color-text: #3F3F3F;
  --color-text-muted: #6B7280;
  --color-border: var(--color-ink-10);
  --color-on-dark: rgba(255, 255, 255, .90);
  --color-on-dark-muted: rgba(255, 255, 255, .70);
  --color-ink-deep: var(--color-ink);
  --color-paper-2: var(--color-paper);
  --on-dark-06: rgba(255, 255, 255, .06);
  --on-dark-12: rgba(255, 255, 255, .12);
  --on-dark-20: rgba(255, 255, 255, .20);
  --on-dark-40: rgba(255, 255, 255, .40);
  --glass-fill: rgba(255, 255, 255, .60);
  --glass-fill-ink: rgba(31, 71, 96, .50);
  --glass-blur: blur(12px);
  --grad-ink: linear-gradient(115deg, #3C6A79 0%, #1F4760 100%);
  --grad-warm: linear-gradient(135deg, #EAC885, #CC6844);
  --grad-soft: linear-gradient(160deg, #FBF4E0, #FEFBEC);
  --grad-cool: linear-gradient(107deg, #F6F8F1 0%, #DFEBED 100.61%);
  --font-sans: 'Poppins', system-ui, -apple-system, sans-serif;
  --text-xs: 0.72rem;
  --text-sm: 0.83rem;
  --text-base: 0.95rem;
  --text-md: 1.05rem;
  --text-lg: 1.25rem;
  --text-xl: 1.5rem;
  --text-2xl: clamp(1.7rem, 2.8vw, 2.3rem);
  --text-3xl: clamp(2.3rem, 4.5vw, 3.4rem);
  --weight-light: var(--weight-regular);
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --weight-extrabold: 800;
  --leading-tight: 1.14;
  --leading-snug: 1.3;
  --leading-normal: 1.6;
  --tracking-tight: -0.02em;
  --tracking-wide: 0.06em;
  --tracking-wider: 0.08em;
  --tracking-widest: 0.12em;
  --space-0-5: 4px;
  --space-1: 8px;
  --space-1-5: 12px;
  --space-2: 16px;
  --space-2-5: 20px;
  --space-3: 24px;
  --space-4: 32px;
  --space-5: 40px;
  --space-6: 48px;
  --space-7: 56px;
  --space-8: 64px;
  --space-10: 80px;
  --section-y: 88px;
  --section-y-compact: 56px;
  --section-y-large: 96px;
  --border-width: 1.5px;
  --border-width-2: 2px;
  --radius-xs: 6px;
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-pill: 999px;
  --shadow: rgba(17, 17, 26, .05) 0 4px 16px, rgba(17, 17, 26, .05) 0 8px 32px;
  --shadow-focus: 0 0 0 3px var(--color-white), 0 0 0 5px var(--color-accent-dark);
  --duration-base: 160ms;
  --ease-out: cubic-bezier(0.0, 0.0, 0.2, 1);
  --transition-base: var(--duration-base) var(--ease-out);
  --max-content: 1200px;
  --max-prose: 680px;
  --max-form: 520px;
  --wrap-x: clamp(20px, 4vw, 80px);
  --z-sticky: 50;
  --z-content: 2;
}

@media (min-width: 1600px) {
  .ipr-2026 {
    --max-content: 1600px;
  }

}


/* Self-hosted Poppins (OFL), GDPR-safe: no Google Fonts at runtime. */

@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/poppins-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/poppins-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }


@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('fonts/poppins-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('fonts/poppins-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }


@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('fonts/poppins-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('fonts/poppins-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }


@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('fonts/poppins-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('fonts/poppins-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }


@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 800; font-display: swap;
  src: url('fonts/poppins-800-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 800; font-display: swap;
  src: url('fonts/poppins-800-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }


/* base.css — the reset, element typography, and the .wrap layout
   utility. Concatenated first by build_css.py, ahead of every component. */

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


.ipr-2026 {
  font-family: var(--font-sans);
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}


.ipr-2026 {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  color: var(--color-text, var(--color-ink));
  background: var(--color-white);
  line-height: var(--leading-normal);
}


.ipr-2026 h1, .ipr-2026 h2, .ipr-2026 h3, .ipr-2026 h4, .ipr-2026 h5, .ipr-2026 h6, .ipr-2026 p, .ipr-2026 ul, .ipr-2026 ol, .ipr-2026 li, .ipr-2026 figure, .ipr-2026 blockquote { margin: 0; }


.ipr-2026 h1, .ipr-2026 h2, .ipr-2026 h3, .ipr-2026 h4, .ipr-2026 h5, .ipr-2026 h6 { font-family: var(--font-sans); }


.ipr-2026 button, .ipr-2026 input, .ipr-2026 select, .ipr-2026 textarea {
  font-family: inherit;
  font-size: inherit;
}


/* Content wrapper — single fixed width, centred, with fluid gutters. */
.ipr-2026 .wrap {
  max-width: var(--max-content);
  margin-inline: auto;
  padding-inline: var(--wrap-x);
}


/* chip — small all-caps pill label */

.ipr-2026 .chip {
  display: inline-block;
  align-self: flex-start;   /* never stretches inside a flex-column parent */
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  border-radius: var(--radius-pill);
  padding: 5px 14px;
  line-height: 1;
  /* Colour axis — base is accent: the colour's own dark text on its light tint. */
  color: var(--color-accent-dark);
  background: var(--color-accent-12);
}


/* Sand — reads clearly on dark ink and hero fills. */
.ipr-2026 .chip--sand {
  color: var(--color-sand);
  background: var(--color-sand-30);
}


.ipr-2026 .chip--positive {
  color: var(--color-positive-dark);
  background: var(--color-positive-12);
}


.ipr-2026 .chip--blue {
  color: var(--color-blue);
  background: var(--color-blue-12);
}


/* Tone axis — --solid is white on the solid colour. */
.ipr-2026 .chip--solid {
  color: var(--color-white);
  background: var(--color-accent);
}


.ipr-2026 .chip--positive.chip--solid { background: var(--color-positive); }

.ipr-2026 .chip--blue.chip--solid { background: var(--color-blue); }


/* Sand is too light to carry white text, so the solid sand chip uses ink. */
.ipr-2026 .chip--sand.chip--solid {
  color: var(--color-ink);
  background: var(--color-sand);
}


/* btn-primary — button kinds: primary, ghost, on-dark, white */

/* Shared base */
.ipr-2026 .btn-primary, .ipr-2026 .btn-ghost, .ipr-2026 .btn-on-dark, .ipr-2026 .btn-white {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 14px 32px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  border: var(--border-width-2) solid transparent;
  transition:
    background var(--transition-base),
    color var(--transition-base),
    border-color var(--transition-base),
    box-shadow var(--transition-base),
    transform var(--transition-base);
  white-space: nowrap;
  align-self: flex-start;   /* buttons always hug their label — never stretch to fill a flex-column parent (card, form) */
}


.ipr-2026 .btn-primary, .ipr-2026 .btn-ghost, .ipr-2026 .btn-on-dark, .ipr-2026 .btn-white {
  -webkit-appearance: none;
  appearance: none;
}


/* Focus ring — shared */
.ipr-2026 .btn-primary:focus-visible, .ipr-2026 .btn-ghost:focus-visible, .ipr-2026 .btn-on-dark:focus-visible, .ipr-2026 .btn-white:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}


/* --- Primary -------------------------------------------------- */
/* One per section maximum. Warm gradient fill, white text, no border.
   Must use border:none — a 2px solid transparent border atop a CSS
   gradient background causes rendering artefacts in all browsers.
   The shared base sets border:2px solid transparent for ghost/on-dark/white;
   primary overrides it to none here. */

.ipr-2026 .btn-primary {
  background: var(--grad-warm);
  border: none;
  color: #fff;
  padding: 16px 34px;
}


.ipr-2026 .btn-primary:hover {
  filter: brightness(0.95) saturate(1.05);
}


.ipr-2026 .btn-primary:active {
  transform: translateY(0);
  box-shadow: none;
}


/* --- Ghost ---------------------------------------------------- */
/* Secondary CTA on light (white/paper) backgrounds. */

.ipr-2026 .btn-ghost {
  background: transparent;
  border-color: var(--color-ink-10);
  color: var(--color-ink);
}


.ipr-2026 .btn-ghost:hover {
  border-color: var(--color-ink);
  background: var(--color-ink-06);
}


/* --- On-dark -------------------------------------------------- */
/* Secondary CTA on dark/hero backgrounds. Semi-transparent, white border. */

.ipr-2026 .btn-on-dark {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.40);
  color: #fff;
}


.ipr-2026 .btn-on-dark:hover {
  background: rgba(255, 255, 255, 0.22);
  border-color: #fff;
}


/* --- White ---------------------------------------------------- */
/* Used inside the warm accent band only. */

.ipr-2026 .btn-white {
  background: #fff;
  border-color: #fff;
  color: var(--color-ink-deep);
}


.ipr-2026 .btn-white:hover {
  background: var(--color-paper);
  border-color: var(--color-paper);
}


/* CTA pair — primary always left, secondary always right.
   Never swap the order. */
.ipr-2026 .btn-pair {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}


@media (prefers-reduced-motion: reduce) {
  .ipr-2026 .btn-primary, .ipr-2026 .btn-ghost, .ipr-2026 .btn-on-dark, .ipr-2026 .btn-white {
    transition: none;
  }

}


/* Centered CTA under a section grid */
.ipr-2026 .btn-center {
  display: flex;
  justify-content: center;
  margin-top: var(--space-6);
}


/* icon-tile — icon-led tile */

/* 56x56 rounded square. Place a Lucide SVG icon inside (aria-hidden="true" on
   the tile div; descriptive text comes from the card heading). The icon renders
   in the tile's accent colour on a semi-transparent same-colour fill. */

.ipr-2026 .icon-tile {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-md);
  flex-shrink: 0;
  background: var(--color-accent-12);
  margin-bottom: var(--space-2);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-accent-dark);
}


.ipr-2026 .icon-tile svg {
  width: 26px;
  height: 26px;
  stroke: currentColor;
  stroke-width: 1.75;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}


/* Three fills — rotate across a grid for visual rhythm */
.ipr-2026 .icon-tile--green { background: var(--color-positive-12); color: var(--color-positive-dark); }

.ipr-2026 .icon-tile--ink { background: var(--color-ink-10);      color: var(--color-ink-deep);      }

.ipr-2026 .icon-tile--warm { background: var(--color-sand-30);     color: var(--color-accent-dark);   }


/* ph — dashed placeholder box standing in for an image asset */

.ipr-2026 .ph {
  /* Subtle but READABLE: a faint fill + a slightly stronger dashed border than
     ink-10 so the box always reads as an intentional media slot (an invisible
     placeholder on white looked broken). */
  border: var(--border-width-2) dashed var(--color-ink-20);
  background: var(--color-ink-06);
  border-radius: var(--radius-xs);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  text-align: center;
  padding: var(--space-5);
  min-height: 320px;
}


.ipr-2026 .ph-tag {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--color-accent-dark);
}


.ipr-2026 .ph-note {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  max-width: 280px;
}


.ipr-2026 .ph img { border-radius: var(--radius-xs); }


/* stat3 — three stats on a light band with vertical dividers */

.ipr-2026 .stat3 {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: center;
  gap: 0;
}


/* Columns axis — the grid template follows the class: one track per stat with
   a divider track between them. Base is three. */
.ipr-2026 .stat3--2 { grid-template-columns: 1fr auto 1fr; }

.ipr-2026 .stat3--4 { grid-template-columns: 1fr auto 1fr auto 1fr auto 1fr; }


/* Stat block */
.ipr-2026 .stat3__item {
  padding: var(--space-4) var(--space-6);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}


/* Vertical divider between stat blocks */
.ipr-2026 .stat3__divider {
  width: 1px;
  height: 60%;   /* ~60% of the cell height — not full-bleed */
  background: var(--color-ink-10);
  align-self: center;
}


/* The numeral — headline scale, extrabold */
.ipr-2026 .stat3__num {
  font-family: var(--font-sans);
  font-size: var(--text-3xl);
  font-weight: var(--weight-extrabold);
  line-height: var(--leading-tight);
  /* Colour sequence — never change order */
}


.ipr-2026 .stat3__item:nth-child(1) .stat3__num { color: var(--color-accent); }

.ipr-2026 .stat3__item:nth-child(3) .stat3__num { color: var(--color-ink); }

.ipr-2026 .stat3__item:nth-child(5) .stat3__num { color: var(--color-positive-dark); }

.ipr-2026 .stat3__item:nth-child(7) .stat3__num { color: var(--color-accent); }


/* Caption — bumped xs -> sm (2026-07-07): the all-caps micro-label under a
   headline-scale number read too small at that combination. */
.ipr-2026 .stat3__caption {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--color-text-muted);
  line-height: var(--leading-normal);
  max-width: 20ch;
}


/* Mobile: single column, horizontal dividers */
@media (max-width: 640px) {
  .ipr-2026 .stat3 {
    grid-template-columns: 1fr;
  }


  .ipr-2026 .stat3__divider {
    width: 60%;
    height: 1px;
    justify-self: center;
  }


  .ipr-2026 .stat3__item {
    padding: var(--space-4) var(--space-3);
  }

}


/* accordion — native details/summary FAQ list */

.ipr-2026 .accordion {
  width: 100%;
}


/* Narrow (prose) variant — default */
.ipr-2026 .accordion--prose {
  max-width: var(--max-prose);
  margin-inline: auto;
}


/* NOTE: Accordions are ALWAYS single-column. They must never be split
   into two columns — a multi-column accordion breaks the open/close
   reading order and the +/− affordance. The previous .accordion--wide
   two-column variant has been removed. Width is controlled by
   .accordion--prose (narrow) only. */

/* FAQ group label — divides thematic clusters */
.ipr-2026 .fgroup {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--color-accent-dark);
  padding: var(--space-4) 0 var(--space-2);
  border-bottom: 1px solid var(--color-ink-10);
  margin-bottom: 0;
}


/* FAQ item */
.ipr-2026 .accordion details {
  border-bottom: 1px solid var(--color-ink-10);
}


.ipr-2026 .accordion summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-2-5) 0;   /* tightened FAQ rhythm (was --space-3) */
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
  cursor: pointer;
  list-style: none;
  gap: var(--space-3);
  transition: color var(--transition-base);
  text-transform: none;   /* questions are sentence case, never all-caps */
}


.ipr-2026 .accordion summary::-webkit-details-marker { display: none; }


/* +/− indicator */
.ipr-2026 .accordion summary::after {
  content: '+';
  font-size: var(--text-lg);
  font-weight: var(--weight-light);
  color: var(--color-accent);
  flex-shrink: 0;
  line-height: 1;
  transition: color var(--transition-base);
}


.ipr-2026 .accordion details[open] summary::after {
  content: '−';
}


.ipr-2026 .accordion summary:hover {
  color: var(--color-accent-dark);
}


.ipr-2026 .accordion summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}


/* Answer body */
.ipr-2026 .accordion details > *:not(summary) {
  padding: 0 0 var(--space-2-5);   /* tightened FAQ rhythm (was --space-3) */
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: var(--leading-normal);
  text-transform: none;   /* DS RULE: expanded answers are ALWAYS sentence case —
                             a stray uppercase wrapper (e.g. a misused .fgroup on
                             the <details>) can never force an all-caps answer. */
}


.ipr-2026 .accordion details > p {
  margin: 0;
}


/* ── Category filter (.accordion--tabs) ──────────────────────────
   Chip tabs that switch full-width Q&A panels — the right shape when an FAQ is
   split into sections and one two-column panel does not fit a stacked Q&A list.
   .tablist and .tab live here because nothing else uses them.

   Markup:
     <div class="accordion--tabs">
       <div class="tablist" role="tablist">
         <button class="tab" role="tab" aria-selected="true"  data-target="faq-a">Basics</button>
         <button class="tab" role="tab" aria-selected="false" data-target="faq-b">Pricing</button>
       </div>
     </div>
     <div class="faq-panel" id="faq-a" data-active="true">
       <div class="accordion accordion--prose"> …<details>… </div>
     </div>
     <div class="faq-panel" id="faq-b"> … </div>

   The small JS that toggles data-active on click / arrow keys lives on the
   page (see the free-skill spec). CSS only handles show/hide + spacing. */
.ipr-2026 .accordion--tabs { margin-bottom: var(--space-5); }

.ipr-2026 .faq-panel:not([data-active]) { display: none; }


/* Tab button row */
.ipr-2026 .tablist {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1-5);
  list-style: none;
  margin: 0;
  padding: 0;
}


/* Individual tab button */
.ipr-2026 .tab {
  display: inline-flex;
  align-items: center;
  padding: 10px 22px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  border: var(--border-width) solid var(--color-ink-10);
  background: var(--color-white);
  color: var(--color-text-muted);
  transition:
    background var(--transition-base),
    border-color var(--transition-base),
    color var(--transition-base);
}


.ipr-2026 .tab:hover {
  border-color: var(--color-ink);
  color: var(--color-ink);
}


/* Active tab */
.ipr-2026 .tab[aria-selected="true"] {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-white);
}


.ipr-2026 .tab:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}


@media (prefers-reduced-motion: reduce) {
  .ipr-2026 .tab {
    transition: none;
  }

}


/* steps — numbered horizontal process row, stacks on mobile */

.ipr-2026 .steps {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--space-6);
  margin-top: var(--space-8);
}

.ipr-2026 .step {
  position: relative;
  text-align: center;
}

.ipr-2026 .step-num {
  width: 44px;
  height: 44px;
  margin: 0 auto var(--space-3);
  border-radius: 50%;
  background: var(--color-ink);
  color: var(--color-white);
  font-weight: 700;
  font-size: var(--text-md);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 1;
}

.ipr-2026 .step:not(:last-child)::before {
  content: "";
  position: absolute;
  top: 22px;
  left: calc(50% + 30px);
  width: calc(100% + var(--space-6) - 60px);
  border-top: 2px dashed var(--color-border);
}

.ipr-2026 .step h3 { font-size: var(--text-lg); margin-bottom: var(--space-1); }

.ipr-2026 .step p { color: var(--color-text-muted); }


@media (max-width: 800px) {
  .ipr-2026 .steps { grid-auto-flow: row; gap: var(--space-5); }

  .ipr-2026 .step {
    display: grid;
    grid-template-columns: 44px 1fr;
    column-gap: var(--space-3);
    text-align: left;
    align-items: start;
  }

  .ipr-2026 .step-num { grid-row: 1 / span 2; margin: 0; }

  .ipr-2026 .step h3 { grid-column: 2; }

  .ipr-2026 .step p { grid-column: 2; }

  .ipr-2026 .step:not(:last-child)::before {
    top: 48px;
    left: 21px;
    width: 0;
    height: calc(100% - 44px);
    border-top: none;
    border-left: 2px dashed var(--color-border);
  }

}


/* statement — oversized two-tone editorial headline */

.ipr-2026 .statement {
  font-size: var(--text-2xl);   /* a bold statement, but not hero-huge */
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
  max-width: 20em;   /* ~2 lines for a long two-tone statement */
  margin: 0;
}

/* Two-tone: the base is navy (prevailing) and the __rest is the ORANGE accent —
   keep the accent span SHORT so navy stays dominant. (Large display text, so the
   accent clears AA large-text contrast on white.) */
.ipr-2026 .statement__rest { color: var(--color-accent); }


/* Optional two-column foot under the statement. A hairline rule divides the
   bold statement from the foot content below it. */
.ipr-2026 .statement-foot {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: start;
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: var(--border-width) solid var(--color-border);
}

.ipr-2026 .statement-foot h3 {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  line-height: var(--leading-snug);
  margin: 0 0 var(--space-3);
}

.ipr-2026 .statement-foot p {
  font-size: var(--text-md);
  color: var(--color-text);
  line-height: var(--leading-normal);
  margin: 0;
}


@media (max-width: 760px) {
  .ipr-2026 .statement { max-width: none; }

  .ipr-2026 .statement-foot { grid-template-columns: 1fr; gap: var(--space-4); }

}


/* ftiles — grid of compact feature tiles */

.ipr-2026 .ftiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2-5);
}


.ipr-2026 .ftile {
  background: var(--color-white);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-xs);
  padding: 26px 24px;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  transition: border-color var(--transition-base), background var(--transition-base);
}


@media (prefers-reduced-motion: no-preference) {
  .ipr-2026 .ftile:hover { background: var(--color-blue-tint); }

}


/* Brand-tint chip — accent fill, centred Lucide icon (18px stroke).
   Usage: <div class="ic" aria-hidden="true"><i data-lucide="name"></i></div>
   Icon inherits color: --color-accent-dark from .ic. Never emoji or text. */
.ipr-2026 .ftile .ic {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  background: var(--color-accent-12);
  color: var(--color-accent-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-bottom: var(--space-1);
}


.ipr-2026 .ftile .ic svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}


.ipr-2026 .ftile b {
  display: block;
  font-size: var(--text-md);
  color: var(--color-ink);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  letter-spacing: -0.015em;
}


.ipr-2026 .ftile span {
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: var(--leading-normal);
}


/* Mobile: two cramped ~150px columns read badly on phones — stack. */
@media (max-width: 480px) {
  .ipr-2026 .ftiles { grid-template-columns: 1fr; }

}


/* shead — a section's heading block */

/* Section heading block (.shead) — chip + h2 + optional lead.
   The 48px bottom margin creates consistent breathing room above grids. */
.ipr-2026 .shead {
  margin-bottom: var(--space-6);
}


/* The chip carries no outside margin; the heading block owns the space
   under it. */
.ipr-2026 .shead > .chip {
  margin-bottom: var(--space-2-5);
}


.ipr-2026 .shead--center {
  text-align: center;
  max-width: 720px;
  margin-inline: auto;
  margin-bottom: var(--space-6);
}


.ipr-2026 .shead h2 {
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-2);
}


.ipr-2026 .shead .lead {
  font-size: var(--text-md);
  font-weight: var(--weight-regular);
  color: var(--color-text);
  line-height: var(--leading-normal);
  margin: 0;
}


/* card — the card surface and the kinds built on it */

/* --- Card shell (shared) -------------------------------------- */
/* PROHIBITED: do not add border-top / box-shadow overrides to
   individual cards to create a "featured" look. Visual equality
   within a grid is a hard rule — hierarchy comes from copy, not
   from singling out one card. THE ONE EXCEPTION is the pricing
   grid: a price comparison is meant to steer the eye, so the
   sanctioned .card--price / .card--price.is-featured variant (§17)
   MAY carry a stronger border + soft elevation + a solid chip.
   That exception applies to pricing cards only — never to content
   grids (challenges, use-cases, benefits, etc.).
   PROHIBITED: never leave an .icon-tile slot without a Lucide icon.
   PROHIBITED: .btn-primary inside a .card is banned — a gradient CTA
   competes with the card surface and breaks visual hierarchy. Use
   .btn-ghost inside cards (on white bg) or .btn-on-dark inside
   .card--glass. The rule below enforces this automatically. */

/* DS RADIUS LANGUAGE (2026-07): all card / panel / media-placeholder SURFACES
   use --radius-xs (a crisp 6px), system-wide — .card + every variant, .ftile,
   .tabbed-panels__panel, .text-cards, .form-card, and the
   .ph placeholder + card imagery all share it, so boxes read as
   one sharp family. PILLS keep their shape (buttons, .chip = --radius-pill)
   and the small ICON tiles keep their softer
   rounding (.icon-tile = --radius-md, .ftile .ic = --radius-sm) as a deliberate
   soft-chip-on-sharp-card contrast. Do not set a larger radius on a card on a page. */
.ipr-2026 .card {
  background: var(--color-white);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-xs);
  padding: 26px 24px;
  transition: border-color var(--transition-base), background var(--transition-base);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  /* Content ALWAYS aligns to the top. When cards in a grid stretch to equal
     height, shorter cards must keep their content anchored to the top edge —
     never centred or pushed to the bottom. Do not override justify-content on
     a card to bottom/centre; a trailing CTA that should sit at the base uses
     margin-top:auto on that single element, not justify-content on the card. */
  justify-content: flex-start;
}


.ipr-2026 .card:hover {
  background: var(--color-blue-tint);
}


/* Button-inside-card enforcement: .btn-primary placed inside a .card
   is automatically rendered as .btn-ghost (secondary). This prevents
   gradient CTAs competing with the card surface. The only valid button
   inside a .card is .btn-ghost. Do not override this rule on pages. */
.ipr-2026 .card .btn-primary {
  background: transparent;
  border: var(--border-width-2) solid var(--color-ink-10);
  color: var(--color-ink);
  filter: none;
  box-shadow: none;
}


.ipr-2026 .card .btn-primary:hover {
  background: var(--color-ink-06);
  border-color: var(--color-ink);
  transform: none;
  box-shadow: none;
  filter: none;
}


.ipr-2026 .card h3 {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  line-height: var(--leading-snug);
  margin: 0;
}


.ipr-2026 .card p {
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  color: var(--color-text);
  line-height: var(--leading-normal);
  margin: 0;
}


/* --- Optional mini-graphic slot (.card__media) ---------------- */
/* A compact 16:10 thumbnail (an <img> or a .ph placeholder) at the TOP of a
   standard .card, above the kicker/heading. Gives a content grid a graphic
   per card without switching to .card--media. Place it as
   the first child of the .card. Do not combine with an .icon-tile icon in the
   same card — pick one visual anchor. */
.ipr-2026 .card__media {
  margin: -2px 0 var(--space-1);
  border-radius: var(--radius-xs);
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--color-ink-06);
}

.ipr-2026 .card__media > img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

.ipr-2026 .card__media > .ph {
  width: 100%; height: 100%;
  min-height: 0;
  border-radius: 0;
  padding: var(--space-2);
}


/* --- Optional corner-graphic accent (.card__corner-graphic) ---- */
/* A triangular clip of a graphic, zoomed in and tucked into the bottom-right
   corner of a card, behind the text. A quieter alternative to `.card__media`
   when a card wants a texture/brand-pattern accent rather than a literal
   thumbnail. Host card needs `position:relative; overflow:hidden` and extra
   `padding-bottom` (~var(--space-10)) so the graphic doesn't crowd the copy.
   Recommended default fill for the host card is `--color-ink-06` (a quiet
   neutral wash) — pairing this with a vivid `.card--color` fill on top of a
   colourful source image reads as "too much colour" (v0.14 feedback); reserve
   the colour-block treatment for cards that do NOT carry this accent.
   Place as the LAST child of the card so it renders behind sibling content
   once `position:relative; z-index:1` is set on the other children. */
.ipr-2026 .card__corner-graphic {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 140px;
  height: 140px;
  object-fit: cover;
  clip-path: polygon(100% 0%, 100% 100%, 0% 100%);
  opacity: 0.55;
  transform: scale(1.6);
  transform-origin: bottom right;
  z-index: 0;
  pointer-events: none;
}


/* --- Variant A: Label-led (.card--label) ---------------------- */
/* A chip above the h3. Its look is the chip's; the card owns the space under
   it — this margin plus the card's own gap, the step the label card has
   always had. .card--label adds nothing else: it is the marker that says
   "this card leads with a chip". */
.ipr-2026 .card--label > .chip { margin-bottom: var(--space-2); }


/* --- Variant C: Glass tile on dark (.card--glass) ------------- */
/* Semi-transparent surface for card grids on section--ink bands.
   Must ONLY be used on dark backgrounds. */

.ipr-2026 .card--glass {
  background: var(--on-dark-06);
  border: 1px solid var(--on-dark-12);
  box-shadow: none;
  border-radius: var(--radius-xs);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  transition:
    border-color var(--transition-base),
    background var(--transition-base);
}


.ipr-2026 .card--glass:hover {
  background: var(--on-dark-12);
  border-color: var(--on-dark-20);
  transform: none; /* no lift on dark — shadow-less surface */
  box-shadow: none;
}


/* A glass card leads with either a compact <strong> label or an h3, then a
   caption (p). All three are styled below. */
.ipr-2026 .card--glass strong {
  color: #fff;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
}


.ipr-2026 .card--glass h3 {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: #fff;
  line-height: var(--leading-snug);
  margin: 0;
}


.ipr-2026 .card--glass p {
  font-size: var(--text-sm);
  color: var(--color-on-dark-muted);
  line-height: var(--leading-snug);
  margin: 0;
}


/* --- Variant D: Colour-block card (.card--color) -------------- */
/* Full coloured background, chip label top, heading + body below.
   Use on a WHITE section band only, for a small set (3) of parallel
   benefits where colour itself is the visual anchor (e.g. "Why X").
   Content top-aligns and the card sizes to content — never force a
   min-height that pushes the heading to the bottom. */

.ipr-2026 .card--color {
  border-radius: var(--radius-xs);
  padding: 34px 30px;
  min-height: 210px;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}


/* Fills — rotate across the grid. Light fills (warm, blue) use ink text;
   the dark fill (ink) uses on-dark text + glass chip. */
.ipr-2026 .card-color-warm { background: var(--color-sand); color: var(--color-ink); }

.ipr-2026 .card-color-blue { background: var(--color-blue-card); color: var(--color-ink); }

.ipr-2026 .card-color-ink { background: var(--color-ink);  color: var(--color-on-dark); }


/* .card--color is flat — no elevation on hover. FIX (2026-07-07): every
   .card--color also carries the base `.card` class, and `.card:hover` sets
   `background: var(--color-blue-tint)` at higher specificity (class+pseudo beats
   the single fill class), silently washing out the colour fill on hover — on
   `.card-color-ink` this left white heading/body text sitting on a pale grey
   background. Restate each fill's background under :hover so the card truly
   stays flat, "no elevation" all the way down. */
.ipr-2026 .card-color-warm:hover { background: var(--color-sand); }

.ipr-2026 .card-color-blue:hover { background: var(--color-blue-card); }

.ipr-2026 .card-color-ink:hover { background: var(--color-ink); }


/* Per-card chip (v3.6): the chip sits at the TOP of the card and each one is a
   tint of its OWN card colour — same hue family, just darker text on a stronger
   tint than the card. The fill decides the tint, so a page never has to pick a
   chip colour inside a colour card. */
.ipr-2026 .card-color-warm > .chip { background: var(--color-accent-12); color: var(--color-accent-dark); }

.ipr-2026 .card-color-blue > .chip { background: var(--color-blue-12);   color: var(--color-blue); }

.ipr-2026 .card-color-ink  > .chip { background: var(--on-dark-20);      color: #fff; }


.ipr-2026 .card--color h3 {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  margin: 18px 0 8px;
}


.ipr-2026 .card-color-warm h3, .ipr-2026 .card-color-blue h3 { color: var(--color-ink); }

.ipr-2026 .card-color-ink  h3 { color: #fff; }


.ipr-2026 .card--color p {
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  margin: 0;
}


/* Explicit body text colours per fill — overrides the shared .card p rule */
.ipr-2026 .card-color-warm p, .ipr-2026 .card-color-blue p { color: var(--color-ink); }

.ipr-2026 .card-color-ink  p { color: var(--color-on-dark); }


@media (prefers-reduced-motion: reduce) {
  .ipr-2026 .card, .ipr-2026 .card--glass, .ipr-2026 .card--color {
    transition: none;
  }

}


/* --- Kind: media-led (.card--media) --------------------------- */
/* Image first in a 16:9 .card__media that bleeds to the card's edges (the
   plain card's optional .card__media stays 16:10 and sits inside the padding),
   then a chip, the heading and copy, an optional .card__note and a .card__cta. */
.ipr-2026 .card--media {
  padding: var(--space-4);
  overflow: hidden;
}


.ipr-2026 .card--media > .card__media {
  position: relative;
  margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) var(--space-2);
  border-radius: 0;
  aspect-ratio: 16 / 9;
  background: var(--color-ink-06);
}


.ipr-2026 .card--media > .card__media > iframe, .ipr-2026 .card--media > .card__media > img, .ipr-2026 .card--media > .card__media > .ph {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  min-height: 0;
  border: 0;
  border-radius: 0;
}


/* Static image fills the 16:9 box and crops centre — no letterboxing. */
.ipr-2026 .card--media > .card__media > img {
  object-fit: cover;
}


/* Footer line under a hairline — an outcome, a date, a source, a reading time. */
.ipr-2026 .card__note {
  font-size: var(--text-sm);
  color: var(--color-text);
  padding-top: var(--space-2);
  border-top: var(--border-width) solid var(--color-border);
}


.ipr-2026 .card__note strong { color: var(--color-accent-dark); }


/* Learn-more link — sits at the bottom of the card (margin-top:auto pins it to
   the foot so links align across a grid of uneven-length cards). Accent
   coloured, the arrow nudges on hover. Use this instead of a bare <a> or a
   (banned) .btn-primary in a card. */
.ipr-2026 .card__cta {
  margin-top: auto;
  align-self: flex-start;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-accent-dark);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-0-5);
  transition: gap var(--transition-base);
}


.ipr-2026 .card__cta::after {
  content: '→';
  transition: transform var(--transition-base);
}


.ipr-2026 .card__cta:hover {
  text-decoration: underline;
}


.ipr-2026 .card__cta:hover::after {
  transform: translateX(3px);
}


@media (prefers-reduced-motion: reduce) {
  .ipr-2026 .card__cta, .ipr-2026 .card__cta::after { transition: none; }

}


/* --- Kind: quotation (.card--quote) --------------------------- */
/* A quote mark, the quotation and the author, in a card grid of any count. */
.ipr-2026 .card--quote {
  padding: var(--space-5);
  gap: var(--space-3);
}


.ipr-2026 .qmark {
  font-size: var(--text-3xl);
  line-height: 0.6;
  color: var(--color-sand);
  font-weight: var(--weight-extrabold);
}


.ipr-2026 .card--quote blockquote {
  font-size: var(--text-md);
  color: var(--color-text);
  line-height: var(--leading-normal);
  font-style: italic;
}


.ipr-2026 .card--quote cite { font-style: normal; margin-top: auto; }


.ipr-2026 .card--quote cite b {
  display: block;
  color: var(--color-accent-dark);
  font-weight: var(--weight-bold);
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
}


.ipr-2026 .card--quote cite span {
  display: block;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}


/* --- Pricing card (.card--price) -----------------------------
   Pricing is a decision surface, so — unlike every other card grid —
   it is ALLOWED to carry emphasis (see the §4 exception). Build a price
   card on .card + .card--price; mark the recommended plan .is-featured.
   This keeps pricing visually louder than the surrounding content grids
   without any per-page box-shadow hacks. */
.ipr-2026 .card--price {
  position: relative;   /* anchors the corner chip */
  padding: var(--space-5) var(--space-4);
  border-width: var(--border-width-2);
  border-color: var(--color-ink-20);
  gap: var(--space-3);
}

.ipr-2026 .card--price:hover { background: var(--color-white); }
   /* no muddy hover tint on a decision surface */

/* Featured / recommended plan — accent border + soft elevation. This is
   the ONLY sanctioned box-shadow on a card, and only on a price card. */
.ipr-2026 .card--price.is-featured {
  border-color: var(--color-accent);
  box-shadow: var(--shadow);
}


/* Emphasis chip — a solid chip pinned to the TOP-RIGHT CORNER of a price card
   (e.g. "Fixed price", "Recommended"). It is absolutely positioned so it sits
   OUT of the vertical flow: the kicker/figure line up across every price card
   whether or not a card carries one (a chip in normal flow pushed the featured
   card's content down a row and broke figure alignment). Author it as a
   child of the .card--price, as `chip chip--solid`. Only the SOLID chip is
   pinned, so a price card can also carry a plain .chip as its plan label
   in normal flow — that is what .card--label gives it. */
.ipr-2026 .card--price > .chip.chip--solid {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
}


/* Feature checklist inside a price card — what the plan includes. Green
   check icons (Lucide) reuse the positive colour. */
.ipr-2026 .price-features {
  list-style: none;
  margin: var(--space-1) 0 0;
  padding: var(--space-3) 0 0;
  border-top: var(--border-width) solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
}

.ipr-2026 .price-features li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1-5);
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-snug);
}

.ipr-2026 .price-features li svg, .ipr-2026 .price-features li i {
  width: 18px; height: 18px;
  flex-shrink: 0;
  margin-top: 1px;
  color: var(--color-positive);
}


/* The second selector is what makes this rule reach a figure inside a card:
   the figure is a <p>, and .card p (0,1,1) would otherwise repaint it as
   plain body text. */
.ipr-2026 .price-figure, .ipr-2026 .card .price-figure {
  font-size: var(--text-2xl);
  font-weight: var(--weight-extrabold);
  color: var(--color-positive-dark);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  margin: 0;
}


/* In a price card the figure carries the section's emphasis — bump it up. */
.ipr-2026 .card--price .price-figure { font-size: var(--text-3xl); }


.ipr-2026 .price-figure small {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  font-style: italic;
  color: var(--color-text-muted);
  margin-top: var(--space-0-5);
}



/* split — a two-column row of copy and a visual */

.ipr-2026 .split {
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  gap: var(--space-7);
  align-items: center;
}


/* Text-column rhythm (2026-07-07 fix): the DS resets all margins to 0, and
   .split's text column is a plain block (no flex `gap`) — only the chip
   carried its own margin-bottom, so a heading/paragraph/CTA stack inside a
   `.split` rendered with zero space before the button. Own the spacing here,
   the same way `.tabbed-panels__panel > div > p` already does. */
.ipr-2026 .split > div > .chip { margin-bottom: var(--space-2-5); }

.ipr-2026 .split > div > h3 { margin: 0 0 var(--space-2); }

.ipr-2026 .split > div > p { margin: 0 0 var(--space-4); }


/* Media side of a split — the image/placeholder column. Accepts a .ph
   placeholder or an <img> (cover-cropped, rounded to match cards). */
.ipr-2026 .split-media {
  width: 100%;
}

.ipr-2026 .split-media img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-xs);
  object-fit: cover;
}

.ipr-2026 .split-media .ph { min-height: 320px; }


/* Alternating text+image ROWS (v3.6).
   Wrap a series of .split rows in .split--rows and they auto-zig-zag:
   row 1 = text-left/media-right (source order), row 2 = media-left/
   text-right, row 3 = text-left, ... — pure CSS, no per-row class.
   Authoring: each child is ONE .split with two children (text, media)
   in that DOM order; the modifier flips the VISUAL order on even rows. */
.ipr-2026 .split--rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
}

.ipr-2026 .split--rows > .split:nth-child(even) > :first-child { order: 2; }

.ipr-2026 .split--rows > .split:nth-child(even) > :last-child { order: 1; }


/* Mobile: a split stacks to one column (text above media). This also
   neutralises the alternating order so reading order stays text->image. */
@media (max-width: 760px) {
  .ipr-2026 .split { grid-template-columns: 1fr; gap: var(--space-5); }

  .ipr-2026 .split--rows > .split:nth-child(even) > :first-child, .ipr-2026 .split--rows > .split:nth-child(even) > :last-child { order: 0; }

}


/* logo-band — a row of partner logos */

.ipr-2026 .logo-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-8);
}


.ipr-2026 .logo-band__item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
}


.ipr-2026 .logo-band__item img {
  height: 100%;
  width: auto;
  max-width: 160px;
  object-fit: contain;
  filter: grayscale(1) opacity(0.55);
  transition: filter var(--transition-base);
}


.ipr-2026 .logo-band__item:hover img {
  filter: grayscale(0) opacity(1);
}


/* .ph placeholder used as a logo stand-in — override its default
   min-height/border/padding so it matches the band's fixed row height
   instead of rendering as a big dashed box.
   DS RULE: a logo placeholder ALWAYS carries a .ph-tag naming the client —
   a blank chip reads as a broken image. The tag is shrunk to fit the small
   silhouette (sentence-cased client name, not the default all-caps micro). */
.ipr-2026 .logo-band__item .ph {
  min-height: 0;
  height: 40px;
  width: 120px;
  padding: 0 var(--space-1);
  border-style: solid;
}

.ipr-2026 .logo-band__item .ph .ph-tag {
  font-size: 0.62rem;
  letter-spacing: var(--tracking-wide);
  text-transform: none;
  color: var(--color-text-muted);
  white-space: nowrap;
}


@media (max-width: 640px) {
  .ipr-2026 .logo-band { gap: var(--space-5); }

  .ipr-2026 .logo-band__item { height: 32px; }

  .ipr-2026 .logo-band__item .ph { height: 32px; width: 100px; }

}


/* ribbon — a full-width banner graphic */

.ipr-2026 .ribbon {
  width: 100%;
  overflow: hidden;
}


/* The image fills the band edge to edge and crops as needed. */
.ipr-2026 .ribbon img {
  display: block;
  width: 100%;
  height: clamp(159px, 18.7vw, 275px);
  object-fit: cover;
  object-position: center;
}


/* Placeholder state — until the ribbon art lands, a .ph fills the band EDGE TO
   EDGE (full width, no rounding), so the reserved area reads at its true size
   rather than as a small centred box. */
.ipr-2026 .ribbon .ph {
  width: 100%;
  max-width: none;
  min-height: clamp(205px, 22vw, 323px);
  border-radius: 0;
  border-left: 0;
  border-right: 0;
}


/* tabbed-panels — a tab strip that swaps detail panels */

/* --- Tab strip ------------------------------------------------ */

.ipr-2026 .tabbed-panels {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1-5);
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0;
}


.ipr-2026 .tabbed-panels__tab {
  display: inline-flex;
  align-items: center;
  padding: 10px 22px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  border: var(--border-width) solid var(--color-border);
  background: transparent;
  color: var(--color-text-muted);
  transition:
    background var(--transition-base),
    border-color var(--transition-base),
    color var(--transition-base);
}


.ipr-2026 .tabbed-panels__tab:hover {
  border-color: var(--color-ink);
  color: var(--color-ink);
  background: var(--color-ink-06);
}


.ipr-2026 .tabbed-panels__tab[aria-selected="true"] {
  background: var(--color-ink-deep);
  border-color: var(--color-ink-deep);
  color: #fff;
}


.ipr-2026 .tabbed-panels__tab:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring, 0 0 0 3px var(--color-accent-12));
}


/* --- Panel: copy + supporting image --------------------------- */

.ipr-2026 .tabbed-panels__panel {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--space-7);
  align-items: center;
  background: var(--grad-cool);
  border-radius: var(--radius-xs);
  padding: var(--space-7);
}


/* One panel per tab; only the active panel renders. Panels stay in
   the DOM so all content is indexable / reachable by screen readers. */
.ipr-2026 .tabbed-panels__wrap { display: none; }

.ipr-2026 .tabbed-panels__wrap[data-active="true"] { display: block; }


@media (max-width: 960px) {
  .ipr-2026 .tabbed-panels__panel {
    grid-template-columns: 1fr;
    padding: var(--space-5);
  }

}


/* Optional chip above the heading. The copy column is a plain block with no
   gap, so the panel owns the space under it. */
.ipr-2026 .tabbed-panels__panel > div > .chip {
  margin-bottom: var(--space-2);
}


.ipr-2026 .tabbed-panels__panel h3 {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  line-height: var(--leading-snug);
  margin: 0 0 var(--space-2);
}


.ipr-2026 .tabbed-panels__panel > div > p {
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: var(--leading-normal);
  margin: 0 0 var(--space-3);
}


/* Green-dot bullet list */
.ipr-2026 .tabbed-panels__panel ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
}


.ipr-2026 .tabbed-panels__panel ul li {
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: var(--leading-normal);
  padding-left: var(--space-3);
  position: relative;
}


.ipr-2026 .tabbed-panels__panel ul li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 9px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-positive);
}


/* Optional stat callout inside the panel copy */
.ipr-2026 .tabbed-panels__stat {
  display: flex;
  align-items: baseline;
  gap: var(--space-1);
  margin: var(--space-3) 0 var(--space-4);
}


/* CTA fix (2026-07-07): whichever element sits last in the copy column
   (the bullet list or the stat) had no bottom margin, so a CTA button
   directly after it rendered flush with zero gap. Both now carry a
   margin-bottom (above); this covers the case where a CTA follows
   neither (e.g. sits right after the intro paragraph, already spaced
   by the panel's own paragraph rule). */

.ipr-2026 .tabbed-panels__stat-num {
  font-size: var(--text-2xl);
  font-weight: var(--weight-extrabold);
  color: var(--color-accent);
  line-height: 1;
}


.ipr-2026 .tabbed-panels__stat-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}


/* Optional CTA — use the standard light-surface .btn-ghost / .btn-primary.
   A bare 'Learn more →' link may use .link-arrow if present. */

/* Supporting image placeholder on the cool panel reads lighter than the
   panel surface so the dashed .ph border stays visible. */
.ipr-2026 .tabbed-panels__panel .ph {
  min-height: 260px;
  background: rgba(255, 255, 255, 0.55);
}


@media (prefers-reduced-motion: reduce) {
  .ipr-2026 .tabbed-panels__tab {
    transition: none;
  }

}


/* card-grid — a grid that lays cards out in equal columns */

/* --- Card grid ----------------------------------------------- */
/* Fit-to-count: pick the count class that matches the number of cards, so no
   ghost slot is left in the last row — .card-grid--1 / --2 / --3 / --4 below.
   Default (no count class) is 3-up; a grid takes two to ten cards, and any
   count that does not fill the last row wraps.
   NEVER set the count with an inline style="--cols:N" — see the collapse
   note below for why that silently breaks the page on a phone. */

.ipr-2026 .card-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: var(--space-4);
}


/* Column-count classes (v0.28). These are the ONLY approved way to change a
   grid's desktop column count. */
.ipr-2026 .card-grid--1 { --cols: 1; }

.ipr-2026 .card-grid--2 { --cols: 2; }

.ipr-2026 .card-grid--3 { --cols: 3; }

.ipr-2026 .card-grid--4 { --cols: 4; }


/* RESPONSIVE COLLAPSE (v0.28) — sets grid-template-columns DIRECTLY.
   It used to re-set --cols, and lost. An inline style="--cols:3" is a
   declaration in the style-attribute origin, which outranks EVERY rule in
   this stylesheet whatever its specificity — so `.card-grid { --cols: 2 }`
   inside a media query could never win, and 3- and 4-up grids stayed 3- and
   4-up at 390px. Overriding the resolved grid-template-columns instead takes
   --cols out of the argument: whatever the variable says, the track count
   below 960px is decided here.
   Trade-off, accepted deliberately: no page can force more than 2 columns
   under 960px, or more than 1 under 640px, by any mechanism. A marketing page
   has no business at 3-up on a phone. Pages that shipped a wider mobile grid
   will look different — that is the fix landing, not a regression. */
@media (max-width: 960px) {
  .ipr-2026 .card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }


  /* A one-up grid stays one up — it is already at the narrowest count. */
  .ipr-2026 .card-grid--1 { grid-template-columns: minmax(0, 1fr); }

}


@media (max-width: 640px) {
  .ipr-2026 .card-grid { grid-template-columns: minmax(0, 1fr); }

}


/* A lone .card--quote in a .card-grid--1 is the full-width quote; the grid
   gives it its width, and this one declaration its larger type. */
.ipr-2026 .card-grid--1 .card--quote blockquote { font-size: var(--text-xl); }


/* Centered note under a card grid (also used under use-case grids). Lives
   here, not in card.css — it sits under a grid, not inside a card (R16). */
.ipr-2026 .price-note {
  max-width: var(--max-prose);
  margin: var(--space-6) auto 0;
  text-align: center;
  font-size: var(--text-base);
  color: var(--color-text);
}


.ipr-2026 .price-note strong { color: var(--color-accent-dark); }


/* bento — an asymmetric grid where cards take different spans instead of a uniform row */

/* --- Bento grid (.bento) ------------------------------------- */
/* An ASYMMETRIC card grid: a 6-column track where cards take different spans,
   so one set of cards can carry visual rhythm (a large lead card + smaller
   supporting ones) instead of a uniform N-up row. Use it for ONE feature/
   benefit cluster per page where variety is the point — not as the default
   grid (that's .card-grid). Children are normal .card (any variant); add a
   span modifier to size them.

   Spans (of 6 cols): default = 2 (thirds). .bento--half = 3, .bento--wide = 4,
   .bento--full = 6; .bento--tall doubles the row height. Compose so each row
   fills 6 (e.g. wide[4] + third[2], or half[3] + half[3], or full[6]).
   A .bento--tall card can hold a .card__media / larger content.

   Collapses to 2 columns ≤960px and 1 column ≤640px (all spans reset). */
.ipr-2026 .bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-rows: minmax(150px, auto);
  gap: var(--space-3);
}

.ipr-2026 .bento > * { grid-column: span 2; }

.ipr-2026 .bento .bento--half { grid-column: span 3; }

.ipr-2026 .bento .bento--wide { grid-column: span 4; }

.ipr-2026 .bento .bento--full { grid-column: span 6; }

.ipr-2026 .bento .bento--tall { grid-row: span 2; }


/* Bento cards are plain white .card surfaces — the visual interest comes from
   the asymmetric layout + the cards' own subtly-tinted icon tiles, not from
   card backgrounds. (Earlier tinted/dark bento fills were reverted.) */

@media (max-width: 960px) {
  .ipr-2026 .bento { grid-template-columns: repeat(2, 1fr); grid-auto-rows: auto; }

  .ipr-2026 .bento > *, .ipr-2026 .bento .bento--half, .ipr-2026 .bento .bento--wide, .ipr-2026 .bento .bento--full { grid-column: span 2; }

  .ipr-2026 .bento .bento--tall { grid-row: auto; }

}

@media (max-width: 640px) {
  .ipr-2026 .bento { grid-template-columns: 1fr; }

  .ipr-2026 .bento > *, .ipr-2026 .bento .bento--half, .ipr-2026 .bento .bento--wide, .ipr-2026 .bento .bento--full { grid-column: span 1; }

}


/* text-cards — a dark band pairing copy with a grid of glass cards */

.ipr-2026 .text-cards {
  background: var(--color-ink);
  border-radius: var(--radius-xs);
  padding: var(--space-8);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: start;
}


.ipr-2026 .text-cards h2 { color: #fff; margin-bottom: var(--space-2); }

.ipr-2026 .text-cards .chip { margin-bottom: var(--space-3); }


/* DS A11Y RULE — the dark band forces its own text/icon tiles to on-dark, so
   content dropped straight into .text-cards (not only .card--glass children)
   can NEVER render dark-on-navy. (A page once placed raw h3 + p items here and
   the headings were invisible.) "Fix once." */
.ipr-2026 .text-cards h3 { color: #fff; }

.ipr-2026 .text-cards p { color: var(--color-on-dark); }

.ipr-2026 .text-cards .icon-tile { background: var(--on-dark-12); color: #fff; }


.ipr-2026 .text-cards > div > p {
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  margin-bottom: var(--space-5);
}


.ipr-2026 .text-cards-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}


/* Mobile: copy + 2×2 glass grid were rendering as a 2-column outer grid
   feeding a 2-column inner grid — four squeezed slivers on a phone.
   Stack the band first, then simplify the glass grid to one column. */
@media (max-width: 760px) {
  .ipr-2026 .text-cards {
    grid-template-columns: 1fr;
    padding: var(--space-5);
    gap: var(--space-5);
  }

}

@media (max-width: 640px) {
  .ipr-2026 .text-cards-grid { grid-template-columns: 1fr; }

}


/* section — a band with its own background and vertical rhythm */

/* Section band — owns its own vertical rhythm.
   Pair with a background modifier: .section--white, .section--paper, etc. */
.ipr-2026 .section {
  padding-block: var(--section-y);
}


.ipr-2026 .section--compact {
  padding-block: var(--section-y-compact);
}


.ipr-2026 .section--large {
  padding-block: var(--section-y-large);
}


/* Background band modifiers. Authors must NEVER set a section background
   with an inline style="background-color:…". Use a class. */
.ipr-2026 .section--white { background: var(--color-white); }

.ipr-2026 .section--paper { background: var(--color-paper); }

.ipr-2026 .section--cool { background: var(--grad-cool); }

.ipr-2026 .section--ink { background: var(--color-ink-deep); }

.ipr-2026 .section--warm { background: var(--grad-warm); }


/* DS A11Y RULE: the chip has no accessible treatment on the warm band
   (orange-on-orange / sand-on-sand both fail AA). Warm sections lead with the
   h2 — a chip sitting on a .section--warm band is hidden if present, so a page
   can't ship an inaccessible chip in an orange SECTION. (Catalog: a chip is
   NOT valid in .section--warm; use .section--ink or a light band if you need
   one.) The rule is band-level, not surface-level: another warm surface,
   .cta-ribbon (also var(--grad-warm)), is not covered, and that
   gap is a Gate D question.
   The hide covers every chip sitting ON the band: one that leads a heading
   block, one placed straight in the band's .wrap, and one in a .card--glass
   (glass is the band showing through, not a surface of its own). It does not
   cover a chip inside a normal card — that card brings its own surface, and
   deleting the chip in a `card--price` or a `card--label` is not what this
   rule is for. */
.ipr-2026 .section--warm :where(.shead, .hero-copy, .split > div, .wrap) > .chip, .ipr-2026 .section--warm .card--glass .chip { display: none; }


/* h2 on dark backgrounds */
.ipr-2026 .section--ink .shead h2, .ipr-2026 .section--ink .shead--center h2, .ipr-2026 .section--warm .shead h2, .ipr-2026 .section--warm .shead--center h2 {
  color: #fff;
}


/* Heading colour rule (v0.13.4): on the cool-grad band, section headings are
   ALWAYS brand green (AA-safe dark step). Elsewhere headings stay single-colour
   ink; a heading never mixes more than 2 colours (the .statement's ink + accent
   tail is the sanctioned two-tone moment). Never green type on dark bands. */
.ipr-2026 .section--cool .shead h2, .ipr-2026 .section--cool .shead--center h2 {
  color: var(--color-positive-dark);
}


.ipr-2026 .section--ink .shead .lead, .ipr-2026 .section--ink .shead--center .lead, .ipr-2026 .section--warm .shead .lead, .ipr-2026 .section--warm .shead--center .lead {
  color: var(--color-on-dark-muted);
}


/* DS A11Y RULE (v0.28) — DARK-BAND TEXT IN THE DS's OWN TEXT POSITIONS.
   Everything above colours text inside a .shead. Two positions the DS itself
   documents were left uncoloured, so they inherited the light-surface
   --color-text (#3F3F3F) and measured 1.07:1 on --color-ink-deep — invisible:

     1. a heading or paragraph placed straight into the band's .wrap,
        without a .shead around it;
     2. the text column of a .split — the spec's own recommended pattern for
        an interior ink spotlight. (The `.split > div > h3/p` margin rule in
        §14 already assumes exactly this shape.)

   Four of five pilot pages hand-wrote the same override for position 2. A tax
   paid four times is a system gap, not four author errors.

   Deliberately NARROW — direct children only, and no band-level
   `color: inherit`. A rule like `.section--ink { color: var(--color-on-dark) }`
   would look tidier and is WRONG: a translucent panel such as `.card--glass`
   sets no colour of its own, so it inherits — the band rule would turn its
   body copy white on a white glass fill.

   Bespoke content on a dark band (custom lists, inline spans, page-invented
   blocks) is still the author's job: put it on --color-on-dark /
   --color-on-dark-muted — the rule for that lives in rules.md. */
.ipr-2026 .section--ink > .wrap > h2, .ipr-2026 .section--ink > .wrap > h3, .ipr-2026 .section--ink .split > div > h3 {
  color: #fff;
}


.ipr-2026 .section--ink > .wrap > p, .ipr-2026 .section--ink .split > div > p {
  color: var(--color-on-dark);
}


/* DS A11Y RULE — a chip on DARK surfaces is ALWAYS the sand treatment.
   The default .chip is a terracotta tint on a faint terracotta fill: on a
   navy band that is orange-on-navy, which fails AA. Rather than trust every
   author to remember `.chip--sand` on dark bands, the system self-corrects:
   any .chip sitting on a dark BAND — .section--ink and .hero in hero.css —
   is re-tinted to the sand palette, whatever class the page used. That is
   the "fix once" guarantee, and it is band-level, not system-wide: a dark
   surface that is not one of those bands (.text-cards) keeps the accent
   chip, which is a Gate D question.
   Mirrors the existing .section--warm chip suppression above.
   Like that rule it reaches every chip sitting ON the band — one that leads a
   heading block, one placed straight in the band's .wrap, and one in a
   .card--glass, where the band shows through the translucent fill. It does not
   reach a chip inside a normal card: that card is a light surface of its own,
   where sand-on-white would be the illegible thing, and its chip colour comes
   from the card (see card.css). (The light .hero--paper surface is excluded —
   it keeps the accent tint; the same rule for the hero band lives in
   hero.css.) */
.ipr-2026 .section--ink :where(.shead, .hero-copy, .split > div, .wrap) > .chip, .ipr-2026 .section--ink .card--glass .chip {
  color: var(--color-sand);
  background: var(--color-sand-30);
}


/* DS A11Y RULE — placeholder on DARK surfaces. The default ink border + accent
   text vanish on navy. On any dark band the .ph flips to a light-on-dark
   treatment (light glass fill, light hairline, sand tag, muted-white note) so
   it stays subtle yet readable. "Fix once": a placeholder can never be an
   invisible box on navy again. The same rule for the hero band lives in
   hero.css. */
.ipr-2026 .section--ink .ph {
  border-color: var(--on-dark-40);
  background: var(--on-dark-06);
}

.ipr-2026 .section--ink .ph-tag { color: var(--color-sand); }

.ipr-2026 .section--ink .ph-note { color: var(--color-on-dark-muted); }


/* Steps on dark bands — auto-correct (v0.13.5). Without this, .steps on navy
   shipped grey-on-navy body text, an ink-on-ink number circle, and an
   invisible dark connector. Same self-correcting contract as .chip / .ph. */
.ipr-2026 .section--ink .step h3 { color: var(--color-on-dark); }

.ipr-2026 .section--ink .step p { color: var(--color-on-dark-muted); }

.ipr-2026 .section--ink .step-num {
  background: var(--color-white);
  color: var(--color-ink);
}

.ipr-2026 .section--ink .step:not(:last-child)::before { border-color: var(--on-dark-40); }


/* On dark bands the statement base flips to white; the accent becomes sand. */
.ipr-2026 .section--ink .statement { color: var(--color-white); }

.ipr-2026 .section--ink .statement__rest { color: var(--color-sand); }


/* On dark bands the divider uses the on-dark hairline. */
.ipr-2026 .section--ink .statement-foot { border-color: var(--on-dark-20); }

.ipr-2026 .section--ink .statement-foot h3 { color: var(--color-white); }

.ipr-2026 .section--ink .statement-foot p { color: var(--color-on-dark-muted); }


/* nav — a dark sticky bar with the logo, links and a call to action */

.ipr-2026 nav {
  background: var(--color-ink);
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}


.ipr-2026 .nav-inner {
  max-width: var(--max-content);
  margin: 0 auto;
  padding: 0 var(--wrap-x);
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}


.ipr-2026 .nav-inner img { height: 34px; width: auto; }


.ipr-2026 nav ul {
  display: flex;
  align-items: center;
  gap: var(--space-0-5);
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
}


.ipr-2026 nav ul li a {
  color: var(--color-on-dark);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  text-decoration: none;
  transition: background var(--transition-base), color var(--transition-base);
}


.ipr-2026 nav ul li a:hover { background: var(--on-dark-12); color: #fff; }


/* Nav CTA — lives OUTSIDE <ul> as <a class="btn-on-dark"> in .nav-inner.
   Authoring pattern:
     <ul>…nav links…</ul>
     <a href="…" class="btn-on-dark">CTA label</a>
   Compact override height-matches it to the nav link rows. */
.ipr-2026 nav .btn-on-dark {
  padding: 8px 18px;
  font-size: var(--text-sm);
  line-height: 1;
  /* The shared button base sets align-self:flex-start (so buttons hug their
     label in flex-column cards/forms). In the horizontal, center-aligned nav
     row that pinned the CTA to the top edge — override back to center so it
     sits level with the nav links. */
  align-self: center;
}


/* Mobile: nav-inner had a fixed 64px height, so a wrapping link list
   (nav ul already sets flex-wrap: wrap) was clipped/overlapping instead
   of growing. Kept as the fallback for any page that hasn't added a
   .nav-toggle button — see the hamburger pattern below, which is now the
   RECOMMENDED mobile nav and supersedes this on pages that adopt it. */
@media (max-width: 640px) {
  .ipr-2026 .nav-inner {
    height: auto;
    flex-wrap: wrap;
    padding-block: var(--space-2);
    row-gap: var(--space-1);
  }

  .ipr-2026 nav ul { gap: 4px; }

  .ipr-2026 nav ul li a { padding: 7px 12px; font-size: var(--text-xs); }

  .ipr-2026 nav .btn-on-dark { padding: 7px 14px; font-size: var(--text-xs); }

}


.ipr-2026 .nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  flex-shrink: 0;
  border: var(--border-width) solid var(--on-dark-20);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-on-dark);
  cursor: pointer;
}

.ipr-2026 .nav-toggle:hover { background: var(--on-dark-12); }

/* Lucide replaces the authored <i data-lucide> with an <svg>, so the rule
   has to name both the authored element and the rendered one. */
.ipr-2026 .nav-toggle svg, .ipr-2026 .nav-toggle i { width: 20px; height: 20px; }


@media (max-width: 780px) {
  .ipr-2026 .nav-inner { flex-wrap: wrap; }

  .ipr-2026 .nav-toggle { display: inline-flex; order: 3; }

  .ipr-2026 .nav-toggle ~ .btn-on-dark { order: 2; margin-left: auto; }


  /* The link list becomes a full-width dropdown, closed by default. */
  .ipr-2026 .nav-toggle ~ ul {
    display: none;
    order: 4;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: var(--border-width) solid var(--on-dark-12);
  }

  .ipr-2026 .nav-toggle ~ ul li a { display: block; padding: 12px 14px; }

  .ipr-2026 nav[data-nav-open="true"] .nav-toggle ~ ul { display: flex; }

  .ipr-2026 nav[data-nav-open="true"] .nav-inner { height: auto; padding-block: var(--space-2); }

}


/* hero — a large intro band carrying the page headline */

/* DS A11Y RULE — a chip sitting ON the hero band is always the sand
   treatment; see the same rule for the dark bands in section.css. It reaches
   the chip that leads a heading block, the one placed straight in
   .hero-inner, and the one in a .card--glass (glass is the band showing
   through). It does not reach a chip inside a normal card on the band — that
   card brings its own light surface, where sand would be illegible. */
.ipr-2026 .hero :where(.hero-copy, .shead, .split > div, .hero-inner) > .chip, .ipr-2026 .hero .card--glass .chip {
  color: var(--color-sand);
  background: var(--color-sand-30);
}

.ipr-2026 .hero--paper :where(.hero-copy, .shead, .split > div, .hero-inner) > .chip, .ipr-2026 .hero--paper .card--glass .chip {
  color: var(--color-accent-dark);
  background: var(--color-accent-12);
}


.ipr-2026 .hero {
  background: var(--grad-ink);
  position: relative;
  overflow: hidden;
}


.ipr-2026 .hero::before {
  content: '';
  position: absolute;
  width: 640px;
  height: 640px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--color-sand-20) 0%, transparent 70%);
  top: -160px;
  right: -120px;
  pointer-events: none;
  z-index: 0;
}


.ipr-2026 .hero-inner {
  max-width: var(--max-content);
  margin-inline: auto;
  padding-inline: var(--wrap-x);
  padding-block: var(--section-y-large);
  position: relative;
  z-index: var(--z-content);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-10);
  align-items: center;
}


.ipr-2026 .hero-copy { max-width: 620px; }


/* The copy column is a plain block with no gap, so it owns the space under
   its chip. */
.ipr-2026 .hero-copy > .chip {
  margin-bottom: var(--space-2-5);
}


/* Same rule for the space above the trust row: the container owns the gap,
   the trust row carries no outside margin of its own. */
.ipr-2026 .hero-copy > .trust-row {
  margin-top: var(--space-3);
}


/* --- Trust row: the claims under the buttons, each with a check ---
   Moved here from its own component in v1: a trust row is a hero
   element, not a component. The class names are unchanged. */
.ipr-2026 .trust-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}


.ipr-2026 .trust-row__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-0-5);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  color: var(--color-on-dark-muted);
  line-height: 1;
}


/* Light variant — a trust row on a light surface. The paper hero recolours
   the row itself further down, so the modifier changes nothing there. */
.ipr-2026 .trust-row--light .trust-row__item {
  color: var(--color-text-muted);
}


/* Divider between items */
.ipr-2026 .trust-row__sep {
  color: rgba(255, 255, 255, 0.20);
  font-size: var(--text-xs);
  user-select: none;
}


.ipr-2026 .trust-row--light .trust-row__sep {
  color: var(--color-ink-10);
}


/* Checkmark mark */
.ipr-2026 .trust-row__item::before {
  content: '✓';
  font-size: var(--text-xs);
  color: var(--color-sand);
  font-weight: var(--weight-bold);
}


.ipr-2026 .trust-row--light .trust-row__item::before {
  color: var(--color-positive);
}


/* A block, so the margin below it is real and it does not share a line
   box with whatever follows. It centres with the hero, not with the
   text, so the centred forms give it an auto inline margin. */
.ipr-2026 .hero-logo {
  display: block;
  height: 56px;
  width: auto;
  margin-bottom: var(--space-4);
}


.ipr-2026 .hero h1 {
  font-size: var(--text-3xl);          /* DS fix: hero headline must use its own scale */
  font-weight: var(--weight-extrabold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: #fff;
  margin-bottom: var(--space-3);
}

.ipr-2026 .hero h1 .hl { color: var(--color-sand); }


.ipr-2026 .hero-copy > p {
  color: var(--color-on-dark);   /* DS fix: default hero band is navy — desc must be white.
                                    The light .hero--paper hero overrides this to --color-text below. */
  font-size: var(--text-md);
  font-weight: var(--weight-regular);
  line-height: var(--leading-normal);
  margin-bottom: var(--space-5);
}


.ipr-2026 .hero-media .ph { min-height: 420px; }


/* Real <img> in hero-media (v3.7 fix — parity with .split-media img).
   Until this rule existed, hero-media only styled the .ph placeholder;
   a real image dropped in its place had no width/height constraint and
   rendered at native/intrinsic size, blowing out the hero band (seen on
   the Magnetforce landing page, which used the real architecture-diagram
   asset instead of a placeholder). Bound it the same way .split-media
   does, with a max-height so a tall/odd-aspect asset can't stretch the
   band vertically — object-fit: contain keeps a diagram legible instead
   of cropping it like a photo. */
.ipr-2026 .hero-media img {
  width: 100%;
  max-height: 480px;
  object-fit: contain;
  display: block;
  border-radius: var(--radius-xs);
}


/* Mobile: collapse to one column, TEXT FIRST (2026-07-08: dropped the
   `order: -1` that put the image/.ph above the headline — copy is the
   thing a phone visitor should read first; source order already puts
   .hero-copy before .hero-media, so no reorder is needed). */
@media (max-width: 960px) {
  .ipr-2026 .hero-inner {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }

  .ipr-2026 .hero-media .ph { min-height: 240px; }

  .ipr-2026 .hero-media img { max-height: 260px; }

}


/* --- Hero modifiers: centered + photo background -------------- */
/* DEFAULT hero is left-text / right-media (above). These two
   modifiers reconfigure the SAME component — never fork a new hero.

   .hero--centered : single centered column, no media slot. The
                     .hero-media element is simply omitted from the
                     markup; copy is centred and width-capped.
   .hero--photo    : swaps the navy gradient fill for a blurred
                     background photo + a navy gradient SCRIM on top,
                     so centred white text always clears AA contrast.

   USAGE (home hero):
     <section class="hero hero--centered hero--photo section--large"
              style="--hero-photo: url('…jpg');">
       <div class="hero-inner"> <div class="hero-copy"> … </div> </div>
     </section>

   Set the image via the --hero-photo custom property (inline on the
   section, OR a page-level rule). Do NOT place an <img> over the
   scrim — the photo lives in the background layer only (this keeps
   the no-stacked-transparency rule intact: transparency is confined
   to the background, never layered between content elements). */

.ipr-2026 .hero--centered .hero-inner {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
}


.ipr-2026 .hero--centered .hero-copy {
  max-width: 760px;
}


/* Center the CTA pair and trust row when the hero is centered */
.ipr-2026 .hero--centered .btn-pair, .ipr-2026 .hero--centered .trust-row {
  justify-content: center;
}


.ipr-2026 .hero--centered .hero-logo { margin-inline: auto; }


/* Photo background: blurred image layer + navy gradient scrim.
   The ::before atmospheric circle from the base .hero is reused as the
   scrim carrier so we add only ONE extra layer (::after = the photo). */
.ipr-2026 .hero--photo {
  background: var(--grad-ink);   /* fallback before image paints */
  isolation: isolate;
}


/* Photo sits BEHIND everything (z-index 0 layer). Blurred + scaled
   slightly so the blur's soft edges never reveal the band edge. */
.ipr-2026 .hero--photo::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: var(--hero-photo, none);
  background-size: cover;
  background-position: center;
  filter: blur(14px) saturate(1.05);
  transform: scale(1.08);          /* hides blurred edge bleed */
  z-index: 0;
  pointer-events: none;
}


/* Navy gradient scrim — guarantees legibility of centered white text.
   Reuses the base .hero::before slot, repurposed from the radial
   accent circle to a full-bleed directional scrim on photo heroes. */
.ipr-2026 .hero--photo::before {
  content: '';
  position: absolute;
  inset: 0;
  width: auto;       /* override the 640px circle from base .hero */
  height: auto;
  border-radius: 0;  /* override the 50% circle */
  top: 0;
  right: 0;
  background: linear-gradient(180deg,
      rgba(31, 71, 96, 0.6) 0%,
      rgba(31, 71, 96, 0.72) 100%);
  opacity: 0.96;
  z-index: 1;
  pointer-events: none;
}



/* --- Hero modifier: paper (light warm surface) ---------------- */
/* Reconfigures the SAME hero onto a light 'paper' surface — never a fork.
   Combine with the DEFAULT left-copy/right-media layout OR with
   .hero--centered (single centred column, copy-only). Do NOT combine
   with .hero--photo (the photo scrim assumes the dark navy fill).

   Surface-matched secondary CTA: use .btn-ghost here (light surface),
   never .btn-on-dark. The chip keeps the default accent tint,
   not .chip--sand. Media, when present, is a real .ph / <img> —
   never a hand-built mockup. */
.ipr-2026 .hero--paper {
  background: var(--color-paper);
}


/* Warm the base atmospheric radial circle for the light surface. */
.ipr-2026 .hero--paper::before {
  background: radial-gradient(circle, var(--color-sand-30) 0%, transparent 70%);
}


/* Copy flips to ink/text on the light surface. */
.ipr-2026 .hero--paper h1 { color: var(--color-ink); }

.ipr-2026 .hero--paper h1 .hl { color: var(--color-accent); }

.ipr-2026 .hero--paper .hero-copy > p { color: var(--color-text); }


/* Trust row adjusts to the light surface (mirrors .trust-row--light). */
.ipr-2026 .hero--paper .trust-row__item { color: var(--color-text-muted); }

.ipr-2026 .hero--paper .trust-row__item::before { color: var(--color-positive); }

.ipr-2026 .hero--paper .trust-row__sep { color: var(--color-ink-10); }


/* Placeholder on this DARK hero surface — same DS A11Y treatment as the
   band-side .ph in section.css; .hero--paper undoes it below. */
.ipr-2026 .hero .ph {
  border-color: var(--on-dark-40);
  background: var(--on-dark-06);
}

.ipr-2026 .hero .ph-tag { color: var(--color-sand); }

.ipr-2026 .hero .ph-note { color: var(--color-on-dark-muted); }


/* The paper hero is a LIGHT surface — undo the dark-.ph treatment inherited
   from the `.hero .ph` rule above (mirrors the .hero--paper chip reset). */
.ipr-2026 .hero--paper .ph {
  border-color: var(--color-ink-20);
  background: var(--color-ink-06);
}

.ipr-2026 .hero--paper .ph-tag { color: var(--color-accent-dark); }

.ipr-2026 .hero--paper .ph-note { color: var(--color-text-muted); }


/* cta-ribbon — a warm accent band with a call to action */

.ipr-2026 .cta-ribbon {
  background: var(--grad-warm);
  padding-block: var(--section-y-large);
}

.ipr-2026 .cta-ribbon .shead { max-width: 640px; margin: 0 auto; }

.ipr-2026 .cta-ribbon h2 { color: var(--color-white); }

.ipr-2026 .cta-ribbon .lead, .ipr-2026 .cta-ribbon p {
  color: var(--color-white);   /* solid white — no alpha, no muted */
}

/* Belt-and-braces: any button that lands inside the ribbon renders white. */
.ipr-2026 .cta-ribbon .btn-primary, .ipr-2026 .cta-ribbon .btn-ghost, .ipr-2026 .cta-ribbon .btn-on-dark {
  background: var(--color-white);
  color: var(--color-accent-dark);
  border-color: var(--color-white);
}


/* contact-section — a light band pairing copy with a contact form */

.ipr-2026 .contact-section {
  background: var(--grad-cool);
  padding-block: var(--section-y-large);
  position: relative;
  overflow: hidden;
}


.ipr-2026 .contact-section::before {
  content: '';
  position: absolute;
  width: 520px;
  height: 520px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--color-accent-12) 0%, transparent 70%);
  bottom: -160px;
  left: -100px;
  pointer-events: none;
  z-index: 0;
}


.ipr-2026 .contact-inner {
  max-width: var(--max-content);
  margin: 0 auto;
  padding: 0 var(--wrap-x);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: start;
  position: relative;
  z-index: var(--z-content);
}


.ipr-2026 .contact-copy h2 { color: var(--color-ink); margin-bottom: var(--space-2); }


.ipr-2026 .contact-copy p {
  color: var(--color-text);   /* dark — the band is light; was --color-on-dark (illegible) */
  font-size: var(--text-md);
  font-weight: var(--weight-light);
  line-height: var(--leading-normal);
  margin-bottom: var(--space-5);
}


/* Image slot — part of the locked structure: an image (or .ph placeholder)
   sits AFTER the description text in .contact-copy. */
.ipr-2026 .contact-copy .ph { min-height: 320px; }

.ipr-2026 .contact-copy img {
  width: 100%;
  min-height: 320px;
  object-fit: cover;
  border-radius: var(--radius-xs);
}


/* Mobile: copy + form were rendering as two squeezed columns with no
   fallback — stack copy above the form card. */
@media (max-width: 760px) {
  .ipr-2026 .contact-inner {
    grid-template-columns: 1fr;
    gap: var(--space-5);
  }

  .ipr-2026 .contact-copy .ph { min-height: 220px; }

}


.ipr-2026 .form-card {
  background: var(--color-white);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-xs);
  padding: var(--space-5);
}


.ipr-2026 .form-card form { display: flex; flex-direction: column; gap: var(--space-3); }

.ipr-2026 .form-group { display: flex; flex-direction: column; gap: var(--space-0-5); }

/* .form-row: every field inside a form is full-width, stacked.
   Two-column splits are not used — they create uneven label wrapping
   and break the visual rhythm on narrow viewports.
   If a side-by-side pair is ever needed, use two sibling .form-group
   elements inside a .form-row wrapper that overrides grid to 1fr 1fr
   at the section level, not here. */
.ipr-2026 .form-row { display: flex; flex-direction: column; gap: var(--space-3); }


.ipr-2026 .form-card label {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}


.ipr-2026 .form-card input, .ipr-2026 .form-card textarea {
  width: 100%;
  padding: 11px var(--space-2);
  border: var(--border-width) solid var(--color-ink-20);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text);
  font-size: var(--text-base);
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}


.ipr-2026 .form-card input:focus, .ipr-2026 .form-card textarea:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-accent-12);
}


.ipr-2026 .form-card textarea { resize: vertical; min-height: 100px; }

.ipr-2026 .form-card .btn-primary { align-self: center; }
  /* CTA centered in the form (was flex-start) */

.ipr-2026 .form-card small {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  text-align: center;
}


/* The fine print carries the privacy-policy link. The DS styles no <a> at
   element level, so without this the link renders browser blue. */
.ipr-2026 .form-card small a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: .15em;
}


/* footer — a dark band of brand and link columns */

.ipr-2026 footer {
  background-color: var(--color-ink);
  padding: var(--space-10) 0 var(--space-6);
}


.ipr-2026 .footer-inner {
  max-width: var(--max-content);
  margin: 0 auto;
  padding: 0 var(--wrap-x);
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: var(--space-6);
  align-items: start;
}


.ipr-2026 .footer-brand img {
  height: 28px;
  width: auto;
  margin-bottom: var(--space-2);
}


.ipr-2026 .footer-brand p {
  color: var(--color-on-dark-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  max-width: 32ch;
}


.ipr-2026 .footer-col h3 {
  color: #fff;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  margin: 0 0 var(--space-2);
}


.ipr-2026 .footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}


.ipr-2026 .footer-col a {
  color: var(--color-on-dark-muted);
  font-size: var(--text-sm);
  text-decoration: none;
  transition: color var(--transition-base, .2s ease);
}


.ipr-2026 .footer-col a:hover { color: #fff; }


.ipr-2026 .footer-base {
  max-width: var(--max-content);
  margin: var(--space-6) auto 0;
  padding: var(--space-4) var(--wrap-x) 0;
  border-top: 1px solid var(--on-dark-12);
  color: var(--color-on-dark-muted);
  font-size: var(--text-sm);
}


/* Responsive: stack footer columns */
@media (max-width: 960px) {
  .ipr-2026 .footer-inner { grid-template-columns: 1fr 1fr; }

}

@media (max-width: 640px) {
  .ipr-2026 .footer-inner { grid-template-columns: 1fr; }

}

