/* ════════════════════════════════════════════════════════════════════
   C.U.L.T. SKY · the shared backdrop layer · 2026-09-06

   Nathan, 2026-09-06: *"Dawn to dusk to sky to deep space."*

   One sky, four times of day. Sparks stands on the ground at dawn; Kids sees
   the sun just gone; Teens sees full night; Adult has left the planet and has
   no horizon at all. The horizon DROPS as you climb, which is the
   Ship-as-licence doctrine drawn as a picture — a child feels the climb
   without anyone explaining it.

   ── WHY THIS IS A SEPARATE FILE ─────────────────────────────────────
   Sparks and Chispas have SEPARATE stylesheets (sparks.css / chispas.css)
   but — usefully — identical token names (--spark-*) and the same .sp-*
   class prefix. So one override layer skins both, and Chispas inherits Dawn
   for free rather than needing its own copy maintained in parallel.

   It loads AFTER the tier stylesheet and overrides by cascade only. Nothing
   in sparks.css or chispas.css was edited, so removing the one <link> puts
   the old look back exactly. That is deliberate: this is a large visual
   change and it should be revertible in one line.

   ── WHAT WAS ACTUALLY DATED ─────────────────────────────────────────
   Not the colours. Three specific things, all fixed here:

     1. NO FONT WAS EVER LOADED. sparks.css named 'Quicksand' but no page
        ever fetched it, so all 34 fell through to Comic Sans MS. One missing
        <link> was doing a lot of the damage.
     2. `0 6px 0` hard offset shadows — the flat-kids-app look of ~2015.
        Replaced with real soft shadows that sit the card on the sky.
     3. 28px radius and 3px peach borders. Both dialled back; the card edge
        should be the quietest thing on the screen, not the loudest.

   ── ADDING THE OTHER THREE TIERS ────────────────────────────────────
   Dawn is the default on :root so Sparks and Chispas need no marker. A tier
   opts out by setting data-tier on <html>; add the block, keep everything
   else. The accents each tier needs already exist in its own stylesheet
   (Kids #FF6622/#8B0000, Teens #4FB8C9/#6A4C93, Adult #C9A84C).
   ════════════════════════════════════════════════════════════════════ */

:root {
  /* ── DAWN · the sky Sparks and Chispas stand under ──────────────── */
  --sky-1:#6B5A93; --sky-2:#8E72A6; --sky-3:#C08C9C;
  --sky-4:#E9A88C; --sky-5:#FFCBA4; --sky-6:#FFE7CA;
  --sky-7:#FFF2E0; --sky-8:#FFF9F0;

  /* Soft, real shadows. Every card in both stylesheets already routes
     through these two tokens, so redefining them re-skins the whole tier. */
  --spark-shadow:   0 10px 30px rgba(58, 32, 74, 0.18);
  --spark-shadow-h: 0 16px 40px rgba(58, 32, 74, 0.26);

  --spark-radius:   20px;
  --spark-radius-s: 14px;

  /* Ink shifts from warm brown to a deep plum so it belongs to the dawn
     rather than to the old cream page. */
  --spark-ink:      #2E2337;
  --spark-ink-soft: #6B5B78;

  --cult-display: 'Fredoka', 'Segoe UI', system-ui, sans-serif;
  --cult-body:    'Nunito', 'Segoe UI', system-ui, sans-serif;
}

/* ── the sky itself ─────────────────────────────────────────────────
   Fixed, so scrolling feels like standing still underneath it. Painted on
   <html> and <body> pseudo-elements rather than injected by script: the
   tile engine has twice now replaced DOM that another module was holding,
   and a backdrop that cannot be replaced cannot suffer that bug. */
html { background: var(--sky-1); }

html::before {
  content: '';
  position: fixed; inset: 0; z-index: -3; pointer-events: none;
  background: linear-gradient(180deg,
    var(--sky-1) 0%,  var(--sky-2) 7%,  var(--sky-3) 17%,
    var(--sky-4) 28%, var(--sky-5) 42%, var(--sky-6) 60%,
    var(--sky-7) 78%, var(--sky-8) 100%);
}

/* The last stars, in the top fifth only. Hand-placed radial gradients rather
   than generated elements — no JS, nothing to bind, nothing to re-bind. */
