@openwarelabs/ui 0.13.0 → 0.14.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.
Files changed (75) hide show
  1. package/README.md +7 -7
  2. package/dist/components/AspectRatio/AspectRatio.d.cts +7 -0
  3. package/dist/components/AspectRatio/AspectRatio.d.ts +7 -0
  4. package/dist/components/AspectRatio/AspectRatio.types.d.cts +7 -0
  5. package/dist/components/AspectRatio/AspectRatio.types.d.ts +7 -0
  6. package/dist/components/Banner/Banner.d.cts +7 -0
  7. package/dist/components/Banner/Banner.d.ts +7 -0
  8. package/dist/components/Banner/Banner.types.d.cts +44 -0
  9. package/dist/components/Banner/Banner.types.d.ts +44 -0
  10. package/dist/components/Carousel/Carousel.d.cts +9 -0
  11. package/dist/components/Carousel/Carousel.d.ts +9 -0
  12. package/dist/components/Carousel/Carousel.types.d.cts +63 -0
  13. package/dist/components/Carousel/Carousel.types.d.ts +63 -0
  14. package/dist/components/ContextMenu/ContextMenu.d.cts +7 -0
  15. package/dist/components/ContextMenu/ContextMenu.d.ts +7 -0
  16. package/dist/components/ContextMenu/ContextMenu.types.d.cts +32 -0
  17. package/dist/components/ContextMenu/ContextMenu.types.d.ts +32 -0
  18. package/dist/components/DescriptionList/DescriptionList.d.cts +9 -0
  19. package/dist/components/DescriptionList/DescriptionList.d.ts +9 -0
  20. package/dist/components/DescriptionList/DescriptionList.types.d.cts +32 -0
  21. package/dist/components/DescriptionList/DescriptionList.types.d.ts +32 -0
  22. package/dist/components/HoverCard/HoverCard.d.cts +8 -0
  23. package/dist/components/HoverCard/HoverCard.d.ts +8 -0
  24. package/dist/components/HoverCard/HoverCard.types.d.cts +28 -0
  25. package/dist/components/HoverCard/HoverCard.types.d.ts +28 -0
  26. package/dist/components/Image/Image.d.cts +7 -0
  27. package/dist/components/Image/Image.d.ts +7 -0
  28. package/dist/components/Image/Image.types.d.cts +28 -0
  29. package/dist/components/Image/Image.types.d.ts +28 -0
  30. package/dist/components/Menu/Menu.context.d.cts +3 -0
  31. package/dist/components/Menu/Menu.context.d.ts +3 -0
  32. package/dist/components/Menu/Menu.d.cts +4 -34
  33. package/dist/components/Menu/Menu.d.ts +4 -34
  34. package/dist/components/Menu/Menu.types.d.cts +39 -0
  35. package/dist/components/Menu/Menu.types.d.ts +39 -0
  36. package/dist/components/PasswordInput/PasswordInput.d.cts +9 -0
  37. package/dist/components/PasswordInput/PasswordInput.d.ts +9 -0
  38. package/dist/components/PasswordInput/PasswordInput.types.d.cts +47 -0
  39. package/dist/components/PasswordInput/PasswordInput.types.d.ts +47 -0
  40. package/dist/components/PasswordInput/passwordStrength.d.cts +9 -0
  41. package/dist/components/PasswordInput/passwordStrength.d.ts +9 -0
  42. package/dist/components/Rating/Rating.d.cts +8 -0
  43. package/dist/components/Rating/Rating.d.ts +8 -0
  44. package/dist/components/Rating/Rating.types.d.cts +59 -0
  45. package/dist/components/Rating/Rating.types.d.ts +59 -0
  46. package/dist/components/Splitter/Splitter.d.cts +14 -0
  47. package/dist/components/Splitter/Splitter.d.ts +14 -0
  48. package/dist/components/Splitter/Splitter.layout.d.cts +12 -0
  49. package/dist/components/Splitter/Splitter.layout.d.ts +12 -0
  50. package/dist/components/Splitter/Splitter.types.d.cts +69 -0
  51. package/dist/components/Splitter/Splitter.types.d.ts +69 -0
  52. package/dist/components/TagInput/TagInput.d.cts +7 -0
  53. package/dist/components/TagInput/TagInput.d.ts +7 -0
  54. package/dist/components/TagInput/TagInput.types.d.cts +78 -0
  55. package/dist/components/TagInput/TagInput.types.d.ts +78 -0
  56. package/dist/components/Timeline/Timeline.d.cts +6 -0
  57. package/dist/components/Timeline/Timeline.d.ts +6 -0
  58. package/dist/components/Timeline/Timeline.types.d.cts +42 -0
  59. package/dist/components/Timeline/Timeline.types.d.ts +42 -0
  60. package/dist/components/Tour/Tour.d.cts +9 -0
  61. package/dist/components/Tour/Tour.d.ts +9 -0
  62. package/dist/components/Tour/Tour.types.d.cts +119 -0
  63. package/dist/components/Tour/Tour.types.d.ts +119 -0
  64. package/dist/components.css +1479 -33
  65. package/dist/icons.d.cts +6 -0
  66. package/dist/icons.d.ts +6 -0
  67. package/dist/index.cjs +3500 -1357
  68. package/dist/index.cjs.map +4 -4
  69. package/dist/index.d.cts +26 -0
  70. package/dist/index.d.ts +26 -0
  71. package/dist/index.js +3516 -1354
  72. package/dist/index.js.map +4 -4
  73. package/dist/openware-ui.iife.js +8 -7
  74. package/dist/styles.css +1479 -33
  75. package/package.json +1 -1
@@ -1622,6 +1622,60 @@
1622
1622
  transform: rotate(180deg);
1623
1623
  }
1624
1624
 
1625
+ /* components/TagInput/TagInput.css */
1626
+ /* TagInput: a grouped field (Input.css) that wraps, with Tags (Tag.css) before the text box, over Select's listbox. */
1627
+ .ow-tag-input {
1628
+ height: auto;
1629
+ min-height: 40px;
1630
+ flex-wrap: wrap;
1631
+ gap: var(--ow-space-2xs);
1632
+ padding: 5px var(--ow-space-sm) 5px 5px;
1633
+ cursor: text;
1634
+ }
1635
+
1636
+ .ow-tag-input.ow-input-group--sm {
1637
+ min-height: 32px;
1638
+ gap: var(--ow-space-2xs);
1639
+ padding: var(--ow-space-2xs) var(--ow-space-xs) var(--ow-space-2xs) var(--ow-space-2xs);
1640
+ }
1641
+
1642
+ .ow-tag-input.ow-input-group--disabled {
1643
+ cursor: not-allowed;
1644
+ }
1645
+
1646
+ /* The list is only for screen readers: its tags sit in the field's own row, beside the text box. */
1647
+ .ow-tag-input__tags {
1648
+ display: contents;
1649
+ margin: 0;
1650
+ padding: 0;
1651
+ list-style: none;
1652
+ }
1653
+
1654
+ /* A tag whose ✕ has focus (after Backspace or the arrow keys) is the one Backspace removes. */
1655
+ .ow-tag-input .ow-tag:has(.ow-tag__remove:focus-visible) {
1656
+ border-color: var(--ow-primary-border);
1657
+ background: var(--ow-primary-subtle);
1658
+ color: var(--ow-primary-text);
1659
+ }
1660
+
1661
+ .ow-tag-input__input {
1662
+ width: auto;
1663
+ min-width: 64px;
1664
+ height: 28px;
1665
+ flex: 1 1 64px;
1666
+ /* With no tags, the text lines up with Input's. */
1667
+ padding-left: 7px;
1668
+ }
1669
+
1670
+ .ow-input-group--sm .ow-tag-input__input {
1671
+ height: 22px;
1672
+ padding-left: var(--ow-space-xs);
1673
+ }
1674
+
1675
+ .ow-tag-input--filled .ow-tag-input__input {
1676
+ padding-left: var(--ow-space-2xs);
1677
+ }
1678
+
1625
1679
  /* components/Checkbox/Checkbox.css */
1626
1680
  /* Checkbox: a native input with its look replaced. */
1627
1681
  .ow-checkbox {
@@ -2106,6 +2160,147 @@
2106
2160
  cursor: not-allowed;
2107
2161
  }
2108
2162
 
