/* ── The cost red travels with this file ────────────────────────────────
   type-motion.css is linked from every template, which makes it the one
   place that reaches the whole site. The cost-red tokens are declared here
   so a page like contact.html or cibil-analyser.html, which loads no other
   shared stylesheet, still resolves them. Identical values to polish.css —
   see there for why there are three. */
:root{
  --cost-red:#B3261E;              /* text on a light surface */
  --cost-red-on-dark:#F0776B;      /* text on a dark surface  */
  --cost-red-bar-on-dark:#E54B3E;  /* a bar on a dark surface */
  --cost-red-auto:#B3261E;
  --cost-red-bar-auto:#B3261E;
}
:root[data-theme="dark"]{
  --cost-red-auto:var(--cost-red-on-dark);
  --cost-red-bar-auto:var(--cost-red-bar-on-dark);
}

/* ═══════════════════════════════════════════════════════════════════════════
   TYPE MOTION — words settle into place as you reach them
   ═══════════════════════════════════════════════════════════════════════════

   A heading arrives slightly small, slightly light and slightly loose, then
   tightens into its finished form: it scales up a touch, the letter-spacing
   closes, and the weight thickens. Read together that looks like the word
   coming into focus rather than sliding in from somewhere.

   ── Why a transition and not a keyframe animation ───────────────────────

   Every heading on this site has its own weight and tracking — the hero is
   750 at -2.4px, a section title is 900 at -0.02em, a card heading is 800
   at normal. A keyframe has to name its `to` values, which would overwrite
   all of that with one hardcoded look.

   A transition does not. The END state is whatever the element was already
   designed to be; only the START is specified here. So this layer can be
   dropped on any heading, in any template, without knowing anything about
   how that heading is styled.

   ── Why the weight part needs the variable font ─────────────────────────

   Manrope was being requested as a list of weights, which serves a separate
   static file per weight — font-weight could only jump 700 → 800, never
   pass through. The request is now the range wght@200..800, which is one
   variable file, so weight is a continuous axis and interpolates. It is
   also fewer files than the thirty static faces that were loading before.

   ── The safety rule, learned the hard way ───────────────────────────────

   `.tm-h:not(.tm-in)` is invisible. That is only acceptable because the
   class is added by type-motion.js and never written in the HTML, and
   because that script sweeps anything already past the fold. A thin
   element that a fast scroll jumps over must never be left hidden — that
   exact bug cost three sections on this site earlier today.
   ═══════════════════════════════════════════════════════════════════════════ */

.tm-h {
  transition:
    opacity        .55s ease,
    scale          .85s cubic-bezier(.2, .85, .25, 1),
    letter-spacing .85s cubic-bezier(.2, .85, .25, 1),
    font-weight    .85s cubic-bezier(.2, .85, .25, 1);
  transform-origin: left center;
  will-change: scale, letter-spacing;
}

/* The pre-arrival state. Lighter, looser, a little smaller — the finished
   values are the element's own, so nothing here has to know them. */
/* The start values are PER ELEMENT, written by type-motion.js from what
   that heading is actually styled as. A flat `font-weight: 500` looked
   right on the hero at 750 and backwards on loans.html, where a section
   title is authored at 400 — that heading animated from heavy to light,
   the opposite of settling in. The script now sets --tm-w0 to roughly
   250 below whatever the real weight is, so every heading thickens into
   place regardless of where it ends up. */
.tm-h:not(.tm-in) {
  opacity: 0;
  scale: .965;
  letter-spacing: var(--tm-ls0, .045em);
  font-weight: var(--tm-w0, 500);
}

/* Centred headings grow from the middle instead of the left edge, or the
   first letter walks sideways. */
.tm-h.tm-centre { transform-origin: center; }

/* A heading that has arrived is finished with — drop the hint so the
   compositor is not holding layers for the rest of the session. */
.tm-h.tm-in { will-change: auto; }

/* Lead paragraphs come with the heading, a beat behind, and only fade —
   moving body copy is harder to read and adds nothing. */
.tm-p { transition: opacity .6s ease .12s; }
.tm-p:not(.tm-in) { opacity: 0; }

/* ── Reduced motion ─────────────────────────────────────────────────────
   No scale, no tracking shift, no weight change — those are the parts that
   move. A plain fade stays, because it does not. Nothing may be left
   invisible under any circumstances. */
@media (prefers-reduced-motion: reduce) {
  .tm-h, .tm-p { transition: opacity .4s ease; }
  .tm-h:not(.tm-in) {
    scale: 1;
    letter-spacing: inherit;
    font-weight: inherit;
    opacity: .001;
  }
  .tm-h.tm-in, .tm-p.tm-in { opacity: 1; }
}
