/* ==========================================================================
   THE PATH — DESIGN TOKENS + CORE COMPONENTS
   ==========================================================================

   Self-contained stylesheet for The Path. Everything here is namespaced
   --tp-* and scoped under .thepath so it can be lifted to a standalone
   site by copying this file, thepath.js and /static/thepath/.

   IMPORTANT — scoping. The host site (colour) declares --color-*, --font-*
   and --bs-* on a global :root and flips them via [data-theme]. The Path
   must not inherit that. Tokens live on .thepath (not :root) and the
   surface colours are set explicitly, so the host's theme toggle cannot
   repaint this page.

   Source of truth: static/thepath/design system/the_path_brand_guide.pdf
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. TYPEFACES

   Brand guide specifies Neue Haas Grotesk. The new standalone site ships
   the provided Neue Haas Display files from /static/thepath/web/font/.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Neue Haas Display";
  src: url("/static/thepath/web/font/NeueHaasDisplay-Roman.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Neue Haas Display";
  src: url("/static/thepath/web/font/NeueHaasDisplay-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Neue Haas Display";
  src: url("/static/thepath/web/font/NeueHaasDisplay-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}


/* --------------------------------------------------------------------------
   2. TOKENS
   -------------------------------------------------------------------------- */

.thepath {
  /* --- Palette ------------------------------------------------------------
     Guide balance: 60% Paper / 20% Ink / 10% Coral / 10% supporting.
     Coral is THE accent — one focal accent per composition.
     Sage / Blue / Aubergine / Ochre are for data differentiation,
     not decoration. Guardrail: never use all colours at once.          */
  --tp-ink:            #171717;
  --tp-paper:          #F5F1E9;
  --tp-stone:          #C8C1B7;
  --tp-coral:          #F35F45;
  /* The shadow side of the Coral, from the about plate's artwork. */
  --tp-coral-deep:     #DD5543;
  --tp-sage:           #9EAA91;
  --tp-blue:           #8DA5B2;
  --tp-aubergine:      #4E3F4D;
  --tp-ochre:          #D5A94E;

  /* Derived — rgb channels for alpha compositing (overlays, rules) */
  --tp-ink-rgb:        23, 23, 23;
  --tp-paper-rgb:      245, 241, 233;
  --tp-coral-rgb:      243, 95, 69;

  /* Stone at 40% over Paper. Used as the tonal step between Paper and Ink
     sections: it keeps the descent without giving a long section the full
     weight of solid Stone.

     Declared twice on purpose — the hex is the fallback for engines
     without color-mix, and the second declaration derives the same value
     from the tokens so it tracks any palette change. */
  --tp-stone-tint:     #E3DED5;
  --tp-stone-tint:     color-mix(in srgb, var(--tp-stone) 40%, var(--tp-paper));

  /* Washes: the palette's colours taken most of the way to Paper, for large
     shapes that sit behind reading. Pale enough to set text over, so they can
     cross copy rather than having to avoid it. */
  --tp-sage-wash:      #DDE0D4;
  --tp-sage-wash:      color-mix(in srgb, var(--tp-sage) 30%, var(--tp-paper));
  --tp-blue-wash:      #D9DFE0;
  --tp-blue-wash:      color-mix(in srgb, var(--tp-blue) 30%, var(--tp-paper));
  --tp-coral-wash:     #F7DDD2;
  --tp-coral-wash:     color-mix(in srgb, var(--tp-coral) 16%, var(--tp-paper));

  /* A warmer, deeper Paper. Mixed from the two grounds either side of it
     rather than picked, so it stays in the family if either moves. */
  --tp-cream:          #EEE9E1;
  --tp-cream:          color-mix(in srgb, var(--tp-stone-tint) 42%, var(--tp-paper));

  /* One step lighter again, for shapes that lift off the Cream ground. Paper
     alone is only a few values above it, so this goes past Paper toward the
     white the card surface already uses. */
  --tp-cream-lift:     #F7F4EE;
  --tp-cream-lift:     color-mix(in srgb, var(--tp-paper) 78%, #FFFFFF);

  /* --- Semantic surface roles --------------------------------------------
     Set per-surface by the .tp-surface--* modifiers below. Everything
     downstream (type, rules, icons, graphics) reads these, never the
     raw palette — so a section flips light/dark by changing four values. */
  --tp-bg:             var(--tp-paper);
  --tp-fg:             var(--tp-ink);
  --tp-fg-muted:       rgba(var(--tp-ink-rgb), 0.62);
  --tp-rule:           rgba(var(--tp-ink-rgb), 0.16);

  /* What a warning is drawn in. Coral on every ground it reads on;
     surfaces where it does not override this. */
  --tp-alert:          var(--tp-coral);

  /* A form control's edge, which has to be findable — 3:1 against its
     ground, per WCAG 1.4.11. Deliberately heavier than --tp-rule, which
     is for hairline dividers and is allowed to whisper. */
  --tp-field-line:     rgba(var(--tp-ink-rgb), 0.50);

  /* Structural colour inside brand SVGs. The cleaned graphics in
     /static/thepath/web/ are surface-agnostic: they read these two,
     so the same file works on Paper or Ink.

     NOTE: these are re-declared inside every .tp-surface--* modifier
     rather than only here. Custom properties inherit their *substituted*
     value, so `var(--tp-fg)` would be resolved once at this level and
     frozen — a surface changing --tp-fg further down would not update it,
     and ink-on-ink graphics would render invisible. */
  --tp-graphic-fg:     var(--tp-fg);
  --tp-graphic-bg:     var(--tp-bg);

  /* --- Typography ---------------------------------------------------------
     Guide scale (print pt) mapped to a responsive web scale. The leading
     percentages are preserved exactly — that tight display leading is
     what makes the system read as editorial rather than corporate. */
  --tp-font-display:   "Neue Haas Display", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --tp-font-text:      "Neue Haas Display", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --tp-font-ui:        "Neue Haas Display", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --tp-weight-roman:   400;
  --tp-weight-medium:  500;
  --tp-weight-bold:    700;

  /* H1  — Display Bold, 48–64pt, 90–96% leading */
  --tp-size-h1:        clamp(2.75rem, 1.55rem + 5.2vw, 4.5rem);
  --tp-lh-h1:          0.94;
  --tp-tracking-h1:    -0.022em;

  /* H2  — Display Bold, 28–36pt, 95–100% */
  --tp-size-h2:        clamp(1.875rem, 1.35rem + 2.4vw, 2.75rem);
  --tp-lh-h2:          0.98;
  --tp-tracking-h2:    -0.018em;

  /* H3  — Display Medium, 18–22pt, 100%
     Guide says 100%; using 1.1 on web so multi-line subheads don't
     collide. Set to 1 if you want it print-exact. */
  /* The gap between h2 and h3 is wide, and a line that has to carry weight
     without competing with a heading lands in it. */
  --tp-size-h2-sm:     clamp(1.375rem, 1.1rem + 1.15vw, 2.125rem);
  --tp-lh-h2-sm:       1.18;

  --tp-size-h3:        clamp(1.125rem, 1.02rem + 0.5vw, 1.375rem);
  --tp-lh-h3:          1.1;
  --tp-tracking-h3:    -0.01em;

  /* Body — Text Roman, 10.5–12pt, 135–150%.
     Set a step larger than the previous sans body: a serif at the same
     nominal size reads smaller, and wants slightly more leading. */
  --tp-size-body:      clamp(1.0625rem, 1.01rem + 0.22vw, 1.125rem);
  --tp-lh-body:        1.62;

  --tp-size-body-lg:   clamp(1.1875rem, 1.1rem + 0.38vw, 1.375rem);
  --tp-lh-body-lg:     1.52;

  /* A step between body and caption, for descriptions inside a card, where
     full body size competes with the card's own heading. */
  --tp-size-body-sm:   clamp(0.9375rem, 0.9rem + 0.16vw, 1rem);
  --tp-lh-body-sm:     1.55;

  /* Caption — Text Roman, 8–9pt, 130% */
  --tp-size-caption:   0.8125rem;
  --tp-lh-caption:     1.4;

  /* Label — Display Medium, 8–10pt, uppercase, tracked.
     Guide states "+4 to +8 tracking". In Illustrator units that is
     0.004–0.008em, which is invisible at label sizes — almost certainly
     shorthand for +40/+80. Using 0.06em, which matches how the labels
     actually appear in the guide. Confirm with the designer. */
  --tp-size-micro:     0.625rem;
  --tp-size-label:     0.75rem;
  --tp-lh-label:       1.2;
  --tp-tracking-label: 0.06em;

  /* Measure — "short introductory copy sits in a narrow measure" */
  --tp-measure:        62ch;
  --tp-measure-narrow: 42ch;

  /* --- Spacing scale ------------------------------------------------------
     4px base. Use these only — no arbitrary values in markup. */
  --tp-space-3xs:      0.25rem;   /*  4 */
  --tp-space-2xs:      0.5rem;    /*  8 */
  --tp-space-xs:       0.75rem;   /* 12 */
  --tp-space-sm:       1rem;      /* 16 */
  --tp-space-md:       1.5rem;    /* 24 */
  --tp-space-lg:       2rem;      /* 32 */
  --tp-space-xl:       3rem;      /* 48 */
  --tp-space-2xl:      4rem;      /* 64 */
  --tp-space-3xl:      6rem;      /* 96 */
  --tp-space-4xl:      8rem;      /* 128 */

  /* Vertical section rhythm — every section uses this, no exceptions */
  --tp-section-y:      clamp(4rem, 8vw, 8rem);
  --tp-section-y-tight: clamp(2.5rem, 5vw, 4.5rem);

  /* --- Layout -------------------------------------------------------------
     Guide: page margins 6–8% of page width. */
  --tp-container:      1240px;
  --tp-container-narrow: 860px;
  --tp-container-wide: 1400px;
  --tp-gutter:         clamp(1.25rem, 6vw, 5.5rem);
  --tp-grid-gap:       clamp(1.5rem, 3vw, 2.5rem);

  /* --- Radius / shadow / motion ------------------------------------------
     The system is flat and editorial. Radius is for cards only; shadow
     is near-absent by design. */
  --tp-radius-none:    0;
  --tp-radius-sm:      2px;
  --tp-radius-md:      6px;
  --tp-radius-card:    16px;
  --tp-radius-pill:    999px;

  --tp-shadow-sm:      0 1px 2px rgba(var(--tp-ink-rgb), 0.06);
  --tp-shadow-md:      0 8px 24px -12px rgba(var(--tp-ink-rgb), 0.18);

  --tp-duration-fast:  160ms;
  --tp-duration:       280ms;
  --tp-duration-slow:  600ms;
  --tp-ease:           cubic-bezier(0.22, 0.61, 0.36, 1);
  --tp-ease-out:       cubic-bezier(0.16, 1, 0.3, 1);

  /* Stroke weight for brand geometry — "use thin geometry" */
  --tp-stroke:         1.5px;
  --tp-stroke-thick:   3px;
}


/* --------------------------------------------------------------------------
   3. ROOT / RESET
   -------------------------------------------------------------------------- */

.thepath {
  background: var(--tp-bg);
  color: var(--tp-fg);
  font-family: var(--tp-font-text);
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);
  font-weight: var(--tp-weight-roman);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

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

/* Kill UA margins on elements we position with the spacing scale.
   These defaults (figure's 0 0 16px, ul/ol's 1em block margins) otherwise
   leak unmanaged spacing in and knock absolutely-positioned siblings —
   like the hero thread — out of alignment with their content. */
.thepath :where(figure, blockquote, dl, dd, ul, ol, p) { margin: 0; }

/* No orphans. `pretty` keeps a single word off the last line of body copy;
   headings use `balance` (set with the type scale) so their lines are of
   comparable length rather than one long line and a stray word.
   Applied here rather than per-component so new copy inherits it. */
.thepath :where(p, li, figcaption, dd) { text-wrap: pretty; }

/* Layout lists carry no marker or indent; content lists keep theirs. */
.thepath :where(ul, ol)[role="list"] {
  padding-inline-start: 0;
  list-style: none;
}

.thepath img,
.thepath svg { max-width: 100%; }

.thepath img {
  display: block;
  height: auto;
}


/* --------------------------------------------------------------------------
   4. SURFACES
   Carry the 60/20/10/10 balance. Paper is the default and should
   dominate; Ink is the punctuation.
   -------------------------------------------------------------------------- */

.tp-surface { background: var(--tp-bg); color: var(--tp-fg); }

.tp-surface--paper {
  --tp-bg:         var(--tp-paper);
  --tp-fg:         var(--tp-ink);
  --tp-fg-muted:   rgba(var(--tp-ink-rgb), 0.62);
  --tp-rule:       rgba(var(--tp-ink-rgb), 0.16);
  --tp-graphic-fg: var(--tp-ink);
  --tp-graphic-bg: var(--tp-paper);
}

.tp-surface--ink {
  --tp-bg:         var(--tp-ink);
  --tp-fg:         var(--tp-paper);
  --tp-fg-muted:   rgba(var(--tp-paper-rgb), 0.66);
  --tp-rule:       rgba(var(--tp-paper-rgb), 0.20);
  --tp-graphic-fg: var(--tp-paper);
  --tp-graphic-bg: var(--tp-ink);
  --tp-field-line: rgba(var(--tp-paper-rgb), 0.38);
}

.tp-surface--stone {
  --tp-bg:         var(--tp-paper);
  --tp-fg:         var(--tp-ink);
  --tp-fg-muted:   rgba(var(--tp-ink-rgb), 0.68);
  --tp-rule:       rgba(var(--tp-ink-rgb), 0.22);
  --tp-graphic-fg: var(--tp-ink);
  --tp-graphic-bg: var(--tp-paper);
}

/* The lighter step. Same role as Stone, less weight over a long section. */
/* Cream — Paper's warmer sibling. Used where a plate needs to sit off white
   without going as far as the Stone tint. Foregrounds are Paper's, since the
   two grounds are close enough to share them. */
.tp-surface--cream {
  --tp-bg:         var(--tp-cream);
  --tp-fg:         var(--tp-ink);
  --tp-fg-muted:   rgba(var(--tp-ink-rgb), 0.62);
  --tp-rule:       rgba(var(--tp-ink-rgb), 0.16);
  --tp-graphic-fg: var(--tp-ink);
  --tp-graphic-bg: var(--tp-cream);
}

.tp-surface--stone-tint {
  --tp-bg:         var(--tp-paper);
  --tp-fg:         var(--tp-ink);
  --tp-fg-muted:   rgba(var(--tp-ink-rgb), 0.64);
  --tp-rule:       rgba(var(--tp-ink-rgb), 0.18);
  --tp-graphic-fg: var(--tp-ink);
  --tp-graphic-bg: var(--tp-paper);
}

/* Dusty Blue — the hero's lower half, reused to close the page on the
   colour it opened on. Foreground is Ink, not Paper: Paper on this ground
   measures 2.3:1, Ink measures 7.0:1. */
.tp-surface--blue {
  --tp-bg:         var(--tp-blue);
  --tp-fg:         var(--tp-ink);
  /* 0.78, not the 0.62 the lighter grounds use: composited over this blue
     that lands at 4.7:1, where 0.72 would sit just under the 4.5 line. */
  --tp-fg-muted:   rgba(var(--tp-ink-rgb), 0.78);
  --tp-rule:       rgba(var(--tp-ink-rgb), 0.26);
  --tp-graphic-fg: var(--tp-ink);
  --tp-graphic-bg: var(--tp-blue);

  /* Coral against this blue is 1.25:1. It holds as a large graphic mark,
     but it cannot carry a warning, so alerts fall back to Ink here. */
  --tp-alert:      var(--tp-ink);

  /* Mid-tone grounds are the hard case for an edge: 0.26 lands at 1.6:1
     and the fields disappear into the blue. 0.60 clears 3:1. */
  --tp-field-line: rgba(var(--tp-ink-rgb), 0.60);
}

/* Aubergine — a dark ground that is not Ink. The close needs the weight of
   a dark surface, but Ink is already spent on discovery, and this keeps
   Coral and Dusty Blue legible in a way Ink does and Blue does not. */
.tp-surface--aubergine {
  --tp-bg:         var(--tp-aubergine);
  --tp-fg:         var(--tp-paper);
  --tp-fg-muted:   rgba(var(--tp-paper-rgb), 0.72);
  --tp-rule:       rgba(var(--tp-paper-rgb), 0.22);
  --tp-graphic-fg: var(--tp-paper);
  --tp-graphic-bg: var(--tp-aubergine);
  --tp-field-line: rgba(var(--tp-paper-rgb), 0.45);

  /* Coral clears 3:1 here, so it can still mark a field or a focus ring,
     but at 3.05:1 it is under the 4.5 a sentence needs. Warning text is
     set in Paper instead and carries its weight from the medium cut. */
  --tp-alert:      var(--tp-paper);
}

/* Card surface — the guide's rounded white panels on Paper */
.tp-surface--card {
  --tp-bg:         #FFFFFF;
  --tp-fg:         var(--tp-ink);
  --tp-fg-muted:   rgba(var(--tp-ink-rgb), 0.62);
  --tp-rule:       rgba(var(--tp-ink-rgb), 0.12);
  --tp-graphic-fg: var(--tp-ink);
  --tp-graphic-bg: #FFFFFF;
}


/* --------------------------------------------------------------------------
   5. LAYOUT
   -------------------------------------------------------------------------- */

.tp-section {
  padding-block: var(--tp-section-y);
  background: var(--tp-bg);
  color: var(--tp-fg);
}

.tp-section--tight { padding-block: var(--tp-section-y-tight); }

/* --- Section wash ---------------------------------------------------------
   A brand graphic held behind a whole section, fixed to the viewport so the
   content scrolls over it. Set --tp-wash-image on the section and the rest
   follows; --tp-wash-opacity tunes how far back it sits.

   The graphic is loaded through url() rather than inlined, because a fixed
   background needs to be a background. That means the file's custom
   properties do not resolve and its FALLBACK colours are what render, so
   only use this with a graphic whose fallbacks already suit the surface.

   background-attachment: fixed is ignored on iOS, where this degrades to a
   normal scrolling background. That is the intended fallback, not a bug. */
.tp-section--wash { position: relative; isolation: isolate; }

.tp-section--wash > .tp-container { position: relative; z-index: 1; }

.tp-section--wash::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;

  background-image: var(--tp-wash-image);
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
  background-attachment: fixed;

  opacity: var(--tp-wash-opacity, 0.09);
}

/* A fixed background repaints the whole viewport on every scroll frame.
   Below the desktop breakpoint it is pinned instead, and under reduced
   motion it stops travelling altogether. */
@media (max-width: 899.98px) {
  .tp-section--wash::before { background-attachment: scroll; }
}

@media (prefers-reduced-motion: reduce) {
  .tp-section--wash::before { background-attachment: scroll; }
}

/* --- Corner graphic -------------------------------------------------------
   A small brand graphic parked in a section's corner, in its own colours
   rather than the surface's. Decorative: aria-hidden in the markup and
   inert to the pointer here.

   Sized to sit inside the section's vertical padding so it cannot reach
   the content, and withdrawn below 1100px where that padding and the
   gutter are both too tight to hold it. */
.tp-corner {
  position: absolute;
  z-index: 0;
  width: var(--tp-corner-size, clamp(7rem, 10vw, 11rem));
  pointer-events: none;
  display: none;
}

.tp-corner svg { display: block; width: 100%; height: auto; }

.tp-corner--xs { --tp-corner-size: clamp(4.5rem, 5.5vw, 6.25rem); }
.tp-corner--sm { --tp-corner-size: clamp(5.5rem, 7vw, 7.75rem); }
.tp-corner--md { --tp-corner-size: clamp(6.5rem, 8.5vw, 9.25rem); }
.tp-corner--soft {
  opacity: 0.48;
  filter: saturate(0.85);
}

.tp-corner--top-right    { inset-block-start: var(--tp-space-lg); inset-inline-end: var(--tp-space-lg); }
.tp-corner--top-left     { inset-block-start: var(--tp-space-lg); inset-inline-start: var(--tp-space-lg); }
.tp-corner--bottom-right { inset-block-end: var(--tp-space-lg);   inset-inline-end: var(--tp-space-lg); }
.tp-corner--bottom-left  { inset-block-end: var(--tp-space-lg);   inset-inline-start: var(--tp-space-lg); }

@media (min-width: 1100px) {
  .tp-corner { display: block; }
}
.tp-section--flush-top { padding-block-start: 0; }
.tp-section--flush-bottom { padding-block-end: 0; }

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

.tp-container--narrow { max-width: var(--tp-container-narrow); }
.tp-container--full { max-width: none; }

/* Grid — the guide favours asymmetry, so these are starting points,
   not a straitjacket. Collapse to one column on small screens. */
.tp-grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .tp-grid--2 { grid-template-columns: repeat(2, 1fr); }
  .tp-grid--3 { grid-template-columns: repeat(2, 1fr); }
  .tp-grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 960px) {
  .tp-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .tp-grid--4 { grid-template-columns: repeat(4, 1fr); }
  /* Asymmetric splits — editorial, not 50/50 */
  .tp-grid--asym    { grid-template-columns: 5fr 7fr; }
  .tp-grid--asym-rev { grid-template-columns: 7fr 5fr; }
}

.tp-stack > * + * { margin-block-start: var(--tp-flow, var(--tp-space-md)); }
.tp-stack--tight { --tp-flow: var(--tp-space-sm); }
.tp-stack--loose { --tp-flow: var(--tp-space-lg); }


/* --------------------------------------------------------------------------
   6. TYPOGRAPHY
   -------------------------------------------------------------------------- */

.tp-h1, .tp-h2, .tp-h3 {
  font-family: var(--tp-font-display);
  color: var(--tp-fg);
  margin: 0;
  text-wrap: balance;
}

/* A coral cursor closes every title. Generated rather than typed, so it
   cannot be missed off a heading or picked up by a screen reader, and it
   stays on the last line because it sits inside the text flow.

   Static, not blinking: the eyebrow's cursor is the one meant to draw the
   eye, and several blinking at once would compete. Add the tp-blink
   animation here if you want them all live. */
.tp-h1::after,
.tp-h2::after {
  content: "_";
  color: var(--tp-coral);
  margin-inline-start: 0.06em;
}

.tp-h1 {
  font-size: var(--tp-size-h1);
  line-height: var(--tp-lh-h1);
  letter-spacing: var(--tp-tracking-h1);
  font-weight: var(--tp-weight-bold);
}

.tp-h2 {
  font-size: var(--tp-size-h2);
  line-height: var(--tp-lh-h2);
  letter-spacing: var(--tp-tracking-h2);
  font-weight: var(--tp-weight-bold);
}

.tp-h3 {
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-body {
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);
  max-width: var(--tp-measure);
  margin: 0;
  text-wrap: pretty;
}

.tp-body--lead {
  font-size: var(--tp-size-body-lg);
  line-height: var(--tp-lh-body-lg);
}

.tp-body--narrow { max-width: var(--tp-measure-narrow); }

.tp-caption {
  font-size: var(--tp-size-caption);
  line-height: var(--tp-lh-caption);
  color: var(--tp-fg-muted);
  margin: 0;
}

/* Section label — "SECTION 02" style, with the guide's short rule under it */
.tp-label {
  display: block;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  font-weight: var(--tp-weight-medium);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg);
  margin: 0;
}

.tp-label--ruled::after {
  content: "";
  display: block;
  width: 3.5rem;
  height: 1px;
  background: var(--tp-fg);
  margin-block-start: var(--tp-space-2xs);
}

/* --- Wordmark eyebrow -----------------------------------------------------
   thePath:<word>, set as type so the glyphs share the text baseline and
   nothing needs aligning by hand. Casing is preserved, and the colon plus
   whatever follows it takes the Coral. Used by the hero and by section
   headers, so there is one implementation rather than two. */
.tp-eyebrow {
  display: inline-flex;
  align-items: baseline;
  margin: 0;
  font-family: var(--tp-font-ui);   /* the wordmark stays sans */
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  text-transform: none;
  color: var(--tp-fg);
}

.tp-eyebrow__mark { color: var(--tp-coral); }

/* The hero's tagline, set after the mark. Coral across the whole phrase
   would shout; it sits in the foreground at the roman weight so the
   wordmark still leads and the tagline reads as the line under it. */
.tp-eyebrow__note {
  margin-inline-start: 0.45em;
  font-weight: var(--tp-weight-roman);
  color: var(--tp-fg-muted);
}

.tp-eyebrow__cursor { animation: tp-blink 1.15s steps(1, end) infinite; }

/* Smaller in the hero. It sits under a 7rem headline there rather than a
   section heading, so at the shared size it read as a second line of copy
   instead of as a label on the page. The note scales with it, since that is
   sized in ems off this. */
.tp-hero .tp-eyebrow { font-size: 1rem; }

@media (prefers-reduced-motion: reduce) {
  .tp-eyebrow__cursor { animation: none; }
}

/* Emphasis — the guide sets the second line of a headline in Coral */
.tp-accent { color: var(--tp-coral); }
.tp-muted  { color: var(--tp-fg-muted); }

/* Large number — "a large number gets room to breathe" */
.tp-figure {
  font-family: var(--tp-font-display);
  font-size: clamp(3.5rem, 2rem + 7vw, 7rem);
  line-height: 0.86;
  letter-spacing: -0.03em;
  font-weight: var(--tp-weight-bold);
  color: var(--tp-coral);
  margin: 0;
}

.tp-rule {
  border: 0;
  border-block-start: 1px solid var(--tp-rule);
  margin-block: var(--tp-space-lg);
}


/* --------------------------------------------------------------------------
   7. THE :_ DEVICE
   "Not decoration — the smallest expression of the brand idea."
   Guardrail: do not attach it to every sentence.
   -------------------------------------------------------------------------- */

/* Proportions are taken from the logo's own geometry rather than guessed,
   so the CSS mark and the wordmark's :_ read as the same device. Measured
   off web/logo.svg against the colon dot's diameter:
     colon span 2.76x · gap 0.33x · bar width 3.24x · bar height 1x
   Everything derives from --tp-dot, so the mark scales as one unit. */
.tp-mark {
  --tp-dot: 0.17em;

  display: inline-flex;
  align-items: flex-end;
  gap: calc(var(--tp-dot) * 0.33);
  vertical-align: baseline;
  color: var(--tp-coral);
}

.tp-mark__colon {
  display: inline-flex;
  flex-direction: column;
  justify-content: space-between;
  height: calc(var(--tp-dot) * 2.76);
}

.tp-mark__colon::before,
.tp-mark__colon::after {
  content: "";
  width: var(--tp-dot);
  height: var(--tp-dot);
  border-radius: 50%;
  background: currentColor;
}

.tp-mark__bar {
  width: calc(var(--tp-dot) * 3.24);
  height: var(--tp-dot);
  background: currentColor;
}

/* Cursor variant — the bar blinks. Used sparingly, hero only. */
.tp-mark--cursor .tp-mark__bar {
  animation: tp-blink 1.15s steps(1, end) infinite;
}

