/* =============================================================================
   ZASTRON LABS V3  ·  PORTFOLIO
   The home page is now the work: a hero built from real data, then six
   projects in a book-page layout (tools in the margin, prose in a reading
   column, one code block told as part of the story, a full-bleed data panel).

   Owns ONLY the portfolio layout. Tokens, reset, nav, footer, buttons, links,
   forms, focus and the reveal system all live in styles.css and are reused
   untouched. Two families, three faces, no font-weight above 500.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   0. LOCAL TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* The rhythm that makes the page feel expensive. The model site runs 160px
     between projects; ours scales down gracefully on small screens. */
  --pf-gap: clamp(5rem, 11vw, 10rem);
  --pf-rail: 11rem;      /* marginalia column */
  --pf-rail-gap: 3rem;
  --pf-shell: 76rem;     /* full spread: rail + gap + reading column + air */

  --pf-code-bg: #16130F;
  --pf-code-ink: #EDE8E1;
  --pf-code-dim: #A79D91;   /* 6.6:1 on --pf-code-bg */
  --pf-code-accent: #E0A86B;
}

/* -----------------------------------------------------------------------------
   1. SHELL
   -------------------------------------------------------------------------- */
.pf-shell {
  width: min(100% - (2 * var(--pad-x)), var(--pf-shell));
  margin-inline: auto;
}

/* Reading column: 40rem keeps prose at roughly 65 characters. */
.pf-read { max-width: var(--w-read); }

/* -----------------------------------------------------------------------------
   2. HERO
   The canvas paints 24 992 dots, one per registered car, settling into the
   real distribution by build year. It animates in once and then holds; it is
   not a loop. Text sits over it in a reading column, left aligned.
   -------------------------------------------------------------------------- */
.pf-hero {
  position: relative;
  padding-block: clamp(4rem, 11vh, 7.5rem) clamp(2rem, 5vh, 3.5rem);
  overflow: hidden;
}

/* NOTE: no width here. The shell owns the width, and an override would
   defeat its padding and push the page into horizontal overflow. */
.pf-hero__inner { position: relative; }

/* The field is a real element in the flow, under the type, never behind it.
   Type and data each get their own ground. */
.pf-hero__field {
  position: relative;
  margin-top: clamp(2.25rem, 6vh, 3.5rem);
  height: clamp(190px, 32vh, 320px);
}

.pf-hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.pf-hero__name {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-5);
}

.pf-hero__line {
  font-size: var(--fs-hero);
  font-weight: 400;
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  max-width: 20ch;
  text-wrap: balance;
}

.pf-hero__role {
  margin-top: var(--s-6);
  max-width: 46ch;
  font-size: var(--fs-lead);
  color: var(--ink-2);
}

.pf-hero__links {
  margin-top: var(--s-5);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  font-size: var(--fs-lead);
}

/* The legend is the honesty note: it says what the dots literally are. */
.pf-hero__legend {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-2) var(--s-5);
  max-width: 54rem;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--ink-3);
}

.pf-hero__legend b {
  font-weight: 400;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.pf-hero__years {
  display: flex;
  gap: var(--s-4);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
  .pf-hero__line { max-width: 16ch; }
  .pf-hero__years { display: none; }
}

/* -----------------------------------------------------------------------------
   3. CATEGORY HEADINGS
   A hairline runs out of the heading into the left margin, the way a printed
   book marks a new part.
   -------------------------------------------------------------------------- */
.pf-cat {
  margin-top: var(--pf-gap);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
}

.pf-cat__label {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ink);
}

.pf-cat__count {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* -----------------------------------------------------------------------------
   4. PROJECT
   -------------------------------------------------------------------------- */
.pf-project {
  display: grid;
  grid-template-columns: var(--pf-rail) minmax(0, 1fr);
  column-gap: var(--pf-rail-gap);
  padding-top: clamp(3.5rem, 8vw, 6rem);
  padding-bottom: var(--pf-gap);
}

.pf-project + .pf-project { border-top: 1px solid var(--line); }

/* --- the marginalia rail ------------------------------------------------- */
.pf-rail {
  grid-column: 1;
  text-align: right;
  position: sticky;
  top: 6.5rem;
  align-self: start;
}

.pf-rail__no {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--s-4);
}

