/* The living Orbilla: one character, drawn one way, for any page. Tokens only; every class starts with orbi-.
   Load after site.css (which draws the eyes: .eye, .eye.l, .eye.r and the blink), with orbi.js for gaze and reactions.

   <div class="orbi" role="img" aria-label="Orbilla, ...">
     <span class="orbi-shadow"></span>
     <span class="orbi-float">
       <span class="orbi-bodies"><img class="orbi-body orbi-on" src="/assets/orbi/lavender.webp" alt="" width="768" height="768"></span>
       <i class="eye l"></i><i class="eye r"></i>
     </span>
   </div>

   Bodies are Zen Timer's own faceless square renders in /assets/orbi/ (768 px; the rings pass side by side below the eyes). The eyes, the glow, the sleeping face and the
   wardrobe's places and layers follow the app (Zen Timer 3.2 build 46; app-incoming/zen-timer/one-orbilla-differences.md). Without orbi.js the character is complete and still floats and blinks; with Reduce Motion it holds still. */

.orbi { position: relative; display: block; width: 100%; aspect-ratio: 1; --orbi-gx: 0; --orbi-gy: 0; -webkit-tap-highlight-color: transparent; }

/* The light Orbilla stands in, as in the app: a soft glow in its rank's colour behind the body, and a faint shadow under it that tightens as Orbilla rises. */
.orbi { --orbi-glow: 178, 161, 245; }
.orbi[data-orbi="mint"] { --orbi-glow: 115, 217, 168; }
.orbi[data-orbi="sky"] { --orbi-glow: 115, 184, 242; }
.orbi[data-orbi="rose"] { --orbi-glow: 245, 133, 158; }
.orbi[data-orbi="gold"] { --orbi-glow: 250, 199, 82; }
.orbi[data-orbi="ruby"] { --orbi-glow: 219, 51, 66; }
.orbi[data-orbi="sapphire"] { --orbi-glow: 51, 77, 191; }
.orbi[data-orbi="aurora"] { --orbi-glow: 204, 115, 242; }
.orbi[data-orbi="sage"] { --orbi-glow: 150, 182, 160; }
.orbi::before { content: ""; position: absolute; inset: -35%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, rgba(var(--orbi-glow), .45) 25%, rgba(var(--orbi-glow), 0) 94%); }
.orbi-mini::before { display: none; }
.orbi-shadow { position: absolute; left: 22%; right: 22%; top: 86%; height: 8%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, rgba(var(--shade), .22), rgba(var(--shade), .08) 55%, rgba(var(--shade), 0));
  animation: orbi-shadow 14s var(--ease-breathe) infinite alternate; }
.orbi-float { position: absolute; inset: 0; display: block; isolation: isolate; animation: orbi-float 14s var(--ease-breathe) infinite alternate; }
@keyframes orbi-float { from { translate: 0 .7%; } to { translate: 0 -1.1%; } }   /* breathing, not bobbing (owner, October 10, 2026) */
@keyframes orbi-shadow { from { scale: 1.04 1; opacity: 1; } to { scale: .9 .9; opacity: .72; } }

/* Colours cross-fade: the new body fades in over the last one, which stays opaque underneath. */
.orbi-bodies { position: absolute; inset: 0; display: block; z-index: 1; }
.orbi-body { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; }
.orbi-body.orbi-was { opacity: 1; }
.orbi-body.orbi-on { opacity: 1; z-index: 1; transition: opacity .7s var(--ease); }

/* Eyes: site.css draws them; here they look where --orbi-gx and --orbi-gy (-1 to 1) point. */
.orbi .eye { z-index: 6; translate: calc(var(--orbi-gx) * 115%) calc(var(--orbi-gy) * 55%); transition: translate .16s var(--ease), scale .5s var(--ease), opacity .25s var(--ease); }
.orbi.orbi-idle .eye { transition: translate .9s var(--ease), scale .5s var(--ease), opacity .25s var(--ease); }
.orbi-b2 .eye { animation-delay: 1.7s; }
.orbi-b3 .eye { animation-delay: 3.1s; }
.orbi-b4 .eye { animation-delay: 4.3s; }