html::after {
  content: '';
  position: fixed; inset: 0 0 80% 0; z-index: -2; pointer-events: none;
  opacity: .55;
  background:
    radial-gradient(1.4px 1.4px at 12% 22%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 27% 8%,  #fff, transparent),
    radial-gradient(1.6px 1.6px at 41% 34%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 55% 14%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 68% 29%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 79% 11%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 89% 26%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 6%  40%, #fff, transparent),
    radial-gradient(1.4px 1.4px at 34% 47%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 62% 44%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 95% 41%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 19% 60%, #fff, transparent);
}

/* the sun, still below the horizon, blooming up from the bottom */
body::after {
  content: '';
  position: fixed; left: 50%; bottom: -30vh;
  width: 140vw; height: 85vh; transform: translateX(-50%);
  z-index: -1; pointer-events: none;
  background: radial-gradient(ellipse at 50% 100%,
    rgba(255,226,176,.95) 0%, rgba(255,196,132,.55) 30%, rgba(255,170,110,0) 64%);
}

html, body {
  background-color: transparent;
  font-family: var(--cult-body);
}

/* ── type ───────────────────────────────────────────────────────────
   Fredoka for anything a child reads as a heading; Nunito for the rest.
   Both are actually fetched now — see the <link> on every page. */
h1, h2, h3,
.sp-world-hero h1, .sp-activity__h, .sp-hero h1,
.sp-world__name, .sp-masthead__brand, .sp-reward {
  font-family: var(--cult-display);
  font-weight: 600;
  letter-spacing: .02em;
}

/* ── cards float on the sky ─────────────────────────────────────────
   The 3px peach border was the loudest thing on the page. A card sitting on
   a sky needs a soft edge and a real shadow, not an outline. */
/* Opaque, and deliberately NOT backdrop-filtered. A card at 94.5% opacity is
   already unreadable-through, so the blur bought nothing visible — while
   costing real GPU on the cheap tablets this age group actually uses, and
   compositing unpredictably. Contrast for an early reader beats a glass
   effect nobody can see. Translucency stays only where it is genuinely
   translucent: the masthead. */
.sp-world-hero, .sp-activity, .sp-grownup__body, .sp-footer, .sp-card {
  background: #FFFFFF;
  border: 1px solid rgba(214,196,222,.55);
}

/* ── the masthead becomes glass ─────────────────────────────────────
   It sits in the band of retreating night at the top, so it takes light
   text. The nav pills stay solid white with dark ink — a small child's tap
   target should never be translucent. */
.sp-masthead {
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.30);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 6px 24px rgba(20,10,40,.20);
}
.sp-masthead__brand,
.sp-masthead__brand a { color: #FFF3E2; text-shadow: 0 1px 6px rgba(0,0,0,.35); }
.sp-masthead__link {
  background: rgba(255,255,255,.90);
  color: #3A2A18;
  border: 1px solid rgba(255,255,255,.95);
}
.sp-masthead__link:hover { background: #fff; }

/* ── tiles keep their warmth, lose the hard edge ────────────────────
   Deliberately still cream rather than white: the tiles are what a child
   actually presses, and they should read as objects on the card. */
.sp-word, .sp-match__tile {
  border-color: rgba(196,150,105,.24);
  box-shadow: 0 3px 10px rgba(120,70,30,.10);
}
.sp-word:hover, .sp-match__tile:hover {
  box-shadow: 0 12px 24px rgba(120,70,30,.20);
}

/* the back button and listen buttons sit on sky, so they need a real lift */
.sp-back { background: rgba(255,255,255,.92); border: 1px solid rgba(255,255,255,.95); }

/* ── honest fallbacks ───────────────────────────────────────────────
   A browser with no backdrop-filter gets opaque cards rather than a smear. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  /* only the masthead is genuinely translucent, so it is the only thing that
     needs a fallback — without the blur it would be an unreadable smear */
  .sp-masthead { background: rgba(46,35,55,.55); }
}

@media (prefers-reduced-motion: reduce) {
  html::after { opacity: .4; }
}

/* ── content never waits on a script ────────────────────────────────
   [data-cult-anim] is authored at opacity 0 and only cult-anim.js reveals
   it. If that script never runs, every card is invisible forever. This
   makes the hidden state conditional on the script having announced
   itself, so the failure mode is 'no animation' rather than 'no page'. */
html:not(.cult-anim-on) [data-cult-anim] {
  opacity: 1 !important;
  transform: none !important;
}

/* ── the corner mascot, once a real avatar exists ────────────────────
   Drop a square PNG at assets/img/nyasia/nyasia-young.png and the drawn
   face is replaced by it automatically. Until then nothing changes. */
.cult-mascot.has-avatar {
  background-size: cover;
  /* the source is a square crop already centred on the face, so a square
     mascot needs no offset */
  background-position: center center;
  border-radius: 50%;
  border: 3px solid rgba(255,255,255,.9);
  box-shadow: 0 6px 18px rgba(40,20,60,.42);
}
.cult-mascot.has-avatar .cult-mascot__svg { display: none; }

/* ── Letters · the alphabet is a prerequisite, not a sampler ─────────
   26 tiles at the default 140px cell would be a wall a child has to
   scroll past. The alphabet gets small dense cells showing only the
   glyph; vowels and reading words get roomier cells and keep their
   labels, because the label is the teaching there. (2026-09-06) */
.sp-words--alpha { grid-template-columns: repeat(auto-fill, minmax(70px,1fr)); gap: 9px; }
.sp-words--alpha .sp-word { padding: 12px 4px; border-width: 2px; }
.sp-words--alpha .sp-word__icon { font-size: 32px; font-weight: 700; }
.sp-words--alpha .sp-word__label { display: none; }

.sp-words--vowel { grid-template-columns: repeat(auto-fill, minmax(104px,1fr)); gap: 10px; }
.sp-words--vowel .sp-word__icon { font-size: 30px; }
.sp-words--vowel .sp-word__label { font-size: 13px; }

.sp-words--read { grid-template-columns: repeat(auto-fill, minmax(104px,1fr)); gap: 10px; }
.sp-words--read .sp-word__icon { display: none; }
.sp-words--read .sp-word__label { font-size: 21px; font-weight: 800; }

.sp-activity__lvl { font-family: var(--cult-body); font-weight: 800; font-size: 10.5px;
  letter-spacing: .2em; text-transform: uppercase; color: #B0761E;
  margin: 22px 0 2px; }