.pf-tools {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.pf-tools li {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  line-height: 1.35;
  color: var(--ink-3);
}

/* --- the reading column --------------------------------------------------- */
.pf-body { grid-column: 2; min-width: 0; }

.pf-project__title {
  font-size: var(--fs-h2);
  font-weight: 400;
  line-height: var(--lh-head);
  letter-spacing: var(--ls-tight);
  max-width: 22ch;
  text-wrap: balance;
}

/* The surprising fact, set apart. One per project, never more. */
.pf-fact {
  margin-top: var(--s-5);
  padding-left: var(--s-5);
  border-left: 2px solid var(--accent);
  max-width: var(--w-read);
  font-size: var(--fs-lead);
  color: var(--ink);
}

.pf-prose {
  margin-top: var(--s-6);
  max-width: var(--w-read);
}

.pf-prose p + p { margin-top: var(--s-4); }
.pf-prose strong { font-weight: 500; }

/* -----------------------------------------------------------------------------
   5. CODE
   Quoted verbatim from the repo. The path label is part of the claim: it says
   where you can go and check.
   -------------------------------------------------------------------------- */
.pf-code {
  margin-top: var(--s-6);
  border-radius: var(--r-input);
  overflow: hidden;
  background: var(--pf-code-bg);
  max-width: 54rem;
}

.pf-code__path {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid rgba(237, 232, 225, 0.12);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.06em;
  color: var(--pf-code-dim);
  word-break: break-all;
}

.pf-code__path::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--pf-code-accent);
}

.pf-code pre {
  margin: 0;
  padding: var(--s-4);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--pf-code-ink);
  tab-size: 2;
}

.pf-code .c { color: var(--pf-code-dim); }  /* comment  */
.pf-code .k { color: var(--pf-code-accent); }  /* keyword */

/* -----------------------------------------------------------------------------
   6. NUMBERS
   A typographic row, not a card grid. Hairlines separate, nothing boxes.
   -------------------------------------------------------------------------- */
.pf-nums {
  margin-top: var(--s-7);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: var(--s-5) var(--s-6);
  max-width: 54rem;
}

.pf-num { border-top: 1px solid var(--line); padding-top: var(--s-3); }

.pf-num__v {
  display: block;
  font-size: var(--fs-h3);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--ls-tight);
}

.pf-num__l {
  display: block;
  margin-top: var(--s-2);
  font-size: var(--fs-small);
  line-height: 1.4;
  color: var(--ink-3);
}

/* -----------------------------------------------------------------------------
   7. PROOF LINK
   -------------------------------------------------------------------------- */
.pf-proof { margin-top: var(--s-6); display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: center; }

/* -----------------------------------------------------------------------------
   8. FULL-BLEED DATA PANEL
   Breaks the container and runs edge to edge, the way the model site runs its
   screenshots. Ours holds charts drawn from the real numbers, so the panel is
   evidence rather than decoration.
   -------------------------------------------------------------------------- */
.pf-panel {
  /* MUST span both grid tracks. Left to auto-placement it lands in the narrow
     marginalia column, and then `calc(50% - 50vw)` measures 50% of that column
     instead of the page, which shunts the whole panel off to the left. */
  grid-column: 1 / -1;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: clamp(2.5rem, 6vw, 4.5rem);
  background: var(--bg-elev);
  border-block: 1px solid var(--line);
  padding-block: clamp(2rem, 5vw, 3.5rem);
}

.pf-panel__inner {
  width: min(100% - (2 * var(--pad-x)), var(--pf-shell));
  margin-inline: auto;
}

.pf-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2) var(--s-4);
  margin-bottom: var(--s-5);
}

