aimeat 2.5.0 → 2.6.0

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 (256) hide show
  1. package/dist/.env.example +33 -0
  2. package/dist/build-stamp.json +13 -0
  3. package/dist/locales/en.json +166 -3
  4. package/dist/locales/fi.json +166 -3
  5. package/dist/public/components/VoiceRecorder.js +116 -0
  6. package/dist/public/connection-done.html +53 -0
  7. package/dist/public/css/components/voice-recorder.css +66 -0
  8. package/dist/public/css/views/inbox.css +41 -0
  9. package/dist/public/css/views/profile.css +171 -95
  10. package/dist/public/js/services/audio-recorder.js +171 -0
  11. package/dist/public/js/services/messages.js +21 -2
  12. package/dist/public/spa.html +3 -0
  13. package/dist/public/views/profile/access-tab/connections.js +264 -0
  14. package/dist/public/views/profile/access-tab.js +2 -0
  15. package/dist/public/views/profile/inbox-tab/components.js +60 -10
  16. package/dist/public/views/profile/inbox-tab/helpers.js +33 -0
  17. package/dist/public/views/profile/inbox-tab/panels.js +6 -1
  18. package/dist/public/views/profile/inbox-tab/use-voice.js +50 -0
  19. package/dist/public/views/profile/inbox-tab/voice-parts.js +111 -0
  20. package/dist/public/views/profile/inbox-tab.js +18 -24
  21. package/dist/public/views/profile/openrouter/budget-panel.js +224 -0
  22. package/dist/public/views/profile/openrouter/model-picker.js +150 -0
  23. package/dist/public/views/profile/openrouter/pricing.js +139 -0
  24. package/dist/public/views/profile/openrouter-settings.js +425 -488
  25. package/dist/scripts/build-sdk-libs.d.ts.map +1 -1
  26. package/dist/scripts/build-sdk-libs.js +1 -0
  27. package/dist/scripts/build-sdk-libs.js.map +1 -1
  28. package/dist/scripts/check-ai-disclosure.d.ts.map +1 -1
  29. package/dist/scripts/check-ai-disclosure.js +65 -0
  30. package/dist/scripts/check-ai-disclosure.js.map +1 -1
  31. package/dist/src/cli/connect/ai-provenance-carry.d.ts +54 -3
  32. package/dist/src/cli/connect/ai-provenance-carry.d.ts.map +1 -1
  33. package/dist/src/cli/connect/ai-provenance-carry.js +84 -12
  34. package/dist/src/cli/connect/ai-provenance-carry.js.map +1 -1
  35. package/dist/src/cli/connect/api-client.d.ts +11 -0
  36. package/dist/src/cli/connect/api-client.d.ts.map +1 -1
  37. package/dist/src/cli/connect/api-client.js +2 -0
  38. package/dist/src/cli/connect/api-client.js.map +1 -1
  39. package/dist/src/cli/connect/mcp/local-server.d.ts.map +1 -1
  40. package/dist/src/cli/connect/mcp/local-server.js +11 -0
  41. package/dist/src/cli/connect/mcp/local-server.js.map +1 -1
  42. package/dist/src/cli/connect/mcp/tools/apps.d.ts +1 -0
  43. package/dist/src/cli/connect/mcp/tools/apps.d.ts.map +1 -1
  44. package/dist/src/cli/connect/mcp/tools/apps.js +3 -2
  45. package/dist/src/cli/connect/mcp/tools/apps.js.map +1 -1
  46. package/dist/src/cli/connect/mcp/tools/core.d.ts +2 -0
  47. package/dist/src/cli/connect/mcp/tools/core.d.ts.map +1 -1
  48. package/dist/src/cli/connect/mcp/tools/core.js +5 -2
  49. package/dist/src/cli/connect/mcp/tools/core.js.map +1 -1
  50. package/dist/src/cli/connect/mcp/tools/knowledge.d.ts +1 -0
  51. package/dist/src/cli/connect/mcp/tools/knowledge.d.ts.map +1 -1
  52. package/dist/src/cli/connect/mcp/tools/knowledge.js +3 -2
  53. package/dist/src/cli/connect/mcp/tools/knowledge.js.map +1 -1
  54. package/dist/src/config-types.d.ts +14 -0
  55. package/dist/src/config-types.d.ts.map +1 -1
  56. package/dist/src/config.d.ts.map +1 -1
  57. package/dist/src/config.js +10 -0
  58. package/dist/src/config.js.map +1 -1
  59. package/dist/src/generated/api-types.d.ts +969 -4
  60. package/dist/src/generated/api-types.d.ts.map +1 -1
  61. package/dist/src/mcp/ai-provenance-input.d.ts +33 -0
  62. package/dist/src/mcp/ai-provenance-input.d.ts.map +1 -1
  63. package/dist/src/mcp/ai-provenance-input.js +36 -0
  64. package/dist/src/mcp/ai-provenance-input.js.map +1 -1
  65. package/dist/src/mcp/apps.d.ts +7 -0
  66. package/dist/src/mcp/apps.d.ts.map +1 -1
  67. package/dist/src/mcp/apps.js +20 -2
  68. package/dist/src/mcp/apps.js.map +1 -1
  69. package/dist/src/models/ai-provenance-schemas.d.ts +7 -1
  70. package/dist/src/models/ai-provenance-schemas.d.ts.map +1 -1
  71. package/dist/src/models/ai-provenance-schemas.js +11 -1
  72. package/dist/src/models/ai-provenance-schemas.js.map +1 -1
  73. package/dist/src/models/connection-schemas.d.ts +203 -0
  74. package/dist/src/models/connection-schemas.d.ts.map +1 -0
  75. package/dist/src/models/connection-schemas.js +33 -0
  76. package/dist/src/models/connection-schemas.js.map +1 -0
  77. package/dist/src/models/message-schemas.d.ts +40 -0
  78. package/dist/src/models/message-schemas.d.ts.map +1 -1
  79. package/dist/src/models/message-schemas.js +23 -0
  80. package/dist/src/models/message-schemas.js.map +1 -1
  81. package/dist/src/routes/ai-provenance.d.ts +6 -0
  82. package/dist/src/routes/ai-provenance.d.ts.map +1 -1
  83. package/dist/src/routes/ai-provenance.js +34 -1
  84. package/dist/src/routes/ai-provenance.js.map +1 -1
  85. package/dist/src/routes/ai.d.ts +5 -0
  86. package/dist/src/routes/ai.d.ts.map +1 -1
  87. package/dist/src/routes/ai.js +83 -0
  88. package/dist/src/routes/ai.js.map +1 -1
  89. package/dist/src/routes/app-grants.d.ts.map +1 -1
  90. package/dist/src/routes/app-grants.js +4 -0
  91. package/dist/src/routes/app-grants.js.map +1 -1
  92. package/dist/src/routes/apps/drafts.d.ts +3 -0
  93. package/dist/src/routes/apps/drafts.d.ts.map +1 -1
  94. package/dist/src/routes/apps/drafts.js +13 -0
  95. package/dist/src/routes/apps/drafts.js.map +1 -1
  96. package/dist/src/routes/apps/publish.d.ts +5 -0
  97. package/dist/src/routes/apps/publish.d.ts.map +1 -1
  98. package/dist/src/routes/apps/publish.js +21 -5
  99. package/dist/src/routes/apps/publish.js.map +1 -1
  100. package/dist/src/routes/connections.d.ts +35 -0
  101. package/dist/src/routes/connections.d.ts.map +1 -0
  102. package/dist/src/routes/connections.js +406 -0
  103. package/dist/src/routes/connections.js.map +1 -0
  104. package/dist/src/routes/libs.js +1 -1
  105. package/dist/src/routes/libs.js.map +1 -1
  106. package/dist/src/routes/messages.d.ts +5 -0
  107. package/dist/src/routes/messages.d.ts.map +1 -1
  108. package/dist/src/routes/messages.js +92 -0
  109. package/dist/src/routes/messages.js.map +1 -1
  110. package/dist/src/routes/openrouter.d.ts +6 -1
  111. package/dist/src/routes/openrouter.d.ts.map +1 -1
  112. package/dist/src/routes/openrouter.js +37 -7
  113. package/dist/src/routes/openrouter.js.map +1 -1
  114. package/dist/src/routes/upload.d.ts +5 -0
  115. package/dist/src/routes/upload.d.ts.map +1 -1
  116. package/dist/src/routes/upload.js +32 -0
  117. package/dist/src/routes/upload.js.map +1 -1
  118. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  119. package/dist/src/server-bootstrap/routes-loader.js +2 -0
  120. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  121. package/dist/src/services/ai-completion.d.ts +48 -0
  122. package/dist/src/services/ai-completion.d.ts.map +1 -1
  123. package/dist/src/services/ai-completion.js +112 -72
  124. package/dist/src/services/ai-completion.js.map +1 -1
  125. package/dist/src/services/ai-disclosure.d.ts +6 -0
  126. package/dist/src/services/ai-disclosure.d.ts.map +1 -1
  127. package/dist/src/services/ai-disclosure.js +20 -2
  128. package/dist/src/services/ai-disclosure.js.map +1 -1
  129. package/dist/src/services/ai-provenance-page.d.ts +59 -0
  130. package/dist/src/services/ai-provenance-page.d.ts.map +1 -0
  131. package/dist/src/services/ai-provenance-page.js +185 -0
  132. package/dist/src/services/ai-provenance-page.js.map +1 -0
  133. package/dist/src/services/ai-provenance.d.ts +6 -0
  134. package/dist/src/services/ai-provenance.d.ts.map +1 -1
  135. package/dist/src/services/ai-provenance.js +5 -0
  136. package/dist/src/services/ai-provenance.js.map +1 -1
  137. package/dist/src/services/ai-transcription.d.ts +66 -0
  138. package/dist/src/services/ai-transcription.d.ts.map +1 -0
  139. package/dist/src/services/ai-transcription.js +90 -0
  140. package/dist/src/services/ai-transcription.js.map +1 -0
  141. package/dist/src/services/app-publish.d.ts.map +1 -1
  142. package/dist/src/services/app-publish.js +16 -1
  143. package/dist/src/services/app-publish.js.map +1 -1
  144. package/dist/src/services/build-app-prompt.d.ts.map +1 -1
  145. package/dist/src/services/build-app-prompt.js +2 -1
  146. package/dist/src/services/build-app-prompt.js.map +1 -1
  147. package/dist/src/services/connections/attach.d.ts +62 -0
  148. package/dist/src/services/connections/attach.d.ts.map +1 -0
  149. package/dist/src/services/connections/attach.js +168 -0
  150. package/dist/src/services/connections/attach.js.map +1 -0
  151. package/dist/src/services/connections/credential.d.ts +39 -0
  152. package/dist/src/services/connections/credential.d.ts.map +1 -0
  153. package/dist/src/services/connections/credential.js +66 -0
  154. package/dist/src/services/connections/credential.js.map +1 -0
  155. package/dist/src/services/connections/instance.d.ts +65 -0
  156. package/dist/src/services/connections/instance.d.ts.map +1 -0
  157. package/dist/src/services/connections/instance.js +144 -0
  158. package/dist/src/services/connections/instance.js.map +1 -0
  159. package/dist/src/services/connections/oauth.d.ts +77 -0
  160. package/dist/src/services/connections/oauth.d.ts.map +1 -0
  161. package/dist/src/services/connections/oauth.js +290 -0
  162. package/dist/src/services/connections/oauth.js.map +1 -0
  163. package/dist/src/services/connections/providers.d.ts +118 -0
  164. package/dist/src/services/connections/providers.d.ts.map +1 -0
  165. package/dist/src/services/connections/providers.js +260 -0
  166. package/dist/src/services/connections/providers.js.map +1 -0
  167. package/dist/src/services/connections/publish-gate.d.ts +103 -0
  168. package/dist/src/services/connections/publish-gate.d.ts.map +1 -0
  169. package/dist/src/services/connections/publish-gate.js +0 -0
  170. package/dist/src/services/connections/publish-gate.js.map +1 -0
  171. package/dist/src/services/connections/publish.d.ts +60 -0
  172. package/dist/src/services/connections/publish.d.ts.map +1 -0
  173. package/dist/src/services/connections/publish.js +340 -0
  174. package/dist/src/services/connections/publish.js.map +1 -0
  175. package/dist/src/services/connections/refresh.d.ts +55 -0
  176. package/dist/src/services/connections/refresh.d.ts.map +1 -0
  177. package/dist/src/services/connections/refresh.js +307 -0
  178. package/dist/src/services/connections/refresh.js.map +1 -0
  179. package/dist/src/services/message-send.d.ts.map +1 -1
  180. package/dist/src/services/message-send.js +16 -2
  181. package/dist/src/services/message-send.js.map +1 -1
  182. package/dist/src/services/openrouter.d.ts +67 -1
  183. package/dist/src/services/openrouter.d.ts.map +1 -1
  184. package/dist/src/services/openrouter.js +102 -11
  185. package/dist/src/services/openrouter.js.map +1 -1
  186. package/dist/src/services/upload-token.d.ts +5 -1
  187. package/dist/src/services/upload-token.d.ts.map +1 -1
  188. package/dist/src/services/upload-token.js +13 -1
  189. package/dist/src/services/upload-token.js.map +1 -1
  190. package/dist/src/services/workflow/engine-util.d.ts +18 -0
  191. package/dist/src/services/workflow/engine-util.d.ts.map +1 -1
  192. package/dist/src/services/workflow/engine-util.js +27 -0
  193. package/dist/src/services/workflow/engine-util.js.map +1 -1
  194. package/dist/src/services/workflow/engine.d.ts.map +1 -1
  195. package/dist/src/services/workflow/engine.js +4 -2
  196. package/dist/src/services/workflow/engine.js.map +1 -1
  197. package/dist/src/storage/interface.d.ts +2 -1
  198. package/dist/src/storage/interface.d.ts.map +1 -1
  199. package/dist/src/storage/providers/postgres-kysely/db-types.d.ts +65 -0
  200. package/dist/src/storage/providers/postgres-kysely/db-types.d.ts.map +1 -1
  201. package/dist/src/storage/providers/postgres-kysely/index.d.ts.map +1 -1
  202. package/dist/src/storage/providers/postgres-kysely/index.js +2 -1
  203. package/dist/src/storage/providers/postgres-kysely/index.js.map +1 -1
  204. package/dist/src/storage/providers/postgres-kysely/methods/connections.d.ts +44 -0
  205. package/dist/src/storage/providers/postgres-kysely/methods/connections.d.ts.map +1 -0
  206. package/dist/src/storage/providers/postgres-kysely/methods/connections.js +308 -0
  207. package/dist/src/storage/providers/postgres-kysely/methods/connections.js.map +1 -0
  208. package/dist/src/storage/providers/postgres-kysely/methods/node-infra.d.ts.map +1 -1
  209. package/dist/src/storage/providers/postgres-kysely/methods/node-infra.js +4 -2
  210. package/dist/src/storage/providers/postgres-kysely/methods/node-infra.js.map +1 -1
  211. package/dist/src/storage/providers/postgres-kysely/migrations/0021_connections.sql +116 -0
  212. package/dist/src/storage/providers/postgres-kysely/migrations/0022_provider_clients.sql +36 -0
  213. package/dist/src/storage/providers/postgres-kysely/migrations/0023_nonce_payload.sql +13 -0
  214. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  215. package/dist/src/storage/providers/sqlite/index.js +2 -1
  216. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  217. package/dist/src/storage/providers/sqlite/methods/community.d.ts.map +1 -1
  218. package/dist/src/storage/providers/sqlite/methods/community.js +2 -1
  219. package/dist/src/storage/providers/sqlite/methods/community.js.map +1 -1
  220. package/dist/src/storage/providers/sqlite/methods/connections.d.ts +60 -0
  221. package/dist/src/storage/providers/sqlite/methods/connections.d.ts.map +1 -0
  222. package/dist/src/storage/providers/sqlite/methods/connections.js +287 -0
  223. package/dist/src/storage/providers/sqlite/methods/connections.js.map +1 -0
  224. package/dist/src/storage/providers/sqlite/schema-tables-1.d.ts.map +1 -1
  225. package/dist/src/storage/providers/sqlite/schema-tables-1.js +4 -0
  226. package/dist/src/storage/providers/sqlite/schema-tables-1.js.map +1 -1
  227. package/dist/src/storage/providers/sqlite/schema-tables-3.d.ts.map +1 -1
  228. package/dist/src/storage/providers/sqlite/schema-tables-3.js +106 -0
  229. package/dist/src/storage/providers/sqlite/schema-tables-3.js.map +1 -1
  230. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  231. package/dist/src/storage/providers/sqlite/schema.js +2 -0
  232. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  233. package/dist/src/storage/repositories/connection.repository.d.ts +124 -0
  234. package/dist/src/storage/repositories/connection.repository.d.ts.map +1 -0
  235. package/dist/src/storage/repositories/connection.repository.js +2 -0
  236. package/dist/src/storage/repositories/connection.repository.js.map +1 -0
  237. package/dist/src/storage/types/agents-messaging.d.ts +19 -0
  238. package/dist/src/storage/types/agents-messaging.d.ts.map +1 -1
  239. package/dist/src/storage/types/agents-messaging.js.map +1 -1
  240. package/dist/src/storage/types/auth.d.ts +8 -1
  241. package/dist/src/storage/types/auth.d.ts.map +1 -1
  242. package/dist/src/utils/build-stamp.d.ts +56 -0
  243. package/dist/src/utils/build-stamp.d.ts.map +1 -0
  244. package/dist/src/utils/build-stamp.js +142 -0
  245. package/dist/src/utils/build-stamp.js.map +1 -0
  246. package/dist/src/utils/messaging.d.ts +14 -0
  247. package/dist/src/utils/messaging.d.ts.map +1 -1
  248. package/dist/src/utils/messaging.js +0 -0
  249. package/dist/src/utils/messaging.js.map +1 -1
  250. package/dist/static/sdk-libs/connect/index.js +199 -0
  251. package/dist/static/sdk-libs/connect/notes.js +47 -0
  252. package/dist/static/sdk-libs/connect/panel.js +238 -0
  253. package/dist/static/sdk-libs/data/index.js +63 -11
  254. package/dist/static/sdk-libs/dist/aimeat-connect.js +357 -0
  255. package/dist/static/sdk-libs/dist/aimeat-data.js +40 -9
  256. package/package.json +2 -2
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @file voice-recorder.css
3
+ * @description Styles for /components/VoiceRecorder.js — the record button and its active state
4
+ * (pulsing dot, elapsed time, input-level meter, stop and cancel). Shared by the inbox composer and
5
+ * the OpenRouter settings transcription test, so it lives with the component rather than inside a
6
+ * view stylesheet.
7
+ * @structure .vr-wrap/.vr-btn (idle) · .vr-active (recording) · .vr-dot · .vr-time · .vr-meter
8
+ * @version-history
9
+ * v1.0.0 — 2026-08-01 — Initial version (voice messages).
10
+ */
11
+
12
+ .vr-wrap { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
13
+
14
+ .vr-btn {
15
+ display: inline-flex; align-items: center; gap: 6px;
16
+ background: none; border: none; cursor: pointer;
17
+ color: var(--text-dim); font-size: 18px; line-height: 1;
18
+ padding: 4px 6px; border-radius: var(--radius, 8px);
19
+ }
20
+ .vr-btn:hover:not(:disabled) { background: var(--bg-dim); color: var(--text); }
21
+ .vr-btn:disabled { opacity: .45; cursor: not-allowed; }
22
+ .vr-label { font-size: 13px; }
23
+
24
+ .vr-active {
25
+ display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap;
26
+ padding: 4px 8px; border-radius: var(--radius, 8px);
27
+ background: var(--bg-dim); border: 1px solid var(--border);
28
+ }
29
+
30
+ .vr-dot {
31
+ width: 9px; height: 9px; border-radius: 50%;
32
+ background: var(--danger);
33
+ animation: vr-pulse 1.4s ease-in-out infinite;
34
+ }
35
+ @keyframes vr-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
36
+ /* Someone who has asked for less motion still needs to see that recording is live — the colour and
37
+ the running timer carry that; only the pulse stops. */
38
+ @media (prefers-reduced-motion: reduce) {
39
+ .vr-dot { animation: none; }
40
+ }
41
+
42
+ .vr-time {
43
+ font-variant-numeric: tabular-nums;
44
+ font-size: 13px; font-weight: 600; min-width: 3.2em;
45
+ }
46
+ .vr-time--near { color: var(--danger); }
47
+
48
+ .vr-meter {
49
+ width: 56px; height: 6px; border-radius: 3px;
50
+ background: var(--bg-surface); overflow: hidden;
51
+ }
52
+ .vr-meter-fill {
53
+ display: block; height: 100%; width: 0;
54
+ background: var(--success);
55
+ transition: width 80ms linear;
56
+ }
57
+
58
+ .vr-note, .vr-error { font-size: 11px; color: var(--text-muted); }
59
+ .vr-error { color: var(--danger); }
60
+
61
+ @media (max-width: 520px) {
62
+ /* The meter is the first thing to go: on a narrow composer the timer and the two buttons are what
63
+ the user needs, and a decorative bar must never push the stop button out of reach. */
64
+ .vr-meter { display: none; }
65
+ .vr-active { width: 100%; }
66
+ }
@@ -801,3 +801,44 @@
801
801
  .inbox-speak-btn--on { background: var(--accent-subtle); border-color: var(--accent-border); color: var(--accent); }
802
802
  .inbox-speak-ico { font-size: 13px; line-height: 1; }
803
803
  .inbox-speak-stop { flex: none; padding-inline: 8px; }
804
+
805
+ /* ── Voice messages (2026-08-01) ──
806
+ A voice message plays where it sits. It used to fall into the generic attachment chip and open in
807
+ a new browser tab, which is a download, not a conversation. */
808
+ .inbox-attach-audio { display: flex; flex-direction: column; gap: 4px; width: 100%; max-width: 380px; }
809
+ .inbox-audio { width: 100%; height: 34px; }
810
+ .inbox-audio--chip { max-width: 190px; height: 30px; }
811
+ .inbox-audio-dur { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
812
+
813
+ .inbox-file-chip--voice { align-items: center; gap: 6px; }
814
+ .inbox-chip-voice { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; }
815
+
816
+ /* Transcript: collapsed by default so a thread of voice messages stays scannable, and the label
817
+ always says who produced the text — the sender's own transcript and one this reader paid for are
818
+ not the same claim. */
819
+ .inbox-transcript { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 2px; }
820
+ .inbox-transcript-toggle {
821
+ background: none; border: none; cursor: pointer; padding: 2px 0;
822
+ font-size: 11px; color: var(--text-dim); display: inline-flex; align-items: center; gap: 6px;
823
+ }
824
+ .inbox-transcript-toggle:hover { color: var(--text); }
825
+ .inbox-transcript-src { color: var(--text-muted); }
826
+ .inbox-transcript-text {
827
+ flex-basis: 100%; font-size: 13px; white-space: pre-wrap; word-break: break-word;
828
+ padding: 8px; border-radius: var(--radius, 8px);
829
+ background: var(--bg-dim); border: 1px solid var(--border);
830
+ }
831
+ .inbox-transcript-btn {
832
+ background: none; border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
833
+ font-size: 11px; padding: 2px 10px; color: var(--text-dim);
834
+ }
835
+ .inbox-transcript-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
836
+ .inbox-transcript-btn:disabled { opacity: .6; cursor: progress; }
837
+ .inbox-transcript-hint { font-size: 11px; color: var(--text-muted); }
838
+ .inbox-transcript-err { font-size: 11px; color: var(--danger); }
839
+
840
+ @media (max-width: 520px) {
841
+ /* Full width on a phone: a 380px cap would leave the player floating in a narrow column. */
842
+ .inbox-attach-audio { max-width: 100%; }
843
+ .inbox-audio--chip { max-width: 100%; }
844
+ }
@@ -1114,7 +1114,7 @@
1114
1114
  textareas a comfortable touch height and let the prompt box scroll. */
1115
1115
  .pf-gen-ws-pane .pf-gen-prompt-box { max-height: 220px; }
1116
1116
  .pf-gen-ws-pane .pf-gen-result-area { min-height: 200px; }
1117
- .pf-gen-or-run-all-bar { flex-direction: column; align-items: stretch; gap: 8px; }
1117
+ .pf-or-run-all-bar { flex-direction: column; align-items: stretch; gap: 8px; }
1118
1118
  }
1119
1119
 
1120
1120
  /* ══ Shared Profile Utilities (2026-03-17) ══════════════ */
@@ -1249,15 +1249,15 @@
1249
1249
  .pf-gen-agent-actions { display: flex; gap: 8px; }
1250
1250
  .pf-gen-stop-btn { margin-left: auto; }
1251
1251
 
1252
- /* ── OpenRouter Settings (pf-gen-or-*) ──────────────── */
1253
- .pf-gen-or-wrapper {
1252
+ /* ── OpenRouter Settings (pf-or-*) ──────────────── */
1253
+ .pf-or-wrapper {
1254
1254
  margin-bottom: 1.25rem;
1255
1255
  background: var(--card, #FFFFFF);
1256
1256
  border: 1px solid var(--border, #E5E7EB);
1257
1257
  border-radius: 8px;
1258
1258
  overflow: hidden;
1259
1259
  }
1260
- .pf-gen-or-toggle {
1260
+ .pf-or-toggle {
1261
1261
  display: flex;
1262
1262
  align-items: center;
1263
1263
  gap: 8px;
@@ -1271,22 +1271,22 @@
1271
1271
  color: var(--text, #1A1A2E);
1272
1272
  text-align: left;
1273
1273
  }
1274
- .pf-gen-or-toggle:hover { background: var(--bg-dim, #F3F4F6); }
1275
- .pf-gen-or-toggle-icon { font-size: 0.65em; color: var(--text-dim, #6B7280); width: 1rem; flex-shrink: 0; }
1276
- .pf-gen-or-status-dot {
1274
+ .pf-or-toggle:hover { background: var(--bg-dim, #F3F4F6); }
1275
+ .pf-or-toggle-icon { font-size: 0.65em; color: var(--text-dim, #6B7280); width: 1rem; flex-shrink: 0; }
1276
+ .pf-or-status-dot {
1277
1277
  width: 8px; height: 8px; border-radius: 50%;
1278
1278
  background: var(--success, #22c55e);
1279
1279
  box-shadow: 0 0 6px rgba(34, 197, 94, 0.4);
1280
1280
  flex-shrink: 0;
1281
1281
  margin-left: auto;
1282
1282
  }
1283
- .pf-gen-or-panel {
1283
+ .pf-or-panel {
1284
1284
  padding: 0 14px 14px;
1285
1285
  }
1286
- .pf-gen-or-field {
1286
+ .pf-or-field {
1287
1287
  margin-bottom: 12px;
1288
1288
  }
1289
- .pf-gen-or-label {
1289
+ .pf-or-label {
1290
1290
  display: block;
1291
1291
  font-size: 0.8em;
1292
1292
  color: var(--text-dim, #6B7280);
@@ -1294,7 +1294,7 @@
1294
1294
  margin-bottom: 4px;
1295
1295
  font-weight: 600;
1296
1296
  }
1297
- .pf-gen-or-input {
1297
+ .pf-or-input {
1298
1298
  width: 100%;
1299
1299
  padding: 8px 12px;
1300
1300
  background: var(--surface, #F9FAFB);
@@ -1305,15 +1305,15 @@
1305
1305
  font-family: inherit;
1306
1306
  box-sizing: border-box;
1307
1307
  }
1308
- .pf-gen-or-input:focus { outline: none; border-color: var(--accent, #E8564A); box-shadow: 0 0 0 3px rgba(232, 86, 74, 0.1); }
1309
- .pf-gen-or-input-sm { max-width: 100px; }
1310
- .pf-gen-or-param-row { display: flex; align-items: center; gap: 10px; }
1311
- .pf-gen-or-param-hint { font-size: 0.8em; color: var(--text-dim, #888); white-space: nowrap; }
1308
+ .pf-or-input:focus { outline: none; border-color: var(--accent, #E8564A); box-shadow: 0 0 0 3px rgba(232, 86, 74, 0.1); }
1309
+ .pf-or-input-sm { max-width: 100px; }
1310
+ .pf-or-param-row { display: flex; align-items: center; gap: 10px; }
1311
+ .pf-or-param-hint { font-size: 0.8em; color: var(--text-dim, #888); white-space: nowrap; }
1312
1312
  /* Model refresh row: sits below the model <select>; let the hint/error wrap on narrow widths. */
1313
- .pf-gen-or-model-row { margin-top: 8px; flex-wrap: wrap; }
1314
- .pf-gen-or-model-row .pf-gen-or-param-hint { white-space: normal; }
1315
- .pf-gen-or-model-error { color: var(--danger, #ef4444); }
1316
- .pf-gen-or-select {
1313
+ .pf-or-model-row { margin-top: 8px; flex-wrap: wrap; }
1314
+ .pf-or-model-row .pf-or-param-hint { white-space: normal; }
1315
+ .pf-or-model-error { color: var(--danger, #ef4444); }
1316
+ .pf-or-select {
1317
1317
  width: 100%;
1318
1318
  padding: 8px 12px;
1319
1319
  background: var(--surface, #F9FAFB);
@@ -1324,9 +1324,9 @@
1324
1324
  font-family: inherit;
1325
1325
  cursor: pointer;
1326
1326
  }
1327
- .pf-gen-or-select:disabled { opacity: 0.5; cursor: not-allowed; }
1328
- .pf-gen-or-select:focus { outline: none; border-color: var(--accent, #E8564A); }
1329
- .pf-gen-or-checkbox {
1327
+ .pf-or-select:disabled { opacity: 0.5; cursor: not-allowed; }
1328
+ .pf-or-select:focus { outline: none; border-color: var(--accent, #E8564A); }
1329
+ .pf-or-checkbox {
1330
1330
  display: flex;
1331
1331
  align-items: center;
1332
1332
  gap: 8px;
@@ -1334,13 +1334,13 @@
1334
1334
  color: var(--text, #1A1A2E);
1335
1335
  cursor: pointer;
1336
1336
  }
1337
- .pf-gen-or-checkbox input[type="checkbox"] { accent-color: var(--accent, #E8564A); width: 16px; height: 16px; cursor: pointer; }
1338
- .pf-gen-or-radio-group {
1337
+ .pf-or-checkbox input[type="checkbox"] { accent-color: var(--accent, #E8564A); width: 16px; height: 16px; cursor: pointer; }
1338
+ .pf-or-radio-group {
1339
1339
  display: flex;
1340
1340
  flex-direction: column;
1341
1341
  gap: 6px;
1342
1342
  }
1343
- .pf-gen-or-radio-label {
1343
+ .pf-or-radio-label {
1344
1344
  display: flex;
1345
1345
  align-items: center;
1346
1346
  gap: 8px;
@@ -1348,34 +1348,34 @@
1348
1348
  color: var(--text, #1A1A2E);
1349
1349
  cursor: pointer;
1350
1350
  }
1351
- .pf-gen-or-radio-label input[type="radio"] { accent-color: var(--accent, #E8564A); width: 16px; height: 16px; cursor: pointer; flex-shrink: 0; }
1352
- .pf-gen-or-loading { font-size: 0.85em; color: var(--text-dim, #6B7280); font-style: italic; }
1353
- .pf-gen-or-actions {
1351
+ .pf-or-radio-label input[type="radio"] { accent-color: var(--accent, #E8564A); width: 16px; height: 16px; cursor: pointer; flex-shrink: 0; }
1352
+ .pf-or-loading { font-size: 0.85em; color: var(--text-dim, #6B7280); font-style: italic; }
1353
+ .pf-or-actions {
1354
1354
  display: flex;
1355
1355
  gap: 8px;
1356
1356
  margin-top: 14px;
1357
1357
  flex-wrap: wrap;
1358
1358
  }
1359
- .pf-gen-or-delete {
1359
+ .pf-or-delete {
1360
1360
  color: var(--danger, #ef4444);
1361
1361
  border-color: var(--danger, #ef4444);
1362
1362
  }
1363
- .pf-gen-or-delete:hover {
1363
+ .pf-or-delete:hover {
1364
1364
  background: var(--danger, #ef4444);
1365
1365
  color: #fff;
1366
1366
  }
1367
- .pf-gen-or-message {
1367
+ .pf-or-message {
1368
1368
  padding: 8px 12px;
1369
1369
  border-radius: 6px;
1370
1370
  font-size: 0.85em;
1371
1371
  margin-top: 8px;
1372
1372
  }
1373
- .pf-gen-or-message-success {
1373
+ .pf-or-message-success {
1374
1374
  background: rgba(34, 197, 94, 0.1);
1375
1375
  color: var(--success, #22c55e);
1376
1376
  border: 1px solid rgba(34, 197, 94, 0.25);
1377
1377
  }
1378
- .pf-gen-or-message-error {
1378
+ .pf-or-message-error {
1379
1379
  background: rgba(239, 68, 68, 0.1);
1380
1380
  color: var(--danger, #ef4444);
1381
1381
  border: 1px solid rgba(239, 68, 68, 0.25);
@@ -1383,57 +1383,133 @@
1383
1383
 
1384
1384
  /* ── AI-apps daily-budget / spend section (generator-settings OpenRouterSettings) ──
1385
1385
  Lifted out of ~28 inline styles + hardcoded hex; all tokenized so it flips in dark mode. */
1386
- .pf-gen-spend-section { border-top: 2px solid var(--border); padding-top: 14px; margin-top: 14px; }
1387
- .pf-gen-spend-desc { font-size: 12px; color: var(--text-dim); margin-bottom: 8px; }
1388
- .pf-gen-spend-bar-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
1389
- .pf-gen-spend-bar { flex: 1; min-width: 200px; background: var(--bg-surface); border-radius: 4px; height: 20px; position: relative; overflow: hidden; }
1390
- .pf-gen-spend-bar-fill { position: absolute; top: 0; left: 0; bottom: 0; transition: width .3s; background: var(--success); }
1391
- .pf-gen-spend-bar-fill.warn { background: var(--warn); }
1392
- .pf-gen-spend-bar-fill.crit { background: var(--danger); }
1393
- .pf-gen-spend-bar-label { position: relative; text-align: center; font-size: 11px; line-height: 20px; font-weight: 700; }
1394
- .pf-gen-spend-budget-input { width: 90px; padding: 4px 6px; font-size: 13px; }
1395
- .pf-gen-spend-details { margin-top: 10px; }
1396
- .pf-gen-spend-summary { cursor: pointer; font-size: 12px; color: var(--text-dim); }
1397
- .pf-gen-spend-hint { font-size: 11px; color: var(--text-muted); margin: 6px 0; }
1398
- .pf-gen-spend-table { width: 100%; margin-top: 4px; font-size: 12px; border-collapse: collapse; }
1399
- .pf-gen-spend-table th, .pf-gen-spend-table td { padding: 4px; text-align: left; }
1400
- .pf-gen-spend-table th.num, .pf-gen-spend-table td.num { text-align: right; }
1401
- .pf-gen-spend-table thead tr { border-bottom: 1px solid var(--border); }
1402
- .pf-gen-spend-cap-input { width: 74px; padding: 3px 5px; font-size: 12px; text-align: right; }
1403
- .pf-gen-spend-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
1404
- .pf-gen-spend-msg { margin-top: 8px; }
1405
- .pf-gen-spend-chart-wrap { margin-top: 14px; }
1406
- .pf-gen-spend-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
1407
- .pf-gen-spend-chart-title { font-size: 12px; font-weight: 600; color: var(--text-dim); }
1408
- .pf-gen-spend-metric-toggle { display: inline-flex; gap: 4px; }
1409
- .pf-gen-spend-footnote { font-size: 11px; color: var(--text-muted); margin-top: 8px; }
1410
-
1411
- /* ── OpenRouter Autopilot (pf-gen-or-*) ──────────────── */
1412
- .pf-gen-or-btn-row {
1386
+ .pf-or-spend-section { border-top: 2px solid var(--border); padding-top: 14px; margin-top: 14px; }
1387
+ .pf-or-spend-desc { font-size: 12px; color: var(--text-dim); margin-bottom: 8px; }
1388
+ .pf-or-spend-bar-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
1389
+ .pf-or-spend-bar { flex: 1; min-width: 200px; background: var(--bg-surface); border-radius: 4px; height: 20px; position: relative; overflow: hidden; }
1390
+ .pf-or-spend-bar-fill { position: absolute; top: 0; left: 0; bottom: 0; transition: width .3s; background: var(--success); }
1391
+ .pf-or-spend-bar-fill.warn { background: var(--warn); }
1392
+ .pf-or-spend-bar-fill.crit { background: var(--danger); }
1393
+ .pf-or-spend-bar-label { position: relative; text-align: center; font-size: 11px; line-height: 20px; font-weight: 700; }
1394
+ .pf-or-spend-budget-input { width: 90px; padding: 4px 6px; font-size: 13px; }
1395
+ .pf-or-spend-details { margin-top: 10px; }
1396
+ .pf-or-spend-summary { cursor: pointer; font-size: 12px; color: var(--text-dim); }
1397
+ .pf-or-spend-hint { font-size: 11px; color: var(--text-muted); margin: 6px 0; }
1398
+ .pf-or-spend-table { width: 100%; margin-top: 4px; font-size: 12px; border-collapse: collapse; }
1399
+ .pf-or-spend-table th, .pf-or-spend-table td { padding: 4px; text-align: left; }
1400
+ .pf-or-spend-table th.num, .pf-or-spend-table td.num { text-align: right; }
1401
+ .pf-or-spend-table thead tr { border-bottom: 1px solid var(--border); }
1402
+ .pf-or-spend-cap-input { width: 74px; padding: 3px 5px; font-size: 12px; text-align: right; }
1403
+ .pf-or-spend-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
1404
+ .pf-or-spend-msg { margin-top: 8px; }
1405
+ .pf-or-spend-chart-wrap { margin-top: 14px; }
1406
+ .pf-or-spend-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
1407
+ .pf-or-spend-chart-title { font-size: 12px; font-weight: 600; color: var(--text-dim); }
1408
+ .pf-or-spend-metric-toggle { display: inline-flex; gap: 4px; }
1409
+ .pf-or-spend-footnote { font-size: 11px; color: var(--text-muted); margin-top: 8px; }
1410
+
1411
+ /* ── AI provider settings v3: sections, model picker, STT (2026-08-01) ──
1412
+ The panel is four sections that each save their own fields, so the answer to "did that save?"
1413
+ appears where the question is asked instead of at the bottom of one long form. */
1414
+ .pf-or-section { padding: 14px 0; border-top: 1px solid var(--border); }
1415
+ .pf-or-section:first-child { border-top: none; padding-top: 4px; }
1416
+ .pf-or-section-title { font-size: 13px; font-weight: 700; margin: 0 0 10px; color: var(--text); }
1417
+
1418
+ .pf-or-status { margin-left: auto; font-size: 11px; color: var(--text-muted); font-weight: 500; }
1419
+ .pf-or-status--on { color: var(--success); }
1420
+
1421
+ /* Key row: the save button sits next to the field it saves. */
1422
+ .pf-or-key-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
1423
+ .pf-or-key-input { flex: 1; min-width: 220px; }
1424
+ .pf-or-links { display: flex; gap: 14px; margin-top: 8px; font-size: 12px; flex-wrap: wrap; }
1425
+
1426
+ .pf-or-models-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
1427
+ .pf-or-hint { font-size: 11px; color: var(--text-muted); display: block; margin-top: 4px; }
1428
+ .pf-or-hint--error { color: var(--danger); }
1429
+ .pf-or-loading { font-size: 12px; color: var(--text-dim); padding: 8px 0; }
1430
+ .pf-or-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 12px; }
1431
+
1432
+ .pf-or-roles-summary,
1433
+ .pf-or-params-summary { cursor: pointer; font-size: 12px; color: var(--text-dim); margin-bottom: 8px; }
1434
+ .pf-or-params-summary { font-size: 13px; font-weight: 700; color: var(--text); }
1435
+
1436
+ .pf-or-inline-field { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
1437
+ .pf-or-label--inline { margin: 0; }
1438
+ .pf-or-select--sm { width: auto; min-width: 150px; }
1439
+
1440
+ /* ── Model picker ──
1441
+ Replaces a <select> holding the provider's whole catalogue (336 options on OpenRouter, unlabelled
1442
+ and unsearchable). Prices are tabular so a column of them can actually be compared. */
1443
+ .pf-or-picker { border: 1px solid var(--border); border-radius: var(--radius, 8px); padding: 8px; background: var(--bg-surface); }
1444
+ .pf-or-picker--off { opacity: .55; }
1445
+ .pf-or-picker-head { display: flex; gap: 8px; align-items: center; justify-content: space-between; margin-bottom: 6px; }
1446
+ .pf-or-picked-id { font-size: 12px; word-break: break-all; }
1447
+ .pf-or-picked-none { font-size: 12px; color: var(--text-muted); }
1448
+ .pf-or-picked-warn { font-size: 11px; color: var(--warn); margin-left: 6px; }
1449
+ .pf-or-msearch { width: 100%; }
1450
+
1451
+ .pf-or-mlist { list-style: none; margin: 8px 0 0; padding: 0; max-height: 260px; overflow-y: auto; }
1452
+ .pf-or-mgroup { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); padding: 4px 2px; }
1453
+ .pf-or-mrow { display: flex; align-items: center; gap: 4px; border-radius: 6px; }
1454
+ .pf-or-mrow:hover { background: var(--bg-dim); }
1455
+ .pf-or-mrow--on { background: var(--bg-dim); box-shadow: inset 2px 0 0 var(--accent); }
1456
+ .pf-or-mpick {
1457
+ flex: 1; min-width: 0; text-align: left; background: none; border: none; cursor: pointer;
1458
+ padding: 6px 6px; color: var(--text); display: flex; flex-direction: column; gap: 2px;
1459
+ }
1460
+ .pf-or-mname { font-size: 13px; font-weight: 600; }
1461
+ .pf-or-mid { font-size: 11px; color: var(--text-muted); word-break: break-all; }
1462
+ .pf-or-mmeta { display: flex; gap: 10px; flex-wrap: wrap; font-size: 11px; color: var(--text-dim); }
1463
+ .pf-or-mprice { font-variant-numeric: tabular-nums; }
1464
+ .pf-or-mlink { padding: 0 6px; color: var(--text-dim); text-decoration: none; font-size: 13px; }
1465
+ .pf-or-mlink:hover { color: var(--accent); }
1466
+ .pf-or-mempty { font-size: 12px; color: var(--text-muted); padding: 10px 4px; }
1467
+ .pf-or-mall { margin-top: 6px; }
1468
+ .pf-or-mcustom { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
1469
+ .pf-or-mcustom .pf-or-input { flex: 1; min-width: 180px; }
1470
+
1471
+ /* ── Speech-to-text ──
1472
+ The measured result is the point of the test: an audio model's listed price carries no unit, so
1473
+ one real transcription says more than any number derived from the catalogue. */
1474
+ .pf-or-stt { border-top: 1px dashed var(--border); padding-top: 12px; margin-top: 12px; }
1475
+ .pf-or-stt-test { margin-top: 10px; }
1476
+ .pf-or-stt-test-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
1477
+ .pf-or-stt-result { margin-top: 8px; padding: 8px; border-radius: var(--radius, 8px); background: var(--bg-dim); border: 1px solid var(--border); }
1478
+ .pf-or-stt-text { font-size: 13px; white-space: pre-wrap; word-break: break-word; }
1479
+ .pf-or-stt-meta { font-size: 11px; color: var(--text-muted); margin-top: 6px; font-variant-numeric: tabular-nums; }
1480
+
1481
+ @media (max-width: 520px) {
1482
+ .pf-or-key-row { flex-direction: column; align-items: stretch; }
1483
+ .pf-or-key-input { min-width: 0; }
1484
+ .pf-or-mmeta { flex-direction: column; gap: 2px; }
1485
+ }
1486
+
1487
+ /* ── OpenRouter Autopilot (pf-or-*) ──────────────── */
1488
+ .pf-or-btn-row {
1413
1489
  display: flex;
1414
1490
  gap: 8px;
1415
1491
  align-items: center;
1416
1492
  flex-wrap: wrap;
1417
1493
  }
1418
- .pf-gen-or-run-btn {
1494
+ .pf-or-run-btn {
1419
1495
  display: inline-flex;
1420
1496
  align-items: center;
1421
1497
  gap: 6px;
1422
1498
  }
1423
- .pf-gen-or-run-btn.pf-gen-or-running {
1499
+ .pf-or-run-btn.pf-or-running {
1424
1500
  opacity: 0.8;
1425
1501
  cursor: wait;
1426
1502
  }
1427
- .pf-gen-or-spinner {
1503
+ .pf-or-spinner {
1428
1504
  display: inline-block;
1429
1505
  width: 14px;
1430
1506
  height: 14px;
1431
1507
  border: 2px solid var(--border, #E5E7EB);
1432
1508
  border-top-color: var(--accent, #E8564A);
1433
1509
  border-radius: 50%;
1434
- animation: pf-gen-or-spin 0.7s linear infinite;
1510
+ animation: pf-or-spin 0.7s linear infinite;
1435
1511
  }
1436
- @keyframes pf-gen-or-spin {
1512
+ @keyframes pf-or-spin {
1437
1513
  to { transform: rotate(360deg); }
1438
1514
  }
1439
1515
  .pf-gen-data-viewer {
@@ -1458,7 +1534,7 @@
1458
1534
  white-space: pre-wrap;
1459
1535
  word-break: break-word;
1460
1536
  }
1461
- .pf-gen-or-run-all-bar {
1537
+ .pf-or-run-all-bar {
1462
1538
  display: flex;
1463
1539
  align-items: center;
1464
1540
  gap: 12px;
@@ -1468,7 +1544,7 @@
1468
1544
  border: 1px solid var(--border, #E5E7EB);
1469
1545
  border-radius: 8px;
1470
1546
  }
1471
- .pf-gen-or-run-all-status {
1547
+ .pf-or-run-all-status {
1472
1548
  display: flex;
1473
1549
  align-items: center;
1474
1550
  gap: 8px;
@@ -2058,8 +2134,8 @@
2058
2134
  .pf-gen-test-scope-compact {
2059
2135
  display: flex; gap: 8px; align-items: center; margin: 0; font-size: 0.85em;
2060
2136
  }
2061
- .pf-gen-test-scope-compact .pf-gen-or-radio-label { margin: 0; white-space: nowrap; }
2062
- .pf-gen-or-run-all-controls {
2137
+ .pf-gen-test-scope-compact .pf-or-radio-label { margin: 0; white-space: nowrap; }
2138
+ .pf-or-run-all-controls {
2063
2139
  display: flex; align-items: center; gap: 12px; width: 100%;
2064
2140
  }
2065
2141
 
@@ -3449,29 +3525,29 @@
3449
3525
  .pf-adk-sev--warn { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }
3450
3526
  .pf-adk-sev--info { background: var(--bg-dim); color: var(--muted); }
3451
3527
  .pf-adk-empty { color: var(--muted); font-size: 0.9rem; padding: 0.9rem; margin-bottom: 0.7rem; }
3452
-
3453
- /* ── AI transparency card (pf-aitr-*) — TARGET-058 Phase 8 ──
3454
- The owner's own view of what they published with a model in it. The one visual decision here is
3455
- that the "public and unlabelled" tile changes colour only when the number is ABOVE zero: a
3456
- compliance surface that is always red teaches people to stop looking at it. */
3457
- .pf-aitr-head { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; width: 100%; background: none; border: 0; padding: 0; cursor: pointer; text-align: left; color: inherit; font: inherit; }
3458
- .pf-aitr-chevron { color: var(--muted); font-size: 1.1rem; line-height: 1; flex-shrink: 0; }
3459
- .pf-aitr-body { margin-top: 0.9rem; border-top: 1px solid var(--border); padding-top: 0.9rem; }
3460
- /* auto-fit, so four tiles become two rows on a phone instead of overflowing the card. */
3461
- .pf-aitr-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); gap: 0.6rem; }
3462
- .pf-aitr-stat { display: flex; flex-direction: column; gap: 0.15rem; padding: 0.7rem 0.8rem; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-dim); min-width: 0; }
3463
- .pf-aitr-stat-warn { border-color: var(--warn); }
3464
- .pf-aitr-stat-warn .pf-aitr-num { color: var(--warn); }
3465
- .pf-aitr-num { font-size: 1.5rem; font-weight: 700; line-height: 1.1; }
3466
- .pf-aitr-lbl { font-size: 0.75rem; color: var(--muted); overflow-wrap: anywhere; }
3467
- .pf-aitr-note { margin: 0.8rem 0 0; font-size: 0.82rem; color: var(--muted); }
3468
- .pf-aitr-warn-line { margin: 0.9rem 0 0.4rem; font-size: 0.85rem; color: var(--fg); }
3469
- .pf-aitr-error { margin: 0; font-size: 0.85rem; color: var(--danger); }
3470
- .pf-aitr-muted { margin: 0.5rem 0 0; font-size: 0.8rem; color: var(--muted); }
3471
- .pf-aitr-sub { margin: 1.2rem 0 0.4rem; font-size: 0.9rem; font-weight: 600; }
3472
- .pf-aitr-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
3473
- .pf-aitr-row, .pf-aitr-policy { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 0.7rem; padding: 0.55rem 0.7rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-dim); min-width: 0; }
3474
- .pf-aitr-policy { flex-direction: column; }
3475
- .pf-aitr-row-main { font-size: 0.85rem; font-weight: 600; overflow-wrap: anywhere; }
3476
- .pf-aitr-row-meta { font-size: 0.78rem; color: var(--muted); overflow-wrap: anywhere; }
3477
- .pf-aitr-row-link { font-size: 0.78rem; color: var(--accent); }
3528
+
3529
+ /* ── AI transparency card (pf-aitr-*) — TARGET-058 Phase 8 ──
3530
+ The owner's own view of what they published with a model in it. The one visual decision here is
3531
+ that the "public and unlabelled" tile changes colour only when the number is ABOVE zero: a
3532
+ compliance surface that is always red teaches people to stop looking at it. */
3533
+ .pf-aitr-head { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; width: 100%; background: none; border: 0; padding: 0; cursor: pointer; text-align: left; color: inherit; font: inherit; }
3534
+ .pf-aitr-chevron { color: var(--muted); font-size: 1.1rem; line-height: 1; flex-shrink: 0; }
3535
+ .pf-aitr-body { margin-top: 0.9rem; border-top: 1px solid var(--border); padding-top: 0.9rem; }
3536
+ /* auto-fit, so four tiles become two rows on a phone instead of overflowing the card. */
3537
+ .pf-aitr-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); gap: 0.6rem; }
3538
+ .pf-aitr-stat { display: flex; flex-direction: column; gap: 0.15rem; padding: 0.7rem 0.8rem; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-dim); min-width: 0; }
3539
+ .pf-aitr-stat-warn { border-color: var(--warn); }
3540
+ .pf-aitr-stat-warn .pf-aitr-num { color: var(--warn); }
3541
+ .pf-aitr-num { font-size: 1.5rem; font-weight: 700; line-height: 1.1; }
3542
+ .pf-aitr-lbl { font-size: 0.75rem; color: var(--muted); overflow-wrap: anywhere; }
3543
+ .pf-aitr-note { margin: 0.8rem 0 0; font-size: 0.82rem; color: var(--muted); }
3544
+ .pf-aitr-warn-line { margin: 0.9rem 0 0.4rem; font-size: 0.85rem; color: var(--fg); }
3545
+ .pf-aitr-error { margin: 0; font-size: 0.85rem; color: var(--danger); }
3546
+ .pf-aitr-muted { margin: 0.5rem 0 0; font-size: 0.8rem; color: var(--muted); }
3547
+ .pf-aitr-sub { margin: 1.2rem 0 0.4rem; font-size: 0.9rem; font-weight: 600; }
3548
+ .pf-aitr-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
3549
+ .pf-aitr-row, .pf-aitr-policy { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 0.7rem; padding: 0.55rem 0.7rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-dim); min-width: 0; }
3550
+ .pf-aitr-policy { flex-direction: column; }
3551
+ .pf-aitr-row-main { font-size: 0.85rem; font-weight: 600; overflow-wrap: anywhere; }
3552
+ .pf-aitr-row-meta { font-size: 0.78rem; color: var(--muted); overflow-wrap: anywhere; }
3553
+ .pf-aitr-row-link { font-size: 0.78rem; color: var(--accent); }