@property --p{syntax:'<number>';inherits:true;initial-value:0}

/* ============ ENTRY LOADER ============
   Full-viewport overlay, shown from first paint, removed from the DOM by
   loader.js once fonts + hero are ready (or the 3s hard timeout fires).
   Self-contained on purpose: it may not depend on styles.css loading, and it
   must not be edited from there. Colours are literals for the same reason -
   :root tokens live in styles.css and the loader outlives neither ordering
   assumption. Only transform/opacity animate.
   The sandwich here is the hero photograph, not a drawing of one. It used to
   be a five-layer CSS rebuild of the .sw renderer, bouncing on a 950ms loop:
   a second copy of a stack that had to be kept in sync by hand, animating
   while the page was still deciding what it looked like. The photograph is
   already being fetched by loader.js to decide when to dismiss, so showing it
   here costs nothing and the first thing anyone sees is real food. */

/* 30: one step above the header bar (20), which is the top of the app's scale. */
#ldr{position:fixed;inset:0;z-index:30;background:#FDF9F4;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:28px;padding:24px 16px;opacity:1;transition:opacity .38s cubic-bezier(.4,0,.2,1)}
#ldr.out{opacity:0}

/* Direct child only: the logo. The hero photograph lives inside .ldstage and
   must not inherit the logo's 88x58 box - an id+element selector outranks the
   .ldhero class, so this has to be scoped rather than overridden. */
#ldr > img{width:88px;height:58px;object-fit:contain}

#ldr h1{margin:0;text-align:center;text-wrap:balance;max-width:11ch;
  font-family:"MomentsDisplay","MomentsDisplay Fallback",Arial,sans-serif;
  font-weight:700;font-size:34px;line-height:40px;color:#292B29}

/* ---------- stage: the hero photograph on a colour fill ---------- */
.ldstage{position:relative;width:min(280px,78vw);aspect-ratio:800/481;
  border-radius:20px;overflow:hidden;background:#EFDBB2}
.ldhero{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}

/* The progress read. --p runs 0 to 1 and the grey copy's clip retreats to the
   right, so colour arrives across the photograph as the page actually loads.
   Nothing here tracks across the screen: the only thing that moves is the
   boundary between grey and colour, which IS the progress bar. */
.ldgray{filter:grayscale(1) brightness(1.06) contrast(.92);
  clip-path:inset(0 0 0 calc(var(--p, 0) * 100%))}

/* No transition on the clip. A CSS transition needs the compositor to be
   running, and the compositor is exactly what a browser stops doing while a
   tab is not painting - which left the boundary frozen at its start value.
   loader.js steps --p on its own timer instead, so the fill advances on the
   same clock that measures the loading it is reporting. */
