/* MAGICDUEL - THE LOOK OF THE HEAT ORBS (2026-10-26; the rule and the library are core/Heat/OrbLook.php,
 * the window's half js/md_orblook.js). The heat orbs of the Erolin Device (templates/layout-* /erolinDevice.php)
 * take the look of the companion the player holds: a shape, a colour worked into a glow gradient, a blur,
 * a reach, and up to four effects, every one a word of the library with a strength (0..1 here) and a speed.
 *
 * HOW AN ORB IS BUILT. The slot (.erolin_slot, the 20px box jQuery moves and clicks) keeps its box-shadow
 * glow, now in the look's colours, and carries children the JS builds once:
 *     .ob          the body: sized by --orb-size, blurred by --orb-blur, and the carrier of the body
 *                  effects that each own ONE property: pulse (scale), jitter (translate), spin (rotate),
 *                  flicker (opacity)
 *       .obs       the shape (background or clip-path), overflow hidden; hum (translate) and wobble
 *                  (transform) live here so they never fight the body's; ::before is the shimmer sweep,
 *                  ::after the swirl
 *     .ofx-<name>  one layer per effect that throws something off (rings, sparks, mist, drip, bolt,
 *                  motes, orbit); its ::before and ::after are the two things thrown
 * Every amplitude is a variable on the box (#erolinDevice_orbs): --fx-<name> 0..1, --fx-<name>-d the
 * period; an effect is switched on by the class orb-fx-<name> on the box, which sets its animation name
 * (a missing variable reads as none, so an unused effect costs nothing). The keyframes read the variables
 * at the animated element, so one keyframe block serves every strength. --seed (0..1, set once per slot)
 * desyncs the orbs. The colours: --orb-core / -mid / -halo / -rim / -accent as hex for the gradients and
 * the same as "r g b" triplets (--orb-*-rgb) wherever an alpha is needed, so no color-mix() is required.
 * --orb-m is the MOOD (1 happy, .25 sad, .3 with the companion), the old jQuery box-shadow animations,
 * now a box-shadow transition that follows the variable.
 *
 * Phones (640px and under) keep the plain sun: the companion never shows there and the orbs there have
 * no glow (each skin's layout.css.php). prefers-reduced-motion stops every animation and keeps the colours.
 * The old browser fallback: a box-shadow in the orange of before stands first, so a browser that cannot
 * read the variable shadow keeps the sun's glow. */

#erolinDevice_orbs {
	--orb-core: #fff4c2; --orb-mid: #ffc20a; --orb-halo: #ffad1c; --orb-rim: #b36b00; --orb-accent: #ffe08a;
	--orb-core-rgb: 255 244 194; --orb-mid-rgb: 255 194 10; --orb-halo-rgb: 255 173 28; --orb-accent-rgb: 255 224 138;
	--orb-m: 1; --orb-g: 1; --orb-blur: 0; --orb-size: 1;
}

/* ---------------------------------------------------------------- the slot: the glow in the look's colours */
#erolinDevice_orbs.orb-look .erolin_slot_on {
	background-image: none;
	animation: none; /* the sun's own spin moved to the body (.ob), so a drop or a shard never turns with the slot */
	box-shadow: 0 0 51px 32px rgba(255, 173, 28, 0.8), inset 0 2px 18px 8px rgba(255, 194, 10, 1);
	box-shadow: 0 0 calc(51px * var(--orb-m) * var(--orb-g)) calc(32px * var(--orb-m) * var(--orb-g)) rgb(var(--orb-halo-rgb) / calc(.8 * var(--orb-m)));
	/* an outer shadow never paints under its own box: without this disc a hollow shape (ring, mote, spark) showed the
	   dark ground through a hole the size of the slot; the disc is the halo at the shadow's own strength, so it is seamless */
	background-color: rgb(var(--orb-halo-rgb) / calc(.8 * var(--orb-m) * min(1, var(--orb-g))));
	transition: box-shadow 5s ease-out, background-color 5s ease-out;
}
/* the sun keeps its hot centre, the inset glow of before; any other shape would be drawn over a filled disc */
#erolinDevice_orbs.orb-look.orb-shape-sun .erolin_slot_on {
	box-shadow:
		0 0 calc(51px * var(--orb-m) * var(--orb-g)) calc(32px * var(--orb-m) * var(--orb-g)) rgb(var(--orb-halo-rgb) / calc(.8 * var(--orb-m))),
		inset 0 2px calc(18px * var(--orb-m)) calc(8px * var(--orb-m)) rgb(var(--orb-mid-rgb) / var(--orb-m));
}
#erolinDevice_orbs.orb-look .erolin_slot.erolin_orbit { --orb-m: .3; } /* with the companion: a modest glow, 28 of the happy 51px were one blob */
#erolinDevice_orbs.orb-look .erolin_slot_off .ob,
#erolinDevice_orbs.orb-look .erolin_slot_off .ofx { display: none; } /* an empty slot is the grey star, as it was */