@keyframes tp-blink {
  0%, 45%  { opacity: 1; }
  50%, 95% { opacity: 0; }
  100%     { opacity: 1; }
}


/* --------------------------------------------------------------------------
   8. LOGO
   -------------------------------------------------------------------------- */

.tp-logo {
  display: inline-block;
  color: var(--tp-fg);
  line-height: 0;
}

.tp-logo__svg {
  display: block;
  width: auto;
  height: var(--tp-logo-height, 2rem);
}

/* Reverse lockup — Coral :_ on Ink, per the guide's reverse treatment.
   The preferred lockup keeps the mark the same colour as the wordmark. */
.tp-logo--accent .tp-logo__mark { fill: var(--tp-coral); }


/* --------------------------------------------------------------------------
   9. ICONS
   Cleaned icons inherit colour via currentColor and keep Coral as the
   focal accent. Must be INLINED (not <img>) for currentColor to apply.
   -------------------------------------------------------------------------- */

.tp-icon {
  display: inline-flex;
  color: var(--tp-fg);
  width: var(--tp-icon-size, 3rem);
  height: var(--tp-icon-size, 3rem);
  flex: none;
}

.tp-icon__svg { width: 100%; height: 100%; display: block; }

.tp-icon--sm { --tp-icon-size: 1.75rem; }
.tp-icon--lg { --tp-icon-size: 4.5rem; }


/* --------------------------------------------------------------------------
   10. GRAPHICS
   Conceptual Geometric illustrations. Surface-agnostic — they read
   --tp-graphic-fg / --tp-graphic-bg, which the surface sets.
   -------------------------------------------------------------------------- */

.tp-graphic {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;   /* all graphics are 1200x800 */
}

.tp-graphic__svg { width: 100%; height: 100%; display: block; }

/* Force a graphic to render inverted regardless of its surface */
.tp-graphic--on-ink {
  --tp-graphic-fg: var(--tp-paper);
  --tp-graphic-bg: var(--tp-ink);
}

.tp-graphic--on-paper {
  --tp-graphic-fg: var(--tp-ink);
  --tp-graphic-bg: var(--tp-paper);
}


/* --------------------------------------------------------------------------
   11. PHOTOGRAPHY

   Four independent layers, so any one can be replaced without touching
   the others:

     1. photo    — a plain <img>, swap the filename and you're done
     2. mask     — CSS clip-path, NOT a pre-cut PNG
     3. duotone  — an SVG filter applied at render, NOT baked into the file
     4. overlay  — separate inline SVG, never composited into the image

   The duotone being a render-time filter is the important one: any image
   dropped in gets unified into the brand automatically, so a set sourced
   from several places still reads as one commissioned shoot.

   Requires the filter defs — include {{ tp.filters() }} once per page.
   -------------------------------------------------------------------------- */

.tp-photo {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--tp-paper);   /* shows while loading / if src missing */
}

.tp-photo__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: url(#tp-duotone);
}

/* Keyed variants. Coral is the focal accent: at most one per view, never
   the default. Blue and Sage are the supporting keys, for differentiating
   items in a set. Keep a set mostly neutral so the keyed ones still read
   as chosen rather than decorative. */
.tp-photo--accent .tp-photo__img,
.tp-photo--key-coral .tp-photo__img { filter: url(#tp-duotone-accent); }
.tp-photo--key-blue  .tp-photo__img { filter: url(#tp-duotone-blue); }
.tp-photo--key-sage  .tp-photo__img { filter: url(#tp-duotone-sage); }

/* Escape hatch: real colour, for when an image genuinely needs it */
.tp-photo--full-colour .tp-photo__img { filter: none; }

.tp-photo__overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

/* Overlay strokes stay hairline at any size */
.tp-photo__overlay :where(circle, path, line, rect) {
  vector-effect: non-scaling-stroke;
}

/* --- Treatment: APERTURE --------------------------------------------------
   Photo visible only through a circle. The circular mask is what forces
   the tight crop that keeps images from reading as stock. */
.tp-photo--aperture {
  aspect-ratio: 1;
  border-radius: 50%;
  background: transparent;
}

.tp-photo--aperture .tp-photo__img { clip-path: circle(50% at 50% 50%); }

/* --- Shapes ---------------------------------------------------------------
   Varied silhouettes for mosaic layouts. A set of identical shapes reads as
   a headshot grid regardless of who is in it; varied ones read as composed.
   These clip via the container's radius and overflow, so no clip-path and
   no per-shape mask to maintain. */
.tp-photo--circle { aspect-ratio: 1;   border-radius: 50%; }
.tp-photo--soft   { aspect-ratio: 4/5; border-radius: var(--tp-radius-card); }
.tp-photo--pill   { aspect-ratio: 3/4; border-radius: var(--tp-radius-pill); }

/* Arch: rounded at the top, squared at the base. */
.tp-photo--arch {
  aspect-ratio: 3/4;
  border-radius: var(--tp-radius-pill) var(--tp-radius-pill)
                 var(--tp-radius-card) var(--tp-radius-card);
}

/* Wide variants for horizontal cells */
.tp-photo--wide { aspect-ratio: 5/4; border-radius: var(--tp-radius-card); }
.tp-photo--stadium { aspect-ratio: 5/4; border-radius: var(--tp-radius-pill); }

/* --- Treatment: HALF-REVEAL -----------------------------------------------
   Photo in one half of a circle, the other half left open — mirrors
   known-unknown-circle from the graphic system. */
.tp-photo--half {
  aspect-ratio: 1;
  background: transparent;
}

.tp-photo--half .tp-photo__img {
  clip-path: circle(50% at 50% 50%);
  -webkit-mask-image: linear-gradient(to right, #000 0 50%, transparent 50% 100%);
          mask-image: linear-gradient(to right, #000 0 50%, transparent 50% 100%);
}

/* --- Treatment: ANNOTATED -------------------------------------------------
   Full-bleed photo with thin geometry laid over it. Guide rule: thin
   geometry, ONE focal accent, photograph stays primary. */
.tp-photo--annotated { aspect-ratio: 16 / 9; }

.tp-photo--annotated .tp-photo__img { filter: url(#tp-duotone) brightness(0.92); }

/* --- Treatment: THREADED --------------------------------------------------
   Apertures sitting on a spine. Used by the stakeholder section. */
.tp-spine {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: 1fr;
  position: relative;
}

@media (min-width: 768px) {
  .tp-spine { grid-template-columns: repeat(4, 1fr); }

  /* the connecting line, drawn behind the apertures */
  .tp-spine::before {
    content: "";
    position: absolute;
    inset-inline: 12.5%;
    top: calc(var(--tp-spine-offset, 50%) - 1px);
    height: 1px;
    background: var(--tp-rule);
    z-index: 0;
  }
}

.tp-spine__item {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-sm);
}

.tp-spine__label { margin-block-start: var(--tp-space-2xs); }

/* Placeholder state — before real imagery lands */
.tp-photo--empty {
  background: var(--tp-paper);
  display: grid;
  place-items: center;
}

.tp-photo--empty .tp-photo__note {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: rgba(var(--tp-ink-rgb), 0.55);
  text-align: center;
  padding: var(--tp-space-sm);
}


/* --------------------------------------------------------------------------
   12. HERO — SPLIT

   Two-tone ground (Paper over Dusty Blue), a dashed technical grid, a large
   circle photograph, and a Coral line that organises the whole frame.

   ALIGNMENT — the line rests along the colour boundary, then pivots 45deg
   about that same point. The figure is CENTRED on the pivot, because a
   45deg line through the centre of a square also passes through its
   top-left and bottom-right corners. That is what keeps the photo's
   diagonal cut locked to the line at every viewport size.

   Both the figure and the line derive from --tp-fig-cx and --tp-split.
   Positioning either independently is what lets the cut drift off the line.
   -------------------------------------------------------------------------- */

.tp-hero--split {
  --tp-split:     58%;                          /* two-tone boundary + pivot */
  --tp-fig-size:  clamp(14rem, 27vw, 24rem);
  --tp-fig-cx:    52%;                          /* pivot, x */

  /* How far off-centre the line cuts the photo, as a fraction of its size.
     0 puts the line through the middle; larger values push the photo down
     and left so the cut takes a smaller corner.

     The offset and the clip are derived from this ONE number. Move the
     photo by hand and the cut stops matching the line. */
  --tp-cut-f:     0.34;
  --tp-grid-f:    1.2;                          /* grid size vs the photo */

  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: linear-gradient(
    to bottom,
    var(--tp-paper) 0 var(--tp-split),
    var(--tp-blue)  var(--tp-split) 100%
  );
  color: var(--tp-ink);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y) + 1.5rem);
  /* The head is held in the Paper half by space-between on the container,
     not by this padding — so it stays shallow and the foot sits low. */
  padding-block-end: var(--tp-space-2xl);

  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: min(94vh, 54rem);
}

/* The hero content sits further left than the page container allows, so it
   carries its own narrower gutter rather than the shared one. Layout for
   this container is declared with the hero content, further down. */
.tp-container--hero {
  max-width: none;
  padding-inline: clamp(1.25rem, 3.5vw, 3rem);
}

/* --- Dashed technical grid ------------------------------------------------
   A real line grid, drawn as an SVG pattern so the dashes stay crisp.
   Bounded rather than full-bleed, as in the reference. */
/* Concentric with the photograph and --tp-grid-f times its size, so the
   two scale together instead of drifting apart at different viewports. */
.tp-hero__grid {
  position: absolute;
  left: var(--tp-fig-cx);
  top: var(--tp-split);
  width: calc(var(--tp-fig-size) * var(--tp-grid-f));
  height: calc(var(--tp-fig-size) * var(--tp-grid-f));
  margin-left: calc(
    var(--tp-fig-size) / -2
    - var(--tp-fig-size) * var(--tp-cut-f) / 2
    - var(--tp-fig-size) * (var(--tp-grid-f) - 1) / 2
  );
  margin-top: calc(
    var(--tp-fig-size) / -2
    + var(--tp-fig-size) * var(--tp-cut-f) / 2
    - var(--tp-fig-size) * (var(--tp-grid-f) - 1) / 2
  );
  z-index: 0;
  pointer-events: none;
  overflow: visible;                      /* extra cells sit outside the box */
  color: rgba(var(--tp-ink-rgb), 0.55);   /* the pattern reads currentColor */
  --tp-cell: 64px;                        /* matches the SVG pattern step */
}

/* A few extra cells stepping out from the grid's edges, so the block ends
   irregularly rather than as a clean rectangle. Positions are keyed to the
   cell size, so they stay aligned to the pattern. */
/* A CSS dashed border draws far more ink than the SVG pattern's 3-on-5-off
   stroke, and a cell outlines all four sides where the pattern draws two.
   Held back so the extras read as part of the grid, not on top of it.

   All of them step out to the right and below: the grid's left edge runs
   into the headline, so cells on that side land in the content. */
.tp-hero__grid-cell {
  position: absolute;
  width: var(--tp-cell);
  height: var(--tp-cell);
  border: 1px dashed currentColor;
  opacity: 0.45;
}

.tp-hero__grid-cell--br1 { left: 100%; top: calc(100% - var(--tp-cell)); }
.tp-hero__grid-cell--br2 { left: 100%; top: 100%; }
.tp-hero__grid-cell--br3 { left: calc(100% - var(--tp-cell)); top: 100%; }
.tp-hero__grid-cell--tr  { left: calc(100% - var(--tp-cell) * 2); top: calc(var(--tp-cell) * -1); }
.tp-hero__grid-cell--rm  { left: 100%; top: 38%; }

.tp-hero__grid svg { width: 100%; height: 100%; display: block; }

/* --- The circle photograph -----------------------------------------------
   Centred on the pivot, so it straddles the colour boundary. */
.tp-hero__figure {
  position: absolute;
  left: var(--tp-fig-cx);
  top: var(--tp-split);
  width: var(--tp-fig-size);
  aspect-ratio: 1;
  /* Offset down and left of the pivot by --tp-cut-f, so the line cuts a
     corner rather than passing through the middle. Margins rather than
     transform, so a GSAP scale tween cannot fight the positioning. */
  margin-left: calc(
    var(--tp-fig-size) / -2 - var(--tp-fig-size) * var(--tp-cut-f) / 2
  );
  margin-top: calc(
    var(--tp-fig-size) / -2 + var(--tp-fig-size) * var(--tp-cut-f) / 2
  );
  border-radius: 50%;
  overflow: hidden;
  z-index: 1;
}

/* The diagonal cut. One element carries only one clip-path, so the circle
   and the cut are nested.

   The cut line runs from (--tp-cut-f, 0) to (100%, 100% - --tp-cut-f),
   which is 45deg and offset from the corner diagonal by exactly the same
   fraction the figure is offset from the pivot. That is what keeps the
   clip sitting on the line rather than near it.

   The mask is the reveal. Its gradient axis points to bottom-left (225deg),
   so its colour boundary is a 45deg line running parallel to the cut. As
   --tp-reveal grows the image is uncovered FROM the line outward, rather
   than fading in beside it. Defaults to 100% so the photo is fully visible
   without JS. */
.tp-hero__figure-cut {
  --tp-reveal: 100%;

  position: absolute;
  inset: 0;
  clip-path: polygon(
    0 0,
    calc(var(--tp-cut-f) * 100%) 0,
    100% calc(100% - var(--tp-cut-f) * 100%),
    100% 100%,
    0 100%
  );
  -webkit-mask-image: linear-gradient(
    225deg,
    #000 0 calc(var(--tp-reveal) - 3%),
    transparent var(--tp-reveal)
  );
          mask-image: linear-gradient(
    225deg,
    #000 0 calc(var(--tp-reveal) - 3%),
    transparent var(--tp-reveal)
  );
}

/* Light archival fade rather than a duotone, so the Coral in the booklet
   survives. */
.tp-hero__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 42% 42%;
  display: block;
  filter: saturate(0.72) contrast(0.92) brightness(1.04) sepia(0.14);
}

.tp-hero__figure--empty { background: var(--tp-paper); }

/* --- The line ------------------------------------------------------------
   Rests along the colour boundary; pivots to the diagonal on load. */
.tp-hero__diagonal {
  position: absolute;
  left: var(--tp-fig-cx);
  top: var(--tp-split);
  width: 320%;
  height: 2px;
  margin-left: -160%;
  margin-top: -1px;
  background: var(--tp-coral);
  transform-origin: 50% 50%;
  transform: rotate(45deg);
  z-index: 2;
  pointer-events: none;
}

/* --- Aside: the founders, on the two-tone boundary ------------------------
   Parked on the boundary rather than the floor: they sit across the line
   where Paper meets Blue, which is the hero's own horizon. */
.tp-hero__aside {
  position: absolute;
  right: var(--tp-gutter);
  top: var(--tp-split);
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--tp-space-md);

  /* Sized by the room that is actually left, not by raw vw: the gap
     between the photograph's right edge and the gutter does not scale at
     the same rate as the viewport, so a vw-based portrait clears the
     circle at 1280 and cuts into it at 950.

     48% is the far side of the 52% pivot, and half the figure less half
     its cut offset is how far right of the pivot its edge reaches. The
     width lives here rather than on the row because this is the
     absolutely positioned box, so the percentage resolves against the
     hero; on the row it would resolve against this shrink-to-fit box and
     collapse. */
  width: clamp(
    11rem,
    calc(48% - var(--tp-gutter) - var(--tp-fig-size) * (1 - var(--tp-cut-f)) / 2 - var(--tp-space-lg)),
    28.5rem
  );
}

.tp-hero__marks {
  display: flex;
  align-items: center;
  gap: var(--tp-space-xs);
  list-style: none;
}

/* Unboxed marks — the icons carry themselves, so they need real presence */
/* The row is an equation, so it is set like one: the terms carry the
   weight and the operators are smaller and quieter, the way they would be
   in type. Tighter gaps than the old icon row too, so the seven glyphs
   read as one phrase rather than a series. */
.tp-hero__mark-item {
  display: flex;
  align-items: center;
  color: var(--tp-ink);
}

.tp-hero__mark-item .tp-icon { width: 2.25rem; height: 2.25rem; }

/* The operators stay smaller, which is how an equation is set, but they no
   longer sit at a lighter weight: one solid ink for the whole row. */
.tp-hero__mark-item--op .tp-icon { width: 1.125rem; height: 1.125rem; }

/* Bottom right of the hero, on the same gutter the hero's own content uses
   so it lines up with the edge of the copy rather than the page gutter. */
.tp-hero__marks {
  position: absolute;
  inset-block-end: var(--tp-space-2xl);
  inset-inline-end: clamp(1.25rem, 3.5vw, 3rem);
  z-index: 3;

  /* One solid ink for the whole row. The icon files carry their own accents
     as var(--tp-coral) and friends, so setting `color` alone leaves those
     showing: redeclaring the three tokens here flattens the artwork itself,
     and only inside this row. */
  --tp-coral: var(--tp-ink);
  --tp-blue:  var(--tp-ink);
  --tp-sage:  var(--tp-ink);
}

/* --- Team, a single row bottom right ------------------------------------- */

/* Sized by the room that is actually left, not by raw vw. The gap between
   the photograph's right edge and the gutter does not scale at the same
   rate as the viewport, so a vw-based portrait clears the circle at 1280
   and cuts into it at 950.

   48% is the far side of the 52% pivot; half the figure less half its cut
   offset is how far right of the pivot its edge reaches. The portraits
   then divide whatever is left, up to a ceiling so they stop growing on
   very wide screens. */
.tp-hero__team {
  display: flex;
  gap: var(--tp-space-md);
  list-style: none;
  width: 100%;
}

.tp-hero__participant-link {
  display: inline-flex;
  align-items: baseline;
  gap: var(--tp-space-2xs);
  color: var(--tp-ink);
  font-family: var(--tp-font-display);
  line-height: 1;
  text-decoration: none;
  text-transform: uppercase;
}

.tp-hero__participant-number {
  font-size: clamp(1.875rem, 2.4vw, 2.75rem);
  font-weight: var(--tp-weight-bold);
  letter-spacing: 0;
}

.tp-hero__participant-text {
  max-width: 8.5rem;
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  color: rgba(var(--tp-ink-rgb), 0.68);
}

.tp-hero__participant-link:hover,
.tp-hero__participant-link:focus-visible {
  color: var(--tp-coral);
}

.tp-hero__participant-link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 0.35rem;
}

.tp-hero__team li {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--tp-space-3xs);
  flex: 1 1 0;
  min-width: 0;
}

/* --- The fake Venn --------------------------------------------------------
   Each founder gets a second circle, the same size as the photograph and
   offset toward the other one, so a crescent of it stands outside the
   portrait. The two are then joined by a square sitting where their overlap
   would be.

   Square rather than a lens on purpose: a true Venn intersection would claim
   these two people overlap in some measurable way, which is not the claim.
   The square is the brand's own geometry saying they are joined, and it is
   the one Coral accent in the group, as the guide asks.
   ------------------------------------------------------------------------ */
.tp-hero__team li::before {
  content: '';
  position: absolute;
  inset: 0;
  border: 1px solid rgba(var(--tp-ink-rgb), 0.45);
  border-radius: 50%;
  pointer-events: none;
  z-index: 1;
}

/* Percentages resolve against the li, which is the portrait's own box, so
   the offset stays the same fraction of the circle at every size. */
.tp-hero__team li:first-child::before  { transform: translateX(15%); }
.tp-hero__team li:last-child::before   { transform: translateX(-15%); }

.tp-hero__team { position: relative; }

/* Centred on the row, which is the midpoint between the two portraits. Wide
   enough to reach into both: the gap is the space between them, so anything
   past that is overlap. */
.tp-hero__team::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 19.6%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border: 1px solid var(--tp-coral);
  opacity: var(--tp-team-join-opacity, 1);
  pointer-events: none;
  z-index: 2;
}

.tp-hero__team .tp-photo {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
}

.tp-hero__team-link {
  display: block;
  text-decoration: none;
  border-radius: 50%;
}

/* Full black and white with a little contrast, rather than the duotone
   the photo component defaults to.

   The 1.2 is not styling. Both crops carry a near-white wedge of the
   mural at one o'clock, and in greyscale on the Paper half it is within a
   few values of the ground, so the circle's edge vanishes there and reads
   as a dip bitten out of the disc. The zoom carries that patch past the
   rim; below about 1.15 it is still visible. Replace the photography and
   check this again rather than assuming the number still applies.

   Scaled about the centre, which is what the crops are composed around. */
.tp-hero__team .tp-photo__img {
  filter: grayscale(1) contrast(1.15);
  transform: scale(1.2);
  transform-origin: 50% 50%;
  transition: transform var(--tp-duration-slow) var(--tp-ease-out);
}

.tp-hero__team-link:hover .tp-photo__img,
.tp-hero__team-link:focus-visible .tp-photo__img {
  transform: scale(1.28);
}

/* --- Content -------------------------------------------------------------
   Split in two: the eyebrow and headline sit high, in the Paper half; the
   description and actions drop to the bottom left. The container grows to
   fill the hero so space-between does the separating. */
.tp-container--hero {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--tp-space-xl);
}

.tp-hero__head,
.tp-hero__foot {
  position: relative;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-md);
}

/* The head spans the full gutter so the section index can sit against the
   right edge, opposite the eyebrow. The width that lets the title break
   into two lines rather than three moves onto the inner block. */
.tp-hero__head {
  flex-direction: row;
  /* Baseline, not flex-start: the index is a size step down from the
     wordmark, so aligning their boxes would leave the two sitting on
     different lines by a pixel or two. */
  align-items: baseline;
  justify-content: space-between;
  gap: var(--tp-space-xl);
}

.tp-hero__head-main {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-md);
  max-width: 42rem;
}

/* The copy has to stop before the photograph's ink, and the photograph is
   a circle whose left edge moves and grows with the viewport, so a fixed
   measure either collides at one width or wastes the line at another.

   Derived from the same two numbers that place the figure, the way the
   grid and the cut are: 52% is the pivot, and half the figure plus half
   its cut offset is how far left of the pivot its edge reaches. Move the
   photo and this follows it.

   It lives on the foot, not the lede: the percentage has to resolve
   against the hero-width container, and on the lede it would resolve
   against the foot instead and collapse to a couple of characters. */
.tp-hero__foot {
  max-width: min(
    34rem,
    calc(52% - var(--tp-fig-size) * (1 + var(--tp-cut-f)) / 2 - var(--tp-space-lg))
  );
}

/* --- Section index --------------------------------------------------------
   Reads as the other half of the eyebrow opposite it: that one ends on a
   blinking cursor, and each of these completes the phrase when hovered.
   Right-aligned so the colons stack into a single edge.

   Set in the UI face at the eyebrow's weight but a step down in size, so
   it belongs to the wordmark without competing with it. */
.tp-hero__nav ul {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--tp-space-3xs);
  list-style: none;
  margin: 0;
  padding: 0;
}

.tp-hero__nav-link {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--tp-font-ui);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.4;
  color: var(--tp-fg-muted);
  text-decoration: none;
  transition: color var(--tp-duration-fast) var(--tp-ease);
}

/* Restated on hover for the same reason as .tp-btn and .tp-link: Bootstrap
   ships a bare a:hover colour that outranks a class-only declaration. */
.tp-hero__nav-link:hover,
.tp-hero__nav-link:focus-visible { color: var(--tp-fg); }

.tp-hero__nav-link:focus-visible {
  outline: 2px solid var(--tp-coral);
  outline-offset: 3px;
}

/* The colon is always lit. The cursor after it holds its space at all
   times and only fades in, so hovering down the list does not reflow it. */
.tp-hero__nav-mark { color: var(--tp-coral); }

.tp-hero__nav-mark::after {
  content: "_";
  opacity: 0;
  transition: opacity var(--tp-duration-fast) var(--tp-ease);
}

.tp-hero__nav-link:hover .tp-hero__nav-mark::after,
.tp-hero__nav-link:focus-visible .tp-hero__nav-mark::after { opacity: 1; }

/* Hero headline sits below the global H1 step. The mosaic and the line
   carry as much of the composition as the type does, so the display size
   is dialled back rather than dominating the frame. */
.tp-hero__title {
  font-size: clamp(2.125rem, 1.4rem + 2.6vw, 3.25rem);
  /* A step off the display leading. 0.94 is drawn for a single dense line;
     over three it closes the lines up more than this headline wants. */
  line-height: 1.02;
  max-width: 23ch;
  text-wrap: balance;
}

.tp-hero__title-note {
  margin: calc(var(--tp-space-sm) * -1) 0 0;
  max-width: 30ch;
  font-family: var(--tp-font-display);
  font-size: clamp(1rem, 0.9rem + 0.35vw, 1.25rem);
  line-height: 1.2;
  font-weight: var(--tp-weight-medium);
  letter-spacing: 0;
  color: rgba(var(--tp-ink-rgb), 0.62);
}

.tp-hero__lede {
  color: rgba(var(--tp-ink-rgb), 0.68);
  max-width: 46ch;
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);
}

/* The actions opt out of the measure above. They sit below the circle,
   where the copy's clearance rule does not apply, and squeezing them into
   it is what pushed the secondary link onto its own line. */
.tp-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tp-space-md);
  margin-block-start: var(--tp-space-xs);
  min-width: max-content;
}

/* --------------------------------------------------------------------------
   MOBILE

   The overlaid composition needs room. Below 900px everything stacks in
   normal flow rather than being squeezed until it collides.
   -------------------------------------------------------------------------- */
@media (max-width: 899.98px) {
  .tp-hero--split {
    --tp-split: 44%;
    display: flex;
    flex-direction: column;
    gap: var(--tp-space-xl);
    min-height: 0;
  }

  .tp-hero__grid { inset-inline: 4% 4%; inset-block: 4% 40%; }

  .tp-hero__figure {
    position: relative;
    left: auto;
    top: auto;
    margin-inline: auto;
    margin-block: 0;
    width: min(68vw, 18rem);
    order: 2;
  }

  .tp-hero__figure-cut { clip-path: none; }

  /* The diagonal is a desktop device. On a phone it crosses the copy and the
     photograph instead of dividing them, so it comes off. */
  .tp-hero__diagonal { display: none; }

  .tp-hero__marks {
    position: relative;
    inset-block-end: auto;
    inset-inline-end: auto;
  }

  .tp-hero__aside { width: auto; }
  .tp-hero__team { width: auto; }
  .tp-hero__team li { flex: none; }
  .tp-hero__team .tp-photo { width: clamp(6rem, 24vw, 9rem); }

  .tp-hero__aside {
    position: relative;
    right: auto;
    top: auto;
    transform: none;
    order: 3;
    align-items: center;
    padding-inline: var(--tp-gutter);
  }

  .tp-hero__head {
    flex-direction: column;
    align-items: stretch;
    gap: var(--tp-space-md);
  }

  .tp-hero__head-main { max-width: none; }

  .tp-hero__nav ul {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: flex-start;
    column-gap: var(--tp-space-sm);
    row-gap: var(--tp-space-3xs);
  }

  /* Stacked, the figure is in flow and no longer beside the copy, so the
     derived measure above would narrow the foot for no reason. */
  .tp-hero__foot { max-width: none; }
  .tp-hero__actions { min-width: 0; }

  /* Head and foot stay together in flow; the split only makes sense once
     there is enough height to separate them. */
  .tp-container--hero {
    order: 1;
    flex: none;
    justify-content: flex-start;
    gap: var(--tp-space-md);
    padding-inline: var(--tp-gutter);
  }

  .tp-hero__grid-cell { display: none; }
}


