/* ==========================================================================
   PULSE V2.1 — changelog.css · "ION ATMOSPHERE"
   The release timeline as a vertical instrument log. The TRACE is the
   timeline rail: a calm oscilloscope waveform at the current release (log
   head), progressively rougher as you descend into history — drawn by
   viz.js, with the flowing pulse on the head connector. Entries sit in
   obsidian cards under an aurora whisper. Huge Space Mono version
   numerals, sentence-case date chips, chip-styled change groups.
   Requires tokens.css + base.css loaded first; viz.js drives the rail.
   No inline styles anywhere — CSP style-src 'self'.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hero — quiet; the log itself is the artifact
   -------------------------------------------------------------------------- */
.cl-hero { padding-bottom: var(--sp-7); }
.cl-hero h1 { max-width: 14ch; }
.cl-hero .section-sub { max-width: 52ch; }

/* --------------------------------------------------------------------------
   The log — rail geometry
   --rail-x   : x position of the rail hairline inside .timeline
   --tl-indent: left padding that clears the rail for entry content
   -------------------------------------------------------------------------- */
.cl-log { padding-block: var(--sp-8) 0; }

.timeline {
  --rail-x: 1.25rem;
  --tl-indent: calc(var(--rail-x) + 1.75rem);
  position: relative;
  padding-left: var(--tl-indent);
}
@media (min-width: 56em) {
  .timeline {
    --rail-x: 2rem;
    --tl-indent: calc(var(--rail-x) + 3rem);
  }
}

/* Continuous rail hairline — the instrument grid the trace weaves around.
   Fades in at the head and out at the tail. */
.timeline::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--rail-x);
  width: 1px;
  background: linear-gradient(
    to bottom,
    transparent 0,
    var(--line-1) 3%,
    var(--line-1) 90%,
    transparent 100%
  );
}

/* Log meta row — selected-entries honesty + the one Illustrative label */
.tl-note {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-4);
  margin-bottom: var(--sp-7);
}

/* --------------------------------------------------------------------------
   Entries — head column + body card
   -------------------------------------------------------------------------- */
.tl-entry {
  position: relative;
  padding-block: var(--sp-2);
}
@media (min-width: 56em) {
  .tl-entry {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: var(--sp-7);
    align-items: start;
  }
  .tl-head {
    position: sticky;
    top: 5.5rem;
  }
}

/* Version node on the rail — round registration dot; canvas fill masks the
   hairline crossing behind it. The log head glows. */
.tl-node {
  position: absolute;
  top: 0.45rem;
  left: calc(var(--rail-x) - var(--tl-indent) - 4.5px);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--canvas);
  border: 1px solid var(--line-3);
}
.tl-entry--latest .tl-node {
  border-color: var(--accent-line);
  background: var(--accent-tint-2);
  box-shadow: 0 0 10px var(--accent-tint-1);
}

/* Version-node pulses — each node on the rail pings on its own slow
   cadence; the live head pings the fastest. html.anim-gated; static
   nodes stand untouched under reduced motion / no JS. */
.tl-node::after {
  content: "";
  position: absolute;
  inset: -7px;
  border-radius: 50%;
  border: 1px solid var(--accent-line);
  opacity: 0;
  transform: scale(0.35);
}
html.anim .tl-node::after { animation: tl-nodeping 6.4s var(--ease-glide) infinite; }
html.anim .tl-entry:nth-of-type(odd) .tl-node::after { animation-delay: 2.4s; }
html.anim .tl-entry:nth-of-type(3n) .tl-node::after { animation-delay: 4.1s; }
html.anim .tl-entry--latest .tl-node::after { animation-duration: 3.4s; animation-delay: 0s; }
@keyframes tl-nodeping {
  0% { transform: scale(0.35); opacity: 0.9; }
  34% { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* Head: date chip row + huge mono version numeral + codename */
.tl-chiprow { margin-bottom: var(--sp-4); }

/* Sentence case (caps diet) — mono micro stays for the numeric date */
.date-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--line-1);
  border-radius: var(--radius-pill);
  background-color: var(--surface-1);
  font: 700 var(--fs-micro) / 1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--text-3);
}
.date-chip--live {
  border-color: var(--accent-line);
  background-color: var(--accent-tint-2);
  color: var(--accent-bright);
}

