/*
 * components.css
 * The reusable pattern library, extracted from the approved landing page.
 * Every other page is assembled from these. A new pattern gets flagged, not
 * freelanced inline. See 02-concept/wireframes.md.
 */

/* ======================================================================
   Header
   ====================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgb(251 250 247 / 90%);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule-light);
  transition: box-shadow var(--t-base) var(--ease);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: 68px;
}

.wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: 0.1em;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  text-decoration: none;
  white-space: nowrap;
}

.wordmark__accent {
  color: var(--accent-ink);
}

.site-footer .wordmark__accent,
.surface-dark .wordmark__accent {
  color: var(--accent-bright);
}

/* Wordmark now carries the full business name. */
.wordmark__tld {
  color: var(--muted);
  font-weight: 500;
}

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-input);
  background: var(--paper-2);
  color: var(--ink);
  cursor: pointer;
}

.site-nav {
  display: none;
}

.site-nav.is-open {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  display: block;
  padding: var(--sp-4) var(--gutter) var(--sp-5);
  background: var(--white);
  border-bottom: 1px solid var(--rule-light);
  box-shadow: var(--shadow-card);
}

.site-nav__list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav__list li + li {
  margin-top: 0;
}

.site-nav a {
  color: var(--ink);
  font-weight: 700;
  text-decoration: none;
}

.site-nav a:hover {
  color: var(--accent-base);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

@media (width >= 60rem) {
  .nav-toggle {
    display: none;
  }

  .site-nav {
    display: block;
    margin-left: auto;
  }

  .site-nav__list {
    flex-direction: row;
    gap: var(--sp-6);
  }
}

/* ======================================================================
   Buttons. Square corners. Not pills.
   ====================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 48px;
  padding: var(--sp-3) var(--sp-5);
  border: 2px solid transparent;
  border-radius: var(--radius-input);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease),
    color var(--t-fast) var(--ease);
}

.btn--primary {
  background: var(--accent-base);
  border-color: var(--accent-base);
  color: var(--white);
}

.btn--primary:hover {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
  color: var(--white);
}

.btn--secondary {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}

.btn--secondary:hover {
  background: var(--ink);
  color: var(--white);
}

/* On dark surfaces the accent fill reads weaker than the outline button beside
   it, which inverts the hierarchy. Solid white is unambiguously primary. */
.surface-dark .btn--primary,
.surface-darkest .btn--primary,
.hero-full .btn--primary,
.result .btn--primary,
.promo .btn--primary {
  background: var(--white);
  border-color: var(--white);
  color: var(--ink);
}

.surface-dark .btn--primary:hover,
.surface-darkest .btn--primary:hover,
.hero-full .btn--primary:hover,
.result .btn--primary:hover,
.promo .btn--primary:hover {
  background: var(--accent-soft);
  border-color: var(--accent-soft);
  color: var(--ink);
}

.surface-dark .btn--secondary,
.surface-darkest .btn--secondary,
.hero-full .btn--secondary,
.result .btn--secondary,
.promo .btn--secondary {
  border-color: var(--accent-soft);
  color: var(--white);
}

.surface-dark .btn--secondary:hover,
.surface-darkest .btn--secondary:hover,
.hero-full .btn--secondary:hover,
.result .btn--secondary:hover,
.promo .btn--secondary:hover {
  background: var(--accent-soft);
  color: var(--ink);
}

.btn--small {
  min-height: 42px;
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-small);
}

.cta-pair {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

.cta-pair .btn {
  flex: 1 1 auto;
}

@media (width >= 40rem) {
  .cta-pair .btn {
    flex: 0 0 auto;
  }
}

/* ======================================================================
   Section head. eyebrow rule, eyebrow label, h2, optional lead.
   ====================================================================== */

.section-head {
  max-width: 46rem;
  margin-bottom: var(--sp-7);
}

.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
  color: var(--eyebrow-on-light);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.eyebrow::before {
  content: "";
  flex: none;
  width: 30px;
  height: 2px;
  background: currentcolor;
}

.surface-dark .eyebrow,
.surface-darkest .eyebrow,
.result .eyebrow {
  color: var(--eyebrow-on-dark);
}

.section-head__lead {
  font-size: var(--fs-lead);
  margin-bottom: 0;
}

/* ======================================================================
   Hero
   ====================================================================== */

.hero {
  padding-block: clamp(3rem, 7vw, 5.5rem) clamp(3rem, 7vw, 5rem);
  background: linear-gradient(180deg, var(--paper-tint) 0%, var(--paper) 100%);
  border-bottom: 1px solid var(--rule-light);
}

.hero h1 {
  max-width: 20ch;
}

.hero__lead {
  max-width: 54ch;
  margin-bottom: var(--sp-6);
  font-size: var(--fs-lead);
}

.hero .cta-pair {
  margin-bottom: var(--sp-6);
}

.hero__price {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-small);
  font-weight: 400;
  opacity: 0.85;
}

/* ======================================================================
   Credential line. Four items, no photography.
   ====================================================================== */

.credentials {
  display: grid;
  gap: var(--sp-4);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--rule-light);
  list-style: none;
  margin: 0;
  padding-left: 0;
}

.credentials li {
  margin-top: 0;
  padding-left: var(--sp-4);
  border-left: var(--accent-bar) solid var(--accent-base);
  font-size: var(--fs-small);
  line-height: 1.45;
}

.credentials strong {
  display: block;
  color: var(--ink);
  font-size: var(--fs-body);
}

.surface-dark .credentials {
  border-top-color: var(--rule-dark);
}

.surface-dark .credentials li {
  border-left-color: var(--accent-bright);
}

.surface-dark .credentials strong {
  color: var(--white);
}

@media (width >= 48rem) {
  .credentials {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-5);
  }
}

@media (width >= 64rem) {
  .credentials {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ======================================================================
   Statement rows. The pain mirror. Plain text carries more weight than icons.
   ====================================================================== */

.statements {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.statements li {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
  margin-top: 0;
  padding-block: var(--sp-5);
  border-bottom: 1px solid var(--rule-light);
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--ink);
}

.statements li::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 0.6em;
  background: var(--accent-base);
  border-radius: var(--radius-pill);
}

/* ======================================================================
   Cards
   ====================================================================== */

.card-grid {
  display: grid;
  gap: var(--sp-4);
}

@media (width >= 40rem) {
  .card-grid--2 {
    grid-template-columns: repeat(2, 1fr);
  }

  .card-grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }

  .card-grid--4 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (width >= 64rem) {
  .card-grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }

  .card-grid--4 {
    grid-template-columns: repeat(4, 1fr);
  }
}

