/* ============================================================================
   Gobo Studios — site.css
   Marketing stylesheet for gobostudios.com. "Paper & Beam".

   This file is ONLY for the marketing shell (views/partials/site-head.ejs +
   site-foot.ejs and views/marketing/*). The billing app keeps /css/style.css.
   Do not load both on the same page.

   ---------------------------------------------------------------------------
   HOW TO USE THIS FILE (read this before writing a page)
   ---------------------------------------------------------------------------
   Every section on a marketing page is a BAND. A band sets the ground, and the
   ground is expressed as a small set of neutral ALIASES. Components read only
   the aliases, so one component rule is correct on both grounds.

     <section class="band">              <!-- PAPER: the default ground -->
       <div class="container"> … </div>
     </section>

     <section class="band band--ink">    <!-- INK: full-bleed dark band -->
       <div class="beam-wash beam-wash--dual"></div>
       <div class="container"> … </div>
     </section>

   The aliases (never hardcode a hex in a component, always use these):
     --surface         the band's own ground
     --surface-raised  cards, panels, popovers, hairline-grid cells
     --surface-inset   inputs, wells, code, anything recessed
     --ink             body text
     --ink-muted       secondary text, captions, meta
     --hairline        borders, dividers, grid gaps
     --on-accent       text that sits ON a sage fill (never white)
     --link            link colour that passes on THIS ground
     --link-hover      link hover
     --focus-edge      the contrast-carrying edge of the focus ring

   Band rhythm (enforced by the design system, not by CSS — mind it in markup):
     hero is always ink; the closing CTA is always ink; never more than two
     consecutive sections on the same ground; every page carries at least one
     ink band in its middle third.

   Beam colours (magenta / cyan / amber / violet) are LIGHT, not paint. They
   appear only through .beam-wash — gradients, glow, blur, screen blend — and
   only inside .band--ink. There is no light source on paper, so .beam-wash
   renders nothing outside an ink band, on purpose.

   Sage (#bbd68f) is a fill, never a text colour on a ground, and never carries
   white type: white on sage is ~1.6:1. Sage fills take --on-accent.
   ========================================================================= */


/* ---------------------------------------------------------------------------
   1. Fonts — self-hosted. Never hotlink Google Fonts (see the Privacy Policy).
   Lato ships 100/300/400/700/900 only. There is no 500, 600 or 800.
   ------------------------------------------------------------------------ */

