/* =========================================================
   timeline-v2 — clean rebuild
   Two-column timeline with central spine, tip icons,
   year markers, and zigzag offset. Server-rendered, no JS.
   ========================================================= */

:root {
  --tl2-spine-color: #fff;
  --tl2-spine-width: 2px;
  --tl2-tip-size: 34px;
  --tl2-tip-icon-size: 20px;
  --tl2-tip-bg: #fff;
  --tl2-tip-icon-color: #d70808;
  --tl2-year-size: 110px;
  --tl2-year-bg: #000;
  --tl2-year-color: #fff;
  --tl2-spine-gutter: 80px;
  --tl2-row-gap: 3rem;
  --tl2-card-max: 440px;
  --tl2-card-bg: #fff;
  --tl2-card-fg: #000;
  --tl2-card-fg-hover: #d70808;
  --tl2-card-radius: 0;
  /* Wide-screen zigzag: a right-side card directly following a
     left-side card pulls up by this offset, so the right card
     visually begins ~80px below the left card's top (matching the
     legacy /releases layout). Card ≈ 518px, row-gap ≈ 48px;
     natural gap = 566px, target = 80px, so offset = 486px. */
  --tl2-zigzag-offset: 486px;
}

.tl2 {
  max-width: 1100px;
  margin: 0 auto;
  /* Top padding clears the fixed year-nav (top:110 + 112 = 222) plus
     a 16px breathing gap below, matching the /releases gap. */
  padding: 238px 1rem 6rem;
  color: #fff;
  position: relative;
}

/* Page heading — visually hidden on desktop (the fixed year-nav and
   the page title in <head> serve that role there) but kept in the DOM
   for screen readers and as an anchor for the mobile breakpoint to
   make it visible. The mobile @media block below restores it as a
   regular heading. */
.tl2__heading {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ----- year navigation -----
   Fixed three-balloon nav at the top center of the viewport. The
   middle balloon is the active year (large); the immediately previous
   and next years render as smaller balloons either side. All other
   year pills are present in the DOM (for anchor linking and JS
   bookkeeping) but visually hidden. Mirrors the legacy /releases
   pattern so the visual language stays consistent across the site.
   Falls back gracefully without JS: only the first pill is marked
   active, the rest are hidden, page still works via anchor links. */
.tl2__year-nav {
  position: fixed;
  top: 110px;                    /* flush below the fixed top-nav (which ends at y=110) so the two never overlap */
  left: 50%;
  transform: translateX(-50%);
  z-index: 105;
  width: 112px;
  height: 112px;
  pointer-events: none;          /* re-enabled on individual pills */
}

.tl2__year-pill {
  position: absolute;
  top: 24px;                     /* aligns small pills vertically with active center */
  left: 24px;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--tl2-year-bg);
  color: var(--tl2-year-color);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  opacity: 0;                    /* hidden by default; .is-prev/.is-next/.is-active reveal */
  visibility: hidden;
  pointer-events: none;
  /* No transition: when the active year changes, pills swap classes
     in the same paint. With a 200ms fade some pills are momentarily
     hidden between class removal and re-application, which reads as
     "the year balloon disappears mid-scroll". Instant swap avoids
     that. The colour-on-hover transition stays defined separately. */
}

.tl2__year-pill.is-active {
  top: 0;
  left: 0;
  width: 112px;
  height: 112px;
  font-size: 1.6rem;
  opacity: 1;
  visibility: visible;
  pointer-events: none;          /* the active year doesn't navigate anywhere */
  z-index: 2;
}

.tl2__year-pill.is-prev {
  transform: translateX(-120px); /* sits to the left of the active circle */
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  cursor: pointer;
  z-index: 1;
}

.tl2__year-pill.is-next {
  transform: translateX(120px);  /* sits to the right of the active circle */
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  cursor: pointer;
  z-index: 1;
}

/* White connector line that fills the entire gap between the
   prev/next pill's edge and the active center pill's edge. With a
   112px active centered at 0,0 and a 64px pill translated to
   ±120px, the inner edge of the small pill sits 32px from the
   active edge, so the line is 32px wide and butts up against both. */
.tl2__year-pill.is-prev::before,
.tl2__year-pill.is-next::before {
  content: "";
  position: absolute;
  top: 50%;
  width: 32px;
  height: 2px;
  margin-top: -1px;
  background: #fff;
  pointer-events: none;
}

.tl2__year-pill.is-prev::before {
  right: -32px;                  /* sits flush against the pill's outer edge */
}

.tl2__year-pill.is-next::before {
  left: -32px;
}

.tl2__year-pill.is-prev:hover,
.tl2__year-pill.is-next:hover,
.tl2__year-pill.is-prev:focus-visible,
.tl2__year-pill.is-next:focus-visible {
  background: var(--tl2-card-fg-hover);
  outline: none;
}

