/* COPIED from ~/Desktop/Design System/components/ai-icon.css on 2026-10-20 by selfprint/tools/build_zds.py.
   Do not edit here — change the Design System, then re-run the script. */
/* =============================================================================
   Zigu — AI icon  (components/ai-icon.css)  · Atom
   Zigu's AI, moving: a small night planet (navy sphere, a breathing core of light) with three light
   comets on tilted orbits and a slow aurora; an iridescent rim and a glass highlight. Idle it drifts.
   While the AI works (--thinking) it breathes in cycles: each comet, tail and all, spirals into the planet over one
   more lap — its orbit closing little by little — and merges with it (the core swells), then spirals back out (it
   shrinks) and orbits again like a satellite. The AI's only mark (it replaces Icon "ai").
   Requires tokens.css. Spec: components/ai-icon.md · no Figma page (motif from the product owner's sample).

   <span class="zg-ai-icon" role="img" aria-label="AI">                 ← aria-hidden="true" next to the word "AI"
     <span class="zg-ai-icon__aurora"></span>
     <span class="zg-ai-icon__orbit"><i class="zg-ai-icon__comet"></i></span>   ← ×3
     <span class="zg-ai-icon__core"></span>
   </span>

   size: (md 20) · --lg 24 · --xl 32 — the sizes of Icon's circle frame (zg-icon-box--circle md · lg · xl); the orb is
         the circle. More sizes only when a screen needs one (product owner) — add a class here, don't size it ad hoc.
         (--zg-ai-icon-size exists for the doc page's magnifier.)
   state: --thinking (the AI is working — say so in words too)
          --still (frozen: an AI that is here but not the live one — past answers, lists of AI things, many on a screen.
          It freezes where it is — every motion pauses mid-way — as frost grows in from the rim and its light cools;
          taking it off thaws it and it moves on from there. Drawn already frozen, it just is — no freeze plays.)
          Stopping thinking: let the running cycle end (the comets come back out) — ZDS.aiIconThinking(el, false);
          removing the class at once snaps them out of the core (CSS can't ease out of an animation).
   Motion: rotate · translate · scale · opacity only. Idle: 5 running animations (aurora + rim · 3 comets · core);
   thinking adds 10 (per comet: the faster lap · the head's and the tail's closing orbit; the core's swell). Each costs a style pass on every frame the page draws, so
   lists show --still and only the live one moves. Reduced motion: still (thinking = a steady brighter core).
   ========================================================================== */
.zg-ai-icon {
  --_s: var(--zg-ai-icon-size, var(--ai-icon-size));
  position: relative;
  display: inline-block;
  flex: none;
  width: var(--_s);
  height: var(--_s);
  border-radius: 50%;
  overflow: hidden;
  isolation: isolate;
  vertical-align: middle;
  background: radial-gradient(circle at 50% 56%, var(--ai-icon-mid) 0%, var(--ai-icon-deep) 64%);
}
.zg-ai-icon--lg { --_s: var(--icon-lg); }    /* 24 */
.zg-ai-icon--xl { --_s: var(--icon-xl); }    /* 32 */

/* aurora: four soft lights drifting round the middle (screen-blended on the night). The rim rides on it (::after),
   so it turns too without an animation of its own — every running animation costs a style pass per frame. */
