/* =========================================================================
   BRANDSCRIBED — DESIGN TOKENS
   Every hex color in this codebase lives in this :root block and nowhere else.
   Everything downstream references these custom properties or color-mix().
   ========================================================================= */
:root {
  /* palette */
  --ink: #141010;
  --paper: #efe7d8;
  --brass: #c49a58;
  --brass-dim: #8f6f3e;
  --bone: #f3ede1;
  --smoke: #a89f92;
  --graphite: #3b332e;
  --line: rgba(243, 237, 225, 0.14);
  --line-paper: rgba(59, 51, 46, 0.25);

  /* typography families — Google Fonts only */
  --font-display: "Bodoni Moda", Georgia, serif;
  --font-label: "Cinzel", Georgia, serif;
  --font-mono: "Courier Prime", "Courier New", monospace;
  --font-body: "Archivo", system-ui, sans-serif;

  /* modular scale — 1.25 minor third, fluid at the top end */
  --step--2: 0.7rem;
  --step--1: 0.82rem;
  --step-0: 1rem;
  --step-1: 1.25rem;
  --step-2: clamp(1.4rem, 0.6vw + 1.25rem, 1.563rem);
  --step-3: clamp(1.7rem, 1.1vw + 1.4rem, 1.953rem);
  --step-4: clamp(2rem, 1.9vw + 1.5rem, 2.441rem);
  --step-5: clamp(2.4rem, 3vw + 1.6rem, 3.052rem);
  --step-6: clamp(2.9rem, 5vw + 1.6rem, 3.815rem);
  --step-7: clamp(3.4rem, 8vw + 1.4rem, 6rem);

  /* layout */
  --measure: 1120px;
  --gutter: 1.5rem;
}

/* =========================================================================
   RESET / BASE
   ========================================================================= */
*,
*::before,
*::after { box-sizing: border-box; }
* { margin: 0; min-width: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
  -webkit-text-size-adjust: 100%;
}

body {
  background-color: var(--ink);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  overflow-x: hidden;
  /* DO NOT re-add -webkit-font-smoothing or text-rendering here.
     The conversion added `-webkit-font-smoothing: antialiased` and
     `text-rendering: optimizeLegibility`; brandscribed.lovable.app sets
     NEITHER, anywhere. `antialiased` forces Chrome off subpixel AA onto
     grayscale, which renders light-on-dark text visibly thinner — and Bodoni
     Moda is a Didone whose hairlines all but vanish under it. Cinzel has no
     hairlines, which is why the hero looked right while every Bodoni heading
     looked wrong. Leaving both unset restores the Lovable rendering. */
}

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

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

/* Tailwind Preflight equivalent. Lovable ships this and the Jekyll conversion
   dropped it, so h4-h6 were still picking up the UA default bold-700 while the
   same elements on brandscribed.lovable.app inherit 400 from body. Must stay
   ABOVE the h1-h3 rule below, which deliberately re-asserts 500. */
h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
}
::selection { background: var(--brass); color: var(--ink); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--brass); color: var(--ink); padding: 0.6rem 1rem;
  font-family: var(--font-label); letter-spacing: 0.12em; text-transform: uppercase;
}
.skip-link:focus { left: 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* =========================================================================
   PRIMITIVES
   ========================================================================= */
.shell {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.eyebrow {
  font-family: var(--font-label);
  font-size: var(--step--1);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--brass);
  line-height: 1.4;
}

.slug {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brass);
  overflow-wrap: anywhere;
}

.rule { border: 0; border-top: 1px solid var(--line); }

.btn, .btn-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.6rem;
  font-family: var(--font-label);
  font-size: var(--step--1);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 0.95rem 1.6rem;
  text-align: center;
  cursor: pointer;
}
.btn {
  border: 1px solid var(--brass);
  color: var(--ink);
  background: var(--brass);
  transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease;
}
.btn:hover { background: transparent; color: var(--brass); }
.btn-ghost {
  border: 1px solid var(--line);
  color: var(--paper);
  background: transparent;
  transition: border-color 200ms ease, color 200ms ease;
}
.btn-ghost:hover { border-color: var(--brass); color: var(--brass); }
.btn-sm { padding: 0.6rem 1.25rem; font-size: var(--step--2); }

.field {
  width: 100%;
  background: color-mix(in srgb, var(--bone) 7%, transparent);
  border: 1px solid var(--brass-dim);
  border-radius: 2px;
  color: var(--paper);
  font-family: var(--font-body);
  font-size: var(--step-0);
  padding: 0.85rem 1rem;
  transition: border-color 200ms ease;
}
.field:hover, .field:focus { border-color: var(--brass); }
.field::placeholder { color: var(--smoke); }

/* honeypot — never display:none */
.hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* =========================================================================
   TYPE / LAYOUT HELPERS  (token-driven, no raw hex)
   ========================================================================= */
/* Big display figures: prices, step numbers. Bodoni, not Courier - the
   conversion had these on .mono, which is the visible substitution. Declared
   before the colour utilities so `.numeral .brass` still resolves to --brass,
   mirroring Tailwind's component-then-utility order on the Lovable build. */
.numeral {
  font-family: var(--font-display);
  font-size: var(--step-4);
  color: var(--brass-dim);
  font-variant-numeric: lining-nums;
  line-height: 1;
}
/* Used by the #playbook section, which is not in the current homepage build -
   see question 27 (section order). Carried so parity holds when it lands. */
.playbook-card {
  border: 1px solid var(--line-paper);
  background: var(--bone);
  color: var(--graphite);
  font-family: var(--font-mono);
  box-shadow: 10px 10px 0 color-mix(in oklab, var(--graphite) 12%, transparent);
  padding: 2.1rem 2.1rem 1.9rem;
}

.center { text-align: center; }
.muted { color: var(--smoke); }
.bone { color: var(--bone); }
.brass { color: var(--brass); }
.emph { font-style: italic; color: var(--brass); }
.emph-plain { font-style: normal; color: var(--brass); }
.strong-bone { font-weight: 500; color: var(--bone); }

.t-xs   { font-size: var(--step--1); }
.t-sm   { font-size: var(--step-0); }
.t-lg   { font-size: var(--step-1); }
.t-xl   { font-size: var(--step-2); }
.t-2xl  { font-size: var(--step-3); }
.t-3xl  { font-size: var(--step-4); }
.t-4xl  { font-size: var(--step-5); }
.t-5xl  { font-size: var(--step-6); }
.t-6xl  { font-size: var(--step-7); }
/* Lovable pins several Bodoni headings to arbitrary pixel values rather than a
   scale step (Tailwind `text-[22px]` and friends). Those are not decorative —
   Bodoni Moda carries an `opsz` axis and `font-optical-sizing: auto`, so the
   font SIZE selects the optical design. Rendering a 22px heading at 25px pulls
   a more display-oriented cut with narrower apertures and thinner hairlines,
   which is why the conversion's Bodoni read as a different typeface. These
   mirror the source values exactly; `leading-tight` is 1.25. */
.t-card    { font-size: 22px; line-height: 1.25; }
.t-card-md { font-size: 24px; line-height: 1.25; }
.t-card-lg { font-size: 26px; line-height: 1.25; }
.t-name    { font-size: 20px; }

.display { font-family: var(--font-display); }
.mono { font-family: var(--font-mono); }

.section { padding-block: clamp(3rem, 5.5vw, 5.5rem); }
/* Two stacked sections used to pay the padding twice, so the gap BETWEEN Act I
   and Act II was double the gap from the top of Act I's own box down to its
   slugline. Collapsing the second one's top padding makes those two distances
   equal, which is exactly what the client asked for.
   The :not()s matter: a section that paints its own background or draws a
   border needs its top padding, or its first line would sit on the seam. So
   this fires only where BOTH neighbours are plain, unbordered sections —
   Act I → Act II, and About → Critical Acclaim. */
