@1agh/maude 0.30.0 → 0.31.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 (90) hide show
  1. package/README.md +5 -5
  2. package/apps/studio/acp/bridge.ts +285 -0
  3. package/apps/studio/acp/env.ts +48 -0
  4. package/apps/studio/acp/index.ts +132 -0
  5. package/apps/studio/acp/probe.ts +112 -0
  6. package/apps/studio/acp/transcript.ts +149 -0
  7. package/apps/studio/annotations-layer.tsx +6 -1
  8. package/apps/studio/api.ts +225 -66
  9. package/apps/studio/bin/chat-open.sh +44 -0
  10. package/apps/studio/canvas-lib.tsx +112 -19
  11. package/apps/studio/canvas-list-watch.ts +177 -0
  12. package/apps/studio/canvas-shell.tsx +22 -2
  13. package/apps/studio/client/app.jsx +781 -26
  14. package/apps/studio/client/canvas-url.js +5 -0
  15. package/apps/studio/client/github.js +99 -0
  16. package/apps/studio/client/panels/ChatPanel.jsx +770 -0
  17. package/apps/studio/client/panels/CollabModelInfographic.jsx +71 -0
  18. package/apps/studio/client/panels/CreateProject.jsx +334 -0
  19. package/apps/studio/client/panels/DiffView.jsx +590 -0
  20. package/apps/studio/client/panels/GitPanel.jsx +767 -0
  21. package/apps/studio/client/panels/IdentityBar.jsx +294 -0
  22. package/apps/studio/client/panels/OnboardingWizard.jsx +563 -0
  23. package/apps/studio/client/panels/RepoBranchSwitcher.jsx +349 -0
  24. package/apps/studio/client/panels/acp-runtime.js +286 -0
  25. package/apps/studio/client/panels/chat-markdown.jsx +138 -0
  26. package/apps/studio/client/panels/git-grouping.js +86 -0
  27. package/apps/studio/client/styles/0-reset.css +4 -0
  28. package/apps/studio/client/styles/3-shell-maude.css +613 -3
  29. package/apps/studio/client/styles/5-maude-overrides.css +25 -0
  30. package/apps/studio/client/styles/6-acp-chat.css +771 -0
  31. package/apps/studio/client/styles/_index.css +2 -0
  32. package/apps/studio/client/tour/collab-tour.js +61 -0
  33. package/apps/studio/client/tour/overlay.jsx +11 -1
  34. package/apps/studio/client/whats-new.jsx +25 -10
  35. package/apps/studio/collab/registry.ts +13 -0
  36. package/apps/studio/collab/room.ts +36 -0
  37. package/apps/studio/cursors-overlay.tsx +17 -1
  38. package/apps/studio/dist/client.bundle.js +28780 -1534
  39. package/apps/studio/dist/comment-mount.js +4 -2
  40. package/apps/studio/dist/styles.css +5633 -1617
  41. package/apps/studio/git/endpoints.ts +338 -0
  42. package/apps/studio/git/service.ts +1334 -0
  43. package/apps/studio/git/watch.ts +97 -0
  44. package/apps/studio/github/endpoints.ts +358 -0
  45. package/apps/studio/github/service.ts +231 -0
  46. package/apps/studio/github/token.ts +53 -0
  47. package/apps/studio/hmr-broadcast.ts +9 -2
  48. package/apps/studio/http.ts +384 -1
  49. package/apps/studio/participants-chrome.tsx +69 -9
  50. package/apps/studio/paths.ts +12 -0
  51. package/apps/studio/scaffold-design.ts +57 -0
  52. package/apps/studio/server.ts +65 -2
  53. package/apps/studio/sync/agent.ts +81 -1
  54. package/apps/studio/sync/codec.ts +24 -0
  55. package/apps/studio/sync/cold-start.ts +40 -0
  56. package/apps/studio/sync/hub-link.ts +137 -0
  57. package/apps/studio/test/acp-bridge.test.ts +127 -0
  58. package/apps/studio/test/acp-env.test.ts +65 -0
  59. package/apps/studio/test/acp-origin-gate.test.ts +78 -0
  60. package/apps/studio/test/acp-transcript.test.ts +112 -0
  61. package/apps/studio/test/canvas-create-api.test.ts +72 -0
  62. package/apps/studio/test/canvas-list-watch.test.ts +322 -0
  63. package/apps/studio/test/canvas-meta-api.test.ts +161 -27
  64. package/apps/studio/test/canvas-origin-gate.test.ts +35 -0
  65. package/apps/studio/test/chat-markdown.test.tsx +58 -0
  66. package/apps/studio/test/collab-session-survival.test.tsx +176 -0
  67. package/apps/studio/test/csrf-write-guard.test.ts +26 -0
  68. package/apps/studio/test/editing-presence.test.ts +103 -0
  69. package/apps/studio/test/fixtures/mock-acp-agent.mjs +45 -0
  70. package/apps/studio/test/git-api.test.ts +0 -0
  71. package/apps/studio/test/git-branches.test.ts +106 -0
  72. package/apps/studio/test/git-grouping.test.ts +106 -0
  73. package/apps/studio/test/git-watch.test.ts +97 -0
  74. package/apps/studio/test/github-api.test.ts +465 -0
  75. package/apps/studio/test/hub-link.test.ts +69 -0
  76. package/apps/studio/test/participants-chrome.test.ts +36 -1
  77. package/apps/studio/test/sync-cold-seed-dedup.test.ts +187 -0
  78. package/apps/studio/test/sync-cold-start.test.ts +61 -1
  79. package/apps/studio/test/tour-overlay.test.tsx +18 -0
  80. package/apps/studio/tool-palette.tsx +18 -9
  81. package/apps/studio/use-chrome-visibility.tsx +66 -0
  82. package/apps/studio/use-collab.tsx +414 -187
  83. package/apps/studio/whats-new.json +73 -0
  84. package/apps/studio/ws.ts +44 -1
  85. package/cli/commands/design.mjs +1 -0
  86. package/cli/lib/gitignore-block.mjs +16 -3
  87. package/cli/lib/gitignore-block.test.mjs +13 -1
  88. package/package.json +11 -9
  89. package/plugins/design/dependencies.json +17 -0
  90. package/plugins/design/templates/_shell.html +30 -8
@@ -170,6 +170,15 @@
170
170
  .st-sb-sync-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--status-warn); flex: none; }
171
171
  .st-sb-sync-dot.is-online { background: var(--presence-online); }
172
172
 
173
+ /* Phase 28 — clickable "changes" slot (opens the Changes panel). Button reset; the
174
+ .st-sb-slot + .st-sb-slot rule still supplies the divider + left padding. */
175
+ .st-sb-changes { appearance: none; border: 0; padding: 0; border-radius: 0; background: transparent; font: inherit; cursor: pointer; }
176
+ .st-sb-changes:hover .val, .st-sb-changes.is-open .val { color: var(--accent); }
177
+ .st-sb-changes:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
178
+ .st-sb-changes-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--border-strong); flex: none; }
179
+ .st-sb-changes.has-changes .st-sb-changes-dot { background: var(--status-warn); }
180
+ .st-sb-changes.has-unpushed .st-sb-changes-dot { background: var(--accent); }
181
+
173
182
  /* ═══ Task 4 — body row · sidebar · tree · rail ═══════════════════════════════ */
174
183
 
175
184
  /* The body flex row replaces the legacy `.app` grid: rail | sidebar | main | rpanel. */
@@ -268,10 +277,13 @@
268
277
  }
269
278
  /* Kept in the a11y tree (opacity, not display:none) so keyboard users reach it. */
270
279
  .st-row-wrap:hover .st-row-del, .st-row-del:focus-visible { opacity: 1; }
271
- /* Shift the open-comments badge left of the delete button on hover so they
272
- don't overlap (the delete is absolute at the row's right edge). */
280
+ /* Shift the open-comments badge AND the M/A/D/U git badge left of the delete
281
+ button on hover/focus so they don't overlap (the delete is absolute at the
282
+ row's right edge). */
273
283
  .st-row-wrap:hover .st-row-badge,
274
- .st-row-wrap:focus-within .st-row-badge { margin-right: 24px; }
284
+ .st-row-wrap:focus-within .st-row-badge,
285
+ .st-row-wrap:hover .st-git-badge,
286
+ .st-row-wrap:focus-within .st-git-badge { margin-right: 24px; }
275
287
  .st-row-del:hover { color: var(--status-error); background: color-mix(in oklab, var(--status-error) 14%, transparent); }
276
288
 
277
289
  /* DS-folder row — chevron toggles disclosure, name opens the system view. */