2163
+ /* components/Rating/Rating.css */
2164
+ /* Rating: a row of stars. Filled ones are brass (one of the few places it shows), empty ones a quiet grey. */
2165
+ .ow-rating {
2166
+ --ow-rating-size: 20px;
2167
+ display: inline-flex;
2168
+ align-items: center;
2169
+ gap: var(--ow-space-sm);
2170
+ color: var(--ow-text-muted);
2171
+ font-size: 14px;
2172
+ line-height: 1.4;
2173
+ vertical-align: middle;
2174
+ }
2175
+
2176
+ .ow-rating--sm {
2177
+ --ow-rating-size: 16px;
2178
+ gap: var(--ow-space-xs);
2179
+ font-size: 13px;
2180
+ }
2181
+
2182
+ .ow-rating--lg {
2183
+ --ow-rating-size: 24px;
2184
+ }
2185
+
2186
+ .ow-rating__stars {
2187
+ display: inline-flex;
2188
+ border-radius: var(--ow-radius-md);
2189
+ }
2190
+
2191
+ /* Each star is a 24px (or larger) box, so it's a big enough target to tap. */
2192
+ .ow-rating__star {
2193
+ position: relative;
2194
+ display: inline-flex;
2195
+ align-items: center;
2196
+ justify-content: center;
2197
+ min-width: 24px;
2198
+ min-height: 24px;
2199
+ padding: 2px;
2200
+ }
2201
+
2202
+ .ow-rating--readonly .ow-rating__star {
2203
+ min-width: 0;
2204
+ min-height: 0;
2205
+ padding: 1px;
2206
+ }
2207
+
2208
+ .ow-rating__icon {
2209
+ display: block;
2210
+ width: var(--ow-rating-size);
2211
+ height: var(--ow-rating-size);
2212
+ flex-shrink: 0;
2213
+ fill: var(--ow-brass);
2214
+ stroke: var(--ow-brass-deep);
2215
+ }
2216
+
2217
+ .ow-rating__icon--empty {
2218
+ fill: var(--ow-meter-track);
2219
+ stroke: var(--ow-border-hover);
2220
+ }
2221
+
2222
+ .ow-rating__glyph {
2223
+ position: relative;
2224
+ display: block;
2225
+ }
2226
+
2227
+ /* The brass star on top, cut to the filled share of this one. */
2228
+ .ow-rating__fill {
2229
+ position: absolute;
2230
+ inset-block: 0;
2231
+ inset-inline-start: 0;
2232
+ width: var(--ow-rating-fill);
2233
+ overflow: hidden;
2234
+ pointer-events: none;
2235
+ transition: width var(--ow-duration-fast) var(--ow-ease-standard);
2236
+ }
2237
+
2238
+ /* Each radio covers its star (or the start half of it, for a half point) and is drawn by the star. */
2239
+ .ow-rating__input {
2240
+ position: absolute;
2241
+ inset-block: 0;
2242
+ inset-inline-start: 0;
2243
+ width: 100%;
2244
+ margin: 0;
2245
+ appearance: none;
2246
+ opacity: 0;
2247
+ cursor: pointer;
2248
+ }
2249
+
2250
+ .ow-rating__input--half {
2251
+ z-index: 1;
2252
+ width: 50%;
2253
+ }
2254
+
2255
+ .ow-rating__input:disabled {
2256
+ cursor: not-allowed;
2257
+ }
2258
+
2259
+ .ow-rating__stars:has(:focus-visible) {
2260
+ outline: 2px solid var(--ow-focus-ring);
2261
+ outline-offset: 0;
2262
+ }
2263
+
2264
+ .ow-rating__star .ow-rating__glyph {
2265
+ transition: transform var(--ow-duration-base) var(--ow-ease-spring);
2266
+ }
2267
+
2268
+ @media (prefers-reduced-motion: no-preference) {
2269
+ .ow-rating__star:has(.ow-rating__input:hover:not(:disabled)) .ow-rating__glyph,
2270
+ .ow-rating__star:has(.ow-rating__input:focus-visible) .ow-rating__glyph {
2271
+ transform: scale(1.12);
2272
+ }
2273
+
2274
+ .ow-rating__star:has(.ow-rating__input:active:not(:disabled)) .ow-rating__glyph {
2275
+ transform: scale(0.92);
2276
+ }
2277
+ }
2278
+
2279
+ .ow-rating__stars[aria-invalid="true"] .ow-rating__icon--empty {
2280
+ stroke: var(--ow-danger-text);
2281
+ }
2282
+
2283
+ .ow-rating--disabled {
2284
+ opacity: 0.55;
2285
+ }
2286
+
2287
+ .ow-rating__value {
2288
+ color: var(--ow-text);
2289
+ font-weight: var(--ow-weight-emphasis);
2290
+ font-variant-numeric: tabular-nums;
2291
+ }
2292
+
2293
+ .ow-rating__value + .ow-rating__count {
2294
+ margin-inline-start: calc(var(--ow-space-sm) * -0.5);
2295
+ }
2296
+
2297
+ @media (prefers-reduced-motion: reduce) {
2298
+ .ow-rating__fill,
2299
+ .ow-rating__star .ow-rating__glyph {
2300
+ transition: none;
2301
+ }
2302
+ }
2303
+
2109
2304
  /* components/NumberField/NumberField.css */
2110
2305
  /* NumberField: − value + in one field. */
2111
2306
  .ow-number-field {
@@ -2584,6 +2779,199 @@
2584
2779
  color: var(--ow-danger-text);
2585
2780
  }
2586
2781
 