.section:not(.surface-raised):not([class*="section-border"])
  + .section:not(.surface-raised):not([class*="section-border"]) {
  padding-top: 0;
}
.section-sm { padding-block: clamp(3rem, 5vw, 4.5rem); }
.section-border-t { border-top: 1px solid var(--line); }
.section-border-y { border-block: 1px solid var(--line); }

.stack > * + * { margin-top: 1.5rem; }
.stack-sm > * + * { margin-top: 0.75rem; }
.stack-lg > * + * { margin-top: 2rem; }

.measure-sm { max-width: 48rem; margin-inline: auto; }
.measure-xs { max-width: 40rem; margin-inline: auto; }
.measure-prose { max-width: 68ch; }

.lead {
  font-size: var(--step-2);
  font-weight: 300;
  line-height: 1.55;
  color: var(--smoke);
}

.head-block { max-width: 46rem; margin-inline: auto; margin-bottom: clamp(3rem, 5vw, 4rem); }
/* The Act II heading is the longest H2 on the site (74 chars). In the default
   46rem / --step-6 head-block it broke to FOUR lines. Measured across
   viewports: a 58rem measure at this clamp lands it on two lines from 1024px
   up, three at 768, and four at 390 (down from six). */
#process .head-block { max-width: 58rem; }
#process .head-block h2 { font-size: clamp(2.2rem, 4.2vw + 1.1rem, 3.3rem); }
.head-block h1, .head-block h2 { font-size: var(--step-6); color: var(--bone); }
.subhead { margin-top: 1.5rem; font-size: var(--step-1); color: var(--smoke); }

.cta-row { margin-top: 2.5rem; display: flex; flex-wrap: wrap; gap: 1rem; }
.cta-row.center { justify-content: center; }

/* generic bordered card grid (act I / models / faq) */
.card-grid {
  display: grid;
  gap: 1px;
  border: 1px solid var(--line);
  background: var(--line);
}
.card-grid.cols-2 { grid-template-columns: 1fr; }
.card-grid.cols-3 { grid-template-columns: 1fr; }
.card-grid > .card { background: var(--ink); padding: clamp(1.75rem, 3vw, 2.75rem); }
.card h3, .card h4 { font-family: var(--font-display); color: var(--bone); line-height: 1.15; }
.card .cue {
  display: block; margin-bottom: 1rem;
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass);
}
.card p { margin-top: 0.75rem; color: var(--smoke); }
@media (min-width: 640px) { .card-grid.cols-2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 768px) { .card-grid.cols-3 { grid-template-columns: repeat(3, 1fr); } }

/* .spaced — real gutters instead of the 1px hairline-grid trick.
   The default .card-grid paints the gap colour behind the WHOLE grid, so an
   odd number of cards leaves the trailing empty cell rendering as a bordered
   phantom block. With per-card borders there is nothing to paint where there
   is no card, so a half-empty last row is simply whitespace. */
.card-grid.spaced { gap: 1rem; border: 0; background: transparent; align-items: start; justify-items: start; }
@media (min-width: 768px) { .card-grid.spaced { gap: 1.5rem; } }
.card-grid.spaced > .card { width: 100%; border: 1px solid var(--line); }

/* two-column split (about, contact) */
.split { display: grid; gap: 2.5rem; }
@media (min-width: 768px) {
  .split { grid-template-columns: 1fr 1fr; gap: 4rem; align-items: start; }
  .split.form-right { grid-template-columns: 1fr 1.15fr; }
  /* Client 2026-09-06: portrait-beside-bio stays ONE column on tablet and
     below. Between 768 and 1023 the 0.85/1.3 split squeezed the portrait to
     about 300px and left the bio in a narrow alley. It splits at 1024 up. */
  .split.media-left { grid-template-columns: 1fr; gap: 2.5rem; }
}
@media (min-width: 1024px) {
  .split.media-left { grid-template-columns: 0.85fr 1.3fr; gap: 4rem; }
}

/* The About closing line, lifted out of the bio column into its own full-width
   row under both the portrait and the bio. */
/* Sits 1.5rem under the portrait/bio row — the same gap the bio's own
   paragraphs use (.stack > * + * { margin-top: 1.5rem }), so it reads as the
   next beat of that block rather than as a separate panel. No rule above it,
   for the same reason: the bio paragraphs do not have one either.

   The size is set to FILL the container on a single line. Measured in-browser:
   this string renders 32.85x its font size, and .shell gives it 1072px at the
   1120px measure, so 32px is the largest size that still holds one line — and
   the ramp below tracks the container down to 768px so it keeps filling the
   width at every desktop size rather than only at one. Above 2rem it would
   wrap to a second line and stop filling the width. */
.about-closer {
  margin: 1.5rem 0 0;
  font-size: clamp(1.35rem, 2.98vw - 1.43px, 2rem);
  font-style: italic;
  line-height: 1.3;
  text-align: center;
}

/* =========================================================================
   HEADER / NAV
   ========================================================================= */
.site-header {
  position: sticky; top: 0; z-index: 50;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--ink) 85%, transparent);
  backdrop-filter: blur(10px);
}
.site-header .bar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding-block: 0.75rem;
}
.brandmark img { height: 1.5rem; width: auto; }
@media (min-width: 768px) { .brandmark img { height: 2rem; } }

.nav-primary { display: none; align-items: center; gap: 1rem; }
.nav-link {
  font-family: var(--font-mono); font-size: var(--step--1);
  /* Tailwind's text-xs utility sets line-height as well as size (calc(1/0.75)
     = 1.3333). Our .t-* classes only carry size, so without this the nav
     inherited body's 1.65 and the header bar rendered taller than Lovable's. */
  line-height: 1.33333;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: color-mix(in srgb, var(--paper) 75%, transparent);
  transition: color 200ms ease;
}
.nav-link:hover { color: var(--brass); }

.nav-drop { position: relative; display: flex; align-items: center; }
.nav-drop-trigger {
  display: inline-flex; align-items: center; gap: 0.35rem;
  background: none; border: 0; cursor: pointer; color: inherit;
  vertical-align: middle;
  /* Deliberately sets NO font-* and NO line-height. The `font` shorthand that
     used to live here outranked .nav-link (same specificity, declared later)
     and reset the trigger to the body face — that was the header bug. And
     `line-height: inherit` measured 21.65px against Lovable's 17.49px, because
     Lovable leaves the button at its UA default. Leave both off. */
}
.nav-drop-trigger svg { fill: none; stroke: currentColor; }
.nav-drop-menu {
  position: absolute; top: calc(100% + 0.6rem); left: 0; min-width: 15rem;
  display: grid; gap: 0.7rem; padding: 1rem 1.1rem;
  background: var(--ink); border: 1px solid var(--line); border-radius: 0.25rem;
  opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: opacity 160ms ease, transform 160ms ease, visibility 160ms;
  z-index: 60;
}
.nav-drop-right .nav-drop-menu { left: auto; right: 0; }
.nav-drop:hover .nav-drop-menu,
.nav-drop:focus-within .nav-drop-menu { opacity: 1; visibility: visible; transform: translateY(0); }

.nav-cta { flex-shrink: 0; }
.nav-mobile-controls { display: flex; align-items: center; gap: 0.75rem; }
.hamburger {
  display: inline-flex; align-items: center; justify-content: center; padding: 0.5rem;
  background: none; border: 0; cursor: pointer;
  color: color-mix(in srgb, var(--paper) 80%, transparent);
}
.hamburger svg { stroke: currentColor; fill: none; }
.nav-mobile { border-top: 1px solid var(--line); background: color-mix(in srgb, var(--ink) 95%, transparent); }
.nav-mobile[hidden] { display: none; }
.nav-mobile nav { display: flex; flex-direction: column; gap: 1rem; padding-block: 1.5rem; }
.nav-mobile-group { display: flex; flex-direction: column; gap: 0.5rem; }
.nav-mobile-group > span {
  font-family: var(--font-mono); font-size: var(--step--1);
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--smoke);
}
.nav-mobile-group .sub { display: flex; flex-direction: column; gap: 0.5rem; padding-left: 1rem; border-left: 1px solid var(--line); }

