/* Home — the fortnight: the honest two-week timeline, and its pinned
   scroll-jacked variant.

   ONE FILE ON PURPOSE. The pinned half re-declares selectors the flat half
   already set — `.rhythm--scroll .fort` is `display: block` in the first part
   and `display: flex` in the second, same specificity — so the later one has to
   win. Splitting this in two would make that a load-order rule to remember;
   keeping it together makes it a non-issue.

   Everything under `.rhythm--scroll` is opt-in: main.js only sets that class
   when the window is wide, the pointer is real, motion is allowed and there is
   room to pin. The card and well heights are measured in JS. */

/* ── The fortnight ──────────────────────────────────────────────
   The admission (ink panel) and the fourteen days that answer it. Two panels of
   one section rather than two sections, so the limit and the remedy are read
   together. The accent budget for this whole region is spent here, on the three
   cells that turn: everything else is ink, paper and a hairline. */

.rhythm__grid { display: grid; grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr); gap: clamp(16px, 1.8vw, 24px); align-items: start; }

/* The stage — the admission plus the four phases of the fortnight. Unpinned (and
   with JS off) it is one ink box divided by hairlines, everything readable at once.
   Pinned, the same cards become a stack; those rules are further down. */
.stage__well { background: var(--ink); color: var(--cream); border-radius: 24px; padding: clamp(24px, 2.6vw, 30px); }
.stage__card + .stage__card { margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,.14); }
.stage__card h3 { color: var(--cream); }
.stage__card p { margin: 0 0 12px; color: var(--on-ink); font-size: 15px; line-height: 1.6; }
.stage__card p:last-child { margin-bottom: 0; }
.stage__when { font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--on-ink-dim); margin: 0 0 8px !important; }
/* The result of a phase: the figure, then what it is. Set apart from the action
   above it by a hairline, because the two are different kinds of claim — one is
   what you do, the other is what a cold account usually gets back. */
.stage__out { margin-top: 14px !important; padding-top: 12px; border-top: 1px solid rgba(255,255,255,.14); }
.stage__out b { display: block; font-family: var(--display); font-weight: 900; font-size: clamp(20px, 1.9vw, 25px); letter-spacing: -.02em; color: var(--cream); }
.stage__out i { display: block; margin-top: 4px; font-style: normal; font-size: 13.5px; line-height: 1.5; color: var(--on-ink-mid); }
.stage__caveat { margin: 14px 4px 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-50); }

/* The day-by-day track is the pinned experience and nothing else: without the pin
   there is no reason to print fourteen more lines under a stage that already spells
   the fortnight out phase by phase. main.js shows this again with .rhythm--scroll. */
.fort { display: none; background: #fff; border: 1px solid var(--line); border-radius: 24px; padding: clamp(24px, 2.6vw, 32px); box-shadow: var(--shadow); }
.rhythm--scroll .fort { display: block; }
.fort__head { display: flex; align-items: center; gap: 14px; margin-bottom: clamp(20px, 2.4vw, 28px); }
.fort__lead { margin: 0; font-size: var(--label-size); font-weight: 700; letter-spacing: var(--label-track); text-transform: uppercase; color: var(--ink-50); }
/* The day counter. Only earns its place while the track is moving, so it is laid
   out but hidden until the controller pins the section. */
.fort__meter { display: none; position: relative; width: 44px; height: 44px; flex: none; }
.fort__meter svg { width: 44px; height: 44px; transform: rotate(-90deg); }
.fort__meter circle { fill: none; stroke-width: 2; }
.fort__ringTrack { stroke: var(--line); }
/* 2πr for r=20, so dashoffset 0 is a whole ring and --c 0 is an empty one. */
.fort__ringArc { stroke: var(--blue-deep); stroke-linecap: round; stroke-dasharray: 125.6; stroke-dashoffset: calc(125.6 - (125.6 * var(--c, 0))); transition: stroke-dashoffset .15s linear; }
.fort__num { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--display); font-weight: 900; font-size: 15px; color: var(--ink); font-variant-numeric: tabular-nums; }