2782
+ /* components/Banner/Banner.css */
2783
+ /* Banner: a bar across the top of the page. Each tone sets the ground, the rule under it and the icon's colour; on
2784
+ narrow bars (its own width, a container query) the action moves under the message. */
2785
+ .ow-banner {
2786
+ --ow-banner-ground: var(--ow-primary);
2787
+ --ow-banner-rule: var(--ow-primary);
2788
+ --ow-banner-icon: var(--ow-on-primary);
2789
+ container: ow-banner / inline-size;
2790
+ display: grid;
2791
+ grid-template-rows: 1fr;
2792
+ border-bottom: 1px solid var(--ow-banner-rule);
2793
+ /* Over the surface, so a translucent dark-theme tint stays solid when the page scrolls under a sticky bar. */
2794
+ background: linear-gradient(var(--ow-banner-ground), var(--ow-banner-ground)) var(--ow-surface);
2795
+ color: var(--ow-text);
2796
+ font-size: 14px;
2797
+ line-height: 1.5;
2798
+ transition-property: grid-template-rows, opacity;
2799
+ transition-duration: var(--ow-duration-exit);
2800
+ transition-timing-function: var(--ow-ease-exit);
2801
+ }
2802
+
2803
+ .ow-banner--sticky {
2804
+ position: sticky;
2805
+ z-index: 10;
2806
+ top: 0;
2807
+ }
2808
+
2809
+ .ow-banner[data-state="closed"] {
2810
+ grid-template-rows: 0fr;
2811
+ opacity: 0;
2812
+ }
2813
+
2814
+ .ow-banner__clip {
2815
+ min-height: 0;
2816
+ }
2817
+
2818
+ .ow-banner[data-state="closed"] .ow-banner__clip {
2819
+ overflow: hidden;
2820
+ }
2821
+
2822
+ .ow-banner__inner {
2823
+ display: flex;
2824
+ align-items: flex-start;
2825
+ gap: var(--ow-space-md);
2826
+ padding: var(--ow-space-md) var(--ow-space-2xl);
2827
+ }
2828
+
2829
+ /* Room on the left as wide as the ✕ on the right, so a centred message sits in the middle of the bar. */
2830
+ .ow-banner--center.ow-banner--dismissible .ow-banner__inner::before {
2831
+ content: "";
2832
+ width: 24px;
2833
+ flex-shrink: 0;
2834
+ }
2835
+
2836
+ .ow-banner__content {
2837
+ display: flex;
2838
+ min-width: 0;
2839
+ flex: 1;
2840
+ gap: var(--ow-space-sm);
2841
+ }
2842
+
2843
+ .ow-banner--center .ow-banner__content {
2844
+ justify-content: center;
2845
+ text-align: center;
2846
+ }
2847
+
2848
+ .ow-banner__icon {
2849
+ display: inline-flex;
2850
+ height: 21px;
2851
+ flex-shrink: 0;
2852
+ align-items: center;
2853
+ color: var(--ow-banner-icon);
2854
+ }
2855
+
2856
+ .ow-banner__text {
2857
+ display: flex;
2858
+ min-width: 0;
2859
+ flex-wrap: wrap;
2860
+ align-items: center;
2861
+ justify-content: inherit;
2862
+ gap: var(--ow-space-2xs) var(--ow-space-lg);
2863
+ }
2864
+
2865
+ .ow-banner__message {
2866
+ min-width: 0;
2867
+ }
2868
+
2869
+ .ow-banner__message > p {
2870
+ margin: 0;
2871
+ }
2872
+
2873
+ /* A small button reaches into the bar's padding, so it doesn't push the message off the icon's line. */
2874
+ .ow-banner__action {
2875
+ display: flex;
2876
+ margin-block: -4px;
2877
+ flex-wrap: wrap;
2878
+ align-items: center;
2879
+ gap: var(--ow-space-sm);
2880
+ font-weight: var(--ow-weight-control);
2881
+ }
2882
+
2883
+ .ow-banner .ow-link,
2884
+ .ow-banner .ow-link:hover {
2885
+ color: inherit;
2886
+ }
2887
+
2888
+ .ow-banner .ow-link:hover {
2889
+ text-decoration-color: currentColor;
2890
+ }
2891
+
2892
+ .ow-banner__close {
2893
+ margin-block: -1px;
2894
+ }
2895
+
2896
+ .ow-banner__close:hover:not(:disabled) {
2897
+ background: color-mix(in srgb, currentColor 12%, transparent);
2898
+ }
2899
+
2900
+ @container ow-banner (max-width: 559px) {
2901
+ .ow-banner .ow-banner__content {
2902
+ justify-content: flex-start;
2903
+ text-align: start;
2904
+ }
2905
+
2906
+ .ow-banner .ow-banner__text {
2907
+ flex-direction: column;
2908
+ align-items: flex-start;
2909
+ }
2910
+
2911
+ .ow-banner .ow-banner__action {
2912
+ margin-block: 0;
2913
+ }
2914
+
2915
+ .ow-banner .ow-banner__inner::before {
2916
+ display: none;
2917
+ }
2918
+ }
2919
+
2920
+ /* Tones */
2921
+
2922
+ .ow-banner--brand {
2923
+ color: var(--ow-on-primary);
2924
+ }
2925
+
2926
+ .ow-banner--brand .ow-link {
2927
+ text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
2928
+ }
2929
+
2930
+ .ow-banner--brand .ow-banner__close,
2931
+ .ow-banner--brand .ow-banner__close:hover:not(:disabled) {
2932
+ color: var(--ow-on-primary);
2933
+ }
2934
+
2935
+ .ow-banner--brand .ow-banner__inner :focus-visible {
2936
+ outline-color: var(--ow-on-primary);
2937
+ }
2938
+
2939
+ .ow-banner--neutral {
2940
+ --ow-banner-ground: var(--ow-surface-muted);
2941
+ --ow-banner-rule: var(--ow-border);
2942
+ --ow-banner-icon: var(--ow-text-muted);
2943
+ }
2944
+
2945
+ .ow-banner--info {
2946
+ --ow-banner-ground: var(--ow-primary-subtle);
2947
+ --ow-banner-rule: var(--ow-primary-border);
2948
+ --ow-banner-icon: var(--ow-primary-text);
2949
+ }
2950
+
2951
+ .ow-banner--success {
2952
+ --ow-banner-ground: var(--ow-success-surface);
2953
+ --ow-banner-rule: var(--ow-success-border);
2954
+ --ow-banner-icon: var(--ow-success-text);
2955
+ }
2956
+
2957
+ .ow-banner--warning {
2958
+ --ow-banner-ground: var(--ow-warning-surface);
2959
+ --ow-banner-rule: var(--ow-warning-border);
2960
+ --ow-banner-icon: var(--ow-warning-text);
2961
+ }
2962
+
2963
+ .ow-banner--danger {
2964
+ --ow-banner-ground: var(--ow-danger-surface);
2965
+ --ow-banner-rule: var(--ow-danger-border);
2966
+ --ow-banner-icon: var(--ow-danger-text);
2967
+ }
2968
+
2969
+ @media (prefers-reduced-motion: reduce) {
2970
+ .ow-banner {
2971
+ transition: none;
2972
+ }
2973
+ }
2974
+
2587
2975
  /* components/Progress/Progress.css */
2588
2976
  /* ProgressBar and ProgressCircle. The fill is ow-progress; tones swap in a status colour. */
2589
2977
  .ow-progress {
@@ -2798,20 +3186,152 @@
2798
3186
  }
2799
3187
  }
2800
3188
 