@@ -1158,4 +1170,602 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
1158
1170
  }
1159
1171
  @media (prefers-reduced-motion: reduce) { .st-avatar.is-pulsing::after { animation: none; opacity: 0; } }
1160
1172
 
1173
+ /* ── Phase 27 (E2) — GitPanel (Changes / History), mockup-faithful ────────────
1174
+ * Ported 1:1 from `.design/ui/GitPanel.css`. The DS treatments the mock LIFTS
1175
+ * (.panel/.tabbar/.tab/.textarea/.callout/.check) are folded into the gp-* names
1176
+ * so they don't collide with the existing shell classes. Every value a token. */
1177
+ .gp-panel { display: flex; flex-direction: column; min-height: 0; background: var(--bg-1); }
1178
+
1179
+ /* header: title + "N unsaved" pill + close, then the Changes/History tabbar */
1180
+ .gp-head { flex: none; }
1181
+ .gp-panel-hd { display: flex; align-items: center; gap: var(--space-2); height: 40px; padding: 0 var(--space-2) 0 var(--space-4); border-bottom: 1px solid var(--border-default); }
1182
+ .gp-panel-title { font-family: var(--font-display); font-weight: 600; font-size: var(--type-md); color: var(--fg-0); flex: none; }
1183
+ .gp-count { font-family: var(--font-mono); font-size: var(--type-xs); font-weight: 600; padding: 1px var(--space-2); border-radius: var(--radius-pill); background: var(--accent-tint); color: var(--accent); border: 1px solid var(--accent-muted); white-space: nowrap; flex: none; }
1184
+ .gp-spacer { flex: 1; min-width: var(--space-2); }
1185
+ .gp-draft { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); display: inline-flex; align-items: center; gap: var(--space-1); padding: 1px var(--space-2); border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-2); white-space: nowrap; min-width: 0; flex: 0 1 auto; }
1186
+ .gp-draft b { color: var(--fg-0); font-weight: 600; overflow: hidden; text-overflow: ellipsis; max-width: 90px; }
1187
+ .gp-draft .gp-sep { color: var(--fg-3); }
1188
+ .gp-x { appearance: none; border: none; background: transparent; color: var(--fg-2); font-size: 16px; line-height: 1; cursor: pointer; padding: 2px 5px; border-radius: var(--radius-xs); }
1189
+ .gp-x:hover { color: var(--fg-1); background: var(--bg-3); }
1190
+ /* tabbar/tab — DS treatment folded in */
1191
+ .gp-tabs { display: flex; gap: var(--space-1); padding: var(--space-2) var(--space-3) 0; border-bottom: 1px solid var(--border-subtle); }
1192
+ .gp-tab { appearance: none; border: 0; background: transparent; font-size: var(--type-sm); color: var(--fg-2); font-family: var(--font-body); padding: var(--space-3) var(--space-4); cursor: pointer; border-bottom: 2px solid transparent; }
1193
+ .gp-tab:hover { color: var(--fg-1); }
1194
+ .gp-tab.is-active { color: var(--fg-0); border-bottom-color: var(--accent); }
1195
+
1196
+ /* the changed-file list */
1197
+ .gp-list { flex: 1; overflow-y: auto; padding: var(--space-2) 0; min-height: 0; }
1198
+ .gp-group-hd { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-4) var(--space-2); font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); }
1199
+ .gp-group-count { color: var(--fg-2); }
1200
+ .gp-file { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3) var(--space-2) var(--space-4); border-radius: var(--radius-sm); margin: 0 var(--space-2); }
1201
+ .gp-file:hover { background: var(--bg-2); }
1202
+ .gp-file.is-checked { background: color-mix(in oklab, var(--accent-tint) 60%, transparent); }
1203
+ .gp-check { flex: 0 0 auto; width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
1204
+ .gp-file-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; cursor: pointer; appearance: none; background: none; border: none; padding: 0; text-align: left; }
1205
+ .gp-file-name { color: var(--fg-0); font-size: var(--type-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1206
+ .gp-file-path { color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1207
+ .gp-file.is-checked .gp-file-path { color: var(--fg-1); }
1208
+ .gp-file-text:hover .gp-file-name { color: var(--accent); }
1209
+ .gp-discard { flex: 0 0 auto; opacity: 0; color: var(--fg-2); background: none; border: none; padding: var(--space-1); border-radius: var(--radius-xs); cursor: pointer; transition: opacity var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out); }
1210
+ .gp-file:hover .gp-discard, .gp-file:focus-within .gp-discard { opacity: 1; }
1211
+ .gp-discard:hover { color: var(--status-error); background: var(--bg-3); }
1212
+ .gp-discard:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-xs); opacity: 1; }
1213
+
1214
+ /* DDR-115 follow-up — canvas-grouped changes: a canvas + its collapsed
1215
+ supporting files (Layout & settings, Annotations) as one logical unit. */
1216
+ .gp-unit { display: flex; flex-direction: column; }
1217
+ .gp-unit-hd .gp-file-name { font-weight: 500; }
1218
+ .gp-disclose { flex: 0 0 auto; display: grid; place-items: center; color: var(--fg-2); background: none; border: none; padding: var(--space-1); border-radius: var(--radius-xs); cursor: pointer; transition: transform var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out); }
1219
+ .gp-disclose.is-open { transform: rotate(90deg); }
1220
+ .gp-disclose:hover { color: var(--fg-0); }
1221
+ .gp-disclose:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1222
+ .gp-support { margin: 0 var(--space-2) var(--space-1) var(--space-6); border-left: 1px solid var(--border-default); padding-left: var(--space-2); }
1223
+ .gp-support-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-1) var(--space-2); min-width: 0; }
1224
+ .gp-support-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
1225
+ .gp-support-row .gp-file-name { color: var(--fg-1); font-size: var(--type-sm); }
1226
+
1227
+ /* M / A / D / U dirty badge — solid for M/A/D, dashed outline for U (untracked) */
1228
+ .gp-badge { flex: 0 0 auto; width: 16px; height: 16px; border-radius: var(--radius-xs); display: grid; place-items: center; font-family: var(--font-mono); font-size: 10px; font-weight: 600; line-height: 1; color: oklch(0.11 0.012 260); }
1229
+ .gp-badge[data-kind="M"] { background: var(--status-warn); }
1230
+ .gp-badge[data-kind="A"] { background: var(--status-success); }
1231
+ .gp-badge[data-kind="D"] { background: var(--status-error); }
1232
+ .gp-badge[data-kind="U"] { background: transparent; border: 1px dashed var(--border-strong); color: var(--fg-2); }
1233
+
1234
+ /* composer footer: select-all · message · Save version / Save all · hint */
1235
+ .gp-compose { flex: none; border-top: 1px solid var(--border-default); padding: var(--space-3) var(--space-4) var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); background: var(--bg-1); }
1236
+ .gp-selectall { display: inline-flex; align-items: center; gap: var(--space-2); align-self: flex-start; appearance: none; background: none; border: none; padding: 0; font-family: var(--font-body); font-size: var(--type-sm); color: var(--fg-1); cursor: pointer; }
1237
+ .gp-msg { font-family: var(--font-body); font-size: var(--type-sm); color: var(--fg-0); background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4); width: 100%; resize: none; min-height: 64px; transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out); }
1238
+ .gp-msg::placeholder { color: var(--fg-2); }
1239
+ .gp-msg:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
1240
+ .gp-compose-actions { display: flex; align-items: center; gap: var(--space-3); }
1241
+ .gp-save { flex: 1; justify-content: center; }
1242
+ .gp-save:disabled, .gp-save[aria-disabled="true"], .gp-publish:disabled, .gp-publish[aria-disabled="true"] { background: var(--bg-3); color: var(--fg-3); border-color: var(--border-default); cursor: not-allowed; }
1243
+ .gp-hint { font-size: var(--type-xs); color: var(--fg-2); }
1244
+
1245
+ /* publish / get-latest bar */
1246
+ .gp-publishbar { flex: none; border-top: 1px solid var(--border-default); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); background: var(--bg-1); }
1247
+ .gp-publish { width: 100%; justify-content: center; }
1248
+ .gp-nudge { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); border-radius: var(--radius-sm); }
1249
+ .gp-nudge-text { flex: 1; font-size: var(--type-sm); }
1250
+ .gp-nudge-text b { color: var(--fg-0); font-weight: 600; }
1251
+ .gp-nudge-text span { color: var(--fg-1); }
1252
+ .gp-dot-pulse { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--status-info); flex: 0 0 auto; box-shadow: 0 0 0 0 color-mix(in oklab, var(--status-info) 60%, transparent); animation: gp-pulse 2.4s var(--ease-out) infinite; }
1253
+ @keyframes gp-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--status-info) 55%, transparent); } 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
1254
+ @media (prefers-reduced-motion: reduce) { .gp-dot-pulse { animation: none; } }
1255
+
1256
+ /* callout (banner / conflict) — uses the client .callout, gp- adds layout */
1257
+ .gp-callout-col { display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
1258
+ .gp-callout-actions { display: flex; gap: var(--space-3); margin-top: var(--space-2); }
1259
+ .gp-pad { padding: var(--space-4) var(--space-4) 0; }
1260
+ .gp-sect-label { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); padding: var(--space-4) var(--space-4) var(--space-2); }
1261
+
1262
+ /* History timeline with rail */
1263
+ .gp-history { padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: 0; overflow-y: auto; min-height: 0; }
1264
+ .gp-version { display: grid; grid-template-columns: 18px 1fr auto; gap: var(--space-3); padding: var(--space-3) var(--space-2); align-items: start; position: relative; }
1265
+ .gp-version-rail { display: grid; place-items: center; position: relative; }
1266
+ .gp-version-node { width: 8px; height: 8px; border-radius: var(--radius-pill); background: var(--accent); margin-top: 4px; z-index: 1; }
1267
+ .gp-version:not(:last-child) .gp-version-rail::after { content: ""; position: absolute; top: 12px; bottom: -12px; width: 1px; background: var(--border-default); }
1268
+ .gp-version-body { display: flex; flex-direction: column; min-width: 0; }
1269
+ .gp-version-msg { color: var(--fg-0); font-size: var(--type-sm); overflow: hidden; text-overflow: ellipsis; }
1270
+ .gp-version-meta { color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); margin-top: 2px; }
1271
+ .gp-version-when { color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); white-space: nowrap; transition: opacity var(--dur-soft) ease; }
1272
+
1273
+ /* phase-27.1 — per-file History rows are click-to-preview when a canvas is open */
1274
+ .gp-history-scope { color: var(--fg-1); font-size: var(--type-xs); padding: var(--space-1) var(--space-2) var(--space-2); margin: 0; }
1275
+ .gp-history-scope b { color: var(--fg-0); }
1276
+ .gp-history-hint { color: var(--fg-2); font-size: var(--type-xs); text-align: center; padding: var(--space-3) var(--space-2); margin: 0; }
1277
+ .gp-version--clickable { width: 100%; text-align: left; font: inherit; color: inherit; background: none; border: 0; border-radius: var(--radius-sm); cursor: pointer; appearance: none; transition: background var(--dur-soft) ease; }
1278
+ .gp-version--clickable:hover { background: var(--bg-2); }
1279
+ .gp-version--clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
1280
+ .gp-version-cue { position: absolute; top: var(--space-2); right: var(--space-2); display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: var(--radius-pill); background: var(--accent-tint); color: var(--accent); font-size: var(--type-xs); font-weight: 600; opacity: 0; pointer-events: none; transition: opacity var(--dur-soft) ease; }
1281
+ .gp-version--clickable:hover .gp-version-cue,
1282
+ .gp-version--clickable:focus-visible .gp-version-cue { opacity: 1; }
1283
+ .gp-version--clickable:hover .gp-version-when,
1284
+ .gp-version--clickable:focus-visible .gp-version-when { opacity: 0; }
1285
+
1286
+ /* empty state — "Nothing to save" */
1287
+ .gp-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-4); padding: var(--space-8) var(--space-6); text-align: center; }
1288
+ .gp-empty-glyph { width: 52px; height: 52px; border-radius: var(--radius-pill); display: grid; place-items: center; background: color-mix(in oklab, var(--status-success) 16%, transparent); color: var(--status-success); }
1289
+ .gp-empty-glyph--publish { background: var(--accent-tint); color: var(--accent); }
1290
+ .gp-empty h3 { font-family: var(--font-display); font-size: var(--type-lg); color: var(--fg-0); margin: 0; font-weight: 600; }
1291
+ .gp-empty p { color: var(--fg-1); font-size: var(--type-sm); max-width: 30ch; margin: 0; }
1292
+
1293
+ /* tree dirty badge — mirrors the activity-overlay badge style (DDR-075) */
1294
+ .st-git-badge { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; margin-left: auto; border-radius: var(--radius-xs); font-family: var(--font-mono); font-size: 9px; font-weight: 700; line-height: 1; color: oklch(0.11 0.012 260); flex: none; }
1295
+ .st-git-badge[data-kind="M"] { background: var(--status-warn); }
1296
+ .st-git-badge[data-kind="A"] { background: var(--status-success); }
1297
+ .st-git-badge[data-kind="D"] { background: var(--status-error); }
1298
+ .st-git-badge[data-kind="U"] { background: transparent; border: 1px dashed var(--border-strong); color: var(--fg-2); }
1299
+
1300
+ /* ── Phase 27 (E2) — DiffView: clean rendered before/after, SYNCED zoom/pan ────
1301
+ * Ported from `.design/ui/DiffView.css`. Each pane renders a CLEAN canvas
1302
+ * (hide-chrome: no toolbar/minimap/devtools) inside a zoom/pan viewport. Both
1303
+ * panes share ONE view transform (locked): scroll to zoom, drag to pan, both
1304
+ * track the same region. Header reuses the app brand (.st-brand). */
1305
+ /* The shared .st-scrim top-anchors short dialogs (place-items:start center + 12vh
1306
+ * pad). The DiffView sheet is tall (92vh), so top-anchoring overflows the bottom
1307
+ * (12vh + 92vh > 100vh — the footer got cut off). Center it instead. */
1308
+ .dv-scrim { place-items: center; padding-top: 0; }
1309
+ .dv-sheet { width: min(1280px, 96vw); height: min(900px, 92vh); display: flex; flex-direction: column; background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden; }
1310
+ .dv-hd { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-default); flex: none; }
1311
+ .dv-hd .st-brand { padding-right: var(--space-3); border-right: 1px solid var(--border-default); }
1312
+ .dv-title { font-family: var(--font-display); font-weight: 600; font-size: var(--type-lg); color: var(--fg-0); }
1313
+ .dv-file { display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-3); border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-2); font-family: var(--font-mono); font-size: var(--type-sm); color: var(--fg-1); }
1314
+ .dv-spacer { flex: 1; }
1315
+ .dv-close { appearance: none; border: none; background: transparent; color: var(--fg-2); cursor: pointer; padding: var(--space-2); border-radius: var(--radius-xs); display: grid; place-items: center; }
1316
+ .dv-close:hover { color: var(--fg-0); background: var(--bg-3); }
1317
+ /* segmented mode toggle (DS .seg) */
1318
+ .dv-seg { display: inline-flex; border: 1px solid var(--border-default); border-radius: var(--radius-sm); overflow: hidden; background: var(--bg-2); }
1319
+ .dv-seg-btn { appearance: none; border: 0; background: transparent; color: var(--fg-2); font-size: var(--type-xs); font-family: var(--font-mono); padding: var(--space-2) var(--space-4); cursor: pointer; }
1320
+ .dv-seg-btn[aria-pressed="true"] { background: var(--bg-4); color: var(--fg-0); }
1321
+ .dv-seg-btn + .dv-seg-btn { border-left: 1px solid var(--border-subtle); }
1322
+
1323
+ /* phase-27.1 — "Saved version" picker: pick which past version the before pane shows */
1324
+ .dv-verpick { display: inline-flex; align-items: center; gap: var(--space-2); }
1325
+ .dv-verpick-lbl { color: var(--fg-2); font-size: var(--type-xs); }
1326
+ .dv-verpick-sel { appearance: none; border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-2); color: var(--fg-0); font-size: var(--type-xs); font-family: var(--font-mono); padding: var(--space-2) var(--space-5) var(--space-2) var(--space-3); max-width: 22ch; cursor: pointer; background-image: linear-gradient(45deg, transparent 50%, var(--fg-2) 50%), linear-gradient(135deg, var(--fg-2) 50%, transparent 50%); background-position: right 12px center, right 7px center; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
1327
+ .dv-verpick-sel:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
1328
+
1329
+ .dv-stage { padding: var(--space-4) var(--space-5) var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); flex: 1; min-height: 0; }
1330
+ .dv-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); align-items: stretch; flex: 1; min-height: 0; }
1331
+ .dv-col { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; min-height: 0; }
1332
+ .dv-col-hd { display: flex; align-items: center; gap: var(--space-2); flex: none; }
1333
+ .dv-col-tag { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); display: inline-flex; align-items: center; gap: var(--space-1); }
1334
+ .dv-col-tag.is-after { color: var(--accent); }
1335
+ .dv-col-who { color: var(--fg-2); font-size: var(--type-xs); margin-left: auto; }
1336
+
1337
+ /* the rendered-canvas thumbnail = a zoom/pan viewport over a clean iframe */
1338
+ .dv-thumb { position: relative; flex: 1; min-height: 0; background: var(--bg-0); border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; }
1339
+ .dv-thumb.is-after { border-color: var(--accent-muted); }
1340
+ .dv-thumb.ring-mine { box-shadow: 0 0 0 2px var(--accent); border-color: var(--accent); }
1341
+ .dv-thumb.ring-theirs { box-shadow: 0 0 0 2px var(--status-info); border-color: var(--status-info); }
1342
+ .dv-viewport { position: absolute; inset: 0; overflow: hidden; cursor: grab; touch-action: none; }
1343
+ .dv-viewport.is-panning { cursor: grabbing; }
1344
+ .dv-frame-wrap { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform-origin: 0 0; will-change: transform; }
1345
+ .dv-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: var(--bg-0); display: block; pointer-events: none; }
1346
+ .dv-thumb-note { position: absolute; inset: 0; display: grid; place-items: center; padding: var(--space-4); text-align: center; font-size: var(--type-xs); color: var(--fg-3); background: repeating-linear-gradient(45deg, var(--bg-1), var(--bg-1) 8px, var(--bg-2) 8px, var(--bg-2) 16px); }
1347
+
1348
+ /* shared zoom toolbar — drives the locked view for both panes */
1349
+ .dv-zoombar { display: inline-flex; align-items: center; gap: var(--space-1); align-self: center; background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-pill); padding: 2px; flex: none; }
1350
+ .dv-zoom-btn { appearance: none; border: none; background: transparent; color: var(--fg-1); cursor: pointer; width: 26px; height: 22px; border-radius: var(--radius-pill); font-size: var(--type-sm); line-height: 1; display: grid; place-items: center; }
1351
+ .dv-zoom-btn:hover { background: var(--bg-3); color: var(--fg-0); }
1352
+ .dv-zoom-val { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); min-width: 44px; text-align: center; cursor: pointer; appearance: none; border: none; background: transparent; }
1353
+ .dv-zoom-val:hover { color: var(--fg-0); }
1354
+ .dv-zoom-sync { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-3); padding-left: var(--space-2); border-left: 1px solid var(--border-subtle); margin-left: var(--space-1); }
1355
+
1356
+ /* overlay / slider compare (shares the locked view; frozen layers for the wipe) */
1357
+ .dv-overlay { --dv-split: 52%; position: relative; flex: 1; min-height: 0; margin: 0 auto; width: 100%; max-width: 900px; background: var(--bg-0); border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; }
1358
+ .dv-overlay-layer { position: absolute; inset: 0; }
1359
+ .dv-overlay-after { position: absolute; inset: 0; clip-path: inset(0 0 0 var(--dv-split)); }
1360
+ .dv-split { position: absolute; top: 0; bottom: 0; left: var(--dv-split); width: 2px; background: var(--accent); z-index: 3; }
1361
+ .dv-split-handle { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 26px; height: 26px; border-radius: var(--radius-pill); background: var(--accent); color: var(--accent-fg); display: grid; place-items: center; box-shadow: var(--shadow-md); cursor: ew-resize; }
1362
+ .dv-split-handle:focus-visible { outline: 2px solid var(--fg-0); outline-offset: 2px; }
1363
+ .dv-overlay-tag { position: absolute; bottom: var(--space-3); font-family: var(--font-mono); font-size: var(--type-xs); padding: 2px var(--space-3); border-radius: var(--radius-sm); background: color-mix(in oklab, var(--bg-0) 70%, transparent); color: var(--fg-1); z-index: 4; }
1364
+ .dv-overlay-tag.l { left: var(--space-3); }
1365
+ .dv-overlay-tag.r { right: var(--space-3); color: var(--accent); }
1366
+
1367
+ /* conflict picker */
1368
+ .dv-pick-intro { padding: var(--space-4) var(--space-6) 0; flex: none; }
1369
+ .dv-picker { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); padding: var(--space-4) var(--space-6) var(--space-2); flex: none; }
1370
+ .dv-pick { text-align: left; appearance: none; cursor: pointer; background: var(--bg-2); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); color: var(--fg-1); }
1371
+ .dv-pick:hover { border-color: var(--border-strong); background: var(--bg-3); }
1372
+ .dv-pick.is-rec { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: var(--accent-tint); }
1373
+ .dv-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1374
+ .dv-pick.is-rec .dv-pick-desc { color: var(--fg-1); }
1375
+ .dv-pick-hd { display: flex; align-items: center; gap: var(--space-2); }
1376
+ .dv-pick-title { font-weight: 600; color: var(--fg-0); font-size: var(--type-sm); }
1377
+ .dv-pick-rec { margin-left: auto; font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--accent-fg); background: var(--accent); border-radius: var(--radius-pill); padding: 1px var(--space-2); }
1378
+ .dv-pick-desc { font-size: var(--type-xs); color: var(--fg-2); line-height: var(--lh-xs); }
1379
+
1380
+ /* footer */
1381
+ .dv-ft { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-6); border-top: 1px solid var(--border-default); flex: none; }
1382
+ .dv-note { color: var(--fg-2); font-size: var(--type-xs); flex: 1; }
1383
+
1384
+ /* ── Phase 28 (E3) — GitHub identity rail + create/pull/share dialogs.
1385
+ * All chrome is the SHELL maude DS: solid surfaces (var(--bg-1)/2) and the
1386
+ * .st-dialog scrim+card treatment — NEVER the canvas-side `.panel` (it isn't in
1387
+ * the client bundle, which made the cards transparent). The identity rail docks
1388
+ * at the BOTTOM of the sidebar as a compact avatar; the menu opens upward. */
1389
+
1390
+ /* text inputs — the maude DS .input/.textarea recipe (lifted from the canvas-side
1391
+ * _components.css, which isn't in the client bundle → my fields fell back to native).
1392
+ * Scoped to the github dialogs so it can't collide with the shell's .st-search/.st-field. */
1393
+ .gi-dialog .input, .cp-dialog .input, .gi-dialog .textarea, .cp-dialog .textarea {
1394
+ font-family: var(--font-body); font-size: var(--type-sm); color: var(--fg-0);
1395
+ background: var(--bg-3); border: 1px solid var(--border-default); border-radius: var(--radius-sm);
1396
+ padding: var(--space-3) var(--space-4); width: 100%;
1397
+ transition: border-color var(--dur-soft) var(--ease-out), box-shadow var(--dur-soft) var(--ease-out);
1398
+ }
1399
+ .gi-dialog .input::placeholder, .cp-dialog .input::placeholder,
1400
+ .gi-dialog .textarea::placeholder, .cp-dialog .textarea::placeholder { color: var(--fg-3); }
1401
+ .gi-dialog .input:focus, .cp-dialog .input:focus, .gi-dialog .textarea:focus, .cp-dialog .textarea:focus {
1402
+ outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint);
1403
+ }
1404
+ .cp-dialog .textarea { resize: vertical; min-height: 76px; }
1405
+
1406
+ /* identity rail — sidebar footer */
1407
+ .gi-rail { position: relative; flex: 0 0 auto; margin-top: auto; padding: var(--space-2) var(--space-3); border-top: 1px solid var(--border-default); display: flex; flex-direction: column; gap: var(--space-2); }
1408
+ .gi-rail-hint { font-size: var(--type-xs); color: var(--fg-2); padding: var(--space-1) var(--space-1); }
1409
+ .gi-rail-signin { width: 100%; justify-content: center; }
1410
+ .gi-rail-err { font-size: var(--type-xs); color: var(--status-error); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1411
+ .gi-avatar { border-radius: var(--radius-pill); display: grid; place-items: center; font-family: var(--font-mono); font-size: 10px; font-weight: 600; color: var(--accent-fg); background: var(--accent); flex: 0 0 auto; }
1412
+ .gi-rail-account { display: flex; align-items: center; gap: var(--space-2); width: 100%; padding: var(--space-1) var(--space-2); border: 1px solid transparent; border-radius: var(--radius-md); background: transparent; color: var(--fg-0); cursor: pointer; text-align: left; }
1413
+ .gi-rail-account:hover { background: var(--bg-2); }
1414
+ .gi-rail-account.is-open { background: var(--bg-2); border-color: var(--border-default); }
1415
+ .gi-rail-account:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1416
+ .gi-rail-login { flex: 1; min-width: 0; font-family: var(--font-mono); font-size: var(--type-sm); color: var(--fg-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1417
+ .gi-rail-caret { color: var(--fg-2); flex: 0 0 auto; display: inline-flex; }
1418
+
1419
+ /* account menu — opens UPWARD, solid surface */
1420
+ .gi-menu { position: absolute; bottom: calc(100% + var(--space-1)); left: var(--space-3); right: var(--space-3); z-index: 9500; background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-2); }
1421
+ .gi-menu-hd { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-2) var(--space-3); border-bottom: 1px solid var(--border-subtle); margin-bottom: var(--space-1); }
1422
+ .gi-menu-id { display: flex; flex-direction: column; min-width: 0; }
1423
+ .gi-menu-name { font-weight: 600; color: var(--fg-0); font-size: var(--type-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1424
+ .gi-menu-login { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
1425
+ .gi-menu-item { display: flex; align-items: center; gap: var(--space-3); width: 100%; padding: var(--space-2) var(--space-3); border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--fg-1); font-size: var(--type-sm); cursor: pointer; text-align: left; }
1426
+ .gi-menu-item svg { color: var(--fg-2); }
1427
+ .gi-menu-item:hover { background: var(--bg-2); color: var(--fg-0); }
1428
+ .gi-menu-item:hover svg { color: var(--fg-1); }
1429
+ .gi-menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
1430
+ .gi-menu-item--danger, .gi-menu-item--danger svg { color: var(--status-error); }
1431
+ .gi-menu-item--danger:hover { background: color-mix(in oklab, var(--status-error) 14%, transparent); color: var(--status-error); }
1432
+ .gi-menu-sep { height: 1px; background: var(--border-subtle); margin: var(--space-1) 0; }
1433
+
1434
+ /* shared dialog shell (device-code + create/pull/share) — lifts .st-scrim/.st-dialog */
1435
+ .gi-modal, .cp-modal { position: fixed; inset: 0; display: grid; place-items: center; z-index: 9600; padding: var(--space-6); }
1436
+ .gi-scrim, .cp-scrim { position: fixed; inset: 0; background: color-mix(in oklab, var(--bg-0) 72%, transparent); }
1437
+ .gi-dialog, .cp-dialog { position: relative; background: var(--bg-1); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; overflow: hidden; animation: st-pop var(--dur-route) var(--ease-out); }
1438
+
1439
+ /* device-code dialog */
1440
+ .gi-dialog--code { width: min(460px, 92vw); padding: var(--space-6); gap: var(--space-5); }
1441
+ .gi-dc-head { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-3); }
1442
+ .gi-dc-head h2 { margin: 0; font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); }
1443
+ .gi-dc-marks { display: grid; place-items: center; width: 52px; height: 52px; border-radius: var(--radius-lg); background: var(--bg-2); border: 1px solid var(--border-default); color: var(--fg-0); }
1444
+ .gi-dc-head p { margin: 0; color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-base); max-width: 38ch; }
1445
+ .gi-dc-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
1446
+ .gi-dc-steps li { display: flex; align-items: flex-start; gap: var(--space-3); }
1447
+ .gi-dc-step-n { flex: 0 0 auto; width: 22px; height: 22px; display: grid; place-items: center; border-radius: var(--radius-pill); background: var(--accent-tint); border: 1px solid var(--accent-muted); color: var(--accent); font-family: var(--font-mono); font-size: var(--type-xs); font-weight: 600; }
1448
+ .gi-dc-step-tx { font-size: var(--type-sm); color: var(--fg-1); line-height: var(--lh-base); display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
1449
+ .gi-dc-url { font-family: var(--font-mono); color: var(--fg-0); background: var(--bg-2); border: 1px solid var(--border-subtle); border-radius: var(--radius-xs); padding: 1px var(--space-2); }
1450
+ .gi-code { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-4) var(--space-5); border: 1px solid var(--border-strong); border-radius: var(--radius-md); background: var(--bg-2); }
1451
+ .gi-code-val { font-family: var(--font-mono); font-size: var(--type-2xl); font-weight: 600; letter-spacing: 0.16em; color: var(--fg-0); }
1452
+ .gi-code-copy { flex: 0 0 auto; }
1453
+ .gi-dc-status { display: flex; align-items: center; gap: var(--space-3); font-size: var(--type-sm); color: var(--fg-2); }
1454
+ .gi-pulse { width: 9px; height: 9px; flex: 0 0 auto; border-radius: var(--radius-pill); background: var(--status-info); animation: gi-pulse 1.8s var(--ease-out) infinite; }
1455
+ @keyframes gi-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--status-info) 55%, transparent); } 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
1456
+ .gi-dc-foot { display: flex; align-items: center; gap: var(--space-3); }
1457
+ .gi-dc-foot-note { font-size: var(--type-xs); color: var(--fg-2); line-height: var(--lh-sm); }
1458
+
1459
+ /* create / pull / share dialog */
1460
+ .cp-dialog { width: min(560px, 94vw); max-height: 88vh; }
1461
+ .cp-dialog-hd { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-5) var(--space-5) var(--space-4); border-bottom: 1px solid var(--border-subtle); flex: none; }
1462
+ .cp-dialog-titles { flex: 1; min-width: 0; }
1463
+ .cp-dialog-hd h2 { margin: 0; font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); }
1464
+ .cp-dialog-hd p { margin: var(--space-1) 0 0; font-size: var(--type-sm); color: var(--fg-2); line-height: var(--lh-base); }
1465
+ .cp-body { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-5); overflow: auto; }
1466
+ .cp-body--list { gap: var(--space-3); }
1467
+ .cp-ft { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-top: 1px solid var(--border-subtle); background: var(--bg-1); flex: none; }
1468
+ .cp-spacer { flex: 1; }
1469
+ .cp-cl-glyph { flex: 0 0 auto; display: inline-flex; }
1470
+ .cp-field { display: flex; flex-direction: column; gap: var(--space-2); }
1471
+ .cp-field-label { font-size: var(--type-sm); font-weight: 600; color: var(--fg-0); display: flex; align-items: center; gap: var(--space-2); }
1472
+ .cp-optional { font-weight: 400; font-size: var(--type-xs); color: var(--fg-2); text-transform: lowercase; }
1473
+ .cp-field-help { font-size: var(--type-xs); color: var(--fg-2); line-height: var(--lh-base); }
1474
+ .cp-field-help b { color: var(--fg-1); font-family: var(--font-mono); font-weight: 500; }
1475
+ .cp-input, .cp-textarea { width: 100%; }
1476
+ .cp-textarea { resize: none; }
1477
+ .cp-seg { width: 100%; }
1478
+ .cp-seg button { flex: 1; justify-content: center; gap: var(--space-2); }
1479
+ .cp-seg button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
1480
+ .cp-invite { display: flex; align-items: center; gap: var(--space-2); position: relative; }
1481
+ .cp-invite-at { position: absolute; left: var(--space-3); font-family: var(--font-mono); color: var(--fg-2); pointer-events: none; }
1482
+ .cp-dialog .cp-invite-input { flex: 1; padding-left: calc(var(--space-3) + 0.9em); font-family: var(--font-mono); }
1483
+ .cp-invite-btn { flex: 0 0 auto; }
1484
+ .cp-repolist { display: flex; flex-direction: column; gap: var(--space-1); max-height: 360px; overflow: auto; }
1485
+ .cp-repo { display: flex; align-items: center; gap: var(--space-3); width: 100%; padding: var(--space-3); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); background: var(--bg-2); color: var(--fg-0); cursor: pointer; text-align: left; }
1486
+ .cp-repo:hover:not(:disabled) { border-color: var(--accent); background: var(--bg-3); }
1487
+ .cp-repo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1488
+ .cp-repo:disabled { cursor: default; opacity: 0.6; }
1489
+ .cp-repo.is-busy { opacity: 1; border-color: var(--accent); }
1490
+ .cp-repo > svg:first-child { color: var(--fg-2); flex: 0 0 auto; }
1491
+ .cp-repo-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; }
1492
+ .cp-repo-name { font-weight: 600; font-size: var(--type-sm); color: var(--fg-0); }
1493
+ .cp-repo-meta { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
1494
+ .cp-repo-go { color: var(--fg-3); flex: 0 0 auto; display: inline-flex; }
1495
+ .cp-repo:hover:not(:disabled) .cp-repo-go { color: var(--accent); }
1496
+ .cp-repo.is-busy .cp-repo-go { color: var(--accent); }
1497
+ .cp-spin { animation: cp-spin 0.9s linear infinite; transform-origin: center; }
1498
+ @keyframes cp-spin { to { transform: rotate(360deg); } }
1499
+
1500
+ @media (prefers-reduced-motion: reduce) { .gi-pulse, .cp-spin { animation: none; } .gi-dialog, .cp-dialog { animation: none; } }
1501
+
1502
+ /* ─── Presentation Mode ────────────────────────────────────────────────────
1503
+ View ▸ Presentation Mode — a non-destructive "artboards only" overlay. Hides
1504
+ every piece of shell chrome while leaving the canvas viewport (.main) mounted
1505
+ so its pan/zoom + open tabs survive an exit. The two structural rules below
1506
+ hide (a) the menubar + status bar — the .st-shell children that aren't the
1507
+ body — and (b) the sidebar / collapsed rail / resize grips / side panels —
1508
+ the .st-body children that aren't the viewport. The canvas iframe hides its
1509
+ OWN floating chrome (minimap, zoom pill, tool palette, annotations, comment
1510
+ pins) via the dgn:'view-chrome' bridge. Escape hatch: Esc or the pill. */
1511
+ .maude.is-present .st-shell > :not(.st-body) { display: none !important; }
1512
+ .maude.is-present .st-body > :not(.main) { display: none !important; }
1513
+ /* Top-level banners (.st-banner — SyncBanner + the "repo state changed" notice)
1514
+ are DELIBERATELY left visible in present mode: they're the DDR-102 fail-closed
1515
+ sync/divergence warnings, and an untrusted canvas (DDR-054) must not be able to
1516
+ silence a security-relevant notice by entering Presentation Mode (phase-28
1517
+ audit F-1). They're transient + rare, so they don't clutter a clean view. */
1518
+
1519
+ /* Floating escape-hatch pill — the only chrome visible while presenting.
1520
+ Deliberately understated (55% opacity) so it doesn't intrude on a clean
1521
+ screenshot, brightening to full on hover/focus. */
1522
+ .st-present-exit {
1523
+ position: fixed; top: var(--space-4); right: var(--space-4); z-index: 200;
1524
+ display: inline-flex; align-items: center; gap: var(--space-2);
1525
+ padding: var(--space-2) var(--space-3);
1526
+ appearance: none; cursor: pointer;
1527
+ font-family: var(--font-body); font-size: var(--type-sm); color: var(--fg-1);
1528
+ background: var(--bg-1); border: 1px solid var(--border-default);
1529
+ border-radius: var(--radius-pill);
1530
+ box-shadow: 0 4px 16px rgb(0 0 0 / 0.18);
1531
+ opacity: 0.72;
1532
+ transition: opacity var(--dur-soft) var(--ease-out),
1533
+ background var(--dur-soft) var(--ease-out), color var(--dur-soft) var(--ease-out);
1534
+ }
1535
+ .st-present-exit:hover,
1536
+ .st-present-exit:focus-visible { opacity: 1; background: var(--bg-3); color: var(--fg-0); }
1537
+ .st-present-exit > svg { color: var(--fg-2); flex: 0 0 auto; }
1538
+ .st-present-exit:hover > svg,
1539
+ .st-present-exit:focus-visible > svg { color: var(--accent); }
1540
+ .st-present-exit-kbd {
1541
+ font-family: var(--font-mono); font-size: var(--type-xs);
1542
+ color: var(--fg-3); border: 1px solid var(--border-subtle);
1543
+ border-radius: var(--radius-xs); padding: 1px 5px; line-height: 1.4;
1544
+ }
1545
+ @media (prefers-reduced-motion: reduce) { .st-present-exit { transition: none; } }
1546
+
1547
+ /* ── Phase 29 (E4) — OnboardingWizard (first-run). Ported from the approved
1548
+ `.design/ui/Onboarding.tsx` mockup (≥4.5/5); ob-* classes, every value a token. ── */
1549
+ .ob-overlay {
1550
+ position: fixed; inset: 0; z-index: 100;
1551
+ background: var(--bg-0);
1552
+ display: flex;
1553
+ }
1554
+ .ob-shell {
1555
+ position: absolute; inset: 0;
1556
+ display: flex;
1557
+ background: var(--bg-0); color: var(--fg-0);
1558
+ font-family: var(--font-body); font-size: var(--type-base); line-height: var(--lh-base);
1559
+ overflow: hidden;
1560
+ }
1561
+ .ob-rail {
1562
+ flex: 0 0 372px; display: flex; flex-direction: column; gap: var(--space-7);
1563
+ padding: var(--space-8) var(--space-7);
1564
+ background: radial-gradient(120% 90% at 0% 0%, var(--accent-tint) 0%, transparent 55%), var(--bg-1);
1565
+ border-right: 1px solid var(--border-default);
1566
+ }
1567
+ .ob-rail-brand { display: inline-flex; align-items: center; gap: var(--space-3); }
1568
+ /* maude mark tile — lifted from system/maude/preview/logo.css `.lg-mark`: spark in
1569
+ * --accent-fg on the indigo, bottom-right corner squared (bubble), accent-tint halo. */
1570
+ .ob-mark { display: grid; place-items: center; flex: 0 0 auto; background: var(--accent); color: var(--accent-fg); border-radius: 24% 24% 0 24%; box-shadow: 0 0 0 3px var(--accent-tint); }
1571
+ .ob-mark svg { width: 100%; height: 100%; display: block; }
1572
+ .ob-rail-wordmark { font-family: var(--font-display); font-size: var(--type-xl); font-weight: 600; letter-spacing: var(--tracking-tight); }
1573
+ .ob-rail-h { margin: 0 0 var(--space-3); font-family: var(--font-display); font-size: var(--type-2xl); line-height: var(--lh-xl); font-weight: 600; letter-spacing: var(--tracking-tight); color: var(--fg-0); }
1574
+ .ob-rail-lede p { margin: 0; max-width: 30ch; color: var(--fg-2); font-size: var(--type-md); line-height: var(--lh-lg); }
1575
+ .ob-rail-reassure { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
1576
+ .ob-rail-reassure li { display: flex; align-items: center; gap: var(--space-3); color: var(--fg-1); font-size: var(--type-sm); }
1577
+ .ob-rail-tick { flex: 0 0 auto; width: 20px; height: 20px; display: grid; place-items: center; border-radius: var(--radius-pill); background: var(--accent-tint); color: var(--accent); }
1578
+ .ob-rail-signed { display: inline-flex; align-items: center; gap: var(--space-3); align-self: flex-start; padding: var(--space-2) var(--space-4); border: 1px solid var(--border-default); border-radius: var(--radius-pill); background: var(--bg-2); font-size: var(--type-sm); color: var(--fg-1); }
1579
+ .ob-rail-signed b { color: var(--fg-0); font-weight: 600; }
1580
+ .ob-rail-signed-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--presence-online); box-shadow: 0 0 0 3px color-mix(in oklab, var(--presence-online) 28%, transparent); }
1581
+ .ob-rail-foot { margin-top: auto; color: var(--fg-2); font-size: var(--type-xs); font-family: var(--font-mono); }
1582
+
1583
+ .ob-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-6); padding: var(--space-8) clamp(var(--space-7), 6vw, 96px); overflow: auto; }
1584
+ .ob-back { align-self: flex-start; display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-3) var(--space-1) var(--space-2); border: 1px solid var(--border-default); border-radius: var(--radius-pill); background: var(--bg-1); color: var(--fg-1); font-size: var(--type-sm); cursor: pointer; }
1585
+ .ob-back:hover { border-color: var(--border-strong); color: var(--fg-0); }
1586
+ .ob-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1587
+ .ob-head { display: flex; flex-direction: column; gap: var(--space-2); }
1588
+ .ob-eyebrow { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--accent); }
1589
+ .ob-head h1 { margin: 0; font-family: var(--font-display); font-size: var(--type-3xl); line-height: var(--lh-2xl); font-weight: 600; letter-spacing: var(--tracking-tight); }
1590
+ .ob-head p { margin: 0; max-width: 56ch; color: var(--fg-2); font-size: var(--type-md); line-height: var(--lh-lg); }
1591
+
1592
+ .ob-doors { display: flex; flex-direction: column; gap: var(--space-4); max-width: 720px; }
1593
+ .ob-door { position: relative; display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-4); width: 100%; text-align: left; padding: var(--space-5); border: 1px solid var(--border-default); border-radius: var(--radius-lg); background: var(--bg-1); color: inherit; cursor: pointer; transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out), transform var(--dur-soft) var(--ease-out); }
1594
+ .ob-door:hover { border-color: var(--border-strong); background: var(--bg-2); transform: translateY(-1px); }
1595
+ .ob-door:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1596
+ .ob-door:disabled { opacity: 0.6; cursor: default; }
1597
+ .ob-door--primary { padding: var(--space-6); border-color: color-mix(in oklab, var(--accent) 55%, transparent); background: linear-gradient(180deg, var(--accent-tint) 0%, transparent 70%), var(--bg-1); box-shadow: var(--shadow-md); }
1598
+ .ob-door--primary:hover { border-color: var(--accent); }
1599
+ .ob-door--advanced { background: var(--bg-1); border-style: dashed; border-color: var(--border-strong); }
1600
+ .ob-door--advanced:hover { background: var(--bg-2); }
1601
+ .ob-door-icon { width: 48px; height: 48px; display: grid; place-items: center; border-radius: var(--radius-md); background: var(--bg-3); color: var(--fg-1); border: 1px solid var(--border-subtle); }
1602
+ .ob-door-icon--gh { background: var(--fg-0); color: var(--bg-0); border-color: transparent; }
1603
+ .ob-door-icon--quiet { width: 40px; height: 40px; background: var(--bg-2); color: var(--fg-2); }
1604
+ .ob-door-tx { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
1605
+ .ob-door-title { display: inline-flex; align-items: center; gap: var(--space-3); font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); }
1606
+ .ob-door--primary .ob-door-title { font-size: var(--type-xl); }
1607
+ .ob-door-sub { color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
1608
+ .ob-door-tag { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--accent); padding: 2px var(--space-2); border-radius: var(--radius-pill); background: var(--accent-tint); }
1609
+ .ob-door-adv { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); padding: 1px var(--space-2); border: 1px solid var(--border-default); border-radius: var(--radius-sm); }
1610
+ .ob-door-cta { display: flex; }
1611
+ .ob-door-btn { pointer-events: none; white-space: nowrap; }
1612
+ .ob-door-go { color: var(--fg-3); display: grid; place-items: center; }
1613
+ .ob-door:hover .ob-door-go { color: var(--fg-1); }
1614
+ .ob-foot-note { margin: 0; color: var(--fg-2); font-size: var(--type-xs); }
1615
+
1616
+ /* Opt-in crash reporting checkbox (Phase 32 / Task 4) — quiet footer affordance. */
1617
+ .ob-crash-optin { display: flex; align-items: flex-start; gap: var(--space-2); max-width: 560px; margin: var(--space-3) 0 0; color: var(--fg-2); font-size: var(--type-xs); line-height: var(--lh-md); cursor: pointer; text-align: left; }
1618
+ .ob-crash-optin input { margin-top: 2px; flex: 0 0 auto; accent-color: var(--accent); cursor: pointer; }
1619
+
1620
+ .ob-create { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-4); width: 100%; max-width: 720px; text-align: left; padding: var(--space-5); border: 1px solid color-mix(in oklab, var(--accent) 45%, transparent); border-radius: var(--radius-lg); background: linear-gradient(180deg, var(--accent-tint) 0%, transparent 80%), var(--bg-1); cursor: pointer; color: inherit; transition: border-color var(--dur-soft) var(--ease-out); }
1621
+ .ob-create:hover { border-color: var(--accent); }
1622
+ .ob-create:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1623
+ .ob-create-icon { width: 44px; height: 44px; display: grid; place-items: center; border-radius: var(--radius-md); background: var(--accent); color: var(--accent-fg); }
1624
+ .ob-create-tx { display: flex; flex-direction: column; gap: 2px; }
1625
+ .ob-create-title { font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); }
1626
+ .ob-create-sub { color: var(--fg-2); font-size: var(--type-sm); }
1627
+ .ob-create-btn { pointer-events: none; }
1628
+ .ob-section-label { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); margin-top: var(--space-2); }
1629
+ .ob-repolist { display: flex; flex-direction: column; gap: var(--space-2); max-width: 720px; }
1630
+ .ob-repo { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-4); width: 100%; text-align: left; padding: var(--space-4); border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-1); color: inherit; cursor: pointer; transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
1631
+ .ob-repo:hover { border-color: var(--border-strong); background: var(--bg-2); }
1632
+ .ob-repo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1633
+ .ob-repo:disabled { opacity: 0.6; cursor: default; }
1634
+ .ob-repo-icon { color: var(--fg-2); display: grid; place-items: center; }
1635
+ .ob-repo-tx { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
1636
+ .ob-repo-name { font-weight: 600; color: var(--fg-0); }
1637
+ .ob-repo-meta { color: var(--fg-2); font-size: var(--type-xs); font-family: var(--font-mono); }
1638
+ .ob-repo-go { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--fg-2); font-size: var(--type-sm); white-space: nowrap; padding: var(--space-1) var(--space-3); border-radius: var(--radius-sm); }
1639
+ .ob-repo:hover .ob-repo-go { color: var(--accent); background: var(--accent-tint); }
1640
+
1641
+ .ob-drop { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-3); width: 100%; max-width: 720px; padding: var(--space-8) var(--space-6); border: 1.5px dashed var(--border-strong); border-radius: var(--radius-lg); background: var(--bg-1); text-align: center; color: inherit; cursor: pointer; }
1642
+ .ob-drop:hover { border-color: var(--accent); }
1643
+ .ob-drop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1644
+ .ob-drop:disabled { opacity: 0.6; cursor: default; }
1645
+ .ob-drop-glyph { width: 64px; height: 64px; display: grid; place-items: center; border-radius: var(--radius-lg); background: var(--bg-3); color: var(--accent); margin-bottom: var(--space-2); }
1646
+ .ob-drop-title { font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); }
1647
+ .ob-drop-or { color: var(--fg-2); font-size: var(--type-sm); }
1648
+ .ob-callout { max-width: 720px; }
1649
+ .ob-callout-glyph { flex: 0 0 auto; display: grid; place-items: center; }
1650
+
1651
+ .ob-form { display: flex; flex-direction: column; gap: var(--space-4); max-width: 560px; }
1652
+ .ob-field { display: flex; flex-direction: column; gap: var(--space-2); }
1653
+ .ob-field-label { font-size: var(--type-sm); font-weight: 600; color: var(--fg-1); }
1654
+ .ob-field-wrap { position: relative; display: flex; align-items: center; }
1655
+ .ob-field-pre { position: absolute; left: var(--space-3); color: var(--fg-3); pointer-events: none; }
1656
+ .ob-input { width: 100%; }
1657
+ .ob-field-wrap .ob-input { padding-left: calc(var(--space-3) * 2 + 16px); font-family: var(--font-mono); }
1658
+ .ob-form-actions { display: flex; gap: var(--space-3); margin-top: var(--space-1); }
1659
+
1660
+ .ob-toast { position: fixed; bottom: var(--space-5); left: 50%; transform: translateX(-50%); max-width: 480px; z-index: 101; box-shadow: var(--shadow-lg); }
1661
+ .ob-spin { animation: ob-spin 0.8s linear infinite; }
1662
+ @keyframes ob-spin { to { transform: rotate(360deg); } }
1663
+ @media (prefers-reduced-motion: reduce) {
1664
+ .ob-door, .ob-create, .ob-repo, .ob-back { transition-duration: 1ms; }
1665
+ .ob-door:hover { transform: none; }
1666
+ .ob-spin { animation-duration: 1ms; }
1667
+ }
1668
+
1669
+ /* ── Phase 29 (E4) — RepoBranchSwitcher. REDESIGNED to the approved mockup
1670
+ (.design/ui/RepoBranchSwitcher.tsx): a compact ONE-LINE dock at the BOTTOM of the
1671
+ sidebar (above the IdentityBar avatar) that opens ONE popup UPWARD. Mirrors the
1672
+ gi-rail/gi-menu anatomy so the two bottom surfaces read as one dock. ── */
1673
+ .rb-dock-wrap {
1674
+ flex: 0 0 auto;
1675
+ display: flex; flex-direction: column; gap: var(--space-1);
1676
+ padding: var(--space-3);
1677
+ border-top: 1px solid var(--border-default);
1678
+ background: var(--bg-1);
1679
+ box-shadow: 0 -10px 18px -12px color-mix(in oklab, var(--bg-0) 80%, transparent);
1680
+ }
1681
+ .rb-dock { position: relative; }
1682
+ /* The compact one-line trigger — "📁 <project> · ◐ <version> ⌃" */
1683
+ .rb-trigger {
1684
+ display: flex; align-items: center; gap: var(--space-2);
1685
+ width: 100%; text-align: left;
1686
+ padding: var(--space-2) var(--space-3);
1687
+ border: 1px solid var(--border-default); border-radius: var(--radius-md);
1688
+ background: var(--bg-2); color: var(--fg-1); cursor: pointer; font-size: var(--type-sm);
1689
+ transition: border-color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out);
1690
+ }
1691
+ .rb-trigger:hover, .rb-trigger.is-open { border-color: var(--border-strong); background: var(--bg-3); }
1692
+ .rb-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1693
+ .rb-trigger-icon { color: var(--accent); flex: 0 0 auto; display: grid; place-items: center; }
1694
+ .rb-trigger-proj { font-weight: 600; color: var(--fg-0); flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1695
+ .rb-trigger-sep { color: var(--fg-3); flex: 0 0 auto; }
1696
+ .rb-trigger-ver { display: inline-flex; align-items: center; gap: var(--space-1); min-width: 0; flex: 1 1 auto; color: var(--presence-online); }
1697
+ .rb-trigger-ver.is-draft { color: var(--status-warn); }
1698
+ .rb-trigger-ver-name { color: var(--fg-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1699
+ .rb-trigger-caret { color: var(--fg-2); flex: 0 0 auto; }
1700
+ /* Web studio: the switcher degrades to a read-only awareness badge (DDR-119).
1701
+ Git vocab ("branch: X"), no hover affordance, no actions — the dev switches
1702
+ from their terminal. Neutral colour distinguishes it from the native dock's
1703
+ green "Shared version" / amber draft. */
1704
+ .rb-trigger--ro { cursor: default; }
1705
+ .rb-trigger--ro:hover { border-color: var(--border-default); background: var(--bg-2); }
1706
+ .rb-trigger-ver--ro { color: var(--fg-2); flex: 0 1 auto; }
1707
+ .rb-trigger-ver--ro .rb-trigger-ver-name { color: var(--fg-1); font-family: var(--font-mono); font-size: var(--type-xs); }
1708
+ /* GitPanel read-only footer hint (web studio — actions live in the terminal). */
1709
+ .gp-ro-hint { padding: var(--space-3) var(--space-4); color: var(--fg-2); }
1710
+ /* The popup — opens UPWARD from the dock (gi-menu anatomy). SOLID opaque menu
1711
+ * surface + border here (NOT the canvas `.panel`, which isn't in the client bundle
1712
+ * — phase-28 lesson; the tree must never bleed through). */
1713
+ .rb-pop { padding: var(--space-2); display: flex; flex-direction: column; gap: 1px; background: var(--bg-2); border: 1px solid var(--border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); }
1714
+ .rb-pop--up { position: absolute; left: 0; right: 0; bottom: calc(100% + var(--space-1)); z-index: 30; max-height: 600px; overflow-y: auto; }
1715
+ .rb-pop-hd, .rb-pop-grouplabel { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--fg-2); padding: var(--space-2) var(--space-3) var(--space-1); }
1716
+ .rb-pop-grouplabel { padding-top: var(--space-3); }
1717
+ .rb-pop-item { display: flex; align-items: center; gap: var(--space-3); width: 100%; text-align: left; padding: var(--space-2) var(--space-3); border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--fg-1); cursor: pointer; transition: background var(--dur-soft) var(--ease-out); }
1718
+ .rb-pop-item:hover { background: var(--bg-2); }
1719
+ .rb-pop-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
1720
+ .rb-pop-item.is-current { background: var(--accent-tint); }
1721
+ .rb-pop-item--action { color: var(--accent); }
1722
+ .rb-pop-icon { flex: 0 0 auto; color: var(--fg-2); display: grid; place-items: center; }
1723
+ .rb-pop-item--action .rb-pop-icon { color: var(--accent); }
1724
+ .rb-pop-icon--shared { color: var(--presence-online); }
1725
+ .rb-pop-icon--draft { color: var(--status-warn); }
1726
+ .rb-pop-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0; }
1727
+ .rb-pop-name { font-weight: 600; font-size: var(--type-sm); color: var(--fg-0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1728
+ .rb-pop-item--action .rb-pop-name { color: var(--accent); }
1729
+ .rb-pop-sub { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1730
+ .rb-pop-item.is-current .rb-pop-sub { color: var(--fg-1); }
1731
+ .rb-pop-check { color: var(--accent); flex: 0 0 auto; }
1732
+ .rb-pop-sep { height: 1px; background: var(--border-default); margin: var(--space-2); }
1733
+ /* fold-back CTA (Task 7) — the one filled action in the Version section. Compact:
1734
+ * type-sm title + type-xs sub + tight padding, so it reads as a strong row, not a
1735
+ * giant banner. */
1736
+ .rb-fold { display: flex; align-items: center; gap: var(--space-2); width: 100%; text-align: left; margin: var(--space-2) 0; padding: var(--space-2) var(--space-3); border: 0; border-radius: var(--radius-sm); background: var(--accent); color: var(--accent-fg); cursor: pointer; transition: background var(--dur-soft) var(--ease-out); }
1737
+ .rb-fold:hover { background: var(--accent-hover); }
1738
+ .rb-fold:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
1739
+ .rb-fold-icon { flex: 0 0 auto; display: grid; place-items: center; color: var(--accent-fg); }
1740
+ .rb-fold-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
1741
+ .rb-fold-title { font-weight: 600; font-size: var(--type-sm); line-height: var(--lh-sm); color: var(--accent-fg); }
1742
+ .rb-fold-sub { font-size: var(--type-xs); line-height: var(--lh-sm); color: var(--accent-fg); }
1743
+ /* new-draft inline form (anchored upward above the dock). Solid bg (not `.panel`). */
1744
+ .rb-newdraft { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); }
1745
+ .rb-newdraft--up { position: absolute; left: 0; right: 0; bottom: calc(100% + var(--space-1)); z-index: 30; background: var(--bg-1); border: 1px solid var(--border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); }
1746
+ .rb-newdraft-field { display: flex; flex-direction: column; gap: var(--space-2); }
1747
+ .rb-newdraft-label { font-size: var(--type-sm); font-weight: 600; color: var(--fg-1); }
1748
+ .rb-newdraft-input { width: 100%; }
1749
+ .rb-newdraft-actions { display: flex; gap: var(--space-2); justify-content: flex-end; }
1750
+ .rb-newdraft-err, .rb-switcher-err { color: var(--status-error); font-size: var(--type-xs); }
1751
+ .rb-newdraft-hint { margin: 0; color: var(--fg-2); font-size: var(--type-xs); line-height: var(--lh-md); }
1752
+ /* switching state (compact, in the dock). */
1753
+ .rb-switching { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-2); color: var(--fg-1); font-size: var(--type-sm); }
1754
+ .rb-switching b { color: var(--fg-0); }
1755
+ .rb-spin { color: var(--accent); animation: rb-spin 0.8s linear infinite; flex: 0 0 auto; }
1756
+ @keyframes rb-spin { to { transform: rotate(360deg); } }
1757
+ /* fold-back confirm sheet (modal over the shell). */
1758
+ .rb-scrim { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: var(--space-6); background: color-mix(in oklab, var(--bg-0) 64%, transparent); backdrop-filter: blur(2px); }
1759
+ .rb-sheet { width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-6); background: var(--bg-1); border: 1px solid var(--border-strong); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); text-align: left; }
1760
+ .rb-sheet-icon { width: 38px; height: 38px; border-radius: var(--radius-md); display: grid; place-items: center; color: var(--accent); background: var(--accent-tint); margin-bottom: var(--space-1); }
1761
+ .rb-sheet-title { margin: 0; font-family: var(--font-display); font-size: var(--type-lg); font-weight: 600; color: var(--fg-0); letter-spacing: var(--tracking-tight); }
1762
+ .rb-sheet-body { margin: 0; color: var(--fg-1); font-size: var(--type-md); line-height: var(--lh-md); }
1763
+ .rb-sheet-body b { color: var(--fg-0); font-weight: 600; }
1764
+ .rb-sheet-meta { margin: 0; color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
1765
+ .rb-sheet-actions { display: flex; gap: var(--space-2); justify-content: flex-end; margin-top: var(--space-2); }
1766
+ @media (prefers-reduced-motion: reduce) {
1767
+ .rb-spin { animation-duration: 1ms; }
1768
+ .rb-trigger, .rb-pop-item, .rb-fold, .rb-identity-account { transition-duration: 1ms; }
1769
+ }
1770
+
1161
1771
  }