.pf-panel__title {
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

.pf-panel__note { font-size: var(--fs-small); color: var(--ink-2); max-width: 46ch; }

.pf-source {
  margin-top: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* --- chart primitives ----------------------------------------------------- */
.pf-chart { width: 100%; height: auto; overflow: visible; }
.pf-chart text { font-family: var(--font-sans); font-size: 15px; fill: var(--ink-2); }
.pf-chart .t-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.pf-chart .t-ink { fill: var(--ink); }
.pf-chart .t-dim { fill: var(--ink-3); font-size: 13px; }
.pf-chart .bar { fill: var(--chart-track); }
.pf-chart .bar--hot { fill: var(--accent); }
.pf-chart .grid { stroke: var(--chart-grid); stroke-width: 1; }
.pf-chart .axis { stroke: var(--line-strong); stroke-width: 1; }
.pf-chart .line { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.pf-chart .area { fill: var(--chart-area); }
.pf-chart .dot { fill: var(--accent); }
.pf-chart .dot--hollow { fill: var(--bg-elev); stroke: var(--accent); stroke-width: 2.5; }
.pf-chart .oe { stroke: var(--ink); stroke-width: 2; }

/* Wide charts scroll inside their own box rather than the page. */
.pf-scroll { overflow-x: auto; }
.pf-scroll > svg { min-width: 40rem; }

/* -----------------------------------------------------------------------------
   9. THE KILL BOARD (project 6)
   -------------------------------------------------------------------------- */
/* Eight tiles, and the column count always divides eight, so the board never
   ends on a half-empty row showing the hairline background through the gap. */
.pf-kills {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}

@media (max-width: 900px) { .pf-kills { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 520px) { .pf-kills { grid-template-columns: repeat(2, 1fr); } }

.pf-kill {
  background: var(--bg-elev);
  padding: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.pf-kills__note {
  margin-top: var(--s-4);
  max-width: 52ch;
  font-size: var(--fs-small);
  color: var(--ink-2);
}

.pf-kill__n {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.1em;
  color: var(--ink-3);
}

.pf-kill__v {
  font-size: var(--fs-lead);
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.pf-kill__v::before {
  content: "";
  width: 1.1rem;
  height: 1px;
  background: var(--accent);
  flex: none;
}

.pf-kill--near { background: var(--bg); }

/* -----------------------------------------------------------------------------
   9b. THE CV
   Same book-page grammar as a project: a marker in the left rail, the content
   in a reading column. Deliberately undated except where a year is actually
   known.
   -------------------------------------------------------------------------- */
.pf-cv { padding-top: clamp(3rem, 7vw, 5rem); }

.pf-cv__intro { max-width: var(--w-read); }

.pf-cv__lead {
  font-size: var(--fs-lead);
  color: var(--ink);
  margin-bottom: var(--s-4);
}

.pf-path { margin-top: clamp(3rem, 7vw, 4.5rem); }

.pf-path__item {
  display: grid;
  grid-template-columns: var(--pf-rail) minmax(0, 1fr);
  column-gap: var(--pf-rail-gap);
  padding-block: var(--s-6);
  border-top: 1px solid var(--line);
}

.pf-path__item > div { max-width: var(--w-read); }

.pf-path__mark {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--accent);
  text-align: right;
  white-space: nowrap;
}

.pf-path__h {
  font-size: var(--fs-lead);
  font-weight: 500;
  line-height: var(--lh-head);
  margin-bottom: var(--s-2);
}

/* --- skills ---------------------------------------------------------------- */
.pf-cv__skills { margin-top: clamp(3rem, 7vw, 4.5rem); }

.pf-cv__h4 {
  font-size: var(--fs-h3);
  font-weight: 400;
  line-height: var(--lh-head);
  letter-spacing: var(--ls-tight);
}

.pf-cv__note {
  margin-top: var(--s-3);
  max-width: 52ch;
  font-size: var(--fs-small);
  color: var(--ink-3);
}

.pf-skills { margin-top: var(--s-6); }

.pf-skill {
  display: grid;
  grid-template-columns: var(--pf-rail) minmax(0, 1fr);
  column-gap: var(--pf-rail-gap);
  padding-block: var(--s-4);
  border-top: 1px solid var(--line);
}

.pf-skill dt {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--ink);
  text-align: right;
}

.pf-skill dd { margin: 0; max-width: var(--w-read); color: var(--ink-2); }

.pf-cv__more {
  margin-top: var(--s-7);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
}

@media (max-width: 1000px) {
  .pf-path__item,
  .pf-skill {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--s-2);
  }
  .pf-path__mark,
  .pf-skill dt { text-align: left; }
}

/* -----------------------------------------------------------------------------
   10. CLOSING CONTACT
   One quiet line. No pitch, no pricing, the way the work-first sites do it.
   -------------------------------------------------------------------------- */
.pf-end { padding-block: var(--pf-gap); border-top: 1px solid var(--line); }

.pf-end__line {
  font-size: var(--fs-h3);
  font-weight: 400;
  line-height: var(--lh-head);
  letter-spacing: var(--ls-tight);
  max-width: 26ch;
}

.pf-end__sub { margin-top: var(--s-5); max-width: 44ch; color: var(--ink-2); }
.pf-end__links { margin-top: var(--s-5); display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); }

/* margin-inline:0 because the shared .form centres itself, and everything
   else in this section is left aligned. */
.pf-end__form { margin: var(--s-8) 0 0; max-width: 34rem; }

/* -----------------------------------------------------------------------------
   11. RESPONSIVE
   Below 1000px the rail stops being a margin and becomes a row above the
   title, which is exactly what the model site does.
   -------------------------------------------------------------------------- */
@media (max-width: 1000px) {
  .pf-project { grid-template-columns: minmax(0, 1fr); row-gap: var(--s-5); }
  .pf-rail { grid-column: 1; text-align: left; position: static; }
  .pf-rail__no { display: inline-block; margin-bottom: var(--s-3); }
  .pf-tools { flex-direction: row; flex-wrap: wrap; gap: var(--s-2) var(--s-4); }
  .pf-tools li + li { position: relative; padding-left: var(--s-4); }
  .pf-tools li + li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--line-strong);
  }
  .pf-body { grid-column: 1; }
}

