shadok-ai 0.8.21 → 0.8.22

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 +51 -46
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.8.21",
3
+ "version": "0.8.22",
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
@@ -1019,17 +1019,15 @@
1019
1019
  /* The pumping Shadok: `color` feeds its `currentColor` fill so it follows the
1020
1020
  palette. The body bobs and the arm swings — the pump — on the same beat. */
1021
1021
  #thinking .tw-shadok { display: inline-flex; color: var(--amber); }
1022
- #thinking .tw-shadok svg { width: 20px; height: 20px; overflow: visible; }
1023
- /* Body bobs with translate (no transform-origin needed that unit is a
1024
- cross-browser trap on SVG). The arm swings from its own top via fill-box, so
1025
- it reads as working a pump handle. */
1026
- #thinking .tw-shadok .sh-body { animation: tw-pump 0.7s ease-in-out infinite; }
1027
- #thinking .tw-shadok .sh-arm { animation: tw-arm 0.7s ease-in-out infinite; transform-box: fill-box; transform-origin: top center; }
1028
- @keyframes tw-pump { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(1.5px); } }
1029
- @keyframes tw-arm { 0%, 100% { transform: rotate(-10deg); } 50% { transform: rotate(28deg); } }
1022
+ #thinking .tw-shadok svg { width: 22px; height: 22px; overflow: visible; }
1023
+ /* The whole Shadok (body + arm + handle) bobs with translate — no
1024
+ transform-origin, which is a cross-browser trap on SVG while the pump rod
1025
+ and legs stay planted, so the handle strokes up and down the rod. */
1026
+ #thinking .tw-shadok .sh-bob { animation: tw-bob 0.62s ease-in-out infinite; }
1027
+ @keyframes tw-bob { 0%, 100% { transform: translateY(-1.6px); } 50% { transform: translateY(1.9px); } }
1030
1028
  @media (prefers-reduced-motion: reduce) {
1031
1029
  #thinking .tw-text { animation: none; color: var(--phosphor); -webkit-text-fill-color: currentColor; }
1032
- #thinking .tw-shadok .sh-body, #thinking .tw-shadok .sh-arm { animation: none; }
1030
+ #thinking .tw-shadok .sh-bob { animation: none; }
1033
1031
  }
1034
1032
 
1035
1033
  /* Composer */
@@ -3168,33 +3166,46 @@
3168
3166
  return v || fallback;
3169
3167
  }