/* --- Buttons --------------------------------------------------------------
   Editorial and architectural rather than SaaS. Ink ground, warm-paper
   text, square corners, and the coral :_ as the distinctive interaction:
   on hover the underscore extends to suggest what comes next.

   Type is the display face (Inter Tight), not Neue Haas Grotesk, per the
   licence-clean substitution agreed for this build.
   -------------------------------------------------------------------------- */

.tp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 2.5rem;

  padding: 1rem 1.25rem;
  min-height: 52px;

  background: var(--tp-ink);
  color: var(--tp-paper);

  font-family: var(--tp-font-display);
  font-size: 1rem;
  font-weight: var(--tp-weight-medium);
  line-height: 1;

  border: 1px solid var(--tp-ink);
  border-radius: 1px;

  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--tp-duration-fast) var(--tp-ease),
              color var(--tp-duration-fast) var(--tp-ease),
              column-gap 350ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* The bar grows by 1.6rem on hover and the gap closes by the same 1.6rem,
   so the button is exactly as wide hovered as at rest and can never push
   a secondary link onto a second line.

   The gap stops at 0.9rem rather than closing completely: run it to zero
   and the underscore ends up against the label, which reads as crowding
   rather than as the mark extending. */
.tp-btn:hover,
.tp-btn:focus-visible { column-gap: 0.9rem; }

.tp-btn:has(.tp-btn__future--arrow):hover,
.tp-btn:has(.tp-btn__future--arrow):focus-visible { column-gap: 2.5rem; }

/* The :_ device. Colon and underscore are drawn, not typed, so they hold
   their proportions independent of the font's punctuation metrics. */
.tp-btn__future {
  display: flex;
  align-items: flex-end;
  gap: 0.15rem;
  color: var(--tp-coral);
  flex: none;
}

.tp-btn__future::before {
  content: "";
  display: block;
  width: 3px;
  height: 11px;
  margin-bottom: 1px;
  background:
    linear-gradient(currentColor 0 3px, transparent 3px 8px, currentColor 8px 11px);
}

.tp-btn__future::after {
  content: "";
  display: block;
  width: 0.65rem;
  height: 2px;
  background: currentColor;
  transition: width 350ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.tp-btn:hover .tp-btn__future::after,
.tp-btn:focus-visible .tp-btn__future::after { width: 2.25rem; }

/* The same colon, with the bar replaced by a real arrow: a shaft and a
   head, not just a wedge. Drawn as SVG rather than borders because a
   border triangle can only ever be a head. It inherits the device's Coral
   through currentColor.

   It does not grow on hover, it travels, so the button holding it keeps a
   constant width without the gap trick the underscore needs. */
.tp-btn__future--arrow { align-items: center; }
.tp-btn__future--arrow::after { content: none; }

.tp-btn__future--arrow svg {
  display: block;
  width: 1.625rem;
  height: auto;
  overflow: visible;
  transition: transform var(--tp-duration) var(--tp-ease-out);
}

.tp-btn:hover .tp-btn__future--arrow svg,
.tp-btn:focus-visible .tp-btn__future--arrow svg { transform: translateX(0.35rem); }

/* Colour is restated on :hover deliberately. Bootstrap ships a bare
   `a:hover { color }` at (0,1,1), which outranks a colour declared only on
   `.tp-btn` at (0,1,0) — so without this the label repaints on hover. */
.tp-btn:hover,
.tp-btn:focus-visible {
  background: #000;
  color: var(--tp-paper);
}

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

/* On the Ink surface the button inverts so it stays legible. */
.tp-surface--ink .tp-btn {
  background: var(--tp-paper);
  color: var(--tp-ink);
  border-color: var(--tp-paper);
}

.tp-surface--ink .tp-btn:hover,
.tp-surface--ink .tp-btn:focus-visible {
  background: #FFF;
  color: var(--tp-ink);
}

.tp-btn--ghost,
.tp-surface--ink .tp-btn--ghost {
  background: transparent;
  border-color: var(--tp-rule);
  color: var(--tp-fg);
}

.tp-btn--ghost:hover,
.tp-btn--ghost:focus-visible,
.tp-surface--ink .tp-btn--ghost:hover,
.tp-surface--ink .tp-btn--ghost:focus-visible {
  background: transparent;
  border-color: var(--tp-fg);
  color: var(--tp-fg);
}

@media (prefers-reduced-motion: reduce) {
  .tp-btn__future::after { transition: none; }
  .tp-btn { transition: background-color var(--tp-duration-fast) var(--tp-ease),
                        color var(--tp-duration-fast) var(--tp-ease); }
}

/* Secondary action: a text link carrying the same underscore, so the two
   read as one family without competing for weight. */
.tp-link {
  display: inline-flex;
  align-items: center;
  gap: var(--tp-space-2xs);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-body);
  font-weight: var(--tp-weight-medium);
  color: var(--tp-fg);
  text-decoration: none;
}

/* Same reason as .tp-btn:hover above — restate the colour on hover so
   Bootstrap's bare a:hover cannot repaint it. */
.tp-link:hover,
.tp-link:focus-visible { color: var(--tp-fg); }

.tp-link__bar {
  display: block;
  width: 0.875rem;
  height: 2px;
  background: var(--tp-coral);
  flex: none;
  transition: width var(--tp-duration) var(--tp-ease-out);
}

.tp-link:hover .tp-link__bar,
.tp-link:focus-visible .tp-link__bar { width: 1.5rem; }


/* --------------------------------------------------------------------------
   13. STORY

   A four-step sequence: three things progress is NOT, then what it is.
   The figures morph from a barely-formed shape to a complete circle, so
   the geometry resolves as the argument does. A connecting rule with a
   node per step carries the reading across.

   MOTION IS ADDITIVE. The resting state is the finished sequence, so the
   section reads without JS; under .tp-animate the steps start flat and
   resolve as they scroll in.
   -------------------------------------------------------------------------- */

/* Positioning context for .tp-corner. Every absolutely-positioned thing
   inside these sections already has a nearer positioned ancestor, so this
   changes nothing else. */
.tp-story,
.tp-value,
.tp-tech,
.tp-team,
.tp-how,
.tp-problem-opening,
.tp-problem-tensions,
.tp-problem-neutral,
.tp-problem-path,
.tp-ask-ways,
.tp-ask-publish,
.tp-ask-form,
.tp-leaders-principle,
.tp-leaders-profiles,
.tp-leaders-position,
.tp-leaders-cta,
.tp-contact-form,
.tp-talk-overview,
.tp-talk-topics,
.tp-talk-form,
.tp-story-opening,
.tp-story-turns,
.tp-story-progress,
.tp-story-name,
.tp-story-close,
.tp-consulting-intro,
.tp-consulting-discovery,
.tp-consulting-readiness,
.tp-consulting-tensions,
.tp-consulting-questions,
.tp-consulting-process,
.tp-consulting-outputs,
.tp-consulting-beliefs,
.tp-consulting-fit,
.tp-consulting-final,
.tp-vp-opening,
.tp-vp-reframe,
.tp-vp-framework,
.tp-vp-comparison,
.tp-vp-path { position: relative; }

.tp-how > .tp-container,
.tp-problem-opening > .tp-container,
.tp-problem-tensions > .tp-container,
.tp-problem-neutral > .tp-container,
.tp-problem-path > .tp-container,
.tp-ask-ways > .tp-container,
.tp-ask-publish > .tp-container,
.tp-ask-form > .tp-container,
.tp-leaders-principle > .tp-container,
.tp-leaders-profiles > .tp-container,
.tp-leaders-position > .tp-container,
.tp-leaders-cta > .tp-container,
.tp-contact-form > .tp-container,
.tp-talk-overview > .tp-container,
.tp-talk-topics > .tp-container,
.tp-talk-form > .tp-container,
.tp-story-opening > .tp-container,
.tp-story-turns > .tp-container,
.tp-story-progress > .tp-container,
.tp-story-name > .tp-container,
.tp-story-close > .tp-container,
.tp-consulting-intro > .tp-container,
.tp-consulting-discovery > .tp-container,
.tp-consulting-readiness > .tp-container,
.tp-consulting-tensions > .tp-container,
.tp-consulting-questions > .tp-container,
.tp-consulting-process > .tp-container,
.tp-consulting-outputs > .tp-container,
.tp-consulting-beliefs > .tp-container,
.tp-consulting-fit > .tp-container,
.tp-consulting-final > .tp-container,
.tp-vp-opening > .tp-container,
.tp-vp-reframe > .tp-container,
.tp-vp-framework > .tp-container,
.tp-vp-comparison > .tp-container,
.tp-vp-path > .tp-container {
  position: relative;
  z-index: 1;
}


.tp-story .tp-container {
  display: flex;
  flex-direction: column;
  gap: var(--tp-section-y-tight);
}

/* --- Head: question, short intro, photograph ------------------------------ */
.tp-story__head {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-grid-gap);
  align-items: center;
}

@media (min-width: 860px) {
  .tp-story__head { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }
}

.tp-story__head-text {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-md);
}

.tp-story__q { max-width: 16ch; }
/* The system's standard body measure rather than another hand-picked
   number. The grid track beside the photograph allows about 76ch, which
   is past comfortable reading, so this is the limit worth having. */
.tp-story__intro { max-width: var(--tp-measure); }

.tp-story__photo {
  width: min(100%, 15rem);
  justify-self: end;
}

/* Crop biased up and slightly left so the head, shoulders and the coral
   booklet sit inside the circle rather than the chair legs. */
.tp-story__photo-img {
  filter: saturate(0.72) contrast(0.94) sepia(0.1);
  object-position: 46% 34%;
}

/* --- The four steps ------------------------------------------------------- */
.tp-story__steps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--tp-space-xl) var(--tp-grid-gap);
  list-style: none;
}

/* 960 rather than 860: below this the four columns are too narrow to hold
   the longest step title on one line, and the row goes ragged. */
@media (min-width: 960px) {
  .tp-story__steps { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.tp-story__step {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-sm);
}

.tp-story__fig { display: block; width: 100%; height: auto; }

/* The rule and its nodes. Each step draws its own dot and the segment
   reaching the next one, so the line survives any column count. */
.tp-story__node {
  position: relative;
  display: flex;
  align-items: center;
  height: 1.25rem;
  margin-block-start: var(--tp-space-2xs);
}

.tp-story__node::before {
  content: "";
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: var(--tp-ink);
  position: relative;
  z-index: 1;
}

.tp-story__node::after {
  content: "";
  position: absolute;
  left: 0.625rem;
  right: calc(var(--tp-grid-gap) * -1);
  top: 50%;
  height: 1px;
  background: var(--tp-ink);
}

/* No trailing segment off the end of each row */
.tp-story__step:last-child .tp-story__node::after { display: none; }

@media (min-width: 860px) {
  .tp-story__step:nth-child(4) .tp-story__node::after { display: none; }
}

@media (max-width: 859.98px) {
  .tp-story__step:nth-child(even) .tp-story__node::after { display: none; }
}

/* Smaller than the .tp-h3 step it inherits. At h3 size the longest title
   only fits on one line near the container's maximum width, so the row
   broke into ragged one- and two-line headings at most viewports. */
/* Inter Bold rather than the display face's medium. At 16px the display
   cut is drawn for headline sizes and reads soft here; the UI face is
   drawn for this size and the weight gives the claim its own voice
   against the label above it. 700 is added to the Inter request in the
   page head for this. */
.tp-story__step-title {
  margin: 0;
  font-family: var(--tp-font-ui);
  font-weight: var(--tp-weight-bold);
  font-size: 1rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

/* Small, as in the reference: the figures and the headings carry the row,
   and the body is there for whoever stops to read it. */
/* Names the vision this step belongs to. Same shape as the label above
   each vision panel below, so the two sections rhyme and the reader
   carries the four groups from one into the other.

   Muted rather than Coral: the accent in this composition is already
   spent on the fourth step's node, and four more would break the guide's
   one-focal-accent rule. */
.tp-story__step-label {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg-muted);
}

/* Down to this group's panel in the visions section, so the two four-part
   sections are wired together rather than merely adjacent.

   Pushed to the bottom of the card with auto margin: the four cards are
   equal height, so all four arrows land on one line instead of following
   copy of four different lengths.

   Muted at rest, Coral on hover. Four permanent Coral arrows would be four
   accents in one composition; one at a time under the pointer is not. */
.tp-story__jump {
  display: inline-flex;
  margin-block-start: auto;
  padding-block-start: var(--tp-space-sm);
  color: var(--tp-fg-muted);
  transition: color var(--tp-duration-fast) var(--tp-ease),
              transform var(--tp-duration) var(--tp-ease-out);
}

.tp-story__jump svg { display: block; width: 1.125rem; height: auto; }

.tp-story__jump:hover,
.tp-story__jump:focus-visible {
  color: var(--tp-coral);
  transform: translateY(3px);
}

.tp-story__step-body {
  color: var(--tp-fg);
  font-size: var(--tp-size-caption);
  line-height: 1.55;
  max-width: 30ch;
}

/* Final step carries the resolution, so it takes the accent */
.tp-story__step--resolve .tp-story__node::before { background: var(--tp-coral); }
.tp-story__step--resolve .tp-story__step-title   { color: var(--tp-coral); }

/* The qualification and the handover link that close the section. The
   contrasts above are claims; this is the honest limit on them. */
.tp-story__close {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tp-space-md);
  padding-block-start: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
}

.tp-story__closing {
  margin: 0;
  font-family: var(--tp-font-text);
  font-size: clamp(1.1875rem, 1.06rem + 0.5vw, 1.4375rem);
  line-height: 1.5;
  color: var(--tp-fg-muted);
  max-width: 52ch;
}

.tp-story__closing em { font-style: normal; font-weight: 600; color: var(--tp-fg); }

/* --- Motion ---------------------------------------------------------------
   The morph figure's circle scales up into place; resting state is fully
   formed so the sequence reads without JS. */
.tp-story__fig-shape {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 800ms var(--tp-ease-out), opacity 600ms var(--tp-ease-out);
}

.thepath.tp-animate .tp-story__fig-shape { transform: scale(0.4); opacity: 0; }
.thepath.tp-animate .is-shown .tp-story__fig-shape { transform: none; opacity: 1; }


/* --------------------------------------------------------------------------
   14. WHERE VALUE LIVES

   Serpentine spine on the left, copy on the right. The circles are sized
   by how much value each place holds, and one is left in Stone: the value
   nothing records.

   MOTION IS ADDITIVE. Resting state is fully drawn. pathLength="1" on the
   spine normalises its dash array, so the draw works without measuring the
   real path length in JS.
   -------------------------------------------------------------------------- */

.tp-value__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-section-y-tight) var(--tp-grid-gap);
  align-items: stretch;   /* lets the spine run the full height of the cards */
}

@media (min-width: 860px) {
  .tp-value__grid { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); }
}

/* --- The spine ------------------------------------------------------------
   The serpentine has a fixed aspect ratio, so stretching it to an arbitrary
   height would turn its circles into ovals. Instead the path runs longer
   than the section is ever likely to be and the figure CLIPS it, so the
   switchbacks keep their rhythm all the way down and the line simply
   carries on past the cut. Works at any card count. */
.tp-value__figure {
  position: relative;
  width: 100%;
  min-height: 22rem;      /* floor, in case the copy column is short */
  overflow: hidden;
}

/* Absolutely positioned so it does NOT contribute to the grid row height.
   Otherwise the over-long spine sets the row height instead of being
   clipped by it, and drags the whole section to the SVG's full length. */
.tp-value__svg {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: block;
  width: min(100%, 17rem);
  height: auto;
  /* The spine strokes currentColor rather than a fixed Stone, so it stays
     legible on any surface. Hardcoding Stone made it invisible the moment
     the section sat on a Stone ground. */
  color: var(--tp-fg);
}

.tp-value__spine { opacity: 0.35; }

/* Stacked layout has no cards to run alongside, so the spine is trimmed
   back to roughly the nodes rather than running off down the page. */
@media (max-width: 859.98px) {
  .tp-value__figure { min-height: 0; height: 26rem; }
}

/* --- Copy ----------------------------------------------------------------- */
.tp-value__copy {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-xl);
}

.tp-value__head {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-md);
}

.tp-value__heading { max-width: 22ch; }

/* A grid rather than a list. Cells read across then down, which still
   follows the spine's circle order 1 to 5. */
.tp-value__places {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-lg) var(--tp-grid-gap);
  list-style: none;
}

@media (min-width: 560px) {
  .tp-value__places { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.tp-value__place {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tp-space-2xs);
}

.tp-value__place .tp-icon {
  width: 3.5rem;
  height: 3.5rem;
  margin-block-end: var(--tp-space-2xs);
}

.tp-value__place-title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: 1rem;
  font-weight: var(--tp-weight-medium);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--tp-fg);
}

.tp-value__place-body {
  margin: 0;
  font-size: var(--tp-size-caption);
  line-height: 1.55;
  color: var(--tp-fg);
  max-width: 32ch;
}

/* Eight cells is a lot of vertical run against a fixed-height spine, so
   they go three-up once there is room. */
@media (min-width: 1080px) {
  .tp-value__places { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.tp-value__closing {
  max-width: 34ch;
  padding-block-start: var(--tp-space-md);
  border-block-start: 1px solid var(--tp-rule);
}

/* --- Motion --------------------------------------------------------------- */
.tp-value__spine {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1600ms var(--tp-ease-out);
}

.tp-value__node {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 700ms var(--tp-ease-out), opacity 500ms var(--tp-ease-out);
}

.thepath.tp-animate .tp-value__spine { stroke-dashoffset: 1; }
.thepath.tp-animate .is-shown .tp-value__spine { stroke-dashoffset: 0; }


.thepath.tp-animate .tp-value__node { transform: scale(0); opacity: 0; }
.thepath.tp-animate .is-shown .tp-value__node { transform: none; opacity: 1; }

/* Nodes resolve in sequence as the line reaches them */
.thepath.tp-animate .is-shown .tp-value__node[data-node="1"] { transition-delay: 200ms; }
.thepath.tp-animate .is-shown .tp-value__node[data-node="2"] { transition-delay: 420ms; }
.thepath.tp-animate .is-shown .tp-value__node[data-node="3"] { transition-delay: 640ms; }
.thepath.tp-animate .is-shown .tp-value__node[data-node="4"] { transition-delay: 860ms; }
.thepath.tp-animate .is-shown .tp-value__node[data-node="5"] { transition-delay: 1080ms; }
.thepath.tp-animate .is-shown .tp-value__node[data-node="6"] { transition-delay: 1280ms; }
.thepath.tp-animate .is-shown .tp-value__node[data-node="7"] { transition-delay: 1280ms; }

/* The travelling node fades in once the line has drawn, then runs its own
   SMIL motion along the spine. */
.tp-value__traveller { transition: opacity 600ms var(--tp-ease-out) 1400ms; }
.thepath.tp-animate .tp-value__traveller { opacity: 0; }
.thepath.tp-animate .is-shown .tp-value__traveller { opacity: 1; }


/* --------------------------------------------------------------------------
   15. THE CONVERSATIONS

   Discovery. The overhead photograph anchors it, four groups say who is
   in the room, and the tension-to-harmony graphic closes the argument:
   the value sits in the overlap between accounts, not in any one of them.
   -------------------------------------------------------------------------- */

.tp-talk .tp-container {
  display: flex;
  flex-direction: column;
  gap: var(--tp-section-y-tight);
}

.tp-talk__head {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-md);
}

.tp-talk__heading { max-width: 20ch; }
.tp-talk__intro   { max-width: 52ch; }

/* --- 1. The photograph ---------------------------------------------------- */
.tp-talk__feature {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-grid-gap);
  align-items: center;
}

@media (min-width: 860px) {
  .tp-talk__feature { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}

.tp-talk__photo {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--tp-radius-card);
  overflow: hidden;
  background: var(--tp-paper);
}

.tp-talk__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(0.74) contrast(0.94) sepia(0.1);
}

/* --- Overlay geometry -----------------------------------------------------
   Registration crosshairs and rings over the photograph, with a single
   solid Coral accent. Guide rule: thin geometry, ONE focal accent, the
   photograph stays primary — so everything but the accent is a hairline
   at partial opacity. Strokes are non-scaling so they stay hairline at
   any rendered size. */
.tp-regmark {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.tp-regmark :where(line, circle) { vector-effect: non-scaling-stroke; }

.tp-regmark__reg line {
  stroke: var(--tp-paper);
  stroke-width: 1;
  opacity: 0.3;
}

.tp-regmark__marks circle {
  fill: none;
  stroke: var(--tp-paper);
  stroke-width: 1;
  opacity: 0.55;
}

.tp-regmark__join {
  stroke: var(--tp-paper);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  opacity: 0.6;
}

/* The accent travels the dashed join, back and forth between the two
   rings. It starts at the midpoint, so the translate is half the join's
   vector in each direction: (65,69) - (31,34) = (34,35), so ±17, ±17.5.
   Values are user units, which is what CSS transforms use inside a
   viewBox. */
.tp-regmark__focus {
  fill: var(--tp-coral);
  animation: tp-connect 4.5s ease-in-out infinite alternate;
}

@keyframes tp-connect {
  from { transform: translate(-17px, -17.5px); }
  to   { transform: translate(17px, 17.5px); }
}

@media (prefers-reduced-motion: reduce) {
  .tp-regmark__focus { animation: none; }
}

/* Structure resolving into possibility: a rigid grid on the left, an arrow,
   then open nodes on the right. It is the section's own argument, held
   behind it. The file's fallbacks are Paper, Blue and Coral, which is why
   this graphic and not another one. */
.tp-talk {
  --tp-wash-image: url("/static/thepath/web/graphics/structure-to-possibility.svg");
  --tp-wash-opacity: 0.13;
}

/* --- The two statements ---------------------------------------------------
   Set in the text face at body-plus size with normal weight and open
   leading, rather than as headings. They are sentences to be read, not
   labels to be scanned, and at h3 weight they shouted. */
.tp-talk__statement,
.tp-talk__closing {
  font-family: var(--tp-font-text);
  font-size: clamp(1.1875rem, 1.06rem + 0.5vw, 1.4375rem);
  font-weight: var(--tp-weight-roman);
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--tp-fg-muted);
  margin: 0;
}

/* The phrase that carries the point. Weight and full-strength colour
   rather than Coral: the accent in this block is already spent on the
   focal dot over the photograph, and the guide allows one per composition. */
.tp-talk__statement em,
.tp-talk__closing em {
  font-style: normal;
  font-weight: 600;
  color: var(--tp-fg);
}

.tp-talk__statement { max-width: 30ch; }

/* --- 2. Who is in the room ------------------------------------------------ */
.tp-talk__groups {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-lg) var(--tp-grid-gap);
  list-style: none;
  padding-block-start: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
}

@media (min-width: 640px) { .tp-talk__groups { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .tp-talk__groups { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

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

.tp-talk__group .tp-icon {
  width: 2.75rem;
  height: 2.75rem;
  margin-block-end: var(--tp-space-3xs);
}

.tp-talk__group-title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: 1rem;
  font-weight: var(--tp-weight-medium);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--tp-fg);
}

.tp-talk__group-body {
  font-size: var(--tp-size-caption);
  line-height: 1.55;
  color: var(--tp-fg);
  max-width: 32ch;
}

/* --- 3. Tension to harmony ------------------------------------------------ */
.tp-talk__resolve {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-grid-gap);
  align-items: center;
  padding-block-start: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
}

@media (min-width: 860px) {
  .tp-talk__resolve { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }
}

.tp-talk__graphic { width: 100%; }

.tp-talk__graphic svg {
  display: block;
  width: 100%;
  height: auto;
}

.tp-talk__closing { max-width: 34ch; }

/* --- The day, and the day worth building ---------------------------------
   Compresses the two omitted beats into one band, using the CONTINUE
   grammar: solid for what is known today, dotted for what is still being
   worked out, Coral for what comes next, closing on the mark.

   It is also the handover into the technology section: the future day is
   the standard the technology then has to meet. */
.tp-talk__day {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-xl);
  padding-block-start: var(--tp-section-y-tight);
  border-block-start: 1px solid var(--tp-rule);
}

.tp-talk__day-title { max-width: 22ch; }
.tp-talk__day-intro { max-width: 52ch; }

.tp-talk__continue svg { display: block; width: 100%; height: auto; }

.tp-talk__continue path { fill: none; stroke-width: 3; }
.tp-talk__seg-now  { stroke: var(--tp-fg); }
.tp-talk__seg-mid  { stroke: var(--tp-stone); stroke-dasharray: 9 11; }
.tp-talk__seg-next { stroke: var(--tp-coral); }

/* --- The trace -----------------------------------------------------------
   Stacked: labels, the line, then descriptions. Each stage straddles its
   own segment, so the list and the drawing are one object rather than a
   diagram with a caption underneath.

   The stage <li> is display: contents so its title and body can be placed
   into the same column but different rows of the parent grid. role is
   restated on the list items because that display value drops them from
   the accessibility tree in some engines. */
.tp-talk__trace {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-md);
}

.tp-talk__stages,
.tp-talk__outcomes {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-lg) var(--tp-grid-gap);
  list-style: none;
}

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

@media (min-width: 760px) {
  .tp-talk__outcomes { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* No column-gap: the line spans all three columns as one drawing, and
     its segment breaks are fixed percentages of the viewBox. A gap would
     push the columns off those breaks by a growing amount. The gutter is
     put back as padding inside each column instead, so the copy still has
     air but the grid lines stay at exact thirds. */
  .tp-talk__trace {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: auto auto auto;
    column-gap: 0;
    row-gap: var(--tp-space-xs);
  }

  .tp-talk__continue { grid-row: 2; grid-column: 1 / -1; }

  .tp-talk__stages { display: contents; }
  .tp-talk__stage  { display: contents; }

  .tp-talk__stage-title { grid-row: 1; align-self: end; }
  .tp-talk__stage-body  { grid-row: 3; }

  .tp-talk__stage-title,
  .tp-talk__stage-body { padding-inline-end: var(--tp-grid-gap); }

  .tp-talk__stage:nth-child(1) > * { grid-column: 1; }
  .tp-talk__stage:nth-child(2) > * { grid-column: 2; }
  .tp-talk__stage:nth-child(3) > * { grid-column: 3; }
}

.tp-talk__stage-title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: 1.0625rem;
  font-weight: var(--tp-weight-medium);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--tp-fg);
}