.zg-ai-icon__aurora {
  --_a: 55%;
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 34%, color-mix(in srgb, var(--ai-icon-aqua) var(--_a), transparent) 0, transparent 36%),
    radial-gradient(circle at 70% 42%, color-mix(in srgb, var(--ai-icon-ocean) var(--_a), transparent) 0, transparent 40%),
    radial-gradient(circle at 62% 74%, color-mix(in srgb, var(--ai-icon-rose) var(--_a), transparent) 0, transparent 34%),
    radial-gradient(circle at 30% 68%, color-mix(in srgb, var(--ai-icon-violet) var(--_a), transparent) 0, transparent 42%);
  mix-blend-mode: screen;
  animation: zg-ai-turn var(--ai-icon-duration) linear infinite;
}
/* the iridescent rim, glowing inward */
.zg-ai-icon__aurora::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 200deg, var(--ai-icon-aqua), var(--ai-icon-ocean), var(--ai-icon-violet), var(--ai-icon-rose), var(--ai-icon-lilac), var(--ai-icon-aqua));
  -webkit-mask: radial-gradient(closest-side, transparent 80%, rgb(0 0 0 / 0.35) 90%, #000 100%);
          mask: radial-gradient(closest-side, transparent 80%, rgb(0 0 0 / 0.35) 90%, #000 100%);
}

/* comets: a light trail on a tilted, flattened orbit — the orbit is the box (tilt · flatten); the comet turns in it.
   The comet is two layers on one turning frame: ::before the long tail, ::after the head with a short streak — idle
   they read as one trail; spiralling in, the tail's orbit closes a moment after the head's, so the tail trails outside
   it like a spiral (v0.5.145). Each layer carries the ring mask, so it shrinks with it. */
.zg-ai-icon__orbit {
  position: absolute;
  inset: var(--_in, 12%);
  rotate: var(--_tilt, 0deg);
  scale: 1 var(--_flat, 0.4);
  mix-blend-mode: screen;
}
.zg-ai-icon__comet {
  position: absolute;
  inset: 0;
  rotate: var(--_from, 0deg);
  animation: zg-ai-orbit var(--_t, var(--ai-icon-orbit-duration)) linear infinite;
}
.zg-ai-icon__comet::before,
.zg-ai-icon__comet::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  -webkit-mask: radial-gradient(closest-side, transparent 64%, #000 84%, transparent 100%);
          mask: radial-gradient(closest-side, transparent 64%, #000 84%, transparent 100%);
}
.zg-ai-icon__comet::before { background: conic-gradient(transparent 0 42%, color-mix(in srgb, var(--_c) 30%, transparent) 68%, var(--_c) 84%, transparent 92%); }   /* tail */
.zg-ai-icon__comet::after { background: conic-gradient(transparent 0 76%, var(--_c) 85%, var(--ai-icon-core) 93%, color-mix(in srgb, var(--ai-icon-core) 40%, transparent) 96%, transparent 99%); }   /* head — it fades (no blade) */
.zg-ai-icon__orbit:nth-child(2) { --_tilt: -32deg; --_flat: 0.42; --_c: var(--ai-icon-aqua); --_from: 40deg; }
.zg-ai-icon__orbit:nth-child(3) { --_in: 17%; --_tilt: 38deg; --_flat: 0.5; --_c: var(--ai-icon-lilac); --_from: 210deg; --_t: calc(var(--ai-icon-orbit-duration) * 1.35); }
.zg-ai-icon__orbit:nth-child(4) { --_in: 7%; --_tilt: 84deg; --_flat: -0.28; --_c: var(--ai-icon-rose); --_from: 120deg; --_t: calc(var(--ai-icon-orbit-duration) * 1.7); }   /* flipped: it goes the other way round */

/* ---- thinking (user, v0.5.143 → v0.5.145): each comet spirals into the planet and back out — one cycle per
   --ai-icon-think-duration. The orbits stay; each comet, tail and all, goes round once more while its orbit closes
   little by little — slowly at first, then faster as it nears the middle, and it turns faster too (like anything
   falling in) — so it slides into the core instead of turning at it. Its tail's orbit closes 0.24s behind the head's,
   so the tail runs outside it, along the spiral. The three come from their own sides and leave their own ways.
   0 → 40%   one more lap (an extra turn on top of its own) as the orbit closes — into the core (0 · 0.1 · 0.2s apart)
   40 → 50%  merged — the core swells (below)
   50 → 70%  spiral back out, a little past the orbit — the core shrinks
   70 → 80%  settle onto the orbit
   80 → 100% orbit like a satellite, as when idle — then again (the extra turn is a whole one, so it's the same pose)
   It starts in the idle pose (no jump going in). Coming out: ZDS.aiIconThinking(el, false) waits for the first comet's
   cycle to end — the others are then in their quiet part — so nothing jumps either. */
.zg-ai-icon--thinking .zg-ai-icon__comet { animation: zg-ai-orbit var(--_t, var(--ai-icon-orbit-duration)) linear infinite, zg-ai-spiral var(--ai-icon-think-duration) var(--_d, 0s) infinite; }
.zg-ai-icon--thinking .zg-ai-icon__comet::after { animation: zg-ai-close var(--ai-icon-think-duration) var(--_d, 0s) infinite; }
.zg-ai-icon--thinking .zg-ai-icon__comet::before { animation: zg-ai-close var(--ai-icon-think-duration) calc(var(--_d, 0s) + var(--ai-icon-tail-lag)) infinite; }
.zg-ai-icon--thinking .zg-ai-icon__orbit:nth-child(3) { --_d: 100ms; }
.zg-ai-icon--thinking .zg-ai-icon__orbit:nth-child(4) { --_d: 200ms; }
/* the extra turn — inside the lap's rotate, so it adds to it */
@keyframes zg-ai-spiral {
  0%   { transform: none; animation-timing-function: cubic-bezier(0.45, 0, 0.8, 0.55); }
  40%, 100% { transform: rotate(1turn); }
}
/* the orbit closing (scale of the layer inside the flattened orbit — it stays an ellipse) */
@keyframes zg-ai-close {
  0%   { scale: 1; opacity: 1; animation-timing-function: cubic-bezier(0.4, 0, 0.85, 0.5); }
  40%  { scale: 0.04; opacity: 0.85; animation-timing-function: linear; }
  44%, 50% { scale: 0.04; opacity: 0; animation-timing-function: cubic-bezier(0.2, 0.6, 0.35, 1); }
  70%  { scale: 1.08; opacity: 1; animation-timing-function: var(--ease-standard); }
  80%, 100% { scale: 1; opacity: 1; }
}

/* the core: the planet's own light, breathing */
.zg-ai-icon__core {
  position: absolute;
  inset: 25%;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--ai-icon-core) 0 16%, var(--white-a65) 34%, color-mix(in srgb, var(--ai-icon-ocean) 40%, transparent) 64%, transparent 100%);
  mix-blend-mode: screen;
  animation: zg-ai-breathe calc(var(--ai-icon-duration) / 3) ease-in-out infinite alternate;
}
/* thinking: the core swells as the comets fall in and shrinks as they leave — a glow round it, on the same cycle
   (it only animates while thinking — idle it costs nothing) */
