/* ==========================================================================
   pogancristian.com — stylesheet
   Design system: "engineering report"
   Reference: build spec v1.0

   TYPE RULE — enforce this or the three-family system drifts:
     Serif (Newsreader)  : 22px and above ONLY
     Mono  (IBM Plex)    : 14px and below ONLY
     Sans  (Inter Tight) : everything else
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. FONTS — self-hosted latin subsets, ~95KB total.
   Newsreader 400 and Inter Tight 400 are preloaded in each page head;
   everything else loads normally with swap.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/newsreader-latin-400.woff2") format("woff2");
}

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/newsreader-latin-500.woff2") format("woff2");
}

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/inter-tight-latin-400.woff2") format("woff2");
}

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/inter-tight-latin-600.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-latin-400.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-latin-500.woff2") format("woff2");
}

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */

:root {
  /* Surface */
  --canvas:       #FAF8F5;
  --canvas-sunk:  #F2EEE8;

  /* Text */
  --ink:          #1A1815;
  --muted:        #6B665D;

  /* Structure */
  /* Hairlines carry all section separation, so they must actually be visible.
     #E3DED6 measured 1.26:1 against --canvas and disappeared. */
  --rule:         #D9D2C6;

  /* Accent — oxide. Target coverage: ~3% of pixels. */
  --accent:       #A8431E;
  --accent-deep:  #7E3216;

  /* Diagram semantics — SVG ONLY, never UI chrome */
  --dia-ok:       #2F6B4F;
  --dia-fail:     #8A2A2A;
  --dia-group:    #6B665D;  /* cascade container frames — 5.38:1, meets 1.4.11 */

  /* Families */
  --f-display: "Newsreader", "Source Serif 4", Georgia, "Times New Roman", serif;
  --f-body:    "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --f-mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Scale — desktop */
  --t-h1:      60px;
  --t-h2:      38px;
  --t-h3:      22px;
  --t-body:    19px;
  --t-body-lg: 22px;
  --t-small:   16px;
  --t-label:   13px;
  --t-caption: 14px;
  --t-numeral: 52px;

  /* Spacing — 8px base */
  --s-1: 8px;
  --s-2: 16px;
  --s-3: 24px;
  --s-4: 32px;
  --s-5: 48px;
  --s-6: 64px;
  --s-7: 96px;
  --s-8: 120px;

  /* Layout */
  --container: 1240px;
  --measure:   680px;
  --margin-w:  140px;
  --gutter:    32px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --------------------------------------------------------------------------
   2. RESET
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.65;
  letter-spacing: 0.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol {
  margin: 0;
}

ul, ol { padding: 0; list-style: none; }

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

a { color: inherit; }

button { font: inherit; }

/* --------------------------------------------------------------------------
   3. TYPOGRAPHY
   -------------------------------------------------------------------------- */

.h1 {
  font-family: var(--f-display);
  font-size: var(--t-h1);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

/* Section titles run at 500 against 400 body — the weight step, together
   with the size step, is what separates title from text at a glance. */
.h2 {
  font-family: var(--f-display);
  font-size: var(--t-h2);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-wrap: balance;
  color: var(--ink);
}

.h3 {
  font-family: var(--f-body);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.005em;
}

/* Serif at 22px — permitted by the type rule. Used for the stall statements
   and FAQ questions, where a quoted register is wanted. */
.serif-md {
  font-family: var(--f-display);
  font-size: var(--t-h3);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: -0.01em;
}

.lede {
  font-size: var(--t-body-lg);
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--muted);
}

.small { font-size: var(--t-small); line-height: 1.55; }

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

.label {
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

.caption {
  font-family: var(--f-mono);
  font-size: var(--t-caption);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--muted);
}

/* Capability spec-sheet lists. Mono, wrapped, generous leading. */
.spec {
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 400;
  line-height: 1.9;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

p + p { margin-top: var(--s-2); }

/* --------------------------------------------------------------------------
   4. PAGE GRID
   Column 1: instrument margin  |  Column 2: reading content  |  Column 3: air
   -------------------------------------------------------------------------- */

.page {
  display: grid;
  grid-template-columns: var(--margin-w) minmax(0, var(--measure)) 1fr;
  column-gap: var(--gutter);
  row-gap: 0;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--s-5);
}

.page > .col-margin { grid-column: 1; }
.page > .col-main   { grid-column: 2; }
.page > .col-wide   { grid-column: 2 / -1; }

/* --------------------------------------------------------------------------
   5. SECTIONS
   Hairline separation, not colour blocking. Two sunk bands only:
   the stack grid and the footer.
   -------------------------------------------------------------------------- */

.section {
  padding-block: var(--s-8);
  border-top: 1px solid var(--rule);
}

.section--sunk {
  background: var(--canvas-sunk);
}

.section--close {
  padding-block: 160px;
}

/* --------------------------------------------------------------------------
   6. INSTRUMENT MARGIN (signature element)
   Never repeats the heading. Always adds a fact.
   -------------------------------------------------------------------------- */

.col-margin {
  position: sticky;
  top: 88px;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-top: 6px; /* optical alignment to serif cap-height */
}

.margin-label {
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink);
}