2801
- /* components/Tooltip/Tooltip.css */
2802
- /* Tooltip: a small dark label in the top layer, on the side of the child it prefers (or the other side when there's no room). */
2803
- .ow-tooltip {
2804
- display: inline-flex;
3189
+ /* components/PasswordInput/PasswordInput.css */
3190
+ /* PasswordInput: an Input group with a show and hide button at the end, and an optional strength meter and checklist under it. */
3191
+ .ow-password-input {
3192
+ display: grid;
3193
+ width: 100%;
3194
+ min-width: 0;
3195
+ gap: var(--ow-space-sm);
2805
3196
  }
2806
3197
 
2807
- .ow-tooltip__bubble {
2808
- z-index: 70;
2809
- max-width: 240px;
2810
- overflow: visible;
3198
+ /* The show and hide button: CloseButton's quiet square, a size down so it sits inside the field. */
3199
+ .ow-password-input__toggle {
3200
+ display: inline-flex;
3201
+ width: 28px;
3202
+ height: 28px;
3203
+ flex-shrink: 0;
3204
+ align-items: center;
3205
+ justify-content: center;
3206
+ margin: 0;
2811
3207
  border: 0;
2812
3208
  border-radius: var(--ow-radius-md);
2813
- background: var(--ow-tooltip);
2814
- padding: var(--ow-space-2xs) var(--ow-space-sm);
3209
+ background: transparent;
3210
+ padding: 0;
3211
+ color: var(--ow-icon);
3212
+ cursor: pointer;
3213
+ transition-property: color, background-color;
3214
+ transition-duration: var(--ow-duration-base);
3215
+ transition-timing-function: var(--ow-ease-standard);
3216
+ }
3217
+
3218
+ .ow-password-input__toggle--sm {
3219
+ width: 24px;
3220
+ height: 24px;
3221
+ }
3222
+
3223
+ .ow-password-input__toggle:hover:not(:disabled) {
3224
+ background: var(--ow-surface-muted);
3225
+ color: var(--ow-text);
3226
+ }
3227
+
3228
+ .ow-password-input__toggle:focus-visible {
3229
+ outline: 2px solid var(--ow-focus-ring);
3230
+ outline-offset: 1px;
3231
+ }
3232
+
3233
+ .ow-password-input__toggle:disabled {
3234
+ cursor: not-allowed;
3235
+ }
3236
+
3237
+ /* The strength line: the meter's blocks, then "Password strength: Good", the word in the meter's colour. */
3238
+ .ow-password-input__strength {
3239
+ display: grid;
3240
+ gap: var(--ow-space-xs);
3241
+ }
3242
+
3243
+ .ow-password-input__strength-text {
3244
+ min-height: 1.45em;
3245
+ margin: 0;
3246
+ color: var(--ow-text-muted);
3247
+ font-size: 13px;
3248
+ line-height: 1.45;
3249
+ }
3250
+
3251
+ .ow-password-input__strength-word {
3252
+ color: var(--ow-text);
3253
+ font-weight: var(--ow-weight-emphasis);
3254
+ transition: color var(--ow-duration-base) var(--ow-ease-standard);
3255
+ }
3256
+
3257
+ .ow-password-input__strength--danger .ow-password-input__strength-word {
3258
+ color: var(--ow-danger-text);
3259
+ }
3260
+
3261
+ .ow-password-input__strength--warning .ow-password-input__strength-word {
3262
+ color: var(--ow-warning-text);
3263
+ }
3264
+
3265
+ .ow-password-input__strength--success .ow-password-input__strength-word {
3266
+ color: var(--ow-success-text);
3267
+ }
3268
+
3269
+ /* The checklist: a ring for each rule, filled with a tick once it's met. */
3270
+ .ow-password-input__requirements {
3271
+ display: grid;
3272
+ gap: var(--ow-space-2xs);
3273
+ margin: 0;
3274
+ padding: 0;
3275
+ list-style: none;
3276
+ }
3277
+
3278
+ .ow-password-input__requirement {
3279
+ display: flex;
3280
+ align-items: center;
3281
+ gap: var(--ow-space-sm);
3282
+ color: var(--ow-text-muted);
3283
+ font-size: 13px;
3284
+ line-height: 1.45;
3285
+ transition: color var(--ow-duration-base) var(--ow-ease-standard);
3286
+ }
3287
+
3288
+ .ow-password-input__mark {
3289
+ display: inline-flex;
3290
+ box-sizing: border-box;
3291
+ width: 16px;
3292
+ height: 16px;
3293
+ flex-shrink: 0;
3294
+ align-items: center;
3295
+ justify-content: center;
3296
+ border: 1.5px solid var(--ow-border-strong);
3297
+ border-radius: var(--ow-radius-pill);
3298
+ color: var(--ow-success-text);
3299
+ transition-property: border-color, background-color;
3300
+ transition-duration: var(--ow-duration-base);
3301
+ transition-timing-function: var(--ow-ease-standard);
3302
+ }
3303
+
3304
+ .ow-password-input__requirement--met {
3305
+ color: var(--ow-text);
3306
+ }
3307
+
3308
+ .ow-password-input__requirement--met .ow-password-input__mark {
3309
+ border-color: var(--ow-success-text);
3310
+ }
3311
+
3312
+ @media (prefers-reduced-motion: reduce) {
3313
+ .ow-password-input__toggle,
3314
+ .ow-password-input__strength-word,
3315
+ .ow-password-input__requirement,
3316
+ .ow-password-input__mark {
3317
+ transition: none;
3318
+ }
3319
+ }
3320
+
3321
+ /* components/Tooltip/Tooltip.css */
3322
+ /* Tooltip: a small dark label in the top layer, on the side of the child it prefers (or the other side when there's no room). */
3323
+ .ow-tooltip {
3324
+ display: inline-flex;
3325
+ }
3326
+
3327
+ .ow-tooltip__bubble {
3328
+ z-index: 70;
3329
+ max-width: 240px;
3330
+ overflow: visible;
3331
+ border: 0;
3332
+ border-radius: var(--ow-radius-md);
3333
+ background: var(--ow-tooltip);
3334
+ padding: var(--ow-space-2xs) var(--ow-space-sm);
2815
3335
  color: var(--ow-on-tooltip);
2816
3336
  font-family: var(--ow-font-sans);
2817
3337
  font-size: 12px;
@@ -3345,6 +3865,172 @@
3345
3865
  line-height: 1.3;
3346
3866
  }
3347
3867
 
3868
+ /* components/Tour/Tour.css */
3869
+ /* Tour and Coachmark: a popover-like card beside each step's target, over an optional spotlight that dims the
3870
+ rest of the page. Both sit in the top layer, the spotlight first. */
3871
+ .ow-tour {
3872
+ z-index: 60;
3873
+ display: grid;
3874
+ gap: var(--ow-space-md);
3875
+ max-width: calc(100vw - 16px);
3876
+ overflow: auto;
3877
+ border: 1px solid var(--ow-border);
3878
+ border-radius: var(--ow-radius-container);
3879
+ background: var(--ow-surface);
3880
+ padding: var(--ow-space-xl) var(--ow-space-xl) var(--ow-space-lg);
3881
+ color: var(--ow-text);
3882
+ font-family: var(--ow-font-sans);
3883
+ font-size: 14px;
3884
+ line-height: 1.45;
3885
+ box-shadow: var(--ow-shadow-menu);
3886
+ outline: none;
3887
+ }
3888
+
3889
+ /* A step without a target: in the middle of the window, where the browser puts a popover. */
3890
+ .ow-tour--centred {
3891
+ position: fixed;
3892
+ inset: 0;
3893
+ height: fit-content;
3894
+ max-height: calc(100dvh - 32px);
3895
+ margin: auto;
3896
+ }
3897
+
3898
+ .ow-tour > * {
3899
+ min-width: 0;
3900
+ }
3901
+
3902
+ .ow-tour__header {
3903
+ display: flex;
3904
+ align-items: flex-start;
3905
+ justify-content: space-between;
3906
+ gap: var(--ow-space-sm);
3907
+ }
3908
+
3909
+ .ow-tour__title {
3910
+ padding-top: 2px;
3911
+ font-size: 14px;
3912
+ font-weight: var(--ow-weight-emphasis);
3913
+ line-height: 1.3;
3914
+ }
3915
+
3916
+ .ow-tour__header .ow-close-button {
3917
+ flex-shrink: 0;
3918
+ margin: -2px -4px 0 0;
3919
+ }
3920
+
3921
+ .ow-tour__content {
3922
+ color: var(--ow-text-muted);
3923
+ }
3924
+
3925
+ .ow-tour__content > p {
3926
+ margin: 0;
3927
+ }
3928
+
3929
+ .ow-tour__footer {
3930
+ display: flex;
3931
+ flex-wrap: wrap;
3932
+ align-items: center;
3933
+ gap: var(--ow-space-sm);
3934
+ margin-top: var(--ow-space-2xs);
3935
+ }
3936
+
3937
+ .ow-tour__progress {
3938
+ color: var(--ow-text-muted);
3939
+ font-size: 13px;
3940
+ font-variant-numeric: tabular-nums;
3941
+ }
3942
+
3943
+ .ow-tour__actions {
3944
+ display: flex;
3945
+ gap: var(--ow-space-sm);
3946
+ margin-left: auto;
3947
+ }
3948
+
3949
+ /* The spotlight: the whole window, in the top layer under the card. It only dims: clicks go through to the page. */
3950
+ .ow-tour-spotlight {
3951
+ position: fixed;
3952
+ inset: 0;
3953
+ width: auto;
3954
+ height: auto;
3955
+ margin: 0;
3956
+ overflow: hidden;
3957
+ border: 0;
3958
+ background: transparent;
3959
+ padding: 0;
3960
+ pointer-events: none;
3961
+ }
3962
+
3963
+ .ow-tour-spotlight[data-state="open"] {
3964
+ animation: ow-tour-fade-in var(--ow-duration-slow) var(--ow-ease-standard);
3965
+ }
3966
+
3967
+ .ow-tour-spotlight[data-state="closed"] {
3968
+ animation: ow-tour-fade-out var(--ow-duration-exit) var(--ow-ease-exit) forwards;
3969
+ }
3970
+
3971
+ /* The hole over the target: a rounded box whose shadow covers everything else. */
3972
+ .ow-tour-spotlight__hole {
3973
+ position: absolute;
3974
+ border-radius: var(--ow-radius-tile);
3975
+ box-shadow: 0 0 0 200vmax var(--ow-backdrop);
3976
+ }
3977
+
3978
+ .ow-tour-spotlight__hole[data-moving] {
3979
+ transition-duration: var(--ow-duration-panel);
3980
+ transition-property: top, left, width, height;
3981
+ transition-timing-function: var(--ow-ease-emphasized);
3982
+ }
3983
+
3984
+ .ow-tour-spotlight__dim {
3985
+ position: absolute;
3986
+ inset: 0;
3987
+ background: var(--ow-backdrop);
3988
+ }
3989
+
3990
+ @keyframes ow-tour-fade-in {
3991
+ from {
3992
+ opacity: 0;
3993
+ }
3994
+ }
3995
+
3996
+ @keyframes ow-tour-fade-out {
3997
+ to {
3998
+ opacity: 0;
3999
+ }
4000
+ }
4001
+
4002
+ @media (prefers-reduced-motion: reduce) {
4003
+ .ow-tour-spotlight__hole[data-moving] {
4004
+ transition: none;
4005
+ }
4006
+ }
4007
+
4008
+ /* components/HoverCard/HoverCard.css */
4009
+ /* HoverCard: Popover's surface, opened by resting the pointer on (or tabbing to) its trigger. */
4010
+ .ow-hover-card-anchor {
4011
+ display: inline-flex;
4012
+ }
4013
+
4014
+ .ow-hover-card {
4015
+ z-index: 60;
4016
+ display: grid;
4017
+ gap: var(--ow-space-md);
4018
+ overflow: auto;
4019
+ border: 1px solid var(--ow-border);
4020
+ border-radius: var(--ow-radius-container);
4021
+ background: var(--ow-surface);
4022
+ padding: var(--ow-space-lg);
4023
+ color: var(--ow-text);
4024
+ font-family: var(--ow-font-sans);
4025
+ font-size: 14px;
4026
+ line-height: 1.45;
4027
+ box-shadow: var(--ow-shadow-menu);
4028
+ }
4029
+
4030
+ .ow-hover-card > * {
4031
+ min-width: 0;
4032
+ }
4033
+
3348
4034
  /* components/Calendar/Calendar.css */
3349
4035
  /* Calendar: a quiet month grid. The chosen day is filled with the primary colour; today has a brass dot. */
3350
4036
  .ow-calendar {
@@ -4486,6 +5172,14 @@
4486
5172
  background: var(--ow-border);
4487
5173
  }
4488
5174
 
5175
+ /* components/ContextMenu/ContextMenu.css */
5176
+ /* ContextMenu: the wrapper adds no box of its own; the panel is Menu's (.ow-menu__panel), opened at the pointer. */
5177
+ .ow-context-menu {
5178
+ display: contents;
5179
+ /* A long press opens the menu, not the browser's callout. */
5180
+ -webkit-touch-callout: none;
5181
+ }
5182
+
4489
5183
  /* components/Accordion/Accordion.css */
4490
5184
  /* Disclosure and Accordion: a header with a chevron that turns as the panel opens. */
4491
5185
  .ow-disclosure,
@@ -4978,35 +5672,253 @@
4978
5672
  }
4979
5673
  }
