/* The shell every page after the home page wears: type, ground, weave canvas,
   nav, footer, marks. It lived inlined in seven files and drifted four times in
   one day - what-is-saga shipped without the weave, privacy/terms/make lost their
   full-width footer, /what/ missed the flex column. One file cannot drift from
   itself. (2026-08-10, after jscpd put the repo over its 3% duplication ceiling
   and was right to.) */

@font-face { font-family:'Nunito'; font-weight:400; font-display:swap;
  src:url('/assets/nunito-400.woff2') format('woff2'); }
@font-face { font-family:'Nunito'; font-weight:600; font-display:swap;
  src:url('/assets/nunito-600.woff2') format('woff2'); }
/* 700 was MISSING here while nunito-700.woff2 sat in the same directory and site.css
   declared it. Nothing errored: asked for 700 with only 600 and 800 present, the browser
   takes the heavier neighbour, so every bold on a shell page rendered ExtraBold. It shows
   up worst on the choice capsules, which are Nunito 22 BOLD in the app and were coming out
   a weight heavier than the phone - Saaim, 2026-08-26: "the boldness of the font... it has
   to be exactly the same". A missing face is a silent substitution, never a failure. */
@font-face { font-family:'Nunito'; font-weight:700; font-display:swap;
  src:url('/assets/nunito-700.woff2') format('woff2'); }
@font-face { font-family:'Nunito'; font-weight:800; font-display:swap;
  src:url('/assets/nunito-800.woff2') format('woff2'); }

:root { --red: #eb3e28; }
html { background: #0b0a09; overscroll-behavior-y: none; }
/* the marks END the page. On a page shorter than the screen they used to stop
   mid-window with bare ground below, so the bleed stopped reading as a bleed. */
body { margin: 0; background: #0b0a09; color: #fff; overscroll-behavior-y: none;
  min-height: 100vh; display: flex; flex-direction: column;
  font-family: 'Nunito', -apple-system, sans-serif; -webkit-font-smoothing: antialiased; }
a { color: inherit; }
#weave { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 0;
         display: block; pointer-events: none; }
/* border-box + width:100% because body is a flex column and margin:0 auto on a
   flex item shrink-wraps it, which once dragged the nav and footer into the
   reading column on three pages at once. */
.hm-page { position: relative; z-index: 1; max-width: 1880px; margin: 0 auto;
           padding: 0 clamp(14px, 3.2vw, 56px); flex: 1 0 auto;
           box-sizing: border-box; width: 100%; }

.hm-nav { --navh: 38px;
  display: flex; align-items: center; gap: 16px; padding: 30px 0 18px; }
.hm-wm { height: var(--navh); width: auto; display: block; }
.hm-icons { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.hm-nw { display: inline-flex; align-items: center; height: var(--navh);
  color: #fff; font-weight: 600; font-size: 14px; padding: 0 0.95rem;
  border-radius: 999px; background: rgba(255,255,255,.16); text-decoration: none;
  transition: background 0.15s ease, transform 0.12s ease; }
.hm-nw:hover { background: rgba(255,255,255,.28); transform: translateY(-1px); }
.hm-make { display: inline-flex; align-items: center; height: var(--navh);
  color: #fff; font-weight: 600; font-size: 14px; padding: 0 0.95rem;
  border-radius: 999px; background: var(--red); text-decoration: none;
  transition: filter 0.15s ease, transform 0.12s ease; }
.hm-make:hover { filter: brightness(1.12); transform: translateY(-1px); }
@media (max-width: 430px) {
  .hm-nav { gap: 10px; }
  .hm-icons { gap: 7px; }
  .hm-nw, .hm-make { padding: 0 0.55rem; }
}
@media (max-width: 380px) {
  .hm-nav { --navh: 34px; }
  .hm-nw, .hm-make { font-size: 13px; padding: 0 0.5rem; }
}

/* footer, matching home */
.hm-foot { margin-top: 56px; padding: 0 0 8px; border-top: 0; }
.hm-fcols { display: flex; flex-wrap: wrap; gap: 10px 26px; padding: 26px 0 30px;
  border-top: 1px solid rgba(255,255,255,.08); }
.hm-fcols a { font-size: 13px; font-weight: 600;
  color: rgba(255,255,255,.55); text-decoration: none; }
.hm-fcols a:hover { color: #fff; }
.hm-frule { font-size: 12.5px; color: rgba(255,255,255,.88); }
.hm-frule span, .hm-foot span { color: rgba(255,255,255,.88); }
.hm-flockwrap { position: relative; z-index: 1; overflow: hidden; margin-top: 30px;
  flex: none; }
.hm-flock { display: flex; align-items: flex-end; justify-content: center; gap: 36px;
  margin-bottom: -74px; color: rgba(255,255,255,.12); pointer-events: none; }
.hm-fblob { width: clamp(140px, 18vw, 252px); height: auto; }
.hm-fword { width: clamp(380px, 56vw, 762px); height: auto; }
@media (max-width: 600px) {
  .hm-fcols { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
    gap: 13px 18px; }
}
@media (max-width: 900px) { .hm-flock { margin-bottom: -37px; } }
/* MUST sit after the 900px rule: equal specificity, so source order decides. */
@media (max-width: 500px) { .hm-flock { margin-bottom: -24px; } }

@media (prefers-reduced-motion: reduce) {
  .hm-nw, .hm-make { transition: none; }
}


/* ---- THE SPINNER (Saaim, 2026-08-29) ---------------------------------------------
   It used to say "loading…" in text. Two things wrong with that, and he named both:
   it is ugly, and a product does not narrate its own machinery to you.

   THE DELAY IS THE WHOLE DESIGN. A spinner that appears the instant a page starts
   loading is WORSE than no spinner: on a fast load it flashes for 150ms and reads as
   jank, which is exactly the flicker he screenshotted. So this is invisible for its
   first 400ms. A load that finishes inside that window shows nothing at all - the
   content simply appears, which is what he described wanting: "it feels normal, like
   oh it's just appearing". Only a genuinely slow load ever reveals it, which is when
   a person actually wants to be told something is happening.

   Two animations doing two jobs: `sg-reveal` holds it at zero opacity and then fades
   it in once, `sg-turn` rotates forever. The element is usually removed before the
   first one has finished waiting. */
.sg-load {
  /* CENTRED IN THE SCREEN, which is what was asked for - not centred in whatever box
     happens to contain it. The first version was `min-height: 42vh` inside the content
     column, so the ring inherited its container's width and offset: measured at 414px it
     sat 178px left and 173px above the middle of the viewport, and on desktop 315px left.
     A ring that is nearly a third of the screen off-centre reads as a stray dot.
     Fixed to the viewport is immune to whatever container the screen puts it in, which is
     the whole reason the first one drifted. pointer-events stay off so it never eats a tap. */
  position: fixed;
  inset: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  z-index: 2;
}
.sg-load::after {
  content: ""; display: block;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2.5px solid rgba(255, 255, 255, .13);
  border-top-color: var(--red);
  opacity: 0;
  animation: sg-reveal .18s ease 400ms forwards, sg-turn .7s linear infinite;
}
@keyframes sg-turn { to { transform: rotate(360deg); } }
@keyframes sg-reveal { to { opacity: 1; } }

/* Reduced motion gets a still ring rather than a spin - the point is "something is
   happening", and a person who asked for less movement should still be told that. */
@media (prefers-reduced-motion: reduce) {
  .sg-load::after {
    animation: sg-reveal .18s ease 400ms forwards;
    border-top-color: var(--red);
  }
}