.margin-fact {
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: 0.02em;
  color: var(--muted);
}

.margin-fact + .margin-fact { margin-top: calc(var(--s-1) * -0.5); }

/* --------------------------------------------------------------------------
   7. HEADER
   -------------------------------------------------------------------------- */

.masthead {
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--rule);
}

.masthead__inner {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--s-5);
}

.wordmark {
  font-family: var(--f-display);
  font-size: var(--t-h3);
  font-weight: 400;
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
}

.nav {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
}

.nav a {
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--muted);
  transition: color 120ms var(--ease);
}

.nav a:hover,
.nav a[aria-current="page"] { color: var(--ink); }

/* The nav's Book a call button must stay white-on-ink - .nav a would
   otherwise out-specify .btn and tint it muted (near-invisible on hover) */
.nav a.btn,
.nav a.btn:hover { color: #FFFFFF; }

/* Sticky bar — appears after 400px, JS toggles .is-visible */
.stickybar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  height: 48px;
  overflow: hidden; /* nothing may ever protrude below the bar */
  background: var(--canvas);
  border-bottom: 1px solid var(--rule);
  transform: translateY(-100%);
  transition: transform 160ms var(--ease);
}

.stickybar .btn {
  flex: none; /* the button never shrinks or wraps when the word row is tight */
  white-space: nowrap;
}

.stickybar.is-visible { transform: translateY(0); }

.stickybar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  height: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--s-5);
}

.stickybar .wordmark { font-size: 17px; }

/* Reading progress: one word per section, coloured once the section is reached */
.stickybar__sections {
  display: flex;
  align-items: center;
  gap: 13px;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}

.stickybar__sections a {
  font-family: var(--f-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--muted);
  opacity: 0.55;
  transition: color 120ms var(--ease), opacity 120ms var(--ease);
}

.stickybar__sections a.is-read {
  color: var(--accent);
  opacity: 1;
}

.stickybar__sections a:hover { color: var(--ink); opacity: 1; }

/* Continuous scroll-progress bar along the sticky bar's bottom edge */
.stickybar__bar {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: 0;
  background: var(--accent);
}

/* --------------------------------------------------------------------------
   8. BUTTONS
   Accent fill is used ONCE per page (hero). Everything else is ink.
   -------------------------------------------------------------------------- */

.btn {
  display: inline-block;
  padding: 14px 28px;
  border: 1px solid transparent;
  border-radius: 4px;
  background: var(--ink);
  color: #FFFFFF; /* pure white on ink — incl. BOOK A CALL in the sticky bar */
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 120ms var(--ease);
}

.btn:hover { background: #2E2A25; }

.btn--accent { background: var(--accent); }
.btn--accent:hover { background: var(--accent-deep); }

.btn--sm { padding: 9px 18px; font-size: 12px; }

/* Inline link */
.link {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-underline-offset 120ms var(--ease);
}

.link:hover { text-underline-offset: 5px; }

/* --------------------------------------------------------------------------
   9. HERO — the one centred element on the site
   -------------------------------------------------------------------------- */

.hero {
  padding-block: 160px var(--s-8);
}

/* Subpage heroes announce rather than dominate */
.hero--page {
  padding-block: 120px 88px;
}

.hero__inner {
  max-width: 980px; /* wide enough that the H1's two authored lines never re-wrap */
  margin-inline: auto;
  padding-inline: var(--s-5);
  text-align: center;
}

/* The manual two-line break is load-bearing. Fluid size keeps each authored
   line on one rendered line at every viewport width. */
.hero .h1 {
  font-size: clamp(24px, 6.7vw, 60px);
}

.hero .lede {
  max-width: 620px;
  margin-inline: auto;
  margin-top: var(--s-4);
}

.hero__cta { margin-top: var(--s-5); }

.hero__meta { margin-top: var(--s-4); }

/* --------------------------------------------------------------------------
   10. RESULT NUMERAL — the most characteristic component
   Every numeral carries its mechanism in the sentence beneath.
   -------------------------------------------------------------------------- */

.result { margin-top: var(--s-5); }

.result__figure {
  font-family: var(--f-mono);
  font-size: var(--t-numeral);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--accent);
}