@media (min-width: 1024px) {
  .nav-primary { display: flex; }
  .nav-mobile-controls { display: none; }
  .nav-mobile { display: none !important; }
}

/* =========================================================================
   BREADCRUMBS
   ========================================================================= */
.breadcrumbs { margin-bottom: 1.5rem; }
.breadcrumbs ol {
  list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0;
  font-family: var(--font-mono); font-size: var(--step--1);
  letter-spacing: 0.06em; color: var(--smoke);
}
.breadcrumbs li { display: inline-flex; align-items: center; gap: 0.5rem; }
.breadcrumbs a { color: var(--smoke); transition: color 200ms ease; }
.breadcrumbs a:hover { color: var(--brass); }
.breadcrumbs [aria-current="page"] { color: var(--bone); }
.breadcrumbs .sep { color: color-mix(in srgb, var(--smoke) 55%, transparent); }

/* =========================================================================
   SLUGLINES (screenplay slug w/ brass rules)
   ========================================================================= */
.sluglines {
  font-family: var(--font-mono); font-size: 0.8125rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--brass);
  display: flex; align-items: center; gap: 14px;
}
.sluglines::before { content: ""; width: 34px; height: 1px; background: var(--brass); flex: none; }
.sluglines.is-center { justify-content: center; }
.sluglines.is-center::after { content: ""; width: 34px; height: 1px; background: var(--brass); flex: none; }
.sluglines.on-paper { color: var(--brass-dim); }
.sluglines.on-paper::before, .sluglines.on-paper::after { background: var(--brass-dim); }

.framemark {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em;
  text-transform: uppercase; color: color-mix(in oklab, var(--smoke) 55%, transparent);
}

/* =========================================================================
   HERO
   ========================================================================= */
.hero {
  position: relative; overflow: hidden; min-height: 65svh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 5rem 1.5rem 4rem;
  background:
    radial-gradient(ellipse 75% 55% at 50% 38%, color-mix(in oklab, var(--brass) 13%, transparent), transparent 65%),
    var(--ink);
}
.hero::before, .hero::after {
  content: ""; position: absolute; left: 0; right: 0; height: 14px;
  background: color-mix(in oklab, var(--ink) 75%, black); z-index: 2;
}
.hero::before { top: 0; }
.hero::after { bottom: 0; }
.hero > * { position: relative; z-index: 1; }
.hero-title {
  font-family: var(--font-label); font-weight: 500; text-transform: uppercase;
  font-size: clamp(2.125rem, 5.6vw, 5.25rem); line-height: 1.14;
  letter-spacing: 0.035em; color: var(--bone);
}
.hero-title .brass { color: var(--brass); }
/* Client 2026-10-09: larger and more prominent, but always ONE line. The
   string is 41 monospace characters; Courier Prime advances 0.6em, plus 0.05em
   tracking, so the line is 26.65em wide. Sizing it to (viewport - the hero's
   3rem of side padding) / 27.5 keeps it inside the hero at every width, capped
   at 1.75rem on desktop. nowrap is the backstop, not the mechanism. */
.hero-sub {
  margin-top: 1.75rem; font-family: var(--font-mono); font-weight: 700;
  font-size: min(1.75rem, calc((100vw - 3rem) / 27.5));
  letter-spacing: 0.05em; color: var(--bone); white-space: nowrap;
}
/* On phones the tracking is what we can afford to give up: at 0 the line is
   24.6em, so the type can be ~10% larger than it could be with it. */
@media (max-width: 639px) {
  .hero-sub { letter-spacing: 0; font-size: calc((100vw - 3rem) / 25); }
}
.hero .frame-top, .hero .frame-bottom {
  position: absolute; left: 0; right: 0; display: flex; justify-content: space-between;
  padding-inline: 1.5rem;
}
/* The bottom framemarks are interactive, so they need real contrast: the
   decorative .framemark colour is 3.00:1, which fails AA once the element is
   no longer aria-hidden. 80% smoke over ink is 4.99:1. */
.framemark a {
  display: inline-flex; align-items: center; gap: 0.5rem;
  color: color-mix(in srgb, var(--smoke) 80%, var(--ink));
  transition: color 200ms ease, transform 200ms ease;
}
.framemark a:hover, .framemark a:focus-visible { color: var(--brass); }
.scroll-cue svg { transition: transform 400ms ease; }
.scroll-cue:hover svg, .scroll-cue:focus-visible svg { transform: translateY(3px); }
@media (prefers-reduced-motion: no-preference) {
  .scroll-cue svg { animation: scroll-nudge 2.4s ease-in-out infinite; }
}
@keyframes scroll-nudge {
  0%, 70%, 100% { transform: translateY(0); }
  85%           { transform: translateY(3px); }
}

.hero .frame-top { top: 2.25rem; }
.hero .frame-bottom { bottom: 2.5rem; }
@media (min-width: 768px) { .hero .frame-top, .hero .frame-bottom { padding-inline: 3rem; } }

.curtain {
  position: absolute; inset: 14px 0; z-index: 0; pointer-events: none;
  background: repeating-linear-gradient(90deg,
    color-mix(in oklab, var(--ink) 92%, black) 0 26px,
    color-mix(in oklab, var(--graphite) 26%, var(--ink)) 26px 46px,
    color-mix(in oklab, var(--ink) 92%, black) 46px 72px);
  opacity: 0.5; mask-image: linear-gradient(to bottom, black, transparent 55%);
}
.vignette {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(ellipse 85% 70% at 50% 45%, transparent 30%, color-mix(in oklab, var(--ink) 88%, black) 100%);
}
.spotlight {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: conic-gradient(from 200deg at 50% -25%, transparent 0deg,
    color-mix(in oklab, var(--brass) 9%, transparent) 20deg, transparent 42deg);
}

.tab {
  font-family: var(--font-mono); font-size: 13px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; padding: 13px 30px;
  border: 1px solid color-mix(in oklab, var(--bone) 28%, transparent); color: var(--bone);
  transition: border-color 0.25s, color 0.25s;
}
.tab:hover { border-color: var(--brass); color: var(--brass); }
.tab-row { margin-top: 2.75rem; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.875rem; }

/* =========================================================================
   SURFACES / SPECIAL
   ========================================================================= */
.surface-raised { background: color-mix(in oklab, var(--ink) 92%, var(--paper)); }

/* The Logline section carried a lot of dead air around a short block of copy.
   Rather than drop a photograph into a film-themed page, the space is filled
   with the frame itself: 35mm sprocket rails down both margins and a brass
   projector wash from above, built from the same vocabulary as the hero's
   .curtain / .spotlight / .vignette. No image request, no layout shift, and
   the whole thing is decorative (aria-hidden) so nothing reaches the a11y
   tree. Remove the `logline` class in index.html to switch it off. */
.logline { position: relative; overflow: hidden; }
.logline > .shell { position: relative; z-index: 1; }
.logline-rails, .logline-wash { position: absolute; inset: 0; pointer-events: none; }
.logline-rails::before, .logline-rails::after {
  content: ""; position: absolute; top: 0; bottom: 0;
  width: clamp(15px, 2vw, 24px);
  background:
    linear-gradient(var(--line), var(--line)) left / 1px 100% no-repeat,
    linear-gradient(var(--line), var(--line)) right / 1px 100% no-repeat,
    repeating-linear-gradient(to bottom,
      transparent 0 15px,
      color-mix(in oklab, var(--bone) 8%, transparent) 15px 31px,
      transparent 31px 46px);
}
.logline-rails::before { left: clamp(0.75rem, 3.5vw, 3.5rem); }
.logline-rails::after { right: clamp(0.75rem, 3.5vw, 3.5rem); }
.logline-wash {
  background:
    radial-gradient(58% 55% at 50% -8%, color-mix(in oklab, var(--brass) 15%, transparent), transparent 72%),
    radial-gradient(115% 85% at 50% 50%, transparent 42%, color-mix(in oklab, black 42%, transparent) 100%);
}
/* Below 768 the rails would crowd the copy, and the section is not empty
   there anyway — the text fills it. */