.tp-talk__stage-body {
  font-size: var(--tp-size-caption);
  line-height: 1.55;
  color: var(--tp-fg-muted);
  max-width: 34ch;
}

/* Who gains, and what they gain. The people the future day is actually for. */
.tp-talk__outcomes { padding-block-start: var(--tp-space-md); border-block-start: 1px solid var(--tp-rule); }

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

.tp-talk__who {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-coral);
}

.tp-talk__gain {
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);
  color: var(--tp-fg);
  max-width: 34ch;
}

.tp-talk__handover {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tp-space-md);
}

.tp-talk__handover .tp-talk__closing { max-width: 46ch; }

/* --- Tension to harmony, in motion ---------------------------------------
   The link node runs the gap between the two dots, and the right-hand pair
   drifts closer together. Slow and small: the guide asks for subtle,
   purposeful motion, and this only needs to suggest the resolution. */
.tp-th__link {
  animation: tp-link 5s ease-in-out infinite alternate;
}

@keyframes tp-link {
  from { transform: translateY(-150px); }
  to   { transform: translateY(150px); }
}

.tp-th__near-a { animation: tp-near-a 6s ease-in-out infinite alternate; }
.tp-th__near-b { animation: tp-near-b 6s ease-in-out infinite alternate; }

@keyframes tp-near-a { from { transform: translateX(0); } to { transform: translateX(14px); } }
@keyframes tp-near-b { from { transform: translateX(0); } to { transform: translateX(-14px); } }

@media (prefers-reduced-motion: reduce) {
  .tp-th__link,
  .tp-th__near-a,
  .tp-th__near-b { animation: none; }
}


/* --------------------------------------------------------------------------
   16. THE TECHNOLOGY

   The Assistant at the centre, with the four pillars threaded on an arc
   beside it. The orbit carries the argument: the pillars are not four
   products in a row, they are what circles and feeds one shared thing.

   Rings turn at different speeds and directions; the core stays still.
   -------------------------------------------------------------------------- */

.tp-tech .tp-container {
  display: flex;
  flex-direction: column;
  gap: var(--tp-section-y-tight);
}

.tp-tech__head { display: flex; flex-direction: column; gap: var(--tp-space-md); }
.tp-tech__heading { max-width: 20ch; }
.tp-tech__intro   { max-width: 52ch; }

.tp-tech__orbit-wrap {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-section-y-tight) var(--tp-grid-gap);
  align-items: center;
}

@media (min-width: 900px) {
  .tp-tech__orbit-wrap { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
}

/* --- The core ------------------------------------------------------------- */
.tp-tech__orbit {
  position: relative;
  width: min(100%, 26rem);
  aspect-ratio: 1;
  margin-inline: auto;
}

.tp-tech__orbit svg { display: block; width: 100%; height: auto; overflow: visible; }

.tp-orb__track {
  fill: none;
  stroke: var(--tp-rule);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.tp-orb__core        { fill: var(--tp-ink); }
.tp-orb__node-ink    { fill: var(--tp-ink); }
.tp-orb__node-coral  { fill: var(--tp-coral); }
.tp-orb__node-stone  { fill: var(--tp-stone); }
.tp-orb__node-stone-soft { fill: var(--tp-stone); opacity: 0.55; }

/* Rotation is about the core's centre in viewBox units, so transform-box
   has to be view-box — fill-box would spin each shape about itself. */
.tp-orb__ring {
  transform-box: view-box;
  transform-origin: 200px 200px;
}

.tp-orb__ring--outer { animation: tp-orbit 68s linear infinite; }
.tp-orb__ring--mid   { animation: tp-orbit 46s linear infinite reverse; }
.tp-orb__ring--inner { animation: tp-orbit 32s linear infinite; }

@keyframes tp-orbit { to { transform: rotate(360deg); } }

.tp-tech__core-label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--tp-font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
  font-weight: var(--tp-weight-bold);
  letter-spacing: -0.02em;
  color: var(--tp-paper);
  pointer-events: none;
}

/* --- Packets ---------------------------------------------------------------
   Dots running from each pillar into the core, so the connection between
   the four and the one is shown rather than asserted. The wires themselves
   are hairlines; the packets carry the Coral. */
.tp-tech__wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  overflow: visible;
}

.tp-tech__wire {
  fill: none;
  stroke: var(--tp-rule);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.tp-tech__packet { fill: var(--tp-coral); }

/* --- The four pillars ------------------------------------------------------ */
.tp-tech__pillars {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-xl);
  list-style: none;
}

/* The arc threading them. Stretched to the list's height, so it always
   spans whatever the copy comes to. */
/* Spans the badge column exactly, so thepath.js can map a badge's centre
   onto a point of this path and translate it there. Its top and height are
   set by that same script so the curve begins at the first badge and ends
   at the last, rather than overshooting the row. */
.tp-tech__arc {
  position: absolute;
  top: 0;
  left: 0;
  width: 7rem;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

.tp-tech__arc path {
  fill: none;
  stroke: var(--tp-rule);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

@media (max-width: 599.98px) { .tp-tech__arc { display: none; } }

.tp-tech__pillar {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-sm);
  align-items: start;
}

/* A fixed first column the width of the arc, so a badge has room to sit
   anywhere along the curve without crowding the copy. */
@media (min-width: 600px) {
  .tp-tech__pillar {
    grid-template-columns: 7rem 1fr;
    gap: var(--tp-space-md);
  }
}

.tp-tech__badge {
  display: grid;
  place-items: center;
  width: 4.25rem;
  height: 4.25rem;
  border-radius: 50%;
  background: var(--tp-ink);
  color: var(--tp-paper);
  flex: none;
}

/* .tp-icon pins `color: var(--tp-fg)`, which overrides the Paper it should
   be inheriting from the badge — so currentColor resolved back to Ink.
   Inherit instead, and the repaint rules below then land on Paper. */
.tp-tech__badge .tp-icon {
  width: 2.25rem;
  height: 2.25rem;
  color: inherit;
}

/* Paper throughout. The cleaned icons carry their own Coral, Sage and Blue
   accents, which currentColor does not reach.

   Matching on the palette token by name is unreliable — the cleaned files
   write `var(--tp-coral, #F35F45)`, so a `^="var(--tp-coral)"` selector
   never matches because of the comma. This instead repaints anything with
   an explicit fill or stroke, whatever it was set to, and leaves `none`
   alone so outlined shapes stay outlines. */
.tp-tech__badge svg [fill]:not([fill="none"])     { fill: currentColor; }
.tp-tech__badge svg [stroke]:not([stroke="none"]) { stroke: currentColor; }

.tp-tech__pillar-copy {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-2xs);
  max-width: 44ch;
}

.tp-tech__pillar-title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: clamp(1.25rem, 1.12rem + 0.55vw, 1.5rem);
  font-weight: var(--tp-weight-bold);
  line-height: 1.1;
  letter-spacing: -0.018em;
}

.tp-tech__pillar-title a { color: var(--tp-fg); text-decoration: none; }
.tp-tech__pillar-title a:hover,
.tp-tech__pillar-title a:focus-visible { color: var(--tp-coral); }

/* Deliberately below body size: the scene is the point here, and the
   description only has to carry enough to send you to the deeper page. */
.tp-tech__pillar-body {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--tp-fg);
}

/* The deeper-page link. Understated: a small label and the underscore,
   which extends on hover like the primary button's. */
.tp-tech__more {
  display: inline-flex;
  align-items: center;
  gap: var(--tp-space-2xs);
  margin-block-start: var(--tp-space-3xs);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg-muted);
  text-decoration: none;
  transition: color var(--tp-duration-fast) var(--tp-ease);
}

.tp-tech__more-bar {
  display: block;
  width: 0.875rem;
  height: 2px;
  background: var(--tp-coral);
  transition: width var(--tp-duration) var(--tp-ease-out);
}

.tp-tech__more:hover,
.tp-tech__more:focus-visible { color: var(--tp-fg); }

.tp-tech__more:hover .tp-tech__more-bar,
.tp-tech__more:focus-visible .tp-tech__more-bar { width: 1.75rem; }

/* --- Close ----------------------------------------------------------------- */
.tp-tech__closing {
  font-family: var(--tp-font-text);
  font-size: clamp(1.1875rem, 1.06rem + 0.5vw, 1.4375rem);
  font-weight: var(--tp-weight-roman);
  line-height: 1.5;
  color: var(--tp-fg-muted);
  max-width: 46ch;
  margin: 0;
  padding-block-start: var(--tp-space-lg);
}

.tp-tech__closing em { font-style: normal; font-weight: 600; color: var(--tp-fg); }

@media (prefers-reduced-motion: reduce) {
  .tp-orb__ring { animation: none; }
}


/* --------------------------------------------------------------------------
   17. MOTION
   Guide: subtle, purposeful, opacity/transform only.
   -------------------------------------------------------------------------- */

/* Content is VISIBLE by default and JS opts into animating by stamping
   .tp-animate on the root.

   The inverse (hiding in CSS, revealing in JS) means disabled JS, a script
   error, or a stalled requestAnimationFrame leaves the page permanently
   blank. Animation may only ever be additive to content that already
   renders. thepath.js also runs a failsafe timer in case the ticker stalls
   after the class is stamped. */
.tp-reveal {
  opacity: 1;
  transform: none;
}

.thepath.tp-animate .tp-reveal {
  opacity: 0;
  transform: translateY(1rem);
  transition: opacity 700ms var(--tp-ease-out),
              transform 700ms var(--tp-ease-out);
  will-change: opacity, transform;
}

.thepath.tp-animate .tp-reveal.is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

.thepath.tp-animate .tp-hero--split.is-preparing .tp-hero__participant-link {
  opacity: 0;
}

.thepath.tp-animate .tp-hero--split.is-preparing .tp-hero__team {
  --tp-team-join-opacity: 0;
}

/* Hero reveals are driven by the GSAP timeline, which writes inline styles
   every frame. A CSS transition on the same properties would fight the
   tween and drag it, so it is switched off inside the hero only. */
.thepath.tp-animate .tp-hero .tp-reveal { transition: none; }

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

  .tp-reveal { opacity: 1; transform: none; }
  .tp-mark--cursor .tp-mark__bar { animation: none; }
}


/* --------------------------------------------------------------------------
   18. ACCESSIBILITY
   -------------------------------------------------------------------------- */

.thepath :where(a, button, input, select, textarea):focus-visible {
  outline: 2px solid var(--tp-coral);
  outline-offset: 3px;
  border-radius: var(--tp-radius-sm);
}

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


/* --------------------------------------------------------------------------
   19. THE TEAM

   A collage, not four cards. The portraits are anchors on a 12 x 10 grid;
   everything else is a tile from a small vocabulary that packs into the
   gaps. Leftover cells stay empty on purpose, so the block ends
   irregularly rather than as a filled rectangle.

   The tile vocabulary is the page's existing drawing language reduced to
   squares: halftone, hatching, rules, thin geometry, flat colour. Adding
   a tile is adding a <li>; nothing is positioned by hand except the four
   portraits.
   -------------------------------------------------------------------------- */

.tp-team .tp-container {
  display: flex;
  flex-direction: column;
  gap: var(--tp-section-y-tight);
}

.tp-team__head { display: flex; flex-direction: column; gap: var(--tp-space-md); }
.tp-team__heading { max-width: 20ch; }
.tp-team__intro { max-width: 52ch; }

/* --- The mosaic ---------------------------------------------------------- */
.tp-mosaic {
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  grid-auto-flow: row dense;
  gap: var(--tp-space-2xs);
}

/* The two lists are structure for the reader, not layout: their children
   place directly onto the mosaic grid. */
.tp-mosaic__people,
.tp-mosaic__tiles {
  display: contents;
  list-style: none;
  margin: 0;
  padding: 0;
}

.tp-mosaic__cell {
  position: relative;
  overflow: hidden;
  border-radius: var(--tp-radius-none);
  aspect-ratio: 1;
}

/* Photo cells set their own ratio through the grid span, so the ratio the
   photo component would otherwise impose is released here. */
.tp-mosaic__cell--photo { aspect-ratio: auto; }

.tp-mosaic__photo {
  position: relative;
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  border-radius: var(--tp-radius-none);
  margin: 0;
}

/* Taken out of flow on purpose. Left in flow the <img> contributes its own
   720x900 intrinsic height, which the grid then grows a row to satisfy,
   and the mosaic's aspect-ratio quietly stops holding. Absolute means the
   cell's size comes from the grid and nothing else. */
.tp-mosaic__photo .tp-photo__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Name label, set as a technical annotation rather than a caption: a Paper
   chip in the corner of the tile, in the label style used elsewhere. */
.tp-mosaic__tag {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  padding: var(--tp-space-3xs) var(--tp-space-2xs);
  background: var(--tp-paper);
  color: var(--tp-ink);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
}

/* --- Sizes --------------------------------------------------------------- */
.tp-mosaic__cell--w2 { grid-column: span 2; aspect-ratio: 2; }
.tp-mosaic__cell--h2 { grid-row: span 2; aspect-ratio: 0.5; }
.tp-mosaic__cell--w2.tp-mosaic__cell--h2 { aspect-ratio: 1; }

/* --- Textures ------------------------------------------------------------
   Drawn with gradients rather than image assets: they take their colour
   from the surface, so the same tile works on Paper, Stone or Ink. */
.tp-mosaic__cell--dots {
  background-image: radial-gradient(currentColor 1.5px, transparent 1.6px);
  background-size: 8px 8px;
  color: rgba(var(--tp-ink-rgb), 0.42);
}

.tp-mosaic__cell--hatch {
  background-image: repeating-linear-gradient(
    45deg,
    currentColor 0 1px,
    transparent 1px 7px
  );
  color: rgba(var(--tp-ink-rgb), 0.5);
}

.tp-mosaic__cell--rules {
  background-image: repeating-linear-gradient(
    to bottom,
    currentColor 0 1.5px,
    transparent 1.5px 7px
  );
  color: rgba(var(--tp-ink-rgb), 0.5);
}

/* --- Flat colour ---------------------------------------------------------
   Coral is the one focal accent, so it appears once and small. */
.tp-mosaic__cell--stone { background: var(--tp-paper); }
.tp-mosaic__cell--blue  { background: var(--tp-blue); }
.tp-mosaic__cell--ink   { background: var(--tp-ink); }
.tp-mosaic__cell--coral { background: var(--tp-coral); }

/* --- Thin geometry -------------------------------------------------------
   The guide's shape set: a filled disc, an outlined ring, a half and a
   quarter. Drawn with border and radius so they stay crisp at any size. */
.tp-mosaic__cell--disc::before,
.tp-mosaic__cell--ring::before,
.tp-mosaic__cell--half::before,
.tp-mosaic__cell--quarter::before {
  content: "";
  position: absolute;
  inset: 0;
}

.tp-mosaic__cell--disc::before {
  background: var(--tp-blue);
  border-radius: 50%;
}

.tp-mosaic__cell--ring::before {
  border: var(--tp-stroke-thick) solid var(--tp-fg);
  border-radius: 50%;
}

.tp-mosaic__cell--half::before {
  background: var(--tp-coral);
  border-radius: 100% 100% 0 0;
}

.tp-mosaic__cell--quarter::before {
  background: var(--tp-paper);
  border-radius: 100% 0 0 0;
}

/* --- Icon tile -----------------------------------------------------------
   Filled rather than outlined. An outlined box at this size reads as an
   empty cell with a hairline round it, which is not a tile. */
.tp-mosaic__cell--icon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--tp-ink);
}

/* Same override as the technology badges: the kit files write their own
   fills, so they are pulled back to the tile's colour. */
.tp-mosaic__cell--icon .tp-icon { width: 1.75rem; height: 1.75rem; color: var(--tp-paper); }
.tp-mosaic__cell--icon svg [fill]:not([fill="none"])     { fill: currentColor; }
.tp-mosaic__cell--icon svg [stroke]:not([stroke="none"]) { stroke: currentColor; }

/* --- The run -------------------------------------------------------------
   Joins two of the four. Same grammar as the discovery overlay: thin
   geometry, dashed for what is still being worked out, one Coral node.

   Non-scaling stroke keeps the line weight constant even though the SVG
   is stretched to the grid. */
.tp-mosaic__run {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
}

.tp-mosaic__run path {
  fill: none;
  stroke: var(--tp-fg);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

.tp-mosaic__run-arc  { stroke-dasharray: 5 4; }
.tp-mosaic__run-line { stroke-dasharray: 2 4; }

/* Nodes are drawn small: the run is an annotation over the collage, not a
   diagram in it. Radius is in viewBox units, so it is set here rather
   than trusting the markup to stay in proportion. */
.tp-mosaic__run-node {
  fill: var(--tp-graphic-bg);
  stroke: var(--tp-fg);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

.tp-mosaic__run-node--key { fill: var(--tp-coral); stroke: var(--tp-coral); }

/* --- The entries ---------------------------------------------------------- */
.tp-team__list {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-xl) var(--tp-grid-gap);
  list-style: none;
  padding-block-start: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
}

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

.tp-team__tag {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-coral);
}

.tp-team__role {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  color: var(--tp-fg);
  text-wrap: balance;
}

.tp-team__body {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--tp-fg-muted);
  max-width: 38ch;
}

.tp-team__closing {
  font-family: var(--tp-font-text);
  font-size: clamp(1.1875rem, 1.06rem + 0.5vw, 1.4375rem);
  font-weight: var(--tp-weight-roman);
  line-height: 1.5;
  color: var(--tp-fg-muted);
  max-width: 46ch;
  margin: 0;
}

.tp-team__closing em { font-style: normal; font-weight: 600; color: var(--tp-fg); }

/* The wider delivery team, named but not pictured: the founders carry this
   section and everyone else is one line and a link away. */
.tp-team__support {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tp-space-md);
}

/* Two founders get the full column each rather than a quarter. */
.tp-team--pair .tp-team__list { grid-template-columns: 1fr; }
.tp-team--pair .tp-team__body { max-width: 46ch; }

@media (min-width: 760px) {
  .tp-team--pair .tp-team__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   TEAM — WIDER

   The full 12 x 10 composition. Below this the mosaic is six columns and
   the portraits sit two by two, because a collage needs room to read as
   one and there is none at phone width.
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .tp-mosaic {
    grid-template-columns: repeat(12, minmax(0, 1fr));
    grid-template-rows: repeat(10, minmax(0, 1fr));
    aspect-ratio: 6 / 5;
  }

  /* The explicit rows size the cells here, so the ratio the stacked
     layout needs is released rather than fighting the grid. */
  .tp-mosaic__cell,
  .tp-mosaic__cell--w2,
  .tp-mosaic__cell--h2 { aspect-ratio: auto; }

  /* The four anchors. Staggered high and low across the width so the
     composition steps rather than sitting in a row. Every one is four
     wide by five tall, so the portraits share one aspect ratio. */
  .tp-mosaic__cell--p1 { grid-column: 1 / 5;   grid-row: 4 / 9;  }
  .tp-mosaic__cell--p2 { grid-column: 5 / 9;   grid-row: 1 / 6;  }
  .tp-mosaic__cell--p3 { grid-column: 7 / 11;  grid-row: 6 / 11; }
  .tp-mosaic__cell--p4 { grid-column: 9 / 13;  grid-row: 1 / 6;  }

  /* Two founders. Same 12 x 10 grid and the same square cells as the four,
     so the tile vocabulary keeps its proportions, but each portrait is
     five wide by six tall instead of four by five. The pair reads as the
     subject rather than as two of a set, and the tiles have room to fill
     the column between them without spilling into an implicit row. */
  .tp-team--pair .tp-mosaic__cell--p1 { grid-column: 1 / 6;  grid-row: 5 / 11; }
  .tp-team--pair .tp-mosaic__cell--p2 { grid-column: 8 / 13; grid-row: 1 / 7;  }

  .tp-team__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 899.98px) {
  /* Two by two, with a strip of texture under them. */
  .tp-mosaic__cell--photo { grid-column: span 3; grid-row: span 4; }

  /* The tall tiles are dropped here. At six columns they would add seven
     rows of decoration under the portraits, which turns the collage into
     a slab of texture with four faces on top of it. */
  .tp-mosaic__cell--h2 { display: none; }

  /* The run is drawn against the wide composition and means nothing
     against the stacked one. */
  .tp-mosaic__run { display: none; }
}

@media (min-width: 600px) and (max-width: 899.98px) {
  .tp-team__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* --------------------------------------------------------------------------
   20. THE CLOSE

   Ink, because the guide makes Ink the punctuation and this is the last
   thing on the page. The logo lands at size here for the only time: the
   word takes the surface's foreground, the :_ mark takes Coral, which is
   the one focal accent in this composition.
   -------------------------------------------------------------------------- */

.tp-cta__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-section-y-tight) var(--tp-grid-gap);
  align-items: start;
}

.tp-cta__say { display: flex; flex-direction: column; gap: var(--tp-space-md); }
.tp-cta__heading { max-width: 18ch; }
.tp-cta__lede,
.tp-cta__body { max-width: 46ch; }
.tp-cta__body { color: var(--tp-fg-muted); }

/* --- The logo -------------------------------------------------------------
   The file is authored with fill="currentColor" and two groups, so the
   word and the mark are coloured here rather than in the asset. */
.tp-cta__logo {
  width: min(100%, 22rem);
  margin-block-end: var(--tp-space-sm);
}

.tp-cta__logo svg { display: block; width: 100%; height: auto; }
.tp-cta__logo .tp-logo__word { fill: var(--tp-fg); }
.tp-cta__logo .tp-logo__mark { fill: var(--tp-coral); }

/* --- The form ------------------------------------------------------------
   Square, thin-ruled and transparent, so the controls read as the same
   drawn geometry as the rest of the page rather than as UI dropped on it.
   -------------------------------------------------------------------------- */
.tp-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-md);
}

.tp-form__trap {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

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

.tp-field__label {
  display: flex;
  align-items: baseline;
  gap: var(--tp-space-2xs);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg);
}

.tp-field__opt {
  letter-spacing: 0;
  text-transform: none;
  color: var(--tp-fg-muted);
}

.tp-field__control {
  width: 100%;
  padding: var(--tp-space-xs) var(--tp-space-sm);
  min-height: 52px;

  background: transparent;
  color: var(--tp-fg);

  font-family: var(--tp-font-text);
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);

  border: 1px solid var(--tp-field-line);
  border-radius: var(--tp-radius-none);
  transition: border-color var(--tp-duration-fast) var(--tp-ease);
}

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

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

.tp-field__control:focus-visible {
  outline: none;
  border-color: var(--tp-alert);
  box-shadow: inset 0 0 0 1px var(--tp-alert);
}

.tp-field__control--select {
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position:
    calc(100% - 1.05rem) 50%,
    calc(100% - 0.72rem) 50%;
  background-size: 0.36rem 0.36rem, 0.36rem 0.36rem;
  background-repeat: no-repeat;
  padding-inline-end: 2.75rem;
}

textarea.tp-field__control { resize: vertical; min-height: 8rem; }

/* Validation is shown only after a submit attempt, so the form does not
   scold anyone for a field they have not finished typing into. */
.tp-field__error {
  font-size: var(--tp-size-caption);
  line-height: var(--tp-lh-caption);
  font-weight: var(--tp-weight-medium);
  color: var(--tp-alert);
  display: none;
}

.tp-form.is-validated .tp-field__control:invalid { border-color: var(--tp-alert); }
.tp-form.is-validated .tp-field__control:invalid ~ .tp-field__error { display: block; }

.tp-form__error {
  margin: 0;
  font-size: var(--tp-size-caption);
  line-height: var(--tp-lh-caption);
  font-weight: var(--tp-weight-medium);
  color: var(--tp-alert);
}

.tp-cta__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tp-space-md);
}

.tp-cta__submit { justify-self: start; }
.tp-cta__submit:disabled { opacity: 0.6; cursor: progress; }

/* --- The reply ----------------------------------------------------------- */
.tp-form__done {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-2xs);
  padding: var(--tp-space-lg);
  border: 1px solid var(--tp-rule);
}

.tp-form__done-title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  color: var(--tp-fg);
}

.tp-form__done-body {
  margin: 0;
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);
  color: var(--tp-fg-muted);
  max-width: 40ch;
}

/* --- The closing band -----------------------------------------------------
   "Aligning people and technology": separate strands converging on one
   point and arriving together. It runs the full container so the dark
   disc sits under the argument and the Coral disc under the ask, which
   is the section's own left-to-right.

   The file is 1200x800 with a third of that height empty above and below
   the drawing. Rather than fork the asset for one crop, the SVG renders
   at its own ratio and is clipped: percentage margins resolve against the
   container's WIDTH, so -18.34% top and bottom leaves a 1200x360 band and
   the crop holds at every size.
   -------------------------------------------------------------------------- */
.tp-cta__band {
  overflow: hidden;
  margin-block-start: var(--tp-section-y-tight);
}

.tp-cta__band .tp-graphic {
  aspect-ratio: auto;
  margin-block: -18.34%;
}

@media (min-width: 860px) {
  .tp-cta__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .tp-cta__band { grid-column: 1 / -1; }
  .tp-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tp-field--wide,
  .tp-form__error,
  .tp-cta__actions { grid-column: 1 / -1; }
}


/* --------------------------------------------------------------------------
   21. THE FOUR VISIONS — THE DIAL

   One circle, most of it off the left edge, with the four visions on the
   arc. The section pins and the ring turns as you scroll.

   Two layouts share one set of markup. The DIAL runs at 900px and up with
   motion allowed; everything else gets the panels flowing normally, which
   is also the no-JS and no-CSS-support state. The dial is opt-IN
   (.is-dial, added by the script once it has decided it can run) so the
   readable layout is what you get by default and the enhancement has to
   earn its way in.
   -------------------------------------------------------------------------- */

.tp-visions .tp-container { display: flex; flex-direction: column; gap: var(--tp-space-md); }
.tp-visions__heading { max-width: 20ch; margin-block-end: var(--tp-space-2xs); }
.tp-visions__intro { max-width: 56ch; }
.tp-visions__lead-in { max-width: 52ch; color: var(--tp-fg); }

/* --- Fallback: the four as ordinary panels -------------------------------- */
.tp-dial__ring,
.tp-dial__controls { display: none; }

.tp-dial__panels {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  list-style: none;
  margin-block-start: var(--tp-section-y-tight);
}

.tp-vision {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tp-space-md);
  padding-block: var(--tp-space-2xl);
  border-block-start: 1px solid var(--tp-rule);
}

.tp-vision:first-child { border-block-start: 0; padding-block-start: 0; }
.tp-vision:last-child  { padding-block-end: 0; }

.tp-vision__body { display: flex; flex-direction: column; align-items: flex-start; gap: var(--tp-space-md); }
.tp-vision__mark { display: none; }

/* The vision's NAME leads. It was the small label under the question, which
   asked the reader to answer something before telling them what it was
   about. */
/* Set as .tp-h2, the same as every other section title on the page, so it
   carries the scale's size, weight, tracking and the Coral cursor rather
   than a size picked for this one place. Only the layout is local. */
