@birdycom/omniaui 0.12.5 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/copy-js.mjs +12 -1
  3. package/bin/omniaui.mjs +2 -2
  4. package/dist/barcode.d.ts +15 -0
  5. package/dist/barcode.js +164 -0
  6. package/dist/components-extra.css +15 -1
  7. package/dist/components.css +2237 -256
  8. package/dist/components.min.css +1 -1
  9. package/dist/contact-form.d.ts +5 -0
  10. package/dist/contact-form.js +138 -0
  11. package/dist/data-table.js +135 -98
  12. package/dist/fly.d.ts +4 -0
  13. package/dist/fly.js +80 -0
  14. package/dist/form-extras.d.ts +11 -0
  15. package/dist/form-extras.js +214 -0
  16. package/dist/lazy.d.ts +5 -0
  17. package/dist/lazy.js +37 -0
  18. package/dist/oc-theme.css +3 -1
  19. package/dist/parts/app-data-table-footer.css +38 -0
  20. package/dist/parts/app-data-table-rich.css +161 -0
  21. package/dist/parts/app-data-table.css +44 -74
  22. package/dist/parts/app-name-card.css +65 -0
  23. package/dist/parts/app-result.css +39 -0
  24. package/dist/parts/app-titlebar.css +16 -8
  25. package/dist/parts/data-meter-row.css +40 -0
  26. package/dist/parts/data-price.css +20 -0
  27. package/dist/parts/data-ribbon.css +76 -0
  28. package/dist/parts/data-spec-list.css +36 -0
  29. package/dist/parts/data-stock.css +41 -0
  30. package/dist/parts/forms-affix-input.css +1 -1
  31. package/dist/parts/forms-avatar-picker.css +43 -0
  32. package/dist/parts/forms-date-field.css +53 -0
  33. package/dist/parts/forms-density.css +13 -0
  34. package/dist/parts/forms-form-section.css +64 -0
  35. package/dist/parts/forms-form.css +76 -0
  36. package/dist/parts/forms-quantity.css +55 -0
  37. package/dist/parts/forms-rating.css +81 -0
  38. package/dist/parts/media-attachment.css +1 -1
  39. package/dist/parts/media-barcode.css +23 -0
  40. package/dist/parts/media-chat-composer.css +3 -0
  41. package/dist/parts/media-emoji-picker.css +3 -1
  42. package/dist/parts/media-gallery.css +55 -0
  43. package/dist/parts/media-glass-liquid.css +99 -0
  44. package/dist/parts/media-glass-options.css +50 -0
  45. package/dist/parts/media-lazy.css +46 -0
  46. package/dist/parts/media-lightbox.css +4 -0
  47. package/dist/parts/media-message-thread.css +1 -1
  48. package/dist/parts/media-message.css +1 -1
  49. package/dist/parts/nav-topbar-variants.css +96 -0
  50. package/dist/parts/site-base.css +33 -0
  51. package/dist/parts/site-brand-mark.css +56 -0
  52. package/dist/parts/site-cards.css +183 -0
  53. package/dist/parts/site-fly.css +40 -0
  54. package/dist/parts/site-header-variants.css +70 -0
  55. package/dist/parts/site-layout.css +69 -0
  56. package/dist/parts/site-panel.css +29 -0
  57. package/dist/parts/site-prose.css +13 -1
  58. package/dist/parts/utility-hover.css +44 -0
  59. package/dist/showcase.css +114 -22
  60. package/manifest.json +193 -9
  61. package/package.json +7 -2
  62. package/snippets/accordion-accent.html +1 -1
  63. package/snippets/attachment.html +4 -4
  64. package/snippets/avatar-picker.html +40 -0
  65. package/snippets/barcode.html +20 -0
  66. package/snippets/brand-mark.html +41 -0
  67. package/snippets/chat-composer.html +3 -3
  68. package/snippets/data-table.html +51 -76
  69. package/snippets/date-field.html +44 -0
  70. package/snippets/doc-viewer.html +1 -1
  71. package/snippets/emoji-picker.html +1 -1
  72. package/snippets/feature-card.html +52 -0
  73. package/snippets/fly-in.html +30 -0
  74. package/snippets/form-density.html +25 -0
  75. package/snippets/form-section.html +47 -0
  76. package/snippets/gallery.html +25 -0
  77. package/snippets/hover-effects.html +19 -0
  78. package/snippets/icon-list.html +28 -0
  79. package/snippets/lazy.html +39 -0
  80. package/snippets/message-thread.html +12 -12
  81. package/snippets/message.html +10 -10
  82. package/snippets/meter-row.html +29 -0
  83. package/snippets/name-card.html +72 -0
  84. package/snippets/page-header.html +1 -1
  85. package/snippets/page-sections.html +50 -0
  86. package/snippets/panel.html +18 -0
  87. package/snippets/price.html +25 -0
  88. package/snippets/prose.html +3 -3
  89. package/snippets/quantity.html +12 -0
  90. package/snippets/rating.html +26 -0
  91. package/snippets/result.html +31 -0
  92. package/snippets/ribbon.html +48 -0
  93. package/snippets/shot-grid.html +27 -0
  94. package/snippets/sidebar.html +3 -3
  95. package/snippets/spec-list.html +34 -0
  96. package/snippets/stock.html +20 -0
  97. package/snippets/table-actions.html +5 -5
  98. package/snippets/table.html +2 -2
  99. package/snippets/titlebar.html +1 -1
  100. package/snippets/user.html +3 -3
  101. package/dist/parts/app-column-menu.css +0 -85
  102. package/snippets/column-menu.html +0 -38
