/* Scroll fill heading: a hard horizontal edge sweeps the heading's colour from --sfh-base to --sfh-fill, bottom up,
   as it scrolls through a band of the window. part.js writes --sfh-p (0..1); this file turns it into the edge.
   Without JS (no .sfh-on) the heading is simply the fill colour. */
.sfh {
  --sfh-base: #8a6e5a;   /* colour above the edge (the unfilled part); set it to the ground colour and the word emerges */
  --sfh-fill: #ffffa8;   /* colour below the edge (the filled part) */
  --sfh-over: .25;       /* how far (share of the heading's height) the edge starts below the box and ends above it */
  --sfh-soft: .005;      /* half-width of the edge blend, share of the heading's height (.005 = a 1% band: a hard edge) */
  --sfh-p: 0;            /* progress, written by part.js (or by you / a scroll-driven animation) */
  color: var(--sfh-fill);
}
.sfh.sfh-on {
  /* edge height from the bottom = p * (1 + 2 * over) - over  (source: p * 1.5 - .25) */
  --sfh-level: calc(var(--sfh-p) * (1 + 2 * var(--sfh-over)) - var(--sfh-over));
  background-image: linear-gradient(to top,
    var(--sfh-fill) calc((var(--sfh-level) - var(--sfh-soft)) * 100%),
    var(--sfh-base) calc((var(--sfh-level) + var(--sfh-soft)) * 100%));
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
/* Fit Width: part.js wraps the text in this box to measure its widest line */
.sfh__fit { display: inline-block; white-space: nowrap; }