@font-face {
  font-family: 'Lato';
  src: url('/fonts/lato-700-latin.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Lato';
  src: url('/fonts/lato-900-latin.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Open Sans';
  src: url('/fonts/open-sans-400-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Open Sans';
  src: url('/fonts/open-sans-600-latin.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}


/* ---------------------------------------------------------------------------
   2. Tokens — straight from DESIGN.md frontmatter. Do not add values here
   without adding them to DESIGN.md first.
   ------------------------------------------------------------------------ */

:root {
  /* Ink ground palette */
  --bg:             #0a0a1a;
  --bg-card:        #1a1a2e;
  --bg-input:       #11111e;
  --border:         #2a2a3e;
  --text:           #e0e0e0;
  --muted:          #8a8aa0;
  --ink-on-light:   #0a0a1a;

  /* Paper ground palette */
  --light-bg:       #f7f6f2;
  --light-bg-card:  #ffffff;
  --light-bg-input: #ffffff;
  --light-border:   #e2e0d8;
  --light-text:     #1a1a17;
  --light-muted:    #5f5f57;

  /* Brand — from the logo. These do not change between grounds. */
  --primary:        #426323;
  --primary-hover:  #547d2d;
  --secondary:      #bbd68f;
  --success:        #bbd68f;
  --warning:        #fdcb6e;
  --danger:         #e74c3c;
  --focus-ring:     rgba(187, 214, 143, 0.4);

  /* rgb triplets, for alpha compositing in alerts and washes */
  --primary-rgb:    66, 99, 35;
  --secondary-rgb:  187, 214, 143;
  --warning-rgb:    253, 203, 110;
  --danger-rgb:     231, 76, 60;

  /* Beam palette — LIGHT ONLY. Never a fill, a button, a border, or text.
     Ink ground only, and only through .beam-wash. */
  --beam-magenta:     #e8318a;
  --beam-cyan:        #2ec5d8;
  --beam-amber:       #f5a524;
  --beam-violet:      #6d4aff;
  --beam-magenta-rgb: 232, 49, 138;
  --beam-cyan-rgb:    46, 197, 216;
  --beam-amber-rgb:   245, 165, 36;
  --beam-violet-rgb:  109, 74, 255;

  /* Type families */
  --font-display: 'Lato', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-body:    'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  /* Type scale — clamp() across a wide range. --fs-display is a hero-only
     step above the 3.2rem h1 token; every other step tops out at its
     DESIGN.md size. */
  --fs-display: clamp(2.4rem,  1.15rem + 5.0vw, 4rem);
  --fs-h1:      clamp(2rem,    1.10rem + 3.6vw, 3.2rem);
  --fs-h2:      clamp(1.6rem,  1.05rem + 2.2vw, 2.2rem);
  --fs-h3:      clamp(1.25rem, 1.10rem + 0.6vw, 1.5rem);
  --fs-h4:      clamp(1.05rem, 1.00rem + 0.2vw, 1.15rem);
  --fs-lead:    clamp(1.05rem, 0.98rem + 0.4vw, 1.25rem);
  --fs-body:    1rem;
  --fs-small:   0.85rem;
  --fs-eyebrow: 0.7rem;
  --fs-stat:    clamp(2.2rem,  1.30rem + 3.2vw, 3.2rem);

  /* Letter-spacing inversion: display type tightens, small caps stretch. */
  --ls-display:  -0.02em;
  --ls-h1:       -0.02em;
  --ls-h2:       -0.015em;
  --ls-h3:       -0.01em;
  --ls-h4:        normal;
  --ls-button:    0.01em;
  --ls-badge:     0.05em;   /* component badge, per DESIGN.md */
  --ls-eyebrow:   0.26em;   /* section eyebrow — the stretched end of the scale */
  --ls-eyebrow-x: 0.36em;   /* extra-wide, for a lone label over a hero */

  --lh-display: 1.05;
  --lh-heading: 1.15;
  --lh-body:    1.6;

  /* Body copy measure */
  --measure: 70ch;

  /* Radius */
  --radius-xs:   4px;
  --radius-sm:   6px;
  --radius-md:  10px;
  --radius-lg:  16px;
  --radius-full: 999px;
  --radius: var(--radius-md);   /* legacy alias */

  /* Spacing — 4px base. Do not invent intermediate values. */
  --space-xs:   4px;
  --space-sm:   8px;
  --space-md:  16px;
  --space-lg:  24px;
  --space-xl:  32px;
  --space-2xl: 48px;
  --space-3xl: 64px;

  /* Band rhythm. Lands on 120px at a 1200px viewport and caps at 152px. */
  --band-pad:       clamp(80px, 8vw + 24px, 152px);
  --band-pad-tight: clamp(56px, 5vw + 20px, 96px);

  /* Layout */
  --container:        1100px;
  --container-narrow: 760px;
  --gutter:           clamp(16px, 5vw, 32px);
  --header-h:         72px;

  /* Motion */
  --dur-hover:  150ms;
  --dur-panel:  250ms;
  --dur-reveal: 400ms;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}


/* ---------------------------------------------------------------------------
   3. The two grounds.
   :root carries the PAPER aliases so anything outside a band is still correct.
   ------------------------------------------------------------------------ */

:root,
.band,
.band--paper {
  --surface:        var(--light-bg);
  --surface-raised: var(--light-bg-card);
  --surface-inset:  var(--light-bg-input);
  --ink:            var(--light-text);
  --ink-muted:      var(--light-muted);
  --hairline:       var(--light-border);
  --on-accent:      var(--light-text);   /* dark type on a sage fill */
  --link:           var(--primary);      /* 6.4:1 on paper */
  --link-hover:     var(--primary-hover);
  --focus-edge:     var(--primary);
}

.band--ink,
.site-header,
.site-footer {
  --surface:        var(--bg);
  --surface-raised: var(--bg-card);
  --surface-inset:  var(--bg-input);
  --ink:            var(--text);
  --ink-muted:      var(--muted);
  --hairline:       var(--border);
  --on-accent:      var(--ink-on-light);
  --link:           var(--secondary);    /* 11.4:1 on ink */
  --link-hover:     var(--secondary);    /* hover reads as the underline */
  --focus-edge:     var(--secondary);
}


/* ---------------------------------------------------------------------------
   4. Base
   ------------------------------------------------------------------------ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--space-md));
}

body {
  margin: 0;
  background: var(--light-bg);
  color: var(--light-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

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

a {
  color: var(--link);
  text-decoration: none;
  transition: color var(--dur-hover) var(--ease);
}
a:hover { color: var(--link-hover); text-decoration: underline; text-underline-offset: 0.18em; }

hr {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: var(--space-2xl) 0;
}

::selection { background: var(--secondary); color: var(--ink-on-light); }


/* ---------------------------------------------------------------------------
   5. Typography
   ------------------------------------------------------------------------ */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  color: var(--ink);
  margin: 0 0 var(--space-md);
  text-wrap: balance;
}

h1 { font-weight: 900; font-size: var(--fs-h1); line-height: var(--lh-display); letter-spacing: var(--ls-h1); }
h2 { font-weight: 900; font-size: var(--fs-h2); line-height: var(--lh-heading); letter-spacing: var(--ls-h2); }
h3 { font-weight: 700; font-size: var(--fs-h3); line-height: 1.25; letter-spacing: var(--ls-h3); }
h4, h5, h6 { font-weight: 700; font-size: var(--fs-h4); line-height: 1.3; letter-spacing: var(--ls-h4); }

/* Hero-scale display. Use on the hero h1 only. */
.display {
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  font-weight: 900;
}

p { margin: 0 0 var(--space-md); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

strong, b { font-weight: 600; }
em { font-style: italic; }

small, .small { font-size: var(--fs-small); line-height: 1.5; }

.lead {
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: 60ch;
}

.muted { color: var(--ink-muted); }

/* Eyebrow — the stretched end of the letter-spacing inversion. */
.eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--ls-eyebrow);
  color: var(--ink-muted);
  margin: 0 0 var(--space-md);
}
.eyebrow--wide   { letter-spacing: var(--ls-eyebrow-x); }
.eyebrow--accent { color: var(--secondary); }        /* ink bands only */
.band:not(.band--ink) .eyebrow--accent { color: var(--primary); }

/* Body copy measure. Wrap running prose in .prose. */
.prose { max-width: var(--measure); }
.prose h2 { margin-top: var(--space-2xl); }
.prose h3 { margin-top: var(--space-xl); }
.prose > :first-child { margin-top: 0; }
.prose ul, .prose ol { padding-left: 1.3em; margin: 0 0 var(--space-md); }
.prose li { margin-bottom: var(--space-sm); }
.prose blockquote {
  margin: var(--space-lg) 0;
  padding-left: var(--space-lg);
  border-left: 3px solid var(--secondary);
  color: var(--ink-muted);
}

/* Unstyled list */
.list-bare { list-style: none; padding: 0; margin: 0; }

/* Tick list — sage marker, text stays --ink */
.list-ticks { list-style: none; padding: 0; margin: 0; }
.list-ticks li {
  position: relative;
  padding-left: var(--space-xl);
  margin-bottom: var(--space-sm);
}
.list-ticks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 12px;
  height: 7px;
  border-left: 2px solid var(--secondary);
  border-bottom: 2px solid var(--secondary);
  transform: rotate(-45deg);
}
.band:not(.band--ink) .list-ticks li::before { border-color: var(--primary); }


/* ---------------------------------------------------------------------------
   6. Layout — bands, container, grids
   ------------------------------------------------------------------------ */

.band {
  position: relative;
  background: var(--surface);
  color: var(--ink);
  padding-block: var(--band-pad);
}
.band--ink {
  isolation: isolate;          /* contains the screen blend of .beam-wash */
  overflow: hidden;            /* keeps blurred washes from bleeding out */
}
.band--tight  { padding-block: var(--band-pad-tight); }
.band--flush-top    { padding-top: 0; }
.band--flush-bottom { padding-bottom: 0; }

/* Two paper bands in a row need a seam. (Never allow a third.) */
.band:not(.band--ink) + .band:not(.band--ink) { border-top: 1px solid var(--hairline); }

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
  position: relative;
  z-index: 1;
}
.container--narrow { max-width: var(--container-narrow); }

/* Vertical rhythm helpers */
.stack > * + * { margin-top: var(--space-md); }
.stack-lg > * + * { margin-top: var(--space-lg); }
.stack-xl > * + * { margin-top: var(--space-xl); }
.stack-2xl > * + * { margin-top: var(--space-2xl); }

/* Section head */
.section-head { max-width: var(--measure); margin-bottom: var(--space-2xl); }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head p:last-child { margin-bottom: 0; }

/* Plain grids */
.grid { display: grid; gap: var(--space-lg); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
.grid--auto { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

/* Split — text beside media */
.split {
  display: grid;
  gap: var(--space-2xl);
  align-items: center;
  grid-template-columns: 1fr 1fr;
}
.split--wide-left  { grid-template-columns: 1.25fr 1fr; }
.split--wide-right { grid-template-columns: 1fr 1.25fr; }
.split__media img,
.split__media video { border-radius: var(--radius-lg); width: 100%; }

/* HAIRLINE GRID — the house pattern for feature/spec blocks.
   One 1px hairline background showing through a 1px gap. No card borders. */
.grid-hair {
  display: grid;
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.grid-hair > * {
  background: var(--surface-raised);
  color: var(--ink);
  padding: var(--space-lg);
  margin: 0;
}
.grid-hair--2 { grid-template-columns: repeat(2, 1fr); }
.grid-hair--3 { grid-template-columns: repeat(3, 1fr); }
.grid-hair--4 { grid-template-columns: repeat(4, 1fr); }
.grid-hair--auto { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.grid-hair h3, .grid-hair h4 { margin-bottom: var(--space-sm); }
.grid-hair p:last-child { margin-bottom: 0; }

/* A hairline grid that sits directly on the ground (no raised cells) */
.grid-hair--flat > * { background: var(--surface); }


/* ---------------------------------------------------------------------------
   7. Beam wash — light, not paint. Ink bands only.
   Usage:  <section class="band band--ink">
             <div class="beam-wash beam-wash--dual"></div>
             …
   Renders nothing on paper by design.
   ------------------------------------------------------------------------ */

.beam-wash { display: none; }

.band--ink > .beam-wash,
.hero > .beam-wash {
  display: block;
  position: absolute;
  inset: -25% -12%;
  z-index: -1;
  pointer-events: none;
  mix-blend-mode: screen;
  filter: blur(70px) saturate(115%);
  opacity: 0.75;
  /* default: a cool wash from the top-left, magenta answering from the right */
  background:
    radial-gradient(48% 60% at 14% 4%,  rgba(var(--beam-cyan-rgb), 0.40), transparent 62%),
    radial-gradient(46% 62% at 86% 12%, rgba(var(--beam-magenta-rgb), 0.34), transparent 64%),
    radial-gradient(70% 50% at 50% 108%, rgba(var(--beam-violet-rgb), 0.22), transparent 70%);
}

/* Two beams crossing — the workhorse for a lighting section. */
.band--ink > .beam-wash--dual {
  background:
    conic-gradient(from 196deg at 22% -14%,
      transparent 0 6%, rgba(var(--beam-magenta-rgb), 0.34) 10%, transparent 17%),
    conic-gradient(from 142deg at 78% -14%,
      transparent 0 6%, rgba(var(--beam-cyan-rgb), 0.32) 10%, transparent 17%),
    radial-gradient(40% 45% at 22% 0%, rgba(var(--beam-magenta-rgb), 0.30), transparent 66%),
    radial-gradient(40% 45% at 78% 0%, rgba(var(--beam-cyan-rgb), 0.28), transparent 66%);
  filter: blur(58px) saturate(120%);
}

/* A fan of beams from a single point above the band. */
.band--ink > .beam-wash--fan {
  background:
    conic-gradient(from 168deg at 50% -18%,
      transparent 0 4%,
      rgba(var(--beam-violet-rgb), 0.26) 7%,
      transparent 10%,
      rgba(var(--beam-cyan-rgb), 0.24) 15%,
      transparent 19%,
      rgba(var(--beam-magenta-rgb), 0.26) 25%,
      transparent 29%,
      rgba(var(--beam-amber-rgb), 0.22) 35%,
      transparent 40%),
    radial-gradient(55% 40% at 50% 0%, rgba(var(--beam-violet-rgb), 0.24), transparent 70%);
  filter: blur(46px) saturate(125%);
  opacity: 0.8;
}

/* Warm — house lights up, amber and magenta. */
.band--ink > .beam-wash--warm {
  background:
    radial-gradient(52% 62% at 18% 6%,  rgba(var(--beam-amber-rgb), 0.34), transparent 64%),
    radial-gradient(48% 58% at 84% 18%, rgba(var(--beam-magenta-rgb), 0.30), transparent 66%),
    radial-gradient(80% 44% at 50% 104%, rgba(var(--beam-amber-rgb), 0.16), transparent 72%);
}

/* Cool — the software bands. Quieter. */
.band--ink > .beam-wash--cool {
  background:
    radial-gradient(50% 60% at 82% 2%,  rgba(var(--beam-cyan-rgb), 0.32), transparent 64%),
    radial-gradient(46% 56% at 12% 24%, rgba(var(--beam-violet-rgb), 0.30), transparent 66%);
  opacity: 0.62;
}

/* Edge — a single low glow along the bottom, for a closing CTA. */
.band--ink > .beam-wash--edge {
  inset: 40% -12% -30%;
  background:
    radial-gradient(60% 100% at 30% 100%, rgba(var(--beam-magenta-rgb), 0.28), transparent 68%),
    radial-gradient(60% 100% at 74% 100%, rgba(var(--beam-cyan-rgb), 0.24), transparent 68%);
  filter: blur(80px);
}

.beam-wash--quiet { opacity: 0.45; }

/* The on-brand ink gradient, for a band with no wash element. */
.band--ink.band--gradient {
  background-image: linear-gradient(135deg, #0a0a1a 0%, #1f3315 50%, #0a0a1a 100%);
}

/* Photo under a scrim. Set --band-image on the element. */
.band--photo { background-image: var(--band-image); background-size: cover; background-position: center; }
.band--photo::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10,10,26,0.72) 0%, rgba(10,10,26,0.86) 100%);
  z-index: 0;
}
.band--photo > .container { z-index: 1; }


/* ---------------------------------------------------------------------------
   8. Header + nav (always ink chrome)
   ------------------------------------------------------------------------ */

.skip-link {
  position: absolute;
  left: var(--space-md);
  top: -100px;
  z-index: 100;
  background: var(--primary);
  color: #fff;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-weight: 700;
  transition: top var(--dur-panel) var(--ease);
}
.skip-link:focus { top: var(--space-md); text-decoration: none; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(10, 10, 26, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--hairline);
  color: var(--ink);
}

.site-header__inner {
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-sm) var(--gutter);
  min-height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
}

.brand { display: inline-flex; align-items: center; flex: 0 0 auto; }
.brand img { height: 40px; width: auto; }
.brand:hover { text-decoration: none; }

.nav {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-sm);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 400;
  white-space: nowrap;
  transition: color var(--dur-hover) var(--ease), background-color var(--dur-hover) var(--ease);
}
.nav__link:hover { color: var(--secondary); background: rgba(255,255,255,0.04); text-decoration: none; }
.nav__link[aria-current="page"],
.nav__link.is-active { color: var(--secondary); font-weight: 400; }
.nav__link[aria-current="page"]::after,
.nav__link.is-active::after {
  content: '';
  position: absolute;
  inset: auto var(--space-sm) 6px;
  height: 2px;
  background: var(--secondary);
  border-radius: var(--radius-full);
}
.nav__item { position: relative; display: flex; }

/* Dropdown — <details>/<summary>, works with JS off. */
.nav-dd { position: relative; }
.nav-dd > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 44px;
  padding: 0 var(--space-sm);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-size: 0.95rem;
  white-space: nowrap;
  transition: color var(--dur-hover) var(--ease), background-color var(--dur-hover) var(--ease);
}
.nav-dd > summary::-webkit-details-marker { display: none; }
.nav-dd > summary::after {
  content: '';
  width: 6px; height: 6px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--dur-panel) var(--ease);
  opacity: 0.7;
}
.nav-dd[open] > summary::after { transform: translateY(1px) rotate(225deg); }
.nav-dd > summary:hover { color: var(--secondary); background: rgba(255,255,255,0.04); }
.nav-dd > summary.is-active { color: var(--secondary); }