@@ -97,6 +97,10 @@
97
97
  .oc-lightbox__nav { grid-row: 1; justify-self: center; }
98
98
  .oc-lightbox__nav--prev { grid-column: 1; }
99
99
  .oc-lightbox__nav--next { grid-column: 3; }
100
+ .oc-lightbox__close :is(svg, iconify-icon, .oc-icon) { inline-size: 1.1rem; block-size: 1.1rem; font-size: 1.1rem; }
101
+ /* A <picture> (animated WebP with a still image for "reduce motion") gets the frame; the image fits in it. */
102
+ .oc-lightbox__media > picture { display: grid; overflow: hidden; }
103
+ .oc-lightbox__media > picture > img { max-inline-size: 100%; max-block-size: calc(100dvh - 9rem); object-fit: contain; }
100
104
 
101
105
  /* ---- Caption with the "2 / 5" counter ---- */
102
106
  .oc-lightbox__caption {
@@ -2,7 +2,7 @@
2
2
  people, status, actions) -> wallpaper (masked doodles in a token color) -> scroll area (starts at the bottom)
3
3
  -> composer footer -> sending overlay (aria-busy) -> reduced motion
4
4
  Message thread: one conversation. The scroll area uses flex-direction: column-reverse, so it opens at the newest message
5
- and stays there when messages are added, without a script. Based on the question chat of the Korrekt app. */
5
+ and stays there when messages are added, without a script. */
6
6
 
7
7
  .oc-message-thread {
8
8
  --oc-message-thread-height: 32rem;
@@ -2,7 +2,7 @@
2
2
  -> grouping (:has) -> hover actions -> date divider + system line -> reduced motion
3
3
  Message: one chat bubble. Incoming on the left with the avatar, outgoing on the right in the primary tint.
4
4
  Consecutive messages of one sender group by themselves: the avatar shows once (on the last one), the name once (on the
5
- first one). Based on the question chat of the Korrekt app. */
5
+ first one). */
6
6
 