.result__body {
  margin-top: var(--s-2);
  max-width: 560px;
}

/* --------------------------------------------------------------------------
   11. ASSET FRAME — diagrams and screenshots
   No browser chrome. No tilt. No shadow.
   -------------------------------------------------------------------------- */

.asset {
  margin-top: var(--s-5);
}

.asset__frame {
  padding: var(--s-3);
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--canvas);
}

.asset__frame > svg { width: 100%; height: auto; }

.asset__frame > video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 2px;
  background: var(--ink); /* letterbox bars in ink, not default black-on-canvas gap */
}

.asset figcaption { margin-top: 12px; }

/* Scroll hint sits inside the frame on narrow screens only */
.asset__hint { display: none; }

/* Smaller photo assets, centred on the full page width */
.asset--narrow {
  grid-column: 1 / -1;
  width: 100%;
  max-width: 680px;
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   12. STALL STATEMENTS
   -------------------------------------------------------------------------- */

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

.stall li {
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--rule);
}

.stall__close { margin-top: var(--s-5); }

/* --------------------------------------------------------------------------
   13. PILLARS
   Stacked, never side by side. Sales always first.
   -------------------------------------------------------------------------- */

.pillar + .pillar {
  margin-top: var(--s-7);
  padding-top: var(--s-7);
  border-top: 1px solid var(--rule);
}

.pillar__desc { margin-top: var(--s-3); }

.pillar .spec { margin-top: var(--s-3); }

/* --------------------------------------------------------------------------
   14. PHASES — the only numbered sequence on the page
   -------------------------------------------------------------------------- */

.phase + .phase {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
}

.phase__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-2);
}

.phase__num {
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.09em;
  color: var(--accent);
}

.phase__terms {
  font-family: var(--f-mono);
  font-size: var(--t-caption);
  letter-spacing: 0.02em;
  color: var(--muted);
}

.phase__body { margin-top: var(--s-2); }

/* --------------------------------------------------------------------------
   15. TABLES
   Hairlines only. No zebra. Figures in mono.
   -------------------------------------------------------------------------- */

.table {
  width: 100%;
  margin-top: var(--s-4);
  border-collapse: collapse;
  font-size: var(--t-small);
}

.table th {
  padding: 12px 16px;
  background: var(--canvas-sunk);
  border: 1px solid var(--rule);
  font-family: var(--f-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-align: left;
  color: var(--muted);
}

.table td {
  padding: 12px 16px;
  border: 1px solid var(--rule);
  vertical-align: top;
}

.table .num {
  font-family: var(--f-mono);
  font-size: var(--t-caption);
  text-align: right;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   16. STACK GRID
   Monochrome. The tools are interchangeable; the operator is the constant.
   -------------------------------------------------------------------------- */

.stack {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--s-5) var(--s-4);
  margin-top: var(--s-5);
}

.stack li {
  font-family: var(--f-mono);
  font-size: var(--t-caption);
  letter-spacing: 0.04em;
}

/* Each tool: colour icon at a uniform 20px + name, linking to the tool's site.
   Text alpha computes 5.17:1 on --canvas-sunk. Do not lower: 0.45 fails AA. */
.stack__item {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px; /* touch target */
  color: rgba(26, 24, 21, 0.65);
  text-decoration: none;
  transition: color 120ms var(--ease);
}

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

.stack__icon {
  height: 20px;
  width: 20px;
  object-fit: contain;
  flex: none;
  border-radius: 3px;
}

/* --------------------------------------------------------------------------
   17. BIO SPLIT — the only column split in the content area
   -------------------------------------------------------------------------- */

.bio {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: var(--s-5);
  align-items: start;
  margin-top: var(--s-5);
}

.portrait {
  aspect-ratio: 4 / 5;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--canvas-sunk);
  object-fit: cover;
  width: 100%;
}

/* Placeholder shown while real photography is pending */
.portrait--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-3);
  text-align: center;
}

.bio__text > p + p { margin-top: var(--s-3); }

/* --------------------------------------------------------------------------
   18. FAQ — collapsed by default, native <details> disclosure.
   A mono + / − on the right is the toggle indicator.
   -------------------------------------------------------------------------- */

.faq { margin-top: var(--s-5); }

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

.faq__item:last-child { border-bottom: 1px solid var(--rule); }

.faq__item summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding-block: var(--s-4);
  cursor: pointer;
  list-style: none; /* remove default disclosure triangle */
}