.tp-vision__title {
  margin-block-end: var(--tp-space-2xs);
  max-width: 20ch;
}

/* The question, now a lead into the copy rather than the heading. Set in
   the text face so it reads as a sentence being asked, not a label. */
.tp-vision__lead {
  margin: 0;
  font-family: var(--tp-font-text);
  font-size: var(--tp-size-body-lg);
  line-height: var(--tp-lh-body-lg);
  color: var(--tp-fg);
  max-width: 40ch;
}

.tp-vision__text {
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);
  color: var(--tp-fg-muted);
  max-width: 54ch;
}

/* The fourteen visions, surfaced only here. Tagged terms rather than
   links, so this stays a point of view and not a menu. */
.tp-vision__includes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-space-2xs) var(--tp-space-xs);
  list-style: none;
  margin: 0;
  padding: 0;
}

.tp-vision__includes li {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: 0.02em;
  color: var(--tp-fg-muted);
  padding: var(--tp-space-3xs) var(--tp-space-2xs);
  border: 1px solid var(--tp-rule);
}

.tp-vision__more { margin-block-start: var(--tp-space-2xs); }

.tp-visions .tp-container { gap: var(--tp-space-lg); }

/* Anchored to the section, not the stage, so it sits under the whole run
   rather than travelling with the dial. Sage is the palette's quiet
   counterweight to the Coral spent on the active node.

   NO overflow here. The wedge sits inside the section's bounds and needs no
   clipping, and any overflow value other than visible makes this a scroll
   container, which stops the pinned stage inside it from sticking to the
   viewport. */
/* The band runs to the section's top edge and carries that padding itself. */
.tp-visions { position: relative; padding-block-start: 0; }

/* The graphic on the seam between Progress and the Visions. Four strokes
   rising out of one section and resolving into the next, which is the join
   the two sections make in words.

   Absolute against the section and pulled up by 60% of its own height, not
   50%: the artwork sits in the lower part of its 1200x800 box, so centring
   the BOX would leave the drawing below the line rather than across it. */
.tp-visions__seam {
  position: absolute;
  top: 0;
  left: clamp(-4rem, -3vw, -1.5rem);
  width: clamp(14rem, 21vw, 21rem);
  transform: translateY(-60%);
  z-index: 4;
  pointer-events: none;
}

.tp-visions__wedge {
  position: absolute;
  inset-block-end: 0;
  inset-inline-end: 0;
  width: clamp(9rem, 18vw, 20rem);
  aspect-ratio: 1;
  background: var(--tp-sage);
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
  pointer-events: none;
  z-index: 0;
}

.tp-visions__closing {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: clamp(1.375rem, 1.1rem + 1.2vw, 2rem);
  font-weight: var(--tp-weight-medium);
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--tp-fg);
  max-width: 30ch;
  text-wrap: balance;
  padding-block-start: var(--tp-space-xl);
  border-block-start: 1px solid var(--tp-rule);
}

/* --------------------------------------------------------------------------
   The dial itself
   -------------------------------------------------------------------------- */
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {

  .tp-dial.is-dial {
    /* Two numbers tune the dial. The radius is NOT one of them: it is
       derived, because the arc has to meet the screen's top and bottom
       edges and that depends on the stage height. For a circle bulging in
       by e across a stage of height H, R = e/2 + H squared / 8e, which
       needs a length squared and so cannot be a calc(). The script works
       it out and writes it here. */
    --tp-dial-bulge: 9rem;      /* how far past the left edge the arc comes */
    --tp-dial-gap: 22deg;       /* angle between visions on the arc */
    --tp-dial-step: 92vh;       /* scroll travel per vision */

    /* Extra track after the last vision, in stage heights, so the section
       holds on that vision instead of unpinning the moment it arrives.

       Unitless on purpose. The stylesheet spends it as vh and the script
       spends it as a multiple of the stage, and the stage is exactly 100vh,
       so the two agree by construction rather than by two numbers being
       kept in step by hand. */
    --tp-dial-hold: 0.6;

    position: relative;
    height: calc(
      var(--tp-dial-count, 4) * var(--tp-dial-step)
      + var(--tp-dial-hold) * 100vh
    );
  }

  /* The pinned stage. Sticky rather than a JS pin: the browser does the
     work, it cannot desync from the scroll, and it survives the script
     failing. */
  .tp-dial.is-dial .tp-dial__stage {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    overflow: hidden;
  }

  .tp-dial.is-dial .tp-dial__inner {
    position: relative;
    width: 100%;
    min-height: 26rem;
  }

  /* --- The ring ----------------------------------------------------------
     Centred off the left edge so only the right of the arc is on screen.
     The equator, where the active vision sits, is the circle's rightmost
     point: dial centre + radius. */
  .tp-dial.is-dial .tp-dial__ring {
    display: block;
    position: absolute;
    inset-block-start: 50%;
    /* Left edge is written by the script alongside the radius: both fall
       out of the same bit of geometry. */
    width: 0;
    height: 0;
    /* Purely an anchor. The visions are placed at their own angles by the
       script rather than by rotating this element, so the whole dial is one
       transform per moving thing and nothing depends on a parent's. */
    z-index: 0;
  }

  .tp-dial.is-dial .tp-dial__arc {
    position: absolute;
    inset-block-start: calc(var(--tp-dial-r, 0px) * -1);
    inset-inline-start: calc(var(--tp-dial-r, 0px) * -1);
    width: calc(var(--tp-dial-r, 0px) * 2);
    height: calc(var(--tp-dial-r, 0px) * 2);
    border: 1px solid var(--tp-rule);
    border-radius: 50%;
  }

  /* Each vision is placed at its own angle and pushed out to the radius,
     written by the script: one transform, on the element that moves. */
  .tp-dial.is-dial .tp-dial__item {
    position: absolute;
    inset: 0;
    transition: transform var(--tp-duration-slow) var(--tp-ease-out);
  }

  /* The node stays on the arc. */
  .tp-dial.is-dial .tp-dial__node {
    position: absolute;
    inset-block-start: -4px;
    inset-inline-start: -4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--tp-rule);
    transition: background-color var(--tp-duration) var(--tp-ease);
  }

  /* The number sits just outside the arc. It rides the ring rather than
     being held upright: at each stop its placement angle and the ring's
     rotation cancel, so the active one stands up and the rest lie along
     the tangent. That tilt is the point. */
  .tp-dial.is-dial .tp-dial__num {
    position: absolute;
    inset-block-start: -2.75rem;
    inset-inline-start: var(--tp-space-md);
    display: block;
    font-family: var(--tp-font-display);
    font-size: clamp(3.25rem, 6vw, 5.5rem);
    font-weight: var(--tp-weight-bold);
    line-height: 1;
    letter-spacing: -0.03em;
    color: var(--tp-fg);
    opacity: 0.13;
    transition: opacity var(--tp-duration-slow) var(--tp-ease-out);
  }

  /* Rides up on the number's shoulder, the way a footnote marker does. */
  .tp-dial.is-dial .tp-dial__num { position: absolute; }

  .tp-dial.is-dial .tp-dial__sup {
    position: absolute;
    inset-block-start: -0.28em;
    inset-inline-start: calc(100% + 0.14em);
    display: block;
    /* Wider than an icon would be: this is the same landscape graphic that
       sits beside the copy, so the mark on the arc and the mark in the
       panel are one thing at two sizes. */
    width: 3.25rem;
  }

  .tp-dial.is-dial .tp-dial__sup .tp-graphic { width: 100%; }

  .tp-dial.is-dial .tp-dial__item.is-active .tp-dial__num { opacity: 1; }
  .tp-dial.is-dial .tp-dial__item.is-active .tp-dial__node { background: var(--tp-coral); }

  /* --- The panels --------------------------------------------------------
     Stacked in one place beside the equator, one shown at a time. Grid
     rather than absolute positioning so the stack is as tall as its
     tallest member and nothing jumps as they change. */
  /* One column holds the write-ups and the controls. The arrow used to be
     positioned to a matching offset, which put it a gutter out: the panels
     are offset from the container's CONTENT box and an absolute inset is
     measured from its padding box. Sharing a box removes the arithmetic. */
  .tp-dial.is-dial .tp-dial__copy {
    margin-inline-start: clamp(6rem, 11vw, 12rem);
    max-width: 58rem;
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: var(--tp-space-2xl);
  }

  .tp-dial.is-dial .tp-dial__panels {
    display: grid;
    margin-block-start: 0;
  }

  /* An abstract mark from the graphic system rather than a literal icon,
     which is also what ties this section back to the rest of the page.
     Beside the copy rather than above it: stacked, the panel ran to 600px
     and pushed the section taller than it needed to be. */
  .tp-dial.is-dial .tp-vision__mark {
    display: block;
    align-self: center;
    justify-self: end;
    width: 100%;
  }

  .tp-dial.is-dial .tp-vision__mark .tp-graphic { width: 100%; }

  .tp-dial.is-dial .tp-vision {
    grid-area: 1 / 1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(9rem, 16vw, 15rem);
    align-items: center;
    gap: var(--tp-grid-gap);
    padding-block: 0;
    border-block-start: 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(0.75rem);
    transition: opacity var(--tp-duration) var(--tp-ease),
                transform var(--tp-duration) var(--tp-ease-out),
                visibility 0s linear var(--tp-duration);
  }

  .tp-dial.is-dial .tp-vision__more,
  .tp-visions .tp-vision__more {
    background: transparent;
    border: 0;
    padding-inline: 0;
    min-height: 0;
    color: var(--tp-fg);
  }

  .tp-dial.is-dial .tp-vision.is-active {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: opacity var(--tp-duration) var(--tp-ease),
                transform var(--tp-duration) var(--tp-ease-out),
                visibility 0s;
  }

  /* --- Controls ----------------------------------------------------------
     For anyone who does not realise the section is scroll-driven. They
     scroll TO a position rather than moving the ring themselves, so scroll
     stays the single source of truth. */
  .tp-dial.is-dial .tp-dial__controls {
    display: flex;
    align-items: center;
    gap: var(--tp-space-md);
  }

  .tp-dial.is-dial .tp-dial__arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    padding: 0;
    background: transparent;
    color: var(--tp-fg);
    border: 1px solid var(--tp-rule);
    border-radius: var(--tp-radius-none);
    cursor: pointer;
    transition: border-color var(--tp-duration-fast) var(--tp-ease),
                color var(--tp-duration-fast) var(--tp-ease);
  }

  .tp-dial.is-dial .tp-dial__arrow svg { width: 1.25rem; height: auto; }

  .tp-dial.is-dial .tp-dial__arrow:hover:not(:disabled),
  .tp-dial.is-dial .tp-dial__arrow:focus-visible:not(:disabled) { border-color: var(--tp-fg); }

  .tp-dial.is-dial .tp-dial__arrow:disabled { opacity: 0.3; cursor: default; }

  .tp-dial.is-dial .tp-dial__count {
    margin: 0;
    font-family: var(--tp-font-display);
    font-size: var(--tp-size-label);
    font-weight: var(--tp-weight-medium);
    letter-spacing: var(--tp-tracking-label);
    text-transform: uppercase;
    color: var(--tp-fg-muted);
    font-variant-numeric: tabular-nums;
  }
}


/* --------------------------------------------------------------------------
   22. WHY PATH

   Short: the four visions have just made a large claim, and this says on
   what basis. Copy left, the aligning graphic right.
   -------------------------------------------------------------------------- */

.tp-why__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-section-y-tight) var(--tp-grid-gap);
  align-items: center;
}

.tp-why__say { display: flex; flex-direction: column; gap: var(--tp-space-md); }
.tp-why__heading { max-width: 18ch; }
.tp-why__body { max-width: 50ch; color: var(--tp-fg-muted); }

/* The one belief from the standards work that earns a place here. */
.tp-why__closing {
  margin: 0;
  margin-block-start: var(--tp-space-2xs);
  font-family: var(--tp-font-text);
  font-size: clamp(1.1875rem, 1.06rem + 0.5vw, 1.4375rem);
  line-height: 1.5;
  color: var(--tp-fg);
  max-width: 44ch;
}

.tp-why__closing em { font-style: normal; font-weight: 600; }

.tp-why__figure .tp-graphic { width: 100%; }

@media (min-width: 900px) {
  .tp-why__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); }
}


/* --------------------------------------------------------------------------
   23. PROGRESS — STAIRCASE VARIANT

   Alternative layout for section 13's content. Its own namespace so the two
   can sit in the codebase together and neither can break the other; swapping
   between them is one line in the page.

   The four steps climb from bottom left to top right. A row of four says
   "here are four items"; a staircase says "this accumulates", which is what
   the section claims, and it repeats at section scale what the first figure
   does inside its own square.
   -------------------------------------------------------------------------- */

.tp-stair { position: relative; }

.tp-stair .tp-container {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-section-y-tight) var(--tp-grid-gap);
}

.tp-stair__head { display: flex; flex-direction: column; gap: var(--tp-space-md); }
.tp-stair__q { max-width: 16ch; margin-block-end: var(--tp-space-2xs); }
.tp-stair__intro { max-width: var(--tp-measure); }

/* --- The steps ------------------------------------------------------------
   Stacked at phone width. The climb only makes sense once there is width to
   climb across. */
.tp-stair__steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-2xl) var(--tp-grid-gap);
  list-style: none;
}

.tp-stair__step {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tp-space-2xs);
}

.tp-stair__fig { display: block; width: 100%; height: auto; margin-block-end: var(--tp-space-sm); }

.tp-stair__step-label {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg-muted);
}

/* Set as an eyebrow rather than a heading: at this card size a bold line
   competes with the figure it belongs to. */
.tp-stair__step-title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-medium);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg);
}

/* Final step carries the resolution, so it takes the accent. */
.tp-stair__step--resolve .tp-stair__step-title { color: var(--tp-coral); }

.tp-stair__step-label { display: none; }

.tp-stair__jump {
  display: inline-flex;
  margin-block-start: auto;
  padding-block-start: var(--tp-space-sm);
  color: var(--tp-fg-muted);
  transition: color var(--tp-duration-fast) var(--tp-ease),
              transform var(--tp-duration) var(--tp-ease-out);
}

.tp-stair__jump svg { display: block; width: 1.125rem; height: auto; }

.tp-stair__jump:hover,
.tp-stair__jump:focus-visible { color: var(--tp-coral); transform: translateY(3px); }

/* --- The close ------------------------------------------------------------ */
.tp-stair__close {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--tp-space-md);
  padding-block-start: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
}

.tp-stair__closing {
  margin: 0;
  font-family: var(--tp-font-text);
  font-size: clamp(1.1875rem, 1.06rem + 0.5vw, 1.4375rem);
  line-height: 1.5;
  color: var(--tp-fg-muted);
  max-width: 52ch;
}

.tp-stair__closing em { font-style: normal; font-weight: 600; color: var(--tp-fg); }

/* --- Motion ---------------------------------------------------------------
   Same additive rule as the row: the resting state is the finished figure,
   so the section reads without JS. */
.tp-stair__fig-shape {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 800ms var(--tp-ease-out), opacity 600ms var(--tp-ease-out);
}

.thepath.tp-animate .tp-stair__fig-shape { transform: scale(0.4); opacity: 0; }
.thepath.tp-animate .is-visible .tp-stair__fig-shape { transform: none; opacity: 1; }

/* --------------------------------------------------------------------------
   The climb
   -------------------------------------------------------------------------- */
@media (min-width: 860px) {
  /* A wider container for this section alone. The copy needs its measure
     and the climb needs run to the right of it; at the standard width one
     of the two has to give. */
  .tp-stair { --tp-container: var(--tp-container-wide); }

  /* Copy left, climb right, both starting on the same line: that is what
     puts the top of the top card level with the top of the content. The
     tracks are proportional rather than sized, so the copy keeps a real
     measure and the climb takes whatever is left, at every width. */
  .tp-stair .tp-container {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: start;
  }

  .tp-stair__head  { grid-column: 1; grid-row: 1; }
  .tp-stair__steps { grid-column: 2; grid-row: 1; }
  .tp-stair__close { grid-column: 1 / -1; }

  .tp-stair__steps {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0;
    align-items: start;
  }

  /* Square, and sized by its column rather than by a number. */
  .tp-stair__fig {
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    margin-block-end: var(--tp-space-2xs);
  }

  /* The climb, in percentages on purpose. A block-axis margin percentage
     resolves against the INLINE size of the containing block, which for a
     grid item is its own track: 100% is exactly one card width, and the
     card is square, so 100% is also exactly one card height. That is the
     corner rule expressed once. Each card's bottom-left corner meets the
     previous card's top-right at any container width, with no measuring
     and nothing to keep in sync. */
  .tp-stair__step:nth-child(1) { margin-block-start: 300%; }
  .tp-stair__step:nth-child(2) { margin-block-start: 200%; }
  .tp-stair__step:nth-child(3) { margin-block-start: 100%; }
  .tp-stair__step:nth-child(4) { margin-block-start: 0; }

  .tp-stair__jump { margin-block-start: var(--tp-space-2xs); padding-block-start: 0; }
}


/* --------------------------------------------------------------------------
   24. BANDED SECTION HEAD

   See components/thepath/band.html for what it is and why.
   -------------------------------------------------------------------------- */

.tp-band {
  /* The conversation photograph, top right. */
  --tp-band-photo: clamp(13rem, 18vw, 20rem);

  position: relative;
}

/* A flat tinted field across the top of the section. It stops the sections
   bleeding into one another, which an unbroken run of Paper never does.

   It clips, which is what lets the photograph sit against its edge. Safe
   here where overflow would not be on the section itself: the dial's sticky
   stage is outside this element. */
.tp-band__field {
  position: relative;
  padding-block: var(--tp-section-y);
  background-color: var(--tp-bg);
  overflow: hidden;
}

/* The angled split: the ground to the right of a 45 degree edge sits a step
   lighter than the ground to its left. No line on the edge, so the tone
   change is the only thing drawing it.

   One rotated block whose bottom edge IS the boundary, rather than a
   gradient. A gradient's hard stop sits at a fraction along an axis whose
   length depends on the box's proportions, so the boundary would land
   somewhere different at every width. */
.tp-band__field::before {
  content: '';
  position: absolute;
  left: 34%;                       /* where the edge meets the top */
  bottom: 100%;
  width: 300%;
  height: 300%;
  background: color-mix(in srgb, var(--tp-bg) 55%, var(--tp-paper));
  transform-origin: 0 100%;
  transform: rotate(45deg);
  pointer-events: none;
  z-index: 0;
}

/* The copy sits above the split and above the discs. */
.tp-band__field > .tp-container { position: relative; z-index: 2; }

/* The field's padding used to be derived from the photograph, so the copy
   column could clear it. The copy is gone and the headline is set left, so
   the photograph has the whole right side to itself and the padding is just
   the section rhythm again, equal top and bottom. */

/* --- The stage ------------------------------------------------------------
   Positioning context for the panel, which has to be able to break across
   the headline rather than sit under it. */
.tp-band__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-xl);
}

/* Pinned to the top left, the way the reference pins its annotations: it is
   a label on the field, not the first line of the copy. */
.tp-band__note { align-self: flex-start; }

/* The headline, set left. A measure in characters rather than a width, so it
   breaks into a block of display type at any size instead of one long line. */
.tp-band__display {
  max-width: 18ch;
  text-align: left;
}

/* The wrap-up, on the field's bottom left edge. Set against the section
   rather than the container, opposite the photograph, which is inset the
   same 50px from its own edge. Each span is a line, and the component
   decides which words land on which, so the two-word count is guaranteed
   rather than hoped for from a narrow column. */
.tp-band__wrap {
  position: absolute;
  left: 50px;
  bottom: var(--tp-space-md);
  margin: 0;
  z-index: 2;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  font-weight: var(--tp-weight-medium);
  line-height: 1.4;
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg-muted);
}

.tp-band__wrap span { display: block; }

/* --- The discs ------------------------------------------------------------
   Four circles stepping up and to the right, from behind the headline toward
   the photograph, each smaller and lighter than the last.

   Every one is mixed from --tp-bg rather than given a colour of its own, so
   changing the field's surface carries the whole cascade with it instead of
   leaving four values behind that used to match. Sizes and centres are
   percentages of the FIELD, which is the same box the photograph is placed
   against, so the run actually arrives where it is aimed.
   ------------------------------------------------------------------------ */
.tp-band__discs {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

.tp-band__disc {
  position: absolute;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}

.tp-band__disc:nth-child(1) {
  left: 52%; top: 52%; width: 30%;
  background: color-mix(in srgb, var(--tp-bg) 38%, var(--tp-paper));
}

.tp-band__disc:nth-child(2) {
  left: 63%; top: 44%; width: 21%;
  background: color-mix(in srgb, var(--tp-bg) 27%, var(--tp-paper));
}

.tp-band__disc:nth-child(3) {
  left: 72%; top: 36%; width: 14%;
  background: color-mix(in srgb, var(--tp-bg) 17%, var(--tp-paper));
}

.tp-band__disc:nth-child(4) {
  left: 79%; top: 31%; width: 9%;
  background: color-mix(in srgb, var(--tp-bg) 8%, var(--tp-paper));
}

/* --- The photograph -------------------------------------------------------
   Under its registration overlay, whole, top right. A circle: the page's
   other photographs are circles, and the overlay was drawn on a square, so
   the crop takes its corners rather than its subject. */
.tp-band__feature {
  position: absolute;
  top: var(--tp-space-md);
  right: 50px;
  width: var(--tp-band-photo);
  aspect-ratio: 1;
  margin: 0;
  border-radius: 50%;
  overflow: hidden;
  background: var(--tp-paper);
  z-index: 2;
}

.tp-band__feature img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(0.74) contrast(0.94) sepia(0.1);
}

/* Goes where the layout stacks and there is no longer a right side for it
   to sit in. */
@media (max-width: 859px) {
  .tp-band__feature { display: none; }
}

/* --- The cue --------------------------------------------------------------
   Covers the field's own box and draws outside it, so both ends can be given
   in one coordinate system: the script sets the viewBox to the field's pixel
   size, which makes one user unit one pixel and lets it place the path
   straight from measured positions. */
.tp-band__cue {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--tp-coral);
  overflow: visible;
  pointer-events: none;
  z-index: 3;
}



/* --------------------------------------------------------------------------
   25. THE CLIMB

   See components/thepath/climb.html. A Coral column with a Paper ribbon
   winding down through it and the stops set either side, numbered.

   Three numbers describe it: the column's width, how far the ribbon swings
   inside that column, and how much it tapers. The script reads all three
   rather than carrying its own copies, so the drawing and the layout cannot
   disagree.
   -------------------------------------------------------------------------- */

.tp-climb {
  /* The artwork's own width. Everything else is derived from it: it is
     720 x 1469.32, so the run cannot be shorter than that ratio without
     squashing the drawing. */
  --tp-climb-col: clamp(8rem, 38vw, 38rem);
  --tp-climb-ratio: 2.0407;

  /* Clear air between the copy and the drawing's box. Measured from the box
     rather than the ink: the drawing's own width varies down its length, so
     holding to the ink would move the copy about from stop to stop. */
  --tp-climb-gap: clamp(1.5rem, 4.5vw, 4.5rem);

  /* One width for every stop's copy. A max-width would let each block shrink
     to its own longest line, so the left-hand stops would each start
     somewhere different and there would be no left edge to align the title
     to in the first place. */
  --tp-climb-say: 15rem;
}

/* Small, and set on the left-hand stops' own edge. The reference sets its
   title as a caption on the drawing rather than as a headline above it, and
   that is the whole reason the shape gets to be the loud thing. */
.tp-climb__head {
  display: grid;
  grid-template-columns: 1fr var(--tp-climb-col) 1fr;
  margin-block-end: var(--tp-section-y-tight);
}

/* Spans the whole head rather than sitting in track 1, because the title is
   set at section scale and a 15rem track would break it to five lines. It
   still STARTS on the left-hand stops' edge: that offset is the track, less
   the gap, less the stop's own width, which is exactly where they begin. Derived,
   so it follows if any of those three change. */
.tp-climb__title {
  grid-column: 1 / -1;
  justify-self: start;
  margin-inline-start: calc(
    50% - var(--tp-climb-col) / 2 - var(--tp-climb-gap) - var(--tp-climb-say)
  );
  width: min(42rem, 100%);
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-sm);
}

/* Set at the section scale the rest of the site uses for its titles, sentence
   case rather than the caption treatment it had. */
.tp-climb__sub { max-width: 20ch; }

.tp-climb__sub span { display: block; }

/* The cursor moves onto the last LINE. .tp-h2's own ::after would sit after
   the final block child, which puts it alone on a line of its own. */
.tp-climb__sub::after { content: none; }

.tp-climb__sub span:last-child::after {
  content: "_";
  color: var(--tp-coral);
  margin-inline-start: 0.06em;
}

/* --- The run --------------------------------------------------------------
   Exactly the artwork's own height, not a floor. The box is then the same
   proportion as the drawing, so the drawing is never stretched: the copy is
   cut to fit the plate rather than the plate stretched to fit the copy. */
.tp-climb__run {
  position: relative;
  height: calc(var(--tp-climb-col) * var(--tp-climb-ratio));
}

/* The artwork. It carries preserveAspectRatio="none" in the file, but the box
   above is its own proportion, so the horizontal and vertical scales come out
   equal and nothing is actually distorted. That only holds while the run's
   height is derived from --tp-climb-ratio: change one without the other and
   the figures on the path stretch.

   (preserveAspectRatio is an SVG attribute, not a CSS property. Setting it in
   a stylesheet does nothing at all, silently.) */
.tp-climb__column {
  position: absolute;
  inset-block: 0;
  left: 50%;
  width: var(--tp-climb-col);
  transform: translateX(-50%);
  z-index: 0;
}

.tp-climb__column .tp-graphic,
.tp-climb__column > .tp-graphic svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* --- Registration marks ---------------------------------------------------
   Laid over the artwork on the same viewBox and stretched the same way, so a
   ring drawn at a figure's coordinates lands on that figure with nothing
   measured. Thin geometry and no fill, per the guide: the drawing stays the
   subject and these annotate it. */
.tp-climb__marks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.tp-climb__marks :where(circle, line) {
  fill: none;
  stroke: var(--tp-ink);
  stroke-width: 1;
  opacity: 0.3;
  /* Constant hairline whatever the box is scaled to, and immune to the
     horizontal squeeze the stretch would otherwise put on it. */
  vector-effect: non-scaling-stroke;
}

/* --- The plate's furniture ------------------------------------------------
   A label in the far bottom corner, on the stops' own edge rather than the
   container's, so the plate reads as having its own margins. */
.tp-climb__foot {
  display: grid;
  grid-template-columns: 1fr var(--tp-climb-col) 1fr;
  margin-block-start: var(--tp-section-y-tight);
}

.tp-climb__footnote {
  grid-column: 1;
  justify-self: end;
  width: min(var(--tp-climb-say), 100%);
  margin: 0;
  margin-inline-end: var(--tp-climb-gap);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  font-weight: var(--tp-weight-medium);
  line-height: 1.4;
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-fg-muted);
}

