@broadpaper/editor 0.1.1
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/LICENSE +143 -0
- package/THIRD-PARTY-NOTICES.md +255 -0
- package/dist/index.d.ts +439 -0
- package/dist/index.js +5505 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +673 -0
- package/package.json +50 -0
package/dist/styles.css
ADDED
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
/* BroadPaper editor design tokens.
|
|
2
|
+
`.bpe` is the editor shell; `.bpe-scope` is a token-only scope used by portalled
|
|
3
|
+
floating elements (tooltips, popovers) so they inherit the palette WITHOUT the
|
|
4
|
+
shell's grid layout, size and background. */
|
|
5
|
+
.bpe,
|
|
6
|
+
.bpe-scope {
|
|
7
|
+
/* colour */
|
|
8
|
+
--bpe-bg: #ffffff;
|
|
9
|
+
--bpe-bg-subtle: #f7f8fa;
|
|
10
|
+
--bpe-bg-muted: #eef0f4;
|
|
11
|
+
--bpe-bg-canvas: #e9ebf0;
|
|
12
|
+
--bpe-bg-elevated: #ffffff;
|
|
13
|
+
--bpe-fg: #111827;
|
|
14
|
+
--bpe-fg-secondary: #4b5563;
|
|
15
|
+
--bpe-fg-muted: #6b7280;
|
|
16
|
+
--bpe-fg-faint: #9ca3af;
|
|
17
|
+
--bpe-border: #e5e7eb;
|
|
18
|
+
--bpe-border-strong: #d1d5db;
|
|
19
|
+
--bpe-accent: #3b5bdb;
|
|
20
|
+
--bpe-accent-hover: #3451c7;
|
|
21
|
+
--bpe-accent-soft: rgba(59, 91, 219, 0.1);
|
|
22
|
+
--bpe-accent-soft-strong: rgba(59, 91, 219, 0.18);
|
|
23
|
+
--bpe-accent-fg: #ffffff;
|
|
24
|
+
|
|
25
|
+
/* The one filled call to action — Export, and any host button asking for
|
|
26
|
+
`variant="primary"`. Separate from the accent, and defaulting to it, because
|
|
27
|
+
a host wanting its brand on that button rarely wants the same colour on
|
|
28
|
+
selection outlines, focus rings and the active tab: BroadPaper's own is a
|
|
29
|
+
vermilion that reads as an error the moment it outlines a selected block,
|
|
30
|
+
and `--bpe-danger` is nearly the same red. Set this alone and the button is
|
|
31
|
+
yours while everything that means "this is selected" stays legible. */
|
|
32
|
+
--bpe-primary: var(--bpe-accent);
|
|
33
|
+
--bpe-primary-hover: var(--bpe-accent-hover);
|
|
34
|
+
--bpe-primary-fg: var(--bpe-accent-fg);
|
|
35
|
+
|
|
36
|
+
--bpe-danger: #dc2626;
|
|
37
|
+
--bpe-danger-soft: rgba(220, 38, 38, 0.1);
|
|
38
|
+
--bpe-warning: #d97706;
|
|
39
|
+
--bpe-warning-soft: rgba(217, 119, 6, 0.12);
|
|
40
|
+
--bpe-success: #059669;
|
|
41
|
+
--bpe-success-soft: rgba(5, 150, 105, 0.12);
|
|
42
|
+
--bpe-token: #2f4f7f;
|
|
43
|
+
--bpe-token-bg: rgba(79, 111, 165, 0.14);
|
|
44
|
+
--bpe-selection: var(--bpe-accent);
|
|
45
|
+
--bpe-hover-outline: rgba(59, 91, 219, 0.45);
|
|
46
|
+
--bpe-drop: #10b981;
|
|
47
|
+
|
|
48
|
+
/* typography */
|
|
49
|
+
--bpe-font: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
50
|
+
--bpe-font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
51
|
+
--bpe-text-xs: 10.5px;
|
|
52
|
+
--bpe-text-sm: 11.5px;
|
|
53
|
+
--bpe-text-md: 12.5px;
|
|
54
|
+
--bpe-text-lg: 14px;
|
|
55
|
+
--bpe-text-xl: 16px;
|
|
56
|
+
|
|
57
|
+
/* geometry */
|
|
58
|
+
--bpe-radius-sm: 4px;
|
|
59
|
+
--bpe-radius: 6px;
|
|
60
|
+
--bpe-radius-lg: 10px;
|
|
61
|
+
--bpe-space-1: 4px;
|
|
62
|
+
--bpe-space-2: 8px;
|
|
63
|
+
--bpe-space-3: 12px;
|
|
64
|
+
--bpe-space-4: 16px;
|
|
65
|
+
--bpe-space-5: 20px;
|
|
66
|
+
--bpe-space-6: 24px;
|
|
67
|
+
--bpe-control-h: 28px;
|
|
68
|
+
--bpe-control-h-sm: 24px;
|
|
69
|
+
--bpe-panel-w: 272px;
|
|
70
|
+
--bpe-inspector-w: 296px;
|
|
71
|
+
--bpe-toolbar-h: 48px;
|
|
72
|
+
|
|
73
|
+
/* effects */
|
|
74
|
+
--bpe-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
|
|
75
|
+
--bpe-shadow: 0 1px 3px rgba(16, 24, 40, 0.1), 0 1px 2px rgba(16, 24, 40, 0.06);
|
|
76
|
+
--bpe-shadow-lg: 0 10px 30px rgba(16, 24, 40, 0.16), 0 2px 6px rgba(16, 24, 40, 0.08);
|
|
77
|
+
--bpe-shadow-page: 0 1px 2px rgba(16, 24, 40, 0.1), 0 12px 32px rgba(16, 24, 40, 0.1);
|
|
78
|
+
--bpe-focus: 0 0 0 2px var(--bpe-bg), 0 0 0 4px var(--bpe-accent);
|
|
79
|
+
--bpe-ease: cubic-bezier(0.2, 0, 0, 1);
|
|
80
|
+
--bpe-dur: 140ms;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.bpe[data-appearance="dark"],
|
|
84
|
+
.bpe-scope[data-appearance="dark"] {
|
|
85
|
+
--bpe-bg: #17191e;
|
|
86
|
+
--bpe-bg-subtle: #1d2026;
|
|
87
|
+
--bpe-bg-muted: #23262d;
|
|
88
|
+
--bpe-bg-canvas: #101114;
|
|
89
|
+
--bpe-bg-elevated: #1f2228;
|
|
90
|
+
--bpe-fg: #e7e9ee;
|
|
91
|
+
--bpe-fg-secondary: #b9bec8;
|
|
92
|
+
--bpe-fg-muted: #8b919c;
|
|
93
|
+
--bpe-fg-faint: #5e636d;
|
|
94
|
+
--bpe-border: #2b2f37;
|
|
95
|
+
--bpe-border-strong: #3a3f49;
|
|
96
|
+
--bpe-accent: #6b8cff;
|
|
97
|
+
--bpe-accent-hover: #7e9bff;
|
|
98
|
+
--bpe-accent-soft: rgba(107, 140, 255, 0.16);
|
|
99
|
+
--bpe-accent-soft-strong: rgba(107, 140, 255, 0.28);
|
|
100
|
+
--bpe-accent-fg: #0e1220;
|
|
101
|
+
--bpe-token: #a9c0ff;
|
|
102
|
+
--bpe-token-bg: rgba(107, 140, 255, 0.2);
|
|
103
|
+
--bpe-hover-outline: rgba(107, 140, 255, 0.55);
|
|
104
|
+
--bpe-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
105
|
+
--bpe-shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.3);
|
|
106
|
+
--bpe-shadow-page: 0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.4);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ===================================================================
|
|
110
|
+
BroadPaper editor — component styles. Scoped under .bpe.
|
|
111
|
+
=================================================================== */
|
|
112
|
+
|
|
113
|
+
.bpe, .bpe *, .bpe *::before, .bpe *::after,
|
|
114
|
+
.bpe-scope, .bpe-scope *, .bpe-scope *::before, .bpe-scope *::after { box-sizing: border-box; }
|
|
115
|
+
.bpe {
|
|
116
|
+
position: relative;
|
|
117
|
+
display: grid;
|
|
118
|
+
grid-template-rows: var(--bpe-toolbar-h) 1fr;
|
|
119
|
+
grid-template-columns: var(--bpe-panel-w) minmax(0, 1fr) var(--bpe-inspector-w);
|
|
120
|
+
grid-template-areas: "toolbar toolbar toolbar" "left canvas right";
|
|
121
|
+
width: 100%;
|
|
122
|
+
height: 100%;
|
|
123
|
+
min-height: 480px;
|
|
124
|
+
background: var(--bpe-bg);
|
|
125
|
+
color: var(--bpe-fg);
|
|
126
|
+
font-family: var(--bpe-font);
|
|
127
|
+
font-size: var(--bpe-text-md);
|
|
128
|
+
line-height: 1.4;
|
|
129
|
+
-webkit-font-smoothing: antialiased;
|
|
130
|
+
overflow: hidden;
|
|
131
|
+
border: 1px solid var(--bpe-border);
|
|
132
|
+
border-radius: var(--bpe-radius-lg);
|
|
133
|
+
}
|
|
134
|
+
.bpe--no-left { grid-template-columns: 0 minmax(0, 1fr) var(--bpe-inspector-w); }
|
|
135
|
+
.bpe--no-right { grid-template-columns: var(--bpe-panel-w) minmax(0, 1fr) 0; }
|
|
136
|
+
.bpe--no-left.bpe--no-right { grid-template-columns: 0 minmax(0, 1fr) 0; }
|
|
137
|
+
.bpe--no-toolbar { grid-template-rows: 0 1fr; }
|
|
138
|
+
.bpe button, .bpe input, .bpe select, .bpe textarea,
|
|
139
|
+
.bpe-scope button, .bpe-scope input, .bpe-scope select, .bpe-scope textarea { font: inherit; color: inherit; }
|
|
140
|
+
.bpe button, .bpe-scope button { cursor: pointer; }
|
|
141
|
+
.bpe :focus-visible, .bpe-scope :focus-visible { outline: none; box-shadow: var(--bpe-focus); }
|
|
142
|
+
.bpe ::selection, .bpe-scope ::selection { background: var(--bpe-accent-soft-strong); }
|
|
143
|
+
.bpe-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
144
|
+
.bpe-mono { font-family: var(--bpe-font-mono); }
|
|
145
|
+
.bpe-muted { color: var(--bpe-fg-muted); }
|
|
146
|
+
.bpe-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
147
|
+
|
|
148
|
+
/* scrollbars */
|
|
149
|
+
.bpe *::-webkit-scrollbar, .bpe-scope *::-webkit-scrollbar { width: 10px; height: 10px; }
|
|
150
|
+
.bpe *::-webkit-scrollbar-thumb, .bpe-scope *::-webkit-scrollbar-thumb { background: var(--bpe-border-strong); border: 3px solid transparent; border-radius: 8px; background-clip: padding-box; }
|
|
151
|
+
.bpe *::-webkit-scrollbar-thumb:hover { background: var(--bpe-fg-faint); background-clip: padding-box; border: 3px solid transparent; }
|
|
152
|
+
.bpe *::-webkit-scrollbar-track { background: transparent; }
|
|
153
|
+
|
|
154
|
+
/* ------------------------------------------------------------------ */
|
|
155
|
+
/* Primitives */
|
|
156
|
+
/* ------------------------------------------------------------------ */
|
|
157
|
+
.bpe-btn {
|
|
158
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
159
|
+
height: var(--bpe-control-h); padding: 0 10px; border-radius: var(--bpe-radius);
|
|
160
|
+
border: 1px solid var(--bpe-border); background: var(--bpe-bg); color: var(--bpe-fg);
|
|
161
|
+
font-size: var(--bpe-text-sm); font-weight: 500; white-space: nowrap; user-select: none; flex-shrink: 0;
|
|
162
|
+
transition: background var(--bpe-dur) var(--bpe-ease), border-color var(--bpe-dur) var(--bpe-ease), color var(--bpe-dur) var(--bpe-ease), transform 80ms var(--bpe-ease);
|
|
163
|
+
}
|
|
164
|
+
.bpe-btn:hover { background: var(--bpe-bg-subtle); border-color: var(--bpe-border-strong); }
|
|
165
|
+
.bpe-btn:active { transform: translateY(0.5px); }
|
|
166
|
+
.bpe-btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
|
|
167
|
+
.bpe-btn--primary { background: var(--bpe-primary); border-color: var(--bpe-primary); color: var(--bpe-primary-fg); }
|
|
168
|
+
.bpe-btn--primary:hover { background: var(--bpe-primary-hover); border-color: var(--bpe-primary-hover); }
|
|
169
|
+
.bpe-btn--ghost { border-color: transparent; background: transparent; }
|
|
170
|
+
.bpe-btn--ghost:hover { background: var(--bpe-bg-muted); border-color: transparent; }
|
|
171
|
+
.bpe-btn--danger { color: var(--bpe-danger); }
|
|
172
|
+
.bpe-btn--danger:hover { background: var(--bpe-danger-soft); border-color: transparent; }
|
|
173
|
+
.bpe-btn--sm { height: var(--bpe-control-h-sm); padding: 0 8px; font-size: var(--bpe-text-xs); }
|
|
174
|
+
.bpe-btn--icon { width: var(--bpe-control-h); padding: 0; }
|
|
175
|
+
.bpe-btn--sm.bpe-btn--icon { width: var(--bpe-control-h-sm); }
|
|
176
|
+
.bpe-btn--active { background: var(--bpe-accent-soft); border-color: transparent; color: var(--bpe-accent); }
|
|
177
|
+
.bpe-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
|
|
178
|
+
.bpe-btn--sm svg { width: 13px; height: 13px; }
|
|
179
|
+
|
|
180
|
+
.bpe-input, .bpe-select, .bpe-textarea {
|
|
181
|
+
width: 100%; height: var(--bpe-control-h); padding: 0 8px; border-radius: var(--bpe-radius);
|
|
182
|
+
border: 1px solid var(--bpe-border); background: var(--bpe-bg); color: var(--bpe-fg); font-size: var(--bpe-text-sm);
|
|
183
|
+
transition: border-color var(--bpe-dur) var(--bpe-ease), box-shadow var(--bpe-dur) var(--bpe-ease);
|
|
184
|
+
}
|
|
185
|
+
.bpe-input::placeholder, .bpe-textarea::placeholder { color: var(--bpe-fg-faint); }
|
|
186
|
+
.bpe-input:hover, .bpe-select:hover, .bpe-textarea:hover { border-color: var(--bpe-border-strong); }
|
|
187
|
+
.bpe-input:focus, .bpe-select:focus, .bpe-textarea:focus { border-color: var(--bpe-accent); box-shadow: 0 0 0 3px var(--bpe-accent-soft); }
|
|
188
|
+
.bpe-input--invalid { border-color: var(--bpe-danger) !important; }
|
|
189
|
+
.bpe-textarea { height: auto; min-height: 56px; padding: 6px 8px; resize: vertical; line-height: 1.45; }
|
|
190
|
+
.bpe-select { appearance: none; padding-right: 24px; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round'/></svg>"); background-repeat: no-repeat; background-position: right 8px center; }
|
|
191
|
+
.bpe-input-group { position: relative; display: flex; align-items: center; }
|
|
192
|
+
.bpe-input-group .bpe-input { padding-right: 28px; }
|
|
193
|
+
.bpe-input-group__suffix { position: absolute; right: 8px; font-size: var(--bpe-text-xs); color: var(--bpe-fg-faint); pointer-events: none; }
|
|
194
|
+
.bpe-input-group__btn { position: absolute; right: 2px; top: 2px; }
|
|
195
|
+
.bpe-number { display: flex; align-items: center; }
|
|
196
|
+
.bpe-number .bpe-input { text-align: left; }
|
|
197
|
+
|
|
198
|
+
.bpe-switch { position: relative; display: inline-flex; width: 30px; height: 18px; border-radius: 9px; background: var(--bpe-border-strong); border: 0; padding: 0; transition: background var(--bpe-dur) var(--bpe-ease); flex-shrink: 0; }
|
|
199
|
+
.bpe-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: var(--bpe-shadow-sm); transition: transform var(--bpe-dur) var(--bpe-ease); }
|
|
200
|
+
.bpe-switch[aria-checked="true"] { background: var(--bpe-accent); }
|
|
201
|
+
.bpe-switch[aria-checked="true"]::after { transform: translateX(12px); }
|
|
202
|
+
|
|
203
|
+
.bpe-segmented { display: inline-flex; padding: 2px; border-radius: var(--bpe-radius); background: var(--bpe-bg-muted); gap: 2px; width: 100%; }
|
|
204
|
+
.bpe-segmented__item { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 22px; padding: 0 6px; border: 0; border-radius: 4px; background: transparent; color: var(--bpe-fg-muted); font-size: var(--bpe-text-xs); font-weight: 500; transition: background var(--bpe-dur) var(--bpe-ease), color var(--bpe-dur) var(--bpe-ease); min-width: 0; }
|
|
205
|
+
.bpe-segmented__item:hover { color: var(--bpe-fg); }
|
|
206
|
+
.bpe-segmented__item[aria-pressed="true"] { background: var(--bpe-bg-elevated); color: var(--bpe-fg); box-shadow: var(--bpe-shadow-sm); }
|
|
207
|
+
.bpe-segmented__item svg { width: 13px; height: 13px; }
|
|
208
|
+
|
|
209
|
+
/* Five named tabs will not fit side by side in a 272px panel, so they stack
|
|
210
|
+
the label under the icon and share the row evenly. Names beat guessing at
|
|
211
|
+
icons; a second row of chrome does not. */
|
|
212
|
+
.bpe-tabs { display: flex; gap: 2px; padding: 6px 6px 0; border-bottom: 1px solid var(--bpe-border); }
|
|
213
|
+
.bpe-tab { position: relative; flex: 1 1 0; min-width: 0; display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; height: 42px; padding: 0 2px; border: 0; background: transparent; color: var(--bpe-fg-muted); font-size: var(--bpe-text-xs); font-weight: 500; border-radius: var(--bpe-radius-sm) var(--bpe-radius-sm) 0 0; }
|
|
214
|
+
.bpe-tab > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
215
|
+
.bpe-tab:hover { color: var(--bpe-fg); background: var(--bpe-bg-subtle); }
|
|
216
|
+
.bpe-tab[aria-selected="true"] { color: var(--bpe-fg); }
|
|
217
|
+
.bpe-tab[aria-selected="true"] { background: var(--bpe-bg-subtle); }
|
|
218
|
+
.bpe-tab[aria-selected="true"]::after { content: ""; position: absolute; left: 6px; right: 6px; bottom: -1px; height: 2px; background: var(--bpe-accent); border-radius: 2px; }
|
|
219
|
+
.bpe-tab svg { width: 14px; height: 14px; }
|
|
220
|
+
|
|
221
|
+
.bpe-popover { z-index: 1000; min-width: 180px; max-width: 340px; padding: 6px; border-radius: var(--bpe-radius-lg); border: 1px solid var(--bpe-border); background: var(--bpe-bg-elevated); color: var(--bpe-fg); box-shadow: var(--bpe-shadow-lg); font-family: var(--bpe-font); font-size: var(--bpe-text-sm); }
|
|
222
|
+
/* Entrance runs only once floating-ui has positioned the element, so it never
|
|
223
|
+
animates from the viewport corner. */
|
|
224
|
+
.bpe-floating--in { animation: bpe-pop var(--bpe-dur) var(--bpe-ease); }
|
|
225
|
+
@keyframes bpe-pop { from { opacity: 0; transform: translateY(-3px) scale(0.98); } to { opacity: 1; transform: none; } }
|
|
226
|
+
.bpe-menu__item { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 28px; padding: 4px 8px; border: 0; border-radius: var(--bpe-radius-sm); background: transparent; color: var(--bpe-fg); text-align: left; font-size: var(--bpe-text-sm); }
|
|
227
|
+
.bpe-menu__item--stacked { align-items: flex-start; padding: 6px 8px; }
|
|
228
|
+
.bpe-menu__item--stacked svg { margin-top: 2px; }
|
|
229
|
+
.bpe-menu__body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
|
|
230
|
+
.bpe-menu__label-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
231
|
+
.bpe-menu__desc { font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
232
|
+
.bpe-menu__item:hover, .bpe-menu__item:focus-visible { background: var(--bpe-bg-muted); box-shadow: none; }
|
|
233
|
+
.bpe-menu__item:disabled { opacity: 0.45; }
|
|
234
|
+
.bpe-menu__item svg { width: 14px; height: 14px; color: var(--bpe-fg-muted); }
|
|
235
|
+
.bpe-menu__item--danger { color: var(--bpe-danger); }
|
|
236
|
+
.bpe-menu__item--danger svg { color: var(--bpe-danger); }
|
|
237
|
+
.bpe-menu__sep { height: 1px; margin: 4px 0; background: var(--bpe-border); }
|
|
238
|
+
.bpe-menu__label { padding: 6px 8px 2px; font-size: var(--bpe-text-xs); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--bpe-fg-faint); }
|
|
239
|
+
.bpe-menu__hint { margin-left: auto; padding-left: 8px; color: var(--bpe-fg-faint); font-size: var(--bpe-text-xs); white-space: nowrap; flex-shrink: 0; }
|
|
240
|
+
/* The portal is a zero-width positioned box, which is the containing block for
|
|
241
|
+
everything floating inside it. A shrink-to-fit element therefore has no room
|
|
242
|
+
at all and wraps after every word; `max-content` is what stops that. */
|
|
243
|
+
.bpe-tooltip { width: max-content; z-index: 1100; padding: 4px 8px; border-radius: var(--bpe-radius-sm); background: #111827; color: #fff; font-size: var(--bpe-text-xs); font-family: var(--bpe-font); font-weight: 500; pointer-events: none; box-shadow: var(--bpe-shadow); max-width: 260px; }
|
|
244
|
+
.bpe-tooltip .bpe-kbd { margin-left: 6px; background: rgba(255,255,255,0.14); color: #fff; border-color: transparent; }
|
|
245
|
+
.bpe-kbd { display: inline-block; padding: 0 4px; border-radius: 3px; border: 1px solid var(--bpe-border); background: var(--bpe-bg-subtle); font-size: 10px; font-family: var(--bpe-font); color: var(--bpe-fg-muted); line-height: 15px; }
|
|
246
|
+
.bpe-badge { display: inline-flex; align-items: center; gap: 4px; height: 18px; padding: 0 6px; border-radius: 999px; background: var(--bpe-bg-muted); color: var(--bpe-fg-secondary); font-size: var(--bpe-text-xs); font-weight: 600; white-space: nowrap; }
|
|
247
|
+
.bpe-badge--accent { background: var(--bpe-accent-soft); color: var(--bpe-accent); }
|
|
248
|
+
.bpe-badge--warning { background: var(--bpe-warning-soft); color: var(--bpe-warning); }
|
|
249
|
+
.bpe-badge--danger { background: var(--bpe-danger-soft); color: var(--bpe-danger); }
|
|
250
|
+
.bpe-badge--success { background: var(--bpe-success-soft); color: var(--bpe-success); }
|
|
251
|
+
.bpe-chip { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 7px; border-radius: 4px; background: var(--bpe-token-bg); color: var(--bpe-token); font-size: var(--bpe-text-xs); font-weight: 500; max-width: 100%; }
|
|
252
|
+
.bpe-chip svg { width: 11px; height: 11px; }
|
|
253
|
+
.bpe-chip__x { margin-left: 2px; border: 0; background: transparent; padding: 0; color: inherit; display: inline-flex; opacity: 0.6; }
|
|
254
|
+
.bpe-chip__x:hover { opacity: 1; }
|
|
255
|
+
.bpe-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 28px 16px; text-align: center; color: var(--bpe-fg-muted); font-size: var(--bpe-text-sm); }
|
|
256
|
+
.bpe-empty svg { width: 22px; height: 22px; color: var(--bpe-fg-faint); }
|
|
257
|
+
|
|
258
|
+
/* One region's failure, contained. See ui/Boundary.tsx. */
|
|
259
|
+
.bpe-boundary { display: flex; align-items: flex-start; gap: 10px; overflow: auto; padding: 12px 14px; background: var(--bpe-bg); border: 1px solid var(--bpe-border); color: var(--bpe-fg); font-size: var(--bpe-text-sm); }
|
|
260
|
+
.bpe-boundary > svg { flex-shrink: 0; margin-top: 1px; color: var(--bpe-warning); }
|
|
261
|
+
.bpe-boundary__body { flex: 1; min-width: 0; }
|
|
262
|
+
.bpe-boundary__title { font-weight: 600; }
|
|
263
|
+
.bpe-boundary__detail { margin-top: 2px; color: var(--bpe-fg-muted); }
|
|
264
|
+
|
|
265
|
+
/* Where it went. Applied to a block the canvas has just scrolled to, so an
|
|
266
|
+
insertion that landed on another page is visibly an insertion and not a
|
|
267
|
+
jump. Motion-sensitive users get the tint without the pulse. */
|
|
268
|
+
@keyframes bpe-flash {
|
|
269
|
+
0% { box-shadow: 0 0 0 2px var(--bpe-accent), 0 0 0 7px var(--bpe-accent-soft); background-color: var(--bpe-accent-soft); }
|
|
270
|
+
70% { box-shadow: 0 0 0 2px var(--bpe-accent), 0 0 0 7px var(--bpe-accent-soft); background-color: var(--bpe-accent-soft); }
|
|
271
|
+
100% { box-shadow: 0 0 0 0 transparent, 0 0 0 0 transparent; background-color: transparent; }
|
|
272
|
+
}
|
|
273
|
+
.bpe-flash { animation: bpe-flash 1.2s ease-out both; border-radius: 3px; }
|
|
274
|
+
@media (prefers-reduced-motion: reduce) {
|
|
275
|
+
.bpe-flash { animation: none; background-color: var(--bpe-accent-soft); box-shadow: 0 0 0 2px var(--bpe-accent); }
|
|
276
|
+
}
|
|
277
|
+
.bpe-empty__title { font-weight: 600; color: var(--bpe-fg-secondary); }
|
|
278
|
+
|
|
279
|
+
/* form field */
|
|
280
|
+
.bpe-field { display: grid; grid-template-columns: 96px minmax(0, 1fr); align-items: center; gap: 6px 10px; min-height: var(--bpe-control-h); }
|
|
281
|
+
.bpe-field--stacked { grid-template-columns: 1fr; gap: 4px; }
|
|
282
|
+
.bpe-field__label { font-size: var(--bpe-text-sm); color: var(--bpe-fg-secondary); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
283
|
+
.bpe-field__control { min-width: 0; display: flex; align-items: center; gap: 4px; }
|
|
284
|
+
.bpe-field__hint { grid-column: 1 / -1; min-width: 0; margin-top: -2px; font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); line-height: 1.35; overflow-wrap: anywhere; }
|
|
285
|
+
.bpe-field__error { grid-column: 1 / -1; font-size: var(--bpe-text-xs); color: var(--bpe-danger); }
|
|
286
|
+
.bpe-prop-grid { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; }
|
|
287
|
+
.bpe-section { border-bottom: 1px solid var(--bpe-border); }
|
|
288
|
+
.bpe-section__head { display: flex; align-items: center; gap: 4px; width: 100%; height: 34px; padding: 0 8px 0 0; }
|
|
289
|
+
.bpe-section__toggle { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; height: 100%; padding: 0 4px 0 12px; border: 0; background: transparent; color: var(--bpe-fg); font-size: var(--bpe-text-sm); font-weight: 600; text-align: left; }
|
|
290
|
+
.bpe-section__toggle:hover { background: var(--bpe-bg-subtle); }
|
|
291
|
+
.bpe-section__toggle svg { width: 13px; height: 13px; color: var(--bpe-fg-faint); transition: transform var(--bpe-dur) var(--bpe-ease); }
|
|
292
|
+
.bpe-section__toggle[aria-expanded="false"] svg.bpe-section__chev { transform: rotate(-90deg); }
|
|
293
|
+
.bpe-section__toggle .bpe-section__chev { margin-left: auto; }
|
|
294
|
+
.bpe-section__actions { display: inline-flex; }
|
|
295
|
+
.bpe-section__body { padding-bottom: 4px; }
|
|
296
|
+
|
|
297
|
+
/* ------------------------------------------------------------------ */
|
|
298
|
+
/* Toolbar */
|
|
299
|
+
/* ------------------------------------------------------------------ */
|
|
300
|
+
/* The side tracks must be allowed to shrink. As plain `1fr` they refuse to go
|
|
301
|
+
below their own content, so the end group overflowed leftwards and drew the
|
|
302
|
+
brand picker on top of the Preview button instead of giving anything up. */
|
|
303
|
+
.bpe-toolbar { grid-area: toolbar; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; padding: 0 12px; border-bottom: 1px solid var(--bpe-border); background: var(--bpe-bg); z-index: 5; }
|
|
304
|
+
.bpe-toolbar__group { display: flex; align-items: center; gap: 4px; min-width: 0; }
|
|
305
|
+
.bpe-toolbar__group--end { justify-content: flex-end; }
|
|
306
|
+
.bpe-toolbar__sep { width: 1px; height: 20px; margin: 0 6px; background: var(--bpe-border); }
|
|
307
|
+
.bpe-toolbar__brand { display: flex; align-items: center; gap: 8px; margin-right: 6px; min-width: 0; }
|
|
308
|
+
/* The product mark. No tile behind it: the sheet is the shape, and a tile
|
|
309
|
+
would make it a second rectangle inside a rectangle. */
|
|
310
|
+
.bpe-toolbar__mark { display: grid; place-items: center; flex-shrink: 0; }
|
|
311
|
+
.bpe-toolbar__mark svg { width: 22px; height: 18px; display: block; }
|
|
312
|
+
.bpe-toolbar__name { height: 26px; flex: 0 1 auto; min-width: 0; width: 220px; max-width: 260px; padding: 0 6px; border: 1px solid transparent; border-radius: var(--bpe-radius-sm); background: transparent; font-weight: 600; font-size: var(--bpe-text-md); color: var(--bpe-fg); }
|
|
313
|
+
.bpe-toolbar__name:hover { border-color: var(--bpe-border); }
|
|
314
|
+
.bpe-toolbar__name:focus { border-color: var(--bpe-accent); box-shadow: 0 0 0 3px var(--bpe-accent-soft); }
|
|
315
|
+
/* The centre group never gives up room; the ends shrink around it. */
|
|
316
|
+
.bpe-toolbar__group--centre { flex: 0 0 auto; white-space: nowrap; }
|
|
317
|
+
.bpe-toolbar__group--start { overflow: hidden; }
|
|
318
|
+
|
|
319
|
+
.bpe-save { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 7px; border: 1px solid transparent; border-radius: var(--bpe-radius-sm); font-size: var(--bpe-text-xs); font-weight: 500; white-space: nowrap; flex-shrink: 0; }
|
|
320
|
+
.bpe-save__text { max-width: 130px; overflow: hidden; text-overflow: ellipsis; }
|
|
321
|
+
.bpe-save--muted, .bpe-save--clean { color: var(--bpe-fg-faint); }
|
|
322
|
+
.bpe-save--dirty { color: var(--bpe-warning); background: var(--bpe-bg-muted); }
|
|
323
|
+
.bpe-save--busy { color: var(--bpe-fg-secondary); }
|
|
324
|
+
.bpe-save--error { color: var(--bpe-danger); border-color: var(--bpe-danger); }
|
|
325
|
+
.bpe-save--action { cursor: pointer; }
|
|
326
|
+
.bpe-save--action:hover { background: var(--bpe-bg-subtle); }
|
|
327
|
+
.bpe-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
328
|
+
|
|
329
|
+
.bpe-theme-select__name { max-width: 140px; }
|
|
330
|
+
|
|
331
|
+
.bpe-issues { width: 340px; }
|
|
332
|
+
.bpe-issues__group + .bpe-issues__group { border-top: 1px solid var(--bpe-border); margin-top: 6px; padding-top: 8px; }
|
|
333
|
+
.bpe-issues__head { display: flex; align-items: center; gap: 6px; padding: 2px 10px 0; }
|
|
334
|
+
.bpe-issues__title { font-size: var(--bpe-text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--bpe-fg-secondary); }
|
|
335
|
+
.bpe-issues__blurb { margin: 2px 10px 6px; font-size: var(--bpe-text-xs); color: var(--bpe-fg-faint); line-height: 1.45; }
|
|
336
|
+
.bpe-issues__ok { display: flex; align-items: baseline; gap: 5px; padding: 2px 10px 6px; font-size: var(--bpe-text-xs); color: var(--bpe-fg-faint); flex-wrap: wrap; }
|
|
337
|
+
.bpe-issues__ok strong { color: var(--bpe-fg-secondary); font-weight: 600; }
|
|
338
|
+
.bpe-mode { width: auto; }
|
|
339
|
+
.bpe-mode .bpe-segmented__item { padding: 0 12px; height: 24px; }
|
|
340
|
+
.bpe-zoom { display: inline-flex; align-items: center; gap: 2px; }
|
|
341
|
+
.bpe-zoom__value { min-width: 44px; text-align: center; font-size: var(--bpe-text-sm); font-variant-numeric: tabular-nums; color: var(--bpe-fg-secondary); }
|
|
342
|
+
.bpe-theme-select { display: inline-flex; align-items: center; gap: 6px; height: var(--bpe-control-h); padding: 0 8px 0 6px; border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); background: var(--bpe-bg); font-size: var(--bpe-text-sm); font-weight: 500; }
|
|
343
|
+
.bpe-theme-select:hover { border-color: var(--bpe-border-strong); background: var(--bpe-bg-subtle); }
|
|
344
|
+
.bpe-swatches { display: inline-flex; gap: 2px; }
|
|
345
|
+
.bpe-swatch { width: 10px; height: 10px; border-radius: 3px; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.08); }
|
|
346
|
+
|
|
347
|
+
/* ------------------------------------------------------------------ */
|
|
348
|
+
/* Left panel */
|
|
349
|
+
/* ------------------------------------------------------------------ */
|
|
350
|
+
.bpe-left { grid-area: left; display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--bpe-border); background: var(--bpe-bg); overflow: hidden; }
|
|
351
|
+
.bpe-left__body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
|
|
352
|
+
.bpe-search { position: relative; padding: 8px 10px 6px; }
|
|
353
|
+
.bpe-search svg { position: absolute; left: 18px; top: 50%; transform: translateY(-50%); width: 13px; height: 13px; color: var(--bpe-fg-faint); pointer-events: none; }
|
|
354
|
+
.bpe-search .bpe-input { padding-left: 26px; }
|
|
355
|
+
.bpe-palette__group { padding: 4px 10px 10px; }
|
|
356
|
+
.bpe-palette__title { display: flex; align-items: center; gap: 6px; padding: 8px 2px 6px; font-size: var(--bpe-text-xs); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--bpe-fg-faint); }
|
|
357
|
+
.bpe-palette__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
|
|
358
|
+
.bpe-palette__item { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding: 8px 9px; border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); background: var(--bpe-bg); color: var(--bpe-fg); text-align: left; cursor: grab; user-select: none; transition: border-color var(--bpe-dur) var(--bpe-ease), background var(--bpe-dur) var(--bpe-ease), transform 120ms var(--bpe-ease), box-shadow var(--bpe-dur) var(--bpe-ease); }
|
|
359
|
+
.bpe-palette__item:hover { border-color: var(--bpe-border-strong); background: var(--bpe-bg-subtle); transform: translateY(-1px); box-shadow: var(--bpe-shadow); }
|
|
360
|
+
.bpe-palette__item:active { cursor: grabbing; transform: none; }
|
|
361
|
+
.bpe-palette__item svg { width: 16px; height: 16px; color: var(--bpe-fg-secondary); }
|
|
362
|
+
.bpe-palette__item-name { font-size: var(--bpe-text-sm); font-weight: 500; line-height: 1.2; }
|
|
363
|
+
.bpe-palette__tier { position: absolute; top: 4px; right: 5px; font-size: 8.5px; font-weight: 700; letter-spacing: 0.06em; color: var(--bpe-accent); }
|
|
364
|
+
.bpe-palette__item--locked { opacity: 0.55; cursor: not-allowed; }
|
|
365
|
+
.bpe-palette__item--locked .bpe-palette__tier { color: var(--bpe-fg-faint); }
|
|
366
|
+
.bpe-layouts__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
|
|
367
|
+
.bpe-layout-item { display: flex; flex-direction: column; gap: 6px; padding: 8px; border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); background: var(--bpe-bg); cursor: grab; }
|
|
368
|
+
.bpe-layout-item:hover { border-color: var(--bpe-border-strong); background: var(--bpe-bg-subtle); }
|
|
369
|
+
.bpe-layout-item__cols { display: grid; gap: 3px; height: 22px; }
|
|
370
|
+
.bpe-layout-item__col { background: var(--bpe-bg-muted); border: 1px solid var(--bpe-border-strong); border-radius: 3px; }
|
|
371
|
+
.bpe-layout-item__name { font-size: var(--bpe-text-xs); color: var(--bpe-fg-secondary); font-weight: 500; }
|
|
372
|
+
|
|
373
|
+
.bpe-data-tree { padding: 4px 6px 12px; }
|
|
374
|
+
.bpe-data-source { margin-bottom: 4px; }
|
|
375
|
+
.bpe-data-source__head { display: flex; align-items: center; gap: 6px; width: 100%; height: 28px; padding: 0 6px; border: 0; border-radius: var(--bpe-radius-sm); background: transparent; color: var(--bpe-fg); font-weight: 600; font-size: var(--bpe-text-sm); text-align: left; }
|
|
376
|
+
.bpe-data-source__head:hover { background: var(--bpe-bg-subtle); }
|
|
377
|
+
.bpe-data-source__head svg { width: 13px; height: 13px; color: var(--bpe-fg-faint); }
|
|
378
|
+
.bpe-data-field { display: flex; align-items: center; gap: 6px; width: 100%; height: 26px; padding: 0 6px; border: 0; border-radius: var(--bpe-radius-sm); background: transparent; color: var(--bpe-fg); font-size: var(--bpe-text-sm); text-align: left; cursor: grab; }
|
|
379
|
+
.bpe-data-field:hover { background: var(--bpe-accent-soft); }
|
|
380
|
+
.bpe-data-field__type { margin-left: auto; font-size: 9.5px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--bpe-fg-faint); }
|
|
381
|
+
.bpe-data-field__icon { width: 13px; height: 13px; color: var(--bpe-fg-muted); flex-shrink: 0; }
|
|
382
|
+
.bpe-data-field--group { color: var(--bpe-fg-secondary); cursor: default; }
|
|
383
|
+
.bpe-data-children { padding-left: 14px; border-left: 1px solid var(--bpe-border); margin-left: 12px; }
|
|
384
|
+
|
|
385
|
+
.bpe-layers { padding: 6px 6px 12px; }
|
|
386
|
+
.bpe-layer { display: flex; align-items: center; gap: 5px; height: 26px; padding-right: 4px; border-radius: var(--bpe-radius-sm); color: var(--bpe-fg); font-size: var(--bpe-text-sm); cursor: default; user-select: none; }
|
|
387
|
+
.bpe-layer:hover { background: var(--bpe-bg-subtle); }
|
|
388
|
+
.bpe-layer--selected { background: var(--bpe-accent-soft) !important; color: var(--bpe-accent); }
|
|
389
|
+
.bpe-layer--hover { background: var(--bpe-bg-muted); }
|
|
390
|
+
.bpe-layer { cursor: grab; }
|
|
391
|
+
.bpe-layer:active { cursor: grabbing; }
|
|
392
|
+
/* Row actions stay out of the way until the row is wanted, so the tree still
|
|
393
|
+
reads as a tree rather than as a wall of buttons. */
|
|
394
|
+
.bpe-layer__actions { display: none; margin-left: auto; gap: 0; flex-shrink: 0; }
|
|
395
|
+
.bpe-layer:hover .bpe-layer__actions, .bpe-layer--selected .bpe-layer__actions { display: flex; }
|
|
396
|
+
.bpe-layer__actions .bpe-btn { width: 20px; height: 20px; }
|
|
397
|
+
.bpe-layer__actions .bpe-btn svg { width: 12px; height: 12px; }
|
|
398
|
+
.bpe-layer:hover .bpe-layer__meta, .bpe-layer--selected .bpe-layer__meta { display: none; }
|
|
399
|
+
|
|
400
|
+
.bpe-layer__toggle { display: grid; place-items: center; width: 18px; height: 18px; border: 0; background: transparent; color: var(--bpe-fg-faint); padding: 0; border-radius: 3px; flex-shrink: 0; }
|
|
401
|
+
.bpe-layer__toggle svg { width: 12px; height: 12px; transition: transform var(--bpe-dur) var(--bpe-ease); }
|
|
402
|
+
.bpe-layer__toggle[aria-expanded="false"] svg { transform: rotate(-90deg); }
|
|
403
|
+
.bpe-layer__icon { width: 13px; height: 13px; color: var(--bpe-fg-muted); flex-shrink: 0; }
|
|
404
|
+
.bpe-layer--selected .bpe-layer__icon { color: var(--bpe-accent); }
|
|
405
|
+
.bpe-layer__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
406
|
+
.bpe-layer__meta { font-size: var(--bpe-text-xs); color: var(--bpe-fg-faint); }
|
|
407
|
+
|
|
408
|
+
.bpe-library__item { display: flex; align-items: center; gap: 8px; padding: 8px 10px; margin: 0 8px 6px; border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); cursor: grab; background: var(--bpe-bg); }
|
|
409
|
+
.bpe-library__item:hover { border-color: var(--bpe-border-strong); background: var(--bpe-bg-subtle); }
|
|
410
|
+
.bpe-library__item svg { width: 15px; height: 15px; color: var(--bpe-fg-secondary); }
|
|
411
|
+
.bpe-library__name { font-weight: 500; font-size: var(--bpe-text-sm); }
|
|
412
|
+
.bpe-library__desc { font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); }
|
|
413
|
+
|
|
414
|
+
/* ------------------------------------------------------------------ */
|
|
415
|
+
/* Canvas */
|
|
416
|
+
/* ------------------------------------------------------------------ */
|
|
417
|
+
.bpe-canvas { grid-area: canvas; position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--bpe-bg-canvas); }
|
|
418
|
+
.bpe-canvas__scroll { position: relative; flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; }
|
|
419
|
+
.bpe-canvas__scroll:focus-visible { box-shadow: none; }
|
|
420
|
+
.bpe-canvas__inner { position: relative; padding: 32px 40px 80px; display: flex; flex-direction: column; align-items: center; min-width: min-content; }
|
|
421
|
+
.bpe-pages { position: relative; display: flex; flex-direction: column; transform-origin: top center; }
|
|
422
|
+
.bpe-page-slot { position: relative; box-shadow: var(--bpe-shadow-page); background: #fff; }
|
|
423
|
+
.bpe-page-slot--placeholder { background: #fff; opacity: 0.9; }
|
|
424
|
+
.bpe-page-number { position: absolute; left: 0; top: -20px; font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); font-weight: 500; user-select: none; }
|
|
425
|
+
.bpe-canvas--design .bp-page__region { outline: 1px dashed rgba(59, 91, 219, 0.22); outline-offset: -1px; }
|
|
426
|
+
.bpe-canvas--design .bp-page__region:hover { outline-color: rgba(59, 91, 219, 0.5); }
|
|
427
|
+
.bpe-canvas--design .bp-page__region::before { content: attr(data-region); position: absolute; right: 0; top: -14px; font: 600 9px/1 var(--bpe-font); letter-spacing: 0.08em; text-transform: uppercase; color: rgba(59, 91, 219, 0.55); opacity: 0; transition: opacity var(--bpe-dur); }
|
|
428
|
+
.bpe-canvas--design .bp-page__region:hover::before, .bpe-canvas--design .bp-page__region--active::before { opacity: 1; }
|
|
429
|
+
.bpe-canvas--design .bp-page__footer::before { top: auto; bottom: -14px; }
|
|
430
|
+
.bpe-canvas--design .bp-page__body { outline: 1px dashed transparent; }
|
|
431
|
+
.bpe-canvas--design.bpe-canvas--guides .bp-page__body { outline-color: rgba(0,0,0,0.08); }
|
|
432
|
+
.bpe-canvas--design .bp-node { cursor: default; }
|
|
433
|
+
.bpe-canvas--design .bp-node--text .bp-text, .bpe-canvas--design .bp-heading { cursor: text; }
|
|
434
|
+
.bpe-canvas--design .bp-node[data-editing] > * { visibility: hidden; }
|
|
435
|
+
.bpe-canvas--design a { pointer-events: none; }
|
|
436
|
+
.bpe-canvas--dragging, .bpe-canvas--dragging * { cursor: grabbing !important; user-select: none !important; }
|
|
437
|
+
|
|
438
|
+
/* overlays */
|
|
439
|
+
.bpe-overlay { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
|
|
440
|
+
.bpe-outline { position: absolute; border: 1.5px solid var(--bpe-hover-outline); border-radius: 2px; pointer-events: none; transition: none; }
|
|
441
|
+
.bpe-outline--selected { border-color: var(--bpe-selection); border-width: 2px; box-shadow: 0 0 0 1px rgba(255,255,255,0.7) inset; }
|
|
442
|
+
.bpe-outline--section { border-style: dashed; border-color: rgba(59,91,219,0.35); }
|
|
443
|
+
.bpe-outline__label { position: absolute; left: -2px; top: -20px; display: inline-flex; align-items: center; gap: 4px; height: 18px; padding: 0 6px; border-radius: 4px 4px 0 0; background: var(--bpe-selection); color: #fff; font: 600 10px/1 var(--bpe-font); letter-spacing: 0.02em; white-space: nowrap; }
|
|
444
|
+
.bpe-outline--hover .bpe-outline__label { background: var(--bpe-hover-outline); }
|
|
445
|
+
.bpe-outline__label svg { width: 10px; height: 10px; }
|
|
446
|
+
.bpe-block-toolbar { position: absolute; z-index: 4; display: inline-flex; align-items: center; gap: 2px; padding: 3px; border-radius: 7px; border: 1px solid var(--bpe-border); background: var(--bpe-bg-elevated); box-shadow: var(--bpe-shadow-lg); pointer-events: auto; animation: bpe-pop var(--bpe-dur) var(--bpe-ease); }
|
|
447
|
+
.bpe-block-toolbar .bpe-btn--icon { width: 24px; height: 24px; }
|
|
448
|
+
.bpe-block-toolbar .bpe-btn svg { width: 13px; height: 13px; }
|
|
449
|
+
.bpe-block-toolbar__handle { cursor: grab; }
|
|
450
|
+
.bpe-block-toolbar__handle:active { cursor: grabbing; }
|
|
451
|
+
.bpe-block-toolbar__type { padding: 0 6px 0 4px; font-size: var(--bpe-text-xs); font-weight: 600; color: var(--bpe-fg-secondary); white-space: nowrap; }
|
|
452
|
+
/* The field list offered while a "{{" is open. Positioned in the overlay's
|
|
453
|
+
coordinate space, so it tracks the caret rather than the block. */
|
|
454
|
+
.bpe-suggest { position: absolute; z-index: 40; width: 340px; max-height: 268px; overflow-y: auto; padding: 4px; border-radius: var(--bpe-radius); border: 1px solid var(--bpe-border); background: var(--bpe-bg-elevated); box-shadow: var(--bpe-shadow-lg); font-size: var(--bpe-text-sm); }
|
|
455
|
+
.bpe-suggest__item { display: flex; align-items: center; gap: 7px; min-width: 0; padding: 5px 8px; border-radius: var(--bpe-radius-sm); cursor: pointer; }
|
|
456
|
+
.bpe-suggest__item--active { background: var(--bpe-accent-soft); }
|
|
457
|
+
.bpe-suggest__icon { color: var(--bpe-fg-faint); flex-shrink: 0; }
|
|
458
|
+
.bpe-suggest__item--active .bpe-suggest__icon { color: var(--bpe-accent); }
|
|
459
|
+
.bpe-suggest__label { flex: 1; min-width: 0; color: var(--bpe-fg); }
|
|
460
|
+
.bpe-suggest__expr { flex-shrink: 0; max-width: 45%; color: var(--bpe-fg-faint); font-family: var(--bpe-font-mono); font-size: 10.5px; }
|
|
461
|
+
.bpe-suggest__hint { padding: 6px 8px 3px; color: var(--bpe-fg-faint); font-size: 10.5px; border-top: 1px solid var(--bpe-border); margin-top: 4px; }
|
|
462
|
+
.bpe-suggest__hint kbd { display: inline-block; padding: 0 3px; border: 1px solid var(--bpe-border); border-bottom-width: 2px; border-radius: 3px; font-family: inherit; font-size: 9.5px; }
|
|
463
|
+
|
|
464
|
+
/* Where a click said the next block should go. Quieter than a drop line,
|
|
465
|
+
because it is a standing intention rather than something happening now. */
|
|
466
|
+
.bpe-caret { position: absolute; height: 2px; margin-top: -1px; border-radius: 2px; background: var(--bpe-accent); opacity: 0.85; pointer-events: none; z-index: 4; animation: bpe-caret-blink 1.1s ease-in-out infinite; }
|
|
467
|
+
.bpe-caret::before { content: ""; position: absolute; left: -4px; top: -3px; width: 8px; height: 8px; border-radius: 50%; background: var(--bpe-accent); }
|
|
468
|
+
@keyframes bpe-caret-blink { 0%, 100% { opacity: 0.85; } 50% { opacity: 0.35; } }
|
|
469
|
+
@media (prefers-reduced-motion: reduce) { .bpe-caret { animation: none; } }
|
|
470
|
+
|
|
471
|
+
.bpe-drop-line { position: absolute; height: 3px; margin-top: -1.5px; border-radius: 2px; background: var(--bpe-drop); box-shadow: 0 0 0 1px rgba(255,255,255,0.8), 0 0 8px rgba(16,185,129,0.5); pointer-events: none; z-index: 5; }
|
|
472
|
+
.bpe-drop-line::before, .bpe-drop-line::after { content: ""; position: absolute; top: -3.5px; width: 10px; height: 10px; border-radius: 50%; background: var(--bpe-drop); box-shadow: 0 0 0 2px #fff; }
|
|
473
|
+
.bpe-drop-line::before { left: -5px; }
|
|
474
|
+
.bpe-drop-line::after { right: -5px; }
|
|
475
|
+
.bpe-drop-zone { position: absolute; border: 2px solid var(--bpe-drop); border-radius: 4px; background: rgba(16,185,129,0.06); pointer-events: none; z-index: 4; }
|
|
476
|
+
.bpe-drop-zone--invalid { border-color: var(--bpe-danger); background: var(--bpe-danger-soft); }
|
|
477
|
+
.bpe-drag-ghost { position: fixed; z-index: 2000; pointer-events: none; display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: var(--bpe-radius); background: var(--bpe-fg); color: var(--bpe-bg); font: 500 12px var(--bpe-font); box-shadow: var(--bpe-shadow-lg); transform: translate(12px, 12px); }
|
|
478
|
+
.bpe-drag-ghost svg { width: 14px; height: 14px; }
|
|
479
|
+
.bpe-page-gap { position: absolute; left: 0; right: 0; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity var(--bpe-dur); pointer-events: auto; }
|
|
480
|
+
.bpe-page-gap:hover { opacity: 1; }
|
|
481
|
+
|
|
482
|
+
.bpe-canvas__bar { display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px; border-top: 1px solid var(--bpe-border); background: var(--bpe-bg); font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); }
|
|
483
|
+
.bpe-breadcrumb { display: flex; align-items: center; gap: 2px; min-width: 0; overflow: hidden; }
|
|
484
|
+
.bpe-breadcrumb__item { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 6px; border: 0; border-radius: 4px; background: transparent; color: var(--bpe-fg-muted); font-size: var(--bpe-text-xs); white-space: nowrap; }
|
|
485
|
+
.bpe-breadcrumb__item:hover { background: var(--bpe-bg-muted); color: var(--bpe-fg); }
|
|
486
|
+
.bpe-breadcrumb__item--current { color: var(--bpe-fg); font-weight: 600; }
|
|
487
|
+
.bpe-breadcrumb__sep { color: var(--bpe-fg-faint); }
|
|
488
|
+
.bpe-canvas__bar-end { margin-left: auto; display: flex; align-items: center; gap: 8px; }
|
|
489
|
+
|
|
490
|
+
/* inline editor */
|
|
491
|
+
.bpe-inline-editor { position: absolute; z-index: 6; outline: none; }
|
|
492
|
+
.bpe-inline-editor .ProseMirror { outline: none; white-space: pre-wrap; word-wrap: break-word; min-height: 1em; }
|
|
493
|
+
.bpe-inline-editor .ProseMirror p { margin: 0; }
|
|
494
|
+
.bpe-inline-editor .ProseMirror ul, .bpe-inline-editor .ProseMirror ol { margin: 0; padding-left: 1.4em; }
|
|
495
|
+
.bpe-inline-editor .ProseMirror .bp-token { display: inline; padding: 0 5px; margin: 0 1px; border-radius: 4px; background: var(--bpe-token-bg); color: var(--bpe-token); font-size: 0.92em; font-weight: 500; white-space: nowrap; user-select: none; }
|
|
496
|
+
.bpe-inline-editor .ProseMirror .bp-token.ProseMirror-selectednode { outline: 2px solid var(--bpe-accent); }
|
|
497
|
+
.bpe-inline-editor .ProseMirror-gapcursor { display: none; }
|
|
498
|
+
.bpe-inline-editor__frame { position: absolute; inset: -4px; border: 1.5px solid var(--bpe-accent); border-radius: 3px; pointer-events: none; }
|
|
499
|
+
.bpe-bubble { position: absolute; z-index: 7; display: inline-flex; align-items: center; gap: 2px; padding: 3px; border-radius: 8px; border: 1px solid var(--bpe-border); background: var(--bpe-bg-elevated); box-shadow: var(--bpe-shadow-lg); animation: bpe-pop var(--bpe-dur) var(--bpe-ease); }
|
|
500
|
+
.bpe-bubble .bpe-btn--icon { width: 26px; height: 26px; }
|
|
501
|
+
.bpe-bubble__sep { width: 1px; height: 18px; margin: 0 2px; background: var(--bpe-border); }
|
|
502
|
+
|
|
503
|
+
/* ------------------------------------------------------------------ */
|
|
504
|
+
/* Inspector */
|
|
505
|
+
/* ------------------------------------------------------------------ */
|
|
506
|
+
.bpe-inspector { grid-area: right; display: flex; flex-direction: column; min-height: 0; border-left: 1px solid var(--bpe-border); background: var(--bpe-bg); overflow: hidden; }
|
|
507
|
+
.bpe-inspector__header { display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 12px; border-bottom: 1px solid var(--bpe-border); }
|
|
508
|
+
.bpe-inspector__icon { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 6px; background: var(--bpe-accent-soft); color: var(--bpe-accent); flex-shrink: 0; }
|
|
509
|
+
.bpe-inspector__icon svg { width: 14px; height: 14px; }
|
|
510
|
+
.bpe-inspector__title { font-weight: 600; font-size: var(--bpe-text-md); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
511
|
+
.bpe-inspector__subtitle { font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); }
|
|
512
|
+
.bpe-inspector__body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
|
|
513
|
+
.bpe-inspector__actions { margin-left: auto; display: flex; gap: 2px; }
|
|
514
|
+
.bpe-spacing-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; }
|
|
515
|
+
.bpe-spacing-grid .bpe-input { padding: 0 4px; text-align: center; }
|
|
516
|
+
.bpe-spacing-grid__lbl { font-size: 9px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--bpe-fg-faint); text-align: center; margin-top: 2px; }
|
|
517
|
+
.bpe-color-btn { display: inline-flex; align-items: center; gap: 6px; height: var(--bpe-control-h); width: 100%; padding: 0 8px 0 6px; border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); background: var(--bpe-bg); font-size: var(--bpe-text-sm); text-align: left; }
|
|
518
|
+
.bpe-color-btn:hover { border-color: var(--bpe-border-strong); }
|
|
519
|
+
.bpe-color-btn__swatch { width: 16px; height: 16px; border-radius: 4px; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12); flex-shrink: 0; background-image: linear-gradient(45deg, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%), linear-gradient(45deg, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%); background-size: 8px 8px; background-position: 0 0, 4px 4px; }
|
|
520
|
+
.bpe-color-btn__swatch::after { content: ""; display: block; width: 100%; height: 100%; border-radius: 4px; background: var(--c, transparent); }
|
|
521
|
+
.bpe-color-btn__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
522
|
+
.bpe-color-popover { width: 236px; }
|
|
523
|
+
.bpe-color-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px; padding: 4px; }
|
|
524
|
+
.bpe-color-grid__item { position: relative; width: 24px; height: 24px; border-radius: 6px; border: 1px solid rgba(0,0,0,0.08); background: var(--c); padding: 0; }
|
|
525
|
+
.bpe-color-grid__item[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--bpe-bg), 0 0 0 4px var(--bpe-accent); }
|
|
526
|
+
.bpe-color-token { display: flex; align-items: center; gap: 8px; width: 100%; height: 26px; padding: 0 6px; border: 0; border-radius: 4px; background: transparent; font-size: var(--bpe-text-sm); text-align: left; color: var(--bpe-fg); }
|
|
527
|
+
.bpe-color-token:hover { background: var(--bpe-bg-muted); }
|
|
528
|
+
.bpe-color-token[aria-pressed="true"] { background: var(--bpe-accent-soft); color: var(--bpe-accent); }
|
|
529
|
+
.bpe-color-token__sw { width: 14px; height: 14px; border-radius: 4px; background: var(--c); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.1); }
|
|
530
|
+
.bpe-color-token__val { margin-left: auto; font-family: var(--bpe-font-mono); font-size: 10px; color: var(--bpe-fg-faint); }
|
|
531
|
+
.bpe-binding { display: flex; align-items: center; gap: 4px; width: 100%; min-width: 0; }
|
|
532
|
+
/* The image field's file input is opened by the button beside it. Hidden with
|
|
533
|
+
clip rather than display:none so the browser still counts it as a real
|
|
534
|
+
control and the button's click reaches it. */
|
|
535
|
+
.bpe-image__file { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
|
|
536
|
+
.bpe-binding__btn { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; height: var(--bpe-control-h); padding: 0 8px; border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); background: var(--bpe-bg); text-align: left; font-size: var(--bpe-text-sm); }
|
|
537
|
+
.bpe-binding__btn:hover { border-color: var(--bpe-border-strong); }
|
|
538
|
+
.bpe-binding__btn--empty { color: var(--bpe-fg-faint); }
|
|
539
|
+
.bpe-binding__btn svg { width: 13px; height: 13px; flex-shrink: 0; color: var(--bpe-fg-muted); }
|
|
540
|
+
.bpe-expr { font-family: var(--bpe-font-mono); font-size: 11px; }
|
|
541
|
+
.bpe-picker { width: 300px; max-height: 380px; display: flex; flex-direction: column; padding: 0; overflow: hidden; }
|
|
542
|
+
.bpe-picker__search { padding: 8px; border-bottom: 1px solid var(--bpe-border); }
|
|
543
|
+
.bpe-picker__list { flex: 1; overflow-y: auto; padding: 4px; }
|
|
544
|
+
.bpe-picker__foot { display: flex; gap: 6px; align-items: center; padding: 8px; border-top: 1px solid var(--bpe-border); }
|
|
545
|
+
.bpe-picker__foot .bpe-input { flex: 1; }
|
|
546
|
+
.bpe-picker__group { padding: 6px 6px 2px; font-size: var(--bpe-text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--bpe-fg-faint); }
|
|
547
|
+
.bpe-cond { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
548
|
+
.bpe-cond__rule { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px; min-width: 0; padding: 6px; border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); background: var(--bpe-bg-subtle); }
|
|
549
|
+
.bpe-cond__row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; min-width: 0; }
|
|
550
|
+
.bpe-cond__op { display: flex; align-items: center; gap: 6px; }
|
|
551
|
+
.bpe-cond__group { padding: 6px; border: 1px dashed var(--bpe-border-strong); border-radius: var(--bpe-radius); }
|
|
552
|
+
.bpe-list-editor { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
553
|
+
.bpe-list-editor__item { border: 1px solid var(--bpe-border); border-radius: var(--bpe-radius); background: var(--bpe-bg-subtle); }
|
|
554
|
+
.bpe-list-editor__head { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; height: 28px; padding: 0 4px 0 8px; font-size: var(--bpe-text-sm); font-weight: 500; }
|
|
555
|
+
.bpe-list-editor__head .bpe-truncate { flex: 1 1 0; min-width: 0; }
|
|
556
|
+
.bpe-list-editor__item { min-width: 0; }
|
|
557
|
+
.bpe-list-editor__body { padding: 6px 8px 8px; border-top: 1px solid var(--bpe-border); display: flex; flex-direction: column; gap: 6px; }
|
|
558
|
+
.bpe-list-editor__drag { cursor: grab; color: var(--bpe-fg-faint); display: inline-flex; }
|
|
559
|
+
.bpe-issue { display: flex; gap: 8px; align-items: flex-start; width: 100%; padding: 6px 8px; border: 0; border-radius: var(--bpe-radius-sm); background: transparent; text-align: left; font-size: var(--bpe-text-sm); color: var(--bpe-fg); }
|
|
560
|
+
.bpe-issue:hover { background: var(--bpe-bg-muted); }
|
|
561
|
+
.bpe-issue svg { width: 13px; height: 13px; flex-shrink: 0; margin-top: 2px; }
|
|
562
|
+
.bpe-issue--error svg { color: var(--bpe-danger); }
|
|
563
|
+
.bpe-issue--warning svg { color: var(--bpe-warning); }
|
|
564
|
+
.bpe-issue--info svg { color: var(--bpe-fg-muted); }
|
|
565
|
+
.bpe-issue__meta { display: block; margin-top: 2px; font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); }
|
|
566
|
+
.bpe-text-style-row { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 6px; }
|
|
567
|
+
.bpe-text-style-preview { font-weight: 600; }
|
|
568
|
+
.bpe-doc-styles__item { display: flex; align-items: center; gap: 8px; width: 100%; height: 32px; padding: 0 12px; border: 0; background: transparent; text-align: left; color: var(--bpe-fg); font-size: var(--bpe-text-sm); }
|
|
569
|
+
.bpe-doc-styles__item:hover { background: var(--bpe-bg-subtle); }
|
|
570
|
+
.bpe-doc-styles__sample { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
571
|
+
.bpe-doc-styles__id { font-family: var(--bpe-font-mono); font-size: 10px; color: var(--bpe-fg-faint); }
|
|
572
|
+
.bpe-preview-bar { display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bpe-accent-soft); color: var(--bpe-accent); font-size: var(--bpe-text-sm); font-weight: 500; border-bottom: 1px solid var(--bpe-border); }
|
|
573
|
+
.bpe-toast { position: absolute; left: 50%; bottom: 44px; transform: translateX(-50%); z-index: 20; display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: var(--bpe-radius); background: var(--bpe-fg); color: var(--bpe-bg); font-size: var(--bpe-text-sm); box-shadow: var(--bpe-shadow-lg); animation: bpe-pop var(--bpe-dur) var(--bpe-ease); }
|
|
574
|
+
.bpe-toast svg { width: 14px; height: 14px; }
|
|
575
|
+
.bpe-portal { position: absolute; width: 0; height: 0; overflow: visible; }
|
|
576
|
+
.bpe-scope { font-family: var(--bpe-font); }
|
|
577
|
+
|
|
578
|
+
.bpe-pager { display: inline-flex; align-items: center; gap: 2px; }
|
|
579
|
+
.bpe-pager__label { min-width: 92px; text-align: center; font-variant-numeric: tabular-nums; }
|
|
580
|
+
|
|
581
|
+
/* Panel resize handles sit on the boundary rather than in the grid, so the
|
|
582
|
+
three-column shell stays three columns and the handles stay draggable even
|
|
583
|
+
when a panel is scrolled. */
|
|
584
|
+
.bpe-resizer { position: absolute; top: var(--bpe-toolbar-h); bottom: 0; width: 9px; cursor: col-resize; z-index: 6; background: transparent; touch-action: none; }
|
|
585
|
+
.bpe-resizer--left { left: var(--bpe-panel-w); margin-left: -4px; }
|
|
586
|
+
.bpe-resizer--right { right: var(--bpe-inspector-w); margin-right: -4px; }
|
|
587
|
+
.bpe-resizer::after { content: ""; position: absolute; inset: 0 3px; border-radius: 2px; background: transparent; transition: background var(--bpe-dur) var(--bpe-ease); }
|
|
588
|
+
.bpe-resizer:hover::after, .bpe-resizer:focus-visible::after { background: var(--bpe-accent); }
|
|
589
|
+
.bpe-resizer:focus-visible { outline: none; }
|
|
590
|
+
|
|
591
|
+
/* A long label stops being a column and becomes a line of its own. */
|
|
592
|
+
.bpe-field--stacked .bpe-field__label { white-space: normal; overflow: visible; }
|
|
593
|
+
|
|
594
|
+
.bpe-block-toolbar__edit { font-weight: 500; }
|
|
595
|
+
|
|
596
|
+
.bpe-legend { width: 340px; }
|
|
597
|
+
.bpe-legend__body { padding: 12px 14px 10px; }
|
|
598
|
+
.bpe-legend__title { margin: 0 0 6px; font-size: var(--bpe-text-md); font-weight: 600; }
|
|
599
|
+
.bpe-legend__intro { margin: 0 0 10px; font-size: var(--bpe-text-xs); color: var(--bpe-fg-secondary); line-height: 1.5; }
|
|
600
|
+
.bpe-legend__list { margin: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
601
|
+
.bpe-legend__entry { display: flex; gap: 9px; align-items: flex-start; }
|
|
602
|
+
.bpe-legend__swatch { flex: 0 0 auto; display: grid; place-items: center; min-width: 22px; padding-top: 1px; color: var(--bpe-fg-muted); }
|
|
603
|
+
.bpe-legend__entry dt { font-size: var(--bpe-text-xs); font-weight: 600; color: var(--bpe-fg); }
|
|
604
|
+
.bpe-legend__entry dd { margin: 1px 0 0; font-size: var(--bpe-text-xs); color: var(--bpe-fg-muted); line-height: 1.45; }
|
|
605
|
+
.bpe-legend__token { font-size: 9px; padding: 1px 4px; }
|
|
606
|
+
.bpe-legend__foot { margin: 10px 0 0; padding-top: 8px; border-top: 1px solid var(--bpe-border); font-size: var(--bpe-text-xs); color: var(--bpe-fg-faint); }
|
|
607
|
+
|
|
608
|
+
/* ===================================================================
|
|
609
|
+
Narrow — the designer in a container too small for three columns.
|
|
610
|
+
|
|
611
|
+
Set by the shell from the root element's own width, not a media query:
|
|
612
|
+
the designer is embedded, so a phone and a narrow pane in a wide page
|
|
613
|
+
are the same problem and the window answers neither. Below the
|
|
614
|
+
breakpoint the panels stop being columns and become drawers over the
|
|
615
|
+
canvas, because 272 + 296 of panel leaves a phone about forty pixels
|
|
616
|
+
of page — which is not a cramped canvas, it is no canvas.
|
|
617
|
+
=================================================================== */
|
|
618
|
+
|
|
619
|
+
/* Two classes deliberately: `.bpe--no-left.bpe--no-right` is also two, and a
|
|
620
|
+
single-class rule would lose to it exactly when both panels are shut —
|
|
621
|
+
which on a phone is the normal state. */
|
|
622
|
+
.bpe.bpe--narrow { grid-template-columns: minmax(0, 1fr); grid-template-areas: "toolbar" "canvas"; }
|
|
623
|
+
|
|
624
|
+
/* Both panels occupy the canvas cell rather than one of their own, so the
|
|
625
|
+
canvas keeps its full width whether a drawer is open or not — nothing
|
|
626
|
+
reflows underneath when one opens, which is what makes it a drawer
|
|
627
|
+
rather than a column that happens to overlap. */
|
|
628
|
+
.bpe--narrow .bpe-left, .bpe--narrow .bpe-inspector {
|
|
629
|
+
grid-area: canvas;
|
|
630
|
+
z-index: 20;
|
|
631
|
+
width: min(88%, 360px);
|
|
632
|
+
max-width: 100%;
|
|
633
|
+
box-shadow: 0 24px 48px -24px rgba(0, 0, 0, 0.45);
|
|
634
|
+
animation: bpe-drawer-in 180ms var(--bpe-ease) both;
|
|
635
|
+
}
|
|
636
|
+
.bpe--narrow .bpe-left { justify-self: start; border-right: 1px solid var(--bpe-border); }
|
|
637
|
+
.bpe--narrow .bpe-inspector { justify-self: end; border-left: 1px solid var(--bpe-border); }
|
|
638
|
+
@keyframes bpe-drawer-in { from { transform: translateX(var(--bpe-drawer-from, -8%)); opacity: 0; } to { transform: none; opacity: 1; } }
|
|
639
|
+
.bpe--narrow .bpe-inspector { --bpe-drawer-from: 8%; }
|
|
640
|
+
@media (prefers-reduced-motion: reduce) { .bpe--narrow .bpe-left, .bpe--narrow .bpe-inspector { animation: none; } }
|
|
641
|
+
|
|
642
|
+
/* Tapping the canvas beside an open drawer closes it. A button rather than
|
|
643
|
+
a div so it is reachable by keyboard and announces itself; it sits under
|
|
644
|
+
the drawer and over everything else. */
|
|
645
|
+
.bpe-scrim { grid-area: canvas; z-index: 15; border: 0; padding: 0; background: rgba(23, 21, 17, 0.32); cursor: default; animation: bpe-fade-in 180ms var(--bpe-ease) both; }
|
|
646
|
+
@keyframes bpe-fade-in { from { opacity: 0; } to { opacity: 1; } }
|
|
647
|
+
@media (prefers-reduced-motion: reduce) { .bpe-scrim { animation: none; } }
|
|
648
|
+
|
|
649
|
+
/* The page needs the room more than the margin around it does. */
|
|
650
|
+
.bpe--narrow .bpe-canvas__inner { padding: 12px 12px 48px; }
|
|
651
|
+
/* Touch targets, and a scroll that does not fight the page it is embedded in. */
|
|
652
|
+
.bpe--narrow .bpe-btn { min-height: 32px; }
|
|
653
|
+
.bpe--narrow .bpe-canvas__scroll { -webkit-overflow-scrolling: touch; }
|
|
654
|
+
|
|
655
|
+
/* The toolbar's three tracks assume a row wide enough for all of them. On a
|
|
656
|
+
phone the centre group alone — Design/Preview plus the zoom controls, both
|
|
657
|
+
of which refuse to wrap — takes the whole width, leaving the leading and
|
|
658
|
+
trailing tracks measuring zero and their contents drawn off the edge. So
|
|
659
|
+
narrow, it wraps: the groups keep their order and their contents, and the
|
|
660
|
+
toolbar takes the two rows it needs. `.bpe` gives it an auto row to grow
|
|
661
|
+
into rather than the fixed height a single row assumed. */
|
|
662
|
+
.bpe.bpe--narrow { grid-template-rows: auto 1fr; }
|
|
663
|
+
.bpe--narrow .bpe-toolbar { display: flex; flex-wrap: wrap; justify-content: space-between; row-gap: 6px; padding: 6px 8px; }
|
|
664
|
+
.bpe--narrow .bpe-toolbar__group--start { overflow: visible; flex: 1 1 auto; }
|
|
665
|
+
.bpe--narrow .bpe-toolbar__group--centre { order: 3; flex: 1 0 100%; justify-content: center; }
|
|
666
|
+
.bpe--narrow .bpe-toolbar__group--end { flex: 0 0 auto; }
|
|
667
|
+
/* The report name gives up its fixed width first; it is the one thing in the
|
|
668
|
+
leading group that can shrink without losing a control. */
|
|
669
|
+
.bpe--narrow .bpe-toolbar__name { width: auto; min-width: 80px; max-width: none; flex: 1 1 80px; }
|
|
670
|
+
/* A backstop for the very narrowest: if the mode switch and the zoom controls
|
|
671
|
+
still will not sit on one row, they take two rather than one of them being
|
|
672
|
+
drawn off the edge. */
|
|
673
|
+
.bpe--narrow .bpe-toolbar__group--centre { flex-wrap: wrap; white-space: normal; row-gap: 6px; }
|