.card {
  display: flex;
  flex-direction: column;
  padding: var(--sp-6);
  background: var(--bg-card);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.card h3 {
  margin-bottom: var(--sp-3);
}

.card p:last-child {
  margin-bottom: 0;
}

.card--accent {
  border-left: 0;
}

.surface-dark .card {
  background: rgb(251 250 247 / 6%);
  border-color: var(--rule-dark);
  box-shadow: none;
  color: var(--ink-body-on-dark);
}

/* ======================================================================
   Numbered steps
   ====================================================================== */

.steps {
  display: grid;
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps li {
  margin-top: 0;
  padding-top: var(--sp-4);
  border-top: 2px solid var(--accent-base);
  counter-increment: step;
}

.steps li::before {
  content: "0" counter(step);
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--accent-ink);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
}

.steps h3 {
  margin-bottom: var(--sp-2);
}

.steps p {
  margin-bottom: 0;
  font-size: var(--fs-small);
}

@media (width >= 48rem) {
  .steps {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (width >= 64rem) {
  .steps {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ======================================================================
   Split panel. For and not-for.
   ====================================================================== */

.split {
  display: grid;
  gap: var(--sp-5);
}

@media (width >= 48rem) {
  .split {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-6);
  }
}

.panel {
  padding: var(--sp-6);
  background: var(--white);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.panel--yes {
  box-shadow:
    inset 0 3px 0 var(--exposure-low),
    var(--shadow-card);
}

.panel--no {
  box-shadow:
    inset 0 3px 0 var(--exposure-high),
    var(--shadow-card);
}

/* Neutral panel. Used where the content is neither affirmative nor caution,
   so the fixed semantic scale is not misapplied. Independence and credentials
   are not warnings and must never carry the rust marker. */
.panel--neutral {
  box-shadow:
    inset 0 3px 0 var(--accent-base),
    var(--shadow-card);
}

.panel h3 {
  margin-bottom: var(--sp-4);
}

.tick-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.tick-list li {
  position: relative;
  margin-top: 0;
  padding-left: var(--sp-5);
  padding-block: var(--sp-2);
  font-size: var(--fs-small);
}

.tick-list li + li {
  border-top: 1px solid rgb(20 24 29 / 6%);
}

.tick-list li::before {
  position: absolute;
  left: 0;
  top: 0.9em;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  content: "";
}

.panel--yes .tick-list li::before {
  background: var(--exposure-low);
}

.panel--no .tick-list li::before {
  background: var(--exposure-high);
}

.panel--neutral .tick-list li::before {
  background: var(--accent-base);
}

/* ======================================================================
   Newsletter
   ====================================================================== */

.issue-card {
  display: flex;
  flex-direction: column;
  padding: var(--sp-5);
  background: var(--white);
  border: 1px solid var(--rule-light);
  border-top: var(--accent-bar) solid var(--accent-base);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  text-decoration: none;
  transition: box-shadow var(--t-base) var(--ease);
}

.issue-card:hover {
  box-shadow: var(--shadow-card-hover);
}

.issue-card__meta {
  margin-bottom: var(--sp-3);
  color: var(--accent-ink);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.issue-card h3 {
  margin-bottom: var(--sp-3);
  color: var(--ink);
}

.issue-card p {
  margin-bottom: 0;
  color: var(--ink-body);
  font-size: var(--fs-small);
}

.subscribe {
  margin-top: var(--sp-6);
  padding: var(--sp-5);
  background: var(--white);
  border: 1px solid var(--rule-light);
  border-radius: var(--radius-card);
}

.subscribe__form {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

.subscribe__form label {
  flex: 1 1 100%;
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--ink);
}

.field {
  flex: 1 1 16rem;
  min-height: 48px;
  padding: var(--sp-3);
  background: var(--white);
  border: 1px solid rgb(20 24 29 / 22%);
  border-radius: var(--radius-input);
}

.field:focus-visible {
  border-color: var(--accent-base);
  outline: var(--focus-ring);
  outline-offset: 1px;
}

.note,
.form-note {
  margin: var(--sp-3) 0 0;
  font-size: var(--fs-small);
  color: var(--muted);
}

/* Honeypot. Never visible, never announced. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ======================================================================
   Closing band
   ====================================================================== */

.close-band h2 {
  max-width: 22ch;
}

.close-band__lead {
  max-width: 52ch;
  margin-bottom: var(--sp-6);
  font-size: var(--fs-lead);
}

.door-grid {
  display: grid;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
}

@media (width >= 48rem) {
  .door-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.door {
  display: flex;
  flex-direction: column;
  padding: var(--sp-6);
  background: rgb(251 250 247 / 7%);
  border: 0;
  border-radius: var(--radius-card);
}

.door h3 {
  margin-bottom: var(--sp-3);
}

.door p {
  flex: 1 1 auto;
  margin-bottom: var(--sp-5);
  color: var(--ink-body-on-dark);
  font-size: var(--fs-small);
}

.door .btn {
  align-self: flex-start;
}

/* ======================================================================
   Footer
   ====================================================================== */

.site-footer {
  padding-block: var(--sp-8) var(--sp-5);
  background: var(--ink-deep);
  color: var(--muted-on-dark);
}

.footer-grid {
  display: grid;
  gap: var(--sp-6);
  padding-bottom: var(--sp-6);
  border-bottom: 1px solid var(--rule-dark);
}

@media (width >= 48rem) {
  .footer-grid {
    grid-template-columns: 1.5fr 1fr 1fr;
  }
}

.site-footer h2 {
  margin-bottom: var(--sp-4);
  color: var(--white);
  font-size: var(--fs-small);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.footer-links {
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-links li {
  margin-top: 0;
}

.footer-links li + li {
  margin-top: var(--sp-3);
}

.footer-links a {
  color: var(--muted-on-dark);
  font-size: var(--fs-small);
  text-decoration: none;
}

.footer-links a:hover {
  color: var(--accent-bright);
}

.site-footer .wordmark {
  color: var(--white);
}

.site-footer .wordmark__tld {
  color: var(--muted-on-dark);
}

.footer-blurb {
  max-width: 34ch;
  margin-top: var(--sp-4);
  font-size: var(--fs-small);
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  justify-content: space-between;
  padding-top: var(--sp-5);
  font-size: var(--fs-small);
}

.footer-bottom p {
  margin: 0;
}

/* Build-state marker. Removed before launch. */
/* ======================================================================
   Governance profile. Illustrated, not tabulated. Rounded meter bars on a
   soft track, generous spacing, no rules or table borders. Reads as a
   product view of the deliverable rather than a spreadsheet.
   ====================================================================== */

.profile {
  margin: 0;
  padding: clamp(var(--sp-5), 3.5vw, var(--sp-7));
  background: var(--white);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.surface-dark .profile,
.hero-full .profile {
  background: rgb(251 250 247 / 7%);
  box-shadow: none;
  backdrop-filter: blur(6px);
}

.profile__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-bottom: var(--sp-6);
}

.profile__title {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.014em;
}

.profile__note {
  padding: var(--sp-1) var(--sp-3);
  background: var(--paper-2);
  border-radius: var(--radius-pill);
  color: var(--muted);
  font-size: 0.8125rem;
}

.surface-dark .profile__title,
.hero-full .profile__title {
  color: var(--white);
}

.surface-dark .profile__note,
.hero-full .profile__note {
  background: rgb(251 250 247 / 12%);
  color: var(--muted-on-dark);
}

.profile__rows {
  display: grid;
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.profile__rows li {
  margin-top: 0;
}

.profile__row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}

.profile__name {
  color: var(--ink);
  font-size: var(--fs-small);
  font-weight: 600;
}

.profile__state {
  color: var(--muted);
  font-size: 0.8125rem;
  white-space: nowrap;
}

.surface-dark .profile__name,
.hero-full .profile__name {
  color: var(--white);
}

.surface-dark .profile__state,
.hero-full .profile__state {
  color: var(--muted-on-dark);
}

/* Track and fill. The fill is a rounded bar with a soft gradient, so the
   component reads as an illustration rather than a data table. */
/* Slightly richer bar treatment now the panel is a hero object. */
.bar {
  position: relative;
  height: 12px;
  background: var(--paper-2);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.surface-dark .bar,
.hero-full .bar {
  background: rgb(251 250 247 / 12%);
}

.bar__fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--exposure-mid) 0%, var(--exposure-mid) 100%);
  box-shadow: inset 0 -1px 0 rgb(20 24 29 / 10%);
}

/* Governance profile bar lengths. These are data, so they live on the element
   as data-score and are resolved here rather than in a style attribute, which
   the CSP would discard. Add a rule when a new value is used; the set is small
   and deliberately explicit so a score can never silently render at full width.
   The Quick Diagnosis meter is a separate element and is driven from JavaScript
   via CSSOM, which the CSP does not restrict. */
.bar__fill[data-score="18"] {
  width: 18%;
}

.bar__fill[data-score="38"] {
  width: 38%;
}

.bar__fill[data-score="40"] {
  width: 40%;
}

.bar__fill[data-score="58"] {
  width: 58%;
}

.bar__fill[data-score="60"] {
  width: 60%;
}

.bar__fill[data-score="80"] {
  width: 80%;
}

.bar__fill[data-band="low"] {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--exposure-low) 78%, white),
    var(--exposure-low)
  );
}

.bar__fill[data-band="mid"] {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--exposure-mid) 74%, white),
    var(--exposure-mid)
  );
}

.bar__fill[data-band="high"] {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--exposure-high) 74%, white),
    var(--exposure-high)
  );
}