@media (max-width: 767px) { .logline-rails { display: none; } }

/* Client 2026-10-09: a photo of Jeff speaking, superimposed behind the copy.
   The only speaking shot on the old site is 558x667, so it is never asked to
   fill the section: it sits on the right, full height, muted and desaturated,
   and fades out into the page towards the copy. He faces left, into the text.
   Sits under the rails and the wash (DOM order), so the frame reads over it. */
.logline-photo { position: absolute; inset: 0 0 0 auto; width: min(46%, 640px); pointer-events: none; }
.logline-photo img {
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 20%;
  filter: grayscale(0.55) sepia(0.25) contrast(1.05) brightness(0.8);
  opacity: 0.5;
  -webkit-mask-image: linear-gradient(to left, black 35%, transparent 100%);
          mask-image: linear-gradient(to left, black 35%, transparent 100%);
}
/* Below 768 the copy spans the full width, so the photo goes behind all of it
   and drops far enough that the text keeps its contrast. */
@media (max-width: 767px) {
  .logline-photo { width: 100%; }
  .logline-photo img {
    opacity: 0.22;
    -webkit-mask-image: linear-gradient(to bottom, black 40%, transparent 100%);
            mask-image: linear-gradient(to bottom, black 40%, transparent 100%);
  }
}

.script-page {
  background: var(--paper); color: var(--graphite);
  max-width: 820px; margin-inline: auto;
  padding: clamp(2.5rem, 6vw, 5.25rem) clamp(1.6rem, 7vw, 6rem);
  box-shadow: 0 40px 90px color-mix(in oklab, black 55%, transparent),
              0 4px 18px color-mix(in oklab, black 40%, transparent);
  font-family: var(--font-mono); position: relative;
}
.script-page::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 5px; background: var(--brass); }
.script-page hr { border: 0; border-top: 1px solid var(--line-paper); margin: 1.75rem 0 0.5rem; }

/* The Brandscribed lockup replaces the wordmark that used to be set in type at
   the top of the framework page. logo-dark.png, not logo-light.png: this sheet
   is --paper, and the light logo's "Brand" half is white. */
.script-brand {
  margin: 0;
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: 0.5rem 0.75rem;
  font-weight: 700; text-transform: uppercase;
  font-size: 0.9rem; letter-spacing: 0.14em;
}
/* Height in `em`, so the lockup is measured against the type it sits beside
   and tracks it at every breakpoint instead of being pinned to a viewport
   size. 1.45em puts the wordmark's cap height just above the caps next to it —
   present, not shouting. */
.script-brand img { height: 1.45em; width: auto; }

.beat { padding: 1.75rem 0 0.5rem; }
.beat + .beat { border-top: 1px dashed var(--line-paper); }
/* Client 2026-09-06: Discover / Create / Share needed to read as deliverables,
   not as a run-in label on a paragraph. The name is now its own uppercase
   line at roughly double the body size, with the session name demoted to a
   brass kicker beneath it and the beat number holding the right rail. */
.beat .beat-head {
  display: grid; grid-template-columns: 1fr auto;
  align-items: baseline; column-gap: 1rem;
  /* Back to Courier: the global `h1, h2, h3` rule sets --font-display, and a
     Bodoni heading on a page that is pretending to be a script printout
     breaks the conceit. Uppercase bold Courier IS the slugline treatment. */
  font-family: var(--font-mono);
  font-weight: 700; letter-spacing: 0.05em;
}
/* Tracking stays tight. Courier is already a wide face, and the 0.1em/0.2em
   this first carried read as gaps between the words rather than as emphasis. */
.beat .beat-title {
  grid-column: 1; grid-row: 1;
  font-size: clamp(1.3rem, 2.4vw, 1.7rem); line-height: 1.1;
  letter-spacing: 0.02em; text-transform: uppercase; color: var(--ink);
}
.beat .beat-kicker {
  grid-column: 1 / -1; grid-row: 2;
  margin-top: 0.3rem;
  font-size: 1rem; letter-spacing: 0.01em; color: var(--brass-dim);
}
.beat .beat-head .n {
  grid-column: 2; grid-row: 1;
  font-size: clamp(1.3rem, 2.4vw, 1.7rem); letter-spacing: 0; color: var(--brass-dim);
}
.beat p.body { margin-top: 0.9rem; max-width: 60ch; font-size: 0.9rem; line-height: 1.75; }
/* Left-aligned at client request 2026-09-06 (was indented 14ch to sit under a
   screenplay dialogue margin). Still italic. */
.parenthetical { font-size: 0.85rem; font-style: italic; color: color-mix(in oklab, var(--graphite) 70%, transparent); margin-top: 0.65rem; }

.portrait {
  position: relative; border: 1px solid var(--line);
  background: color-mix(in oklab, var(--ink) 92%, var(--paper));
  aspect-ratio: 4 / 5; max-width: 420px; overflow: hidden;
}
.portrait::before { content: ""; position: absolute; inset: 14px; border: 1px solid color-mix(in oklab, var(--brass) 35%, transparent); pointer-events: none; z-index: 2; }
.portrait img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.portrait .framemark { position: absolute; inset-inline: 1.5rem; bottom: 1.25rem; z-index: 3; display: flex; justify-content: space-between; }

/* definition-style rows */
.deliverable-row {
  display: grid; gap: 1.25rem; padding-block: 2rem; border-top: 1px solid var(--line);
}
.deliverable-row:first-of-type { border-top: 0; }
.deliverable-row .role { display: block; margin-bottom: 0.6rem; font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass); }
.deliverable-row h3 { font-family: var(--font-display); font-size: var(--step-3); color: var(--bone); }
.deliverable-row p { max-width: 56ch; color: var(--smoke); }
@media (min-width: 768px) { .deliverable-row { grid-template-columns: minmax(220px, 0.9fr) 1.6fr; gap: 4rem; padding-block: 2.75rem; } }

/* =========================================================================
   AS-SEEN-IN / CREDITS
   ========================================================================= */
.proof-strip {
  background: var(--ink);
  border-top: 1px solid color-mix(in oklab, var(--brass-dim) 20%, transparent);
  border-bottom: 1px solid color-mix(in oklab, var(--brass-dim) 20%, transparent);
  padding: 1.6rem 0 2rem;
}
/* The track holds SIX copies of the logo set. The keyframe travels exactly -50%
   (= three copies, 3198px), so the frame it lands on is pixel-identical to the
   frame it started on — no seam, no gap, no reset flash. Two copies is not
   enough: -50% is then 1066px, narrower than a desktop viewport, which leaves
   dead space on the right at the wrap point. Never pauses on hover. */
.logo-marquee { overflow: hidden; margin-top: 1.4rem; }
.logo-track { display: flex; align-items: center; gap: 3rem; width: max-content; animation: logo-scroll 76s linear infinite; }
.logo-track img { height: 34px; width: auto; object-fit: contain; filter: brightness(0) invert(1); opacity: 0.6; transition: opacity 200ms ease; }
.logo-track img:hover { opacity: 1; }
.credits-text { margin-top: 1.5rem; font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.14em; color: var(--smoke); }
@keyframes logo-scroll { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }
@media (prefers-reduced-motion: reduce) { .logo-track { animation: none; flex-wrap: wrap; width: 100%; gap: 2rem; justify-content: center; } }

/* =========================================================================
   TESTIMONIALS / MEDIA
   ========================================================================= */
.stars { font-family: var(--font-mono); font-size: 15px; letter-spacing: 0.3em; color: var(--brass); margin-bottom: 1.25rem; }

/* Critical Acclaim: four testimonials in ONE grid — two across on desktop,
   one across on tablet and mobile. Every card is the same bordered
   .figure-card, so a text-only testimonial is that same card minus the video
   well and nothing else. The thin --line border reads as the card edge on all
   four. */
