openvibers/openvibe.actor Commits

Motion: Calm reduces, only Off stops (#402)

OP OpenVibers committed 3 days ago · 50cc7dded1 · 12 files, +12 −65

* Bump openvibe-shared v4.179.0 → v4.183.0

The pin and the lockfile only (ov bump, no model). CI's pin-drift check failed on v4.179.0.

* Motion: Calm reduces, only Off stops

Delete the CSS rules that stopped the pulses, the timeline and the two
transition effects under reduced motion; Calm plays them, smaller and slower.
The script now skips its glide only with motion Off, and the test asserts that.

* Pin: name openvibe-shared 4.183.0 in README and STATUS

Changes

ddiff --git a/README.md b/README.md
iindex 7043a81..78fb7aa 100644
---- a/README.md
++++ b/README.md
@@@ -266,5 +266,5 @@ Part of the [OpenVibe network](https://openvibe.network). Built in the open by [
<!-- versions:start -->
- openvibe-contracts: v0.384.0
- openvibe-sdk: v0.133.0
--- openvibe-shared: v4.179.0
++- openvibe-shared: v4.183.0
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex acbe8e3..eb358ce 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -9,11 +9,11 @@
"domain": "openvibe.actor",
"contracts": "openvibe-contracts v0.384.0",
"sdk": "openvibe-sdk v0.133.0",
-- "shared": "openvibe-shared v4.179.0",
++ "shared": "openvibe-shared v4.183.0",
"packages": [
"openvibe-contracts v0.384.0",
"openvibe-sdk v0.133.0",
-- "openvibe-shared v4.179.0"
++ "openvibe-shared v4.183.0"
],
"summary": "Public at https://openvibe.actor (sudo ovhost deploy actor; unit openvibe-actor on 127.0.0.1:4950). A task in plain words is classified, routed by openvibe-sdk/placement to the agent system that can do it (the OpenVibe runtime acting through OpenVibe.Search and OpenVibe.Tools, OpenAI's web agent, an open model on OpenVibe's server for private mode), run with its steps streamed live, checked by a model of another family, and delivered as platform.task@1 with its cost to a fraction of a cent and the explanation; a failed agent or check hands it to the next agent. Free tier per person with an operator ceiling.",
"works": [
ddiff --git a/package-lock.json b/package-lock.json
iindex cf4172e..b82ed1d 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -17,7 +17,7 @@
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.384.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.133.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.179.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.183.0",
"pg": "^8.23.0",
"sharp": "^0.34.5"
},
@@@ -143,9 +143,6 @@
"cpu": [
"arm"
],
-- "libc": [
-- "glibc"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -162,9 +159,6 @@
"cpu": [
"arm64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -181,9 +175,6 @@
"cpu": [
"ppc64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -200,9 +191,6 @@
"cpu": [
"riscv64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -219,9 +207,6 @@
"cpu": [
"s390x"
],
-- "libc": [
-- "glibc"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -238,9 +223,6 @@
"cpu": [
"x64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -257,9 +239,6 @@
"cpu": [
"arm64"
],
-- "libc": [
-- "musl"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -276,9 +255,6 @@
"cpu": [
"x64"
],
-- "libc": [
-- "musl"
-- ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@@ -295,9 +271,6 @@
"cpu": [
"arm"
],
-- "libc": [
-- "glibc"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -320,9 +293,6 @@
"cpu": [
"arm64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -345,9 +315,6 @@
"cpu": [
"ppc64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -370,9 +337,6 @@
"cpu": [
"riscv64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -395,9 +359,6 @@
"cpu": [
"s390x"
],
-- "libc": [
-- "glibc"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -420,9 +381,6 @@
"cpu": [
"x64"
],
-- "libc": [
-- "glibc"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -445,9 +403,6 @@
"cpu": [
"arm64"
],
-- "libc": [
-- "musl"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -470,9 +425,6 @@
"cpu": [
"x64"
],
-- "libc": [
-- "musl"
-- ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@@ -1723,9 +1675,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "4.179.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.179.0",
-- "integrity": "sha512-Fjffjq3gLINhiXTqQJwsKQT/QbV4TYvsmz6GTp5hBJ8xA6KUQgu0wDgCQ3BRxCZ0ehmn0HGVAHUI+5m0LtPQCQ==",
++ "version": "4.183.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.183.0",
++ "integrity": "sha512-vp9gg++Dhyj3h0cwvBjujM6dSFYoeXdh1UXdZ6OXP/NjG672Fs7uRANV4MjT467JtFDN7r7qLI3OJAwGQxOuQw==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0",
ddiff --git a/package.json b/package.json
iindex fa509c4..9168f5e 100644
---- a/package.json
++++ b/package.json
@@@ -30,7 +30,7 @@
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.384.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.133.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.179.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.183.0",
"pg": "^8.23.0",
"sharp": "^0.34.5"
},
ddiff --git a/public/css/actor.css b/public/css/actor.css
iindex 1387f10..4641453 100644
---- a/public/css/actor.css
++++ b/public/css/actor.css
@@@ -148,7 +148,6 @@ button.sc-btn.sc-primary { border: 0; }
/* A step's label says what differs on a phone: two lines, not one ellipsis that hides the query. */
.task-session .ovas-sum b { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
}
--@media (prefers-reduced-motion: reduce) { .tl-item, .dot-pulse { animation: none; } .mode span { transition: none; } }
/* /agents: who does the work, as plain cards (plan L55; the owner, 2026-11-01: "so confusing"). */
ddiff --git a/public/css/chat.css b/public/css/chat.css
iindex 7f81730..6be94c4 100644
---- a/public/css/chat.css
++++ b/public/css/chat.css
@@@ -173,7 +173,6 @@ body:has(.page-app) > footer, body:has(.page-app) #ov-footer, body:has(.page-app
@keyframes ct-breathe { 0%, 100% { opacity: .55; transform: scale(.94); } 50% { opacity: 1; transform: scale(1); } }
@keyframes ct-shimmer { from { background-position: 100% 0; } to { background-position: -50% 0; } }
--@media (prefers-reduced-motion: reduce) { .ct-hello-mark, .ct-live::before { animation: none !important; } }
/* ── The canvas (plan HO9, actor.canvas@1) ───────────────────────────────────────────────────────────────────────
The same data document in two places: the thread's third column on a wide screen (thread.css's own panel, which is
ddiff --git a/public/css/home.css b/public/css/home.css
iindex 6b07e5b..b44d2ec 100644
---- a/public/css/home.css
++++ b/public/css/home.css
@@@ -82,7 +82,6 @@
.hm-now-dot { flex: none; width: 10px; height: 10px; margin-top: 6px; border-radius: 50%; background: var(--success, #22c55e);
box-shadow: 0 0 0 4px color-mix(in srgb, var(--success, #22c55e) 22%, transparent); animation: hmNowPulse 1.8s ease-in-out infinite; }
@keyframes hmNowPulse { 50% { opacity: .45; } }
--@media (prefers-reduced-motion: reduce) { .hm-now-dot { animation: none; } }
.hm-now-done { margin: 0; padding-left: 20px; display: grid; gap: 4px; color: var(--text-secondary, #b6bdd2); font-size: .9rem; }
.hm-now-ask { display: grid; gap: 4px; padding: 12px; border-radius: 12px; background: color-mix(in srgb, var(--accent, #3b82f6) 12%, transparent);
border: 1px solid color-mix(in srgb, var(--accent, #3b82f6) 35%, transparent); }
ddiff --git a/public/css/task.css b/public/css/task.css
iindex d664412..79678f5 100644
---- a/public/css/task.css
++++ b/public/css/task.css
@@@ -18,7 +18,6 @@
.plan-assume { margin: .4rem 0 0 32px; font-size: .85rem; color: var(--text-muted, #7386a3); }
.plan-assume[hidden] { display: none; }
@keyframes ps-pulse { from { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent, #3b82f6) 50%, transparent); } to { box-shadow: 0 0 0 7px transparent; } }
--@media (prefers-reduced-motion: reduce) { .ps.is-active .ps-mark { animation: none; } }
.tl-plan .tl-k { color: var(--accent-light, #60a5fa); }
/* An answer's citations: a numbered chip per piece of evidence, opening what that tool returned. */
@@@ -95,7 +94,6 @@
.follow-form .sc-btn { flex: none; min-height: 40px; padding: 0 18px; border-radius: 12px; }
.follow-hint { margin: .45rem 0 0 4px; font-size: .82rem; color: var(--text-muted, #7386a3); }
--@media (prefers-reduced-motion: reduce) { .ps, .ps.is-active .ps-mark { animation: none; } .ev, .ev-item { transition: none; } }
/* A cited memory (Actor v2, stage V2-6): what the answer leaned on, opening the row on /memory with its source. */
.ev-mem { margin: .5rem 0 0; padding: .5rem .65rem; border-left: 2px solid var(--accent); border-radius: 0 8px 8px 0; background: color-mix(in srgb, var(--accent) 6%, transparent); }
ddiff --git a/public/css/you.css b/public/css/you.css
iindex f4d5f80..27996f7 100644
---- a/public/css/you.css
++++ b/public/css/you.css
@@@ -1,4 +1,4 @@
--.ay-page{max-width:1120px;margin:28px auto 80px;padding:0 20px;color:var(--text-primary);overflow-wrap:anywhere}.ay-page *{box-sizing:border-box}.ay-page h2{font-size:1.25rem;margin:0}.ay-page h3{font-size:1rem}.ay-header{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:12px 0 24px;border-bottom:1px solid var(--border-light)}.ay-avatar{width:52px;height:52px;border-radius:18px;display:grid;place-items:center;background:var(--bg-secondary);font-size:24px;color:var(--accent-light);overflow:hidden}.ay-avatar img{width:100%;height:100%;object-fit:cover}.ay-name{flex:1;min-width:120px}.ay-eyebrow{display:block;color:var(--text-secondary);font-size:12px;letter-spacing:.12em}.ay-name-button{display:block;padding:0;border:0;background:none;color:inherit;font-size:1.6rem;font-weight:700;text-align:left;min-height:44px;cursor:pointer}.ay-chips{display:flex;gap:8px;flex-wrap:wrap}.ay-state{display:flex;align-items:center;gap:7px;min-height:32px}.ay-layout{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px}.ay-card{min-width:0;margin:0;padding:22px;border:1px solid var(--border-light);border-radius:18px;background:var(--bg-card,var(--bg-secondary))}.ay-section-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}#ay-now,#ay-asks,#ay-tell,#ay-today,#ay-goals{grid-column:1/-1}.ay-current{font-size:1.2rem;line-height:1.6;margin:6px 0 14px}.ay-pulse{display:inline-block;width:8px;height:8px;border-radius:50%;background:#4cae88;margin-right:8px;animation:ay-pulse 2s ease-in-out infinite}@keyframes ay-pulse{50%{opacity:.35}}@media(prefers-reduced-motion:reduce){.ay-pulse{animation:none}}.ay-looking{display:flex;gap:8px;align-items:center;color:var(--text-secondary)}.ay-looking svg{width:20px;flex:none}.ay-steps,.ay-journal{list-style:none;margin:0;padding:0}.ay-steps li{display:flex;gap:14px;margin:10px 0}.ay-page time,.ay-muted,.ay-next,.ay-page small{color:var(--text-secondary)}.ay-page time{font-size:12px;white-space:nowrap}.ay-spend{display:flex;align-items:center;gap:20px;margin-top:20px;font-size:13px}.ay-spend progress{flex:1;height:5px;min-width:40px;accent-color:var(--accent)}.ay-ask{padding:16px 0;border-top:1px solid var(--border-light)}.ay-ask:first-of-type{border:0;padding-top:0}.ay-ask blockquote{margin:12px 0;padding:12px;border-left:3px solid var(--accent);background:var(--bg-primary);white-space:pre-wrap}.ay-actions{display:flex;gap:8px;flex-wrap:wrap}.ay-page .ovk-btn,.ay-page input:not([type=checkbox]):not([type=hidden]),.ay-page select{min-height:44px}.ay-page .ovk-btn{white-space:normal}.ay-page label{display:grid;gap:7px;font-size:13px;margin:10px 0}.ay-page input:not([type=checkbox]):not([type=hidden]),.ay-page select,.ay-page textarea{width:100%;max-width:100%;padding:10px 12px;border:1px solid var(--border-light);border-radius:10px;background:var(--bg-primary);color:inherit;font:inherit}.ay-page textarea{min-height:90px;resize:vertical}.ay-page .ay-check{display:flex;align-items:center;gap:10px;min-height:44px}.ay-page input[type=checkbox]{width:20px;height:20px;accent-color:var(--accent);flex:none}.ay-page summary{min-height:44px;display:flex;align-items:center;gap:8px;cursor:pointer}.ay-thread{display:block;min-height:0}.ay-thread .ovt-composer{position:static;margin:0;background:var(--bg-primary)}.ay-thread textarea{min-height:60px}.ay-thread .ovt-attach,.ay-thread .ovt-send{width:44px;height:44px;min-height:44px}.ay-thread .ovt-turn{margin-top:18px}.ay-journal li{display:grid;grid-template-columns:42px minmax(0,1fr) auto;gap:10px;margin:18px 0}.ay-journal p{margin:0;line-height:1.5}.ay-journal img{max-width:110px;max-height:70px;object-fit:cover;border-radius:7px;margin-bottom:7px}.ay-goal-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-bottom:18px}.ay-goal{padding:18px;border-radius:12px;border:1px solid var(--border-light);background:var(--bg-primary)}.ay-goal header,.ay-goal footer{display:flex;gap:8px;align-items:center}.ay-goal header>svg{width:18px}.ay-goal footer{justify-content:space-between}.ay-goal .ay-switch{margin-left:auto;display:flex;align-items:center;min-height:44px}.ay-goal h3{font-size:1.1rem}.ay-goal p{font-size:13px;line-height:1.6}.ay-money-total{display:flex;gap:25px;flex-wrap:wrap}.ay-money-total span{display:block;font-size:12px;color:var(--text-secondary)}.ay-money-total strong{font-size:1.7rem}.ay-week{display:grid;grid-template-columns:minmax(0,1fr) minmax(50px,1fr) auto;gap:10px;align-items:center;margin:12px 0;font-size:12px}.ay-week meter{width:100%}.ay-page dialog{color:var(--text-primary)}.ay-page .ay-model{width:100%;display:flex;justify-content:space-between;text-align:left;flex-wrap:wrap;margin:7px 0}.ay-model small{font-weight:400}.ay-lanes{display:grid;gap:10px}.ay-lane{display:flex;align-items:center;gap:14px;width:100%;padding:16px!important}.ay-lane svg{width:24px}.ay-days{display:flex;flex-wrap:wrap;gap:6px}.ay-days label{display:flex;align-items:center;gap:4px;min-height:44px}.ay-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}.ay-page fieldset{border:1px solid var(--border-light);border-radius:10px}.ay-screen{position:relative;aspect-ratio:16/9;overflow:hidden;border-radius:12px;background:var(--bg-primary);margin-bottom:12px}.ay-screen img{width:100%;height:100%;object-fit:contain;display:block}.ay-screen[data-control=true] img{cursor:crosshair;touch-action:none}.ay-screen:fullscreen{border-radius:0}.ay-screen-note{position:absolute;bottom:6px;left:10px;font-size:12px}.ay-error{color:var(--danger,#d45f63)}#ay-notice:empty{display:none}#ay-notice{padding:12px;border:1px solid var(--border-light);border-radius:10px}.ay-page [hidden]{display:none!important}.ay-page a{color:var(--accent-light,var(--accent))}#ay-sites li{display:flex;justify-content:space-between;align-items:center;gap:12px;margin:10px 0}#ay-sites ul{padding:0;list-style:none}@media(max-width:680px){.ay-page{padding:0 14px;margin-top:16px}.ay-layout{grid-template-columns:minmax(0,1fr);gap:14px}.ay-card{padding:18px}.ay-header{gap:8px}.ay-chips{width:100%}.ay-goal-grid{grid-template-columns:minmax(0,1fr)}.ay-spend{gap:12px}.ay-journal li{grid-template-columns:35px minmax(0,1fr) auto;gap:7px}.ay-name-button{font-size:1.35rem}.ay-screen{margin-inline:-4px}.ay-week{grid-template-columns:minmax(0,1fr) 60px auto}}
++.ay-page{max-width:1120px;margin:28px auto 80px;padding:0 20px;color:var(--text-primary);overflow-wrap:anywhere}.ay-page *{box-sizing:border-box}.ay-page h2{font-size:1.25rem;margin:0}.ay-page h3{font-size:1rem}.ay-header{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:12px 0 24px;border-bottom:1px solid var(--border-light)}.ay-avatar{width:52px;height:52px;border-radius:18px;display:grid;place-items:center;background:var(--bg-secondary);font-size:24px;color:var(--accent-light);overflow:hidden}.ay-avatar img{width:100%;height:100%;object-fit:cover}.ay-name{flex:1;min-width:120px}.ay-eyebrow{display:block;color:var(--text-secondary);font-size:12px;letter-spacing:.12em}.ay-name-button{display:block;padding:0;border:0;background:none;color:inherit;font-size:1.6rem;font-weight:700;text-align:left;min-height:44px;cursor:pointer}.ay-chips{display:flex;gap:8px;flex-wrap:wrap}.ay-state{display:flex;align-items:center;gap:7px;min-height:32px}.ay-layout{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px}.ay-card{min-width:0;margin:0;padding:22px;border:1px solid var(--border-light);border-radius:18px;background:var(--bg-card,var(--bg-secondary))}.ay-section-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}#ay-now,#ay-asks,#ay-tell,#ay-today,#ay-goals{grid-column:1/-1}.ay-current{font-size:1.2rem;line-height:1.6;margin:6px 0 14px}.ay-pulse{display:inline-block;width:8px;height:8px;border-radius:50%;background:#4cae88;margin-right:8px;animation:ay-pulse 2s ease-in-out infinite}@keyframes ay-pulse{50%{opacity:.35}}.ay-looking{display:flex;gap:8px;align-items:center;color:var(--text-secondary)}.ay-looking svg{width:20px;flex:none}.ay-steps,.ay-journal{list-style:none;margin:0;padding:0}.ay-steps li{display:flex;gap:14px;margin:10px 0}.ay-page time,.ay-muted,.ay-next,.ay-page small{color:var(--text-secondary)}.ay-page time{font-size:12px;white-space:nowrap}.ay-spend{display:flex;align-items:center;gap:20px;margin-top:20px;font-size:13px}.ay-spend progress{flex:1;height:5px;min-width:40px;accent-color:var(--accent)}.ay-ask{padding:16px 0;border-top:1px solid var(--border-light)}.ay-ask:first-of-type{border:0;padding-top:0}.ay-ask blockquote{margin:12px 0;padding:12px;border-left:3px solid var(--accent);background:var(--bg-primary);white-space:pre-wrap}.ay-actions{display:flex;gap:8px;flex-wrap:wrap}.ay-page .ovk-btn,.ay-page input:not([type=checkbox]):not([type=hidden]),.ay-page select{min-height:44px}.ay-page .ovk-btn{white-space:normal}.ay-page label{display:grid;gap:7px;font-size:13px;margin:10px 0}.ay-page input:not([type=checkbox]):not([type=hidden]),.ay-page select,.ay-page textarea{width:100%;max-width:100%;padding:10px 12px;border:1px solid var(--border-light);border-radius:10px;background:var(--bg-primary);color:inherit;font:inherit}.ay-page textarea{min-height:90px;resize:vertical}.ay-page .ay-check{display:flex;align-items:center;gap:10px;min-height:44px}.ay-page input[type=checkbox]{width:20px;height:20px;accent-color:var(--accent);flex:none}.ay-page summary{min-height:44px;display:flex;align-items:center;gap:8px;cursor:pointer}.ay-thread{display:block;min-height:0}.ay-thread .ovt-composer{position:static;margin:0;background:var(--bg-primary)}.ay-thread textarea{min-height:60px}.ay-thread .ovt-attach,.ay-thread .ovt-send{width:44px;height:44px;min-height:44px}.ay-thread .ovt-turn{margin-top:18px}.ay-journal li{display:grid;grid-template-columns:42px minmax(0,1fr) auto;gap:10px;margin:18px 0}.ay-journal p{margin:0;line-height:1.5}.ay-journal img{max-width:110px;max-height:70px;object-fit:cover;border-radius:7px;margin-bottom:7px}.ay-goal-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-bottom:18px}.ay-goal{padding:18px;border-radius:12px;border:1px solid var(--border-light);background:var(--bg-primary)}.ay-goal header,.ay-goal footer{display:flex;gap:8px;align-items:center}.ay-goal header>svg{width:18px}.ay-goal footer{justify-content:space-between}.ay-goal .ay-switch{margin-left:auto;display:flex;align-items:center;min-height:44px}.ay-goal h3{font-size:1.1rem}.ay-goal p{font-size:13px;line-height:1.6}.ay-money-total{display:flex;gap:25px;flex-wrap:wrap}.ay-money-total span{display:block;font-size:12px;color:var(--text-secondary)}.ay-money-total strong{font-size:1.7rem}.ay-week{display:grid;grid-template-columns:minmax(0,1fr) minmax(50px,1fr) auto;gap:10px;align-items:center;margin:12px 0;font-size:12px}.ay-week meter{width:100%}.ay-page dialog{color:var(--text-primary)}.ay-page .ay-model{width:100%;display:flex;justify-content:space-between;text-align:left;flex-wrap:wrap;margin:7px 0}.ay-model small{font-weight:400}.ay-lanes{display:grid;gap:10px}.ay-lane{display:flex;align-items:center;gap:14px;width:100%;padding:16px!important}.ay-lane svg{width:24px}.ay-days{display:flex;flex-wrap:wrap;gap:6px}.ay-days label{display:flex;align-items:center;gap:4px;min-height:44px}.ay-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}.ay-page fieldset{border:1px solid var(--border-light);border-radius:10px}.ay-screen{position:relative;aspect-ratio:16/9;overflow:hidden;border-radius:12px;background:var(--bg-primary);margin-bottom:12px}.ay-screen img{width:100%;height:100%;object-fit:contain;display:block}.ay-screen[data-control=true] img{cursor:crosshair;touch-action:none}.ay-screen:fullscreen{border-radius:0}.ay-screen-note{position:absolute;bottom:6px;left:10px;font-size:12px}.ay-error{color:var(--danger,#d45f63)}#ay-notice:empty{display:none}#ay-notice{padding:12px;border:1px solid var(--border-light);border-radius:10px}.ay-page [hidden]{display:none!important}.ay-page a{color:var(--accent-light,var(--accent))}#ay-sites li{display:flex;justify-content:space-between;align-items:center;gap:12px;margin:10px 0}#ay-sites ul{padding:0;list-style:none}@media(max-width:680px){.ay-page{padding:0 14px;margin-top:16px}.ay-layout{grid-template-columns:minmax(0,1fr);gap:14px}.ay-card{padding:18px}.ay-header{gap:8px}.ay-chips{width:100%}.ay-goal-grid{grid-template-columns:minmax(0,1fr)}.ay-spend{gap:12px}.ay-journal li{grid-template-columns:35px minmax(0,1fr) auto;gap:7px}.ay-name-button{font-size:1.35rem}.ay-screen{margin-inline:-4px}.ay-week{grid-template-columns:minmax(0,1fr) 60px auto}}
/* Now: the model for the next step. One row (the picker takes the width, the button stays one word); a quiet inset so it
reads as a control of the run above it, not as another card. */
.ay-run-model{display:grid;gap:6px;margin:0 0 14px;padding:12px;border:1px solid var(--border);border-radius:12px;background:color-mix(in srgb,var(--text-primary) 3%,transparent)}
ddiff --git a/public/js/chat.js b/public/js/chat.js
iindex 6cdc46b..35dceae 100644
---- a/public/js/chat.js
++++ b/public/js/chat.js
@@@ -30,7 +30,7 @@
var send = chat.querySelector('[data-ovt-send]');
var note = chat.querySelector('[data-cc-note]');
var fine = window.matchMedia && window.matchMedia('(hover: hover) and (pointer: fine)').matches;
-- var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
++ var reduce = document.documentElement.getAttribute('data-ov-motion') === 'off';
// ── The canvas (plan HO9). The document rides in an inert template; openvibe-shared's ov-canvas.js draws it
// into the wide panel and the phone fold from the same data. A button's label goes to the agent as the
ddiff --git a/public/js/task.js b/public/js/task.js
iindex 0e42a08..1c0f30a 100644
---- a/public/js/task.js
++++ b/public/js/task.js
@@@ -107,7 +107,7 @@
item.classList.add('is-flash', 'is-open');
chip.classList.add('is-on');
try { history.replaceState(null, '', '#ev-' + chip.getAttribute('data-ev')); } catch (err) { /* a sandboxed frame */ }
-- var still = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
++ var still = document.documentElement.getAttribute('data-ov-motion') === 'off';
item.scrollIntoView({ behavior: still ? 'auto' : 'smooth', block: 'center' });
setTimeout(function () { item.classList.remove('is-flash'); chip.classList.remove('is-on'); }, 2400);
});
ddiff --git a/test/chat.test.js b/test/chat.test.js
iindex 38fad1a..448eacc 100644
---- a/test/chat.test.js
++++ b/test/chat.test.js
@@@ -179,7 +179,7 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;
assert.match(js, /'\/chat\/' \+ encodeURIComponent\(w\.getAttribute\('data-task'\)\) \+ '\/steer'/, 'what you write while it works steers it');
assert.match(js, /'\/tasks\/' \+ encodeURIComponent\(id\) \+ '\/look\?at='/, 'the screen refreshes from the last picture');
assert.match(js, /\(hover: hover\) and \(pointer: fine\)/, 'Enter sends only with a keyboard and mouse; a phone\'s Enter is a new line');
-- assert.match(js, /prefers-reduced-motion: reduce/);
++ assert.match(js, /document\.documentElement\.getAttribute\('data-ov-motion'\) === 'off'/, 'only motion Off skips the glide');
// The checked answer types in word by word, Copy leaves out the citation numbers, and reduced motion is
// respected: the network's conversation UI does it (openvibe-shared/ov-thread.js, L55 C4); Actor swaps the
// finished turn in through it and marks its citations whole and not for copying.