.profile__key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-5);
  margin: var(--sp-6) 0 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 0.8125rem;
}

.profile__key li {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: 0;
}

.profile__key i {
  width: 22px;
  height: 8px;
  border-radius: var(--radius-pill);
}

/* Legend swatches carry data-band, matching the bars they explain, so the
   colour is set here rather than in a style attribute the CSP would discard. */
.profile__key i[data-band="high"] {
  background: var(--exposure-high);
}

.profile__key i[data-band="mid"] {
  background: var(--exposure-mid);
}

.profile__key i[data-band="low"] {
  background: var(--exposure-low);
}

.surface-dark .profile__key,
.hero-full .profile__key {
  color: var(--muted-on-dark);
}

/* ======================================================================
   Hero layout with the scorecard alongside
   ====================================================================== */

.hero__grid {
  display: grid;
  gap: var(--sp-7);
  align-items: start;
}

@media (width >= 64rem) {
  .hero__grid {
    grid-template-columns: 1.05fr 0.95fr;
    gap: var(--sp-8);
  }
}

/* ======================================================================
   Deliverables list. What the client receives, itemised.
   ====================================================================== */

.deliverables {
  margin: 0;
  padding: 0;
  list-style: none;
}

.deliverables li {
  position: relative;
  margin-top: 0;
  padding: var(--sp-3) 0 var(--sp-3) var(--sp-5);
}

.deliverables li + li {
  border-top: 1px solid rgb(20 24 29 / 6%);
}

.deliverables li::before {
  position: absolute;
  left: 0;
  top: 1.2em;
  width: 8px;
  height: 8px;
  background: var(--accent-base);
  border-radius: var(--radius-pill);
  content: "";
}

.spec-grid {
  display: grid;
  gap: var(--sp-6);
}

@media (width >= 60rem) {
  .spec-grid {
    grid-template-columns: 1.1fr 0.9fr;
    gap: var(--sp-8);
  }
}

.spec-meta {
  padding: var(--sp-6);
  background: var(--paper-tint);
  border-radius: var(--radius-card);
}

.spec-meta dl {
  margin: 0;
}

.spec-meta dt {
  color: var(--ink);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.spec-meta dd {
  margin: var(--sp-2) 0 var(--sp-5);
  font-size: var(--fs-small);
}

.spec-meta dd:last-child {
  margin-bottom: 0;
}

/* ======================================================================
   Domain rows. Numbered, no decorative icons.
   ====================================================================== */

.domains {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule-light);
}

.domains li {
  display: grid;
  gap: var(--sp-2) var(--sp-5);
  margin-top: 0;
  padding-block: var(--sp-5);
  border-bottom: 1px solid var(--rule-light);
}

@media (width >= 48rem) {
  .domains li {
    grid-template-columns: 3rem 16rem 1fr;
    align-items: baseline;
  }
}

.domains__num {
  color: var(--accent-ink);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
}

.domains__name {
  color: var(--ink);
  font-size: var(--fs-h3);
  font-weight: 700;
  line-height: 1.25;
}

.domains__desc {
  margin: 0;
}

/* ======================================================================
   Outcome rows
   ====================================================================== */

.outcomes {
  display: grid;
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (width >= 48rem) {
  .outcomes {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-5) var(--sp-7);
  }
}

@media (width >= 64rem) {
  .outcomes {
    grid-template-columns: repeat(3, 1fr);
  }
}

.outcomes li {
  margin-top: 0;
  padding-top: var(--sp-4);
  border-top: 2px solid var(--accent-bright);
}

.outcomes strong {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--white);
  font-size: var(--fs-h3);
}

.outcomes span {
  font-size: var(--fs-small);
}

/* ======================================================================
   Newsletter strip. Deliberately after the close and visually quieter, so it
   does not interrupt the credibility to engagement path.
   ====================================================================== */

.news-strip {
  padding-block: var(--sp-7);
  background: var(--paper-2);
  border-top: 1px solid var(--rule-light);
}

.news-strip__inner {
  display: grid;
  gap: var(--sp-5);
  align-items: center;
}

@media (width >= 60rem) {
  .news-strip__inner {
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-8);
  }
}

.news-strip h2 {
  margin-bottom: var(--sp-2);
  font-size: var(--fs-h3);
}

.news-strip p {
  font-size: var(--fs-small);
}

/* ======================================================================
   FULL-BLEED HERO. Original generated image under an ink scrim weighted to the
   left, so headline text sits on the quiet side of the composition.
   See genhero.py. Nothing here is third-party licensed.
   ====================================================================== */

.hero-full {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 78vh;
  padding-block: var(--sp-9) var(--sp-8);
  background:
    linear-gradient(180deg, rgb(12 15 19 / 78%) 0%, rgb(12 15 19 / 94%) 100%),
    var(--ink) url("/assets/images/hero-structure-sm.jpg") center / cover no-repeat;
  background-blend-mode: normal;
  color: var(--ink-body-on-dark);
}

.hero-full h1 {
  max-width: 17ch;
  color: var(--white);
}

@media (width >= 48rem) {
  .hero-full {
    background-image:
      linear-gradient(
        90deg,
        rgb(12 15 19 / 92%) 0%,
        rgb(12 15 19 / 58%) 52%,
        rgb(12 15 19 / 30%) 100%
      ),
      url("/assets/images/hero-structure.jpg");
  }
}

.hero-full__lead {
  max-width: 56ch;
  margin-bottom: var(--sp-6);
  font-size: var(--fs-lead);
  color: var(--muted-on-dark);
}