/* Asleep: the eyes close slowly, two flat lids take their place, and a small "z" rises beside the head (as in the app). */
.orbi .orbi-lid { top: 47%; width: 8.4%; height: 2%; margin-left: -.95%; background: rgba(0, 0, 0, .55); opacity: 0; animation: none; translate: 0 0; }
.orbi .orbi-lid::after { display: none; }
.orbi-z { position: absolute; left: 82%; top: 6%; width: 10%; z-index: 9; fill: rgba(0, 0, 0, .55); opacity: 0; pointer-events: none; }
.orbi-asleep .orbi-z { opacity: .9; transition: opacity .45s var(--ease) 1.15s; animation: orbi-z 6s var(--ease-breathe) infinite alternate; }
@keyframes orbi-z { from { translate: 0 6%; } to { translate: 0 -6%; } }
.orbi-asleep .eye:not(.orbi-lid) { animation: none; scale: 1 .06; opacity: 0; translate: 0 22%; transition: scale 1.5s cubic-bezier(.5, 0, .3, 1), translate 1.5s var(--ease), opacity .35s var(--ease) 1.2s; }
.orbi-asleep .orbi-lid { opacity: 1; transition: opacity .45s var(--ease) 1.15s; }

/* Things it wears, stacked back to front as Zen Timer draws them (ZenWardrobeFit, R011): headphones and earmuffs behind
   the body; scarf tails and the lights; feet; the medal; face; the eyes; head; neck; held; the near side of the rings;
   then the pin, the bow tie and the beads, which sit in front of the ring. Each piece waits just out of
   place until worn, then settles. The pictures are Zen Timer's own, in /assets/orbi/wardrobe-<id>.webp, and each
   is fitted to the ball by the generated rule below (tools/wardrobe_fit.py). */
.orbi-wear { position: absolute; height: auto; opacity: 0; pointer-events: none; transition: opacity .2s var(--ease), translate .5s var(--ease), scale .5s var(--ease); }   /* settles, never overshoots (section 6b) */
.orbi-s-feet { z-index: 3; translate: 0 18%; }
.orbi-s-face { z-index: 5; scale: 1.25; }
.orbi-s-head { z-index: 7; translate: 0 -24%; }
.orbi-s-neck { z-index: 8; translate: 0 14%; }
.orbi-s-held { z-index: 9; translate: 14% 0; }
.orbi-s-clip { z-index: 11; scale: .3; }
.orbi-s-ring { z-index: 7; translate: 14% -18%; }
.orbi-w-headphones, .orbi-w-winter-earmuffs { z-index: 0; }
.orbi-w-scarf, .orbi-w-bookmark-scarf, .orbi-w-autumn-scarf, .orbi-w-winter-scarf, .orbi-w-fairy-lights-wrap { z-index: 2; }
.orbi-w-gold-medal { z-index: 4; }
.orbi-w-bowtie, .orbi-w-mala-beads { z-index: 11; }
/* The near side of the rings, over everything worn at the neck and below (orbi.js adds it on the first wear). */
.orbi-ringfront { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 10; pointer-events: none;
  -webkit-mask: url(/assets/orbi/ringfront.webp) center / 100% 100% no-repeat; mask: url(/assets/orbi/ringfront.webp) center / 100% 100% no-repeat; }
