/* ===========================================================================
   V2 · delta over precision-a.css
   ---------------------------------------------------------------------------
   1  Lime accent, replacing the periwinkle
   2  Scroll text highlight on the thesis lede
   ======================================================================== */

/* ---------------------------------------------------------------------------
   1 · BLACK AND LIME
   ----------------------------------------------------------------------------
   Lime is exceptional on a dark ground and unusable on a light one, so this
   palette only exists because the page went dark first. On the canvas it
   measures 16.48; on white it would have been 1.5 and confined to fills, the
   same trap the four supplied pastels fell into.

   THE BUTTON INVERTS. White on lime measures 1.19 and would be invisible, so
   the label is near-black at 16.48. That is the "black and lime" pairing
   doing real work rather than being a mood.

   THE PANEL STATES HAD TO MOVE, and this is the part that is not obvious.
   Lime sits 0.95 from the old mint "ok" state and 1.17 from sky: both are
   separable by hue alone, and `panel__step` puts the accent and the ok state
   in the same list, where a reader compares them directly. Dropping both
   states clear of lime's luminance fixes it. Measured on the raised ground,
   which is the tightest of the three:

       ok vs flag    1.59    the pair a reader actually compares
       ok vs lime    1.54
       flag vs lime  2.45

   Audited by tools/contrast.mjs. Every pair that shares a component is in
   there as a required row, not a comment.
   ------------------------------------------------------------------------ */
.p-body-root {
  --accent: #c6ff00;          /* 16.48 canvas · 15.90 sunken · 14.51 surface */
  --accent-quiet: #a8d900;    /* 11.72 canvas                                */
  --accent-contrast: #0a0c12; /* 16.48 on lime                               */
  --accent-tint: rgba(198, 255, 0, 0.12);

  --panel-accent: #c6ff00;    /* 14.51 panel · 13.08 raised */
  --panel-accent-alt: #7fc8f5;
  --panel-ok: #7fc8f5;        /*  9.41 panel ·  8.48 raised */
  --panel-flag: #d98324;      /*  5.93 panel ·  5.34 raised */

  /* The scroll highlight's two states. Both are reading colours. */
  --hl-rest: var(--ink-tertiary); /* 6.15 on canvas  */
  --hl-lit: var(--ink);           /* 19.55 on canvas */
}

/* The primary button is the pairing itself: lime ground, near-black label at
   16.48. In v1 it inherits `--ink` and comes out white, which is a perfectly
   good dark-mode button and not what was asked for. Hover swaps to white so
   the state change is unmistakable at a glance rather than a shade of lime. */
.p-btn--primary {
  background: var(--accent);
  color: var(--accent-contrast);
}

.p-btn--primary:hover {
  background: var(--ink);
  color: var(--canvas);
}

/* Focus rings are drawn from the accent elsewhere in the system. On a lime
   button the ring would sit lime-on-lime, so it inverts here. */
.p-btn--primary:focus-visible {
  outline-color: var(--ink);
}

/* ---------------------------------------------------------------------------
   2 · THE TURN
   ----------------------------------------------------------------------------
   The pivot from what is wrong to what is owed, given its own band.

   Everything here is about the pause rather than the type. The band carries
   roughly a third of a viewport of space above and below it, and holds
   nothing else, so a reader coming off five problem items gets a beat before
   the platform is introduced. Set between lede and h2 size: large enough to
   read as a statement, small enough that it does not compete with the
   headline it is setting up.

   Centred, which is the one exception to this page's alignment discipline
   besides the hero. Both are single-sentence moments where the line is the
   whole content of the band, and left-aligning either would leave the
   right-hand side of the screen conspicuously empty.
   ------------------------------------------------------------------------ */
.p-turn {
  padding-block: clamp(var(--s-24), 18vh, var(--s-40));
  text-align: center;
}

.p-turn__line {
  margin-inline: auto;
  max-width: 26ch;
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
  line-height: 1.3;
  letter-spacing: var(--tracking-h3);
  font-weight: var(--weight-regular);
  color: var(--ink);
  text-wrap: balance;
}

/* ---------------------------------------------------------------------------
   3 · SCROLL TEXT HIGHLIGHT
   ----------------------------------------------------------------------------
   Originkit's effect, without its runtime. The supplied component drives this
   with GSAP and ScrollTrigger; CSS scroll-driven animations do the same job
   with no script, which matters on a page that has no dependencies and
   inlines everything into one file.

   HOW THE STAGGER WORKS. There is no stagger property on a scroll timeline,
   so each word gets its own slice of the parent's progress instead: `--i / --n`
   places the word in the sequence, and its animation range starts and ends
   that fraction later than the first word's. The result is a diagonal wipe
   through the paragraph tied to scroll position rather than to time, so it
   runs backwards when the reader scrolls back up, which a time-based
   implementation does not.

   The timeline is named on the paragraph and referenced by the words. Using
   an anonymous `view()` on each word would give every word its own timeline
   measured against its own box, which is not the same thing at all: short
   words would light faster than long ones.
   ------------------------------------------------------------------------ */
.p-scrollhl__w {
  /* The base state, and the only state on a browser that will not animate. */
  color: var(--hl-lit);
}

@supports (animation-timeline: view()) {
  .p-scrollhl {
    view-timeline-name: --p-scrollhl;
    view-timeline-axis: block;
  }

  .p-scrollhl__w {
    --p: calc(var(--i) / var(--n));
    color: var(--hl-rest);
    display: inline-block;
    animation: p-scrollhl-in linear both;
    animation-timeline: --p-scrollhl;
    /* Opens once the block is a third of the way up the viewport and finishes
       before it leaves, so the last word lights while the paragraph is still
       comfortably in view rather than as it exits the top. */
    animation-range-start: cover calc(14% + var(--p) * 36%);
    animation-range-end: cover calc(30% + var(--p) * 36%);
  }
}

@keyframes p-scrollhl-in {
  from { color: var(--hl-rest); }
  to { color: var(--hl-lit); }
}

/* Reduced motion gets the finished paragraph. Not the resting tone, and not a
   faster version of the wipe: the point of the effect is the movement, and
   without it the only honest state is fully lit. */
@media (prefers-reduced-motion: reduce) {
  .p-scrollhl__w {
    color: var(--hl-lit);
    animation: none;
  }
}