/* ---------------------------------------------------------------- the body and the shape */
#erolinDevice_orbs.orb-look .ob {
	position: absolute;
	inset: calc(50% - 50% * var(--orb-size));
	pointer-events: none;
	filter: blur(calc(var(--orb-blur) * 4px));
	animation-name: var(--an-pulse, none), var(--an-flicker, none), var(--an-jitter, none), var(--an-spin, none);
	animation-duration: var(--fx-pulse-d, 4s), var(--fx-flicker-d, 1.2s), var(--fx-jitter-d, .6s), var(--fx-spin-d, 8s);
	animation-timing-function: ease-in-out, linear, steps(1, end), linear;
	animation-iteration-count: infinite;
	animation-delay: calc(var(--seed, 0) * -11s);
}
#erolinDevice_orbs.orb-look .obs {
	position: absolute;
	inset: 0;
	overflow: hidden;
	animation-name: var(--an-hum, none), var(--an-wobble, none);
	animation-duration: var(--fx-hum-d, .1s), var(--fx-wobble-d, 2.5s);
	animation-timing-function: linear, ease-in-out;
	animation-direction: alternate, normal;
	animation-iteration-count: infinite;
	animation-delay: calc(var(--seed, 0) * -3s);
}
#erolinDevice_orbs.orb-shape-sun .obs { background: var(--orb-sun) center / 100% 100% no-repeat; }
#erolinDevice_orbs.orb-shape-disc .obs {
	border-radius: 50%;
	background: radial-gradient(circle at 42% 38%, var(--orb-core) 0 16%, var(--orb-mid) 40%, var(--orb-halo) 64%, rgb(var(--orb-halo-rgb) / 0) 76%);
}
#erolinDevice_orbs.orb-shape-drop .obs {
	clip-path: polygon(50% 0%, 68% 24%, 88% 52%, 86% 76%, 70% 96%, 50% 100%, 30% 96%, 14% 76%, 12% 52%, 32% 24%);
	background: radial-gradient(circle at 50% 68%, var(--orb-core) 0 18%, var(--orb-mid) 42%, var(--orb-halo) 70%, var(--orb-rim) 100%);
}
#erolinDevice_orbs.orb-shape-spark .obs {
	clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%);
	background: radial-gradient(circle, var(--orb-core) 0 22%, var(--orb-mid) 45%, var(--orb-halo) 75%, var(--orb-rim) 100%);
}
#erolinDevice_orbs.orb-shape-ring .obs {
	border-radius: 50%;
	background: radial-gradient(circle, rgb(var(--orb-halo-rgb) / 0) 0 28%, var(--orb-core) 38% 46%, var(--orb-halo) 56%, rgb(var(--orb-halo-rgb) / 0) 70%);
}
#erolinDevice_orbs.orb-shape-shard .obs {
	clip-path: polygon(50% 0, 86% 50%, 50% 100%, 14% 50%);
	background: linear-gradient(160deg, var(--orb-core) 0 30%, var(--orb-mid) 31% 55%, var(--orb-halo) 56% 80%, var(--orb-rim) 81%);
}
#erolinDevice_orbs.orb-shape-mote .obs {
	border-radius: 50%;
	background: radial-gradient(circle, var(--orb-core) 0 9%, var(--orb-halo) 16%, rgb(var(--orb-halo-rgb) / .35) 26%, rgb(var(--orb-halo-rgb) / 0) 44%);
}

