konpeki 0.3.1 → 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.
Files changed (167) hide show
  1. package/AGENTS.md +21 -28
  2. package/AUTHORING.md +68 -229
  3. package/CONTRIBUTING.md +10 -23
  4. package/README.md +98 -106
  5. package/SETUP.md +49 -129
  6. package/docs/development.md +43 -256
  7. package/docs/workflow.md +6 -108
  8. package/html/README.md +140 -0
  9. package/html/browser.ts +103 -0
  10. package/html/document.ts +38 -0
  11. package/html/floor.ts +34 -0
  12. package/html/index.html +5 -0
  13. package/html/inspect.ts +313 -0
  14. package/html/preview.css +62 -0
  15. package/html/preview.tsx +463 -0
  16. package/html/review-hints.ts +63 -0
  17. package/html/server.ts +99 -0
  18. package/html/source.ts +104 -0
  19. package/html/starter.ts +6 -0
  20. package/html/theme-authoring.md +176 -0
  21. package/html/theme.md +61 -0
  22. package/index.html +9 -9
  23. package/package.json +21 -37
  24. package/plugin.json +1 -1
  25. package/public/og.png +0 -0
  26. package/runtime/browser-B-29TH1a.mjs +595 -0
  27. package/runtime/floor-Cmk7G3pU.mjs +41 -0
  28. package/runtime/konpeki.mjs +90 -1410
  29. package/runtime/server-BAqC_5WD.mjs +2 -0
  30. package/runtime/server-DfRpfcY9.mjs +205 -0
  31. package/runtime/source-B_Ui9tMp.mjs +141 -0
  32. package/runtime/source-CZQq9GUO.mjs +2 -0
  33. package/skills/konpeki/SKILL.md +88 -172
  34. package/skills/konpeki/assets/blank.html +17 -0
  35. package/skills/konpeki/floor.md +76 -0
  36. package/skills/konpeki/references/cover.md +27 -0
  37. package/skills/konpeki/references/long-document.md +40 -0
  38. package/skills/konpeki/references/one-pager.md +27 -0
  39. package/skills/konpeki/references/patterns.md +118 -0
  40. package/skills/konpeki/references/resume.md +28 -0
  41. package/skills/konpeki/references/slides.md +28 -0
  42. package/skills/konpeki/scripts/ensure-runtime.mjs +10 -31
  43. package/skills/konpeki/scripts/prepare-document.mjs +25 -14
  44. package/src/components/PageBoard.tsx +156 -0
  45. package/src/lib/alignment.ts +21 -0
  46. package/src/lib/page-board.ts +25 -0
  47. package/src/lib/review-position.ts +19 -0
  48. package/src/styles/base.css +1 -10
  49. package/src/styles/feedback.css +2 -1
  50. package/src/styles/shell.css +94 -354
  51. package/theme-base.css +90 -0
  52. package/theme.css +56 -0
  53. package/vite.config.ts +2 -5
  54. package/composition/README.md +0 -156
  55. package/composition/compile.ts +0 -227
  56. package/composition/document.ts +0 -600
  57. package/composition/schema.json +0 -3001
  58. package/composition/schema.ts +0 -437
  59. package/composition/theme-tokens.ts +0 -16
  60. package/composition/types.ts +0 -269
  61. package/composition/validate.ts +0 -226
  62. package/composition/vector.ts +0 -143
  63. package/composition/visualizations.ts +0 -319
  64. package/design/README.md +0 -17
  65. package/design/palettes/README.md +0 -14
  66. package/design/palettes/base.ts +0 -14
  67. package/design/palettes/candidates.ts +0 -19
  68. package/design/palettes/index.ts +0 -78
  69. package/design/review/color-theme.md +0 -44
  70. package/design/review/layout.md +0 -16
  71. package/design/review/text.md +0 -18
  72. package/design/review/typography.md +0 -15
  73. package/design/review/visuals.md +0 -31
  74. package/design/semantic-patterns.md +0 -43
  75. package/design/themes/README.md +0 -40
  76. package/design/themes/index.ts +0 -24
  77. package/design/visual-languages/technical-product.md +0 -17
  78. package/design/visual-review.md +0 -88
  79. package/lib/assets.d.ts +0 -8
  80. package/lib/charts.ts +0 -18
  81. package/lib/contrast.ts +0 -16
  82. package/lib/layouts.ts +0 -50
  83. package/lib/slide.tsx +0 -42
  84. package/lib/taste.ts +0 -17
  85. package/lib/text.tsx +0 -89
  86. package/lib/typeface.ts +0 -44
  87. package/scripts/migrate-react-page.ts +0 -120
  88. package/skills/konpeki/assets/blank.json +0 -23
  89. package/slides/README.md +0 -56
  90. package/slides/architecture/PROMPT.md +0 -31
  91. package/slides/architecture/index.tsx +0 -102
  92. package/slides/article-brief/PROMPT.md +0 -35
  93. package/slides/article-brief/index.tsx +0 -71
  94. package/slides/bar-chart/PROMPT.md +0 -39
  95. package/slides/bar-chart/index.tsx +0 -97
  96. package/slides/comparison/PROMPT.md +0 -29
  97. package/slides/comparison/index.tsx +0 -95
  98. package/slides/decision-memo/PROMPT.md +0 -34
  99. package/slides/decision-memo/index.tsx +0 -85
  100. package/slides/delivery-plan/PROMPT.md +0 -45
  101. package/slides/delivery-plan/index.tsx +0 -105
  102. package/slides/drawing-references.md +0 -32
  103. package/slides/experiment/PROMPT.md +0 -44
  104. package/slides/experiment/index.tsx +0 -127
  105. package/slides/github-cover/PROMPT.md +0 -21
  106. package/slides/github-cover/README.md +0 -21
  107. package/slides/github-cover/author.ts +0 -67
  108. package/slides/github-cover/composition.json +0 -595
  109. package/slides/incident-workflow/PROMPT.md +0 -57
  110. package/slides/incident-workflow/index.tsx +0 -78
  111. package/slides/introducing-konpeki/PROMPT.md +0 -30
  112. package/slides/introducing-konpeki/README.md +0 -44
  113. package/slides/introducing-konpeki/SOURCE.md +0 -19
  114. package/slides/introducing-konpeki/author.ts +0 -165
  115. package/slides/introducing-konpeki/composition.json +0 -3270
  116. package/slides/line-chart/PROMPT.md +0 -40
  117. package/slides/line-chart/index.tsx +0 -72
  118. package/slides/migration/PROMPT.md +0 -38
  119. package/slides/migration/index.tsx +0 -89
  120. package/slides/og-images/PROMPT.md +0 -21
  121. package/slides/og-images/index.tsx +0 -76
  122. package/slides/product-introduction/PROMPT.md +0 -24
  123. package/slides/product-introduction/index.tsx +0 -105
  124. package/slides/research-brief/PROMPT.md +0 -40
  125. package/slides/research-brief/index.tsx +0 -104
  126. package/slides/results-explanation/PROMPT.md +0 -32
  127. package/slides/results-explanation/index.tsx +0 -96
  128. package/slides/retrospective/PROMPT.md +0 -43
  129. package/slides/retrospective/index.tsx +0 -105
  130. package/slides/sankey/PROMPT.md +0 -11
  131. package/slides/sankey/index.tsx +0 -93
  132. package/slides/teaching/PROMPT.md +0 -45
  133. package/slides/teaching/index.tsx +0 -124
  134. package/slides/vertical-bar-charts/PROMPT.md +0 -13
  135. package/slides/vertical-bar-charts/index.tsx +0 -97
  136. package/src/app/App.tsx +0 -845
  137. package/src/components/BuildOrb.tsx +0 -40
  138. package/src/components/Canvas.tsx +0 -1191
  139. package/src/components/DiagramTypeIcon.tsx +0 -78
  140. package/src/components/InspectorPanel.tsx +0 -757
  141. package/src/components/LeftPanel.tsx +0 -120
  142. package/src/components/PageSizePicker.tsx +0 -30
  143. package/src/components/Presentation.tsx +0 -105
  144. package/src/components/RevisionNotes.tsx +0 -55
  145. package/src/components/RightPanel.tsx +0 -233
  146. package/src/components/VectorOverflowWarning.tsx +0 -73
  147. package/src/components/WorkspaceChrome.tsx +0 -316
  148. package/src/components/ui.tsx +0 -147
  149. package/src/lib/examples/react-page-migration.json +0 -1295
  150. package/src/lib/examples.ts +0 -42
  151. package/src/lib/export-png.ts +0 -104
  152. package/src/lib/file-session.ts +0 -87
  153. package/src/lib/history.ts +0 -53
  154. package/src/lib/model.ts +0 -188
  155. package/src/lib/page-size.ts +0 -24
  156. package/src/lib/presentation.ts +0 -17
  157. package/src/lib/review.ts +0 -26
  158. package/src/lib/storage.ts +0 -71
  159. package/src/lib/theme.ts +0 -25
  160. package/src/lib/use-file-session.ts +0 -249
  161. package/src/main.tsx +0 -29
  162. package/src/styles/canvas.css +0 -299
  163. package/src/styles/chrome.css +0 -475
  164. package/src/styles/component-previews.css +0 -386
  165. package/src/styles/left-panel.css +0 -187
  166. package/src/styles/presentation.css +0 -72
  167. package/src/styles/right-panel.css +0 -1298
