/* ==========================================================================
   Austin Nguyen — portfolio hub
   assets/css/portfolio.css

   Property token group: "hub". Dark-first, near-monochrome, one lime accent.
   The four case-study cards supply all of the page's color.

   The token block below is GENERATED from design-system/tokens.json.
   Do not hand-edit values here — edit tokens.json, re-run
   tools/check_tokens.py, and regenerate.

   Every rule below the token block consumes var(--semantic-role) only.
   No raw color literals, no primitive references outside the token block.
   ========================================================================== */


/* ==========================================================================
   1. TOKENS  (generated from design-system/tokens.json)
   ========================================================================== */

:root {

  /* --- primitives: primitive.hub --------------------------------------- */
  --hub-ink-950: #0A0E13;
  --hub-ink-900: #111720;
  --hub-ink-850: #161D27;
  --hub-ink-800: #1D2530;
  --hub-ink-700: #2A3441;
  --hub-ink-600: #5A6875;
  --hub-ink-400: #8D9BAA;
  --hub-ink-300: #AFBCC9;
  --hub-ink-100: #DCE4EC;
  --hub-ink-050: #EFF4F9;
  --hub-lime-300: #D4F96B;
  --hub-lime-400: #C3F53C;
  --hub-lime-600: #8FBF12;
  --hub-white: #FFFFFF;

  /* --- primitives: borrowed for the case-study cards --------------------
     The work grid shows four demo sites, and each card carries its own
     demo's accent so the four read as four different design languages.
     These are lifted verbatim from the other property groups in
     tokens.json — primitive.terra, primitive.iron, primitive.lumen and
     primitive.maison — not invented here. They are bound to the
     --case-* semantic roles below and used nowhere else.
     --------------------------------------------------------------------- */
  --terra-clay-600: #A8421D;
  --terra-clay-500: #C4562B;
  --terra-olive-600: #55643C;
  --iron-amber-700: #B45309;
  --iron-amber-500: #F59E0B;
  --iron-navy-800: #1E3A8A;
  --lumen-teal-700: #0E7490;
  --lumen-teal-600: #0891B2;
  --lumen-mint-200: #BFE3DD;
  --maison-gold-400: #D4BC7E;
  --maison-noir-700: #33302B;

  /* --- semantic roles: semantic.hub ------------------------------------ */
  --bg: var(--hub-ink-950);
  --surface: var(--hub-ink-900);
  --surface-raised: var(--hub-ink-850);
  --surface-inset: var(--hub-ink-800);
  --border-subtle: var(--hub-ink-700);
  --border-interactive: var(--hub-ink-600);
  --text-primary: var(--hub-ink-050);
  --text-secondary: var(--hub-ink-300);
  --text-muted: var(--hub-ink-400);
  --action-primary: var(--hub-lime-400);
  --action-primary-hover: var(--hub-lime-300);
  --on-action-primary: var(--hub-ink-950);
  --accent-graphic: var(--hub-lime-600);
  --focus-ring: var(--hub-lime-400);
  --border-interactive-hover: var(--hub-ink-400);
  --text-emphasis: var(--hub-ink-100);
  --text-max: var(--hub-white);

  /* --- semantic roles: case-study accents ------------------------------
     The -dot roles are the readable sibling of each -accent. The accent
     itself is a 4px rule and an SVG fill; the dot is a glyph on the card
     surface, where clay-600, amber-700 and teal-700 all fall under 3:1.
     --------------------------------------------------------------------- */
  --case-terra-accent: var(--terra-clay-600);
  --case-terra-graphic: var(--terra-olive-600);
  --case-terra-dot: var(--terra-clay-500);
  --case-iron-accent: var(--iron-amber-700);
  --case-iron-graphic: var(--iron-navy-800);
  --case-iron-dot: var(--iron-amber-500);
  --case-lumen-accent: var(--lumen-teal-700);
  --case-lumen-graphic: var(--lumen-mint-200);
  --case-lumen-dot: var(--lumen-teal-600);
  --case-maison-accent: var(--maison-gold-400);
  --case-maison-graphic: var(--maison-noir-700);
  --case-maison-dot: var(--maison-gold-400);

  /* --- shared scale: space (scales.space, 4px grid) -------------------- */
  --space-0: 0px;
  --space-px: 2px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-32: 128px;
  --space-40: 160px;

  /* --- shared scale: type (scales.type) -------------------------------- */
  --type-xs: 12px;
  --type-sm: 14px;
  --type-base: 16px;
  --type-md: 18px;
  --type-lg: 20px;
  --type-xl: 24px;
  --type-2xl: 30px;
  --type-3xl: 36px;
  --type-4xl: 48px;
  --type-5xl: 60px;
  --type-6xl: 72px;
  --type-7xl: 96px;

  /* --- shared scale: leading (scales.leading) -------------------------- */
  --leading-tight: 1.05;
  --leading-snug: 1.2;
  --leading-normal: 1.5;
  --leading-relaxed: 1.65;
  --leading-loose: 1.75;

  /* --- shared scale: weight (scales.weight) ---------------------------- */
  --weight-light: 300;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --weight-black: 800;

  /* --- shared scale: radius (scales.radius) ----------------------------
     The hub binds md 8 and lg 12 only (MASTER section 5).
     --------------------------------------------------------------------- */
  --radius-none: 0px;
  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 20px;
  --radius-3xl: 24px;
  --radius-4xl: 32px;
  --radius-full: 999px;

  /* --- shared scale: motion (scales.motion) ---------------------------- */
  --dur-instant: 120ms;
  --dur-fast: 180ms;
  --dur-base: 240ms;
  --dur-slow: 320ms;
  --dur-slower: 480ms;
  --dur-slowest: 640ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* --- shared scale: z (scales.z) -------------------------------------- */
  --z-base: 0;
  --z-raised: 10;
  --z-sticky: 20;
  --z-overlay: 40;
  --z-modal: 100;
  --z-toast: 1000;

  /* --- shared scale: container (scales.container) ---------------------- */
  --container-prose: 680px;
  --container-narrow: 880px;
  --container-default: 1160px;
  --container-wide: 1360px;

  /* --- typography stacks (typography.hub) ------------------------------ */
  --font-display: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-body: 'Space Grotesk', 'Segoe UI', system-ui, -apple-system, sans-serif;

  /* --- derived layout values -------------------------------------------
     Composed from the scales above, never from fresh numbers. The hairline
     is the one exception: it is deliberately one device pixel, not a
     spacing step.
     --------------------------------------------------------------------- */
  --gutter: var(--space-5);
  --rule-hairline: 1px;
  --header-height: var(--space-16);

  /* Breakpoints live in the media queries themselves because custom
     properties cannot be used in media conditions. The token values from
     scales.breakpoint are 480, 768, 1024, 1280 and 1536. */
}


/* ==========================================================================
   2. RESET AND BASE
   ========================================================================== */

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

* {
  margin: 0;
}

