@jinntec/jinntap 1.31.0 → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/jinn-tap.css CHANGED
@@ -1,52 +1,924 @@
1
1
  jinn-tap {
2
+ /* Toolbar design tokens — hosts/themes may override these. */
3
+ --jinn-tap-toolbar-bg: #f4f4f4;
4
+ --jinn-tap-toolbar-fg: #1a1a1a;
5
+ --jinn-tap-toolbar-separator: rgba(0, 0, 0, 0.14);
6
+ --jinn-tap-toolbar-hover: rgba(0, 0, 0, 0.06);
7
+ --jinn-tap-toolbar-active: rgba(0, 0, 0, 0.1);
8
+ --jinn-tap-toolbar-mark: rgba(0, 0, 0, 0.12);
9
+ --jinn-tap-toolbar-mark-fg: #1a1a1a;
10
+ --jinn-tap-toolbar-btn-size: 2rem;
11
+ --jinn-tap-toolbar-dropdown-bg: #fff;
12
+ --jinn-tap-toolbar-dropdown-border: rgba(0, 0, 0, 0.16);
13
+ --jinn-tap-toolbar-dropdown-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
14
+ --jinn-tap-toolbar-focus-ring: rgba(0, 90, 180, 0.45);
15
+ /* --jinn-tap-content-max-width, --jinn-tap-connector-panel-width and
16
+ --jinn-tap-chrome-inline are intentionally unset here so hosts can set them
17
+ without losing to this stylesheet when it loads/injects after theirs.
18
+ Consumers fall back via var(--name, default):
19
+ - --jinn-tap-content-max-width: caps editor content width; when a connector
20
+ panel opens, it docks beside the content only if host width fits content +
21
+ panel without shrinking content. Unset/`none` = content fills the editor
22
+ and the panel always overlays. Falls back to `none`.
23
+ - --jinn-tap-connector-panel-width: width of the docked connector panel.
24
+ Falls back to `20rem`.
25
+ - --jinn-tap-chrome-inline: horizontal inset for toolbar/breadcrumb. Falls
26
+ back to `1rem`. */
27
+
2
28
  display: grid;
3
- grid-template-rows: min-content 1fr;
4
- grid-template-columns: 1fr minmax(220px, 460px);
29
+ position: relative;
30
+ grid-template-columns: 1fr;
31
+ grid-template-rows: min-content min-content 1fr min-content;
5
32
  grid-template-areas:
6
- "toolbar aside"
7
- "editor aside";
8
- column-gap: 1rem;
9
- row-gap: .5rem;
33
+ "toolbar"
34
+ "breadcrumb"
35
+ "editor"
36
+ "aside";
10
37
  height: fit-content;
11
- /* Add a bit of space under the viewport to allow one to scroll a bit beyond the end of the
12
- document */
13
- margin-bottom:50vh
14
- }
15
-
16
- jinn-tap[sidebar] {
17
- grid-template-columns: 1fr;
38
+ /* Add a bit of space under the viewport to allow one to scroll a bit beyond the end of the
39
+ document */
40
+ margin-bottom: 50vh;
18
41
  }
19
42
 
