/* ansatz / gear
 *
 * paints the SVG markup emitted by `crates/gear`. the engine assigns
 * stable class names to every node it produces; this sheet maps those
 * to the ansatz palette. rotation is driven by SMIL animateTransform
 * inside the SVG itself, not CSS, because explicit pivots are the
 * only way to keep rotation centres stable across browser reflow.
 *
 * structure (top-down):
 *   .gear-planetary svg root
 *     .gear-backplate                 ember plate, engravings, ghosts, jewels
 *       .gear-backplate-disc          ember disc behind the ring
 *       .gear-ghosts                  steel ghost gears (no mesh, decorative)
 *       .gear-ghosts-orbiting         orbiting epicyclic mini-mechanisms
 *       .gear-engrave-{ring,tick,...} thin bronze engravings
 *       .gear-jewel                   small red decorative ruby
 *     .gear-body.gear-ring            brass annulus (evenodd path)
 *     .gear-orbit                     carrier wrapping planet + satellites
 *       .gear-spinner                 each gear's spin layer
 *         .gear-body                  toothed contour, brass
 *         .gear-spoke                 thin radial line
 *         .gear-hub                   small central dot
 */

/* -- root svg ----------------------------------------------------- */

.gear,
.gear-planetary,
.gear-train {
  display: block;
  overflow: visible;
}

/* -- foreground gears (sun, planet, ring, satellites) ------------- */

.gear-body {
  fill: var(--bronze);
  stroke: var(--bronze-deep);
  stroke-width: 0.18;
  stroke-linejoin: round;
}

/* the planetary ring is the same path style but punches its toothed
 * inner contour out of an outer circle via fill-rule: evenodd. so the
 * brass reads as an annulus and the backplate shows through the hole.
 */
.gear-body.gear-ring {
  fill: var(--bronze-deep);
  stroke: var(--bronze-faint);
}

.gear-spoke {
  stroke: var(--bronze-faint);
  stroke-width: 0.4;
  stroke-linecap: round;
  opacity: 0.85;
}

.gear-hub {
  fill: var(--bronze-deep);
  stroke: var(--bronze-faint);
  stroke-width: 0.25;
}

/* -- backplate (ember disc + engravings + ghost gears) ------------ */

.gear-backplate-disc {
  fill: var(--ember-deep);
  stroke: var(--bronze-faint);
  stroke-width: 0.4;
}

.gear-engrave-ring {
  fill: none;
  stroke: var(--ember-engrave);
  stroke-width: 0.18;
  opacity: 0.75;
}

.gear-engrave-tick {
  stroke: var(--ember-engrave);
  stroke-width: 0.18;
  opacity: 0.7;
}

.gear-engrave-tick-major {
  stroke-width: 0.32;
  opacity: 0.95;
}

.gear-engrave-spiral {
  fill: none;
  stroke: var(--ember-engrave);
  stroke-width: 0.16;
  stroke-linejoin: round;
  opacity: 0.55;
}

.gear-engrave-screw {
  fill: var(--ember-screw);
  stroke: var(--bronze-faint);
  stroke-width: 0.14;
}

.gear-engrave-dot {
  fill: var(--bronze-faint);
  opacity: 0.8;
}

/* back-layer steel mechanism. paints solid in cool tones so the brass
 * ring on top reads as the dial cover, with this train showing through
 * the ring's tooth gaps and through the planetary's empty interior.
 * the SVG is layered backplate -> ring -> carrier -> sun, so these
 * already sit physically behind the brass; no opacity trick needed.
 */
.gear-ghosts .gear-body {
  fill: var(--steel-mid);
  stroke: var(--steel-deep);
  stroke-width: 0.18;
  stroke-linejoin: round;
}

.gear-ghosts .gear-spoke {
  stroke: var(--steel-deep);
  stroke-width: 0.4;
  stroke-linecap: round;
}

.gear-ghosts .gear-hub {
  fill: var(--steel-deep);
  stroke: var(--steel-mid);
  stroke-width: 0.25;
}

/* -- jewels ------------------------------------------------------- *
 *
 * decorative ruby/garnet accents drawn on top of every other backplate
 * detail. red against the warm bronze and cool steel palette gives the
 * mechanism a watch-movement feel without competing for attention.
 */

.gear-jewel {
  fill: var(--vermilion);
  stroke: var(--carmine);
  stroke-width: 0.15;
  stroke-linejoin: round;
}

/* -- layer opacity ------------------------------------------------- *
 *
 * the back layer sits nearly opaque so its mechanism dominates the
 * dial, with a hair of transparency letting the cosmos peek through
 * the disc's edges and the engravings show against the steel where
 * they overlap.
 *
 * the foreground (carrier riders + sun) is more transparent so the
 * busy steel mechanism behind is always visible through the brass.
 * the brass annulus stays full opacity since it's the structural
 * frame the design reads against.
 */

.gear-backplate {
  opacity: 0.95;
}

.gear-orbit {
  opacity: 0.78;
}

/* the foreground sun is a bare spinner directly under the SVG root
 * (rendered as a sibling of `.gear-orbit`, not a descendant). this
 * selector picks it out without also catching ghost spinners (which
 * sit deeper inside `.gear-backplate`) or carrier riders (which sit
 * inside `.gear-orbit`).
 */
.gear-planetary > g > .gear-spinner {
  opacity: 0.78;
}

/* -- rotation ----------------------------------------------------- *
 *
 * the engine emits SMIL `<animateTransform>` elements directly inside
 * each `.gear-spinner` and `.gear-orbit`, with explicit `from="θ 0 0"`
 * pivots so rotation happens around user-coord (0, 0) regardless of
 * bbox shape. we don't drive rotation from CSS, but the keyframes
 * approach was tried first - turns out `transform-box: fill-box`
 * pivots are too brittle across browser reflow / zoom for groups
 * whose intrinsic bbox isn't centred (asymmetric carrier layouts in
 * particular). SMIL is what `OrbitingBackplate` already uses and the
 * only reliable option here.
 *
 * if the user prefers reduced motion we'd ideally pause the SMIL
 * timeline. SMIL doesn't honour `prefers-reduced-motion` natively,
 * so this needs JS hooking later. for now: motion is unconditional,
 * matching the orbiting backplate's existing behaviour.
 */