/* ---------------------------------------------------------------- the body effects (one property each) */
#erolinDevice_orbs.orb-fx-pulse { --an-pulse: orb-pulse; }
#erolinDevice_orbs.orb-fx-flicker { --an-flicker: orb-flicker; }
#erolinDevice_orbs.orb-fx-jitter { --an-jitter: orb-jitter; }
#erolinDevice_orbs.orb-fx-spin { --an-spin: orb-spin; }
#erolinDevice_orbs.orb-fx-hum { --an-hum: orb-hum; }
#erolinDevice_orbs.orb-fx-wobble { --an-wobble: orb-wobble; }
@keyframes orb-pulse { 0%, 100% { scale: 1; } 50% { scale: calc(1 + var(--fx-pulse, 0) * .35); } }
@keyframes orb-flicker {
	0%, 100% { opacity: 1; }
	9% { opacity: calc(1 - var(--fx-flicker, 0) * .55); } 14% { opacity: 1; }
	27% { opacity: calc(1 - var(--fx-flicker, 0) * .25); } 33% { opacity: calc(1 - var(--fx-flicker, 0) * .6); } 38% { opacity: 1; }
	55% { opacity: calc(1 - var(--fx-flicker, 0) * .35); } 61% { opacity: 1; }
	78% { opacity: calc(1 - var(--fx-flicker, 0) * .5); } 83% { opacity: 1; }
}
@keyframes orb-jitter {
	0% { translate: 0 0; }
	12% { translate: calc(var(--fx-jitter, 0) * 4px) calc(var(--fx-jitter, 0) * -2px); }
	25% { translate: calc(var(--fx-jitter, 0) * -3px) calc(var(--fx-jitter, 0) * 2px); }
	37% { translate: calc(var(--fx-jitter, 0) * 1px) calc(var(--fx-jitter, 0) * 4px); }
	50% { translate: calc(var(--fx-jitter, 0) * -4px) calc(var(--fx-jitter, 0) * -1px); }
	62% { translate: calc(var(--fx-jitter, 0) * 2px) calc(var(--fx-jitter, 0) * 1px); }
	75% { translate: 0 calc(var(--fx-jitter, 0) * -4px); }
	87% { translate: calc(var(--fx-jitter, 0) * -1px) calc(var(--fx-jitter, 0) * -3px); }
	100% { translate: 0 0; }
}
@keyframes orb-spin { from { rotate: 0deg; } to { rotate: calc(360deg * var(--fx-spin, 0)); } }
@keyframes orb-hum { from { translate: calc(var(--fx-hum, 0) * -.7px) 0; } to { translate: calc(var(--fx-hum, 0) * .7px) calc(var(--fx-hum, 0) * .3px); } }
@keyframes orb-wobble {
	0%, 100% { transform: none; }
	30% { transform: scale(calc(1 + var(--fx-wobble, 0) * .22), calc(1 - var(--fx-wobble, 0) * .2)); }
	65% { transform: scale(calc(1 - var(--fx-wobble, 0) * .16), calc(1 + var(--fx-wobble, 0) * .2)) skewX(calc(var(--fx-wobble, 0) * 6deg)); }
}