.faq__item summary::-webkit-details-marker { display: none; }

.faq__item summary::after {
  content: "+";
  font-family: var(--f-mono);
  font-size: var(--t-caption);
  font-weight: 500;
  color: var(--muted);
  flex: none;
  transition: color 120ms var(--ease);
}

.faq__item[open] summary::after { content: "\2212"; /* minus */ }

.faq__item summary:hover::after { color: var(--accent); }

.faq__body {
  padding-bottom: var(--s-4);
}

.faq__body > p + p { margin-top: var(--s-2); }

/* --------------------------------------------------------------------------
   19. CASE STUDIES
   -------------------------------------------------------------------------- */

.case + .case {
  margin-top: var(--s-8);
  padding-top: var(--s-8);
  border-top: 1px solid var(--rule);
}

.case__block { margin-top: var(--s-5); }

.case__block > .label + p { margin-top: var(--s-2); }

/* Insight text blocks: semantic cues in the diagram colour code -
   red = the failure mode, accent = the path to take, green = fit */
.case__block {
  padding-left: 18px;
  border-left: 2px solid var(--rule);
}

.case__block .label {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.blk-glyph { font-weight: 500; }

.case__block--usually .blk-glyph { color: var(--dia-fail); }
.case__block--why .blk-glyph { color: var(--muted); }
.case__block--instead .blk-glyph { color: var(--accent); }
.case__block--fit .blk-glyph { color: var(--dia-ok); }

.case__block--instead { border-left-color: var(--accent); }

.case__block strong { font-weight: 600; }

.margin-fact.case__stack {
  margin-top: var(--s-3);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* --------------------------------------------------------------------------
   19b. RELEVANCE CHIPS — reorder the insights, never hide them
   -------------------------------------------------------------------------- */

.chips-title {
  text-align: center; /* aligns with the centred chip rows below */
  font-weight: 400;
  color: var(--ink); /* match the page H1, not the muted lede */
}

.chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center; /* every row centred, incl. the remainder */
  gap: 10px;
  margin-top: var(--s-3);
}

.chip {
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--canvas);
  border: 1px solid var(--rule);
  border-radius: 4px;
  flex: 0 0 152px; /* uniform blocks - six per full row at desktop */
  padding: 9px 0;
  text-align: center;
  min-height: 38px;
  cursor: pointer;
  transition: color 120ms var(--ease), border-color 120ms var(--ease);
}

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

.chip.is-on { color: var(--accent); border-color: var(--accent); }

/* Reorder crossfade */
section[data-cat] { transition: opacity 150ms var(--ease); }
section[data-cat].is-dim { opacity: 0; }

/* Matched insights: accent category in the margin with a check */
.section.is-matched > .page > .col-margin > .margin-fact:first-of-type {
  color: var(--accent);
}
.section.is-matched > .page > .col-margin > .margin-fact:first-of-type::before {
  content: "\2713 ";
}

/* Divider between the matched group and the rest */
.insights-divider {
  padding: var(--s-5) 0 0;
  text-align: center;
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

/* --------------------------------------------------------------------------
   20. ABOUT
   -------------------------------------------------------------------------- */

.chapter + .chapter {
  margin-top: var(--s-6);
  padding-top: var(--s-6);
  border-top: 1px solid var(--rule);
}

/* Organisation marks inside a chapter (P&G, Dalli) */
.orgs {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-3);
}

.orgs__logo {
  height: 40px;
  width: 40px;
  object-fit: contain;
  opacity: 0.7;
}

.chapter__body { margin-top: var(--s-3); }

.photo {
  width: 100%;
  height: auto; /* keep natural aspect ratio when the width/height attrs are overridden */
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--canvas-sunk);
}

.photo--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 320px;
  padding: var(--s-4);
  text-align: center;
}

/* --------------------------------------------------------------------------
   21. FOOTER
   -------------------------------------------------------------------------- */

.footer {
  padding-block: var(--s-6);
  background: var(--canvas-sunk);
  border-top: 1px solid var(--rule);
}

.footer__inner {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--s-5);
}

.footer__cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
}

.footer__cols a {
  text-decoration: none;
  color: var(--muted);
  transition: color 120ms var(--ease);
}

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

.footer__list { display: flex; flex-direction: column; gap: var(--s-1); }

.footer__list a { display: inline-flex; align-items: center; gap: 8px; }

/* Small social marks next to the LinkedIn / GitHub links */
.social__logo {
  height: 15px;
  width: 15px;
  object-fit: contain;
  flex: none;
  opacity: 0.7;
}