html {
  background-color: var(--bg);
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-height) + var(--space-6));
}

body {
  background-color: transparent;
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: var(--type-base);
  font-weight: var(--weight-regular);
  line-height: var(--leading-relaxed);
  min-height: 100%;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
}

svg {
  height: auto;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
}

/* Scoped to classed lists so an unclassed <ul> in prose keeps its markers.
   Every classed list in the markup carries role="list", because Safari with
   VoiceOver drops list semantics from any list whose list-style is none. */
ul[class],
ol[class] {
  list-style: none;
  padding: 0;
}

a {
  color: var(--action-primary);
  text-decoration-color: var(--action-primary);
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
  transition: color var(--dur-fast) var(--ease-out),
              text-decoration-thickness var(--dur-fast) var(--ease-out);
}

a:hover {
  color: var(--action-primary-hover);
  text-decoration-thickness: 2px;
}

strong,
b {
  color: var(--text-primary);
  font-weight: var(--weight-semibold);
}

/* No border-radius here: a bare :focus-visible radius reshapes every
   element that does not declare its own (the skip link, .brand, inline
   links, the mobile nav links) at the moment it receives focus. Elements
   that want a rounded ring carry their own radius in their own rule. */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

::selection {
  background-color: var(--action-primary);
  color: var(--on-action-primary);
}


/* ==========================================================================
   3. TYPOGRAPHY ROLES
   ========================================================================== */

h1, h2, h3, h4 {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  line-height: var(--leading-snug);
  text-wrap: balance;
}

/* MASTER section 9 item 5, settled: Space Grotesk stays on headings and UI,
   long-form body copy is set in Archivo. --font-display is Archivo, so the
   prose selectors below take it and everything else - body, buttons,
   eyebrows, labels, nav, badges, metadata - stays on --font-body. */
.hero__lede,
.t-lead,
.case__problem,
.work__notice-text,
.capability__text,
.deliver__text,
.proof__text,
.step__role-text,
.process__total-text,
.faq__panel p,
.faq__foot,
.terms-card__text,
.terms-card__list li,
.tier__who,
.contact__direct-text,
.form__intro,
.form__success-text,
.site-footer__blurb {
  font-family: var(--font-display);
}

/* Typography roles from MASTER section 6. The page binds the ones it uses;
   the hero binds display sizes directly on .hero__name because it is the
   only element on the site that runs the full 36 -> 96 ramp. */
.t-h2 {
  font-size: var(--type-2xl);
  letter-spacing: -0.025em;
  line-height: var(--leading-snug);
}

.t-h3 {
  font-size: var(--type-xl);
  letter-spacing: -0.02em;
}

.t-lead {
  color: var(--text-emphasis);
  font-size: var(--type-md);
  line-height: var(--leading-relaxed);
  max-width: var(--container-prose);
}

.t-eyebrow {
  align-items: center;
  color: var(--text-muted);
  display: flex;
  font-family: var(--font-body);
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  gap: var(--space-3);
  letter-spacing: 0.16em;
  line-height: var(--leading-normal);
  text-transform: uppercase;
}

.t-eyebrow__num {
  color: var(--action-primary);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
}

.t-eyebrow__num::after {
  background-color: var(--border-subtle);
  content: "";
  display: inline-block;
  height: 1px;
  margin-inline-start: var(--space-3);
  vertical-align: middle;
  width: var(--space-6);
}

code {
  background-color: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.875em;
  padding: var(--space-px) var(--space-2);
  white-space: nowrap;
}

.t-num {
  font-variant-numeric: tabular-nums;
}


/* ==========================================================================
   4. LAYOUT PRIMITIVES
   ========================================================================== */

.container {
  margin-inline: auto;
  max-width: var(--container-default);
  padding-inline: var(--gutter);
  width: 100%;
}

/* The work gallery runs wider than the rest of the page so the four cards
   can go two-up without crushing. Every other section stays at 1160. */
.container--wide {
  max-width: var(--container-wide);
}

.section {
  padding-block: var(--space-16);
  position: relative;
}

.section--tight {
  padding-block: var(--space-12);
}

.section__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-bottom: var(--space-10);
}

.section__head .t-lead {
  margin-top: var(--space-1);
}

.section--surface {
  background-color: var(--surface);
}


/* ==========================================================================
   5. UTILITIES
   ========================================================================== */

.skip-link {
  background-color: var(--action-primary);
  border-radius: var(--radius-md);
  color: var(--on-action-primary);
  font-family: var(--font-body);
  font-size: var(--type-sm);
  font-weight: var(--weight-bold);
  left: var(--space-4);
  padding: var(--space-3) var(--space-5);
  position: fixed;
  text-decoration: none;
  top: var(--space-4);
  transform: translateY(-200%);
  z-index: var(--z-toast);
}

.skip-link:focus-visible {
  color: var(--on-action-primary);
  transform: translateY(0);
}

.visually-hidden {
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

.grain {
  inset: 0;
  mix-blend-mode: overlay;
  opacity: 0.05;
  pointer-events: none;
  position: fixed;
  z-index: -1;
}


/* ==========================================================================
   6. COMPONENT — BUTTON
   Contract: MASTER section 6. Every state declared, never defaulted.
   Sizes: sm 36 (desktop only), md 44, lg 52. Touch floor is 44px.
   ========================================================================== */

.btn {
  align-items: center;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  display: inline-flex;
  font-family: var(--font-body);
  font-size: var(--type-base);
  font-weight: var(--weight-semibold);
  gap: var(--space-2);
  justify-content: center;
  letter-spacing: -0.01em;
  line-height: var(--leading-normal);
  min-height: 44px;
  padding-inline: var(--space-5);
  text-align: center;
  text-decoration: none;
  transition: background-color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out),
              transform var(--dur-instant) var(--ease-out);
}

.btn--lg {
  font-size: var(--type-md);
  min-height: 52px;
  padding-inline: var(--space-6);
}

.btn--sm {
  font-size: var(--type-sm);
  min-height: 36px;
  padding-inline: var(--space-3);
}

.btn--primary {
  background-color: var(--action-primary);
  color: var(--on-action-primary);
}

.btn--primary:hover {
  background-color: var(--action-primary-hover);
  color: var(--on-action-primary);
}

.btn--primary:active {
  transform: scale(0.98);
}

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

.btn--secondary:hover {
  background-color: var(--surface-raised);
  color: var(--action-primary-hover);
}

.btn--secondary:active {
  transform: scale(0.98);
}

.btn--ghost {
  background-color: transparent;
  border-color: var(--border-subtle);
  color: var(--text-primary);
}

.btn--ghost:hover {
  background-color: var(--surface-raised);
  border-color: var(--border-interactive);
  color: var(--text-primary);
}

.btn--ghost:active {
  transform: scale(0.98);
}

.btn:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.btn[disabled],
.btn[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.45;
  transform: none;
}