4980
5674
 
4981
- /* components/ChoiceCard/ChoiceCard.css */
4982
- /* ChoiceCard: a tactile card-button with an icon tile, a title and one line of description. */
4983
- .ow-choice {
5675
+ /* components/Timeline/Timeline.css */
5676
+ /* Timeline: events down a 1px line. Each item draws the line above its marker (::before) and below it (::after), so
5677
+ the line stops a few pixels short of every marker, whatever its size, and can turn dashed around a pending item. */
5678
+ .ow-timeline {
5679
+ --ow-timeline-marker: 28px;
5680
+ --ow-timeline-dot: 10px;
5681
+ --ow-timeline-space: var(--ow-space-5xl);
5682
+ --ow-timeline-line: var(--ow-border-strong);
5683
+
4984
5684
  display: grid;
4985
- align-content: start;
4986
- gap: var(--ow-space-lg);
4987
5685
  margin: 0;
4988
- border: 1px solid var(--ow-border-strong);
4989
- border-radius: var(--ow-radius-container);
4990
- background-color: var(--ow-control);
4991
- background-image: linear-gradient(to bottom, var(--ow-control), var(--ow-control-shade));
4992
- padding: var(--ow-space-2xl);
4993
- color: var(--ow-text);
4994
- font: inherit;
4995
- text-align: left;
4996
- cursor: pointer;
4997
- box-shadow: var(--ow-shadow-button-secondary);
4998
- transition-property: transform, border-color, color, background-color, box-shadow, opacity;
4999
- transition-duration: var(--ow-duration-base);
5000
- transition-timing-function: var(--ow-ease-standard);
5686
+ padding: 0;
5687
+ list-style: none;
5001
5688
  }
5002
5689
 
5003
- .ow-choice--recommended {
5004
- border-color: var(--ow-primary-border);
5690
+ .ow-timeline--compact {
5691
+ --ow-timeline-marker: 24px;
5692
+ --ow-timeline-dot: 8px;
5693
+ --ow-timeline-space: var(--ow-space-xl);
5005
5694
  }
5006
5695
 
5007
- .ow-choice:hover:not(:disabled),
5008
- .ow-choice:focus-visible {
5009
- border-color: var(--ow-primary-text);
5696
+ .ow-timeline__item {
5697
+ /* Half of what shows of the marker, plus the gap to the line. */
5698
+ --ow-timeline-reach: calc(var(--ow-timeline-marker) / 2 + 4px);
5699
+ --ow-timeline-pad: var(--ow-timeline-space);
5700
+
5701
+ position: relative;
5702
+ display: grid;
5703
+ grid-template-columns: var(--ow-timeline-marker) minmax(0, 1fr);
5704
+ column-gap: var(--ow-space-lg);
5705
+ padding-top: var(--ow-timeline-pad);
5706
+ }
5707
+
5708
+ .ow-timeline__item:first-child {
5709
+ --ow-timeline-pad: 0px;
5710
+ }
5711
+
5712
+ .ow-timeline__item--dot {
5713
+ --ow-timeline-reach: calc(var(--ow-timeline-dot) / 2 + 4px);
5714
+ }
5715
+
5716
+ .ow-timeline__item::before,
5717
+ .ow-timeline__item::after {
5718
+ content: "";
5719
+ position: absolute;
5720
+ left: calc(var(--ow-timeline-marker) / 2 - 0.5px);
5721
+ border-left: 1px solid var(--ow-timeline-line);
5722
+ }
5723
+
5724
+ /* From the item's top edge down to just above its marker. */
5725
+ .ow-timeline__item:not(:first-child)::before {
5726
+ top: 0;
5727
+ height: max(0px, calc(var(--ow-timeline-pad) + var(--ow-timeline-marker) / 2 - var(--ow-timeline-reach)));
5728
+ }
5729
+
5730
+ /* From just below the marker to the item's bottom edge, where the next item's line takes over. */
5731
+ .ow-timeline__item:not(:last-child)::after {
5732
+ top: calc(var(--ow-timeline-pad) + var(--ow-timeline-marker) / 2 + var(--ow-timeline-reach));
5733
+ bottom: 0;
5734
+ }
5735
+
5736
+ /* The way to and from something that hasn't happened yet is dashed. */
5737
+ .ow-timeline__item--pending::before,
5738
+ .ow-timeline__item--pending::after,
5739
+ .ow-timeline__item:has(+ .ow-timeline__item--pending)::after {
5740
+ border-left-style: dashed;
5741
+ }
5742
+
5743
+ .ow-timeline__marker {
5744
+ display: flex;
5745
+ width: var(--ow-timeline-marker);
5746
+ height: var(--ow-timeline-marker);
5747
+ align-items: center;
5748
+ justify-content: center;
5749
+ }
5750
+
5751
+ .ow-timeline__dot {
5752
+ width: var(--ow-timeline-dot);
5753
+ height: var(--ow-timeline-dot);
5754
+ box-sizing: border-box;
5755
+ border: 2px solid var(--ow-timeline-solid, var(--ow-border-strong));
5756
+ border-radius: 50%;
5757
+ background: var(--ow-timeline-solid, var(--ow-border-strong));
5758
+ }
5759
+
5760
+ .ow-timeline__item--icon .ow-timeline__marker {
5761
+ box-sizing: border-box;
5762
+ border: 1px solid var(--ow-timeline-border, var(--ow-border));
5763
+ border-radius: 50%;
5764
+ background: var(--ow-timeline-surface, var(--ow-surface-muted));
5765
+ color: var(--ow-timeline-text, var(--ow-icon));
5766
+ }
5767
+
5768
+ .ow-timeline__item--brand {
5769
+ --ow-timeline-solid: var(--ow-primary);
5770
+ --ow-timeline-border: var(--ow-primary-border);
5771
+ --ow-timeline-surface: var(--ow-primary-subtle);
5772
+ --ow-timeline-text: var(--ow-primary-text);
5773
+ }
5774
+
5775
+ .ow-timeline__item--success {
5776
+ --ow-timeline-solid: var(--ow-success-solid);
5777
+ --ow-timeline-border: var(--ow-success-border);
5778
+ --ow-timeline-surface: var(--ow-success-surface);
5779
+ --ow-timeline-text: var(--ow-success-text);
5780
+ }
5781
+
5782
+ .ow-timeline__item--warning {
5783
+ --ow-timeline-solid: var(--ow-warning-solid);
5784
+ --ow-timeline-border: var(--ow-warning-border);
5785
+ --ow-timeline-surface: var(--ow-warning-surface);
5786
+ --ow-timeline-text: var(--ow-warning-text);
5787
+ }
5788
+
5789
+ .ow-timeline__item--danger {
5790
+ --ow-timeline-solid: var(--ow-danger-solid);
5791
+ --ow-timeline-border: var(--ow-danger-border);
5792
+ --ow-timeline-surface: var(--ow-danger-surface);
5793
+ --ow-timeline-text: var(--ow-danger-text);
5794
+ }
5795
+
5796
+ /* Pending: a hollow marker, drawn with a dashed edge when it's an icon's circle. */
5797
+ .ow-timeline__item--pending .ow-timeline__dot {
5798
+ background: transparent;
5799
+ }
5800
+
5801
+ .ow-timeline__item--pending.ow-timeline__item--icon .ow-timeline__marker {
5802
+ border-style: dashed;
5803
+ border-color: var(--ow-border-strong);
5804
+ background: transparent;
5805
+ color: var(--ow-text-muted);
5806
+ }
5807
+
5808
+ .ow-timeline__content {
5809
+ display: grid;
5810
+ min-width: 0;
5811
+ align-content: start;
5812
+ gap: var(--ow-space-xs);
5813
+ /* Centres the first line (20px) on the marker. */
5814
+ padding-top: calc((var(--ow-timeline-marker) - 20px) / 2);
5815
+ }
5816
+
5817
+ .ow-timeline__header {
5818
+ display: flex;
5819
+ flex-wrap: wrap;
5820
+ align-items: baseline;
5821
+ gap: var(--ow-space-2xs) var(--ow-space-md);
5822
+ font-size: 14px;
5823
+ line-height: 20px;
5824
+ }
5825
+
5826
+ .ow-timeline__title {
5827
+ min-width: 0;
5828
+ flex: 1 1 auto;
5829
+ color: var(--ow-text);
5830
+ font-weight: var(--ow-weight-emphasis);
5831
+ }
5832
+
5833
+ .ow-timeline__separator {
5834
+ display: none;
5835
+ }
5836
+
5837
+ .ow-timeline__time {
5838
+ color: var(--ow-text-muted);
5839
+ font-size: 12px;
5840
+ font-variant-numeric: tabular-nums;
5841
+ white-space: nowrap;
5842
+ }
5843
+
5844
+ .ow-timeline__item--pending .ow-timeline__title {
5845
+ color: var(--ow-text-muted);
5846
+ }
5847
+
5848
+ .ow-timeline__body {
5849
+ min-width: 0;
5850
+ color: var(--ow-text-soft);
5851
+ font-size: 14px;
5852
+ line-height: 1.5;
5853
+ }
5854
+
5855
+ .ow-timeline__body > p {
5856
+ margin: 0;
5857
+ }
5858
+
5859
+ /* Compact: one sentence with the time after it, in the flow of the text. */
5860
+ .ow-timeline--compact .ow-timeline__header {
5861
+ display: block;
5862
+ }
5863
+
5864
+ .ow-timeline--compact .ow-timeline__title {
5865
+ color: var(--ow-text-soft);
5866
+ font-weight: var(--ow-weight-regular);
5867
+ }
5868
+
5869
+ .ow-timeline--compact .ow-timeline__title :is(strong, b) {
5870
+ color: var(--ow-text);
5871
+ font-weight: var(--ow-weight-emphasis);
5872
+ }
5873
+
5874
+ .ow-timeline--compact .ow-timeline__separator {
5875
+ display: inline;
5876
+ margin-inline: var(--ow-space-xs);
5877
+ color: var(--ow-text-muted);
5878
+ }
5879
+
5880
+ .ow-timeline--compact .ow-timeline__time {
5881
+ font-size: 13px;
5882
+ }
5883
+
5884
+ .ow-timeline--compact .ow-timeline__content {
5885
+ gap: var(--ow-space-2xs);
5886
+ }
5887
+
5888
+ .ow-timeline--compact .ow-timeline__body {
5889
+ color: var(--ow-text-muted);
5890
+ font-size: 13px;
5891
+ }
5892
+
5893
+ /* components/ChoiceCard/ChoiceCard.css */
5894
+ /* ChoiceCard: a tactile card-button with an icon tile, a title and one line of description. */
5895
+ .ow-choice {
5896
+ display: grid;
5897
+ align-content: start;
5898
+ gap: var(--ow-space-lg);
5899
+ margin: 0;
5900
+ border: 1px solid var(--ow-border-strong);
5901
+ border-radius: var(--ow-radius-container);
5902
+ background-color: var(--ow-control);
5903
+ background-image: linear-gradient(to bottom, var(--ow-control), var(--ow-control-shade));
5904
+ padding: var(--ow-space-2xl);
5905
+ color: var(--ow-text);
5906
+ font: inherit;
5907
+ text-align: left;
5908
+ cursor: pointer;
5909
+ box-shadow: var(--ow-shadow-button-secondary);
5910
+ transition-property: transform, border-color, color, background-color, box-shadow, opacity;
5911
+ transition-duration: var(--ow-duration-base);
5912
+ transition-timing-function: var(--ow-ease-standard);
5913
+ }
5914
+
5915
+ .ow-choice--recommended {
5916
+ border-color: var(--ow-primary-border);
5917
+ }
5918
+
5919
+ .ow-choice:hover:not(:disabled),
5920
+ .ow-choice:focus-visible {
5921
+ border-color: var(--ow-primary-text);
5010
5922
  }
5011
5923
 
5012
5924
  .ow-choice:focus-visible {
@@ -5205,6 +6117,86 @@
5205
6117
  white-space: nowrap;
5206
6118
  }
5207
6119
 
6120
+ /* components/Image/Image.css */
6121
+ /* Image: an <img> in a box that pulses while it loads and shows a fallback if it fails. With a ratio, the box is an
6122
+ AspectRatio and the image fills it. */
6123
+ .ow-image {
6124
+ position: relative;
6125
+ display: inline-block;
6126
+ max-width: 100%;
6127
+ overflow: hidden;
6128
+ vertical-align: top;
6129
+ }
6130
+
6131
+ .ow-image.ow-aspect-ratio {
6132
+ display: block;
6133
+ }
6134
+
6135
+ .ow-image__img {
6136
+ display: block;
6137
+ max-width: 100%;
6138
+ transition: opacity var(--ow-duration-base) var(--ow-ease-standard);
6139
+ }
6140
+
6141
+ .ow-image--cover .ow-image__img {
6142
+ object-fit: cover;
6143
+ }
6144
+
6145
+ .ow-image--contain .ow-image__img {
6146
+ object-fit: contain;
6147
+ }
6148
+
6149
+ .ow-image--radius-control {
6150
+ border-radius: var(--ow-radius-form);
6151
+ }
6152
+
6153
+ .ow-image--radius-container {
6154
+ border-radius: var(--ow-radius-container);
6155
+ }
6156
+
6157
+ /* Loading: the Skeleton's grey and pulse, with the image hidden until it's ready. */
6158
+ .ow-image--loading {
6159
+ background: var(--ow-skeleton);
6160
+ animation: ow-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
6161
+ }
6162
+
6163
+ .ow-image--loading .ow-image__img {
6164
+ opacity: 0;
6165
+ }
6166
+
6167
+ .ow-image__fallback {
6168
+ display: flex;
6169
+ box-sizing: border-box;
6170
+ min-width: 64px;
6171
+ max-width: 100%;
6172
+ min-height: 64px;
6173
+ align-items: center;
6174
+ justify-content: center;
6175
+ }
6176
+
6177
+ .ow-image__fallback--default {
6178
+ background: var(--ow-skeleton-soft);
6179
+ color: var(--ow-icon);
6180
+ }
6181
+
6182
+ .ow-image-figure {
6183
+ display: grid;
6184
+ margin: 0;
6185
+ gap: var(--ow-space-sm);
6186
+ justify-items: start;
6187
+ }
6188
+
6189
+ .ow-image-figure > .ow-aspect-ratio {
6190
+ justify-self: stretch;
6191
+ }
6192
+
6193
+ .ow-image-figure__caption {
6194
+ color: var(--ow-text-muted);
6195
+ font-family: var(--ow-font-sans);
6196
+ font-size: 13px;
6197
+ line-height: 1.4;
6198
+ }
6199
+
5208
6200
  /* components/Kbd/Kbd.css */
5209
6201
  /* Kbd and inline Code, both in the mono face. */
5210
6202
  .ow-kbd {
@@ -5890,6 +6882,287 @@
5890
6882
  transform: translate(-50%, -50%);
5891
6883
  }
5892
6884
 
6885
+ /* components/Carousel/Carousel.css */
6886
+ /* Carousel: a row of slides on the browser's own scroll-snap, with round buttons on the edges and dots below. */
6887
+ .ow-carousel {
6888
+ --ow-carousel-per-view: 1;
6889
+ --ow-carousel-gap: var(--ow-space-md);
6890
+ --ow-carousel-arrow: 32px;
6891
+ display: flex;
6892
+ min-width: 0;
6893
+ flex-direction: column;
6894
+ gap: var(--ow-space-md);
6895
+ }
6896
+
6897
+ .ow-carousel__viewport {
6898
+ position: relative;
6899
+ container-type: inline-size;
6900
+ }
6901
+
6902
+ .ow-carousel--arrows-outside .ow-carousel__viewport {
6903
+ margin-inline: calc(var(--ow-carousel-arrow) + var(--ow-space-sm));
6904
+ }
6905
+
6906
+ .ow-carousel__track {
6907
+ --ow-carousel-slide: calc((100cqi - (var(--ow-carousel-per-view) - 1) * var(--ow-carousel-gap)) / var(--ow-carousel-per-view));
6908
+ display: flex;
6909
+ gap: var(--ow-carousel-gap);
6910
+ overflow-x: auto;
6911
+ overscroll-behavior-x: contain;
6912
+ border-radius: var(--ow-radius-container);
6913
+ scroll-snap-type: x mandatory;
6914
+ scrollbar-width: none;
6915
+ }
6916
+
6917
+ .ow-carousel__track::-webkit-scrollbar {
6918
+ display: none;
6919
+ }
6920
+
6921
+ .ow-carousel--center .ow-carousel__track {
6922
+ padding-inline: calc((100cqi - var(--ow-carousel-slide)) / 2);
6923
+ }
6924
+
6925
+ .ow-carousel__track:focus-visible {
6926
+ outline: 2px solid var(--ow-focus-ring);
6927
+ outline-offset: 2px;
6928
+ }
6929
+
6930
+ .ow-carousel__slide {
6931
+ flex: 0 0 var(--ow-carousel-slide);
6932
+ min-width: 0;
6933
+ scroll-snap-align: start;
6934
+ }
6935
+
6936
+ .ow-carousel--center .ow-carousel__slide {
6937
+ scroll-snap-align: center;
6938
+ }
6939
+
6940
+ .ow-carousel__arrow,
6941
+ .ow-carousel__play {
6942
+ position: absolute;
6943
+ z-index: 1;
6944
+ border-radius: 50%;
6945
+ }
6946
+
6947
+ .ow-carousel__arrow {
6948
+ top: 50%;
6949
+ translate: 0 -50%;
6950
+ }
6951
+
6952
+ .ow-carousel__arrow--previous {
6953
+ left: var(--ow-space-sm);
6954
+ }
6955
+
6956
+ .ow-carousel__arrow--next {
6957
+ right: var(--ow-space-sm);
6958
+ }
6959
+
6960
+ .ow-carousel--arrows-outside .ow-carousel__arrow--previous {
6961
+ left: calc(-1 * (var(--ow-carousel-arrow) + var(--ow-space-sm)));
6962
+ }
6963
+
6964
+ .ow-carousel--arrows-outside .ow-carousel__arrow--next {
6965
+ right: calc(-1 * (var(--ow-carousel-arrow) + var(--ow-space-sm)));
6966
+ }
6967
+
6968
+ /* On the slides, a button with nowhere to go gets out of the way. */
6969
+ .ow-carousel--arrows-overlay .ow-carousel__arrow:disabled {
6970
+ opacity: 0;
6971
+ pointer-events: none;
6972
+ }
6973
+
6974
+ .ow-carousel__play {
6975
+ right: var(--ow-space-sm);
6976
+ bottom: var(--ow-space-sm);
6977
+ }
6978
+
6979
+ .ow-carousel__dots {
6980
+ display: flex;
6981
+ flex-wrap: wrap;
6982
+ justify-content: center;
6983
+ }
6984
+
6985
+ /* A 24px target around a small dot; the current one stretches into a pill in the primary colour. */
6986
+ .ow-carousel__dot {
6987
+ display: inline-flex;
6988
+ width: 24px;
6989
+ height: 24px;
6990
+ align-items: center;
6991
+ justify-content: center;
6992
+ margin: 0;
6993
+ border: 0;
6994
+ border-radius: 999px;
6995
+ background: none;
6996
+ padding: 0;
6997
+ cursor: pointer;
6998
+ }
6999
+
7000
+ .ow-carousel__dot::before {
7001
+ width: 8px;
7002
+ height: 8px;
7003
+ border-radius: 999px;
7004
+ background: var(--ow-text-muted);
7005
+ content: "";
7006
+ transition-property: width, background-color;
7007
+ transition-duration: var(--ow-duration-base);
7008
+ transition-timing-function: var(--ow-ease-standard);
7009
+ }
7010
+
7011
+ .ow-carousel__dot:hover::before {
7012
+ background: var(--ow-text-soft);
7013
+ }
7014
+
7015
+ .ow-carousel__dot[aria-current="true"]::before {
7016
+ width: 20px;
7017
+ background: var(--ow-primary);
7018
+ }
7019
+
7020
+ .ow-carousel__dot[aria-current="true"] {
7021
+ width: 32px;
7022
+ }
7023
+
7024
+ .ow-carousel__dot:focus-visible {
7025
+ outline: 2px solid var(--ow-focus-ring);
7026
+ outline-offset: -2px;
7027
+ }
7028
+
7029
+ /* components/DescriptionList/DescriptionList.css */
7030
+ /* DescriptionList: terms and their values in a <dl>. Its own width decides the layout (a container query), so it
7031
+ stacks in a narrow card or panel as well as on a phone. */
7032
+ .ow-description-list {
7033
+ container: ow-description-list / inline-size;
7034
+ display: grid;
7035
+ margin: 0;
7036
+ color: var(--ow-text);
7037
+ font-size: 14px;
7038
+ line-height: 1.5;
7039
+ }
7040
+
7041
+ .ow-description-item {
7042
+ display: grid;
7043
+ min-width: 0;
7044
+ align-content: start;
7045
+ gap: var(--ow-space-2xs);
7046
+ padding-block: var(--ow-space-lg);
7047
+ }
7048
+
7049
+ .ow-description-list--compact .ow-description-item {
7050
+ padding-block: var(--ow-space-sm);
7051
+ }
7052
+
7053
+ .ow-description-item__term {
7054
+ color: var(--ow-text-muted);
7055
+ }
7056
+
7057
+ .ow-description-item__value {
7058
+ min-width: 0;
7059
+ margin: 0;
7060
+ overflow-wrap: anywhere;
7061
+ }
7062
+
7063
+ .ow-description-item__value--action {
7064
+ display: flex;
7065
+ align-items: center;
7066
+ gap: var(--ow-space-lg);
7067
+ }
7068
+
7069
+ .ow-description-item__content {
7070
+ min-width: 0;
7071
+ flex: 1;
7072
+ }
7073
+
7074
+ .ow-description-item__action {
7075
+ display: flex;
7076
+ flex-shrink: 0;
7077
+ align-items: center;
7078
+ gap: var(--ow-space-2xs);
7079
+ margin-block: -4px;
7080
+ }
7081
+
7082
+ /* Horizontal and vertical: one pair under another, without space past the first and last. */
7083
+ .ow-description-list:not(.ow-description-list--grid) > .ow-description-item:first-child {
7084
+ padding-top: 0;
7085
+ }
7086
+
7087
+ .ow-description-list:not(.ow-description-list--grid) > .ow-description-item:last-child {
7088
+ padding-bottom: 0;
7089
+ }
7090
+
7091
+ .ow-description-list--divided:not(.ow-description-list--grid) > .ow-description-item + .ow-description-item {
7092
+ border-top: 1px solid var(--ow-border);
7093
+ }
7094
+
7095
+ .ow-description-list--horizontal > .ow-description-item {
7096
+ grid-template-columns: var(--ow-description-term-width, 160px) minmax(0, 1fr);
7097
+ align-items: baseline;
7098
+ column-gap: var(--ow-space-2xl);
7099
+ }
7100
+
7101
+ /* Grid: the pairs in columns, term above value, with a smaller label. A column is at least 160px, so a grid with
7102
+ less room has fewer columns; the items then read the list's width (the container) to keep their spans inside it. */
7103
+ .ow-description-list--grid {
7104
+ --ow-description-gap: var(--ow-space-4xl);
7105
+ grid-template-columns: repeat(
7106
+ auto-fill,
7107
+ minmax(max(160px, (100% - (var(--ow-description-columns) - 1) * var(--ow-description-gap)) / var(--ow-description-columns)), 1fr)
7108
+ );
7109
+ column-gap: var(--ow-description-gap);
7110
+ }
7111
+
7112
+ .ow-description-list--cols-2 {
7113
+ --ow-description-columns: 2;
7114
+ }
7115
+
7116
+ .ow-description-list--cols-3 {
7117
+ --ow-description-columns: 3;
7118
+ }
7119
+
7120
+ .ow-description-list--cols-4 {
7121
+ --ow-description-columns: 4;
7122
+ }
7123
+
7124
+ .ow-description-list--grid .ow-description-item__term {
7125
+ font-size: 12px;
7126
+ font-weight: var(--ow-weight-control);
7127
+ }
7128
+
7129
+ .ow-description-list--grid.ow-description-list--divided > .ow-description-item {
7130
+ border-top: 1px solid var(--ow-border);
7131
+ }
7132
+
7133
+ .ow-description-item--span-2 {
7134
+ grid-column: span 2;
7135
+ }
7136
+
7137
+ .ow-description-item--span-3 {
7138
+ grid-column: span 3;
7139
+ }
7140
+
7141
+ .ow-description-item--span-4,
7142
+ .ow-description-item--span-full,
7143
+ .ow-description-list--cols-2 > .ow-description-item--span-3 {
7144
+ grid-column: 1 / -1;
7145
+ }
7146
+
7147
+ @container ow-description-list (max-width: 519px) {
7148
+ .ow-description-item--span-3 {
7149
+ grid-column: 1 / -1;
7150
+ }
7151
+ }
7152
+
7153
+ @container ow-description-list (max-width: 419px) {
7154
+ .ow-description-list--horizontal > .ow-description-item {
7155
+ grid-template-columns: minmax(0, 1fr);
7156
+ }
7157
+ }
7158
+
7159
+ @container ow-description-list (max-width: 339px) {
7160
+ .ow-description-item--span-2,
7161
+ .ow-description-item--span-3 {
7162
+ grid-column: auto;
7163
+ }
7164
+ }
7165
+
5893
7166
  /* components/Chart/Chart.css */
5894
7167
  /* Charts: thin marks in the chart palette (--ow-chart-1 to 8), hairline grids, text in text colours, never the series'. */
5895
7168
 
@@ -6847,6 +8120,179 @@
6847
8120
  }
6848
8121
  }
6849
8122
 
8123
+ /* components/Splitter/Splitter.css */
8124
+ /* Splitter: panels with handles between them. A panel's flex-grow is its size in percent. */
8125
+ .ow-splitter {
8126
+ display: flex;
8127
+ width: 100%;
8128
+ height: 100%;
8129
+ min-width: 0;
8130
+ min-height: 0;
8131
+ overflow: hidden;
8132
+ }
8133
+
8134
+ .ow-splitter--vertical {
8135
+ flex-direction: column;
8136
+ }
8137
+
8138
+ .ow-splitter__panel {
8139
+ flex: 0 1 0px;
8140
+ min-width: 0;
8141
+ min-height: 0;
8142
+ overflow: auto;
8143
+ }
8144
+
8145
+ .ow-splitter__panel[data-collapsed="hidden"] {
8146
+ visibility: hidden;
8147
+ }
8148
+
8149
+ /* The line is 1px; the area you can catch is 9px. */
8150
+ .ow-splitter__handle {
8151
+ position: relative;
8152
+ flex: none;
8153
+ background: var(--ow-border);
8154
+ outline: none;
8155
+ touch-action: none;
8156
+ transition: background-color var(--ow-duration-fast) var(--ow-ease-standard);
8157
+ }
8158
+
8159
+ .ow-splitter--horizontal > .ow-splitter__handle {
8160
+ width: 1px;
8161
+ cursor: col-resize;
8162
+ }
8163
+
8164
+ .ow-splitter--vertical > .ow-splitter__handle {
8165
+ height: 1px;
8166
+ cursor: row-resize;
8167
+ }
8168
+
8169
+ .ow-splitter__handle::before,
8170
+ .ow-splitter__handle::after {
8171
+ content: "";
8172
+ position: absolute;
8173
+ z-index: 1;
8174
+ }
8175
+
8176
+ .ow-splitter--horizontal > .ow-splitter__handle::before {
8177
+ inset: 0 -4px;
8178
+ }
8179
+
8180
+ .ow-splitter--vertical > .ow-splitter__handle::before {
8181
+ inset: -4px 0;
8182
+ }
8183
+
8184
+ /* The highlight: a 3px bar over the line. */
8185
+ .ow-splitter__handle::after {
8186
+ inset: 0 -1px;
8187
+ border-radius: var(--ow-radius-pill);
8188
+ opacity: 0;
8189
+ background: var(--ow-border-strong);
8190
+ transition: opacity var(--ow-duration-fast) var(--ow-ease-standard);
8191
+ }
8192
+
8193
+ .ow-splitter--vertical > .ow-splitter__handle::after {
8194
+ inset: -1px 0;
8195
+ }
8196
+
8197
+ .ow-splitter__handle:hover::after {
8198
+ opacity: 1;
8199
+ }
8200
+
8201
+ .ow-splitter__handle[data-dragging]::after,
8202
+ .ow-splitter__handle:focus-visible::after {
8203
+ opacity: 1;
8204
+ background: var(--ow-focus-ring);
8205
+ }
8206
+
8207
+ .ow-splitter__handle[aria-disabled] {
8208
+ cursor: default;
8209
+ }
8210
+
8211
+ .ow-splitter__handle[aria-disabled]::after {
8212
+ display: none;
8213
+ }
8214
+
8215
+ /* A grip in the middle of the line. */
8216
+ .ow-splitter__handle--grip::after {
8217
+ inset: 50% auto auto 50%;
8218
+ width: 6px;
8219
+ height: 24px;
8220
+ translate: -50% -50%;
8221
+ opacity: 1;
8222
+ border: 1px solid var(--ow-border-strong);
8223
+ background: var(--ow-surface);
8224
+ box-shadow: var(--ow-shadow-control);
8225
+ }
8226
+
8227
+ .ow-splitter--vertical > .ow-splitter__handle--grip::after {
8228
+ inset: 50% auto auto 50%;
8229
+ width: 24px;
8230
+ height: 6px;
8231
+ }
8232
+
8233
+ .ow-splitter__handle--grip:hover::after {
8234
+ background: var(--ow-surface-muted);
8235
+ }
8236
+
8237
+ .ow-splitter__handle--grip[data-dragging]::after,
8238
+ .ow-splitter__handle--grip:focus-visible::after {
8239
+ border-color: var(--ow-focus-ring);
8240
+ background: var(--ow-surface);
8241
+ box-shadow: 0 0 0 1px var(--ow-focus-ring);
8242
+ }
8243
+
8244
+ /* While dragging, the cursor stays a resize one everywhere and nothing gets selected. */
8245
+ :root[data-ow-splitter-drag],
8246
+ :root[data-ow-splitter-drag] * {
8247
+ user-select: none;
8248
+ -webkit-user-select: none;
8249
+ }
8250
+
8251
+ :root[data-ow-splitter-drag="horizontal"] * {
8252
+ cursor: col-resize !important;
8253
+ }
8254
+
8255
+ :root[data-ow-splitter-drag="vertical"] * {
8256
+ cursor: row-resize !important;
8257
+ }
8258
+
8259
+ @media (prefers-reduced-motion: reduce) {
8260
+ .ow-splitter__handle,
8261
+ .ow-splitter__handle::after {
8262
+ transition: none;
8263
+ }
8264
+ }
8265
+
8266
+ /* components/AspectRatio/AspectRatio.css */
8267
+ /* AspectRatio: a box that keeps its shape, with whatever is inside filling it. The hidden overflow keeps the ratio
8268
+ when the content is taller than the box would be. */
8269
+ .ow-aspect-ratio {
8270
+ position: relative;
8271
+ display: block;
8272
+ box-sizing: border-box;
8273
+ width: 100%;
8274
+ overflow: hidden;
8275
+ }
8276
+
8277
+ .ow-aspect-ratio > * {
8278
+ position: absolute;
8279
+ inset: 0;
8280
+ box-sizing: border-box;
8281
+ width: 100%;
8282
+ height: 100%;
8283
+ }
8284
+
8285
+ .ow-aspect-ratio > :is(img, video, iframe, embed, object, picture, canvas, svg) {
8286
+ border: 0;
8287
+ object-fit: cover;
8288
+ }
8289
+
8290
+ .ow-aspect-ratio > picture > img {
8291
+ width: 100%;
8292
+ height: 100%;
8293
+ object-fit: cover;
8294
+ }
8295
+
6850
8296
  /* components/Marketing/Marketing.css */
6851
8297
  /* Marketing patterns from the site: Chip, SectionHeading, SiteHeader and the dot grid. */
6852
8298
  .ow-chip {