/* ---------------------------------------------------------------- shimmer and swirl, inside the shape */
#erolinDevice_orbs.orb-fx-shimmer .obs::before {
	content: ''; position: absolute; inset: -20% -60%;
	background: linear-gradient(115deg, rgb(var(--orb-accent-rgb) / 0) 42%, rgb(var(--orb-accent-rgb) / calc(.35 + var(--fx-shimmer, .5) * .6)) 50%, rgb(var(--orb-accent-rgb) / 0) 58%);
	mix-blend-mode: screen;
	animation: orb-shimmer var(--fx-shimmer-d, 5s) ease-in-out infinite;
	animation-delay: calc(var(--seed, 0) * -5s);
}
@keyframes orb-shimmer { 0% { translate: -70% 0; } 30% { translate: 70% 0; } 100% { translate: 70% 0; } }
#erolinDevice_orbs.orb-fx-swirl .obs::after {
	content: ''; position: absolute; inset: -10%; border-radius: 50%;
	background: conic-gradient(from 0deg, rgb(var(--orb-accent-rgb) / 0) 0 20%, rgb(var(--orb-accent-rgb) / .85) 32%, rgb(var(--orb-accent-rgb) / 0) 46% 60%, rgb(var(--orb-core-rgb) / .8) 74%, rgb(var(--orb-core-rgb) / 0) 88%);
	opacity: calc(.15 + var(--fx-swirl, .5) * .85);
	mix-blend-mode: screen;
	filter: blur(.6px);
	animation: orb-rot var(--fx-swirl-d, 6s) linear infinite;
	animation-delay: calc(var(--seed, 0) * -6s);
}
@keyframes orb-rot { to { rotate: 360deg; } }

/* ---------------------------------------------------------------- the layers that throw something off */
#erolinDevice_orbs.orb-look .ofx { position: absolute; inset: 0; pointer-events: none; }
#erolinDevice_orbs.orb-look .ofx::before,
#erolinDevice_orbs.orb-look .ofx::after { content: ''; position: absolute; }

/* rings: two rings of the accent, half a period apart */
#erolinDevice_orbs.orb-look .ofx-rings::before,
#erolinDevice_orbs.orb-look .ofx-rings::after {
	inset: 0; border-radius: 50%; box-sizing: border-box;
	border: 1.5px solid rgb(var(--orb-accent-rgb) / .9);
	animation: orb-rings var(--fx-rings-d, 3s) ease-out infinite;
	animation-delay: calc(var(--seed, 0) * -3s);
}
#erolinDevice_orbs.orb-look .ofx-rings::after { animation-delay: calc(var(--seed, 0) * -3s - var(--fx-rings-d, 3s) / 2); }
@keyframes orb-rings { 0% { scale: .55; opacity: calc(.25 + var(--fx-rings, .5) * .7); } 100% { scale: calc(1.5 + var(--fx-rings, .5) * 2.4); opacity: 0; } }

/* sparks: six points of the accent flung outward (the shadows scale with the dot), two throws a period */
#erolinDevice_orbs.orb-look .ofx-sparks::before,
#erolinDevice_orbs.orb-look .ofx-sparks::after {
	left: 50%; top: 50%; width: 2px; height: 2px; margin: -1px; border-radius: 50%;
	background: rgb(var(--orb-accent-rgb));
	box-shadow: 6px -3px 0 rgb(var(--orb-accent-rgb)), -5px -5px 0 rgb(var(--orb-accent-rgb)), 4px 6px 0 rgb(var(--orb-accent-rgb)), -6px 2px 0 rgb(var(--orb-accent-rgb)), 1px -7px 0 rgb(var(--orb-accent-rgb)), -2px 7px 0 rgb(var(--orb-accent-rgb));
	animation: orb-sparks var(--fx-sparks-d, 2.5s) ease-out infinite;
	animation-delay: calc(var(--seed, 0) * -2.5s);
}
#erolinDevice_orbs.orb-look .ofx-sparks::after { rotate: 40deg; animation-delay: calc(var(--seed, 0) * -2.5s - var(--fx-sparks-d, 2.5s) / 2); }
@keyframes orb-sparks { 0% { scale: .2; opacity: 0; } 15% { opacity: 1; } 100% { scale: calc(.9 + var(--fx-sparks, .5) * 2.4); opacity: 0; } }

