/* THE PAGE LOADER (2026-10-06).

   page-loader.js marks <html data-loader="on"> before the body is drawn. While it is on, this
   covers the page with the page's own background and, after 160 ms, the seal inside a gold arc
   turning round it like a vault dial. When the page is whole the script sets data-loader="off":
   the cover fades and the attribute goes. Drawn with body::before and body::after, so no page
   carries markup for it and no script can find it.

   It never takes a click (pointer-events: none). If the script dies part way, the cover hides
   itself after six seconds (sfl-failsafe). Without JavaScript the attribute is never set and
   none of this applies. The front page is dark in either theme, and so is its cover; How it
   works and the other style.css pages have a light theme, and the cover follows it. */

@property --sfl-turn {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

html[data-loader] body::before,
html[data-loader] body::after {
  content: "";
  position: fixed;
  z-index: 2147483647;
  pointer-events: none;
}

/* The cover: the page's own ground, so a fast load reads as the page arriving, not a flash. */
html[data-loader] body::before {
  inset: 0;
  background: #0a0a09;
  animation: sfl-failsafe 200ms ease 6s forwards;
}
html[data-theme="light"][data-loader] body::before { background: #f4f5f8; }

/* The dial: the seal, a fine track, and a bright arc running round it. The middle layer paints
   the ground over all but the outer two pixels of the arc's circle, which leaves the ring. */
html[data-loader] body::after {
  top: 50%;
  left: 50%;
  width: 96px;
  height: 96px;
  margin: -48px 0 0 -48px;
  border-radius: 50%;
  background:
    url("/assets/logo-192.png") center / 60px 60px no-repeat,
    radial-gradient(closest-side, #0a0a09 calc(100% - 2px), transparent calc(100% - 1.5px)),
    conic-gradient(from var(--sfl-turn), rgba(230, 201, 124, 0) 0deg, rgba(230, 201, 124, 0.95) 100deg, rgba(201, 169, 97, 0.18) 100.5deg 360deg);
  opacity: 0;
  animation:
    sfl-in 280ms ease 160ms forwards,
    sfl-turn 1.4s linear infinite,
    sfl-failsafe 200ms ease 6s forwards;
}
html[data-theme="light"][data-loader] body::after {
  background:
    url("/assets/logo-192.png") center / 60px 60px no-repeat,
    radial-gradient(closest-side, #f4f5f8 calc(100% - 2px), transparent calc(100% - 1.5px)),
    conic-gradient(from var(--sfl-turn), rgba(95, 77, 44, 0) 0deg, rgba(95, 77, 44, 0.9) 100deg, rgba(95, 77, 44, 0.18) 100.5deg 360deg);
}

/* Lifting: the dial goes at once, the cover fades. */
html[data-loader="off"] body::before {
  opacity: 0;
  animation: none;
  transition: opacity 240ms ease;
}
html[data-loader="off"] body::after { content: none; }

/* WHAT IS ON SCREEN WHEN THE COVER LIFTS IS ALREADY IN PLACE. Sections that fade in as they come
   into view (motion.css, data-reveal) and the wins cards (wins-spot.css) would otherwise be
   caught half way through their entrance as the cover lifts. While it is up they arrive at once;
   below the fold they still come in as the reader scrolls to them. */
html[data-loader="on"] [data-reveal],
html[data-loader="on"] [data-reveal-group] > *,
html[data-loader="on"] .ws-card { transition: none !important; }

@keyframes sfl-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes sfl-turn {
  to { --sfl-turn: 360deg; }
}
@keyframes sfl-failsafe {
  to { opacity: 0; visibility: hidden; }
}

/* Still for anybody who asked for less motion: the dial stands, the cover goes without a fade. */
@media (prefers-reduced-motion: reduce) {
  html[data-loader] body::after {
    animation:
      sfl-in 1ms linear 160ms forwards,
      sfl-failsafe 200ms ease 6s forwards;
  }
  html[data-loader="off"] body::before { transition: none; }
}