/* Anchor offset so smooth-scroll to a year-marker doesn't tuck it
   under the fixed top-nav + year-nav. */
.tl2__year-marker {
  scroll-margin-top: 220px;
}

.tl2__list {
  list-style: none;
  padding: 0;
  margin: 0;
  position: relative;
}

/* central spine
   Extends 16px above the list so it visually connects to the bottom
   of the active year balloon (which sits at viewport top:110 + 112
   = bottom:222, while the list begins at padding-top:238). At any
   scroll position the spine fills the full visible column. */
.tl2__list::before {
  content: "";
  position: absolute;
  top: -16px;
  bottom: 0;
  left: 24px;
  width: var(--tl2-spine-width);
  background: var(--tl2-spine-color);
  z-index: 0;
}

/* ----- year marker -----
   Year-markers act as visual separators between years in the
   timeline, and as anchor targets for the year-nav (id="year-XXXX")
   plus section landmarks for the JS scroll-tracker. The first marker
   (newest year, currently on screen) is hidden because the fixed
   year-nav already shows that year — keeping it would double up.

   In-timeline markers are visually distinct from the nav-pills
   (smaller, red) so they read as "year boundary" rather than as a
   second active year-balloon, even when scrolling has a nav-pill
   active at the same time. */
.tl2__year-marker {
  position: relative;
  display: flex;
  justify-content: flex-start;
  margin-bottom: var(--tl2-row-gap);
  z-index: 2;
}

.tl2__list > .tl2__year-marker:first-child {
  display: none;
}

.tl2__year-label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--tl2-card-fg-hover); /* red — matches tip-icon accent */
  color: #fff;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  margin-left: calc(24px - 36px); /* center the 72px balloon on the spine */
}

/* ----- entry -----
   Pointer events: the <li> spans the full width via grid, but the
   visible card only occupies one column. The other column is empty
   space — on wide-screens with zigzag offsets, a right-side entry
   sits visually on top of the previous left-side entry, and its
   empty left-column cells would otherwise eat hover/clicks on the
   card underneath. Disable hit-testing on the entry itself and
   re-enable it only on the card and tip. */
.tl2__entry {
  position: relative;
  padding-left: 60px;
  margin-bottom: var(--tl2-row-gap);
  z-index: 1;
  pointer-events: none;
}

.tl2__entry .tl2__card,
.tl2__entry .tl2__tip {
  pointer-events: auto;
}

.tl2__tip {
  position: absolute;
  top: 24px;
  left: 24px;
  width: var(--tl2-tip-size);
  height: var(--tl2-tip-size);
  background: var(--tl2-tip-bg);
  border-radius: 50%;
  transform: translate(calc(-50% + var(--tl2-spine-width) / 2), 0);
  z-index: 2;
  pointer-events: none;
}

.tl2__tip-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--tl2-tip-icon-size);
  height: var(--tl2-tip-icon-size);
  margin: calc(-1 * var(--tl2-tip-icon-size) / 2) 0 0 calc(-1 * var(--tl2-tip-icon-size) / 2);
  /* The sprite is a monochromatic PNG. We use it as a mask and fill
     the icon with our own colour, so a single asset can render in any
     colour via CSS. (Falls back to invisible if mask-image is not
     supported — old browsers; acceptable since the rest still works.) */
  background-color: var(--tl2-tip-icon-color);
  -webkit-mask-image: url("../images/icon-timeline-sprite.png");
          mask-image: url("../images/icon-timeline-sprite.png");
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: 20px auto;
          mask-size: 20px auto;
}

@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  .tl2__tip-icon {
    -webkit-mask-image: url("../images/icon-timeline-sprite@2x.png");
            mask-image: url("../images/icon-timeline-sprite@2x.png");
  }
}

.tl2__tip-icon--release { -webkit-mask-position: 0 0;     mask-position: 0 0; }
.tl2__tip-icon--radio   { -webkit-mask-position: 0 -20px; mask-position: 0 -20px; }
.tl2__tip-icon--show    { -webkit-mask-position: 0 -40px; mask-position: 0 -40px; }
.tl2__tip-icon--news    { -webkit-mask-position: 0 -60px; mask-position: 0 -60px; }
.tl2__tip-icon--video   { -webkit-mask-position: 0 -80px; mask-position: 0 -80px; }
.tl2__tip-icon--contest { -webkit-mask-position: 0 -100px; mask-position: 0 -100px; }

/* ----- card ----- */
.tl2__card {
  background: var(--tl2-card-bg);
  color: var(--tl2-card-fg);
  border-radius: var(--tl2-card-radius);
  overflow: hidden;
  max-width: var(--tl2-card-max);
  /* Subtle lift on hover: scale 2% up + soft shadow. transform-origin
     center so the card grows evenly from its visual center; the
     transition keeps the motion gentle enough to read as 'lift'
     rather than 'jump'. */
  transition: transform 180ms ease-out, box-shadow 180ms ease-out;
  transform-origin: center center;
  will-change: transform;
}

