shadok-ai 0.9.18 → 0.9.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/index.html +25 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.9.18",
3
+ "version": "0.9.19",
4
4
  "main": "dist/session.js",
5
5
  "scripts": {
6
6
  "test": "node --import tsx --test test/*.ts context/*/test/*.test.mjs",
package/public/index.html CHANGED
@@ -3377,12 +3377,35 @@
3377
3377
  * end down = negative angle) and the ball dips with the effort — shared by the
3378
3378
  * favicon and the in-page indicator so both pump the same way. */
3379
3379
  function pumpPose(p) { return { lever: 13 - p * 28, bob: +(p * 1.5).toFixed(2) }; }
3380
- /** The "working" favicon: the Shadok pumping its lever. `phase` rides a cycle. */
3380
+ /** Blend `t` of `b` into `a`, both 6-digit hex. Every palette colour is written
3381
+ * that way on purpose (see the theme blocks), so this needs no colour parser —
3382
+ * but anything else RETURNS `a` rather than producing `#NaNNaNNaN`, which is
3383
+ * an invalid fill and would take the whole favicon down silently. */
3384
+ const HEX6 = /^#[0-9a-f]{6}$/i;
3385
+ function mixHex(a, b, t) {
3386
+ if (!HEX6.test(a) || !HEX6.test(b)) return a;
3387
+ const ch = (c, i) => parseInt(c.slice(1 + i * 2, 3 + i * 2), 16);
3388
+ const out = [0, 1, 2].map((i) => Math.round(ch(a, i) + (ch(b, i) - ch(a, i)) * t));
3389
+ return "#" + out.map((v) => v.toString(16).padStart(2, "0")).join("");
3390
+ }
3391
+ /** The "working" favicon: the Shadok pumping its lever, on a tile that BREATHES
3392
+ * with the stroke. `phase` rides a cycle.
3393
+ *
3394
+ * The breathing is the part that survives. The pump is line work: the lever
3395
+ * swings 28° about a 5px radius and the body dips 1.5 — roughly 1.2 and 0.75
3396
+ * real pixels at the 16px a tab actually paints, i.e. under the threshold of a
3397
+ * rendered pixel. Idle and mid-stroke were pixel-identical there, so the whole
3398
+ * animation existed only for someone who zoomed in. Moving the GROUND moves
3399
+ * every pixel of the icon at once, which is the only thing that reads at that
3400
+ * size — the same lesson as the waiting glyph. The Shadok keeps pumping on top
3401
+ * for whoever looks closely. */
3381
3402
  const PUMP_FRAMES = 12;
3403
+ const BREATHE = 0.26; // how far the ground travels toward the accent, at full stroke
3382
3404
  function faviconPumpingSVG(phase) {
3383
3405
  const accent = themeColor("--amber", "#f0a848");
3406
+ const base = themeColor("--bg", "#14161d");
3384
3407
  const p = (Math.sin((phase / PUMP_FRAMES) * 2 * Math.PI - Math.PI / 2) + 1) / 2; // 0..1..0
3385
- return faviconWrap(shadokInner(accent, pumpPose(p)));
3408
+ return faviconWrap(shadokInner(accent, pumpPose(p)), mixHex(base, accent, p * BREATHE));
3386
3409
  }
3387
3410
  /** What each channel is asking for, as the pure module wants it. */
3388
3411
  function attentionInput() {