.footer__legal {
  margin-top: var(--s-5);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
}

/* --------------------------------------------------------------------------
   22. CALENDAR EMBED SLOT
   -------------------------------------------------------------------------- */

.calendar {
  margin-top: var(--s-5);
  min-height: 340px;
  padding: var(--s-4);
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--canvas);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--s-2);
}

/* Inline Google appointment embed. Kept narrow on purpose: below ~700px the
   widget switches to its compact layout - date picker first, then hours for
   the selected day only - which is also short enough to avoid both the blank
   band and internal scrolling. */
.calendar--embed {
  padding: 0;
  overflow: hidden;
  grid-column: 1 / -1;      /* span the full page grid, centred */
  width: 100%;
  max-width: 640px;
  margin-inline: auto;
}

.calendar--embed iframe {
  display: block;
  width: 100%;
  height: 920px;
  border: 0;
}

@media (max-width: 899px) {
  .calendar--embed iframe { height: 950px; } /* compact layout stacks taller on phones */
}

/* Footnote under the embed, centred with it */
.calendar__foot {
  grid-column: 1 / -1;
  width: 100%;
  max-width: 1000px;
  margin-inline: auto;
  margin-top: var(--s-3);
  text-align: center;
}

/* --------------------------------------------------------------------------
   23. UTILITIES
   -------------------------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--ink);
  color: var(--canvas);
  font-family: var(--f-mono);
  font-size: var(--t-label);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  text-decoration: none;
}

.skip-link:focus { left: 8px; top: 8px; }

.mt-3 { margin-top: var(--s-3); }
.mt-4 { margin-top: var(--s-4); }
.mt-5 { margin-top: var(--s-5); }

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

/* --------------------------------------------------------------------------
   24. FOCUS
   -------------------------------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   25. MOTION
   Opacity-only reveal on assets. No transforms anywhere.
   -------------------------------------------------------------------------- */

.reveal { opacity: 1; }

/* Hidden only once JS has confirmed it is alive. A failsafe in the head
   script removes .js after 2s if main.js never loads, so content can never
   be stranded at opacity 0. */
.js .reveal { opacity: 0; transition: opacity 180ms var(--ease); }
.js .reveal.is-in { opacity: 1; }

/* --------------------------------------------------------------------------
   26. RESPONSIVE
   -------------------------------------------------------------------------- */

/* --- Tablet: margin narrows, facts drop --- */
@media (max-width: 1159px) {
  :root {
    --margin-w: 108px;
    --t-h1: 50px;
    --t-h2: 34px;
    --t-numeral: 46px;
  }

  .margin-fact { display: none; }

}

@media (max-width: 1259px) {
  /* Not enough width for the section words; the 2px bar carries the progress */
  .stickybar__sections { display: none; }
}