.fort__notes { list-style: none; margin: clamp(24px, 3vw, 40px) 0 0; padding: clamp(18px, 2vw, 24px) 0 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px clamp(20px, 2.4vw, 34px); border-top: 1px solid var(--line); }
.fort__notes li { color: var(--ink-70); font-size: 15px; line-height: 1.55; }
.fort__notes b { color: var(--ink); font-weight: 700; }

/* ── The fourteen days ──────────────────────────────────────────
   Mobile and any pointer that can't hover get the honest version: a vertical rail
   with all fourteen lines open. The horizontal axis is layered on top of it lower
   down, gated on `hover: hover`, because a timeline you have to hover is no
   timeline at all on a phone. */

.tl__axis { list-style: none; margin: 0; padding: 0; position: relative; display: grid; }
/* The rail the dots sit on. Inset by half a dot at each end so it starts and stops
   on a day rather than in mid-air. */
.tl__axis::before { content: ''; position: absolute; left: 5px; top: 17px; bottom: 17px; width: 1px; background: var(--line); }
.tl__stop { position: relative; display: grid; grid-template-columns: 11px 1fr; align-items: start; gap: 12px; padding: 7px 0; }
.tl__d { display: none; }
.tl__dot {
  width: 11px; height: 11px; border-radius: 50%; margin-top: 5px;
  background: var(--ink); border: 1px solid var(--ink);
  transform: scale(.55); opacity: 0;
  transition: opacity .35s ease-out, transform .35s ease-out, background-color .2s ease-out, border-color .2s ease-out;
  transition-delay: calc(var(--i, 0) * 45ms);
}
/* A day you didn't post. Hollow, so the rhythm's gaps are visible as gaps. */
.tl__stop.is-rest .tl__dot { background: #fff; }
.tl__stop.is-rest .tl__pop { color: var(--ink-50); }
/* Served in sequence off the existing .reveal observer — no second observer. */
.fort.is-in .tl__dot { opacity: 1; transform: none; }
.tl__pop { color: var(--ink-70); font-size: 15px; line-height: 1.5; }
.tl__pop b { color: var(--ink); font-weight: 700; margin-right: 6px; }
.tl__idle { margin: 16px 4px 0; color: var(--ink-70); font-size: 15.5px; line-height: 1.6; }
.tl__idle b { color: var(--ink); }
/* Only ever seen while the track is moving; the vertical rail closes with .tl__idle. */
.tl__cap { display: none; }

@media (min-width: 721px) and (hover: hover) {
  /* One line, fourteen stops. Each stop is exactly 1/14 of the axis, which is what
     makes the pop positioning below work from --i alone. */
  .tl { position: relative; }
  .tl__axis { grid-template-columns: repeat(14, 1fr); }
  .tl__axis::before { left: 3.57%; right: 3.57%; top: 5px; bottom: auto; width: auto; height: 1px; }
  .tl__stop { grid-template-columns: none; justify-items: center; gap: 0; padding: 0; }
  .tl__dot { margin-top: 0; }
  .tl__d { display: block; margin-top: 12px; font-size: 12.5px; font-weight: 600; color: var(--ink-50); font-variant-numeric: tabular-nums; transition: color .2s ease-out; }
  /* Every pop lands on the same block under the axis: shifted left by --i of its own
     width it sits at the axis's left edge, and fourteen widths across is the axis.
     They overlay the idle line exactly, so swapping one for another shifts nothing. */
  .tl__pop {
    position: absolute; top: calc(100% + 18px);
    left: calc(var(--i) * -100%); width: 1400%;
    opacity: 0; pointer-events: none;
    transition: opacity .18s ease-out;
    font-size: 15.5px; line-height: 1.6;
  }
  .tl__stop:hover .tl__dot { background: var(--blue-deep); border-color: var(--blue-deep); transform: scale(1.45); }
  .tl__stop:hover .tl__d { color: var(--ink); }
  .tl__stop:hover .tl__pop { opacity: 1; }
  .tl__idle { transition: opacity .18s ease-out; min-height: 3.2em; }
  /* There was a `.tl__axis:hover ~ .tl__idle { opacity: 0 }` here, meant to fade
     the summary line out while the pointer walked the timeline. It never fired:
     `~` needs a later SIBLING, and .tl__idle sits inside the <aside> that closes
     before .tl__axis begins (index.html:634 vs :661). Removed rather than fixed,
     because making it work is a markup change and a visible one. Its comment
     claimed "source order matters", which would have been a false invariant to
     carry into a split file. */
}

@media (prefers-reduced-motion: reduce) {
  /* The global block zeroes the duration but not this rule's starting opacity, and
     a row of invisible dots is not a reduced version of anything. */
  .tl__dot { opacity: 1; transform: none; }
}

/* ── The fortnight, pinned ──────────────────────────────────────
   Everything under `.rhythm--scroll` is switched on by main.js, and only where it
   can work: a wide window, a real pointer, motion allowed. The class is the whole
   feature flag — with JS off none of this applies and the section is the plain
   vertical rail above. */

.rhythm--scroll .rhythm__pin { position: sticky; top: 92px; }
/* The pinned block owns the viewport while it runs, so its own vertical padding
   comes off: the section's rhythm is now the scroll distance, not the margins. */
.rhythm--scroll { padding-bottom: var(--gap); }
.rhythm--scroll .section__head { margin-bottom: clamp(24px, 2.6vw, 34px); }
/* The stage holds still on the left and the fortnight runs past it on the right.
   minmax(0,…), not 1fr, on the track column: a `width: max-content` strip inside an
   auto-min column pushes it out to the full 3640px and there is nothing to scroll. */
.rhythm--scroll .rhythm__grid { grid-template-columns: clamp(300px, 26vw, 360px) minmax(0, 1fr); gap: clamp(20px, 2.2vw, 30px); align-items: start; }
/* The two boxes are one pair and read as one: main.js gives them a shared height
   (the taller of the two contents), and the track centres itself in whatever is
   left rather than sitting at the top of a half-empty card. */
.rhythm--scroll .fort { display: flex; flex-direction: column; }
.rhythm--scroll .tl { flex: 1; display: flex; align-items: center; }
.rhythm--scroll .fort, .rhythm--scroll .tl { min-width: 0; }

/* The stack. Each phase is its own ink card in the same well; the ones already
   passed stay visible as edges behind the current one, so the fortnight piles up
   instead of just replacing itself. --n is how far back a card is, set by main.js. */
.rhythm--scroll .stage__well { position: relative; background: none; padding: 0; }
.rhythm--scroll .stage__card {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; flex-direction: column; justify-content: center;
  box-sizing: border-box; margin: 0; padding: 22px 24px;
  background: var(--ink); border: 1px solid rgba(255,255,255,.14); border-radius: 20px;
  /* Not yet reached: waiting just below, invisible. */
  opacity: 0; transform: translateY(22px) scale(.99); z-index: 1;
  transition: opacity .45s ease-out, transform .45s ease-out;
}
.rhythm--scroll .stage__card h3 { font-size: 19px; }
.rhythm--scroll .stage__card p { font-size: 13.5px; line-height: 1.5; margin-bottom: 10px; color: #B9B9BC; }
.rhythm--scroll .stage__out b { font-size: clamp(19px, 1.7vw, 23px); }
.rhythm--scroll .stage__out i { font-size: 12.5px; }
/* The one being read. */
.rhythm--scroll .stage__card.is-on { opacity: 1; transform: none; z-index: 10; }
/* Behind it: lifted and shrunk a step per card, so only their top edge shows. */
.rhythm--scroll .stage__card.is-back {
  opacity: calc(1 - .3 * var(--n, 1));
  transform: translateY(calc(-11px * var(--n, 1))) scale(calc(1 - .035 * var(--n, 1)));
  z-index: calc(9 - var(--n, 1));
}
.rhythm--scroll .stage__caveat { margin-top: 16px; }
.rhythm--scroll .fort__meter { display: block; }

/* The window the fortnight moves through. It runs to the card's inner edges, and the
   mask is what stops the edge from slicing dots in half as they arrive and leave: a
   day fades out across the last 36px instead of being cut down the middle. */
.rhythm--scroll .tl {
  overflow: hidden;
  margin: 0 calc(clamp(24px, 2.6vw, 32px) * -1);
  padding: 0 clamp(24px, 2.6vw, 32px);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 36px, #000 calc(100% - 36px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 36px, #000 calc(100% - 36px), transparent 100%);
}
/* flex-start, not stretch: stretching every day to the ink panel's height left a
   third of the card empty under two lines of text. */
.rhythm--scroll .tl__strip { display: flex; align-items: flex-start; width: max-content; will-change: transform; }
/* `flex: none` matters: with the default `flex-shrink: 1`, Safari squeezes this box
   down towards the width of the visible window while its fourteen fixed-width days
   carry on overflowing it — and the tail, which is laid out right after the box,
   lands on top of them. main.js also pins an explicit width on it for the same
   reason. Centred in the row because the note beside it is taller than two lines of
   day copy, and parking the days at the top leaves all of that height dead. */
.rhythm--scroll .tl__axis { grid-template-columns: none; display: flex; flex-wrap: nowrap; flex: none; width: max-content; align-self: center; }
/* The terminus: the same dot on the same rail, then the sentence the fortnight was
   heading for. Its box has to stay as wide as main.js sets it — that width is what
   carries day 14 to the focus point — so the readable measure is capped on the text
   inside instead of on the stop. */
.rhythm--scroll .tl__cap { display: block; flex: none; box-sizing: border-box; padding-right: 24px; }
.rhythm--scroll .tl__capDot {
  display: block; width: 13px; height: 13px; margin: -1px 0 13px -1px;
  border-radius: 50%; background: var(--ink);
  /* A ring instead of a bigger dot: it reads as the end of the line, not as another
     day that happens to be louder. */
  box-shadow: 0 0 0 4px #fff, 0 0 0 5px var(--line);
}
.rhythm--scroll .tl__capWhen { margin: 0 0 6px; font-size: var(--label-size); font-weight: 700; letter-spacing: var(--label-track); text-transform: uppercase; color: var(--ink-50); }
.rhythm--scroll .tl__capLine { margin: 0; max-width: 34ch; color: var(--ink-50); font-size: 14.5px; line-height: 1.55; }
.rhythm--scroll .tl__capLine b { display: block; margin-bottom: 5px; color: var(--ink); font-family: var(--display); font-weight: 800; font-size: 18px; line-height: 1.25; letter-spacing: -.015em; }
/* From the first day's dot to the terminus, and no further: --rail-end is the width
   of the last stop, which main.js sets along with it. */
.rhythm--scroll .tl__axis::before { left: 5px; right: var(--rail-end, 130px); top: 5px; bottom: auto; width: auto; height: 1px; }
.rhythm--scroll .tl__stop {
  flex: 0 0 260px; display: block; padding: 0 26px 0 0; gap: 0;
  /* Off the focus point a day is still legible, just clearly not the one being
     read — the dimming is what makes the moving one feel like the subject. */
  opacity: .34; transition: opacity .3s ease-out;
}
.rhythm--scroll .tl__stop.is-on { opacity: 1; }
/* The stop is a block here rather than a grid, so the dot has to be told to stop
   being an inline span or it renders as a hairline sliver. The stagger delay goes
   too: it belongs to the entrance, and inherited by the active state it made the
   last days take half a second to light up as they reached the focus point. */
.rhythm--scroll .tl__dot { display: block; margin: 0 0 14px; transition-delay: 0s; }
.rhythm--scroll .tl__stop.is-on .tl__dot { background: var(--blue-deep); border-color: var(--blue-deep); transform: scale(1.35); }
.rhythm--scroll .tl__d { display: none; }
.rhythm--scroll .tl__pop { position: static; opacity: 1; width: auto; font-size: 15.5px; line-height: 1.55; }
.rhythm--scroll .tl__pop b { display: block; margin: 0 0 4px; font-family: var(--display); font-size: 15px; }
/* The summary belongs to the un-pinned version; pinned, the days speak for
   themselves and the counter says where you are. */
.rhythm--scroll .tl__idle { display: none; }

/* ── Breakpoints ─────────────────────────────────────────────── */

@media (max-width: 980px) {
  /* The admission stacks above the calendar, which is the reading order the
     argument needs anyway: the problem, then the fourteen days that answer it. */
  .rhythm__grid { grid-template-columns: 1fr; }
  .fort__notes { grid-template-columns: 1fr; }
}