/* mist: two soft puffs rising and thinning */
#erolinDevice_orbs.orb-look .ofx-mist::before,
#erolinDevice_orbs.orb-look .ofx-mist::after {
	left: 15%; top: 25%; width: 70%; height: 50%; border-radius: 50%;
	background: radial-gradient(ellipse, rgb(var(--orb-accent-rgb) / .75), rgb(var(--orb-accent-rgb) / 0) 70%);
	filter: blur(1.5px);
	animation: orb-mist var(--fx-mist-d, 4s) ease-out infinite;
	animation-delay: calc(var(--seed, 0) * -4s);
}
#erolinDevice_orbs.orb-look .ofx-mist::after { left: 25%; animation-delay: calc(var(--seed, 0) * -4s - var(--fx-mist-d, 4s) / 2); }
@keyframes orb-mist {
	0% { translate: 0 2px; scale: .5; opacity: 0; }
	25% { opacity: calc(.3 + var(--fx-mist, .5) * .55); }
	100% { translate: calc(var(--seed, 0) * 6px - 3px) calc(-14px - var(--fx-mist, .5) * 12px); scale: calc(1.1 + var(--fx-mist, .5)); opacity: 0; }
}

/* drip: drops bead under the orb and fall */
#erolinDevice_orbs.orb-look .ofx-drip::before,
#erolinDevice_orbs.orb-look .ofx-drip::after {
	left: 50%; top: 80%; width: 4px; height: 5px; margin-left: -2px;
	border-radius: 50% 50% 50% 50% / 35% 35% 65% 65%;
	background: linear-gradient(180deg, var(--orb-core), var(--orb-halo));
	animation: orb-drip var(--fx-drip-d, 3s) ease-in infinite;
	animation-delay: calc(var(--seed, 0) * -3s);
}
#erolinDevice_orbs.orb-look .ofx-drip::after { left: 36%; animation-delay: calc(var(--seed, 0) * -3s - var(--fx-drip-d, 3s) * .6); }
@keyframes orb-drip {
	0% { translate: 0 0; scale: .3; opacity: 0; }
	25% { opacity: .95; scale: calc(.5 + var(--fx-drip, .5) * .8); }
	100% { translate: 0 calc(12px + var(--fx-drip, .5) * 12px); scale: calc(.4 + var(--fx-drip, .5) * .6); opacity: 0; }
}

/* bolt: a forked flash of the accent, twice near the end of each period, a mirrored one on its own clock */
#erolinDevice_orbs.orb-look .ofx-bolt::before,
#erolinDevice_orbs.orb-look .ofx-bolt::after {
	left: 50%; top: 50%; width: 14px; height: 22px; margin: -11px -7px;
	clip-path: polygon(45% 0, 70% 0, 52% 38%, 78% 38%, 30% 100%, 44% 55%, 20% 55%);
	background: rgb(var(--orb-accent-rgb));
	filter: drop-shadow(0 0 2px rgb(var(--orb-accent-rgb)));
	opacity: 0;
	transform-origin: 50% 50%;
	animation: orb-bolt var(--fx-bolt-d, 5s) linear infinite;
	animation-delay: calc(var(--seed, 0) * -5s);
}
#erolinDevice_orbs.orb-look .ofx-bolt::after { scale: -1 1; animation-delay: calc(var(--seed, 0) * -5s - var(--fx-bolt-d, 5s) * .37); }
@keyframes orb-bolt {
	0%, 86% { opacity: 0; translate: 0 0; }
	88% { opacity: calc(.4 + var(--fx-bolt, .5) * .6); translate: calc(var(--fx-bolt, .5) * 6px) calc(var(--fx-bolt, .5) * -5px); scale: calc(.6 + var(--fx-bolt, .5) * .9); rotate: 18deg; }
	91% { opacity: 0; }
	94% { opacity: calc(.3 + var(--fx-bolt, .5) * .5); translate: calc(var(--fx-bolt, .5) * -7px) calc(var(--fx-bolt, .5) * 3px); scale: calc(.5 + var(--fx-bolt, .5) * .7); rotate: -34deg; }
	96%, 100% { opacity: 0; }
}