.tl2__card:hover {
  transform: scale(1.02);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
}

.tl2__link {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: color 200ms ease;
}

.tl2__link:hover,
.tl2__link:focus-visible {
  color: var(--tl2-card-fg-hover);
}

/* ----- sentinel -----
   Invisible marker near the end of the list. timeline-v2.js observes
   it with IntersectionObserver and triggers a fetch for the next
   page when it enters (or nears) the viewport. The 1px height is
   enough to be observable; pointer-events: none so it never gets in
   the way of the layout or interactions. */
.tl2__sentinel {
  display: block;
  height: 1px;
  pointer-events: none;
  list-style: none;
}

.tl2__cover {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.tl2__cover--placeholder {
  background: rgba(0, 0, 0, 0.05);
  aspect-ratio: 1 / 1;
}

.tl2__meta { padding: 1rem; }

.tl2__date {
  display: block;
  font-size: 0.75rem;
  opacity: 0.55;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin-bottom: 0.35rem;
}

.tl2__entry-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
}

/* ----- mobile (< 700px) -----
   Stripped-down stacked list: no spine, no year-nav, no year-markers,
   no tip icons. Just the cards in chronological order between the
   site header and footer. This deliberately drops the timeline
   metaphor on small screens where the central spine + zigzag layout
   doesn't fit usefully anyway — keeping only what's actionable
   (the entries themselves) avoids visual clutter.

   The hidden elements stay in the DOM so the page still works
   without JS, the year-nav anchors still resolve, and the desktop
   layout reactivates intact when the viewport widens. */
@media (max-width: 699.98px) {
  /* hide spine */
  .tl2__list::before { display: none; }

  /* hide the fixed three-balloon year-nav */
  .tl2__year-nav { display: none; }

  /* hide in-flow year markers (red year balloons between entries) */
  .tl2__year-marker { display: none; }

  /* hide tip + tip-icon (anchored to spine, has no meaning without it) */
  .tl2__entry .tl2__tip { display: none; }

  /* drop left padding that made room for spine + tip */
  .tl2__entry { padding-left: 0; }

  /* card full-width (within the .tl2 container's 1rem horizontal padding) */
  .tl2__card { max-width: none; }

  /* Top padding clears the fixed site header (.contain-to-grid is
     70px tall) and adds breathing room above the page heading. */
  .tl2 { padding-top: 6rem; }

  /* tighten the gap between cards now that the spine isn't there
     to space them visually */
  .tl2__entry { margin-bottom: 1.5rem; }

  /* show the page heading instead of the year-nav — gives mobile
     users the same "what page am I on" cue. Reset from the
     screen-reader-only positioning so it renders normally.
     Centered to match the homepage banner/title alignment
     and the /shows h1 alignment on mobile. */
  .tl2__heading {
    position: static;
    width: auto;
    height: auto;
    margin: 0 0 1.5rem;
    padding: 0;
    overflow: visible;
    clip: auto;
    white-space: normal;
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: 0.01em;
    color: #fff;
    text-align: center;
  }
}

/* ----- wide screens ----- */
@media (min-width: 700px) {
  /* spine centered */
  .tl2__list::before {
    left: 50%;
    transform: translateX(-50%);
  }

  /* year marker centered on spine */
  .tl2__year-marker { justify-content: center; }
  .tl2__year-label  { margin-left: 0; }

  /* entry as 3-column grid */
  .tl2__entry {
    padding-left: 0;
    display: grid;
    grid-template-columns: 1fr var(--tl2-spine-gutter) 1fr;
    align-items: start;
  }

  .tl2__entry[data-side="left"]  .tl2__card { grid-column: 1; justify-self: end; }
  .tl2__entry[data-side="right"] .tl2__card { grid-column: 3; justify-self: start; }

  /* Zigzag offset: a right-side card directly following a left-side
     card pulls up so the two visually interlock. Applied ONLY when
     a right follows a left (not when a year-marker breaks the
     adjacency, and not when a new left starts a fresh pair). */
  .tl2__entry[data-side="left"] + .tl2__entry[data-side="right"] {
    margin-top: calc(-1 * var(--tl2-zigzag-offset));
  }

  /* tip centered on spine */
  .tl2__tip {
    top: 24px;
    left: 50%;
    transform: translateX(-50%);
  }
}


/* 2026-05-11: pill is loading older pages to find its target marker.
   Dim it and disable pointer events so users don't double-click. */
.tl2__year-pill.is-loading {
  opacity: 0.5;
  pointer-events: none;
  cursor: wait;
}