.tp-climb__footnote span { display: block; }


/* --- The stops ------------------------------------------------------------
   Three tracks: copy, the column, copy. Odd stops take the left track and
   even ones the right, so the reader zigzags with the ribbon rather than
   running down one rail.
   -------------------------------------------------------------------------- */
.tp-climb__stops {
  position: relative;
  z-index: 2;
  list-style: none;
  display: grid;
  grid-template-columns: 1fr var(--tp-climb-col) 1fr;
}

.tp-climb__stop {
  position: relative;
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
  align-items: center;
  padding-block: clamp(1rem, 2.5vw, 2.5rem);
}

/* The run is floored at the artwork's height, so the stops are stretched to
   fill it rather than bunching at the top and leaving the drawing running on
   under empty space. */
.tp-climb__stops {
  height: 100%;
  align-content: space-between;
}

.tp-climb__say {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-2xs);
  width: min(var(--tp-climb-say), 100%);
}

/* A disc behind each stop, a shade lighter than the ground, so the copy sits
   on something rather than floating on the plate.

   Sized as a percentage of the copy's own box, not a fixed width, so it
   holds its relationship to the text at every viewport instead of being a
   number that happens to look right at one. */
.tp-climb__say::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 128%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--tp-cream-lift);
  z-index: -1;
  pointer-events: none;
}

/* Held off the column. Without the gap the copy runs right up to the Coral
   edge and, at the widths where a line happens to be long, over it. */
/* Every stop is set left, both sides of the drawing. Ranging the left-hand
   ones right would mirror the type as well as the position, and the page
   would have two reading edges instead of one. */
.tp-climb__stop:nth-child(odd) .tp-climb__say {
  grid-column: 1;
  justify-self: end;
  margin-inline-end: var(--tp-climb-gap);
}

.tp-climb__stop:nth-child(even) .tp-climb__say {
  grid-column: 3;
  justify-self: start;
  margin-inline-start: var(--tp-climb-gap);
}

/* The number is the structure of the plate, so it is set as one: display
   scale and bold, the way the dial sets its own. Tabular figures, because
   these are a numbered set and their widths should not wander. */
.tp-climb__num {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h2-sm);
  font-weight: var(--tp-weight-bold);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--tp-coral);
  font-variant-numeric: tabular-nums;
  margin-block-end: var(--tp-space-3xs);
}

/* An h2 by role and a caption by size. On a plate like this the label is a
   marker on the path, not a section heading. */
.tp-climb__label {
  margin: 0;
  font-family: var(--tp-font-ui);
  font-size: var(--tp-size-h3);
  font-weight: var(--tp-weight-bold);
  line-height: var(--tp-lh-h3);
  letter-spacing: -0.012em;
  color: var(--tp-fg);
}

/* The same cursor every title on the site closes on, generated rather than
   typed so it can never be edited out of the copy by accident. */
.tp-climb__label::after {
  content: "_";
  color: var(--tp-coral);
  margin-inline-start: 0.08em;
}

/* Set in the UI face, not the text face. At caption size against a drawing
   this size the serif reads as a footnote; the sans reads as an annotation
   on the plate, which is what it is.

   Full foreground rather than muted. At 13px on this ground the muted grey
   was doing two jobs at once, marking the copy as secondary AND making it
   harder to read; the size already says which it is. */
.tp-climb__body,
.tp-climb__asks {
  margin: 0;
  font-family: var(--tp-font-ui);
  font-size: var(--tp-size-caption);
  line-height: 1.5;
  color: var(--tp-fg);
}

.tp-climb__asks { list-style: none; display: flex; flex-direction: column; gap: 0.2rem; }

/* Same weight of ink as the body it follows. The landing line is picked out
   in Coral, so the grading no longer has to be carried by holding these
   back. */
.tp-climb__close {
  margin: 0;
  font-family: var(--tp-font-ui);
  font-size: var(--tp-size-caption);
  font-weight: var(--tp-weight-medium);
  line-height: 1.45;
  color: var(--tp-fg);
}

.tp-climb__close span { display: block; }

/* The line each stop lands on, in Coral. See the note in the review below:
   Coral on this ground is about 2.7:1, which is under what a sentence needs,
   so this is a deliberate call rather than an oversight. */
.tp-climb__land { color: var(--tp-coral); font-weight: var(--tp-weight-bold); }

/* --- Narrow ---------------------------------------------------------------
   The column moves left and every stop sits to its right. A zigzag needs two
   columns of room; below that it is just text jumping about. */
@media (max-width: 859px) {
  .tp-climb { --tp-climb-col: 4.5rem; }

  /* The run goes back to being sized by the copy: a 4.5rem column at the
     drawing's proportion would be 9rem tall, which is nothing. The Coral
     stretches, which it can take, and the figures are pulled because they
     cannot: at this width they would be a few pixels of smear. */
  .tp-climb__run { height: auto; }
  .tp-climb__stops { height: auto; }
  .tp-climb__column svg path[fill*="--tp-ink"] { display: none; }

  .tp-climb__column { left: var(--tp-gutter); transform: none; }

  /* One column, so the head goes back to being an ordinary block on the
     container's own edge. */
  .tp-climb__head,
  .tp-climb__foot { display: block; }

  .tp-climb__title,
  .tp-climb__footnote { width: auto; margin-inline: 0; }

  /* The marks go with the figures they annotate. */
  .tp-climb__marks { display: none; }
  .tp-climb__say { width: auto; max-width: 34ch; }

  /* No disc: at this width the copy runs nearly the full column, so a circle
     around it would be wider than the screen. */
  .tp-climb__say::before { display: none; }
  .tp-climb__stops { grid-template-columns: calc(var(--tp-gutter) + var(--tp-climb-col)) 1fr; }

  .tp-climb__stop:nth-child(odd) .tp-climb__say,
  .tp-climb__stop:nth-child(even) .tp-climb__say {
    grid-column: 2;
    justify-self: start;
    text-align: left;
    margin-inline: 0;
    padding-inline: var(--tp-space-lg) var(--tp-gutter);
  }
}


/* ==========================================================================
   VISION PAGES
   ========================================================================== */

.tp-vision-page { background: var(--tp-paper); }

.tp-vp-hero {
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  min-height: min(88vh, 48rem);
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-vp-hero__shape {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(12rem, 30vw, 28rem);
  aspect-ratio: 1;
  pointer-events: none;
  overflow: visible;
}

.tp-vp-hero__shape-mark {
  fill: none;
  stroke: rgba(var(--tp-ink-rgb), 0.28);
  stroke-width: 0.7;
  stroke-dasharray: 2.4 2.4;
  vector-effect: non-scaling-stroke;
}

.tp-vp-hero--rectangle .tp-vp-hero__shape {
  width: clamp(14rem, 34vw, 30rem);
}

.tp-vp-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-vp-hero__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 2;
}

.tp-vp-hero__copy { max-width: 860px; }
.tp-vp-hero__title { margin-block-start: var(--tp-space-md); }

.tp-vp-hero__kicker {
  max-width: 19ch;
  margin: var(--tp-space-lg) 0 0;
  font-family: var(--tp-font-display);
  font-size: clamp(1.5rem, 1.05rem + 2vw, 2.625rem);
  line-height: 1.06;
  letter-spacing: var(--tp-tracking-h2);
  font-weight: var(--tp-weight-medium);
}

.tp-vp-hero__statement {
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-md);
  max-width: 36rem;
}

.tp-vp-hero__statement p {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: clamp(1.25rem, 1rem + 1vw, 1.875rem);
  line-height: 1.14;
  letter-spacing: var(--tp-tracking-h3);
}

.tp-vp-hero__statement p + p {
  margin-block-start: var(--tp-space-sm);
  color: var(--tp-coral);
}

@media (min-width: 960px) {
  .tp-vp-hero__grid {
    grid-template-columns: minmax(0, 8fr) minmax(18rem, 4fr);
    align-items: end;
  }
}

.tp-vp-reading {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
}

.tp-vp-diagram {
  padding-block: var(--tp-space-2xl);
}

.tp-vp-diagram__frame {
  width: min(100%, 980px);
}

.tp-vp-diagram__head {
  max-width: 46rem;
  margin-block-end: var(--tp-space-lg);
}

.tp-vp-diagram__head .tp-h2 {
  margin-block-start: var(--tp-space-xs);
  max-width: 24ch;
  font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.625rem);
  line-height: 1.05;
}

.tp-vp-map {
  position: relative;
  margin: 0;
  border-block: 1px solid var(--tp-rule);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-section-y-tight) var(--tp-grid-gap);
  align-items: center;
  padding-block: var(--tp-space-xl);
}

@media (min-width: 900px) {
  .tp-vp-map {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }
}

.tp-vp-map__system {
  position: relative;
  min-height: clamp(21rem, 38vw, 28rem);
  display: grid;
  place-items: center;
}

.tp-vp-map__orbit {
  position: relative;
  width: min(100%, 25rem);
  aspect-ratio: 1;
  z-index: 2;
}

.tp-vp-map__orbit svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.tp-vp-map__core-label {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52%;
  aspect-ratio: 1;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  padding: var(--tp-space-md);
  transform: translate(-50%, -50%);
  font-family: var(--tp-font-display);
  font-size: clamp(1rem, 0.88rem + 0.52vw, 1.25rem);
  font-weight: var(--tp-weight-bold);
  line-height: 1.08;
  letter-spacing: -0.018em;
  text-align: center;
  text-wrap: balance;
  color: var(--tp-paper);
  pointer-events: none;
}

.tp-vp-map__flow {
  position: absolute;
  z-index: 1;
  inset: 0;
  pointer-events: none;
}

.tp-vp-map__flow-line {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 22%;
  width: 56%;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-21deg);
  transform-origin: center;
}

.tp-vp-map__endpoint {
  position: absolute;
  display: grid;
  gap: var(--tp-space-2xs);
  max-width: 9.5rem;
  font-family: var(--tp-font-display);
}

.tp-vp-map__endpoint--capacity {
  inset-block-start: 3%;
  inset-inline-start: 0;
}

.tp-vp-map__endpoint span,
.tp-vp-map__badge {
  font-family: var(--tp-font-ui);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  color: var(--tp-coral);
}

.tp-vp-map__endpoint strong {
  font-size: clamp(1rem, 0.92rem + 0.45vw, 1.25rem);
  line-height: 1.08;
  letter-spacing: -0.018em;
}

.tp-vp-map__endpoint--outcome {
  inset-block-end: 3%;
  inset-inline-end: 0;
  text-align: right;
}

.tp-vp-map__questions {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-xl);
  list-style: none;
  margin: 0;
  padding: 0;
}

.tp-vp-map__arc {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 7rem;
  height: 100%;
  pointer-events: none;
}

.tp-vp-map__arc path {
  fill: none;
  stroke: var(--tp-rule);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.tp-vp-map__question {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-sm);
  align-items: start;
}

@media (min-width: 600px) {
  .tp-vp-map__question {
    grid-template-columns: 7rem 1fr;
    gap: var(--tp-space-md);
  }
}

.tp-vp-map__question-link,
.tp-vp-map__question-copy {
  color: inherit;
  text-decoration: none;
}

.tp-vp-map__question-link {
  display: inline-grid;
  width: max-content;
}

.tp-vp-map__badge {
  --tp-badge-arc-x: 0px;
  --tp-badge-scale: 1;

  display: grid;
  place-items: center;
  width: 4.25rem;
  height: 4.25rem;
  border-radius: 50%;
  background: var(--tp-ink);
  color: var(--tp-paper);
  transform: translateX(var(--tp-badge-arc-x)) scale(var(--tp-badge-scale));
  transition: background-color var(--tp-duration-fast) var(--tp-ease),
              transform var(--tp-duration) var(--tp-ease-out);
}

.tp-vp-map__question-copy {
  display: flex;
  flex-direction: column;
  gap: var(--tp-space-2xs);
  max-width: 40ch;
}

.tp-vp-map__question:hover .tp-vp-map__badge,
.tp-vp-map__question:focus-within .tp-vp-map__badge {
  background: var(--tp-coral);
  --tp-badge-scale: 1.04;
}

.tp-vp-map__question:hover .tp-vp-map__question-copy strong,
.tp-vp-map__question:focus-within .tp-vp-map__question-copy strong {
  color: var(--tp-coral);
}

.tp-vp-map__question-copy strong {
  font-family: var(--tp-font-display);
  font-size: clamp(1.25rem, 1.12rem + 0.55vw, 1.5rem);
  font-weight: var(--tp-weight-bold);
  line-height: 1.1;
  letter-spacing: -0.018em;
}

.tp-vp-map__question-copy span {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--tp-fg);
}

@media (min-width: 960px) {
  .tp-vp-diagram__frame {
    margin-inline-start: max(-2.5rem, -4vw);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .tp-vp-map__flow-line {
    animation: tp-vp-flow 4.5s var(--tp-ease) infinite;
  }

  .tp-vp-map__core-label {
    animation: tp-vp-pulse 4s var(--tp-ease) infinite;
  }
}

@keyframes tp-vp-flow {
  0%, 100% { transform: scaleX(0.28); transform-origin: left center; }
  50% { transform: scaleX(1); transform-origin: left center; }
}

@keyframes tp-vp-pulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50% { transform: translate(-50%, -50%) scale(1.025); }
}

@media (max-width: 767.98px) {
  .tp-vp-diagram {
    padding-block: var(--tp-space-xl);
  }

  .tp-vp-map {
    display: grid;
    gap: var(--tp-space-md);
    min-height: 0;
    padding-block: var(--tp-space-md);
  }

  .tp-vp-map__flow,
  .tp-vp-map__arc {
    display: none;
  }

  .tp-vp-map__system {
    min-height: 0;
  }

  .tp-vp-map__orbit {
    width: min(100%, 18rem);
  }

  .tp-vp-map__questions {
    display: grid;
    gap: var(--tp-space-md);
  }
}

.tp-vp-reading__main {
  display: grid;
  gap: var(--tp-space-md);
  max-width: var(--tp-container-narrow);
}

.tp-vp-margin-note {
  border-block-start: 2px solid var(--tp-coral);
  padding-block-start: var(--tp-space-sm);
}

.tp-vp-margin-note p {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

@media (min-width: 1024px) {
  .tp-vp-reading {
    grid-template-columns: minmax(0, 8fr) minmax(13rem, 3fr);
    align-items: start;
  }

  .tp-vp-margin-note {
    position: sticky;
    top: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  }
}

.tp-vp-reframe { overflow: hidden; }

.tp-vp-reframe__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
}

.tp-vp-reframe__head,
.tp-vp-reframe__body {
  display: grid;
  gap: var(--tp-space-md);
}

.tp-vp-reframe__body { gap: var(--tp-space-lg); }

.tp-vp-question-list,
.tp-vp-checklist,
.tp-vp-path ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.tp-vp-question-list {
  border-block-start: 1px solid var(--tp-rule);
}

.tp-vp-question-list li {
  padding-block: var(--tp-space-sm);
  border-block-end: 1px solid var(--tp-rule);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

@media (min-width: 900px) {
  .tp-vp-reframe__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
  }
}

.tp-vp-framework__intro {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 760px;
  margin-block-end: var(--tp-space-2xl);
}

.tp-vp-framework__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
}

.tp-vp-rail { display: none; }

.tp-vp-rail ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--tp-space-xs);
}

.tp-vp-rail__link {
  display: grid;
  grid-template-columns: 2.5rem minmax(0, 1fr);
  gap: var(--tp-space-sm);
  align-items: baseline;
  color: var(--tp-fg-muted);
  text-decoration: none;
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-xs);
  transition: color var(--tp-duration) var(--tp-ease),
              border-color var(--tp-duration) var(--tp-ease);
}

.tp-vp-rail__link span,
.tp-vp-rail__link strong {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
}

.tp-vp-rail__link strong { font-weight: var(--tp-weight-medium); }

.tp-vp-rail__link:hover,
.tp-vp-rail__link:focus-visible,
.tp-vp-rail__link.is-active {
  color: var(--tp-fg);
  border-color: var(--tp-coral);
}

@media (min-width: 1080px) {
  .tp-vp-framework__grid {
    grid-template-columns: minmax(13rem, 2.5fr) minmax(0, 9.5fr);
    align-items: start;
  }

  .tp-vp-rail {
    display: block;
    position: sticky;
    top: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  }
}

.tp-vp-decisions {
  display: grid;
  gap: var(--tp-space-2xl);
}

.tp-vp-decision {
  position: relative;
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-xl);
  scroll-margin-top: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
}

.tp-vp-decision__number {
  font-family: var(--tp-font-display);
  font-size: clamp(3rem, 8vw, 7rem);
  line-height: 0.86;
  letter-spacing: -0.03em;
  font-weight: var(--tp-weight-bold);
  color: var(--tp-coral);
}

.tp-vp-decision__copy {
  display: grid;
  gap: var(--tp-space-md);
}

.tp-vp-decision__copy .tp-label { color: var(--tp-fg-muted); }

.tp-vp-decision__note {
  border-inline-start: 2px solid var(--tp-coral);
  padding-inline-start: var(--tp-space-md);
}

.tp-vp-decision__note p {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

@media (min-width: 760px) {
  .tp-vp-decision {
    grid-template-columns: minmax(5rem, 1.5fr) minmax(0, 7fr) minmax(12rem, 3fr);
  }
}

.tp-vp-comparison {
  position: relative;
  overflow: hidden;
}

.tp-vp-comparison::before {
  content: "";
  position: absolute;
  inset-block: var(--tp-section-y-tight);
  inset-inline-start: 50%;
  width: 1px;
  background: rgba(var(--tp-paper-rgb), 0.22);
  display: none;
}

.tp-vp-comparison__head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 840px;
  margin-block-end: var(--tp-space-2xl);
  position: relative;
  z-index: 1;
}

.tp-vp-paths {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-vp-path {
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
  display: grid;
  gap: var(--tp-space-lg);
}

.tp-vp-path h3 {
  font-size: var(--tp-size-h2-sm);
  line-height: var(--tp-lh-h2-sm);
}

.tp-vp-path li {
  padding-block: var(--tp-space-sm);
  border-block-end: 1px solid var(--tp-rule);
  font-size: var(--tp-size-body);
  line-height: var(--tp-lh-body);
  color: var(--tp-fg-muted);
}

.tp-vp-path--stronger h3::after {
  content: "_";
  color: var(--tp-coral);
  margin-inline-start: 0.06em;
}

.tp-vp-comparison__close {
  max-width: 18ch;
  margin: var(--tp-space-2xl) 0 0 auto;
  font-family: var(--tp-font-display);
  font-size: clamp(1.75rem, 1.2rem + 2.4vw, 3rem);
  line-height: 1;
  letter-spacing: var(--tp-tracking-h2);
  font-weight: var(--tp-weight-bold);
}

@media (min-width: 900px) {
  .tp-vp-comparison::before { display: block; }

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

.tp-vp-checklist {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

.tp-vp-checklist li {
  position: relative;
  padding-inline-start: var(--tp-space-lg);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
}

.tp-vp-checklist li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.42em;
  width: 0.7em;
  height: 0.7em;
  border: 1px solid var(--tp-coral);
}

.tp-vp-next__head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 760px;
  margin-block-end: var(--tp-space-xl);
}

.tp-vp-next__grid {
  display: grid;
  gap: var(--tp-space-md);
  grid-template-columns: minmax(0, 1fr);
}

.tp-vp-next__item {
  display: grid;
  gap: var(--tp-space-sm);
  color: var(--tp-fg);
  text-decoration: none;
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-md);
}

.tp-vp-next__item span,
.tp-vp-next__item strong { font-family: var(--tp-font-display); }

.tp-vp-next__item span {
  color: var(--tp-coral);
  font-size: var(--tp-size-label);
  letter-spacing: var(--tp-tracking-label);
}

.tp-vp-next__item strong {
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
}

.tp-vp-next__item em {
  color: var(--tp-fg-muted);
  font-style: normal;
  line-height: var(--tp-lh-body);
}

.tp-vp-next__item:hover,
.tp-vp-next__item:focus-visible { color: var(--tp-coral); }

@media (min-width: 760px) {
  .tp-vp-next__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.tp-vp-final__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
}

.tp-vp-final__action {
  display: grid;
  gap: var(--tp-space-lg);
  justify-items: start;
}

@media (min-width: 900px) {
  .tp-vp-final__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  }
}


/* ==========================================================================
   HOW IT WORKS
   ========================================================================== */

.tp-how__head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 880px;
  margin-block-end: var(--tp-space-2xl);
}

.tp-how__steps {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  counter-reset: how;
}

.tp-how__step {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-md);
}

.tp-how__step span {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  font-weight: var(--tp-weight-medium);
  color: var(--tp-coral);
}

.tp-how__step h3,
.tp-how__step p {
  margin: 0;
}

@media (min-width: 760px) {
  .tp-how__steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1080px) {
  .tp-how__steps {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}


/* ==========================================================================
   THE PROBLEM
   ========================================================================== */

.tp-problem-page {
  background: var(--tp-paper);
}

.tp-problem-hero {
  min-height: min(88vh, 48rem);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-problem-hero__shape {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(12rem, 30vw, 28rem);
  aspect-ratio: 1;
  pointer-events: none;
}

.tp-problem-hero__shape path {
  fill: none;
  stroke: rgba(var(--tp-ink-rgb), 0.28);
  stroke-width: 0.7;
  stroke-dasharray: 2.4 2.4;
  vector-effect: non-scaling-stroke;
}

.tp-problem-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-problem-hero__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-problem-hero__title {
  margin-block-start: var(--tp-space-md);
}

.tp-problem-hero__lede {
  max-width: 24ch;
  display: grid;
  gap: var(--tp-space-sm);
  font-family: var(--tp-font-display);
  font-size: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
  line-height: 1.18;
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-problem-hero__lede p {
  margin: 0;
}

@media (min-width: 960px) {
  .tp-problem-hero__grid {
    grid-template-columns: minmax(0, 8fr) minmax(18rem, 4fr);
    align-items: end;
  }
}

.tp-problem-section-head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 880px;
  margin-block-end: var(--tp-space-2xl);
}

.tp-problem-tensions__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
}

.tp-problem-tension {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-md);
  align-content: start;
}

.tp-problem-tension span {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  color: var(--tp-coral);
}

.tp-problem-tension h3,
.tp-problem-tension p {
  margin: 0;
}

@media (min-width: 760px) {
  .tp-problem-tensions__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.tp-problem-neutral__grid,
.tp-problem-path__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
}

.tp-problem-neutral__grid h2 {
  max-width: 12ch;
}

.tp-problem-neutral__grid p + p {
  margin-block-start: var(--tp-space-md);
}

.tp-problem-path__grid > div {
  display: grid;
  gap: var(--tp-space-md);
}

.tp-problem-path__grid h2 {
  overflow-wrap: break-word;
}

@media (min-width: 900px) {
  /* Heading left, reading column right: the prose needs the room. */
  .tp-problem-neutral__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
  }

}

/* The proposal is the other way round: its right column is a short checklist,
   while the heading is the largest type on the page. It splits later than the
   sections above, because below this width the display size cannot set a long
   word inside a column and would run into the checklist beside it. */
@media (min-width: 1200px) {
  .tp-problem-path__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    align-items: start;
  }
}


/* ==========================================================================
   PARTICIPATE
   ========================================================================== */

.tp-ask-page {
  background: var(--tp-paper);
}

.tp-ask-hero {
  min-height: min(84vh, 46rem);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-ask-hero__shape {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(12rem, 30vw, 28rem);
  aspect-ratio: 1;
  pointer-events: none;
  overflow: visible;
}

.tp-ask-hero__shape :where(circle, rect, path) {
  fill: none;
  stroke: rgba(var(--tp-ink-rgb), 0.28);
  stroke-width: 0.7;
  stroke-dasharray: 2.4 2.4;
  vector-effect: non-scaling-stroke;
}

.tp-ask-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-ask-hero__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-ask-hero__grid h1 {
  margin-block-start: var(--tp-space-md);
}

.tp-ask-hero__copy {
  display: grid;
  gap: var(--tp-space-sm);
  max-width: 34rem;
  font-family: var(--tp-font-display);
  font-size: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
  line-height: 1.18;
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-ask-hero__copy p {
  margin: 0;
}

@media (min-width: 960px) {
  .tp-ask-hero__grid {
    grid-template-columns: minmax(0, 8fr) minmax(18rem, 4fr);
    align-items: end;
  }
}

.tp-ask-section-head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 880px;
  margin-block-end: var(--tp-space-2xl);
}

.tp-ask-ways__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
}

.tp-ask-way {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-md);
}

.tp-ask-way span {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  color: var(--tp-coral);
  text-transform: uppercase;
}

.tp-ask-way h3,
.tp-ask-way p {
  margin: 0;
}

@media (min-width: 760px) {
  .tp-ask-ways__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1180px) {
  .tp-ask-ways__grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

.tp-ask-publish__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
}

.tp-ask-publish__grid > div {
  display: grid;
  gap: var(--tp-space-md);
}

@media (min-width: 900px) {
  .tp-ask-publish__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
  }
}


/* ==========================================================================
   LEADERS
   ========================================================================== */

.tp-leaders-page {
  background: var(--tp-paper);
}

.tp-leaders-hero {
  min-height: min(86vh, 48rem);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-leaders-hero__mark {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(11rem, 26vw, 25rem);
  aspect-ratio: 1;
  pointer-events: none;
}

.tp-leaders-hero__mark span {
  position: absolute;
  border: 1px dashed rgba(var(--tp-ink-rgb), 0.28);
}

.tp-leaders-hero__mark span:first-child {
  inset: 8% 20% 20% 8%;
}

.tp-leaders-hero__mark span:last-child {
  inset: 34% 6% 8% 38%;
  background:
    linear-gradient(90deg, transparent calc(100% - 1px), rgba(var(--tp-ink-rgb), 0.12) 0),
    linear-gradient(180deg, transparent calc(100% - 1px), rgba(var(--tp-ink-rgb), 0.12) 0);
  background-size: 18px 18px;
}

.tp-leaders-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-leaders-hero__grid,
.tp-leaders-principle__grid,
.tp-leaders-position__grid,
.tp-leaders-cta__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-leaders-hero__grid h1 {
  margin-block-start: var(--tp-space-md);
}

.tp-leaders-hero__copy,
.tp-leaders-principle__copy,
.tp-leaders-cta__copy {
  display: grid;
  gap: var(--tp-space-sm);
  max-width: 36rem;
}

.tp-leaders-hero__copy {
  font-family: var(--tp-font-display);
  font-size: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
  line-height: 1.18;
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-leaders-hero__copy p,
.tp-leaders-principle__copy p,
.tp-leaders-cta__copy p {
  margin: 0;
}

@media (min-width: 960px) {
  .tp-leaders-hero__grid,
  .tp-leaders-principle__grid,
  .tp-leaders-position__grid,
  .tp-leaders-cta__grid {
    grid-template-columns: minmax(0, 7fr) minmax(18rem, 5fr);
    align-items: end;
  }

  .tp-leaders-principle__grid,
  .tp-leaders-position__grid,
  .tp-leaders-cta__grid {
    align-items: start;
  }
}

.tp-leaders-section-head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 860px;
  margin-block-end: var(--tp-space-2xl);
}

.tp-leaders-profile-list {
  display: grid;
  gap: var(--tp-section-y-tight);
}

.tp-leader-card {
  display: grid;
  gap: var(--tp-grid-gap);
  align-items: end;
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-xl);
}