.nav-dd__panel {
  position: absolute;
  top: calc(100% + var(--space-sm));
  left: 0;
  min-width: 232px;
  background: var(--surface-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--space-sm);
  list-style: none;
  margin: 0;
  z-index: 60;
}
.nav-dd__panel a {
  display: block;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.35;
}
.nav-dd__panel a:hover { background: rgba(255,255,255,0.06); color: var(--secondary); text-decoration: none; }
.nav-dd__panel .nav-dd__note {
  display: block;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}

.nav-actions { display: flex; align-items: center; gap: var(--space-sm); flex: 0 0 auto; }

/* Mobile toggle */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  color: var(--ink);
  cursor: pointer;
}
.nav-toggle__bars, .nav-toggle__bars::before, .nav-toggle__bars::after {
  display: block;
  width: 18px;
  height: 2px;
  background: currentColor;
  border-radius: var(--radius-full);
  transition: transform var(--dur-panel) var(--ease), opacity var(--dur-panel) var(--ease);
}
.nav-toggle__bars { position: relative; }
.nav-toggle__bars::before, .nav-toggle__bars::after { content: ''; position: absolute; left: 0; }
.nav-toggle__bars::before { top: -6px; }
.nav-toggle__bars::after  { top: 6px; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after  { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; }
  .site-nav {
    display: none;
    position: absolute;
    left: 0; right: 0;
    top: 100%;
    background: var(--bg);
    border-bottom: 1px solid var(--hairline);
    padding: var(--space-md) var(--gutter) var(--space-lg);
    max-height: calc(100dvh - var(--header-h));
    overflow-y: auto;
  }
  .site-nav.is-open { display: block; }
  .nav { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__item { display: block; }
  .nav__link, .nav-dd > summary {
    width: 100%;
    padding: var(--space-md) var(--space-sm);
    border-bottom: 1px solid var(--hairline);
    border-radius: 0;
  }
  .nav__link[aria-current="page"]::after, .nav__link.is-active::after { display: none; }
  .nav-dd > summary { justify-content: space-between; }
  .nav-dd__panel {
    position: static;
    min-width: 0;
    border: 0;
    border-bottom: 1px solid var(--hairline);
    border-radius: 0;
    box-shadow: none;
    background: var(--surface-inset);
    padding: var(--space-sm) var(--space-sm) var(--space-sm) var(--space-lg);
  }
  .nav-actions--desktop { display: none; }
  .site-nav .nav-actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    margin-top: var(--space-lg);
  }
  .site-nav .nav-actions .btn { width: 100%; }
}
@media (min-width: 901px) {
  .site-nav { display: flex !important; align-items: center; gap: var(--space-lg); }
  .site-nav .nav-actions--mobile { display: none; }
}


/* ---------------------------------------------------------------------------
   9. Buttons
   ------------------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  min-height: 44px;
  padding: var(--space-sm) var(--space-lg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--ls-button);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  background: transparent;
  color: var(--ink);
  transition: background-color var(--dur-hover) var(--ease),
              border-color var(--dur-hover) var(--ease),
              color var(--dur-hover) var(--ease),
              transform var(--dur-hover) var(--ease);
}
.btn:hover { text-decoration: none; }

.btn--primary {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;                      /* 6.9:1 on olive */
}
.btn--primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: #fff; }

.btn--secondary {
  background: transparent;
  border-color: var(--hairline);
  color: var(--ink);
}
.btn--secondary:hover { border-color: var(--primary); color: var(--ink); }
.band--ink .btn--secondary:hover,
.site-header .btn--secondary:hover,
.site-footer .btn--secondary:hover { border-color: var(--secondary); color: var(--secondary); }

/* Sage fill. Dark type only — never white. */
.btn--accent {
  background: var(--secondary);
  border-color: var(--secondary);
  color: var(--on-accent);
}
.btn--accent:hover { filter: brightness(1.06); color: var(--on-accent); }

.btn--danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn--danger:hover { filter: brightness(1.08); }

.btn--ghost { background: transparent; border-color: transparent; color: var(--link); padding-inline: var(--space-sm); }
.btn--ghost:hover { color: var(--link-hover); text-decoration: underline; }

.btn--lg { min-height: 52px; padding: var(--space-md) var(--space-xl); font-size: 1.05rem; }
.btn--sm { min-height: 36px; padding: var(--space-xs) var(--space-md); font-size: var(--fs-small); }
.btn--block { display: flex; width: 100%; }

.btn[disabled], .btn.is-disabled, .btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transition: none;
  pointer-events: none;
}

/* Header CTA — visually distinct from the nav links. */
.btn--cta {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
  box-shadow: 0 0 0 1px rgba(var(--secondary-rgb), 0.35);
}
.btn--cta:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: #fff; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-md); align-items: center; }
.btn-row--center { justify-content: center; }


/* ---------------------------------------------------------------------------
   10. Cards
   ------------------------------------------------------------------------ */

.card {
  background: var(--surface-raised);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--space-lg);
}
.card > :last-child { margin-bottom: 0; }
.card h3, .card h4 { margin-bottom: var(--space-sm); }
.card__meta { font-size: var(--fs-small); color: var(--ink-muted); }