.btn__arrow {
  flex: none;
  height: 14px;
  transition: transform var(--dur-base) var(--ease-out);
  width: 14px;
}

.btn:hover .btn__arrow {
  transform: translateX(3px);
}


/* ==========================================================================
   7. COMPONENT — LINK, BADGE, SURFACE
   ========================================================================== */

.link-inline {
  color: var(--action-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.link-quiet {
  color: var(--text-secondary);
  text-decoration: none;
}

.link-quiet:hover {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.badge {
  align-items: center;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-full);
  color: var(--text-muted);
  display: inline-flex;
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  gap: var(--space-2);
  letter-spacing: 0.08em;
  line-height: var(--leading-tight);
  padding: var(--space-2) var(--space-3);
  text-transform: uppercase;
  white-space: nowrap;
}

.badge__dot {
  background-color: currentColor;
  border-radius: var(--radius-full);
  flex: none;
  height: 6px;
  width: 6px;
}


/* ==========================================================================
   8. SITE HEADER AND NAV
   ========================================================================== */

.site-header {
  background-color: var(--bg);
  border-bottom: var(--rule-hairline) solid var(--border-subtle);
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}

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

.brand {
  align-items: center;
  color: var(--text-primary);
  display: inline-flex;
  gap: var(--space-3);
  min-height: 44px;
  text-decoration: none;
}

.brand:hover {
  color: var(--text-primary);
}

.brand__mark {
  flex: none;
  height: 32px;
  width: 32px;
}

.brand__mark-frame {
  fill: none;
  stroke: var(--border-interactive);
  stroke-width: 2;
}

.brand__mark-glyph {
  fill: var(--action-primary);
}

.brand__name {
  font-family: var(--font-display);
  font-size: var(--type-base);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  line-height: var(--leading-tight);
}

.brand__role {
  color: var(--text-muted);
  display: block;
  font-family: var(--font-body);
  font-size: var(--type-xs);
  font-weight: var(--weight-regular);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.nav-toggle {
  align-items: center;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  display: inline-flex;
  gap: var(--space-2);
  font-size: var(--type-sm);
  font-weight: var(--weight-medium);
  justify-content: center;
  min-height: 44px;
  padding-inline: var(--space-4);
}

.nav-toggle:hover {
  background-color: var(--surface-raised);
  border-color: var(--border-interactive);
}

.nav-toggle__bars {
  display: inline-flex;
  flex-direction: column;
  gap: var(--space-1);
  width: var(--space-5);
}

.nav-toggle__bars span {
  background-color: currentColor;
  display: block;
  height: var(--space-px);
  transition: transform var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
  width: 100%;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* The mobile nav is shown and hidden with a class rather than the hidden
   attribute, so that the desktop override below cannot leave it visible on
   screen but missing from the accessibility tree. */
.site-nav {
  background-color: var(--surface);
  border-bottom: var(--rule-hairline) solid var(--border-subtle);
  border-top: var(--rule-hairline) solid var(--border-subtle);
  display: none;
  left: 0;
  padding-block: var(--space-2);
  position: absolute;
  right: 0;
  top: 100%;
  z-index: var(--z-overlay);
}

.site-nav.is-open {
  display: block;
}

.site-nav__list {
  display: flex;
  flex-direction: column;
  margin-inline: auto;
  max-width: var(--container-default);
  padding-inline: var(--gutter);
  width: 100%;
}

.site-nav__link {
  align-items: center;
  border-bottom: var(--rule-hairline) solid var(--border-subtle);
  color: var(--text-secondary);
  display: flex;
  font-size: var(--type-base);
  font-weight: var(--weight-medium);
  min-height: 52px;
  text-decoration: none;
  width: 100%;
}

.site-nav__list li:last-child .site-nav__link {
  border-bottom: 0;
}

.site-nav__link:hover {
  color: var(--text-primary);
}

.site-nav__link[aria-current="true"] {
  color: var(--action-primary);
}

.site-header__cta {
  display: none;
}


/* ==========================================================================
   9. HERO
   ========================================================================== */

.hero {
  overflow: hidden;
  padding-block: var(--space-16) var(--space-16);
  position: relative;
}

.hero__backdrop {
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  position: absolute;
  z-index: var(--z-base);
}

.hero__grid {
  background-image:
    repeating-linear-gradient(to right, var(--border-subtle) 0 1px, transparent 1px 80px),
    repeating-linear-gradient(to bottom, var(--border-subtle) 0 1px, transparent 1px 80px);
  inset: 0;
  -webkit-mask-image: radial-gradient(120% 90% at 12% 0%, var(--bg) 0%, transparent 72%);
  mask-image: radial-gradient(120% 90% at 12% 0%, var(--bg) 0%, transparent 72%);
  opacity: 0.55;
  position: absolute;
}

.hero__glow {
  background-image:
    radial-gradient(58% 48% at 8% 4%, var(--accent-graphic) 0%, transparent 62%),
    radial-gradient(46% 40% at 96% 22%, var(--surface-inset) 0%, transparent 68%);
  inset: -20% -10% auto -10%;
  height: 120%;
  opacity: 0.28;
  position: absolute;
}

.hero__inner {
  position: relative;
  z-index: var(--z-raised);
}

.hero__title {
  margin-top: var(--space-6);
}

.hero__name {
  display: block;
  font-size: var(--type-3xl);
  font-weight: var(--weight-black);
  letter-spacing: -0.04em;
  line-height: var(--leading-tight);
}

.hero__role {
  color: var(--text-secondary);
  display: block;
  font-size: var(--type-lg);
  font-weight: var(--weight-medium);
  letter-spacing: -0.01em;
  line-height: var(--leading-snug);
  margin-top: var(--space-3);
  max-width: 20ch;
}

.hero__rule {
  background-color: var(--action-primary);
  height: var(--space-1);
  margin-block: var(--space-6);
  width: var(--space-20);
}

.hero__lede {
  color: var(--text-secondary);
  font-size: var(--type-md);
  line-height: var(--leading-relaxed);
  max-width: 48ch;
}

.hero__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-8);
}

.hero__meta {
  border-top: var(--rule-hairline) solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-10);
  padding-top: var(--space-5);
}

.hero__meta-item {
  color: var(--text-muted);
  display: flex;
  font-size: var(--type-sm);
  gap: var(--space-3);
  line-height: var(--leading-normal);
}

.hero__meta-key {
  color: var(--text-primary);
  flex: none;
  font-weight: var(--weight-medium);
  min-width: 9ch;
}


/* ==========================================================================
   10. CAPABILITY STRIP
   ========================================================================== */

.capability {
  background-color: var(--surface);
  border-block: var(--rule-hairline) solid var(--border-subtle);
}

.capability__grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  margin-top: var(--space-8);
}

.capability__item {
  border-top: 2px solid var(--border-subtle);
  padding-top: var(--space-4);
}

.capability__item:first-child {
  border-top-color: var(--action-primary);
}