.quote-grid { display: grid; gap: 1.5rem; }
@media (min-width: 1024px) {
  .quote-grid { grid-template-columns: 1fr 1fr; gap: 2rem; }
  /* An odd card out (three testimonials while the fourth is pending) sits
     centred under the pair at the same width, not stranded on the left. */
  .quote-grid > :last-child:nth-child(odd) {
    grid-column: 1 / -1; justify-self: center; width: calc(50% - 1rem);
  }
}
/* Equal heights across a row: the quotes are different lengths, and one is
   still a bracket. */
.figure-card { display: flex; flex-direction: column; }
.figure-card .body { flex: 1; }
/* With no video above it the body's top border would double up on the card's
   own border. */
.figure-card .body:first-child { border-top: 0; }
.figure-card { overflow: hidden; border-radius: 3px; border: 1px solid var(--line); background: color-mix(in oklab, var(--graphite) 40%, transparent); }
.figure-card video, .figure-card .video-frame { display: block; aspect-ratio: 16/9; width: 100%; background: var(--ink); }
.figure-card .body { border-top: 1px solid var(--line); background: var(--ink); padding: clamp(1.75rem, 3vw, 2.75rem); }
/* Lovable hard-codes text-[21px] leading-snug here and text-[11.5px] on the
   caption; the conversion rounded both to the nearest scale token, drifting
   4px and 0.02px. Matched to the source rather than to the token. */
.figure-card blockquote { font-family: var(--font-display); font-size: 21px; font-weight: 500; font-style: italic; line-height: 1.375; color: var(--bone); }
.figure-card figcaption { margin-top: 1.5rem; border-top: 1px solid var(--line); padding-top: 1rem; font-family: var(--font-mono); font-size: 11.5px; text-transform: uppercase; line-height: 1.8; letter-spacing: 0.14em; color: var(--smoke); }
.figure-card figcaption b { display: block; color: var(--brass); }
.placeholder-box {
  display: flex; min-height: 10rem; align-items: center; justify-content: center;
  border: 1px dashed var(--line); padding: 1.5rem; text-align: center;
  font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase;
  line-height: 2; letter-spacing: 0.16em; color: var(--smoke);
}

.video-frame {
  position: relative; display: block; aspect-ratio: 16/9; width: 100%;
  border: 1px solid var(--line); background: var(--graphite); overflow: hidden;
}
.video-frame iframe, .video-frame img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border: 0; }

/* Click-to-load facade. Nothing is requested from YouTube (or the mp4 fetched)
   until the visitor actually clicks, so third-party JS and multi-MB media stay
   off the initial load entirely. site.js swaps the button for the real player. */
.video-facade { position: relative; }
.video-facade .video-facade-btn {
  position: relative; display: block; width: 100%; padding: 0;
  aspect-ratio: 16 / 9; overflow: hidden; cursor: pointer;
  border: 1px solid var(--line); background: var(--graphite);
}
.video-facade .video-facade-btn img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.video-facade .video-facade-btn:hover img { opacity: 0.75; }
.video-facade .video-facade-btn img { transition: opacity 200ms ease; }
.video-facade .video-facade-blank {
  position: absolute; inset: 0; display: flex; align-items: flex-end; justify-content: flex-start;
  padding: 1.25rem; background: color-mix(in oklab, var(--ink) 88%, var(--paper));
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--smoke); text-align: left;
}
.video-facade .video-facade-play {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  width: 66px; height: 66px; border: 1px solid var(--brass);
  background: color-mix(in oklab, var(--ink) 72%, transparent);
  color: var(--brass); transition: background-color 200ms ease, color 200ms ease;
}
.video-facade .video-facade-play svg { width: 20px; height: 20px; margin-left: 3px; }
.video-facade .video-facade-btn:hover .video-facade-play,
.video-facade .video-facade-btn:focus-visible .video-facade-play { background: var(--brass); color: var(--ink); }
.video-facade video, .video-facade iframe {
  display: block; width: 100%; aspect-ratio: 16 / 9;
  border: 1px solid var(--line); background: var(--ink);
}
.figure-card .video-facade .video-facade-btn { border: 0; }
/* Both testimonial clips are 4:3 (1440x1080). Forcing the default 16/9 frame
   on them either crops the speaker's head or pillarboxes with dead bars. */
.video-facade.is-4x3 .video-facade-btn,
.video-facade.is-4x3 video,
.video-facade.is-4x3 iframe { aspect-ratio: 4 / 3; }

/* =========================================================================
   FAQ ACCORDION
   Native <details>/<summary>. Full width of .shell — no max-width clamp, the
   brief asked for it to span its container.
   ========================================================================= */
.faq-list { display: grid; gap: 1px; border: 1px solid var(--line); background: var(--line); width: 100%; }
.faq-item { background: var(--ink); }
.faq-item > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  padding: clamp(1.15rem, 2.2vw, 1.6rem) clamp(1.25rem, 3vw, 2.25rem);
  cursor: pointer; list-style: none;
  transition: color 200ms ease, background-color 200ms ease;
}
/* Kill the UA disclosure triangle in both engines; .faq-mark replaces it. */
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::marker { content: ""; }
.faq-item > summary:hover { color: var(--brass); background: color-mix(in oklab, var(--paper) 3%, transparent); }
.faq-item > summary:focus-visible { outline: 2px solid var(--brass); outline-offset: -2px; }
.faq-q { font-family: var(--font-display); font-size: var(--step-2); font-weight: 500; line-height: 1.25; color: var(--bone); }
.faq-item > summary:hover .faq-q { color: inherit; }
/* Plus sign drawn from two rules so it can rotate into a minus on open. */
.faq-mark { position: relative; flex: none; width: 16px; height: 16px; }
.faq-mark::before, .faq-mark::after {
  content: ""; position: absolute; inset: 50% 0 auto 0; height: 1px;
  background: var(--brass); transition: transform 250ms ease;
}
.faq-mark::after { transform: rotate(90deg); }
.faq-item[open] .faq-mark::after { transform: rotate(0deg); }
.faq-a {
  padding: 0 clamp(1.25rem, 3vw, 2.25rem) clamp(1.35rem, 2.5vw, 1.85rem);
  color: var(--smoke); max-width: 70ch;
}

/* =========================================================================
   IN THE MEDIA — entry grid
   Two across on desktop, one on mobile. Each entry is a self-contained block:
   thumbnail (click-to-load facade or an outbound link) over its title.
   ========================================================================= */
/* Real spacing between blocks, not the 1px hairline-grid trick used elsewhere.
   That technique paints the gap colour behind the whole grid, so an odd number
   of entries left the trailing empty cell rendering as a bordered phantom
   block. Each card owns its border now, so a half-empty last row is just
   whitespace and nothing renders where there is no entry. */
/* 16px mobile / 24px desktop, per the build spec, on the same rem rhythm as
   every other gap here. justify-items: start keeps a lone card in the final row
   at its normal column width instead of stretching across it. */
.media-grid { display: grid; gap: 1rem; align-items: start; justify-items: start; }
@media (min-width: 768px) { .media-grid { grid-template-columns: repeat(2, 1fr); gap: 1.5rem; } }
.media-card { width: 100%; background: var(--ink); border: 1px solid var(--line); display: flex; flex-direction: column; }
.media-card > .video-facade, .media-card > .video-frame { border-bottom: 1px solid var(--line); }
.media-card-body { padding: clamp(1.25rem, 2.5vw, 1.75rem); display: grid; gap: 0.5rem; }
.media-card-outlet { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass); }
.media-card-date { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--smoke); }

/* =========================================================================
   CONTACT FOOTER SECTION
   ========================================================================= */