.hero-full .eyebrow {
  color: var(--accent-soft);
}

.hero-full__note {
  margin-top: var(--sp-5);
  font-size: var(--fs-small);
  color: var(--muted-on-dark);
}

/* ======================================================================
   PROOF STRIP. Numbers only, and only numbers that are true today.
   No client counts, no ratings, nothing that cannot be evidenced.
   ====================================================================== */

.proof {
  padding-block: var(--sp-7);
  background: var(--ink-deep);
  color: var(--muted-on-dark);
}

.proof__grid {
  display: grid;
  gap: var(--sp-5);
}

@media (width >= 40rem) {
  .proof__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (width >= 64rem) {
  .proof__grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.proof__item {
  padding-left: var(--sp-4);
  border-left: var(--accent-bar) solid var(--accent-bright);
}

.proof__num {
  display: block;
  color: var(--white);
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 4.4vw, 3.4rem);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.03em;
}

.proof__label {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  line-height: 1.4;
}

/* ======================================================================
   TABS. Four question-led panels. Without JavaScript every panel is
   visible and stacked, so nothing is hidden from a reader or a crawler.
   JavaScript upgrades it to a tablist.
   ====================================================================== */

.tabs__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-6);
  padding: 0;
  list-style: none;
}

.tabs__list li {
  margin-top: 0;
}

.tabs__btn {
  padding: var(--sp-3) var(--sp-5);
  background: transparent;
  border: 0;
  border-radius: var(--radius-pill);
  color: var(--muted);
  font-size: var(--fs-small);
  font-weight: 700;
  cursor: pointer;
  transition:
    color var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease);
}

.tabs__btn:hover {
  color: var(--ink);
}

.tabs__btn[aria-selected="true"] {
  background: var(--ink);
  color: var(--white);
}

/* Panels are visible by default. JS adds .is-enhanced to the wrapper before
   it starts hiding anything, so a no-JS reader loses nothing. */
.tabs__panels {
  display: grid;
  gap: var(--sp-6);
}

.tabs.is-enhanced .tabs__panels {
  display: block;
}

.tabs.is-enhanced .tabs__panel[hidden] {
  display: none;
}