.tp-leader-card__portrait {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--tp-paper);
  aspect-ratio: 4 / 5;
}

.tp-leader-card__portrait::after {
  content: "";
  position: absolute;
  inset: var(--tp-space-sm);
  border: 1px solid rgba(var(--tp-paper-rgb), 0.72);
  pointer-events: none;
}

.tp-leader-card__portrait img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.tp-leader-card__portrait figcaption {
  position: absolute;
  inset-inline-start: var(--tp-space-sm);
  inset-block-end: var(--tp-space-sm);
  padding: 0.35rem 0.5rem;
  background: var(--tp-paper);
  color: var(--tp-ink);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
}

.tp-leader-card__copy {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 44rem;
}

.tp-leader-card__copy h3,
.tp-leader-card__copy p {
  margin: 0;
}

.tp-leader-card__belief {
  max-width: 36rem;
  margin-block-start: var(--tp-space-sm);
  padding-block-start: var(--tp-space-md);
  border-block-start: 1px solid var(--tp-rule);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  color: var(--tp-fg);
}

@media (min-width: 900px) {
  .tp-leader-card {
    grid-template-columns: minmax(16rem, 4fr) minmax(0, 8fr);
  }

  .tp-leader-card:nth-child(even) {
    grid-template-columns: minmax(0, 8fr) minmax(16rem, 4fr);
  }

  .tp-leader-card:nth-child(even) .tp-leader-card__portrait {
    order: 2;
  }
}

.tp-leaders-position__list {
  display: grid;
  gap: var(--tp-space-md);
  margin: 0;
  padding: 0;
  counter-reset: leader-position;
  list-style: none;
}

.tp-leaders-position__list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--tp-space-sm);
  align-items: start;
  margin: 0;
  padding-block-start: var(--tp-space-md);
  border-block-start: 1px solid var(--tp-rule);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
}

.tp-leaders-position__list li::before {
  counter-increment: leader-position;
  content: "0" counter(leader-position);
  color: var(--tp-coral);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
}

.tp-leaders-cta__copy {
  align-content: start;
  justify-items: start;
}


/* ==========================================================================
   CONTACT
   ========================================================================== */

.tp-contact-page {
  background: var(--tp-paper);
}

.tp-contact-hero {
  min-height: min(80vh, 44rem);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-contact-hero__shape {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(10rem, 24vw, 22rem);
  aspect-ratio: 1;
  border: 1px dashed rgba(var(--tp-ink-rgb), 0.28);
  pointer-events: none;
}

.tp-contact-hero__shape::after {
  content: "";
  position: absolute;
  inset: 30% -18% -18% 30%;
  border: 1px solid var(--tp-coral);
}

.tp-contact-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-contact-hero__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-contact-hero__grid h1 {
  margin-block-start: var(--tp-space-md);
}

.tp-contact-hero__copy {
  display: grid;
  gap: var(--tp-space-sm);
  max-width: 36rem;
  font-family: var(--tp-font-display);
  font-size: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
  line-height: 1.18;
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-contact-hero__copy p {
  margin: 0;
}

@media (min-width: 960px) {
  .tp-contact-hero__grid {
    grid-template-columns: minmax(0, 7fr) minmax(18rem, 5fr);
    align-items: end;
  }
}

.tp-contact-section-head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 860px;
}

.tp-contact-form__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

.tp-contact-form__panel {
  display: grid;
  gap: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

@media (min-width: 760px) {
  .tp-contact-form__panel .tp-form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 960px) {
  .tp-contact-form__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }
}


/* ==========================================================================
   BOOK A TALK
   ========================================================================== */

.tp-talk-page {
  background: var(--tp-paper);
}

.tp-talk-hero {
  min-height: min(86vh, 48rem);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-talk-hero__shape {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(12rem, 28vw, 26rem);
  aspect-ratio: 1;
  pointer-events: none;
}

.tp-talk-hero__shape::before,
.tp-talk-hero__shape::after {
  content: "";
  position: absolute;
  border: 1px dashed rgba(var(--tp-ink-rgb), 0.28);
}

.tp-talk-hero__shape::before {
  inset: 0 26% 26% 0;
  border-radius: 50%;
}

.tp-talk-hero__shape::after {
  inset: 30% 0 0 30%;
  border-color: var(--tp-coral);
}

.tp-talk-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-talk-hero__grid,
.tp-talk-overview__grid,
.tp-talk-topics__grid,
.tp-talk-form__grid {
  display: grid;
  gap: var(--tp-grid-gap);
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-talk-hero__grid h1 {
  margin-block-start: var(--tp-space-md);
}

.tp-talk-hero__copy,
.tp-talk-form__head {
  display: grid;
  gap: var(--tp-space-sm);
  max-width: 38rem;
}

.tp-talk-hero__copy {
  font-family: var(--tp-font-display);
  font-size: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
  line-height: 1.18;
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-talk-hero__copy p,
.tp-talk-form__head p {
  margin: 0;
}

.tp-talk-format-list {
  display: grid;
  gap: var(--tp-space-lg);
}

.tp-talk-format {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-md);
}

.tp-talk-format h3,
.tp-talk-format p {
  margin: 0;
}

.tp-talk-topic-list {
  display: grid;
  gap: var(--tp-space-md);
  margin: 0;
  padding: 0;
  counter-reset: talk-topic;
  list-style: none;
}

.tp-talk-topic-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--tp-space-sm);
  align-items: start;
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-md);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
}

.tp-talk-topic-list li::before {
  counter-increment: talk-topic;
  content: "0" counter(talk-topic);
  color: var(--tp-coral);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
}

.tp-talk-form__panel {
  display: grid;
  gap: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

@media (min-width: 760px) {
  .tp-talk-form__panel .tp-form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 960px) {
  .tp-talk-hero__grid,
  .tp-talk-overview__grid,
  .tp-talk-topics__grid,
  .tp-talk-form__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
  }

  .tp-talk-hero__grid {
    grid-template-columns: minmax(0, 7fr) minmax(18rem, 5fr);
    align-items: end;
  }
}


/* ==========================================================================
   STORY
   ========================================================================== */

.tp-story-page {
  background: var(--tp-paper);
}

.tp-story-hero {
  min-height: min(84vh, 46rem);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-story-hero__shape {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(12rem, 28vw, 26rem);
  aspect-ratio: 1;
  border: 1px dashed rgba(var(--tp-ink-rgb), 0.28);
  border-radius: 50%;
  pointer-events: none;
}

.tp-story-hero__shape::before,
.tp-story-hero__shape::after {
  content: "";
  position: absolute;
  border: 1px solid var(--tp-coral);
}

.tp-story-hero__shape::before {
  inset: 22% 22% 22% 22%;
}

.tp-story-hero__shape::after {
  inset: 48% -18% -18% 48%;
  border-color: rgba(var(--tp-ink-rgb), 0.22);
}

.tp-story-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-story-hero__grid,
.tp-story-turns__grid,
.tp-story-progress__grid,
.tp-story-name__grid,
.tp-story-close__grid {
  display: grid;
  gap: clamp(var(--tp-space-2xl), 6vw, var(--tp-section-y-tight));
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-story-hero__grid > *,
.tp-story-turns__grid > *,
.tp-story-progress__grid > *,
.tp-story-name__grid > *,
.tp-story-close__grid > * {
  min-width: 0;
}

.tp-story-hero__grid h1 {
  margin-block-start: var(--tp-space-md);
}

.tp-story-hero__copy {
  display: grid;
  gap: var(--tp-space-sm);
  max-width: 36rem;
  font-family: var(--tp-font-display);
  font-size: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
  line-height: 1.18;
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-story-hero__copy p,
.tp-story-prose p {
  margin: 0;
}

.tp-story-prose {
  display: grid;
  gap: var(--tp-space-md);
  color: var(--tp-fg-muted);
}

.tp-story-opening h2 {
  margin-block-end: var(--tp-space-xl);
}

.tp-story-turns,
.tp-story-progress,
.tp-story-name,
.tp-story-close {
  border-block-start: 1px solid var(--tp-rule);
}

.tp-story-turns__head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 44rem;
}

.tp-story-turns__head .tp-h1 {
  max-width: 15ch;
  font-size: clamp(2.75rem, 4vw, 4.75rem);
  line-height: 1;
}

.tp-story-progress .tp-h1 {
  max-width: 13ch;
  font-size: clamp(2.75rem, 4.4vw, 5.25rem);
  line-height: 1;
}

.tp-story-turn-list {
  display: grid;
  gap: var(--tp-space-xl);
  margin: 0;
  padding: 0;
  counter-reset: story-turn;
  list-style: none;
}

.tp-story-turn {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

.tp-story-turn::before {
  counter-increment: story-turn;
  content: "0" counter(story-turn);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  color: var(--tp-coral);
}

.tp-story-turn h3,
.tp-story-turn p {
  margin: 0;
}

.tp-story-progress__grid > p {
  max-width: 40rem;
}

.tp-story-name .tp-h1 {
  max-width: 12ch;
  font-size: clamp(2.75rem, 4.4vw, 5.25rem);
  line-height: 1;
}

.tp-story-name__items {
  display: grid;
  gap: var(--tp-space-xl);
}

.tp-story-name__item {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

.tp-story-name__item h3,
.tp-story-name__item p {
  margin: 0;
}

.tp-story-quote {
  margin: 0;
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

.tp-story-quote blockquote {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: clamp(2rem, 1.35rem + 2.6vw, 4rem);
  line-height: 0.98;
  letter-spacing: 0;
  font-weight: var(--tp-weight-bold);
  text-wrap: balance;
}

@media (min-width: 960px) {
  .tp-story-hero__grid {
    grid-template-columns: minmax(0, 7fr) minmax(18rem, 5fr);
    align-items: end;
  }

  .tp-story-turns__grid,
  .tp-story-progress__grid,
  .tp-story-name__grid,
  .tp-story-close__grid {
    grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
    align-items: start;
  }
}


/* ==========================================================================
   CONSULTING
   ========================================================================== */

.tp-consulting-page {
  background: var(--tp-paper);
}

.tp-consulting-hero {
  min-height: min(88vh, 50rem);
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
  display: grid;
  align-items: end;
  position: relative;
  overflow: hidden;
}

.tp-consulting-hero__shape {
  position: absolute;
  inset-block-start: calc(var(--site-header-height, 0px) + var(--tp-space-xl));
  inset-inline-end: var(--tp-gutter);
  width: clamp(12rem, 30vw, 28rem);
  aspect-ratio: 1;
  border: 1px dashed rgba(var(--tp-ink-rgb), 0.28);
  pointer-events: none;
}

.tp-consulting-hero__shape::before,
.tp-consulting-hero__shape::after {
  content: "";
  position: absolute;
  border: 1px solid var(--tp-coral);
}

.tp-consulting-hero__shape::before {
  inset: 20% 20% 20% 20%;
  border-radius: 50%;
}

.tp-consulting-hero__shape::after {
  inset: 52% -16% -16% 52%;
  border-color: rgba(var(--tp-ink-rgb), 0.24);
}

.tp-consulting-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 2px;
  background: var(--tp-coral);
  transform: rotate(-8deg) scaleX(1.12);
  transform-origin: 75% 50%;
  pointer-events: none;
}

.tp-consulting-hero__grid,
.tp-consulting-split,
.tp-consulting-beliefs__grid,
.tp-consulting-final__grid {
  display: grid;
  gap: clamp(var(--tp-space-2xl), 6vw, var(--tp-section-y-tight));
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  z-index: 1;
}

.tp-consulting-hero__grid > *,
.tp-consulting-split > *,
.tp-consulting-beliefs__grid > *,
.tp-consulting-final__grid > * {
  min-width: 0;
}

.tp-consulting-hero__grid h1 {
  margin-block-start: var(--tp-space-md);
}

.tp-consulting-hero__copy,
.tp-consulting-final__copy,
.tp-consulting-fit__copy {
  display: grid;
  gap: var(--tp-space-md);
  align-content: start;
}

.tp-consulting-hero__copy {
  max-width: 38rem;
  font-family: var(--tp-font-display);
  font-size: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
  line-height: 1.18;
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-consulting-hero__copy p,
.tp-consulting-final__copy p,
.tp-consulting-fit__copy p {
  margin: 0;
}

.tp-consulting-page :is(
  .tp-consulting-intro,
  .tp-consulting-discovery,
  .tp-consulting-readiness,
  .tp-consulting-tensions,
  .tp-consulting-questions,
  .tp-consulting-process,
  .tp-consulting-outputs,
  .tp-consulting-beliefs,
  .tp-consulting-fit,
  .tp-consulting-final
) {
  border-block-start: 1px solid var(--tp-rule);
}

.tp-consulting-split > div:first-child,
.tp-consulting-beliefs__grid > div:first-child,
.tp-consulting-final__grid > div:first-child {
  display: grid;
  gap: var(--tp-space-md);
  align-content: start;
}

.tp-consulting-split .tp-h1,
.tp-consulting-beliefs__grid .tp-h1,
.tp-consulting-final__grid .tp-h1 {
  max-width: 13ch;
  font-size: clamp(2.75rem, 4.4vw, 5.25rem);
  line-height: 1;
}

.tp-consulting-discovery__steps,
.tp-consulting-process__list,
.tp-consulting-beliefs__grid ul {
  display: grid;
  gap: var(--tp-space-lg);
  margin: 0;
  padding: 0;
  list-style: none;
}

.tp-consulting-discovery__steps li,
.tp-consulting-process__list li,
.tp-consulting-beliefs__grid li {
  display: grid;
  gap: var(--tp-space-sm);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

.tp-consulting-discovery__steps span,
.tp-consulting-process__list span {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  color: var(--tp-coral);
}

.tp-consulting-discovery__steps h3,
.tp-consulting-discovery__steps p,
.tp-consulting-process__list h3,
.tp-consulting-process__list p,
.tp-consulting-beliefs__grid li {
  margin: 0;
}

.tp-consulting-callout {
  display: grid;
  gap: var(--tp-space-md);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

.tp-consulting-callout p {
  margin: 0;
}

.tp-consulting-callout p:last-child,
.tp-consulting-beliefs__grid li {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-consulting-tension-card {
  display: grid;
  gap: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
  padding-block-start: var(--tp-space-lg);
}

.tp-consulting-tension-card dl {
  display: grid;
  gap: var(--tp-space-md);
  margin: 0;
}

.tp-consulting-tension-card dl > div {
  display: grid;
  gap: var(--tp-space-2xs);
}

.tp-consulting-tension-card dt {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  line-height: var(--tp-lh-label);
  letter-spacing: var(--tp-tracking-label);
  text-transform: uppercase;
  color: var(--tp-coral);
}

.tp-consulting-tension-card dd,
.tp-consulting-tension-card p {
  margin: 0;
}

.tp-consulting-tension-card dd {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
  font-weight: var(--tp-weight-medium);
}

.tp-consulting-section-head {
  display: grid;
  gap: var(--tp-space-md);
  max-width: 56rem;
  margin-block-end: var(--tp-space-2xl);
}

.tp-consulting-process__list {
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 760px) {
  .tp-consulting-process__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1180px) {
  .tp-consulting-process__list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

@media (min-width: 960px) {
  .tp-consulting-hero__grid {
    grid-template-columns: minmax(0, 7fr) minmax(18rem, 5fr);
    align-items: end;
  }

  .tp-consulting-split,
  .tp-consulting-beliefs__grid,
  .tp-consulting-final__grid {
    grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
    align-items: start;
  }
}


/* --------------------------------------------------------------------------
   Keep the last two words of a block together. Emitted by the widont filter
   in app.py; see there for why an inline-block rather than a non-breaking
   space. */
.tp-keep { display: inline-block; }

/* ==========================================================================
   VISION PAGES: EDITORIAL LAYOUT

   See pages/vision-editorial.html. A margin column carrying the page's
   navigation and a rule at the head of every section, a reading column
   beside it, wide documentary photography, and large pale circles behind
   the whole page.
   ========================================================================== */

/* clip, not hidden: the circles bleed off both edges and must not cause a
   sideways scroll, but overflow:hidden would make this a scroll container
   and the framework's sticky rail would stop sticking. */
.tp-ed {
  position: relative;
  overflow-x: clip;
  padding-block-end: var(--tp-section-y);
}

/* --- The two columns -------------------------------------------------------
   Every section is the same pair: margin, then reading. Shared rather than
   restated per section, so the whole page holds one left edge. */
.tp-ed__row {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--tp-space-md) var(--tp-grid-gap);
}

.tp-ed__section { padding-block-start: var(--tp-section-y); }

.tp-ed__main > * + * { margin-block-start: var(--tp-space-md); }

/* Prose holds a reading measure; figures and the orbit run the full column,
   wider than the text, as the reference sets its photographs. */
.tp-ed__main > p,
.tp-ed__main > ul,
.tp-ed__main > ol,
.tp-ed__main > .tp-ed__statement { max-width: 40rem; }

.tp-ed__main .tp-h2 { max-width: 22ch; }

/* --- Hero ----------------------------------------------------------------- */
.tp-ed__hero {
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
}

/* 18ch, not 16: wide enough that a long closing pair such as
   "Organizational Intelligence" can share a line at desktop size. */
.tp-ed__title { max-width: 18ch; }

/* The kicker as a second headline, led by a drawn rule rather than a typed
   dash: the reference's device, without putting a dash into the copy. */
.tp-ed__lead {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h2);
  font-weight: var(--tp-weight-bold);
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--tp-fg);
  max-width: 22ch;
  text-wrap: balance;
}

.tp-ed__statement p {
  margin: 0;
  font-size: var(--tp-size-body-lg);
  line-height: 1.5;
  color: var(--tp-fg-muted);
}

.tp-ed__statement p + p { color: var(--tp-fg); font-weight: var(--tp-weight-medium); }

/* --- The margin column ---------------------------------------------------- */
.tp-ed__rail { display: none; }

/* The hero's page navigation: each entry followed by a short rule, as the
   reference lists its sections. */
.tp-ed__nav { list-style: none; padding: 0; margin: 0; border-block-start: 3px solid var(--tp-fg); padding-block-start: var(--tp-space-xs); }
.tp-ed__nav li { margin-block-end: var(--tp-space-xs); }
.tp-ed__nav a {
  display: inline-block;
  font-size: var(--tp-size-caption);
  color: var(--tp-fg);
  text-decoration: none;
}
.tp-ed__nav a::after {
  content: '';
  display: block;
  width: 0.6rem;
  height: 1px;
  margin-block-start: 0.3rem;
  background: currentColor;
  transition: width 200ms var(--tp-ease, ease);
}
.tp-ed__nav a:hover::after,
.tp-ed__nav a:focus-visible::after { width: 1.6rem; }

/* The rule and marker at the head of each section. */
.tp-ed__marker {
  display: grid;
  gap: var(--tp-space-2xs);
  padding-block-start: 0.35rem;
}
.tp-ed__marker-rule { display: block; height: 3px; background: var(--tp-fg); }
.tp-ed__marker-tick {
  width: 0;
  height: 0;
  border-inline: 4px solid transparent;
  border-block-end: 6px solid var(--tp-coral);
}
.tp-ed__marker-label {
  font-size: var(--tp-size-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tp-fg-muted);
}

.tp-ed__rail-sticky {
  position: sticky;
  top: calc(var(--site-header-height, 0px) + var(--tp-space-lg));
  display: grid;
  gap: var(--tp-space-lg);
}

.tp-ed__decisions-nav ol { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--tp-space-xs); }

/* --- Photography -----------------------------------------------------------
   Shared by every page through components/thepath/wide-photo.html.
   Wide and near-monochrome, as the reference sets its pictures, but not all
   the way to grey: enough colour survives for the Coral of the booklet to
   read, which makes it the one colour in the frame. */
.tp-photo-wide {
  /* Positioned so it paints over a hero's line-art shape where the two
     meet: the shape tucks behind the picture instead of drawing across it. */
  position: relative;
  margin-block: var(--tp-space-xl) 0;
  aspect-ratio: 12 / 5;
  overflow: hidden;
  background: var(--tp-stone-tint);
}

.tp-photo-wide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  filter: grayscale(0.82) contrast(1.05);
}

.tp-photo-wide--high img { object-position: 50% 32%; }
.tp-photo-wide--low img  { object-position: 50% 66%; }
.tp-photo-wide--top img  { object-position: 50% 4%; }

.tp-ed__main > .tp-photo-wide + * { margin-block-start: var(--tp-space-xl); }

/* --- Prose devices -------------------------------------------------------- */
/* The thesis opens the section in bold, the reference's device. */
.tp-ed__thesis {
  font-size: var(--tp-size-body-lg);
  font-weight: var(--tp-weight-bold);
  line-height: 1.4;
  color: var(--tp-fg);
}

.tp-ed__questions,
.tp-ed__checklist {
  list-style: none;
  padding: 0;
  border-block-start: 1px solid var(--tp-rule);
}

.tp-ed__questions li,
.tp-ed__checklist li {
  padding-block: var(--tp-space-sm);
  border-block-end: 1px solid var(--tp-rule);
  font-size: var(--tp-size-body);
  line-height: 1.45;
  color: var(--tp-fg);
}

.tp-ed__checklist li { padding-inline-start: 1.5rem; position: relative; }
.tp-ed__checklist li::before {
  content: '';
  position: absolute;
  left: 0;
  top: calc(var(--tp-space-sm) + 0.55em);
  width: 0.6rem;
  height: 2px;
  background: var(--tp-coral);
}

/* A note that has something to say: set as a pulled line with a Coral rule,
   not in a margin where it reads as an afterthought. */
.tp-ed__note {
  padding-inline-start: var(--tp-space-md);
  border-inline-start: 2px solid var(--tp-coral);
  font-size: var(--tp-size-body-lg);
  font-weight: var(--tp-weight-medium);
  line-height: 1.4;
  color: var(--tp-fg);
}

.tp-ed__close {
  font-size: var(--tp-size-body-lg);
  font-weight: var(--tp-weight-bold);
  line-height: 1.4;
  color: var(--tp-fg);
}

/* --- The four decisions --------------------------------------------------- */
.tp-ed__decision {
  margin-block-start: var(--tp-space-2xl);
  padding-block-start: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
  scroll-margin-top: calc(var(--site-header-height, 0px) + var(--tp-space-lg));
}

.tp-ed__decision > * + * { margin-block-start: var(--tp-space-sm); }
.tp-ed__decision > p,
.tp-ed__decision > h3 { max-width: 40rem; }

.tp-ed__decision-num {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h1);
  font-weight: var(--tp-weight-bold);
  line-height: 0.9;
  letter-spacing: -0.03em;
  color: var(--tp-coral);
  font-variant-numeric: tabular-nums;
}

.tp-ed__decision-q {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  font-weight: var(--tp-weight-bold);
  line-height: 1.2;
  color: var(--tp-fg);
  text-wrap: balance;
}

/* --- Comparison ----------------------------------------------------------- */
.tp-ed__versus {
  display: grid;
  gap: var(--tp-space-lg);
  margin-block-start: var(--tp-space-xl);
}

.tp-ed__side {
  padding-block-start: var(--tp-space-sm);
  border-block-start: 3px solid var(--tp-fg-muted);
}
.tp-ed__side--stronger { border-block-start-color: var(--tp-coral); }
.tp-ed__side ul { list-style: none; padding: 0; margin: var(--tp-space-sm) 0 0; }
.tp-ed__side li {
  padding-block: var(--tp-space-2xs);
  border-block-end: 1px solid var(--tp-rule);
  line-height: 1.45;
  color: var(--tp-fg);
}

/* --- Connected lenses ----------------------------------------------------- */
.tp-ed__lenses { list-style: none; padding: 0; border-block-start: 1px solid var(--tp-rule); }
.tp-ed__lenses a {
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  gap: 0.2rem var(--tp-space-sm);
  padding-block: var(--tp-space-md);
  border-block-end: 1px solid var(--tp-rule);
  text-decoration: none;
  color: var(--tp-fg);
}
.tp-ed__lenses span { grid-row: span 2; color: var(--tp-coral); font-weight: var(--tp-weight-bold); }
.tp-ed__lenses strong { font-size: var(--tp-size-h3); }
.tp-ed__lenses em { font-style: normal; color: var(--tp-fg-muted); }
.tp-ed__lenses a:hover strong,
.tp-ed__lenses a:focus-visible strong { color: var(--tp-coral); }

/* --- Wide screens ----------------------------------------------------------
   The margin column appears. Below this the page reads as one column, the
   markers go, and the hero's navigation with them: at phone width a list of
   eight links above the title is only something to scroll past. */
@media (min-width: 960px) {
  .tp-ed__row { grid-template-columns: minmax(9rem, 11rem) minmax(0, 1fr); }
  .tp-ed__rail { display: block; }
  .tp-ed__versus { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 960px) {
  /* The orbit's own offset assumed a full-width container. */
  .tp-ed .tp-vp-diagram__frame { margin-inline-start: 0; width: 100%; }
}

/* The one line about what happens to a contribution, set under the examples
   on the contribute pages rather than given a section of its own. */
.tp-ask__promise {
  margin-block-start: var(--tp-space-xl);
  max-width: 44ch;
}

/* --- The four questions, as a list of links -------------------------------
   Used on a lens page to point at its four question pages, and on a question
   page to point at its three siblings. */
.tp-ed__questions-list {
  list-style: none;
  margin: var(--tp-space-xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--tp-space-lg);
}

.tp-ed__questions-list a {
  display: grid;
  gap: var(--tp-space-2xs);
  padding-block-end: var(--tp-space-lg);
  border-block-end: 1px solid var(--tp-rule);
  color: inherit;
  text-decoration: none;
}

.tp-ed__questions-list a:hover .tp-ed__decision-q,
.tp-ed__questions-list a:focus-visible .tp-ed__decision-q {
  color: var(--tp-coral);
}

.tp-ed__questions-list .tp-ed__decision-num { margin: 0; }
.tp-ed__questions-list .tp-label { margin: 0; }
.tp-ed__questions-list .tp-ed__decision-q { margin: 0; }

/* --- The long arrow on a question link ------------------------------------
   Short and solid rather than a hairline across the column. The shaft is a
   rule and the head is drawn beside it, so the point keeps its geometry at
   any width. It steps forward on hover and keyboard focus. */
.tp-arrow {
  display: flex;
  align-items: center;
  width: 4.5rem;
  margin-block-start: var(--tp-space-md);
  color: var(--tp-ink);
  opacity: 0.55;
  transition: transform 220ms ease, opacity 220ms ease, color 220ms ease;
}

.tp-arrow__shaft {
  flex: 1 1 auto;
  height: 0;
  border-block-start: 2px solid currentColor;
}

.tp-arrow__head {
  flex: 0 0 auto;
  width: 0.9rem;
  height: 1.5rem;
  margin-inline-start: -1px;
  overflow: visible;
}

.tp-ed__questions-list a:hover .tp-arrow,
.tp-ed__questions-list a:focus-visible .tp-arrow {
  color: var(--tp-coral);
  opacity: 1;
  transform: translateX(var(--tp-space-2xs));
}

@media (prefers-reduced-motion: reduce) {
  .tp-arrow { transition: opacity 220ms ease, color 220ms ease; }
  .tp-ed__questions-list a:hover .tp-arrow,
  .tp-ed__questions-list a:focus-visible .tp-arrow { transform: none; }
}

/* ===========================================================================
   EDITORIAL: ARTICLE DEVICES

   The parts a page reads with when it is written as an article rather than a
   run of sections: a byline under the title, a drop cap on the first
   paragraph, numbered beats through the narrative, and a pull quote where a
   part turns. All inside .tp-ed, so they never leak onto other layouts.
   =========================================================================== */

.tp-ed__byline {
  margin-block: var(--tp-space-md) 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-space-2xs) var(--tp-space-sm);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-caption);
  letter-spacing: 0.02em;
  color: var(--tp-fg-muted, var(--tp-fg));
}

.tp-ed__byline-date { opacity: 0.7; }

/* The drop cap. Three lines deep, set in the display face, and only ever on
   the paragraph that opens the piece. */
.tp-ed__opening::first-letter {
  float: inline-start;
  margin-inline-end: 0.08em;
  margin-block-start: 0.04em;
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: 3.4em;
  line-height: 0.82;
  color: var(--tp-coral);
}

/* The beats of the narrative: numbered, but reading as prose rather than as
   a row of cards. */
.tp-ed__beats {
  list-style: none;
  margin: var(--tp-space-2xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--tp-space-xl);
}

.tp-ed__beat {
  display: grid;
  gap: var(--tp-space-2xs);
  padding-block-start: var(--tp-space-md);
  border-block-start: 1px solid var(--tp-rule);
}

.tp-ed__beat-num {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-caption);
  letter-spacing: 0.14em;
  color: var(--tp-coral);
}

.tp-ed__beat-title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
  letter-spacing: var(--tp-tracking-h3);
}