3170
3168
  /** The Shadok itself — the cockpit's mascot, which famously PUMPS. One drawing
3171
- * serves every use: the favicon states here and the in-page "pumping"
3172
- * indicator. `dx` shifts it left to clear room for a "!" / "?"; `bob`/`armRot`
3173
- * pose a single frame of the pump (the favicon animates by re-generating with
3174
- * new values, like the old spinner did); `anim` instead tags the body and arm
3175
- * groups so CSS can drive them (used only in the DOM indicator, never a data
3176
- * URI CSS animation inside a favicon is unreliable). Legs stay planted. */
3177
- function shadokInner(fill, { dx = 0, bob = 0, armRot = 6, anim = false } = {}) {
3169
+ * serves every use. `bob` poses one frame of the pump (the favicon animates by
3170
+ * re-generating with new values); `anim` instead tags the bobbing group so CSS
3171
+ * drives it (the DOM indicator only CSS animation inside a favicon data URI
3172
+ * is unreliable). `pump` gives it a hand-pump a FIXED rod the Shadok works up
3173
+ * and down; that steady reference is what makes the bob read at favicon size, a
3174
+ * bob with nothing to measure against looked static. `sym` overlays a bold "!"
3175
+ * / "?" ON the Shadok, outlined in the ground colour so the accent-on-accent
3176
+ * "?" still reads. Legs (and, while pumping, the rod) stay planted; everything
3177
+ * else bobs. The body sits left when pumping, to seat the rod on its right. */
3178
+ function shadokInner(fill, { bob = 0, pump = false, anim = false, sym = null, symColor } = {}) {
3178
3179
  const base = themeColor("--bg", "#14161d");
3179
- const bodyCls = anim ? ' class="sh-body"' : "";
3180
- const armCls = anim ? ' class="sh-arm"' : "";
3181
- const bodyTf = anim ? "" : ` transform="translate(0 ${bob})"`;
3182
- const armTf = anim ? "" : ` transform="rotate(${armRot} 19.6 15.6)"`;
3180
+ const cx = pump ? 13 : 15;
3181
+ const bobCls = anim ? ' class="sh-bob"' : "";
3182
+ const bobTf = anim ? "" : ` transform="translate(0 ${bob})"`;
3183
+ // The fore-limb: a resting stub, or pumping an arm gripping a handle bar.
3184
+ // Both live INSIDE the bobbing group, so the handle strokes down the rod.
3185
+ const arm = pump
3186
+ ? `<rect x="${cx + 6.2}" y="12.6" width="6" height="1.7" rx="0.85"/>` +
3187
+ `<rect x="${cx + 5.8}" y="13.6" width="1.9" height="6" rx="0.95" transform="rotate(12 ${cx + 6.7} 13.6)"/>`
3188
+ : `<g transform="rotate(6 ${cx + 4.6} 15.6)"><rect x="${cx + 3.6}" y="15" width="2.1" height="8.4" rx="1.05"/></g>`;
3189
+ const rod = pump ? `<rect x="${cx + 9.6}" y="16.5" width="1.5" height="12.7" rx="0.6" fill="${fill}"/>` : "";
3190
+ const glyph = sym
3191
+ ? `<text x="${cx}" y="20.4" font-family="monospace" font-size="16" font-weight="800" fill="${symColor || fill}" stroke="${base}" stroke-width="2.6" paint-order="stroke" text-anchor="middle">${sym}</text>`
3192
+ : "";
3183
3193
  return (
3184
- `<g transform="translate(${dx} 0)">` +
3194
+ rod +
3185
3195
  // legs + feet (planted, not part of the bob)
3186
3196
  `<g fill="${fill}">` +
3187
- `<rect x="11.4" y="21" width="1.7" height="9" rx="0.85"/><rect x="17.4" y="21" width="1.7" height="9" rx="0.85"/>` +
3188
- `<rect x="9.2" y="28.7" width="4.6" height="1.7" rx="0.85"/><rect x="16.4" y="28.7" width="4.6" height="1.7" rx="0.85"/>` +
3197
+ `<rect x="${cx - 3.6}" y="21" width="1.7" height="9" rx="0.85"/><rect x="${cx + 2.4}" y="21" width="1.7" height="9" rx="0.85"/>` +
3198
+ `<rect x="${cx - 5.8}" y="28.7" width="4.6" height="1.7" rx="0.85"/><rect x="${cx + 1.4}" y="28.7" width="4.6" height="1.7" rx="0.85"/>` +
3199
+ `</g>` +
3200
+ // body + arm(/handle) + long neck + head + beak + eye — all bob together
3201
+ `<g${bobCls} fill="${fill}"${bobTf}>` +
3202
+ `<ellipse cx="${cx}" cy="16.8" rx="7.4" ry="7.6"/>` +
3203
+ arm +
3204
+ `<path d="M${cx - 0.4} 10 C ${cx - 0.4} 6.6, ${cx + 1.6} 4.8, ${cx + 3.9} 4.8" stroke="${fill}" stroke-width="3" fill="none" stroke-linecap="round"/>` +
3205
+ `<circle cx="${cx + 4.5}" cy="4.7" r="3"/><path d="M${cx + 7.1} 3.5 L${cx + 11.4} 5 L${cx + 7.1} 6.5 Z"/>` +
3206
+ `<circle cx="${cx + 5.2}" cy="4.2" r="0.95" fill="${base}"/>` +
3189
3207
  `</g>` +
3190
- // body + pumping arm + long neck + head + beak + eye
3191
- `<g${bodyCls} fill="${fill}"${bodyTf}>` +
3192
- `<ellipse cx="15" cy="16.8" rx="7.4" ry="7.6"/>` +
3193
- `<g${armCls}${armTf}><rect x="18.6" y="15" width="2.1" height="8.4" rx="1.05"/></g>` +
3194
- `<path d="M14.6 10 C 14.6 6.6, 16.6 4.8, 18.9 4.8" stroke="${fill}" stroke-width="3" fill="none" stroke-linecap="round"/>` +
3195
- `<circle cx="19.5" cy="4.7" r="3"/><path d="M22.1 3.5 L26.4 5 L22.1 6.5 Z"/>` +
3196
- `<circle cx="20.2" cy="4.2" r="0.95" fill="${base}"/>` +
3197
- `</g></g>`
3208
+ glyph
3198
3209
  );
3199
3210
  }
3200
3211
  function faviconWrap(inner) {
@@ -3207,27 +3218,21 @@
3207
3218
  )
3208
3219
  );