.zg-ai-icon__core::after {
  content: "";
  position: absolute;
  inset: -22%;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--ai-icon-core) 0 22%, var(--white-a65) 40%, color-mix(in srgb, var(--ai-icon-aqua) 35%, transparent) 66%, transparent 100%);
  opacity: 0;
  scale: 0.5;
}
.zg-ai-icon--thinking .zg-ai-icon__core::after { animation: zg-ai-swell var(--ai-icon-think-duration) infinite; }
@keyframes zg-ai-swell {
  0%, 18% { scale: 0.5; opacity: 0; animation-timing-function: ease-in; }
  34%  { scale: 0.7; opacity: 0.5; animation-timing-function: ease-out; }     /* they're closing in */
  46%  { scale: 1; opacity: 1; animation-timing-function: ease-in-out; }      /* all in — full */
  52%  { scale: 0.95; opacity: 1; animation-timing-function: ease-in; }
  66%  { scale: 0.64; opacity: 0.35; animation-timing-function: ease-out; }   /* they're out */
  76%, 100% { scale: 0.5; opacity: 0; }
}

/* glass: a soft highlight up-left */
.zg-ai-icon::before {
  content: "";
  position: absolute;
  z-index: 2;
  inset: 6% 24% 56% 16%;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--white-a30), transparent);
  pointer-events: none;
}

@keyframes zg-ai-turn { to { rotate: 1turn; } }   /* the aurora (and the rim on it) */
@keyframes zg-ai-orbit { from { rotate: var(--_from); } to { rotate: calc(var(--_from) + 1turn); } }
@keyframes zg-ai-breathe { from { scale: 0.84; opacity: 0.82; } to { scale: 1.06; opacity: 1; } }

/* ---- --still (user, v0.5.146): frozen — an AI that is here but not the live one (past answers, lists, many at once).
   Frozen in place: every animation pauses where it is (not reset — a paused animation also costs nothing per frame),
   so the comets hang mid-lap; frost grows in from the rim — needles of ice and a pale shell, the frost layer shrinks
   from 1.35 onto the orb — and the light inside cools (less colour). Thawing (class off) runs it backwards: the frost
   lets go outward and everything moves on from where it stopped. Transitions, not animations: an icon drawn already
   --still (a list on load) is simply frozen — no freeze plays for each row. */