.capability__label {
  align-items: baseline;
  display: flex;
  gap: var(--space-3);
}

.capability__num {
  color: var(--action-primary);
  font-family: var(--font-body);
  font-size: var(--type-xs);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  letter-spacing: 0.1em;
}

.capability__title {
  font-size: var(--type-md);
  font-weight: var(--weight-bold);
  letter-spacing: -0.015em;
}

.capability__text {
  color: var(--text-muted);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-2);
}


/* ==========================================================================
   11. WORK — CASE STUDY CARDS
   ========================================================================== */

.work__notice {
  align-items: flex-start;
  background-color: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--action-primary);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-10);
  padding: var(--space-5);
}

.work__notice-title {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-base);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
}

.work__notice-text {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  max-width: 72ch;
}

.work__grid {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
}

.case {
  background-color: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  border-top-width: 4px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: border-color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out),
              background-color var(--dur-base) var(--ease-out);
}

.case:hover {
  background-color: var(--surface-raised);
  border-color: var(--border-interactive);
  transform: translateY(-2px);
}

.case--terra {
  border-top-color: var(--case-terra-accent);
}

.case--iron {
  border-top-color: var(--case-iron-accent);
}

.case--lumen {
  border-top-color: var(--case-lumen-accent);
}

.case--maison {
  border-top-color: var(--case-maison-accent);
}

.case__art {
  background-color: var(--surface-inset);
  border-bottom: 1px solid var(--border-subtle);
  padding: var(--space-5);
}

.case__svg {
  display: block;
  height: auto;
  width: 100%;
}

/* Art fills. Every shape class resolves through a semantic role, so the
   four abstractions differ only by which case modifier wraps them. */
.art-field {
  fill: var(--surface-raised);
}

.art-line {
  fill: var(--border-subtle);
}

.art-ink {
  fill: var(--border-interactive);
}

.art-stroke {
  fill: none;
  stroke: var(--border-interactive);
  stroke-width: 1.5;
}

.case--terra .art-accent { fill: var(--case-terra-accent); }
.case--terra .art-second { fill: var(--case-terra-graphic); }
.case--terra .art-accent-stroke { fill: none; stroke: var(--case-terra-accent); stroke-width: 1.5; }

.case--iron .art-accent { fill: var(--case-iron-accent); }
.case--iron .art-second { fill: var(--case-iron-graphic); }
.case--iron .art-accent-stroke { fill: none; stroke: var(--case-iron-accent); stroke-width: 1.5; }

.case--lumen .art-accent { fill: var(--case-lumen-accent); }
.case--lumen .art-second { fill: var(--case-lumen-graphic); }
.case--lumen .art-accent-stroke { fill: none; stroke: var(--case-lumen-accent); stroke-width: 1.5; }

.case--maison .art-accent { fill: var(--case-maison-accent); }
.case--maison .art-second { fill: var(--case-maison-graphic); }
.case--maison .art-accent-stroke { fill: none; stroke: var(--case-maison-accent); stroke-width: 1.5; }

.case__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-5) var(--space-6);
}

.case__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.case__tags {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.case__vertical {
  color: var(--text-muted);
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.case__name {
  font-size: var(--type-xl);
  font-weight: var(--weight-black);
  letter-spacing: -0.03em;
  line-height: var(--leading-snug);
}

/* The dot is a glyph on --surface, not a rule on --bg, so it binds the
   -dot role rather than the -accent one. Each card keeps its own demo's
   color; all four now clear 3:1 on the card (4.04 / 8.38 / 4.89 / 9.68). */
.case--terra .case__name-dot { color: var(--case-terra-dot); }
.case--iron .case__name-dot { color: var(--case-iron-dot); }
.case--lumen .case__name-dot { color: var(--case-lumen-dot); }
.case--maison .case__name-dot { color: var(--case-maison-dot); }

.case__problem {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
}

.case__subhead {
  color: var(--text-muted);
  font-size: var(--type-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.case__specs {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.case__specs li {
  color: var(--text-secondary);
  display: flex;
  font-size: var(--type-base);
  gap: var(--space-3);
  line-height: var(--leading-normal);
}

.case__specs li::before {
  color: var(--action-primary);
  content: "\002B";
  flex: none;
  font-weight: var(--weight-bold);
  line-height: inherit;
}

.case__notes {
  border-top: var(--rule-hairline) solid var(--border-subtle);
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding-top: var(--space-4);
}

.case__notes-row {
  display: flex;
  gap: var(--space-3);
}

.case__notes dt {
  color: var(--text-muted);
  flex: none;
  font-size: var(--type-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.1em;
  line-height: var(--leading-loose);
  text-transform: uppercase;
  width: 7ch;
}

.case__notes dd {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-normal);
  margin: 0;
}

.case__foot {
  margin-top: auto;
  padding-top: var(--space-5);
}

.case__link {
  width: 100%;
}

.case__url {
  color: var(--text-muted);
  display: block;
  font-size: var(--type-xs);
  letter-spacing: 0.04em;
  margin-top: var(--space-3);
  overflow-wrap: anywhere;
}

/* --- checkable facts block (this is where social proof would sit) ------ */

.proof {
  border-top: var(--rule-hairline) solid var(--border-subtle);
  margin-top: var(--space-16);
  padding-top: var(--space-10);
}

.proof__grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  margin-top: var(--space-8);
}

.proof__item {
  background-color: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-5);
}

.proof__check {
  color: var(--action-primary);
  display: block;
  height: 20px;
  margin-bottom: var(--space-3);
  width: 20px;
}

.proof__title {
  font-size: var(--type-base);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
}

.proof__text {
  color: var(--text-muted);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-2);
}


/* ==========================================================================
   12. WHAT YOU GET
   ========================================================================== */

.deliver__grid {
  counter-reset: deliver;
  display: grid;
  gap: 0;
  grid-template-columns: 1fr;
  margin-top: var(--space-8);
}

.deliver__item {
  border-top: var(--rule-hairline) solid var(--border-subtle);
  counter-increment: deliver;
  display: grid;
  gap: var(--space-2) var(--space-5);
  grid-template-columns: auto 1fr;
  padding-block: var(--space-5);
}

.deliver__item:last-child {
  border-bottom: var(--rule-hairline) solid var(--border-subtle);
}

.deliver__item::before {
  color: var(--action-primary);
  content: counter(deliver, decimal-leading-zero);
  font-family: var(--font-body);
  font-size: var(--type-sm);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  grid-row: span 2;
  letter-spacing: 0.08em;
  line-height: var(--leading-relaxed);
  padding-top: var(--space-px);
}

.deliver__title {
  font-size: var(--type-md);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.015em;
}

.deliver__text {
  color: var(--text-muted);
  font-size: var(--type-base);
  grid-column: 2;
  line-height: var(--leading-relaxed);
  max-width: 68ch;
}


/* ==========================================================================
   13. PRICING
   ========================================================================== */

.pricing__grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  margin-top: var(--space-10);
}

.tier {
  background-color: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  padding: var(--space-6) var(--space-5);
  position: relative;
}

.tier--featured {
  background-color: var(--surface-raised);
  border-color: var(--action-primary);
  border-width: 2px;
}

.tier__flag {
  background-color: var(--action-primary);
  border-radius: var(--radius-full);
  color: var(--on-action-primary);
  font-size: var(--type-xs);
  font-weight: var(--weight-bold);
  left: var(--space-5);
  letter-spacing: 0.1em;
  line-height: var(--leading-tight);
  padding: var(--space-2) var(--space-3);
  position: absolute;
  text-transform: uppercase;
  top: 0;
  transform: translateY(-50%);
}

.tier__name {
  font-size: var(--type-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
}

.tier__price {
  align-items: baseline;
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.tier__amount {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-4xl);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-black);
  letter-spacing: -0.04em;
  line-height: var(--leading-tight);
}

.tier--featured .tier__amount {
  color: var(--text-max);
}

.tier__unit {
  color: var(--text-muted);
  font-size: var(--type-sm);
}

.tier__who {
  border-bottom: var(--rule-hairline) solid var(--border-subtle);
  color: var(--text-emphasis);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-4);
  padding-bottom: var(--space-5);
}