.card--link { display: block; transition: transform var(--dur-hover) var(--ease), border-color var(--dur-hover) var(--ease); }
.card--link:hover { transform: translateY(-2px); border-color: var(--primary); text-decoration: none; }
.band--ink .card--link:hover { border-color: var(--secondary); }

.card--feature { border-color: rgba(var(--secondary-rgb), 0.55); }
.card--flat { background: var(--surface); }
.card--pad-lg { padding: var(--space-xl); }

/* Product card — used on /software and in cross-links */
.product-card { display: flex; flex-direction: column; gap: var(--space-sm); height: 100%; }
.product-card__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm); }
.product-card__foot { margin-top: auto; padding-top: var(--space-md); }


/* ---------------------------------------------------------------------------
   11. Badges + pills
   ------------------------------------------------------------------------ */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-xs);
  background: var(--secondary);
  color: var(--on-accent);          /* never white on sage */
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--ls-badge);
  white-space: nowrap;
}
.badge--outline { background: transparent; border: 1px solid var(--hairline); color: var(--ink-muted); }
.badge--warning { background: var(--warning); color: var(--ink-on-light); }
.badge--danger  { background: var(--danger);  color: #fff; }
.badge--soon    { background: transparent; border: 1px dashed var(--hairline); color: var(--ink-muted); }

.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-xs) var(--space-md);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-full);
  background: var(--surface-raised);
  color: var(--ink-muted);
  font-size: var(--fs-small);
  white-space: nowrap;
}
.pill-row { display: flex; flex-wrap: wrap; gap: var(--space-sm); }


/* ---------------------------------------------------------------------------
   12. Alerts — fill 12%, border 40%, text at --ink. Colour is never the only
   signal: each alert carries a label.
   ------------------------------------------------------------------------ */

.alert {
  display: flex;
  gap: var(--space-md);
  padding: var(--space-md);
  border-radius: var(--radius-sm);
  border: 1px solid var(--hairline);
  background: var(--surface-raised);
  color: var(--ink);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
.alert > :last-child { margin-bottom: 0; }
.alert__label {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-badge);
  line-height: 1.6;
  color: var(--ink-muted);
}
.alert--success { background: rgba(var(--secondary-rgb), 0.12); border-color: rgba(var(--secondary-rgb), 0.4); }
.alert--warning { background: rgba(var(--warning-rgb), 0.12);   border-color: rgba(var(--warning-rgb), 0.4); }
.alert--error   { background: rgba(var(--danger-rgb), 0.12);    border-color: rgba(var(--danger-rgb), 0.4); }
.alert--info    { background: rgba(var(--primary-rgb), 0.10);   border-color: rgba(var(--primary-rgb), 0.35); }

.flash { padding-block: var(--space-md); background: var(--surface); }
.flash .alert + .alert { margin-top: var(--space-sm); }


/* ---------------------------------------------------------------------------
   13. Forms
   ------------------------------------------------------------------------ */

.form { max-width: var(--container-narrow); }
.form-grid { display: grid; gap: var(--space-md); grid-template-columns: repeat(2, 1fr); }
.form-grid .field--full { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: var(--space-sm); }
.field + .field { margin-top: var(--space-md); }

.field > label,
.label {
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.01em;
}
.field__req { color: var(--danger); font-weight: 600; }
.field__hint { font-size: var(--fs-small); color: var(--ink-muted); }

.input, .select, .textarea,
input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
input[type="date"], input[type="time"], input[type="number"], input[type="password"],
input[type="search"], select, textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-inset);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  transition: border-color var(--dur-hover) var(--ease), background-color var(--dur-hover) var(--ease);
}
textarea { min-height: 132px; resize: vertical; }
select {
  appearance: none;
  padding-right: var(--space-xl);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 12px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
::placeholder { color: var(--ink-muted); opacity: 1; }

input:hover, select:hover, textarea:hover { border-color: var(--ink-muted); }

/* Error state — border + message + aria-invalid, never colour alone */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"],
.field.has-error input, .field.has-error select, .field.has-error textarea {
  border-color: var(--danger);
  background: rgba(var(--danger-rgb), 0.06);
}
.field__error {
  display: flex;
  gap: var(--space-xs);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--danger);
}
.field__error::before { content: '!'; font-weight: 700; }

/* Checkbox / radio rows */
.check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  min-height: 44px;
  padding: var(--space-sm) 0;
  font-size: var(--fs-body);
  cursor: pointer;
}
.check input[type="checkbox"], .check input[type="radio"] {
  width: 20px; height: 20px;
  min-height: 0;
  margin: 2px 0 0;
  flex: 0 0 auto;
  accent-color: var(--primary);
  cursor: pointer;
}
.check-grid { display: grid; gap: 0 var(--space-lg); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }

/* Honeypot — must never be visible or focusable in a normal flow */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  overflow: hidden;
}

fieldset { border: 0; padding: 0; margin: 0 0 var(--space-xl); }
legend {
  padding: 0;
  margin-bottom: var(--space-md);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h4);
  color: var(--ink);
}

/* Form panel — a form on a card */
.form-card {
  background: var(--surface-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--space-xl);
}


/* ---------------------------------------------------------------------------
   14. Pricing tiers
   ------------------------------------------------------------------------ */

.tiers {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  align-items: start;
}

.tier {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--space-lg);
  height: 100%;
}
.tier__name { font-size: var(--fs-h4); margin-bottom: var(--space-xs); }
.tier__blurb { font-size: var(--fs-small); color: var(--ink-muted); margin-bottom: var(--space-md); }
.tier__price {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.9rem, 1.3rem + 1.8vw, 2.4rem);
  line-height: 1;
  letter-spacing: var(--ls-h2);
  color: var(--ink);
  margin: 0 0 var(--space-xs);
}
.tier__period { font-family: var(--font-body); font-size: var(--fs-small); font-weight: 400; color: var(--ink-muted); letter-spacing: normal; }
.tier__note { font-size: var(--fs-small); color: var(--ink-muted); margin-bottom: var(--space-md); }

.tier__features { list-style: none; padding: 0; margin: var(--space-md) 0; }
.tier__features li {
  padding: var(--space-sm) 0;
  border-bottom: 1px solid var(--hairline);
  font-size: var(--fs-small);
  line-height: 1.5;
}
.tier__features li:last-child { border-bottom: 0; }

.tier__cta { margin-top: auto; padding-top: var(--space-md); }
.tier__cta .btn { width: 100%; }

/* Featured tier — sage border and a sage ribbon with dark type. */
.tier--featured { border-color: var(--secondary); border-width: 2px; padding-top: var(--space-xl); }
.tier__ribbon {
  position: absolute;
  top: calc(-1 * var(--space-md));
  left: var(--space-lg);
  background: var(--secondary);
  color: var(--on-accent);
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-badge);
  line-height: 1;
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-xs);
}

/* Monthly / yearly switch */
.billing-toggle {
  display: inline-flex;
  gap: var(--space-xs);
  padding: var(--space-xs);
  background: var(--surface-inset);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-full);
  margin-bottom: var(--space-xl);
}
.billing-toggle button {
  min-height: 36px;
  padding: var(--space-xs) var(--space-md);
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--ink-muted);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  cursor: pointer;
  transition: background-color var(--dur-hover) var(--ease), color var(--dur-hover) var(--ease);
}
.billing-toggle button[aria-pressed="true"] { background: var(--primary); color: #fff; }


/* ---------------------------------------------------------------------------
   15. Tables (specs, procurement, comparison). Scroll inside their own box.
   ------------------------------------------------------------------------ */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  -webkit-overflow-scrolling: touch;
}
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); }
.table th, .table td {
  padding: var(--space-md);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--hairline);
}
.table thead th {
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-badge);
  color: var(--ink-muted);
  white-space: nowrap;
  background: var(--surface);
}
.table tbody tr:last-child td { border-bottom: 0; }
.table th[scope="row"] { font-weight: 600; color: var(--ink); }
.table td.num { text-align: right; font-variant-numeric: tabular-nums; }


/* ---------------------------------------------------------------------------
   16. Process / step list
   ------------------------------------------------------------------------ */

.steps { list-style: none; counter-reset: step; padding: 0; margin: 0; display: grid; gap: var(--space-xl); }
.steps--row { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.steps > li {
  counter-increment: step;
  position: relative;
  padding-left: var(--space-3xl);
}
.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-full);
  border: 1px solid var(--hairline);
  background: var(--surface-raised);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 0.95rem;
  line-height: 1;
}
.steps > li h3, .steps > li h4 { margin-bottom: var(--space-xs); }
.steps > li p:last-child { margin-bottom: 0; }
.steps > li p { color: var(--ink-muted); }