@media (max-width: 600px) {
  .pf-nums { grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); }
  .pf-code pre { font-size: 0.75rem; }
}

/* -----------------------------------------------------------------------------
   11b. SINGLE PROJECT PAGE
   One project given room: the same fact, prose, code, numbers and chart as the
   home page (generated FROM it, so the figures cannot drift), plus the two
   things a listing has no room for, how it was done and where it stops.
   -------------------------------------------------------------------------- */
.pf-single { padding-block: clamp(3rem, 8vh, 5rem) var(--pf-gap); }

.pf-single__back { margin-bottom: var(--s-7); font-size: var(--fs-small); }

.pf-single__head { max-width: var(--w-read); }

.pf-single__no {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--s-3);
}

.pf-single__title {
  font-size: var(--fs-h2);
  font-weight: 400;
  line-height: var(--lh-head);
  letter-spacing: var(--ls-tight);
  max-width: 20ch;
  text-wrap: balance;
}

.pf-single__head .pf-fact { margin-top: var(--s-5); }

.pf-single__tools {
  margin-top: var(--s-6);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
}

.pf-single__tools li {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--ink-3);
  position: relative;
}

.pf-single__tools li + li { padding-left: var(--s-4); }

.pf-single__tools li + li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--line-strong);
}

.pf-single__sect { margin-top: clamp(3.5rem, 8vw, 6rem); }

.pf-single__h2 {
  font-size: var(--fs-h3);
  font-weight: 400;
  line-height: var(--lh-head);
  letter-spacing: var(--ls-tight);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}

.pf-single__lead {
  margin-top: var(--s-5);
  max-width: var(--w-read);
  color: var(--ink-2);
}

/* --- how it was done ------------------------------------------------------ */
.pf-steps {
  margin-top: var(--s-6);
  counter-reset: step;
  max-width: 54rem;
}

.pf-step {
  counter-increment: step;
  position: relative;
  padding-left: 3.25rem;
  max-width: var(--w-read);
}

.pf-step + .pf-step { margin-top: var(--s-6); }

.pf-step::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.15em;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.pf-step__h {
  font-size: var(--fs-lead);
  font-weight: 500;
  line-height: var(--lh-head);
  margin-bottom: var(--s-2);
}

/* --- what it does not tell you -------------------------------------------- */
.pf-limits { margin-top: var(--s-6); max-width: var(--w-read); }

.pf-limit {
  position: relative;
  padding-left: var(--s-5);
  color: var(--ink-2);
}

.pf-limit + .pf-limit { margin-top: var(--s-4); }

.pf-limit::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 10px;
  height: 1px;
  background: var(--line-strong);
}

.pf-single__end { padding-top: var(--s-7); border-top: 1px solid var(--line); }
.pf-single__next { margin-top: var(--s-5); font-size: var(--fs-small); }

@media (max-width: 600px) {
  .pf-step { padding-left: 2.5rem; }
}

/* -----------------------------------------------------------------------------
   12. SCROLL-DRAWN CHARTS
   The signature moment of the page: arrive at a panel and the chart DRAWS
   ITSELF, line first, then the fill, then the points and their labels. It is
   scroll-linked and purposeful (it shows the data being made, which is the
   whole argument of the site) rather than decoration.

   The `--anim` class is added BY SCRIPT, so with no JS, or with reduced motion,
   every chart is simply already drawn. Nothing here can hide content.
   -------------------------------------------------------------------------- */
.pf-chart--anim rect {
  transform-box: fill-box;
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform 780ms var(--ease);
}

.pf-chart--anim.is-drawn rect { transform: scaleX(1); }

