@birdycom/omniaui 0.0.0-stage → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +21 -3
- package/bin/lib/add.mjs +126 -0
- package/bin/lib/catalog.mjs +169 -0
- package/bin/lib/project.mjs +90 -0
- package/bin/omniaui.mjs +70 -0
- package/dist/code-block.css +163 -0
- package/dist/components-extra.css +916 -0
- package/dist/components.css +10171 -0
- package/dist/components.min.css +1 -0
- package/dist/data-table.d.ts +9 -0
- package/dist/data-table.js +505 -0
- package/dist/docs-ui.css +267 -0
- package/dist/oc-theme.css +69 -0
- package/dist/parts/.gitkeep +0 -0
- package/dist/parts/app-accordion-accent.css +60 -0
- package/dist/parts/app-alpha-tabs.css +68 -0
- package/dist/parts/app-busy-overlay.css +25 -0
- package/dist/parts/app-column-menu.css +85 -0
- package/dist/parts/app-confirm-dialog.css +70 -0
- package/dist/parts/app-cookie-consent.css +63 -0
- package/dist/parts/app-data-table.css +174 -0
- package/dist/parts/app-greeting.css +47 -0
- package/dist/parts/app-list-toolbar.css +81 -0
- package/dist/parts/app-page-header.css +54 -0
- package/dist/parts/app-severity-card.css +91 -0
- package/dist/parts/app-sidebar-dark.css +15 -0
- package/dist/parts/app-sortable-row.css +52 -0
- package/dist/parts/app-stat-card.css +68 -0
- package/dist/parts/app-table-actions.css +71 -0
- package/dist/parts/app-table-compact.css +54 -0
- package/dist/parts/app-top-progress.css +68 -0
- package/dist/parts/app-tree.css +104 -0
- package/dist/parts/app-upgrade-banner.css +90 -0
- package/dist/parts/app-version-banner.css +80 -0
- package/dist/parts/data-chart-line.css +167 -0
- package/dist/parts/forms-affix-input.css +75 -0
- package/dist/parts/forms-barcode-input.css +75 -0
- package/dist/parts/forms-chip-filter.css +91 -0
- package/dist/parts/forms-color-select.css +97 -0
- package/dist/parts/forms-decimal-input.css +51 -0
- package/dist/parts/forms-filter-counts.css +94 -0
- package/dist/parts/forms-language-select.css +89 -0
- package/dist/parts/forms-number-input.css +98 -0
- package/dist/parts/forms-password-requirements.css +55 -0
- package/dist/parts/forms-phone-input.css +85 -0
- package/dist/parts/forms-time-input.css +74 -0
- package/dist/parts/forms-toggle-field.css +69 -0
- package/dist/parts/media-art.css +21 -0
- package/dist/parts/media-attachment.css +160 -0
- package/dist/parts/media-browser-frame.css +73 -0
- package/dist/parts/media-card.css +83 -0
- package/dist/parts/media-chat-composer.css +90 -0
- package/dist/parts/media-doc-viewer.css +151 -0
- package/dist/parts/media-emoji-picker.css +88 -0
- package/dist/parts/media-entity-card.css +52 -0
- package/dist/parts/media-flip-card.css +78 -0
- package/dist/parts/media-image-zoom.css +68 -0
- package/dist/parts/media-lightbox.css +131 -0
- package/dist/parts/media-message-thread.css +136 -0
- package/dist/parts/media-message.css +160 -0
- package/dist/parts/media-row.css +78 -0
- package/dist/parts/media-stack-card.css +82 -0
- package/dist/parts/media-terminal-log.css +76 -0
- package/dist/parts/media-thumb.css +71 -0
- package/dist/parts/site-fact-list.css +25 -0
- package/dist/parts/site-link-arrow.css +34 -0
- package/dist/parts/site-marquee.css +34 -0
- package/dist/parts/site-next-teaser.css +75 -0
- package/dist/parts/site-price-card.css +91 -0
- package/dist/parts/site-product-mark.css +66 -0
- package/dist/parts/site-project-card.css +111 -0
- package/dist/parts/site-prose.css +124 -0
- package/dist/parts/site-stack-list.css +48 -0
- package/dist/parts/site-timeline.css +54 -0
- package/dist/showcase.css +404 -0
- package/manifest.json +1108 -0
- package/package.json +69 -6
- package/snippets/accordion-accent.html +24 -0
- package/snippets/accordion.html +11 -0
- package/snippets/affix-input.html +30 -0
- package/snippets/alert-dialog.html +22 -0
- package/snippets/alert.html +5 -0
- package/snippets/alpha-tabs.html +37 -0
- package/snippets/aspect-ratio.html +15 -0
- package/snippets/attachment.html +43 -0
- package/snippets/avatar.html +6 -0
- package/snippets/back-link.html +5 -0
- package/snippets/badge.html +5 -0
- package/snippets/barcode-input.html +18 -0
- package/snippets/breadcrumb.html +6 -0
- package/snippets/browser-frame.html +18 -0
- package/snippets/busy-overlay.html +31 -0
- package/snippets/button-group.html +21 -0
- package/snippets/button.html +8 -0
- package/snippets/calendar.html +43 -0
- package/snippets/card.html +17 -0
- package/snippets/carousel.html +21 -0
- package/snippets/chart-line.html +46 -0
- package/snippets/chart.html +27 -0
- package/snippets/chat-composer.html +21 -0
- package/snippets/checkbox.html +5 -0
- package/snippets/checklist.html +23 -0
- package/snippets/chip-filter.html +14 -0
- package/snippets/code-window.html +20 -0
- package/snippets/collapsible.html +19 -0
- package/snippets/color-field.html +13 -0
- package/snippets/color-select.html +18 -0
- package/snippets/column-menu.html +38 -0
- package/snippets/combobox.html +19 -0
- package/snippets/command.html +24 -0
- package/snippets/confirm-dialog.html +32 -0
- package/snippets/context-menu.html +25 -0
- package/snippets/cookie-consent.html +70 -0
- package/snippets/copy-field.html +19 -0
- package/snippets/counter.html +2 -0
- package/snippets/data-table.html +151 -0
- package/snippets/date-picker.html +32 -0
- package/snippets/decimal-input.html +20 -0
- package/snippets/definition-list.html +20 -0
- package/snippets/demo-panel.html +18 -0
- package/snippets/doc-viewer.html +58 -0
- package/snippets/drawer.html +30 -0
- package/snippets/dropdown-menu.html +27 -0
- package/snippets/dropdown.html +9 -0
- package/snippets/dropzone.html +13 -0
- package/snippets/emoji-picker.html +51 -0
- package/snippets/empty-state.html +17 -0
- package/snippets/entity-card.html +26 -0
- package/snippets/expandable-table.html +26 -0
- package/snippets/fact-list.html +14 -0
- package/snippets/filter-counts.html +30 -0
- package/snippets/flip-card.html +22 -0
- package/snippets/form-field.html +6 -0
- package/snippets/greeting.html +22 -0
- package/snippets/heading.html +14 -0
- package/snippets/hover-card.html +18 -0
- package/snippets/image-zoom.html +30 -0
- package/snippets/input-group.html +10 -0
- package/snippets/input.html +5 -0
- package/snippets/item.html +26 -0
- package/snippets/kbd.html +13 -0
- package/snippets/label.html +9 -0
- package/snippets/language-select.html +26 -0
- package/snippets/launcher-card.html +14 -0
- package/snippets/lightbox.html +50 -0
- package/snippets/link-arrow.html +10 -0
- package/snippets/list-toolbar.html +33 -0
- package/snippets/marquee.html +15 -0
- package/snippets/media-card.html +28 -0
- package/snippets/media-row.html +21 -0
- package/snippets/media-thumb.html +12 -0
- package/snippets/menubar.html +30 -0
- package/snippets/message-thread.html +123 -0
- package/snippets/message.html +51 -0
- package/snippets/modal.html +15 -0
- package/snippets/native-select.html +15 -0
- package/snippets/navmenu.html +23 -0
- package/snippets/next-teaser.html +15 -0
- package/snippets/number-input.html +27 -0
- package/snippets/otp-input.html +9 -0
- package/snippets/page-header.html +24 -0
- package/snippets/pagination.html +6 -0
- package/snippets/password-input.html +24 -0
- package/snippets/password-requirements.html +30 -0
- package/snippets/phone-input.html +22 -0
- package/snippets/popover.html +15 -0
- package/snippets/price-card.html +34 -0
- package/snippets/product-mark.html +13 -0
- package/snippets/progress.html +4 -0
- package/snippets/project-card.html +23 -0
- package/snippets/prose.html +54 -0
- package/snippets/radio.html +17 -0
- package/snippets/recovery-codes.html +20 -0
- package/snippets/resizable.html +16 -0
- package/snippets/scroll-area.html +20 -0
- package/snippets/search.html +8 -0
- package/snippets/segmented.html +11 -0
- package/snippets/select.html +7 -0
- package/snippets/separator.html +15 -0
- package/snippets/severity-card.html +35 -0
- package/snippets/sheet.html +32 -0
- package/snippets/sidebar-docs.html +24 -0
- package/snippets/sidebar.html +55 -0
- package/snippets/site-footer.html +6 -0
- package/snippets/site-header.html +26 -0
- package/snippets/skeleton.html +4 -0
- package/snippets/slider.html +17 -0
- package/snippets/sortable-row.html +31 -0
- package/snippets/spinner.html +14 -0
- package/snippets/stack-card.html +17 -0
- package/snippets/stack-list.html +16 -0
- package/snippets/stat-card.html +24 -0
- package/snippets/stepper.html +13 -0
- package/snippets/switch.html +6 -0
- package/snippets/table-actions.html +39 -0
- package/snippets/table-compact.html +24 -0
- package/snippets/table.html +29 -0
- package/snippets/tabs.html +9 -0
- package/snippets/tag-input.html +60 -0
- package/snippets/terminal-log.html +23 -0
- package/snippets/textarea.html +3 -0
- package/snippets/theme-switch.html +6 -0
- package/snippets/time-input.html +26 -0
- package/snippets/timeline.html +28 -0
- package/snippets/toast-stack.html +10 -0
- package/snippets/toast.html +36 -0
- package/snippets/toc.html +13 -0
- package/snippets/toggle-field.html +20 -0
- package/snippets/toggle.html +22 -0
- package/snippets/tooltip.html +4 -0
- package/snippets/top-progress.html +12 -0
- package/snippets/tree.html +38 -0
- package/snippets/upgrade-banner.html +28 -0
- package/snippets/user.html +15 -0
- package/snippets/version-banner.html +15 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-marquee.css
|
|
2
|
+
Map: pause on focus -> direction / speed modifiers -> plain items -> no fade -> reduced motion
|
|
3
|
+
Marquee component. The base .oc-marquee (endless track, pause on hover) lives in showcase.css.
|
|
4
|
+
This part only ADDS modifiers and a reduced-motion fallback that shows every item without movement. */
|
|
5
|
+
|
|
6
|
+
/* Keyboard users: pause too when a link inside the strip has focus. */
|
|
7
|
+
.oc-marquee:focus-within .oc-marquee__track { animation-play-state: paused; }
|
|
8
|
+
|
|
9
|
+
/* Scroll the other way (nice for a second row). */
|
|
10
|
+
.oc-marquee--reverse .oc-marquee__track { animation-direction: reverse; }
|
|
11
|
+
|
|
12
|
+
/* Speed presets. You can also set --oc-marquee-duration yourself. */
|
|
13
|
+
.oc-marquee--slow { --oc-marquee-duration: 70s; }
|
|
14
|
+
.oc-marquee--fast { --oc-marquee-duration: 20s; }
|
|
15
|
+
|
|
16
|
+
/* Plain items: no pill, just text (logo or name strips). */
|
|
17
|
+
.oc-marquee--plain .oc-marquee__item {
|
|
18
|
+
padding-inline: 0.5rem;
|
|
19
|
+
border-color: transparent;
|
|
20
|
+
background: none;
|
|
21
|
+
font-family: inherit;
|
|
22
|
+
font-size: 1.05rem;
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* No soft fade at both edges. */
|
|
27
|
+
.oc-marquee--no-fade { mask-image: none; }
|
|
28
|
+
|
|
29
|
+
/* Reduced motion: no animation (showcase.css), no fade, the items wrap and the duplicates hide. */
|
|
30
|
+
@media (prefers-reduced-motion: reduce) {
|
|
31
|
+
.oc-marquee { mask-image: none; }
|
|
32
|
+
.oc-marquee__track { flex-wrap: wrap; inline-size: auto; }
|
|
33
|
+
.oc-marquee__item[aria-hidden="true"] { display: none; }
|
|
34
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-next-teaser.css
|
|
2
|
+
Map: card -> label -> name (+ mark) -> tagline with arrow -> previous variant -> hover -> reduced motion
|
|
3
|
+
Next teaser: a "Next product / Next project" card at the end of a detail page.
|
|
4
|
+
Accent: --oc-accent-from, or an .oc-accent--* preset on the card. */
|
|
5
|
+
|
|
6
|
+
.oc-next-teaser {
|
|
7
|
+
display: grid;
|
|
8
|
+
gap: 0.45rem;
|
|
9
|
+
padding: 2rem;
|
|
10
|
+
border: 1px solid var(--oc-border);
|
|
11
|
+
border-radius: var(--oc-radius-lg);
|
|
12
|
+
background:
|
|
13
|
+
radial-gradient(28rem circle at 100% 0%, color-mix(in oklch, var(--oc-accent-from) 12%, transparent), transparent 60%),
|
|
14
|
+
var(--oc-surface);
|
|
15
|
+
color: var(--oc-foreground);
|
|
16
|
+
text-decoration: none;
|
|
17
|
+
transition: transform 0.3s var(--oc-ease-out), border-color 0.3s;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Small uppercase label ("Next product"). */
|
|
21
|
+
.oc-next-teaser__label {
|
|
22
|
+
color: var(--oc-muted-foreground);
|
|
23
|
+
font-size: 0.78rem;
|
|
24
|
+
font-weight: 600;
|
|
25
|
+
letter-spacing: 0.14em;
|
|
26
|
+
text-transform: uppercase;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Name with an optional product mark in front. */
|
|
30
|
+
.oc-next-teaser__name {
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: 0.75rem;
|
|
34
|
+
margin: 0;
|
|
35
|
+
font-size: clamp(1.4rem, 3vw, 1.85rem);
|
|
36
|
+
font-weight: 700;
|
|
37
|
+
letter-spacing: -0.02em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Tagline + arrow that moves on hover. */
|
|
41
|
+
.oc-next-teaser__tagline {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 0.4rem;
|
|
45
|
+
margin: 0;
|
|
46
|
+
color: var(--oc-muted-foreground);
|
|
47
|
+
}
|
|
48
|
+
.oc-next-teaser__tagline::after {
|
|
49
|
+
content: "→";
|
|
50
|
+
color: var(--oc-accent-from);
|
|
51
|
+
transition: translate 0.25s var(--oc-ease-out);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Previous: the arrow points left and sits before the tagline. */
|
|
55
|
+
.oc-next-teaser--prev .oc-next-teaser__tagline::after { content: none; }
|
|
56
|
+
.oc-next-teaser--prev .oc-next-teaser__tagline::before {
|
|
57
|
+
content: "←";
|
|
58
|
+
color: var(--oc-accent-from);
|
|
59
|
+
transition: translate 0.25s var(--oc-ease-out);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Hover / focus */
|
|
63
|
+
.oc-next-teaser:is(a):hover {
|
|
64
|
+
transform: translateY(-4px);
|
|
65
|
+
border-color: color-mix(in oklch, var(--oc-accent-from) 55%, transparent);
|
|
66
|
+
}
|
|
67
|
+
.oc-next-teaser:hover .oc-next-teaser__tagline::after { translate: 4px 0; }
|
|
68
|
+
.oc-next-teaser--prev:hover .oc-next-teaser__tagline::before { translate: -4px 0; }
|
|
69
|
+
.oc-next-teaser:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 3px; }
|
|
70
|
+
|
|
71
|
+
@media (prefers-reduced-motion: reduce) {
|
|
72
|
+
.oc-next-teaser,
|
|
73
|
+
.oc-next-teaser__tagline::after,
|
|
74
|
+
.oc-next-teaser__tagline::before { transition: none; }
|
|
75
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-price-card.css
|
|
2
|
+
Map: card -> head + discount badge -> period toggle -> monthly / yearly price (:has) -> features -> featured
|
|
3
|
+
Price card: one plan with a monthly / yearly switch (radio inputs + :has(), no JavaScript).
|
|
4
|
+
The toggle is the segmented component; give every card its own radio name. */
|
|
5
|
+
|
|
6
|
+
.oc-price-card {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: 1rem;
|
|
10
|
+
padding: 1.75rem;
|
|
11
|
+
border: 1px solid var(--oc-border);
|
|
12
|
+
border-radius: var(--oc-radius-lg);
|
|
13
|
+
background: var(--oc-card);
|
|
14
|
+
color: var(--oc-foreground);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.oc-price-card__head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
|
|
18
|
+
.oc-price-card__name { margin: 0; font-size: 1.2rem; font-weight: 700; }
|
|
19
|
+
.oc-price-card__desc { margin: 0; color: var(--oc-muted-foreground); font-size: 0.92rem; }
|
|
20
|
+
|
|
21
|
+
/* Discount badge ("Save 20%"). It is dimmed while the monthly price shows. */
|
|
22
|
+
.oc-price-card__discount {
|
|
23
|
+
padding: 0.2rem 0.6rem;
|
|
24
|
+
border-radius: 999px;
|
|
25
|
+
background: color-mix(in oklch, var(--oc-success) 16%, transparent);
|
|
26
|
+
color: var(--oc-success);
|
|
27
|
+
font-size: 0.75rem;
|
|
28
|
+
font-weight: 700;
|
|
29
|
+
white-space: nowrap;
|
|
30
|
+
transition: opacity 0.2s;
|
|
31
|
+
}
|
|
32
|
+
.oc-price-card:has(.oc-price-card__toggle input[value="monthly"]:checked) .oc-price-card__discount { opacity: 0.55; }
|
|
33
|
+
|
|
34
|
+
.oc-price-card__toggle { align-self: flex-start; }
|
|
35
|
+
|
|
36
|
+
/* Price rows: monthly shows by default, yearly when its radio is checked. */
|
|
37
|
+
.oc-price-card__price {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-wrap: wrap;
|
|
40
|
+
align-items: baseline;
|
|
41
|
+
gap: 0.35rem;
|
|
42
|
+
margin: 0;
|
|
43
|
+
}
|
|
44
|
+
.oc-price-card__price--yearly { display: none; }
|
|
45
|
+
.oc-price-card:has(.oc-price-card__toggle input[value="yearly"]:checked) .oc-price-card__price--yearly { display: flex; }
|
|
46
|
+
.oc-price-card:has(.oc-price-card__toggle input[value="yearly"]:checked) .oc-price-card__price--monthly { display: none; }
|
|
47
|
+
|
|
48
|
+
.oc-price-card__amount { font-size: 2.5rem; font-weight: 700; line-height: 1; letter-spacing: -0.03em; }
|
|
49
|
+
.oc-price-card__period { color: var(--oc-muted-foreground); font-size: 0.9rem; }
|
|
50
|
+
/* Old price, struck through. */
|
|
51
|
+
.oc-price-card__was { color: var(--oc-muted-foreground); font-size: 0.95rem; }
|
|
52
|
+
.oc-price-card__note { flex-basis: 100%; color: var(--oc-muted-foreground); font-size: 0.8rem; }
|
|
53
|
+
|
|
54
|
+
/* Features: a check for included, a cross + muted text for excluded. */
|
|
55
|
+
.oc-price-card__features {
|
|
56
|
+
display: grid;
|
|
57
|
+
gap: 0.55rem;
|
|
58
|
+
flex-grow: 1;
|
|
59
|
+
align-content: start; /* the list grows to push the button down, its rows stay together */
|
|
60
|
+
margin: 0;
|
|
61
|
+
padding: 0;
|
|
62
|
+
list-style: none;
|
|
63
|
+
font-size: 0.92rem;
|
|
64
|
+
}
|
|
65
|
+
.oc-price-card__feature { display: flex; align-items: baseline; gap: 0.55rem; }
|
|
66
|
+
.oc-price-card__feature::before { content: "✓"; flex-shrink: 0; color: var(--oc-success); font-weight: 700; }
|
|
67
|
+
.oc-price-card__feature--excluded { color: var(--oc-muted-foreground); }
|
|
68
|
+
.oc-price-card__feature--excluded::before { content: "✕"; color: var(--oc-muted-foreground); font-weight: 400; }
|
|
69
|
+
|
|
70
|
+
.oc-price-card__cta { inline-size: 100%; }
|
|
71
|
+
|
|
72
|
+
/* Featured plan: accent border + soft glow. The glow follows the pointer: the card you hover or tab into gets it,
|
|
73
|
+
and the featured card gives it up while another card in the same row is hovered. */
|
|
74
|
+
.oc-price-card {
|
|
75
|
+
transition: border-color 0.25s var(--oc-ease-out), box-shadow 0.25s var(--oc-ease-out), translate 0.25s var(--oc-ease-out);
|
|
76
|
+
}
|
|
77
|
+
.oc-price-card--featured,
|
|
78
|
+
.oc-price-card:hover,
|
|
79
|
+
.oc-price-card:focus-within {
|
|
80
|
+
border-color: color-mix(in oklch, var(--oc-accent-from) 60%, transparent);
|
|
81
|
+
box-shadow: 0 24px 60px -30px var(--oc-accent-from);
|
|
82
|
+
}
|
|
83
|
+
.oc-price-card:hover { translate: 0 -2px; }
|
|
84
|
+
:has(> .oc-price-card:hover) > .oc-price-card--featured:not(:hover, :focus-within) {
|
|
85
|
+
border-color: var(--oc-border);
|
|
86
|
+
box-shadow: none;
|
|
87
|
+
}
|
|
88
|
+
@media (prefers-reduced-motion: reduce) {
|
|
89
|
+
.oc-price-card { transition: none; }
|
|
90
|
+
.oc-price-card:hover { translate: none; }
|
|
91
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-product-mark.css
|
|
2
|
+
Map: base tile -> squircle (corner-shape) -> image / svg -> sizes -> soft variant -> glow
|
|
3
|
+
Product mark: a filled app-icon tile in the accent gradient (logo, glyph or SVG).
|
|
4
|
+
Accent: --oc-accent-from / --oc-accent-to, or an .oc-accent--* preset on the element. */
|
|
5
|
+
|
|
6
|
+
.oc-product-mark {
|
|
7
|
+
--oc-mark-size: 3rem;
|
|
8
|
+
display: inline-grid;
|
|
9
|
+
place-items: center;
|
|
10
|
+
inline-size: var(--oc-mark-size);
|
|
11
|
+
aspect-ratio: 1;
|
|
12
|
+
flex-shrink: 0;
|
|
13
|
+
/* Fallback shape: a rounded square close to an app icon. */
|
|
14
|
+
border-radius: 26%;
|
|
15
|
+
background: linear-gradient(135deg, var(--oc-accent-from), var(--oc-accent-to));
|
|
16
|
+
color: var(--color-white-50);
|
|
17
|
+
font-size: calc(var(--oc-mark-size) * 0.45);
|
|
18
|
+
line-height: 1;
|
|
19
|
+
/* Light edge on top + a soft drop shadow in the accent color. */
|
|
20
|
+
box-shadow:
|
|
21
|
+
inset 0 1px 0 color-mix(in oklch, var(--color-white-50) 35%, transparent),
|
|
22
|
+
0 10px 24px -12px var(--oc-accent-to);
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Real squircle where the browser supports corner-shape (a larger radius looks right with it). */
|
|
27
|
+
@supports (corner-shape: squircle) {
|
|
28
|
+
.oc-product-mark {
|
|
29
|
+
border-radius: 50%;
|
|
30
|
+
corner-shape: squircle;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Logo image or inline SVG inside the tile. */
|
|
35
|
+
.oc-product-mark > :is(img, svg) {
|
|
36
|
+
inline-size: 58%;
|
|
37
|
+
block-size: 58%;
|
|
38
|
+
object-fit: contain;
|
|
39
|
+
}
|
|
40
|
+
/* Full-bleed image (the logo already is a tile). */
|
|
41
|
+
.oc-product-mark--cover > img {
|
|
42
|
+
inline-size: 100%;
|
|
43
|
+
block-size: 100%;
|
|
44
|
+
object-fit: cover;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Sizes */
|
|
48
|
+
.oc-product-mark--sm { --oc-mark-size: 2.25rem; }
|
|
49
|
+
.oc-product-mark--lg { --oc-mark-size: 4rem; }
|
|
50
|
+
.oc-product-mark--xl {
|
|
51
|
+
--oc-mark-size: clamp(6rem, 18vw, 10rem);
|
|
52
|
+
box-shadow:
|
|
53
|
+
inset 0 2px 0 color-mix(in oklch, var(--color-white-50) 35%, transparent),
|
|
54
|
+
0 0 80px -20px var(--oc-accent-from);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Soft variant: tinted background, accent glyph (quieter, for lists). */
|
|
58
|
+
.oc-product-mark--soft {
|
|
59
|
+
border: 1px solid color-mix(in oklch, var(--oc-accent-from) 40%, transparent);
|
|
60
|
+
background: color-mix(in oklch, var(--oc-accent-from) 16%, var(--oc-card));
|
|
61
|
+
color: var(--oc-accent-from);
|
|
62
|
+
box-shadow: none;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Extra glow (hero visuals). */
|
|
66
|
+
.oc-product-mark--glow { box-shadow: 0 0 48px -8px var(--oc-accent-from); }
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-project-card.css
|
|
2
|
+
Map: card -> preview frame (bar + dots + shot) -> body (type / name / meta / more) -> hover -> reduced motion
|
|
3
|
+
Project card: portfolio item with a browser-like preview. Self-contained: it does not use other frame classes.
|
|
4
|
+
Accent: --oc-accent-from / --oc-accent-to, or an .oc-accent--* preset on the card. */
|
|
5
|
+
|
|
6
|
+
.oc-project-card {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
border: 1px solid var(--oc-border);
|
|
10
|
+
border-radius: var(--oc-radius-lg);
|
|
11
|
+
background: var(--oc-surface);
|
|
12
|
+
color: var(--oc-foreground);
|
|
13
|
+
text-decoration: none;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
transition: transform 0.35s var(--oc-ease-out), border-color 0.35s;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Preview: a small window with a title bar and a screenshot (or a gradient placeholder). */
|
|
19
|
+
.oc-project-card__frame {
|
|
20
|
+
display: block;
|
|
21
|
+
margin: 1rem 1rem 0;
|
|
22
|
+
border: 1px solid var(--oc-border-strong);
|
|
23
|
+
border-radius: var(--oc-radius-md);
|
|
24
|
+
background: var(--oc-card);
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
box-shadow: 0 24px 48px -28px color-mix(in oklch, var(--oc-accent-to) 60%, transparent);
|
|
27
|
+
}
|
|
28
|
+
.oc-project-card__bar {
|
|
29
|
+
display: flex;
|
|
30
|
+
gap: 0.35rem;
|
|
31
|
+
padding: 0.5rem 0.7rem;
|
|
32
|
+
border-block-end: 1px solid var(--oc-border);
|
|
33
|
+
background: var(--oc-surface-strong);
|
|
34
|
+
}
|
|
35
|
+
.oc-project-card__bar > i {
|
|
36
|
+
inline-size: 0.55rem;
|
|
37
|
+
aspect-ratio: 1;
|
|
38
|
+
border-radius: 50%;
|
|
39
|
+
background: var(--oc-border-strong);
|
|
40
|
+
}
|
|
41
|
+
.oc-project-card__bar > i:first-child { background: var(--oc-accent-from); }
|
|
42
|
+
|
|
43
|
+
/* Screenshot area. Without an <img> it shows an accent gradient placeholder. */
|
|
44
|
+
.oc-project-card__shot {
|
|
45
|
+
display: block;
|
|
46
|
+
inline-size: 100%;
|
|
47
|
+
aspect-ratio: 16 / 10;
|
|
48
|
+
object-fit: cover;
|
|
49
|
+
object-position: top;
|
|
50
|
+
background:
|
|
51
|
+
radial-gradient(circle at 80% 20%, color-mix(in oklch, var(--color-white-50) 30%, transparent), transparent 45%),
|
|
52
|
+
linear-gradient(135deg, var(--oc-accent-from), var(--oc-accent-to));
|
|
53
|
+
transition: scale 0.5s var(--oc-ease-out);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Text below the preview. */
|
|
57
|
+
.oc-project-card__body {
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
flex-grow: 1;
|
|
61
|
+
gap: 0.35rem;
|
|
62
|
+
padding: 1.1rem 1.25rem 1.3rem;
|
|
63
|
+
}
|
|
64
|
+
.oc-project-card__type {
|
|
65
|
+
align-self: flex-start;
|
|
66
|
+
padding: 0.2rem 0.6rem;
|
|
67
|
+
border-radius: 999px;
|
|
68
|
+
background: color-mix(in oklch, var(--oc-accent-from) 14%, transparent);
|
|
69
|
+
color: var(--oc-accent-from);
|
|
70
|
+
font-size: 0.75rem;
|
|
71
|
+
font-weight: 600;
|
|
72
|
+
}
|
|
73
|
+
.oc-project-card__name {
|
|
74
|
+
margin: 0.25rem 0 0;
|
|
75
|
+
font-size: 1.25rem;
|
|
76
|
+
font-weight: 700;
|
|
77
|
+
letter-spacing: -0.02em;
|
|
78
|
+
}
|
|
79
|
+
.oc-project-card__meta {
|
|
80
|
+
margin: 0;
|
|
81
|
+
color: var(--oc-muted-foreground);
|
|
82
|
+
font-size: 0.9rem;
|
|
83
|
+
}
|
|
84
|
+
.oc-project-card__more {
|
|
85
|
+
display: inline-flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 0.4rem;
|
|
88
|
+
margin-block-start: auto;
|
|
89
|
+
padding-block-start: 0.6rem;
|
|
90
|
+
color: var(--oc-accent-from);
|
|
91
|
+
font-size: 0.9rem;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
}
|
|
94
|
+
.oc-project-card__more::after { content: "→"; transition: translate 0.25s var(--oc-ease-out); }
|
|
95
|
+
|
|
96
|
+
/* Hover / focus: lift, accent border, zoom the shot a little, move the arrow. */
|
|
97
|
+
.oc-project-card:is(a, [tabindex]):hover {
|
|
98
|
+
transform: translateY(-4px);
|
|
99
|
+
border-color: color-mix(in oklch, var(--oc-accent-from) 55%, transparent);
|
|
100
|
+
}
|
|
101
|
+
.oc-project-card:hover .oc-project-card__shot { scale: 1.03; }
|
|
102
|
+
.oc-project-card:hover .oc-project-card__more::after { translate: 4px 0; }
|
|
103
|
+
.oc-project-card:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 3px; }
|
|
104
|
+
|
|
105
|
+
/* Flat: no frame margin, the preview runs edge to edge. */
|
|
106
|
+
.oc-project-card--flat .oc-project-card__frame { margin: 0; border: 0; border-radius: 0; box-shadow: none; }
|
|
107
|
+
|
|
108
|
+
@media (prefers-reduced-motion: reduce) {
|
|
109
|
+
.oc-project-card,
|
|
110
|
+
.oc-project-card__shot { transition: none; }
|
|
111
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-prose.css | Map: container (measure, rhythm) -> headings -> paragraphs + lead -> links + inline
|
|
2
|
+
(strong, code, kbd, mark) -> lists (markers, nesting) -> blockquote -> code block -> table -> figure + image + caption -> hr
|
|
3
|
+
-> sizes (--sm, --lg) -> full width
|
|
4
|
+
Prose: typography for long-form text from a CMS, blog or help page, where the HTML has no classes of its own.
|
|
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. */
|
|
7
|
+
|
|
8
|
+
.oc-prose {
|
|
9
|
+
max-inline-size: 68ch;
|
|
10
|
+
color: var(--oc-foreground);
|
|
11
|
+
font-size: 1rem;
|
|
12
|
+
line-height: 1.7;
|
|
13
|
+
overflow-wrap: break-word;
|
|
14
|
+
}
|
|
15
|
+
.oc-prose :where(*) { margin-block: 0; }
|
|
16
|
+
.oc-prose :where(* + *) { margin-block-start: 1.1em; }
|
|
17
|
+
.oc-prose > :where(:first-child) { margin-block-start: 0; }
|
|
18
|
+
|
|
19
|
+
/* ---- Headings ---- */
|
|
20
|
+
.oc-prose :where(h1, h2, h3, h4) { color: var(--oc-foreground); font-weight: 700; line-height: 1.25; letter-spacing: -0.01em; text-wrap: balance; }
|
|
21
|
+
.oc-prose :where(h1) { font-size: 2.1em; letter-spacing: -0.02em; }
|
|
22
|
+
.oc-prose :where(h2) { margin-block-start: 1.8em; font-size: 1.45em; }
|
|
23
|
+
.oc-prose :where(h3) { margin-block-start: 1.6em; font-size: 1.2em; }
|
|
24
|
+
.oc-prose :where(h4) { margin-block-start: 1.4em; font-size: 1em; }
|
|
25
|
+
.oc-prose :where(h1, h2, h3, h4) + :where(*) { margin-block-start: 0.6em; }
|
|
26
|
+
.oc-prose :where(h2, h3, h4) { scroll-margin-block-start: 5rem; }
|
|
27
|
+
|
|
28
|
+
/* ---- Paragraphs ---- */
|
|
29
|
+
.oc-prose :where(p) { text-wrap: pretty; }
|
|
30
|
+
.oc-prose :where(.oc-prose-lead) { color: var(--oc-muted-foreground); font-size: 1.2em; line-height: 1.6; }
|
|
31
|
+
|
|
32
|
+
/* ---- Links and inline elements ---- */
|
|
33
|
+
.oc-prose :where(a) {
|
|
34
|
+
color: var(--oc-primary);
|
|
35
|
+
font-weight: 500;
|
|
36
|
+
text-decoration: underline;
|
|
37
|
+
text-decoration-color: color-mix(in oklch, var(--oc-primary) 40%, transparent);
|
|
38
|
+
text-decoration-thickness: 1px;
|
|
39
|
+
text-underline-offset: 0.18em;
|
|
40
|
+
transition: text-decoration-color var(--oc-transition-normal);
|
|
41
|
+
}
|
|
42
|
+
.oc-prose :where(a:hover) { text-decoration-color: currentColor; }
|
|
43
|
+
.oc-prose :where(a:focus-visible) { outline: 2px solid var(--oc-ring); outline-offset: 2px; border-radius: 2px; }
|
|
44
|
+
.oc-prose :where(strong, b) { font-weight: 650; }
|
|
45
|
+
.oc-prose :where(:not(pre) > code) {
|
|
46
|
+
padding: 0.1em 0.35em;
|
|
47
|
+
border: 1px solid var(--oc-border);
|
|
48
|
+
border-radius: 0.3em;
|
|
49
|
+
background: var(--oc-muted);
|
|
50
|
+
font-size: 0.875em;
|
|
51
|
+
}
|
|
52
|
+
.oc-prose :where(kbd) {
|
|
53
|
+
padding: 0.05em 0.4em;
|
|
54
|
+
border: 1px solid var(--oc-border);
|
|
55
|
+
border-block-end-width: 2px;
|
|
56
|
+
border-radius: 0.3em;
|
|
57
|
+
background: var(--oc-card);
|
|
58
|
+
font-family: inherit;
|
|
59
|
+
font-size: 0.85em;
|
|
60
|
+
}
|
|
61
|
+
.oc-prose :where(mark) { padding: 0 0.15em; border-radius: 0.2em; background: color-mix(in oklch, var(--oc-warning) 28%, transparent); color: inherit; }
|
|
62
|
+
.oc-prose :where(small) { color: var(--oc-muted-foreground); }
|
|
63
|
+
|
|
64
|
+
/* ---- Lists ---- */
|
|
65
|
+
.oc-prose :where(ul, ol) { padding-inline-start: 1.5em; }
|
|
66
|
+
.oc-prose :where(ul) { list-style: disc; }
|
|
67
|
+
.oc-prose :where(ol) { list-style: decimal; }
|
|
68
|
+
.oc-prose :where(ul ul) { list-style: circle; }
|
|
69
|
+
.oc-prose :where(li) { padding-inline-start: 0.3em; }
|
|
70
|
+
.oc-prose :where(li + li, li > ul, li > ol) { margin-block-start: 0.4em; }
|
|
71
|
+
.oc-prose :where(ul > li)::marker { color: var(--oc-muted-foreground); }
|
|
72
|
+
.oc-prose :where(ol > li)::marker { color: var(--oc-muted-foreground); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
73
|
+
.oc-prose :where(dt) { font-weight: 650; }
|
|
74
|
+
.oc-prose :where(dd) { margin-block-start: 0.25em; padding-inline-start: 1.5em; color: var(--oc-muted-foreground); }
|
|
75
|
+
|
|
76
|
+
/* ---- Blockquote ---- */
|
|
77
|
+
.oc-prose :where(blockquote) {
|
|
78
|
+
padding: 0.2em 0 0.2em 1.1em;
|
|
79
|
+
border-inline-start: 3px solid var(--oc-primary);
|
|
80
|
+
color: var(--oc-foreground);
|
|
81
|
+
font-size: 1.08em;
|
|
82
|
+
font-style: italic;
|
|
83
|
+
}
|
|
84
|
+
.oc-prose :where(blockquote p + p) { margin-block-start: 0.6em; }
|
|
85
|
+
.oc-prose :where(blockquote footer, blockquote cite) { display: block; margin-block-start: 0.6em; color: var(--oc-muted-foreground); font-size: 0.85em; font-style: normal; }
|
|
86
|
+
|
|
87
|
+
/* ---- Code block ---- */
|
|
88
|
+
.oc-prose :where(pre) {
|
|
89
|
+
padding: 0.9em 1.1em;
|
|
90
|
+
overflow-x: auto;
|
|
91
|
+
border: 1px solid var(--oc-border);
|
|
92
|
+
border-radius: calc(var(--oc-radius) + 2px);
|
|
93
|
+
background: var(--oc-muted);
|
|
94
|
+
font-size: 0.85em;
|
|
95
|
+
line-height: 1.6;
|
|
96
|
+
tab-size: 2;
|
|
97
|
+
}
|
|
98
|
+
.oc-prose :where(pre code) { padding: 0; border: 0; background: none; font-size: inherit; }
|
|
99
|
+
|
|
100
|
+
/* ---- Table ---- */
|
|
101
|
+
.oc-prose :where(table) { inline-size: 100%; border-collapse: collapse; font-size: 0.9em; line-height: 1.5; font-variant-numeric: tabular-nums; }
|
|
102
|
+
.oc-prose :where(caption) { padding-block-end: 0.5em; color: var(--oc-muted-foreground); font-size: 0.9em; text-align: start; }
|
|
103
|
+
.oc-prose :where(th, td) { padding: 0.55em 0.75em; border-block-end: 1px solid var(--oc-border); text-align: start; vertical-align: top; }
|
|
104
|
+
.oc-prose :where(thead th) { border-block-end-width: 2px; color: var(--oc-foreground); font-weight: 650; }
|
|
105
|
+
.oc-prose :where(tbody tr:hover) { background: var(--oc-surface); }
|
|
106
|
+
|
|
107
|
+
/* ---- Figure, image, caption ---- */
|
|
108
|
+
.oc-prose :where(img, video, .oc-media-art) { display: block; max-inline-size: 100%; block-size: auto; border-radius: calc(var(--oc-radius) + 2px); }
|
|
109
|
+
.oc-prose :where(figure) { margin-inline: 0; }
|
|
110
|
+
.oc-prose :where(figure > .oc-media-art) { aspect-ratio: 16 / 9; }
|
|
111
|
+
.oc-prose :where(figcaption) { margin-block-start: 0.6em; color: var(--oc-muted-foreground); font-size: 0.85em; line-height: 1.5; text-align: center; }
|
|
112
|
+
|
|
113
|
+
/* ---- Horizontal rule ---- */
|
|
114
|
+
.oc-prose :where(hr) { margin-block: 2.2em; border: 0; border-block-start: 1px solid var(--oc-border); }
|
|
115
|
+
.oc-prose :where(hr + *) { margin-block-start: 0; }
|
|
116
|
+
|
|
117
|
+
/* ---- Sizes and width ---- */
|
|
118
|
+
.oc-prose--sm { font-size: 0.875rem; line-height: 1.65; }
|
|
119
|
+
.oc-prose--lg { font-size: 1.125rem; line-height: 1.75; }
|
|
120
|
+
.oc-prose--full { max-inline-size: none; }
|
|
121
|
+
|
|
122
|
+
@media (prefers-reduced-motion: reduce) {
|
|
123
|
+
.oc-prose :where(a) { transition: none; }
|
|
124
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-stack-list.css
|
|
2
|
+
Map: list -> pill item -> optional icon -> neutral / small modifiers
|
|
3
|
+
Stack list: technology pills (tech stack of a product or project).
|
|
4
|
+
Accent: --oc-accent-from, or an .oc-accent--* preset on the list. */
|
|
5
|
+
|
|
6
|
+
.oc-stack-list {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-wrap: wrap;
|
|
9
|
+
gap: 0.6rem;
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
list-style: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* One technology as a pill, tinted with the accent color. */
|
|
16
|
+
.oc-stack-list__item {
|
|
17
|
+
display: inline-flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: 0.45rem;
|
|
20
|
+
padding: 0.5rem 1rem;
|
|
21
|
+
border: 1px solid color-mix(in oklch, var(--oc-accent-from) 35%, transparent);
|
|
22
|
+
border-radius: 999px;
|
|
23
|
+
background: color-mix(in oklch, var(--oc-accent-from) 10%, transparent);
|
|
24
|
+
color: var(--oc-foreground);
|
|
25
|
+
font-family: var(--oc-font-mono);
|
|
26
|
+
font-size: 0.88rem;
|
|
27
|
+
white-space: nowrap;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Small glyph, emoji or SVG before the name. */
|
|
31
|
+
.oc-stack-list__icon {
|
|
32
|
+
display: inline-grid;
|
|
33
|
+
place-items: center;
|
|
34
|
+
inline-size: 1.1em;
|
|
35
|
+
color: var(--oc-accent-from);
|
|
36
|
+
}
|
|
37
|
+
.oc-stack-list__icon > :is(img, svg) { inline-size: 100%; block-size: auto; }
|
|
38
|
+
|
|
39
|
+
/* Neutral pills: border + surface instead of the accent tint. */
|
|
40
|
+
.oc-stack-list--neutral .oc-stack-list__item {
|
|
41
|
+
border-color: var(--oc-border);
|
|
42
|
+
background: var(--oc-surface);
|
|
43
|
+
color: var(--oc-muted-foreground);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Smaller pills (cards, table cells). */
|
|
47
|
+
.oc-stack-list--sm { gap: 0.4rem; }
|
|
48
|
+
.oc-stack-list--sm .oc-stack-list__item { padding: 0.25rem 0.65rem; font-size: 0.78rem; }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* File: packages/ui/src/parts/site-timeline.css
|
|
2
|
+
Map: item + marker dot -> date / title / text -> current item -> size modifier
|
|
3
|
+
Timeline component. The base .oc-timeline (vertical line, <strong> + <span> rows) lives in showcase.css.
|
|
4
|
+
This part only ADDS elements and modifiers, so the simple showcase markup keeps working unchanged. */
|
|
5
|
+
|
|
6
|
+
/* One entry. The dot sits on the vertical line of .oc-timeline (its padding-inline-start is 1.25rem). */
|
|
7
|
+
.oc-timeline__item {
|
|
8
|
+
position: relative;
|
|
9
|
+
padding-block-end: 0.25rem;
|
|
10
|
+
}
|
|
11
|
+
.oc-timeline__item::before {
|
|
12
|
+
content: "";
|
|
13
|
+
position: absolute;
|
|
14
|
+
/* Center the 0.7rem dot on the 1px line: padding (1.25rem) + half the dot (0.35rem) + half the line. */
|
|
15
|
+
inset-inline-start: calc(-1.25rem - 0.35rem - 0.5px);
|
|
16
|
+
inset-block-start: 0.35rem;
|
|
17
|
+
inline-size: 0.7rem;
|
|
18
|
+
aspect-ratio: 1;
|
|
19
|
+
border: 2px solid var(--oc-accent-from);
|
|
20
|
+
border-radius: 50%;
|
|
21
|
+
background: var(--oc-background);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Date or year label (use a <time> element when it is a real date).
|
|
25
|
+
Scoped under .oc-timeline so it wins over the showcase rules ".oc-timeline span / strong". */
|
|
26
|
+
.oc-timeline .oc-timeline__date {
|
|
27
|
+
color: var(--oc-accent-from);
|
|
28
|
+
font-family: var(--oc-font-mono);
|
|
29
|
+
font-size: 0.85rem;
|
|
30
|
+
}
|
|
31
|
+
.oc-timeline .oc-timeline__title {
|
|
32
|
+
margin: 0;
|
|
33
|
+
color: var(--oc-foreground);
|
|
34
|
+
font-size: 1.05rem;
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
}
|
|
37
|
+
.oc-timeline .oc-timeline__text {
|
|
38
|
+
margin: 0;
|
|
39
|
+
color: var(--oc-muted-foreground);
|
|
40
|
+
font-size: 0.95rem;
|
|
41
|
+
line-height: 1.55;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Current / latest entry: filled dot with a soft ring in the accent color. */
|
|
45
|
+
.oc-timeline__item--current::before {
|
|
46
|
+
background: var(--oc-accent-from);
|
|
47
|
+
box-shadow: 0 0 0 4px color-mix(in oklch, var(--oc-accent-from) 25%, transparent);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Larger spacing between entries (about pages, long histories). */
|
|
51
|
+
.oc-timeline--lg { gap: 1.75rem; }
|
|
52
|
+
|
|
53
|
+
/* Line in the accent color instead of the neutral border. */
|
|
54
|
+
.oc-timeline--accent { border-inline-start-color: color-mix(in oklch, var(--oc-accent-from) 55%, transparent); }
|