7
7
  .oc-message-list {
8
8
  --oc-message-in: var(--oc-card);
@@ -0,0 +1,96 @@
1
+ /* File: packages/ui/src/parts/nav-topbar-variants.css
2
+ Map: brand (logo tile, room before the menu) -> centred menu -> plain links -> dark / brand colour -> floating pill
3
+ -> strip above the bar -> footer bar (split, links, dark)
4
+ Variants of the site header (.oc-topbar in docs-ui.css) and the footer bar (.oc-footerbar). Colours are tokens. */
5
+
6
+ /* Brand: a logo tile and the name, always with room before the menu. */
7
+ .oc-topbar-brand { display: inline-flex; align-items: center; gap: 0.55rem; margin-inline-end: 1rem; }
8
+ .oc-topbar-logo {
9
+ display: grid;
10
+ place-items: center;
11
+ flex: none;
12
+ inline-size: 1.85rem;
13
+ block-size: 1.85rem;
14
+ border-radius: 9px;
15
+ color: var(--color-white-50);
16
+ background: linear-gradient(135deg, var(--oc-accent-from, var(--oc-primary)), var(--oc-accent-to, var(--oc-primary)));
17
+ font-size: 0.95rem;
18
+ }
19
+ .oc-topbar-logo > :is(svg, iconify-icon) { inline-size: 1.1rem; block-size: 1.1rem; font-size: 1.1rem; }
20
+ .oc-topbar-nav { min-inline-size: 0; }
21
+ .oc-topbar-actions .oc-btn { white-space: nowrap; }
22
+
23
+ /* Centred menu: brand left, menu in the middle, actions right (from 761px; smaller screens keep the burger). */
24
+ @media (min-width: 761px) {
25
+ .oc-topbar--center { display: grid; grid-template-columns: 1fr auto 1fr; }
26
+ .oc-topbar--center .oc-topbar-brand { justify-self: start; }
27
+ .oc-topbar--center .oc-topbar-actions { justify-self: end; }
28
+ }
29
+
30
+ /* Plain links: no pill frames, the current page underlined. */
31
+ .oc-topbar--plain .oc-navmenu--site .oc-navmenu-link {
32
+ border-color: transparent;
33
+ border-radius: 0;
34
+ background: none;
35
+ color: var(--oc-muted-foreground);
36
+ box-shadow: inset 0 -2px 0 transparent;
37
+ }
38
+ .oc-topbar--plain .oc-navmenu--site .oc-navmenu-link:hover { color: var(--oc-foreground); border-color: transparent; background: none; }
39
+ .oc-topbar--plain .oc-navmenu--site .oc-navmenu-link[aria-current="page"] {
40
+ color: var(--oc-foreground);
41
+ border-color: transparent;
42
+ background: none;
43
+ box-shadow: inset 0 -2px 0 var(--oc-primary);
44
+ }
45
+
46
+ /* Dark bar and brand-colour bar: light text, links as soft pills. */
47
+ .oc-topbar:is(.oc-topbar--dark, .oc-topbar--brand) { color: var(--color-white-50); border-block-end-color: transparent; }
48
+ .oc-topbar.oc-topbar--dark { background: var(--oc-dark-band, var(--color-duskblue-95)); }
49
+ .oc-topbar--brand { background: linear-gradient(100deg, var(--oc-accent-from, var(--oc-primary)), var(--oc-accent-to, var(--oc-primary))); }
50
+ .oc-topbar:is(.oc-topbar--dark, .oc-topbar--brand) .oc-navmenu--site .oc-navmenu-link {
51
+ color: oklch(from var(--color-white-50) l c h / 0.8);
52
+ border-color: transparent;
53
+ background: none;
54
+ }
55
+ .oc-topbar:is(.oc-topbar--dark, .oc-topbar--brand) .oc-navmenu--site .oc-navmenu-link:is(:hover, [aria-current="page"]) {
56
+ color: var(--color-white-50);
57
+ border-color: transparent;
58
+ background: oklch(from var(--color-white-50) l c h / 0.14);
59
+ }
60
+ .oc-topbar--dark .oc-topbar-logo { background: oklch(from var(--color-white-50) l c h / 0.14); }
61
+ .oc-topbar--brand .oc-topbar-logo { color: var(--oc-primary); background: var(--color-white-50); }
62
+ .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); }
63
+
64
+ /* Floating: a rounded bar with room around it and a soft shadow (over a hero or a photo). */
65
+ .oc-topbar--floating {
66
+ margin: 0.75rem;
67
+ border: 1px solid var(--oc-border);
68
+ border-radius: 16px;
69
+ box-shadow: 0 14px 34px -18px oklch(from var(--color-black-60) l c h / 0.35);
70
+ }
71
+
72
+ /* Strip: a small row above the bar (contact, language, account). */
73
+ .oc-topbar-strip {
74
+ display: flex;
75
+ flex-wrap: wrap;
76
+ align-items: center;
77
+ justify-content: space-between;
78
+ gap: 0.25rem 1rem;
79
+ padding: 0.35rem clamp(14px, 2vw, 28px);
80
+ font-size: 0.78rem;
81
+ color: var(--oc-muted-foreground);
82
+ background: var(--oc-muted);
83
+ }
84
+ .oc-topbar-strip a { color: inherit; text-decoration: none; }
85
+ .oc-topbar-strip a:hover { color: var(--oc-foreground); }
86
+ .oc-topbar-strip > span { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 1rem; }
87
+
88
+ /* Footer bar: text left and links right (--split), a link list, a dark bar. */
89
+ .oc-footerbar--split { justify-content: space-between; gap: 1rem; text-align: start; }
90
+ .oc-footerbar--tall { block-size: auto; min-block-size: var(--ocm-footer-height, 2.25rem); padding-block: 0.85rem; flex-wrap: wrap; }
91
+ .oc-footerbar-links { display: inline-flex; flex-wrap: wrap; gap: 0.25rem 1rem; margin: 0; padding: 0; list-style: none; }
92
+ .oc-footerbar-links a { color: var(--oc-muted-foreground); text-decoration: none; }
93
+ .oc-footerbar-links a:hover { color: var(--oc-foreground); }
94
+ .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; }
95
+ .oc-footerbar--dark :is(a, .oc-footerbar-links a) { color: oklch(from var(--color-white-50) l c h / 0.85); }
96
+ .oc-footerbar--dark .oc-footerbar-links a:hover { color: var(--color-white-50); }
@@ -0,0 +1,33 @@
1
+ /* File: packages/ui/src/parts/site-base.css */
2
+ /* Map: skip link -> icon */
3
+ /* Two small site helpers: a skip link for keyboard users (hidden above the page until it gets the focus) and a basic
4
+ inline icon (svg or iconify-icon) that is as large as the text around it. */
5
+
6
+ /* <a class="oc-skip-link" href="#main">Skip to content</a> as the first element in <body>. */
7
+ .oc-skip-link {
8
+ position: absolute;
9
+ inset-inline-start: 1rem;
10
+ inset-block-start: 1rem;
11
+ /* Fully above the edge, whatever its height; drops in on focus. */
12
+ translate: 0 calc(-100% - 2rem);
13
+ z-index: 100;
14
+ padding: 0.6rem 1rem;
15
+ border-radius: var(--oc-radius-md, 0.75rem);
16
+ background: var(--oc-foreground);
17
+ color: var(--oc-background);
18
+ font-weight: 600;
19
+ text-decoration: none;
20
+ transition: translate var(--oc-transition-fast);
21
+ }
22
+ .oc-skip-link:focus { translate: none; }
23
+
24
+ /* Inline icon: 1.25em (1.1em in a button), never squeezed in a flex row. */
25
+ .oc-icon {
26
+ inline-size: 1.25em;
27
+ block-size: 1.25em;
28
+ flex-shrink: 0;
29
+ }
30
+ .oc-btn > .oc-icon {
31
+ inline-size: 1.1em;
32
+ block-size: 1.1em;
33
+ }
@@ -0,0 +1,56 @@
1
+ /* File: packages/ui/src/parts/site-brand-mark.css */
2
+ /* Map: brand mark (icon + text) -> word (accent part in the brand gradient) -> tagline -> sizes */
3
+ /* A logo built from an icon and text: the mark (svg or img) with a soft glow in the brand color, the word mark with one
4
+ part in the brand gradient, and a small tagline under it. Sizes --sm and --lg (a footer, a hero or a map). */
5
+
6
+ .oc-brand-mark {
7
+ --oc-brand-mark-icon: 2.25rem;
8
+ --oc-brand-mark-word: 1.35rem;
9
+ --oc-brand-mark-tagline: 0.6rem;
10
+ display: inline-flex;
11
+ align-items: center;
12
+ gap: 0.6rem;
13
+ color: var(--oc-foreground);
14
+ text-decoration: none;
15
+ }
16
+ .oc-brand-mark__icon {
17
+ flex: none;
18
+ inline-size: var(--oc-brand-mark-icon);
19
+ block-size: var(--oc-brand-mark-icon);
20
+ filter: drop-shadow(0 6px 14px oklch(from var(--oc-brand-1) l c h / 0.35));
21
+ }
22
+ .oc-brand-mark__text {
23
+ display: grid;
24
+ line-height: 1;
25
+ }
26
+ .oc-brand-mark__word {
27
+ font-family: var(--oc-font-display, inherit);
28
+ font-size: var(--oc-brand-mark-word);
29
+ font-weight: 800;
30
+ letter-spacing: -0.04em;
31
+ }
32
+ .oc-brand-mark__accent {
33
+ background: linear-gradient(90deg, var(--oc-brand-1), var(--oc-brand-2));
34
+ -webkit-background-clip: text;
35
+ background-clip: text;
36
+ color: transparent;
37
+ }
38
+ .oc-brand-mark__tagline {
39
+ margin-block-start: 0.3rem;
40
+ color: var(--oc-subtle-foreground, var(--oc-muted-foreground));
41
+ font-family: var(--oc-font-mono);
42
+ font-size: var(--oc-brand-mark-tagline);
43
+ font-weight: 600;
44
+ letter-spacing: 0.16em;
45
+ text-transform: uppercase;
46
+ }
47
+ .oc-brand-mark--sm {
48
+ --oc-brand-mark-icon: 1.75rem;
49
+ --oc-brand-mark-word: 1.1rem;
50
+ --oc-brand-mark-tagline: 0.55rem;
51
+ }
52
+ .oc-brand-mark--lg {
53
+ --oc-brand-mark-icon: 2.6rem;
54
+ --oc-brand-mark-word: 1.6rem;
55
+ --oc-brand-mark-tagline: 0.66rem;
56
+ }
@@ -0,0 +1,183 @@
1
+ /* File: packages/ui/src/parts/site-cards.css */
2
+ /* Map: feature card -> link card -> icon list (+ points) -> accent list + note -> badge row + accent tagline
3
+ -> screenshot grid -> browser frame glow + mark */
4
+ /* Cards and lists for the pages of a company site: services and features (icon tile + title + text), cards that are
5
+ links, a list of icon rows in frames (or as points with a title), a list with markers in the accent color, a small
6
+ note, a row of badges, a tagline in the accent color, a grid of screenshots that open in the lightbox, and a browser
7
+ frame with a glow in the accent color and a product mark on it. */
8
+
9
+ /* Feature / service card: tile, title, text; a quiet hover. In an .oc-card-grid (--oc-card-min sets the column width). */
10
+ .oc-feature-card {
11
+ padding: 1.6rem;
12
+ border: 1px solid var(--oc-border);
13
+ border-radius: var(--oc-radius-lg, 1.25rem);
14
+ background: var(--oc-surface);
15
+ transition: border-color 0.3s, background 0.3s;
16
+ }
17
+ .oc-feature-card:hover {
18
+ border-color: var(--oc-border-strong);
19
+ background: var(--oc-surface-strong);
20
+ }
21
+ .oc-feature-card > .oc-icon-tile { margin-block-end: 1.1rem; }
22
+ .oc-feature-card__title {
23
+ margin: 0 0 0.6rem;
24
+ font-family: var(--oc-font-display, inherit);
25
+ font-size: 1.2rem;
26
+ line-height: 1.25;
27
+ }
28
+ .oc-feature-card__text {
29
+ margin: 0;
30
+ color: var(--oc-muted-foreground);
31
+ font-size: 0.95rem;
32
+ }
33
+
34
+ /* Card that is a link (an agent, a tool, a document): tile, title, text and a "more" line; hover in the accent color. */
35
+ .oc-link-card {
36
+ display: grid;
37
+ align-content: start;
38
+ gap: 0.4rem;
39
+ padding: 1.25rem;
40
+ border: 1px solid var(--oc-border);
41
+ border-radius: var(--oc-radius-lg, 1.25rem);
42
+ background: var(--oc-surface);
43
+ color: var(--oc-foreground);
44
+ text-decoration: none;
45
+ transition: border-color 0.3s, background 0.3s;
46
+ }
47
+ /* --oc-link-card-hover: the hover color alone (without an accent preset, so the tile keeps its own color). */
48
+ .oc-link-card:hover {
49
+ border-color: oklch(from var(--oc-link-card-hover, var(--oc-accent-from)) l c h / 0.5);
50
+ background: var(--oc-surface-strong);
51
+ }
52
+ .oc-link-card:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 2px; }
53
+ .oc-link-card > .oc-icon-tile { margin-block-end: 0.4rem; }
54
+ .oc-link-card__title { font-family: var(--oc-font-display, inherit); font-weight: 700; }
55
+ .oc-link-card__text { color: var(--oc-muted-foreground); font-size: 0.93rem; }
56
+ .oc-link-card__more {
57
+ display: inline-flex;
58
+ align-items: center;
59
+ gap: 0.35rem;
60
+ margin-block-start: 0.4rem;
61
+ font-size: 0.9rem;
62
+ font-weight: 600;
63
+ }
64
+ .oc-link-card__more::after { content: "→"; transition: translate 0.25s var(--oc-ease-out, ease); }
65
+ .oc-link-card:hover .oc-link-card__more::after { translate: 4px 0; }
66
+
67
+ /* Icon list: rows with an icon in a frame. --points: an icon tile next to a title and a text, without frames. */
68
+ .oc-icon-list {
69
+ display: grid;
70
+ gap: 0.75rem;
71
+ margin: 0;
72
+ padding: 0;
73
+ list-style: none;
74
+ }
75
+ .oc-icon-list > li {
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 0.75rem;
79
+ padding: 0.85rem 1rem;
80
+ border: 1px solid var(--oc-border);
81
+ border-radius: var(--oc-radius-md, 0.75rem);
82
+ background: var(--oc-surface);
83
+ }
84
+ .oc-icon-list > li > :is(svg, iconify-icon, .oc-icon) {
85
+ flex: none;
86
+ inline-size: 1.25rem;
87
+ block-size: 1.25rem;
88
+ font-size: 1.25rem;
89
+ color: var(--oc-primary);
90
+ }
91
+ .oc-icon-list--points { gap: 1rem; }
92
+ .oc-icon-list--points > li {
93
+ display: grid;
94
+ grid-template-columns: auto 1fr;
95
+ align-items: start;
96
+ gap: 0.25rem 0.9rem;
97
+ padding: 0;
98
+ border: 0;
99
+ background: none;
100
+ }
101
+ .oc-icon-list--points > li > .oc-icon-tile { grid-row: span 2; }
102
+ .oc-icon-list__title { font-family: var(--oc-font-display, inherit); font-weight: 700; }
103
+ .oc-icon-list__text { color: var(--oc-muted-foreground); font-size: 0.95rem; }
104
+
105
+ /* List with markers in the accent color, and a small note under a block. */
106
+ .oc-list--accent {
107
+ display: grid;
108
+ gap: 0.6rem;
109
+ margin: 0;
110
+ padding-inline-start: 1.1rem;
111
+ list-style: disc;
112
+ color: var(--oc-muted-foreground);
113
+ font-size: 0.95rem;
114
+ }
115
+ .oc-list--accent > li::marker { color: var(--oc-accent-from, var(--oc-primary)); }
116
+ .oc-note {
117
+ margin: 1.25rem 0 0;
118
+ color: var(--oc-muted-foreground);
119
+ font-size: 0.85rem;
120
+ }
121
+ .oc-note--md {
122
+ max-inline-size: 60rem;
123
+ font-size: 1rem;
124
+ }
125
+
126
+ /* Row of badges or pills above a title, and a tagline in the accent color (lighter, so it reads on a dark page). */
127
+ .oc-badge-row {
128
+ display: flex;
129
+ flex-wrap: wrap;
130
+ gap: 0.5rem;
131
+ margin-block-end: 1.25rem;
132
+ }
133
+ .oc-tagline--accent {
134
+ margin: 0 0 1rem;
135
+ color: light-dark(var(--oc-accent-from), color-mix(in oklch, var(--oc-accent-from) 55%, white));
136
+ font-size: clamp(1.2rem, 2.5vw, 1.6rem);
137
+ font-weight: 600;
138
+ }
139
+
140
+ /* Screenshot grid: figures with the whole image visible (contain, 16:10 on the card color) and a caption;
141
+ a link or a button around the image opens the lightbox
142
+ (<button command="show-modal" commandfor="<lightbox id>">). A <picture> (animated WebP with a still image) works the same. */
143
+ .oc-shot-grid {
144
+ display: grid;
145
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--oc-shot-min, 18rem)), 1fr));
146
+ gap: 1.25rem;
147
+ }
148
+ .oc-shot {
149
+ margin: 0;
150
+ border: 1px solid var(--oc-border);
151
+ border-radius: var(--oc-radius-lg, 1.25rem);
152
+ overflow: hidden;
153
+ background: var(--oc-surface);
154
+ }
155
+ .oc-shot > :is(a, button) { display: block; inline-size: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
156
+ .oc-shot > :is(a, button):focus-visible { outline: 2px solid var(--oc-ring); outline-offset: -2px; }
157
+ .oc-shot :is(picture) { display: block; }
158
+ .oc-shot img {
159
+ display: block;
160
+ inline-size: 100%;
161
+ aspect-ratio: var(--oc-shot-ratio, 16 / 10);
162
+ object-fit: contain;
163
+ background: var(--oc-card);
164
+ }
165
+ .oc-shot > figcaption {
166
+ padding: 0.8rem 1rem;
167
+ color: var(--oc-muted-foreground);
168
+ font-size: 0.88rem;
169
+ }
170
+
171
+ /* Browser frame with a shadow in the accent color and a product mark on the bottom end corner. */
172
+ .oc-browser-frame--glow {
173
+ position: relative;
174
+ box-shadow: 0 40px 90px -40px color-mix(in srgb, var(--oc-accent-from) 70%, transparent);
175
+ }
176
+ .oc-browser-frame--glow :is(.oc-browser-frame__view, .oc-browser-frame__body) img { transition: scale 0.6s var(--oc-ease-out, ease); }
177
+ .oc-browser-frame--glow:hover :is(.oc-browser-frame__view, .oc-browser-frame__body) img { scale: 1.02; }
178
+ .oc-browser-frame__mark {
179
+ position: absolute;
180
+ inset-block-end: 1rem;
181
+ inset-inline-end: 1rem;
182
+ filter: drop-shadow(0 10px 20px oklch(0 0 0 / 0.6));
183
+ }
@@ -0,0 +1,40 @@
1
+ /* File: packages/ui/src/parts/site-fly.css */
2
+ /* Map: fly in (only with fly.js) -> visible -> reduced motion -> product card badge -> code window tokens */
3
+ /* Cards that fly in when they scroll into view: they start from the middle of their row (--oc-fly-x, set by fly.js),
4
+ 70px lower, smaller and tilted, and land in their place. Without fly.js (html.oc-fly-ready is missing) or with
5
+ "reduce motion" everything simply stands in its place. Options: --oc-fly-step (offset per column), --oc-fly-stagger
6
+ (delay per column) and data-oc-fly-repeat (fly out again when leaving the view). The lift on hover uses translate, so it never fights the
7
+ transform of the fly-in. Also: a "New" badge in a product card name and short syntax classes for a code window. */
8
+
9
+ .oc-fly-ready .oc-reveal--fly {
10
+ /* --oc-fly-delay: set per card by fly.js from --oc-fly-stagger (delay per column). */
11
+ transition:
12
+ opacity 0.6s var(--oc-ease-out, ease) var(--oc-fly-delay, 0s),
13
+ transform 0.9s cubic-bezier(0.16, 1, 0.3, 1) var(--oc-fly-delay, 0s),
14
+ border-color 0.35s;
15
+ }
16
+ .oc-fly-ready .oc-reveal--fly:not(.is-visible) {
17
+ opacity: 0;
18
+ transform: perspective(900px) translate3d(var(--oc-fly-x, 0), 70px, 0) scale(0.9) rotateX(14deg);
19
+ }
20
+ @media (prefers-reduced-motion: reduce) {
21
+ .oc-fly-ready .oc-reveal--fly:not(.is-visible) { opacity: 1; transform: none; }
22
+ }
23
+
24
+ /* "New" after the name of a product card: <h3 class="oc-product-card__name">Product 1 <span class="oc-product-card__badge oc-pill">New</span></h3> */
25
+ .oc-product-card__badge {
26
+ margin-inline-start: 0.4rem;
27
+ vertical-align: middle;
28
+ font-family: var(--oc-font-sans);
29
+ font-size: 0.7rem;
30
+ letter-spacing: 0.04em;
31
+ text-transform: uppercase;
32
+ }
33
+
34
+ /* Short syntax classes for hand-written code in an .oc-code-window: keyword, string, constant, function, muted.
35
+ They take the colors of the window (--oc-syntax-*), so they follow light and dark mode and a theme can change them. */
36
+ .oc-code-window .oc-tok-k { color: var(--oc-syntax-keyword); }
37
+ .oc-code-window .oc-tok-s { color: var(--oc-syntax-string); }
38
+ .oc-code-window .oc-tok-c { color: var(--oc-syntax-constant); }
39
+ .oc-code-window .oc-tok-f { color: var(--oc-syntax-function); }
40
+ .oc-code-window .oc-tok-m { color: var(--oc-syntax-comment); }
@@ -0,0 +1,70 @@
1
+ /* File: packages/ui/src/parts/site-header-variants.css
2
+ Map: actions slot -> centred menu -> dark -> floating pill -> glass pill -> footer: centred, dark, newsletter, social
3
+ Variants of the marketing header (.oc-site-header) and footer (.oc-site-footer) in showcase.css. The sticky header
4
+ turns to glass while scrolling; the coloured variants keep their own background (no scroll animation). */
5
+
6
+ .oc-site-header__actions { display: flex; align-items: center; gap: 0.5rem; flex: none; }
7
+ .oc-site-header__brand { white-space: nowrap; flex: none; }
8
+ .oc-site-header__nav > :is(a, button):not(.oc-btn) { white-space: nowrap; }
9
+
10
+ /* Centred menu: brand left, menu in the middle, actions right. */
11
+ @media (min-width: 861px) {
12
+ .oc-site-header--center .oc-site-header__inner { display: grid; grid-template-columns: 1fr auto 1fr; }
13
+ .oc-site-header--center .oc-site-header__brand { justify-self: start; }
14
+ .oc-site-header--center .oc-site-header__actions { justify-self: end; }
15
+ }
16
+
17
+ /* Dark: a solid dark bar with light text. */
18
+ .oc-site-header--dark {
19
+ animation: none;
20
+ color: var(--color-white-50);
21
+ background: var(--oc-dark-band, var(--color-duskblue-95));
22
+ }
23
+ .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); }
24
+ .oc-site-header--dark .oc-site-header__nav a:not(.oc-btn) { color: oklch(from var(--color-white-50) l c h / 0.72); }
25
+
26
+ /* Floating: the bar as a rounded card with room around it. */
27
+ .oc-site-header:is(.oc-site-header--floating, .oc-site-header--glass) { animation: none; padding: 0.75rem; }
28
+ .oc-site-header--floating .oc-site-header__inner {
29
+ block-size: 4rem;
30
+ padding-inline: 1rem 0.75rem;
31
+ border: 1px solid var(--oc-border);
32
+ border-radius: 18px;
33
+ background: var(--oc-background);
34
+ box-shadow: 0 16px 36px -22px oklch(from var(--color-black-60) l c h / 0.45);
35
+ }
36
+
37
+ /* Glass: a clear liquid-glass pill over a photo or a hero (look in media-glass-liquid.css). */
38
+ .oc-site-header--glass .oc-site-header__inner { block-size: 3.75rem; padding-inline: 1.1rem 0.6rem; border-radius: 999px; }
39
+ .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)); }
40
+
41
+ /* ---- Footer variants ---- */
42
+ /* Centred: brand, one row of links, social icons and the bottom line, all centred. */
43
+ .oc-site-footer--center { text-align: center; }
44
+ .oc-site-footer--center :is(.oc-site-footer__about, .oc-site-footer__bottom) { justify-items: center; justify-content: center; }
45
+ .oc-site-footer--center .oc-site-footer__about { display: grid; gap: 1rem; }
46
+ .oc-site-footer--center .oc-site-footer__about p { margin: 0; max-inline-size: 34rem; }
47
+ .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; }
48
+ .oc-site-footer__social { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; list-style: none; }
49
+ .oc-site-footer--center .oc-site-footer__social { justify-content: center; margin-block-start: 1.5rem; }
50
+ .oc-site-footer__social a {
51
+ display: grid;
52
+ place-items: center;
53
+ inline-size: 2.25rem;
54
+ block-size: 2.25rem;
55
+ border: 1px solid var(--oc-border);
56
+ border-radius: 999px;
57
+ transition: border-color 0.2s, color 0.2s;
58
+ }
59
+ .oc-site-footer__social a:hover { border-color: var(--oc-primary); color: var(--oc-primary); }
60
+ .oc-site-footer__social :is(svg, iconify-icon) { inline-size: 1.1rem; block-size: 1.1rem; font-size: 1.1rem; }
61
+
62
+ /* Dark: light text on a dark band, the same deep blue in light and dark mode (--oc-dark-band), no top border. */
63
+ .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)); }
64
+ .oc-site-footer--dark :is(.oc-site-footer__title, .oc-site-header__brand, a:hover) { color: var(--color-white-50); }
65
+ .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); }
66
+
67
+ /* Newsletter: a sign-up field in the brand column. */
68
+ .oc-site-footer__signup { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-block-start: 1.25rem; max-inline-size: 24rem; }
69
+ .oc-site-footer__signup .oc-input { flex: 1 1 12rem; min-inline-size: 0; }
70
+ .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); }
@@ -0,0 +1,69 @@
1
+ /* File: packages/ui/src/parts/site-layout.css */
2
+ /* Map: page hero -> section head / more -> action row -> group title -> band -> meta line */
3
+ /* Page building blocks for a marketing or company site, on top of the showcase classes (.oc-section-pad, .oc-display):
4
+ the larger header of an inner page, a section head and a "see more" row, a row of buttons, a group title with a count,
5
+ a full-width band (for a stat strip) and a meta line (version · date). */
6
+
7
+ /* Inner page header: more room on top, less below, and a larger display title. */
8
+ .oc-section-pad--page { padding-block: clamp(4rem, 10vw, 7rem) clamp(2rem, 5vw, 3rem); }
9
+ .oc-display--page {
10
+ margin-block-end: 1.25rem;
11
+ font-size: clamp(2.5rem, 6.5vw, 4.75rem);
12
+ }
13
+
14
+ /* Head of a section (eyebrow, title, lead) and the row with a "see all" link under the section. */
15
+ .oc-section-head {
16
+ max-inline-size: 46rem;
17
+ margin-block-end: 3rem;
18
+ }
19
+ .oc-section-head--center {
20
+ margin-inline: auto;
21
+ text-align: center;
22
+ }
23
+ .oc-section-more { margin-block-start: 2.5rem; }
24
+
25
+ /* Row of buttons under a text: wraps on a narrow screen. */
26
+ .oc-actions {
27
+ display: flex;
28
+ flex-wrap: wrap;
29
+ gap: 0.75rem;
30
+ margin-block-start: 2rem;
31
+ }
32
+ .oc-actions--center { justify-content: center; }
33
+ .oc-actions--end { justify-content: flex-end; }
34
+ .oc-actions--tight { margin-block-start: 1rem; }
35
+
36
+ /* Title of a group of cards with the number of items in a pill: <h3 class="oc-group-title">Apps <span class="oc-group-title__count">8</span></h3> */
37
+ .oc-group-title {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 0.75rem;
41
+ margin: 0 0 1.5rem;
42
+ font-size: 1.4rem;
43
+ }
44
+ .oc-group-title__count {
45
+ padding: 0.1rem 0.6rem;
46
+ border-radius: 999px;
47
+ background: var(--oc-surface-strong);
48
+ color: var(--oc-muted-foreground);
49
+ font-size: 0.85rem;
50
+ font-weight: 500;
51
+ }
52
+
53
+ /* Band over the full width of the page with a line above and below; the content stays in its .oc-container.
54
+ Put a .oc-stat-strip--plain in it for a row of key figures. */
55
+ .oc-band {
56
+ border-block: 1px solid var(--oc-border);
57
+ background: var(--oc-band-bg, var(--oc-surface));
58
+ }
59
+
60
+ /* Meta line under a page title: version · date, author. */
61
+ .oc-meta {
62
+ margin: 0 0 1rem;
63
+ color: var(--oc-subtle-foreground, var(--oc-muted-foreground));
64
+ font-size: 0.9rem;
65
+ }
66
+
67
+ /* Muted and subtle text from the theme tokens, for running text inside a panel, a spotlight or a split. */
68
+ .oc-text-muted { color: var(--oc-muted-foreground); }
69
+ .oc-text-subtle { color: var(--oc-subtle-foreground, var(--oc-muted-foreground)); }
@@ -0,0 +1,29 @@
1
+ /* File: packages/ui/src/parts/site-panel.css */
2
+ /* Map: panel -> glow (start / end / both) */
3
+ /* A framed panel on the page (a form, a call to action, a feature with a list): card background, strong border, large
4
+ radius, and room above it when a link jumps to it (#form). --glow adds a soft radial light in a corner:
5
+ --oc-panel-glow-color (brand 1) and --oc-panel-glow-at (top left); --glow-end puts it top right, --glow-both adds a
6
+ second light (brand 3) bottom right. */
7
+
8
+ .oc-panel {
9
+ --oc-panel-glow-color: var(--oc-brand-1);
10
+ --oc-panel-glow-at: 0% 0%;
11
+ position: relative;
12
+ padding: var(--oc-panel-padding, clamp(1.5rem, 4vw, 2.5rem));
13
+ border: 1px solid var(--oc-border-strong);
14
+ border-radius: calc(var(--oc-radius-lg, 1.25rem) * 1.2);
15
+ background: var(--oc-card);
16
+ scroll-margin-top: var(--oc-scroll-offset, 6rem);
17
+ }
18
+ .oc-panel--glow {
19
+ background:
20
+ radial-gradient(30rem circle at var(--oc-panel-glow-at), oklch(from var(--oc-panel-glow-color) l c h / 0.12), transparent 60%),
21
+ var(--oc-card);
22
+ }
23
+ .oc-panel--glow-end { --oc-panel-glow-at: 100% 0%; }
24
+ .oc-panel--glow-both {
25
+ background:
26
+ radial-gradient(40rem circle at 0% 0%, oklch(from var(--oc-brand-1) l c h / 0.18), transparent 55%),
27
+ radial-gradient(40rem circle at 100% 100%, oklch(from var(--oc-brand-3) l c h / 0.2), transparent 55%),
28
+ var(--oc-card);
29
+ }
@@ -3,7 +3,7 @@
3
3
  -> sizes (--sm, --lg) -> full width