/* Vertical rail connecting the steps (stacked layout only) */
.steps:not(.steps--row) > li::after {
  content: '';
  position: absolute;
  left: 20px;
  top: 44px;
  bottom: calc(-1 * var(--space-xl));
  width: 1px;
  background: var(--hairline);
}
.steps:not(.steps--row) > li:last-child::after { display: none; }

.steps--row > li { padding-left: 0; padding-top: 56px; }
.steps--row > li::before { top: 0; left: 0; }
.steps--row > li::after { display: none; }


/* ---------------------------------------------------------------------------
   17. Stat strip — hairline grid, Lato 900 numerals, eyebrow labels.
   Only ever put TRUE numbers here.
   ------------------------------------------------------------------------ */

.stat-strip {
  display: grid;
  gap: 1px;
  background: var(--hairline);
  border-block: 1px solid var(--hairline);
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.stat {
  background: var(--surface);
  padding: var(--space-xl) var(--space-lg);
  text-align: center;
}
.stat__num {
  display: block;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--fs-stat);
  line-height: 1;
  letter-spacing: var(--ls-display);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.stat__label {
  display: block;
  margin-top: var(--space-sm);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-eyebrow);
  color: var(--ink-muted);
}
.stat__note { display: block; margin-top: var(--space-xs); font-size: var(--fs-small); color: var(--ink-muted); }

/* Boxed variant, inside a container */
.stat-strip--boxed {
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.stat-strip--boxed .stat { background: var(--surface-raised); }


/* ---------------------------------------------------------------------------
   18. Hero
   ------------------------------------------------------------------------ */

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--bg);
  background-image: linear-gradient(135deg, #0a0a1a 0%, #1f3315 50%, #0a0a1a 100%);
  color: var(--ink);
  display: flex;
  align-items: center;
  min-height: clamp(480px, 74vh, 720px);
  padding-block: var(--band-pad-tight);
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
}
.hero__media video,
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(10,10,26,0.62) 0%, rgba(10,10,26,0.50) 45%, rgba(10,10,26,0.88) 100%),
    linear-gradient(90deg, rgba(10,10,26,0.72) 0%, rgba(10,10,26,0.28) 60%, rgba(10,10,26,0.18) 100%);
}
.hero__inner { max-width: 46rem; }
.hero h1 { margin-bottom: var(--space-lg); }
.hero .lead { color: var(--text); max-width: 44ch; }
.hero .btn-row { margin-top: var(--space-xl); }

/* Reduced-motion play control — hidden unless the shell script reveals it */
.hero__play { display: none; }
.hero__play.is-shown { display: inline-flex; }

.hero--short { min-height: clamp(340px, 46vh, 460px); }
.hero--center { text-align: center; }
.hero--center .hero__inner { margin-inline: auto; }
.hero--center .lead { margin-inline: auto; }


/* ---------------------------------------------------------------------------
   19. Footer (always ink chrome)
   ------------------------------------------------------------------------ */

.site-footer {
  background: var(--bg);
  color: var(--ink);
  border-top: 1px solid var(--hairline);
  padding-block: var(--space-3xl) var(--space-xl);
  font-size: var(--fs-small);
}
.site-footer__grid {
  display: grid;
  gap: var(--space-xl);
  grid-template-columns: 1.4fr repeat(3, 1fr);
}
.site-footer h2, .site-footer h3 {
  font-size: var(--fs-eyebrow);
  font-family: var(--font-body);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-eyebrow);
  color: var(--ink-muted);
  margin-bottom: var(--space-md);
}
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: var(--space-sm); }
.site-footer a { color: var(--ink); }
.site-footer a:hover { color: var(--secondary); }
.site-footer__brand img { height: 44px; width: auto; margin-bottom: var(--space-md); }
.site-footer__blurb { color: var(--ink-muted); max-width: 34ch; }
.site-footer__phone {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--secondary);
  margin-top: var(--space-sm);
}
.site-footer__legal {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--hairline);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-lg);
  align-items: center;
  justify-content: space-between;
  color: var(--ink-muted);
}
.site-footer__legal a { color: var(--ink-muted); }
.site-footer__legal a:hover { color: var(--ink); }
.site-footer__legal nav { display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-md); }
.site-footer__dba { color: var(--ink-muted); }

@media (max-width: 900px) {
  .site-footer__grid { grid-template-columns: repeat(2, 1fr); }
  .site-footer__brand { grid-column: 1 / -1; }
}


/* ---------------------------------------------------------------------------
   20. Media
   ------------------------------------------------------------------------ */

.media { border-radius: var(--radius-lg); overflow: hidden; background: var(--surface-inset); }
.media img, .media video { width: 100%; display: block; }
.media--frame { border: 1px solid var(--hairline); }

.figure { margin: 0; }
.figure figcaption { margin-top: var(--space-sm); font-size: var(--fs-small); color: var(--ink-muted); }

.ratio { position: relative; }
.ratio > * { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ratio--16x9 { aspect-ratio: 16 / 9; }
.ratio--4x3  { aspect-ratio: 4 / 3; }
.ratio--1x1  { aspect-ratio: 1 / 1; }

/* Gallery — masonry-ish grid that stays honest on mobile */
.gallery { display: grid; gap: var(--space-md); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.gallery img { border-radius: var(--radius-md); width: 100%; }


/* ---------------------------------------------------------------------------
   21. Focus. Sage glow, with a contrast-carrying edge that works on both
   grounds (olive on paper, sage on ink). Never remove without a replacement.
   ------------------------------------------------------------------------ */

:focus-visible {
  outline: 2px solid var(--focus-edge);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-ring);
  border-radius: var(--radius-xs);
}
.btn:focus-visible, .card--link:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible { border-radius: var(--radius-sm); }
input:focus, select:focus, textarea:focus { border-color: var(--focus-edge); }
:focus:not(:focus-visible) { outline: none; }


/* ---------------------------------------------------------------------------
   22. Utilities
   ------------------------------------------------------------------------ */

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.text-center { text-align: center; }
.center { margin-inline: auto; }
.nowrap { white-space: nowrap; }
.full { width: 100%; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.mt-lg { margin-top: var(--space-lg); }
.mt-xl { margin-top: var(--space-xl); }
.mt-2xl { margin-top: var(--space-2xl); }
.mb-lg { margin-bottom: var(--space-lg); }
.mb-xl { margin-bottom: var(--space-xl); }
.mb-2xl { margin-bottom: var(--space-2xl); }

/* Scroll reveal — one class, one observer, unobserved after it fires. */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-reveal) var(--ease), transform var(--dur-reveal) var(--ease);
  will-change: opacity, transform;
}
.reveal.is-in { opacity: 1; transform: none; }
/* No JS? Show everything. */
.no-js .reveal { opacity: 1; transform: none; }


/* ---------------------------------------------------------------------------
   23. Responsive
   ------------------------------------------------------------------------ */

@media (max-width: 900px) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .grid-hair--3, .grid-hair--4 { grid-template-columns: repeat(2, 1fr); }
  .split, .split--wide-left, .split--wide-right { grid-template-columns: 1fr; gap: var(--space-xl); }
  .split--media-first .split__media { order: -1; }
}