/* One line lifted out of the column. */
.tp-ed__pull {
  margin-block: var(--tp-space-2xl);
  padding-inline-start: var(--tp-space-lg);
  border-inline-start: 3px solid var(--tp-coral);
}

.tp-ed__pull p {
  margin: 0;
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-h2-sm, var(--tp-size-h3));
  line-height: 1.16;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

/* An article keeps its reading column narrow, whatever the grid allows. */
.tp-ed--story .tp-ed__main > p.tp-body,
.tp-ed--story .tp-ed__beat p.tp-body {
  max-width: 62ch;
}

/* The line and button that close the ways section when it is used as a page's
   final ask rather than as the body of the Participate hub. */
.tp-ask-ways__close {
  margin-block-start: var(--tp-space-2xl);
  padding-block-start: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
  display: grid;
  gap: var(--tp-space-md);
  justify-items: start;
  max-width: 48ch;
}

/* ===========================================================================
   MOBILE: THE DECORATIVE LAYER COMES OFF

   The connectors, cues and background shapes are drawn for a wide canvas. On
   a phone they cross the copy, bleed off the edge, or land on a heading, so
   the whole secondary layer is switched off and the content is left to speak
   for itself. Everything here is decoration: nothing hidden carries meaning
   or a link.
   =========================================================================== */
@media (max-width: 767.98px) {
  /* The snaking cue from a section head down to what follows it. */
  .tp-band__cue { display: none; }

  /* The rule and dot that thread the progress steps together. */
  .tp-story__node { display: none; }

  /* The wedge and seam behind the lenses section. */
  .tp-visions__wedge,
  .tp-visions__seam { display: none; }

  /* The corner graphics are already off at this width; this keeps them off
     if that rule ever moves. */
  .tp-corner { display: none; }

  /* The wrap-up line is parked in the bottom left corner of its section on a
     wide screen. With the cue gone and the column narrow it lands on the
     heading, so on a phone it simply follows the copy. */
  .tp-band__wrap {
    position: static;
    margin-block-start: var(--tp-space-lg);
    max-width: none;
  }
}

/* ===========================================================================
   SHARE THE PATH

   Three new patterns, all reusable: the labelled placeholder (.tp-slot), the
   asset card (.tp-share-card) and the ready-made post (.tp-post). Everything
   else on the page is the site's existing section, container, type, button
   and link.
   =========================================================================== */

/* Every grid on this page starts as a single column that can never be wider
   than its container. Without minmax(0, 1fr) an implicit column sizes to its
   content, and a card with a long unbroken action row pushes past the page. */
.tp-share-hero__grid,
.tp-share-grid,
.tp-post,
.tp-badge-grid,
.tp-guide,
.tp-press-top,
.tp-language,
.tp-share-social__grid,
.tp-share-final__grid {
  grid-template-columns: minmax(0, 1fr);
}

/* --- The labelled placeholder ---------------------------------------------
   A reserved space, not a design: a keyline, the asset's name, its size. It
   holds the exact ratio the artwork will need, so the layout can be judged
   before anything is drawn. */
.tp-slot {
  position: relative;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: var(--tp-space-3xs);
  aspect-ratio: var(--tp-slot-ratio, 16 / 9);
  padding: var(--tp-space-md);
  text-align: center;
  background: var(--tp-stone-tint);
  border: 1px dashed var(--tp-rule);
}

.tp-slot__label {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  font-weight: var(--tp-weight-bold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tp-fg);
}

.tp-slot__note {
  font-family: var(--tp-font-text);
  font-size: var(--tp-size-caption);
  color: var(--tp-fg-muted);
}

/* --- Section heads --------------------------------------------------------- */
.tp-share-head { max-width: 46rem; display: grid; gap: var(--tp-space-md); }
.tp-share-head .tp-label { margin: 0; }
.tp-share-head h2 { margin: 0; max-width: 20ch; }
.tp-share-head p { margin: 0; }

.tp-share-head--split { max-width: none; }

@media (min-width: 900px) {
  .tp-share-head--split {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    align-items: end;
    gap: var(--tp-grid-gap);
  }
  .tp-share-head--split > div { display: grid; gap: var(--tp-space-md); }
}

.tp-share-note {
  margin-block-start: var(--tp-space-2xl);
  max-width: 52ch;
  font-size: var(--tp-size-caption);
  line-height: 1.55;
  color: var(--tp-fg-muted);
  padding-inline-start: var(--tp-space-md);
  border-inline-start: 2px solid var(--tp-coral);
}

.tp-share-note--wide { max-width: 68ch; }

/* --- Hero ------------------------------------------------------------------ */
.tp-share-hero {
  padding-block-start: calc(var(--site-header-height, 0px) + var(--tp-section-y));
}

.tp-share-hero__grid { display: grid; gap: var(--tp-grid-gap); }

.tp-share-hero__head { display: grid; gap: var(--tp-space-md); }
.tp-share-hero__head h1 { margin: 0; max-width: 20ch; }

.tp-share-hero__copy { display: grid; gap: var(--tp-space-md); align-content: start; }
.tp-share-hero__copy p { margin: 0; max-width: 46ch; }

.tp-share-hero__close { font-weight: var(--tp-weight-bold); }

.tp-share-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tp-space-md) var(--tp-space-xl);
  margin-block-start: var(--tp-space-lg);
}

@media (min-width: 900px) {
  /* The graphic takes the larger share. It is a composed card, not a
     photograph: it carries its own margins, the thread, and the lockup, so it
     needs room to be read rather than a column to be squeezed into. The copy
     sits in a narrower measure beside it, which reads better anyway. */
  .tp-share-hero__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
    column-gap: var(--tp-space-3xl);
    row-gap: var(--tp-space-2xl);
  }

  .tp-share-hero__head { grid-column: 1 / -1; }
  .tp-share-hero__copy p { max-width: 40ch; }
}

/* Below that the graphic leads, above the words: it says what the page is
   faster than the headline does. */
@media (max-width: 899.98px) {
  .tp-share-hero__figure { order: -1; margin-block-end: var(--tp-space-lg); }
}

/* --- The asset library ----------------------------------------------------- */
.tp-share-grid {
  margin-block-start: var(--tp-space-3xl);
  display: grid;
  gap: var(--tp-grid-gap);
}

.tp-share-card { display: grid; gap: var(--tp-space-sm); align-content: start; }
.tp-share-card h3 { margin: var(--tp-space-sm) 0 0; }
.tp-share-card p { margin: 0; max-width: 42ch; }

/* Card descriptions take the smaller step, so the card's heading leads and
   the description supports it. */
.tp-share-card p,
.tp-guide__resource p,
.tp-badge p:not(.tp-badge__title) {
  font-size: var(--tp-size-body-sm);
  line-height: var(--tp-lh-body-sm);
}

.tp-share-card__actions {
  margin-block-start: var(--tp-space-sm);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tp-space-md) var(--tp-space-lg);
}

/* A button that is a link in waiting keeps the link's look, not a button's. */
.tp-share-card__actions .tp-link,
.tp-badge__actions .tp-link,
.tp-post__actions .tp-link {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

@media (min-width: 760px) {
  .tp-share-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
  /* Four even columns, with the first item taking two of them. The library
     then reads as one editorial spread rather than a catalogue row. */
  .tp-share-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .tp-share-card--wide { grid-column: span 2; grid-row: span 2; }
  .tp-share-card--wide h3 { font-size: var(--tp-size-h2-sm); }
}

/* --- Ready-made posts ------------------------------------------------------ */
.tp-post-list {
  list-style: none;
  margin: var(--tp-space-3xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--tp-space-3xl);
}

.tp-post { display: grid; gap: var(--tp-space-lg); }
.tp-post__copy { display: grid; gap: var(--tp-space-md); align-content: center; }

.tp-post__platforms {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-space-2xs);
}

.tp-post__platforms li {
  padding: 0.25rem 0.6rem;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 1px solid var(--tp-rule);
}

.tp-post__text {
  display: grid;
  gap: var(--tp-space-sm);
  padding-inline-start: var(--tp-space-lg);
  border-inline-start: 1px solid var(--tp-rule);
}

.tp-post__text p { margin: 0; max-width: 52ch; }

.tp-post__title {
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
}

.tp-post__tags { color: var(--tp-coral); }

.tp-post__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tp-space-md) var(--tp-space-lg);
}

@media (min-width: 900px) {
  .tp-post {
    grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
    gap: var(--tp-grid-gap);
    align-items: center;
  }

  /* Every second post turns around, so the run has a rhythm. */
  .tp-post:nth-child(even) .tp-post__figure { order: 2; }
}

/* --- Website badges -------------------------------------------------------- */
.tp-badge-grid {
  margin-block-start: var(--tp-space-3xl);
  display: grid;
  gap: var(--tp-grid-gap);
}

.tp-badge { display: grid; gap: var(--tp-space-sm); align-content: start; }

.tp-badge__title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-body);
  line-height: 1.3;
}

.tp-badge__actions { display: flex; flex-wrap: wrap; gap: var(--tp-space-sm) var(--tp-space-md); }

@media (min-width: 640px) { .tp-badge-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .tp-badge-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* --- The discussion guide --------------------------------------------------- */
.tp-guide { margin-block-start: var(--tp-space-3xl); display: grid; gap: var(--tp-space-3xl); }

.tp-guide__resource { display: grid; gap: var(--tp-space-sm); align-content: start; }
.tp-guide__resource h3 { margin: var(--tp-space-sm) 0 0; }
.tp-guide__resource p { margin: 0; }
.tp-guide__resource .tp-btn { margin-block-start: var(--tp-space-md); justify-self: start; }

.tp-guide__list { list-style: none; margin: 0; padding: 0; display: grid; }

.tp-guide__list li {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1fr);
  gap: var(--tp-space-sm);
  padding-block: var(--tp-space-md);
  border-block-start: 1px solid var(--tp-rule);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: 1.25;
}

.tp-guide__list li:last-child { border-block-end: 1px solid var(--tp-rule); }

.tp-guide__num {
  font-size: var(--tp-size-caption);
  letter-spacing: 0.12em;
  color: var(--tp-coral);
  padding-block-start: 0.35em;
}

@media (min-width: 900px) {
  .tp-guide {
    grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
    gap: var(--tp-grid-gap);
    align-items: start;
  }
}

/* --- What we can write for you ---------------------------------------------- */
.tp-service-list {
  list-style: none;
  margin: var(--tp-space-3xl) 0 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.tp-service {
  display: grid;
  gap: var(--tp-space-2xs);
  padding-block: var(--tp-space-lg);
  border-block-start: 1px solid var(--tp-rule);
}

.tp-service:last-child { border-block-end: 1px solid var(--tp-rule); }

.tp-service__num {
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  letter-spacing: 0.14em;
  color: var(--tp-coral);
}

.tp-service__title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-h3);
  line-height: var(--tp-lh-h3);
}

.tp-service p { margin: 0; max-width: 56ch; }

@media (min-width: 900px) {
  .tp-service {
    grid-template-columns: 4rem minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--tp-space-lg);
    align-items: baseline;
  }
  .tp-service__num { padding-block-start: 0.4em; }
}

/* --- Press ------------------------------------------------------------------ */
.tp-press-top { margin-block-start: var(--tp-space-3xl); display: grid; gap: var(--tp-grid-gap); }
.tp-press-boilerplates { display: grid; gap: var(--tp-space-xl); align-content: start; }

.tp-press-quote { display: grid; gap: var(--tp-space-xs); justify-items: start; }
.tp-press-quote .tp-label { margin: 0; }

.tp-press-quote__body {
  margin: 0;
  max-width: 52ch;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: 1.35;
}

.tp-press-quote .tp-link { border: 0; background: none; padding: 0; font: inherit; cursor: pointer; }

.tp-press-index { list-style: none; margin: var(--tp-space-3xl) 0 0; padding: 0; display: grid; }

.tp-press-index__item {
  display: grid;
  width: 100%;
  text-decoration: none;
  display: grid;
  gap: var(--tp-space-2xs);
  padding-block: var(--tp-space-md);
  border: 0;
  border-block-start: 1px solid var(--tp-rule);
  background: none;
  text-align: start;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.tp-press-index li:last-child .tp-press-index__item { border-block-end: 1px solid var(--tp-rule); }

.tp-press-index__title {
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-body-lg);
}

.tp-press-index__body { font-size: var(--tp-size-caption); color: var(--tp-fg-muted); }

.tp-press-index__item:hover .tp-press-index__title,
.tp-press-index__item:focus-visible .tp-press-index__title { color: var(--tp-coral); }

.tp-press-index__item:hover .tp-arrow,
.tp-press-index__item:focus-visible .tp-arrow {
  color: var(--tp-coral);
  opacity: 1;
  transform: translateX(var(--tp-space-2xs));
}

.tp-press-action { margin-block-start: var(--tp-space-2xl); }

@media (min-width: 900px) {
  .tp-press-top { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: start; }
  .tp-press-index { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--tp-grid-gap); }
}

/* --- How to describe it ------------------------------------------------------ */
.tp-language { margin-block-start: var(--tp-space-3xl); display: grid; gap: var(--tp-space-2xl); }
.tp-language__col { display: grid; gap: var(--tp-space-md); align-content: start; }

.tp-language__title {
  margin: 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-label);
  font-weight: var(--tp-weight-bold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.tp-language__list { list-style: none; margin: 0; padding: 0; display: grid; }

.tp-language__list li {
  padding-block: var(--tp-space-md);
  border-block-start: 1px solid var(--tp-rule);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-h3);
  line-height: 1.3;
}

.tp-language__list li:last-child { border-block-end: 1px solid var(--tp-rule); }

/* The second column is what this is not, so it is set quieter and struck
   through: the difference has to read at a glance. */
.tp-language__list--not li { color: var(--tp-fg-muted); }

.tp-language__list--not li::before {
  content: "";
  display: inline-block;
  width: 1.25rem;
  height: 1px;
  margin-inline-end: 0.75rem;
  vertical-align: 0.3em;
  background: var(--tp-coral);
}

@media (min-width: 900px) {
  .tp-language { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--tp-grid-gap); }
}

/* --- Hashtags ---------------------------------------------------------------- */
.tp-share-social__grid { display: grid; gap: var(--tp-space-xl); }

.tp-share-social__primary {
  margin: 0 0 var(--tp-space-md);
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-h2);
  line-height: 1.1;
  color: var(--tp-coral);
}

.tp-share-social__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-space-sm) var(--tp-space-lg);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-body);
  color: var(--tp-fg-muted);
}

@media (min-width: 900px) {
  .tp-share-social__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: center; }
}

/* --- The close ---------------------------------------------------------------- */
.tp-share-final__grid { display: grid; gap: var(--tp-grid-gap); align-items: center; }
.tp-share-final h2 { margin: 0 0 var(--tp-space-md); max-width: 18ch; }
.tp-share-final p { margin: 0 0 var(--tp-space-sm); max-width: 48ch; }

/* On Ink the placeholder has to invert with the surface. */
.tp-share-final .tp-slot {
  background: rgba(var(--tp-paper-rgb), 0.06);
  border-color: rgba(var(--tp-paper-rgb), 0.28);
}

/* The close carries only words now, so it keeps a reading measure rather
   than a column that used to have a graphic beside it. */
.tp-share-final h2 { max-width: 20ch; }
.tp-share-final p { max-width: 54ch; }

/* --- Copy button state --------------------------------------------------------- */
.tp-btn[data-copy].is-copied,
.tp-link[data-copy].is-copied { color: var(--tp-coral); }

/* --- The page's own navigation ---------------------------------------------
   A long page carries a sticky index under the site header. Set on Ink so it
   separates from every section surface below it (Paper, Stone and Cream all
   sit close together) and reads as navigation rather than as a caption. It
   scrolls sideways on a phone rather than wrapping to three lines. */
.tp-subnav {
  position: sticky;
  top: var(--site-header-height, 0px);
  z-index: 40;
  background: var(--tp-ink);
  color: var(--tp-paper);
}

.tp-subnav__inner {
  display: flex;
  align-items: center;
  gap: var(--tp-space-lg);
  overflow-x: auto;
  scrollbar-width: none;
}

.tp-subnav__inner::-webkit-scrollbar { display: none; }

/* The page's name, so the bar states what it is indexing. */
.tp-subnav__title {
  flex: none;
  margin: 0;
  padding-block: var(--tp-space-sm);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-caption);
  font-weight: var(--tp-weight-bold);
  letter-spacing: 0.02em;
  color: var(--tp-paper);
  white-space: nowrap;
}

.tp-subnav__title span { color: var(--tp-coral); }

.tp-subnav__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: var(--tp-space-lg);
  white-space: nowrap;
}

.tp-subnav__list a {
  display: block;
  position: relative;
  padding-block: var(--tp-space-sm);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-caption);
  font-weight: var(--tp-weight-medium, 500);
  letter-spacing: 0.06em;
  color: rgba(var(--tp-paper-rgb), 0.66);
  text-decoration: none;
  transition: color 160ms ease;
}

/* The mark sits on the bar's own bottom edge rather than under the word, so
   the current section reads from across the page. */
.tp-subnav__list a::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 3px;
  background: var(--tp-coral);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 200ms ease;
}

.tp-subnav__list a:hover,
.tp-subnav__list a:focus-visible { color: var(--tp-paper); }

.tp-subnav__list a.is-current { color: var(--tp-paper); }
.tp-subnav__list a.is-current::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .tp-subnav__list a::after { transition: none; }
}

/* The site header above it is Paper with a hairline; against Ink that line
   is redundant, so the two bars read as one unit. */
.tp-share-page .tp-subnav { border-block-start: 0; }

/* An anchored section has to clear both sticky bars, the site header and the
   page's own nav, or its heading lands underneath them. */
.tp-share-page .tp-section[id] {
  scroll-margin-top: calc(var(--site-header-height, 0px) + 3.5rem);
}

/* --- Carousel ---------------------------------------------------------------
   A scroll-snap track. It swipes on a phone and scrolls with a trackpad with
   no script at all; the buttons and the counter are the enhancement.

   The buttons flank the slide rather than sitting in a bar above it, so the
   control is attached to the thing it moves. Below the breakpoint they drop
   under the track, where a thumb can reach them and where they are not
   sitting on top of the post. */
.tp-carousel { margin-block-start: var(--tp-space-2xl); }

.tp-carousel__viewport { position: relative; }

.tp-carousel__count {
  margin: var(--tp-space-md) 0 0;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-caption);
  letter-spacing: 0.14em;
  color: var(--tp-fg-muted);
}

.tp-carousel__count [data-carousel-current] { color: var(--tp-coral); }

.tp-carousel__btn {
  width: 3.5rem;
  height: 3.5rem;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--tp-rule);
  background: var(--tp-bg, var(--tp-paper));
  color: inherit;
  cursor: pointer;
  transition: border-color 160ms ease, color 160ms ease, opacity 160ms ease;
}

.tp-carousel__btn svg { width: 1.5rem; height: 1.5rem; }

.tp-carousel__btn:hover:not(:disabled),
.tp-carousel__btn:focus-visible { border-color: var(--tp-coral); color: var(--tp-coral); }

.tp-carousel__btn:disabled { opacity: 0.25; cursor: default; }

/* Below the breakpoint: a pair under the track, thumb height. Flex rather
   than grid areas, because a grid column sized to the buttons would let the
   track size itself from its slides and run off the page. */
.tp-carousel__viewport {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-space-md) var(--tp-space-2xs);
}

.tp-carousel__track { flex: 0 0 100%; min-width: 0; order: 1; }
.tp-carousel__btn--prev { order: 2; }
.tp-carousel__btn--next { order: 3; }

/* They only flank the slide once the page gutter is wide enough to hold them
   outside it. Any narrower and they would sit on top of the post's own copy,
   so they stay under the track. */
@media (min-width: 1320px) {
  .tp-carousel__viewport { display: block; }

  .tp-carousel__btn {
    position: absolute;
    top: 50%;
    z-index: 3;
    width: 4rem;
    height: 4rem;
    transform: translateY(-50%);
  }

  .tp-carousel__btn svg { width: 1.75rem; height: 1.75rem; }

  .tp-carousel__btn--prev { inset-inline-start: -5rem; }
  .tp-carousel__btn--next { inset-inline-end: -5rem; }
}

.tp-carousel__track {
  margin: 0;
  padding: var(--tp-space-xl) 0;
  display: grid;
  /* The track shares .tp-post-list, whose single-column rule would otherwise
     win here and squeeze all three slides into the frame. */
  grid-template-columns: none;
  grid-auto-flow: column;
  /* A fixed 100%, not minmax: with a min of 0 the tracks size to content
     and all three slides squeeze into the frame instead of one per view. */
  grid-auto-columns: 100%;
  gap: var(--tp-grid-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}

.tp-carousel__track::-webkit-scrollbar { display: none; }
.tp-carousel__track > * { scroll-snap-align: start; }
.tp-carousel__track:focus-visible { outline: 2px solid var(--tp-coral); outline-offset: 4px; }

@media (prefers-reduced-motion: reduce) {
  .tp-carousel__track { scroll-behavior: auto; }
}

/* A slot holding real artwork: no keyline, no tint, the image fills the ratio
   the placeholder was reserving. */
.tp-slot--filled {
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  overflow: hidden;
}

.tp-slot--filled img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Artwork that must not be cropped: a logo sits inside the slot's ratio with
   room around it, on the surface rather than on a tint. */
.tp-slot--contain { background: var(--tp-stone-tint); padding: var(--tp-space-xl); }
.tp-slot--contain img { object-fit: contain; }

/* --- An asset: preview, name, and the files it comes in ---------------------
   Used by the logos and the badges. Smaller and quieter than the old library
   card: these sections are short, so each item is an entry, not a panel. */
.tp-asset-grid {
  margin-block-start: var(--tp-space-2xl);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--tp-space-2xl) var(--tp-grid-gap);
}

.tp-asset { display: grid; gap: var(--tp-space-xs); align-content: start; }

.tp-asset__title {
  margin: var(--tp-space-2xs) 0 0;
  font-family: var(--tp-font-display);
  font-weight: var(--tp-weight-bold);
  font-size: var(--tp-size-body);
  line-height: 1.3;
}

.tp-asset__body {
  margin: 0;
  font-size: var(--tp-size-body-sm);
  line-height: var(--tp-lh-body-sm);
  color: var(--tp-fg-muted);
}

/* The formats, as a row of short links rather than a stack of buttons. */
.tp-asset__files {
  list-style: none;
  margin: var(--tp-space-2xs) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--tp-space-2xs);
}

.tp-asset__files a {
  display: block;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--tp-rule);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: inherit;
  transition: border-color 160ms ease, color 160ms ease;
}

.tp-asset__files a:hover,
.tp-asset__files a:focus-visible { border-color: var(--tp-coral); color: var(--tp-coral); }

@media (min-width: 640px) { .tp-asset-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .tp-asset-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.tp-share-action { margin-block-start: var(--tp-space-2xl); }

/* --- The embed snippet ------------------------------------------------------
   Shown rather than hidden: anyone pasting it into their site wants to see
   what they are pasting. Closed by default so the grid stays quiet. */
.tp-embed { margin-block-start: var(--tp-space-2xs); }

.tp-embed summary {
  cursor: pointer;
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tp-fg-muted);
}

.tp-embed summary:hover { color: var(--tp-coral); }

.tp-embed__body {
  margin-block-start: var(--tp-space-xs);
  display: grid;
  gap: var(--tp-space-xs);
  justify-items: start;
}

.tp-embed code {
  display: block;
  width: 100%;
  max-height: 7.5rem;
  overflow: auto;
  padding: var(--tp-space-sm);
  background: var(--tp-stone-tint);
  border: 1px solid var(--tp-rule);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.75rem;
  line-height: 1.5;
  word-break: break-all;
}

.tp-embed .tp-link { border: 0; background: none; padding: 0; font: inherit; cursor: pointer; }

/* The carousel's counter and its set download sit on one line. */
.tp-carousel__foot {
  margin-block-start: var(--tp-space-md);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tp-space-md);
}

.tp-carousel__foot .tp-carousel__count { margin: 0; }

/* A resource that is written but not published yet: stated rather than shown
   as a control that does nothing. */
.tp-press-index__item--soon { cursor: default; opacity: 0.7; }

.tp-tag {
  display: inline-block;
  margin-inline-start: var(--tp-space-2xs);
  padding: 0.15rem 0.45rem;
  border: 1px solid var(--tp-coral);
  font-family: var(--tp-font-display);
  font-size: var(--tp-size-micro);
  font-weight: var(--tp-weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tp-coral);
  vertical-align: 0.15em;
}