.tl-version { letter-spacing: normal; }
.tl-v {
  display: block;
  font: 700 var(--fs-num-lg) / 1 var(--font-mono);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text-1);
}
.tl-entry--latest .tl-v {
  font-size: var(--fs-h1);
  color: var(--accent-bright);
}
.tl-codename {
  display: block;
  margin-top: var(--sp-3);
  font: 600 var(--fs-h4) / var(--lh-heading) var(--font-sans);
  letter-spacing: var(--track-tight);
  color: var(--text-3);
  max-width: 24ch;
  text-wrap: balance;
}

/* Body: the entry card — an obsidian panel on the atmosphere.
   background-color (never the shorthand) so .texture-scan survives. */
.tl-body {
  margin-top: var(--sp-6);
  background-color: var(--surface-1);
  border: 1px solid var(--line-1);
  border-radius: var(--radius-lg);
  padding: var(--sp-5) var(--sp-6);
  transition: border-color var(--dur-2) ease;
}
.tl-body:hover { border-color: var(--line-2); }
.tl-entry--latest .tl-body { border-color: var(--accent-line); }
@media (min-width: 56em) {
  .tl-body { margin-top: 0; }
}

.tl-group + .tl-group { margin-top: var(--sp-6); }

/* Change-group head — chip-styled, sentence case (the caps wall is gone) */
.tl-group-head {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  font: 700 var(--fs-micro) / 1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--text-3);
  margin-bottom: var(--sp-2);
}

.tl-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.tl-list li {
  position: relative;
  padding: var(--sp-3) 0 var(--sp-3) 1.4rem;
  border-bottom: 1px solid var(--line-0);
  font-size: var(--fs-body-sm);
  color: var(--text-2);
  max-width: 60ch;
  transition: border-color var(--dur-2) ease;
}
.tl-list li:last-child { border-bottom: 0; }
.tl-list li:hover { border-bottom-color: var(--line-2); }
/* Cyan hairline tick — the v2.1 marker */
.tl-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(var(--sp-3) + 0.7em);
  width: 9px;
  height: 1px;
  background: var(--accent-line);
}

.tl-footnote {
  margin-top: var(--sp-5);
  font-size: var(--fs-body-sm);
  color: var(--text-3);
  max-width: 60ch;
}
.tl-footnote .mono-label {
  display: inline-block;
  margin-right: var(--sp-3);
}

/* Latest entry — log head: no invented notes, just the honest pointer */
.tl-latest-line {
  font-size: var(--fs-lead);
  color: var(--text-2);
  max-width: 44ch;
}
.tl-latest-meta {
  display: block;
  margin-top: var(--sp-4);
}

/* --------------------------------------------------------------------------
   Rail connectors — vertical TRACE segments between entries. Geometry is
   the message: a near-flat instrument line at the head, progressively
   rougher amplitude descending into history, fading out at the tail.
   viz.js draws each on scroll; the head connector carries the pulse.
   -------------------------------------------------------------------------- */
.tl-link {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding-block: var(--sp-4);
}
.tl-link .trace-svg {
  flex: none;
  width: 64px;
  height: auto;
  margin-left: calc(var(--rail-x) - var(--tl-indent) - 2rem);
}

/* Sentence-case gap marker */
.tl-gap {
  font: 400 var(--fs-micro) / 1.5 var(--font-mono);
  letter-spacing: 0.06em;
  color: var(--text-3);
}

/* Tail — the rough past, fading out below the oldest entry */
.tl-tail { padding-bottom: 0; }
.tl-tail .trace-svg {
  -webkit-mask-image: linear-gradient(to bottom, #000 25%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 25%, transparent 100%);
}

/* --------------------------------------------------------------------------
   Closing CTA — under its own aurora
   -------------------------------------------------------------------------- */
.cl-cta { margin-top: var(--sp-9); }
.cl-cta .container { padding-top: var(--sp-8); }
.cl-cta h2 {
  margin-top: var(--sp-4);
  max-width: 22ch;
}
.cl-cta .hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
}
.cl-cta .trust-strip { margin-top: var(--sp-5); }
