/* ExactSky — zi-motifs: graphical motif kit (2026-08).
   Companion to app.css. Everything reads the existing celestial-atlas tokens
   (--accent, --ink, --muted, --line, --font-display) so both schemes work with
   no extra rules. All classes are namespaced .zim-* — nothing here collides with
   the app.css / admin class contracts.

   FONTS: the trilingual motifs (astrolabe, frieze, watermark) set script fonts via
   the three --zim-font-* tokens below. Devanagari and the sigils use fonts already on
   the visitor's OS (Devanagari MT / Apple Symbols and their Windows peers). The Chinese
   glyphs use a SELF-HOSTED subset of Ma Shan Zheng (brush calligraphy, SIL OFL 1.1 —
   licence beside the file in /static/fonts/mashanzheng/): the 27 glyphs the kit draws
   (ten stems, twelve branches, five elements; the frieze set lies inside those), 9 KB,
   a one-off fonttools build (recipe: docs/zir_v1_motifs_results.md). No Google Fonts
   request — the site makes no third-party requests. The Kai faces remain the fallback
   (per-glyph, so anything outside the subset still renders). */

@font-face {
  font-family: "Ma Shan Zheng";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/mashanzheng/MaShanZheng-Regular.zi-subset.woff2") format("woff2");
  unicode-range: U+4E01, U+4E11, U+4E19, U+4E59, U+4EA5, U+5348, U+536F, U+571F, U+58EC, U+5B50, U+5BC5, U+5DF1, U+5DF3, U+5E9A, U+620A, U+620C, U+6728, U+672A, U+6C34, U+706B, U+7532, U+7533, U+7678, U+8F9B, U+8FB0, U+9149, U+91D1;
}

:root {
  --zim-font-zh: "Ma Shan Zheng", "Kaiti SC", "KaiTi", "STKaiti", "DFKai-SB", "BiauKai", serif;
  --zim-font-dev: "Devanagari MT", "Nirmala UI", "Noto Serif Devanagari", serif;
  --zim-font-sym: "Apple Symbols", "Segoe UI Symbol", "Noto Sans Symbols", serif;
}

/* ---------- 01 + 02 · Astrolabe (data-zim="astrolabe") ---------- */

.zim-astro { display: block; }
@keyframes zim-spin { to { transform: rotate(360deg); } }
.zim-astro .zim-ring { transform-origin: 140px 140px; }
.zim-astro .zim-ring-outer { animation: zim-spin 90s linear infinite; }
.zim-astro .zim-ring-mid   { animation: zim-spin 60s linear infinite reverse; }
.zim-astro .zim-ring-inner { animation: zim-spin 40s linear infinite; }
/* Stems ring: twice the branch speed (20s vs 40s), so the difference is plain
   and the 甲子 markers reunite at 12 o'clock every 40s exactly. */
.zim-astro .zim-ring-stems { animation: zim-spin 20s linear infinite; }
/* data-rate="real": each ring keeps its tradition's own clock, compressed to
   one day per second — Sun's tropical year (Western), Moon's sidereal month
   (Vedic / nakshatra cycle), Jupiter's orbit (BaZi; the earthly branches began
   as stations of the Year Star). Uniform direction, as the sky moves. */
.zim-astro[data-rate="real"] .zim-ring-outer { animation: zim-spin 365.24s linear infinite reverse; }
.zim-astro[data-rate="real"] .zim-ring-mid   { animation: zim-spin 27.32s  linear infinite reverse; }
.zim-astro[data-rate="real"] .zim-ring-inner { animation: zim-spin 4332.6s linear infinite reverse; }
/* Real mode: stems turn in ten civil years; branches follow true Jupiter
   (11.86y, not 12), so the pair drifts slowly out of register — the same
   slippage that led the old astronomers to invent the counter-Jupiter. */
.zim-astro[data-rate="real"] .zim-ring-stems { animation: zim-spin 3652.4s linear infinite reverse; }
.zim-astro .zim-rg-w, .zim-astro .zim-rg-v, .zim-astro .zim-rg-c { transition: opacity 0.35s ease; }
.zim-astro.zim-hl-w .zim-rg-v, .zim-astro.zim-hl-w .zim-rg-c,
.zim-astro.zim-hl-v .zim-rg-w, .zim-astro.zim-hl-v .zim-rg-c,
.zim-astro.zim-hl-c .zim-rg-w, .zim-astro.zim-hl-c .zim-rg-v { opacity: 0.16; }
.zim-astro-label {
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 0.85em;
  color: var(--muted);
  min-height: 1.4em;
  margin: 0.9em 0 0;
}

/* ---------- 03 · Constellation backdrop (data-zim="constellations") ---------- */

.zim-const-host { position: relative; overflow: hidden; }
.zim-const-host > :not(canvas) { position: relative; z-index: 2; }
.zim-const {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
}

/* ---------- 03b · Starfield backdrop (data-zim="starfield") ---------- */
/* A drifting, twinkling sky fixed behind the whole page (owner 2026-10-20; zi-motifs.js
   buildStarfield). It stands in for app.css's static body::before stars while it shows. Dark theme
   only (owner 2026-10-20): the light theme hides it and sets its scale to 0, which also stops the
   script drawing, by the same three-state pattern as app.css's tokens. */