.contact-footer {
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, color-mix(in oklab, var(--brass) 8%, transparent), transparent 65%),
    color-mix(in oklab, var(--ink) 96%, var(--paper));
  border-top: 1px solid var(--line);
}
.contact-footer dt { margin-bottom: 0.15rem; font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--smoke); }
.contact-footer dd { font-size: var(--step-1); color: var(--bone); }
.contact-form { border: 1px solid var(--line); padding: clamp(1.25rem, 3vw, 2rem); }
/* One field per line. The old three-across grid squeezed Name/Email/Phone into
   thirds; on its own page the form has the room to be read top to bottom. */
.form-stack { margin-top: 1.5rem; display: grid; gap: 1.25rem; }
.field-row { display: grid; gap: 0.4rem; }
.newsletter-form { display: grid; gap: 1rem; }
.form-error {
  margin-bottom: 1.25rem; padding: 0.85rem 1rem;
  border: 1px solid var(--brass); background: color-mix(in oklab, var(--brass) 12%, transparent);
  font-family: var(--font-mono); font-size: 0.82rem; line-height: 1.6; color: var(--bone);
}
.form-error[hidden] { display: none; }
/* Inline contact pair on the homepage teaser. */
.contact-inline { display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem 3rem; }
.formlabel { display: block; font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--smoke); }
.fineprint { margin-top: 0.5rem; font-family: var(--font-mono); font-size: 11px; line-height: 1.6; color: var(--smoke); }
.fineprint a { color: var(--brass); text-decoration: underline; text-underline-offset: 2px; }

.social-links { display: flex; align-items: center; gap: 1rem; }
.social-links a { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border: 1px solid var(--line); color: var(--smoke); transition: border-color 200ms ease, color 200ms ease; }
.social-links a svg { width: 18px; height: 18px; }
.social-links a:hover { border-color: var(--brass); color: var(--brass); }

/* =========================================================================
   SITE FOOTER
   ========================================================================= */
/* Two blocks: brand on the left, link columns flush right against it. The nav
   used to be `repeat(3, 1fr)` while only two columns ever render, so a third of
   the footer was a reserved empty track. It is a flex row now — it takes the
   width it needs and no more, however many columns nav.yml produces. */
.site-footer { border-top: 1px solid var(--line); padding-block: clamp(2.75rem, 5vw, 4rem); }
.footer-grid { display: grid; gap: 2.5rem; }
@media (min-width: 768px) {
  .footer-grid { grid-template-columns: minmax(0, 1fr) auto; gap: 4rem; align-items: start; }
}

.footer-brand img { height: 1.75rem; width: auto; }
/* The tagline under the logo was removed at client request 2026-10-09, so the
   contact list now follows the logo directly and takes the gap the tagline
   used to have. */
.footer-brand .contact { margin-top: 1.1rem; font-family: var(--font-mono); font-size: 13px; color: var(--smoke); }
.footer-brand .contact a:hover { color: var(--brass); }
.footer-brand .socials { margin-top: 1.5rem; display: flex; align-items: center; gap: 1rem; }
.footer-brand .socials a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border: 1px solid var(--line); color: var(--smoke);
  transition: border-color 200ms ease, color 200ms ease;
}
.footer-brand .socials a svg { width: 17px; height: 17px; }
.footer-brand .socials a:hover { border-color: var(--brass); color: var(--brass); }

.footer-nav { display: flex; flex-wrap: wrap; gap: 2rem 4rem; }
.footer-nav > div { min-width: 8.5rem; }
.footer-title {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--brass); margin-bottom: 0.9rem;
}
.footer-nav ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.55rem; }

/* The rule owns the space around it. Nothing else adds to it. */
.footer-rule { margin-block: clamp(2rem, 4vw, 2.75rem); }

.footer-bottom { display: flex; flex-direction: column; gap: 1rem; }
@media (min-width: 768px) {
  .footer-bottom { flex-direction: row; align-items: center; justify-content: space-between; gap: 1.5rem 1.75rem; }
  .footer-bottom nav { justify-content: flex-end; }
}
/* Copyright and designer credit are one block now — the credit used to hang
   below the legal nav as a third row with its own 1.75rem margin. */
.footer-bottom-meta { display: grid; gap: 0.4rem; }
.footer-bottom .copy { font-family: var(--font-mono); font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--smoke); }
.footer-bottom nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.15rem; }
.footer-bottom nav a { font-family: var(--font-label); font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.09em; color: var(--smoke); transition: color 200ms ease; }
.footer-bottom nav a:hover { color: var(--brass); }

/* Designer credit — deliberately the quietest thing on the page. */
/* Discreet by size, spacing and placement — NOT by dimming the colour. Fading
   --smoke to 62% over --ink measured 3.49:1, which fails WCAG AA (4.5:1) and
   cost Lighthouse Accessibility 100 on every page. Full --smoke is 7.30:1. */
.footer-credit { margin: 0; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--smoke); }
.footer-credit a { color: inherit; border-bottom: 1px solid transparent; transition: color 200ms ease, border-color 200ms ease; }
.footer-credit a:hover { color: var(--brass); border-bottom-color: color-mix(in oklab, var(--brass) 45%, transparent); }

/* Termageddon's "policy settings trigger". A button, because it performs an
   action rather than navigating, painted exactly like the legal links beside
   it. Hidden until site.js confirms the CMP actually loaded — a control that
   silently does nothing is worse than no control at all. */
.uc-settings-link {
  appearance: none; background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--font-label); font-size: 11.5px;
  text-transform: uppercase; letter-spacing: 0.09em; color: var(--smoke);
  transition: color 200ms ease;
}
.uc-settings-link:hover { color: var(--brass); }

/* =========================================================================
   POLICY / LONG-FORM PAGES
   ========================================================================= */
.policy-body { max-width: 68ch; margin-inline: auto; font-size: var(--step-0); line-height: 1.8; color: color-mix(in srgb, var(--paper) 85%, transparent); }
.policy-body h2 { font-size: var(--step-3); color: var(--bone); margin-top: 2.5rem; margin-bottom: 0.75rem; }
.policy-body h3 { font-size: var(--step-2); color: var(--bone); margin-top: 1.75rem; margin-bottom: 0.5rem; }
.policy-body p + p { margin-top: 1.1rem; }
.policy-body ul, .policy-body ol { margin: 1rem 0 1rem 1.25rem; display: grid; gap: 0.5rem; }
.policy-body a { color: var(--brass); text-decoration: underline; text-underline-offset: 2px; }
.legal-placeholder { border: 1px dashed var(--line); padding: 2rem; font-family: var(--font-mono); font-size: 0.8rem; color: var(--smoke); text-align: center; line-height: 1.9; }

/* =========================================================================
   BLOG
   ========================================================================= */
.post-header { max-width: 760px; margin-inline: auto; }
.post-figure { max-width: 900px; margin: 2rem auto; border: 1px solid var(--line); overflow: hidden; }
.post-figure img { width: 100%; height: auto; display: block; }
.post-title { font-size: var(--step-6); color: var(--bone); margin-top: 1rem; }
.post-meta { margin-top: 1rem; font-family: var(--font-mono); font-size: var(--step--1); letter-spacing: 0.08em; text-transform: uppercase; color: var(--smoke); display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-items: center; }
.post-meta a { color: var(--brass); }
.post-meta .dot { color: color-mix(in srgb, var(--smoke) 55%, transparent); }

/* long-form reading measure 65–75ch, Archivo body */
.prose { max-width: 70ch; margin-inline: auto; font-family: var(--font-body); font-size: 1.06rem; line-height: 1.8; color: color-mix(in srgb, var(--paper) 90%, transparent); }
.prose > * + * { margin-top: 1.35rem; }
.prose h2 { font-family: var(--font-display); font-size: var(--step-4); color: var(--bone); margin-top: 2.5rem; }
.prose h3 { font-family: var(--font-display); font-size: var(--step-3); color: var(--bone); margin-top: 2rem; }
.prose a { color: var(--brass); text-decoration: underline; text-underline-offset: 2px; }
.prose strong { color: var(--bone); font-weight: 600; }
.prose ul, .prose ol { padding-left: 1.4rem; display: grid; gap: 0.5rem; }
.prose li { padding-left: 0.35rem; }
.prose li::marker { color: var(--brass-dim); }
.prose blockquote { border-left: 3px solid var(--brass); padding-left: 1.25rem; margin-left: 0; color: var(--bone); font-style: italic; }
.prose img { border: 1px solid var(--line); margin-block: 1.5rem; }