/* --- Mobile: margin collapses to an inline eyebrow --- */
@media (max-width: 899px) {
  :root {
    --t-h1: 36px;
    --t-h2: 27px;
    --t-h3: 20px;
    --t-body: 17px;
    --t-body-lg: 19px;
    --t-small: 15px;
    --t-label: 12px;
    --t-caption: 13px;
    --t-numeral: 40px;
    --s-8: 64px;
  }

  .page {
    grid-template-columns: minmax(0, 1fr);
    padding-inline: var(--s-3);
  }

  .page > .col-margin,
  .page > .col-main,
  .page > .col-wide { grid-column: 1; }

  /* Eyebrow form — same semantic device, different shape */
  .col-margin {
    position: static;
    padding-top: 0;
    margin-bottom: var(--s-3);
  }

  .masthead__inner,
  .stickybar__inner,
  .footer__inner,
  .hero__inner { padding-inline: var(--s-3); }

  .hero { padding-block: var(--s-7) var(--s-8); }
  .section--close { padding-block: var(--s-7); }

  .nav { gap: var(--s-3); }
  .nav a.nav__link { display: none; } /* Work / About move to the footer */

  .bio { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
  .portrait { max-width: 220px; }

  .stack { grid-template-columns: repeat(3, 1fr); gap: var(--s-4) var(--s-3); }

  .footer__cols { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }

  .pillar + .pillar,
  .case + .case { margin-top: var(--s-6); padding-top: var(--s-6); }

  /* Diagrams scroll horizontally. Topology is the content — never reflow it. */
  .asset__frame {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  .asset__frame > svg { min-width: 560px; }

  .asset__hint {
    display: block;
    margin-bottom: var(--s-2);
    font-family: var(--f-mono);
    font-size: 12px;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--muted);
  }

  .table { font-size: 14px; }
  .table th, .table td { padding: 10px 12px; }

  /* Touch targets */
  .nav a, .footer__cols a { display: inline-block; min-height: 44px; line-height: 44px; }
  .footer__list { gap: 0; }
}

@media (max-width: 460px) {
  .stack { grid-template-columns: repeat(2, 1fr); }
  .btn { display: block; text-align: center; }
}

/* --------------------------------------------------------------------------
   26b. STALL PROGRESS ANIMATION (Block 2 diagram)
   Bar starts at 70% in steel blue (#1F3A5F - the spec's fallback accent),
   fills to 100% on scroll-into-view, ends green and stays there.
   Base styles ARE the finished state, so no-JS and reduced-motion users
   see the completed bar. The .is-in trigger reuses the reveal observer.
   -------------------------------------------------------------------------- */

/* Base styles ARE the finished state (bar full + green). Only the transform
   uses a keyframe; every colour/opacity change is a plain transition with a
   delay - keyframed fill/var() combinations are unreliable in Safari. */

/* This diagram runs frameless - no contour line around it */
.stall-anim .asset__frame { border: none; }

.stall-anim .sd-bar {
  fill: #2F6B4F; /* --dia-ok, literal for Safari-safe transition */
  transform-box: fill-box;
  transform-origin: left center;
}

.stall-anim .sd-dash,
.stall-anim .sd-mark70 { opacity: 0; }

.stall-anim .sd-prod { stroke: #2F6B4F; }
.stall-anim .sd-prodtext { fill: #2F6B4F; }

/* Start state, held until the figure scrolls into view. Also the RESET state:
   scrolling up above the figure removes .is-in so the bar replays on return.
   transition: none makes that rollback snap while off-screen. */
.js .stall-anim:not(.is-run) .sd-bar { transform: scaleX(0.7); fill: #1F3A5F; transition: none; }
.js .stall-anim:not(.is-run) .sd-dash,
.js .stall-anim:not(.is-run) .sd-mark70 { opacity: 1; transition: none; }
.js .stall-anim:not(.is-run) .sd-lbl100 { opacity: 0; transition: none; }
.js .stall-anim:not(.is-run) .sd-prod { stroke: var(--muted); transition: none; }
.js .stall-anim:not(.is-run) .sd-prodtext { fill: var(--muted); transition: none; }

/* Timeline on .is-in: grow 0.3-1.9s, everything turns green 1.9-2.3s */
.js .stall-anim.is-run .sd-bar {
  animation: sd-grow 1.6s cubic-bezier(0.22, 0.61, 0.36, 1) 0.3s both;
  transition: fill 0.4s ease-out 1.9s;
}

@keyframes sd-grow {
  from { transform: scaleX(0.7); }
  to   { transform: scaleX(1); }
}

.js .stall-anim.is-run .sd-dash { transition: opacity 1.6s ease-out 0.3s; }
.js .stall-anim.is-run .sd-mark70 { transition: opacity 0.6s ease-out 0.7s; }
.js .stall-anim.is-run .sd-lbl100 { opacity: 1; transition: opacity 0.4s ease-out 2s; }
.js .stall-anim.is-run .sd-prod { transition: stroke 0.4s ease-out 1.9s; }
.js .stall-anim.is-run .sd-prodtext { transition: fill 0.4s ease-out 1.9s; }

/* --------------------------------------------------------------------------
   26c. ENGAGEMENT BOARD ANIMATION (Block 5)
   One card completes: slides from IN PROGRESS into DONE, turns green,
   the check draws in, counts update, and a backlog card moves up.
   Base styles ARE the end state; :not(.is-run) holds the start; the
   same centre-band observer as the stall bar drives .is-run.
   -------------------------------------------------------------------------- */

.board-anim .asset__frame { border: none; }

/* Base = finished board */
.board-anim .pb-herorect { stroke: #2F6B4F; }
.board-anim .pb-herotitle { fill: #6B665D; }
.board-anim .pb-herocheck { stroke-dasharray: 1; stroke-dashoffset: 0; }
.board-anim .pb-herometa1 { opacity: 0; }
.board-anim .pb-cb-old,
.board-anim .pb-cd-old { opacity: 0; }

/* Start state, held until the board reaches screen centre; snaps on reset */
.js .board-anim:not(.is-run) .pb-hero { transform: translate(-530px, 0); transition: none; }
.js .board-anim:not(.is-run) .pb-herorect { stroke: #1A1815; transition: none; }
.js .board-anim:not(.is-run) .pb-herotitle { transform: translateX(-22px); fill: #1A1815; transition: none; }
.js .board-anim:not(.is-run) .pb-herocheck { stroke-dashoffset: 1; opacity: 0; transition: none; }
.js .board-anim:not(.is-run) .pb-herometa1 { opacity: 1; transform: translateX(-22px); transition: none; }
.js .board-anim:not(.is-run) .pb-herometa2 { opacity: 0; transition: none; }
.js .board-anim:not(.is-run) .pb-done-shift { transform: translateY(-76px); transition: none; }
.js .board-anim:not(.is-run) .pb-b1 { transform: translateX(-265px); transition: none; }
.js .board-anim:not(.is-run) .pb-bl-shift { transform: translateY(76px); transition: none; }
.js .board-anim:not(.is-run) .pb-cb-old,
.js .board-anim:not(.is-run) .pb-cd-old { opacity: 1; transition: none; }
.js .board-anim:not(.is-run) .pb-cb-new,
.js .board-anim:not(.is-run) .pb-cd-new { opacity: 0; transition: none; }

/* Timeline on .is-run */
.js .board-anim.is-run .pb-hero { transition: transform 0.7s var(--ease) 0.3s; }

.js .board-anim.is-run .pb-done-shift { transition: transform 0.45s var(--ease); }
.js .board-anim.is-run .pb-d1 { transition-delay: 0.35s; }
.js .board-anim.is-run .pb-d2 { transition-delay: 0.42s; }
.js .board-anim.is-run .pb-d3 { transition-delay: 0.49s; }

.js .board-anim.is-run .pb-herorect { transition: stroke 0.4s ease-out 1.05s; }
.js .board-anim.is-run .pb-herotitle { transition: transform 0.4s ease-out 1.05s, fill 0.4s ease-out 1.05s; }
.js .board-anim.is-run .pb-herocheck { transition: stroke-dashoffset 0.35s ease-out 1.2s, opacity 0.01s linear 1.15s; }
.js .board-anim.is-run .pb-herometa1 { transition: opacity 0.25s ease-out 1.05s, transform 0.4s ease-out 1.05s; }
.js .board-anim.is-run .pb-herometa2 { transition: opacity 0.3s ease-out 1.25s; }

.js .board-anim.is-run .pb-cd-old,
.js .board-anim.is-run .pb-cd-new { transition: opacity 0.35s ease-out 1.5s; }

.js .board-anim.is-run .pb-b1 { transition: transform 0.6s var(--ease) 1.8s; }
.js .board-anim.is-run .pb-bl-shift { transition: transform 0.4s var(--ease); }
.js .board-anim.is-run .pb-bl2 { transition-delay: 2.2s; }
.js .board-anim.is-run .pb-bl3 { transition-delay: 2.28s; }

.js .board-anim.is-run .pb-cb-old,
.js .board-anim.is-run .pb-cb-new { transition: opacity 0.35s ease-out 2.5s; }

/* --------------------------------------------------------------------------
   26d. ENGAGEMENT MODEL ANIMATION (Block 4, Diagram D)
   The three phases light up in order, each arrow draws itself, then the
   credit arc draws from Discovery back into Operate and the label lands.
   Base = fully drawn end state; same centre-band trigger as the others.
   -------------------------------------------------------------------------- */

.eng-anim .asset__frame { border: none; }

/* Start state, held until centred; snaps on off-screen reset */
.js .eng-anim:not(.is-run) .eg-p1,
.js .eng-anim:not(.is-run) .eg-p2,
.js .eng-anim:not(.is-run) .eg-p3 { opacity: 0.25; transition: none; }
.js .eng-anim:not(.is-run) .eg-a1,
.js .eng-anim:not(.is-run) .eg-a2,
.js .eng-anim:not(.is-run) .eg-arc { stroke-dasharray: 1; stroke-dashoffset: 1; opacity: 0; transition: none; }
.js .eng-anim:not(.is-run) .eg-c1,
.js .eng-anim:not(.is-run) .eg-c2,
.js .eng-anim:not(.is-run) .eg-c3,
.js .eng-anim:not(.is-run) .eg-lbl { opacity: 0; transition: none; }

/* End state needs the dash values too, so the draw has something to land on */
.eng-anim .eg-a1,
.eng-anim .eg-a2,
.eng-anim .eg-arc { stroke-dasharray: 1; stroke-dashoffset: 0; }

/* Timeline on .is-run */
.js .eng-anim.is-run .eg-p1 { transition: opacity 0.35s ease-out 0.2s; }
.js .eng-anim.is-run .eg-a1 { transition: stroke-dashoffset 0.3s ease-out 0.55s, opacity 0.05s linear 0.55s; }
.js .eng-anim.is-run .eg-c1 { transition: opacity 0.2s ease-out 0.85s; }
.js .eng-anim.is-run .eg-p2 { transition: opacity 0.35s ease-out 0.95s; }
.js .eng-anim.is-run .eg-a2 { transition: stroke-dashoffset 0.3s ease-out 1.3s, opacity 0.05s linear 1.3s; }
.js .eng-anim.is-run .eg-c2 { transition: opacity 0.2s ease-out 1.6s; }
.js .eng-anim.is-run .eg-p3 { transition: opacity 0.35s ease-out 1.7s; }
.js .eng-anim.is-run .eg-arc { transition: stroke-dashoffset 0.8s var(--ease) 2.15s, opacity 0.05s linear 2.15s; }
.js .eng-anim.is-run .eg-c3 { transition: opacity 0.25s ease-out 2.9s; }
.js .eng-anim.is-run .eg-lbl { transition: opacity 0.3s ease-out 2.95s; }

/* --------------------------------------------------------------------------
   26e. OWNERSHIP ANIMATION (Block 6, "your side of the line")
   The boundary appears first, the three assets light up inside it,
   connectors draw down into YOUR TEAM, which lands last with the note.
   Base = fully drawn end state; same centre-band trigger as the others.
   -------------------------------------------------------------------------- */

.own-anim .asset__frame { border: none; }

/* Start state, held until centred; snaps on off-screen reset */
.js .own-anim:not(.is-run) .og-line { opacity: 0; transition: none; }
.js .own-anim:not(.is-run) .og-b1,
.js .own-anim:not(.is-run) .og-b2,
.js .own-anim:not(.is-run) .og-b3,
.js .own-anim:not(.is-run) .og-team { opacity: 0.25; transition: none; }
.js .own-anim:not(.is-run) .og-w1,
.js .own-anim:not(.is-run) .og-w2,
.js .own-anim:not(.is-run) .og-w3 { stroke-dasharray: 1; stroke-dashoffset: 1; opacity: 0; transition: none; }
.js .own-anim:not(.is-run) .og-h1,
.js .own-anim:not(.is-run) .og-h2,
.js .own-anim:not(.is-run) .og-h3,
.js .own-anim:not(.is-run) .og-note { opacity: 0; transition: none; }

/* End state needs the dash values so the draws have somewhere to land */
.own-anim .og-w1,
.own-anim .og-w2,
.own-anim .og-w3 { stroke-dasharray: 1; stroke-dashoffset: 0; }

/* Timeline on .is-run: boundary, assets, connectors, team, note */
.js .own-anim.is-run .og-line { transition: opacity 0.4s ease-out 0.25s; }
.js .own-anim.is-run .og-b1 { transition: opacity 0.3s ease-out 0.7s; }
.js .own-anim.is-run .og-b2 { transition: opacity 0.3s ease-out 0.9s; }
.js .own-anim.is-run .og-b3 { transition: opacity 0.3s ease-out 1.1s; }
.js .own-anim.is-run .og-w1 { transition: stroke-dashoffset 0.4s ease-out 1.5s, opacity 0.05s linear 1.5s; }
.js .own-anim.is-run .og-w2 { transition: stroke-dashoffset 0.3s ease-out 1.6s, opacity 0.05s linear 1.6s; }
.js .own-anim.is-run .og-w3 { transition: stroke-dashoffset 0.4s ease-out 1.7s, opacity 0.05s linear 1.7s; }
.js .own-anim.is-run .og-h1 { transition: opacity 0.2s ease-out 1.9s; }
.js .own-anim.is-run .og-h2 { transition: opacity 0.2s ease-out 1.9s; }
.js .own-anim.is-run .og-h3 { transition: opacity 0.2s ease-out 2.1s; }
.js .own-anim.is-run .og-team { transition: opacity 0.35s ease-out 2.25s; }
.js .own-anim.is-run .og-note { transition: opacity 0.3s ease-out 2.6s; }

/* --------------------------------------------------------------------------
   27. REDUCED MOTION
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .reveal { opacity: 1; }
}

/* --------------------------------------------------------------------------
   28. PRINT
   The site is forwardable. Someone will print it.
   -------------------------------------------------------------------------- */

@media print {
  .stickybar, .calendar, .skip-link { display: none; }
  body { font-size: 11pt; }
  .section { padding-block: 24pt; }
  .page { grid-template-columns: 1fr; }
  .reveal { opacity: 1; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
}