.tier__scope {
  color: var(--text-muted);
  font-size: var(--type-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.12em;
  margin-top: var(--space-5);
  text-transform: uppercase;
}

.tier__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.tier__list li {
  color: var(--text-secondary);
  display: flex;
  font-size: var(--type-base);
  gap: var(--space-3);
  line-height: var(--leading-normal);
}

.tier__tick {
  color: var(--action-primary);
  flex: none;
  height: 16px;
  margin-top: 4px;
  width: 16px;
}

.tier__time {
  border-top: var(--rule-hairline) solid var(--border-subtle);
  color: var(--text-muted);
  font-size: var(--type-sm);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
}

.tier__time strong {
  color: var(--text-primary);
}

.tier__cta {
  margin-top: var(--space-5);
  width: 100%;
}

.pricing__terms {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  margin-top: var(--space-10);
}

.terms-card {
  background-color: var(--surface-inset);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-5);
}

.terms-card--guarantee {
  border: 1px solid var(--action-primary);
}

.terms-card__title {
  font-size: var(--type-md);
  font-weight: var(--weight-bold);
  letter-spacing: -0.015em;
}

.terms-card__text {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-3);
}

.terms-card__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.terms-card__list li {
  color: var(--text-muted);
  display: flex;
  font-size: var(--type-base);
  gap: var(--space-3);
  line-height: var(--leading-normal);
}

.terms-card__list li::before {
  color: var(--text-muted);
  content: "\2014";
  flex: none;
}


/* ==========================================================================
   14. PROCESS
   ========================================================================== */

.process__list {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
  margin-top: var(--space-10);
  position: relative;
}

.step {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: auto 1fr;
  position: relative;
}

.step__marker {
  align-items: center;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.step__num {
  align-items: center;
  background-color: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  color: var(--action-primary);
  display: flex;
  flex: none;
  font-family: var(--font-body);
  font-size: var(--type-sm);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  height: 44px;
  justify-content: center;
  width: 44px;
}

.step__spine {
  background-color: var(--border-subtle);
  flex: 1;
  min-height: var(--space-6);
  width: 1px;
}

.step:last-child .step__spine {
  display: none;
}

.step__body {
  padding-bottom: var(--space-2);
}

.step__when {
  color: var(--text-muted);
  font-size: var(--type-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.step__title {
  font-size: var(--type-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  margin-top: var(--space-2);
}

.step__split {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
  margin-top: var(--space-4);
}

.step__role {
  border-top: 2px solid var(--border-subtle);
  padding-top: var(--space-3);
}

.step__role--mine {
  border-top-color: var(--action-primary);
}

.step__role-label {
  color: var(--text-muted);
  font-size: var(--type-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.step__role-text {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-2);
}

.process__total {
  background-color: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  margin-top: var(--space-10);
  padding: var(--space-5);
}

.process__total-text {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
}

.process__total-text strong {
  color: var(--action-primary);
}


/* ==========================================================================
   15. FAQ
   ========================================================================== */

.faq__list {
  border-top: var(--rule-hairline) solid var(--border-subtle);
  margin-top: var(--space-8);
  max-width: var(--container-narrow);
}

.faq__item {
  border-bottom: var(--rule-hairline) solid var(--border-subtle);
}

.faq__trigger {
  align-items: flex-start;
  color: var(--text-primary);
  display: flex;
  font-family: var(--font-display);
  font-size: var(--type-md);
  font-weight: var(--weight-semibold);
  gap: var(--space-4);
  justify-content: space-between;
  letter-spacing: -0.015em;
  line-height: var(--leading-normal);
  min-height: 52px;
  padding-block: var(--space-4);
  text-align: left;
  transition: color var(--dur-fast) var(--ease-out);
  width: 100%;
}

.faq__trigger:hover {
  color: var(--action-primary);
}

.faq__icon {
  flex: none;
  height: 20px;
  margin-top: 3px;
  stroke: currentColor;
  transition: transform var(--dur-base) var(--ease-out);
  width: 20px;
}

.faq__trigger[aria-expanded="true"] {
  color: var(--action-primary);
}

.faq__trigger[aria-expanded="true"] .faq__icon {
  transform: rotate(45deg);
}

.faq__panel {
  padding-bottom: var(--space-6);
  padding-right: var(--space-8);
}

.faq__panel[hidden] {
  display: none;
}

.faq__panel p + p {
  margin-top: var(--space-3);
}

.faq__panel p {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  max-width: 68ch;
}

.faq__foot {
  color: var(--text-muted);
  font-size: var(--type-base);
  margin-top: var(--space-6);
  max-width: var(--container-prose);
}


/* ==========================================================================
   16. CONTACT
   ========================================================================== */

.contact__layout {
  display: grid;
  gap: var(--space-10);
  grid-template-columns: 1fr;
  margin-top: var(--space-8);
}

.contact__direct {
  background-color: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-5);
}

.contact__direct-title {
  font-size: var(--type-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
}

.contact__direct-text {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-3);
}

.contact__mail {
  margin-top: var(--space-5);
  width: 100%;
}

.contact__address {
  color: var(--text-muted);
  display: block;
  font-size: var(--type-sm);
  margin-top: var(--space-4);
  overflow-wrap: anywhere;
}

.contact__promises {
  border-top: var(--rule-hairline) solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-5);
  padding-top: var(--space-5);
}

.contact__promises li {
  color: var(--text-muted);
  display: flex;
  font-size: var(--type-base);
  gap: var(--space-3);
  line-height: var(--leading-normal);
}

.contact__promises li::before {
  color: var(--action-primary);
  content: "\2192";
  flex: none;
}


/* --- Field primitive (MASTER section 6) -------------------------------- */

.form {
  background-color: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-5);
}

.form[hidden] {
  display: none;
}

.form__legend {
  font-family: var(--font-display);
  font-size: var(--type-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  padding: 0;
}

.form__intro {
  color: var(--text-muted);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-3);
}

.form__grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  margin-top: var(--space-6);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field--wide {
  grid-column: 1 / -1;
}

.field__label {
  color: var(--text-primary);
  font-size: var(--type-sm);
  font-weight: var(--weight-medium);
  letter-spacing: 0.01em;
}

.field__hint {
  color: var(--text-muted);
  font-size: var(--type-xs);
  font-weight: var(--weight-regular);
}

.field__control {
  background-color: var(--surface-inset);
  border: 1px solid var(--border-interactive);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--type-base);
  line-height: var(--leading-normal);
  min-height: 48px;
  padding: var(--space-3) var(--space-4);
  transition: border-color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out);
  width: 100%;
}