4
4
  Prose: typography for long-form text from a CMS, blog or help page, where the HTML has no classes of its own.
5
5
  Every rule is scoped with :where(), so a utility class on an element inside still wins. Spacing is in em, so --sm and --lg
6
- scale the whole text. Based on the help and maintenance pages of the Korrekt app. */
6
+ scale the whole text. */
7
7
 
8
8
  .oc-prose {
9
9
  max-inline-size: 68ch;
@@ -134,3 +134,15 @@
134
134
  @media (prefers-reduced-motion: reduce) {
135
135
  .oc-prose :where(a) { transition: none; }
136
136
  }
137
+
138
+ /* ---- Legal text (terms, privacy, cookies): narrower, muted body text in a slightly larger size, headings and strong
139
+ in the foreground, disc lists with a gap, links in brand 1. A table in an .oc-table-wrap scrolls on a phone. ---- */
140
+ .oc-prose--legal { max-inline-size: 46rem; color: var(--oc-muted-foreground); font-size: 1.0625rem; }
141
+ .oc-prose--legal :where(h2) { margin-block-start: 2.5rem; font-size: 1.35rem; color: var(--oc-foreground); }
142
+ .oc-prose--legal :where(h3) { margin-block-start: 1.5rem; font-size: 1.05rem; color: var(--oc-foreground); }
143
+ .oc-prose--legal :where(strong, b) { color: var(--oc-foreground); }
144
+ .oc-prose--legal :where(ul) { display: grid; gap: 0.4rem; padding-inline-start: 1.25rem; list-style: disc; }
145
+ .oc-prose--legal :where(ul > li) { margin-block-start: 0; }
146
+ .oc-prose--legal :where(a) { color: var(--oc-brand-1); font-weight: inherit; text-decoration-color: currentColor; text-underline-offset: 3px; }
147
+ .oc-prose--legal :where(a:hover) { color: var(--oc-foreground); }
148
+ .oc-prose--legal :where(table) { font-size: 0.93rem; }