slidemind 0.3.20 → 0.4.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +591 -15
- package/README.md +202 -7
- package/bin/slidemind.mjs +50 -2
- package/package.json +2 -2
- package/skills/create-slides/SKILL.md +484 -886
- package/skills/search/SKILL.md +46 -23
- package/src/bridge/build-and-push.mjs +548 -73
- package/src/bridge/bundle.mjs +100 -31
- package/src/bridge/capture.mjs +14 -17
- package/src/bridge/client/brands.mjs +157 -18
- package/src/bridge/client/engine-routing.mjs +48 -13
- package/src/bridge/client/engine-search.mjs +24 -1
- package/src/bridge/client/render.mjs +27 -1
- package/src/bridge/client/transport.mjs +499 -23
- package/src/bridge/client.mjs +10 -0
- package/src/bridge/config.mjs +67 -6
- package/src/bridge/engine-download.mjs +0 -10
- package/src/bridge/graph-auth.mjs +55 -3
- package/src/bridge/image-intent-envelope.mjs +239 -0
- package/src/bridge/package-preview.mjs +67 -0
- package/src/bridge/sharepoint.mjs +914 -0
- package/src/builders/asset-fetch.mjs +203 -0
- package/src/builders/block-dividers.mjs +83 -0
- package/src/builders/build.mjs +171 -87
- package/src/builders/card-height.mjs +294 -0
- package/src/builders/chart-hole.mjs +183 -0
- package/src/builders/chart-jsx.mjs +410 -0
- package/src/builders/chart-labels.mjs +326 -0
- package/src/builders/concept-geometry.mjs +370 -0
- package/src/builders/concept-intent.mjs +200 -0
- package/src/builders/concept-layout.mjs +79 -0
- package/src/builders/concept-lines.mjs +509 -0
- package/src/builders/concept-lists.mjs +270 -0
- package/src/builders/concept-marks.mjs +84 -0
- package/src/builders/concept-relationships.mjs +12 -0
- package/src/builders/concept-spec.mjs +645 -0
- package/src/builders/concept-text.mjs +140 -0
- package/src/builders/concept-waves.mjs +57 -0
- package/src/builders/copy-fit.mjs +139 -0
- package/src/builders/design-tokens.mjs +347 -0
- package/src/builders/draft-check.mjs +552 -340
- package/src/builders/draft-lines.mjs +369 -0
- package/src/builders/edit-route.mjs +29 -0
- package/src/builders/figure-sketch.mjs +375 -0
- package/src/builders/fold-sets.mjs +639 -0
- package/src/builders/gate-server.mjs +9 -4
- package/src/builders/gate-session.js +273 -12
- package/src/builders/gate-shell.js +1494 -0
- package/src/builders/image-intent-check.mjs +308 -0
- package/src/builders/image-use-reconcile.mjs +107 -0
- package/src/builders/kit-helpers.mjs +121 -0
- package/src/builders/layout-names.mjs +32 -0
- package/src/builders/legacy-reference-uses.mjs +179 -0
- package/src/builders/line-fit.mjs +224 -0
- package/src/builders/line-native.mjs +895 -0
- package/src/builders/line-relations.mjs +230 -0
- package/src/builders/lint-fix.mjs +117 -9
- package/src/builders/lint.mjs +25 -20
- package/src/builders/list-jsx.mjs +88 -0
- package/src/builders/placement.mjs +133 -0
- package/src/builders/plan-checks.mjs +135 -0
- package/src/builders/plan-comments.mjs +19 -0
- package/src/builders/plan-handlers.mjs +95 -0
- package/src/builders/plan-markdown-edit.mjs +3 -3
- package/src/builders/plan-overlay.js +1530 -1608
- package/src/builders/plan.mjs +689 -186
- package/src/builders/preset-definitions.json +1 -0
- package/src/builders/preset-eval.mjs +244 -0
- package/src/builders/preview.html +51 -120
- package/src/builders/red-thread-backbone.mjs +135 -36
- package/src/builders/repair.mjs +205 -0
- package/src/builders/repeat-groups.mjs +540 -0
- package/src/builders/resolve-skill.mjs +5 -4
- package/src/builders/review-overlay.js +296 -293
- package/src/builders/review.mjs +305 -84
- package/src/builders/rule-shift.mjs +96 -0
- package/src/builders/seat.mjs +354 -0
- package/src/builders/settle-driver.mjs +236 -0
- package/src/builders/settle.mjs +1448 -0
- package/src/builders/slide-prep.mjs +67 -0
- package/src/builders/spec-assets.mjs +236 -0
- package/src/builders/spec-match.mjs +56 -0
- package/src/builders/stack.mjs +413 -0
- package/src/builders/storyboard-markdown.mjs +70 -27
- package/src/builders/storyboard-schema.mjs +54 -114
- package/src/builders/text-blocks.mjs +212 -0
- package/src/builders/text-card-fit.mjs +552 -0
- package/src/builders/text-stack.mjs +276 -0
- package/src/builders/transcribe.mjs +1069 -0
- package/src/cli/assets.mjs +164 -0
- package/src/cli/common.mjs +173 -12
- package/src/cli/concept-spec-support.mjs +76 -0
- package/src/cli/concepts.mjs +1002 -103
- package/src/cli/deck.mjs +401 -65
- package/src/cli/diagnose.mjs +4 -2
- package/src/cli/engine-helpers.mjs +17 -10
- package/src/cli/engine-results.mjs +76 -3
- package/src/cli/help.mjs +232 -28
- package/src/cli/install.mjs +9 -0
- package/src/cli/maintenance.mjs +104 -0
- package/src/cli/read.mjs +2 -1
- package/src/cli/ready.mjs +6 -3
- package/src/cli/record.mjs +522 -0
- package/src/cli/remote.mjs +818 -0
- package/src/cli/revision.mjs +686 -0
- package/src/cli/search.mjs +30 -11
- package/src/cli/session.mjs +56 -13
- package/src/cli/setup.mjs +46 -2
- package/src/cli/status.mjs +142 -33
- package/src/cli/tasks.mjs +246 -0
- package/src/cli/transcribe.mjs +854 -0
- package/src/cli/workspace-ui.mjs +260 -0
- package/src/cli/workspace.mjs +212 -34
- package/src/install-channel.mjs +64 -7
- package/src/lib/adopt.mjs +346 -25
- package/src/lib/concept-spec-binding.mjs +96 -0
- package/src/lib/conversions.mjs +70 -6
- package/src/lib/convert-folded.mjs +107 -0
- package/src/lib/deck-paths.mjs +418 -0
- package/src/lib/durable-ids.mjs +47 -0
- package/src/lib/edit-operations.mjs +316 -0
- package/src/lib/edit-state.mjs +1244 -0
- package/src/lib/edit-transitions.mjs +120 -0
- package/src/lib/extensions.mjs +501 -0
- package/src/lib/image-assets.mjs +465 -0
- package/src/lib/image-derivatives.mjs +234 -0
- package/src/lib/image-intent-fingerprint.mjs +70 -0
- package/src/lib/image-intent-tags.mjs +176 -0
- package/src/lib/image-intent.mjs +802 -0
- package/src/lib/image-use-overrides.mjs +279 -0
- package/src/lib/inline-components.mjs +613 -0
- package/src/lib/lint-converted.mjs +68 -4
- package/src/lib/merge-json.mjs +163 -0
- package/src/lib/overwrite-guard.mjs +3 -3
- package/src/lib/presentation-context.mjs +531 -0
- package/src/lib/preservation-tags.mjs +157 -0
- package/src/lib/preservation-verdict.mjs +1342 -0
- package/src/lib/publish.mjs +1557 -0
- package/src/lib/rebase.mjs +945 -0
- package/src/lib/reconcile-ack.mjs +4 -6
- package/src/lib/reconcile.mjs +62 -24
- package/src/lib/record-client.mjs +175 -0
- package/src/lib/record-state.mjs +151 -0
- package/src/lib/remote.mjs +661 -0
- package/src/lib/revision.mjs +1210 -0
- package/src/lib/slide-guids.mjs +4 -6
- package/src/lib/slide-preservation.mjs +423 -0
- package/src/lib/slide-selection.mjs +9 -0
- package/src/lib/workspace-transaction.mjs +117 -0
- package/src/pptx/content-digest.mjs +334 -0
- package/src/pptx/deck-assemble.mjs +1278 -0
- package/src/pptx/fill/engine.mjs +2 -3
- package/src/pptx/fill/freeform.mjs +6 -3
- package/src/pptx/ooxml.mjs +20 -0
- package/src/pptx/package-evidence.mjs +383 -0
- package/src/pptx/tags.mjs +163 -11
- package/src/update-check.mjs +22 -4
- package/src/workspace/adapters.mjs +222 -0
- package/src/workspace/auth.mjs +256 -0
- package/src/workspace/autostart.mjs +204 -0
- package/src/workspace/daemon.mjs +360 -0
- package/src/workspace/discovery.mjs +180 -0
- package/src/workspace/edit.mjs +167 -0
- package/src/workspace/events.mjs +52 -0
- package/src/workspace/gate-client.mjs +290 -0
- package/src/workspace/handback.mjs +73 -0
- package/src/workspace/lifecycle.mjs +635 -0
- package/src/workspace/operations.mjs +200 -0
- package/src/workspace/pick-folder.mjs +152 -0
- package/src/workspace/registry.mjs +359 -0
- package/src/workspace/remote-links.mjs +397 -0
- package/src/workspace/remote-status.mjs +359 -0
- package/src/workspace/routes.mjs +1331 -0
- package/src/workspace/server.mjs +159 -0
- package/src/workspace/sync.mjs +1119 -0
- package/src/workspace/task-actions.mjs +215 -0
- package/src/workspace/tasks.mjs +507 -0
- package/src/workspace/ui/app.js +1886 -0
- package/src/workspace/ui/index.html +141 -0
- package/src/workspace/ui/plan-bridge.js +120 -0
- package/src/workspace/ui/sharepoint.svg +59 -0
- package/src/workspace/ui/styles.css +423 -0
- package/src/builders/visual-families.mjs +0 -46
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/* The workspace page — the same chrome as the plan and review gates
|
|
2
|
+
(src/builders/review-overlay.js): dark surfaces, Poppins, the slide|mind
|
|
3
|
+
wordmark, white primary button, ghost buttons, uppercase state chips. */
|
|
4
|
+
:root {
|
|
5
|
+
color-scheme: dark;
|
|
6
|
+
--sm-bg: #111113;
|
|
7
|
+
--sm-surface: #161618;
|
|
8
|
+
--sm-surface-2: #1c1c20;
|
|
9
|
+
--sm-border: #2b2b30;
|
|
10
|
+
--sm-fg: #ededed;
|
|
11
|
+
--sm-dim: #9a9aa0;
|
|
12
|
+
--sm-accent: #a9c2ff;
|
|
13
|
+
--sm-success: #2ecc71;
|
|
14
|
+
--sm-warn: #fbbf24;
|
|
15
|
+
--sm-danger: #f87171;
|
|
16
|
+
--sm-font: "Poppins", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
17
|
+
--sm-word: "Urbanist", var(--sm-font);
|
|
18
|
+
--sm-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
19
|
+
--sm-top: 62px;
|
|
20
|
+
--sm-side: 272px;
|
|
21
|
+
}
|
|
22
|
+
@keyframes sm-drift-a { 0%, 100% { transform: translateX(-5px); } 50% { transform: translateX(5px); } }
|
|
23
|
+
@keyframes sm-drift-b { 0%, 100% { transform: translateX(5px); } 50% { transform: translateX(-5px); } }
|
|
24
|
+
@keyframes sm-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
|
|
25
|
+
@keyframes sm-spin { to { transform: rotate(360deg); } }
|
|
26
|
+
|
|
27
|
+
* { box-sizing: border-box; }
|
|
28
|
+
[hidden] { display: none !important; }
|
|
29
|
+
html, body { margin: 0; height: 100%; background: var(--sm-bg); color: var(--sm-fg); }
|
|
30
|
+
body { font: 13.5px/1.5 var(--sm-font); -webkit-font-smoothing: antialiased; overflow: hidden; }
|
|
31
|
+
a { color: var(--sm-accent); text-decoration: none; }
|
|
32
|
+
a:hover { text-decoration: underline; }
|
|
33
|
+
code { font-family: var(--sm-mono); font-size: .9em; background: var(--sm-surface-2); padding: .1em .4em; border-radius: 5px; }
|
|
34
|
+
h1, h2, h3 { margin: 0; font-weight: 600; line-height: 1.25; }
|
|
35
|
+
h1 { font-size: 20px; }
|
|
36
|
+
h2 { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--sm-dim); }
|
|
37
|
+
.muted { color: var(--sm-dim); }
|
|
38
|
+
.ok { color: var(--sm-success); }
|
|
39
|
+
.error { color: var(--sm-danger); background: rgba(248, 113, 113, .1); border: 1px solid rgba(248, 113, 113, .35); padding: 9px 12px; border-radius: 9px; margin: 0 0 12px; font-size: 12.5px; }
|
|
40
|
+
|
|
41
|
+
/* ---------- top bar ---------- */
|
|
42
|
+
.top { position: fixed; top: 0; left: 0; right: 0; z-index: 20; height: var(--sm-top); display: flex; align-items: center; gap: 14px; padding: 0 18px; background: var(--sm-bg); border-bottom: 1px solid var(--sm-border); user-select: none; }
|
|
43
|
+
.brand { display: flex; align-items: center; gap: 11px; color: var(--sm-fg); }
|
|
44
|
+
.brand:hover { text-decoration: none; }
|
|
45
|
+
.logo { position: relative; width: 48px; height: 27px; border-radius: 5px; overflow: hidden; flex-shrink: 0; background: #0a0c11; box-shadow: 0 1px 3px rgba(0, 0, 0, .5); }
|
|
46
|
+
.logo svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
|
|
47
|
+
.word { display: flex; flex-direction: column; line-height: .98; font-family: var(--sm-word); font-weight: 300; font-size: 13px; letter-spacing: .46em; }
|
|
48
|
+
.word b { font-weight: 300; display: block; }
|
|
49
|
+
.word .t { animation: sm-drift-a 20s ease-in-out infinite; }
|
|
50
|
+
.word .b { margin-left: .18em; animation: sm-drift-b 20s ease-in-out infinite; }
|
|
51
|
+
.sep { width: 1px; height: 28px; background: var(--sm-border); }
|
|
52
|
+
.meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
53
|
+
.meta .t { font-weight: 600; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
54
|
+
.meta .h { font-size: 11.5px; color: var(--sm-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
55
|
+
/* the top bar is the page's one header: a deck's name can be copied, its folder line reveals the folder */
|
|
56
|
+
.meta .t { user-select: text; }
|
|
57
|
+
.meta .meta-folder { gap: 5px; max-width: 100%; padding: 0; border: 0; border-radius: 4px; background: none; color: inherit; font: inherit; }
|
|
58
|
+
.meta .meta-folder:hover { background: none; color: var(--sm-fg); }
|
|
59
|
+
.meta .meta-folder svg { width: 12px; height: 12px; }
|
|
60
|
+
.top-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
|
|
61
|
+
.top-actions:empty { display: none; }
|
|
62
|
+
.grow { flex: 1; }
|
|
63
|
+
.top nav { display: flex; align-items: center; gap: 8px; }
|
|
64
|
+
.badge { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--sm-accent); color: #0f0f0f; font-size: 10.5px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; font-variant-numeric: tabular-nums; }
|
|
65
|
+
.badge:empty { display: none; }
|
|
66
|
+
|
|
67
|
+
/* ---------- shell: sidebar + main ---------- */
|
|
68
|
+
.shell { position: fixed; inset: var(--sm-top) 0 0 0; display: grid; grid-template-columns: auto 1fr; }
|
|
69
|
+
/* the sidebar is dragged wider/narrower by the full-height grip on its right edge (app.js sidebarGrip) */
|
|
70
|
+
#side { position: relative; width: var(--sm-side); min-width: 200px; max-width: 50vw; display: flex; flex-direction: column; min-height: 0; background: var(--sm-surface); border-right: 1px solid var(--sm-border); }
|
|
71
|
+
#side-grip { position: absolute; top: 0; bottom: 0; right: -4px; width: 8px; cursor: col-resize; z-index: 5; }
|
|
72
|
+
#side-grip::after { content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 2px; background: var(--sm-accent); opacity: 0; transition: opacity .15s; }
|
|
73
|
+
#side-grip:hover::after, body.resizing #side-grip::after { opacity: .8; }
|
|
74
|
+
body.resizing { cursor: col-resize; user-select: none; }
|
|
75
|
+
body.resizing iframe { pointer-events: none; }
|
|
76
|
+
button.icon { padding: 0; width: 22px; height: 22px; justify-content: center; border-radius: 7px; color: var(--sm-dim); }
|
|
77
|
+
button.icon:hover { color: var(--sm-fg); }
|
|
78
|
+
button.icon .arrow { font-size: 13px; line-height: 1; }
|
|
79
|
+
/* scrollbars stay usable but invisible */
|
|
80
|
+
.side-body, .page, .fs-list { scrollbar-width: none; }
|
|
81
|
+
.side-body::-webkit-scrollbar, .page::-webkit-scrollbar { display: none; }
|
|
82
|
+
|
|
83
|
+
/* ---------- the navigation: search · Inbox · folders of decks · add ----------
|
|
84
|
+
Every row is one line, 30px tall, left-aligned at the same inset; folders
|
|
85
|
+
indent their decks by one chevron. The one colour on the rail is the count
|
|
86
|
+
pill for "your agent is waiting" — the same pill as the Inbox row's. */
|
|
87
|
+
.side-search { position: relative; margin: 12px 10px 6px; }
|
|
88
|
+
.side-search-ico { position: absolute; left: 10px; top: 50%; width: 14px; height: 14px; transform: translateY(-50%); color: var(--sm-dim); pointer-events: none; }
|
|
89
|
+
.side-search input[type=search] { padding: 7px 44px 7px 31px; border-radius: 9px; font-size: 12.5px; background: var(--sm-bg); }
|
|
90
|
+
.side-search input[type=search]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
|
|
91
|
+
.side-kbd { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); padding: 1px 5px; border: 1px solid var(--sm-border); border-radius: 5px; font: 500 10px/1.5 var(--sm-font); color: var(--sm-dim); background: var(--sm-surface); pointer-events: none; transition: opacity .12s; }
|
|
92
|
+
.side-search input:focus ~ .side-kbd, .side-search input:not(:placeholder-shown) ~ .side-kbd { opacity: 0; }
|
|
93
|
+
.side-nav { padding: 0 8px; }
|
|
94
|
+
.side-link { display: flex; align-items: center; gap: 9px; height: 30px; padding: 0 8px 0 9px; border-radius: 8px; font-weight: 500; font-size: 12.5px; color: var(--sm-fg); border: 1px solid transparent; transition: background .12s; }
|
|
95
|
+
.side-link:hover { background: rgba(255, 255, 255, .05); text-decoration: none; }
|
|
96
|
+
.side-link svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--sm-dim); transition: color .12s; }
|
|
97
|
+
.side-link:hover svg, .side-link[aria-current="page"] svg { color: var(--sm-fg); }
|
|
98
|
+
.side-link-txt { flex: 1; min-width: 0; }
|
|
99
|
+
.side-link[aria-current="page"] { background: rgba(169, 194, 255, .1); }
|
|
100
|
+
.side-sec { display: flex; align-items: center; gap: 8px; padding: 14px 10px 4px 17px; }
|
|
101
|
+
.side-sec h2 { flex: 1; min-width: 0; }
|
|
102
|
+
.side-filter { margin: 0; padding: 2px; border-radius: 7px; }
|
|
103
|
+
.side-filter button { padding: 2px 8px; font-size: 10.5px; border-radius: 5px; }
|
|
104
|
+
.side-body { flex: 1; overflow-y: auto; padding: 2px 8px 12px; }
|
|
105
|
+
.side-foot { padding: 8px; border-top: 1px solid var(--sm-border); display: flex; gap: 6px; }
|
|
106
|
+
.side-foot .btn { flex: 1; justify-content: center; border-color: transparent; color: var(--sm-dim); font-weight: 500; }
|
|
107
|
+
.side-foot .btn:hover { color: var(--sm-fg); background: rgba(255, 255, 255, .05); }
|
|
108
|
+
#more { margin: 6px 0 0; width: 100%; justify-content: center; border-color: transparent; color: var(--sm-dim); font-weight: 500; }
|
|
109
|
+
|
|
110
|
+
/* sidebar rows are plain, not cards */
|
|
111
|
+
#library { gap: 1px; }
|
|
112
|
+
#library li { background: none; border: none; border-radius: 8px; padding: 0; }
|
|
113
|
+
#library li.side-empty { padding: 14px 10px; }
|
|
114
|
+
.side-empty { font-size: 12.5px; color: var(--sm-dim); line-height: 1.5; }
|
|
115
|
+
|
|
116
|
+
/* a folder: a disclosure row; the reveal arrow shows on hover */
|
|
117
|
+
.side-group { position: relative; display: flex; align-items: center; margin-top: 2px; }
|
|
118
|
+
#library li.side-group:first-child { margin-top: 0; }
|
|
119
|
+
button.side-group-name { flex: 1; min-width: 0; height: 30px; gap: 5px; padding: 0 8px 0 5px; border: 0; border-radius: 8px; background: none; color: var(--sm-dim); font: 500 12px var(--sm-font); text-align: left; }
|
|
120
|
+
button.side-group-name:hover { background: rgba(255, 255, 255, .05); color: var(--sm-fg); border-color: transparent; }
|
|
121
|
+
button.side-group-name > svg { width: 12px; height: 12px; flex-shrink: 0; transform: rotate(90deg); transition: transform .14s cubic-bezier(.2, .7, .2, 1), color .12s; }
|
|
122
|
+
.side-group.closed button.side-group-name > svg { transform: none; }
|
|
123
|
+
.side-group-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
124
|
+
.side-group-n { font-size: 10.5px; font-variant-numeric: tabular-nums; opacity: .55; }
|
|
125
|
+
/* on hover the reveal arrow takes the count's place */
|
|
126
|
+
.side-group .side-group-reveal { position: absolute; right: 4px; top: 4px; opacity: 0; transition: opacity .12s, color .12s, background .12s; }
|
|
127
|
+
.side-group:hover .side-group-reveal, .side-group .side-group-reveal:focus-visible, .side-group:has(.side-group-name:focus-visible) .side-group-reveal { opacity: 1; }
|
|
128
|
+
.side-group:hover .side-group-n, .side-group:has(:focus-visible) .side-group-n { opacity: 0; }
|
|
129
|
+
.side-group .side-group-reveal:hover { background: rgba(255, 255, 255, .08); border-color: transparent; }
|
|
130
|
+
.side-group .side-group-reveal svg { width: 13px; height: 13px; }
|
|
131
|
+
|
|
132
|
+
/* a deck: one line — mark · name · (SharePoint) · status · bin on hover; the name's ::after
|
|
133
|
+
stretches the link over the row, so the whole line opens the deck */
|
|
134
|
+
#library li.deck-row { position: relative; display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 6px 0 9px; color: var(--sm-fg); transition: background .12s; }
|
|
135
|
+
#library li.deck-row.nested { padding-left: 24px; }
|
|
136
|
+
.deck-row:hover { background: rgba(255, 255, 255, .05); }
|
|
137
|
+
.deck-row[aria-current="page"] { background: rgba(169, 194, 255, .12); }
|
|
138
|
+
.deck-row[aria-current="page"]::before { content: ""; position: absolute; left: 0; top: 7px; bottom: 7px; width: 2px; border-radius: 2px; background: var(--sm-accent); }
|
|
139
|
+
.deck-row.missing { color: var(--sm-dim); }
|
|
140
|
+
.deck-ico { flex-shrink: 0; width: 18px; height: 11px; border-radius: 2.5px; border: 1.5px solid var(--sm-dim); background: #0a0c11; opacity: .8; transition: border-color .12s, opacity .12s; }
|
|
141
|
+
.deck-row:hover .deck-ico { opacity: 1; }
|
|
142
|
+
.deck-row[aria-current="page"] .deck-ico { border-color: var(--sm-accent); opacity: 1; }
|
|
143
|
+
.deck-ico.sp { border-color: #1a9ba1; } /* the SharePoint logo's teal */
|
|
144
|
+
.deck-row.missing .deck-ico { border-style: dashed; opacity: .5; }
|
|
145
|
+
#library li.deck-row a.deck-name { flex: 1; min-width: 0; color: inherit; font-weight: 500; font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
146
|
+
.deck-row a.deck-name:hover { text-decoration: none; }
|
|
147
|
+
.deck-row a.deck-name::after { content: ""; position: absolute; inset: 0; border-radius: 8px; }
|
|
148
|
+
.deck-row a.deck-name:focus-visible { outline: none; }
|
|
149
|
+
.deck-row:has(a.deck-name:focus-visible) { box-shadow: inset 0 0 0 2px var(--sm-accent); }
|
|
150
|
+
.sp-mark { width: 12px; height: 12px; flex-shrink: 0; opacity: .85; }
|
|
151
|
+
.deck-sub { display: flex; gap: 5px; align-items: center; flex-shrink: 0; }
|
|
152
|
+
.deck-sub:empty { display: none; }
|
|
153
|
+
.deck-state { font-size: 11px; color: var(--sm-dim); font-style: italic; }
|
|
154
|
+
.deck-sub .chip { font-size: 9px; padding: 0 6px; line-height: 1.6; }
|
|
155
|
+
.deck-x { position: relative; z-index: 1; flex-shrink: 0; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px; background: none; color: var(--sm-dim); justify-content: center; opacity: 0; transition: opacity .12s, color .12s, background .12s; }
|
|
156
|
+
.deck-x svg { width: 13px; height: 13px; }
|
|
157
|
+
.deck-row:hover .deck-x, .deck-x:focus-visible { opacity: 1; }
|
|
158
|
+
.deck-row:hover .deck-sub:not(:empty) + .deck-x { margin-left: -2px; }
|
|
159
|
+
.deck-x:hover { background: rgba(248, 113, 113, .14); border-color: transparent; color: var(--sm-danger); }
|
|
160
|
+
/* keyboard focus on the rail: one ring, the same for links and disclosures */
|
|
161
|
+
#side [data-side-item]:focus-visible { outline: 2px solid var(--sm-accent); outline-offset: -2px; }
|
|
162
|
+
button.mini { padding: 2px 9px; font-size: 11px; border-radius: 7px; }
|
|
163
|
+
|
|
164
|
+
main { min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
|
|
165
|
+
.page { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 22px 28px 28px; overflow: auto; animation: sm-rise .18s ease-out; }
|
|
166
|
+
.page > * + * { margin-top: 14px; }
|
|
167
|
+
.path { font-family: var(--sm-mono); font-size: 11px; color: var(--sm-dim); word-break: break-all; }
|
|
168
|
+
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
|
|
169
|
+
|
|
170
|
+
/* ---------- controls ---------- */
|
|
171
|
+
button, .btn { display: inline-flex; align-items: center; gap: 7px; border: 1px solid var(--sm-border); border-radius: 9px; padding: 7px 13px; background: transparent; color: var(--sm-fg); font: 600 12.5px var(--sm-font); cursor: pointer; white-space: nowrap; transition: transform .14s, background .14s, box-shadow .14s, border-color .14s; }
|
|
172
|
+
button:hover, .btn:hover { background: rgba(255, 255, 255, .06); border-color: #3a3a40; text-decoration: none; }
|
|
173
|
+
button.primary { background: #f4f4f5; color: #0f0f0f; border-color: transparent; }
|
|
174
|
+
button.primary:hover { background: #fff; transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0, 0, 0, .45); }
|
|
175
|
+
button.danger { border-color: rgba(248, 113, 113, .4); color: var(--sm-danger); }
|
|
176
|
+
button.danger:hover { background: rgba(248, 113, 113, .12); }
|
|
177
|
+
button:disabled { opacity: .4; cursor: not-allowed; transform: none; box-shadow: none; }
|
|
178
|
+
button svg { width: 14px; height: 14px; flex-shrink: 0; }
|
|
179
|
+
input[type=search], input[type=text], textarea { width: 100%; background: #0c0c0e; color: var(--sm-fg); border: 1px solid var(--sm-border); border-radius: 8px; padding: 8px 10px; font: 13px var(--sm-font); outline: none; transition: border-color .15s; }
|
|
180
|
+
input:focus, textarea:focus { border-color: var(--sm-accent); }
|
|
181
|
+
input::placeholder, textarea::placeholder { color: #6b6b72; }
|
|
182
|
+
input[type=search] { -webkit-appearance: none; appearance: none; }
|
|
183
|
+
|
|
184
|
+
.chip { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 9.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; border: 1px solid var(--sm-border); color: var(--sm-dim); white-space: nowrap; line-height: 1.7; }
|
|
185
|
+
.chip.ok { border-color: rgba(46, 204, 113, .45); color: var(--sm-success); }
|
|
186
|
+
.chip.warn { border-color: rgba(251, 191, 36, .5); color: var(--sm-warn); }
|
|
187
|
+
.chip.bad { border-color: rgba(248, 113, 113, .5); color: var(--sm-danger); }
|
|
188
|
+
.chip.accent { border-color: rgba(169, 194, 255, .45); color: var(--sm-accent); }
|
|
189
|
+
#conn { display: inline-flex; align-items: center; gap: 6px; }
|
|
190
|
+
#conn::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
191
|
+
|
|
192
|
+
/* ---------- tabs ---------- */
|
|
193
|
+
.tabs { display: flex; gap: 2px; padding: 3px; border: 1px solid var(--sm-border); border-radius: 11px; background: var(--sm-surface); align-self: flex-start; }
|
|
194
|
+
.tabs button { border: none; border-radius: 8px; padding: 6px 14px; color: var(--sm-dim); font-weight: 600; }
|
|
195
|
+
.tabs button:hover { background: rgba(255, 255, 255, .05); color: var(--sm-fg); }
|
|
196
|
+
.tabs button[aria-selected=true] { background: rgba(255, 255, 255, .1); color: var(--sm-fg); }
|
|
197
|
+
#tab-body { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 12px; }
|
|
198
|
+
|
|
199
|
+
/* ---------- cards / lists ---------- */
|
|
200
|
+
ul.list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
201
|
+
ul.list li, .card { background: var(--sm-surface); border: 1px solid var(--sm-border); border-radius: 12px; padding: 12px 14px; }
|
|
202
|
+
ul.list li.muted { background: none; border: 1px dashed var(--sm-border); text-align: center; padding: 22px; }
|
|
203
|
+
ul.list li a { color: var(--sm-fg); font-weight: 600; }
|
|
204
|
+
.card.mine { border-color: var(--sm-accent); box-shadow: 0 0 0 1px rgba(169, 194, 255, .25); }
|
|
205
|
+
.card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
206
|
+
.card-head .kind { font-weight: 600; font-size: 13px; }
|
|
207
|
+
.card-head .path { margin-left: auto; }
|
|
208
|
+
.card .actions { margin-top: 10px; }
|
|
209
|
+
.task-result { margin-top: 8px; }
|
|
210
|
+
.task-result .error { margin: 0; }
|
|
211
|
+
.done { margin-top: 10px; border-top: 1px solid var(--sm-border); padding-top: 10px; }
|
|
212
|
+
.done p { margin: 0 0 6px; font-weight: 600; }
|
|
213
|
+
.stat { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
|
|
214
|
+
.stat .card { padding: 12px 14px; }
|
|
215
|
+
.stat .k { font-size: 11px; color: var(--sm-dim); letter-spacing: .06em; text-transform: uppercase; font-weight: 600; }
|
|
216
|
+
.stat .v { font-size: 18px; font-weight: 600; margin-top: 4px; }
|
|
217
|
+
.stat .v .chip { vertical-align: middle; margin-left: 6px; }
|
|
218
|
+
|
|
219
|
+
iframe.view { flex: 1; min-height: 260px; width: 100%; border: 1px solid var(--sm-border); background: #fff; border-radius: 12px; }
|
|
220
|
+
textarea.plan { flex: 1; min-height: 320px; resize: none; font: 13px/1.5 var(--sm-mono); padding: 14px; border-radius: 12px; border: 0; }
|
|
221
|
+
textarea.plan:focus { border: 0; }
|
|
222
|
+
.banner { background: rgba(251, 191, 36, .1); border: 1px solid rgba(251, 191, 36, .4); color: #fde68a; padding: 9px 12px; border-radius: 9px; font-size: 12.5px; }
|
|
223
|
+
.banner.conflict { background: rgba(248, 113, 113, .08); border-color: rgba(248, 113, 113, .4); color: var(--sm-fg); padding: 14px; }
|
|
224
|
+
.banner.conflict strong { display: block; margin-bottom: 4px; }
|
|
225
|
+
.banner.conflict pre { max-height: 16em; overflow: auto; }
|
|
226
|
+
.banner.conflict details { margin-top: 10px; }
|
|
227
|
+
.banner.conflict summary { cursor: pointer; color: var(--sm-dim); font-size: 12px; }
|
|
228
|
+
pre.copy { background: #0c0c0e; border: 1px solid var(--sm-border); color: #e4e4e7; padding: 10px 12px; border-radius: 9px; overflow: auto; font: 12px/1.5 var(--sm-mono); margin: 0; user-select: all; }
|
|
229
|
+
p { margin: 0; }
|
|
230
|
+
p + p { margin-top: 6px; }
|
|
231
|
+
.spin { width: 11px; height: 11px; border-radius: 50%; border: 2px solid var(--sm-accent); border-top-color: transparent; animation: sm-spin .9s linear infinite; display: inline-block; vertical-align: middle; }
|
|
232
|
+
|
|
233
|
+
/* ---------- small screens: the deck list becomes a drawer, the deck page
|
|
234
|
+
keeps every pixel for the plan / preview frame ---------- */
|
|
235
|
+
#side-toggle { display: none; }
|
|
236
|
+
@media (max-width: 1000px) {
|
|
237
|
+
.shell { grid-template-columns: 1fr; }
|
|
238
|
+
#side { position: fixed; top: var(--sm-top); bottom: 0; left: 0; z-index: 25; width: min(320px, 88vw); max-width: none; transform: translateX(-100%); transition: transform .2s cubic-bezier(.2, .7, .2, 1); box-shadow: 0 18px 54px rgba(0, 0, 0, .5); }
|
|
239
|
+
body.side-open #side { transform: none; }
|
|
240
|
+
#side-grip { display: none; }
|
|
241
|
+
#side-toggle { display: inline-flex; }
|
|
242
|
+
.page { padding: 12px 14px 14px; }
|
|
243
|
+
.page > * + * { margin-top: 10px; }
|
|
244
|
+
.top { gap: 10px; padding: 0 12px; }
|
|
245
|
+
.top .meta .h { display: none; }
|
|
246
|
+
iframe.view { border-radius: 9px; }
|
|
247
|
+
}
|
|
248
|
+
@media (prefers-reduced-motion: reduce) {
|
|
249
|
+
.word .t, .word .b { animation: none; }
|
|
250
|
+
button.side-group-name > svg, #side, .page, dialog.dlg, .toast, .conn-banner { transition: none; animation: none; }
|
|
251
|
+
}
|
|
252
|
+
@media (max-width: 600px) {
|
|
253
|
+
.top .sep, .top .word { display: none; }
|
|
254
|
+
.top-actions { flex-shrink: 1; min-width: 0; overflow: hidden; }
|
|
255
|
+
/* a phone keeps the deck's name: a button with an icon is its icon, the connection its dot */
|
|
256
|
+
.top-actions .lbl { display: none; }
|
|
257
|
+
.top #conn { font-size: 0; gap: 0; padding: 5px; }
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* ---------- dialog + toast ---------- */
|
|
261
|
+
dialog.dlg { background: var(--sm-surface); color: var(--sm-fg); border: 1px solid var(--sm-border); border-radius: 14px; padding: 18px; width: min(480px, calc(100vw - 32px)); box-shadow: 0 20px 54px rgba(0, 0, 0, .6); animation: sm-rise .16s ease-out; }
|
|
262
|
+
dialog.dlg::backdrop { background: rgba(5, 5, 7, .6); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
|
|
263
|
+
dialog.dlg form { display: flex; flex-direction: column; gap: 10px; }
|
|
264
|
+
dialog.dlg h3 { font-size: 14px; }
|
|
265
|
+
dialog.dlg p.muted { font-size: 12.5px; }
|
|
266
|
+
dialog.dlg textarea { min-height: 96px; resize: vertical; font: 13px/1.5 var(--sm-font); }
|
|
267
|
+
dialog.dlg .error { margin: 0; }
|
|
268
|
+
dialog.dlg .path { word-break: break-word; overflow-wrap: anywhere; }
|
|
269
|
+
.row.end { justify-content: flex-end; }
|
|
270
|
+
.toast { position: fixed; right: 18px; bottom: 18px; z-index: 30; max-width: 380px; padding: 10px 14px; background: var(--sm-surface); border: 1px solid var(--sm-border); border-radius: 10px; font-size: 12.5px; box-shadow: 0 12px 36px rgba(0, 0, 0, .5); animation: sm-rise .2s ease-out; }
|
|
271
|
+
.toast.bad { border-color: rgba(248, 113, 113, .5); color: var(--sm-danger); }
|
|
272
|
+
.toast:has(button) { display: flex; align-items: center; gap: 10px; padding: 10px 10px 10px 14px; }
|
|
273
|
+
/* an ask about another deck: top right, clear of the gate's composer at the bottom */
|
|
274
|
+
.toast.attn { top: calc(var(--sm-top) + 12px); bottom: auto; border-color: rgba(169, 194, 255, .55); box-shadow: 0 12px 36px rgba(0, 0, 0, .5), 0 0 0 1px rgba(169, 194, 255, .2); }
|
|
275
|
+
.toast .toast-x { padding: 4px; }
|
|
276
|
+
|
|
277
|
+
/* ---------- tooltip: every [data-tip] (app.js showTip); a popover in the top layer, so the UA's popover box is reset ---------- */
|
|
278
|
+
.tip { position: fixed; inset: auto; margin: 0; z-index: 40; width: max-content; max-width: min(360px, calc(100vw - 16px)); height: auto; overflow: visible; padding: 6px 9px; background: var(--sm-surface-2); color: var(--sm-fg); border: 1px solid var(--sm-border); border-radius: 8px; box-shadow: 0 10px 30px rgba(0, 0, 0, .55); font: 400 12px/1.45 var(--sm-font); white-space: pre-line; overflow-wrap: anywhere; pointer-events: none; visibility: hidden; }
|
|
279
|
+
.tip.on { visibility: visible; animation: sm-tip .12s ease-out; }
|
|
280
|
+
@keyframes sm-tip { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
|
|
281
|
+
@media (prefers-reduced-motion: reduce) { .tip.on { animation: none; } }
|
|
282
|
+
|
|
283
|
+
/* ---------- connection: one sentence under the top bar while the workspace is away ---------- */
|
|
284
|
+
.conn-banner { position: fixed; top: calc(var(--sm-top) + 10px); left: 50%; transform: translateX(-50%); z-index: 26; max-width: min(640px, calc(100vw - 32px)); padding: 9px 16px; border-radius: 999px; font-size: 12.5px; font-weight: 500; text-align: center; background: var(--sm-surface); border: 1px solid var(--sm-border); box-shadow: 0 12px 36px rgba(0, 0, 0, .5); animation: sm-rise .2s ease-out; }
|
|
285
|
+
.conn-banner.warn { border-color: rgba(251, 191, 36, .5); color: #fde68a; }
|
|
286
|
+
.conn-banner.bad { border-color: rgba(248, 113, 113, .5); color: #fecaca; }
|
|
287
|
+
|
|
288
|
+
/* ---------- the hand-off: the one thing the user has to do ---------- */
|
|
289
|
+
.done.handoff p { font-weight: 400; }
|
|
290
|
+
.done.handoff p.ok strong { font-weight: 600; }
|
|
291
|
+
/* the hand-over: the message the user pastes into their chat with the agent */
|
|
292
|
+
dialog.dlg textarea.handoff-msg { display: block; min-height: 0; resize: none; width: 100%; padding: 10px 44px 10px 12px; border: 1px solid var(--sm-border); border-radius: 9px; background: rgba(255, 255, 255, .04); color: var(--sm-fg); font: 12.5px/1.5 var(--sm-font); }
|
|
293
|
+
/* the copy icon sits in the message's corner, as in every chat and code block; nothing copies until it is clicked */
|
|
294
|
+
.msgbox { position: relative; }
|
|
295
|
+
.msgbox button.copy-icon { position: absolute; top: 7px; right: 7px; width: 28px; height: 28px; }
|
|
296
|
+
button.copy-icon svg { width: 15px; height: 15px; }
|
|
297
|
+
button.copy-icon:hover { background: rgba(255, 255, 255, .08); }
|
|
298
|
+
button.copy-icon.is-copied { color: var(--sm-success); }
|
|
299
|
+
|
|
300
|
+
/* ---------- view chrome: the framed view's messages, shown by this page ----------
|
|
301
|
+
Its status line beside the save state, its notices in a stack above the
|
|
302
|
+
frame, its one dialog as this page's own. The view keeps its navigation. */
|
|
303
|
+
#view-meta:empty { display: none; }
|
|
304
|
+
#view-meta { position: relative; gap: 8px; }
|
|
305
|
+
/* the two state chips never reflow the row: one line, clipped, the full text on hover */
|
|
306
|
+
#tab-meta .chip { white-space: nowrap; }
|
|
307
|
+
.chip.view-status { display: inline-flex; align-items: center; gap: 6px; max-width: min(380px, 40vw); text-transform: none; letter-spacing: 0; font-size: 11px; padding: 2px 9px; font-family: var(--sm-font); font-weight: 600; cursor: default; }
|
|
308
|
+
.chip.view-status::before { content: ""; flex-shrink: 0; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .9; }
|
|
309
|
+
.chip.view-status .view-status-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
310
|
+
.chip.view-status .spin { width: 9px; height: 9px; }
|
|
311
|
+
.chip.view-status:has(.spin)::before { display: none; }
|
|
312
|
+
/* the save state is the normal case: quiet words beside the badge, a pill only when it needs a look */
|
|
313
|
+
.chip.save { text-transform: none; letter-spacing: 0; font: 500 11px/1.7 var(--sm-font); border-color: transparent; padding: 2px 4px; color: var(--sm-dim); }
|
|
314
|
+
.chip.save.ok::before { content: "✓"; margin-right: 5px; color: var(--sm-success); }
|
|
315
|
+
.chip.save.warn { color: var(--sm-warn); border-color: rgba(251, 191, 36, .5); padding: 2px 9px; }
|
|
316
|
+
.chip.save.bad { color: var(--sm-danger); border-color: rgba(248, 113, 113, .5); padding: 2px 9px; }
|
|
317
|
+
button.chip.view-status.listed { cursor: pointer; background: transparent; transition: background .12s; }
|
|
318
|
+
button.chip.view-status.listed:hover, button.chip.view-status[aria-expanded="true"] { background: rgba(255, 255, 255, .06); }
|
|
319
|
+
.view-pop { position: absolute; top: calc(100% + 8px); right: 0; z-index: 15; width: min(440px, calc(100vw - 32px)); padding: 12px 14px; background: var(--sm-surface); border: 1px solid var(--sm-border); border-radius: 12px; box-shadow: 0 16px 44px rgba(0, 0, 0, .55); animation: sm-rise .14s ease-out; font-size: 12.5px; }
|
|
320
|
+
.view-pop-head { margin: 0 0 8px; font-weight: 600; }
|
|
321
|
+
.view-pop-list { list-style: none; margin: 0; padding: 0; max-height: 40vh; overflow: auto; display: flex; flex-direction: column; gap: 6px; }
|
|
322
|
+
.view-pop-list li { display: flex; gap: 10px; align-items: baseline; line-height: 1.4; }
|
|
323
|
+
.view-pop-list li b { flex-shrink: 0; min-width: 52px; font: 600 10.5px/1.6 var(--sm-mono); color: var(--sm-accent); }
|
|
324
|
+
.view-pop-list li[data-kind="add"] b { color: var(--sm-success); }
|
|
325
|
+
.view-pop-list li[data-kind="remove"] b { color: var(--sm-danger); }
|
|
326
|
+
.view-pop-list li[data-kind="deck"] b { color: var(--sm-dim); }
|
|
327
|
+
.view-pop-list li span { min-width: 0; overflow-wrap: anywhere; }
|
|
328
|
+
.view-notices { display: flex; flex-direction: column; gap: 6px; }
|
|
329
|
+
.view-notice { display: flex; align-items: center; gap: 12px; padding: 9px 12px; border-radius: 10px; font-size: 12.5px; border: 1px solid var(--sm-border); background: var(--sm-surface); }
|
|
330
|
+
.view-notice.info { border-color: rgba(169, 194, 255, .35); background: rgba(169, 194, 255, .07); }
|
|
331
|
+
.view-notice.ok { border-color: rgba(46, 204, 113, .35); background: rgba(46, 204, 113, .07); }
|
|
332
|
+
.view-notice.warn { border-color: rgba(251, 191, 36, .45); background: rgba(251, 191, 36, .08); }
|
|
333
|
+
.view-notice.error { border-color: rgba(248, 113, 113, .45); background: rgba(248, 113, 113, .08); }
|
|
334
|
+
.view-notice .txt { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; column-gap: 8px; line-height: 1.45; }
|
|
335
|
+
.view-notice .txt b { font-weight: 600; }
|
|
336
|
+
.view-notice .txt span { color: var(--sm-dim); }
|
|
337
|
+
.view-notice.warn .txt span, .view-notice.error .txt span { color: var(--sm-fg); }
|
|
338
|
+
.view-notice .acts { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
|
|
339
|
+
.view-notice .notice-x { width: 24px; height: 24px; font-size: 15px; }
|
|
340
|
+
kbd.say { display: inline-block; padding: 0 7px; border-radius: 6px; border: 1px solid rgba(169, 194, 255, .5); background: rgba(169, 194, 255, .12); color: var(--sm-accent); font: 600 12px/1.6 var(--sm-font); }
|
|
341
|
+
dialog.view-dialog { width: min(560px, calc(100vw - 32px)); display: flex; flex-direction: column; gap: 10px; }
|
|
342
|
+
dialog.view-dialog h3 { font-size: 15px; }
|
|
343
|
+
dialog.view-dialog p.big { font-size: 14px; line-height: 1.5; color: #ececf0; }
|
|
344
|
+
dialog.view-dialog .row.end { margin-top: 6px; }
|
|
345
|
+
|
|
346
|
+
/* ---------- plan tab ---------- */
|
|
347
|
+
.plan-editor { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
348
|
+
|
|
349
|
+
/* ---------- deck page: the frame is the page, everything above it is trim ----
|
|
350
|
+
The header, the tabs and the "your turn" cards are fixed rows; the tab body
|
|
351
|
+
takes what is left. Without this the frame is the only flexible thing in a
|
|
352
|
+
scrolling column, so on a short window it collapses to its floor and the page
|
|
353
|
+
scrolls instead — the plan ends up a strip. */
|
|
354
|
+
.page.deck > * { flex: 0 0 auto; }
|
|
355
|
+
.page.deck > #tab-body { flex: 1 1 auto; min-height: 0; gap: 10px; }
|
|
356
|
+
.page.deck > * + * { margin-top: 10px; }
|
|
357
|
+
/* the tab's tools sit by the tabs; its state chips alone at the right end */
|
|
358
|
+
.tab-row { align-items: center; gap: 12px; flex-wrap: nowrap; }
|
|
359
|
+
.tab-row #tab-tools { gap: 10px; }
|
|
360
|
+
.tab-row #tab-tools:empty { display: none; }
|
|
361
|
+
.tab-row #tab-meta { margin-left: auto; gap: 10px; flex-wrap: nowrap; min-width: 0; }
|
|
362
|
+
/* N pending tasks must never starve the frame */
|
|
363
|
+
.your-turn { max-height: 28vh; overflow-y: auto; gap: 6px; }
|
|
364
|
+
@media (max-height: 900px) {
|
|
365
|
+
.page.deck { padding-top: 14px; padding-bottom: 14px; }
|
|
366
|
+
.page.deck > * + * { margin-top: 8px; }
|
|
367
|
+
.page.deck .task.turn { padding: 5px 10px; }
|
|
368
|
+
.page.deck .task.turn button { padding: 4px 11px; }
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* empty state: the header mark, blown up, over the page's own dark */
|
|
372
|
+
.empty { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; text-align: center; }
|
|
373
|
+
.empty .brand { flex-direction: column; gap: 14px; margin-bottom: 8px; }
|
|
374
|
+
.empty .logo { width: 132px; height: 74px; border-radius: 10px; }
|
|
375
|
+
.empty .word { font-size: 24px; }
|
|
376
|
+
.empty p { font-size: 13.5px; }
|
|
377
|
+
|
|
378
|
+
/* ---------- SharePoint mark ---------- */
|
|
379
|
+
.chip.sp { display: inline-flex; align-items: center; gap: 5px; border-color: rgba(26, 155, 161, .6); color: #37c6d0; text-decoration: none; }
|
|
380
|
+
.chip.sp img { width: 12px; height: 12px; display: block; }
|
|
381
|
+
a.chip.sp:hover { background: rgba(26, 155, 161, .15); text-decoration: none; }
|
|
382
|
+
|
|
383
|
+
button.mini .sp-ico { width: 12px; height: 12px; }
|
|
384
|
+
|
|
385
|
+
/* ---------- icon switch (page ⟷ markdown) ---------- */
|
|
386
|
+
.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
|
|
387
|
+
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
|
|
388
|
+
.sw-track { position: relative; width: 36px; height: 20px; border-radius: 999px; background: var(--sm-surface-2); border: 1px solid var(--sm-border); transition: background .15s, border-color .15s; }
|
|
389
|
+
.sw-track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #f4f4f5; box-shadow: 0 1px 3px rgba(0, 0, 0, .5); transition: transform .18s cubic-bezier(.2, .7, .2, 1); }
|
|
390
|
+
.switch input:checked ~ .sw-track { background: rgba(169, 194, 255, .25); border-color: rgba(169, 194, 255, .6); }
|
|
391
|
+
.switch input:checked ~ .sw-track::after { transform: translateX(16px); }
|
|
392
|
+
.switch input:focus-visible ~ .sw-track { outline: 2px solid var(--sm-accent); outline-offset: 2px; }
|
|
393
|
+
.sw-ico { display: inline-flex; color: var(--sm-dim); transition: color .15s; }
|
|
394
|
+
.sw-ico.on { color: var(--sm-fg); }
|
|
395
|
+
.sw-ico svg { width: 16px; height: 16px; }
|
|
396
|
+
|
|
397
|
+
/* ---------- sidebar filter ---------- */
|
|
398
|
+
.seg { display: inline-flex; gap: 2px; padding: 3px; border: 1px solid var(--sm-border); border-radius: 10px; background: var(--sm-surface-2); }
|
|
399
|
+
.seg button { border: none; border-radius: 7px; padding: 4px 11px; font-size: 11.5px; color: var(--sm-dim); }
|
|
400
|
+
.seg button:hover { background: rgba(255, 255, 255, .05); color: var(--sm-fg); }
|
|
401
|
+
.seg button[aria-pressed="true"] { background: rgba(255, 255, 255, .1); color: var(--sm-fg); }
|
|
402
|
+
|
|
403
|
+
/* ---------- your turn ---------- */
|
|
404
|
+
.your-turn { display: flex; flex-direction: column; gap: 8px; }
|
|
405
|
+
.task.turn { background: rgba(169, 194, 255, .08); border: 1px solid rgba(169, 194, 255, .35); border-radius: 12px; padding: 9px 12px; display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; }
|
|
406
|
+
.task.turn.mine { box-shadow: 0 0 0 1px rgba(169, 194, 255, .35); }
|
|
407
|
+
.task.turn .card-head { flex: 0 0 auto; }
|
|
408
|
+
.task.turn p { margin-top: 0; flex: 1 1 200px; min-width: 0; }
|
|
409
|
+
.task.turn .actions { margin-top: 0; margin-left: auto; }
|
|
410
|
+
.task.turn .task-result, .task.turn .done { flex: 1 1 100%; }
|
|
411
|
+
.task.turn .task-result:empty { display: none; }
|
|
412
|
+
.task.turn .dismiss { width: 26px; height: 26px; margin-left: 2px; border-color: transparent; color: var(--sm-dim); font-size: 15px; line-height: 1; opacity: 0; transition: opacity .12s, color .12s, background .12s; }
|
|
413
|
+
.task.turn:hover .dismiss, .task.turn .dismiss:focus-visible { opacity: 1; }
|
|
414
|
+
.task.turn .dismiss:hover { background: rgba(255, 255, 255, .08); color: var(--sm-fg); border-color: transparent; }
|
|
415
|
+
/* answered: the card is a receipt, so it reads as one settled line */
|
|
416
|
+
.task.turn.answered { background: rgba(46, 204, 113, .06); border-color: rgba(46, 204, 113, .3); }
|
|
417
|
+
.task.turn.answered .task-result { flex: 1 1 auto; min-width: 0; }
|
|
418
|
+
.task.turn .done { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin: 0; padding: 0; border-top: 0; }
|
|
419
|
+
.task.turn .done p { margin: 0; font-weight: 500; }
|
|
420
|
+
.task.turn .done button.mini { margin-left: auto; }
|
|
421
|
+
.task.turn .done pre.copy { flex: 1 1 100%; min-width: 0; }
|
|
422
|
+
.done .copy { margin: 8px 0; }
|
|
423
|
+
.tabs .tab-ok { margin-left: 6px; color: var(--sm-success); font-size: 11px; }
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { splitPlanMarkdownIntoSegments } from "./storyboard-markdown.mjs";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Split a per-slide concept batch into the dependency waves expected by the
|
|
5
|
-
* add-in: independent slides and family anchors first, family variants second.
|
|
6
|
-
*/
|
|
7
|
-
// The slide numbers the plan's storyboards actually carry, ascending. This is
|
|
8
|
-
// the set concept generation must cover — the server's slideCount is only the
|
|
9
|
-
// number of beats IT parsed, and one beat it drops (an older schema rejecting
|
|
10
|
-
// a cover's empty block list) would otherwise also drop the LAST slide from a
|
|
11
|
-
// 2..slideCount request range.
|
|
12
|
-
export function plannedSlideNumbers(planMarkdown) {
|
|
13
|
-
const slides = new Set();
|
|
14
|
-
for (const segment of splitPlanMarkdownIntoSegments(planMarkdown)) {
|
|
15
|
-
if (segment.type !== "storyboard" || !segment.data) continue;
|
|
16
|
-
if (Number.isFinite(segment.data.slide)) slides.add(segment.data.slide);
|
|
17
|
-
}
|
|
18
|
-
return [...slides].sort((a, b) => a - b);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function conceptGenerationWaves(planMarkdown) {
|
|
22
|
-
const groups = new Map();
|
|
23
|
-
for (const segment of splitPlanMarkdownIntoSegments(planMarkdown)) {
|
|
24
|
-
if (segment.type !== "storyboard" || !segment.data) continue;
|
|
25
|
-
const family = segment.data.visualFamily?.trim();
|
|
26
|
-
const slide = segment.data.slide;
|
|
27
|
-
if (!family || !Number.isFinite(slide)) continue;
|
|
28
|
-
groups.set(family, [...(groups.get(family) ?? []), slide]);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const variants = new Set();
|
|
32
|
-
for (const unsorted of groups.values()) {
|
|
33
|
-
const members = [...new Set(unsorted)].sort((a, b) => a - b);
|
|
34
|
-
if (members.length < 2) continue;
|
|
35
|
-
for (const slide of members.slice(1)) variants.add(slide);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Every slide the plan names, slide 1 included. The server derives its own
|
|
39
|
-
// beat list from the SAME storyboard-canvas blocks, so there is nothing a
|
|
40
|
-
// request to it could tell us about the deck's size that this does not.
|
|
41
|
-
const planned = plannedSlideNumbers(planMarkdown);
|
|
42
|
-
return {
|
|
43
|
-
firstWave: planned.filter((slide) => !variants.has(slide)),
|
|
44
|
-
variants: planned.filter((slide) => variants.has(slide)),
|
|
45
|
-
};
|
|
46
|
-
}
|