@@ -1,249 +0,0 @@
1
- import { useEffect, useRef, useState } from "react";
2
- import { canonicalJSON } from "../../composition/compile.ts";
3
- import { validateComposition } from "../../composition/validate.ts";
4
- import type { Draft } from "./model.ts";
5
- import { activeRequest, emptyReview, type ReviewState, type ReviewTarget } from "./review.ts";
6
- import {
7
- addNote,
8
- removeNote,
9
- cancelRequest,
10
- FileSessionError,
11
- fileSessionToken,
12
- loadFileSession,
13
- saveFileSession,
14
- sendBuildRequest,
15
- } from "./file-session.ts";
16
-
17
- export type FileStatus = "loading" | "saved" | "saving" | "conflict" | "error";
18
-
19
- type Callbacks = {
20
- onOpen: (draft: Draft, name: string) => void;
21
- onExternalChange: (draft: Draft) => void;
22
- onNotice: (message: string, tone?: "neutral" | "error") => void;
23
- onError: (message: string) => void;
24
- };
25
-
26
- export function useFileSession(
27
- enabled: boolean,
28
- draft: Draft,
29
- callbacks: Callbacks,
30
- ) {
31
- const token = fileSessionToken();
32
- const [status, setStatus] = useState<FileStatus>(enabled ? "loading" : "saved");
33
- const [building, setBuilding] = useState(false);
34
- const [review, setReview] = useState<ReviewState>(emptyReview);
35
- const reviewRef = useRef(review);
36
- const buildPending = useRef(false);
37
- const submittingBuild = useRef(false);
38
- const loading = useRef(false);
39
- const loadGeneration = useRef(0);
40
- const callbacksRef = useRef(callbacks);
41
- callbacksRef.current = callbacks;
42
- const draftRef = useRef(draft);
43
- draftRef.current = draft;
44
- const state = useRef<{
45
- ready: boolean;
46
- revision: string;
47
- savedJSON: string;
48
- pending?: { draft: Draft; serialized: string };
49
- drain?: Promise<void>;
50
- }>({ ready: false, revision: "", savedJSON: "" });
51
-
52
- useEffect(() => {
53
- if (!enabled || !token) return;
54
- void reload();
55
- return () => {
56
- loadGeneration.current++;
57
- loading.current = false;
58
- };
59
- }, [enabled, token]);
60
-
61
- useEffect(() => {
62
- if (!enabled || !state.current.ready || ["loading", "conflict", "error"].includes(status))
63
- return;
64
- if (!validateComposition(draft).ok) return;
65
- const timer = window.setTimeout(() => { void save(draft); }, 250);
66
- return () => window.clearTimeout(timer);
67
- }, [draft, enabled, status]);
68
-
69
- useEffect(() => {
70
- if (!enabled || !token) return;
71
- let cancelled = false;
72
- const timer = window.setInterval(() => {
73
- if (!state.current.ready || loading.current || state.current.drain || submittingBuild.current) return;
74
- const revision = state.current.revision;
75
- const generation = loadGeneration.current;
76
- void loadFileSession(token).then((remote) => {
77
- if (cancelled || generation !== loadGeneration.current || loading.current || state.current.drain || submittingBuild.current || revision !== state.current.revision) return;
78
- receiveReview(remote.review);
79
- if (canonicalJSON(draftRef.current) === state.current.savedJSON) {
80
- setStatus("saved");
81
- callbacksRef.current.onError("");
82
- }
83
- if (remote.revision === revision) return;
84
- if (canonicalJSON(draftRef.current) !== state.current.savedJSON) {
85
- setStatus("conflict");
86
- callbacksRef.current.onError("The file changed elsewhere. Your browser edits are not saved; neither version was overwritten.");
87
- return;
88
- }
89
- state.current = {
90
- ready: true,
91
- revision: remote.revision,
92
- savedJSON: canonicalJSON(remote.document),
93
- };
94
- setStatus("saved");
95
- callbacksRef.current.onExternalChange(remote.document);
96
- }).catch((error) => {
97
- if (cancelled || generation !== loadGeneration.current || loading.current || state.current.drain || submittingBuild.current || revision !== state.current.revision) return;
98
- setStatus("error");
99
- callbacksRef.current.onError(`Could not load the latest file. ${error instanceof Error ? error.message : "Check the local file service."}`);
100
- });
101
- }, 1000);
102
- return () => {
103
- cancelled = true;
104
- window.clearInterval(timer);
105
- };
106
- }, [enabled, token]);
107
-
108
- function finishBuild() {
109
- buildPending.current = false;
110
- setBuilding(false);
111
- }
112
-
113
- function receiveReview(next: ReviewState) {
114
- if (next.version < reviewRef.current.version) return;
115
- reviewRef.current = next;
116
- setReview(next);
117
- buildPending.current = activeRequest(next.request);
118
- setBuilding(buildPending.current);
119
- }
120
-
121
- async function noteAction(action: () => Promise<ReviewState>, saveFirst = false) {
122
- if (loading.current || !state.current.ready) throw new Error("Wait for the file to open before submitting.");
123
- if (submittingBuild.current) throw new Error("Wait for the current save before submitting.");
124
- submittingBuild.current = true;
125
- try {
126
- if (saveFirst && !await save(draftRef.current)) throw new Error("Save the composition before adding a note.");
127
- receiveReview(await action());
128
- } finally { submittingBuild.current = false; }
129
- }
130
-
131
- function save(next: Draft): Promise<string | undefined> {
132
- if (!token || loading.current || !state.current.ready || activeRequest(reviewRef.current.request)) return Promise.resolve(undefined);
133
- if (!validateComposition(next).ok) return Promise.resolve(undefined);
134
- const serialized = canonicalJSON(next);
135
- if (serialized === state.current.savedJSON && !state.current.drain)
136
- return Promise.resolve(state.current.revision);
137
- state.current.pending = { draft: next, serialized };
138
- if (!state.current.drain) {
139
- state.current.drain = drain(token).finally(() => {
140
- state.current.drain = undefined;
141
- });
142
- }
143
- return state.current.drain.then(() =>
144
- state.current.savedJSON === serialized ? state.current.revision : undefined,
145
- );
146
- }
147
-
148
- async function drain(activeToken: string) {
149
- while (state.current.pending) {
150
- const pending = state.current.pending;
151
- state.current.pending = undefined;
152
- setStatus("saving");
153
- try {
154
- const result = await saveFileSession(
155
- activeToken,
156
- state.current.revision,
157
- pending.draft,
158
- );
159
- state.current.revision = result.revision;
160
- state.current.savedJSON = pending.serialized;
161
- setStatus("saved");
162
- callbacksRef.current.onError("");
163
- } catch (error) {
164
- state.current.pending = undefined;
165
- const conflict = error instanceof FileSessionError && error.status === 409;
166
- setStatus(conflict ? "conflict" : "error");
167
- callbacksRef.current.onError(
168
- conflict
169
- ? "The file changed elsewhere. Your browser edits are not saved; neither version was overwritten."
170
- : `Changes are not saved. ${error instanceof Error ? error.message : "Could not save the composition file."}`,
171
- );
172
- return;
173
- }
174
- }
175
- }
176
-
177
- async function build(
178
- instruction: string,
179
- slideId: string,
180
- componentId?: string,
181
- elementId?: string,
182
- ) {
183
- if (!token || loading.current || !state.current.ready || buildPending.current) return false;
184
- if (submittingBuild.current) throw new Error("Wait for your note to finish saving before building.");
185
- buildPending.current = true;
186
- submittingBuild.current = true;
187
- setBuilding(true);
188
- try {
189
- const revision = await save(draftRef.current);
190
- if (!revision) {
191
- finishBuild();
192
- return false;
193
- }
194
- receiveReview(await sendBuildRequest(token, {
195
- revision,
196
- instruction,
197
- slideId,
198
- ...(componentId ? { componentId } : {}),
199
- ...(elementId ? { elementId } : {}),
200
- }));
201
- return true;
202
- } catch (error) {
203
- finishBuild();
204
- throw error;
205
- } finally {
206
- submittingBuild.current = false;
207
- }
208
- }
209
-
210
- async function reload() {
211
- if (!token || loading.current || state.current.drain || submittingBuild.current) return;
212
- loading.current = true;
213
- const generation = ++loadGeneration.current;
214
- const requestedJSON = canonicalJSON(draftRef.current);
215
- setStatus("loading");
216
- try {
217
- const session = await loadFileSession(token);
218
- if (generation !== loadGeneration.current) return;
219
- if (canonicalJSON(draftRef.current) !== requestedJSON) {
220
- setStatus("conflict");
221
- callbacksRef.current.onError("Your browser edits changed while opening the file. Neither version was overwritten. Download JSON before loading the file again.");
222
- return;
223
- }
224
- state.current = { ready: true, revision: session.revision, savedJSON: canonicalJSON(session.document) };
225
- draftRef.current = session.document;
226
- receiveReview(session.review);
227
- callbacksRef.current.onOpen(session.document, session.name);
228
- callbacksRef.current.onError("");
229
- setStatus("saved");
230
- } catch (error) {
231
- if (generation !== loadGeneration.current) return;
232
- setStatus("error");
233
- callbacksRef.current.onError(error instanceof Error ? error.message : "Could not open the file.");
234
- } finally {
235
- if (generation === loadGeneration.current) loading.current = false;
236
- }
237
- }
238
-
239
- return {
240
- status, build, building, review,
241
- opening: status === "loading",
242
- ready: state.current.ready,
243
- reload,
244
- retry: () => state.current.ready && !activeRequest(reviewRef.current.request) ? save(draftRef.current) : reload(),
245
- addNote: (target: ReviewTarget, text: string) => noteAction(() => addNote(token!, target, text), true),
246
- removeNote: (id: string) => noteAction(() => removeNote(token!, id)),
247
- cancel: () => noteAction(() => cancelRequest(token!, reviewRef.current.request!.id)),
248
- };
249
- }
package/src/main.tsx DELETED
@@ -1,29 +0,0 @@
1
- import { StrictMode } from "react";
2
- import { createRoot } from "react-dom/client";
3
- import "@fontsource/ibm-plex-sans/400.css";
4
- import "@fontsource/ibm-plex-sans/500.css";
5
- import "@fontsource/ibm-plex-sans/600.css";
6
- import "@fontsource/ibm-plex-serif/latin-400.css";
7
- import "@fontsource/ibm-plex-serif/latin-500.css";
8
- import "@fontsource/ibm-plex-serif/latin-600.css";
9
- import "@fontsource/noto-sans/latin-400.css";
10
- import "@fontsource/noto-sans/latin-500.css";
11
- import "@fontsource/noto-sans/latin-600.css";
12
- import "@fontsource/hanken-grotesk/latin-400.css";
13
- import "@fontsource/hanken-grotesk/latin-500.css";
14
- import "@fontsource/hanken-grotesk/latin-600.css";
15
- import { App } from "./app/App.tsx";
16
- import "./styles/base.css";
17
- import "./styles/shell.css";
18
- import "./styles/chrome.css";
19
- import "./styles/left-panel.css";
20
- import "./styles/right-panel.css";
21
- import "./styles/canvas.css";
22
- import "./styles/component-previews.css";
23
- import "./styles/feedback.css";
24
- import "./styles/presentation.css";
25
- createRoot(document.getElementById("root")!).render(
26
- <StrictMode>
27
- <App />
28
- </StrictMode>,
29
- );
@@ -1,299 +0,0 @@
1
- .canvas {
2
- width: 100%;
3
- aspect-ratio: var(--page-ratio);
4
- background: var(--slide-bg);
5
- position: relative;
6
- outline: 1px solid #dedede;
7
- box-shadow: 0 7px 26px #00000012;
8
- container-type: inline-size;
9
- }
10
- .presentation-canvas .slide-component:hover {
11
- outline: 0;
12
- }
13
- .presentation-canvas .component-surface {
14
- cursor: default;
15
- touch-action: auto;
16
- }
17
- .canvas .component-heading {
18
- font-family: var(--vector-heading-font);
19
- }
20
- .canvas {
21
- font-family: var(--vector-body-font);
22
- }
23
- .slide-component {
24
- position: absolute;
25
- background: var(--slide-bg);
26
- color: var(--slide-ink);
27
- border: 1px solid transparent;
28
- --component-accent: var(--slide-accent);
29
- --component-context: var(--slide-context);
30
- }
31
- .slide-component:hover {
32
- outline: 1px solid #a9a9a9;
33
- }
34
- .slide-component.selected {
35
- outline: 1px solid var(--accent);
36
- }
37
- .slide-component:has(.component-surface:focus-visible) {
38
- outline: 2px solid var(--accent);
39
- }
40
- .component-surface {
41
- border: 0;
42
- border-radius: 0;
43
- color: inherit;
44
- background: transparent;
45
- width: 100%;
46
- height: 100%;
47
- padding: 1.4cqw;
48
- text-align: inherit;
49
- overflow: hidden;
50
- display: flex;
51
- flex-direction: column;
52
- align-items: stretch;
53
- cursor: move;
54
- touch-action: none;
55
- }
56
- .component-surface:focus-visible {
57
- outline: 0;
58
- }
59
- .component-surface:hover:not(:disabled) {
60
- border-color: transparent;
61
- background: transparent;
62
- }
63
- .custom-visual .component-surface {
64
- padding: 0;
65
- }
66
- .custom-visual.border-none.rule-none {
67
- border: 0;
68
- }
69
- .custom-visual-art {
70
- display: block;
71
- width: 100%;
72
- height: 100%;
73
- pointer-events: none;
74
- user-select: none;
75
- }
76
- .custom-visual-art.fit-contain {
77
- object-fit: contain;
78
- }
79
- .custom-visual-art.fit-cover {
80
- object-fit: cover;
81
- }
82
- .custom-visual-art.fit-stretch {
83
- object-fit: fill;
84
- }
85
- .custom-vector-art {
86
- display: block;
87
- width: 100%;
88
- height: 100%;
89
- overflow: visible;
90
- }
91
- .custom-vector-art.editing .vector-element {
92
- pointer-events: all;
93
- cursor: pointer;
94
- }
95
- .custom-vector-art.editing .vector-element.selected {
96
- outline: 2px solid #0974e9;
97
- outline-offset: 3px;
98
- filter: drop-shadow(0 0 5px #0974e980);
99
- }
100
- .vector-handles circle {
101
- fill: #ffffff;
102
- stroke: #0974e9;
103
- stroke-width: 3;
104
- vector-effect: non-scaling-stroke;
105
- cursor: crosshair;
106
- }
107
- .component-heading {
108
- font-size: max(1.7cqw, 11px);
109
- font-weight: 500;
110
- line-height: 1.3;
111
- }
112
- .title-prominent .component-heading {
113
- font-weight: 600;
114
- font-size: 2.2cqw;
115
- }
116
- .component-intent {
117
- display: block;
118
- color: var(--slide-muted);
119
- font-size: max(1.7cqw, 11px);
120
- margin-top: 0.7cqw;
121
- line-height: 1.5;
122
- cursor: text;
123
- }
124
- .inline-intent-editor {
125
- position: absolute;
126
- inset: 0;
127
- z-index: 3;
128
- width: 100%;
129
- height: max(100%, 8.5cqw);
130
- min-height: calc(1.5em + 2.8cqw + 2px);
131
- margin: 0;
132
- padding: 1.4cqw;
133
- box-sizing: border-box;
134
- border: 1px solid var(--slide-accent);
135
- border-radius: 2px;
136
- outline: 0;
137
- background: var(--slide-bg);
138
- color: var(--slide-ink);
139
- font: inherit;
140
- line-height: 1.5;
141
- resize: none;
142
- }
143
- .kind-text-block.role-title:not(.custom-visual) .component-surface {
144
- justify-content: flex-end;
145
- padding: 0.5cqw 0;
146
- }
147
- .kind-text-block.role-title .component-heading {
148
- font-size: max(2.6cqw, 20px);
149
- font-weight: 600;
150
- line-height: 1.18;
151
- }
152
- .kind-text-block.role-title .component-intent {
153
- font-size: max(1.7cqw, 11px);
154
- margin-top: 0.4cqw;
155
- }
156
- .kind-text-block.role-footnote:not(.custom-visual) .component-surface {
157
- padding: 1cqw 0;
158
- }
159
- .kind-text-block.role-footnote .component-heading {
160
- display: none;
161
- }
162
- .kind-text-block.role-footnote .component-intent {
163
- font-size: max(1.7cqw, 11px);
164
- margin: 0;
165
- }
166
- .slide-page-number {
167
- position: absolute;
168
- z-index: var(--component-layers);
169
- right: 5.833333%;
170
- bottom: 2.2%;
171
- font-size: max(1.5cqw, 11px);
172
- font-variant-numeric: tabular-nums;
173
- line-height: 1;
174
- }
175
- .color-muted {
176
- color: var(--slide-muted);
177
- }
178
- .color-accent {
179
- color: var(--slide-accent);
180
- }
181
- .border-outline {
182
- border: 1px solid var(--slide-context);
183
- }
184
- .border-filled {
185
- background: color-mix(in srgb, var(--slide-context) 22%, var(--slide-bg));
186
- }
187
- .rule-top {
188
- border-top: 1px solid var(--slide-context);
189
- }
190
- .rule-bottom {
191
- border-bottom: 1px solid var(--slide-context);
192
- }
193
- .resize-handle {
194
- position: absolute;
195
- width: 40px;
196
- height: 40px;
197
- padding: 0;
198
- border: 0;
199
- background: transparent;
200
- touch-action: none;
201
- z-index: 2;
202
- }
203
- .resize-handle::after {
204
- position: absolute;
205
- top: 17px;
206
- left: 17px;
207
- width: 6px;
208
- height: 6px;
209
- border: 1px solid var(--accent);
210
- background: white;
211
- content: "";
212
- }
213
- .resize-handle:hover:not(:disabled) {
214
- border-color: transparent;
215
- background: transparent;
216
- }
217
- .resize-nw {
218
- top: -20px;
219
- left: -20px;
220
- cursor: nwse-resize;
221
- }
222
- .resize-ne {
223
- top: -20px;
224
- right: -20px;
225
- cursor: nesw-resize;
226
- }
227
- .resize-sw {
228
- bottom: -20px;
229
- left: -20px;
230
- cursor: nesw-resize;
231
- }
232
- .resize-se {
233
- right: -20px;
234
- bottom: -20px;
235
- cursor: nwse-resize;
236
- }
237
- .guide {
238
- position: absolute;
239
- pointer-events: none;
240
- z-index: calc(var(--component-layers) + 1);
241
- }
242
- .guide-x {
243
- top: 0;
244
- bottom: 0;
245
- border-left: 1px solid var(--accent);
246
- }
247
- .guide-y {
248
- left: 0;
249
- right: 0;
250
- border-top: 1px solid var(--accent);
251
- }
252
-
253
- .kind-text-block:not(.custom-visual) .component-surface {
254
- padding: 0;
255
- justify-content: flex-start;
256
- }
257
- .text-block-content {
258
- white-space: pre-wrap;
259
- overflow-wrap: anywhere;
260
- flex: none;
261
- width: 100%;
262
- }
263
- .kind-text-block:not(.custom-visual) .inline-intent-editor {
264
- padding: 0;
265
- text-align: inherit;
266
- min-height: 100%;
267
- height: 100%;
268
- }
269
- .revision-pin {
270
- position: absolute;
271
- display: grid;
272
- place-items: center;
273
- width: 40px;
274
- height: 40px;
275
- min-height: 0;
276
- padding: 0;
277
- border: 0;
278
- border-radius: 50%;
279
- background: radial-gradient(
280
- circle,
281
- var(--accent) 0 10px,
282
- var(--ui-surface) 10.5px 11.5px,
283
- transparent 12px
284
- );
285
- color: white;
286
- font: 500 11px "IBM Plex Sans", sans-serif;
287
- box-shadow: none;
288
- filter: drop-shadow(0 1px 2px #0003);
289
- }
290
- .revision-pin:hover:not(:disabled),
291
- .revision-pin:active:not(:disabled) {
292
- border-color: transparent;
293
- background: radial-gradient(
294
- circle,
295
- #006aa1 0 10px,
296
- var(--ui-surface) 10.5px 11.5px,
297
- transparent 12px
298
- );
299
- }