.tabs__panel {
  padding: clamp(var(--sp-6), 4vw, var(--sp-8));
  background: var(--white);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.tabs__panel h3 {
  max-width: 24ch;
  font-size: var(--fs-h2);
  letter-spacing: -0.015em;
}

.tabs__panel p {
  max-width: 62ch;
}

/* Only shown when JS is absent, to label each stacked panel. */
.tabs__panel-label {
  display: block;
  margin-bottom: var(--sp-3);
  color: var(--accent-base);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.tabs.is-enhanced .tabs__panel-label {
  display: none;
}

/* ======================================================================
   CHALLENGE GRID. Six equal cards with an explore affordance.
   ====================================================================== */

.challenge-grid {
  display: grid;
  gap: var(--sp-4);
}

@media (width >= 40rem) {
  .challenge-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (width >= 64rem) {
  .challenge-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.challenge {
  display: flex;
  flex-direction: column;
  padding: var(--sp-5);
  background: var(--white);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  text-decoration: none;
  transition:
    box-shadow var(--t-base) var(--ease),
    transform var(--t-base) var(--ease);
}

.challenge:hover {
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-2px);
}

.challenge__num {
  color: var(--accent-ink);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
}

.challenge h3 {
  margin: var(--sp-3) 0;
  color: var(--ink);
}

.challenge p {
  flex: 1 1 auto;
  color: var(--ink-body);
  font-size: var(--fs-small);
}

.challenge__more {
  margin-top: var(--sp-4);
  color: var(--accent-ink);
  font-size: var(--fs-small);
  font-weight: 700;
}

.challenge__more::after {
  content: " \2192";
}

/* ======================================================================
   EXPERTS. Replaces a team-photo grid. No portraits, no invented headcount.
   ====================================================================== */

.experts {
  display: grid;
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (width >= 48rem) {
  .experts {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Three columns, not four. There are six items, so four leaves a ragged
   4 + 2 with two empty cells; three gives a clean 3 + 3. Revisit the count
   here if the list ever changes length. */
@media (width >= 64rem) {
  .experts {
    grid-template-columns: repeat(3, 1fr);
  }
}

.experts li {
  margin-top: 0;
  padding-top: var(--sp-4);
  border-top: 2px solid var(--accent-base);
}

.experts strong {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--white);
  font-size: var(--fs-h3);
}

.experts span {
  font-size: var(--fs-small);
}

/* ======================================================================
   RESOURCE CARDS
   ====================================================================== */

.resource-grid {
  display: grid;
  gap: var(--sp-4);
}

@media (width >= 48rem) {
  .resource-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.resource {
  display: flex;
  flex-direction: column;
  padding: var(--sp-6);
  background: var(--white);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  text-decoration: none;
  transition: box-shadow var(--t-base) var(--ease);
}

.resource:hover {
  box-shadow: var(--shadow-card-hover);
}

.resource__type {
  color: var(--accent-ink);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.resource h3 {
  margin: var(--sp-3) 0;
  color: var(--ink);
  font-size: var(--fs-h3);
}

.resource p {
  flex: 1 1 auto;
  margin-bottom: 0;
  color: var(--ink-body);
  font-size: var(--fs-small);
}

/* ======================================================================
   Grid overflow guard.
   Grid and flex children default to min-width:auto, so a child whose content
   has a wide min-content size (the scorecard table) refuses to shrink and
   pushes past the viewport. Caught at 360px by the overflow check.
   ====================================================================== */

.spec-grid > *,
.hero__grid > *,
.news-strip__inner > *,
.split > *,
.card-grid > *,
.challenge-grid > *,
.resource-grid > * {
  min-width: 0;
}

@media (width < 26rem) {
  .scorecard {
    padding: var(--sp-4);
  }

  .scorecard__table th {
    padding-right: var(--sp-2);
    font-size: 0.875rem;
  }

  .scorecard__table td {
    padding-left: var(--sp-2);
  }

  .scorecard__level {
    font-size: 0.8125rem;
  }

  .meter span {
    width: 11px;
  }
}

/* ======================================================================
   Mechanisms. Five reinforcing mechanisms that make governance real.
   Soft tiles, numbered, no outlines.
   ====================================================================== */

.mechanisms {
  display: grid;
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (width >= 40rem) {
  .mechanisms {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (width >= 68rem) {
  .mechanisms {
    grid-template-columns: repeat(5, 1fr);
    gap: var(--sp-3);
  }
}

.mechanisms li {
  margin-top: 0;
  padding: var(--sp-5);
  background: var(--white);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.mechanisms__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-bottom: var(--sp-4);
  background: var(--paper-tint);
  border-radius: var(--radius-pill);
  color: var(--accent-ink);
  font-size: 0.8125rem;
  font-weight: 700;
}

.mechanisms strong {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.012em;
}

.mechanisms span {
  font-size: var(--fs-small);
}

/* ======================================================================
   Question list. The bigger questions a board should be able to answer.
   ====================================================================== */

.questions {
  display: grid;
  gap: var(--sp-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.questions li {
  margin-top: 0;
  padding: var(--sp-4) var(--sp-5);
  background: var(--white);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-card);
  color: var(--ink);
  font-size: var(--fs-body);
}

.reactive {
  display: grid;
  gap: var(--sp-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.reactive li {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  margin-top: 0;
  color: var(--muted-on-dark);
  font-size: var(--fs-small);
}

.reactive li::before {
  flex: none;
  width: 7px;
  height: 7px;
  margin-top: 0.6em;
  background: var(--exposure-high);
  border-radius: var(--radius-pill);
  content: "";
}

.pullquote {
  margin: var(--sp-6) 0 0;
  padding: var(--sp-5) var(--sp-6);
  background: rgb(151 54 42 / 16%);
  border-radius: var(--radius-card);
  color: var(--white);
  font-size: var(--fs-lead);
}

.statement-band {
  padding: var(--sp-6);
  background: var(--ink);
  border-radius: var(--radius-card);
  color: var(--white);
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  font-weight: 500;
  letter-spacing: -0.015em;
  text-align: center;
}

.statement-band em {
  color: var(--accent-bright);
  font-style: normal;
}

/* Reactive list on a light surface. */
.reactive--light {
  margin-top: var(--sp-5);
}

.reactive--light li {
  color: var(--muted);
}

/* Full business name in the wordmark. On narrow screens it stacks to two
   lines so the header CTA and menu button still fit at 360px. */
.wordmark__name {
  display: inline-flex;
  align-items: baseline;
}

@media (width < 48rem) {
  .wordmark {
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    font-size: 1.05rem;
    line-height: 1.05;
  }

  .wordmark__tld {
    font-size: 0.8125rem;
  }

  .btn--small {
    padding: var(--sp-2) var(--sp-3);
  }
}

/* ======================================================================
   DELIVERABLE ILLUSTRATION.
   The profile panel previously read as a live dashboard, which is ambiguous:
   a visitor could mistake it for real data or for part of the site's own UI.
   It is now presented as an illustration. Tilted in 3D on a stack of ghost
   documents, lifted off the page with depth shadow and a soft glow, and the
   bars draw on entry. Clearly a depiction of the deliverable, not the thing.
   ====================================================================== */

.deliverable-visual {
  position: relative;
  perspective: 1050px;
  padding: var(--sp-7) var(--sp-4) var(--sp-8);
}

/* Soft light pool behind the stack, so it sits in space rather than on a flat
   background. */
.deliverable-visual::before {
  position: absolute;
  inset: 8% -4% 4%;
  background: radial-gradient(
    60% 55% at 50% 45%,
    rgb(31 92 61 / 13%) 0%,
    rgb(31 92 61 / 5%) 45%,
    transparent 72%
  );
  filter: blur(6px);
  content: "";
}

.deliverable-stack {
  position: relative;
  transform-style: preserve-3d;
  transform: rotateY(-15deg) rotateX(6deg) rotateZ(-1deg) scale(0.9);
  transition: transform var(--t-base) var(--ease);
}

/* Two ghost documents behind the front panel: the full report and the
   one-page summary. They give the stack real depth. */
.deliverable-stack::before,
.deliverable-stack::after {
  position: absolute;
  inset: 0;
  background: var(--white);
  border-radius: var(--radius-card);
  content: "";
}

.deliverable-stack::before {
  transform: translate3d(34px, 30px, -110px) rotateZ(2.2deg);
  box-shadow: 0 30px 70px rgb(20 24 29 / 13%);
  opacity: 0.5;
}

.deliverable-stack::after {
  transform: translate3d(17px, 15px, -55px) rotateZ(1.1deg);
  box-shadow: 0 22px 52px rgb(20 24 29 / 11%);
  opacity: 0.78;
}

.deliverable-stack .profile {
  position: relative;
  z-index: 1;
  box-shadow:
    0 2px 4px rgb(20 24 29 / 5%),
    0 30px 70px rgb(20 24 29 / 16%),
    0 60px 120px rgb(20 24 29 / 10%);
}

/* A caption that names it as a depiction, so it cannot be mistaken for data. */
.deliverable-visual__caption {
  position: relative;
  margin: var(--sp-8) 0 0;
  color: var(--muted);
  font-size: 0.8125rem;
  text-align: center;
}

@media (width >= 60rem) {
  .deliverable-stack:hover {
    transform: rotateY(-9deg) rotateX(3.5deg) rotateZ(-0.5deg) scale(0.93);
  }
}

/* Flatten until the panel has its own grid column. Below that the tilt both
   overflows the viewport and makes the figures harder to read. */
@media (width < 60rem) {
  .deliverable-visual {
    padding: var(--sp-2) 0 var(--sp-4);
  }

  .deliverable-stack {
    transform: none;
  }

  .deliverable-stack::before,
  .deliverable-stack::after {
    display: none;
  }
}

/* ======================================================================
   MODULAR SCOPE. Makes it explicit that engagements are chosen by domain,
   not sold as one fixed package.
   ====================================================================== */

.scope-note {
  display: grid;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
  padding: var(--sp-6);
  background: var(--paper-tint);
  border-radius: var(--radius-card);
}

@media (width >= 48rem) {
  .scope-note {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-6);
  }
}

.scope-note h4 {
  margin: 0 0 var(--sp-2);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.012em;
}

.scope-note p {
  margin: 0;
  font-size: var(--fs-small);
}

.scope-note__price {
  display: block;
  margin-top: var(--sp-3);
  color: var(--accent-ink);
  font-weight: 600;
}

/* ======================================================================
   Forms. Used on the contact page and the Quick Diagnosis.
   ====================================================================== */

.enquiry {
  max-width: 34rem;
}

.field-row {
  margin-bottom: var(--sp-5);
}

.field-row label {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--ink);
  font-size: var(--fs-small);
  font-weight: 600;
}

.field-row .field {
  width: 100%;
}

textarea.field {
  min-height: 8rem;
  padding: var(--sp-3);
  line-height: var(--lh-body);
  resize: vertical;
}

select.field {
  min-height: 48px;
  padding: var(--sp-3);
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position:
    calc(100% - 20px) 50%,
    calc(100% - 14px) 50%;
  background-size:
    6px 6px,
    6px 6px;
  background-repeat: no-repeat;
}

.field-hint {
  margin: var(--sp-2) 0 0;
  color: var(--muted);
  font-size: 0.8125rem;
}

.spec-meta dd a {
  color: var(--accent-ink);
}

/* ======================================================================
   Quick Diagnosis
   ====================================================================== */

.track-picker {
  display: grid;
  gap: var(--sp-4);
  margin: 0 0 var(--sp-7);
  padding: 0;
  list-style: none;
}

@media (width >= 48rem) {
  .track-picker {
    grid-template-columns: repeat(3, 1fr);
  }
}

.track-picker li {
  margin-top: 0;
}

.track {
  display: block;
  width: 100%;
  padding: var(--sp-5);
  background: var(--white);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    box-shadow var(--t-base) var(--ease),
    transform var(--t-base) var(--ease);
}

.track:hover {
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-2px);
}

.track[aria-pressed="true"] {
  background: var(--ink);
  color: var(--muted-on-dark);
}

.track strong {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.014em;
}

.track[aria-pressed="true"] strong {
  color: var(--white);
}

.track span {
  font-size: var(--fs-small);
}

/* --- Question cards ---------------------------------------------------
   Each question is its own card so the eye has somewhere to land, and the
   card, its number and its chip all change state together on answering.
   Progress is visible from the first click, which is what makes a
   twenty-one-question form feel finishable. */

.q-progress {
  position: sticky;
  bottom: var(--sp-4);
  z-index: 4;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: min(26rem, 100%);
  margin: var(--sp-5) auto 0;
  padding: var(--sp-3) var(--sp-5);
  background: var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: 0 14px 34px rgb(20 24 29 / 26%);

  /* Informational only. Without this it would swallow clicks on whatever it
     happens to be floating over. */
  pointer-events: none;
}

.q-progress[hidden] {
  display: none;
}

.q-progress__track {
  flex: 1 1 auto;
  min-width: 0;
  height: 6px;
  background: rgb(251 250 247 / 20%);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.q-progress__track span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--accent-bright);
  transition: width 420ms var(--ease);
}

.q-progress__label {
  flex: 0 0 auto;
  margin: 0;
  color: var(--white);
  font-size: var(--fs-small);
  font-weight: 600;
  white-space: nowrap;
}

@media (width < 30rem) {
  .q-progress {
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
  }
}

.q {
  min-width: 0;
  margin: 0 0 var(--sp-4);
  padding: clamp(var(--sp-5), 3.2vw, var(--sp-6));
  background: var(--white);
  border: 1px solid rgb(20 24 29 / 8%);
  border-radius: var(--radius-card);
  box-shadow: 0 1px 2px rgb(20 24 29 / 4%);
  transition:
    border-color var(--t-base) var(--ease),
    box-shadow var(--t-base) var(--ease),
    background var(--t-base) var(--ease);
}

.q:hover {
  border-color: rgb(31 92 61 / 24%);
  box-shadow: var(--shadow-card);
}

.q:focus-within {
  border-color: rgb(31 92 61 / 40%);
  box-shadow: var(--shadow-card);
}

.q--answered {
  border-color: rgb(31 92 61 / 30%);
  background: linear-gradient(180deg, rgb(31 92 61 / 3%), rgb(255 255 255 / 0%) 40%), var(--white);
}

.q legend {
  /* A legend is painted over the fieldset border by default, which punches a
     notch in the card and leaves dead space inside it. Floating it returns it
     to normal flow; the elements after it clear the float. */
  float: left;
  width: 100%;
  padding: 0;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.008em;

  /* The float's margin box is what following content clears against, so all
     the spacing below the question lives here. Anything set as a margin-top on
     the hint or the options would be swallowed by clearance. */
  margin-bottom: var(--sp-5);
}

.q__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-right: 0.6rem;
  vertical-align: -0.4rem;
  background: var(--paper-tint);
  border-radius: var(--radius-pill);
  color: var(--accent-ink);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0;
  transition:
    background var(--t-base) var(--ease),
    color var(--t-base) var(--ease);
}

.q--answered .q__num {
  background: var(--accent-base);
  color: var(--white);
}

.q__hint {
  clear: both;
  margin: 0 0 var(--sp-4);
  padding-left: 2.35rem;
  color: var(--muted);
  font-size: var(--fs-small);
}

.q__opts {
  clear: both;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--sp-2);
  margin-top: 0;
}

@media (width < 30rem) {
  .q__opts {
    grid-template-columns: repeat(2, 1fr);
  }

  .q__hint {
    padding-left: 0;
  }
}

.q__opt {
  position: relative;
  min-width: 0;
}

.q__opt input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.q__opt span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding: var(--sp-3);
  background: var(--paper);
  border: 1px solid rgb(20 24 29 / 10%);
  border-radius: var(--radius-input);
  color: var(--ink);
  font-size: var(--fs-small);
  font-weight: 600;
  text-align: center;
  transition:
    background var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease),
    color var(--t-fast) var(--ease),
    box-shadow var(--t-fast) var(--ease),
    transform var(--t-fast) var(--ease);
}

.q__opt:hover span {
  background: var(--white);
  border-color: var(--accent-mid);
  color: var(--accent-ink);
}

.q__opt input:checked + span {
  background: var(--accent-base);
  border-color: var(--accent-base);
  box-shadow: 0 6px 16px rgb(31 92 61 / 22%);
  color: var(--white);
  transform: translateY(-1px);
}

.q__opt input:focus-visible + span {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

.q-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
}

.q-actions .note {
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  .q,
  .q__num,
  .q__opt span,
  .q-progress__track span {
    transition: none;
  }

  .q__opt input:checked + span {
    transform: none;
  }
}

.result {
  margin-top: var(--sp-7);
  padding: clamp(var(--sp-5), 4vw, var(--sp-7));
  background: var(--ink);
  border-radius: var(--radius-card);
  color: var(--muted-on-dark);
}

.result[hidden] {
  display: none;
}

.result__band {
  display: inline-block;
  margin-bottom: var(--sp-4);
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--radius-pill);
  color: var(--white);
  font-size: var(--fs-small);
  font-weight: 600;
}

.result h3 {
  color: var(--white);
  font-size: var(--fs-h2);
}

/* h4 must be listed explicitly. It sits on the same ink surface as h3 and was
   previously white only because of an inline style attribute, which the CSP
   discards. Without this rule it inherits an ink colour and renders invisible
   on an ink background. That failure mode has now appeared four times in this
   file; see HANDOFF.md, "Two traps that cost real time". */
.result h4 {
  margin-top: var(--sp-6);
  color: var(--white);
}

.result ol {
  margin: var(--sp-5) 0 0;
  padding-left: 1.2rem;
}

.result ol li {
  color: var(--muted-on-dark);
}

.result__meter {
  height: 12px;
  margin: var(--sp-4) 0 var(--sp-5);
  background: rgb(251 250 247 / 12%);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.result__meter span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: var(--radius-pill);
  transition: width 600ms var(--ease);
}

/* ======================================================================
   PROMOTIONAL BAND. Currently used once, on the AI governance and literacy
   domain page, to carry the automation offer. It is deliberately the loudest
   thing on that page.

   This is a dark surface. Every text colour below is set explicitly rather
   than inherited, because inheriting an ink colour onto an ink background is
   the failure that has appeared four times in this file. If you add an element
   here, give it a colour in this block. See HANDOFF.md.
   ====================================================================== */

.promo {
  position: relative;
  background: var(--bg-darkest);
  background-image: radial-gradient(
    120% 140% at 88% 0%,
    rgb(99 185 142 / 22%) 0%,
    rgb(99 185 142 / 6%) 38%,
    transparent 70%
  );
  color: var(--muted-on-dark);
  overflow: hidden;
}

/* Accent rule down the leading edge, so the band reads as a distinct offer
   rather than as another section of the same page. */
.promo::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: var(--accent-bar);
  background: linear-gradient(180deg, var(--accent-bright) 0%, var(--accent-base) 100%);
}

.promo__inner {
  max-width: 62rem;
}

.promo .eyebrow {
  color: var(--eyebrow-on-dark);
}

.promo__head {
  max-width: 22ch;
  margin-bottom: var(--sp-4);
  color: var(--white);
  font-size: var(--fs-h1);
  font-weight: 500;
  letter-spacing: var(--tracking-display);
  line-height: var(--lh-tight);
}

.promo__lead {
  max-width: 54ch;
  margin-bottom: var(--sp-5);
  color: var(--white);
  font-size: var(--fs-lead);
}

.promo__detail {
  max-width: 62ch;
  margin-bottom: var(--sp-6);
  color: var(--muted-on-dark);
}

.promo__points {
  display: grid;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-6);
  padding: 0;
  list-style: none;
}

.promo__points li {
  position: relative;
  margin-top: 0;
  padding-left: var(--sp-6);
  color: var(--white);
  line-height: 1.45;
}

/* Marker is drawn, not a bullet glyph, so it keeps its colour on dark. */
.promo__points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 14px;
  height: 2px;
  background: var(--accent-bright);
}

.promo__close {
  max-width: 58ch;
  margin-bottom: 0;
  color: var(--muted-on-dark);
  font-size: var(--fs-small);
}

@media (width >= 60rem) {
  .promo__points {
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-3) var(--sp-6);
  }
}