.author-bio { max-width: 760px; margin: 3.5rem auto 0; border-top: 1px solid var(--line); padding-top: 2rem; display: grid; gap: 1.25rem; }
@media (min-width: 640px) { .author-bio { grid-template-columns: auto 1fr; align-items: start; } }
.author-bio .avatar { width: 84px; height: 84px; border: 1px solid var(--line); background: color-mix(in oklab, var(--ink) 92%, var(--paper)); display: flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: 0.6rem; color: var(--smoke); text-align: center; }
.author-bio .name { font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.14em; color: var(--brass); font-size: var(--step--1); }
.author-bio p { margin-top: 0.5rem; color: var(--smoke); font-size: 0.98rem; }

.post-nav { max-width: 760px; margin: 2.5rem auto 0; }

/* blog index cards */
.post-list { display: grid; gap: 1px; border: 1px solid var(--line); background: var(--line); }
.post-card { background: var(--ink); display: grid; gap: 1.25rem; padding: clamp(1.5rem, 3vw, 2.25rem); }
@media (min-width: 700px) { .post-card { grid-template-columns: minmax(0, 240px) 1fr; align-items: center; } }
.post-card .thumb { aspect-ratio: 16/10; overflow: hidden; border: 1px solid var(--line); background: color-mix(in oklab, var(--ink) 92%, var(--paper)); }
.post-card .thumb img { width: 100%; height: 100%; object-fit: cover; }
.post-card h2 { font-size: var(--step-3); color: var(--bone); line-height: 1.2; }
.post-card h2 a:hover { color: var(--brass); }
.post-card .excerpt { margin-top: 0.6rem; color: var(--smoke); }
.post-card .card-meta { margin-top: 0.75rem; font-family: var(--font-mono); font-size: var(--step--1); text-transform: uppercase; letter-spacing: 0.08em; color: var(--smoke); }

.category-bar { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 2.5rem; }
.category-bar a { font-family: var(--font-mono); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.12em; padding: 0.4rem 0.9rem; border: 1px solid var(--line); color: var(--smoke); transition: border-color 200ms ease, color 200ms ease; }
.category-bar a:hover, .category-bar a[aria-current="page"] { border-color: var(--brass); color: var(--brass); }

.pagination { margin-top: 3rem; display: flex; align-items: center; justify-content: center; gap: 1rem; font-family: var(--font-mono); font-size: var(--step--1); text-transform: uppercase; letter-spacing: 0.1em; }
.pagination a { color: var(--brass); }
/* 50% smoke over ink measured 2.66:1 and failed WCAG AA. This only surfaced
   once the blog passed 10 posts and the pager actually rendered. 80% measures
   4.99:1 and still reads clearly dimmer than an active page link. */
.pagination .disabled { color: color-mix(in srgb, var(--smoke) 80%, var(--ink)); }

/* Newsletter signup block on the blog index. */
.newsletter-cta { margin-top: clamp(3rem, 6vw, 4.5rem); border: 1px solid var(--line); padding: clamp(1.5rem, 4vw, 2.5rem); max-width: 34rem; }
.newsletter-cta .footer-title { margin-bottom: 0.5rem; }
.newsletter-cta .btn { justify-self: start; }

/* =========================================================================
   AEO answer block
   ========================================================================= */
.aeo { max-width: 62ch; margin-inline: auto; font-size: var(--step-1); line-height: 1.6; color: var(--smoke); }
/* Inside a .lead block the answer paragraph is part of the run of copy, not a
   footnote to it — it takes the block's size. Standalone .aeo elsewhere
   (/about, /contact, /calendar) is unaffected. */
.lead .aeo { font-size: inherit; }

/* reveal */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.8s ease, transform 0.8s ease; }
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; } }

/* generic page main */
.page-main { padding-block: clamp(3.5rem, 6vw, 6rem); }

/* iframe embed (calendar) */
/* Transparent, not a tinted panel. The GHL booking widget paints its own
   background, so anything behind it only showed as a mismatched band while the
   iframe was still loading and around its edges once it had. */
.embed-frame { width: 100%; min-height: 720px; border: 1px solid var(--line); background: transparent; }

/* =========================================================================
   WIDOWS + ORPHANS
   Client 2026-09-04/06: no single word stranded on its own line, at any
   screen size — and text must still reach the edge of its container.

   Those two are in tension, and which property you pick decides it.

   `text-wrap: balance` EVENS the line lengths, which by definition stops them
   reaching the container edge. On a centred display heading that is exactly
   right. On a left-set card headline it is wrong, and visibly so: it broke
   "You've been told your story / is incredible your whole life." at 60% of the
   card while the card beside it ran the full width, which reads as an
   arbitrary line break.

   `text-wrap: pretty` fills each line normally and only reworks the last one.
   Full-width lines AND no stranded word. So: balance for centred headings,
   pretty for everything set left.

   Both degrade silently — a browser without them lays the text out exactly as
   it does today, so nothing regresses. Where a specific pair must never split
   at all ("highest level"), the markup carries a non-breaking space too, and
   copy that arrives through Liquid goes through the `widont` filter.
   ========================================================================= */

/* Set left — fill the width, fix only the last line. */
h1, h2, h3, h4,
.t-card, .t-card-md, .t-card-lg, .faq-q,
.card h3, .card h4, .deliverable-row h3,
.post-title, .post-card h2, .media-card-body h3,
blockquote, .figure-card blockquote, figcaption,
p, li, dd,
.card p, .deliverable-row p, .beat p.body, .parenthetical,
.prose p, .policy-body p, .post-card .excerpt {
  text-wrap: pretty;
}

/* Centred — even the lines. Below 640px these run long enough to cross the
   ~6-line cap where `balance` silently gives up (and, because it wins the
   cascade, would take `pretty` down with it), so they only get balanced from
   640px up. */
.hero-title, .hero-sub, .head-block h1, .head-block h2,
.subhead, .about-closer, .aeo, .lead > p {
  text-wrap: pretty;
}
@media (min-width: 640px) {
  .hero-title, .hero-sub, .head-block h1, .head-block h2,
  .subhead, .about-closer, .aeo, .lead > p {
    text-wrap: balance;
  }
}

/* --- Narrow screens ------------------------------------------------------
   Jeff's 2026-09-04 call tightened the brief: no stranded single words on ANY
   screen size, not just desktop. Three separate causes turned up below 640px.

   1. `text-wrap: balance` is capped at about 6 lines in Chrome and silently
      degrades to `normal` past that — and because it wins the cascade over
      `pretty`, it was DISABLING the very fix these long blocks needed. On a
      375px phone the Start Here subhead runs 8 lines and Ed's quote runs 10.
      So the blocks that can go long take `pretty` as their base and are
      promoted to `balance` only from 640px up, where they are short enough for
      balance to actually engage. Headings keep `balance` everywhere; they are
      never long enough to hit the cap. */
/* 2. "Act III · The Deliverables" is the longest slugline on the site. The two
      34px brass rules and their 14px gaps ate 96px of a 327px line and pushed
      "Deliverables" onto a line by itself. Tighten the ornament, not the
      words — the rules are decoration and the copy is not. */
@media (max-width: 479px) {
  .sluglines { gap: 9px; letter-spacing: 0.1em; }
  .sluglines::before, .sluglines.is-center::after { width: 16px; }
}
/* At 320px even that is not enough: the line needs 287px and has 272px. The
   ornament gives up the last of its width before the words do. */
@media (max-width: 359px) {
  .sluglines { gap: 7px; font-size: 0.75rem; }
  .sluglines::before, .sluglines.is-center::after { width: 12px; }
}