.field__control::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

.field__control:hover {
  border-color: var(--border-interactive-hover);
}

.field__control:focus-visible {
  border-color: var(--action-primary);
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.field__control[disabled] {
  cursor: not-allowed;
  opacity: 0.45;
}

.field__control[readonly] {
  background-color: var(--surface-raised);
}

textarea.field__control {
  line-height: var(--leading-relaxed);
  min-height: var(--space-32);
  resize: vertical;
}

select.field__control {
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
    linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position:
    calc(100% - 20px) calc(50% + 2px),
    calc(100% - 14px) calc(50% + 2px);
  background-repeat: no-repeat;
  background-size: 6px 6px, 6px 6px;
  cursor: pointer;
  padding-right: var(--space-10);
}

/* The hub group in tokens.json ships no danger role, and MASTER section 8
   says not to invent a primitive for it. Validation messages therefore use
   the accent, which already carries "look here" on this page, and never
   rely on color alone: the message is text, tied to the field by
   aria-describedby, and announced with role="alert". */
.field__error {
  color: var(--action-primary);
  font-size: var(--type-sm);
  font-weight: var(--weight-medium);
  line-height: var(--leading-normal);
}

.field__error[hidden] {
  display: none;
}

.field__control[aria-invalid="true"] {
  border-color: var(--action-primary);
}

.form__foot {
  align-items: flex-start;
  border-top: var(--rule-hairline) solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
}

.form__note {
  color: var(--text-muted);
  font-size: var(--type-sm);
  line-height: var(--leading-relaxed);
}

.form__submit {
  width: 100%;
}

.form__success {
  align-items: flex-start;
  background-color: var(--surface-inset);
  border: 1px solid var(--action-primary);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6) var(--space-5);
}

.form__success[hidden] {
  display: none;
}

.form__success-icon {
  color: var(--action-primary);
  height: var(--space-8);
  width: var(--space-8);
}