/* Read-more link at the foot of each domain summary on /services. */
.domains__more {
  margin-top: var(--sp-4);
  margin-bottom: 0;
  font-size: var(--fs-small);
  font-weight: 600;
}

.domains__name a {
  color: inherit;
  text-decoration: none;
}

.domains__name a:hover {
  color: var(--accent-base);
  text-decoration: underline;
}

/* ======================================================================
   DIAGNOSIS HERO. A variant of .hero-full carrying its own generated image.
   The Quick Diagnosis is the page that has to make a visitor stop and think,
   so it gets the strongest opening on the site after the home page.

   Dark surface. Every colour below is explicit. .hero-full is already listed
   in the dark-surface button and eyebrow groups, so buttons and the eyebrow
   are covered; anything added here needs its own colour.
   ====================================================================== */

.hero-full--diagnosis {
  background:
    linear-gradient(180deg, rgb(12 15 19 / 74%) 0%, rgb(12 15 19 / 92%) 100%),
    var(--ink) url("/assets/images/diagnosis-field-sm.jpg") center / cover no-repeat;
}

@media (width >= 48rem) {
  .hero-full--diagnosis {
    background-image:
      linear-gradient(
        90deg,
        rgb(12 15 19 / 93%) 0%,
        rgb(12 15 19 / 62%) 55%,
        rgb(12 15 19 / 34%) 100%
      ),
      url("/assets/images/diagnosis-field.jpg");
  }
}

