@birdycom/omniaui 0.12.5 → 0.12.6
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/README.md +1 -1
- package/bin/lib/copy-js.mjs +10 -1
- package/bin/omniaui.mjs +2 -2
- package/dist/barcode.d.ts +15 -0
- package/dist/barcode.js +164 -0
- package/dist/components-extra.css +15 -1
- package/dist/components.css +1489 -187
- package/dist/components.min.css +1 -1
- package/dist/data-table.js +135 -98
- package/dist/form-extras.d.ts +11 -0
- package/dist/form-extras.js +214 -0
- package/dist/lazy.d.ts +5 -0
- package/dist/lazy.js +37 -0
- package/dist/oc-theme.css +1 -1
- package/dist/parts/app-data-table-footer.css +38 -0
- package/dist/parts/app-data-table-rich.css +161 -0
- package/dist/parts/app-data-table.css +44 -74
- package/dist/parts/app-name-card.css +65 -0
- package/dist/parts/app-titlebar.css +16 -8
- package/dist/parts/data-meter-row.css +40 -0
- package/dist/parts/data-price.css +20 -0
- package/dist/parts/data-ribbon.css +76 -0
- package/dist/parts/data-spec-list.css +36 -0
- package/dist/parts/data-stock.css +41 -0
- package/dist/parts/forms-affix-input.css +1 -1
- package/dist/parts/forms-avatar-picker.css +43 -0
- package/dist/parts/forms-date-field.css +53 -0
- package/dist/parts/forms-density.css +13 -0
- package/dist/parts/forms-form-section.css +64 -0
- package/dist/parts/forms-quantity.css +55 -0
- package/dist/parts/forms-rating.css +81 -0
- package/dist/parts/media-attachment.css +1 -1
- package/dist/parts/media-barcode.css +23 -0
- package/dist/parts/media-chat-composer.css +3 -0
- package/dist/parts/media-emoji-picker.css +3 -1
- package/dist/parts/media-gallery.css +55 -0
- package/dist/parts/media-glass-liquid.css +99 -0
- package/dist/parts/media-glass-options.css +50 -0
- package/dist/parts/media-lazy.css +46 -0
- package/dist/parts/media-message-thread.css +1 -1
- package/dist/parts/media-message.css +1 -1
- package/dist/parts/nav-topbar-variants.css +96 -0
- package/dist/parts/site-header-variants.css +70 -0
- package/dist/parts/site-prose.css +1 -1
- package/dist/showcase.css +33 -3
- package/manifest.json +121 -9
- package/package.json +5 -2
- package/snippets/accordion-accent.html +1 -1
- package/snippets/attachment.html +4 -4
- package/snippets/avatar-picker.html +40 -0
- package/snippets/barcode.html +20 -0
- package/snippets/chat-composer.html +3 -3
- package/snippets/data-table.html +51 -76
- package/snippets/date-field.html +44 -0
- package/snippets/doc-viewer.html +1 -1
- package/snippets/emoji-picker.html +1 -1
- package/snippets/form-density.html +25 -0
- package/snippets/form-section.html +47 -0
- package/snippets/gallery.html +25 -0
- package/snippets/lazy.html +39 -0
- package/snippets/message-thread.html +12 -12
- package/snippets/message.html +10 -10
- package/snippets/meter-row.html +29 -0
- package/snippets/name-card.html +72 -0
- package/snippets/page-header.html +1 -1
- package/snippets/price.html +25 -0
- package/snippets/prose.html +3 -3
- package/snippets/quantity.html +12 -0
- package/snippets/rating.html +26 -0
- package/snippets/ribbon.html +48 -0
- package/snippets/sidebar.html +3 -3
- package/snippets/spec-list.html +34 -0
- package/snippets/stock.html +20 -0
- package/snippets/table-actions.html +5 -5
- package/snippets/table.html +2 -2
- package/snippets/titlebar.html +1 -1
- package/snippets/user.html +3 -3
- package/dist/parts/app-column-menu.css +0 -85
- package/snippets/column-menu.html +0 -38
package/dist/components.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* File: oc-theme.css — generated from tokens/semantic.json by @birdycom/omniacss 0.12.
|
|
1
|
+
/* File: oc-theme.css — generated from tokens/semantic.json by @birdycom/omniacss 0.12.6. Do not edit. */
|
|
2
2
|
/* Semantic theme tokens: every color is light-dark() of an Omnia palette token (oc-colors.css). */
|
|
3
3
|
/* Same source as the desktop export: npx omniacss tokens --format json|dtcg|python */
|
|
4
4
|
:root {
|
|
@@ -486,14 +486,63 @@ flex-direction: column;
|
|
|
486
486
|
border-radius: calc(var(--oc-radius) + 2px);
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
+
/* Square, exactly as tall as a text button of the same size, so both line up in a toolbar. */
|
|
489
490
|
.oc-btn--icon {
|
|
490
|
-
|
|
491
|
-
|
|
491
|
+
--oc-btn-square: calc(2.25rem + 2px);
|
|
492
|
+
padding: 0;
|
|
493
|
+
inline-size: var(--oc-btn-square);
|
|
494
|
+
block-size: var(--oc-btn-square);
|
|
495
|
+
flex-shrink: 0;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.oc-btn--icon.oc-btn--xs { --oc-btn-square: calc(1.75rem + 2px); }
|
|
499
|
+
.oc-btn--icon.oc-btn--sm { --oc-btn-square: calc(2rem + 2px); }
|
|
500
|
+
.oc-btn--icon.oc-btn--lg { --oc-btn-square: calc(2.5rem + 2px); }
|
|
501
|
+
|
|
502
|
+
/* Webicons in a button: <iconify-icon> before (or after) the label, the same size as an inline SVG. */
|
|
503
|
+
.oc-btn > iconify-icon { font-size: 1.15em; flex-shrink: 0; }
|
|
504
|
+
|
|
505
|
+
/* Soft — tinted background in a tone, for row actions (edit, view, delete …) and quiet secondary actions.
|
|
506
|
+
--soft-primary | --soft-success | --soft-warning | --soft-destructive | --soft-info */
|
|
507
|
+
.oc-btn[class*="oc-btn--soft-"] {
|
|
508
|
+
background: light-dark(oklch(from var(--oc-btn-tone) l c h / 0.12), oklch(from var(--oc-btn-tone) l c h / 0.22));
|
|
509
|
+
color: var(--oc-btn-tone);
|
|
510
|
+
border-color: transparent;
|
|
511
|
+
}
|
|
512
|
+
.oc-btn[class*="oc-btn--soft-"]:hover {
|
|
513
|
+
background: light-dark(oklch(from var(--oc-btn-tone) l c h / 0.2), oklch(from var(--oc-btn-tone) l c h / 0.32));
|
|
514
|
+
opacity: 1;
|
|
515
|
+
}
|
|
516
|
+
.oc-btn--soft-primary { --oc-btn-tone: var(--oc-primary); }
|
|
517
|
+
.oc-btn--soft-success { --oc-btn-tone: var(--oc-success); }
|
|
518
|
+
.oc-btn--soft-warning { --oc-btn-tone: var(--oc-warning); }
|
|
519
|
+
.oc-btn--soft-destructive { --oc-btn-tone: var(--oc-destructive); }
|
|
520
|
+
.oc-btn--soft-info { --oc-btn-tone: var(--oc-info, light-dark(var(--color-deepskyblue-70), var(--color-skyblue-50))); }
|
|
521
|
+
|
|
522
|
+
/* Plain — only the icon: no surface, no padding; muted until hovered (menus, toolbars, inline actions). */
|
|
523
|
+
.oc-btn--plain {
|
|
524
|
+
padding: 0;
|
|
525
|
+
background: transparent;
|
|
526
|
+
border-color: transparent;
|
|
527
|
+
color: var(--oc-muted-foreground);
|
|
492
528
|
}
|
|
529
|
+
.oc-btn--plain:hover,
|
|
530
|
+
.oc-btn--plain[aria-expanded="true"] { color: var(--oc-primary); opacity: 1; }
|
|
493
531
|
|
|
494
|
-
|
|
495
|
-
.oc-btn
|
|
496
|
-
.oc-btn
|
|
532
|
+
/* Loading — aria-busy="true": a spinner in front of the label (it replaces a leading icon); not clickable. */
|
|
533
|
+
.oc-btn[aria-busy="true"] { pointer-events: none; }
|
|
534
|
+
.oc-btn[aria-busy="true"]::before {
|
|
535
|
+
content: "";
|
|
536
|
+
inline-size: 1em;
|
|
537
|
+
block-size: 1em;
|
|
538
|
+
flex-shrink: 0;
|
|
539
|
+
border: 2px solid currentColor;
|
|
540
|
+
border-inline-end-color: transparent;
|
|
541
|
+
border-radius: 50%;
|
|
542
|
+
animation: oc-btn-spin 0.7s linear infinite;
|
|
543
|
+
}
|
|
544
|
+
.oc-btn[aria-busy="true"] > :is(svg, iconify-icon):first-child { display: none; }
|
|
545
|
+
@keyframes oc-btn-spin { to { rotate: 360deg; } }
|
|
497
546
|
|
|
498
547
|
/* Button group */
|
|
499
548
|
.oc-btn-group {
|
|
@@ -1633,6 +1682,8 @@ textarea.oc-input {
|
|
|
1633
1682
|
/* Vertical tabs */
|
|
1634
1683
|
.oc-tab-list--vertical {
|
|
1635
1684
|
flex-direction: column;
|
|
1685
|
+
/* Every tab as wide as the list, so the active line on the right stays on one vertical line. */
|
|
1686
|
+
align-items: stretch;
|
|
1636
1687
|
border-bottom: none;
|
|
1637
1688
|
border-right: 1px solid var(--oc-border);
|
|
1638
1689
|
}
|
|
@@ -1645,7 +1696,9 @@ textarea.oc-input {
|
|
|
1645
1696
|
text-align: left;
|
|
1646
1697
|
}
|
|
1647
1698
|
|
|
1648
|
-
.oc-tab-list--vertical .oc-tab-trigger.is-active
|
|
1699
|
+
.oc-tab-list--vertical .oc-tab-trigger.is-active,
|
|
1700
|
+
.oc-tab-list--vertical .oc-tab-trigger[aria-selected="true"] {
|
|
1701
|
+
border-bottom-color: transparent;
|
|
1649
1702
|
border-right-color: var(--oc-foreground);
|
|
1650
1703
|
}
|
|
1651
1704
|
|
|
@@ -1848,6 +1901,12 @@ textarea.oc-input {
|
|
|
1848
1901
|
border-radius: calc(var(--oc-radius) + 2px);
|
|
1849
1902
|
}
|
|
1850
1903
|
.oc-table-wrap > .oc-table { min-inline-size: 32rem; }
|
|
1904
|
+
/* The rounded frame draws the outer border; the cells keep only the inner lines, so nothing is cut at the corners. */
|
|
1905
|
+
.oc-table-wrap:has(> .oc-table) { border: 1px solid var(--oc-border); }
|
|
1906
|
+
.oc-table-wrap > .oc-table :is(th, td):first-child { border-inline-start: 0; }
|
|
1907
|
+
.oc-table-wrap > .oc-table :is(th, td):last-child { border-inline-end: 0; }
|
|
1908
|
+
.oc-table-wrap > .oc-table > :first-child > tr:first-child > * { border-block-start: 0; }
|
|
1909
|
+
.oc-table-wrap > .oc-table > :last-child > tr:last-child > * { border-block-end: 0; }
|
|
1851
1910
|
|
|
1852
1911
|
/* ===================================================================
|
|
1853
1912
|
Shared docs utility table styles (dark theme)
|
|
@@ -1984,6 +2043,42 @@ a.oc-breadcrumb-item:hover {
|
|
|
1984
2043
|
font-weight: 500;
|
|
1985
2044
|
}
|
|
1986
2045
|
|
|
2046
|
+
/* Icons: a webicon or SVG before the label of any item (the link or the item itself). */
|
|
2047
|
+
.oc-breadcrumb-item,
|
|
2048
|
+
.oc-breadcrumb-item a { gap: 0.375rem; }
|
|
2049
|
+
.oc-breadcrumb-item a { display: inline-flex; align-items: center; }
|
|
2050
|
+
.oc-breadcrumb-item :is(svg, iconify-icon) { font-size: 1.1em; inline-size: 1.1em; block-size: 1.1em; flex-shrink: 0; }
|
|
2051
|
+
|
|
2052
|
+
/* --chevron: a › chevron between the items instead of "/". */
|
|
2053
|
+
.oc-breadcrumb--chevron .oc-breadcrumb-item + .oc-breadcrumb-item::before {
|
|
2054
|
+
content: "";
|
|
2055
|
+
inline-size: 1em;
|
|
2056
|
+
block-size: 1em;
|
|
2057
|
+
margin: 0 0.25rem;
|
|
2058
|
+
background: currentColor;
|
|
2059
|
+
color: var(--oc-muted-foreground);
|
|
2060
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M8.59 16.58L13.17 12L8.59 7.41L10 6l6 6l-6 6z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
2061
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M8.59 16.58L13.17 12L8.59 7.41L10 6l6 6l-6 6z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
/* Collapsed middle of a long trail: a "…" button (opens a menu with the hidden levels). */
|
|
2065
|
+
.oc-breadcrumb-ellipsis {
|
|
2066
|
+
display: inline-flex;
|
|
2067
|
+
align-items: center;
|
|
2068
|
+
justify-content: center;
|
|
2069
|
+
inline-size: 1.75rem;
|
|
2070
|
+
block-size: 1.5rem;
|
|
2071
|
+
padding: 0;
|
|
2072
|
+
border: 0;
|
|
2073
|
+
border-radius: calc(var(--oc-radius) - 2px);
|
|
2074
|
+
background: transparent;
|
|
2075
|
+
color: var(--oc-muted-foreground);
|
|
2076
|
+
font: inherit;
|
|
2077
|
+
cursor: pointer;
|
|
2078
|
+
}
|
|
2079
|
+
.oc-breadcrumb-ellipsis:hover { background: var(--oc-accent); color: var(--oc-foreground); }
|
|
2080
|
+
.oc-breadcrumb-ellipsis:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
2081
|
+
|
|
1987
2082
|
/* ===================================================================
|
|
1988
2083
|
PROGRESS BAR
|
|
1989
2084
|
=================================================================== */
|
|
@@ -3670,6 +3765,9 @@ details.oc-collapsible[open]::details-content { block-size: auto; }
|
|
|
3670
3765
|
background: var(--oc-gradient-brand);
|
|
3671
3766
|
-webkit-background-clip: text;
|
|
3672
3767
|
background-clip: text;
|
|
3768
|
+
/* The gradient only paints the box: keep italic or tight last letters inside it without moving the text. */
|
|
3769
|
+
padding-inline-end: 0.08em;
|
|
3770
|
+
margin-inline-end: -0.08em;
|
|
3673
3771
|
color: transparent;
|
|
3674
3772
|
}
|
|
3675
3773
|
.oc-text-accent { background-image: linear-gradient(100deg, var(--oc-accent-from), var(--oc-accent-to)); }
|
|
@@ -3769,17 +3867,44 @@ details.oc-collapsible[open]::details-content { block-size: auto; }
|
|
|
3769
3867
|
.oc-lead { margin: 0 0 1rem; color: var(--oc-muted-foreground); font-size: 1.15rem; line-height: 1.65; max-inline-size: 42rem; text-wrap: pretty; }
|
|
3770
3868
|
.oc-split { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr)); gap: 3rem; align-items: center; }
|
|
3771
3869
|
|
|
3772
|
-
/* Code window: editor frame with traffic lights and a file name
|
|
3870
|
+
/* Code window: editor frame with traffic lights and a file name. It follows the page theme: a light frame and light
|
|
3871
|
+
syntax colors in light mode, the Omnia Dark editor colors in dark mode. --dark keeps it dark on a light page (the
|
|
3872
|
+
hero blocks, where it reads as an editor screenshot). */
|
|
3773
3873
|
.oc-code-window {
|
|
3774
3874
|
position: relative;
|
|
3775
3875
|
border: 1px solid var(--oc-border-strong);
|
|
3776
3876
|
border-radius: var(--oc-radius-lg);
|
|
3777
|
-
background: oklch(from var(--color-shallowblue-60) l c h / 0.9);
|
|
3877
|
+
background: light-dark(var(--oc-card), oklch(from var(--color-shallowblue-60) l c h / 0.9));
|
|
3778
3878
|
box-shadow: 0 40px 80px -30px oklch(from var(--color-black-50) l c h / 0.6);
|
|
3779
3879
|
backdrop-filter: blur(12px);
|
|
3780
3880
|
overflow: hidden;
|
|
3781
|
-
|
|
3782
|
-
|
|
3881
|
+
/* Syntax colors (oc-code-syntax.css) for both themes; the code sits on the window surface. */
|
|
3882
|
+
--oc-syntax-bg: transparent;
|
|
3883
|
+
--oc-syntax-bg-preview: transparent;
|
|
3884
|
+
--oc-syntax-fg: light-dark(var(--color-shallowblue-60), var(--color-silver-60));
|
|
3885
|
+
--oc-syntax-comment: light-dark(var(--color-gray-60), var(--color-purple-2));
|
|
3886
|
+
--oc-syntax-string: light-dark(var(--color-green-80), var(--color-green-2));
|
|
3887
|
+
--oc-syntax-keyword: light-dark(var(--color-purple-70), var(--color-purple-2));
|
|
3888
|
+
--oc-syntax-variable: light-dark(var(--color-skycyan-90), var(--color-skycyan-30));
|
|
3889
|
+
--oc-syntax-function: light-dark(var(--color-skycyan-90), var(--color-skycyan-60));
|
|
3890
|
+
--oc-syntax-number: light-dark(var(--color-peru-80), var(--color-peru-40));
|
|
3891
|
+
--oc-syntax-operator: light-dark(var(--color-red-70), var(--color-red-50));
|
|
3892
|
+
--oc-syntax-constant: light-dark(var(--color-skycyan-90), var(--color-skycyan-70));
|
|
3893
|
+
--oc-syntax-storage: light-dark(var(--color-green-80), var(--color-green-2));
|
|
3894
|
+
--oc-syntax-tag: light-dark(var(--color-brown-70), var(--color-brown-10));
|
|
3895
|
+
--oc-syntax-attr: light-dark(var(--color-skycyan-90), var(--color-skycyan-70));
|
|
3896
|
+
--oc-syntax-prop: light-dark(var(--color-green-80), var(--color-green-2));
|
|
3897
|
+
--oc-syntax-value: light-dark(var(--color-teal-80), var(--color-teal-10));
|
|
3898
|
+
--oc-syntax-cls: light-dark(var(--color-darkgoldenrod-80), var(--color-wheat-70));
|
|
3899
|
+
--oc-syntax-id: light-dark(var(--color-skycyan-90), var(--color-skycyan-70));
|
|
3900
|
+
--oc-syntax-unit: light-dark(var(--color-peru-80), var(--color-peru-40));
|
|
3901
|
+
--oc-syntax-key: light-dark(var(--color-brown-70), var(--color-brown-10));
|
|
3902
|
+
--oc-code-block-line-number-color: light-dark(var(--color-gray-40), oklch(from var(--color-white-2) l c h / 0.25));
|
|
3903
|
+
}
|
|
3904
|
+
.oc-code-window--dark { color-scheme: dark; box-shadow: 0 40px 80px -30px oklch(from var(--color-black-50) l c h / 0.6); }
|
|
3905
|
+
.oc-code-window:not(.oc-code-window--dark) { box-shadow: 0 24px 60px -30px oklch(from var(--color-black-50) l c h / 0.25); }
|
|
3906
|
+
/* The code block inside follows the window instead of its own always-dark theme. */
|
|
3907
|
+
.oc-code-window :is(.oc-code-block, pre.code-preview) { color-scheme: inherit; }
|
|
3783
3908
|
.oc-code-window__bar { display: flex; align-items: center; gap: 0.45rem; padding: 0.8rem 1rem; border-block-end: 1px solid var(--oc-border); }
|
|
3784
3909
|
.oc-code-window__bar > i { inline-size: 0.7rem; aspect-ratio: 1; border-radius: 50%; background: var(--color-red-50); }
|
|
3785
3910
|
.oc-code-window__bar > i:nth-child(2) { background: var(--color-orange-60); }
|
|
@@ -4437,7 +4562,21 @@ details.oc-collapsible[open]::details-content { block-size: auto; }
|
|
|
4437
4562
|
.oc-slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px oklch(from var(--oc-ring) l c h / 0.28); }
|
|
4438
4563
|
.oc-slider:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px oklch(from var(--oc-ring) l c h / 0.28); }
|
|
4439
4564
|
.oc-slider:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
4440
|
-
|
|
4565
|
+
/* In a vertical writing mode the inline axis is vertical: inline-size is the height of the slider. */
|
|
4566
|
+
.oc-slider--vertical { writing-mode: vertical-lr; direction: rtl; inline-size: 10rem; block-size: var(--oc-slider-thumb); }
|
|
4567
|
+
/* Scale under a stepped slider: one mark per step (or per labelled value), centered under the thumb positions.
|
|
4568
|
+
The padding keeps the first and last mark under the thumb center at min and max. */
|
|
4569
|
+
.oc-slider-scale {
|
|
4570
|
+
display: flex;
|
|
4571
|
+
justify-content: space-between;
|
|
4572
|
+
padding-inline: calc(var(--oc-slider-thumb, 1.125rem) / 2);
|
|
4573
|
+
margin-block-start: 0.25rem;
|
|
4574
|
+
font-size: 0.6875rem;
|
|
4575
|
+
font-variant-numeric: tabular-nums;
|
|
4576
|
+
color: var(--oc-muted-foreground);
|
|
4577
|
+
}
|
|
4578
|
+
.oc-slider-scale > * { display: flex; flex-direction: column; align-items: center; gap: 0.125rem; inline-size: 0; }
|
|
4579
|
+
.oc-slider-scale > *::before { content: ""; inline-size: 1px; block-size: 0.375rem; background: var(--oc-border); }
|
|
4441
4580
|
.oc-slider--vertical::-webkit-slider-runnable-track {
|
|
4442
4581
|
background: linear-gradient(to top, var(--oc-primary) var(--oc-slider-progress), var(--oc-muted) var(--oc-slider-progress));
|
|
4443
4582
|
}
|
|
@@ -5440,93 +5579,6 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5440
5579
|
@keyframes oc-busy-in { from { opacity: 0; } }
|
|
5441
5580
|
@media (prefers-reduced-motion: reduce) { .oc-busy-overlay[open], .oc-busy-overlay[open]::backdrop { animation-duration: 0s; } }
|
|
5442
5581
|
|
|
5443
|
-
/* parts/app-column-menu.css */
|
|
5444
|
-
/* File: packages/ui/src/parts/app-column-menu.css | Map: menu panel -> title + list -> item states -> footer -> CSS-only column hiding (scope) */
|
|
5445
|
-
/* Column menu: a popover with one checkbox per table column (column visibility).
|
|
5446
|
-
CSS-only hiding: wrap the menu and the table in .oc-column-menu-scope and give each checkbox
|
|
5447
|
-
data-col="<column number>". An unchecked box hides that column (th and td) through :has(). */
|
|
5448
|
-
|
|
5449
|
-
/* Panel look. Without the popover attribute it is a normal block (e.g. inside a sheet or sidebar). */
|
|
5450
|
-
.oc-column-menu {
|
|
5451
|
-
inline-size: 14rem;
|
|
5452
|
-
max-inline-size: calc(100vw - 1rem);
|
|
5453
|
-
padding: 0.375rem;
|
|
5454
|
-
font-size: 0.875rem;
|
|
5455
|
-
color: var(--oc-popover-foreground);
|
|
5456
|
-
background: var(--oc-popover);
|
|
5457
|
-
border: 1px solid var(--oc-border);
|
|
5458
|
-
border-radius: var(--oc-radius);
|
|
5459
|
-
box-shadow: 0 8px 24px oklch(from var(--color-black-60) l c h / 0.15);
|
|
5460
|
-
}
|
|
5461
|
-
/* As a popover: in the top layer, tethered to its trigger like the dropdown. */
|
|
5462
|
-
.oc-column-menu[popover] {
|
|
5463
|
-
position: fixed;
|
|
5464
|
-
inset: auto;
|
|
5465
|
-
margin: 4px 0 0;
|
|
5466
|
-
position-area: block-end span-inline-start;
|
|
5467
|
-
position-try-fallbacks: flip-block, flip-inline;
|
|
5468
|
-
transition: opacity var(--oc-transition-fast), display var(--oc-transition-fast) allow-discrete, overlay var(--oc-transition-fast) allow-discrete;
|
|
5469
|
-
}
|
|
5470
|
-
.oc-column-menu[popover]:popover-open {
|
|
5471
|
-
display: block;
|
|
5472
|
-
@starting-style { opacity: 0; }
|
|
5473
|
-
}
|
|
5474
|
-
|
|
5475
|
-
/* Small heading above the list ("Columns"). */
|
|
5476
|
-
.oc-column-menu-title {
|
|
5477
|
-
margin: 0;
|
|
5478
|
-
padding: 0.375rem 0.5rem 0.25rem;
|
|
5479
|
-
font-size: 0.75rem;
|
|
5480
|
-
font-weight: 600;
|
|
5481
|
-
color: var(--oc-muted-foreground);
|
|
5482
|
-
}
|
|
5483
|
-
|
|
5484
|
-
/* The list is a <form>, so a native <button type="reset"> restores the default columns. */
|
|
5485
|
-
.oc-column-menu-list { display: grid; gap: 1px; margin: 0; max-block-size: 18rem; overflow-y: auto; }
|
|
5486
|
-
|
|
5487
|
-
/* One row: label around a checkbox and the column name. */
|
|
5488
|
-
.oc-column-menu-item {
|
|
5489
|
-
display: flex;
|
|
5490
|
-
align-items: center;
|
|
5491
|
-
gap: 0.5rem;
|
|
5492
|
-
padding: 0.375rem 0.5rem;
|
|
5493
|
-
border-radius: calc(var(--oc-radius) - 2px);
|
|
5494
|
-
cursor: pointer;
|
|
5495
|
-
user-select: none;
|
|
5496
|
-
}
|
|
5497
|
-
.oc-column-menu-item:hover { background: var(--oc-accent); }
|
|
5498
|
-
.oc-column-menu-item:has(:focus-visible) { outline: 2px solid var(--oc-ring); outline-offset: -2px; }
|
|
5499
|
-
.oc-column-menu-item input { margin: 0; accent-color: var(--oc-primary); }
|
|
5500
|
-
/* Locked column (always visible): <input disabled checked>. */
|
|
5501
|
-
.oc-column-menu-item:has(input:disabled) { color: var(--oc-muted-foreground); cursor: default; }
|
|
5502
|
-
.oc-column-menu-item:has(input:disabled):hover { background: none; }
|
|
5503
|
-
|
|
5504
|
-
/* Footer row with "Reset" (type="reset") or other small buttons. */
|
|
5505
|
-
.oc-column-menu-footer {
|
|
5506
|
-
display: flex;
|
|
5507
|
-
justify-content: flex-end;
|
|
5508
|
-
gap: 0.25rem;
|
|
5509
|
-
margin-block-start: 0.375rem;
|
|
5510
|
-
padding-block-start: 0.375rem;
|
|
5511
|
-
border-block-start: 1px solid var(--oc-border);
|
|
5512
|
-
}
|
|
5513
|
-
|
|
5514
|
-
/* ---- CSS-only column hiding (columns 1 to 10) ---- */
|
|
5515
|
-
.oc-column-menu-scope:has([data-col="1"]:not(:checked)) .oc-table :is(th, td):nth-child(1),
|
|
5516
|
-
.oc-column-menu-scope:has([data-col="2"]:not(:checked)) .oc-table :is(th, td):nth-child(2),
|
|
5517
|
-
.oc-column-menu-scope:has([data-col="3"]:not(:checked)) .oc-table :is(th, td):nth-child(3),
|
|
5518
|
-
.oc-column-menu-scope:has([data-col="4"]:not(:checked)) .oc-table :is(th, td):nth-child(4),
|
|
5519
|
-
.oc-column-menu-scope:has([data-col="5"]:not(:checked)) .oc-table :is(th, td):nth-child(5),
|
|
5520
|
-
.oc-column-menu-scope:has([data-col="6"]:not(:checked)) .oc-table :is(th, td):nth-child(6),
|
|
5521
|
-
.oc-column-menu-scope:has([data-col="7"]:not(:checked)) .oc-table :is(th, td):nth-child(7),
|
|
5522
|
-
.oc-column-menu-scope:has([data-col="8"]:not(:checked)) .oc-table :is(th, td):nth-child(8),
|
|
5523
|
-
.oc-column-menu-scope:has([data-col="9"]:not(:checked)) .oc-table :is(th, td):nth-child(9),
|
|
5524
|
-
.oc-column-menu-scope:has([data-col="10"]:not(:checked)) .oc-table :is(th, td):nth-child(10) { display: none; }
|
|
5525
|
-
|
|
5526
|
-
@media (prefers-reduced-motion: reduce) {
|
|
5527
|
-
.oc-column-menu[popover] { transition: none; }
|
|
5528
|
-
}
|
|
5529
|
-
|
|
5530
5582
|
/* parts/app-confirm-dialog.css */
|
|
5531
5583
|
/* File: packages/ui/src/parts/app-confirm-dialog.css | Map: confirm modifier (icon ring) -> close button -> typed confirm field -> confirm lock -> three-button footer -> narrow screens */
|
|
5532
5584
|
/* Confirm dialog: a variant of the alert dialog (dialog.oc-modal + .oc-alert-dialog).
|
|
@@ -5664,9 +5716,213 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5664
5716
|
}
|
|
5665
5717
|
@media (prefers-reduced-motion: reduce) { .oc-cookie-consent { transition: none; } }
|
|
5666
5718
|
|
|
5719
|
+
/* parts/app-data-table-footer.css */
|
|
5720
|
+
/* File: packages/ui/src/parts/app-data-table-footer.css | Map: footer grid (count, rows per page, pager) -> page buttons -> narrow screens */
|
|
5721
|
+
/* Footer of the list table (app-data-table.css): the count on the left, rows per page in the middle, the pager on the right. */
|
|
5722
|
+
|
|
5723
|
+
/* Footer: count on the left, rows-per-page in the middle, pager on the right. */
|
|
5724
|
+
.oc-data-table-footer {
|
|
5725
|
+
display: grid;
|
|
5726
|
+
grid-template-columns: 1fr auto 1fr;
|
|
5727
|
+
align-items: center;
|
|
5728
|
+
gap: 0.75rem;
|
|
5729
|
+
}
|
|
5730
|
+
.oc-data-table-summary { margin: 0; font-size: 0.8125rem; color: var(--oc-muted-foreground); }
|
|
5731
|
+
.oc-data-table-per-page { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem; }
|
|
5732
|
+
.oc-data-table-per-page .oc-select { inline-size: auto; }
|
|
5733
|
+
.oc-data-table-pager { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.25rem; }
|
|
5734
|
+
.oc-data-table-page {
|
|
5735
|
+
min-inline-size: 2rem;
|
|
5736
|
+
padding: 0.25rem 0.45rem;
|
|
5737
|
+
font: inherit;
|
|
5738
|
+
font-size: 0.8125rem;
|
|
5739
|
+
color: var(--oc-foreground);
|
|
5740
|
+
background: var(--oc-card);
|
|
5741
|
+
border: 1px solid var(--oc-border);
|
|
5742
|
+
border-radius: calc(var(--oc-radius) - 2px);
|
|
5743
|
+
cursor: pointer;
|
|
5744
|
+
}
|
|
5745
|
+
.oc-data-table-page[aria-current="page"] {
|
|
5746
|
+
color: var(--oc-primary);
|
|
5747
|
+
background: oklch(from var(--oc-primary) l c h / 0.1);
|
|
5748
|
+
border-color: oklch(from var(--oc-primary) l c h / 0.35);
|
|
5749
|
+
}
|
|
5750
|
+
.oc-data-table-page:disabled { opacity: 0.4; cursor: default; }
|
|
5751
|
+
.oc-data-table-page:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
5752
|
+
.oc-data-table-ellipsis { padding-inline: 0.25rem; color: var(--oc-muted-foreground); }
|
|
5753
|
+
|
|
5754
|
+
@media (max-width: 40rem) {
|
|
5755
|
+
.oc-data-table-footer { grid-template-columns: 1fr; }
|
|
5756
|
+
.oc-data-table-pager { justify-content: flex-start; }
|
|
5757
|
+
}
|
|
5758
|
+
|
|
5759
|
+
/* parts/app-data-table-rich.css */
|
|
5760
|
+
/* File: packages/ui/src/parts/app-data-table-rich.css | Map: control height -> header (sort icons, columns) -> type tabs -> filter row -> name, truncate and count cells -> card fields */
|
|
5761
|
+
/* The rich relations list on top of app-data-table.css: tabs that filter a column, filter selects with an icon,
|
|
5762
|
+
rich cells and the label/value lines of the card view. Behaviour: data-oc-col-filter in src/data-table.js. */
|
|
5763
|
+
|
|
5764
|
+
/* Every control is 2rem high: search, filter selects, trash pills, icon buttons, rows per page and the pager. */
|
|
5765
|
+
.oc-data-table :is(.oc-data-table-toolbar, .oc-data-table-filters, .oc-data-table-footer) :is(.oc-input, .oc-select) { block-size: 2rem; padding-block: 0; font-size: 0.8125rem; }
|
|
5766
|
+
.oc-data-table .oc-data-table-page { min-block-size: 2rem; }
|
|
5767
|
+
.oc-data-table :is(.oc-data-table-toolbar, .oc-data-table-filters, thead) .oc-btn--icon { --oc-btn-square: 2rem; }
|
|
5768
|
+
.oc-data-table-toolbar .oc-filter-pill {
|
|
5769
|
+
display: inline-flex;
|
|
5770
|
+
align-items: center;
|
|
5771
|
+
block-size: 2rem;
|
|
5772
|
+
padding-inline: 0.625rem;
|
|
5773
|
+
border-radius: calc(var(--oc-radius) - 2px);
|
|
5774
|
+
}
|
|
5775
|
+
|
|
5776
|
+
/* Header: the sort mark only on the sorted column (and on hover); the actions header holds the column button. */
|
|
5777
|
+
/* The sort mark always keeps its 1rem, so sorting another column never moves the header: empty while unsorted,
|
|
5778
|
+
faint chevrons on hover, the accent sort icon on the sorted column. */
|
|
5779
|
+
:is(.oc-data-table, .oc-block-datatable) th:has(.oc-table-sort) { cursor: pointer; }
|
|
5780
|
+
:is(.oc-data-table, .oc-block-datatable) th .oc-table-sort::after { content: ""; flex-shrink: 0; inline-size: 1rem; block-size: 1rem; opacity: 1; }
|
|
5781
|
+
:is(.oc-data-table, .oc-block-datatable) th:not([aria-sort]):hover .oc-table-sort::after {
|
|
5782
|
+
background: var(--oc-muted-foreground);
|
|
5783
|
+
opacity: 0.6;
|
|
5784
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 18.17L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15M12 5.83L15.17 9l1.41-1.41L12 3L7.41 7.59L8.83 9z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
5785
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 18.17L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15M12 5.83L15.17 9l1.41-1.41L12 3L7.41 7.59L8.83 9z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
5786
|
+
}
|
|
5787
|
+
/* Sorted column: a bold label and a sort icon in the accent color. aria-sort on a header in the HTML
|
|
5788
|
+
is the column sorted when the page opens. */
|
|
5789
|
+
:is(.oc-data-table, .oc-block-datatable) th[aria-sort] .oc-table-sort { color: var(--oc-foreground); }
|
|
5790
|
+
:is(.oc-data-table, .oc-block-datatable) th[aria-sort] .oc-table-sort::after {
|
|
5791
|
+
content: "";
|
|
5792
|
+
inline-size: 1rem;
|
|
5793
|
+
block-size: 1rem;
|
|
5794
|
+
opacity: 1;
|
|
5795
|
+
background: var(--oc-primary);
|
|
5796
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 17h3l-4 4l-4-4h3V3h2M2 17h10v2H2M6 5v2H2V5m0 6h7v2H2z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
5797
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 17h3l-4 4l-4-4h3V3h2M2 17h10v2H2M6 5v2H2V5m0 6h7v2H2z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
5798
|
+
}
|
|
5799
|
+
:is(.oc-data-table, .oc-block-datatable) th[aria-sort="descending"] .oc-table-sort::after {
|
|
5800
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 7h3l-4-4l-4 4h3v14h2M2 17h10v2H2M6 5v2H2V5m0 6h7v2H2z'/%3E%3C/svg%3E");
|
|
5801
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 7h3l-4-4l-4 4h3v14h2M2 17h10v2H2M6 5v2H2V5m0 6h7v2H2z'/%3E%3C/svg%3E");
|
|
5802
|
+
}
|
|
5803
|
+
.oc-data-table th[data-oc-col="actions"] .oc-data-table-th { justify-content: flex-end; gap: 0.5rem; font-weight: 500; color: var(--oc-muted-foreground); }
|
|
5804
|
+
.oc-data-table td[data-oc-col="actions"] { text-align: end; }
|
|
5805
|
+
/* Row actions per status: data-oc-when="active" (edit, view) only on live rows, data-oc-when="deleted" (restore,
|
|
5806
|
+
delete permanently) only on rows in the trash. */
|
|
5807
|
+
.oc-data-table tr[data-oc-status="deleted"] [data-oc-when="active"],
|
|
5808
|
+
.oc-data-table tr:not([data-oc-status="deleted"]) [data-oc-when="deleted"] { display: none; }
|
|
5809
|
+
/* The column chooser in the actions header: a large plain icon (1.75rem), no button frame. */
|
|
5810
|
+
.oc-data-table-columns-btn { font-size: 1.75rem; }
|
|
5811
|
+
.oc-data-table-columns-btn > :is(svg, iconify-icon) { font-size: 1em; inline-size: 1em; block-size: 1em; }
|
|
5812
|
+
|
|
5813
|
+
/* Tabs above the toolbar (All / Customers / Companies …): icon, label and a count; they filter one column. */
|
|
5814
|
+
.oc-data-table-tabs { display: flex; inline-size: 100%; overflow-x: auto; scrollbar-width: none; }
|
|
5815
|
+
.oc-data-table-tabs .oc-tab-trigger { flex-shrink: 0; }
|
|
5816
|
+
.oc-data-table-tabs .oc-tab-trigger { display: inline-flex; align-items: center; gap: 0.4rem; }
|
|
5817
|
+
.oc-data-table-tabs .oc-tab-trigger :is(svg, iconify-icon) { font-size: 1.1em; inline-size: 1.1em; block-size: 1.1em; }
|
|
5818
|
+
.oc-data-table-tabs .oc-tab-trigger[aria-selected="true"] { color: var(--oc-primary); border-bottom-color: var(--oc-primary); }
|
|
5819
|
+
.oc-data-table-tab-count {
|
|
5820
|
+
min-inline-size: 1.25rem;
|
|
5821
|
+
padding: 0 0.375rem;
|
|
5822
|
+
font-size: 0.6875rem;
|
|
5823
|
+
line-height: 1.125rem;
|
|
5824
|
+
text-align: center;
|
|
5825
|
+
color: var(--oc-muted-foreground);
|
|
5826
|
+
background: var(--oc-muted);
|
|
5827
|
+
border-radius: 999px;
|
|
5828
|
+
}
|
|
5829
|
+
.oc-data-table-tabs [aria-selected="true"] .oc-data-table-tab-count { color: var(--oc-primary); background: oklch(from var(--oc-primary) l c h / 0.12); }
|
|
5830
|
+
/* A count in the color of its type (the same tone as the type badge in the table). */
|
|
5831
|
+
.oc-data-table-tab-count:is(.oc-data-table-tab-count--success, .oc-data-table-tab-count--info, .oc-data-table-tab-count--warning) {
|
|
5832
|
+
color: var(--oc-tab-tone);
|
|
5833
|
+
background: oklch(from var(--oc-tab-tone) l c h / 0.12);
|
|
5834
|
+
box-shadow: inset 0 0 0 1px oklch(from var(--oc-tab-tone) l c h / 0.35);
|
|
5835
|
+
}
|
|
5836
|
+
.oc-data-table-tab-count--success { --oc-tab-tone: var(--oc-success); }
|
|
5837
|
+
.oc-data-table-tab-count--info { --oc-tab-tone: var(--oc-info, light-dark(var(--color-deepskyblue-70), var(--color-skyblue-50))); }
|
|
5838
|
+
.oc-data-table-tab-count--warning { --oc-tab-tone: var(--oc-warning); }
|
|
5839
|
+
|
|
5840
|
+
/* Filter row: selects with a leading icon (status, type …) and the column button on the right. */
|
|
5841
|
+
.oc-data-table-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
|
|
5842
|
+
.oc-data-table-filters[hidden] { display: none; }
|
|
5843
|
+
.oc-data-table-filters > :last-child:is(.oc-btn) { margin-inline-start: auto; }
|
|
5844
|
+
.oc-data-table-filter { position: relative; display: inline-flex; align-items: center; }
|
|
5845
|
+
.oc-data-table-filter > :is(svg, iconify-icon) {
|
|
5846
|
+
position: absolute;
|
|
5847
|
+
inset-inline-start: 0.625rem;
|
|
5848
|
+
font-size: 1rem;
|
|
5849
|
+
inline-size: 1rem;
|
|
5850
|
+
block-size: 1rem;
|
|
5851
|
+
color: var(--oc-muted-foreground);
|
|
5852
|
+
pointer-events: none;
|
|
5853
|
+
}
|
|
5854
|
+
.oc-data-table-filter > .oc-select { inline-size: auto; min-inline-size: 11rem; padding-inline-start: 2.125rem; }
|
|
5855
|
+
|
|
5856
|
+
/* Cells. Name: avatar, name with a badge, and a muted second line (VAT number, e-mail …). */
|
|
5857
|
+
.oc-data-table-name { display: flex; align-items: center; gap: 0.625rem; min-inline-size: 0; }
|
|
5858
|
+
.oc-data-table-name .oc-avatar { inline-size: 2.25rem; block-size: 2.25rem; font-size: 0.75rem; }
|
|
5859
|
+
.oc-data-table-name-text { display: grid; min-inline-size: 0; }
|
|
5860
|
+
.oc-data-table-name-line { display: flex; align-items: center; gap: 0.375rem; font-weight: 600; }
|
|
5861
|
+
.oc-data-table-name-sub { font-size: 0.75rem; color: var(--oc-muted-foreground); }
|
|
5862
|
+
/* One line with an ellipsis; put the full text in title="". */
|
|
5863
|
+
.oc-data-table-truncate { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: var(--oc-data-table-truncate, 18rem); }
|
|
5864
|
+
/* A count that opens the related list (projects, invoices …); muted while it is 0. */
|
|
5865
|
+
.oc-data-table-count { font-variant-numeric: tabular-nums; }
|
|
5866
|
+
.oc-data-table-count[data-count="0"] { color: var(--oc-muted-foreground); opacity: 0.75; }
|
|
5867
|
+
/* The sort is visible in the header (icon, bold label); the summary line is for screen readers only. */
|
|
5868
|
+
.oc-data-table-sort-summary {
|
|
5869
|
+
position: absolute;
|
|
5870
|
+
inline-size: 1px;
|
|
5871
|
+
block-size: 1px;
|
|
5872
|
+
margin: 0;
|
|
5873
|
+
overflow: hidden;
|
|
5874
|
+
clip-path: inset(50%);
|
|
5875
|
+
white-space: nowrap;
|
|
5876
|
+
}
|
|
5877
|
+
.oc-data-table-file { display: none; }
|
|
5878
|
+
|
|
5879
|
+
/* The other visible columns as label / value lines, and the row actions at the bottom. */
|
|
5880
|
+
.oc-data-table-card-fields { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.25rem 0.75rem; margin: 0; font-size: 0.8125rem; }
|
|
5881
|
+
.oc-data-table-card-fields dt { color: var(--oc-muted-foreground); }
|
|
5882
|
+
.oc-data-table-card-fields dd { margin: 0; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
5883
|
+
.oc-data-table-card-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.375rem; margin-block-start: auto; }
|
|
5884
|
+
|
|
5885
|
+
/* Code cells (article numbers, SKUs): monospace and a step smaller. */
|
|
5886
|
+
.oc-data-table-code { font-family: var(--oc-font-mono); font-size: 0.75rem; }
|
|
5887
|
+
|
|
5888
|
+
/* Version 2, ".oc-data-table--bordered": a tinted header row, a line between the columns and the
|
|
5889
|
+
sort chevrons always visible; the filter select has its icon in a zone of its own. The rest is the same table. */
|
|
5890
|
+
.oc-data-table.oc-data-table--bordered .oc-table :is(th, td) { border-inline-end: 1px solid var(--oc-border); }
|
|
5891
|
+
.oc-data-table.oc-data-table--bordered .oc-table :is(th, td):last-child { border-inline-end: 0; }
|
|
5892
|
+
.oc-data-table.oc-data-table--bordered .oc-table thead th {
|
|
5893
|
+
font-weight: 500;
|
|
5894
|
+
background: color-mix(in oklch, var(--oc-card), var(--oc-foreground) 4%);
|
|
5895
|
+
}
|
|
5896
|
+
.oc-data-table.oc-data-table--bordered .oc-table thead th[data-oc-col="actions"] {
|
|
5897
|
+
background: color-mix(in oklch, var(--oc-card), var(--oc-foreground) 4%);
|
|
5898
|
+
}
|
|
5899
|
+
.oc-data-table--bordered td[data-oc-col="actions"] { text-align: center; }
|
|
5900
|
+
.oc-data-table--bordered th[data-oc-col="actions"] .oc-data-table-th { justify-content: center; }
|
|
5901
|
+
.oc-data-table--bordered th:not([aria-sort]) .oc-table-sort::after,
|
|
5902
|
+
.oc-data-table--bordered th:not([aria-sort]):hover .oc-table-sort::after {
|
|
5903
|
+
content: "";
|
|
5904
|
+
inline-size: 0.875rem;
|
|
5905
|
+
block-size: 0.875rem;
|
|
5906
|
+
opacity: 0.5;
|
|
5907
|
+
background: currentColor;
|
|
5908
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 18.17L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15M12 5.83L15.17 9l1.41-1.41L12 3L7.41 7.59L8.83 9z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
5909
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 18.17L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15M12 5.83L15.17 9l1.41-1.41L12 3L7.41 7.59L8.83 9z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
5910
|
+
}
|
|
5911
|
+
.oc-data-table--bordered .oc-data-table-filter::after {
|
|
5912
|
+
content: "";
|
|
5913
|
+
position: absolute;
|
|
5914
|
+
inset-block: 0;
|
|
5915
|
+
inset-inline-start: 2rem;
|
|
5916
|
+
inline-size: 1px;
|
|
5917
|
+
background: var(--oc-border);
|
|
5918
|
+
pointer-events: none;
|
|
5919
|
+
}
|
|
5920
|
+
.oc-data-table--bordered .oc-data-table-filter > .oc-select { padding-inline-start: 2.75rem; }
|
|
5921
|
+
|
|
5667
5922
|
/* parts/app-data-table.css */
|
|
5668
|
-
/* File: packages/ui/src/parts/app-data-table.css | Map: shell -> toolbar -> frame and scroll -> header
|
|
5669
|
-
/* List table
|
|
5923
|
+
/* File: packages/ui/src/parts/app-data-table.css | Map: shell -> toolbar -> frame and scroll -> header label -> select and actions columns -> deleted row -> bulk bar -> card view -> compact density */
|
|
5924
|
+
/* List table for business apps. The frame, toolbar and footer are styling. Tabs, filter row, rich cells and
|
|
5925
|
+
card fields: app-data-table-rich.css; footer and pager: app-data-table-footer.css.
|
|
5670
5926
|
Behaviour (search, sort, pages, resize, drag, trash, bulk) lives in src/data-table.js.
|
|
5671
5927
|
Set --oc-data-table-max on the shell when the body should scroll and the header should stick. */
|
|
5672
5928
|
|
|
@@ -5679,13 +5935,16 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5679
5935
|
background: var(--oc-card);
|
|
5680
5936
|
border: 1px solid var(--oc-border);
|
|
5681
5937
|
border-radius: var(--oc-radius);
|
|
5938
|
+
/* Full width, and in a grid or flex parent the table scrolls inside the frame instead of stretching the card. */
|
|
5939
|
+
inline-size: 100%;
|
|
5940
|
+
min-inline-size: 0;
|
|
5682
5941
|
}
|
|
5683
5942
|
|
|
5684
|
-
/* Toolbar: title + gear, search, trash pills, table/cards toggle, page actions. */
|
|
5943
|
+
/* Toolbar: title + gear/filter button, search (takes the free width), trash pills, table/cards toggle, page actions. */
|
|
5685
5944
|
.oc-data-table-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
|
|
5686
5945
|
.oc-data-table-heading { display: flex; align-items: center; gap: 0.5rem; min-inline-size: 0; }
|
|
5687
5946
|
.oc-data-table-title { font-size: 0.875rem; font-weight: 600; }
|
|
5688
|
-
.oc-data-table-search { flex: 1 1
|
|
5947
|
+
.oc-data-table-search { flex: 1 1 10rem; min-inline-size: 9rem; }
|
|
5689
5948
|
.oc-data-table-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-inline-start: auto; }
|
|
5690
5949
|
.oc-data-table-view { display: inline-flex; gap: 0.25rem; }
|
|
5691
5950
|
.oc-data-table-view [aria-pressed="true"] {
|
|
@@ -5693,55 +5952,52 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5693
5952
|
background: oklch(from var(--oc-primary) l c h / 0.1);
|
|
5694
5953
|
border-color: oklch(from var(--oc-primary) l c h / 0.35);
|
|
5695
5954
|
}
|
|
5696
|
-
|
|
5697
|
-
.oc-data-table-
|
|
5698
|
-
.oc-data-table-
|
|
5955
|
+
/* In the toolbar the trash pills read as one switch: the chosen one is filled. */
|
|
5956
|
+
.oc-data-table-toolbar .oc-filter-pills { border-inline-start: 0; padding-inline-start: 0; }
|
|
5957
|
+
.oc-data-table-toolbar .oc-filter-pill[aria-current="true"] {
|
|
5958
|
+
color: var(--oc-primary-foreground);
|
|
5959
|
+
background: var(--oc-primary);
|
|
5960
|
+
border-color: var(--oc-primary);
|
|
5961
|
+
}
|
|
5699
5962
|
|
|
5700
5963
|
/* The table sits in its own rounded frame. The scroll box keeps the header sticky. */
|
|
5701
5964
|
.oc-data-table-frame {
|
|
5965
|
+
min-inline-size: 0;
|
|
5702
5966
|
overflow: hidden;
|
|
5703
|
-
background: var(--oc-
|
|
5967
|
+
background: var(--oc-card);
|
|
5704
5968
|
border: 1px solid var(--oc-border);
|
|
5705
5969
|
border-radius: calc(var(--oc-radius) - 2px);
|
|
5706
5970
|
}
|
|
5707
5971
|
.oc-data-table-scroll { overflow: auto; max-block-size: var(--oc-data-table-max, none); }
|
|
5708
5972
|
.oc-data-table .oc-table :is(th, td) { border-inline: 0; border-block-start: 0; }
|
|
5973
|
+
/* Columns size to their content and cells stay on one line: a narrow screen scrolls the frame sideways instead of
|
|
5974
|
+
squeezing names and phone numbers onto two lines. .oc-data-table-wrap on a cell lets long text wrap again. */
|
|
5975
|
+
.oc-data-table .oc-data-table-table { table-layout: auto; }
|
|
5976
|
+
.oc-data-table .oc-data-table-table :is(th, td) { white-space: nowrap; vertical-align: middle; padding-inline: 0.625rem; }
|
|
5977
|
+
.oc-data-table .oc-data-table-table td.oc-data-table-wrap { white-space: normal; }
|
|
5709
5978
|
.oc-data-table .oc-table thead th {
|
|
5710
5979
|
position: sticky;
|
|
5711
5980
|
inset-block-start: 0;
|
|
5712
5981
|
z-index: 1;
|
|
5713
|
-
block-size: 2.
|
|
5714
|
-
font-size: 0.
|
|
5715
|
-
font-weight:
|
|
5982
|
+
block-size: 2.75rem;
|
|
5983
|
+
font-size: 0.8125rem;
|
|
5984
|
+
font-weight: 600;
|
|
5985
|
+
color: var(--oc-foreground);
|
|
5716
5986
|
background: var(--oc-card);
|
|
5717
5987
|
}
|
|
5718
|
-
|
|
5988
|
+
/* Striped rows (every second visible row), the row under the pointer a step stronger. Solid colors, so the sticky
|
|
5989
|
+
actions cell can take the same background (inherit) and nothing scrolls through it. */
|
|
5990
|
+
.oc-data-table {
|
|
5991
|
+
--oc-data-table-stripe: color-mix(in oklch, var(--oc-card), var(--oc-foreground) 3.5%);
|
|
5992
|
+
--oc-data-table-hover: color-mix(in oklch, var(--oc-card), var(--oc-primary) 8%);
|
|
5993
|
+
}
|
|
5994
|
+
.oc-data-table .oc-table tbody tr:nth-child(even of :not([hidden])) { background: var(--oc-data-table-stripe); }
|
|
5995
|
+
.oc-data-table .oc-table tbody tr:hover { background: var(--oc-data-table-hover); }
|
|
5996
|
+
.oc-data-table--plain .oc-table tbody tr:nth-child(even of :not([hidden])):not(:hover) { background: none; }
|
|
5719
5997
|
.oc-data-table .oc-table tbody tr:last-child > td { border-block-end: 0; }
|
|
5720
5998
|
|
|
5721
|
-
/* Header label
|
|
5722
|
-
.oc-data-table-th { display: flex; align-items: center; gap: 0.25rem;
|
|
5723
|
-
.oc-data-table-resize {
|
|
5724
|
-
position: absolute;
|
|
5725
|
-
inset-block: 0;
|
|
5726
|
-
inset-inline-end: -0.45rem;
|
|
5727
|
-
inline-size: 0.55rem;
|
|
5728
|
-
padding: 0;
|
|
5729
|
-
background: none;
|
|
5730
|
-
border: 0;
|
|
5731
|
-
cursor: col-resize;
|
|
5732
|
-
touch-action: none;
|
|
5733
|
-
}
|
|
5734
|
-
.oc-data-table-resize::after {
|
|
5735
|
-
content: "";
|
|
5736
|
-
position: absolute;
|
|
5737
|
-
inset-block: 0.4rem;
|
|
5738
|
-
inset-inline-start: 0.25rem;
|
|
5739
|
-
inline-size: 1px;
|
|
5740
|
-
background: var(--oc-border);
|
|
5741
|
-
}
|
|
5742
|
-
.oc-data-table.is-resizing { cursor: col-resize; user-select: none; }
|
|
5743
|
-
/* After a resize the table grows with its columns and the frame scrolls sideways. */
|
|
5744
|
-
.oc-data-table-table--sized { inline-size: max-content; min-inline-size: 100%; }
|
|
5999
|
+
/* Header label (column width by dragging is OmniaUI Pro: app-data-table-pro.css). */
|
|
6000
|
+
.oc-data-table-th { display: flex; align-items: center; gap: 0.25rem; min-inline-size: 0; }
|
|
5745
6001
|
|
|
5746
6002
|
/* Narrow control columns. The actions column stays on the right while the rest scrolls. */
|
|
5747
6003
|
.oc-data-table .oc-table :is(th, td)[data-oc-col="select"],
|
|
@@ -5757,8 +6013,8 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5757
6013
|
background: var(--oc-card);
|
|
5758
6014
|
box-shadow: -1px 0 0 var(--oc-border);
|
|
5759
6015
|
}
|
|
5760
|
-
.oc-data-table .oc-table thead th[data-oc-col="actions"] { z-index: 3; }
|
|
5761
|
-
.oc-data-table .oc-table tbody tr:nth-child(even) > td[data-oc-col="actions"] { background:
|
|
6016
|
+
.oc-data-table .oc-table thead th[data-oc-col="actions"] { z-index: 3; background: var(--oc-card); }
|
|
6017
|
+
.oc-data-table .oc-table tbody tr:is(:nth-child(even of :not([hidden])), :hover) > td[data-oc-col="actions"] { background: inherit; }
|
|
5762
6018
|
|
|
5763
6019
|
/* Trash and archive rows stay readable but quieter than active rows. */
|
|
5764
6020
|
.oc-data-table tr[data-oc-status="deleted"],
|
|
@@ -5787,55 +6043,24 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5787
6043
|
padding: 0.75rem;
|
|
5788
6044
|
}
|
|
5789
6045
|
.oc-data-table-card {
|
|
5790
|
-
|
|
6046
|
+
display: flex;
|
|
6047
|
+
flex-direction: column;
|
|
6048
|
+
gap: 0.75rem;
|
|
6049
|
+
padding: 0.875rem;
|
|
5791
6050
|
background: var(--oc-card);
|
|
5792
6051
|
border: 1px solid var(--oc-border);
|
|
5793
6052
|
border-radius: calc(var(--oc-radius) - 2px);
|
|
5794
6053
|
}
|
|
5795
6054
|
.oc-data-table-card-title { margin: 0; font-size: 0.875rem; font-weight: 600; }
|
|
5796
|
-
|
|
6055
|
+
.oc-data-table-card-title .oc-data-table-name-sub { font-weight: 400; }
|
|
5797
6056
|
.oc-data-table-empty { margin: 0; padding: 2rem 1rem; text-align: center; color: var(--oc-muted-foreground); }
|
|
5798
6057
|
.oc-data-table-empty[hidden] { display: none; }
|
|
5799
6058
|
|
|
5800
|
-
/* Footer: count on the left, rows-per-page in the middle, pager on the right. */
|
|
5801
|
-
.oc-data-table-footer {
|
|
5802
|
-
display: grid;
|
|
5803
|
-
grid-template-columns: 1fr auto 1fr;
|
|
5804
|
-
align-items: center;
|
|
5805
|
-
gap: 0.75rem;
|
|
5806
|
-
}
|
|
5807
|
-
.oc-data-table-summary { margin: 0; font-size: 0.8125rem; color: var(--oc-muted-foreground); }
|
|
5808
|
-
.oc-data-table-per-page { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem; }
|
|
5809
|
-
.oc-data-table-per-page .oc-select { inline-size: auto; }
|
|
5810
|
-
.oc-data-table-pager { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.25rem; }
|
|
5811
|
-
.oc-data-table-page {
|
|
5812
|
-
min-inline-size: 2rem;
|
|
5813
|
-
padding: 0.25rem 0.45rem;
|
|
5814
|
-
font: inherit;
|
|
5815
|
-
font-size: 0.8125rem;
|
|
5816
|
-
color: var(--oc-foreground);
|
|
5817
|
-
background: var(--oc-card);
|
|
5818
|
-
border: 1px solid var(--oc-border);
|
|
5819
|
-
border-radius: calc(var(--oc-radius) - 2px);
|
|
5820
|
-
cursor: pointer;
|
|
5821
|
-
}
|
|
5822
|
-
.oc-data-table-page[aria-current="page"] {
|
|
5823
|
-
color: var(--oc-primary);
|
|
5824
|
-
background: oklch(from var(--oc-primary) l c h / 0.1);
|
|
5825
|
-
border-color: oklch(from var(--oc-primary) l c h / 0.35);
|
|
5826
|
-
}
|
|
5827
|
-
.oc-data-table-page:disabled { opacity: 0.4; cursor: default; }
|
|
5828
|
-
.oc-data-table-page:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
5829
|
-
.oc-data-table-ellipsis { padding-inline: 0.25rem; color: var(--oc-muted-foreground); }
|
|
5830
6059
|
|
|
5831
6060
|
/* Design choice from the gear menu: tighter rows, like the compact article lists. */
|
|
5832
6061
|
.oc-data-table--compact .oc-table :is(th, td) { padding: 0.25rem 0.5rem; font-size: 0.8125rem; }
|
|
5833
6062
|
.oc-data-table--compact .oc-table thead th { block-size: 2rem; }
|
|
5834
6063
|
|
|
5835
|
-
@media (max-width: 40rem) {
|
|
5836
|
-
.oc-data-table-footer { grid-template-columns: 1fr; }
|
|
5837
|
-
.oc-data-table-pager { justify-content: flex-start; }
|
|
5838
|
-
}
|
|
5839
6064
|
@media (prefers-reduced-motion: reduce) {
|
|
5840
6065
|
.oc-data-table .oc-table tbody tr { transition: none; }
|
|
5841
6066
|
}
|
|
@@ -5972,6 +6197,73 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5972
6197
|
.oc-list-toolbar-view { transition: none; }
|
|
5973
6198
|
}
|
|
5974
6199
|
|
|
6200
|
+
/* parts/app-name-card.css */
|
|
6201
|
+
/* File: packages/ui/src/parts/app-name-card.css | Map: card (details) -> head (chevron, name, rename, amount, actions) -> rename input -> body -> nested cards */
|
|
6202
|
+
/* Name card: a collapsible card for one part of a quote or plan,
|
|
6203
|
+
with its name, a rename pencil, an optional amount and a delete button. Native <details>: it opens without script;
|
|
6204
|
+
packages/ui/src/name-card.js adds the rename (pencil -> input, Enter saves, Escape cancels). */
|
|
6205
|
+
|
|
6206
|
+
.oc-name-card {
|
|
6207
|
+
background: var(--oc-card);
|
|
6208
|
+
border: 1px solid var(--oc-border);
|
|
6209
|
+
border-radius: var(--oc-radius);
|
|
6210
|
+
}
|
|
6211
|
+
.oc-name-card + .oc-name-card { margin-block-start: 0.5rem; }
|
|
6212
|
+
.oc-name-card__head {
|
|
6213
|
+
display: flex;
|
|
6214
|
+
align-items: center;
|
|
6215
|
+
gap: 0.5rem;
|
|
6216
|
+
min-block-size: 2.75rem;
|
|
6217
|
+
padding: 0.375rem 0.5rem 0.375rem 0.75rem;
|
|
6218
|
+
list-style: none;
|
|
6219
|
+
cursor: pointer;
|
|
6220
|
+
}
|
|
6221
|
+
.oc-name-card__head::-webkit-details-marker { display: none; }
|
|
6222
|
+
.oc-name-card__head::before {
|
|
6223
|
+
content: "";
|
|
6224
|
+
flex-shrink: 0;
|
|
6225
|
+
inline-size: 1rem;
|
|
6226
|
+
block-size: 1rem;
|
|
6227
|
+
background: var(--oc-muted-foreground);
|
|
6228
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M8.59 16.58L13.17 12L8.59 7.41L10 6l6 6l-6 6z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
6229
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M8.59 16.58L13.17 12L8.59 7.41L10 6l6 6l-6 6z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
6230
|
+
transition: rotate var(--oc-transition-fast);
|
|
6231
|
+
}
|
|
6232
|
+
.oc-name-card[open] > .oc-name-card__head::before { rotate: 90deg; }
|
|
6233
|
+
.oc-name-card__head:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: -2px; border-radius: var(--oc-radius); }
|
|
6234
|
+
.oc-name-card__title { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
|
|
6235
|
+
.oc-name-card__meta { font-size: 0.75rem; color: var(--oc-muted-foreground); white-space: nowrap; }
|
|
6236
|
+
.oc-name-card__head .oc-btn { flex-shrink: 0; }
|
|
6237
|
+
/* Amount and actions sit on the right; the amount is tabular so a column of cards lines up. */
|
|
6238
|
+
.oc-name-card__amount { margin-inline-start: auto; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
6239
|
+
.oc-name-card__actions { display: inline-flex; flex-shrink: 0; gap: 0.25rem; margin-inline-start: auto; }
|
|
6240
|
+
.oc-name-card__amount + .oc-name-card__actions { margin-inline-start: 0.5rem; }
|
|
6241
|
+
|
|
6242
|
+
/* Rename: the title becomes an input of the same size (hidden toggles between the two). */
|
|
6243
|
+
.oc-name-card__input {
|
|
6244
|
+
flex: 1;
|
|
6245
|
+
min-inline-size: 0;
|
|
6246
|
+
block-size: 2rem;
|
|
6247
|
+
padding: 0 0.5rem;
|
|
6248
|
+
font: inherit;
|
|
6249
|
+
font-weight: 600;
|
|
6250
|
+
color: var(--oc-foreground);
|
|
6251
|
+
background: var(--oc-background);
|
|
6252
|
+
border: 1px solid var(--oc-ring);
|
|
6253
|
+
border-radius: calc(var(--oc-radius) - 2px);
|
|
6254
|
+
}
|
|
6255
|
+
.oc-name-card__input[hidden],
|
|
6256
|
+
.oc-name-card__title[hidden] { display: none; }
|
|
6257
|
+
|
|
6258
|
+
.oc-name-card__body { padding: 0.75rem 0.75rem 0.875rem 2.25rem; border-block-start: 1px solid var(--oc-border); }
|
|
6259
|
+
/* Nested cards (the parts of a title) use a quieter surface; --total colors the amount of the main card. */
|
|
6260
|
+
.oc-name-card__body > .oc-name-card { background: var(--oc-surface); }
|
|
6261
|
+
.oc-name-card--total > .oc-name-card__head .oc-name-card__amount { color: var(--oc-primary); }
|
|
6262
|
+
|
|
6263
|
+
@media (prefers-reduced-motion: reduce) {
|
|
6264
|
+
.oc-name-card__head::before { transition: none; }
|
|
6265
|
+
}
|
|
6266
|
+
|
|
5975
6267
|
/* parts/app-page-header.css */
|
|
5976
6268
|
/* File: packages/ui/src/parts/app-page-header.css | Map: header (container) -> back link row -> main row (text + actions) -> title + subtitle + meta -> wide layout (@container) -> modifiers (bordered, sticky, sm) */
|
|
5977
6269
|
/* Page header: back link + title + subtitle + actions at the top of an app page.
|
|
@@ -6456,6 +6748,11 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6456
6748
|
min-block-size: 0;
|
|
6457
6749
|
timeline-scope: --oc-titlebar-scroll;
|
|
6458
6750
|
}
|
|
6751
|
+
/* A card with a title bar on top: the bar runs edge to edge, its last button follows the card corner. */
|
|
6752
|
+
.oc-card:has(> .oc-titlebar:first-child) { padding: 0; --oc-titlebar-radius: calc(var(--oc-radius) + 3px); }
|
|
6753
|
+
/* As the heading of a card section (bar + .oc-card-content): the title lines up with the content below. */
|
|
6754
|
+
.oc-card > .oc-titlebar:first-child:has(+ .oc-card-content) { padding-inline-start: 24px; }
|
|
6755
|
+
.oc-card > .oc-titlebar:first-child:has(+ .oc-card-content) .oc-titlebar__title { font-size: 0.9375rem; }
|
|
6459
6756
|
|
|
6460
6757
|
.oc-titlebar {
|
|
6461
6758
|
display: flex;
|
|
@@ -6463,7 +6760,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6463
6760
|
align-items: center;
|
|
6464
6761
|
gap: 2px;
|
|
6465
6762
|
min-block-size: 46px;
|
|
6466
|
-
padding: 0
|
|
6763
|
+
padding: 0 0 0 14px;
|
|
6467
6764
|
border-block-end: 1px solid transparent;
|
|
6468
6765
|
-webkit-user-select: none;
|
|
6469
6766
|
user-select: none;
|
|
@@ -6480,7 +6777,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6480
6777
|
/* Title area: grows, cuts the subtitle off with …. */
|
|
6481
6778
|
.oc-titlebar__main { display: flex; flex: 1; align-items: center; gap: 8px; min-inline-size: 0; }
|
|
6482
6779
|
.oc-titlebar__icon { flex: none; inline-size: 18px; block-size: 18px; }
|
|
6483
|
-
.oc-titlebar__title { flex: none; font-size: 0.8667rem; font-weight: 650; letter-spacing: -0.01em; }
|
|
6780
|
+
.oc-titlebar__title { flex: none; margin: 0; font-size: 0.8667rem; font-weight: 650; letter-spacing: -0.01em; }
|
|
6484
6781
|
.oc-titlebar__subtitle {
|
|
6485
6782
|
min-inline-size: 0;
|
|
6486
6783
|
overflow: hidden;
|
|
@@ -6490,17 +6787,19 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6490
6787
|
white-space: nowrap;
|
|
6491
6788
|
}
|
|
6492
6789
|
.oc-titlebar__subtitle::before { content: "·"; margin-inline-end: 8px; }
|
|
6493
|
-
|
|
6790
|
+
/* Window buttons sit in the top right corner (as on a desktop window), not centred on the title line. */
|
|
6791
|
+
.oc-titlebar__actions { display: flex; flex: none; align-self: flex-start; align-items: flex-start; margin-inline-start: auto; }
|
|
6494
6792
|
|
|
6495
|
-
/*
|
|
6793
|
+
/* Window buttons: muted, a light surface on hover, the close button red. The last one follows the
|
|
6794
|
+
rounded corner of the card or window around the bar (--oc-titlebar-radius). */
|
|
6496
6795
|
.oc-titlebar__btn {
|
|
6497
6796
|
display: inline-grid;
|
|
6498
6797
|
place-items: center;
|
|
6499
|
-
inline-size:
|
|
6500
|
-
block-size:
|
|
6798
|
+
inline-size: 40px;
|
|
6799
|
+
block-size: 34px;
|
|
6501
6800
|
padding: 0;
|
|
6502
6801
|
border: 0;
|
|
6503
|
-
border-radius:
|
|
6802
|
+
border-radius: 0;
|
|
6504
6803
|
background: transparent;
|
|
6505
6804
|
color: var(--oc-muted-foreground);
|
|
6506
6805
|
font: inherit;
|
|
@@ -6511,6 +6810,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6511
6810
|
.oc-titlebar__btn:hover { background: var(--oc-glass-panel-strong, var(--oc-accent)); color: var(--oc-foreground); }
|
|
6512
6811
|
.oc-titlebar__btn:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: -2px; }
|
|
6513
6812
|
.oc-titlebar__btn--close:hover { background: var(--oc-destructive); color: var(--oc-destructive-foreground); }
|
|
6813
|
+
.oc-titlebar__actions > .oc-titlebar__btn:last-child { border-start-end-radius: var(--oc-titlebar-radius, calc(var(--oc-radius) - 1px)); }
|
|
6514
6814
|
|
|
6515
6815
|
/* Body: the part that scrolls under the bar. */
|
|
6516
6816
|
.oc-titlebar-body {
|
|
@@ -6535,7 +6835,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6535
6835
|
|
|
6536
6836
|
/* Sizes */
|
|
6537
6837
|
.oc-titlebar--sm { min-block-size: 36px; padding-inline-start: 10px; }
|
|
6538
|
-
.oc-titlebar--sm .oc-titlebar__btn { inline-size:
|
|
6838
|
+
.oc-titlebar--sm .oc-titlebar__btn { inline-size: 34px; block-size: 28px; }
|
|
6539
6839
|
|
|
6540
6840
|
@media (prefers-reduced-motion: reduce) {
|
|
6541
6841
|
.oc-titlebar-window > .oc-titlebar { animation: none; }
|
|
@@ -7060,6 +7360,229 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7060
7360
|
.oc-chart-line__dot, .oc-chart-line__tip { transition: none; }
|
|
7061
7361
|
}
|
|
7062
7362
|
|
|
7363
|
+
/* parts/data-meter-row.css */
|
|
7364
|
+
/* File: packages/ui/src/parts/data-meter-row.css | Map: row grid -> label and value -> bar and fill -> levels -> reset line -> list */
|
|
7365
|
+
/* Usage meter row: a label, the usage as text, a bar and when it resets. The fill comes from
|
|
7366
|
+
--oc-meter (0–100%); data-level="warn" or "critical" changes the color. */
|
|
7367
|
+
|
|
7368
|
+
.oc-meter-row {
|
|
7369
|
+
display: grid;
|
|
7370
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
7371
|
+
align-items: baseline;
|
|
7372
|
+
gap: 0.375rem 0.75rem;
|
|
7373
|
+
}
|
|
7374
|
+
.oc-meter-row__label { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.875rem; font-weight: 600; }
|
|
7375
|
+
.oc-meter-row__value { font-size: 0.8125rem; font-variant-numeric: tabular-nums; color: var(--oc-muted-foreground); white-space: nowrap; }
|
|
7376
|
+
.oc-meter-row__value strong { color: var(--oc-foreground); }
|
|
7377
|
+
.oc-meter-row__bar {
|
|
7378
|
+
grid-column: 1 / -1;
|
|
7379
|
+
block-size: 0.5rem;
|
|
7380
|
+
overflow: hidden;
|
|
7381
|
+
background: var(--oc-muted);
|
|
7382
|
+
border-radius: 999px;
|
|
7383
|
+
}
|
|
7384
|
+
.oc-meter-row__bar::before {
|
|
7385
|
+
content: "";
|
|
7386
|
+
display: block;
|
|
7387
|
+
inline-size: clamp(0%, var(--oc-meter, 0%), 100%);
|
|
7388
|
+
block-size: 100%;
|
|
7389
|
+
background: var(--oc-meter-color, var(--oc-success));
|
|
7390
|
+
border-radius: inherit;
|
|
7391
|
+
transition: inline-size 0.4s ease;
|
|
7392
|
+
}
|
|
7393
|
+
.oc-meter-row[data-level="warn"] { --oc-meter-color: var(--oc-warning); }
|
|
7394
|
+
.oc-meter-row[data-level="critical"] { --oc-meter-color: var(--oc-destructive); }
|
|
7395
|
+
.oc-meter-row[data-level="critical"] .oc-meter-row__value strong { color: var(--oc-destructive); }
|
|
7396
|
+
.oc-meter-row__reset { grid-column: 1 / -1; display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.75rem; color: var(--oc-muted-foreground); }
|
|
7397
|
+
.oc-meter-list { display: grid; gap: 1rem; }
|
|
7398
|
+
.oc-meter-list--compact { gap: 0.625rem; }
|
|
7399
|
+
.oc-meter-list--compact .oc-meter-row__bar { block-size: 0.375rem; }
|
|
7400
|
+
|
|
7401
|
+
@media (prefers-reduced-motion: reduce) {
|
|
7402
|
+
.oc-meter-row__bar::before { transition: none; }
|
|
7403
|
+
}
|
|
7404
|
+
|
|
7405
|
+
/* parts/data-price.css */
|
|
7406
|
+
/* File: packages/ui/src/parts/data-price.css | Map: price block -> main line (amount, old price, discount) -> VAT note and alternative -> sizes and sale */
|
|
7407
|
+
/* A price as shops and quotes show it: the amount, an optional old price and discount badge, a VAT note
|
|
7408
|
+
("excl. VAT") and the other amount ("€ 121,00 incl. VAT"). Numbers use tabular digits. */
|
|
7409
|
+
|
|
7410
|
+
.oc-price { display: inline-grid; gap: 0.125rem; min-inline-size: 0; }
|
|
7411
|
+
.oc-price__main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.5rem; }
|
|
7412
|
+
.oc-price__amount { font-size: 1.25rem; font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
7413
|
+
.oc-price__old { font-size: 0.875rem; color: var(--oc-muted-foreground); text-decoration: line-through; text-decoration-thickness: 1px; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
7414
|
+
.oc-price__main > .oc-badge { align-self: center; }
|
|
7415
|
+
.oc-price__note { font-size: 0.75rem; font-weight: 500; color: var(--oc-muted-foreground); }
|
|
7416
|
+
.oc-price__alt { font-size: 0.8125rem; color: var(--oc-muted-foreground); font-variant-numeric: tabular-nums; }
|
|
7417
|
+
|
|
7418
|
+
.oc-price--sm .oc-price__amount { font-size: 1rem; }
|
|
7419
|
+
.oc-price--lg .oc-price__amount { font-size: 1.75rem; }
|
|
7420
|
+
.oc-price--sale .oc-price__amount { color: var(--oc-destructive); }
|
|
7421
|
+
/* Inline: amount and note on one line (table cells, lists). */
|
|
7422
|
+
.oc-price--inline { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.5rem; }
|
|
7423
|
+
.oc-price--inline .oc-price__amount { font-size: inherit; font-weight: 600; }
|
|
7424
|
+
td[data-numeric] > .oc-price, .oc-price--end { justify-items: end; text-align: end; }
|
|
7425
|
+
td[data-numeric] > .oc-price .oc-price__main, .oc-price--end .oc-price__main { justify-content: flex-end; }
|
|
7426
|
+
|
|
7427
|
+
/* parts/data-ribbon.css */
|
|
7428
|
+
/* File: packages/ui/src/parts/data-ribbon.css | Map: host (positioned, clipped) -> ribbon band -> four corners -> tones -> size -> RTL */
|
|
7429
|
+
/* Corner ribbon: a diagonal band across one corner of a card, an image or a document ("Paid", "New", "Sale").
|
|
7430
|
+
Put .oc-ribbon as a child of the box; the box gets position: relative and clips the band (zero specificity,
|
|
7431
|
+
so your own position or overflow wins). The text is real text, so screen readers read it. */
|
|
7432
|
+
|
|
7433
|
+
:where(:has(> .oc-ribbon)) { position: relative; overflow: clip; }
|
|
7434
|
+
|
|
7435
|
+
.oc-ribbon {
|
|
7436
|
+
/* Distance from the corner to the middle of the band, along both edges. */
|
|
7437
|
+
--oc-ribbon-inset: 2.25rem;
|
|
7438
|
+
--oc-ribbon-x: 1;
|
|
7439
|
+
--oc-ribbon-y: -1;
|
|
7440
|
+
--oc-ribbon-turn: 45deg;
|
|
7441
|
+
--oc-ribbon-bg: var(--oc-primary);
|
|
7442
|
+
--oc-ribbon-fg: var(--oc-primary-foreground);
|
|
7443
|
+
position: absolute;
|
|
7444
|
+
z-index: 2;
|
|
7445
|
+
inset-block-start: var(--oc-ribbon-inset);
|
|
7446
|
+
inset-inline-end: var(--oc-ribbon-inset);
|
|
7447
|
+
inline-size: calc(var(--oc-ribbon-inset) * 2.83 + 3rem);
|
|
7448
|
+
padding: 0.3em 0;
|
|
7449
|
+
overflow: hidden;
|
|
7450
|
+
color: var(--oc-ribbon-fg);
|
|
7451
|
+
background: var(--oc-ribbon-bg);
|
|
7452
|
+
box-shadow: 0 1px 3px oklch(0 0 0 / 0.18);
|
|
7453
|
+
font-size: 0.75rem;
|
|
7454
|
+
font-weight: 700;
|
|
7455
|
+
line-height: 1.25;
|
|
7456
|
+
letter-spacing: 0.08em;
|
|
7457
|
+
text-align: center;
|
|
7458
|
+
text-overflow: ellipsis;
|
|
7459
|
+
text-transform: uppercase;
|
|
7460
|
+
white-space: nowrap;
|
|
7461
|
+
pointer-events: none;
|
|
7462
|
+
translate: calc(50% * var(--oc-ribbon-x)) calc(50% * var(--oc-ribbon-y));
|
|
7463
|
+
rotate: var(--oc-ribbon-turn);
|
|
7464
|
+
}
|
|
7465
|
+
|
|
7466
|
+
/* Corners: top end is the default. */
|
|
7467
|
+
.oc-ribbon--top-start {
|
|
7468
|
+
inset-inline-end: auto;
|
|
7469
|
+
inset-inline-start: var(--oc-ribbon-inset);
|
|
7470
|
+
--oc-ribbon-x: -1;
|
|
7471
|
+
--oc-ribbon-turn: -45deg;
|
|
7472
|
+
}
|
|
7473
|
+
.oc-ribbon--bottom-end {
|
|
7474
|
+
inset-block-start: auto;
|
|
7475
|
+
inset-block-end: var(--oc-ribbon-inset);
|
|
7476
|
+
--oc-ribbon-y: 1;
|
|
7477
|
+
--oc-ribbon-turn: -45deg;
|
|
7478
|
+
}
|
|
7479
|
+
.oc-ribbon--bottom-start {
|
|
7480
|
+
inset-block-start: auto;
|
|
7481
|
+
inset-block-end: var(--oc-ribbon-inset);
|
|
7482
|
+
inset-inline-end: auto;
|
|
7483
|
+
inset-inline-start: var(--oc-ribbon-inset);
|
|
7484
|
+
--oc-ribbon-x: -1;
|
|
7485
|
+
--oc-ribbon-y: 1;
|
|
7486
|
+
}
|
|
7487
|
+
|
|
7488
|
+
/* Tones. */
|
|
7489
|
+
.oc-ribbon--success { --oc-ribbon-bg: var(--oc-success); --oc-ribbon-fg: var(--oc-success-foreground); }
|
|
7490
|
+
.oc-ribbon--warning { --oc-ribbon-bg: var(--oc-warning); --oc-ribbon-fg: var(--oc-warning-foreground); }
|
|
7491
|
+
.oc-ribbon--destructive { --oc-ribbon-bg: var(--oc-destructive); --oc-ribbon-fg: var(--oc-destructive-foreground); }
|
|
7492
|
+
.oc-ribbon--muted { --oc-ribbon-bg: var(--oc-muted); --oc-ribbon-fg: var(--oc-muted-foreground); }
|
|
7493
|
+
|
|
7494
|
+
/* Sizes: a smaller band for a product card, a larger one for a document or a hero image. */
|
|
7495
|
+
.oc-ribbon--sm { --oc-ribbon-inset: 1.6rem; font-size: 0.625rem; }
|
|
7496
|
+
.oc-ribbon--lg { --oc-ribbon-inset: 2.9rem; font-size: 0.875rem; }
|
|
7497
|
+
|
|
7498
|
+
/* Right to left: start and end swap sides, so the band leans the other way. */
|
|
7499
|
+
.oc-ribbon:dir(rtl) { translate: calc(-50% * var(--oc-ribbon-x)) calc(50% * var(--oc-ribbon-y)); rotate: calc(var(--oc-ribbon-turn) * -1); }
|
|
7500
|
+
|
|
7501
|
+
@media (forced-colors: active) {
|
|
7502
|
+
.oc-ribbon { forced-color-adjust: none; color: Canvas; background: CanvasText; }
|
|
7503
|
+
}
|
|
7504
|
+
|
|
7505
|
+
/* parts/data-spec-list.css */
|
|
7506
|
+
/* File: packages/ui/src/parts/data-spec-list.css | Map: list (container) -> groups in columns -> group title -> rows (term / value) -> stack modifier */
|
|
7507
|
+
/* Technical specifications in named groups (Dimensions, Electrical, Package …): label / value rows with tabular
|
|
7508
|
+
digits. Two columns of groups once the list is wide enough (container query), one column with --stack. */
|
|
7509
|
+
|
|
7510
|
+
.oc-spec-list { container-type: inline-size; inline-size: 100%; display: grid; gap: 1.25rem; min-inline-size: 0; }
|
|
7511
|
+
@container (min-width: 40rem) {
|
|
7512
|
+
.oc-spec-list:not(.oc-spec-list--stack) { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; gap: 1.25rem 2rem; }
|
|
7513
|
+
}
|
|
7514
|
+
.oc-spec-group { min-inline-size: 0; }
|
|
7515
|
+
.oc-spec-group__title {
|
|
7516
|
+
display: flex;
|
|
7517
|
+
align-items: center;
|
|
7518
|
+
gap: 0.5rem;
|
|
7519
|
+
margin: 0 0 0.25rem;
|
|
7520
|
+
padding-block-end: 0.375rem;
|
|
7521
|
+
font-size: 0.75rem;
|
|
7522
|
+
font-weight: 600;
|
|
7523
|
+
letter-spacing: 0.04em;
|
|
7524
|
+
text-transform: uppercase;
|
|
7525
|
+
color: var(--oc-muted-foreground);
|
|
7526
|
+
border-block-end: 1px solid var(--oc-border);
|
|
7527
|
+
}
|
|
7528
|
+
.oc-spec-group__title > :is(svg, iconify-icon) { inline-size: 1rem; block-size: 1rem; font-size: 1rem; }
|
|
7529
|
+
.oc-spec-group__rows { margin: 0; }
|
|
7530
|
+
.oc-spec-row {
|
|
7531
|
+
display: grid;
|
|
7532
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
|
|
7533
|
+
gap: 1rem;
|
|
7534
|
+
padding: 0.4rem 0;
|
|
7535
|
+
font-size: 0.875rem;
|
|
7536
|
+
border-block-end: 1px dashed var(--oc-border);
|
|
7537
|
+
}
|
|
7538
|
+
.oc-spec-row:last-child { border-block-end: 0; }
|
|
7539
|
+
.oc-spec-row > dt { margin: 0; color: var(--oc-muted-foreground); }
|
|
7540
|
+
.oc-spec-row > dd { margin: 0; min-inline-size: 0; font-weight: 500; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
|
|
7541
|
+
.oc-spec-row > dd > small { margin-inline-start: 0.25rem; font-weight: 400; color: var(--oc-muted-foreground); }
|
|
7542
|
+
|
|
7543
|
+
/* parts/data-stock.css */
|
|
7544
|
+
/* File: packages/ui/src/parts/data-stock.css | Map: indicator (dot + text) -> levels (ok, low, out, order) -> badge variant -> count */
|
|
7545
|
+
/* Stock status: a colored dot with a short text ("In stock", "Only 3 left", "Out of stock", "On order").
|
|
7546
|
+
data-level picks the color; the text always says it too, so color is never the only signal. */
|
|
7547
|
+
|
|
7548
|
+
.oc-stock {
|
|
7549
|
+
--oc-stock-color: var(--oc-success);
|
|
7550
|
+
/* Inline text (not flex), so "Only <b>3</b> left" keeps normal word spacing. */
|
|
7551
|
+
display: inline-block;
|
|
7552
|
+
font-size: 0.8125rem;
|
|
7553
|
+
font-weight: 500;
|
|
7554
|
+
line-height: 1.3;
|
|
7555
|
+
color: var(--oc-foreground);
|
|
7556
|
+
white-space: nowrap;
|
|
7557
|
+
}
|
|
7558
|
+
.oc-stock::before {
|
|
7559
|
+
content: "";
|
|
7560
|
+
display: inline-block;
|
|
7561
|
+
margin-inline-end: 0.4rem;
|
|
7562
|
+
vertical-align: 0.05em;
|
|
7563
|
+
inline-size: 0.5rem;
|
|
7564
|
+
block-size: 0.5rem;
|
|
7565
|
+
background: var(--oc-stock-color);
|
|
7566
|
+
border-radius: 50%;
|
|
7567
|
+
box-shadow: 0 0 0 3px oklch(from var(--oc-stock-color) l c h / 0.18);
|
|
7568
|
+
}
|
|
7569
|
+
.oc-stock[data-level="low"] { --oc-stock-color: var(--oc-warning); }
|
|
7570
|
+
.oc-stock[data-level="out"] { --oc-stock-color: var(--oc-destructive); }
|
|
7571
|
+
.oc-stock[data-level="order"] { --oc-stock-color: var(--oc-info, light-dark(var(--color-deepskyblue-70), var(--color-skyblue-50))); }
|
|
7572
|
+
.oc-stock__count { font-weight: 700; font-variant-numeric: tabular-nums; }
|
|
7573
|
+
.oc-stock__note { font-weight: 400; color: var(--oc-muted-foreground); }
|
|
7574
|
+
|
|
7575
|
+
/* Badge: a tinted pill (table cells, product cards). */
|
|
7576
|
+
.oc-stock--badge {
|
|
7577
|
+
padding: 0.125rem 0.5rem 0.125rem 0.45rem;
|
|
7578
|
+
font-size: 0.75rem;
|
|
7579
|
+
color: color-mix(in oklch, var(--oc-stock-color) 75%, var(--oc-foreground));
|
|
7580
|
+
background: oklch(from var(--oc-stock-color) l c h / 0.12);
|
|
7581
|
+
border: 1px solid oklch(from var(--oc-stock-color) l c h / 0.3);
|
|
7582
|
+
border-radius: 999px;
|
|
7583
|
+
}
|
|
7584
|
+
.oc-stock--badge::before { inline-size: 0.4rem; block-size: 0.4rem; margin-inline-end: 0.3rem; vertical-align: 0.1em; box-shadow: none; }
|
|
7585
|
+
|
|
7063
7586
|
/* parts/forms-affix-input.css */
|
|
7064
7587
|
/* File: packages/ui/src/parts/forms-affix-input.css
|
|
7065
7588
|
Map: --affix group (frame on the wrapper) -> inner input -> inline affix (€, %, @) -> states -> --end alignment
|
|
@@ -7088,7 +7611,7 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7088
7611
|
min-inline-size: 0;
|
|
7089
7612
|
}
|
|
7090
7613
|
|
|
7091
|
-
/* Symbol column: same chrome as the
|
|
7614
|
+
/* Symbol column: the same chrome as the other fields (€, %, @, barcode icon).
|
|
7092
7615
|
A divider separates the symbol from the value. */
|
|
7093
7616
|
.oc-input-group.oc-input-group--affix .oc-input-addon {
|
|
7094
7617
|
align-self: stretch;
|
|
@@ -7137,6 +7660,51 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7137
7660
|
}
|
|
7138
7661
|
.oc-input-group--affix:has(.oc-input:disabled) .oc-input { opacity: 1; }
|
|
7139
7662
|
|
|
7663
|
+
/* parts/forms-avatar-picker.css */
|
|
7664
|
+
/* File: packages/ui/src/parts/forms-avatar-picker.css | Map: picker -> preview (initials or image) -> file input -> text and buttons -> drop state -> square and logo */
|
|
7665
|
+
/* Logo or avatar picker: a preview, "Upload" and "Remove", a hint, and dropping a file
|
|
7666
|
+
on the preview. The file input is a real <input type="file">; packages/ui/src/avatar-picker.js shows the preview. */
|
|
7667
|
+
|
|
7668
|
+
.oc-avatar-picker { display: flex; align-items: center; gap: 1rem; }
|
|
7669
|
+
.oc-avatar-picker__preview {
|
|
7670
|
+
position: relative;
|
|
7671
|
+
display: inline-flex;
|
|
7672
|
+
align-items: center;
|
|
7673
|
+
justify-content: center;
|
|
7674
|
+
flex-shrink: 0;
|
|
7675
|
+
inline-size: var(--oc-avatar-picker-size, 4.5rem);
|
|
7676
|
+
block-size: var(--oc-avatar-picker-size, 4.5rem);
|
|
7677
|
+
overflow: hidden;
|
|
7678
|
+
font-size: 1.25rem;
|
|
7679
|
+
font-weight: 600;
|
|
7680
|
+
color: var(--oc-muted-foreground);
|
|
7681
|
+
background: var(--oc-muted);
|
|
7682
|
+
border: 1px dashed var(--oc-border-strong, var(--oc-border));
|
|
7683
|
+
border-radius: 50%;
|
|
7684
|
+
cursor: pointer;
|
|
7685
|
+
}
|
|
7686
|
+
.oc-avatar-picker--square .oc-avatar-picker__preview { border-radius: var(--oc-radius); }
|
|
7687
|
+
.oc-avatar-picker__preview img { inline-size: 100%; block-size: 100%; object-fit: cover; }
|
|
7688
|
+
.oc-avatar-picker--logo .oc-avatar-picker__preview img { object-fit: contain; padding: 0.375rem; background: var(--color-white-50); }
|
|
7689
|
+
.oc-avatar-picker__preview:has(img) { border-style: solid; }
|
|
7690
|
+
.oc-avatar-picker__preview:hover,
|
|
7691
|
+
.oc-avatar-picker.is-dragover .oc-avatar-picker__preview {
|
|
7692
|
+
color: var(--oc-primary);
|
|
7693
|
+
background: oklch(from var(--oc-primary) l c h / 0.08);
|
|
7694
|
+
border-color: var(--oc-primary);
|
|
7695
|
+
}
|
|
7696
|
+
.oc-avatar-picker__preview:has(:focus-visible) { outline: 2px solid var(--oc-ring); outline-offset: 2px; }
|
|
7697
|
+
.oc-avatar-picker__file { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
|
|
7698
|
+
.oc-avatar-picker__text { display: grid; gap: 0.375rem; min-inline-size: 0; }
|
|
7699
|
+
.oc-avatar-picker__label { font-size: 0.875rem; font-weight: 600; }
|
|
7700
|
+
.oc-avatar-picker__hint { font-size: 0.75rem; color: var(--oc-muted-foreground); }
|
|
7701
|
+
.oc-avatar-picker__actions { display: flex; flex-wrap: wrap; gap: 0.375rem; }
|
|
7702
|
+
/* "Remove" only while there is an image. */
|
|
7703
|
+
.oc-avatar-picker:not(:has(.oc-avatar-picker__preview img)) [data-oc-avatar-remove] { display: none; }
|
|
7704
|
+
/* A refused file (wrong type or too large): red outline and the reason under the buttons. */
|
|
7705
|
+
.oc-avatar-picker.is-invalid .oc-avatar-picker__preview { border-color: var(--oc-destructive); }
|
|
7706
|
+
.oc-avatar-picker__error { font-size: 0.75rem; font-weight: 500; color: var(--oc-destructive); }
|
|
7707
|
+
|
|
7140
7708
|
/* parts/forms-barcode-input.css */
|
|
7141
7709
|
/* File: packages/ui/src/parts/forms-barcode-input.css
|
|
7142
7710
|
Map: wrapper (field + preview stacked) -> monospace field -> preview area -> placeholder bars -> code caption -> empty / invalid states
|
|
@@ -7406,6 +7974,61 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7406
7974
|
/* Small swatches. */
|
|
7407
7975
|
.oc-color-select--sm .oc-color-select-swatch { inline-size: 1.25rem; block-size: 1.25rem; }
|
|
7408
7976
|
|
|
7977
|
+
/* parts/forms-date-field.css */
|
|
7978
|
+
/* File: packages/ui/src/parts/forms-date-field.css | Map: field frame -> icon zone -> native date input -> ISO week label -> sizes and states */
|
|
7979
|
+
/* Date field: calendar icon | line | date, with the ISO week at the end when wanted.
|
|
7980
|
+
The date is a native <input type="date"> (keyboard, picker and locale from the browser). The week label is filled
|
|
7981
|
+
by packages/ui/src/date-field.js (or by your own code). */
|
|
7982
|
+
|
|
7983
|
+
.oc-date-field {
|
|
7984
|
+
display: inline-flex;
|
|
7985
|
+
align-items: stretch;
|
|
7986
|
+
block-size: 2.5rem;
|
|
7987
|
+
background: var(--oc-background);
|
|
7988
|
+
border: 1px solid var(--oc-input, var(--oc-border));
|
|
7989
|
+
border-radius: var(--oc-radius);
|
|
7990
|
+
overflow: hidden;
|
|
7991
|
+
}
|
|
7992
|
+
.oc-date-field:focus-within { border-color: var(--oc-ring); box-shadow: 0 0 0 3px oklch(from var(--oc-ring) l c h / 0.18); }
|
|
7993
|
+
.oc-date-field__icon {
|
|
7994
|
+
display: inline-flex;
|
|
7995
|
+
align-items: center;
|
|
7996
|
+
justify-content: center;
|
|
7997
|
+
inline-size: 2.5rem;
|
|
7998
|
+
font-size: 1.125rem;
|
|
7999
|
+
color: var(--oc-muted-foreground);
|
|
8000
|
+
border-inline-end: 1px solid var(--oc-border);
|
|
8001
|
+
}
|
|
8002
|
+
.oc-date-field__input {
|
|
8003
|
+
min-inline-size: 0;
|
|
8004
|
+
padding: 0 0.75rem;
|
|
8005
|
+
font: inherit;
|
|
8006
|
+
font-size: 0.875rem;
|
|
8007
|
+
color: var(--oc-foreground);
|
|
8008
|
+
background: transparent;
|
|
8009
|
+
border: 0;
|
|
8010
|
+
outline: none;
|
|
8011
|
+
}
|
|
8012
|
+
.oc-date-field__input::-webkit-calendar-picker-indicator { opacity: 0.55; cursor: pointer; }
|
|
8013
|
+
/* ISO week: a quiet label at the end ("Week 45"); hidden while there is no date. */
|
|
8014
|
+
.oc-date-field__week {
|
|
8015
|
+
display: inline-flex;
|
|
8016
|
+
align-items: center;
|
|
8017
|
+
padding-inline: 0.75rem;
|
|
8018
|
+
font-size: 0.75rem;
|
|
8019
|
+
font-weight: 600;
|
|
8020
|
+
font-variant-numeric: tabular-nums;
|
|
8021
|
+
color: var(--oc-primary);
|
|
8022
|
+
background: oklch(from var(--oc-primary) l c h / 0.08);
|
|
8023
|
+
border-inline-start: 1px solid var(--oc-border);
|
|
8024
|
+
white-space: nowrap;
|
|
8025
|
+
}
|
|
8026
|
+
.oc-date-field__week:empty { display: none; }
|
|
8027
|
+
.oc-date-field--sm { block-size: 2rem; }
|
|
8028
|
+
.oc-date-field--sm .oc-date-field__icon { inline-size: 2rem; font-size: 1rem; }
|
|
8029
|
+
.oc-date-field:has(.oc-date-field__input:disabled) { opacity: 0.55; }
|
|
8030
|
+
.oc-date-field:has(.oc-date-field__input[aria-invalid="true"]) { border-color: var(--oc-destructive); }
|
|
8031
|
+
|
|
7409
8032
|
/* parts/forms-decimal-input.css */
|
|
7410
8033
|
/* File: packages/ui/src/parts/forms-decimal-input.css
|
|
7411
8034
|
Map: field (right-aligned tabular digits) -> unit suffix wrapper -> states -> --start alignment
|
|
@@ -7459,6 +8082,21 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7459
8082
|
/* Disabled wrapper. */
|
|
7460
8083
|
.oc-decimal-field:has(.oc-decimal-input:disabled) { opacity: 0.5; cursor: not-allowed; }
|
|
7461
8084
|
|
|
8085
|
+
/* parts/forms-density.css */
|
|
8086
|
+
/* File: packages/ui/src/parts/forms-density.css | Map: compact scope -> inputs, selects, date fields, textareas -> buttons -> field gaps */
|
|
8087
|
+
/* Form density: .oc-density-compact on a form or any wrapper makes its controls
|
|
8088
|
+
2rem high instead of 2.5rem, for dense editors (invoice templates, inline tables). The default needs no class. */
|
|
8089
|
+
|
|
8090
|
+
.oc-density-compact :is(.oc-input, .oc-select, .oc-date-field) { block-size: 2rem; font-size: 0.8125rem; }
|
|
8091
|
+
.oc-density-compact :is(.oc-input, .oc-select) { padding-block: 0; }
|
|
8092
|
+
.oc-density-compact .oc-textarea { padding-block: 0.375rem; font-size: 0.8125rem; }
|
|
8093
|
+
.oc-density-compact .oc-date-field__icon { inline-size: 2rem; font-size: 1rem; }
|
|
8094
|
+
.oc-density-compact .oc-date-field__input { font-size: 0.8125rem; }
|
|
8095
|
+
.oc-density-compact .oc-btn:not(.oc-btn--icon, .oc-btn--plain, .oc-btn--inline) { padding-block: 0.3125rem; font-size: 0.8125rem; }
|
|
8096
|
+
.oc-density-compact .oc-btn--icon { --oc-btn-square: 2rem; }
|
|
8097
|
+
.oc-density-compact .oc-field { gap: 0.25rem; }
|
|
8098
|
+
.oc-density-compact .oc-field-label { font-size: 0.75rem; }
|
|
8099
|
+
|
|
7462
8100
|
/* parts/forms-filter-counts.css */
|
|
7463
8101
|
/* File: packages/ui/src/parts/forms-filter-counts.css
|
|
7464
8102
|
Map: group (grid of tiles) -> tile (label + hidden radio) -> value / label / hint -> tones -> states -> --compact
|
|
@@ -7555,6 +8193,72 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7555
8193
|
.oc-filter-counts--compact .oc-filter-counts-label { font-size: 0.8rem; font-weight: 500; }
|
|
7556
8194
|
.oc-filter-counts--compact .oc-filter-counts-hint { display: none; }
|
|
7557
8195
|
|
|
8196
|
+
/* parts/forms-form-section.css */
|
|
8197
|
+
/* File: packages/ui/src/parts/forms-form-section.css | Map: section (details) -> summary (icon, title, hint, status, chevron) -> body grid -> invalid state */
|
|
8198
|
+
/* Collapsible form section: a long form in named parts that open and close.
|
|
8199
|
+
Native <details>; sections with the same name="" keep one open at a time. */
|
|
8200
|
+
|
|
8201
|
+
.oc-form-section {
|
|
8202
|
+
background: var(--oc-card);
|
|
8203
|
+
border: 1px solid var(--oc-border);
|
|
8204
|
+
border-radius: var(--oc-radius);
|
|
8205
|
+
}
|
|
8206
|
+
.oc-form-section + .oc-form-section { margin-block-start: 0.75rem; }
|
|
8207
|
+
.oc-form-section__summary {
|
|
8208
|
+
display: grid;
|
|
8209
|
+
grid-template-columns: auto minmax(0, 1fr) auto auto;
|
|
8210
|
+
align-items: center;
|
|
8211
|
+
gap: 0.25rem 0.75rem;
|
|
8212
|
+
padding: 0.875rem 1rem;
|
|
8213
|
+
list-style: none;
|
|
8214
|
+
cursor: pointer;
|
|
8215
|
+
}
|
|
8216
|
+
.oc-form-section__summary::-webkit-details-marker { display: none; }
|
|
8217
|
+
.oc-form-section__summary:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: -2px; border-radius: var(--oc-radius); }
|
|
8218
|
+
.oc-form-section__icon {
|
|
8219
|
+
display: inline-flex;
|
|
8220
|
+
align-items: center;
|
|
8221
|
+
justify-content: center;
|
|
8222
|
+
inline-size: 2.25rem;
|
|
8223
|
+
block-size: 2.25rem;
|
|
8224
|
+
font-size: 1.25rem;
|
|
8225
|
+
color: var(--oc-primary);
|
|
8226
|
+
background: oklch(from var(--oc-primary) l c h / 0.1);
|
|
8227
|
+
border-radius: calc(var(--oc-radius) - 2px);
|
|
8228
|
+
}
|
|
8229
|
+
.oc-form-section__heading { display: grid; gap: 0.125rem; min-inline-size: 0; }
|
|
8230
|
+
.oc-form-section__title { margin: 0; font-size: 0.9375rem; font-weight: 600; }
|
|
8231
|
+
.oc-form-section__hint { margin: 0; font-size: 0.8125rem; color: var(--oc-muted-foreground); }
|
|
8232
|
+
.oc-form-section__status { font-size: 0.75rem; white-space: nowrap; }
|
|
8233
|
+
.oc-form-section__summary::after {
|
|
8234
|
+
content: "";
|
|
8235
|
+
inline-size: 1.125rem;
|
|
8236
|
+
block-size: 1.125rem;
|
|
8237
|
+
background: var(--oc-muted-foreground);
|
|
8238
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6l-6-6z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
8239
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6l-6-6z'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
8240
|
+
transition: rotate var(--oc-transition-fast);
|
|
8241
|
+
}
|
|
8242
|
+
.oc-form-section[open] > .oc-form-section__summary::after { rotate: 180deg; }
|
|
8243
|
+
.oc-form-section__body {
|
|
8244
|
+
display: grid;
|
|
8245
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
|
|
8246
|
+
gap: 1rem;
|
|
8247
|
+
padding: 1rem;
|
|
8248
|
+
border-block-start: 1px solid var(--oc-border);
|
|
8249
|
+
}
|
|
8250
|
+
.oc-form-section__body > .oc-form-section__wide { grid-column: 1 / -1; }
|
|
8251
|
+
/* A section with an invalid field gets a red edge, also while closed, so an error is never hidden. */
|
|
8252
|
+
.oc-form-section:has(:user-invalid, [aria-invalid="true"]) { border-color: var(--oc-destructive); }
|
|
8253
|
+
.oc-form-section:has(:user-invalid, [aria-invalid="true"]) .oc-form-section__icon {
|
|
8254
|
+
color: var(--oc-destructive);
|
|
8255
|
+
background: oklch(from var(--oc-destructive) l c h / 0.1);
|
|
8256
|
+
}
|
|
8257
|
+
|
|
8258
|
+
@media (prefers-reduced-motion: reduce) {
|
|
8259
|
+
.oc-form-section__summary::after { transition: none; }
|
|
8260
|
+
}
|
|
8261
|
+
|
|
7558
8262
|
/* parts/forms-language-select.css */
|
|
7559
8263
|
/* File: packages/ui/src/parts/forms-language-select.css
|
|
7560
8264
|
Map: wrapper (icon + native select) -> icon -> select control -> chevron -> states -> --ghost / --currency
|
|
@@ -7890,6 +8594,146 @@ button.oc-language-select:hover { background: var(--oc-surface); }
|
|
|
7890
8594
|
font-size: 0.8rem;
|
|
7891
8595
|
}
|
|
7892
8596
|
|
|
8597
|
+
/* parts/forms-quantity.css */
|
|
8598
|
+
/* File: packages/ui/src/parts/forms-quantity.css | Map: frame -> step buttons -> number input (no spinners) -> focus and disabled -> sizes */
|
|
8599
|
+
/* Quantity field: minus, a number input and plus in one frame. Without a script it is a normal number input
|
|
8600
|
+
(the browser's arrows and keyboard); form-extras.js makes the buttons step within min / max / step. */
|
|
8601
|
+
|
|
8602
|
+
.oc-quantity {
|
|
8603
|
+
display: inline-flex;
|
|
8604
|
+
inline-size: fit-content;
|
|
8605
|
+
justify-self: start;
|
|
8606
|
+
align-items: stretch;
|
|
8607
|
+
block-size: 2.25rem;
|
|
8608
|
+
background: var(--oc-background);
|
|
8609
|
+
border: 1px solid var(--oc-input, var(--oc-border));
|
|
8610
|
+
border-radius: var(--oc-radius);
|
|
8611
|
+
overflow: hidden;
|
|
8612
|
+
}
|
|
8613
|
+
.oc-quantity__step {
|
|
8614
|
+
display: inline-grid;
|
|
8615
|
+
place-items: center;
|
|
8616
|
+
flex-shrink: 0;
|
|
8617
|
+
inline-size: 2.25rem;
|
|
8618
|
+
padding: 0;
|
|
8619
|
+
font: inherit;
|
|
8620
|
+
color: var(--oc-muted-foreground);
|
|
8621
|
+
background: transparent;
|
|
8622
|
+
border: 0;
|
|
8623
|
+
cursor: pointer;
|
|
8624
|
+
}
|
|
8625
|
+
.oc-quantity__step > :is(svg, iconify-icon) { inline-size: 1rem; block-size: 1rem; font-size: 1rem; }
|
|
8626
|
+
.oc-quantity__step:hover { color: var(--oc-foreground); background: var(--oc-accent); }
|
|
8627
|
+
.oc-quantity__step:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: -2px; }
|
|
8628
|
+
.oc-quantity__step:disabled { opacity: 0.35; cursor: not-allowed; background: transparent; }
|
|
8629
|
+
.oc-quantity__input {
|
|
8630
|
+
inline-size: 3.25rem;
|
|
8631
|
+
min-inline-size: 0;
|
|
8632
|
+
padding: 0 0.25rem;
|
|
8633
|
+
font: inherit;
|
|
8634
|
+
font-size: 0.875rem;
|
|
8635
|
+
font-weight: 600;
|
|
8636
|
+
font-variant-numeric: tabular-nums;
|
|
8637
|
+
text-align: center;
|
|
8638
|
+
color: var(--oc-foreground);
|
|
8639
|
+
background: transparent;
|
|
8640
|
+
border: 0;
|
|
8641
|
+
border-inline: 1px solid var(--oc-border);
|
|
8642
|
+
-moz-appearance: textfield;
|
|
8643
|
+
appearance: textfield;
|
|
8644
|
+
}
|
|
8645
|
+
.oc-quantity__input::-webkit-outer-spin-button,
|
|
8646
|
+
.oc-quantity__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
|
8647
|
+
.oc-quantity__input:focus { outline: none; }
|
|
8648
|
+
.oc-quantity:has(.oc-quantity__input:focus-visible) { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
8649
|
+
.oc-quantity:has(.oc-quantity__input:disabled) { opacity: 0.5; }
|
|
8650
|
+
.oc-quantity--sm { block-size: 2rem; }
|
|
8651
|
+
.oc-quantity--sm .oc-quantity__step { inline-size: 2rem; }
|
|
8652
|
+
.oc-quantity--sm .oc-quantity__input { inline-size: 2.75rem; font-size: 0.8125rem; }
|
|
8653
|
+
|
|
8654
|
+
/* parts/forms-rating.css */
|
|
8655
|
+
/* File: packages/ui/src/parts/forms-rating.css | Map: star mask -> rating (display) -> sizes -> summary line -> rating input (radios, hover preview) -> focus */
|
|
8656
|
+
/* Star rating without JavaScript. .oc-rating shows a score (--oc-rating, halves and decimals work); .oc-rating-input
|
|
8657
|
+
is five radio buttons drawn as stars: :has() fills up to the checked or hovered star. */
|
|
8658
|
+
|
|
8659
|
+
.oc-rating,
|
|
8660
|
+
.oc-rating-input {
|
|
8661
|
+
--oc-rating-size: 1.125rem;
|
|
8662
|
+
--oc-rating-color: var(--oc-warning);
|
|
8663
|
+
--oc-rating-empty: oklch(from var(--oc-muted-foreground) l c h / 0.28);
|
|
8664
|
+
--oc-rating-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2L9.19 8.62L2 9.24l5.45 4.73L5.82 21z'/%3E%3C/svg%3E");
|
|
8665
|
+
}
|
|
8666
|
+
|
|
8667
|
+
/* Display: one bar of five stars; the fill is the score out of --oc-rating-max (default 5). */
|
|
8668
|
+
.oc-rating {
|
|
8669
|
+
--oc-rating: 0;
|
|
8670
|
+
--oc-rating-max: 5;
|
|
8671
|
+
display: inline-block;
|
|
8672
|
+
flex-shrink: 0;
|
|
8673
|
+
inline-size: calc(var(--oc-rating-size) * var(--oc-rating-max));
|
|
8674
|
+
block-size: var(--oc-rating-size);
|
|
8675
|
+
vertical-align: middle;
|
|
8676
|
+
background: linear-gradient(90deg, var(--oc-rating-color) calc(var(--oc-rating) / var(--oc-rating-max) * 100%), var(--oc-rating-empty) 0);
|
|
8677
|
+
-webkit-mask: var(--oc-rating-star) left center / var(--oc-rating-size) var(--oc-rating-size) repeat-x;
|
|
8678
|
+
mask: var(--oc-rating-star) left center / var(--oc-rating-size) var(--oc-rating-size) repeat-x;
|
|
8679
|
+
}
|
|
8680
|
+
.oc-rating--sm, .oc-rating-input.oc-rating-input--sm { --oc-rating-size: 0.875rem; }
|
|
8681
|
+
.oc-rating--lg, .oc-rating-input.oc-rating-input--lg { --oc-rating-size: 1.5rem; }
|
|
8682
|
+
|
|
8683
|
+
/* Summary: stars, the score and the number of reviews on one line. */
|
|
8684
|
+
.oc-rating-summary { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; font-size: 0.875rem; }
|
|
8685
|
+
.oc-rating-summary__score { font-weight: 700; font-variant-numeric: tabular-nums; }
|
|
8686
|
+
.oc-rating-summary__count { color: var(--oc-muted-foreground); }
|
|
8687
|
+
a.oc-rating-summary__count { text-decoration: underline; text-underline-offset: 0.2em; }
|
|
8688
|
+
a.oc-rating-summary__count:hover { color: var(--oc-foreground); }
|
|
8689
|
+
|
|
8690
|
+
/* Input: a fieldset with five labels (radio inside). The stars are one masked bar behind the labels. */
|
|
8691
|
+
.oc-rating-input {
|
|
8692
|
+
position: relative;
|
|
8693
|
+
display: inline-flex;
|
|
8694
|
+
inline-size: calc(var(--oc-rating-size) * 5 + 0.5rem);
|
|
8695
|
+
block-size: calc(var(--oc-rating-size) + 0.5rem);
|
|
8696
|
+
margin: 0;
|
|
8697
|
+
padding: 0.25rem;
|
|
8698
|
+
border: 0;
|
|
8699
|
+
border-radius: calc(var(--oc-radius) - 2px);
|
|
8700
|
+
}
|
|
8701
|
+
.oc-rating-input::before {
|
|
8702
|
+
content: "";
|
|
8703
|
+
position: absolute;
|
|
8704
|
+
inset: 0.25rem;
|
|
8705
|
+
background: linear-gradient(90deg, var(--oc-rating-color) calc(var(--oc-rating-hover, var(--oc-rating-pick, 0)) * var(--oc-rating-size)), var(--oc-rating-empty) 0);
|
|
8706
|
+
-webkit-mask: var(--oc-rating-star) left center / var(--oc-rating-size) var(--oc-rating-size) repeat-x;
|
|
8707
|
+
mask: var(--oc-rating-star) left center / var(--oc-rating-size) var(--oc-rating-size) repeat-x;
|
|
8708
|
+
pointer-events: none;
|
|
8709
|
+
}
|
|
8710
|
+
.oc-rating-input > legend { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
8711
|
+
.oc-rating-input > label { position: relative; z-index: 1; flex: 0 0 var(--oc-rating-size); cursor: pointer; }
|
|
8712
|
+
.oc-rating-input > label > input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
|
|
8713
|
+
.oc-rating-input > label > span { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
8714
|
+
|
|
8715
|
+
.oc-rating-input:has(label:nth-of-type(1) input:checked) { --oc-rating-pick: 1; }
|
|
8716
|
+
.oc-rating-input:has(label:nth-of-type(2) input:checked) { --oc-rating-pick: 2; }
|
|
8717
|
+
.oc-rating-input:has(label:nth-of-type(3) input:checked) { --oc-rating-pick: 3; }
|
|
8718
|
+
.oc-rating-input:has(label:nth-of-type(4) input:checked) { --oc-rating-pick: 4; }
|
|
8719
|
+
.oc-rating-input:has(label:nth-of-type(5) input:checked) { --oc-rating-pick: 5; }
|
|
8720
|
+
/* Hover preview (pointer devices only, so a tap does not leave a preview behind). */
|
|
8721
|
+
@media (hover: hover) {
|
|
8722
|
+
.oc-rating-input:has(label:nth-of-type(1):hover) { --oc-rating-hover: 1; }
|
|
8723
|
+
.oc-rating-input:has(label:nth-of-type(2):hover) { --oc-rating-hover: 2; }
|
|
8724
|
+
.oc-rating-input:has(label:nth-of-type(3):hover) { --oc-rating-hover: 3; }
|
|
8725
|
+
.oc-rating-input:has(label:nth-of-type(4):hover) { --oc-rating-hover: 4; }
|
|
8726
|
+
.oc-rating-input:has(label:nth-of-type(5):hover) { --oc-rating-hover: 5; }
|
|
8727
|
+
}
|
|
8728
|
+
.oc-rating-input:has(input:focus-visible) { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
8729
|
+
.oc-rating-input:has(input:disabled) { opacity: 0.5; }
|
|
8730
|
+
.oc-rating-input:has(input:disabled) > label,
|
|
8731
|
+
.oc-rating-input:has(input:disabled) > label > input { cursor: not-allowed; }
|
|
8732
|
+
|
|
8733
|
+
@media (forced-colors: active) {
|
|
8734
|
+
.oc-rating, .oc-rating-input::before { --oc-rating-color: CanvasText; --oc-rating-empty: GrayText; forced-color-adjust: none; }
|
|
8735
|
+
}
|
|
8736
|
+
|
|
7893
8737
|
/* parts/forms-time-input.css */
|
|
7894
8738
|
/* File: packages/ui/src/parts/forms-time-input.css
|
|
7895
8739
|
Map: 24h text field (HH:mm) -> invalid state -> slot list (radio chips) -> slot states -> --sm
|
|
@@ -8064,7 +8908,7 @@ button.oc-language-select:hover { background: var(--oc-surface); }
|
|
|
8064
8908
|
/* File: packages/ui/src/parts/media-attachment.css | Map: list -> file chip (icon by type, name, size, open/remove) -> type tones
|
|
8065
8909
|
-> uploading progress + error -> image preview (in a message) -> thumbnail chip (in a composer) -> reduced motion
|
|
8066
8910
|
Attachment: a file chip or an image preview inside a chat message or a composer. The icon tile shows the extension and is
|
|
8067
|
-
tinted per type (--pdf, --doc, --sheet, --zip, --image).
|
|
8911
|
+
tinted per type (--pdf, --doc, --sheet, --zip, --image). */
|
|
8068
8912
|
|
|
8069
8913
|
.oc-attachment-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; list-style: none; }
|
|
8070
8914
|
.oc-attachment-list--stack { flex-direction: column; flex-wrap: nowrap; }
|
|
@@ -8222,6 +9066,31 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8222
9066
|
.oc-attachment, .oc-attachment--uploading::after { transition: none; }
|
|
8223
9067
|
}
|
|
8224
9068
|
|
|
9069
|
+
/* parts/media-barcode.css */
|
|
9070
|
+
/* File: packages/ui/src/parts/media-barcode.css | Map: barcode figure -> svg bars -> digits -> sizes (hero, compact) -> error */
|
|
9071
|
+
/* Barcode display: EAN-13, EAN-8, UPC-A or Code 128, drawn as SVG by
|
|
9072
|
+
packages/ui/src/barcode.js from data-value. Always black bars on white, in both themes, so scanners read it. */
|
|
9073
|
+
|
|
9074
|
+
.oc-barcode {
|
|
9075
|
+
display: inline-flex;
|
|
9076
|
+
flex-direction: column;
|
|
9077
|
+
align-items: center;
|
|
9078
|
+
gap: 0.25rem;
|
|
9079
|
+
margin: 0;
|
|
9080
|
+
padding: 0.75rem 1rem;
|
|
9081
|
+
color: var(--color-black-50);
|
|
9082
|
+
background: var(--color-white-50);
|
|
9083
|
+
border: 1px solid var(--oc-border);
|
|
9084
|
+
border-radius: var(--oc-radius);
|
|
9085
|
+
}
|
|
9086
|
+
.oc-barcode svg { display: block; inline-size: auto; block-size: var(--oc-barcode-height, 4rem); max-inline-size: 100%; }
|
|
9087
|
+
.oc-barcode__digits { font-family: var(--oc-font-mono); font-size: 0.8125rem; letter-spacing: 0.18em; color: inherit; }
|
|
9088
|
+
.oc-barcode--hero { padding: 1.25rem 1.5rem; --oc-barcode-height: 6rem; }
|
|
9089
|
+
.oc-barcode--hero .oc-barcode__digits { font-size: 1rem; }
|
|
9090
|
+
.oc-barcode--compact { padding: 0.375rem 0.5rem; --oc-barcode-height: 2.25rem; }
|
|
9091
|
+
.oc-barcode--compact .oc-barcode__digits { font-size: 0.6875rem; letter-spacing: 0.1em; }
|
|
9092
|
+
.oc-barcode[data-error] .oc-barcode__digits { color: var(--color-red-70); letter-spacing: 0; }
|
|
9093
|
+
|
|
8225
9094
|
/* parts/media-browser-frame.css */
|
|
8226
9095
|
/* File: packages/ui/src/parts/media-browser-frame.css | Map: frame -> chrome bar (dots, address pill, actions)
|
|
8227
9096
|
-> view (screenshot slot, ratio) -> caption -> minimal / dark / tilt modifiers -> motion
|
|
@@ -8441,6 +9310,9 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8441
9310
|
line-height: 1;
|
|
8442
9311
|
cursor: pointer;
|
|
8443
9312
|
}
|
|
9313
|
+
/* Webicons in the buttons (inline SVG or <iconify-icon>): a fixed size, so nothing is cut off at the round edge. */
|
|
9314
|
+
.oc-chat-composer__tool > :is(svg, iconify-icon) { inline-size: 1.25rem; block-size: 1.25rem; font-size: 1.25rem; }
|
|
9315
|
+
.oc-chat-composer__send > :is(svg, iconify-icon) { inline-size: 1.125rem; block-size: 1.125rem; font-size: 1.125rem; }
|
|
8444
9316
|
.oc-chat-composer__tool:hover { background: var(--oc-surface-strong); color: var(--oc-foreground); }
|
|
8445
9317
|
.oc-chat-composer__tool:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
8446
9318
|
|
|
@@ -8645,9 +9517,11 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8645
9517
|
background: transparent;
|
|
8646
9518
|
font-size: 1.15rem;
|
|
8647
9519
|
line-height: 1;
|
|
9520
|
+
color: var(--oc-muted-foreground);
|
|
8648
9521
|
cursor: pointer;
|
|
8649
9522
|
}
|
|
8650
|
-
.oc-emoji-picker__trigger:
|
|
9523
|
+
.oc-emoji-picker__trigger > :is(svg, iconify-icon) { inline-size: 1.25rem; block-size: 1.25rem; font-size: 1.25rem; }
|
|
9524
|
+
.oc-emoji-picker__trigger:hover { color: var(--oc-foreground); background: var(--oc-surface-strong); }
|
|
8651
9525
|
.oc-emoji-picker__trigger:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
8652
9526
|
|
|
8653
9527
|
/* The panel: floats above the trigger (implicit anchor of popovertarget), flips when there is no room. */
|
|
@@ -8851,6 +9725,216 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8851
9725
|
.oc-flip-card--hover:is(:hover, :focus-within) .oc-flip-card__face--back { opacity: 1; visibility: visible; }
|
|
8852
9726
|
}
|
|
8853
9727
|
|
|
9728
|
+
/* parts/media-gallery.css */
|
|
9729
|
+
/* File: packages/ui/src/parts/media-gallery.css | Map: gallery grid -> stage and slides (radio + :has, up to 8) -> badge -> thumbnails -> side layout (container query) */
|
|
9730
|
+
/* Product gallery without JavaScript: one large photo and a row of thumbnails. Every thumbnail is a label with a
|
|
9731
|
+
radio; :has() shows the slide at the same position. Arrow keys move between the photos (native radios). */
|
|
9732
|
+
|
|
9733
|
+
.oc-gallery { container-type: inline-size; inline-size: 100%; display: grid; gap: 0.75rem; min-inline-size: 0; }
|
|
9734
|
+
.oc-gallery__stage {
|
|
9735
|
+
position: relative;
|
|
9736
|
+
aspect-ratio: var(--oc-gallery-ratio, 4 / 3);
|
|
9737
|
+
overflow: hidden;
|
|
9738
|
+
background: var(--oc-muted);
|
|
9739
|
+
border: 1px solid var(--oc-border);
|
|
9740
|
+
border-radius: calc(var(--oc-radius) + 4px);
|
|
9741
|
+
}
|
|
9742
|
+
.oc-gallery__slide { display: none; margin: 0; block-size: 100%; }
|
|
9743
|
+
.oc-gallery__slide > img { display: block; inline-size: 100%; block-size: 100%; object-fit: var(--oc-gallery-fit, contain); }
|
|
9744
|
+
.oc-gallery:not(:has(.oc-gallery__thumb input:checked)) .oc-gallery__slide:first-of-type,
|
|
9745
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(1) input:checked) .oc-gallery__slide:nth-of-type(1),
|
|
9746
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(2) input:checked) .oc-gallery__slide:nth-of-type(2),
|
|
9747
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(3) input:checked) .oc-gallery__slide:nth-of-type(3),
|
|
9748
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(4) input:checked) .oc-gallery__slide:nth-of-type(4),
|
|
9749
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(5) input:checked) .oc-gallery__slide:nth-of-type(5),
|
|
9750
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(6) input:checked) .oc-gallery__slide:nth-of-type(6),
|
|
9751
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(7) input:checked) .oc-gallery__slide:nth-of-type(7),
|
|
9752
|
+
.oc-gallery:has(.oc-gallery__thumb:nth-of-type(8) input:checked) .oc-gallery__slide:nth-of-type(8) { display: block; }
|
|
9753
|
+
.oc-gallery__badge { position: absolute; inset: 0.75rem auto auto 0.75rem; z-index: 1; }
|
|
9754
|
+
|
|
9755
|
+
.oc-gallery__thumbs { display: flex; gap: 0.5rem; min-inline-size: 0; margin: 0; padding: 0.125rem; overflow-x: auto; border: 0; scrollbar-width: thin; }
|
|
9756
|
+
.oc-gallery__thumbs > legend { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
9757
|
+
.oc-gallery__thumb {
|
|
9758
|
+
position: relative;
|
|
9759
|
+
flex: 0 0 auto;
|
|
9760
|
+
inline-size: var(--oc-gallery-thumb, 4rem);
|
|
9761
|
+
aspect-ratio: 1;
|
|
9762
|
+
overflow: hidden;
|
|
9763
|
+
background: var(--oc-muted);
|
|
9764
|
+
border: 2px solid transparent;
|
|
9765
|
+
border-radius: var(--oc-radius);
|
|
9766
|
+
outline: 1px solid var(--oc-border);
|
|
9767
|
+
outline-offset: -1px;
|
|
9768
|
+
cursor: pointer;
|
|
9769
|
+
}
|
|
9770
|
+
.oc-gallery__thumb > img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
|
|
9771
|
+
.oc-gallery__thumb > input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
|
|
9772
|
+
.oc-gallery__thumb:hover { outline-color: var(--oc-muted-foreground); }
|
|
9773
|
+
.oc-gallery__thumb:has(input:checked) { border-color: var(--oc-primary); outline-color: transparent; }
|
|
9774
|
+
.oc-gallery__thumb:has(input:focus-visible) { box-shadow: 0 0 0 2px var(--oc-background), 0 0 0 4px var(--oc-ring); }
|
|
9775
|
+
|
|
9776
|
+
/* Side: thumbnails in a column on the left once the gallery itself is 32rem wide or more. The grid is always two
|
|
9777
|
+
tracks; below 32rem both children span them, so the query only moves the children (a container cannot query itself). */
|
|
9778
|
+
.oc-gallery--side { grid-template-columns: auto minmax(0, 1fr); }
|
|
9779
|
+
.oc-gallery--side > * { grid-column: 1 / -1; }
|
|
9780
|
+
@container (min-width: 32rem) {
|
|
9781
|
+
.oc-gallery--side > .oc-gallery__stage { grid-column: 2; grid-row: 1; }
|
|
9782
|
+
.oc-gallery--side > .oc-gallery__thumbs { grid-column: 1; grid-row: 1; flex-direction: column; overflow: visible; }
|
|
9783
|
+
}
|
|
9784
|
+
|
|
9785
|
+
/* parts/media-glass-liquid.css */
|
|
9786
|
+
/* File: packages/ui/src/parts/media-glass-liquid.css
|
|
9787
|
+
Map: liquid sheet (.oc-glass--liquid: clear tint, strong blur + saturation, inner light, specular rim) -> menu bar
|
|
9788
|
+
(.oc-glass-bar: items with icon and label, the current one in a raised bubble) -> icon-only and round button -> fallbacks
|
|
9789
|
+
Liquid glass in the style of recent desktop and phone systems, in CSS only: the backdrop is blurred and brightened,
|
|
9790
|
+
the edge catches light. Put it over a photo or colourful content; on a plain page it looks like a soft card. */
|
|
9791
|
+
|
|
9792
|
+
.oc-glass.oc-glass--liquid,
|
|
9793
|
+
.oc-glass--liquid,
|
|
9794
|
+
.oc-glass-bar,
|
|
9795
|
+
.oc-site-header--glass .oc-site-header__inner {
|
|
9796
|
+
--oc-liquid-tint: light-dark(oklch(100% 0 0deg / 0.1), oklch(100% 0 0deg / 0.05));
|
|
9797
|
+
--oc-liquid-edge: light-dark(oklch(100% 0 0deg / 0.55), oklch(100% 0 0deg / 0.22));
|
|
9798
|
+
--oc-liquid-blur: 5px;
|
|
9799
|
+
position: relative;
|
|
9800
|
+
isolation: isolate;
|
|
9801
|
+
background: var(--oc-liquid-tint);
|
|
9802
|
+
border: 1px solid var(--oc-liquid-edge);
|
|
9803
|
+
/* Light enters at the top left and leaves at the bottom right; a soft glow runs along the inner edge,
|
|
9804
|
+
so the sheet reads as a thick, clear lens rather than frosted plastic. */
|
|
9805
|
+
box-shadow:
|
|
9806
|
+
0 10px 30px -10px oklch(0% 0 0deg / 0.35),
|
|
9807
|
+
inset 2px 2px 1px -2px oklch(100% 0 0deg / 0.95),
|
|
9808
|
+
inset -2px -2px 1px -2px oklch(100% 0 0deg / 0.7),
|
|
9809
|
+
inset 0 0 10px 1px oklch(100% 0 0deg / 0.22),
|
|
9810
|
+
inset 0 -8px 16px -12px oklch(100% 0 0deg / 0.35);
|
|
9811
|
+
backdrop-filter: blur(var(--oc-liquid-blur)) saturate(1.9) brightness(1.1) contrast(1.05);
|
|
9812
|
+
}
|
|
9813
|
+
/* Specular rim: bright on the top-left and bottom-right edge, only on the border ring. */
|
|
9814
|
+
.oc-glass--liquid::before,
|
|
9815
|
+
.oc-glass-bar::before,
|
|
9816
|
+
.oc-site-header--glass .oc-site-header__inner::before {
|
|
9817
|
+
content: "";
|
|
9818
|
+
position: absolute;
|
|
9819
|
+
inset: -1px;
|
|
9820
|
+
z-index: 1;
|
|
9821
|
+
padding: 1.5px;
|
|
9822
|
+
border-radius: inherit;
|
|
9823
|
+
background: linear-gradient(135deg, oklch(100% 0 0deg / 1), oklch(100% 0 0deg / 0.15) 25%, oklch(100% 0 0deg / 0) 50%, oklch(100% 0 0deg / 0.15) 75%, oklch(100% 0 0deg / 0.8));
|
|
9824
|
+
mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
|
9825
|
+
mask-composite: exclude;
|
|
9826
|
+
pointer-events: none;
|
|
9827
|
+
}
|
|
9828
|
+
|
|
9829
|
+
/* Menu bar: a pill of items, each an icon over a short label. */
|
|
9830
|
+
.oc-glass-bar {
|
|
9831
|
+
display: inline-flex;
|
|
9832
|
+
align-items: center;
|
|
9833
|
+
gap: 0.2rem;
|
|
9834
|
+
padding: 0.35rem;
|
|
9835
|
+
border-radius: 999px;
|
|
9836
|
+
}
|
|
9837
|
+
.oc-glass-bar__item {
|
|
9838
|
+
position: relative;
|
|
9839
|
+
display: grid;
|
|
9840
|
+
justify-items: center;
|
|
9841
|
+
gap: 0.15rem;
|
|
9842
|
+
min-inline-size: 4.25rem;
|
|
9843
|
+
padding: 0.45rem 0.85rem;
|
|
9844
|
+
border: 0;
|
|
9845
|
+
border-radius: 999px;
|
|
9846
|
+
color: light-dark(oklch(22% 0.02 260deg / 0.78), oklch(100% 0 0deg / 0.82));
|
|
9847
|
+
background: none;
|
|
9848
|
+
font: inherit;
|
|
9849
|
+
font-size: 0.7rem;
|
|
9850
|
+
font-weight: 600;
|
|
9851
|
+
line-height: 1.1;
|
|
9852
|
+
text-decoration: none;
|
|
9853
|
+
cursor: pointer;
|
|
9854
|
+
transition: background-color 0.25s, color 0.25s, box-shadow 0.25s, scale 0.2s;
|
|
9855
|
+
}
|
|
9856
|
+
.oc-glass-bar__item > :is(svg, iconify-icon) { inline-size: 1.4rem; block-size: 1.4rem; font-size: 1.4rem; }
|
|
9857
|
+
.oc-glass-bar__item:hover { background: light-dark(oklch(100% 0 0deg / 0.28), oklch(100% 0 0deg / 0.08)); }
|
|
9858
|
+
.oc-glass-bar__item:active { scale: 0.94; }
|
|
9859
|
+
.oc-glass-bar__item:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
9860
|
+
/* The current item sits in a raised, lighter bubble. */
|
|
9861
|
+
.oc-glass-bar__item:is([aria-current="page"], [aria-pressed="true"], :has(> input:checked)) {
|
|
9862
|
+
color: light-dark(var(--oc-primary), var(--color-white-50));
|
|
9863
|
+
background: light-dark(oklch(100% 0 0deg / 0.62), oklch(100% 0 0deg / 0.24));
|
|
9864
|
+
box-shadow: inset 0 1px 1px oklch(100% 0 0deg / 0.85), 0 6px 14px -8px oklch(0% 0 0deg / 0.4);
|
|
9865
|
+
}
|
|
9866
|
+
.oc-glass-bar__item > input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
|
|
9867
|
+
.oc-glass-bar__item:has(> input:focus-visible) { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
9868
|
+
|
|
9869
|
+
/* Icons only, and a separate round button next to the bar (search, compose). */
|
|
9870
|
+
.oc-glass-bar--icons .oc-glass-bar__item { min-inline-size: 0; padding: 0.6rem; }
|
|
9871
|
+
.oc-glass-bar--round { padding: 0.35rem; border-radius: 999px; }
|
|
9872
|
+
.oc-glass-bar--round .oc-glass-bar__item { min-inline-size: 0; padding: 0.6rem; }
|
|
9873
|
+
.oc-glass-bar__sep { align-self: stretch; inline-size: 1px; margin: 0.4rem 0.15rem; background: var(--oc-liquid-edge); }
|
|
9874
|
+
|
|
9875
|
+
/* Less transparency asked for, or no backdrop-filter: a solid bar that still reads as one. */
|
|
9876
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
9877
|
+
.oc-glass--liquid, .oc-glass-bar { --oc-liquid-tint: var(--oc-card); backdrop-filter: none; }
|
|
9878
|
+
}
|
|
9879
|
+
@supports not (backdrop-filter: blur(1px)) {
|
|
9880
|
+
.oc-glass--liquid, .oc-glass-bar { --oc-liquid-tint: light-dark(oklch(100% 0 0deg / 0.85), oklch(25% 0.02 260deg / 0.9)); }
|
|
9881
|
+
}
|
|
9882
|
+
@media (prefers-reduced-motion: reduce) {
|
|
9883
|
+
.oc-glass-bar__item { transition: none; }
|
|
9884
|
+
}
|
|
9885
|
+
|
|
9886
|
+
/* parts/media-glass-options.css */
|
|
9887
|
+
/* File: packages/ui/src/parts/media-glass-options.css
|
|
9888
|
+
Map: amount (--clear: more see-through, --frost: more frosted) -> light content on a colourful backdrop -> stage (moving colour blobs to show it off)
|
|
9889
|
+
Extras for .oc-glass, .oc-glass--liquid and .oc-glass-bar (media-glass.css, media-glass-liquid.css). The selectors
|
|
9890
|
+
carry two classes so they win over the base glass whatever order the parts load in. */
|
|
9891
|
+
|
|
9892
|
+
/* Amount of glass: --clear lets more of the backdrop through, --frost hides more of it. */
|
|
9893
|
+
:is(.oc-glass, .oc-glass-bar).oc-glass--clear {
|
|
9894
|
+
--oc-glass-sheet: light-dark(oklch(from var(--oc-background) l c h / 0.32), oklch(from var(--oc-background) l c h / 0.26));
|
|
9895
|
+
--oc-glass-blur: 10px;
|
|
9896
|
+
--oc-liquid-tint: light-dark(oklch(100% 0 0deg / 0.05), oklch(100% 0 0deg / 0.03));
|
|
9897
|
+
--oc-liquid-blur: 2px;
|
|
9898
|
+
}
|
|
9899
|
+
:is(.oc-glass, .oc-glass-bar).oc-glass--frost {
|
|
9900
|
+
--oc-glass-sheet: light-dark(oklch(from var(--oc-background) l c h / 0.86), oklch(from var(--oc-background) l c h / 0.8));
|
|
9901
|
+
--oc-glass-blur: 40px;
|
|
9902
|
+
--oc-liquid-tint: light-dark(oklch(100% 0 0deg / 0.38), oklch(100% 0 0deg / 0.12));
|
|
9903
|
+
--oc-liquid-blur: 18px;
|
|
9904
|
+
}
|
|
9905
|
+
|
|
9906
|
+
|
|
9907
|
+
/* Light content: white icons and labels for glass over a dark or very colourful backdrop. */
|
|
9908
|
+
.oc-glass-bar.oc-glass-bar--light .oc-glass-bar__item {
|
|
9909
|
+
color: oklch(100% 0 0deg / 0.92);
|
|
9910
|
+
text-shadow: 0 1px 2px oklch(0% 0 0deg / 0.25);
|
|
9911
|
+
}
|
|
9912
|
+
.oc-glass-bar.oc-glass-bar--light .oc-glass-bar__item:is([aria-current="page"], [aria-pressed="true"], :has(> input:checked)) {
|
|
9913
|
+
color: var(--color-white-50);
|
|
9914
|
+
background: oklch(100% 0 0deg / 0.2);
|
|
9915
|
+
}
|
|
9916
|
+
.oc-glass-bar.oc-glass-bar--light .oc-glass-bar__item:hover { background: oklch(100% 0 0deg / 0.12); }
|
|
9917
|
+
|
|
9918
|
+
/* Stage: round colour shapes that drift slowly, so the change through the glass shows. A background for a hero or a demo. */
|
|
9919
|
+
.oc-glass-stage {
|
|
9920
|
+
position: relative;
|
|
9921
|
+
overflow: hidden;
|
|
9922
|
+
background:
|
|
9923
|
+
radial-gradient(circle at 22% 72%, var(--color-magenta-50) 0 16%, transparent 16.5%),
|
|
9924
|
+
radial-gradient(circle at 82% 68%, var(--color-orange-50) 0 18%, transparent 18.5%),
|
|
9925
|
+
radial-gradient(circle at 58% 18%, var(--color-skycyan-50) 0 13%, transparent 13.5%),
|
|
9926
|
+
radial-gradient(60% 70% at 30% 30%, var(--color-magenta-60), transparent 70%),
|
|
9927
|
+
linear-gradient(120deg, var(--color-purple-60), var(--color-violet-80));
|
|
9928
|
+
background-size: 140% 140%;
|
|
9929
|
+
animation: oc-glass-stage 18s ease-in-out infinite alternate;
|
|
9930
|
+
}
|
|
9931
|
+
@keyframes oc-glass-stage {
|
|
9932
|
+
to { background-position: 100% 60%; }
|
|
9933
|
+
}
|
|
9934
|
+
@media (prefers-reduced-motion: reduce) {
|
|
9935
|
+
.oc-glass-stage { animation: none; }
|
|
9936
|
+
}
|
|
9937
|
+
|
|
8854
9938
|
/* parts/media-glass.css */
|
|
8855
9939
|
/* File: packages/ui/src/parts/media-glass.css
|
|
8856
9940
|
Map: tokens (light-dark) -> sheet (.oc-glass: see-through, blurred, light top edge, soft shadow) -> panel (.oc-glass-panel:
|
|
@@ -8994,6 +10078,54 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8994
10078
|
.oc-image-zoom__canvas { transition: inline-size var(--oc-transition-normal); }
|
|
8995
10079
|
}
|
|
8996
10080
|
|
|
10081
|
+
/* parts/media-lazy.css */
|
|
10082
|
+
/* File: packages/ui/src/parts/media-lazy.css | Map: box (aspect ratio, shimmer placeholder or a tiny blurred preview) -> image fades in -> error -> lazy sections
|
|
10083
|
+
Lazy loading. .oc-lazy: an image box that keeps its place, shows a shimmer (or --oc-lazy-preview, a tiny blurred
|
|
10084
|
+
copy) until the photo is there and then fades it in (lazy.js adds .is-loaded). .oc-lazy-section: content the browser
|
|
10085
|
+
only lays out and draws when it comes near the screen (content-visibility). */
|
|
10086
|
+
|
|
10087
|
+
.oc-lazy {
|
|
10088
|
+
--oc-lazy-ratio: 16 / 10;
|
|
10089
|
+
position: relative;
|
|
10090
|
+
display: block;
|
|
10091
|
+
margin: 0;
|
|
10092
|
+
overflow: hidden;
|
|
10093
|
+
aspect-ratio: var(--oc-lazy-ratio);
|
|
10094
|
+
border-radius: var(--oc-radius);
|
|
10095
|
+
background:
|
|
10096
|
+
linear-gradient(100deg, transparent 30%, oklch(from var(--oc-background) l c h / 0.55) 50%, transparent 70%) -150% 0 / 60% 100% no-repeat,
|
|
10097
|
+
var(--oc-muted);
|
|
10098
|
+
animation: oc-lazy-shimmer 1.4s ease-in-out infinite;
|
|
10099
|
+
}
|
|
10100
|
+
/* A tiny blurred preview instead of the shimmer: style="--oc-lazy-preview: url(photo-20px.webp)". */
|
|
10101
|
+
.oc-lazy[style*="--oc-lazy-preview"] { animation: none; background: var(--oc-muted); }
|
|
10102
|
+
.oc-lazy[style*="--oc-lazy-preview"]::before { content: ""; position: absolute; inset: 0; background: var(--oc-lazy-preview) center / cover no-repeat; filter: blur(14px); scale: 1.15; }
|
|
10103
|
+
.oc-lazy > img { position: relative; display: block; inline-size: 100%; block-size: 100%; object-fit: cover; opacity: 0; transition: opacity 0.45s ease; }
|
|
10104
|
+
.oc-lazy.is-loaded { animation: none; background: none; }
|
|
10105
|
+
.oc-lazy.is-loaded::before { display: none; }
|
|
10106
|
+
.oc-lazy.is-loaded > img { opacity: 1; }
|
|
10107
|
+
.oc-lazy.is-error { animation: none; }
|
|
10108
|
+
.oc-lazy.is-error > img { opacity: 0; }
|
|
10109
|
+
.oc-lazy > figcaption { position: absolute; inset: auto 0 0; padding: 0.4rem 0.6rem; font-size: 0.75rem; color: var(--color-white-50); background: linear-gradient(transparent, oklch(0% 0 0deg / 0.55)); }
|
|
10110
|
+
/* Without the script (or when it is off) the photo shows as soon as it is there. */
|
|
10111
|
+
@media (scripting: none) { .oc-lazy > img { opacity: 1; } }
|
|
10112
|
+
@keyframes oc-lazy-shimmer { to { background-position: 250% 0, 0 0; } }
|
|
10113
|
+
|
|
10114
|
+
/* Sections far down a long page: laid out and drawn only when they come near the screen. */
|
|
10115
|
+
.oc-lazy-section { content-visibility: auto; contain-intrinsic-size: auto var(--oc-lazy-size, 600px); }
|
|
10116
|
+
|
|
10117
|
+
@media (prefers-reduced-motion: reduce) {
|
|
10118
|
+
.oc-lazy { animation: none; }
|
|
10119
|
+
.oc-lazy > img { transition: none; }
|
|
10120
|
+
}
|
|
10121
|
+
|
|
10122
|
+
/* In a table or a list: a small square thumbnail, and placeholder rows (.oc-lazy-row) while the next page loads. */
|
|
10123
|
+
.oc-lazy.oc-lazy--thumb { --oc-lazy-ratio: 1; inline-size: 2.5rem; flex: none; border-radius: calc(var(--oc-radius) - 2px); }
|
|
10124
|
+
.oc-lazy-row > :is(td, th) { padding-block: 0.6rem; }
|
|
10125
|
+
.oc-lazy-row .oc-lazy-bar { display: block; block-size: 0.75rem; inline-size: var(--oc-lazy-bar, 70%); border-radius: 999px; background: var(--oc-muted); animation: oc-lazy-pulse 1.2s ease-in-out infinite alternate; }
|
|
10126
|
+
@keyframes oc-lazy-pulse { to { opacity: 0.45; } }
|
|
10127
|
+
@media (prefers-reduced-motion: reduce) { .oc-lazy-row .oc-lazy-bar { animation: none; } }
|
|
10128
|
+
|
|
8997
10129
|
/* parts/media-lightbox.css */
|
|
8998
10130
|
/* File: packages/ui/src/parts/media-lightbox.css | Map: thumbnails -> dialog + backdrop -> bar -> track + slides
|
|
8999
10131
|
-> nav buttons -> caption + counter -> single image -> small screens -> motion
|
|
@@ -9172,7 +10304,7 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
9172
10304
|
people, status, actions) -> wallpaper (masked doodles in a token color) -> scroll area (starts at the bottom)
|
|
9173
10305
|
-> composer footer -> sending overlay (aria-busy) -> reduced motion
|
|
9174
10306
|
Message thread: one conversation. The scroll area uses flex-direction: column-reverse, so it opens at the newest message
|
|
9175
|
-
and stays there when messages are added, without a script.
|
|
10307
|
+
and stays there when messages are added, without a script. */
|
|
9176
10308
|
|
|
9177
10309
|
.oc-message-thread {
|
|
9178
10310
|
--oc-message-thread-height: 32rem;
|
|
@@ -9310,7 +10442,7 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
9310
10442
|
-> grouping (:has) -> hover actions -> date divider + system line -> reduced motion
|
|
9311
10443
|
Message: one chat bubble. Incoming on the left with the avatar, outgoing on the right in the primary tint.
|
|
9312
10444
|
Consecutive messages of one sender group by themselves: the avatar shows once (on the last one), the name once (on the
|
|
9313
|
-
first one).
|
|
10445
|
+
first one). */
|
|
9314
10446
|
|
|
9315
10447
|
.oc-message-list {
|
|
9316
10448
|
--oc-message-in: var(--oc-card);
|
|
@@ -9880,6 +11012,104 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
9880
11012
|
.oc-watermark { --oc-watermark-opacity: 0.2; print-color-adjust: exact; }
|
|
9881
11013
|
}
|
|
9882
11014
|
|
|
11015
|
+
/* parts/nav-topbar-variants.css */
|
|
11016
|
+
/* File: packages/ui/src/parts/nav-topbar-variants.css
|
|
11017
|
+
Map: brand (logo tile, room before the menu) -> centred menu -> plain links -> dark / brand colour -> floating pill
|
|
11018
|
+
-> strip above the bar -> footer bar (split, links, dark)
|
|
11019
|
+
Variants of the site header (.oc-topbar in docs-ui.css) and the footer bar (.oc-footerbar). Colours are tokens. */
|
|
11020
|
+
|
|
11021
|
+
/* Brand: a logo tile and the name, always with room before the menu. */
|
|
11022
|
+
.oc-topbar-brand { display: inline-flex; align-items: center; gap: 0.55rem; margin-inline-end: 1rem; }
|
|
11023
|
+
.oc-topbar-logo {
|
|
11024
|
+
display: grid;
|
|
11025
|
+
place-items: center;
|
|
11026
|
+
flex: none;
|
|
11027
|
+
inline-size: 1.85rem;
|
|
11028
|
+
block-size: 1.85rem;
|
|
11029
|
+
border-radius: 9px;
|
|
11030
|
+
color: var(--color-white-50);
|
|
11031
|
+
background: linear-gradient(135deg, var(--oc-accent-from, var(--oc-primary)), var(--oc-accent-to, var(--oc-primary)));
|
|
11032
|
+
font-size: 0.95rem;
|
|
11033
|
+
}
|
|
11034
|
+
.oc-topbar-logo > :is(svg, iconify-icon) { inline-size: 1.1rem; block-size: 1.1rem; font-size: 1.1rem; }
|
|
11035
|
+
.oc-topbar-nav { min-inline-size: 0; }
|
|
11036
|
+
.oc-topbar-actions .oc-btn { white-space: nowrap; }
|
|
11037
|
+
|
|
11038
|
+
/* Centred menu: brand left, menu in the middle, actions right (from 761px; smaller screens keep the burger). */
|
|
11039
|
+
@media (min-width: 761px) {
|
|
11040
|
+
.oc-topbar--center { display: grid; grid-template-columns: 1fr auto 1fr; }
|
|
11041
|
+
.oc-topbar--center .oc-topbar-brand { justify-self: start; }
|
|
11042
|
+
.oc-topbar--center .oc-topbar-actions { justify-self: end; }
|
|
11043
|
+
}
|
|
11044
|
+
|
|
11045
|
+
/* Plain links: no pill frames, the current page underlined. */
|
|
11046
|
+
.oc-topbar--plain .oc-navmenu--site .oc-navmenu-link {
|
|
11047
|
+
border-color: transparent;
|
|
11048
|
+
border-radius: 0;
|
|
11049
|
+
background: none;
|
|
11050
|
+
color: var(--oc-muted-foreground);
|
|
11051
|
+
box-shadow: inset 0 -2px 0 transparent;
|
|
11052
|
+
}
|
|
11053
|
+
.oc-topbar--plain .oc-navmenu--site .oc-navmenu-link:hover { color: var(--oc-foreground); border-color: transparent; background: none; }
|
|
11054
|
+
.oc-topbar--plain .oc-navmenu--site .oc-navmenu-link[aria-current="page"] {
|
|
11055
|
+
color: var(--oc-foreground);
|
|
11056
|
+
border-color: transparent;
|
|
11057
|
+
background: none;
|
|
11058
|
+
box-shadow: inset 0 -2px 0 var(--oc-primary);
|
|
11059
|
+
}
|
|
11060
|
+
|
|
11061
|
+
/* Dark bar and brand-colour bar: light text, links as soft pills. */
|
|
11062
|
+
.oc-topbar:is(.oc-topbar--dark, .oc-topbar--brand) { color: var(--color-white-50); border-block-end-color: transparent; }
|
|
11063
|
+
.oc-topbar.oc-topbar--dark { background: var(--oc-dark-band, var(--color-duskblue-95)); }
|
|
11064
|
+
.oc-topbar--brand { background: linear-gradient(100deg, var(--oc-accent-from, var(--oc-primary)), var(--oc-accent-to, var(--oc-primary))); }
|
|
11065
|
+
.oc-topbar:is(.oc-topbar--dark, .oc-topbar--brand) .oc-navmenu--site .oc-navmenu-link {
|
|
11066
|
+
color: oklch(from var(--color-white-50) l c h / 0.8);
|
|
11067
|
+
border-color: transparent;
|
|
11068
|
+
background: none;
|
|
11069
|
+
}
|
|
11070
|
+
.oc-topbar:is(.oc-topbar--dark, .oc-topbar--brand) .oc-navmenu--site .oc-navmenu-link:is(:hover, [aria-current="page"]) {
|
|
11071
|
+
color: var(--color-white-50);
|
|
11072
|
+
border-color: transparent;
|
|
11073
|
+
background: oklch(from var(--color-white-50) l c h / 0.14);
|
|
11074
|
+
}
|
|
11075
|
+
.oc-topbar--dark .oc-topbar-logo { background: oklch(from var(--color-white-50) l c h / 0.14); }
|
|
11076
|
+
.oc-topbar--brand .oc-topbar-logo { color: var(--oc-primary); background: var(--color-white-50); }
|
|
11077
|
+
.oc-topbar:is(.oc-topbar--dark, .oc-topbar--brand) .oc-topbar-burger { color: inherit; border-color: oklch(from var(--color-white-50) l c h / 0.3); }
|
|
11078
|
+
|
|
11079
|
+
/* Floating: a rounded bar with room around it and a soft shadow (over a hero or a photo). */
|
|
11080
|
+
.oc-topbar--floating {
|
|
11081
|
+
margin: 0.75rem;
|
|
11082
|
+
border: 1px solid var(--oc-border);
|
|
11083
|
+
border-radius: 16px;
|
|
11084
|
+
box-shadow: 0 14px 34px -18px oklch(from var(--color-black-60) l c h / 0.35);
|
|
11085
|
+
}
|
|
11086
|
+
|
|
11087
|
+
/* Strip: a small row above the bar (contact, language, account). */
|
|
11088
|
+
.oc-topbar-strip {
|
|
11089
|
+
display: flex;
|
|
11090
|
+
flex-wrap: wrap;
|
|
11091
|
+
align-items: center;
|
|
11092
|
+
justify-content: space-between;
|
|
11093
|
+
gap: 0.25rem 1rem;
|
|
11094
|
+
padding: 0.35rem clamp(14px, 2vw, 28px);
|
|
11095
|
+
font-size: 0.78rem;
|
|
11096
|
+
color: var(--oc-muted-foreground);
|
|
11097
|
+
background: var(--oc-muted);
|
|
11098
|
+
}
|
|
11099
|
+
.oc-topbar-strip a { color: inherit; text-decoration: none; }
|
|
11100
|
+
.oc-topbar-strip a:hover { color: var(--oc-foreground); }
|
|
11101
|
+
.oc-topbar-strip > span { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 1rem; }
|
|
11102
|
+
|
|
11103
|
+
/* Footer bar: text left and links right (--split), a link list, a dark bar. */
|
|
11104
|
+
.oc-footerbar--split { justify-content: space-between; gap: 1rem; text-align: start; }
|
|
11105
|
+
.oc-footerbar--tall { block-size: auto; min-block-size: var(--ocm-footer-height, 2.25rem); padding-block: 0.85rem; flex-wrap: wrap; }
|
|
11106
|
+
.oc-footerbar-links { display: inline-flex; flex-wrap: wrap; gap: 0.25rem 1rem; margin: 0; padding: 0; list-style: none; }
|
|
11107
|
+
.oc-footerbar-links a { color: var(--oc-muted-foreground); text-decoration: none; }
|
|
11108
|
+
.oc-footerbar-links a:hover { color: var(--oc-foreground); }
|
|
11109
|
+
.oc-footerbar.oc-footerbar--dark { color: oklch(from var(--color-white-50) l c h / 0.7); background: var(--oc-dark-band, var(--color-duskblue-95)); border-block-start-color: transparent; }
|
|
11110
|
+
.oc-footerbar--dark :is(a, .oc-footerbar-links a) { color: oklch(from var(--color-white-50) l c h / 0.85); }
|
|
11111
|
+
.oc-footerbar--dark .oc-footerbar-links a:hover { color: var(--color-white-50); }
|
|
11112
|
+
|
|
9883
11113
|
/* parts/site-fact-list.css */
|
|
9884
11114
|
/* File: packages/ui/src/parts/site-fact-list.css
|
|
9885
11115
|
Map: plain -> compact -> stacked -> accent values -> narrow screens
|
|
@@ -9907,6 +11137,78 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
9907
11137
|
/* Very narrow containers: wrap instead of squeezing label and value together. */
|
|
9908
11138
|
.oc-fact-list > div { flex-wrap: wrap; }
|
|
9909
11139
|
|
|
11140
|
+
/* parts/site-header-variants.css */
|
|
11141
|
+
/* File: packages/ui/src/parts/site-header-variants.css
|
|
11142
|
+
Map: actions slot -> centred menu -> dark -> floating pill -> glass pill -> footer: centred, dark, newsletter, social
|
|
11143
|
+
Variants of the marketing header (.oc-site-header) and footer (.oc-site-footer) in showcase.css. The sticky header
|
|
11144
|
+
turns to glass while scrolling; the coloured variants keep their own background (no scroll animation). */
|
|
11145
|
+
|
|
11146
|
+
.oc-site-header__actions { display: flex; align-items: center; gap: 0.5rem; flex: none; }
|
|
11147
|
+
.oc-site-header__brand { white-space: nowrap; flex: none; }
|
|
11148
|
+
.oc-site-header__nav > :is(a, button):not(.oc-btn) { white-space: nowrap; }
|
|
11149
|
+
|
|
11150
|
+
/* Centred menu: brand left, menu in the middle, actions right. */
|
|
11151
|
+
@media (min-width: 861px) {
|
|
11152
|
+
.oc-site-header--center .oc-site-header__inner { display: grid; grid-template-columns: 1fr auto 1fr; }
|
|
11153
|
+
.oc-site-header--center .oc-site-header__brand { justify-self: start; }
|
|
11154
|
+
.oc-site-header--center .oc-site-header__actions { justify-self: end; }
|
|
11155
|
+
}
|
|
11156
|
+
|
|
11157
|
+
/* Dark: a solid dark bar with light text. */
|
|
11158
|
+
.oc-site-header--dark {
|
|
11159
|
+
animation: none;
|
|
11160
|
+
color: var(--color-white-50);
|
|
11161
|
+
background: var(--oc-dark-band, var(--color-duskblue-95));
|
|
11162
|
+
}
|
|
11163
|
+
.oc-site-header--dark :is(.oc-site-header__brand, .oc-site-header__nav a[aria-current="page"], .oc-site-header__nav a:not(.oc-btn):hover) { color: var(--color-white-50); }
|
|
11164
|
+
.oc-site-header--dark .oc-site-header__nav a:not(.oc-btn) { color: oklch(from var(--color-white-50) l c h / 0.72); }
|
|
11165
|
+
|
|
11166
|
+
/* Floating: the bar as a rounded card with room around it. */
|
|
11167
|
+
.oc-site-header:is(.oc-site-header--floating, .oc-site-header--glass) { animation: none; padding: 0.75rem; }
|
|
11168
|
+
.oc-site-header--floating .oc-site-header__inner {
|
|
11169
|
+
block-size: 4rem;
|
|
11170
|
+
padding-inline: 1rem 0.75rem;
|
|
11171
|
+
border: 1px solid var(--oc-border);
|
|
11172
|
+
border-radius: 18px;
|
|
11173
|
+
background: var(--oc-background);
|
|
11174
|
+
box-shadow: 0 16px 36px -22px oklch(from var(--color-black-60) l c h / 0.45);
|
|
11175
|
+
}
|
|
11176
|
+
|
|
11177
|
+
/* Glass: a clear liquid-glass pill over a photo or a hero (look in media-glass-liquid.css). */
|
|
11178
|
+
.oc-site-header--glass .oc-site-header__inner { block-size: 3.75rem; padding-inline: 1.1rem 0.6rem; border-radius: 999px; }
|
|
11179
|
+
.oc-site-header--glass :is(.oc-site-header__brand, .oc-site-header__nav a:not(.oc-btn)) { color: light-dark(var(--color-black-95), var(--color-white-50)); text-shadow: 0 1px 2px light-dark(oklch(100% 0 0deg / 0.5), oklch(0% 0 0deg / 0.4)); }
|
|
11180
|
+
|
|
11181
|
+
/* ---- Footer variants ---- */
|
|
11182
|
+
/* Centred: brand, one row of links, social icons and the bottom line, all centred. */
|
|
11183
|
+
.oc-site-footer--center { text-align: center; }
|
|
11184
|
+
.oc-site-footer--center :is(.oc-site-footer__about, .oc-site-footer__bottom) { justify-items: center; justify-content: center; }
|
|
11185
|
+
.oc-site-footer--center .oc-site-footer__about { display: grid; gap: 1rem; }
|
|
11186
|
+
.oc-site-footer--center .oc-site-footer__about p { margin: 0; max-inline-size: 34rem; }
|
|
11187
|
+
.oc-site-footer__row { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem 1.75rem; margin: 2rem 0 0; padding: 0; list-style: none; }
|
|
11188
|
+
.oc-site-footer__social { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; list-style: none; }
|
|
11189
|
+
.oc-site-footer--center .oc-site-footer__social { justify-content: center; margin-block-start: 1.5rem; }
|
|
11190
|
+
.oc-site-footer__social a {
|
|
11191
|
+
display: grid;
|
|
11192
|
+
place-items: center;
|
|
11193
|
+
inline-size: 2.25rem;
|
|
11194
|
+
block-size: 2.25rem;
|
|
11195
|
+
border: 1px solid var(--oc-border);
|
|
11196
|
+
border-radius: 999px;
|
|
11197
|
+
transition: border-color 0.2s, color 0.2s;
|
|
11198
|
+
}
|
|
11199
|
+
.oc-site-footer__social a:hover { border-color: var(--oc-primary); color: var(--oc-primary); }
|
|
11200
|
+
.oc-site-footer__social :is(svg, iconify-icon) { inline-size: 1.1rem; block-size: 1.1rem; font-size: 1.1rem; }
|
|
11201
|
+
|
|
11202
|
+
/* Dark: light text on a dark band, the same deep blue in light and dark mode (--oc-dark-band), no top border. */
|
|
11203
|
+
.oc-site-footer--dark { border-block-start: 0; color: oklch(from var(--color-white-50) l c h / 0.7); background: var(--oc-dark-band, var(--color-duskblue-95)); }
|
|
11204
|
+
.oc-site-footer--dark :is(.oc-site-footer__title, .oc-site-header__brand, a:hover) { color: var(--color-white-50); }
|
|
11205
|
+
.oc-site-footer--dark :is(.oc-site-footer__bottom, .oc-site-footer__social a) { border-color: oklch(from var(--color-white-50) l c h / 0.16); }
|
|
11206
|
+
|
|
11207
|
+
/* Newsletter: a sign-up field in the brand column. */
|
|
11208
|
+
.oc-site-footer__signup { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-block-start: 1.25rem; max-inline-size: 24rem; }
|
|
11209
|
+
.oc-site-footer__signup .oc-input { flex: 1 1 12rem; min-inline-size: 0; }
|
|
11210
|
+
.oc-site-footer--dark .oc-site-footer__signup .oc-input { color: var(--color-white-50); background: oklch(from var(--color-white-50) l c h / 0.08); border-color: oklch(from var(--color-white-50) l c h / 0.2); }
|
|
11211
|
+
|
|
9910
11212
|
/* parts/site-link-arrow.css */
|
|
9911
11213
|
/* File: packages/ui/src/parts/site-link-arrow.css
|
|
9912
11214
|
Map: focus ring -> back arrow -> external arrow -> color modifiers -> sizes -> reduced motion
|
|
@@ -10400,7 +11702,7 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
10400
11702
|
-> sizes (--sm, --lg) -> full width
|
|
10401
11703
|
Prose: typography for long-form text from a CMS, blog or help page, where the HTML has no classes of its own.
|
|
10402
11704
|
Every rule is scoped with :where(), so a utility class on an element inside still wins. Spacing is in em, so --sm and --lg
|
|
10403
|
-
scale the whole text.
|
|
11705
|
+
scale the whole text. */
|
|
10404
11706
|
|
|
10405
11707
|
.oc-prose {
|
|
10406
11708
|
max-inline-size: 68ch;
|