/* motes: grains of the accent drifting up around the orb */
#erolinDevice_orbs.orb-look .ofx-motes::before,
#erolinDevice_orbs.orb-look .ofx-motes::after {
	left: 50%; top: 60%; width: 1.5px; height: 1.5px; border-radius: 50%;
	background: rgb(var(--orb-accent-rgb));
	box-shadow: 7px 2px 0 rgb(var(--orb-accent-rgb)), -8px -1px 0 rgb(var(--orb-accent-rgb)), 3px -5px 0 rgb(var(--orb-accent-rgb)), -4px 5px 0 rgb(var(--orb-accent-rgb));
	animation: orb-motes var(--fx-motes-d, 5s) linear infinite;
	animation-delay: calc(var(--seed, 0) * -5s);
}
#erolinDevice_orbs.orb-look .ofx-motes::after { left: 40%; animation-delay: calc(var(--seed, 0) * -5s - var(--fx-motes-d, 5s) / 2); }
@keyframes orb-motes {
	0% { translate: 0 8px; opacity: 0; }
	15% { opacity: calc(.35 + var(--fx-motes, .5) * .65); }
	100% { translate: calc(var(--seed, 0) * 4px - 2px) calc(-16px - var(--fx-motes, .5) * 10px); opacity: 0; }
}

/* orbit: a dot painted at the far end of an invisible arm that turns about the orb's centre; two moons */
#erolinDevice_orbs.orb-look .ofx-orbit::before,
#erolinDevice_orbs.orb-look .ofx-orbit::after {
	left: 50%; top: 50%; width: 3px; height: calc(8px + var(--fx-orbit, .5) * 10px);
	margin-left: -1.5px; margin-top: calc(-8px - var(--fx-orbit, .5) * 10px);
	transform-origin: 50% 100%;
	background: radial-gradient(circle at 50% 1.5px, rgb(var(--orb-accent-rgb)) 0 1.4px, rgb(var(--orb-accent-rgb) / 0) 2px);
	animation: orb-rot var(--fx-orbit-d, 4s) linear infinite;
	animation-delay: calc(var(--seed, 0) * -4s);
}
#erolinDevice_orbs.orb-look .ofx-orbit::after { height: calc(6px + var(--fx-orbit, .5) * 7px); margin-top: calc(-6px - var(--fx-orbit, .5) * 7px); animation-direction: reverse; animation-duration: calc(var(--fx-orbit-d, 4s) * 1.6); }

/* ---------------------------------------------------------------- the change of a look: a short fade of the body */
#erolinDevice_orbs.orb-look.orb-swap .ob { animation: none; opacity: 0; transition: opacity .45s ease; }
#erolinDevice_orbs.orb-look.orb-swap .ofx { opacity: 0; transition: opacity .45s ease; }

/* ---------------------------------------------------------------- phones keep the plain sun; reduced motion keeps the colours */
@media (max-width: 640px) {
	#erolinDevice_orbs.orb-look .ob, #erolinDevice_orbs.orb-look .ofx { display: none; }
	#erolinDevice_orbs.orb-look .erolin_slot_on { background-image: var(--orb-sun); animation: orb-rot 5s linear infinite; }
}
@media (prefers-reduced-motion: reduce) {
	#erolinDevice_orbs.orb-look .ob, #erolinDevice_orbs.orb-look .obs, #erolinDevice_orbs.orb-look .obs::before, #erolinDevice_orbs.orb-look .obs::after,
	#erolinDevice_orbs.orb-look .ofx::before, #erolinDevice_orbs.orb-look .ofx::after, #erolinDevice_orbs.orb-look .erolin_slot_on { animation: none !important; }
}