/* 3. Act I's H2 carries a hard <br>, so `balance` can only even out the lines
      WITHIN each half, and the second half ("The credibility isn't.") does not
      fit on one line below ~512px at --step-6 — it broke with "isn't." alone.
      Measured in-browser: this string needs about 9.0x the font size, so it
      fits while font-size <= (viewport - 48px) / 9. The ramp below is built to
      meet the unmodified --step-6 at 512px, so there is no step at the
      boundary, and it only ever applies where the widow actually occurs.
      Jeff sanctioned trading heading size for this on the call: "the fix is
      just to make the font smaller." If the smaller size reads as too quiet on
      a phone, the alternative he offered was rewording that line. */
@media (max-width: 511px) {
  .head-block h1, .head-block h2 { font-size: clamp(1.75rem, 10.5vw - 0.32rem, 3.2rem); }
}
/* Act I's H2 is the one heading a wrap strategy cannot rescue: it carries a
   hard <br>, so `balance` can only even the lines WITHIN each half, and the
   second half ("The credibility isn't.") has three words — if it does not hold
   one line, "isn't." is stranded and there is no better break available.

   Measured in-browser at 375, 512 and 640: this string occupies 9.84x its font
   size, the same ratio at all three. So it fits while
       font-size <= (viewport - 48px) / 9.84
   and the unramped --step-6 only satisfies that from about 591px up. The ramp
   below carries it from 320 to 640 with a 3% margin. An earlier version of this
   rule was calibrated at 9.01 from a probe that did not copy the weight and
   tracking, which is why it stopped short at 511px and let the widow back in
   between 512 and 590. */
@media (max-width: 640px) {
  #story .head-block h2 { font-size: clamp(1.6rem, 9.87vw - 4.74px, 3.4rem); }
}

/* =========================================================================
   TERMAGEDDON POLICY EMBED
   The policy is fetched at runtime and injected as innerHTML, so none of this
   markup exists at build time.

   SPECIFICITY — why every selector below starts with `#main`.
   The embed ships its own reset: `font: revert; margin: revert; padding: revert`
   applied to EIGHTY-ONE selectors of the form `#<policy-key> h2`,
   `#<policy-key> p`, `#<policy-key> ul`. That is (1,0,1) — one id, one element.
   A plain `.policy-embed h2` is (0,1,1) and loses, which is why a first pass
   came out with the right colours (the reset does not touch colour) but the
   browser's default typography: `font: revert` hands h2 straight back to the
   UA's 1.5em bold Archivo. `#main` in front makes it (1,1,1) — same id count,
   one more class — so it wins. Specificity arithmetic, not a stray selector,
   and it beats carpet-bombing the file with !important.

   Everything the reset does NOT touch (colour, border, background) would work
   without the prefix; the prefix is applied uniformly anyway so the next person
   editing this block does not have to know which is which.
   ========================================================================= */
#main .policy-embed {
  /* Fills the shell, so the policy is exactly as wide as the header and the
     footer — verified: left edge 184px, right edge 1256px, identical to both
     at 1440. Client 2026-09-06: "the full container is filled." */
  width: 100%;
  margin-top: 2.5rem;
  font-family: var(--font-body);
  font-size: 0.98rem;
  line-height: 1.75;
  color: color-mix(in srgb, var(--paper) 88%, transparent);
}

/* The sidebar ships `position: sticky; top: 1em`, which parks it underneath our
   own sticky header. 5.5rem is the same clearance html{scroll-padding-top}
   already uses for in-page anchors, so the two agree. */
#main .policy-embed .tg-floating-toc-sidebar {
  top: 5.5rem;
  max-height: calc(100vh - 7rem);
  flex-basis: 240px;
  padding-right: 1.5rem;
  border-right: 1px solid var(--line);
}
#main .policy-embed .tg-floating-toc-layout { gap: 3rem; }
@media (max-width: 900px) {
  /* flex-direction MUST flip with the sidebar. The embed's own stacking media
     query fires at a narrower width than this one, so setting the sidebar to
     width:100% here without also turning the layout into a column left it as a
     full-width flex item in a ROW — which squeezed the content column to
     roughly zero and pushed the accordions off-screen, giving the page 344px of
     horizontal scroll between their breakpoint and this one. */
  #main .policy-embed .tg-floating-toc-layout { flex-direction: column; gap: 2rem; }
  #main .policy-embed .tg-floating-toc-sidebar {
    position: static; max-height: none; flex-basis: auto; width: 100%;
    padding-right: 0; padding-bottom: 1.5rem;
    border-right: 0; border-bottom: 1px solid var(--line);
  }
}
/* Long unbroken strings in legal copy (URLs, email addresses, statute names)
   have no break opportunity and will push a narrow column sideways. */
#main .policy-embed { overflow-wrap: anywhere; }

/* Table of contents */
#main .policy-embed .tg-toc-heading {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass);
  margin: 0 0 1rem;
}
#main .policy-embed .tg-toc-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.6rem; }
#main .policy-embed .tg-toc-item { font-size: 0.85rem; line-height: 1.45; }
#main .policy-embed .tg-toc-link { color: var(--smoke); text-decoration: none; }
#main .policy-embed .tg-toc-link:hover { color: var(--brass); }
#main .policy-embed .tg-toc-divider { border: 0; border-top: 1px solid var(--line); margin-block: 1rem; }

/* Headings */
#main .policy-embed h2,
#main .policy-embed .tpt-section-heading {
  font-family: var(--font-display); font-size: var(--step-3); font-weight: 500;
  color: var(--bone); line-height: 1.2;
  margin: 2.75rem 0 0.75rem;
}
#main .policy-embed h3 {
  font-family: var(--font-display); font-size: var(--step-1); font-weight: 500;
  color: var(--bone); line-height: 1.3; margin: 0;
}
#main .policy-embed h4 {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass-dim);
  margin: 1rem 0 0.35rem;
}
#main .policy-embed .tg-last-updated-date {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--smoke);
}
#main .policy-embed p { margin: 0 0 0.9rem; }
#main .policy-embed a { color: var(--brass); text-decoration: underline; text-underline-offset: 2px; }
#main .policy-embed ul,
#main .policy-embed ol { margin: 0.9rem 0 0.9rem 1.25rem; padding: 0; display: grid; gap: 0.4rem; }
#main .policy-embed li::marker { color: var(--brass-dim); }
#main .policy-embed strong, #main .policy-embed b { color: var(--bone); font-weight: 600; }

/* Accordions — native <details>/<summary>, so this is presentation only. */
#main .policy-embed .accordion { border-top: 1px solid var(--line); }
#main .policy-embed .accordion:last-of-type { border-bottom: 1px solid var(--line); }
#main .policy-embed .accordion-summary {
  cursor: pointer; padding: 0.9rem 0; margin: 0;
  list-style: none; display: flex; align-items: baseline; gap: 0.75rem;
}
#main .policy-embed .accordion-summary::-webkit-details-marker { display: none; }
#main .policy-embed .accordion-summary::marker { content: ""; }
#main .policy-embed .accordion-summary::before {
  content: "+"; flex: none;
  font-family: var(--font-mono); font-weight: 700; color: var(--brass);
}
#main .policy-embed details[open] > .accordion-summary::before { content: "\2212"; }
/* Their own hover fill is a light grey that all but vanishes on --ink. */
#main .policy-embed .accordion-summary:hover { background-color: color-mix(in oklab, var(--paper) 5%, transparent); }
#main .policy-embed .accordion-content,
#main .policy-embed .accordion-section-content { padding-bottom: 1rem; }

/* Tables already scroll inside .table-responsive; give them site borders. */
#main .policy-embed table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
#main .policy-embed th,
#main .policy-embed td { border: 1px solid var(--line); padding: 0.6rem 0.8rem; text-align: left; }
#main .policy-embed th { color: var(--bone); font-weight: 600; }