/* Bars land one after another, top to bottom. */
.pf-chart--anim rect:nth-of-type(1)  { transition-delay:  20ms; }
.pf-chart--anim rect:nth-of-type(2)  { transition-delay:  70ms; }
.pf-chart--anim rect:nth-of-type(3)  { transition-delay: 120ms; }
.pf-chart--anim rect:nth-of-type(4)  { transition-delay: 170ms; }
.pf-chart--anim rect:nth-of-type(5)  { transition-delay: 220ms; }
.pf-chart--anim rect:nth-of-type(6)  { transition-delay: 270ms; }
.pf-chart--anim rect:nth-of-type(7)  { transition-delay: 320ms; }
.pf-chart--anim rect:nth-of-type(8)  { transition-delay: 370ms; }
.pf-chart--anim rect:nth-of-type(9)  { transition-delay: 420ms; }
.pf-chart--anim rect:nth-of-type(10) { transition-delay: 470ms; }
.pf-chart--anim rect:nth-of-type(11) { transition-delay: 520ms; }
.pf-chart--anim rect:nth-of-type(12) { transition-delay: 570ms; }

/* The line writes itself left to right. 4000 comfortably exceeds the longest
   path in these charts, so no per-path measurement is needed. */
.pf-chart--anim .line {
  stroke-dasharray: 4000;
  stroke-dashoffset: 4000;
  transition: stroke-dashoffset 1500ms var(--ease);
}

.pf-chart--anim.is-drawn .line { stroke-dashoffset: 0; }

.pf-chart--anim .area {
  opacity: 0;
  transition: opacity 700ms var(--ease) 550ms;
}

.pf-chart--anim.is-drawn .area { opacity: 1; }

.pf-chart--anim circle,
.pf-chart--anim .oe line {
  opacity: 0;
  transition: opacity 420ms var(--ease);
}

.pf-chart--anim.is-drawn circle,
.pf-chart--anim.is-drawn .oe line { opacity: 1; }

.pf-chart--anim circle:nth-of-type(1) { transition-delay: 700ms; }
.pf-chart--anim circle:nth-of-type(2) { transition-delay: 840ms; }
.pf-chart--anim circle:nth-of-type(3) { transition-delay: 980ms; }
.pf-chart--anim circle:nth-of-type(4) { transition-delay: 1120ms; }
.pf-chart--anim circle:nth-of-type(5) { transition-delay: 1260ms; }
.pf-chart--anim circle:nth-of-type(6) { transition-delay: 1400ms; }
.pf-chart--anim circle:nth-of-type(7) { transition-delay: 1540ms; }
.pf-chart--anim .oe line { transition-delay: 800ms; }

/* Value labels arrive with their marks, never before them. */
.pf-chart--anim .t-num.t-ink,
.pf-chart--anim g.t-num.t-ink text {
  opacity: 0;
  transition: opacity 500ms var(--ease) 900ms;
}

.pf-chart--anim.is-drawn .t-num.t-ink,
.pf-chart--anim.is-drawn g.t-num.t-ink text { opacity: 1; }

/* -----------------------------------------------------------------------------
   13. THE ACTIVE PROJECT
   Scroll-linked, not merely triggered: the marginalia rail marks which project
   you are actually reading. One quiet state change, no movement.
   -------------------------------------------------------------------------- */
.pf-rail__no {
  position: relative;
  color: var(--ink-3);
  transition: color 240ms var(--ease);
}

.pf-rail__no::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 320ms var(--ease);
}

.pf-project.is-active .pf-rail__no { color: var(--accent); }
.pf-project.is-active .pf-rail__no::after { transform: scaleX(1); }

@media (max-width: 1000px) {
  /* The rail is an inline row on small screens; the underline would sit under
     the tools rather than the number, so drop it and keep the colour only. */
  .pf-rail__no::after { display: none; }
}

/* -----------------------------------------------------------------------------
   14. MOTION SAFETY
   Entrances only. Nothing on this page loops.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .pf-hero__canvas { opacity: 0.5; }

  /* Belt and braces: even if the script somehow adds the class, show it all. */
  .pf-chart--anim rect { transform: none; transition: none; }
  .pf-chart--anim .line { stroke-dashoffset: 0; transition: none; }
  .pf-chart--anim .area,
  .pf-chart--anim circle,
  .pf-chart--anim .oe line,
  .pf-chart--anim .t-num.t-ink,
  .pf-chart--anim g.t-num.t-ink text { opacity: 1; transition: none; }
  .pf-rail__no::after { transition: none; }
}
