/* terranimus-loader kit. Do not hand-edit.
   Source: Meet desktop/ui/loader.css @ ed3f9e9424997401ce5940998303d961459dabc0
   The block below is that file, unchanged. */
/* VENDORED FILE - do not hand-edit.
   Canonical source: terranimus.com, public/brand/loader.css (branch feat/hex-logo when vendored, 2026-09-30).
   Canonical SHA-256 of everything below this comment, LF line endings:
   6462d2f587bb94451807a3790f0864bc8613117e7d5e054c44f1b555405a0d50
   test/brand-loader.test.mjs recomputes the checksum and fails when the body drifts from it. To update,
   copy the new canonical file below this comment, then replace the checksum here and in that test.
   Users: components/loader/LoaderScreen.vue (full screen), components/loader/LoaderMark.vue (the mark
   alone, sized by its container), public/whiteboard-editor/index.html (inline copy of the same rules). */
/* Terranimus loading screen (canonical, generated by gen.mjs - regenerate, do not hand-edit copies).
   The compass-and-hexagon mark draws itself, the clay hexagon pulses, and the wordmark's two roots
   slide together onto their shared A. From Meet 11c9e5b whiteboard-editor/index.html; changes:
   the inner ring is a hexagon frame (R 26) and the seed a solid clay hexagon (R 13); the seed's intro
   and pulse sit on two elements (.seedIn / .seed) so the pulse stays composited while the app boots;
   gePulse has explicit 0%/100% keyframes; .geWord .r cancels the trailing letter-spacing (centring);
   the two inline style="" attributes became classes (.ring2, .geNoscript).
   Wordmark colours (2026-09-30; edited here by hand - the design-side gen.mjs needs the same change before
   it is next run): the site's own wordmark (Wordmark.astro). TERR and the left half of the shared A are
   --clay-ink (--w), the right half of the A and NIMUS are --ink (--t). The A stays ONE glyph, painted half and
   half, so it still animates as one letter. It drops its own trailing letter-spacing and takes it back as
   margin (.34em = .42em - .08em): its box is then the glyph, the split lands on the middle of the letter, and
   nothing moves.
   Colours: the host's brand tokens (--clay, --clay-ink, --ink, --paper-deep, else --paper) win; the literals
   are the no-theme fallbacks. #geStatus stays (empty): the whiteboard's js/bootstrap.js writes its
   load-failure text into it. Clear the screen by removing #geInfo. */
.geBlock {
	position: fixed; inset: 0;
	display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 34px;
	background: var(--paper-deep, var(--paper, #1c1815));
	--c: var(--clay, #d0673a);
	--t: var(--ink, #f1e9de);
	--w: var(--clay-ink, #ffae85);
	font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	overflow: hidden;
}
.geBlock::before { /* soft breathing glow behind the mark */
	content: ""; position: absolute; width: 46vmin; height: 46vmin; border-radius: 50%;
	background: radial-gradient(closest-side, color-mix(in oklab, var(--c) 30%, transparent), transparent);
	animation: geGlow 3.2s ease-in-out infinite;
}
.geMark { position: relative; width: min(30vmin, 168px); height: auto; overflow: visible; }
.geMark * { fill: none; stroke: var(--c); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.geMark .draw { stroke-dasharray: 1; stroke-dashoffset: 1; animation: geDraw 1.6s cubic-bezier(.6,0,.2,1) forwards; }
.geMark .ring2 { stroke-width: 1.5; opacity: 0.6; animation-delay: .25s; }
.geMark .rays { transform-origin: 60px 60px; animation: geDraw 1.2s .5s cubic-bezier(.6,0,.2,1) forwards, geSpin 14s 1.7s linear infinite; }
.geMark .seedIn { transform-origin: 60px 60px; opacity: 0; animation: geSeedIn .6s 1.2s ease-out forwards; }
.geMark .seed { fill: var(--c); stroke: none; transform-origin: 60px 60px; animation: gePulse 1.8s 1.8s ease-in-out infinite; }
.geWord { position: relative; display: flex; align-items: baseline; font: 500 clamp(18px, 3.4vmin, 26px)/1 Georgia, "Times New Roman", serif; letter-spacing: .42em; color: var(--t); }
.geWord span { display: inline-block; opacity: 0; }
.geWord .l { color: var(--w); text-align: right; animation: geFromL 1.1s .9s cubic-bezier(.2,.7,.2,1) forwards; }
.geWord .r { margin-right: -.42em; animation: geFromR 1.1s .9s cubic-bezier(.2,.7,.2,1) forwards; }
.geWord .a { color: var(--w); letter-spacing: 0; margin: 0 .34em 0 -.08em; animation: geA .8s 1.5s ease-out forwards; }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.geWord .a { color: transparent; background: linear-gradient(90deg, var(--w) 50%, var(--t) 50%); -webkit-background-clip: text; background-clip: text; }
}
#geStatus { position: absolute; bottom: 12vh; margin: 0; font-size: 14px; color: var(--t); opacity: .8; text-align: center; padding: 0 24px; }
.geNoscript { position: relative; color: var(--t); }
@keyframes geDraw { to { stroke-dashoffset: 0; } }
@keyframes geSeedIn { from { opacity: 0; transform: scale(.2); } to { opacity: 1; transform: scale(1); } }
@keyframes gePulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.14); opacity: .8; } }
@keyframes geSpin { to { transform: rotate(360deg); } }
@keyframes geGlow { 50% { transform: scale(1.18); opacity: .6; } }
@keyframes geFromL { from { opacity: 0; transform: translateX(-46px); } to { opacity: 1; transform: none; } }
@keyframes geFromR { from { opacity: 0; transform: translateX(46px); } to { opacity: 1; transform: none; } }
@keyframes geA { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: none; } }
@media (forced-colors: active) {
	.geWord .a { background: none; color: inherit; }
}
@media (prefers-reduced-motion: reduce) {
	.geBlock *, .geBlock::before { animation-duration: .01s !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; }
}