.zg-ai-icon { transition: filter var(--ai-icon-freeze-duration) var(--ease-standard); }
.zg-ai-icon--still { filter: saturate(0.55) brightness(1.04); }
.zg-ai-icon--still :is(.zg-ai-icon__aurora, .zg-ai-icon__core, .zg-ai-icon__comet),
.zg-ai-icon--still :is(.zg-ai-icon__core, .zg-ai-icon__comet)::after,
.zg-ai-icon--still .zg-ai-icon__comet::before { animation-play-state: paused; }
.zg-ai-icon::after {
  content: "";
  position: absolute;
  z-index: 3;
  inset: 0;
  border-radius: 50%;
  /* frost (v0.5.147): one vector drawing whose lines keep their screen width at every size (non-scaling strokes) — so at
     20 · 24 · 32 a snowflake glint up-left, the crust just inside the rim and the long needles are 1–1.6px and read,
     and in a large view they stay fine: needles of uneven length (the long ones branched), rime grains, the glint.
     Under it the ice shell (a pale band toward the rim) and an icy glaze. At the very edge a 1px ice-blue line, and the
     shell stops short of white there — so the circle keeps its edge on a light page. Drawn once, no cost per frame.
     The drawing is generated: change tools/build-ai-frost.py and run it — never hand-edit the data URI. */
  background:
    /* frost-svg:start */url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath vector-effect='non-scaling-stroke' stroke-width='1.6' stroke-opacity='.6' d='M50 4.4L53 4.7L55.9 4.9L58.9 5.1L62 5.3L65.1 5.6L68.1 6.2L71.1 7.3L73.7 8.9L76.1 11L78.2 13.3L80.1 15.6L82.1 17.9L84.1 20.1L86.1 22.3L88 24.6L89.7 27.1L91.2 29.7L92.4 32.4L93.5 35.2L94.5 38.1L95.5 40.9L96.5 43.9L97.2 46.9L97.5 50L97.2 53.1L96.4 56.1L95.2 59L93.9 61.8L92.6 64.5L91.6 67.2L90.6 70L89.6 72.8L88.3 75.6L86.8 78.2L84.9 80.6L82.8 82.8L80.6 84.9L78.3 86.9L76 88.9L73.5 90.8L70.9 92.3L68 93.4L65 94.1L61.9 94.3L58.8 94.4L55.9 94.5L52.9 94.7L50 95.2L47 95.6L44 95.9L40.9 95.8L37.9 95.3L34.9 94.4L32.1 93.1L29.4 91.8L26.7 90.4L24.1 88.8L21.5 87.1L19.3 85.1L17.3 82.7L15.6 80.2L14.1 77.5L12.7 74.9L11.1 72.4L9.4 70L7.6 67.6L5.9 65L4.5 62.2L3.6 59.2L3.2 56.2L3.2 53.1L3.4 50L3.8 47L4.1 44L4.6 41L5.4 38L6.4 35.2L7.8 32.5L9.3 29.9L10.9 27.5L12.5 24.9L13.9 22.3L15.4 19.6L16.9 16.9L18.8 14.4L21.1 12.3L23.7 10.6L26.5 9.3L29.5 8.3L32.4 7.5L35.3 6.7L38.2 5.8L41.1 5.1L44 4.6L47 4.3Z'/%3E%3Cpath vector-effect='non-scaling-stroke' stroke-width='.9' stroke-opacity='.6' d='M48.8 3L47.6 14.7M48 10.8l1.4 2M90.9 26.8L79.9 33.1M85.3 30l-4.5 -0.7M84 30.8l-1.6 3.6M94.3 34.2L81 40.6M87.2 37.6l-2.9 -0.6M96.7 45L79.8 47.7M88.8 46.3l-3.3 -2.4M88.1 46.4l-4.9 -3.2M96.6 56L80.4 54.9M86.9 55.4l-4.4 -3.6M88.3 55.5l-2.5 2.1M95.3 62.7L84.6 58.1M90 60.4l-2.3 1.1M88.3 59.7l-0.7 -2.5M77.4 88.2L69.1 79.3M73.2 83.6l-0.1 -4.2M62.4 95.3L59.5 80M60.8 86.7l-2.3 -1.6M61.2 89.2l1.9 -2.8M32.4 93.6L38.7 77.6M36 84.4l-2.3 -4.5M36.4 83.4l-1.5 -5.3M22.4 88.1L30.7 78.1M26.6 83l4.7 0M26.4 83.3l-0.1 -2.7M3.3 55.2L13.8 53.4M7.6 54.4l2.2 -2.1M10.6 54l2 -2.5M9.7 25.9L20.5 31.4M14.7 28.4l0.9 3.2M22.7 11.7L32.4 22.7M28.5 18.2l-0.1 3.8M29.3 7.8L38.4 23.9M35.2 18.1l3.4 1.2'/%3E%3Cpath vector-effect='non-scaling-stroke' stroke-width='.7' stroke-opacity='.45' d='M56.9 3.5L58.1 8.1M69.9 7.4L69 14M75 10.2L71.3 16.7M85.2 18.9L79.8 22.9M90.1 74.6L85.9 70.7M86.1 80.1L82.5 75.1M69.8 92.6L67.5 87.2M50.2 97L50.2 87.1M50.2 93l2.2 -2.4M38.9 95.7L42.2 88M41 90.9l-0.7 -1.7M15.8 82.3L20.2 78.3M8.8 72.6L14.8 68M4.8 62.9L13 62.2M9 62.5l1.6 -2M8.2 62.6l1 -1.2M3.6 42.5L11.8 43.9M7.2 43.1l1.9 -0.9M8.6 43.3l1.6 2.5M6.2 33L14 34.9M13.3 20.6L18.2 24.5M39 4.3L42.3 13.4M41.2 10.5l-0.8 2.8'/%3E%3Cpath stroke-width='1.1' stroke-opacity='.5' d='M41 6.3h.01M39.2 15h.01M53.1 88.7h.01M10.1 27.3h.01M65 82.7h.01M84.1 71.3h.01M83 65.2h.01M55.2 7.7h.01M64.9 87.8h.01M79.8 66.8h.01M46.8 91.4h.01M46.7 15.4h.01M42.3 7.2h.01M85.1 53.4h.01M16.1 43.8h.01M77.1 24.4h.01M29.4 16.8h.01M93.8 52.4h.01M32.6 18.7h.01M11.1 62.5h.01M62.4 17.2h.01M69.1 87.7h.01M36.8 17.7h.01M10.6 36.7h.01M22.5 28.3h.01M23.6 27.4h.01M83.4 71h.01M31.9 13.6h.01M77 24.4h.01M90.2 47.1h.01M80 31.4h.01M83 39.7h.01M85.5 62.8h.01M91.8 60.7h.01M86 32.5h.01M54.3 12.1h.01M53.6 13.2h.01M36.5 90.6h.01M55.7 85.8h.01M78 14.5h.01'/%3E%3Cpath vector-effect='non-scaling-stroke' stroke-width='1.25' d='M31.5 16.5L31.5 42.5M42.8 23L20.2 36M42.8 36L20.2 23'/%3E%3Cpath vector-effect='non-scaling-stroke' stroke-width='.9' stroke-opacity='.9' d='M31.5 36.3l3.3 3M31.5 36.3l-3.3 3M25.6 32.9l-0.9 4.3M25.6 32.9l-4.2 -1.4M25.6 26.1l-4.2 1.4M25.6 26.1l-0.9 -4.3M31.5 22.7l-3.3 -3M31.5 22.7l3.3 -3M37.4 26.1l0.9 -4.3M37.4 26.1l4.2 1.4M37.4 32.9l4.2 -1.4M37.4 32.9l0.9 4.3'/%3E%3C/svg%3E")/* frost-svg:end */ center / 100% 100% no-repeat,
    radial-gradient(closest-side, transparent calc(100% - 1.25px), var(--ai-icon-frost-line) calc(100% - 1px)),
    radial-gradient(closest-side, color-mix(in srgb, var(--ai-icon-frost) 14%, transparent) 0, transparent 52%,
      color-mix(in srgb, var(--ai-icon-frost) 18%, transparent) 72%, color-mix(in srgb, var(--ai-icon-frost) 55%, transparent) 88%,
      color-mix(in srgb, var(--ai-icon-frost-edge) 78%, transparent) calc(100% - 1.5px), transparent calc(100% - 1px));   /* the glowing shell, up to the line */
  opacity: 0;
  scale: 1.35;
  pointer-events: none;
  transition: opacity var(--ai-icon-freeze-duration) var(--ease-standard), scale var(--ai-icon-freeze-duration) cubic-bezier(0.2, 0.7, 0.2, 1);
}
.zg-ai-icon--still::after { opacity: 1; scale: 1; }

/* reduced motion: no motion at all (the idle pose; thinking = a steady swollen core). --still still shows its frost, without the freeze. */
@media (prefers-reduced-motion: reduce) {
  .zg-ai-icon :is(.zg-ai-icon__aurora, .zg-ai-icon__core, .zg-ai-icon__comet),
  .zg-ai-icon :is(.zg-ai-icon__core, .zg-ai-icon__comet)::after,
  .zg-ai-icon .zg-ai-icon__comet::before { animation: none; }
  .zg-ai-icon--thinking .zg-ai-icon__core::after { opacity: 0.9; scale: 0.85; }
  .zg-ai-icon, .zg-ai-icon::after { transition: none; }
}