20
- jinn-tap > nav {
43
+ /* The toolbar nav only — not the breadcrumb nav, which is also a direct child. */
44
+ jinn-tap > nav:has(.toolbar) {
21
45
  grid-area: toolbar;
22
46
  position: sticky;
23
47
  top: 0;
48
+ z-index: 5;
49
+ margin: 0;
50
+ /* Horizontal inset lives on the toolbar list (see below), not here — host
51
+ themes like Pico apply negative margins to `nav li a` that would otherwise
52
+ pull the first button past the nav padding. */
53
+ padding: 0.5rem 0;
54
+ background-color: var(--jinn-tap-toolbar-bg, var(--jinn-tap-background-color, white));
55
+ border-bottom: 1px solid var(--jinn-tap-toolbar-separator);
56
+ }
57
+
58
+ /*
59
+ * Constrained host layout (`fill`): occupy the parent box and scroll only the
60
+ * editor row. Used by the docs embed and workbench-style hosts. Without `fill`,
61
+ * the component grows with content (page scroll + sticky toolbar).
62
+ */
63
+ jinn-tap[fill] {
64
+ height: 100%;
65
+ min-height: 0;
66
+ max-height: 100%;
67
+ margin-bottom: 0;
68
+ overflow: hidden;
69
+ grid-template-rows: auto auto minmax(0, 1fr) auto;
70
+ }
71
+
72
+ jinn-tap[fill] > nav:has(.toolbar),
73
+ jinn-tap[fill] > nav.navigation-panel {
74
+ position: static;
75
+ top: auto;
76
+ z-index: auto;
77
+ }
78
+
79
+ jinn-tap[fill] .editor-area,
80
+ jinn-tap[fill] .code-area {
81
+ min-height: 0;
82
+ overflow-y: auto;
83
+ overscroll-behavior: contain;
84
+ }
85
+
86
+ /* Isolate from host page chrome that also targets `.toolbar`. */
87
+ jinn-tap .toolbar.jinn-tap-toolbar {
88
+ background: none;
89
+ background-image: none;
90
+ }
91
+
92
+ /* ── Toolbar (usable without host theming) ───────────────────────── */
93
+
94
+ .jinn-tap-toolbar {
95
+ /* Same defaults as on jinn-tap, for when the toolbar is hosted externally. */
96
+ --jinn-tap-toolbar-bg: #f4f4f4;
97
+ --jinn-tap-toolbar-fg: #1a1a1a;
98
+ --jinn-tap-toolbar-separator: rgba(0, 0, 0, 0.14);
99
+ --jinn-tap-toolbar-hover: rgba(0, 0, 0, 0.06);
100
+ --jinn-tap-toolbar-active: rgba(0, 0, 0, 0.1);
101
+ --jinn-tap-toolbar-mark: rgba(0, 0, 0, 0.12);
102
+ --jinn-tap-toolbar-mark-fg: #1a1a1a;
103
+ --jinn-tap-toolbar-btn-size: 2rem;
104
+ --jinn-tap-toolbar-dropdown-bg: #fff;
105
+ --jinn-tap-toolbar-dropdown-border: rgba(0, 0, 0, 0.16);
106
+ --jinn-tap-toolbar-dropdown-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
107
+ --jinn-tap-toolbar-focus-ring: rgba(0, 90, 180, 0.45);
108
+ }
109
+
110
+ .jinn-tap-toolbar,
111
+ jinn-tap .toolbar {
112
+ display: flex;
113
+ flex-wrap: wrap;
114
+ align-items: center;
115
+ gap: 0.3rem;
116
+ list-style: none;
117
+ margin: 0;
118
+ padding: 0 var(--jinn-tap-chrome-inline, 1rem);
119
+ }
120
+
121
+ .jinn-tap-toolbar > li,
122
+ jinn-tap .toolbar > li {
123
+ list-style: none;
124
+ margin: 0;
125
+ padding: 0;
126
+ display: flex;
127
+ align-items: center;
128
+ }
129
+
130
+ /* Visual separators before dropdown groups */
131
+ .jinn-tap-toolbar > li:has(> details.dropdown):not(:first-child),
132
+ jinn-tap .toolbar > li:has(> details.dropdown):not(:first-child) {
133
+ margin-left: 0.45rem;
134
+ padding-left: 0.55rem;
135
+ border-left: 1px solid var(--jinn-tap-toolbar-separator);
136
+ }
137
+
138
+ .jinn-tap-toolbar a,
139
+ jinn-tap .toolbar a,
140
+ .jinn-tap-toolbar label[data-tooltip].toolbar-button,
141
+ jinn-tap label[data-tooltip].toolbar-button {
142
+ color: var(--jinn-tap-toolbar-fg);
143
+ text-decoration: none;
144
+ outline: none;
145
+ box-shadow: none;
146
+ /* Pico's `nav li :where(a)` uses negative margins — cancel them. */
147
+ margin: 0;
148
+ margin-inline: 0;
149
+ }
150
+
151
+ .jinn-tap-toolbar label[data-tooltip].toolbar-button,
152
+ jinn-tap label[data-tooltip].toolbar-button {
153
+ margin: 0;
154
+ cursor: pointer;
155
+ }
156
+
157
+ .jinn-tap-toolbar .toolbar-button,
158
+ jinn-tap .toolbar-button,
159
+ .jinn-tap-toolbar a.outline.toolbar-button,
160
+ jinn-tap .toolbar a.outline.toolbar-button {
161
+ display: inline-flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ width: var(--jinn-tap-toolbar-btn-size);
165
+ height: var(--jinn-tap-toolbar-btn-size);
166
+ min-width: var(--jinn-tap-toolbar-btn-size);
167
+ min-height: var(--jinn-tap-toolbar-btn-size);
168
+ padding: 0;
169
+ border: none;
170
+ border-radius: 5px;
171
+ background: transparent;
172
+ color: var(--jinn-tap-toolbar-fg);
173
+ font-size: inherit;
174
+ line-height: 1;
175
+ cursor: pointer;
176
+ -webkit-appearance: none;
177
+ appearance: none;
178
+ transition: background-color 0.1s ease, color 0.1s ease;
179
+ }
180
+
181
+ .jinn-tap-toolbar .toolbar-button:hover,
182
+ jinn-tap .toolbar-button:hover,
183
+ .jinn-tap-toolbar a.outline.toolbar-button:hover,
184
+ jinn-tap .toolbar a.outline.toolbar-button:hover {
185
+ background: var(--jinn-tap-toolbar-hover);
186
+ color: var(--jinn-tap-toolbar-fg);
187
+ border: none;
188
+ }
189
+
190
+ .jinn-tap-toolbar .toolbar-button:active,
191
+ jinn-tap .toolbar-button:active,
192
+ .jinn-tap-toolbar a.outline.toolbar-button:active,
193
+ jinn-tap .toolbar a.outline.toolbar-button:active {
194
+ background: var(--jinn-tap-toolbar-active);
195
+ }
196
+
197
+ .jinn-tap-toolbar .toolbar-button.active,
198
+ jinn-tap .toolbar-button.active,
199
+ .jinn-tap-toolbar a.outline.toolbar-button.active,
200
+ jinn-tap .toolbar a.outline.toolbar-button.active {
201
+ background: var(--jinn-tap-toolbar-mark);
202
+ color: var(--jinn-tap-toolbar-mark-fg);
203
+ }
204
+
205
+ .jinn-tap-toolbar .toolbar-button.disabled,
206
+ jinn-tap .toolbar-button.disabled,
207
+ .jinn-tap-toolbar .disabled,
208
+ jinn-tap .toolbar .disabled,
209
+ .jinn-tap-toolbar a.outline.toolbar-button.disabled,
210
+ jinn-tap .toolbar a.outline.toolbar-button.disabled {
211
+ opacity: 0.35;
212
+ cursor: not-allowed;
213
+ pointer-events: none;
214
+ }
215
+
216
+ .jinn-tap-toolbar .toolbar-button:focus-visible,
217
+ jinn-tap .toolbar-button:focus-visible,
218
+ .jinn-tap-toolbar a.outline.toolbar-button:focus-visible,
219
+ jinn-tap .toolbar a.outline.toolbar-button:focus-visible,
220
+ .jinn-tap-toolbar details.dropdown > summary:focus-visible,
221
+ jinn-tap .toolbar details.dropdown > summary:focus-visible {
222
+ outline: 2px solid var(--jinn-tap-toolbar-focus-ring);
223
+ outline-offset: 1px;
224
+ }
225
+
226
+ .jinn-tap-toolbar .toolbar-button i,
227
+ jinn-tap .toolbar-button i {
228
+ font-size: 1rem;
229
+ line-height: 1;
230
+ pointer-events: none;
231
+ }
232
+
233
+ /* Dropdown groups */
234
+ .jinn-tap-toolbar details.dropdown,
235
+ jinn-tap .toolbar details.dropdown {
236
+ position: relative;
237
+ margin: 0;
238
+ }
239
+
240
+ .jinn-tap-toolbar details.dropdown > summary,
241
+ jinn-tap .toolbar details.dropdown > summary {
242
+ display: inline-flex;
243
+ align-items: center;
244
+ justify-content: center;
245
+ min-width: var(--jinn-tap-toolbar-btn-size);
246
+ height: var(--jinn-tap-toolbar-btn-size);
247
+ padding: 0 0.35rem;
248
+ border: none;
249
+ border-radius: 5px;
250
+ background: transparent;
251
+ color: var(--jinn-tap-toolbar-fg);
252
+ list-style: none;
253
+ cursor: pointer;
254
+ transition: background-color 0.1s ease;
255
+ }
256
+
257
+ .jinn-tap-toolbar details.dropdown > summary::-webkit-details-marker,
258
+ jinn-tap .toolbar details.dropdown > summary::-webkit-details-marker,
259
+ .jinn-tap-toolbar details.dropdown > summary::marker,
260
+ jinn-tap .toolbar details.dropdown > summary::marker {
261
+ display: none;
262
+ content: '';
263
+ }
264
+
265
+ .jinn-tap-toolbar details.dropdown > summary:hover,
266
+ jinn-tap .toolbar details.dropdown > summary:hover {
267
+ background: var(--jinn-tap-toolbar-hover);
268
+ }
269
+
270
+ .jinn-tap-toolbar details.dropdown[open] > summary,
271
+ jinn-tap .toolbar details.dropdown[open] > summary {
272
+ background: var(--jinn-tap-toolbar-active);
273
+ }
274
+
275
+ .jinn-tap-toolbar details.dropdown > ul,
276
+ jinn-tap .toolbar details.dropdown > ul {
277
+ position: absolute;
278
+ top: calc(100% + 4px);
279
+ left: 0;
280
+ z-index: 30;
281
+ min-width: 11rem;
282
+ margin: 0;
283
+ padding: 0.35rem;
284
+ list-style: none;
285
+ background: var(--jinn-tap-toolbar-dropdown-bg);
286
+ border: 1px solid var(--jinn-tap-toolbar-dropdown-border);
287
+ border-radius: 8px;
288
+ box-shadow: var(--jinn-tap-toolbar-dropdown-shadow);
289
+ }
290
+
291
+ .jinn-tap-toolbar details.dropdown > ul a,
292
+ jinn-tap .toolbar details.dropdown > ul a {
293
+ display: block;
294
+ padding: 0.4rem 0.55rem;
295
+ border: none;
296
+ border-radius: 5px;
297
+ color: var(--jinn-tap-toolbar-fg);
298
+ text-decoration: none;
299
+ white-space: nowrap;
300
+ }
301
+
302
+ .jinn-tap-toolbar details.dropdown > ul a:hover,
303
+ jinn-tap .toolbar details.dropdown > ul a:hover {
304
+ background: var(--jinn-tap-toolbar-hover);
305
+ color: var(--jinn-tap-toolbar-fg);
306
+ }
307
+
308
+ .jinn-tap-toolbar details.dropdown > ul li + li,
309
+ jinn-tap .toolbar details.dropdown > ul li + li {
310
+ margin-top: 0.125rem;
311
+ }
312
+
313
+ .jinn-tap-toolbar details.dropdown i,
314
+ jinn-tap .toolbar details.dropdown i {
315
+ padding-right: 0.5rem;
316
+ }
317
+
318
+ /* Breadcrumb navigation: sits directly below the toolbar. */
319
+ jinn-tap > nav.navigation-panel {
320
+ grid-area: breadcrumb;
321
+ margin: 0;
322
+ /* Same horizontal inset as the toolbar (`--jinn-tap-chrome-inline`). */
323
+ padding: 0.3rem var(--jinn-tap-chrome-inline, 1rem);
24
324
  background-color: var(--jinn-tap-background-color, white);
325
+ border: none;
326
+ border-bottom: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
327
+ /* Host themes (e.g. Pico) set nowrap/ellipsis on [aria-label=breadcrumb]. */
328
+ white-space: normal;
329
+ font-size: 0.78rem;
330
+ line-height: 1.3;
331
+ color: inherit;
25
332
  }
26
333
 
27
- .jinn-tap-aside .user-info {
28
- font-size: 0.75rem;
334
+ /* Nothing to show until the cursor resolves a path — the panel always holds a
335
+ <ul>, so key off whether it has any crumbs. */
336
+ jinn-tap > nav.navigation-panel:not(:has(li)) {
337
+ display: none;
29
338
  }
30
339
 
31
- jinn-tap .editor-area, jinn-tap .code-area {
340
+ jinn-tap > nav.navigation-panel ul {
341
+ display: flex;
342
+ flex-wrap: wrap;
343
+ align-items: center;
344
+ /* Inter-crumb space comes only from the › divider margins. */
345
+ gap: 0;
346
+ list-style: none;
347
+ margin: 0;
348
+ padding: 0;
349
+ }
350
+
351
+ /* Beat Pico's `nav li` / breadcrumb link spacing so crumbs align with the
352
+ toolbar/editor inset instead of being pulled flush to the left edge. */
353
+ jinn-tap > nav.navigation-panel[aria-label='breadcrumb'] ul li {
354
+ list-style: none;
355
+ display: inline-flex;
356
+ align-items: center;
357
+ margin: 0;
358
+ margin-inline-start: 0;
359
+ padding: 0;
360
+ }
361
+
362
+ /* Pico injects its own breadcrumb divider via li::after — suppress it.
363
+ Include [aria-label=breadcrumb] so specificity beats Pico's nav rule. */
364
+ jinn-tap > nav.navigation-panel[aria-label='breadcrumb'] ul li::after {
365
+ content: none;
366
+ display: none;
367
+ }
368
+
369
+ jinn-tap > nav.navigation-panel li + li::before {
370
+ content: '\203A'; /* › */
371
+ margin: 0 0.35rem;
372
+ opacity: 0.55;
373
+ font-weight: 400;
374
+ pointer-events: none;
375
+ }
376
+
377
+ jinn-tap > nav.navigation-panel li:not(:last-child) {
378
+ font-weight: 600;
379
+ }
380
+
381
+ jinn-tap > nav.navigation-panel[aria-label='breadcrumb'] ul li a,
382
+ jinn-tap > nav.navigation-panel[aria-label='breadcrumb'] ul li button {
383
+ display: inline-block;
384
+ margin: 0;
385
+ margin-inline-start: 0;
386
+ /* No horizontal padding — keep crumb text flush with toolbar button edges. */
387
+ padding: 0.08rem 0;
388
+ border: none;
389
+ border-radius: 4px;
390
+ background: none;
391
+ color: inherit;
392
+ font: inherit;
393
+ opacity: 0.75;
394
+ text-decoration: none;
395
+ font-size: inherit;
396
+ line-height: inherit;
397
+ cursor: pointer;
398
+ }
399
+
400
+ jinn-tap > nav.navigation-panel[aria-label='breadcrumb'] ul li a:hover,
401
+ jinn-tap > nav.navigation-panel[aria-label='breadcrumb'] ul li button:hover {
402
+ background: var(--jinn-tap-toolbar-hover, rgba(0, 0, 0, 0.06));
403
+ opacity: 1;
404
+ text-decoration: none;
405
+ }
406
+
407
+ jinn-tap .editor-area,
408
+ jinn-tap .code-area {
32
409
  grid-area: editor;
33
410
  min-height: 1rem;
411
+ width: 100%;
412
+ max-width: var(--jinn-tap-content-max-width, none);
34
413
  }
35
414
 
36
415
  jinn-tap .code-area {
37
416
  text-wrap: wrap;
38
417
  }
39
418
 
40
- jinn-tap .jinn-tap-aside {
419
+ /* Default: attribute panel lives in a bottom dock inside jinn-tap.
420
+ Hosts can move it out with the sidebar="…" attribute and style it themselves. */
421
+ jinn-tap > .jinn-tap-aside {
41
422
  grid-area: aside;
42
423
  background: var(--jinn-tap-background-color, white);
43
- padding: 20px;
44
- max-height: fit-content;
45
- position: sticky;
46
- top: 0;
424
+ padding: 0;
47
425
  z-index: 10;
48
426
  }
49
427
 
428
+ /* Table bubble menu is appended to document.body (see Table extension) so it
429
+ isn't trapped under the attribute dock or auto-placed in the jinn-tap grid. */
430
+ .table-menu {
431
+ z-index: 40;
432
+ }
433
+
434
+ jinn-tap > .jinn-tap-aside .user-info {
435
+ font-size: 0.75rem;
436
+ }
437
+
438
+ jinn-tap > .jinn-tap-aside .user-info:empty {
439
+ display: none;
440
+ }
441
+
442
+ jinn-tap > .jinn-tap-aside .user-info:not(:empty) {
443
+ padding: 0.25rem 0.65rem 0;
444
+ border-top: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
445
+ }
446
+
447
+ /* ── Attribute panel: bottom dock (internal) ─────────────────────── */
448
+
449
+ jinn-tap .attribute-panel:empty {
450
+ display: none;
451
+ }
452
+
453
+ jinn-tap .attribute-panel:not(:empty) {
454
+ display: flex;
455
+ flex-wrap: wrap;
456
+ align-items: center;
457
+ gap: 0.35rem 0.65rem;
458
+ padding: 0.35rem 0.65rem 0.45rem;
459
+ border-top: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
460
+ max-height: 9.5rem;
461
+ overflow-y: auto;
462
+ }
463
+
464
+ jinn-tap .attribute-panel:not(:empty) h4 {
465
+ flex: 0 0 auto;
466
+ margin: 0;
467
+ padding-right: 0.65rem;
468
+ border-right: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
469
+ font-size: 0.85rem;
470
+ font-weight: 700;
471
+ line-height: 1.3;
472
+ }
473
+
474
+ jinn-tap .attribute-panel:not(:empty) > div:not(.occurrences) {
475
+ display: none;
476
+ }
477
+
478
+ jinn-tap > .jinn-tap-aside .attribute-panel form {
479
+ display: flex;
480
+ /* Don't grow — keeps the Apply button beside the fields on wide screens. */
481
+ flex: 0 1 auto;
482
+ flex-wrap: wrap;
483
+ align-items: center;
484
+ gap: 0.35rem 0.75rem;
485
+ min-width: 0;
486
+ margin: 0;
487
+ }
488
+
489
+ jinn-tap > .jinn-tap-aside .attribute-panel fieldset {
490
+ display: flex;
491
+ flex-wrap: wrap;
492
+ align-items: center;
493
+ gap: 0.35rem 0.75rem;
494
+ flex: 1 1 auto;
495
+ border: none;
496
+ padding: 0;
497
+ margin: 0;
498
+ min-width: 0;
499
+ }
500
+
501
+ jinn-tap > .jinn-tap-aside .attribute-panel fieldset label {
502
+ display: inline;
503
+ padding: 0;
504
+ margin: 0;
505
+ font-size: 0.72rem;
506
+ font-weight: 600;
507
+ white-space: nowrap;
508
+ }
509
+
510
+ jinn-tap > .jinn-tap-aside .attribute-panel fieldset label::after {
511
+ content: ':';
512
+ margin-right: 0.2rem;
513
+ font-weight: 400;
514
+ }
515
+
516
+ /* Group each label with its control so flex-wrap keeps the pair together. */
517
+ jinn-tap > .jinn-tap-aside .attribute-panel fieldset .attribute-panel__field {
518
+ display: inline-flex;
519
+ align-items: center;
520
+ gap: 0.35rem;
521
+ flex: 0 0 auto;
522
+ min-width: 0;
523
+ }
524
+
525
+ jinn-tap > .jinn-tap-aside .attribute-panel fieldset input,
526
+ jinn-tap > .jinn-tap-aside .attribute-panel fieldset select {
527
+ display: inline-block;
528
+ width: auto;
529
+ min-width: 4.5rem;
530
+ max-width: 9rem;
531
+ height: auto;
532
+ min-height: 0;
533
+ margin: 0;
534
+ margin-bottom: 0;
535
+ padding: 0.18rem 0.4rem;
536
+ box-sizing: border-box;
537
+ font: inherit;
538
+ font-size: 0.8rem;
539
+ line-height: 1.3;
540
+ }
541
+
542
+ jinn-tap > .jinn-tap-aside .attribute-panel details {
543
+ flex: 1 1 100%;
544
+ margin: 0.15rem 0 0;
545
+ font-size: 0.8rem;
546
+ }
547
+
548
+ jinn-tap > .jinn-tap-aside .attribute-panel footer {
549
+ display: flex;
550
+ flex: 0 0 auto;
551
+ align-items: center;
552
+ margin: 0;
553
+ padding: 0;
554
+ }
555
+
556
+ jinn-tap > .jinn-tap-aside .attribute-panel footer button {
557
+ display: inline-flex;
558
+ align-items: center;
559
+ gap: 0.25rem;
560
+ height: auto;
561
+ min-height: 0;
562
+ margin: 0;
563
+ padding: 0.22rem 0.45rem;
564
+ border: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
565
+ border-radius: 4px;
566
+ background: var(--jinn-tap-background-color, white);
567
+ color: inherit;
568
+ font: inherit;
569
+ font-size: 0.78rem;
570
+ font-weight: 500;
571
+ line-height: 1;
572
+ cursor: pointer;
573
+ }
574
+
575
+ jinn-tap > .jinn-tap-aside .attribute-panel footer button:hover {
576
+ background: var(--jinn-tap-toolbar-hover, rgba(0, 0, 0, 0.06));
577
+ }
578
+
579
+ jinn-tap > .jinn-tap-aside .attribute-panel footer button svg {
580
+ width: 0.95rem;
581
+ height: 0.95rem;
582
+ flex: 0 0 auto;
583
+ }
584
+
585
+ jinn-tap > .jinn-tap-aside .attribute-panel .occurrences {
586
+ flex: 1 1 100%;
587
+ margin: 0.25rem 0 0;
588
+ padding-top: 0.35rem;
589
+ border-top: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
590
+ font-size: 0.78rem;
591
+ max-height: 5.5rem;
592
+ overflow-y: auto;
593
+ }
594
+
595
+ jinn-tap > .jinn-tap-aside .attribute-panel .occurrences h5 {
596
+ margin: 0 0 0.25rem;
597
+ font-size: 0.72rem;
598
+ font-weight: 600;
599
+ text-transform: uppercase;
600
+ letter-spacing: 0.04em;
601
+ opacity: 0.75;
602
+ }
603
+
604
+ jinn-tap > .jinn-tap-aside .attribute-panel .occurrences [role="group"] {
605
+ float: right;
606
+ width: fit-content;
607
+ }
608
+
609
+ jinn-tap > .jinn-tap-aside .attribute-panel .occurrences ul {
610
+ height: auto;
611
+ margin: 0;
612
+ padding: 0;
613
+ list-style: none;
614
+ }
615
+
616
+ jinn-tap > .jinn-tap-aside .attribute-panel .occurrences li {
617
+ list-style: none;
618
+ }
619
+
620
+ /* Attribute panel chrome (connector collapse/expand) */
621
+ .attribute-panel__chrome {
622
+ display: none;
623
+ }
624
+
625
+ .attribute-panel.has-connector > .attribute-panel__chrome {
626
+ display: flex;
627
+ align-items: center;
628
+ justify-content: space-between;
629
+ gap: 0.75rem;
630
+ }
631
+
632
+ .attribute-panel__summary {
633
+ margin: 0;
634
+ min-width: 0;
635
+ overflow: hidden;
636
+ text-overflow: ellipsis;
637
+ white-space: nowrap;
638
+ font-size: 0.85rem;
639
+ font-weight: 600;
640
+ }
641
+
642
+ .attribute-panel__toggle {
643
+ flex: 0 0 auto;
644
+ margin: 0;
645
+ padding: 0.25rem 0.55rem;
646
+ border: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
647
+ border-radius: 4px;
648
+ background: transparent;
649
+ font: inherit;
650
+ font-size: 0.78rem;
651
+ font-weight: 500;
652
+ cursor: pointer;
653
+ }
654
+
655
+ .attribute-panel__toggle:hover {
656
+ background: var(--jinn-tap-toolbar-hover, rgba(0, 0, 0, 0.05));
657
+ }
658
+
659
+ jinn-tap .attribute-panel.has-connector:not(:empty) {
660
+ max-height: none;
661
+ overflow: visible;
662
+ }
663
+
664
+ jinn-tap .attribute-panel.has-connector > .attribute-panel__chrome {
665
+ flex: 1 1 auto;
666
+ min-width: 0;
667
+ }
668
+
669
+ jinn-tap .attribute-panel.has-connector:not(.is-expanded) h4,
670
+ jinn-tap .attribute-panel.has-connector:not(.is-expanded) form,
671
+ jinn-tap .attribute-panel.has-connector:not(.is-expanded) footer,
672
+ jinn-tap .attribute-panel.has-connector:not(.is-expanded) .occurrences,
673
+ jinn-tap .attribute-panel.has-connector:not(.is-expanded) form > details {
674
+ display: none;
675
+ }
676
+
677
+ /* Connector session: drawer over the editor (positioned against jinn-tap). */
678
+ jinn-tap .attribute-panel.has-connector.is-expanded {
679
+ position: absolute;
680
+ top: 0;
681
+ right: 0;
682
+ bottom: 0;
683
+ width: min(80%, 20rem);
684
+ z-index: 16;
685
+ display: flex;
686
+ flex-direction: column;
687
+ flex-wrap: nowrap;
688
+ align-items: stretch;
689
+ gap: 0.65rem;
690
+ max-height: none;
691
+ padding: 0.65rem 0.85rem 0.85rem;
692
+ overflow-x: hidden;
693
+ overflow-y: auto;
694
+ background: var(--jinn-tap-background-color, white);
695
+ border: none;
696
+ border-left: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
697
+ box-shadow: -12px 0 28px rgba(0, 0, 0, 0.14);
698
+ }
699
+
700
+ jinn-tap .attribute-panel.has-connector.is-expanded > .attribute-panel__chrome {
701
+ flex: 0 0 auto;
702
+ padding-bottom: 0.35rem;
703
+ border-bottom: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
704
+ }
705
+
706
+ jinn-tap .attribute-panel.has-connector.is-expanded > .attribute-panel__info:not(:empty) {
707
+ display: block;
708
+ flex: 0 0 auto;
709
+ }
710
+
711
+ .attribute-panel__info .label {
712
+ margin: 0 0 0.15rem;
713
+ font-size: 0.85rem;
714
+ font-weight: 600;
715
+ }
716
+
717
+ .attribute-panel__info .label a {
718
+ color: inherit;
719
+ text-decoration: none;
720
+ }
721
+
722
+ .attribute-panel__info .label a:hover {
723
+ text-decoration: underline;
724
+ }
725
+
726
+ .attribute-panel__info p {
727
+ margin: 0.1rem 0;
728
+ font-size: 0.78rem;
729
+ }
730
+
731
+ jinn-tap .attribute-panel.has-connector.is-expanded form {
732
+ display: flex;
733
+ flex: 0 0 auto;
734
+ flex-direction: column;
735
+ align-items: stretch;
736
+ gap: 0.55rem;
737
+ }
738
+
739
+ jinn-tap .attribute-panel.has-connector.is-expanded fieldset {
740
+ display: grid;
741
+ grid-template-columns: minmax(4.5rem, max-content) minmax(0, 1fr);
742
+ align-items: center;
743
+ column-gap: 0.75rem;
744
+ row-gap: 0.45rem;
745
+ }
746
+
747
+ jinn-tap .attribute-panel.has-connector.is-expanded fieldset .attribute-panel__field {
748
+ display: contents;
749
+ }
750
+
751
+ jinn-tap .attribute-panel.has-connector.is-expanded fieldset label::after {
752
+ content: none;
753
+ }
754
+
755
+ jinn-tap .attribute-panel.has-connector.is-expanded fieldset input,
756
+ jinn-tap .attribute-panel.has-connector.is-expanded fieldset select {
757
+ max-width: none;
758
+ width: 100%;
759
+ }
760
+
761
+ jinn-tap .attribute-panel.has-connector.is-expanded form > details {
762
+ display: block;
763
+ flex: 1 1 auto;
764
+ margin: 0;
765
+ min-height: 0;
766
+ }
767
+
768
+ jinn-tap .attribute-panel.has-connector.is-expanded pb-authority-lookup {
769
+ display: block;
770
+ height: auto;
771
+ max-height: none;
772
+ min-height: 0;
773
+ overflow: visible;
774
+ }
775
+
776
+ jinn-tap .attribute-panel.has-connector.is-expanded pb-authority-lookup::part(output) {
777
+ /* Grow with the viewport when the connector panel has room; still capped. */
778
+ max-height: min(50vh, 32rem);
779
+ overflow-y: auto;
780
+ }
781
+
782
+ /*
783
+ * Authority action buttons (link / edit / add). Icons are inline SVGs that use
784
+ * stroke="currentColor"; requires @teipublisher/pb-components >= 3.6.6 for
785
+ * part="select|…" and built-in .ionicon sizing.
786
+ */
787
+ jinn-tap pb-authority-lookup::part(select) {
788
+ color: var(--jinn-tap-authority-select-fg, #fffefc);
789
+ background: var(--jinn-tap-authority-select-bg, #1a1816);
790
+ border-radius: 4px;
791
+ }
792
+
793
+ jinn-tap pb-authority-lookup::part(select):hover {
794
+ background: var(--jinn-tap-authority-select-bg-hover, #55504a);
795
+ color: var(--jinn-tap-authority-select-fg, #fffefc);
796
+ }
797
+
798
+ jinn-tap pb-authority-lookup::part(edit-entity),
799
+ jinn-tap pb-authority-lookup::part(add-entity) {
800
+ color: var(--jinn-tap-toolbar-fg, #1a1a1a);
801
+ background: var(--jinn-tap-toolbar-hover, rgba(0, 0, 0, 0.06));
802
+ border-radius: 4px;
803
+ }
804
+
805
+ jinn-tap pb-authority-lookup::part(edit-entity):hover,
806
+ jinn-tap pb-authority-lookup::part(add-entity):hover {
807
+ background: var(--jinn-tap-toolbar-active, rgba(0, 0, 0, 0.1));
808
+ }
809
+
810
+ jinn-tap .attribute-panel.has-connector.is-expanded footer {
811
+ margin: 0;
812
+ justify-content: flex-end;
813
+ }
814
+
815
+ jinn-tap .attribute-panel.has-connector.is-expanded .occurrences {
816
+ flex: 1 1 auto;
817
+ max-height: none;
818
+ min-height: 0;
819
+ margin: 0;
820
+ padding-top: 0.5rem;
821
+ overflow: visible;
822
+ }
823
+
824
+ jinn-tap .attribute-panel.has-connector.is-expanded .occurrences ul {
825
+ max-height: none;
826
+ overflow: visible;
827
+ }
828
+
829
+ /* Wide layout: reserve a right column so opening a connector panel does not
830
+ shift the editor. Normal attributes stay in the bottom status bar; only an
831
+ expanded connector panel moves into the reserved column. */
832
+ jinn-tap.is-wide-layout {
833
+ grid-template-columns: minmax(0, 1fr) var(--jinn-tap-connector-panel-width, 20rem);
834
+ grid-template-rows: min-content min-content minmax(0, 1fr) min-content;
835
+ grid-template-areas:
836
+ "toolbar toolbar"
837
+ "breadcrumb breadcrumb"
838
+ "editor reserved"
839
+ "aside aside";
840
+ }
841
+
842
+ jinn-tap.is-wide-layout::after {
843
+ content: '';
844
+ grid-area: reserved;
845
+ min-height: 0;
846
+ pointer-events: none;
847
+ border-left: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
848
+ }
849
+
850
+ jinn-tap.is-wide-layout[fill] {
851
+ grid-template-rows: auto auto minmax(0, 1fr) auto;
852
+ }
853
+
854
+ jinn-tap.is-wide-layout:has(> .jinn-tap-aside .attribute-panel.has-connector.is-expanded) {
855
+ grid-template-rows: min-content min-content minmax(0, 1fr);
856
+ grid-template-areas:
857
+ "toolbar toolbar"
858
+ "breadcrumb breadcrumb"
859
+ "editor aside";
860
+ }
861
+
862
+ jinn-tap.is-wide-layout:has(> .jinn-tap-aside .attribute-panel.has-connector.is-expanded)[fill] {
863
+ grid-template-rows: auto auto minmax(0, 1fr);
864
+ }
865
+
866
+ jinn-tap.is-wide-layout:has(> .jinn-tap-aside .attribute-panel.has-connector.is-expanded)::after {
867
+ display: none;
868
+ }
869
+
870
+ jinn-tap.is-wide-layout:has(> .jinn-tap-aside .attribute-panel.has-connector.is-expanded) > .jinn-tap-aside {
871
+ display: flex;
872
+ flex-direction: column;
873
+ min-height: 0;
874
+ overflow: hidden;
875
+ border-left: 1px solid var(--jinn-tap-toolbar-separator, rgba(0, 0, 0, 0.14));
876
+ }
877
+
878
+ jinn-tap.is-wide-layout .attribute-panel.has-connector.is-expanded {
879
+ position: static;
880
+ top: auto;
881
+ right: auto;
882
+ bottom: auto;
883
+ width: auto;
884
+ flex: 1 1 auto;
885
+ min-height: 0;
886
+ z-index: auto;
887
+ box-shadow: none;
888
+ border-left: none;
889
+ }
890
+
891
+ jinn-tap.is-wide-layout .attribute-panel.has-connector .attribute-panel__toggle {
892
+ display: none;
893
+ }
894
+
895
+ jinn-tap:fullscreen {
896
+ width: 100%;
897
+ height: 100%;
898
+ max-height: none;
899
+ margin-bottom: 0;
900
+ background: var(--jinn-tap-background-color, white);
901
+ grid-template-rows: min-content min-content minmax(0, 1fr) min-content;
902
+ }
903
+
904
+ jinn-tap:fullscreen .editor-area,
905
+ jinn-tap:fullscreen .code-area {
906
+ min-height: 0;
907
+ overflow-y: auto;
908
+ }
909
+
910
+ /* External sidebar host (sidebar="…"): traditional stacked form layout.
911
+ Internal dock styles above use `jinn-tap …` / `jinn-tap > .jinn-tap-aside`
912
+ and win on specificity when the panel lives inside the component. */
913
+ .jinn-tap-aside {
914
+ background: var(--jinn-tap-background-color, white);
915
+ padding: 20px;
916
+ }
917
+
918
+ .jinn-tap-aside .user-info {
919
+ font-size: 0.75rem;
920
+ }
921
+
50
922
  .jinn-tap-aside .attribute-panel > div {
51
923
  overflow-y: auto;
52
924
  }
@@ -85,9 +957,10 @@ jinn-tap .jinn-tap-aside {
85
957
  margin-top: 1rem;
86
958
  }
87
959
 
88
- .jinn-tap-aside pb-authority-lookup {
960
+ .jinn-tap-aside pb-authority-lookup::part(output) {
961
+ /* Only the results list scrolls; the search header above stays visible */
962
+ max-height: min(50vh, 32rem);
89
963
  overflow-y: auto;
90
- height: 20rem;
91
964
  }
92
965
 
93
966
  .jinn-tap-aside .occurrences {
@@ -111,16 +984,6 @@ jinn-tap .jinn-tap-aside {
111
984
  list-style: none;
112
985
  }
113
986
 
114
- .jinn-tap-toolbar .toolbar .disabled {
115
- opacity: 0.5;
116
- cursor: not-allowed;
117
- pointer-events: none;
118
- }
119
-
120
- .jinn-tap-toolbar .toolbar details i {
121
- padding-right: 0.5rem;
122
- }
123
-
124
987
  jinn-tap .ProseMirror {
125
988
  outline: none;
126
989
  height: 100%;
@@ -174,3 +1037,29 @@ jinn-tap .ProseMirror {
174
1037
  .jinn-tap.overlay {
175
1038
  border: 2px dotted var(--jinn-tap-overlay-color, rgb(255, 123, 0));
176
1039
  }
1040
+
1041
+ /* Elements not described by the schema, preserved generically. The XML tag name
1042
+ is shown around the content via ::before / ::after (data-tag is set at render
1043
+ time only, so it never ends up in the serialized XML). */
1044
+ .jinn-tap-unknown {
1045
+ padding: 0 0.15em;
1046
+ }
1047
+
1048
+ .jinn-tap-unknown::before,
1049
+ .jinn-tap-unknown::after,
1050
+ .jinn-tap-unknown-empty {
1051
+ font-family: var(--jinn-tap-unknown-font-family, ui-monospace, SFMono-Regular, Menlo, monospace);
1052
+ font-size: var(--jinn-tap-unknown-font-size, 0.7em);
1053
+ color: var(--jinn-tap-unknown-color, #b36b00);
1054
+ opacity: 0.75;
1055
+ -webkit-user-select: none;
1056
+ user-select: none;
1057
+ }
1058
+
1059
+ .jinn-tap-unknown::before {
1060
+ content: '<' attr(data-tag) '>';
1061
+ }
1062
+
1063
+ .jinn-tap-unknown::after {
1064
+ content: '</' attr(data-tag) '>';
1065
+ }