@media (max-width: 640px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  .grid-hair--2, .grid-hair--3, .grid-hair--4 { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .btn-row .btn { width: 100%; }
  .site-footer__grid { grid-template-columns: 1fr; }
  .steps > li { padding-left: var(--space-2xl); }
  .steps > li::before { width: 32px; height: 32px; font-size: 0.85rem; }
  .steps:not(.steps--row) > li::after { left: 16px; top: 36px; }
}


/* ---------------------------------------------------------------------------
   24. Reduced motion
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
  .card--link:hover { transform: none; }
}


/* ---------------------------------------------------------------------------
   25. Print — pricing and procurement pages get printed. Flatten ink to paper.
   ------------------------------------------------------------------------ */

/* Print mark — hidden on screen, the only branding a printed page carries.
   The header and footer are dropped in print, so without this a quote or a
   pricing page comes off the business office printer unbranded. Uses the
   flattened paper asset so it renders identically on any printer. */
.print-mark { display: none; }

@media print {
  .site-header, .site-footer, .beam-wash, .hero__media, .hero__scrim, .nav-toggle { display: none !important; }
  .print-mark {
    display: block;
    margin: 0 0 var(--space-lg);
    padding-bottom: var(--space-md);
    border-bottom: 1px solid #ccc;
  }
  .print-mark img { width: 150px; height: auto; }
  .print-mark .print-mark__contact {
    font-family: var(--font-body);
    font-size: 10pt;
    color: #333;
    margin-top: 6px;
  }
  body { background: #fff; color: #000; }
  .band, .band--ink, .hero {
    background: #fff !important;
    background-image: none !important;
    color: #000 !important;
    padding-block: var(--space-xl);
    min-height: 0;
    --surface: #fff; --surface-raised: #fff; --surface-inset: #fff;
    --ink: #000; --ink-muted: #333; --hairline: #bbb; --link: #000;
  }
  .card, .tier, .table-wrap, .grid-hair { border-color: #bbb !important; }
  a { text-decoration: underline; }
  .reveal { opacity: 1; transform: none; }
}


/* ---------------------------------------------------------------------------
   26. Code — added for the software cluster (/software and the four product
   pages). A REST plugin page has to show a curl call and a plugin path, and a
   proportional font makes those unreadable.

   NOTE FOR THE DESIGN SYSTEM: --font-mono is a SYSTEM stack. No new webfont is
   downloaded and no new colour, radius, or spacing value is introduced — every
   value below comes from the existing token set. DESIGN.md does not yet name a
   monospace family; ratify this stack there (or replace it) when convenient.
   ------------------------------------------------------------------------ */

:root {
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
               'Liberation Mono', 'Courier New', monospace;
}

code, kbd, samp, pre { font-family: var(--font-mono); }

/* Inline code — a quiet chip on either ground. */
:not(pre) > code {
  padding: 0 var(--space-xs);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-xs);
  background: var(--surface-inset);
  color: var(--ink);
  font-size: 0.9em;
  overflow-wrap: break-word;
}

/* Block code. Scrolls inside its own box — the page never scrolls sideways. */
.code-block {
  margin: 0;
  padding: var(--space-lg);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--surface-inset);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  color: var(--ink);
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  tab-size: 2;
}
.code-block code {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font-size: inherit;
  white-space: pre;
}


/* ---------------------------------------------------------------------------
   27. FAQ accordion — REMOVED. Another page builder appended an equivalent
   .faq / .faq__item / .faq__answer component further down this file, so the
   duplicate that stood here was deleted rather than shipped twice.
   /software/karaokeflow uses that component, with .faq__answer as the body.
   ------------------------------------------------------------------------ */


/* ---------------------------------------------------------------------------
   28. Product mark — a square product icon in a hero. Sized so it never
   competes with the headline.
   ------------------------------------------------------------------------ */

.product-mark {
  width: 88px;
  height: 88px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--hairline);
  margin-bottom: var(--space-lg);
}


/* ---------------------------------------------------------------------------
   26. Definition list — hairline-separated term/description pairs.
   Added for the audiences cluster (schools / corporate / parties), where the
   FAQ blocks are real question-and-answer pairs and want <dl> semantics.

   Deliberately NOT an accordion: these pages get printed and Ctrl-F'd by a
   business office, so every answer stays open and every answer prints.

   Markup:
     <dl class="deflist">
       <div class="deflist__item">
         <dt>Question</dt>
         <dd>Answer</dd>
       </div>
     </dl>

   Neutral aliases only, so it is correct on paper and on ink unchanged.
   ------------------------------------------------------------------------ */

.deflist { margin: 0; max-width: var(--measure); }

.deflist__item {
  padding-block: var(--space-lg);
  border-top: 1px solid var(--hairline);
}
.deflist__item:first-child { padding-top: 0; border-top: 0; }
.deflist__item:last-child { padding-bottom: 0; }

.deflist dt {
  font-family: var(--font-display);
  font-weight: 700;              /* Lato 700 — no 500/600/800 in the family */
  font-size: var(--fs-h4);
  line-height: 1.3;
  letter-spacing: var(--ls-h4);
  color: var(--ink);
}
.deflist dd {
  margin: var(--space-sm) 0 0;
  color: var(--ink);
}
.deflist dd + dt { margin-top: var(--space-md); }

@media print {
  .deflist__item { border-color: #bbb !important; }
}


/* ---------------------------------------------------------------------------
   26. Commerce cluster — pricing tables, the FAQ accordion, the gallery grid,
   and the lightbox. Added by the pricing/book/gallery build.

   Everything here reads the ground aliases only (--surface, --ink, --hairline,
   --on-accent, --focus-edge …), so each component is correct on paper and on
   ink without a per-ground variant. No hardcoded hex, no beam colour used as
   paint, no white on sage.
   ------------------------------------------------------------------------ */

/* --- Featured table row -----------------------------------------------------
   The table equivalent of .tier--featured: a sage edge and a sage tint, with
   the label carried by a .badge in the row header so colour is never the only
   signal. Sage stays a fill; the type in the row is still --ink. */
.table tr.is-featured > * { background: rgba(var(--secondary-rgb), 0.12); }
.table tr.is-featured > *:first-child { box-shadow: inset 3px 0 0 var(--secondary); }

/* --- Stacking table ---------------------------------------------------------
   A five-column price table is unreadable in a sideways scroller on a phone,
   so .table--stack turns every row into a card under 900px. Each <td> carries
   data-label="…" matching its column header, which becomes the row label. */
@media (max-width: 900px) {
  .table--stack thead {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .table--stack tbody tr {
    display: block;
    padding: var(--space-md) 0;
    border-bottom: 1px solid var(--hairline);
  }
  .table--stack tbody tr:last-child { border-bottom: 0; }
  .table--stack tbody th,
  .table--stack tbody td {
    display: block;
    padding: var(--space-xs) var(--space-md);
    border-bottom: 0;
  }
  .table--stack tbody th[scope="row"] { padding-top: var(--space-md); font-size: var(--fs-body); }
  .table--stack tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: var(--space-xs);
    font-family: var(--font-body);
    font-size: var(--fs-eyebrow);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--ls-badge);
    color: var(--ink-muted);
  }
}

/* --- Footnote list under a table -------------------------------------------- */
.footnotes { margin-top: var(--space-lg); padding-left: 1.2em; font-size: var(--fs-small); color: var(--ink-muted); }
.footnotes li { margin-bottom: var(--space-sm); }
.footnotes li:last-child { margin-bottom: 0; }

/* --- FAQ accordion ----------------------------------------------------------
   <details>/<summary>: keyboard-operable for free, closed on load, 250ms
   disclosure. The page script opens every item before printing, because this
   page gets attached to requisitions. */
.faq { border-top: 1px solid var(--hairline); max-width: var(--measure); }
.faq__item { border-bottom: 1px solid var(--hairline); }
.faq__item > summary {
  list-style: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: 44px;
  padding: var(--space-md) 0;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h4);
  line-height: 1.3;
  color: var(--ink);
  transition: color var(--dur-hover) var(--ease);
}
.faq__item > summary::-webkit-details-marker { display: none; }
.faq__item > summary:hover { color: var(--link); }
.faq__item > summary::after {
  content: '';
  flex: 0 0 auto;
  margin-top: 0.4em;
  width: 8px; height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--dur-panel) var(--ease);
  opacity: 0.6;
}
.faq__item[open] > summary::after { transform: rotate(-135deg); }
.faq__answer { padding: 0 0 var(--space-lg); color: var(--ink-muted); }
.faq__answer > :last-child { margin-bottom: 0; }

/* --- Filter bar (gallery) ---------------------------------------------------
   Pill buttons carrying aria-pressed. Selected state is a sage fill with
   --on-accent type, never white on sage. Without JS every pill is inert and
   every item stays visible, which is the correct degradation. */
.filter-bar { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-bottom: var(--space-xl); }
.pill--filter {
  min-height: 44px;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
  transition: background-color var(--dur-hover) var(--ease),
              border-color var(--dur-hover) var(--ease),
              color var(--dur-hover) var(--ease);
}
.pill--filter:hover { border-color: var(--focus-edge); }
.pill--filter[aria-pressed="true"] {
  background: var(--secondary);
  border-color: var(--secondary);
  color: var(--on-accent);
}

/* --- Gallery tile -----------------------------------------------------------
   A figure, not a link: the media may be a video, and the lightbox trigger is
   an explicit button underneath so the control is reachable and labelled. */
.tile { display: flex; flex-direction: column; gap: var(--space-sm); margin: 0; }
.tile__frame {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  background: var(--surface-inset);
  transition: border-color var(--dur-hover) var(--ease), transform var(--dur-hover) var(--ease);
}
.tile:hover .tile__frame { border-color: var(--focus-edge); }
.tile__frame img, .tile__frame video { width: 100%; height: 100%; object-fit: cover; }
.tile__badge { position: absolute; top: var(--space-sm); left: var(--space-sm); z-index: 2; }
.tile__empty {
  display: grid;
  place-items: center;
  padding: var(--space-md);
  text-align: center;
  font-size: var(--fs-small);
  color: var(--ink-muted);
  background: repeating-linear-gradient(135deg,
    transparent 0 12px, rgba(var(--secondary-rgb), 0.06) 12px 24px);
}
.tile__caption { font-size: var(--fs-small); color: var(--ink-muted); }
.tile__caption b, .tile__caption strong { color: var(--ink); }
.tile__actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); }

