@birdycom/omniaui 0.12.4 → 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 +1496 -193
- 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 +40 -9
- 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); }
|
|
@@ -3880,19 +4005,20 @@ details.oc-collapsible[open]::details-content { block-size: auto; }
|
|
|
3880
4005
|
background: oklch(from var(--oc-accent-from) l c h / 0.14);
|
|
3881
4006
|
color: light-dark(var(--oc-accent-from), oklch(from var(--oc-accent-from) max(l, 0.72) c h));
|
|
3882
4007
|
}
|
|
3883
|
-
/*
|
|
4008
|
+
/* Live dot in a pill (.oc-pill > .oc-status-dot): the ring starts at --oc-status-dot-pulse-alpha of the accent and grows
|
|
4009
|
+
to --oc-status-dot-pulse-size. Scoped to the pill: a plain .oc-status-dot is the status light (parts/app-status-dot.css).
|
|
3884
4010
|
--strong starts at the full accent with a wider ring. */
|
|
3885
|
-
.oc-status-dot {
|
|
4011
|
+
.oc-pill .oc-status-dot {
|
|
3886
4012
|
--oc-status-dot-pulse-alpha: 0.6;
|
|
3887
4013
|
--oc-status-dot-pulse-size: 8px;
|
|
3888
4014
|
inline-size: 0.5rem;
|
|
3889
4015
|
aspect-ratio: 1;
|
|
3890
4016
|
border-radius: 50%;
|
|
3891
4017
|
background: var(--oc-accent-from);
|
|
3892
|
-
animation: oc-
|
|
4018
|
+
animation: oc-status-dot-ring 2s infinite;
|
|
3893
4019
|
}
|
|
3894
|
-
.oc-status-dot--strong { --oc-status-dot-pulse-alpha: 1; --oc-status-dot-pulse-size: 10px; }
|
|
3895
|
-
@keyframes oc-
|
|
4020
|
+
.oc-pill .oc-status-dot--strong { --oc-status-dot-pulse-alpha: 1; --oc-status-dot-pulse-size: 10px; }
|
|
4021
|
+
@keyframes oc-status-dot-ring {
|
|
3896
4022
|
0% { box-shadow: 0 0 0 0 oklch(from var(--oc-accent-from) l c h / var(--oc-status-dot-pulse-alpha)); }
|
|
3897
4023
|
70%, 100% { box-shadow: 0 0 0 var(--oc-status-dot-pulse-size) transparent; }
|
|
3898
4024
|
}
|
|
@@ -4053,7 +4179,7 @@ details.oc-collapsible[open]::details-content { block-size: auto; }
|
|
|
4053
4179
|
|
|
4054
4180
|
@media (prefers-reduced-motion: reduce) {
|
|
4055
4181
|
.oc-backdrop::before, .oc-backdrop::after, .oc-backdrop > .oc-backdrop__blob,
|
|
4056
|
-
.oc-icon-tile--float, .oc-marquee__track, .oc-status-dot, .oc-reveal, .oc-site-header { animation: none; }
|
|
4182
|
+
.oc-icon-tile--float, .oc-marquee__track, .oc-pill .oc-status-dot, .oc-reveal, .oc-site-header { animation: none; }
|
|
4057
4183
|
}
|
|
4058
4184
|
|
|
4059
4185
|
/* ===================================================================
|
|
@@ -4436,7 +4562,21 @@ details.oc-collapsible[open]::details-content { block-size: auto; }
|
|
|
4436
4562
|
.oc-slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px oklch(from var(--oc-ring) l c h / 0.28); }
|
|
4437
4563
|
.oc-slider:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px oklch(from var(--oc-ring) l c h / 0.28); }
|
|
4438
4564
|
.oc-slider:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
4439
|
-
|
|
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); }
|
|
4440
4580
|
.oc-slider--vertical::-webkit-slider-runnable-track {
|
|
4441
4581
|
background: linear-gradient(to top, var(--oc-primary) var(--oc-slider-progress), var(--oc-muted) var(--oc-slider-progress));
|
|
4442
4582
|
}
|
|
@@ -5439,93 +5579,6 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5439
5579
|
@keyframes oc-busy-in { from { opacity: 0; } }
|
|
5440
5580
|
@media (prefers-reduced-motion: reduce) { .oc-busy-overlay[open], .oc-busy-overlay[open]::backdrop { animation-duration: 0s; } }
|
|
5441
5581
|
|
|
5442
|
-
/* parts/app-column-menu.css */
|
|
5443
|
-
/* File: packages/ui/src/parts/app-column-menu.css | Map: menu panel -> title + list -> item states -> footer -> CSS-only column hiding (scope) */
|
|
5444
|
-
/* Column menu: a popover with one checkbox per table column (column visibility).
|
|
5445
|
-
CSS-only hiding: wrap the menu and the table in .oc-column-menu-scope and give each checkbox
|
|
5446
|
-
data-col="<column number>". An unchecked box hides that column (th and td) through :has(). */
|
|
5447
|
-
|
|
5448
|
-
/* Panel look. Without the popover attribute it is a normal block (e.g. inside a sheet or sidebar). */
|
|
5449
|
-
.oc-column-menu {
|
|
5450
|
-
inline-size: 14rem;
|
|
5451
|
-
max-inline-size: calc(100vw - 1rem);
|
|
5452
|
-
padding: 0.375rem;
|
|
5453
|
-
font-size: 0.875rem;
|
|
5454
|
-
color: var(--oc-popover-foreground);
|
|
5455
|
-
background: var(--oc-popover);
|
|
5456
|
-
border: 1px solid var(--oc-border);
|
|
5457
|
-
border-radius: var(--oc-radius);
|
|
5458
|
-
box-shadow: 0 8px 24px oklch(from var(--color-black-60) l c h / 0.15);
|
|
5459
|
-
}
|
|
5460
|
-
/* As a popover: in the top layer, tethered to its trigger like the dropdown. */
|
|
5461
|
-
.oc-column-menu[popover] {
|
|
5462
|
-
position: fixed;
|
|
5463
|
-
inset: auto;
|
|
5464
|
-
margin: 4px 0 0;
|
|
5465
|
-
position-area: block-end span-inline-start;
|
|
5466
|
-
position-try-fallbacks: flip-block, flip-inline;
|
|
5467
|
-
transition: opacity var(--oc-transition-fast), display var(--oc-transition-fast) allow-discrete, overlay var(--oc-transition-fast) allow-discrete;
|
|
5468
|
-
}
|
|
5469
|
-
.oc-column-menu[popover]:popover-open {
|
|
5470
|
-
display: block;
|
|
5471
|
-
@starting-style { opacity: 0; }
|
|
5472
|
-
}
|
|
5473
|
-
|
|
5474
|
-
/* Small heading above the list ("Columns"). */
|
|
5475
|
-
.oc-column-menu-title {
|
|
5476
|
-
margin: 0;
|
|
5477
|
-
padding: 0.375rem 0.5rem 0.25rem;
|
|
5478
|
-
font-size: 0.75rem;
|
|
5479
|
-
font-weight: 600;
|
|
5480
|
-
color: var(--oc-muted-foreground);
|
|
5481
|
-
}
|
|
5482
|
-
|
|
5483
|
-
/* The list is a <form>, so a native <button type="reset"> restores the default columns. */
|
|
5484
|
-
.oc-column-menu-list { display: grid; gap: 1px; margin: 0; max-block-size: 18rem; overflow-y: auto; }
|
|
5485
|
-
|
|
5486
|
-
/* One row: label around a checkbox and the column name. */
|
|
5487
|
-
.oc-column-menu-item {
|
|
5488
|
-
display: flex;
|
|
5489
|
-
align-items: center;
|
|
5490
|
-
gap: 0.5rem;
|
|
5491
|
-
padding: 0.375rem 0.5rem;
|
|
5492
|
-
border-radius: calc(var(--oc-radius) - 2px);
|
|
5493
|
-
cursor: pointer;
|
|
5494
|
-
user-select: none;
|
|
5495
|
-
}
|
|
5496
|
-
.oc-column-menu-item:hover { background: var(--oc-accent); }
|
|
5497
|
-
.oc-column-menu-item:has(:focus-visible) { outline: 2px solid var(--oc-ring); outline-offset: -2px; }
|
|
5498
|
-
.oc-column-menu-item input { margin: 0; accent-color: var(--oc-primary); }
|
|
5499
|
-
/* Locked column (always visible): <input disabled checked>. */
|
|
5500
|
-
.oc-column-menu-item:has(input:disabled) { color: var(--oc-muted-foreground); cursor: default; }
|
|
5501
|
-
.oc-column-menu-item:has(input:disabled):hover { background: none; }
|
|
5502
|
-
|
|
5503
|
-
/* Footer row with "Reset" (type="reset") or other small buttons. */
|
|
5504
|
-
.oc-column-menu-footer {
|
|
5505
|
-
display: flex;
|
|
5506
|
-
justify-content: flex-end;
|
|
5507
|
-
gap: 0.25rem;
|
|
5508
|
-
margin-block-start: 0.375rem;
|
|
5509
|
-
padding-block-start: 0.375rem;
|
|
5510
|
-
border-block-start: 1px solid var(--oc-border);
|
|
5511
|
-
}
|
|
5512
|
-
|
|
5513
|
-
/* ---- CSS-only column hiding (columns 1 to 10) ---- */
|
|
5514
|
-
.oc-column-menu-scope:has([data-col="1"]:not(:checked)) .oc-table :is(th, td):nth-child(1),
|
|
5515
|
-
.oc-column-menu-scope:has([data-col="2"]:not(:checked)) .oc-table :is(th, td):nth-child(2),
|
|
5516
|
-
.oc-column-menu-scope:has([data-col="3"]:not(:checked)) .oc-table :is(th, td):nth-child(3),
|
|
5517
|
-
.oc-column-menu-scope:has([data-col="4"]:not(:checked)) .oc-table :is(th, td):nth-child(4),
|
|
5518
|
-
.oc-column-menu-scope:has([data-col="5"]:not(:checked)) .oc-table :is(th, td):nth-child(5),
|
|
5519
|
-
.oc-column-menu-scope:has([data-col="6"]:not(:checked)) .oc-table :is(th, td):nth-child(6),
|
|
5520
|
-
.oc-column-menu-scope:has([data-col="7"]:not(:checked)) .oc-table :is(th, td):nth-child(7),
|
|
5521
|
-
.oc-column-menu-scope:has([data-col="8"]:not(:checked)) .oc-table :is(th, td):nth-child(8),
|
|
5522
|
-
.oc-column-menu-scope:has([data-col="9"]:not(:checked)) .oc-table :is(th, td):nth-child(9),
|
|
5523
|
-
.oc-column-menu-scope:has([data-col="10"]:not(:checked)) .oc-table :is(th, td):nth-child(10) { display: none; }
|
|
5524
|
-
|
|
5525
|
-
@media (prefers-reduced-motion: reduce) {
|
|
5526
|
-
.oc-column-menu[popover] { transition: none; }
|
|
5527
|
-
}
|
|
5528
|
-
|
|
5529
5582
|
/* parts/app-confirm-dialog.css */
|
|
5530
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 */
|
|
5531
5584
|
/* Confirm dialog: a variant of the alert dialog (dialog.oc-modal + .oc-alert-dialog).
|
|
@@ -5663,9 +5716,213 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5663
5716
|
}
|
|
5664
5717
|
@media (prefers-reduced-motion: reduce) { .oc-cookie-consent { transition: none; } }
|
|
5665
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
|
+
|
|
5666
5922
|
/* parts/app-data-table.css */
|
|
5667
|
-
/* File: packages/ui/src/parts/app-data-table.css | Map: shell -> toolbar -> frame and scroll -> header
|
|
5668
|
-
/* 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.
|
|
5669
5926
|
Behaviour (search, sort, pages, resize, drag, trash, bulk) lives in src/data-table.js.
|
|
5670
5927
|
Set --oc-data-table-max on the shell when the body should scroll and the header should stick. */
|
|
5671
5928
|
|
|
@@ -5678,13 +5935,16 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5678
5935
|
background: var(--oc-card);
|
|
5679
5936
|
border: 1px solid var(--oc-border);
|
|
5680
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;
|
|
5681
5941
|
}
|
|
5682
5942
|
|
|
5683
|
-
/* 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. */
|
|
5684
5944
|
.oc-data-table-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
|
|
5685
5945
|
.oc-data-table-heading { display: flex; align-items: center; gap: 0.5rem; min-inline-size: 0; }
|
|
5686
5946
|
.oc-data-table-title { font-size: 0.875rem; font-weight: 600; }
|
|
5687
|
-
.oc-data-table-search { flex: 1 1
|
|
5947
|
+
.oc-data-table-search { flex: 1 1 10rem; min-inline-size: 9rem; }
|
|
5688
5948
|
.oc-data-table-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-inline-start: auto; }
|
|
5689
5949
|
.oc-data-table-view { display: inline-flex; gap: 0.25rem; }
|
|
5690
5950
|
.oc-data-table-view [aria-pressed="true"] {
|
|
@@ -5692,55 +5952,52 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5692
5952
|
background: oklch(from var(--oc-primary) l c h / 0.1);
|
|
5693
5953
|
border-color: oklch(from var(--oc-primary) l c h / 0.35);
|
|
5694
5954
|
}
|
|
5695
|
-
|
|
5696
|
-
.oc-data-table-
|
|
5697
|
-
.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
|
+
}
|
|
5698
5962
|
|
|
5699
5963
|
/* The table sits in its own rounded frame. The scroll box keeps the header sticky. */
|
|
5700
5964
|
.oc-data-table-frame {
|
|
5965
|
+
min-inline-size: 0;
|
|
5701
5966
|
overflow: hidden;
|
|
5702
|
-
background: var(--oc-
|
|
5967
|
+
background: var(--oc-card);
|
|
5703
5968
|
border: 1px solid var(--oc-border);
|
|
5704
5969
|
border-radius: calc(var(--oc-radius) - 2px);
|
|
5705
5970
|
}
|
|
5706
5971
|
.oc-data-table-scroll { overflow: auto; max-block-size: var(--oc-data-table-max, none); }
|
|
5707
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; }
|
|
5708
5978
|
.oc-data-table .oc-table thead th {
|
|
5709
5979
|
position: sticky;
|
|
5710
5980
|
inset-block-start: 0;
|
|
5711
5981
|
z-index: 1;
|
|
5712
|
-
block-size: 2.
|
|
5713
|
-
font-size: 0.
|
|
5714
|
-
font-weight:
|
|
5982
|
+
block-size: 2.75rem;
|
|
5983
|
+
font-size: 0.8125rem;
|
|
5984
|
+
font-weight: 600;
|
|
5985
|
+
color: var(--oc-foreground);
|
|
5715
5986
|
background: var(--oc-card);
|
|
5716
5987
|
}
|
|
5717
|
-
|
|
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; }
|
|
5718
5997
|
.oc-data-table .oc-table tbody tr:last-child > td { border-block-end: 0; }
|
|
5719
5998
|
|
|
5720
|
-
/* Header label
|
|
5721
|
-
.oc-data-table-th { display: flex; align-items: center; gap: 0.25rem;
|
|
5722
|
-
.oc-data-table-resize {
|
|
5723
|
-
position: absolute;
|
|
5724
|
-
inset-block: 0;
|
|
5725
|
-
inset-inline-end: -0.45rem;
|
|
5726
|
-
inline-size: 0.55rem;
|
|
5727
|
-
padding: 0;
|
|
5728
|
-
background: none;
|
|
5729
|
-
border: 0;
|
|
5730
|
-
cursor: col-resize;
|
|
5731
|
-
touch-action: none;
|
|
5732
|
-
}
|
|
5733
|
-
.oc-data-table-resize::after {
|
|
5734
|
-
content: "";
|
|
5735
|
-
position: absolute;
|
|
5736
|
-
inset-block: 0.4rem;
|
|
5737
|
-
inset-inline-start: 0.25rem;
|
|
5738
|
-
inline-size: 1px;
|
|
5739
|
-
background: var(--oc-border);
|
|
5740
|
-
}
|
|
5741
|
-
.oc-data-table.is-resizing { cursor: col-resize; user-select: none; }
|
|
5742
|
-
/* After a resize the table grows with its columns and the frame scrolls sideways. */
|
|
5743
|
-
.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; }
|
|
5744
6001
|
|
|
5745
6002
|
/* Narrow control columns. The actions column stays on the right while the rest scrolls. */
|
|
5746
6003
|
.oc-data-table .oc-table :is(th, td)[data-oc-col="select"],
|
|
@@ -5756,8 +6013,8 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5756
6013
|
background: var(--oc-card);
|
|
5757
6014
|
box-shadow: -1px 0 0 var(--oc-border);
|
|
5758
6015
|
}
|
|
5759
|
-
.oc-data-table .oc-table thead th[data-oc-col="actions"] { z-index: 3; }
|
|
5760
|
-
.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; }
|
|
5761
6018
|
|
|
5762
6019
|
/* Trash and archive rows stay readable but quieter than active rows. */
|
|
5763
6020
|
.oc-data-table tr[data-oc-status="deleted"],
|
|
@@ -5786,55 +6043,24 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5786
6043
|
padding: 0.75rem;
|
|
5787
6044
|
}
|
|
5788
6045
|
.oc-data-table-card {
|
|
5789
|
-
|
|
6046
|
+
display: flex;
|
|
6047
|
+
flex-direction: column;
|
|
6048
|
+
gap: 0.75rem;
|
|
6049
|
+
padding: 0.875rem;
|
|
5790
6050
|
background: var(--oc-card);
|
|
5791
6051
|
border: 1px solid var(--oc-border);
|
|
5792
6052
|
border-radius: calc(var(--oc-radius) - 2px);
|
|
5793
6053
|
}
|
|
5794
6054
|
.oc-data-table-card-title { margin: 0; font-size: 0.875rem; font-weight: 600; }
|
|
5795
|
-
|
|
6055
|
+
.oc-data-table-card-title .oc-data-table-name-sub { font-weight: 400; }
|
|
5796
6056
|
.oc-data-table-empty { margin: 0; padding: 2rem 1rem; text-align: center; color: var(--oc-muted-foreground); }
|
|
5797
6057
|
.oc-data-table-empty[hidden] { display: none; }
|
|
5798
6058
|
|
|
5799
|
-
/* Footer: count on the left, rows-per-page in the middle, pager on the right. */
|
|
5800
|
-
.oc-data-table-footer {
|
|
5801
|
-
display: grid;
|
|
5802
|
-
grid-template-columns: 1fr auto 1fr;
|
|
5803
|
-
align-items: center;
|
|
5804
|
-
gap: 0.75rem;
|
|
5805
|
-
}
|
|
5806
|
-
.oc-data-table-summary { margin: 0; font-size: 0.8125rem; color: var(--oc-muted-foreground); }
|
|
5807
|
-
.oc-data-table-per-page { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem; }
|
|
5808
|
-
.oc-data-table-per-page .oc-select { inline-size: auto; }
|
|
5809
|
-
.oc-data-table-pager { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.25rem; }
|
|
5810
|
-
.oc-data-table-page {
|
|
5811
|
-
min-inline-size: 2rem;
|
|
5812
|
-
padding: 0.25rem 0.45rem;
|
|
5813
|
-
font: inherit;
|
|
5814
|
-
font-size: 0.8125rem;
|
|
5815
|
-
color: var(--oc-foreground);
|
|
5816
|
-
background: var(--oc-card);
|
|
5817
|
-
border: 1px solid var(--oc-border);
|
|
5818
|
-
border-radius: calc(var(--oc-radius) - 2px);
|
|
5819
|
-
cursor: pointer;
|
|
5820
|
-
}
|
|
5821
|
-
.oc-data-table-page[aria-current="page"] {
|
|
5822
|
-
color: var(--oc-primary);
|
|
5823
|
-
background: oklch(from var(--oc-primary) l c h / 0.1);
|
|
5824
|
-
border-color: oklch(from var(--oc-primary) l c h / 0.35);
|
|
5825
|
-
}
|
|
5826
|
-
.oc-data-table-page:disabled { opacity: 0.4; cursor: default; }
|
|
5827
|
-
.oc-data-table-page:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
5828
|
-
.oc-data-table-ellipsis { padding-inline: 0.25rem; color: var(--oc-muted-foreground); }
|
|
5829
6059
|
|
|
5830
6060
|
/* Design choice from the gear menu: tighter rows, like the compact article lists. */
|
|
5831
6061
|
.oc-data-table--compact .oc-table :is(th, td) { padding: 0.25rem 0.5rem; font-size: 0.8125rem; }
|
|
5832
6062
|
.oc-data-table--compact .oc-table thead th { block-size: 2rem; }
|
|
5833
6063
|
|
|
5834
|
-
@media (max-width: 40rem) {
|
|
5835
|
-
.oc-data-table-footer { grid-template-columns: 1fr; }
|
|
5836
|
-
.oc-data-table-pager { justify-content: flex-start; }
|
|
5837
|
-
}
|
|
5838
6064
|
@media (prefers-reduced-motion: reduce) {
|
|
5839
6065
|
.oc-data-table .oc-table tbody tr { transition: none; }
|
|
5840
6066
|
}
|
|
@@ -5971,6 +6197,73 @@ input.oc-input[type="month"] { inline-size: auto; min-inline-size: 11rem; }
|
|
|
5971
6197
|
.oc-list-toolbar-view { transition: none; }
|
|
5972
6198
|
}
|
|
5973
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
|
+
|
|
5974
6267
|
/* parts/app-page-header.css */
|
|
5975
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) */
|
|
5976
6269
|
/* Page header: back link + title + subtitle + actions at the top of an app page.
|
|
@@ -6455,6 +6748,11 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6455
6748
|
min-block-size: 0;
|
|
6456
6749
|
timeline-scope: --oc-titlebar-scroll;
|
|
6457
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; }
|
|
6458
6756
|
|
|
6459
6757
|
.oc-titlebar {
|
|
6460
6758
|
display: flex;
|
|
@@ -6462,7 +6760,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6462
6760
|
align-items: center;
|
|
6463
6761
|
gap: 2px;
|
|
6464
6762
|
min-block-size: 46px;
|
|
6465
|
-
padding: 0
|
|
6763
|
+
padding: 0 0 0 14px;
|
|
6466
6764
|
border-block-end: 1px solid transparent;
|
|
6467
6765
|
-webkit-user-select: none;
|
|
6468
6766
|
user-select: none;
|
|
@@ -6479,7 +6777,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6479
6777
|
/* Title area: grows, cuts the subtitle off with …. */
|
|
6480
6778
|
.oc-titlebar__main { display: flex; flex: 1; align-items: center; gap: 8px; min-inline-size: 0; }
|
|
6481
6779
|
.oc-titlebar__icon { flex: none; inline-size: 18px; block-size: 18px; }
|
|
6482
|
-
.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; }
|
|
6483
6781
|
.oc-titlebar__subtitle {
|
|
6484
6782
|
min-inline-size: 0;
|
|
6485
6783
|
overflow: hidden;
|
|
@@ -6489,17 +6787,19 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6489
6787
|
white-space: nowrap;
|
|
6490
6788
|
}
|
|
6491
6789
|
.oc-titlebar__subtitle::before { content: "·"; margin-inline-end: 8px; }
|
|
6492
|
-
|
|
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; }
|
|
6493
6792
|
|
|
6494
|
-
/*
|
|
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). */
|
|
6495
6795
|
.oc-titlebar__btn {
|
|
6496
6796
|
display: inline-grid;
|
|
6497
6797
|
place-items: center;
|
|
6498
|
-
inline-size:
|
|
6499
|
-
block-size:
|
|
6798
|
+
inline-size: 40px;
|
|
6799
|
+
block-size: 34px;
|
|
6500
6800
|
padding: 0;
|
|
6501
6801
|
border: 0;
|
|
6502
|
-
border-radius:
|
|
6802
|
+
border-radius: 0;
|
|
6503
6803
|
background: transparent;
|
|
6504
6804
|
color: var(--oc-muted-foreground);
|
|
6505
6805
|
font: inherit;
|
|
@@ -6510,6 +6810,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6510
6810
|
.oc-titlebar__btn:hover { background: var(--oc-glass-panel-strong, var(--oc-accent)); color: var(--oc-foreground); }
|
|
6511
6811
|
.oc-titlebar__btn:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: -2px; }
|
|
6512
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)); }
|
|
6513
6814
|
|
|
6514
6815
|
/* Body: the part that scrolls under the bar. */
|
|
6515
6816
|
.oc-titlebar-body {
|
|
@@ -6534,7 +6835,7 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6534
6835
|
|
|
6535
6836
|
/* Sizes */
|
|
6536
6837
|
.oc-titlebar--sm { min-block-size: 36px; padding-inline-start: 10px; }
|
|
6537
|
-
.oc-titlebar--sm .oc-titlebar__btn { inline-size:
|
|
6838
|
+
.oc-titlebar--sm .oc-titlebar__btn { inline-size: 34px; block-size: 28px; }
|
|
6538
6839
|
|
|
6539
6840
|
@media (prefers-reduced-motion: reduce) {
|
|
6540
6841
|
.oc-titlebar-window > .oc-titlebar { animation: none; }
|
|
@@ -7059,6 +7360,229 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7059
7360
|
.oc-chart-line__dot, .oc-chart-line__tip { transition: none; }
|
|
7060
7361
|
}
|
|
7061
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
|
+
|
|
7062
7586
|
/* parts/forms-affix-input.css */
|
|
7063
7587
|
/* File: packages/ui/src/parts/forms-affix-input.css
|
|
7064
7588
|
Map: --affix group (frame on the wrapper) -> inner input -> inline affix (€, %, @) -> states -> --end alignment
|
|
@@ -7087,7 +7611,7 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7087
7611
|
min-inline-size: 0;
|
|
7088
7612
|
}
|
|
7089
7613
|
|
|
7090
|
-
/* Symbol column: same chrome as the
|
|
7614
|
+
/* Symbol column: the same chrome as the other fields (€, %, @, barcode icon).
|
|
7091
7615
|
A divider separates the symbol from the value. */
|
|
7092
7616
|
.oc-input-group.oc-input-group--affix .oc-input-addon {
|
|
7093
7617
|
align-self: stretch;
|
|
@@ -7136,6 +7660,51 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7136
7660
|
}
|
|
7137
7661
|
.oc-input-group--affix:has(.oc-input:disabled) .oc-input { opacity: 1; }
|
|
7138
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
|
+
|
|
7139
7708
|
/* parts/forms-barcode-input.css */
|
|
7140
7709
|
/* File: packages/ui/src/parts/forms-barcode-input.css
|
|
7141
7710
|
Map: wrapper (field + preview stacked) -> monospace field -> preview area -> placeholder bars -> code caption -> empty / invalid states
|
|
@@ -7405,6 +7974,61 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7405
7974
|
/* Small swatches. */
|
|
7406
7975
|
.oc-color-select--sm .oc-color-select-swatch { inline-size: 1.25rem; block-size: 1.25rem; }
|
|
7407
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
|
+
|
|
7408
8032
|
/* parts/forms-decimal-input.css */
|
|
7409
8033
|
/* File: packages/ui/src/parts/forms-decimal-input.css
|
|
7410
8034
|
Map: field (right-aligned tabular digits) -> unit suffix wrapper -> states -> --start alignment
|
|
@@ -7458,6 +8082,21 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7458
8082
|
/* Disabled wrapper. */
|
|
7459
8083
|
.oc-decimal-field:has(.oc-decimal-input:disabled) { opacity: 0.5; cursor: not-allowed; }
|
|
7460
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
|
+
|
|
7461
8100
|
/* parts/forms-filter-counts.css */
|
|
7462
8101
|
/* File: packages/ui/src/parts/forms-filter-counts.css
|
|
7463
8102
|
Map: group (grid of tiles) -> tile (label + hidden radio) -> value / label / hint -> tones -> states -> --compact
|
|
@@ -7554,6 +8193,72 @@ a.oc-tree-label:focus-visible { outline: 2px solid var(--oc-ring); outline-offse
|
|
|
7554
8193
|
.oc-filter-counts--compact .oc-filter-counts-label { font-size: 0.8rem; font-weight: 500; }
|
|
7555
8194
|
.oc-filter-counts--compact .oc-filter-counts-hint { display: none; }
|
|
7556
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
|
+
|
|
7557
8262
|
/* parts/forms-language-select.css */
|
|
7558
8263
|
/* File: packages/ui/src/parts/forms-language-select.css
|
|
7559
8264
|
Map: wrapper (icon + native select) -> icon -> select control -> chevron -> states -> --ghost / --currency
|
|
@@ -7889,6 +8594,146 @@ button.oc-language-select:hover { background: var(--oc-surface); }
|
|
|
7889
8594
|
font-size: 0.8rem;
|
|
7890
8595
|
}
|
|
7891
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
|
+
|
|
7892
8737
|
/* parts/forms-time-input.css */
|
|
7893
8738
|
/* File: packages/ui/src/parts/forms-time-input.css
|
|
7894
8739
|
Map: 24h text field (HH:mm) -> invalid state -> slot list (radio chips) -> slot states -> --sm
|
|
@@ -8063,7 +8908,7 @@ button.oc-language-select:hover { background: var(--oc-surface); }
|
|
|
8063
8908
|
/* File: packages/ui/src/parts/media-attachment.css | Map: list -> file chip (icon by type, name, size, open/remove) -> type tones
|
|
8064
8909
|
-> uploading progress + error -> image preview (in a message) -> thumbnail chip (in a composer) -> reduced motion
|
|
8065
8910
|
Attachment: a file chip or an image preview inside a chat message or a composer. The icon tile shows the extension and is
|
|
8066
|
-
tinted per type (--pdf, --doc, --sheet, --zip, --image).
|
|
8911
|
+
tinted per type (--pdf, --doc, --sheet, --zip, --image). */
|
|
8067
8912
|
|
|
8068
8913
|
.oc-attachment-list { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; list-style: none; }
|
|
8069
8914
|
.oc-attachment-list--stack { flex-direction: column; flex-wrap: nowrap; }
|
|
@@ -8221,6 +9066,31 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8221
9066
|
.oc-attachment, .oc-attachment--uploading::after { transition: none; }
|
|
8222
9067
|
}
|
|
8223
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
|
+
|
|
8224
9094
|
/* parts/media-browser-frame.css */
|
|
8225
9095
|
/* File: packages/ui/src/parts/media-browser-frame.css | Map: frame -> chrome bar (dots, address pill, actions)
|
|
8226
9096
|
-> view (screenshot slot, ratio) -> caption -> minimal / dark / tilt modifiers -> motion
|
|
@@ -8440,6 +9310,9 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8440
9310
|
line-height: 1;
|
|
8441
9311
|
cursor: pointer;
|
|
8442
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; }
|
|
8443
9316
|
.oc-chat-composer__tool:hover { background: var(--oc-surface-strong); color: var(--oc-foreground); }
|
|
8444
9317
|
.oc-chat-composer__tool:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
8445
9318
|
|
|
@@ -8644,9 +9517,11 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8644
9517
|
background: transparent;
|
|
8645
9518
|
font-size: 1.15rem;
|
|
8646
9519
|
line-height: 1;
|
|
9520
|
+
color: var(--oc-muted-foreground);
|
|
8647
9521
|
cursor: pointer;
|
|
8648
9522
|
}
|
|
8649
|
-
.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); }
|
|
8650
9525
|
.oc-emoji-picker__trigger:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 1px; }
|
|
8651
9526
|
|
|
8652
9527
|
/* The panel: floats above the trigger (implicit anchor of popovertarget), flips when there is no room. */
|
|
@@ -8850,6 +9725,216 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8850
9725
|
.oc-flip-card--hover:is(:hover, :focus-within) .oc-flip-card__face--back { opacity: 1; visibility: visible; }
|
|
8851
9726
|
}
|
|
8852
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
|
+
|
|
8853
9938
|
/* parts/media-glass.css */
|
|
8854
9939
|
/* File: packages/ui/src/parts/media-glass.css
|
|
8855
9940
|
Map: tokens (light-dark) -> sheet (.oc-glass: see-through, blurred, light top edge, soft shadow) -> panel (.oc-glass-panel:
|
|
@@ -8993,6 +10078,54 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8993
10078
|
.oc-image-zoom__canvas { transition: inline-size var(--oc-transition-normal); }
|
|
8994
10079
|
}
|
|
8995
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
|
+
|
|
8996
10129
|
/* parts/media-lightbox.css */
|
|
8997
10130
|
/* File: packages/ui/src/parts/media-lightbox.css | Map: thumbnails -> dialog + backdrop -> bar -> track + slides
|
|
8998
10131
|
-> nav buttons -> caption + counter -> single image -> small screens -> motion
|
|
@@ -9171,7 +10304,7 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
9171
10304
|
people, status, actions) -> wallpaper (masked doodles in a token color) -> scroll area (starts at the bottom)
|
|
9172
10305
|
-> composer footer -> sending overlay (aria-busy) -> reduced motion
|
|
9173
10306
|
Message thread: one conversation. The scroll area uses flex-direction: column-reverse, so it opens at the newest message
|
|
9174
|
-
and stays there when messages are added, without a script.
|
|
10307
|
+
and stays there when messages are added, without a script. */
|
|
9175
10308
|
|
|
9176
10309
|
.oc-message-thread {
|
|
9177
10310
|
--oc-message-thread-height: 32rem;
|
|
@@ -9309,7 +10442,7 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
9309
10442
|
-> grouping (:has) -> hover actions -> date divider + system line -> reduced motion
|
|
9310
10443
|
Message: one chat bubble. Incoming on the left with the avatar, outgoing on the right in the primary tint.
|
|
9311
10444
|
Consecutive messages of one sender group by themselves: the avatar shows once (on the last one), the name once (on the
|
|
9312
|
-
first one).
|
|
10445
|
+
first one). */
|
|
9313
10446
|
|
|
9314
10447
|
.oc-message-list {
|
|
9315
10448
|
--oc-message-in: var(--oc-card);
|
|
@@ -9879,6 +11012,104 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
9879
11012
|
.oc-watermark { --oc-watermark-opacity: 0.2; print-color-adjust: exact; }
|
|
9880
11013
|
}
|
|
9881
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
|
+
|
|
9882
11113
|
/* parts/site-fact-list.css */
|
|
9883
11114
|
/* File: packages/ui/src/parts/site-fact-list.css
|
|
9884
11115
|
Map: plain -> compact -> stacked -> accent values -> narrow screens
|
|
@@ -9906,6 +11137,78 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
9906
11137
|
/* Very narrow containers: wrap instead of squeezing label and value together. */
|
|
9907
11138
|
.oc-fact-list > div { flex-wrap: wrap; }
|
|
9908
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
|
+
|
|
9909
11212
|
/* parts/site-link-arrow.css */
|
|
9910
11213
|
/* File: packages/ui/src/parts/site-link-arrow.css
|
|
9911
11214
|
Map: focus ring -> back arrow -> external arrow -> color modifiers -> sizes -> reduced motion
|
|
@@ -10399,7 +11702,7 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
10399
11702
|
-> sizes (--sm, --lg) -> full width
|
|
10400
11703
|
Prose: typography for long-form text from a CMS, blog or help page, where the HTML has no classes of its own.
|
|
10401
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
|
|
10402
|
-
scale the whole text.
|
|
11705
|
+
scale the whole text. */
|
|
10403
11706
|
|
|
10404
11707
|
.oc-prose {
|
|
10405
11708
|
max-inline-size: 68ch;
|