.orbi-wear.orbi-worn { opacity: 1; translate: 0 0; scale: 1; }
/* The sleep mask covers the eyes; the visor lets them show through faintly, as in the app. */
.orbi-w-sleep-mask { z-index: 7; }
.orbi:has(.orbi-w-visor.orbi-worn) .eye { opacity: .6; }
.orbi:has(.orbi-w-sleep-mask.orbi-worn) .eye { opacity: 0; }
/* wardrobe-fit: generated by tools/wardrobe_fit.py from Zen Timer's fit table. Do not edit by hand. */
.orbi-w-sprout { left: 36.10%; top: 1.76%; width: 27.59%; }
.orbi-w-crown { left: 31.50%; top: 8.75%; width: 36.79%; }
.orbi-w-flowers { left: 21.65%; top: 11.82%; width: 56.50%; }
.orbi-w-beanie { left: 24.28%; top: -20.38%; width: 51.25%; }
.orbi-w-gradcap { left: 26.90%; top: -10.15%; width: 48.62%; rotate: -6deg; }
.orbi-w-beret { left: 22.96%; top: -0.13%; width: 48.62%; rotate: -10deg; }
.orbi-w-lotus-crown { left: 26.90%; top: -1.45%; width: 45.99%; }
.orbi-w-flower-crown-spring { left: 22.31%; top: -1.90%; width: 55.19%; }
.orbi-w-sweatband { left: 26.90%; top: 3.74%; width: 45.99%; }
.orbi-w-headphones { left: 3.91%; top: -12.67%; width: 91.98%; }
.orbi-w-winter-earmuffs { left: 7.19%; top: -5.27%; width: 85.41%; }
.orbi-w-glasses { left: 32.23%; top: 41.34%; width: 35.35%; }
.orbi-w-heart-glasses { left: 33.38%; top: 38.27%; width: 44.61%; }
.orbi-w-reading-specs { left: 31.87%; top: 40.52%; width: 37.25%; }
.orbi-w-visor { left: 26.25%; top: 28.51%; width: 47.30%; }
.orbi-w-sleep-mask { left: 27.56%; top: 32.47%; width: 44.68%; }
.orbi-w-scarf { left: 41.36%; top: 66.99%; width: 32.85%; rotate: -8deg; }
.orbi-w-bookmark-scarf { left: 31.50%; top: 66.98%; width: 39.42%; rotate: -4deg; }
.orbi-w-autumn-scarf { left: 32.82%; top: 66.99%; width: 36.79%; rotate: -4deg; }
.orbi-w-winter-scarf { left: 30.85%; top: 67.00%; width: 40.73%; rotate: -4deg; }
.orbi-w-mala-beads { left: 18.69%; top: 18.62%; width: 62.41%; clip-path: inset(44.6% 0 0 0); }
.orbi-w-bowtie { left: 29.53%; top: 55.77%; width: 40.73%; }
.orbi-w-fairy-lights-wrap { left: 30.19%; top: 66.96%; width: 39.42%; }
.orbi-w-gold-medal { left: 42.02%; top: 61.70%; width: 15.77%; }
.orbi-w-pencil { left: 76.18%; top: 45.97%; width: 15.77%; rotate: 18deg; }
.orbi-w-quill { left: 79.47%; top: 49.46%; width: 22.34%; rotate: 10deg; }
.orbi-w-reading-lamp { left: 75.52%; top: 46.11%; width: 22.34%; }
.orbi-w-dumbbell { left: 71.58%; top: 67.13%; width: 27.59%; rotate: -12deg; }
.orbi-w-tea-cup { left: 72.24%; top: 62.99%; width: 27.59%; }
.orbi-w-diya { left: 72.89%; top: 61.93%; width: 24.97%; }
.orbi-w-umbrella { left: 64.35%; top: -12.44%; width: 55.19%; rotate: 14deg; }
.orbi-w-boxing-gloves { left: 72.24%; top: 58.74%; width: 27.59%; rotate: -8deg; }
.orbi-w-rain-boots { left: 34.79%; top: 81.46%; width: 30.22%; }
.orbi-w-running-shoes { left: 31.50%; top: 81.40%; width: 36.79%; }
.orbi-w-star { left: 64.35%; top: 24.67%; width: 15.77%; rotate: -15deg; }
.orbi-w-starter-ribbon { left: 19.02%; top: 21.17%; width: 17.08%; rotate: 12deg; }
/* /wardrobe-fit */
/* Orbilla the Organizer: brass reading glasses round the eyes, a document clipped to the ring. */
.orbi-w-brass { left: 29%; top: 37.9%; width: 42%; }
.orbi-w-document { left: 67%; top: 20%; width: 23%; rotate: 4deg; }

/* A small still Orbilla for rows and controls: no shadow, no float. */
.orbi-mini .eye { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .orbi-float, .orbi-shadow, .orbi .eye, .orbi-asleep .orbi-z { animation: none; }
  .orbi .eye, .orbi-body.orbi-on, .orbi-wear, .orbi-asleep .eye:not(.orbi-lid), .orbi-asleep .orbi-lid { transition: none; }
  .orbi .eye:not(.orbi-lid) { translate: 0 0; }
}