:root { --zim-star-scale: 1; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) { --zim-star-scale: 0; }
  :root:not([data-theme="dark"]) .zim-starfield { display: none; }
}
:root[data-theme="light"] { --zim-star-scale: 0; }
:root[data-theme="light"] .zim-starfield { display: none; }

.zim-starfield {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.zim-starfield canvas { display: block; width: 100%; height: 100%; }
html.zim-starfield-on body::before { display: none; }

/* ---------- 04 · Self-drawing chart wheel (data-zim="wheel") ---------- */

.zim-wheel { display: block; width: min(320px, 82vw); height: auto; margin: 0 auto; }
.zim-wheel .zim-dr { transition: stroke-dashoffset 1s ease; }
.zim-wheel .zim-fd { opacity: 0; transition: opacity 0.5s ease; }
.zim-wheel .zim-pp {
  opacity: 0;
  transform: scale(0.4);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.2, 0.8, 0.3, 1.2);
}
.zim-wheel.zim-play .zim-fd { opacity: 1; }
.zim-wheel.zim-play .zim-pp { opacity: 1; transform: scale(1); }
.zim-wheel.zim-noanim * { transition: none !important; }
.zim-replay {
  display: inline-block;
  font: 600 0.8em/1 var(--font-ui);
  letter-spacing: 0.03em;
  color: var(--accent);
  background: none;
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 0.55em 1.3em;
  cursor: pointer;
}
.zim-replay:hover { background: var(--accent-soft); }
.zim-replay:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- 05 · Trilingual frieze (data-zim="frieze") ---------- */

.zim-frieze { position: relative; height: 46px; overflow: hidden; }
.zim-frieze-track {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-flex;
  align-items: center;
  height: 46px;
  white-space: nowrap;
  animation: zim-drift 44s linear infinite;
}
@keyframes zim-drift { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.zim-fz { display: inline-block; line-height: 1; padding: 0 17px; color: var(--accent); }
.zim-fz-w { font-family: var(--zim-font-sym); font-size: 19px; }
.zim-fz-v { font-family: var(--zim-font-dev); font-size: 15px; font-weight: 500; }
.zim-fz-c { font-family: var(--zim-font-zh); font-size: 24px; }
.zim-fz-dot { font-size: 8px; opacity: 0.45; padding: 0 2px; }

/* ---------- 06 · Glyph watermark (plain HTML + CSS, no JS) ---------- */

.zim-wm-host { position: relative; overflow: hidden; }
.zim-wm-host > :not(.zim-wm) { position: relative; z-index: 2; }
.zim-wm { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.zim-wm span { position: absolute; color: var(--accent); line-height: 1; }
.zim-wm .zim-wm-zh  { font-family: var(--zim-font-zh); }
.zim-wm .zim-wm-dev { font-family: var(--zim-font-dev); }
.zim-wm .zim-wm-sym { font-family: var(--zim-font-sym); }

/* ---------- 07 · Step marks ---------- */
/* The .participate list already draws its numbered badges; the marks in
   snippets.html are small inline SVGs sized to drop into whatever badge
   element app.css renders. Only a helper for vertical centering: */

.zim-mark { display: inline-flex; align-items: center; justify-content: center; }

/* ---------- 08 · Live sky line (data-zim="sunsign" fills the span) ---------- */

.zim-skyline {
  display: flex;
  align-items: center;
  font: 600 0.7em/1.4 var(--font-ui);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.zim-skyline .zim-pulse {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  margin-right: 8px;
  animation: zim-pulse 2.4s ease-in-out infinite;
}
@keyframes zim-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1); }
}

/* ---------- 09 · Sun/moon theme toggle (zi-theme-toggle.js) ---------- */

.zim-toggle .zim-tg-box {
  position: relative;
  display: inline-block;
  width: 20px;
  height: 20px;
  vertical-align: middle;
}
.zim-toggle .zim-tg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  transition: transform 0.55s cubic-bezier(0.3, 0.7, 0.3, 1), opacity 0.35s ease;
}
/* Icon shows what you'll switch TO (matches the original toggle's semantics):
   dark scheme shows the sun, light scheme shows the moon. */
.zim-toggle .zim-tg-sun  { transform: rotate(90deg) scale(0.5); opacity: 0; }
.zim-toggle .zim-tg-moon { transform: rotate(0deg) scale(1); opacity: 1; }
.zim-toggle.zim-is-dark .zim-tg-sun  { transform: rotate(0deg) scale(1); opacity: 1; }
.zim-toggle.zim-is-dark .zim-tg-moon { transform: rotate(-120deg) scale(0.5); opacity: 0; }

/* Radial scheme wash (View Transitions API; inert elsewhere).
   zi-theme-toggle.js animates a growing circle clip on the new snapshot,
   so the incoming scheme radiates out from the toggle button. */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}
::view-transition-old(root) { z-index: 1; }
::view-transition-new(root) { z-index: 2; }

/* ---------- Motion preferences ---------- */

@media (prefers-reduced-motion: reduce) {
  .zim-astro .zim-ring, .zim-frieze-track, .zim-skyline .zim-pulse { animation: none !important; }
  .zim-wheel .zim-dr, .zim-wheel .zim-fd, .zim-wheel .zim-pp { transition: none !important; }
  .zim-toggle .zim-tg { transition: none !important; }
}