3209
3220
  }
3210
- /** The favicon: an accent Shadok on the dark ground. A waiting state adds a
3211
- * bold "!" (something to answer) or "?" (something to read) in its colour, and
3212
- * the Shadok slides left to make room — the coloured glyph is what the user
3213
- * asked to distinguish the two. No symbol → the idle Shadok. */
3221
+ /** The favicon: an accent Shadok on the dark ground. A waiting state stamps a
3222
+ * bold "!" (something to answer) or "?" (something to read) OVER it, in its
3223
+ * colour. No symbol the idle Shadok. */
3214
3224
  function faviconSVG(symbol, symColor) {
3215
3225
  const accent = themeColor("--amber", "#f0a848");
3216
- const shadok = shadokInner(accent, symbol ? { dx: -3.6 } : {});
3217
- const sym = symbol
3218
- ? `<text x="25.8" y="13" font-family="monospace" font-size="15" font-weight="800" fill="${symColor || accent}" text-anchor="middle">${symbol}</text>`
3219
- : "";
3220
- return faviconWrap(shadok + sym);
3226
+ return faviconWrap(shadokInner(accent, symbol ? { sym: symbol, symColor } : {}));
3221
3227
  }
3222
- /** The "working" favicon: the Shadok pumping. `phase` (0..PUMP_FRAMES-1) rides
3223
- * a cycle the body bobs and the arm swings, re-generated each tick. */
3228
+ /** The "working" favicon: the Shadok pumping. `phase` (0..PUMP_FRAMES-1) rides a
3229
+ * cycle; the whole Shadok heaves up and down against the fixed rod. */
3224
3230
  const PUMP_FRAMES = 8;
3225
3231
  function faviconPumpingSVG(phase) {
3226
3232
  const accent = themeColor("--amber", "#f0a848");
3227
3233
  const p = (Math.sin((phase / PUMP_FRAMES) * 2 * Math.PI - Math.PI / 2) + 1) / 2; // 0..1..0
3228
- const bob = +(p * 1.8).toFixed(2);
3229
- const armRot = Math.round(-8 + p * 32); // -8 (up) .. +24 (down)
3230
- return faviconWrap(shadokInner(accent, { bob, armRot }));
3234
+ const bob = +(-2 + p * 4.2).toFixed(2); // -2 (up) .. +2.2 (down): a big, visible stroke
3235
+ return faviconWrap(shadokInner(accent, { bob, pump: true }));
3231
3236
  }
3232
3237
  /** What each channel is asking for, as the pure module wants it. */
3233
3238
  function attentionInput() {
@@ -3299,7 +3304,7 @@
3299
3304
  const twShadok = document.querySelector("#thinking .tw-shadok");
3300
3305
  if (twShadok)
3301
3306
  twShadok.innerHTML =
3302
- `<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">${shadokInner("currentColor", { anim: true })}</svg>`;
3307
+ `<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">${shadokInner("currentColor", { pump: true, anim: true })}</svg>`;
3303
3308
  }
3304
3309
  // Coming back must stop the blink at once, not at the next tick. Both signals
3305
3310
  // matter: switching tabs fires visibilitychange, switching application only