@21stware/rpui 0.2.1 → 0.3.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/dist/rpui.js CHANGED
@@ -38,12 +38,12 @@ function resolveHeight(el, fallback) {
38
38
  function isTopAnnotation(node) {
39
39
  if (!(node instanceof HTMLElement)) return false;
40
40
  const tag = node.tagName.toLowerCase();
41
- return tag === "rp-annotation" || tag === "proto-annotation";
41
+ return tag === "annotation-el" || tag === "annotation-el";
42
42
  }
43
43
  function isViewportNode(node) {
44
44
  if (!(node instanceof HTMLElement)) return false;
45
45
  const tag = node.tagName.toLowerCase();
46
- return tag === "rp-viewport" || tag === "snap-viewport";
46
+ return tag === "viewport-el" || tag === "viewport-el";
47
47
  }
48
48
  function define(name, ctor) {
49
49
  if (customElements.get(name)) return;
@@ -51,410 +51,591 @@ function define(name, ctor) {
51
51
  };
52
52
  customElements.define(name, Alias);
53
53
  }
54
+ const PRIMITIVES = [
55
+ // layout
56
+ "viewport",
57
+ "layout",
58
+ "panel",
59
+ "sidebar",
60
+ "logo",
61
+ "split-pane",
62
+ "divider",
63
+ "spacer",
64
+ // controls
65
+ "search",
66
+ "input",
67
+ "textarea",
68
+ "select",
69
+ "button",
70
+ "button-group",
71
+ "checkbox",
72
+ "radio",
73
+ "toggle",
74
+ "form",
75
+ "form-item",
76
+ "date-picker",
77
+ "upload",
78
+ "image-placeholder",
79
+ "progress",
80
+ "slider",
81
+ "range",
82
+ "number-input",
83
+ "rating",
84
+ "pin-input",
85
+ "color-swatch",
86
+ "autocomplete",
87
+ // navigation
88
+ "badge",
89
+ "avatar",
90
+ "list",
91
+ "list-item",
92
+ "tabs",
93
+ "tab",
94
+ "pagination",
95
+ "steps",
96
+ "breadcrumb",
97
+ "segmented",
98
+ "command-palette",
99
+ "context-menu",
100
+ "menu",
101
+ "menu-item",
102
+ "toc",
103
+ "kbd",
104
+ // data display
105
+ "table",
106
+ "table-row",
107
+ "bulk-action-bar",
108
+ "empty",
109
+ "loading",
110
+ "alert",
111
+ "toast",
112
+ "dropdown",
113
+ "popover",
114
+ "tooltip",
115
+ "modal",
116
+ "drawer",
117
+ "card",
118
+ "stat-card",
119
+ "tag",
120
+ "chip",
121
+ "tree",
122
+ "tree-item",
123
+ "timeline",
124
+ "timeline-item",
125
+ "calendar",
126
+ "kanban",
127
+ "kanban-column",
128
+ "kanban-card",
129
+ "code-block",
130
+ "diff",
131
+ "image-grid",
132
+ "key-value",
133
+ "kv-row",
134
+ "accordion",
135
+ "accordion-item",
136
+ "banner",
137
+ "skeleton",
138
+ "countdown",
139
+ "result",
140
+ "permission-gate",
141
+ "quota-bar",
142
+ "api-key",
143
+ "audit-row",
144
+ "workflow-node",
145
+ // iOS
146
+ "ios-navbar",
147
+ "ios-tabbar",
148
+ "ios-list",
149
+ "ios-list-item",
150
+ "ios-action-sheet",
151
+ "ios-alert",
152
+ "ios-switch",
153
+ "ios-segmented",
154
+ "ios-button",
155
+ "ios-search",
156
+ "ios-stepper",
157
+ // macOS
158
+ "macos-window",
159
+ "macos-toolbar",
160
+ "macos-menubar",
161
+ "macos-sidebar",
162
+ "macos-source-item",
163
+ "macos-segmented",
164
+ "macos-popover",
165
+ "macos-sheet",
166
+ "macos-stepper",
167
+ "macos-disclosure",
168
+ "macos-table",
169
+ // agent / conversational UI
170
+ "chat",
171
+ "user-message",
172
+ "assistant-message",
173
+ "system-message",
174
+ "tool-call",
175
+ "agent-output",
176
+ "reasoning",
177
+ "message-actions",
178
+ "suggestions",
179
+ "typing",
180
+ "composer",
181
+ "citation",
182
+ "token-usage"
183
+ ];
184
+ function primitiveComponentTag(lang) {
185
+ return lang.includes("-") ? lang : `${lang}-el`;
186
+ }
187
+ const EXPLICIT = {
188
+ // canvas
189
+ page: "page-el",
190
+ view: "main-view",
191
+ annotation: "annotation-el",
192
+ enum: "enum-el",
193
+ "enum-item": "enum-item",
194
+ viewport: "viewport-el",
195
+ // curated primitive rename
196
+ navigator: "navbar-el"
197
+ };
198
+ const LANG_TO_COMPONENT = (() => {
199
+ const map = {};
200
+ for (const lang of PRIMITIVES) map[lang] = primitiveComponentTag(lang);
201
+ for (const [lang, comp] of Object.entries(EXPLICIT)) map[lang] = comp;
202
+ return map;
203
+ })();
204
+ (() => {
205
+ const map = {};
206
+ for (const [lang, comp] of Object.entries(LANG_TO_COMPONENT)) map[comp] = lang;
207
+ return map;
208
+ })();
209
+ function toComponentTag(tag) {
210
+ return LANG_TO_COMPONENT[tag.toLowerCase()] ?? tag;
211
+ }
212
+ function expandSelfClosing(source) {
213
+ return source.replace(
214
+ /<([a-zA-Z][\w:-]*)((?:"[^"]*"|'[^']*'|[^>"'])*?)\/>/g,
215
+ (_m, tag, attrs) => `<${tag}${attrs}></${tag}>`
216
+ );
217
+ }
218
+ function rewriteTags(source) {
219
+ return source.replace(
220
+ /<(\/?)([a-zA-Z][\w:-]*)((?:"[^"]*"|'[^']*'|[^>])*)>/g,
221
+ (_m, slash, tag, rest) => `<${slash}${toComponentTag(tag)}${rest}>`
222
+ );
223
+ }
224
+ function normalize(source) {
225
+ return rewriteTags(expandSelfClosing(source.trim()));
226
+ }
227
+ function parseToPage(source) {
228
+ const holder = document.createElement("div");
229
+ holder.innerHTML = normalize(source);
230
+ const root = holder.querySelector("page-el") ?? holder.firstElementChild;
231
+ if (!root) throw new Error("RPML parse error: no <page> root element found");
232
+ return root;
233
+ }
54
234
  const RPUI_STYLE_ID = "rpui-runtime-style";
55
235
  const style = `
56
236
  :root { --rp-bg:#f0f2f5; --rp-surface:#fff; --rp-surface-soft:#f9fafb; --rp-text:#111827; --rp-muted:#6b7280; --rp-border:#e5e7eb; --rp-border-strong:#d1d5db; --rp-primary:#2563eb; --rp-success:#059669; --rp-warning:#d97706; --rp-danger:#dc2626; --rp-purple:#7c3aed; --rp-radius-sm:4px; --rp-radius-md:8px; --rp-radius-lg:12px; --rp-shadow:0 8px 28px rgba(15,23,42,.08); --rp-font:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; }
57
237
  * { box-sizing:border-box; }
58
238
  body { margin:0; font-family:var(--rp-font); color:var(--rp-text); background:var(--rp-bg); }
59
239
  .rp-icon { display:inline-block; flex:0 0 auto; vertical-align:-0.16em; }
60
- rp-page, proto-page { display:block; min-height:100vh; padding:32px 40px; overflow:auto; }
61
- .rp-page-shell { display:grid; grid-template-columns:max-content max-content; gap:24px; min-height:100vh; align-items:start; }
62
- .rp-page-main { display:flex; flex-direction:column; min-width:0; overflow:visible; }
63
- .rp-page-header { flex:0 0 auto; width:fit-content; max-width:none; margin:0 0 22px; }
64
- .rp-page-title-row { display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; }
65
- .rp-page-title { margin:0; font-size:28px; line-height:1.2; letter-spacing:-.02em; }
66
- .rp-page-route { font-size:13px; color:var(--rp-muted); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; background:rgba(255,255,255,.7); border:1px solid var(--rp-border); border-radius:999px; padding:3px 9px; }
67
- .rp-page-description { margin:10px 0 0; color:#374151; line-height:1.6; font-size:14px; }
68
- .rp-page-body { flex:0 1 auto; display:block; width:fit-content; max-width:100%; min-height:0; overflow:visible; }
69
- .rp-annotation-pane { min-width:380px; max-width:680px; position:sticky; top:0; height:100vh; overflow-y:auto; overflow-x:auto; padding:0 0 48px 0; align-self:start; }
70
- .rp-annotation-pane-inner { padding:4px 12px 24px 6px; }
71
- rp-main-view, proto-main-view { display:block; width:fit-content; margin:0 0 28px; position:relative; }
240
+ page-el, page-el { display:block; min-height:100vh; padding:32px 40px; overflow:auto; }
241
+ .page-el-shell { display:grid; grid-template-columns:max-content max-content; gap:24px; min-height:100vh; align-items:start; }
242
+ .page-el-main { display:flex; flex-direction:column; min-width:0; overflow:visible; }
243
+ .page-el-header { flex:0 0 auto; width:fit-content; max-width:none; margin:0 0 22px; }
244
+ .page-el-title-row { display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; }
245
+ .page-el-title { margin:0; font-size:28px; line-height:1.2; letter-spacing:-.02em; }
246
+ .page-el-route { font-size:13px; color:var(--rp-muted); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; background:rgba(255,255,255,.7); border:1px solid var(--rp-border); border-radius:999px; padding:3px 9px; }
247
+ .page-el-description { margin:10px 0 0; color:#374151; line-height:1.6; font-size:14px; }
248
+ .page-el-body { flex:0 1 auto; display:block; width:fit-content; max-width:100%; min-height:0; overflow:visible; }
249
+ .annotation-el-pane { min-width:380px; max-width:680px; position:sticky; top:0; height:100vh; overflow-y:auto; overflow-x:auto; padding:0 0 48px 0; align-self:start; }
250
+ .annotation-el-pane-inner { padding:4px 12px 24px 6px; }
251
+ main-view, main-view { display:block; width:fit-content; margin:0 0 28px; position:relative; }
72
252
  .rp-main-shell { position:relative; overflow:visible; border:1px solid var(--rp-border-strong); border-radius:var(--rp-radius-md); background:var(--rp-surface); box-shadow:var(--rp-shadow); }
73
253
  .rp-main-stage-clip { overflow:hidden; border-radius:var(--rp-radius-md); }
74
254
  .rp-main-stage { position:relative; transform-origin:top left; background:var(--rp-surface); }
75
255
  .rp-pin { position:absolute; z-index:20; display:grid; place-items:center; width:24px; height:24px; color:#fff; font-size:11px; font-weight:700; background:var(--rp-primary); border-radius:50% 50% 50% 0; transform:translate(-6px,-6px) rotate(-45deg); box-shadow:0 2px 8px rgba(37,99,235,.25); cursor:pointer; }
76
256
  .rp-pin > span { transform:rotate(45deg); }
77
257
  .rp-pin:hover { opacity:0.85; }
78
- rp-annotation, proto-annotation { display:block; width:fit-content; max-width:980px; margin:14px 0; line-height:1.65; color:#1f2937; font-size:14px; }
79
- rp-annotation rp-annotation, proto-annotation proto-annotation, rp-annotation proto-annotation, proto-annotation rp-annotation { margin:10px 0 8px 22px; }
80
- .rp-annotation-head { display:flex; align-items:center; gap:8px; margin:0 0 4px; width:fit-content; }
81
- .rp-annotation-title { font-weight:700; color:#111827; }
82
- .rp-annotation-marker { display:inline-grid; place-items:center; flex:0 0 auto; color:#fff; font-size:10px; font-weight:700; line-height:1; }
83
- .rp-annotation-marker.drop { width:22px; height:22px; background:var(--rp-primary); border-radius:50% 50% 50% 0; transform:rotate(-45deg); }
84
- .rp-annotation-marker.drop > span { transform:rotate(45deg); }
85
- .rp-annotation-marker.circle { width:16px; height:16px; background:var(--rp-purple); border-radius:50%; }
86
- .rp-annotation-marker.triangle { width:18px; height:16px; background:var(--rp-success); clip-path:polygon(50% 0, 100% 100%, 0 100%); }
87
- .rp-annotation-marker.triangle > span { transform:translateY(2px); font-size:9px; }
88
- .rp-annotation-body { display:block; position:relative; width:fit-content; max-width:920px; }
258
+ annotation-el, annotation-el { display:block; width:fit-content; max-width:980px; margin:14px 0; line-height:1.65; color:#1f2937; font-size:14px; }
259
+ annotation-el annotation-el, annotation-el annotation-el, annotation-el annotation-el, annotation-el annotation-el { margin:10px 0 8px 22px; }
260
+ .annotation-el-head { display:flex; align-items:center; gap:8px; margin:0 0 4px; width:fit-content; }
261
+ .annotation-el-title { font-weight:700; color:#111827; }
262
+ .annotation-el-marker { display:inline-grid; place-items:center; flex:0 0 auto; color:#fff; font-size:10px; font-weight:700; line-height:1; }
263
+ .annotation-el-marker.drop { width:22px; height:22px; background:var(--rp-primary); border-radius:50% 50% 50% 0; transform:rotate(-45deg); }
264
+ .annotation-el-marker.drop > span { transform:rotate(45deg); }
265
+ .annotation-el-marker.circle { width:16px; height:16px; background:var(--rp-purple); border-radius:50%; }
266
+ .annotation-el-marker.triangle { width:18px; height:16px; background:var(--rp-success); clip-path:polygon(50% 0, 100% 100%, 0 100%); }
267
+ .annotation-el-marker.triangle > span { transform:translateY(2px); font-size:9px; }
268
+ .annotation-el-body { display:block; position:relative; width:fit-content; max-width:920px; }
89
269
  .rp-pin-slice { width:18px; height:18px; font-size:10px; box-shadow:0 1px 5px rgba(37,99,235,.3); }
90
- .rp-annotation-body > :not(rp-annotation):not(proto-annotation):not(rp-enum):not(proto-enum) { max-width:820px; }
91
- .rp-annotation-pane rp-annotation, .rp-annotation-pane proto-annotation { max-width:none; }
92
- .rp-annotation-pane .rp-annotation-body { max-width:none; }
93
- .rp-annotation-pane .rp-annotation-body > :not(rp-annotation):not(proto-annotation):not(rp-enum):not(proto-enum) { max-width:420px; }
94
- .rp-annotation-body p { margin:0 0 8px; }
95
- rp-enum, proto-enum { display:flex; align-items:flex-start; flex-wrap:wrap; gap:10px; width:fit-content; margin:8px 0 12px; }
96
- .rp-annotation-pane rp-enum, .rp-annotation-pane proto-enum { flex-wrap:wrap; }
97
- rp-enum-item, proto-enum-item { display:block; flex:0 0 auto; width:fit-content; min-width:180px; max-width:600px; border:1px solid #f0f0f0; border-radius:var(--rp-radius-md); background:#fff; overflow:hidden; }
98
- .rp-enum-label { display:flex; align-items:flex-start; gap:6px; padding:5px 9px 4px; font-size:12px; font-weight:650; color:#374151; }
99
- .rp-enum-index { display:inline-grid; place-items:center; min-width:16px; height:16px; padding:0 4px; background:#111827; color:#fff; font-size:10px; font-weight:750; border-radius:3px; flex:0 0 auto; margin-top:1px; }
100
- .rp-enum-label-text { display:block; }
101
- .rp-enum-description { display:block; margin-top:2px; font-size:11px; line-height:1.35; font-weight:400; color:var(--rp-muted); }
102
- .rp-enum-content { display:block; width:fit-content; padding:8px; }
103
- .rp-annotation-title { font-weight:700; color:#111827; cursor:pointer; }
104
- .rp-annotation-title:hover { color:var(--rp-primary); }
270
+ .annotation-el-body > :not(annotation-el):not(annotation-el):not(enum-el):not(enum-el) { max-width:820px; }
271
+ .annotation-el-pane annotation-el, .annotation-el-pane annotation-el { max-width:none; }
272
+ .annotation-el-pane .annotation-el-body { max-width:none; }
273
+ .annotation-el-pane .annotation-el-body > :not(annotation-el):not(annotation-el):not(enum-el):not(enum-el) { max-width:420px; }
274
+ .annotation-el-body p { margin:0 0 8px; }
275
+ enum-el, enum-el { display:flex; align-items:flex-start; flex-wrap:wrap; gap:10px; width:fit-content; margin:8px 0 12px; }
276
+ .annotation-el-pane enum-el, .annotation-el-pane enum-el { flex-wrap:wrap; }
277
+ enum-item, enum-item { display:block; flex:0 0 auto; width:fit-content; min-width:180px; max-width:600px; border:1px solid #f0f0f0; border-radius:var(--rp-radius-md); background:#fff; overflow:hidden; }
278
+ .enum-el-label { display:flex; align-items:flex-start; gap:6px; padding:5px 9px 4px; font-size:12px; font-weight:650; color:#374151; }
279
+ .enum-el-index { display:inline-grid; place-items:center; min-width:16px; height:16px; padding:0 4px; background:#111827; color:#fff; font-size:10px; font-weight:750; border-radius:3px; flex:0 0 auto; margin-top:1px; }
280
+ .enum-el-label-text { display:block; }
281
+ .enum-el-description { display:block; margin-top:2px; font-size:11px; line-height:1.35; font-weight:400; color:var(--rp-muted); }
282
+ .enum-el-content { display:block; width:fit-content; padding:8px; }
283
+ .annotation-el-title { font-weight:700; color:#111827; cursor:pointer; }
284
+ .annotation-el-title:hover { color:var(--rp-primary); }
105
285
  .rp-section-focus { outline:2px dashed var(--rp-primary); outline-offset:4px; border-radius:4px; }
106
- snap-viewport, rp-viewport { display:flex; flex-direction:column; width:var(--snap-width,1440px); height:var(--snap-height,900px); background:#f8fafc; overflow:hidden; color:#111827; }
107
- snap-layout, rp-layout { display:grid; grid-template-columns:var(--snap-columns,1fr); grid-template-rows:var(--snap-rows,auto); gap:var(--snap-gap,0); align-content:start; width:fit-content; max-width:100%; min-width:0; }
108
- snap-layout > *, rp-layout > * { min-width:0; }
109
- snap-viewport snap-layout, rp-viewport rp-layout { width:100%; }
110
- snap-viewport > snap-layout, rp-viewport > rp-layout { flex:1 1 auto; min-height:0; }
111
- snap-viewport > snap-navbar, rp-viewport > rp-navbar { flex:0 0 auto; }
112
- snap-panel, rp-panel { display:block; width:fit-content; max-width:100%; background:#fff; border:1px solid var(--rp-border); border-radius:var(--rp-radius-md); padding:var(--snap-padding,16px); }
113
- snap-viewport snap-panel, rp-viewport rp-panel { width:auto; min-width:0; }
114
- snap-panel[elevation="1"], rp-panel[elevation="1"] { box-shadow:0 4px 16px rgba(15,23,42,.06); }
115
- snap-panel[elevation="2"], rp-panel[elevation="2"] { box-shadow:var(--rp-shadow); }
116
- snap-navbar, rp-navbar { display:flex; align-items:center; gap:14px; height:var(--snap-height,64px); padding:0 24px; background:#fff; border-bottom:1px solid var(--rp-border); }
117
- snap-sidebar, rp-sidebar { display:block; width:var(--snap-width,260px); min-height:0; background:#fff; border-right:1px solid var(--rp-border); padding:14px; }
118
- snap-viewport snap-sidebar, rp-viewport rp-sidebar { min-height:100%; }
119
- snap-sidebar[collapsed], rp-sidebar[collapsed] { width:72px; }
120
- snap-logo, rp-logo { display:inline-grid; place-items:center; width:var(--snap-size,82px); height:32px; border-radius:8px; background:#111827; color:#fff; font-size:12px; font-weight:800; letter-spacing:.08em; }
121
- snap-search, rp-search, snap-input, rp-input, snap-date-picker, rp-date-picker { display:inline-flex; align-items:center; gap:8px; width:280px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; }
122
- snap-textarea, rp-textarea { display:block; width:320px; min-height:calc(var(--snap-rows,3) * 24px + 22px); padding:9px 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; white-space:pre-wrap; }
123
- snap-search[state="focus"], rp-search[state="focus"], snap-input[state="focus"], rp-input[state="focus"], snap-textarea[state="focus"], rp-textarea[state="focus"], snap-date-picker[state="focus"], rp-date-picker[state="focus"] { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
124
- snap-search[state="filled"], rp-search[state="filled"], snap-input[state="filled"], rp-input[state="filled"], snap-textarea[state="filled"], rp-textarea[state="filled"], snap-date-picker[state="filled"], rp-date-picker[state="filled"] { border-color:#93c5fd; background:#f8fbff; }
125
- snap-search[state="error"], rp-search[state="error"], snap-input[state="error"], rp-input[state="error"], snap-textarea[state="error"], rp-textarea[state="error"], snap-date-picker[state="error"], rp-date-picker[state="error"] { border-color:var(--rp-danger); box-shadow:0 0 0 3px rgba(220,38,38,.1); }
126
- snap-search[state="disabled"], rp-search[state="disabled"], snap-input[state="disabled"], rp-input[state="disabled"], snap-textarea[state="disabled"], rp-textarea[state="disabled"], snap-date-picker[state="disabled"], rp-date-picker[state="disabled"] { opacity:.55; background:#f3f4f6; }
127
- snap-input[label], rp-input[label], snap-date-picker[label], rp-date-picker[label] { display:inline-grid; align-items:start; gap:6px; width:280px; min-height:0; padding:0; border:0; background:transparent; box-shadow:none; }
128
- snap-input[label][state="focus"], rp-input[label][state="focus"], snap-input[label][state="filled"], rp-input[label][state="filled"], snap-input[label][state="error"], rp-input[label][state="error"], snap-date-picker[label][state="focus"], rp-date-picker[label][state="focus"], snap-date-picker[label][state="filled"], rp-date-picker[label][state="filled"], snap-date-picker[label][state="error"], rp-date-picker[label][state="error"] { border:0; background:transparent; box-shadow:none; }
286
+ viewport-el, viewport-el { display:flex; flex-direction:column; width:var(--snap-width,1440px); height:var(--snap-height,900px); background:#f8fafc; overflow:hidden; color:#111827; }
287
+ layout-el, layout-el { display:grid; grid-template-columns:var(--snap-columns,1fr); grid-template-rows:var(--snap-rows,auto); gap:var(--snap-gap,0); align-content:start; width:fit-content; max-width:100%; min-width:0; }
288
+ layout-el > *, layout-el > * { min-width:0; }
289
+ viewport-el layout-el, viewport-el layout-el { width:100%; }
290
+ viewport-el > layout-el, viewport-el > layout-el { flex:1 1 auto; min-height:0; }
291
+ viewport-el > navbar-el, viewport-el > navbar-el { flex:0 0 auto; }
292
+ panel-el, panel-el { display:block; width:fit-content; max-width:100%; background:#fff; border:1px solid var(--rp-border); border-radius:var(--rp-radius-md); padding:var(--snap-padding,16px); }
293
+ viewport-el panel-el, viewport-el panel-el { width:auto; min-width:0; }
294
+ panel-el[elevation="1"], panel-el[elevation="1"] { box-shadow:0 4px 16px rgba(15,23,42,.06); }
295
+ panel-el[elevation="2"], panel-el[elevation="2"] { box-shadow:var(--rp-shadow); }
296
+ navbar-el, navbar-el { display:flex; align-items:center; gap:14px; height:var(--snap-height,64px); padding:0 24px; background:#fff; border-bottom:1px solid var(--rp-border); }
297
+ sidebar-el, sidebar-el { display:block; width:var(--snap-width,260px); min-height:0; background:#fff; border-right:1px solid var(--rp-border); padding:14px; }
298
+ viewport-el sidebar-el, viewport-el sidebar-el { min-height:100%; }
299
+ sidebar-el[collapsed], sidebar-el[collapsed] { width:72px; }
300
+ logo-el, logo-el { display:inline-grid; place-items:center; width:var(--snap-size,82px); height:32px; border-radius:8px; background:#111827; color:#fff; font-size:12px; font-weight:800; letter-spacing:.08em; }
301
+ search-el, search-el, input-el, input-el, date-picker, date-picker { display:inline-flex; align-items:center; gap:8px; width:280px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; }
302
+ textarea-el, textarea-el { display:block; width:320px; min-height:calc(var(--snap-rows,3) * 24px + 22px); padding:9px 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; white-space:pre-wrap; }
303
+ search-el[state="focus"], search-el[state="focus"], input-el[state="focus"], input-el[state="focus"], textarea-el[state="focus"], textarea-el[state="focus"], date-picker[state="focus"], date-picker[state="focus"] { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
304
+ search-el[state="filled"], search-el[state="filled"], input-el[state="filled"], input-el[state="filled"], textarea-el[state="filled"], textarea-el[state="filled"], date-picker[state="filled"], date-picker[state="filled"] { border-color:#93c5fd; background:#f8fbff; }
305
+ search-el[state="error"], search-el[state="error"], input-el[state="error"], input-el[state="error"], textarea-el[state="error"], textarea-el[state="error"], date-picker[state="error"], date-picker[state="error"] { border-color:var(--rp-danger); box-shadow:0 0 0 3px rgba(220,38,38,.1); }
306
+ search-el[state="disabled"], search-el[state="disabled"], input-el[state="disabled"], input-el[state="disabled"], textarea-el[state="disabled"], textarea-el[state="disabled"], date-picker[state="disabled"], date-picker[state="disabled"] { opacity:.55; background:#f3f4f6; }
307
+ input-el[label], input-el[label], date-picker[label], date-picker[label] { display:inline-grid; align-items:start; gap:6px; width:280px; min-height:0; padding:0; border:0; background:transparent; box-shadow:none; }
308
+ input-el[label][state="focus"], input-el[label][state="focus"], input-el[label][state="filled"], input-el[label][state="filled"], input-el[label][state="error"], input-el[label][state="error"], date-picker[label][state="focus"], date-picker[label][state="focus"], date-picker[label][state="filled"], date-picker[label][state="filled"], date-picker[label][state="error"], date-picker[label][state="error"] { border:0; background:transparent; box-shadow:none; }
129
309
  .rp-field-control { display:flex; align-items:center; gap:8px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; }
130
- snap-input[state="focus"] .rp-field-control, rp-input[state="focus"] .rp-field-control, snap-date-picker[state="focus"] .rp-field-control, rp-date-picker[state="focus"] .rp-field-control { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
131
- snap-input[state="filled"] .rp-field-control, rp-input[state="filled"] .rp-field-control, snap-date-picker[state="filled"] .rp-field-control, rp-date-picker[state="filled"] .rp-field-control { border-color:#93c5fd; background:#f8fbff; }
132
- snap-input[state="error"] .rp-field-control, rp-input[state="error"] .rp-field-control, snap-date-picker[state="error"] .rp-field-control, rp-date-picker[state="error"] .rp-field-control { border-color:var(--rp-danger); box-shadow:0 0 0 3px rgba(220,38,38,.1); }
310
+ input-el[state="focus"] .rp-field-control, input-el[state="focus"] .rp-field-control, date-picker[state="focus"] .rp-field-control, date-picker[state="focus"] .rp-field-control { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
311
+ input-el[state="filled"] .rp-field-control, input-el[state="filled"] .rp-field-control, date-picker[state="filled"] .rp-field-control, date-picker[state="filled"] .rp-field-control { border-color:#93c5fd; background:#f8fbff; }
312
+ input-el[state="error"] .rp-field-control, input-el[state="error"] .rp-field-control, date-picker[state="error"] .rp-field-control, date-picker[state="error"] .rp-field-control { border-color:var(--rp-danger); box-shadow:0 0 0 3px rgba(220,38,38,.1); }
133
313
  .rp-field-label { display:block; margin:0 0 6px; color:#374151; font-size:12px; font-weight:650; }
134
314
  .rp-placeholder { color:#9ca3af; }
135
315
  .rp-value { color:#111827; }
136
316
  .rp-error-text { color:var(--rp-danger); font-size:12px; }
137
- snap-select, rp-select { display:inline-block; width:var(--snap-width,280px); }
138
- .rp-select-control { display:flex; align-items:center; gap:8px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; }
139
- snap-select[state="expanded"] .rp-select-control, rp-select[state="expanded"] .rp-select-control { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
140
- snap-select[state="disabled"], rp-select[state="disabled"] { opacity:.55; }
141
- .rp-select-value { flex:1 1 auto; min-width:0; }
142
- .rp-select-options { display:none; margin-top:6px; padding:5px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; box-shadow:0 10px 18px rgba(15,23,42,.08); }
143
- snap-select[state="expanded"] .rp-select-options, rp-select[state="expanded"] .rp-select-options { display:grid; gap:2px; }
144
- .rp-select-option { padding:7px 8px; border-radius:6px; font-size:13px; color:#374151; }
145
- .rp-select-option.selected { background:#eff6ff; color:#1d4ed8; font-weight:700; }
146
- snap-badge, rp-badge { display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 6px; border-radius:999px; background:#ef4444; color:#fff; font-size:11px; font-weight:750; }
147
- snap-avatar, rp-avatar { display:inline-grid; place-items:center; width:var(--snap-size,32px); height:var(--snap-size,32px); border-radius:999px; background:#e0e7ff; color:#3730a3; font-size:12px; font-weight:800; }
148
- snap-list, rp-list { display:flex; flex-direction:column; gap:4px; width:100%; }
149
- snap-list-item, rp-list-item { display:flex; align-items:center; gap:8px; width:100%; min-width:180px; height:36px; padding:0 10px; border-radius:8px; color:#374151; }
150
- snap-list-item[state="selected"], rp-list-item[state="selected"] { background:#eff6ff; color:#1d4ed8; font-weight:700; }
151
- snap-list-item[state="disabled"], rp-list-item[state="disabled"] { opacity:.5; }
152
- .rp-list-label { flex:1 1 auto; }
153
- .rp-list-badge { margin-left:auto; min-width:18px; height:18px; border-radius:999px; display:grid; place-items:center; padding:0 6px; background:#e5e7eb; color:#374151; font-size:11px; font-weight:700; }
154
- snap-tabs, rp-tabs { display:flex; gap:6px; border-bottom:1px solid var(--rp-border); margin-bottom:12px; width:fit-content; }
155
- snap-tab, rp-tab { display:inline-flex; align-items:center; gap:6px; padding:9px 13px; border-bottom:2px solid transparent; color:#6b7280; font-size:14px; }
156
- snap-tab.rp-tab-active, rp-tab.rp-tab-active { color:var(--rp-primary); border-bottom-color:var(--rp-primary); font-weight:700; }
157
- snap-button, rp-button { display:inline-flex; align-items:center; justify-content:center; gap:7px; min-height:34px; padding:0 12px; border-radius:8px; border:1px solid var(--rp-border); background:#fff; color:#374151; font-size:13px; font-weight:650; }
158
- snap-button[size="sm"], rp-button[size="sm"] { min-height:28px; padding:0 9px; font-size:12px; border-radius:6px; }
159
- snap-button[size="lg"], rp-button[size="lg"] { min-height:40px; padding:0 16px; font-size:14px; }
160
- snap-button[variant="primary"], rp-button[variant="primary"] { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; }
161
- snap-button[variant="secondary"], rp-button[variant="secondary"] { border-color:#bfdbfe; background:#eff6ff; color:#1d4ed8; }
162
- snap-button[variant="danger"], rp-button[variant="danger"] { border-color:var(--rp-danger); color:var(--rp-danger); }
163
- snap-button[variant="link"], rp-button[variant="link"] { border-color:transparent; background:transparent; color:var(--rp-primary); padding-inline:2px; }
164
- snap-button[variant="ghost"], rp-button[variant="ghost"] { border-color:transparent; background:transparent; }
165
- snap-button[state="disabled"], rp-button[state="disabled"], snap-button[disabled], rp-button[disabled] { opacity:.5; }
166
- snap-button-group, rp-button-group { display:inline-flex; gap:0; width:fit-content; }
167
- snap-button-group > snap-button, rp-button-group > rp-button { border-radius:0; margin-left:-1px; }
168
- snap-button-group > :first-child { border-radius:8px 0 0 8px; margin-left:0; }
169
- snap-button-group > :last-child { border-radius:0 8px 8px 0; }
170
- snap-table, rp-table { display:table; border-collapse:collapse; width:fit-content; min-width:720px; max-width:980px; background:#fff; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
171
- snap-viewport snap-table, rp-viewport rp-table { width:100%; max-width:none; }
172
- .rp-table-row { display:table-row; }
173
- .rp-table-cell { display:table-cell; padding:11px 12px; border-bottom:1px solid var(--rp-border); font-size:13px; vertical-align:middle; white-space:nowrap; }
174
- .rp-table-head .rp-table-cell { background:#f9fafb; color:#6b7280; font-size:12px; font-weight:750; }
175
- .rp-table-row:last-child .rp-table-cell { border-bottom:0; }
176
- snap-table-row, rp-table-row { display:grid; grid-template-columns:44px 150px 240px 90px 90px; align-items:center; min-width:560px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#fff; }
177
- snap-table-row > span, rp-table-row > span { padding:10px 12px; font-size:13px; }
178
- snap-table-row[state="unread"], rp-table-row[state="unread"] { background:#eff6ff; font-weight:700; }
179
- snap-table-row[state="selected"], rp-table-row[state="selected"] { outline:2px solid rgba(37,99,235,.35); background:#f8fbff; }
180
- snap-table-row[state="highlighted"], rp-table-row[state="highlighted"] { background:#fffbeb; }
181
- snap-table-row[state="disabled"], rp-table-row[state="disabled"] { opacity:.5; }
182
- snap-bulk-action-bar, rp-bulk-action-bar { display:flex; align-items:center; gap:8px; width:fit-content; padding:8px 10px; margin:0 0 10px; border:1px solid #bfdbfe; background:#eff6ff; border-radius:8px; color:#1e40af; font-size:13px; font-weight:650; }
183
- snap-empty, rp-empty { display:grid; justify-items:center; gap:8px; width:fit-content; min-width:240px; padding:24px; border:1px dashed var(--rp-border-strong); border-radius:10px; background:#fff; color:#6b7280; text-align:center; }
184
- .rp-empty-title { color:#111827; font-weight:700; }
185
- .rp-empty-desc { font-size:13px; }
186
- snap-loading, rp-loading { display:grid; gap:8px; min-width:260px; color:var(--rp-primary); }
187
- .rp-skeleton-line { height:14px; border-radius:999px; background:linear-gradient(90deg,#f3f4f6,#e5e7eb,#f3f4f6); }
317
+ select-el, select-el { display:inline-block; width:280px; max-width:100%; }
318
+ .select-el-control { display:flex; align-items:center; gap:8px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; }
319
+ select-el[state="expanded"] .select-el-control, select-el[state="expanded"] .select-el-control { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
320
+ select-el[state="disabled"], select-el[state="disabled"] { opacity:.55; }
321
+ .select-el-value { flex:1 1 auto; min-width:0; }
322
+ .select-el-options { display:none; margin-top:6px; padding:5px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; box-shadow:0 10px 18px rgba(15,23,42,.08); }
323
+ select-el[state="expanded"] .select-el-options, select-el[state="expanded"] .select-el-options { display:grid; gap:2px; }
324
+ .select-el-option { padding:7px 8px; border-radius:6px; font-size:13px; color:#374151; }
325
+ .select-el-option.selected { background:#eff6ff; color:#1d4ed8; font-weight:700; }
326
+ badge-el, badge-el { display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 6px; border-radius:999px; background:#ef4444; color:#fff; font-size:11px; font-weight:750; }
327
+ avatar-el, avatar-el { display:inline-grid; place-items:center; width:var(--snap-size,32px); height:var(--snap-size,32px); border-radius:999px; background:#e0e7ff; color:#3730a3; font-size:12px; font-weight:800; }
328
+ list-el, list-el { display:flex; flex-direction:column; gap:4px; width:100%; }
329
+ list-item, list-item { display:flex; align-items:center; gap:8px; width:100%; min-width:180px; height:36px; padding:0 10px; border-radius:8px; color:#374151; }
330
+ list-item[state="selected"], list-item[state="selected"] { background:#eff6ff; color:#1d4ed8; font-weight:700; }
331
+ list-item[state="disabled"], list-item[state="disabled"] { opacity:.5; }
332
+ .list-el-label { flex:1 1 auto; }
333
+ .list-el-badge { margin-left:auto; min-width:18px; height:18px; border-radius:999px; display:grid; place-items:center; padding:0 6px; background:#e5e7eb; color:#374151; font-size:11px; font-weight:700; }
334
+ tabs-el, tabs-el { display:flex; gap:6px; border-bottom:1px solid var(--rp-border); margin-bottom:12px; width:fit-content; }
335
+ tab-el, tab-el { display:inline-flex; align-items:center; gap:6px; padding:9px 13px; border-bottom:2px solid transparent; color:#6b7280; font-size:14px; }
336
+ tab-el.tab-el-active, tab-el.tab-el-active { color:var(--rp-primary); border-bottom-color:var(--rp-primary); font-weight:700; }
337
+ button-el, button-el { display:inline-flex; align-items:center; justify-content:center; gap:7px; min-height:34px; padding:0 12px; border-radius:8px; border:1px solid var(--rp-border); background:#fff; color:#374151; font-size:13px; font-weight:650; }
338
+ button-el[size="sm"], button-el[size="sm"] { min-height:28px; padding:0 9px; font-size:12px; border-radius:6px; }
339
+ button-el[size="lg"], button-el[size="lg"] { min-height:40px; padding:0 16px; font-size:14px; }
340
+ button-el[variant="primary"], button-el[variant="primary"] { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; }
341
+ button-el[variant="secondary"], button-el[variant="secondary"] { border-color:#bfdbfe; background:#eff6ff; color:#1d4ed8; }
342
+ button-el[variant="danger"], button-el[variant="danger"] { border-color:var(--rp-danger); color:var(--rp-danger); }
343
+ button-el[variant="link"], button-el[variant="link"] { border-color:transparent; background:transparent; color:var(--rp-primary); padding-inline:2px; }
344
+ button-el[variant="ghost"], button-el[variant="ghost"] { border-color:transparent; background:transparent; }
345
+ button-el[state="disabled"], button-el[state="disabled"], button-el[disabled], button-el[disabled] { opacity:.5; }
346
+ button-group, button-group { display:inline-flex; gap:0; width:fit-content; }
347
+ button-group > button-el, button-group > button-el { border-radius:0; margin-left:-1px; }
348
+ button-group > :first-child { border-radius:8px 0 0 8px; margin-left:0; }
349
+ button-group > :last-child { border-radius:0 8px 8px 0; }
350
+ table-el, table-el { display:table; border-collapse:collapse; width:fit-content; min-width:720px; max-width:980px; background:#fff; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
351
+ viewport-el table-el, viewport-el table-el { width:100%; max-width:none; }
352
+ .table-row { display:table-row; }
353
+ .table-el-cell { display:table-cell; padding:11px 12px; border-bottom:1px solid var(--rp-border); font-size:13px; vertical-align:middle; white-space:nowrap; }
354
+ .table-el-head .table-el-cell { background:#f9fafb; color:#6b7280; font-size:12px; font-weight:750; }
355
+ .table-row:last-child .table-el-cell { border-bottom:0; }
356
+ table-row, table-row { display:grid; grid-template-columns:44px 150px 240px 90px 90px; align-items:center; min-width:560px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#fff; }
357
+ table-row > span, table-row > span { padding:10px 12px; font-size:13px; }
358
+ table-row[state="unread"], table-row[state="unread"] { background:#eff6ff; font-weight:700; }
359
+ table-row[state="selected"], table-row[state="selected"] { outline:2px solid rgba(37,99,235,.35); background:#f8fbff; }
360
+ table-row[state="highlighted"], table-row[state="highlighted"] { background:#fffbeb; }
361
+ table-row[state="disabled"], table-row[state="disabled"] { opacity:.5; }
362
+ bulk-action-bar, bulk-action-bar { display:flex; align-items:center; gap:8px; width:fit-content; padding:8px 10px; margin:0 0 10px; border:1px solid #bfdbfe; background:#eff6ff; border-radius:8px; color:#1e40af; font-size:13px; font-weight:650; }
363
+ empty-el, empty-el { display:grid; justify-items:center; gap:8px; width:fit-content; min-width:240px; padding:24px; border:1px dashed var(--rp-border-strong); border-radius:10px; background:#fff; color:#6b7280; text-align:center; }
364
+ .empty-el-title { color:#111827; font-weight:700; }
365
+ .empty-el-desc { font-size:13px; }
366
+ loading-el, loading-el { display:grid; gap:8px; min-width:260px; color:var(--rp-primary); }
367
+ .skeleton-el-line { height:14px; border-radius:999px; background:linear-gradient(90deg,#f3f4f6,#e5e7eb,#f3f4f6); }
188
368
  .rp-spinner { display:inline-grid; place-items:center; width:32px; height:32px; }
189
- snap-alert, rp-alert, snap-toast, rp-toast { display:flex; align-items:flex-start; gap:8px; width:fit-content; max-width:420px; padding:10px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; font-size:13px; }
190
- snap-alert[type="info"], rp-alert[type="info"], snap-toast[type="info"], rp-toast[type="info"] { border-color:#bfdbfe; background:#eff6ff; color:#1e40af; }
191
- snap-alert[type="success"], rp-alert[type="success"], snap-toast[type="success"], rp-toast[type="success"] { border-color:#bbf7d0; background:#f0fdf4; color:#166534; }
192
- snap-alert[type="warning"], rp-alert[type="warning"], snap-toast[type="warning"], rp-toast[type="warning"] { border-color:#fde68a; background:#fffbeb; color:#92400e; }
193
- snap-alert[type="error"], rp-alert[type="error"], snap-toast[type="error"], rp-toast[type="error"] { border-color:#fecaca; background:#fef2f2; color:#991b1b; }
194
- snap-dropdown, rp-dropdown, snap-popover, rp-popover { display:block; width:var(--snap-width,300px); padding:8px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; box-shadow:0 12px 24px rgba(15,23,42,.1); }
195
- snap-tooltip, rp-tooltip { display:inline-block; width:fit-content; max-width:240px; padding:6px 8px; border-radius:6px; background:#111827; color:#fff; font-size:12px; }
369
+ alert-el, alert-el, toast-el, toast-el { display:flex; align-items:flex-start; gap:8px; width:fit-content; max-width:420px; padding:10px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; font-size:13px; }
370
+ alert-el[type="info"], alert-el[type="info"], toast-el[type="info"], toast-el[type="info"] { border-color:#bfdbfe; background:#eff6ff; color:#1e40af; }
371
+ alert-el[type="success"], alert-el[type="success"], toast-el[type="success"], toast-el[type="success"] { border-color:#bbf7d0; background:#f0fdf4; color:#166534; }
372
+ alert-el[type="warning"], alert-el[type="warning"], toast-el[type="warning"], toast-el[type="warning"] { border-color:#fde68a; background:#fffbeb; color:#92400e; }
373
+ alert-el[type="error"], alert-el[type="error"], toast-el[type="error"], toast-el[type="error"] { border-color:#fecaca; background:#fef2f2; color:#991b1b; }
374
+ dropdown-el, dropdown-el, popover-el, popover-el { display:block; width:var(--snap-width,300px); padding:8px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; box-shadow:0 12px 24px rgba(15,23,42,.1); }
375
+ tooltip-el, tooltip-el { display:inline-block; width:fit-content; max-width:240px; padding:6px 8px; border-radius:6px; background:#111827; color:#fff; font-size:12px; }
196
376
  .rp-overlay-title { margin:0 0 8px; color:#111827; font-size:14px; font-weight:750; }
197
- snap-modal, rp-modal { display:block; width:min(var(--snap-width,480px), 100%); border:1px solid var(--rp-border); border-radius:12px; background:#fff; box-shadow:0 24px 48px rgba(15,23,42,.18); overflow:hidden; }
198
- snap-drawer, rp-drawer { display:block; width:min(var(--snap-width,360px), 100%); min-height:320px; border:1px solid var(--rp-border); background:#fff; box-shadow:0 18px 40px rgba(15,23,42,.14); }
199
- .rp-modal-head, .rp-drawer-head { display:flex; align-items:center; justify-content:space-between; padding:14px 16px; border-bottom:1px solid var(--rp-border); font-weight:750; }
200
- .rp-modal-body, .rp-drawer-body { padding:16px; }
201
- .rp-modal-footer { display:flex; justify-content:flex-end; gap:8px; padding:12px 16px; border-top:1px solid var(--rp-border); background:#f9fafb; }
202
- snap-card, rp-card { display:block; width:auto; min-width:220px; padding:14px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
203
- .rp-card-image { display:grid; place-items:center; height:120px; margin:-14px -14px 12px; border-radius:10px 10px 0 0; background:#f3f4f6; color:#6b7280; }
204
- .rp-card-title { display:block; color:#111827; font-weight:750; }
205
- .rp-card-subtitle { display:block; margin-top:4px; color:#6b7280; font-size:13px; }
206
- .rp-card-footer { display:block; margin:12px -14px -14px; padding:10px 14px; border-top:1px solid var(--rp-border); background:#f9fafb; }
207
- snap-stat-card, rp-stat-card { display:grid; gap:6px; width:auto; min-width:0; padding:16px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
377
+ modal-el, modal-el { display:block; width:min(var(--snap-width,480px), 100%); border:1px solid var(--rp-border); border-radius:12px; background:#fff; box-shadow:0 24px 48px rgba(15,23,42,.18); overflow:hidden; }
378
+ drawer-el, drawer-el { display:block; width:min(var(--snap-width,360px), 100%); min-height:320px; border:1px solid var(--rp-border); background:#fff; box-shadow:0 18px 40px rgba(15,23,42,.14); }
379
+ .modal-el-head, .drawer-el-head { display:flex; align-items:center; justify-content:space-between; padding:14px 16px; border-bottom:1px solid var(--rp-border); font-weight:750; }
380
+ .modal-el-body, .drawer-el-body { padding:16px; }
381
+ .modal-el-footer { display:flex; justify-content:flex-end; gap:8px; padding:12px 16px; border-top:1px solid var(--rp-border); background:#f9fafb; }
382
+ card-el, card-el { display:block; width:auto; min-width:220px; padding:14px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
383
+ .card-el-image { display:grid; place-items:center; height:120px; margin:-14px -14px 12px; border-radius:10px 10px 0 0; background:#f3f4f6; color:#6b7280; }
384
+ .card-el-title { display:block; color:#111827; font-weight:750; }
385
+ .card-el-subtitle { display:block; margin-top:4px; color:#6b7280; font-size:13px; }
386
+ .card-el-footer { display:block; margin:12px -14px -14px; padding:10px 14px; border-top:1px solid var(--rp-border); background:#f9fafb; }
387
+ stat-card, stat-card { display:grid; gap:6px; width:auto; min-width:0; padding:16px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
208
388
  .rp-stat-label { color:#6b7280; font-size:12px; font-weight:650; }
209
389
  .rp-stat-value { color:#111827; font-size:26px; font-weight:800; }
210
390
  .rp-stat-change { font-size:12px; font-weight:700; }
211
- snap-stat-card[trend="up"] .rp-stat-change, rp-stat-card[trend="up"] .rp-stat-change { color:var(--rp-success); }
212
- snap-stat-card[trend="down"] .rp-stat-change, rp-stat-card[trend="down"] .rp-stat-change { color:var(--rp-danger); }
213
- snap-tag, rp-tag { display:inline-flex; align-items:center; gap:5px; height:24px; padding:0 8px; border-radius:999px; background:#eef2ff; color:#3730a3; font-size:12px; font-weight:650; }
214
- snap-tag[color="green"], rp-tag[color="green"] { background:#dcfce7; color:#166534; }
215
- snap-tag[color="orange"], rp-tag[color="orange"] { background:#ffedd5; color:#9a3412; }
216
- snap-tag[color="red"], rp-tag[color="red"] { background:#fee2e2; color:#991b1b; }
217
- snap-checkbox, rp-checkbox, snap-radio, rp-radio { display:inline-flex; align-items:center; gap:8px; font-size:13px; }
391
+ stat-card[trend="up"] .rp-stat-change, stat-card[trend="up"] .rp-stat-change { color:var(--rp-success); }
392
+ stat-card[trend="down"] .rp-stat-change, stat-card[trend="down"] .rp-stat-change { color:var(--rp-danger); }
393
+ tag-el, tag-el { display:inline-flex; align-items:center; gap:5px; height:24px; padding:0 8px; border-radius:999px; background:#eef2ff; color:#3730a3; font-size:12px; font-weight:650; }
394
+ tag-el[color="green"], tag-el[color="green"] { background:#dcfce7; color:#166534; }
395
+ tag-el[color="orange"], tag-el[color="orange"] { background:#ffedd5; color:#9a3412; }
396
+ tag-el[color="red"], tag-el[color="red"] { background:#fee2e2; color:#991b1b; }
397
+ checkbox-el, checkbox-el, radio-el, radio-el { display:inline-flex; align-items:center; gap:8px; font-size:13px; }
218
398
  .rp-box { display:inline-grid; place-items:center; width:16px; height:16px; border:1px solid var(--rp-border-strong); border-radius:4px; color:#fff; }
219
- snap-checkbox[state="checked"] .rp-box, rp-checkbox[state="checked"] .rp-box, snap-radio[state="checked"] .rp-box, rp-radio[state="checked"] .rp-box, snap-checkbox[state="indeterminate"] .rp-box, rp-checkbox[state="indeterminate"] .rp-box { background:var(--rp-primary); border-color:var(--rp-primary); }
220
- snap-checkbox[state="disabled"], rp-checkbox[state="disabled"], snap-radio[state="disabled"], rp-radio[state="disabled"] { opacity:.5; }
221
- snap-radio .rp-box, rp-radio .rp-box { border-radius:999px; }
222
- snap-toggle, rp-toggle { display:inline-flex; align-items:center; gap:8px; font-size:13px; }
223
- .rp-toggle-track { display:flex; align-items:center; width:34px; height:20px; border-radius:999px; background:#d1d5db; padding:2px; }
224
- .rp-toggle-dot { display:block; width:16px; height:16px; border-radius:999px; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.2); transition:none; }
225
- snap-toggle[state="on"] .rp-toggle-track, rp-toggle[state="on"] .rp-toggle-track { background:var(--rp-primary); }
226
- snap-toggle[state="on"] .rp-toggle-dot, rp-toggle[state="on"] .rp-toggle-dot { margin-left:14px; }
227
- snap-toggle[state="disabled"], rp-toggle[state="disabled"] { opacity:.5; }
228
- snap-form, rp-form { display:grid; gap:12px; width:fit-content; }
229
- snap-form[layout="horizontal"], rp-form[layout="horizontal"] { grid-template-columns:max-content 1fr; align-items:start; }
230
- snap-form-item, rp-form-item { display:grid; gap:6px; width:fit-content; }
231
- .rp-form-label { color:#374151; font-size:12px; font-weight:700; }
232
- .rp-form-label.required::after { content:" *"; color:var(--rp-danger); }
233
- .rp-form-error { color:var(--rp-danger); font-size:12px; }
234
- snap-upload, rp-upload { display:grid; justify-items:center; gap:8px; width:280px; padding:18px; border:1px dashed var(--rp-border-strong); border-radius:10px; background:#fff; color:#6b7280; text-align:center; font-size:13px; }
235
- snap-upload[state="has-file"], rp-upload[state="has-file"] { justify-items:start; border-style:solid; color:#374151; }
236
- snap-upload[state="uploading"], rp-upload[state="uploading"] { border-color:#bfdbfe; background:#eff6ff; color:#1e40af; }
237
- snap-image-placeholder, rp-image-placeholder { display:grid; place-items:center; width:var(--snap-width,160px); height:var(--snap-height,100px); background:#f3f4f6; border:1px dashed var(--rp-border-strong); border-radius:8px; color:#6b7280; font-size:12px; }
238
- snap-progress, rp-progress { display:block; width:180px; height:8px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
239
- snap-progress[kind="circle"], rp-progress[kind="circle"], snap-progress[style="circle"], rp-progress[style="circle"] { display:grid; place-items:center; width:52px; height:52px; border-radius:999px; background:conic-gradient(var(--rp-primary) var(--progress,40%), #e5e7eb 0); font-size:12px; font-weight:750; }
240
- .rp-progress-bar { display:block; height:100%; width:var(--progress,40%); background:var(--rp-primary); }
241
- snap-progress[status="success"] .rp-progress-bar, rp-progress[status="success"] .rp-progress-bar { background:var(--rp-success); }
242
- snap-progress[status="error"] .rp-progress-bar, rp-progress[status="error"] .rp-progress-bar { background:var(--rp-danger); }
243
- snap-pagination, rp-pagination { display:inline-flex; align-items:center; gap:6px; width:fit-content; font-size:13px; }
244
- .rp-page-btn { display:inline-grid; place-items:center; min-width:30px; height:30px; padding:0 8px; border:1px solid var(--rp-border); border-radius:6px; background:#fff; color:#374151; }
245
- .rp-page-btn.active { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; font-weight:750; }
246
- snap-steps, rp-steps { display:flex; align-items:center; gap:8px; width:fit-content; }
399
+ checkbox-el[state="checked"] .rp-box, checkbox-el[state="checked"] .rp-box, radio-el[state="checked"] .rp-box, radio-el[state="checked"] .rp-box, checkbox-el[state="indeterminate"] .rp-box, checkbox-el[state="indeterminate"] .rp-box { background:var(--rp-primary); border-color:var(--rp-primary); }
400
+ checkbox-el[state="disabled"], checkbox-el[state="disabled"], radio-el[state="disabled"], radio-el[state="disabled"] { opacity:.5; }
401
+ radio-el .rp-box, radio-el .rp-box { border-radius:999px; }
402
+ toggle-el, toggle-el { display:inline-flex; align-items:center; gap:8px; font-size:13px; }
403
+ .toggle-el-track { display:flex; align-items:center; width:34px; height:20px; border-radius:999px; background:#d1d5db; padding:2px; }
404
+ .toggle-el-dot { display:block; width:16px; height:16px; border-radius:999px; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.2); transition:none; }
405
+ toggle-el[state="on"] .toggle-el-track, toggle-el[state="on"] .toggle-el-track { background:var(--rp-primary); }
406
+ toggle-el[state="on"] .toggle-el-dot, toggle-el[state="on"] .toggle-el-dot { margin-left:14px; }
407
+ toggle-el[state="disabled"], toggle-el[state="disabled"] { opacity:.5; }
408
+ form-el, form-el { display:grid; gap:12px; width:fit-content; max-width:100%; }
409
+ form-el[layout="horizontal"], form-el[layout="horizontal"] { grid-template-columns:max-content 1fr; align-items:start; }
410
+ form-item, form-item { display:grid; gap:6px; width:fit-content; max-width:100%; }
411
+ form-item > *, form-item > * { max-width:100%; }
412
+ .form-el-label { color:#374151; font-size:12px; font-weight:700; }
413
+ .form-el-label.required::after { content:" *"; color:var(--rp-danger); }
414
+ .form-el-error { color:var(--rp-danger); font-size:12px; }
415
+ upload-el, upload-el { display:grid; justify-items:center; gap:8px; width:280px; padding:18px; border:1px dashed var(--rp-border-strong); border-radius:10px; background:#fff; color:#6b7280; text-align:center; font-size:13px; }
416
+ upload-el[state="has-file"], upload-el[state="has-file"] { justify-items:start; border-style:solid; color:#374151; }
417
+ upload-el[state="uploading"], upload-el[state="uploading"] { border-color:#bfdbfe; background:#eff6ff; color:#1e40af; }
418
+ image-placeholder, image-placeholder { display:grid; place-items:center; width:var(--snap-width,160px); height:var(--snap-height,100px); background:#f3f4f6; border:1px dashed var(--rp-border-strong); border-radius:8px; color:#6b7280; font-size:12px; }
419
+ progress-el, progress-el { display:block; width:180px; height:8px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
420
+ progress-el[kind="circle"], progress-el[kind="circle"], progress-el[style="circle"], progress-el[style="circle"] { display:grid; place-items:center; width:52px; height:52px; border-radius:999px; background:conic-gradient(var(--rp-primary) var(--progress,40%), #e5e7eb 0); font-size:12px; font-weight:750; }
421
+ .progress-el-bar { display:block; height:100%; width:var(--progress,40%); background:var(--rp-primary); }
422
+ progress-el[status="success"] .progress-el-bar, progress-el[status="success"] .progress-el-bar { background:var(--rp-success); }
423
+ progress-el[status="error"] .progress-el-bar, progress-el[status="error"] .progress-el-bar { background:var(--rp-danger); }
424
+ pagination-el, pagination-el { display:inline-flex; align-items:center; gap:6px; width:fit-content; font-size:13px; }
425
+ .page-el-btn { display:inline-grid; place-items:center; min-width:30px; height:30px; padding:0 8px; border:1px solid var(--rp-border); border-radius:6px; background:#fff; color:#374151; }
426
+ .page-el-btn.active { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; font-weight:750; }
427
+ steps-el, steps-el { display:flex; align-items:center; gap:8px; width:fit-content; }
247
428
  .rp-step { display:inline-flex; align-items:center; gap:6px; color:#6b7280; font-size:13px; }
248
429
  .rp-step-dot { display:inline-grid; place-items:center; width:22px; height:22px; border-radius:999px; border:1px solid var(--rp-border-strong); background:#fff; color:#6b7280; font-size:11px; font-weight:750; }
249
430
  .rp-step.active { color:var(--rp-primary); font-weight:750; }
250
431
  .rp-step.active .rp-step-dot { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; }
251
432
  .rp-step.done .rp-step-dot { border-color:var(--rp-success); background:var(--rp-success); color:#fff; }
252
433
  .rp-step-sep { width:28px; height:1px; background:var(--rp-border); }
253
- snap-breadcrumb, rp-breadcrumb { display:inline-flex; align-items:center; gap:6px; color:#6b7280; font-size:13px; }
254
- .rp-breadcrumb-current { color:#111827; font-weight:650; }
434
+ breadcrumb-el, breadcrumb-el { display:inline-flex; align-items:center; gap:6px; color:#6b7280; font-size:13px; }
435
+ .breadcrumb-el-current { color:#111827; font-weight:650; }
255
436
 
256
437
  /* --- data input --- */
257
- snap-slider, rp-slider { display:inline-flex; align-items:center; gap:10px; width:220px; }
258
- .rp-slider-track { position:relative; flex:1; height:4px; border-radius:999px; background:#e5e7eb; }
259
- .rp-slider-fill { position:absolute; height:100%; border-radius:999px; background:var(--rp-primary); }
260
- .rp-slider-thumb { position:absolute; top:50%; width:16px; height:16px; margin-left:-8px; transform:translateY(-50%); border-radius:50%; background:#fff; border:1px solid var(--rp-border-strong); box-shadow:0 1px 3px rgba(0,0,0,.2); }
261
- .rp-slider-value { font-size:12px; color:#374151; min-width:24px; }
262
- snap-range, rp-range { display:inline-flex; align-items:center; width:220px; }
263
- snap-number-input, rp-number-input { display:inline-flex; align-items:center; gap:6px; min-height:34px; padding:0 4px 0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; width:120px; }
438
+ slider-el, slider-el { display:inline-flex; align-items:center; gap:10px; width:220px; }
439
+ .slider-el-track { position:relative; flex:1; height:4px; border-radius:999px; background:#e5e7eb; }
440
+ .slider-el-fill { position:absolute; height:100%; border-radius:999px; background:var(--rp-primary); }
441
+ .slider-el-thumb { position:absolute; top:50%; width:16px; height:16px; margin-left:-8px; transform:translateY(-50%); border-radius:50%; background:#fff; border:1px solid var(--rp-border-strong); }
442
+ .slider-el-value { font-size:12px; color:#374151; min-width:24px; }
443
+ range-el, range-el { display:inline-flex; align-items:center; width:220px; }
444
+ number-input, number-input { display:inline-flex; align-items:center; gap:6px; min-height:34px; padding:0 4px 0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; width:120px; }
264
445
  .rp-num-value { flex:1; font-size:13px; }
265
446
  .rp-num-steppers { display:flex; flex-direction:column; }
266
447
  .rp-num-step { display:grid; place-items:center; width:20px; height:15px; color:#6b7280; cursor:pointer; }
267
- snap-rating, rp-rating { display:inline-flex; gap:2px; color:#d1d5db; }
448
+ rating-el, rating-el { display:inline-flex; gap:2px; color:#d1d5db; }
268
449
  .rp-star.filled { color:#f59e0b; }
269
- snap-pin-input, rp-pin-input { display:inline-flex; gap:8px; }
450
+ pin-input, pin-input { display:inline-flex; gap:8px; }
270
451
  .rp-pin-cell { display:grid; place-items:center; width:40px; height:46px; border:1px solid var(--rp-border-strong); border-radius:8px; font-size:18px; font-weight:700; background:#fff; }
271
- .rp-pin-cell.active { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
272
- snap-color-swatch, rp-color-swatch { display:inline-flex; align-items:center; gap:8px; padding:4px 10px 4px 4px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; }
452
+ .rp-pin-cell.active { border-color:var(--rp-primary); }
453
+ color-swatch, color-swatch { display:inline-flex; align-items:center; gap:8px; padding:4px 10px 4px 4px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; }
273
454
  .rp-swatch-chip { width:24px; height:24px; border-radius:6px; border:1px solid rgba(0,0,0,.1); }
274
455
  .rp-swatch-hex { font-family:ui-monospace,Menlo,monospace; font-size:12px; color:#374151; }
275
- snap-autocomplete, rp-autocomplete { display:inline-block; width:280px; }
276
- .rp-ac-options { display:grid; gap:1px; margin-top:6px; padding:5px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; box-shadow:0 10px 18px rgba(15,23,42,.08); }
456
+ autocomplete-el, autocomplete-el { display:inline-block; width:280px; }
457
+ .rp-ac-options { display:grid; gap:1px; margin-top:6px; padding:5px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; }
277
458
  .rp-ac-option { padding:7px 8px; border-radius:6px; font-size:13px; color:#374151; }
278
459
  .rp-ac-option:first-child { background:#eff6ff; color:#1d4ed8; }
279
460
 
280
461
  /* --- data display additions --- */
281
- snap-chip, rp-chip { display:inline-flex; align-items:center; gap:5px; height:26px; padding:0 9px; border-radius:999px; border:1px solid var(--rp-border); background:#f9fafb; color:#374151; font-size:12px; }
282
- snap-tree, rp-tree { display:flex; flex-direction:column; gap:1px; width:fit-content; min-width:240px; }
283
- .rp-tree-row { display:flex; align-items:center; gap:6px; padding:5px 8px; border-radius:6px; color:#374151; font-size:13px; padding-left:calc(8px + var(--tree-level,0) * 18px); }
284
- .rp-tree-row.selected { background:#eff6ff; color:#1d4ed8; font-weight:650; }
285
- .rp-tree-spacer { display:inline-block; width:12px; }
286
- .rp-tree-label { flex:1; }
287
- snap-timeline, rp-timeline { display:flex; flex-direction:column; width:fit-content; min-width:260px; }
288
- snap-timeline-item, rp-timeline-item { display:flex; gap:12px; padding-bottom:16px; position:relative; }
289
- snap-timeline-item:not(:last-child)::before, rp-timeline-item:not(:last-child)::before { content:''; position:absolute; left:6px; top:16px; bottom:0; width:2px; background:var(--rp-border); }
290
- .rp-timeline-dot { flex:0 0 auto; width:14px; height:14px; margin-top:2px; border-radius:50%; background:#fff; border:2px solid var(--rp-border-strong); z-index:1; }
291
- .rp-timeline-dot.active { border-color:var(--rp-primary); background:var(--rp-primary); }
292
- .rp-timeline-dot.done { border-color:var(--rp-success); background:var(--rp-success); }
293
- .rp-timeline-dot.error { border-color:var(--rp-danger); background:var(--rp-danger); }
294
- .rp-timeline-main { flex:1; }
295
- .rp-timeline-head { display:flex; align-items:baseline; gap:8px; }
296
- .rp-timeline-label { font-weight:650; color:#111827; font-size:13px; }
297
- .rp-timeline-time { font-size:12px; color:#9ca3af; }
298
- .rp-timeline-content { font-size:13px; color:#6b7280; margin-top:2px; }
299
- snap-calendar, rp-calendar { display:inline-block; width:280px; padding:12px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
462
+ chip-el, chip-el { display:inline-flex; align-items:center; gap:5px; height:26px; padding:0 9px; border-radius:999px; border:1px solid var(--rp-border); background:#f9fafb; color:#374151; font-size:12px; }
463
+ tree-el, tree-el { display:flex; flex-direction:column; gap:1px; width:fit-content; min-width:240px; }
464
+ .tree-el-row { display:flex; align-items:center; gap:6px; padding:5px 8px; border-radius:6px; color:#374151; font-size:13px; padding-left:calc(8px + var(--tree-level,0) * 18px); }
465
+ .tree-el-row.selected { background:#eff6ff; color:#1d4ed8; font-weight:650; }
466
+ .tree-el-spacer { display:inline-block; width:12px; }
467
+ .tree-el-label { flex:1; }
468
+ timeline-el, timeline-el { display:flex; flex-direction:column; width:fit-content; min-width:260px; }
469
+ timeline-item, timeline-item { display:flex; gap:12px; padding-bottom:16px; position:relative; }
470
+ timeline-item:not(:last-child)::before, timeline-item:not(:last-child)::before { content:''; position:absolute; left:6px; top:16px; bottom:0; width:2px; background:var(--rp-border); }
471
+ .timeline-el-dot { flex:0 0 auto; width:14px; height:14px; margin-top:2px; border-radius:50%; background:#fff; border:2px solid var(--rp-border-strong); z-index:1; }
472
+ .timeline-el-dot.active { border-color:var(--rp-primary); background:var(--rp-primary); }
473
+ .timeline-el-dot.done { border-color:var(--rp-success); background:var(--rp-success); }
474
+ .timeline-el-dot.error { border-color:var(--rp-danger); background:var(--rp-danger); }
475
+ .timeline-el-main { flex:1; }
476
+ .timeline-el-head { display:flex; align-items:baseline; gap:8px; }
477
+ .timeline-el-label { font-weight:650; color:#111827; font-size:13px; }
478
+ .timeline-el-time { font-size:12px; color:#9ca3af; }
479
+ .timeline-el-content { font-size:13px; color:#6b7280; margin-top:2px; }
480
+ calendar-el, calendar-el { display:inline-block; width:280px; padding:12px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
300
481
  .rp-cal-head { text-align:center; font-weight:700; font-size:14px; margin-bottom:10px; }
301
482
  .rp-cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
302
483
  .rp-cal-dow { display:grid; place-items:center; height:24px; font-size:11px; color:#9ca3af; }
303
484
  .rp-cal-cell { display:grid; place-items:center; height:32px; border-radius:6px; font-size:13px; color:#374151; }
304
485
  .rp-cal-cell.selected { background:var(--rp-primary); color:#fff; font-weight:700; }
305
486
  .rp-cal-cell.muted { color:transparent; }
306
- snap-kanban, rp-kanban { display:flex; gap:12px; width:fit-content; align-items:flex-start; }
307
- snap-kanban-column, rp-kanban-column { display:flex; flex-direction:column; width:200px; padding:10px; border-radius:10px; background:#f3f4f6; }
308
- .rp-kanban-head { display:flex; align-items:center; justify-content:space-between; font-weight:650; font-size:13px; margin-bottom:8px; color:#374151; }
309
- .rp-kanban-count { display:grid; place-items:center; min-width:18px; height:18px; padding:0 5px; border-radius:999px; background:#e5e7eb; font-size:11px; }
310
- .rp-kanban-body { display:flex; flex-direction:column; gap:8px; }
311
- snap-kanban-card, rp-kanban-card { display:block; padding:10px; border-radius:8px; background:#fff; border:1px solid var(--rp-border); }
312
- .rp-kanban-card-title { display:block; font-size:13px; color:#111827; }
313
- .rp-kanban-card-tag { display:inline-block; margin-top:6px; padding:1px 7px; border-radius:999px; background:#eef2ff; color:#3730a3; font-size:11px; }
314
- snap-code-block, rp-code-block { display:block; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#0f172a; }
487
+ kanban-el, kanban-el { display:flex; gap:12px; width:fit-content; align-items:flex-start; }
488
+ kanban-column, kanban-column { display:flex; flex-direction:column; width:200px; padding:10px; border-radius:10px; background:#f3f4f6; }
489
+ .kanban-el-head { display:flex; align-items:center; justify-content:space-between; font-weight:650; font-size:13px; margin-bottom:8px; color:#374151; }
490
+ .kanban-el-count { display:grid; place-items:center; min-width:18px; height:18px; padding:0 5px; border-radius:999px; background:#e5e7eb; font-size:11px; }
491
+ .kanban-el-body { display:flex; flex-direction:column; gap:8px; }
492
+ kanban-card, kanban-card { display:block; padding:10px; border-radius:8px; background:#fff; border:1px solid var(--rp-border); }
493
+ .kanban-card-title { display:block; font-size:13px; color:#111827; }
494
+ .kanban-card-tag { display:inline-block; margin-top:6px; padding:1px 7px; border-radius:999px; background:#eef2ff; color:#3730a3; font-size:11px; }
495
+ code-block, code-block { display:block; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#0f172a; }
315
496
  .rp-code-head { padding:6px 12px; font-family:ui-monospace,Menlo,monospace; font-size:11px; color:#94a3b8; background:#1e293b; }
316
497
  .rp-code-body { padding:10px 0; }
317
498
  .rp-code-line { display:flex; align-items:center; gap:12px; padding:1px 12px; }
318
499
  .rp-code-ln { width:20px; text-align:right; color:#475569; font-family:ui-monospace,Menlo,monospace; font-size:11px; }
319
500
  .rp-code-bar { height:8px; border-radius:3px; background:#334155; }
320
- snap-diff, rp-diff { display:block; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; font-family:ui-monospace,Menlo,monospace; }
321
- .rp-diff-line { display:flex; align-items:center; gap:10px; padding:2px 10px; }
322
- .rp-diff-line.add { background:#dcfce7; }
323
- .rp-diff-line.del { background:#fee2e2; }
324
- .rp-diff-sign { width:10px; color:#6b7280; }
325
- .rp-diff-line.add .rp-code-bar { background:#86efac; }
326
- .rp-diff-line.del .rp-code-bar { background:#fca5a5; }
327
- .rp-diff-line.ctx .rp-code-bar { background:#e5e7eb; }
328
- snap-image-grid, rp-image-grid { display:grid; grid-template-columns:repeat(var(--grid-cols,3),1fr); gap:8px; width:fit-content; }
501
+ diff-el, diff-el { display:block; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; font-family:ui-monospace,Menlo,monospace; }
502
+ .diff-el-line { display:flex; align-items:center; gap:10px; padding:2px 10px; }
503
+ .diff-el-line.add { background:#dcfce7; }
504
+ .diff-el-line.del { background:#fee2e2; }
505
+ .diff-el-sign { width:10px; color:#6b7280; }
506
+ .diff-el-line.add .rp-code-bar { background:#86efac; }
507
+ .diff-el-line.del .rp-code-bar { background:#fca5a5; }
508
+ .diff-el-line.ctx .rp-code-bar { background:#e5e7eb; }
509
+ image-grid, image-grid { display:grid; grid-template-columns:repeat(var(--grid-cols,3),1fr); gap:8px; width:fit-content; }
329
510
  .rp-grid-cell { display:grid; place-items:center; width:80px; height:80px; border-radius:8px; background:#f3f4f6; color:#9ca3af; }
330
- snap-key-value, rp-key-value { display:flex; flex-direction:column; width:fit-content; min-width:240px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
331
- snap-kv-row, rp-kv-row { display:flex; border-bottom:1px solid var(--rp-border); }
332
- snap-kv-row:last-child, rp-kv-row:last-child { border-bottom:0; }
511
+ key-value, key-value { display:flex; flex-direction:column; width:fit-content; min-width:240px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
512
+ kv-row, kv-row { display:flex; border-bottom:1px solid var(--rp-border); }
513
+ kv-row:last-child, kv-row:last-child { border-bottom:0; }
333
514
  .rp-kv-key { width:120px; padding:8px 12px; background:#f9fafb; color:#6b7280; font-size:13px; }
334
515
  .rp-kv-val { flex:1; padding:8px 12px; color:#111827; font-size:13px; }
335
- snap-accordion, rp-accordion { display:flex; flex-direction:column; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
336
- snap-accordion-item, rp-accordion-item { display:block; border-bottom:1px solid var(--rp-border); }
337
- snap-accordion-item:last-child, rp-accordion-item:last-child { border-bottom:0; }
338
- .rp-accordion-head { display:flex; align-items:center; gap:8px; padding:11px 14px; font-weight:650; font-size:13px; color:#111827; }
339
- .rp-accordion-body { padding:0 14px 14px 36px; font-size:13px; color:#6b7280; }
340
- snap-banner, rp-banner { display:flex; align-items:center; gap:10px; width:fit-content; min-width:480px; padding:12px 16px; border-radius:8px; font-size:13px; background:#eff6ff; color:#1e40af; border:1px solid #bfdbfe; }
341
- snap-banner[type="success"], rp-banner[type="success"] { background:#f0fdf4; color:#166534; border-color:#bbf7d0; }
342
- snap-banner[type="warning"], rp-banner[type="warning"] { background:#fffbeb; color:#92400e; border-color:#fde68a; }
343
- snap-banner[type="error"], rp-banner[type="error"] { background:#fef2f2; color:#991b1b; border-color:#fecaca; }
344
- .rp-banner-text { flex:1; }
345
- snap-skeleton, rp-skeleton { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:240px; }
516
+ accordion-el, accordion-el { display:flex; flex-direction:column; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
517
+ accordion-item, accordion-item { display:block; border-bottom:1px solid var(--rp-border); }
518
+ accordion-item:last-child, accordion-item:last-child { border-bottom:0; }
519
+ .accordion-el-head { display:flex; align-items:center; gap:8px; padding:11px 14px; font-weight:650; font-size:13px; color:#111827; }
520
+ .accordion-el-body { padding:0 14px 14px 36px; font-size:13px; color:#6b7280; }
521
+ banner-el, banner-el { display:flex; align-items:center; gap:10px; width:fit-content; min-width:480px; padding:12px 16px; border-radius:8px; font-size:13px; background:#eff6ff; color:#1e40af; border:1px solid #bfdbfe; }
522
+ banner-el[type="success"], banner-el[type="success"] { background:#f0fdf4; color:#166534; border-color:#bbf7d0; }
523
+ banner-el[type="warning"], banner-el[type="warning"] { background:#fffbeb; color:#92400e; border-color:#fde68a; }
524
+ banner-el[type="error"], banner-el[type="error"] { background:#fef2f2; color:#991b1b; border-color:#fecaca; }
525
+ .banner-el-text { flex:1; }
526
+ skeleton-el, skeleton-el { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:240px; }
346
527
  .rp-skel { border-radius:8px; background:linear-gradient(90deg,#f3f4f6,#e5e7eb,#f3f4f6); }
347
528
  .rp-skel-block { height:120px; }
348
529
  .rp-skel-avatar { width:40px; height:40px; border-radius:50%; }
349
530
  .rp-skel-avatar.sm { width:28px; height:28px; }
350
531
  .rp-skel-row { display:flex; align-items:center; gap:10px; }
351
- snap-countdown, rp-countdown { display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px; background:#fef2f2; color:#991b1b; font-size:12px; font-weight:650; font-variant-numeric:tabular-nums; }
352
- snap-result, rp-result { display:grid; justify-items:center; gap:8px; width:fit-content; min-width:280px; padding:32px; text-align:center; }
353
- .rp-result-icon.success { color:var(--rp-success); }
354
- .rp-result-icon.error { color:var(--rp-danger); }
355
- .rp-result-icon.empty { color:#9ca3af; }
356
- .rp-result-title { font-size:16px; font-weight:700; color:#111827; }
357
- .rp-result-desc { font-size:13px; color:#6b7280; }
358
- snap-permission-gate, rp-permission-gate { display:block; position:relative; width:fit-content; }
532
+ countdown-el, countdown-el { display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px; background:#fef2f2; color:#991b1b; font-size:12px; font-weight:650; font-variant-numeric:tabular-nums; }
533
+ result-el, result-el { display:grid; justify-items:center; gap:8px; width:fit-content; min-width:280px; padding:32px; text-align:center; }
534
+ .result-el-icon.success { color:var(--rp-success); }
535
+ .result-el-icon.error { color:var(--rp-danger); }
536
+ .result-el-icon.empty { color:#9ca3af; }
537
+ .result-el-title { font-size:16px; font-weight:700; color:#111827; }
538
+ .result-el-desc { font-size:13px; color:#6b7280; }
539
+ permission-gate, permission-gate { display:block; position:relative; width:fit-content; }
359
540
  .rp-gate-content { opacity:.4; filter:grayscale(1); pointer-events:none; }
360
541
  .rp-gate-overlay { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:6px; background:rgba(255,255,255,.6); color:#6b7280; font-size:12px; font-weight:650; border-radius:8px; }
361
- snap-quota-bar, rp-quota-bar { display:block; width:fit-content; min-width:240px; }
542
+ quota-bar, quota-bar { display:block; width:fit-content; min-width:240px; }
362
543
  .rp-quota-head { display:flex; justify-content:space-between; font-size:12px; color:#374151; margin-bottom:5px; }
363
544
  .rp-quota-num.danger { color:var(--rp-danger); font-weight:700; }
364
545
  .rp-quota-track { display:block; height:8px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
365
546
  .rp-quota-fill { display:block; height:100%; background:var(--rp-primary); }
366
547
  .rp-quota-fill.danger { background:var(--rp-danger); }
367
- snap-api-key, rp-api-key { display:inline-flex; align-items:center; gap:8px; padding:6px 8px 6px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#f9fafb; }
548
+ api-key, api-key { display:inline-flex; align-items:center; gap:8px; padding:6px 8px 6px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#f9fafb; }
368
549
  .rp-apikey-val { font-family:ui-monospace,Menlo,monospace; font-size:12px; color:#374151; }
369
550
  .rp-apikey-copy { display:grid; place-items:center; width:26px; height:26px; border-radius:6px; color:#6b7280; }
370
- snap-audit-row, rp-audit-row { display:flex; align-items:baseline; gap:8px; padding:8px 0; border-bottom:1px solid var(--rp-border); width:fit-content; min-width:320px; font-size:13px; }
551
+ audit-row, audit-row { display:flex; align-items:baseline; gap:8px; padding:8px 0; border-bottom:1px solid var(--rp-border); width:fit-content; min-width:320px; font-size:13px; }
371
552
  .rp-audit-actor { font-weight:650; color:#111827; }
372
553
  .rp-audit-action { flex:1; color:#6b7280; }
373
554
  .rp-audit-time { color:#9ca3af; font-size:12px; }
374
- snap-workflow-node, rp-workflow-node { display:inline-flex; align-items:center; gap:7px; padding:7px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; font-size:13px; }
555
+ workflow-node, workflow-node { display:inline-flex; align-items:center; gap:7px; padding:7px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; font-size:13px; }
375
556
  .rp-wf-icon.done { color:var(--rp-success); }
376
557
  .rp-wf-icon.active { color:var(--rp-primary); }
377
558
  .rp-wf-icon.error { color:var(--rp-danger); }
378
559
  .rp-wf-icon.default { color:#9ca3af; }
379
560
 
380
561
  /* --- navigation & layout additions --- */
381
- snap-segmented, rp-segmented { display:inline-flex; padding:2px; border-radius:8px; background:#f3f4f6; gap:2px; }
562
+ segmented-el, segmented-el { display:inline-flex; padding:2px; border-radius:8px; background:#f3f4f6; gap:2px; }
382
563
  .rp-seg-item { padding:5px 14px; border-radius:6px; font-size:13px; color:#6b7280; }
383
- .rp-seg-item.active { background:#fff; color:#111827; font-weight:650; box-shadow:0 1px 3px rgba(0,0,0,.08); }
384
- snap-command-palette, rp-command-palette { display:block; width:520px; border:1px solid var(--rp-border); border-radius:12px; background:#fff; box-shadow:0 24px 48px rgba(15,23,42,.18); overflow:hidden; }
564
+ .rp-seg-item.active { background:#fff; color:#111827; font-weight:650; }
565
+ command-palette, command-palette { display:block; width:520px; border:1px solid var(--rp-border); border-radius:12px; background:#fff; overflow:hidden; }
385
566
  .rp-cmdk-input { display:flex; align-items:center; gap:10px; padding:14px 16px; border-bottom:1px solid var(--rp-border); }
386
567
  .rp-cmdk-list { padding:6px; }
387
568
  .rp-cmdk-item { display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:8px; font-size:13px; color:#374151; }
388
569
  .rp-cmdk-item.active { background:#eff6ff; color:#1d4ed8; }
389
- snap-context-menu, rp-context-menu, snap-menu, rp-menu { display:inline-flex; flex-direction:column; min-width:180px; padding:5px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; box-shadow:0 12px 24px rgba(15,23,42,.12); }
390
- .rp-menu-item, snap-menu-item, rp-menu-item { display:flex; align-items:center; gap:8px; padding:7px 10px; border-radius:6px; font-size:13px; color:#374151; }
391
- .rp-menu-item.danger, snap-menu-item.danger, rp-menu-item.danger { color:var(--rp-danger); }
392
- .rp-menu-item.disabled, snap-menu-item.disabled, rp-menu-item.disabled { opacity:.45; }
393
- .rp-menu-label { flex:1; }
394
- .rp-menu-shortcut { color:#9ca3af; font-size:12px; }
395
- snap-toc, rp-toc { display:flex; flex-direction:column; gap:2px; width:fit-content; min-width:160px; border-left:2px solid var(--rp-border); }
396
- .rp-toc-item { padding:4px 12px; font-size:13px; color:#6b7280; border-left:2px solid transparent; margin-left:-2px; }
397
- .rp-toc-item.active { color:var(--rp-primary); border-left-color:var(--rp-primary); font-weight:650; }
398
- snap-kbd, rp-kbd { display:inline-flex; align-items:center; gap:3px; }
399
- .rp-kbd-key { display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 5px; border:1px solid var(--rp-border-strong); border-bottom-width:2px; border-radius:5px; background:#f9fafb; font-size:11px; font-family:var(--rp-font); color:#374151; }
400
- .rp-kbd-plus { color:#9ca3af; font-size:11px; }
401
- snap-split-pane, rp-split-pane { display:grid; grid-template-columns:var(--snap-columns,1fr 1fr); width:fit-content; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
402
- snap-split-pane > *, rp-split-pane > * { padding:14px; }
403
- snap-split-pane > *:not(:last-child), rp-split-pane > *:not(:last-child) { border-right:1px solid var(--rp-border); }
404
- snap-divider, rp-divider { display:block; height:1px; background:var(--rp-border); margin:12px 0; }
405
- snap-divider.rp-divider-v, rp-divider.rp-divider-v { display:inline-block; width:1px; height:auto; align-self:stretch; margin:0 12px; }
406
- snap-spacer, rp-spacer { display:block; height:var(--snap-size,16px); }
570
+ context-menu, context-menu, menu-el, menu-el { display:inline-flex; flex-direction:column; min-width:180px; padding:5px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
571
+ .menu-item, menu-item, menu-item { display:flex; align-items:center; gap:8px; padding:7px 10px; border-radius:6px; font-size:13px; color:#374151; }
572
+ .menu-item.danger, menu-item.danger, menu-item.danger { color:var(--rp-danger); }
573
+ .menu-item.disabled, menu-item.disabled, menu-item.disabled { opacity:.45; }
574
+ .menu-el-label { flex:1; }
575
+ .menu-el-shortcut { color:#9ca3af; font-size:12px; }
576
+ toc-el, toc-el { display:flex; flex-direction:column; gap:2px; width:fit-content; min-width:160px; border-left:2px solid var(--rp-border); }
577
+ .toc-el-item { padding:4px 12px; font-size:13px; color:#6b7280; border-left:2px solid transparent; margin-left:-2px; }
578
+ .toc-el-item.active { color:var(--rp-primary); border-left-color:var(--rp-primary); font-weight:650; }
579
+ kbd-el, kbd-el { display:inline-flex; align-items:center; gap:3px; }
580
+ .kbd-el-key { display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 5px; border:1px solid var(--rp-border-strong); border-bottom-width:2px; border-radius:5px; background:#f9fafb; font-size:11px; font-family:var(--rp-font); color:#374151; }
581
+ .kbd-el-plus { color:#9ca3af; font-size:11px; }
582
+ split-pane, split-pane { display:grid; grid-template-columns:var(--snap-columns,1fr 1fr); width:fit-content; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
583
+ split-pane > *, split-pane > * { padding:14px; }
584
+ split-pane > *:not(:last-child), split-pane > *:not(:last-child) { border-right:1px solid var(--rp-border); }
585
+ divider-el, divider-el { display:block; height:1px; background:var(--rp-border); margin:12px 0; }
586
+ divider-el.divider-el-v, divider-el.divider-el-v { display:inline-block; width:1px; height:auto; align-self:stretch; margin:0 12px; }
587
+ spacer-el, spacer-el { display:block; height:var(--snap-size,16px); }
407
588
 
408
589
  /* --- iOS --- */
409
- snap-ios-navbar, rp-ios-navbar { display:block; background:rgba(249,249,249,.94); border-bottom:1px solid #d8d8dc; padding:6px 12px; font-family:-apple-system,BlinkMacSystemFont,sans-serif; }
410
- .rp-ios-navbar-row { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; min-height:36px; }
590
+ ios-navbar, ios-navbar { display:block; background:rgba(249,249,249,.94); border-bottom:1px solid #d8d8dc; padding:6px 12px; font-family:-apple-system,BlinkMacSystemFont,sans-serif; }
591
+ .ios-navbar-row { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; min-height:36px; }
411
592
  .rp-ios-nav-leading { display:flex; align-items:center; gap:2px; color:#007aff; font-size:15px; }
412
593
  .rp-ios-nav-title { text-align:center; font-weight:600; font-size:16px; color:#000; }
413
594
  .rp-ios-nav-trailing { text-align:right; color:#007aff; font-size:15px; }
414
595
  .rp-ios-nav-large { font-size:30px; font-weight:700; color:#000; padding:2px 2px 6px; }
415
- snap-ios-tabbar, rp-ios-tabbar { display:flex; background:rgba(249,249,249,.94); border-top:1px solid #d8d8dc; padding:6px 0 4px; }
596
+ ios-tabbar, ios-tabbar { display:flex; background:rgba(249,249,249,.94); border-top:1px solid #d8d8dc; padding:6px 0 4px; }
416
597
  .rp-ios-tab { flex:1; display:flex; flex-direction:column; align-items:center; gap:2px; color:#8e8e93; font-size:10px; }
417
598
  .rp-ios-tab.active { color:#007aff; }
418
599
  .rp-ios-tab-label { font-size:10px; }
419
- snap-ios-list, rp-ios-list { display:block; border-radius:10px; background:#fff; overflow:hidden; width:fit-content; min-width:300px; border:1px solid #e5e5ea; font-family:-apple-system,sans-serif; }
420
- .rp-ios-list-header { padding:6px 16px; font-size:13px; color:#6d6d72; background:#f2f2f7; text-transform:none; }
421
- snap-ios-list-item, rp-ios-list-item { display:flex; align-items:center; gap:10px; padding:11px 16px; border-bottom:1px solid #e5e5ea; font-size:15px; color:#000; }
422
- snap-ios-list-item:last-child, rp-ios-list-item:last-child { border-bottom:0; }
600
+ ios-list, ios-list { display:block; border-radius:10px; background:#fff; overflow:hidden; width:fit-content; min-width:300px; border:1px solid #e5e5ea; font-family:-apple-system,sans-serif; }
601
+ .ios-list-header { padding:6px 16px; font-size:13px; color:#6d6d72; background:#f2f2f7; text-transform:none; }
602
+ ios-list-item, ios-list-item { display:flex; align-items:center; gap:10px; padding:11px 16px; border-bottom:1px solid #e5e5ea; font-size:15px; color:#000; }
603
+ ios-list-item:last-child, ios-list-item:last-child { border-bottom:0; }
423
604
  .rp-ios-li-icon { display:grid; place-items:center; width:28px; height:28px; border-radius:6px; background:#007aff; color:#fff; }
424
605
  .rp-ios-li-label { flex:1; }
425
606
  .rp-ios-li-detail { color:#8e8e93; }
426
607
  .rp-ios-li-chevron { color:#c7c7cc; }
427
- snap-ios-action-sheet, rp-ios-action-sheet { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:320px; padding:8px; font-family:-apple-system,sans-serif; }
608
+ ios-action-sheet, ios-action-sheet { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:320px; padding:8px; font-family:-apple-system,sans-serif; }
428
609
  .rp-ios-as-group { border-radius:14px; overflow:hidden; background:rgba(255,255,255,.82); backdrop-filter:blur(20px); }
429
610
  .rp-ios-as-title { padding:14px; text-align:center; font-size:13px; color:#8e8e93; border-bottom:1px solid #d1d1d6; }
430
611
  .rp-ios-as-action { padding:16px; text-align:center; font-size:18px; color:#007aff; border-bottom:1px solid #d1d1d6; }
431
612
  .rp-ios-as-action:last-child { border-bottom:0; }
432
613
  .rp-ios-as-action.destructive { color:#ff3b30; }
433
614
  .rp-ios-as-action.cancel { font-weight:600; }
434
- snap-ios-alert, rp-ios-alert { display:block; width:270px; border-radius:14px; overflow:hidden; background:rgba(255,255,255,.92); backdrop-filter:blur(20px); font-family:-apple-system,sans-serif; }
435
- .rp-ios-alert-body { padding:18px 16px 14px; text-align:center; }
436
- .rp-ios-alert-title { font-size:17px; font-weight:600; color:#000; }
437
- .rp-ios-alert-msg { margin-top:3px; font-size:13px; color:#000; }
438
- .rp-ios-alert-actions { display:flex; border-top:1px solid #d1d1d6; }
439
- .rp-ios-alert-btn { flex:1; padding:11px; text-align:center; font-size:17px; color:#007aff; }
440
- .rp-ios-alert-btn.primary { font-weight:600; }
441
- .rp-ios-alert-btn:not(:last-child) { border-right:1px solid #d1d1d6; }
442
- snap-ios-switch, rp-ios-switch { display:inline-flex; align-items:center; gap:8px; font-family:-apple-system,sans-serif; font-size:15px; }
443
- .rp-ios-switch-track { width:51px; height:31px; border-radius:999px; background:#34c759; padding:2px; }
444
- .rp-ios-switch-dot { display:block; width:27px; height:27px; border-radius:50%; background:#fff; margin-left:20px; box-shadow:0 2px 4px rgba(0,0,0,.2); }
445
- snap-ios-segmented, rp-ios-segmented { display:inline-flex; padding:2px; border-radius:9px; background:#767680; background:rgba(118,118,128,.12); gap:2px; font-family:-apple-system,sans-serif; }
615
+ ios-alert, ios-alert { display:block; width:270px; border-radius:14px; overflow:hidden; background:rgba(255,255,255,.92); backdrop-filter:blur(20px); font-family:-apple-system,sans-serif; }
616
+ .ios-alert-body { padding:18px 16px 14px; text-align:center; }
617
+ .ios-alert-title { font-size:17px; font-weight:600; color:#000; }
618
+ .ios-alert-msg { margin-top:3px; font-size:13px; color:#000; }
619
+ .ios-alert-actions { display:flex; border-top:1px solid #d1d1d6; }
620
+ .ios-alert-btn { flex:1; padding:11px; text-align:center; font-size:17px; color:#007aff; }
621
+ .ios-alert-btn.primary { font-weight:600; }
622
+ .ios-alert-btn:not(:last-child) { border-right:1px solid #d1d1d6; }
623
+ ios-switch, ios-switch { display:inline-flex; align-items:center; gap:8px; font-family:-apple-system,sans-serif; font-size:15px; }
624
+ .ios-switch-track { width:51px; height:31px; border-radius:999px; background:#34c759; padding:2px; }
625
+ .ios-switch-dot { display:block; width:27px; height:27px; border-radius:50%; background:#fff; margin-left:20px; }
626
+ ios-segmented, ios-segmented { display:inline-flex; padding:2px; border-radius:9px; background:#767680; background:rgba(118,118,128,.12); gap:2px; font-family:-apple-system,sans-serif; }
446
627
  .rp-ios-seg-item { padding:6px 16px; border-radius:7px; font-size:13px; color:#000; }
447
- .rp-ios-seg-item.active { background:#fff; font-weight:600; box-shadow:0 1px 3px rgba(0,0,0,.12); }
448
- snap-ios-button, rp-ios-button { display:inline-grid; place-items:center; min-height:34px; padding:0 16px; border-radius:8px; background:#007aff; color:#fff; font-size:15px; font-weight:600; font-family:-apple-system,sans-serif; }
449
- snap-ios-button[variant="tinted"], rp-ios-button[variant="tinted"] { background:rgba(0,122,255,.15); color:#007aff; }
450
- snap-ios-button[variant="plain"], rp-ios-button[variant="plain"] { background:transparent; color:#007aff; }
451
- snap-ios-search, rp-ios-search { display:inline-flex; align-items:center; gap:6px; width:280px; height:36px; padding:0 10px; border-radius:10px; background:rgba(118,118,128,.12); color:#8e8e93; font-size:15px; font-family:-apple-system,sans-serif; }
452
- snap-ios-stepper, rp-ios-stepper { display:inline-flex; align-items:center; border-radius:8px; background:rgba(118,118,128,.12); }
628
+ .rp-ios-seg-item.active { background:#fff; font-weight:600; }
629
+ ios-button, ios-button { display:inline-grid; place-items:center; min-height:34px; padding:0 16px; border-radius:8px; background:#007aff; color:#fff; font-size:15px; font-weight:600; font-family:-apple-system,sans-serif; }
630
+ ios-button[variant="tinted"], ios-button[variant="tinted"] { background:rgba(0,122,255,.15); color:#007aff; }
631
+ ios-button[variant="plain"], ios-button[variant="plain"] { background:transparent; color:#007aff; }
632
+ ios-search, ios-search { display:inline-flex; align-items:center; gap:6px; width:280px; height:36px; padding:0 10px; border-radius:10px; background:rgba(118,118,128,.12); color:#8e8e93; font-size:15px; font-family:-apple-system,sans-serif; }
633
+ ios-stepper, ios-stepper { display:inline-flex; align-items:center; border-radius:8px; background:rgba(118,118,128,.12); }
453
634
  .rp-ios-step { display:grid; place-items:center; width:46px; height:32px; color:#000; }
454
635
  .rp-ios-step-div { width:1px; height:18px; background:rgba(0,0,0,.15); }
455
636
 
456
637
  /* --- macOS --- */
457
- snap-macos-window, rp-macos-window { display:block; width:fit-content; min-width:480px; border-radius:10px; overflow:hidden; border:1px solid #d1d1d6; background:#fff; box-shadow:0 20px 60px rgba(0,0,0,.25); font-family:-apple-system,sans-serif; }
638
+ macos-window, macos-window { display:block; width:fit-content; min-width:480px; border-radius:10px; overflow:hidden; border:1px solid #d1d1d6; background:#fff; font-family:-apple-system,sans-serif; }
458
639
  .rp-mac-titlebar { display:flex; align-items:center; gap:10px; height:38px; padding:0 14px; background:#ececec; border-bottom:1px solid #d1d1d6; }
459
640
  .rp-mac-lights { display:flex; gap:8px; }
460
641
  .rp-mac-light { width:12px; height:12px; border-radius:50%; }
@@ -463,35 +644,35 @@ snap-macos-window, rp-macos-window { display:block; width:fit-content; min-width
463
644
  .rp-mac-light.max { background:#28c840; }
464
645
  .rp-mac-title { flex:1; text-align:center; font-size:13px; font-weight:600; color:#3c3c43; }
465
646
  .rp-mac-window-body { padding:0; }
466
- snap-macos-toolbar, rp-macos-toolbar { display:flex; align-items:center; gap:10px; padding:8px 14px; background:#f6f6f6; border-bottom:1px solid #d1d1d6; }
467
- snap-macos-menubar, rp-macos-menubar { display:flex; align-items:center; gap:18px; height:26px; padding:0 14px; background:rgba(246,246,246,.9); border-bottom:1px solid #d1d1d6; font-size:13px; font-family:-apple-system,sans-serif; }
647
+ macos-toolbar, macos-toolbar { display:flex; align-items:center; gap:10px; padding:8px 14px; background:#f6f6f6; border-bottom:1px solid #d1d1d6; }
648
+ macos-menubar, macos-menubar { display:flex; align-items:center; gap:18px; height:26px; padding:0 14px; background:rgba(246,246,246,.9); border-bottom:1px solid #d1d1d6; font-size:13px; font-family:-apple-system,sans-serif; }
468
649
  .rp-mac-menubar-apple { color:#000; }
469
650
  .rp-mac-menu-title { color:#000; }
470
651
  .rp-mac-menu-title.active { background:#007aff; color:#fff; padding:1px 7px; border-radius:4px; }
471
- snap-macos-sidebar, rp-macos-sidebar { display:flex; flex-direction:column; gap:1px; width:220px; padding:8px; background:rgba(246,246,246,.85); font-family:-apple-system,sans-serif; }
472
- snap-macos-source-item, rp-macos-source-item { display:flex; align-items:center; gap:7px; padding:5px 8px; border-radius:6px; font-size:13px; color:#3c3c43; }
473
- snap-macos-source-item.selected, rp-macos-source-item.selected { background:#007aff; color:#fff; }
652
+ macos-sidebar, macos-sidebar { display:flex; flex-direction:column; gap:1px; width:220px; padding:8px; background:rgba(246,246,246,.85); font-family:-apple-system,sans-serif; }
653
+ macos-source-item, macos-source-item { display:flex; align-items:center; gap:7px; padding:5px 8px; border-radius:6px; font-size:13px; color:#3c3c43; }
654
+ macos-source-item.selected, macos-source-item.selected { background:#007aff; color:#fff; }
474
655
  .rp-mac-source-group { padding:8px 8px 3px; font-size:11px; font-weight:700; color:#8e8e93; text-transform:uppercase; }
475
- snap-macos-segmented, rp-macos-segmented { display:inline-flex; border:1px solid #c4c4c7; border-radius:6px; overflow:hidden; font-family:-apple-system,sans-serif; }
656
+ macos-segmented, macos-segmented { display:inline-flex; border:1px solid #c4c4c7; border-radius:6px; overflow:hidden; font-family:-apple-system,sans-serif; }
476
657
  .rp-mac-seg-item { padding:4px 14px; font-size:13px; color:#000; background:#fff; border-right:1px solid #c4c4c7; }
477
658
  .rp-mac-seg-item:last-child { border-right:0; }
478
659
  .rp-mac-seg-item.active { background:#007aff; color:#fff; }
479
- snap-macos-popover, rp-macos-popover { display:inline-block; position:relative; }
660
+ macos-popover, macos-popover { display:inline-block; position:relative; }
480
661
  .rp-mac-pop-arrow { display:block; width:16px; height:8px; margin:0 auto -1px; clip-path:polygon(50% 0,100% 100%,0 100%); background:#fff; border:1px solid #d1d1d6; }
481
- .rp-mac-pop-body { min-width:220px; padding:12px; border-radius:10px; border:1px solid #d1d1d6; background:#fff; box-shadow:0 12px 40px rgba(0,0,0,.2); }
662
+ .rp-mac-pop-body { min-width:220px; padding:12px; border-radius:10px; border:1px solid #d1d1d6; background:#fff; }
482
663
  .rp-mac-pop-title { font-weight:600; font-size:13px; margin-bottom:8px; }
483
- snap-macos-sheet, rp-macos-sheet { display:block; width:fit-content; min-width:420px; border-radius:10px; background:#fff; box-shadow:0 24px 60px rgba(0,0,0,.3); padding:18px; font-family:-apple-system,sans-serif; }
664
+ macos-sheet, macos-sheet { display:block; width:fit-content; min-width:420px; border-radius:10px; background:#fff; box-shadow:0 24px 60px rgba(0,0,0,.3); padding:18px; font-family:-apple-system,sans-serif; }
484
665
  .rp-mac-sheet-title { font-size:15px; font-weight:700; margin-bottom:12px; }
485
666
  .rp-mac-sheet-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:16px; }
486
- snap-macos-stepper, rp-macos-stepper { display:inline-flex; flex-direction:column; border:1px solid #c4c4c7; border-radius:5px; overflow:hidden; }
667
+ macos-stepper, macos-stepper { display:inline-flex; flex-direction:column; border:1px solid #c4c4c7; border-radius:5px; overflow:hidden; }
487
668
  .rp-mac-step { display:grid; place-items:center; width:22px; height:13px; background:#fff; color:#3c3c43; }
488
669
  .rp-mac-step.up { border-bottom:1px solid #c4c4c7; }
489
- snap-macos-disclosure, rp-macos-disclosure { display:block; font-family:-apple-system,sans-serif; }
670
+ macos-disclosure, macos-disclosure { display:block; font-family:-apple-system,sans-serif; }
490
671
  .rp-mac-disc-head { display:flex; align-items:center; gap:5px; font-size:13px; font-weight:600; color:#000; }
491
672
  .rp-mac-disc-tri { display:inline-flex; transition:none; }
492
673
  .rp-mac-disc-tri.open { transform:rotate(90deg); }
493
674
  .rp-mac-disc-body { padding:8px 0 0 18px; font-size:13px; color:#3c3c43; }
494
- snap-macos-table, rp-macos-table { display:flex; flex-direction:column; width:fit-content; min-width:360px; border:1px solid #d1d1d6; border-radius:6px; overflow:hidden; font-family:-apple-system,sans-serif; }
675
+ macos-table, macos-table { display:flex; flex-direction:column; width:fit-content; min-width:360px; border:1px solid #d1d1d6; border-radius:6px; overflow:hidden; font-family:-apple-system,sans-serif; }
495
676
  .rp-mac-tr { display:flex; }
496
677
  .rp-mac-tr.rp-mac-th { background:#f6f6f6; border-bottom:1px solid #d1d1d6; font-size:12px; font-weight:600; color:#3c3c43; }
497
678
  .rp-mac-tr.alt { background:#f5f8ff; }
@@ -499,14 +680,14 @@ snap-macos-table, rp-macos-table { display:flex; flex-direction:column; width:fi
499
680
  .rp-mac-cell-bar { height:8px; border-radius:3px; background:#e5e7eb; }
500
681
 
501
682
  /* --- agent / conversational UI (Codex-style: single column, de-bubbled) --- */
502
- snap-chat, rp-chat { display:flex; flex-direction:column; gap:24px; width:fit-content; min-width:520px; max-width:680px; }
503
- snap-user-message, rp-user-message, snap-assistant-message, rp-assistant-message { display:block; }
683
+ chat-el, chat-el { display:flex; flex-direction:column; gap:24px; width:fit-content; min-width:520px; max-width:680px; }
684
+ user-message, user-message, assistant-message, assistant-message { display:block; }
504
685
  .rp-msg-role { font-size:12px; font-weight:700; color:#9ca3af; letter-spacing:.02em; margin:0 0 6px; }
505
686
  .rp-msg-content { display:flex; flex-direction:column; gap:12px; font-size:14px; line-height:1.7; color:#1f2937; }
506
- snap-user-message .rp-msg-content, rp-user-message .rp-msg-content { color:#111827; }
507
- snap-system-message, rp-system-message { display:flex; justify-content:center; }
687
+ user-message .rp-msg-content, user-message .rp-msg-content { color:#111827; }
688
+ system-message, system-message { display:flex; justify-content:center; }
508
689
  .rp-sysmsg-line { padding:3px 12px; border-radius:999px; background:#f3f4f6; color:#6b7280; font-size:12px; }
509
- snap-tool-call, rp-tool-call { display:block; width:fit-content; min-width:280px; max-width:600px; }
690
+ tool-call, tool-call { display:block; width:fit-content; min-width:280px; max-width:600px; }
510
691
  .rp-tool-head { display:flex; align-items:center; gap:8px; font-size:13px; color:#6b7280; }
511
692
  .rp-tool-glyph { display:inline-flex; }
512
693
  .rp-tool-glyph.done { color:var(--rp-success); }
@@ -515,30 +696,30 @@ snap-tool-call, rp-tool-call { display:block; width:fit-content; min-width:280px
515
696
  .rp-tool-name { font-family:ui-monospace,Menlo,monospace; font-weight:650; color:#374151; }
516
697
  .rp-tool-args-inline { font-family:ui-monospace,Menlo,monospace; color:#9ca3af; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
517
698
  .rp-tool-body { margin-top:8px; padding-left:21px; }
518
- snap-agent-output, rp-agent-output { display:block; width:fit-content; min-width:280px; max-width:600px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#f8fafc; }
699
+ agent-output, agent-output { display:block; width:fit-content; min-width:280px; max-width:600px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#f8fafc; }
519
700
  .rp-output-head { padding:6px 12px; font-size:12px; color:#6b7280; border-bottom:1px solid var(--rp-border); font-family:ui-monospace,Menlo,monospace; }
520
701
  .rp-output-body { padding:12px; font-family:ui-monospace,Menlo,monospace; font-size:12.5px; line-height:1.6; color:#334155; white-space:pre-wrap; }
521
- snap-reasoning, rp-reasoning { display:block; width:fit-content; min-width:280px; max-width:600px; }
702
+ reasoning-el, reasoning-el { display:block; width:fit-content; min-width:280px; max-width:600px; }
522
703
  .rp-reason-head { display:flex; align-items:center; gap:6px; font-size:13px; color:#9ca3af; }
523
704
  .rp-reason-body { margin-top:8px; padding-left:19px; border-left:2px solid var(--rp-border); font-size:13px; line-height:1.7; color:#6b7280; }
524
- snap-message-actions, rp-message-actions { display:inline-flex; gap:2px; }
705
+ message-actions, message-actions { display:inline-flex; gap:2px; }
525
706
  .rp-msg-action { display:grid; place-items:center; width:28px; height:28px; border-radius:6px; color:#9ca3af; cursor:pointer; }
526
707
  .rp-msg-action:hover { background:#f3f4f6; color:#374151; }
527
- snap-suggestions, rp-suggestions { display:flex; flex-wrap:wrap; gap:8px; }
708
+ suggestions-el, suggestions-el { display:flex; flex-wrap:wrap; gap:8px; }
528
709
  .rp-suggestion { padding:7px 13px; border:1px solid var(--rp-border); border-radius:8px; font-size:13px; color:#374151; background:#fff; cursor:pointer; }
529
710
  .rp-suggestion:hover { border-color:var(--rp-border-strong); background:#f9fafb; }
530
- snap-typing, rp-typing { display:flex; align-items:center; }
531
- .rp-typing-dots { display:inline-flex; gap:4px; }
532
- .rp-typing-dots > span { width:7px; height:7px; border-radius:50%; background:#c7c7cc; }
533
- snap-composer, rp-composer { display:flex; align-items:center; gap:10px; width:fit-content; min-width:520px; max-width:680px; padding:9px 9px 9px 14px; border:1px solid var(--rp-border-strong); border-radius:14px; background:#fff; }
534
- .rp-composer-attach { display:inline-flex; color:#9ca3af; }
535
- .rp-composer-input { flex:1; font-size:14px; }
536
- .rp-composer-send { display:grid; place-items:center; width:32px; height:32px; border-radius:8px; background:#111827; color:#fff; }
537
- .rp-composer-send.streaming { background:var(--rp-danger); }
538
- snap-citation, rp-citation { display:inline-flex; align-items:center; gap:6px; max-width:280px; padding:3px 9px 3px 3px; border:1px solid var(--rp-border); border-radius:6px; background:#f9fafb; font-size:12px; color:#374151; }
711
+ typing-el, typing-el { display:flex; align-items:center; }
712
+ .typing-el-dots { display:inline-flex; gap:4px; }
713
+ .typing-el-dots > span { width:7px; height:7px; border-radius:50%; background:#c7c7cc; }
714
+ composer-el, composer-el { display:flex; align-items:center; gap:10px; width:fit-content; min-width:520px; max-width:680px; padding:9px 9px 9px 14px; border:1px solid var(--rp-border-strong); border-radius:14px; background:#fff; }
715
+ .composer-el-attach { display:inline-flex; color:#9ca3af; }
716
+ .composer-el-input { flex:1; font-size:14px; }
717
+ .composer-el-send { display:grid; place-items:center; width:32px; height:32px; border-radius:8px; background:#111827; color:#fff; }
718
+ .composer-el-send.streaming { background:var(--rp-danger); }
719
+ citation-el, citation-el { display:inline-flex; align-items:center; gap:6px; max-width:280px; padding:3px 9px 3px 3px; border:1px solid var(--rp-border); border-radius:6px; background:#f9fafb; font-size:12px; color:#374151; }
539
720
  .rp-cite-idx { display:grid; place-items:center; width:17px; height:17px; border-radius:4px; background:#e5e7eb; color:#374151; font-size:11px; font-weight:700; }
540
721
  .rp-cite-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
541
- snap-token-usage, rp-token-usage { display:inline-flex; align-items:center; gap:7px; font-size:12px; color:#9ca3af; }
722
+ token-usage, token-usage { display:inline-flex; align-items:center; gap:7px; font-size:12px; color:#9ca3af; }
542
723
  .rp-token-track { width:90px; height:5px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
543
724
  .rp-token-fill { display:block; height:100%; background:#9ca3af; }
544
725
  `;
@@ -573,7 +754,7 @@ class RpAnnotation extends HTMLElement {
573
754
  } else {
574
755
  const parentSection = ((_a = this.closest("[data-rp-section]")) == null ? void 0 : _a.dataset.rpSection) ?? "";
575
756
  const siblings = this.parentElement ? Array.from(this.parentElement.children).filter(
576
- (el) => el.tagName.toLowerCase() === "rp-annotation" || el.tagName.toLowerCase() === "proto-annotation"
757
+ (el) => el.tagName.toLowerCase() === "annotation-el" || el.tagName.toLowerCase() === "annotation-el"
577
758
  ) : [];
578
759
  const idx = siblings.indexOf(this) + 1;
579
760
  sectionPath = parentSection ? `${parentSection}-${idx}` : String(idx);
@@ -581,14 +762,14 @@ class RpAnnotation extends HTMLElement {
581
762
  this.dataset.rpSection = sectionPath;
582
763
  const marker = document.createElement("span");
583
764
  const kind = id ? "drop" : depth <= 1 ? "circle" : "triangle";
584
- marker.className = `rp-annotation-marker ${kind}`;
765
+ marker.className = `annotation-el-marker ${kind}`;
585
766
  const localIndex = id || sectionPath.split("-").pop() || "";
586
767
  marker.innerHTML = `<span>${escapeHtml(localIndex)}</span>`;
587
768
  const head = document.createElement("div");
588
- head.className = "rp-annotation-head";
769
+ head.className = "annotation-el-head";
589
770
  head.append(marker);
590
771
  const title = document.createElement("span");
591
- title.className = "rp-annotation-title";
772
+ title.className = "annotation-el-title";
592
773
  title.textContent = label;
593
774
  title.addEventListener("click", () => {
594
775
  const url = new URL(location.href);
@@ -598,7 +779,7 @@ class RpAnnotation extends HTMLElement {
598
779
  });
599
780
  head.append(title);
600
781
  const body = document.createElement("div");
601
- body.className = "rp-annotation-body";
782
+ body.className = "annotation-el-body";
602
783
  existing.forEach((n) => body.appendChild(n));
603
784
  this.append(head, body);
604
785
  this.setupSlicePins();
@@ -610,10 +791,10 @@ class RpAnnotation extends HTMLElement {
610
791
  }
611
792
  // A UI slice inside this annotation may carry data-pin markers on sub-regions.
612
793
  // Render pins on those slices so their numbers connect to the deeper annotations
613
- // that explain them — mirroring how rp-main-view pins top-level regions.
794
+ // that explain them — mirroring how main-view pins top-level regions.
614
795
  setupSlicePins() {
615
796
  var _a;
616
- const body = this.querySelector(":scope > .rp-annotation-body");
797
+ const body = this.querySelector(":scope > .annotation-el-body");
617
798
  if (!body || !body.querySelector("[data-pin]")) return;
618
799
  (_a = this.ro) == null ? void 0 : _a.disconnect();
619
800
  this.scheduleSlicePins(body);
@@ -631,7 +812,7 @@ class RpAnnotation extends HTMLElement {
631
812
  body.querySelectorAll(":scope > .rp-pin").forEach((p) => p.remove());
632
813
  const bodyRect = body.getBoundingClientRect();
633
814
  body.querySelectorAll("[data-pin]").forEach((target) => {
634
- if (target.closest("rp-annotation, proto-annotation") !== this) return;
815
+ if (target.closest("annotation-el, annotation-el") !== this) return;
635
816
  const pinId = target.dataset.pin;
636
817
  if (!pinId) return;
637
818
  const r = target.getBoundingClientRect();
@@ -647,7 +828,7 @@ class RpAnnotation extends HTMLElement {
647
828
  let d = 0;
648
829
  let p = this.parentElement;
649
830
  while (p) {
650
- if (p.tagName.toLowerCase() === "rp-annotation" || p.tagName.toLowerCase() === "proto-annotation") d++;
831
+ if (p.tagName.toLowerCase() === "annotation-el" || p.tagName.toLowerCase() === "annotation-el") d++;
651
832
  p = p.parentElement;
652
833
  }
653
834
  return d;
@@ -666,27 +847,27 @@ class RpEnumItem extends HTMLElement {
666
847
  const children = Array.from(this.childNodes);
667
848
  const parent = this.parentElement;
668
849
  const siblings = parent ? Array.from(parent.children).filter(
669
- (el) => el.tagName.toLowerCase() === "rp-enum-item" || el.tagName.toLowerCase() === "proto-enum-item"
850
+ (el) => el.tagName.toLowerCase() === "enum-item" || el.tagName.toLowerCase() === "enum-item"
670
851
  ) : [];
671
852
  const idx = siblings.indexOf(this) + 1;
672
853
  const labelEl = document.createElement("span");
673
- labelEl.className = "rp-enum-label";
854
+ labelEl.className = "enum-el-label";
674
855
  const idxBadge = document.createElement("span");
675
- idxBadge.className = "rp-enum-index";
856
+ idxBadge.className = "enum-el-index";
676
857
  idxBadge.textContent = String(idx);
677
858
  const labelText = document.createElement("span");
678
- labelText.className = "rp-enum-label-text";
859
+ labelText.className = "enum-el-label-text";
679
860
  labelText.textContent = attr(this, "label", "State");
680
861
  const description = attr(this, "description");
681
862
  if (description) {
682
863
  const desc = document.createElement("span");
683
- desc.className = "rp-enum-description";
864
+ desc.className = "enum-el-description";
684
865
  desc.textContent = description;
685
866
  labelText.appendChild(desc);
686
867
  }
687
868
  labelEl.append(idxBadge, labelText);
688
869
  const content = document.createElement("div");
689
- content.className = "rp-enum-content";
870
+ content.className = "enum-el-content";
690
871
  children.forEach((n) => content.appendChild(n));
691
872
  this.append(labelEl, content);
692
873
  }
@@ -738,7 +919,10 @@ class RpMainView extends HTMLElement {
738
919
  disconnectedCallback() {
739
920
  var _a;
740
921
  (_a = this.ro) == null ? void 0 : _a.disconnect();
741
- if (this.frame) cancelAnimationFrame(this.frame);
922
+ if (this.frame) {
923
+ cancelAnimationFrame(this.frame);
924
+ this.frame = 0;
925
+ }
742
926
  }
743
927
  scheduleRender() {
744
928
  if (this.frame) return;
@@ -806,26 +990,26 @@ class RpPage extends HTMLElement {
806
990
  this.removeAttribute("title");
807
991
  const existing = Array.from(this.childNodes);
808
992
  const header = document.createElement("div");
809
- header.className = "rp-page-header";
810
- header.innerHTML = `<div class="rp-page-title-row"><h1 class="rp-page-title">${escapeHtml(pageTitle)}</h1><span class="rp-page-route">${escapeHtml(route)}</span></div><p class="rp-page-description">${escapeHtml(description)}</p>`;
993
+ header.className = "page-el-header";
994
+ header.innerHTML = `<div class="page-el-title-row"><h1 class="page-el-title">${escapeHtml(pageTitle)}</h1><span class="page-el-route">${escapeHtml(route)}</span></div><p class="page-el-description">${escapeHtml(description)}</p>`;
811
995
  const body = document.createElement("div");
812
- body.className = "rp-page-body";
996
+ body.className = "page-el-body";
813
997
  const main = document.createElement("main");
814
- main.className = "rp-page-main";
998
+ main.className = "page-el-main";
815
999
  const pane = document.createElement("aside");
816
- pane.className = "rp-annotation-pane";
1000
+ pane.className = "annotation-el-pane";
817
1001
  pane.setAttribute("aria-label", "Annotations");
818
1002
  const paneInner = document.createElement("div");
819
- paneInner.className = "rp-annotation-pane-inner";
1003
+ paneInner.className = "annotation-el-pane-inner";
820
1004
  existing.forEach((n) => (isTopAnnotation(n) ? paneInner : body).appendChild(n));
821
1005
  pane.appendChild(paneInner);
822
1006
  main.append(header, body);
823
1007
  const shell = document.createElement("div");
824
- shell.className = "rp-page-shell";
1008
+ shell.className = "page-el-shell";
825
1009
  shell.append(main, pane);
826
1010
  this.appendChild(shell);
827
1011
  requestAnimationFrame(() => {
828
- const mv = body.querySelector("rp-main-view, proto-main-view");
1012
+ const mv = body.querySelector("main-view, main-view");
829
1013
  if (mv) header.style.maxWidth = `${mv.offsetWidth}px`;
830
1014
  });
831
1015
  const go = () => {
@@ -892,7 +1076,7 @@ class SplitPaneElement extends HTMLElement {
892
1076
  class DividerElement extends HTMLElement {
893
1077
  connectedCallback() {
894
1078
  injectStyle();
895
- if (this.hasAttribute("vertical")) this.classList.add("rp-divider-v");
1079
+ if (this.hasAttribute("vertical")) this.classList.add("divider-el-v");
896
1080
  }
897
1081
  }
898
1082
  class SpacerElement extends HTMLElement {
@@ -1005,7 +1189,7 @@ class SelectElement extends HTMLElement {
1005
1189
  const options = csv(this, "options", "选项 A,选项 B,选项 C");
1006
1190
  const value = attr(this, "value", options[0] || "Select");
1007
1191
  const label = attr(this, "label");
1008
- this.innerHTML = `${label ? `<span class="rp-field-label">${escapeHtml(label)}</span>` : ""}<span class="rp-select-control"><span class="rp-select-value">${escapeHtml(value)}</span>${icon("chevron-down")}</span><span class="rp-select-options">${options.map((o) => `<span class="rp-select-option${o === value ? " selected" : ""}">${escapeHtml(o)}</span>`).join("")}</span>`;
1192
+ this.innerHTML = `${label ? `<span class="rp-field-label">${escapeHtml(label)}</span>` : ""}<span class="select-el-control"><span class="select-el-value">${escapeHtml(value)}</span>${icon("chevron-down")}</span><span class="select-el-options">${options.map((o) => `<span class="select-el-option${o === value ? " selected" : ""}">${escapeHtml(o)}</span>`).join("")}</span>`;
1009
1193
  }
1010
1194
  }
1011
1195
  class ButtonElement extends HTMLElement {
@@ -1044,7 +1228,7 @@ class ToggleElement extends HTMLElement {
1044
1228
  injectStyle();
1045
1229
  if (this.dataset.rpReady) return;
1046
1230
  this.dataset.rpReady = "true";
1047
- this.innerHTML = `<span class="rp-toggle-track"><span class="rp-toggle-dot"></span></span><span>${escapeHtml(attr(this, "label", ""))}</span>`;
1231
+ this.innerHTML = `<span class="toggle-el-track"><span class="toggle-el-dot"></span></span><span>${escapeHtml(attr(this, "label", ""))}</span>`;
1048
1232
  }
1049
1233
  }
1050
1234
  class FormElement extends HTMLElement {
@@ -1060,9 +1244,9 @@ class FormItemElement extends HTMLElement {
1060
1244
  const children = Array.from(this.childNodes);
1061
1245
  const label = attr(this, "label");
1062
1246
  const error = attr(this, "error");
1063
- this.innerHTML = `${label ? `<span class="rp-form-label${this.hasAttribute("required") ? " required" : ""}">${escapeHtml(label)}</span>` : ""}`;
1247
+ this.innerHTML = `${label ? `<span class="form-el-label${this.hasAttribute("required") ? " required" : ""}">${escapeHtml(label)}</span>` : ""}`;
1064
1248
  children.forEach((n) => this.appendChild(n));
1065
- if (error) this.insertAdjacentHTML("beforeend", `<span class="rp-form-error">${escapeHtml(error)}</span>`);
1249
+ if (error) this.insertAdjacentHTML("beforeend", `<span class="form-el-error">${escapeHtml(error)}</span>`);
1066
1250
  }
1067
1251
  }
1068
1252
  class DatePickerElement extends FieldElement {
@@ -1077,7 +1261,7 @@ class UploadElement extends HTMLElement {
1077
1261
  this.dataset.rpReady = "true";
1078
1262
  const state = attr(this, "state", "empty");
1079
1263
  if (state === "has-file") this.innerHTML = `${icon("file")}<span>${escapeHtml(attr(this, "file", "document.pdf"))}</span>`;
1080
- else if (state === "uploading") this.innerHTML = `${icon("loader")}<span>上传中...</span><span class="rp-progress-bar" style="width:${escapeHtml(attr(this, "progress", "60"))}%"></span>`;
1264
+ else if (state === "uploading") this.innerHTML = `${icon("loader")}<span>上传中...</span><span class="progress-el-bar" style="width:${escapeHtml(attr(this, "progress", "60"))}%"></span>`;
1081
1265
  else this.innerHTML = `${icon("upload", 24)}<span>${escapeHtml(attr(this, "label", "点击或拖拽文件上传"))}</span>`;
1082
1266
  }
1083
1267
  }
@@ -1097,7 +1281,7 @@ class ProgressElement extends HTMLElement {
1097
1281
  const value = attr(this, "value", "40");
1098
1282
  this.style.setProperty("--progress", `${value}%`);
1099
1283
  const kind = attr(this, "kind", attr(this, "style"));
1100
- this.innerHTML = kind === "circle" ? `${escapeHtml(value)}%` : '<span class="rp-progress-bar"></span>';
1284
+ this.innerHTML = kind === "circle" ? `${escapeHtml(value)}%` : '<span class="progress-el-bar"></span>';
1101
1285
  }
1102
1286
  }
1103
1287
  class SliderElement extends HTMLElement {
@@ -1110,7 +1294,7 @@ class SliderElement extends HTMLElement {
1110
1294
  const value = intAttr(this, "value", 40);
1111
1295
  const pct = max > min ? Math.max(0, Math.min(100, (value - min) / (max - min) * 100)) : 0;
1112
1296
  const label = attr(this, "label");
1113
- this.innerHTML = `${label ? `<span class="rp-field-label">${escapeHtml(label)}</span>` : ""}<span class="rp-slider-track"><span class="rp-slider-fill" style="width:${pct}%"></span><span class="rp-slider-thumb" style="left:${pct}%"></span></span>${this.hasAttribute("show-value") ? `<span class="rp-slider-value">${value}</span>` : ""}`;
1297
+ this.innerHTML = `${label ? `<span class="rp-field-label">${escapeHtml(label)}</span>` : ""}<span class="slider-el-track"><span class="slider-el-fill" style="width:${pct}%"></span><span class="slider-el-thumb" style="left:${pct}%"></span></span>${this.hasAttribute("show-value") ? `<span class="slider-el-value">${value}</span>` : ""}`;
1114
1298
  }
1115
1299
  }
1116
1300
  class RangeElement extends HTMLElement {
@@ -1125,7 +1309,7 @@ class RangeElement extends HTMLElement {
1125
1309
  const span = max - min || 1;
1126
1310
  const l = (low - min) / span * 100;
1127
1311
  const h = (high - min) / span * 100;
1128
- this.innerHTML = `<span class="rp-slider-track"><span class="rp-slider-fill" style="left:${l}%;width:${h - l}%"></span><span class="rp-slider-thumb" style="left:${l}%"></span><span class="rp-slider-thumb" style="left:${h}%"></span></span>`;
1312
+ this.innerHTML = `<span class="slider-el-track"><span class="slider-el-fill" style="left:${l}%;width:${h - l}%"></span><span class="slider-el-thumb" style="left:${l}%"></span><span class="slider-el-thumb" style="left:${h}%"></span></span>`;
1129
1313
  }
1130
1314
  }
1131
1315
  class NumberInputElement extends HTMLElement {
@@ -1202,7 +1386,7 @@ class ListElement extends HTMLElement {
1202
1386
  this.dataset.rpReady = "true";
1203
1387
  const items = intAttr(this, "items", 3);
1204
1388
  const state = attr(this, "state");
1205
- this.innerHTML = Array.from({ length: items }, (_, i) => `<snap-list-item label="${["全部", "未读", "@ 我", "已归档", "设置"][i] || `Item ${i + 1}`}" icon="${["inbox", "message-square", "at-sign", "archive", "settings"][i] || "file"}"${state === "first-selected" && i === 0 ? ' state="selected"' : ""}></snap-list-item>`).join("");
1389
+ this.innerHTML = Array.from({ length: items }, (_, i) => `<list-item label="${["全部", "未读", "@ 我", "已归档", "设置"][i] || `Item ${i + 1}`}" icon="${["inbox", "message-square", "at-sign", "archive", "settings"][i] || "file"}"${state === "first-selected" && i === 0 ? ' state="selected"' : ""}></list-item>`).join("");
1206
1390
  }
1207
1391
  }
1208
1392
  class ListItemElement extends HTMLElement {
@@ -1214,7 +1398,7 @@ class ListItemElement extends HTMLElement {
1214
1398
  const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "Item");
1215
1399
  const badge = attr(this, "badge");
1216
1400
  const ic = attr(this, "icon");
1217
- this.innerHTML = `${ic ? icon(ic) : ""}<span class="rp-list-label">${escapeHtml(label)}</span>${badge ? `<span class="rp-list-badge">${escapeHtml(badge)}</span>` : ""}`;
1401
+ this.innerHTML = `${ic ? icon(ic) : ""}<span class="list-el-label">${escapeHtml(label)}</span>${badge ? `<span class="list-el-badge">${escapeHtml(badge)}</span>` : ""}`;
1218
1402
  }
1219
1403
  }
1220
1404
  class TabsElement extends HTMLElement {
@@ -1227,7 +1411,7 @@ class TabsElement extends HTMLElement {
1227
1411
  var _a;
1228
1412
  const label = child.getAttribute("label") || ((_a = child.textContent) == null ? void 0 : _a.trim()) || "";
1229
1413
  const isActive = Number.isFinite(numeric) ? i === numeric : label === active;
1230
- child.classList.toggle("rp-tab-active", isActive);
1414
+ child.classList.toggle("tab-el-active", isActive);
1231
1415
  });
1232
1416
  }
1233
1417
  }
@@ -1239,7 +1423,7 @@ class TabElement extends HTMLElement {
1239
1423
  this.dataset.rpReady = "true";
1240
1424
  const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "Tab");
1241
1425
  const badge = attr(this, "badge");
1242
- this.innerHTML = `<span>${escapeHtml(label)}</span>${badge ? `<span class="rp-list-badge">${escapeHtml(badge)}</span>` : ""}`;
1426
+ this.innerHTML = `<span>${escapeHtml(label)}</span>${badge ? `<span class="list-el-badge">${escapeHtml(badge)}</span>` : ""}`;
1243
1427
  }
1244
1428
  }
1245
1429
  class PaginationElement extends HTMLElement {
@@ -1252,7 +1436,7 @@ class PaginationElement extends HTMLElement {
1252
1436
  const pageSize = intAttr(this, "page-size", 10);
1253
1437
  const pages = Math.max(1, Math.ceil(total / pageSize));
1254
1438
  const visible = Array.from({ length: Math.min(pages, 5) }, (_, i) => i + 1);
1255
- this.innerHTML = `<span class="rp-page-btn">${icon("chevron-left", 14)}</span>${visible.map((p) => `<span class="rp-page-btn${p === current ? " active" : ""}">${p}</span>`).join("")}<span class="rp-page-btn">${icon("chevron-right", 14)}</span><span>共 ${total} 条</span>`;
1439
+ this.innerHTML = `<span class="page-el-btn">${icon("chevron-left", 14)}</span>${visible.map((p) => `<span class="page-el-btn${p === current ? " active" : ""}">${p}</span>`).join("")}<span class="page-el-btn">${icon("chevron-right", 14)}</span><span>共 ${total} 条</span>`;
1256
1440
  }
1257
1441
  }
1258
1442
  class StepsElement extends HTMLElement {
@@ -1271,7 +1455,7 @@ class BreadcrumbElement extends HTMLElement {
1271
1455
  if (this.dataset.rpReady) return;
1272
1456
  this.dataset.rpReady = "true";
1273
1457
  const items = csv(this, "items", "首页,当前页");
1274
- this.innerHTML = items.map((item, i) => `<span class="${i === items.length - 1 ? "rp-breadcrumb-current" : ""}">${escapeHtml(item)}</span>${i < items.length - 1 ? "<span>/</span>" : ""}`).join("");
1458
+ this.innerHTML = items.map((item, i) => `<span class="${i === items.length - 1 ? "breadcrumb-el-current" : ""}">${escapeHtml(item)}</span>${i < items.length - 1 ? "<span>/</span>" : ""}`).join("");
1275
1459
  }
1276
1460
  }
1277
1461
  class SegmentedElement extends HTMLElement {
@@ -1301,7 +1485,7 @@ class ContextMenuElement extends HTMLElement {
1301
1485
  if (this.dataset.rpReady || this.children.length) return;
1302
1486
  this.dataset.rpReady = "true";
1303
1487
  const items = csv(this, "items", "复制,重命名,移动到,删除");
1304
- this.innerHTML = items.map((it) => `<div class="rp-menu-item${it === "删除" ? " danger" : ""}"><span>${escapeHtml(it)}</span></div>`).join("");
1488
+ this.innerHTML = items.map((it) => `<div class="menu-item${it === "删除" ? " danger" : ""}"><span>${escapeHtml(it)}</span></div>`).join("");
1305
1489
  }
1306
1490
  }
1307
1491
  class MenuElement extends HTMLElement {
@@ -1319,7 +1503,7 @@ class MenuItemElement extends HTMLElement {
1319
1503
  const ic = attr(this, "icon");
1320
1504
  const shortcut = attr(this, "shortcut");
1321
1505
  const disabled = attr(this, "state") === "disabled";
1322
- this.innerHTML = `${ic ? icon(ic, 14) : ""}<span class="rp-menu-label">${escapeHtml(label)}</span>${shortcut ? `<span class="rp-menu-shortcut">${escapeHtml(shortcut)}</span>` : ""}`;
1506
+ this.innerHTML = `${ic ? icon(ic, 14) : ""}<span class="menu-el-label">${escapeHtml(label)}</span>${shortcut ? `<span class="menu-el-shortcut">${escapeHtml(shortcut)}</span>` : ""}`;
1323
1507
  if (disabled) this.classList.add("disabled");
1324
1508
  }
1325
1509
  }
@@ -1329,7 +1513,7 @@ class TocElement extends HTMLElement {
1329
1513
  if (this.dataset.rpReady || this.children.length) return;
1330
1514
  this.dataset.rpReady = "true";
1331
1515
  const items = csv(this, "items", "概述,安装,用法,API,常见问题");
1332
- this.innerHTML = items.map((it, i) => `<span class="rp-toc-item${i === 0 ? " active" : ""}">${escapeHtml(it)}</span>`).join("");
1516
+ this.innerHTML = items.map((it, i) => `<span class="toc-el-item${i === 0 ? " active" : ""}">${escapeHtml(it)}</span>`).join("");
1333
1517
  }
1334
1518
  }
1335
1519
  class KbdElement extends HTMLElement {
@@ -1338,7 +1522,7 @@ class KbdElement extends HTMLElement {
1338
1522
  if (this.dataset.rpReady) return;
1339
1523
  this.dataset.rpReady = "true";
1340
1524
  const keys = csv(this, "keys", "⌘,K");
1341
- this.innerHTML = keys.map((k) => `<kbd class="rp-kbd-key">${escapeHtml(k)}</kbd>`).join('<span class="rp-kbd-plus">+</span>');
1525
+ this.innerHTML = keys.map((k) => `<kbd class="kbd-el-key">${escapeHtml(k)}</kbd>`).join('<span class="kbd-el-plus">+</span>');
1342
1526
  }
1343
1527
  }
1344
1528
  function sampleCell(c, j, i) {
@@ -1359,9 +1543,9 @@ class TableElement extends HTMLElement {
1359
1543
  const hasCheckbox = this.hasAttribute("has-checkbox");
1360
1544
  const hasAction = this.hasAttribute("has-action");
1361
1545
  const finalCols = hasAction ? [...cols, "操作"] : cols;
1362
- const headCells = `${hasCheckbox ? '<span class="rp-table-cell">✓</span>' : ""}${finalCols.map((c) => `<span class="rp-table-cell">${escapeHtml(c)}</span>`).join("")}`;
1363
- const body = Array.from({ length: rows }, (_, i) => `<div class="rp-table-row">${hasCheckbox ? `<span class="rp-table-cell"><span class="rp-box">${i === 1 ? icon("check", 12) : ""}</span></span>` : ""}${finalCols.map((c, j) => `<span class="rp-table-cell">${c === "操作" ? '<snap-button label="查看" variant="link"></snap-button>' : escapeHtml(sampleCell(c, j, i))}</span>`).join("")}</div>`).join("");
1364
- this.innerHTML = `<div class="rp-table-row rp-table-head">${headCells}</div>${body}`;
1546
+ const headCells = `${hasCheckbox ? '<span class="table-el-cell">✓</span>' : ""}${finalCols.map((c) => `<span class="table-el-cell">${escapeHtml(c)}</span>`).join("")}`;
1547
+ const body = Array.from({ length: rows }, (_, i) => `<div class="table-row">${hasCheckbox ? `<span class="table-el-cell"><span class="rp-box">${i === 1 ? icon("check", 12) : ""}</span></span>` : ""}${finalCols.map((c, j) => `<span class="table-el-cell">${c === "操作" ? '<button-el label="查看" variant="link"></button-el>' : escapeHtml(sampleCell(c, j, i))}</span>`).join("")}</div>`).join("");
1548
+ this.innerHTML = `<div class="table-row table-el-head">${headCells}</div>${body}`;
1365
1549
  }
1366
1550
  }
1367
1551
  class TableRowElement extends HTMLElement {
@@ -1379,7 +1563,7 @@ class BulkActionBarElement extends HTMLElement {
1379
1563
  this.dataset.rpReady = "true";
1380
1564
  const count = attr(this, "count", "1");
1381
1565
  const actions = csv(this, "actions", "确认,取消");
1382
- this.innerHTML = `${icon("check")}<span>已选 ${escapeHtml(count)} 项</span>${actions.map((a) => `<snap-button label="${escapeHtml(a)}" variant="ghost"></snap-button>`).join("")}`;
1566
+ this.innerHTML = `${icon("check")}<span>已选 ${escapeHtml(count)} 项</span>${actions.map((a) => `<button-el label="${escapeHtml(a)}" variant="ghost"></button-el>`).join("")}`;
1383
1567
  }
1384
1568
  }
1385
1569
  class EmptyElement extends HTMLElement {
@@ -1387,7 +1571,7 @@ class EmptyElement extends HTMLElement {
1387
1571
  injectStyle();
1388
1572
  if (this.dataset.rpReady) return;
1389
1573
  this.dataset.rpReady = "true";
1390
- this.innerHTML = `${icon("empty", 28)}<span class="rp-empty-title">${escapeHtml(attr(this, "label", "暂无数据"))}</span><span class="rp-empty-desc">${escapeHtml(attr(this, "description", ""))}</span>${this.hasAttribute("has-action") ? '<snap-button label="新建" variant="primary" icon="plus"></snap-button>' : ""}`;
1574
+ this.innerHTML = `${icon("empty", 28)}<span class="empty-el-title">${escapeHtml(attr(this, "label", "暂无数据"))}</span><span class="empty-el-desc">${escapeHtml(attr(this, "description", ""))}</span>${this.hasAttribute("has-action") ? '<button-el label="新建" variant="primary" icon="plus"></button-el>' : ""}`;
1391
1575
  }
1392
1576
  }
1393
1577
  class LoadingElement extends HTMLElement {
@@ -1396,7 +1580,7 @@ class LoadingElement extends HTMLElement {
1396
1580
  if (this.dataset.rpReady) return;
1397
1581
  this.dataset.rpReady = "true";
1398
1582
  const rows = intAttr(this, "rows", 3);
1399
- this.innerHTML = attr(this, "kind") === "spinner" || attr(this, "style") === "spinner" ? `<span class="rp-spinner">${icon("loader", 24)}</span>` : Array.from({ length: rows }, (_, i) => `<span class="rp-skeleton-line" style="width:${220 - i * 24}px"></span>`).join("");
1583
+ this.innerHTML = attr(this, "kind") === "spinner" || attr(this, "style") === "spinner" ? `<span class="rp-spinner">${icon("loader", 24)}</span>` : Array.from({ length: rows }, (_, i) => `<span class="skeleton-el-line" style="width:${220 - i * 24}px"></span>`).join("");
1400
1584
  }
1401
1585
  }
1402
1586
  class AlertElement extends HTMLElement {
@@ -1441,11 +1625,11 @@ class ModalElement extends HTMLElement {
1441
1625
  this.style.setProperty("--snap-width", `${attr(this, "width", "480")}px`);
1442
1626
  const children = Array.from(this.childNodes);
1443
1627
  const body = document.createElement("div");
1444
- body.className = "rp-modal-body";
1628
+ body.className = "modal-el-body";
1445
1629
  children.forEach((n) => body.appendChild(n));
1446
- this.innerHTML = `<div class="rp-modal-head"><span>${escapeHtml(attr(this, "title", "标题"))}</span>${icon("x", 14)}</div>`;
1630
+ this.innerHTML = `<div class="modal-el-head"><span>${escapeHtml(attr(this, "title", "标题"))}</span>${icon("x", 14)}</div>`;
1447
1631
  this.appendChild(body);
1448
- if (this.hasAttribute("has-footer")) this.insertAdjacentHTML("beforeend", '<div class="rp-modal-footer"><snap-button label="取消"></snap-button><snap-button label="确认" variant="primary"></snap-button></div>');
1632
+ if (this.hasAttribute("has-footer")) this.insertAdjacentHTML("beforeend", '<div class="modal-el-footer"><button-el label="取消"></button-el><button-el label="确认" variant="primary"></button-el></div>');
1449
1633
  }
1450
1634
  }
1451
1635
  class DrawerElement extends HTMLElement {
@@ -1456,9 +1640,9 @@ class DrawerElement extends HTMLElement {
1456
1640
  this.style.setProperty("--snap-width", `${attr(this, "width", "360")}px`);
1457
1641
  const children = Array.from(this.childNodes);
1458
1642
  const body = document.createElement("div");
1459
- body.className = "rp-drawer-body";
1643
+ body.className = "drawer-el-body";
1460
1644
  children.forEach((n) => body.appendChild(n));
1461
- this.innerHTML = `<div class="rp-drawer-head"><span>${escapeHtml(attr(this, "title", "抽屉"))}</span>${icon("x", 14)}</div>`;
1645
+ this.innerHTML = `<div class="drawer-el-head"><span>${escapeHtml(attr(this, "title", "抽屉"))}</span>${icon("x", 14)}</div>`;
1462
1646
  this.appendChild(body);
1463
1647
  }
1464
1648
  }
@@ -1470,9 +1654,9 @@ class CardElement extends HTMLElement {
1470
1654
  const children = Array.from(this.childNodes);
1471
1655
  const title = attr(this, "title");
1472
1656
  const subtitle = attr(this, "subtitle");
1473
- this.innerHTML = `${this.hasAttribute("has-image") ? `<span class="rp-card-image">${icon("image")} Image</span>` : ""}${title ? `<span class="rp-card-title">${escapeHtml(title)}</span>` : ""}${subtitle ? `<span class="rp-card-subtitle">${escapeHtml(subtitle)}</span>` : ""}`;
1657
+ this.innerHTML = `${this.hasAttribute("has-image") ? `<span class="card-el-image">${icon("image")} Image</span>` : ""}${title ? `<span class="card-el-title">${escapeHtml(title)}</span>` : ""}${subtitle ? `<span class="card-el-subtitle">${escapeHtml(subtitle)}</span>` : ""}`;
1474
1658
  children.forEach((n) => this.appendChild(n));
1475
- if (this.hasAttribute("has-footer")) this.insertAdjacentHTML("beforeend", '<span class="rp-card-footer"><snap-button label="查看" variant="secondary"></snap-button></span>');
1659
+ if (this.hasAttribute("has-footer")) this.insertAdjacentHTML("beforeend", '<span class="card-el-footer"><button-el label="查看" variant="secondary"></button-el></span>');
1476
1660
  }
1477
1661
  }
1478
1662
  class StatCardElement extends HTMLElement {
@@ -1519,9 +1703,9 @@ class TreeItemElement extends HTMLElement {
1519
1703
  const ic = attr(this, "icon");
1520
1704
  const expandable = this.hasAttribute("expanded") || this.hasAttribute("collapsed");
1521
1705
  const expanded = this.hasAttribute("expanded");
1522
- const caret = expandable ? icon(expanded ? "chevron-down" : "chevron-right", 12) : '<span class="rp-tree-spacer"></span>';
1706
+ const caret = expandable ? icon(expanded ? "chevron-down" : "chevron-right", 12) : '<span class="tree-el-spacer"></span>';
1523
1707
  this.style.setProperty("--tree-level", String(level));
1524
- this.innerHTML = `<span class="rp-tree-row${attr(this, "state") === "selected" ? " selected" : ""}">${caret}${icon(ic || (expandable ? "folder" : "file"), 14)}<span class="rp-tree-label">${escapeHtml(label)}</span></span>`;
1708
+ this.innerHTML = `<span class="tree-el-row${attr(this, "state") === "selected" ? " selected" : ""}">${caret}${icon(ic || (expandable ? "folder" : "file"), 14)}<span class="tree-el-label">${escapeHtml(label)}</span></span>`;
1525
1709
  }
1526
1710
  }
1527
1711
  class TimelineElement extends HTMLElement {
@@ -1538,13 +1722,13 @@ class TimelineItemElement extends HTMLElement {
1538
1722
  const label = attr(this, "label");
1539
1723
  const time = attr(this, "time");
1540
1724
  const state = attr(this, "state", "default");
1541
- const dot = `<span class="rp-timeline-dot ${state}"></span>`;
1542
- const head = `<div class="rp-timeline-head"><span class="rp-timeline-label">${escapeHtml(label)}</span>${time ? `<span class="rp-timeline-time">${escapeHtml(time)}</span>` : ""}</div>`;
1725
+ const dot = `<span class="timeline-el-dot ${state}"></span>`;
1726
+ const head = `<div class="timeline-el-head"><span class="timeline-el-label">${escapeHtml(label)}</span>${time ? `<span class="timeline-el-time">${escapeHtml(time)}</span>` : ""}</div>`;
1543
1727
  const body = document.createElement("div");
1544
- body.className = "rp-timeline-content";
1728
+ body.className = "timeline-el-content";
1545
1729
  children.forEach((n) => body.appendChild(n));
1546
- this.innerHTML = `${dot}<div class="rp-timeline-main">${head}</div>`;
1547
- this.querySelector(".rp-timeline-main").appendChild(body);
1730
+ this.innerHTML = `${dot}<div class="timeline-el-main">${head}</div>`;
1731
+ this.querySelector(".timeline-el-main").appendChild(body);
1548
1732
  }
1549
1733
  }
1550
1734
  class CalendarElement extends HTMLElement {
@@ -1577,10 +1761,10 @@ class KanbanColumnElement extends HTMLElement {
1577
1761
  const title = attr(this, "title", "列");
1578
1762
  const count = attr(this, "count");
1579
1763
  const head = document.createElement("div");
1580
- head.className = "rp-kanban-head";
1581
- head.innerHTML = `<span>${escapeHtml(title)}</span>${count ? `<span class="rp-kanban-count">${escapeHtml(count)}</span>` : ""}`;
1764
+ head.className = "kanban-el-head";
1765
+ head.innerHTML = `<span>${escapeHtml(title)}</span>${count ? `<span class="kanban-el-count">${escapeHtml(count)}</span>` : ""}`;
1582
1766
  const body = document.createElement("div");
1583
- body.className = "rp-kanban-body";
1767
+ body.className = "kanban-el-body";
1584
1768
  children.forEach((n) => body.appendChild(n));
1585
1769
  this.append(head, body);
1586
1770
  }
@@ -1592,7 +1776,7 @@ class KanbanCardElement extends HTMLElement {
1592
1776
  this.dataset.rpReady = "true";
1593
1777
  const label = attr(this, "label", "卡片");
1594
1778
  const tag = attr(this, "tag");
1595
- this.innerHTML = `<span class="rp-kanban-card-title">${escapeHtml(label)}</span>${tag ? `<span class="rp-kanban-card-tag">${escapeHtml(tag)}</span>` : ""}`;
1779
+ this.innerHTML = `<span class="kanban-card-title">${escapeHtml(label)}</span>${tag ? `<span class="kanban-card-tag">${escapeHtml(tag)}</span>` : ""}`;
1596
1780
  }
1597
1781
  }
1598
1782
  class CodeBlockElement extends HTMLElement {
@@ -1615,7 +1799,7 @@ class DiffElement extends HTMLElement {
1615
1799
  const body = Array.from({ length: rows }, (_, i) => {
1616
1800
  const kind = i % 3 === 0 ? "add" : i % 3 === 1 ? "del" : "ctx";
1617
1801
  const sign = kind === "add" ? "+" : kind === "del" ? "-" : " ";
1618
- return `<span class="rp-diff-line ${kind}"><span class="rp-diff-sign">${sign}</span><span class="rp-code-bar" style="width:${45 + i * 29 % 45}%"></span></span>`;
1802
+ return `<span class="diff-el-line ${kind}"><span class="diff-el-sign">${sign}</span><span class="rp-code-bar" style="width:${45 + i * 29 % 45}%"></span></span>`;
1619
1803
  }).join("");
1620
1804
  this.innerHTML = body;
1621
1805
  }
@@ -1658,12 +1842,12 @@ class AccordionItemElement extends HTMLElement {
1658
1842
  const label = attr(this, "label", "分节");
1659
1843
  const expanded = this.hasAttribute("expanded");
1660
1844
  const head = document.createElement("div");
1661
- head.className = "rp-accordion-head";
1845
+ head.className = "accordion-el-head";
1662
1846
  head.innerHTML = `${icon(expanded ? "chevron-down" : "chevron-right", 14)}<span>${escapeHtml(label)}</span>`;
1663
1847
  this.appendChild(head);
1664
1848
  if (expanded) {
1665
1849
  const body = document.createElement("div");
1666
- body.className = "rp-accordion-body";
1850
+ body.className = "accordion-el-body";
1667
1851
  children.forEach((n) => body.appendChild(n));
1668
1852
  this.appendChild(body);
1669
1853
  }
@@ -1676,7 +1860,7 @@ class BannerElement extends HTMLElement {
1676
1860
  this.dataset.rpReady = "true";
1677
1861
  const type = attr(this, "type", "info");
1678
1862
  const ic = type === "error" ? "circle-alert" : type === "warning" ? "alert-triangle" : type === "success" ? "circle-check" : "info";
1679
- this.innerHTML = `${icon(ic)}<span class="rp-banner-text"><strong>${escapeHtml(attr(this, "title", "通知"))}</strong>${attr(this, "message") ? ` ${escapeHtml(attr(this, "message"))}` : ""}</span>${this.hasAttribute("has-action") ? '<snap-button label="查看" variant="link"></snap-button>' : ""}${this.hasAttribute("closable") ? icon("x", 14) : ""}`;
1863
+ this.innerHTML = `${icon(ic)}<span class="banner-el-text"><strong>${escapeHtml(attr(this, "title", "通知"))}</strong>${attr(this, "message") ? ` ${escapeHtml(attr(this, "message"))}` : ""}</span>${this.hasAttribute("has-action") ? '<button-el label="查看" variant="link"></button-el>' : ""}${this.hasAttribute("closable") ? icon("x", 14) : ""}`;
1680
1864
  }
1681
1865
  }
1682
1866
  class SkeletonElement extends HTMLElement {
@@ -1686,9 +1870,9 @@ class SkeletonElement extends HTMLElement {
1686
1870
  this.dataset.rpReady = "true";
1687
1871
  const shape = attr(this, "shape", "line");
1688
1872
  if (shape === "avatar") this.innerHTML = '<span class="rp-skel rp-skel-avatar"></span>';
1689
- else if (shape === "card") this.innerHTML = '<span class="rp-skel rp-skel-block"></span><span class="rp-skeleton-line" style="width:70%"></span><span class="rp-skeleton-line" style="width:50%"></span>';
1690
- else if (shape === "list") this.innerHTML = Array.from({ length: 3 }, () => '<span class="rp-skel-row"><span class="rp-skel rp-skel-avatar sm"></span><span class="rp-skeleton-line" style="width:60%"></span></span>').join("");
1691
- else this.innerHTML = '<span class="rp-skeleton-line"></span>';
1873
+ else if (shape === "card") this.innerHTML = '<span class="rp-skel rp-skel-block"></span><span class="skeleton-el-line" style="width:70%"></span><span class="skeleton-el-line" style="width:50%"></span>';
1874
+ else if (shape === "list") this.innerHTML = Array.from({ length: 3 }, () => '<span class="rp-skel-row"><span class="rp-skel rp-skel-avatar sm"></span><span class="skeleton-el-line" style="width:60%"></span></span>').join("");
1875
+ else this.innerHTML = '<span class="skeleton-el-line"></span>';
1692
1876
  }
1693
1877
  }
1694
1878
  class CountdownElement extends HTMLElement {
@@ -1706,7 +1890,7 @@ class ResultElement extends HTMLElement {
1706
1890
  this.dataset.rpReady = "true";
1707
1891
  const status = attr(this, "status", "success");
1708
1892
  const ic = status === "error" ? "circle-x" : status === "empty" ? "empty" : "circle-check";
1709
- this.innerHTML = `<span class="rp-result-icon ${status}">${icon(ic, 40)}</span><span class="rp-result-title">${escapeHtml(attr(this, "title", "操作成功"))}</span><span class="rp-result-desc">${escapeHtml(attr(this, "description", ""))}</span>${this.hasAttribute("has-action") ? '<snap-button label="返回" variant="primary"></snap-button>' : ""}`;
1893
+ this.innerHTML = `<span class="result-el-icon ${status}">${icon(ic, 40)}</span><span class="result-el-title">${escapeHtml(attr(this, "title", "操作成功"))}</span><span class="result-el-desc">${escapeHtml(attr(this, "description", ""))}</span>${this.hasAttribute("has-action") ? '<button-el label="返回" variant="primary"></button-el>' : ""}`;
1710
1894
  }
1711
1895
  }
1712
1896
  class PermissionGateElement extends HTMLElement {
@@ -1772,7 +1956,7 @@ class IosNavbarElement extends HTMLElement {
1772
1956
  const large = this.hasAttribute("large");
1773
1957
  const back = attr(this, "back");
1774
1958
  const trailing = attr(this, "trailing");
1775
- this.innerHTML = `<div class="rp-ios-navbar-row"><span class="rp-ios-nav-leading">${back ? `${icon("chevron-left", 18)}<span>${escapeHtml(back)}</span>` : ""}</span><span class="rp-ios-nav-title${large ? " inline" : ""}">${large ? "" : escapeHtml(title)}</span><span class="rp-ios-nav-trailing">${trailing ? escapeHtml(trailing) : ""}</span></div>${large ? `<div class="rp-ios-nav-large">${escapeHtml(title)}</div>` : ""}`;
1959
+ this.innerHTML = `<div class="ios-navbar-row"><span class="rp-ios-nav-leading">${back ? `${icon("chevron-left", 18)}<span>${escapeHtml(back)}</span>` : ""}</span><span class="rp-ios-nav-title${large ? " inline" : ""}">${large ? "" : escapeHtml(title)}</span><span class="rp-ios-nav-trailing">${trailing ? escapeHtml(trailing) : ""}</span></div>${large ? `<div class="rp-ios-nav-large">${escapeHtml(title)}</div>` : ""}`;
1776
1960
  }
1777
1961
  }
1778
1962
  class IosTabbarElement extends HTMLElement {
@@ -1794,7 +1978,7 @@ class IosListElement extends HTMLElement {
1794
1978
  const header = attr(this, "header");
1795
1979
  if (header) {
1796
1980
  const h = document.createElement("div");
1797
- h.className = "rp-ios-list-header";
1981
+ h.className = "ios-list-header";
1798
1982
  h.textContent = header;
1799
1983
  this.insertBefore(h, this.firstChild);
1800
1984
  }
@@ -1833,7 +2017,7 @@ class IosAlertElement extends HTMLElement {
1833
2017
  const title = attr(this, "title", "提示");
1834
2018
  const message = attr(this, "message", "");
1835
2019
  const actions = csv(this, "actions", "取消,确定");
1836
- this.innerHTML = `<div class="rp-ios-alert-body"><div class="rp-ios-alert-title">${escapeHtml(title)}</div>${message ? `<div class="rp-ios-alert-msg">${escapeHtml(message)}</div>` : ""}</div><div class="rp-ios-alert-actions">${actions.map((a, i) => `<span class="rp-ios-alert-btn${i === actions.length - 1 ? " primary" : ""}">${escapeHtml(a)}</span>`).join("")}</div>`;
2020
+ this.innerHTML = `<div class="ios-alert-body"><div class="ios-alert-title">${escapeHtml(title)}</div>${message ? `<div class="ios-alert-msg">${escapeHtml(message)}</div>` : ""}</div><div class="ios-alert-actions">${actions.map((a, i) => `<span class="ios-alert-btn${i === actions.length - 1 ? " primary" : ""}">${escapeHtml(a)}</span>`).join("")}</div>`;
1837
2021
  }
1838
2022
  }
1839
2023
  class IosSwitchElement extends HTMLElement {
@@ -1842,7 +2026,7 @@ class IosSwitchElement extends HTMLElement {
1842
2026
  if (this.dataset.rpReady) return;
1843
2027
  this.dataset.rpReady = "true";
1844
2028
  const label = attr(this, "label");
1845
- this.innerHTML = `${label ? `<span class="rp-ios-switch-label">${escapeHtml(label)}</span>` : ""}<span class="rp-ios-switch-track"><span class="rp-ios-switch-dot"></span></span>`;
2029
+ this.innerHTML = `${label ? `<span class="ios-switch-label">${escapeHtml(label)}</span>` : ""}<span class="ios-switch-track"><span class="ios-switch-dot"></span></span>`;
1846
2030
  }
1847
2031
  }
1848
2032
  class IosSegmentedElement extends HTMLElement {
@@ -1974,7 +2158,7 @@ class MacSheetElement extends HTMLElement {
1974
2158
  children.forEach((n) => body.appendChild(n));
1975
2159
  this.innerHTML = `<div class="rp-mac-sheet-title">${escapeHtml(title)}</div>`;
1976
2160
  this.appendChild(body);
1977
- this.insertAdjacentHTML("beforeend", '<div class="rp-mac-sheet-actions"><snap-button label="取消"></snap-button><snap-button label="完成" variant="primary"></snap-button></div>');
2161
+ this.insertAdjacentHTML("beforeend", '<div class="rp-mac-sheet-actions"><button-el label="取消"></button-el><button-el label="完成" variant="primary"></button-el></div>');
1978
2162
  }
1979
2163
  }
1980
2164
  class MacStepperElement extends HTMLElement {
@@ -2142,7 +2326,7 @@ class TypingElement extends HTMLElement {
2142
2326
  injectStyle();
2143
2327
  if (this.dataset.rpReady) return;
2144
2328
  this.dataset.rpReady = "true";
2145
- this.innerHTML = `<span class="rp-typing-dots"><span></span><span></span><span></span></span>`;
2329
+ this.innerHTML = `<span class="typing-el-dots"><span></span><span></span><span></span></span>`;
2146
2330
  }
2147
2331
  }
2148
2332
  class ComposerElement extends HTMLElement {
@@ -2153,7 +2337,7 @@ class ComposerElement extends HTMLElement {
2153
2337
  const value = attr(this, "value");
2154
2338
  const state = attr(this, "state", "idle");
2155
2339
  const sendIcon = state === "streaming" ? icon("stop", 16) : icon("send", 16);
2156
- this.innerHTML = `<span class="rp-composer-attach">${icon("paperclip", 16)}</span><span class="rp-composer-input ${value ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || attr(this, "placeholder", "给助手发消息…"))}</span><span class="rp-composer-send ${state}">${sendIcon}</span>`;
2340
+ this.innerHTML = `<span class="composer-el-attach">${icon("paperclip", 16)}</span><span class="composer-el-input ${value ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || attr(this, "placeholder", "给助手发消息…"))}</span><span class="composer-el-send ${state}">${sendIcon}</span>`;
2157
2341
  }
2158
2342
  }
2159
2343
  class CitationElement extends HTMLElement {
@@ -2179,22 +2363,17 @@ class TokenUsageElement extends HTMLElement {
2179
2363
  }
2180
2364
  }
2181
2365
  function registerAll() {
2182
- define("rp-page", RpPage);
2183
- define("proto-page", RpPage);
2184
- define("rp-main-view", RpMainView);
2185
- define("proto-main-view", RpMainView);
2186
- define("rp-annotation", RpAnnotation);
2187
- define("proto-annotation", RpAnnotation);
2188
- define("rp-enum", RpEnum);
2189
- define("proto-enum", RpEnum);
2190
- define("rp-enum-item", RpEnumItem);
2191
- define("proto-enum-item", RpEnumItem);
2366
+ define("page-el", RpPage);
2367
+ define("main-view", RpMainView);
2368
+ define("annotation-el", RpAnnotation);
2369
+ define("enum-el", RpEnum);
2370
+ define("enum-item", RpEnumItem);
2192
2371
  const pairs = [
2193
2372
  // layout
2194
2373
  ["viewport", ViewportElement],
2195
2374
  ["layout", LayoutElement],
2196
2375
  ["panel", PanelElement],
2197
- ["navbar", NavbarElement],
2376
+ ["navigator", NavbarElement],
2198
2377
  ["sidebar", SidebarElement],
2199
2378
  ["logo", LogoElement],
2200
2379
  ["split-pane", SplitPaneElement],
@@ -2320,13 +2499,18 @@ function registerAll() {
2320
2499
  ["citation", CitationElement],
2321
2500
  ["token-usage", TokenUsageElement]
2322
2501
  ];
2502
+ for (const [suffix] of pairs) {
2503
+ if (toComponentTag(suffix) === suffix && !suffix.includes("-"))
2504
+ console.warn(`[rpui] registry tag "${suffix}" missing from RPML vocabulary`);
2505
+ }
2323
2506
  for (const [suffix, ctor] of pairs) {
2324
- define(`snap-${suffix}`, ctor);
2325
- define(`rp-${suffix}`, ctor);
2507
+ define(toComponentTag(suffix), ctor);
2326
2508
  }
2327
2509
  }
2328
2510
  registerAll();
2329
2511
  export {
2330
- registerAll
2512
+ parseToPage,
2513
+ registerAll,
2514
+ rewriteTags
2331
2515
  };
2332
2516
  //# sourceMappingURL=rpui.js.map