.form__success-title {
  font-size: var(--type-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
}

.form__success-text {
  color: var(--text-secondary);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
}


/* ==========================================================================
   17. FOOTER
   ========================================================================== */

.site-footer {
  background-color: var(--surface);
  border-top: var(--rule-hairline) solid var(--border-subtle);
  padding-block: var(--space-12) var(--space-8);
}

.site-footer__grid {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
}

.site-footer__blurb {
  color: var(--text-muted);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  margin-top: var(--space-4);
  max-width: 46ch;
}

.site-footer__heading {
  color: var(--text-muted);
  font-family: var(--font-body);
  font-size: var(--type-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.site-footer__list {
  display: flex;
  flex-direction: column;
  margin-top: var(--space-3);
}

.site-footer__list a {
  align-items: center;
  color: var(--text-secondary);
  display: flex;
  font-size: var(--type-sm);
  min-height: 44px;
  text-decoration: none;
}

.site-footer__list a:hover {
  color: var(--action-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.site-footer__bottom {
  align-items: flex-start;
  border-top: var(--rule-hairline) solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-10);
  padding-top: var(--space-6);
}

.site-footer__legal {
  color: var(--text-muted);
  font-size: var(--type-xs);
  line-height: var(--leading-relaxed);
  max-width: 76ch;
}


/* ==========================================================================
   18. SCROLL REVEAL
   Applied only when JS is running, so the page is fully readable without it.
   ========================================================================== */

.js .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

.js .reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}


/* ==========================================================================
   19. IMAGERY
   All art on this page is hand-authored inline SVG plus layered CSS
   gradients. There are no image files anywhere in this build.

   --- PHOTO SWAP POINTS -------------------------------------------------
   Replace the gradient/SVG art on these selectors with real photography:
     .hero__backdrop   -> 1920x1080 backdrop, dark, low detail behind type
     .hero__grid       -> remove entirely once a photo backdrop is in
     .case__art        -> 800x600 each, one screenshot per demo site
     .brand__mark      -> keep as SVG; it is the logotype, not an image
   Each swap point already reserves its own aspect ratio, so dropping a
   real asset in does not move the layout. Set width and height attributes
   on the replacement and add loading="lazy" to anything below the fold.
   ---------------------------------------------------------------------- */


/* ==========================================================================
   20. RESPONSIVE — mobile-first, at the token breakpoints
   scales.breakpoint: sm 480, md 768, lg 1024, xl 1280, 2xl 1536
   ========================================================================== */

/* --- sm: 480px -------------------------------------------------------- */
@media (min-width: 480px) {

  :root {
    --gutter: var(--space-6);
  }

  .hero__name {
    font-size: var(--type-4xl);
  }

  .hero__role {
    font-size: var(--type-xl);
  }

  .hero__actions {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .hero__actions .btn {
    flex: 1 1 auto;
    min-width: var(--space-40);
  }

  .t-h2 {
    font-size: var(--type-3xl);
  }

  .capability__grid {
    gap: var(--space-6) var(--space-8);
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .proof__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .step__split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .case__link {
    width: auto;
  }

  .form__submit,
  .contact__mail {
    width: auto;
  }
}

/* --- md: 768px -------------------------------------------------------- */
@media (min-width: 768px) {

  :root {
    --gutter: var(--space-8);
    --header-height: calc(var(--space-16) + var(--space-2));
  }

  .section {
    padding-block: var(--space-20);
  }

  .section--tight {
    padding-block: var(--space-16);
  }

  .hero {
    padding-block: var(--space-20) var(--space-20);
  }

  .hero__name {
    font-size: var(--type-5xl);
  }

  .hero__role {
    font-size: var(--type-2xl);
    max-width: 24ch;
  }

  .hero__lede {
    font-size: var(--type-lg);
  }

  .hero__meta {
    flex-direction: row;
    gap: var(--space-10);
  }

  .hero__meta-item {
    flex-direction: column;
    gap: var(--space-1);
  }

  .hero__meta-key {
    color: var(--text-muted);
    font-size: var(--type-xs);
    letter-spacing: 0.12em;
    min-width: 0;
    text-transform: uppercase;
  }

  .hero__meta-val {
    color: var(--text-secondary);
  }

  .t-h2 {
    font-size: var(--type-4xl);
  }

  .t-h3 {
    font-size: var(--type-2xl);
  }

  .t-lead {
    font-size: var(--type-lg);
  }

  .work__grid {
    gap: var(--space-8);
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .case__body {
    padding: var(--space-8) var(--space-6);
  }

  .case__name {
    font-size: var(--type-2xl);
  }

  .work__notice {
    flex-direction: row;
    gap: var(--space-6);
    padding: var(--space-6);
  }

  .work__notice-title {
    flex: none;
    width: 18ch;
  }

  .proof__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .deliver__grid {
    column-gap: var(--space-10);
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .pricing__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tier--premium {
    grid-column: span 2;
  }

  .pricing__terms {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .terms-card {
    padding: var(--space-8) var(--space-6);
  }

  .process__list {
    gap: var(--space-10);
  }

  .step {
    gap: var(--space-6);
  }

  .step__title {
    font-size: var(--type-xl);
  }

  .faq__trigger {
    font-size: var(--type-lg);
    padding-block: var(--space-5);
  }

  .contact__layout {
    align-items: start;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--space-8);
  }

  .form {
    padding: var(--space-8) var(--space-6);
  }

  .form__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .form__foot {
    align-items: center;
    flex-direction: row;
    justify-content: space-between;
  }

  .form__note {
    max-width: 46ch;
  }

  .site-footer__grid {
    grid-template-columns: minmax(0, 2fr) repeat(2, minmax(0, 1fr));
    gap: var(--space-10);
  }

  .site-footer__bottom {
    align-items: center;
    flex-direction: row;
    justify-content: space-between;
  }
}

/* --- lg: 1024px ------------------------------------------------------- */
@media (min-width: 1024px) {

  :root {
    --gutter: var(--space-10);
  }

  .section {
    padding-block: var(--space-24);
  }

  .section--tight {
    padding-block: var(--space-20);
  }

  .nav-toggle {
    display: none;
  }

  .site-nav,
  .site-nav.is-open {
    background-color: transparent;
    border: 0;
    display: block;
    padding: 0;
    position: static;
  }

  .site-nav__list {
    align-items: center;
    flex-direction: row;
    gap: var(--space-1);
    max-width: none;
    padding-inline: 0;
    width: auto;
  }

  .site-nav__link {
    border-bottom: 0;
    border-radius: var(--radius-md);
    font-size: var(--type-sm);
    min-height: 44px;
    padding-inline: var(--space-3);
    width: auto;
  }

  .site-nav__link:hover {
    background-color: var(--surface-raised);
  }

  .site-header__cta {
    display: inline-flex;
  }

  .hero {
    padding-block: var(--space-24) var(--space-24);
  }

  .hero__name {
    font-size: var(--type-6xl);
  }

  .hero__role {
    font-size: var(--type-3xl);
  }

  .hero__inner {
    max-width: 76ch;
  }

  .section__head {
    margin-bottom: var(--space-12);
  }

  .capability__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-8);
  }

  .proof__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .pricing__grid {
    align-items: start;
    gap: var(--space-6);
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .tier--premium {
    grid-column: auto;
  }

  .tier--featured {
    margin-block: calc(var(--space-4) * -1);
    padding-block: var(--space-10);
  }

  .tier {
    padding-inline: var(--space-6);
  }

  .process__list {
    gap: var(--space-12);
  }

  .step {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .step__split {
    gap: var(--space-8);
  }

  .contact__layout {
    gap: var(--space-12);
  }

  .site-footer__grid {
    grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
  }
}

/* --- xl: 1280px ------------------------------------------------------- */
@media (min-width: 1280px) {

  :root {
    --gutter: var(--space-12);
  }

  .work__grid {
    gap: var(--space-10);
  }

  .case__body {
    padding: var(--space-10) var(--space-8);
  }

  .deliver__grid {
    column-gap: var(--space-16);
  }
}

/* --- 2xl: 1536px ------------------------------------------------------ */
@media (min-width: 1536px) {

  .section {
    padding-block: var(--space-32);
  }

  .hero {
    padding-block: var(--space-32) var(--space-24);
  }
}


/* ==========================================================================
   21. REDUCED MOTION
   Disables every transform and animation, per BRIEF section 4.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-delay: 0ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-delay: 0ms !important;
    transition-duration: 1ms !important;
  }

  .js .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .case:hover,
  .btn:active,
  .btn--primary:active,
  .btn--secondary:active,
  .btn--ghost:active {
    transform: none;
  }

  .btn:hover .btn__arrow {
    transform: none;
  }

  /* The FAQ icon's 45deg turn and the nav-toggle's X are state shape cues,
     not decoration: they are what distinguishes open from closed. The
     transition-duration override above already makes both instantaneous,
     which is what prefers-reduced-motion asks for, so the end states stay. */

  .grain {
    display: none;
  }
}


/* ==========================================================================
   22. PRINT
   ========================================================================== */

/* Browsers suppress background painting when printing, so the dark surfaces
   this page is built on simply do not arrive on paper. Every colour the
   screen design sets for a dark ground therefore has to be reset here, or
   the sheet prints near-white text on white. --bg is the near-black ink the
   page normally paints behind everything, which makes it the correct print
   foreground; --on-action-primary means "label sitting on the lime button"
   (MASTER section 6, Button) and is not a page-text role. */

@media print {

  .site-header,
  .site-nav,
  .nav-toggle,
  .grain,
  .hero__backdrop,
  .skip-link,
  .case__art,
  .form {
    display: none !important;
  }

  html,
  body {
    background: none !important;
  }

  body,
  h1, h2, h3, h4,
  p, li, dt, dd, span, strong, code,
  a, button, .btn {
    color: var(--bg) !important;
  }

  .section--surface,
  .capability,
  .site-footer,
  .case,
  .tier,
  .terms-card,
  .proof__item,
  .contact__direct,
  .process__total,
  .work__notice,
  .form__success,
  .step__num,
  .tier__flag,
  .btn {
    background: none !important;
    border-color: var(--border-interactive) !important;
  }

  .proof__check,
  .tier__tick,
  .form__success-icon,
  .faq__icon,
  .btn__arrow,
  .step__num {
    color: var(--bg) !important;
  }

  .brand__mark-glyph {
    fill: var(--bg) !important;
  }

  .brand__mark-frame {
    stroke: var(--border-interactive) !important;
  }

  /* Script collapses all but the first answer; on paper they all belong. */
  .faq__panel[hidden] {
    display: block !important;
  }

  .section {
    padding-block: var(--space-6);
  }
}

/* Cross-link between the build pricing and the SEO & AEO monthly pricing */
.pricing-crosslink{
  margin-top: var(--space-4);
  max-width: var(--container-prose);
  color: var(--text-secondary);
  font-size: var(--type-base);
}
.pricing-crosslink a{
  color: var(--action-primary);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  font-weight: 500;
}
.pricing-crosslink a:hover{ color: var(--action-primary-hover); }

/* Service switcher — Web Design / SEO & AEO, present on both pages */
.svc-switch{
  display:inline-flex; align-items:center; gap:2px; padding:2px;
  margin:var(--space-2) var(--space-4) var(--space-1);
  background:var(--surface-raised);
  border:1px solid var(--border-subtle);
  border-radius:999px; width:max-content;
}
.svc-switch__item{
  display:inline-flex; align-items:center; min-height:44px; padding:0 14px;
  border-radius:999px; font-size:var(--type-sm); font-weight:500; line-height:1;
  color:var(--text-secondary); text-decoration:none; white-space:nowrap;
  transition:color .16s ease, background-color .16s ease;
}
.svc-switch__item:hover{ color:var(--text-primary); }
.svc-switch__item.is-active{ background:var(--action-primary); color:var(--on-action-primary); font-weight:600; }
@media (min-width:1024px){
  .site-nav{ display:flex; align-items:center; gap:var(--space-4); }
  .svc-switch{ margin:0; }
}


/* ==========================================================================
   23. LOAD CHOREOGRAPHY, AMBIENT MOTION, VIEW TRANSITIONS
   Progressive enhancement only. An inline <head> script adds .is-loading,
   which hides the [data-load] hero pieces; assets/js/portfolio.js removes
   the class on its first frame and builds the hero in under a second at
   the hub's 240ms / 40ms-stagger tempo. If the script never runs, the
   failsafe animation shows everything at 2.5s. seo-aeo/styles.css carries
   the same block, so the two pages move as one site.
   ========================================================================== */

@view-transition {
  navigation: auto;
}

/* Shared by both service pages, so they stay put while the content
   crossfades. Scoped to the header: the footer carries a second .brand,
   and a transition name must be unique on the page. */
.site-header .brand {
  view-transition-name: site-brand;
}

.svc-switch {
  view-transition-name: service-switch;
}

/* "Stays put" needs the switcher at the same x on both pages. Under
   space-between it floated with each page's link count and CTA width, so
   on desktop it now sits a fixed gap after the brand while the links take
   the free space; from xl up the brand also reserves a width that fits
   either page's role line. */
@media (min-width: 1024px) {
  .site-nav {
    flex: 1 1 auto;
  }

  .site-nav__list {
    margin-inline: auto 0;
  }
}

@media (min-width: 1280px) {
  .site-header .brand {
    min-width: 14rem;
  }
}

::view-transition-group(*) {
  animation-duration: var(--dur-slow);
  animation-timing-function: var(--ease-out);
}

/* The shared pieces keep their snapshot size, so a small width change (the
   active pill's weight, the brand's role line) never scales their text. */
::view-transition-old(site-brand),
::view-transition-new(site-brand),
::view-transition-old(service-switch),
::view-transition-new(service-switch) {
  height: 100%;
  object-fit: none;
  object-position: left;
  width: auto;
}

.is-loading [data-load] {
  opacity: 0;
  animation: load-failsafe 0s 2.5s forwards;
}

/* A view-transition arrival from the sibling page captures the hero as it
   stands, so nothing is hidden while the transition runs; the script then
   skips the build and the content really crossfades to content. */
.is-loading:active-view-transition [data-load] {
  opacity: 1;
}

@keyframes load-failsafe {
  to { opacity: 1; }
}

/* Sections that scroll-reveal while the hero is still building wait for
   it to land, instead of competing with it. */
.is-load-running .reveal {
  transition-delay: calc(var(--reveal-delay, 0ms) + 720ms);
}

/* The headline is split into words only for the length of its wipe, then
   restored to plain text, unless restoring would change its height. */
.load-word {
  display: inline-block;
}

.hero__rule {
  transform-origin: left center;
}

/* Count-up figures. While counting, data-hold carries the final figure into
   a zero-height ::before, so the box keeps that width in whichever font is
   live; tabular digits keep every step the same width. Nothing beside the
   number moves, even if a webfont swaps in mid-count. */
.count {
  display: inline-block;
  font-variant-numeric: tabular-nums;
  text-align: end;
}

.count[data-hold]::before {
  content: attr(data-hold);
  display: block;
  height: 0;
  overflow: hidden;
  visibility: hidden;
}

.hero__canvas {
  color: var(--action-primary);
  height: 100%;
  inset: 0;
  -webkit-mask-image: linear-gradient(to bottom, var(--bg) 55%, transparent);
  mask-image: linear-gradient(to bottom, var(--bg) 55%, transparent);
  pointer-events: none;
  position: absolute;
  width: 100%;
}

/* Hover physics (fine pointers only). The script writes the cursor's offset
   from centre, -1..1, as --mx / --my and adds .is-leaning. While tracking,
   a short ease-out smooths each update; on leave the spring easing brings
   the element home with a slight overshoot. .lean-ready arrives on first
   hover, so a card keeps the reveal system's transition until it is shown. */
.btn.lean-ready {
  transition: background-color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out),
              transform var(--dur-instant) var(--ease-out),
              translate var(--dur-slow) var(--ease-spring);
}

/* Primary CTAs lean toward the cursor. The script clamps the offset to the
   unit circle, so the pull tops out at 6px in any direction, diagonals
   included. The individual translate property leaves the :active scale
   intact. */
.btn.lean-ready.is-leaning {
  transition-duration: var(--dur-base), var(--dur-base), var(--dur-base), var(--dur-instant), var(--dur-fast);
  transition-timing-function: var(--ease-out);
  translate: calc(var(--mx, 0) * 6px) calc(var(--my, 0) * 6px);
}

/* Case cards tilt up to 4deg toward the cursor, with the spec's 2px lift. */
.js .case.lean-ready {
  transition: border-color var(--dur-base) var(--ease-out),
              background-color var(--dur-base) var(--ease-out),
              transform var(--dur-slow) var(--ease-spring);
}

/* Once a card has leaned, its resting transform lists the same functions
   as the lean, so the spring-back interpolates each one in turn instead of
   decomposing a matrix and overshooting the perspective term. */
.js .case.lean-ready.is-visible {
  transform: perspective(1000px) translateY(0) rotateX(0deg) rotateY(0deg);
}

.js .case.lean-ready.is-leaning {
  transform: perspective(1000px) translateY(-2px)
             rotateX(calc(var(--my, 0) * -4deg)) rotateY(calc(var(--mx, 0) * 4deg));
  transition-duration: var(--dur-base), var(--dur-base), var(--dur-fast);
  transition-timing-function: var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {

  @view-transition {
    navigation: none;
  }

  .hero__canvas {
    display: none;
  }

  .btn.lean-ready.is-leaning {
    translate: none;
  }

  .js .case.lean-ready.is-visible,
  .js .case.lean-ready.is-leaning {
    transform: none;
  }
}