/* --- Lightbox ---------------------------------------------------------------
   Native <dialog>. showModal() supplies role=dialog, aria-modal, the focus
   trap, Escape, the body scroll lock, and focus return to the trigger — all of
   it from the platform rather than from hand-written JS. The dialog renders in
   the top layer, outside any band, so it declares the ink aliases itself the
   way .site-header does. */
.lightbox {
  --surface:        var(--bg);
  --surface-raised: var(--bg-card);
  --surface-inset:  var(--bg-input);
  --ink:            var(--text);
  --ink-muted:      var(--muted);
  --hairline:       var(--border);
  --on-accent:      var(--ink-on-light);
  --link:           var(--secondary);
  --link-hover:     var(--secondary);
  --focus-edge:     var(--secondary);

  width: min(1040px, 92vw);
  max-width: 92vw;
  max-height: 90dvh;
  padding: 0;
  overflow: auto;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  color: var(--ink);
}
.lightbox::backdrop { background: rgba(10, 10, 26, 0.82); }
.lightbox__media { background: var(--surface-inset); }
.lightbox__media img, .lightbox__media video { width: 100%; max-height: 62dvh; object-fit: contain; }
.lightbox__slot {
  display: grid;
  place-items: center;
  min-height: 220px;
  padding: var(--space-2xl) var(--space-lg);
  text-align: center;
  color: var(--ink-muted);
}
.lightbox__body { padding: var(--space-lg); }
.lightbox__caption { margin-bottom: var(--space-xs); }
.lightbox__count { font-size: var(--fs-small); color: var(--ink-muted); }
.lightbox__controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid var(--hairline);
}
.lightbox__nav { display: flex; gap: var(--space-sm); }

/* --- Two-step quote form ----------------------------------------------------
   Step 2 is hidden with the `hidden` attribute by script only. With JS off it
   never gets hidden, so the whole form is one continuous page. */
.step-note { margin-top: var(--space-md); font-size: var(--fs-small); color: var(--ink-muted); max-width: 52ch; }
.date-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-md);
  margin-bottom: var(--space-xl);
  padding: var(--space-md);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--surface-inset);
  font-size: var(--fs-small);
}
.date-bar__value { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-body); color: var(--ink); }
.error-summary ul { margin: var(--space-sm) 0 0; padding-left: 1.2em; }
.error-summary li { margin-bottom: var(--space-xs); }

@media (prefers-reduced-motion: reduce) {
  .tile:hover .tile__frame { transform: none; }
}

@media print {
  /* The FAQ hairlines already flatten with the band's --hairline token. */
  .filter-bar, .lightbox, .tile__actions, .billing-toggle { display: none !important; }
  .faq__answer { display: block !important; }
  .table tr.is-featured > * { background: transparent !important; box-shadow: none !important; }
}


/* ---------------------------------------------------------------------------
   29. FIGURE & COLOUR — icon system, icon tiles, beam cards, card alignment.

   Added for revision 1. The brief: several paper bands in a row were carrying
   flat hairline card grids with centred, icon-free text. This section supplies
   (a) an inline-SVG icon system, (b) a tile that carries brand colour onto a
   paper card, (c) the beam card for ink bands, and (d) the alignment and
   rhythm fixes that stop card grids reading as centred text in whitespace.

   NOTHING NEW IS INTRODUCED INTO THE PALETTE. Every value below is an existing
   DESIGN.md token, an existing alias, or an alpha of an existing token. No new
   colour, font, radius, or spacing value.

   Ground rules restated, because this section is where they are easiest to
   break:
     - Sage (--secondary) is a FILL. It never carries white type and it is
       never body text on a ground. A sage fill takes --on-accent.
     - Beam colours are LIGHT. Gradient, glow, blur. Never a flat fill, never a
       border, never a stroke on a glyph, never text. INK GROUND ONLY.
     - Components read the neutral aliases. No hardcoded hex in a component.
   ------------------------------------------------------------------------ */


/* --- 29.1 Two new aliases, one per ground ----------------------------------
   The icon tile is sage-on-paper and sage-glyph-on-a-sage-tint on ink, so the
   difference lives in the ground blocks — exactly like --surface and --ink —
   and the component rule below is written once and is correct on both.

     --tile-fill   the tile's background
     --tile-ink    the glyph colour (what currentColor resolves to)
     --tile-edge   the tile's hairline (transparent on paper: the sage fill
                   already separates it from the white card)                */

:root,
.band,
.band--paper {
  --tile-fill: var(--secondary);              /* sage fill */
  --tile-ink:  var(--on-accent);              /* #1a1a17 on sage — 8.9:1 */
  --tile-edge: transparent;
}

.band--ink,
.hero,
.site-header,
.site-footer,
.lightbox {
  --tile-fill: rgba(var(--secondary-rgb), 0.14);   /* sage tint, not a flat fill */
  --tile-ink:  var(--secondary);                   /* sage glyph — ~7:1 on the tint */
  --tile-edge: rgba(var(--secondary-rgb), 0.30);
}


/* --- 29.2 The icon ---------------------------------------------------------
   Hand-authored inline SVG only. No icon font, no sprite sheet, no external
   request — the Privacy Policy commitment that rules out the Google Fonts CDN
   rules out an icon CDN for the same reason.

   Every glyph is authored to the same spec, and the page must not deviate:
     viewBox="0 0 24 24"  fill="none"  stroke="currentColor"
     stroke-width="1.5"   stroke-linecap="round"  stroke-linejoin="round"
     aria-hidden="true"   focusable="false"

   The glyph inherits colour from its parent via currentColor, so an icon is
   correct on both grounds without a variant. Icons are decorative: the text
   beside them always carries the meaning, so they are aria-hidden and colour
   is never the only signal (DESIGN.md, Do's).                               */

.icon {
  width: 1.5rem;
  height: 1.5rem;
  display: block;
  flex: none;
}
.icon--sm { width: 1rem;   height: 1rem; }
.icon--lg { width: 2rem;   height: 2rem; }

/* An icon set inline in a run of text, rather than in a tile. */
.icon--inline { display: inline-block; vertical-align: -0.18em; }


/* --- 29.3 The icon tile ----------------------------------------------------
   A rounded square holding one icon. This is the sanctioned sage-fill pattern:
   on paper it is a sage plate with dark glyph (passes), on ink it is a raised
   sage tint with a sage glyph (passes). One rule, two grounds.

   Radius: --radius-sm (6px), deliberately smaller than the --radius-md (10px)
   of the card it sits in — "never nest an equal-or-larger radius inside a
   smaller one". 44px matches the hit-target rhythm used by .btn and .nav__link
   so a tile and a button line up on the same baseline grid.                 */

.icon-tile {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--tile-edge);
  background: var(--tile-fill);
  color: var(--tile-ink);
}

/* Section leads, band intros, hero. NOT for inside a card: --radius-md would
   equal the card's own radius. Inside a card use the default .icon-tile. */
.icon-tile--lg {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-md);
}
.icon-tile--lg .icon { width: 1.75rem; height: 1.75rem; }

/* Olive plate, white glyph — 6.9:1, the same pairing as .btn--primary. Use it
   for the one tile in a set that maps to a primary action. Identical on both
   grounds, so it is written flat rather than through the aliases. */
.icon-tile--olive { background: var(--primary); border-color: var(--primary); color: #fff; }

/* Quiet tile — hairline outline, muted glyph. For a supporting or "not yet"
   item where a sage plate would over-claim. */
.icon-tile--ghost { background: transparent; border-color: var(--hairline); color: var(--ink-muted); }

/* Beam halo behind a tile. INK ONLY, and light rather than paint: the tile
   fill and the glyph both stay sage, the beam appears only as a blurred glow
   spilling out from under the plate. Set --beam on the card or the tile.

   Implemented as a box-shadow rather than a pseudo-element on purpose: a
   shadow paints behind the element's own background from any stacking context,
   so the halo is correct whether the tile sits in a plain .card (no stacking
   context) or in a .card--beam (isolated). A z-index:-1 pseudo would land on
   TOP of the sage plate in the second case.

   The fallback lives in the var() call, NOT in a `--beam:` declaration on the
   tile — declaring it here would shadow the --beam inherited from an enclosing
   .card--beam, and every halo in a rotated set would come out the same
   colour. */
.band--ink .icon-tile--glow,
.hero .icon-tile--glow {
  box-shadow: 0 0 22px -2px var(--beam, var(--beam-cyan)),
              0 0 7px  -3px var(--beam, var(--beam-cyan));
}


/* --- 29.4 Icon + content inside a card or a hairline cell ------------------
   Two arrangements. Both work in a .card and in a bare .grid-hair cell, and
   neither centres anything.

   Stacked — tile above the heading:
     <div class="card">
       <span class="icon-tile card__icon" aria-hidden="true">…svg…</span>
       <h3>Heading</h3>
       <p>Body.</p>
     </div>

   Inline — tile beside the heading:
     <div class="card">
       <div class="card__head">
         <span class="icon-tile" aria-hidden="true">…svg…</span>
         <h3>Heading</h3>
       </div>
       <p>Body.</p>
     </div>                                                                  */

.card__icon { margin-bottom: var(--space-md); }

.card__head {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-md);
}
.card__head > h2,
.card__head > h3,
.card__head > h4 { margin: 0; }