/* Three facts that answer the objections a visitor has before starting:
   how long, how hard, and what it will cost them in personal details. */
.hero-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5) var(--sp-7);
  margin: var(--sp-6) 0;
  padding: 0;
  list-style: none;
}

.hero-facts li {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  margin-top: 0;
}

.hero-facts strong {
  color: var(--accent-soft);
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 500;
  letter-spacing: var(--tracking-display);
  line-height: 1;
}

.hero-facts span {
  max-width: 14ch;
  color: var(--muted-on-dark);
  font-size: var(--fs-small);
  line-height: 1.35;
}

/* Qualifier under the expertise list. It sits on a dark surface, so the colour
   is set explicitly rather than inherited. */
.experts__note {
  max-width: 68ch;
  margin-top: var(--sp-6);
  margin-bottom: 0;
  color: var(--muted-on-dark);
  font-size: var(--fs-small);
}

/* ======================================================================
   BRIEFS. Long-form reading with a generated illustration per topic.

   Desktop gets two columns: a measured article and a sidebar carrying the
   contents and a compact call to action. A single measured column on a 1200px
   container leaves roughly half the viewport empty, and a sidebar that earns
   its place is better than prose stretched past a comfortable line length.
   Body measure stays at about 62 characters regardless of viewport, because
   that is a readability constant, not a layout preference.
   ====================================================================== */

.brief-hero {
  padding-block: var(--sp-8) var(--sp-7);
  background: linear-gradient(180deg, var(--paper-tint) 0%, var(--paper) 100%);
  border-bottom: 1px solid var(--rule-light);
}

.brief-hero__inner {
  display: grid;
  gap: var(--sp-6);
  align-items: center;
}

.brief-hero h1 {
  /* Briefing titles are full sentences and run longer than the site's other
     headings, so this is wider than the 20ch used elsewhere. */
  max-width: 26ch;
}

.brief-hero__standfirst {
  max-width: 46ch;
  margin-bottom: 0;
  color: var(--ink-body);
  font-size: var(--fs-lead);
}

.brief-hero__figure {
  order: -1;
}

.brief-hero__figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

@media (width >= 64rem) {
  .brief-hero__inner {
    grid-template-columns: 1fr 0.85fr;
    gap: var(--sp-7);
  }

  /* Text first on desktop. The illustration supports the headline, it does
     not announce the page. */
  .brief-hero__figure {
    order: 0;
  }
}

.brief__meta {
  margin-top: var(--sp-5);
  margin-bottom: 0;
  color: var(--muted);
  font-size: var(--fs-small);
}

.brief__layout {
  display: grid;
  gap: var(--sp-7);
  align-items: start;
}

@media (width >= 64rem) {
  .brief__layout {
    grid-template-columns: minmax(0, 62ch) minmax(0, 1fr);
    gap: var(--sp-9);
  }
}

.brief__body {
  max-width: 62ch;
}

.brief__body h2 {
  margin-top: var(--sp-7);
  font-size: var(--fs-h3);
  scroll-margin-top: 96px;
}

.brief__body h2:first-child {
  margin-top: 0;
}

.brief__body h3 {
  margin-top: var(--sp-6);
  font-size: var(--fs-body);
}

.brief__body p,
.brief__body li {
  line-height: 1.65;
}

.brief__body ul,
.brief__body ol {
  margin-bottom: var(--sp-5);
}

/* Sidebar. Sticky only where there is room for it to be useful. */
.brief__aside {
  display: grid;
  gap: var(--sp-6);
  align-content: start;
}

@media (width >= 64rem) {
  .brief__aside {
    position: sticky;
    /* Clears the sticky header, which is 68px plus its border. */
    top: 88px;
  }
}

.brief__toc {
  padding-left: var(--sp-5);
  border-left: 1px solid var(--rule-light);
}

.brief__toc-title {
  margin-bottom: var(--sp-4);
  color: var(--muted);
  font-family: var(--font);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.brief__toc ol {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: toc;
}

.brief__toc li {
  margin-top: 0;
  counter-increment: toc;
}

.brief__toc li + li {
  margin-top: var(--sp-3);
}

.brief__toc a {
  display: block;
  color: var(--ink-body);
  font-size: var(--fs-small);
  line-height: 1.4;
  text-decoration: none;
}

.brief__toc a::before {
  content: counter(toc) ".";
  margin-right: var(--sp-2);
  color: var(--accent-base);
  font-weight: 700;
}

.brief__toc a:hover {
  color: var(--accent-base);
  text-decoration: underline;
}

.brief__cta {
  padding: var(--sp-5);
  background: var(--paper-2);
  border-radius: var(--radius-card);
}

.brief__cta p {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-small);
  line-height: 1.5;
}

/* Illustrated cards on the Insights index. */
.issue-card--illustrated {
  padding: 0;
  overflow: hidden;
}

.issue-card__media {
  display: block;
  background: var(--ink);
}