/* Use in a grid where some headings wrap to two lines: centring each tile on
   its own heading leaves the tiles at different heights across the row. */
.card__head--top { align-items: flex-start; }

/* A lead block for a section head: big tile beside the h2. */
.lead-icon {
  display: flex;
  align-items: flex-start;
  gap: var(--space-lg);
  margin-bottom: var(--space-md);
}
.lead-icon > :last-child { flex: 1 1 auto; }
.lead-icon h2, .lead-icon h3 { margin-bottom: var(--space-sm); }


/* --- 29.5 Icon list --------------------------------------------------------
   The .list-ticks sibling, for when the marker should carry meaning rather
   than just say "yes". Olive stroke on paper (6.4:1), sage on ink (11.4:1) —
   both sanctioned as an accent stroke on their ground.

     <ul class="icon-list">
       <li>…svg class="icon"…<div><b>Label</b> Body.</div></li>
     </ul>                                                                    */

.icon-list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-md); }
.icon-list > li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  text-align: left;
  margin: 0;
}
.icon-list .icon { margin-top: 0.12em; color: var(--secondary); }
.band:not(.band--ink) .icon-list .icon { color: var(--primary); }
.icon-list p:last-child { margin-bottom: 0; }


/* --- 29.6 Accent rule ------------------------------------------------------
   Cheap colour on a paper card with no icon: a short olive (paper) or sage
   (ink) bar above the heading. A fill, not a beam.                          */

.rule-accent {
  display: block;
  width: 48px;
  height: 3px;
  border-radius: var(--radius-full);
  background: var(--secondary);
  margin: 0 0 var(--space-md);
}
.band:not(.band--ink) .rule-accent { background: var(--primary); }


/* --- 29.7 THE BEAM CARD — INK GROUND ONLY ----------------------------------
   A hairline card with a soft blurred glow bleeding up from its bottom edge in
   one beam colour. The colour arrives from markup as a per-card custom
   property, so one rule serves all four beams:

     <article class="card card--beam" style="--beam: var(--beam-magenta)">
       <span class="icon-tile" aria-hidden="true">…svg…</span>
       <h3>Heading</h3>
       <p>Body.</p>
     </article>

   GUARD: the glow lives entirely on ::before, which is display:none by
   default and is switched on only by an ancestor .band--ink or .hero. This is
   the same guard .beam-wash uses (§7). On a paper band the ::before never
   generates a box, so the card degrades to a plain .card and no beam colour
   can reach a paper ground. .hero is included because .hero hardcodes
   background: var(--bg) — it is unconditionally a dark ground — and every hero
   in this codebase also carries .band--ink.

   The glow is clipped by the card's own overflow, so it reads as light inside
   the box rather than a coloured halo floating on the band.                  */

.card--beam {
  --beam: var(--beam-magenta);   /* fallback if markup sets nothing */
  position: relative;
  isolation: isolate;            /* contains the screen blend */
  overflow: hidden;
}
.card--beam::before { content: ''; display: none; }

.band--ink .card--beam::before,
.hero .card--beam::before {
  display: block;
  position: absolute;
  left: -25%;
  right: -25%;
  bottom: -62%;
  height: 118%;
  z-index: 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--beam), transparent 74%);
  filter: blur(34px);
  opacity: 0.40;
  mix-blend-mode: screen;
  pointer-events: none;
}
.card--beam > * { position: relative; z-index: 1; }

/* Slightly stronger for a single hero-adjacent card; quieter for a dense set. */
.band--ink .card--beam.is-bright::before { opacity: 0.55; }
.band--ink .card--beam.is-quiet::before  { opacity: 0.26; }

/* Rotate the four beams across a set without touching every card's style
   attribute. Put it on the grid: <div class="grid grid--3 beam-rotate">     */
.beam-rotate > *:nth-child(4n + 1) { --beam: var(--beam-magenta); }
.beam-rotate > *:nth-child(4n + 2) { --beam: var(--beam-cyan); }
.beam-rotate > *:nth-child(4n + 3) { --beam: var(--beam-amber); }
.beam-rotate > *:nth-child(4n + 4) { --beam: var(--beam-violet); }


/* --- 29.8 Card grids read LEFT ---------------------------------------------
   Max's note: "cards centered, text only". Card content is left-aligned by
   default from here on.

   :where() zeroes the specificity, which is the whole trick:
     - it beats INHERITED text-align:center from an ancestor (a declared value
       always beats an inherited one, whatever the specificity), so a card grid
       dropped inside <div class="container text-center"> no longer centres;
     - it loses to an explicit .text-center ON the card itself, so a page that
       genuinely wants a centred card can still say so.                       */

:where(.card, .grid-hair > *, .tier, .product-card, .steps > li, .deflist,
       .icon-list, .faq, .form-card) { text-align: left; }


/* --- 29.9 Rhythm inside card grids -----------------------------------------
   Band padding is untouched — it stays at --band-pad (120–152px), which is the
   page's breathing. What was too loose was the space INSIDE and immediately
   above a grid of short cards. DESIGN.md fixes card padding at `lg`, so that
   is left alone and the tightening comes from the gaps between the pieces.

   Overrides of earlier rules in this file, on purpose, appended rather than
   edited in place.                                                          */

/* 48px → 32px under a section head. Half a card's height of dead space above
   a four-up grid was most of the "tons of whitespace". */
.section-head { margin-bottom: var(--space-xl); }
.section-head--airy { margin-bottom: var(--space-2xl); }   /* opt back in */

/* 16px → 8px between paragraphs inside a card or a hairline cell. */
:where(.card, .grid-hair > *) p { margin-bottom: var(--space-sm); }

/* Denser cells for a 3- or 4-up grid of one-line facts. */
.grid-hair--tight > * { padding: var(--space-md) var(--space-lg); }
.grid--tight { gap: var(--space-md); }

/* Cards in a grid stretch to the row height. .card--fill makes the card a
   column so its content tops out and any .card__foot sits on the floor,
   instead of a short card's text floating in the middle of the extra height.
   OPT-IN, not a default: turning every .card into a flex column would change
   how images and .card--link anchors already lay out on the 17 built pages.

     <div class="card card--fill"> … <div class="card__foot">…</div> </div>  */
.card--fill { display: flex; flex-direction: column; }
.card__foot { margin-top: auto; padding-top: var(--space-md); }


/* --- 29.10 Print -----------------------------------------------------------
   A sage plate prints as a grey block and a beam glow prints as nothing useful
   at best. Flatten both, and keep the glyph — the outline reads fine in mono. */

@media print {
  .card--beam::before { display: none !important; }
  .icon-tile {
    background: transparent !important;
    border-color: #bbb !important;
    color: #000 !important;
    box-shadow: none !important;
  }
  .rule-accent { background: #bbb !important; }
  .icon-list .icon { color: #000 !important; }
}

/* Revision 1 fix — muted copy inside a beam card fell under 4.5:1. --ink-muted
   has only 0.56 of contrast headroom on --surface-raised, and the beam glow
   spends all of it. Inside a glowing card, muted text reverts to full strength. */
.card--beam .muted,
.card--beam .card__meta,
.card--beam .tier__period,
.card--beam p.small { color: var(--ink); }

/* Embedded video (YouTube via youtube-nocookie). .ratio positions the iframe;
   these two lines stop it rendering as a bordered rectangle with square
   corners against a rounded design. */
.video-embed { border-radius: var(--radius-md); overflow: hidden; background: #000; }
.video-embed iframe { border: 0; }

/* .field + .field adds a top margin so stacked fields breathe. Inside
   .form-grid the adjacent sibling is in the SAME ROW, so that margin pushed
   every field after the first downward — visibly, Email sat lower than Name.
   The grid's own gap already handles spacing in both axes. */
.form-grid .field + .field { margin-top: 0; }

/* Package name in the pricing table — the row heading is now a name, with the
   crowd size demoted to a subtitle beneath it. */
.pkg-name { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; }