.issue-card__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.issue-card__body {
  padding: var(--sp-5);
}

.issue-card__body > :last-child {
  margin-bottom: 0;
}

/* ======================================================================
   MOTION.

   Four patterns, and that is the whole system. Values come from tokens.css;
   nothing here invents a duration or an easing.

   Three rules this block obeys without exception:

   1. Only transform and opacity are animated. Never height, width, margin or
      top. Those trigger layout, cost frames, and move content under the
      reader, which is both a Cumulative Layout Shift and rude.
   2. Everything that hides an element is nested under `.has-motion`, which
      assets/js/motion.js adds to <html>. Without script, or before it runs,
      every element is already in its final state. A reveal system that hides
      first and shows with script gives a reader without script a blank page.
   3. The whole block is inside prefers-reduced-motion: no-preference. There is
      no separate "reduced" variant to maintain, because the reduced state is
      simply the page as authored.
   ====================================================================== */

@media (prefers-reduced-motion: no-preference) {
  /* ---- 1. Reveal on entry --------------------------------------------- */

  .has-motion [data-reveal] {
    opacity: 0;
    transform: translateY(var(--reveal-shift));
    transition:
      opacity var(--t-enter) var(--ease-enter),
      transform var(--t-enter) var(--ease-enter);
  }

  .has-motion [data-reveal].is-in {
    opacity: 1;
    transform: none;
  }

  /* Stagger children of a revealed group. Done with nth-child rather than a
     per-element custom property, because setting one would need a style
     attribute and the CSP discards those. Six steps covers every group on the
     site; a seventh child simply arrives with the sixth. */
  .has-motion [data-reveal-group].is-in > * {
    opacity: 1;
    transform: none;
    transition-delay: calc(var(--stagger) * 5);
  }

  .has-motion [data-reveal-group].is-in > :nth-child(1) {
    transition-delay: 0ms;
  }

  .has-motion [data-reveal-group].is-in > :nth-child(2) {
    transition-delay: var(--stagger);
  }

  .has-motion [data-reveal-group].is-in > :nth-child(3) {
    transition-delay: calc(var(--stagger) * 2);
  }

  .has-motion [data-reveal-group].is-in > :nth-child(4) {
    transition-delay: calc(var(--stagger) * 3);
  }

  .has-motion [data-reveal-group].is-in > :nth-child(5) {
    transition-delay: calc(var(--stagger) * 4);
  }

  .has-motion [data-reveal-group] > * {
    opacity: 0;
    transform: translateY(var(--reveal-shift));
    transition:
      opacity var(--t-enter) var(--ease-enter),
      transform var(--t-enter) var(--ease-enter);
  }

  /* ---- 2. The governance profile draws itself -------------------------- */

  /* This previously ran on page load, which meant it had finished before a
     reader ever scrolled to it: an animation nobody saw. It now waits for the
     section to enter the viewport. It is the site's signature graphic and the
     one place a little theatre is earned, because watching six bars arrive at
     six different lengths is the argument the page is making. */
  .has-motion .profile__rows .bar__fill {
    transform: scaleX(0);
    transform-origin: left center;
    opacity: 0.4;
    transition:
      transform var(--t-enter) var(--ease-enter),
      opacity var(--t-enter) var(--ease-enter);
  }

  .has-motion .profile__rows.is-in .bar__fill {
    transform: scaleX(1);
    opacity: 1;
  }

  .has-motion .profile__rows.is-in li:nth-child(1) .bar__fill {
    transition-delay: 60ms;
  }

  .has-motion .profile__rows.is-in li:nth-child(2) .bar__fill {
    transition-delay: 150ms;
  }

  .has-motion .profile__rows.is-in li:nth-child(3) .bar__fill {
    transition-delay: 240ms;
  }

  .has-motion .profile__rows.is-in li:nth-child(4) .bar__fill {
    transition-delay: 330ms;
  }

  .has-motion .profile__rows.is-in li:nth-child(5) .bar__fill {
    transition-delay: 420ms;
  }

  .has-motion .profile__rows.is-in li:nth-child(6) .bar__fill {
    transition-delay: 510ms;
  }

  /* ---- 3. Reading progress on a briefing ------------------------------- */

  /* Scroll-driven, in CSS, with no JavaScript at all. Where the browser does
     not support scroll timelines the bar simply stays at zero width and is
     invisible against the rule it sits on, so there is nothing to fall back
     to. */
  @supports (animation-timeline: scroll()) {
    .brief-progress__bar {
      transform-origin: left center;
      animation: read-progress linear both;
      animation-timeline: scroll(root block);
    }
  }

  /* ---- 4. Interaction --------------------------------------------------- */

  .card,
  .issue-card,
  .door {
    transition:
      transform var(--t-base) var(--ease),
      box-shadow var(--t-base) var(--ease),
      border-color var(--t-base) var(--ease);
  }

  .card:hover,
  .issue-card:hover,
  .door:hover {
    transform: translateY(-3px);
  }

  .domains li {
    transition: transform var(--t-base) var(--ease);
  }

  .domains li:hover {
    transform: translateX(3px);
  }
}

/* Header depth cue. Outside the reduced-motion gate because a shadow appearing
   is a state change rather than motion, and it is what separates the sticky
   header from content passing under it. The transition lives on the base
   .site-header rule at the top of this file. */
.site-header.is-scrolled {
  box-shadow:
    0 1px 0 var(--rule-light),
    0 8px 24px rgb(20 24 29 / 7%);
}

/* Zero-height sentinel at the top of the document. The header watches it
   rather than listening to scroll, so nothing runs on the scroll thread. */
.scroll-sentinel {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

/* Reading progress rail, sitting under the header on briefing pages. */
.brief-progress {
  position: sticky;
  top: 0;
  z-index: 99;
  height: 2px;
  background: transparent;
}

.brief-progress__bar {
  display: block;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, var(--accent-base), var(--accent-bright));
  transform: scaleX(0);
}

@keyframes read-progress {
  from {
    transform: scaleX(0);
  }

  to {
    transform: scaleX(1);
  }
}

/* Briefing contents: marks the section being read. */
.brief__toc a.is-current {
  color: var(--accent-base);
  font-weight: 600;
}

.brief__toc a.is-current::before {
  color: var(--accent-base);
}

/* ---- Spacing utilities ---------------------------------------------------
   These exist so no page needs an inline style attribute. The shipped CSP sets
   `style-src 'self'` with no 'unsafe-inline', which means a browser discards
   every inline style attribute in the markup. Local preview does not send
   _headers, so that breakage is invisible until deployment.

   Adding a style attribute to a page is therefore a defect, not a shortcut.
   There is a test for this; see tests/e2e/csp.spec.js. Use these classes, or
   add a component rule if the need is not one-off. Values map to the spacing
   scale in tokens.css. Styles set from JavaScript via element.style are a
   different mechanism (CSSOM) and are not affected by the CSP. */

.mt-5 {
  margin-top: var(--sp-5);
}

.mt-6 {
  margin-top: var(--sp-6);
}

.mt-7 {
  margin-top: var(--sp-7);
}

.mb-5 {
  margin-bottom: var(--sp-5);
}

.pt-8 {
  padding-top: var(--sp-8);
}

.text-left {
  text-align: left;
}
