@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
package/dist/styles.css CHANGED
@@ -2086,6 +2086,60 @@
2086
2086
  transform: rotate(180deg);
2087
2087
  }
2088
2088
 
2089
+ /* components/TagInput/TagInput.css */
2090
+ /* TagInput: a grouped field (Input.css) that wraps, with Tags (Tag.css) before the text box, over Select's listbox. */
2091
+ .ow-tag-input {
2092
+ height: auto;
2093
+ min-height: 40px;
2094
+ flex-wrap: wrap;
2095
+ gap: var(--ow-space-2xs);
2096
+ padding: 5px var(--ow-space-sm) 5px 5px;
2097
+ cursor: text;
2098
+ }
2099
+
2100
+ .ow-tag-input.ow-input-group--sm {
2101
+ min-height: 32px;
2102
+ gap: var(--ow-space-2xs);
2103
+ padding: var(--ow-space-2xs) var(--ow-space-xs) var(--ow-space-2xs) var(--ow-space-2xs);
2104
+ }
2105
+
2106
+ .ow-tag-input.ow-input-group--disabled {
2107
+ cursor: not-allowed;
2108
+ }
2109
+
2110
+ /* The list is only for screen readers: its tags sit in the field's own row, beside the text box. */
2111
+ .ow-tag-input__tags {
2112
+ display: contents;
2113
+ margin: 0;
2114
+ padding: 0;
2115
+ list-style: none;
2116
+ }
2117
+
2118
+ /* A tag whose ✕ has focus (after Backspace or the arrow keys) is the one Backspace removes. */
2119
+ .ow-tag-input .ow-tag:has(.ow-tag__remove:focus-visible) {
2120
+ border-color: var(--ow-primary-border);
2121
+ background: var(--ow-primary-subtle);
2122
+ color: var(--ow-primary-text);
2123
+ }
2124
+
2125
+ .ow-tag-input__input {
2126
+ width: auto;
2127
+ min-width: 64px;
2128
+ height: 28px;
2129
+ flex: 1 1 64px;
2130
+ /* With no tags, the text lines up with Input's. */
2131
+ padding-left: 7px;
2132
+ }
2133
+
2134
+ .ow-input-group--sm .ow-tag-input__input {
2135
+ height: 22px;
2136
+ padding-left: var(--ow-space-xs);
2137
+ }
2138
+
2139
+ .ow-tag-input--filled .ow-tag-input__input {
2140
+ padding-left: var(--ow-space-2xs);
2141
+ }
2142
+
2089
2143
  /* components/Checkbox/Checkbox.css */
2090
2144
  /* Checkbox: a native input with its look replaced. */
2091
2145
  .ow-checkbox {
@@ -2570,6 +2624,147 @@
2570
2624
  cursor: not-allowed;
2571
2625
  }
2572
2626
 
2627
+ /* components/Rating/Rating.css */
2628
+ /* Rating: a row of stars. Filled ones are brass (one of the few places it shows), empty ones a quiet grey. */
2629
+ .ow-rating {
2630
+ --ow-rating-size: 20px;
2631
+ display: inline-flex;
2632
+ align-items: center;
2633
+ gap: var(--ow-space-sm);
2634
+ color: var(--ow-text-muted);
2635
+ font-size: 14px;
2636
+ line-height: 1.4;
2637
+ vertical-align: middle;
2638
+ }
2639
+
2640
+ .ow-rating--sm {
2641
+ --ow-rating-size: 16px;
2642
+ gap: var(--ow-space-xs);
2643
+ font-size: 13px;
2644
+ }
2645
+
2646
+ .ow-rating--lg {
2647
+ --ow-rating-size: 24px;
2648
+ }
2649
+
2650
+ .ow-rating__stars {
2651
+ display: inline-flex;
2652
+ border-radius: var(--ow-radius-md);
2653
+ }
2654
+
2655
+ /* Each star is a 24px (or larger) box, so it's a big enough target to tap. */
2656
+ .ow-rating__star {
2657
+ position: relative;
2658
+ display: inline-flex;
2659
+ align-items: center;
2660
+ justify-content: center;
2661
+ min-width: 24px;
2662
+ min-height: 24px;
2663
+ padding: 2px;
2664
+ }
2665
+
2666
+ .ow-rating--readonly .ow-rating__star {
2667
+ min-width: 0;
2668
+ min-height: 0;
2669
+ padding: 1px;
2670
+ }
2671
+
2672
+ .ow-rating__icon {
2673
+ display: block;
2674
+ width: var(--ow-rating-size);
2675
+ height: var(--ow-rating-size);
2676
+ flex-shrink: 0;
2677
+ fill: var(--ow-brass);
2678
+ stroke: var(--ow-brass-deep);
2679
+ }
2680
+
2681
+ .ow-rating__icon--empty {
2682
+ fill: var(--ow-meter-track);
2683
+ stroke: var(--ow-border-hover);
2684
+ }
2685
+
2686
+ .ow-rating__glyph {
2687
+ position: relative;
2688
+ display: block;
2689
+ }
2690
+
2691
+ /* The brass star on top, cut to the filled share of this one. */
2692
+ .ow-rating__fill {
2693
+ position: absolute;
2694
+ inset-block: 0;
2695
+ inset-inline-start: 0;
2696
+ width: var(--ow-rating-fill);
2697
+ overflow: hidden;
2698
+ pointer-events: none;
2699
+ transition: width var(--ow-duration-fast) var(--ow-ease-standard);
2700
+ }
2701
+
2702
+ /* Each radio covers its star (or the start half of it, for a half point) and is drawn by the star. */
2703
+ .ow-rating__input {
2704
+ position: absolute;
2705
+ inset-block: 0;
2706
+ inset-inline-start: 0;
2707
+ width: 100%;
2708
+ margin: 0;
2709
+ appearance: none;
2710
+ opacity: 0;
2711
+ cursor: pointer;
2712
+ }
2713
+
2714
+ .ow-rating__input--half {
2715
+ z-index: 1;
2716
+ width: 50%;
2717
+ }
2718
+
2719
+ .ow-rating__input:disabled {
2720
+ cursor: not-allowed;
2721
+ }
2722
+
2723
+ .ow-rating__stars:has(:focus-visible) {
2724
+ outline: 2px solid var(--ow-focus-ring);
2725
+ outline-offset: 0;
2726
+ }
2727
+
2728
+ .ow-rating__star .ow-rating__glyph {
2729
+ transition: transform var(--ow-duration-base) var(--ow-ease-spring);
2730
+ }
2731
+
2732
+ @media (prefers-reduced-motion: no-preference) {
2733
+ .ow-rating__star:has(.ow-rating__input:hover:not(:disabled)) .ow-rating__glyph,
2734
+ .ow-rating__star:has(.ow-rating__input:focus-visible) .ow-rating__glyph {
2735
+ transform: scale(1.12);
2736
+ }
2737
+
2738
+ .ow-rating__star:has(.ow-rating__input:active:not(:disabled)) .ow-rating__glyph {
2739
+ transform: scale(0.92);
2740
+ }
2741
+ }
2742
+
2743
+ .ow-rating__stars[aria-invalid="true"] .ow-rating__icon--empty {
2744
+ stroke: var(--ow-danger-text);
2745
+ }
2746
+
2747
+ .ow-rating--disabled {
2748
+ opacity: 0.55;
2749
+ }
2750
+
2751
+ .ow-rating__value {
2752
+ color: var(--ow-text);
2753
+ font-weight: var(--ow-weight-emphasis);
2754
+ font-variant-numeric: tabular-nums;
2755
+ }
2756
+
2757
+ .ow-rating__value + .ow-rating__count {
2758
+ margin-inline-start: calc(var(--ow-space-sm) * -0.5);
2759
+ }
2760
+
2761
+ @media (prefers-reduced-motion: reduce) {
2762
+ .ow-rating__fill,
2763
+ .ow-rating__star .ow-rating__glyph {
2764
+ transition: none;
2765
+ }
2766
+ }
2767
+
2573
2768
  /* components/NumberField/NumberField.css */
2574
2769
  /* NumberField: − value + in one field. */
2575
2770
  .ow-number-field {
@@ -3048,6 +3243,199 @@
3048
3243
  color: var(--ow-danger-text);
3049
3244
  }
3050
3245
 
3246
+ /* components/Banner/Banner.css */
3247
+ /* Banner: a bar across the top of the page. Each tone sets the ground, the rule under it and the icon's colour; on
3248
+ narrow bars (its own width, a container query) the action moves under the message. */
3249
+ .ow-banner {
3250
+ --ow-banner-ground: var(--ow-primary);
3251
+ --ow-banner-rule: var(--ow-primary);
3252
+ --ow-banner-icon: var(--ow-on-primary);
3253
+ container: ow-banner / inline-size;
3254
+ display: grid;
3255
+ grid-template-rows: 1fr;
3256
+ border-bottom: 1px solid var(--ow-banner-rule);
3257
+ /* Over the surface, so a translucent dark-theme tint stays solid when the page scrolls under a sticky bar. */
3258
+ background: linear-gradient(var(--ow-banner-ground), var(--ow-banner-ground)) var(--ow-surface);
3259
+ color: var(--ow-text);
3260
+ font-size: 14px;
3261
+ line-height: 1.5;
3262
+ transition-property: grid-template-rows, opacity;
3263
+ transition-duration: var(--ow-duration-exit);
3264
+ transition-timing-function: var(--ow-ease-exit);
3265
+ }
3266
+
3267
+ .ow-banner--sticky {
3268
+ position: sticky;
3269
+ z-index: 10;
3270
+ top: 0;
3271
+ }
3272
+
3273
+ .ow-banner[data-state="closed"] {
3274
+ grid-template-rows: 0fr;
3275
+ opacity: 0;
3276
+ }
3277
+
3278
+ .ow-banner__clip {
3279
+ min-height: 0;
3280
+ }
3281
+
3282
+ .ow-banner[data-state="closed"] .ow-banner__clip {
3283
+ overflow: hidden;
3284
+ }
3285
+
3286
+ .ow-banner__inner {
3287
+ display: flex;
3288
+ align-items: flex-start;
3289
+ gap: var(--ow-space-md);
3290
+ padding: var(--ow-space-md) var(--ow-space-2xl);
3291
+ }
3292
+
3293
+ /* Room on the left as wide as the ✕ on the right, so a centred message sits in the middle of the bar. */
3294
+ .ow-banner--center.ow-banner--dismissible .ow-banner__inner::before {
3295
+ content: "";
3296
+ width: 24px;
3297
+ flex-shrink: 0;
3298
+ }
3299
+
3300
+ .ow-banner__content {
3301
+ display: flex;
3302
+ min-width: 0;
3303
+ flex: 1;
3304
+ gap: var(--ow-space-sm);
3305
+ }
3306
+
3307
+ .ow-banner--center .ow-banner__content {
3308
+ justify-content: center;
3309
+ text-align: center;
3310
+ }
3311
+
3312
+ .ow-banner__icon {
3313
+ display: inline-flex;
3314
+ height: 21px;
3315
+ flex-shrink: 0;
3316
+ align-items: center;
3317
+ color: var(--ow-banner-icon);
3318
+ }
3319
+
3320
+ .ow-banner__text {
3321
+ display: flex;
3322
+ min-width: 0;
3323
+ flex-wrap: wrap;
3324
+ align-items: center;
3325
+ justify-content: inherit;
3326
+ gap: var(--ow-space-2xs) var(--ow-space-lg);
3327
+ }
3328
+
3329
+ .ow-banner__message {
3330
+ min-width: 0;
3331
+ }
3332
+
3333
+ .ow-banner__message > p {
3334
+ margin: 0;
3335
+ }
3336
+
3337
+ /* A small button reaches into the bar's padding, so it doesn't push the message off the icon's line. */
3338
+ .ow-banner__action {
3339
+ display: flex;
3340
+ margin-block: -4px;
3341
+ flex-wrap: wrap;
3342
+ align-items: center;
3343
+ gap: var(--ow-space-sm);
3344
+ font-weight: var(--ow-weight-control);
3345
+ }
3346
+
3347
+ .ow-banner .ow-link,
3348
+ .ow-banner .ow-link:hover {
3349
+ color: inherit;
3350
+ }
3351
+
3352
+ .ow-banner .ow-link:hover {
3353
+ text-decoration-color: currentColor;
3354
+ }
3355
+
3356
+ .ow-banner__close {
3357
+ margin-block: -1px;
3358
+ }
3359
+
3360
+ .ow-banner__close:hover:not(:disabled) {
3361
+ background: color-mix(in srgb, currentColor 12%, transparent);
3362
+ }
3363
+
3364
+ @container ow-banner (max-width: 559px) {
3365
+ .ow-banner .ow-banner__content {
3366
+ justify-content: flex-start;
3367
+ text-align: start;
3368
+ }
3369
+
3370
+ .ow-banner .ow-banner__text {
3371
+ flex-direction: column;
3372
+ align-items: flex-start;
3373
+ }
3374
+
3375
+ .ow-banner .ow-banner__action {
3376
+ margin-block: 0;
3377
+ }
3378
+
3379
+ .ow-banner .ow-banner__inner::before {
3380
+ display: none;
3381
+ }
3382
+ }
3383
+
3384
+ /* Tones */
3385
+
3386
+ .ow-banner--brand {
3387
+ color: var(--ow-on-primary);
3388
+ }
3389
+
3390
+ .ow-banner--brand .ow-link {
3391
+ text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
3392
+ }
3393
+
3394
+ .ow-banner--brand .ow-banner__close,
3395
+ .ow-banner--brand .ow-banner__close:hover:not(:disabled) {
3396
+ color: var(--ow-on-primary);
3397
+ }
3398
+
3399
+ .ow-banner--brand .ow-banner__inner :focus-visible {
3400
+ outline-color: var(--ow-on-primary);
3401
+ }
3402
+
3403
+ .ow-banner--neutral {
3404
+ --ow-banner-ground: var(--ow-surface-muted);
3405
+ --ow-banner-rule: var(--ow-border);
3406
+ --ow-banner-icon: var(--ow-text-muted);
3407
+ }
3408
+
3409
+ .ow-banner--info {
3410
+ --ow-banner-ground: var(--ow-primary-subtle);
3411
+ --ow-banner-rule: var(--ow-primary-border);
3412
+ --ow-banner-icon: var(--ow-primary-text);
3413
+ }
3414
+
3415
+ .ow-banner--success {
3416
+ --ow-banner-ground: var(--ow-success-surface);
3417
+ --ow-banner-rule: var(--ow-success-border);
3418
+ --ow-banner-icon: var(--ow-success-text);
3419
+ }
3420
+
3421
+ .ow-banner--warning {
3422
+ --ow-banner-ground: var(--ow-warning-surface);
3423
+ --ow-banner-rule: var(--ow-warning-border);
3424
+ --ow-banner-icon: var(--ow-warning-text);
3425
+ }
3426
+
3427
+ .ow-banner--danger {
3428
+ --ow-banner-ground: var(--ow-danger-surface);
3429
+ --ow-banner-rule: var(--ow-danger-border);
3430
+ --ow-banner-icon: var(--ow-danger-text);
3431
+ }
3432
+
3433
+ @media (prefers-reduced-motion: reduce) {
3434
+ .ow-banner {
3435
+ transition: none;
3436
+ }
3437
+ }
3438
+
3051
3439
  /* components/Progress/Progress.css */
3052
3440
  /* ProgressBar and ProgressCircle. The fill is ow-progress; tones swap in a status colour. */
3053
3441
  .ow-progress {
@@ -3262,20 +3650,152 @@
3262
3650
  }
3263
3651
  }
3264
3652
 
3265
- /* components/Tooltip/Tooltip.css */
3266
- /* 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). */
3267
- .ow-tooltip {
3268
- display: inline-flex;
3653
+ /* components/PasswordInput/PasswordInput.css */
3654
+ /* PasswordInput: an Input group with a show and hide button at the end, and an optional strength meter and checklist under it. */
3655
+ .ow-password-input {
3656
+ display: grid;
3657
+ width: 100%;
3658
+ min-width: 0;
3659
+ gap: var(--ow-space-sm);
3269
3660
  }
3270
3661
 
3271
- .ow-tooltip__bubble {
3272
- z-index: 70;
3273
- max-width: 240px;
3274
- overflow: visible;
3662
+ /* The show and hide button: CloseButton's quiet square, a size down so it sits inside the field. */
3663
+ .ow-password-input__toggle {
3664
+ display: inline-flex;
3665
+ width: 28px;
3666
+ height: 28px;
3667
+ flex-shrink: 0;
3668
+ align-items: center;
3669
+ justify-content: center;
3670
+ margin: 0;
3275
3671
  border: 0;
3276
3672
  border-radius: var(--ow-radius-md);
3277
- background: var(--ow-tooltip);
3278
- padding: var(--ow-space-2xs) var(--ow-space-sm);
3673
+ background: transparent;
3674
+ padding: 0;
3675
+ color: var(--ow-icon);
3676
+ cursor: pointer;
3677
+ transition-property: color, background-color;
3678
+ transition-duration: var(--ow-duration-base);
3679
+ transition-timing-function: var(--ow-ease-standard);
3680
+ }
3681
+
3682
+ .ow-password-input__toggle--sm {
3683
+ width: 24px;
3684
+ height: 24px;
3685
+ }
3686
+
3687
+ .ow-password-input__toggle:hover:not(:disabled) {
3688
+ background: var(--ow-surface-muted);
3689
+ color: var(--ow-text);
3690
+ }
3691
+
3692
+ .ow-password-input__toggle:focus-visible {
3693
+ outline: 2px solid var(--ow-focus-ring);
3694
+ outline-offset: 1px;
3695
+ }
3696
+
3697
+ .ow-password-input__toggle:disabled {
3698
+ cursor: not-allowed;
3699
+ }
3700
+
3701
+ /* The strength line: the meter's blocks, then "Password strength: Good", the word in the meter's colour. */
3702
+ .ow-password-input__strength {
3703
+ display: grid;
3704
+ gap: var(--ow-space-xs);
3705
+ }
3706
+
3707
+ .ow-password-input__strength-text {
3708
+ min-height: 1.45em;
3709
+ margin: 0;
3710
+ color: var(--ow-text-muted);
3711
+ font-size: 13px;
3712
+ line-height: 1.45;
3713
+ }
3714
+
3715
+ .ow-password-input__strength-word {
3716
+ color: var(--ow-text);
3717
+ font-weight: var(--ow-weight-emphasis);
3718
+ transition: color var(--ow-duration-base) var(--ow-ease-standard);
3719
+ }
3720
+
3721
+ .ow-password-input__strength--danger .ow-password-input__strength-word {
3722
+ color: var(--ow-danger-text);
3723
+ }
3724
+
3725
+ .ow-password-input__strength--warning .ow-password-input__strength-word {
3726
+ color: var(--ow-warning-text);
3727
+ }
3728
+
3729
+ .ow-password-input__strength--success .ow-password-input__strength-word {
3730
+ color: var(--ow-success-text);
3731
+ }
3732
+
3733
+ /* The checklist: a ring for each rule, filled with a tick once it's met. */
3734
+ .ow-password-input__requirements {
3735
+ display: grid;
3736
+ gap: var(--ow-space-2xs);
3737
+ margin: 0;
3738
+ padding: 0;
3739
+ list-style: none;
3740
+ }
3741
+
3742
+ .ow-password-input__requirement {
3743
+ display: flex;
3744
+ align-items: center;
3745
+ gap: var(--ow-space-sm);
3746
+ color: var(--ow-text-muted);
3747
+ font-size: 13px;
3748
+ line-height: 1.45;
3749
+ transition: color var(--ow-duration-base) var(--ow-ease-standard);
3750
+ }
3751
+
3752
+ .ow-password-input__mark {
3753
+ display: inline-flex;
3754
+ box-sizing: border-box;
3755
+ width: 16px;
3756
+ height: 16px;
3757
+ flex-shrink: 0;
3758
+ align-items: center;
3759
+ justify-content: center;
3760
+ border: 1.5px solid var(--ow-border-strong);
3761
+ border-radius: var(--ow-radius-pill);
3762
+ color: var(--ow-success-text);
3763
+ transition-property: border-color, background-color;
3764
+ transition-duration: var(--ow-duration-base);
3765
+ transition-timing-function: var(--ow-ease-standard);
3766
+ }
3767
+
3768
+ .ow-password-input__requirement--met {
3769
+ color: var(--ow-text);
3770
+ }
3771
+
3772
+ .ow-password-input__requirement--met .ow-password-input__mark {
3773
+ border-color: var(--ow-success-text);
3774
+ }
3775
+
3776
+ @media (prefers-reduced-motion: reduce) {
3777
+ .ow-password-input__toggle,
3778
+ .ow-password-input__strength-word,
3779
+ .ow-password-input__requirement,
3780
+ .ow-password-input__mark {
3781
+ transition: none;
3782
+ }
3783
+ }
3784
+
3785
+ /* components/Tooltip/Tooltip.css */
3786
+ /* 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). */
3787
+ .ow-tooltip {
3788
+ display: inline-flex;
3789
+ }
3790
+
3791
+ .ow-tooltip__bubble {
3792
+ z-index: 70;
3793
+ max-width: 240px;
3794
+ overflow: visible;
3795
+ border: 0;
3796
+ border-radius: var(--ow-radius-md);
3797
+ background: var(--ow-tooltip);
3798
+ padding: var(--ow-space-2xs) var(--ow-space-sm);
3279
3799
  color: var(--ow-on-tooltip);
3280
3800
  font-family: var(--ow-font-sans);
3281
3801
  font-size: 12px;
@@ -3809,6 +4329,172 @@
3809
4329
  line-height: 1.3;
3810
4330
  }
3811
4331
 
4332
+ /* components/Tour/Tour.css */
4333
+ /* Tour and Coachmark: a popover-like card beside each step's target, over an optional spotlight that dims the
4334
+ rest of the page. Both sit in the top layer, the spotlight first. */
4335
+ .ow-tour {
4336
+ z-index: 60;
4337
+ display: grid;
4338
+ gap: var(--ow-space-md);
4339
+ max-width: calc(100vw - 16px);
4340
+ overflow: auto;
4341
+ border: 1px solid var(--ow-border);
4342
+ border-radius: var(--ow-radius-container);
4343
+ background: var(--ow-surface);
4344
+ padding: var(--ow-space-xl) var(--ow-space-xl) var(--ow-space-lg);
4345
+ color: var(--ow-text);
4346
+ font-family: var(--ow-font-sans);
4347
+ font-size: 14px;
4348
+ line-height: 1.45;
4349
+ box-shadow: var(--ow-shadow-menu);
4350
+ outline: none;
4351
+ }
4352
+
4353
+ /* A step without a target: in the middle of the window, where the browser puts a popover. */
4354
+ .ow-tour--centred {
4355
+ position: fixed;
4356
+ inset: 0;
4357
+ height: fit-content;
4358
+ max-height: calc(100dvh - 32px);
4359
+ margin: auto;
4360
+ }
4361
+
4362
+ .ow-tour > * {
4363
+ min-width: 0;
4364
+ }
4365
+
4366
+ .ow-tour__header {
4367
+ display: flex;
4368
+ align-items: flex-start;
4369
+ justify-content: space-between;
4370
+ gap: var(--ow-space-sm);
4371
+ }
4372
+
4373
+ .ow-tour__title {
4374
+ padding-top: 2px;
4375
+ font-size: 14px;
4376
+ font-weight: var(--ow-weight-emphasis);
4377
+ line-height: 1.3;
4378
+ }
4379
+
4380
+ .ow-tour__header .ow-close-button {
4381
+ flex-shrink: 0;
4382
+ margin: -2px -4px 0 0;
4383
+ }
4384
+
4385
+ .ow-tour__content {
4386
+ color: var(--ow-text-muted);
4387
+ }
4388
+
4389
+ .ow-tour__content > p {
4390
+ margin: 0;
4391
+ }
4392
+
4393
+ .ow-tour__footer {
4394
+ display: flex;
4395
+ flex-wrap: wrap;
4396
+ align-items: center;
4397
+ gap: var(--ow-space-sm);
4398
+ margin-top: var(--ow-space-2xs);
4399
+ }
4400
+
4401
+ .ow-tour__progress {
4402
+ color: var(--ow-text-muted);
4403
+ font-size: 13px;
4404
+ font-variant-numeric: tabular-nums;
4405
+ }
4406
+
4407
+ .ow-tour__actions {
4408
+ display: flex;
4409
+ gap: var(--ow-space-sm);
4410
+ margin-left: auto;
4411
+ }
4412
+
4413
+ /* The spotlight: the whole window, in the top layer under the card. It only dims: clicks go through to the page. */
4414
+ .ow-tour-spotlight {
4415
+ position: fixed;
4416
+ inset: 0;
4417
+ width: auto;
4418
+ height: auto;
4419
+ margin: 0;
4420
+ overflow: hidden;
4421
+ border: 0;
4422
+ background: transparent;
4423
+ padding: 0;
4424
+ pointer-events: none;
4425
+ }
4426
+
4427
+ .ow-tour-spotlight[data-state="open"] {
4428
+ animation: ow-tour-fade-in var(--ow-duration-slow) var(--ow-ease-standard);
4429
+ }
4430
+
4431
+ .ow-tour-spotlight[data-state="closed"] {
4432
+ animation: ow-tour-fade-out var(--ow-duration-exit) var(--ow-ease-exit) forwards;
4433
+ }
4434
+
4435
+ /* The hole over the target: a rounded box whose shadow covers everything else. */
4436
+ .ow-tour-spotlight__hole {
4437
+ position: absolute;
4438
+ border-radius: var(--ow-radius-tile);
4439
+ box-shadow: 0 0 0 200vmax var(--ow-backdrop);
4440
+ }
4441
+
4442
+ .ow-tour-spotlight__hole[data-moving] {
4443
+ transition-duration: var(--ow-duration-panel);
4444
+ transition-property: top, left, width, height;
4445
+ transition-timing-function: var(--ow-ease-emphasized);
4446
+ }
4447
+
4448
+ .ow-tour-spotlight__dim {
4449
+ position: absolute;
4450
+ inset: 0;
4451
+ background: var(--ow-backdrop);
4452
+ }
4453
+
4454
+ @keyframes ow-tour-fade-in {
4455
+ from {
4456
+ opacity: 0;
4457
+ }
4458
+ }
4459
+
4460
+ @keyframes ow-tour-fade-out {
4461
+ to {
4462
+ opacity: 0;
4463
+ }
4464
+ }
4465
+
4466
+ @media (prefers-reduced-motion: reduce) {
4467
+ .ow-tour-spotlight__hole[data-moving] {
4468
+ transition: none;
4469
+ }
4470
+ }
4471
+
4472
+ /* components/HoverCard/HoverCard.css */
4473
+ /* HoverCard: Popover's surface, opened by resting the pointer on (or tabbing to) its trigger. */
4474
+ .ow-hover-card-anchor {
4475
+ display: inline-flex;
4476
+ }
4477
+
4478
+ .ow-hover-card {
4479
+ z-index: 60;
4480
+ display: grid;
4481
+ gap: var(--ow-space-md);
4482
+ overflow: auto;
4483
+ border: 1px solid var(--ow-border);
4484
+ border-radius: var(--ow-radius-container);
4485
+ background: var(--ow-surface);
4486
+ padding: var(--ow-space-lg);
4487
+ color: var(--ow-text);
4488
+ font-family: var(--ow-font-sans);
4489
+ font-size: 14px;
4490
+ line-height: 1.45;
4491
+ box-shadow: var(--ow-shadow-menu);
4492
+ }
4493
+
4494
+ .ow-hover-card > * {
4495
+ min-width: 0;
4496
+ }
4497
+
3812
4498
  /* components/Calendar/Calendar.css */
3813
4499
  /* Calendar: a quiet month grid. The chosen day is filled with the primary colour; today has a brass dot. */
3814
4500
  .ow-calendar {
@@ -4950,6 +5636,14 @@
4950
5636
  background: var(--ow-border);
4951
5637
  }
4952
5638
 
5639
+ /* components/ContextMenu/ContextMenu.css */
5640
+ /* ContextMenu: the wrapper adds no box of its own; the panel is Menu's (.ow-menu__panel), opened at the pointer. */
5641
+ .ow-context-menu {
5642
+ display: contents;
5643
+ /* A long press opens the menu, not the browser's callout. */
5644
+ -webkit-touch-callout: none;
5645
+ }
5646
+
4953
5647
  /* components/Accordion/Accordion.css */
4954
5648
  /* Disclosure and Accordion: a header with a chevron that turns as the panel opens. */
4955
5649
  .ow-disclosure,
@@ -5442,35 +6136,253 @@
5442
6136
  }
5443
6137
  }
5444
6138
 
5445
- /* components/ChoiceCard/ChoiceCard.css */
5446
- /* ChoiceCard: a tactile card-button with an icon tile, a title and one line of description. */
5447
- .ow-choice {
6139
+ /* components/Timeline/Timeline.css */
6140
+ /* Timeline: events down a 1px line. Each item draws the line above its marker (::before) and below it (::after), so
6141
+ the line stops a few pixels short of every marker, whatever its size, and can turn dashed around a pending item. */
6142
+ .ow-timeline {
6143
+ --ow-timeline-marker: 28px;
6144
+ --ow-timeline-dot: 10px;
6145
+ --ow-timeline-space: var(--ow-space-5xl);
6146
+ --ow-timeline-line: var(--ow-border-strong);
6147
+
5448
6148
  display: grid;
5449
- align-content: start;
5450
- gap: var(--ow-space-lg);
5451
6149
  margin: 0;
5452
- border: 1px solid var(--ow-border-strong);
5453
- border-radius: var(--ow-radius-container);
5454
- background-color: var(--ow-control);
5455
- background-image: linear-gradient(to bottom, var(--ow-control), var(--ow-control-shade));
5456
- padding: var(--ow-space-2xl);
5457
- color: var(--ow-text);
5458
- font: inherit;
5459
- text-align: left;
5460
- cursor: pointer;
5461
- box-shadow: var(--ow-shadow-button-secondary);
5462
- transition-property: transform, border-color, color, background-color, box-shadow, opacity;
5463
- transition-duration: var(--ow-duration-base);
5464
- transition-timing-function: var(--ow-ease-standard);
6150
+ padding: 0;
6151
+ list-style: none;
5465
6152
  }
5466
6153
 
5467
- .ow-choice--recommended {
5468
- border-color: var(--ow-primary-border);
6154
+ .ow-timeline--compact {
6155
+ --ow-timeline-marker: 24px;
6156
+ --ow-timeline-dot: 8px;
6157
+ --ow-timeline-space: var(--ow-space-xl);
5469
6158
  }
5470
6159
 
5471
- .ow-choice:hover:not(:disabled),
5472
- .ow-choice:focus-visible {
5473
- border-color: var(--ow-primary-text);
6160
+ .ow-timeline__item {
6161
+ /* Half of what shows of the marker, plus the gap to the line. */
6162
+ --ow-timeline-reach: calc(var(--ow-timeline-marker) / 2 + 4px);
6163
+ --ow-timeline-pad: var(--ow-timeline-space);
6164
+
6165
+ position: relative;
6166
+ display: grid;
6167
+ grid-template-columns: var(--ow-timeline-marker) minmax(0, 1fr);
6168
+ column-gap: var(--ow-space-lg);
6169
+ padding-top: var(--ow-timeline-pad);
6170
+ }
6171
+
6172
+ .ow-timeline__item:first-child {
6173
+ --ow-timeline-pad: 0px;
6174
+ }
6175
+
6176
+ .ow-timeline__item--dot {
6177
+ --ow-timeline-reach: calc(var(--ow-timeline-dot) / 2 + 4px);
6178
+ }
6179
+
6180
+ .ow-timeline__item::before,
6181
+ .ow-timeline__item::after {
6182
+ content: "";
6183
+ position: absolute;
6184
+ left: calc(var(--ow-timeline-marker) / 2 - 0.5px);
6185
+ border-left: 1px solid var(--ow-timeline-line);
6186
+ }
6187
+
6188
+ /* From the item's top edge down to just above its marker. */
6189
+ .ow-timeline__item:not(:first-child)::before {
6190
+ top: 0;
6191
+ height: max(0px, calc(var(--ow-timeline-pad) + var(--ow-timeline-marker) / 2 - var(--ow-timeline-reach)));
6192
+ }
6193
+
6194
+ /* From just below the marker to the item's bottom edge, where the next item's line takes over. */
6195
+ .ow-timeline__item:not(:last-child)::after {
6196
+ top: calc(var(--ow-timeline-pad) + var(--ow-timeline-marker) / 2 + var(--ow-timeline-reach));
6197
+ bottom: 0;
6198
+ }
6199
+
6200
+ /* The way to and from something that hasn't happened yet is dashed. */
6201
+ .ow-timeline__item--pending::before,
6202
+ .ow-timeline__item--pending::after,
6203
+ .ow-timeline__item:has(+ .ow-timeline__item--pending)::after {
6204
+ border-left-style: dashed;
6205
+ }
6206
+
6207
+ .ow-timeline__marker {
6208
+ display: flex;
6209
+ width: var(--ow-timeline-marker);
6210
+ height: var(--ow-timeline-marker);
6211
+ align-items: center;
6212
+ justify-content: center;
6213
+ }
6214
+
6215
+ .ow-timeline__dot {
6216
+ width: var(--ow-timeline-dot);
6217
+ height: var(--ow-timeline-dot);
6218
+ box-sizing: border-box;
6219
+ border: 2px solid var(--ow-timeline-solid, var(--ow-border-strong));
6220
+ border-radius: 50%;
6221
+ background: var(--ow-timeline-solid, var(--ow-border-strong));
6222
+ }
6223
+
6224
+ .ow-timeline__item--icon .ow-timeline__marker {
6225
+ box-sizing: border-box;
6226
+ border: 1px solid var(--ow-timeline-border, var(--ow-border));
6227
+ border-radius: 50%;
6228
+ background: var(--ow-timeline-surface, var(--ow-surface-muted));
6229
+ color: var(--ow-timeline-text, var(--ow-icon));
6230
+ }
6231
+
6232
+ .ow-timeline__item--brand {
6233
+ --ow-timeline-solid: var(--ow-primary);
6234
+ --ow-timeline-border: var(--ow-primary-border);
6235
+ --ow-timeline-surface: var(--ow-primary-subtle);
6236
+ --ow-timeline-text: var(--ow-primary-text);
6237
+ }
6238
+
6239
+ .ow-timeline__item--success {
6240
+ --ow-timeline-solid: var(--ow-success-solid);
6241
+ --ow-timeline-border: var(--ow-success-border);
6242
+ --ow-timeline-surface: var(--ow-success-surface);
6243
+ --ow-timeline-text: var(--ow-success-text);
6244
+ }
6245
+
6246
+ .ow-timeline__item--warning {
6247
+ --ow-timeline-solid: var(--ow-warning-solid);
6248
+ --ow-timeline-border: var(--ow-warning-border);
6249
+ --ow-timeline-surface: var(--ow-warning-surface);
6250
+ --ow-timeline-text: var(--ow-warning-text);
6251
+ }
6252
+
6253
+ .ow-timeline__item--danger {
6254
+ --ow-timeline-solid: var(--ow-danger-solid);
6255
+ --ow-timeline-border: var(--ow-danger-border);
6256
+ --ow-timeline-surface: var(--ow-danger-surface);
6257
+ --ow-timeline-text: var(--ow-danger-text);
6258
+ }
6259
+
6260
+ /* Pending: a hollow marker, drawn with a dashed edge when it's an icon's circle. */
6261
+ .ow-timeline__item--pending .ow-timeline__dot {
6262
+ background: transparent;
6263
+ }
6264
+
6265
+ .ow-timeline__item--pending.ow-timeline__item--icon .ow-timeline__marker {
6266
+ border-style: dashed;
6267
+ border-color: var(--ow-border-strong);
6268
+ background: transparent;
6269
+ color: var(--ow-text-muted);
6270
+ }
6271
+
6272
+ .ow-timeline__content {
6273
+ display: grid;
6274
+ min-width: 0;
6275
+ align-content: start;
6276
+ gap: var(--ow-space-xs);
6277
+ /* Centres the first line (20px) on the marker. */
6278
+ padding-top: calc((var(--ow-timeline-marker) - 20px) / 2);
6279
+ }
6280
+
6281
+ .ow-timeline__header {
6282
+ display: flex;
6283
+ flex-wrap: wrap;
6284
+ align-items: baseline;
6285
+ gap: var(--ow-space-2xs) var(--ow-space-md);
6286
+ font-size: 14px;
6287
+ line-height: 20px;
6288
+ }
6289
+
6290
+ .ow-timeline__title {
6291
+ min-width: 0;
6292
+ flex: 1 1 auto;
6293
+ color: var(--ow-text);
6294
+ font-weight: var(--ow-weight-emphasis);
6295
+ }
6296
+
6297
+ .ow-timeline__separator {
6298
+ display: none;
6299
+ }
6300
+
6301
+ .ow-timeline__time {
6302
+ color: var(--ow-text-muted);
6303
+ font-size: 12px;
6304
+ font-variant-numeric: tabular-nums;
6305
+ white-space: nowrap;
6306
+ }
6307
+
6308
+ .ow-timeline__item--pending .ow-timeline__title {
6309
+ color: var(--ow-text-muted);
6310
+ }
6311
+
6312
+ .ow-timeline__body {
6313
+ min-width: 0;
6314
+ color: var(--ow-text-soft);
6315
+ font-size: 14px;
6316
+ line-height: 1.5;
6317
+ }
6318
+
6319
+ .ow-timeline__body > p {
6320
+ margin: 0;
6321
+ }
6322
+
6323
+ /* Compact: one sentence with the time after it, in the flow of the text. */
6324
+ .ow-timeline--compact .ow-timeline__header {
6325
+ display: block;
6326
+ }
6327
+
6328
+ .ow-timeline--compact .ow-timeline__title {
6329
+ color: var(--ow-text-soft);
6330
+ font-weight: var(--ow-weight-regular);
6331
+ }
6332
+
6333
+ .ow-timeline--compact .ow-timeline__title :is(strong, b) {
6334
+ color: var(--ow-text);
6335
+ font-weight: var(--ow-weight-emphasis);
6336
+ }
6337
+
6338
+ .ow-timeline--compact .ow-timeline__separator {
6339
+ display: inline;
6340
+ margin-inline: var(--ow-space-xs);
6341
+ color: var(--ow-text-muted);
6342
+ }
6343
+
6344
+ .ow-timeline--compact .ow-timeline__time {
6345
+ font-size: 13px;
6346
+ }
6347
+
6348
+ .ow-timeline--compact .ow-timeline__content {
6349
+ gap: var(--ow-space-2xs);
6350
+ }
6351
+
6352
+ .ow-timeline--compact .ow-timeline__body {
6353
+ color: var(--ow-text-muted);
6354
+ font-size: 13px;
6355
+ }
6356
+
6357
+ /* components/ChoiceCard/ChoiceCard.css */
6358
+ /* ChoiceCard: a tactile card-button with an icon tile, a title and one line of description. */
6359
+ .ow-choice {
6360
+ display: grid;
6361
+ align-content: start;
6362
+ gap: var(--ow-space-lg);
6363
+ margin: 0;
6364
+ border: 1px solid var(--ow-border-strong);
6365
+ border-radius: var(--ow-radius-container);
6366
+ background-color: var(--ow-control);
6367
+ background-image: linear-gradient(to bottom, var(--ow-control), var(--ow-control-shade));
6368
+ padding: var(--ow-space-2xl);
6369
+ color: var(--ow-text);
6370
+ font: inherit;
6371
+ text-align: left;
6372
+ cursor: pointer;
6373
+ box-shadow: var(--ow-shadow-button-secondary);
6374
+ transition-property: transform, border-color, color, background-color, box-shadow, opacity;
6375
+ transition-duration: var(--ow-duration-base);
6376
+ transition-timing-function: var(--ow-ease-standard);
6377
+ }
6378
+
6379
+ .ow-choice--recommended {
6380
+ border-color: var(--ow-primary-border);
6381
+ }
6382
+
6383
+ .ow-choice:hover:not(:disabled),
6384
+ .ow-choice:focus-visible {
6385
+ border-color: var(--ow-primary-text);
5474
6386
  }
5475
6387
 
5476
6388
  .ow-choice:focus-visible {
@@ -5669,6 +6581,86 @@
5669
6581
  white-space: nowrap;
5670
6582
  }
5671
6583
 
6584
+ /* components/Image/Image.css */
6585
+ /* 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
6586
+ AspectRatio and the image fills it. */
6587
+ .ow-image {
6588
+ position: relative;
6589
+ display: inline-block;
6590
+ max-width: 100%;
6591
+ overflow: hidden;
6592
+ vertical-align: top;
6593
+ }
6594
+
6595
+ .ow-image.ow-aspect-ratio {
6596
+ display: block;
6597
+ }
6598
+
6599
+ .ow-image__img {
6600
+ display: block;
6601
+ max-width: 100%;
6602
+ transition: opacity var(--ow-duration-base) var(--ow-ease-standard);
6603
+ }
6604
+
6605
+ .ow-image--cover .ow-image__img {
6606
+ object-fit: cover;
6607
+ }
6608
+
6609
+ .ow-image--contain .ow-image__img {
6610
+ object-fit: contain;
6611
+ }
6612
+
6613
+ .ow-image--radius-control {
6614
+ border-radius: var(--ow-radius-form);
6615
+ }
6616
+
6617
+ .ow-image--radius-container {
6618
+ border-radius: var(--ow-radius-container);
6619
+ }
6620
+
6621
+ /* Loading: the Skeleton's grey and pulse, with the image hidden until it's ready. */
6622
+ .ow-image--loading {
6623
+ background: var(--ow-skeleton);
6624
+ animation: ow-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
6625
+ }
6626
+
6627
+ .ow-image--loading .ow-image__img {
6628
+ opacity: 0;
6629
+ }
6630
+
6631
+ .ow-image__fallback {
6632
+ display: flex;
6633
+ box-sizing: border-box;
6634
+ min-width: 64px;
6635
+ max-width: 100%;
6636
+ min-height: 64px;
6637
+ align-items: center;
6638
+ justify-content: center;
6639
+ }
6640
+
6641
+ .ow-image__fallback--default {
6642
+ background: var(--ow-skeleton-soft);
6643
+ color: var(--ow-icon);
6644
+ }
6645
+
6646
+ .ow-image-figure {
6647
+ display: grid;
6648
+ margin: 0;
6649
+ gap: var(--ow-space-sm);
6650
+ justify-items: start;
6651
+ }
6652
+
6653
+ .ow-image-figure > .ow-aspect-ratio {
6654
+ justify-self: stretch;
6655
+ }
6656
+
6657
+ .ow-image-figure__caption {
6658
+ color: var(--ow-text-muted);
6659
+ font-family: var(--ow-font-sans);
6660
+ font-size: 13px;
6661
+ line-height: 1.4;
6662
+ }
6663
+
5672
6664
  /* components/Kbd/Kbd.css */
5673
6665
  /* Kbd and inline Code, both in the mono face. */
5674
6666
  .ow-kbd {
@@ -6354,6 +7346,287 @@
6354
7346
  transform: translate(-50%, -50%);
6355
7347
  }
6356
7348
 
7349
+ /* components/Carousel/Carousel.css */
7350
+ /* Carousel: a row of slides on the browser's own scroll-snap, with round buttons on the edges and dots below. */
7351
+ .ow-carousel {
7352
+ --ow-carousel-per-view: 1;
7353
+ --ow-carousel-gap: var(--ow-space-md);
7354
+ --ow-carousel-arrow: 32px;
7355
+ display: flex;
7356
+ min-width: 0;
7357
+ flex-direction: column;
7358
+ gap: var(--ow-space-md);
7359
+ }
7360
+
7361
+ .ow-carousel__viewport {
7362
+ position: relative;
7363
+ container-type: inline-size;
7364
+ }
7365
+
7366
+ .ow-carousel--arrows-outside .ow-carousel__viewport {
7367
+ margin-inline: calc(var(--ow-carousel-arrow) + var(--ow-space-sm));
7368
+ }
7369
+
7370
+ .ow-carousel__track {
7371
+ --ow-carousel-slide: calc((100cqi - (var(--ow-carousel-per-view) - 1) * var(--ow-carousel-gap)) / var(--ow-carousel-per-view));
7372
+ display: flex;
7373
+ gap: var(--ow-carousel-gap);
7374
+ overflow-x: auto;
7375
+ overscroll-behavior-x: contain;
7376
+ border-radius: var(--ow-radius-container);
7377
+ scroll-snap-type: x mandatory;
7378
+ scrollbar-width: none;
7379
+ }
7380
+
7381
+ .ow-carousel__track::-webkit-scrollbar {
7382
+ display: none;
7383
+ }
7384
+
7385
+ .ow-carousel--center .ow-carousel__track {
7386
+ padding-inline: calc((100cqi - var(--ow-carousel-slide)) / 2);
7387
+ }
7388
+
7389
+ .ow-carousel__track:focus-visible {
7390
+ outline: 2px solid var(--ow-focus-ring);
7391
+ outline-offset: 2px;
7392
+ }
7393
+
7394
+ .ow-carousel__slide {
7395
+ flex: 0 0 var(--ow-carousel-slide);
7396
+ min-width: 0;
7397
+ scroll-snap-align: start;
7398
+ }
7399
+
7400
+ .ow-carousel--center .ow-carousel__slide {
7401
+ scroll-snap-align: center;
7402
+ }
7403
+
7404
+ .ow-carousel__arrow,
7405
+ .ow-carousel__play {
7406
+ position: absolute;
7407
+ z-index: 1;
7408
+ border-radius: 50%;
7409
+ }
7410
+
7411
+ .ow-carousel__arrow {
7412
+ top: 50%;
7413
+ translate: 0 -50%;
7414
+ }
7415
+
7416
+ .ow-carousel__arrow--previous {
7417
+ left: var(--ow-space-sm);
7418
+ }
7419
+
7420
+ .ow-carousel__arrow--next {
7421
+ right: var(--ow-space-sm);
7422
+ }
7423
+
7424
+ .ow-carousel--arrows-outside .ow-carousel__arrow--previous {
7425
+ left: calc(-1 * (var(--ow-carousel-arrow) + var(--ow-space-sm)));
7426
+ }
7427
+
7428
+ .ow-carousel--arrows-outside .ow-carousel__arrow--next {
7429
+ right: calc(-1 * (var(--ow-carousel-arrow) + var(--ow-space-sm)));
7430
+ }
7431
+
7432
+ /* On the slides, a button with nowhere to go gets out of the way. */
7433
+ .ow-carousel--arrows-overlay .ow-carousel__arrow:disabled {
7434
+ opacity: 0;
7435
+ pointer-events: none;
7436
+ }
7437
+
7438
+ .ow-carousel__play {
7439
+ right: var(--ow-space-sm);
7440
+ bottom: var(--ow-space-sm);
7441
+ }
7442
+
7443
+ .ow-carousel__dots {
7444
+ display: flex;
7445
+ flex-wrap: wrap;
7446
+ justify-content: center;
7447
+ }
7448
+
7449
+ /* A 24px target around a small dot; the current one stretches into a pill in the primary colour. */
7450
+ .ow-carousel__dot {
7451
+ display: inline-flex;
7452
+ width: 24px;
7453
+ height: 24px;
7454
+ align-items: center;
7455
+ justify-content: center;
7456
+ margin: 0;
7457
+ border: 0;
7458
+ border-radius: 999px;
7459
+ background: none;
7460
+ padding: 0;
7461
+ cursor: pointer;
7462
+ }
7463
+
7464
+ .ow-carousel__dot::before {
7465
+ width: 8px;
7466
+ height: 8px;
7467
+ border-radius: 999px;
7468
+ background: var(--ow-text-muted);
7469
+ content: "";
7470
+ transition-property: width, background-color;
7471
+ transition-duration: var(--ow-duration-base);
7472
+ transition-timing-function: var(--ow-ease-standard);
7473
+ }
7474
+
7475
+ .ow-carousel__dot:hover::before {
7476
+ background: var(--ow-text-soft);
7477
+ }
7478
+
7479
+ .ow-carousel__dot[aria-current="true"]::before {
7480
+ width: 20px;
7481
+ background: var(--ow-primary);
7482
+ }
7483
+
7484
+ .ow-carousel__dot[aria-current="true"] {
7485
+ width: 32px;
7486
+ }
7487
+
7488
+ .ow-carousel__dot:focus-visible {
7489
+ outline: 2px solid var(--ow-focus-ring);
7490
+ outline-offset: -2px;
7491
+ }
7492
+
7493
+ /* components/DescriptionList/DescriptionList.css */
7494
+ /* DescriptionList: terms and their values in a <dl>. Its own width decides the layout (a container query), so it
7495
+ stacks in a narrow card or panel as well as on a phone. */
7496
+ .ow-description-list {
7497
+ container: ow-description-list / inline-size;
7498
+ display: grid;
7499
+ margin: 0;
7500
+ color: var(--ow-text);
7501
+ font-size: 14px;
7502
+ line-height: 1.5;
7503
+ }
7504
+
7505
+ .ow-description-item {
7506
+ display: grid;
7507
+ min-width: 0;
7508
+ align-content: start;
7509
+ gap: var(--ow-space-2xs);
7510
+ padding-block: var(--ow-space-lg);
7511
+ }
7512
+
7513
+ .ow-description-list--compact .ow-description-item {
7514
+ padding-block: var(--ow-space-sm);
7515
+ }
7516
+
7517
+ .ow-description-item__term {
7518
+ color: var(--ow-text-muted);
7519
+ }
7520
+
7521
+ .ow-description-item__value {
7522
+ min-width: 0;
7523
+ margin: 0;
7524
+ overflow-wrap: anywhere;
7525
+ }
7526
+
7527
+ .ow-description-item__value--action {
7528
+ display: flex;
7529
+ align-items: center;
7530
+ gap: var(--ow-space-lg);
7531
+ }
7532
+
7533
+ .ow-description-item__content {
7534
+ min-width: 0;
7535
+ flex: 1;
7536
+ }
7537
+
7538
+ .ow-description-item__action {
7539
+ display: flex;
7540
+ flex-shrink: 0;
7541
+ align-items: center;
7542
+ gap: var(--ow-space-2xs);
7543
+ margin-block: -4px;
7544
+ }
7545
+
7546
+ /* Horizontal and vertical: one pair under another, without space past the first and last. */
7547
+ .ow-description-list:not(.ow-description-list--grid) > .ow-description-item:first-child {
7548
+ padding-top: 0;
7549
+ }
7550
+
7551
+ .ow-description-list:not(.ow-description-list--grid) > .ow-description-item:last-child {
7552
+ padding-bottom: 0;
7553
+ }
7554
+
7555
+ .ow-description-list--divided:not(.ow-description-list--grid) > .ow-description-item + .ow-description-item {
7556
+ border-top: 1px solid var(--ow-border);
7557
+ }
7558
+
7559
+ .ow-description-list--horizontal > .ow-description-item {
7560
+ grid-template-columns: var(--ow-description-term-width, 160px) minmax(0, 1fr);
7561
+ align-items: baseline;
7562
+ column-gap: var(--ow-space-2xl);
7563
+ }
7564
+
7565
+ /* Grid: the pairs in columns, term above value, with a smaller label. A column is at least 160px, so a grid with
7566
+ less room has fewer columns; the items then read the list's width (the container) to keep their spans inside it. */
7567
+ .ow-description-list--grid {
7568
+ --ow-description-gap: var(--ow-space-4xl);
7569
+ grid-template-columns: repeat(
7570
+ auto-fill,
7571
+ minmax(max(160px, (100% - (var(--ow-description-columns) - 1) * var(--ow-description-gap)) / var(--ow-description-columns)), 1fr)
7572
+ );
7573
+ column-gap: var(--ow-description-gap);
7574
+ }
7575
+
7576
+ .ow-description-list--cols-2 {
7577
+ --ow-description-columns: 2;
7578
+ }
7579
+
7580
+ .ow-description-list--cols-3 {
7581
+ --ow-description-columns: 3;
7582
+ }
7583
+
7584
+ .ow-description-list--cols-4 {
7585
+ --ow-description-columns: 4;
7586
+ }
7587
+
7588
+ .ow-description-list--grid .ow-description-item__term {
7589
+ font-size: 12px;
7590
+ font-weight: var(--ow-weight-control);
7591
+ }
7592
+
7593
+ .ow-description-list--grid.ow-description-list--divided > .ow-description-item {
7594
+ border-top: 1px solid var(--ow-border);
7595
+ }
7596
+
7597
+ .ow-description-item--span-2 {
7598
+ grid-column: span 2;
7599
+ }
7600
+
7601
+ .ow-description-item--span-3 {
7602
+ grid-column: span 3;
7603
+ }
7604
+
7605
+ .ow-description-item--span-4,
7606
+ .ow-description-item--span-full,
7607
+ .ow-description-list--cols-2 > .ow-description-item--span-3 {
7608
+ grid-column: 1 / -1;
7609
+ }
7610
+
7611
+ @container ow-description-list (max-width: 519px) {
7612
+ .ow-description-item--span-3 {
7613
+ grid-column: 1 / -1;
7614
+ }
7615
+ }
7616
+
7617
+ @container ow-description-list (max-width: 419px) {
7618
+ .ow-description-list--horizontal > .ow-description-item {
7619
+ grid-template-columns: minmax(0, 1fr);
7620
+ }
7621
+ }
7622
+
7623
+ @container ow-description-list (max-width: 339px) {
7624
+ .ow-description-item--span-2,
7625
+ .ow-description-item--span-3 {
7626
+ grid-column: auto;
7627
+ }
7628
+ }
7629
+
6357
7630
  /* components/Chart/Chart.css */
6358
7631
  /* Charts: thin marks in the chart palette (--ow-chart-1 to 8), hairline grids, text in text colours, never the series'. */
6359
7632
 
@@ -7311,6 +8584,179 @@
7311
8584
  }
7312
8585
  }
7313
8586
 
8587
+ /* components/Splitter/Splitter.css */
8588
+ /* Splitter: panels with handles between them. A panel's flex-grow is its size in percent. */
8589
+ .ow-splitter {
8590
+ display: flex;
8591
+ width: 100%;
8592
+ height: 100%;
8593
+ min-width: 0;
8594
+ min-height: 0;
8595
+ overflow: hidden;
8596
+ }
8597
+
8598
+ .ow-splitter--vertical {
8599
+ flex-direction: column;
8600
+ }
8601
+
8602
+ .ow-splitter__panel {
8603
+ flex: 0 1 0px;
8604
+ min-width: 0;
8605
+ min-height: 0;
8606
+ overflow: auto;
8607
+ }
8608
+
8609
+ .ow-splitter__panel[data-collapsed="hidden"] {
8610
+ visibility: hidden;
8611
+ }
8612
+
8613
+ /* The line is 1px; the area you can catch is 9px. */
8614
+ .ow-splitter__handle {
8615
+ position: relative;
8616
+ flex: none;
8617
+ background: var(--ow-border);
8618
+ outline: none;
8619
+ touch-action: none;
8620
+ transition: background-color var(--ow-duration-fast) var(--ow-ease-standard);
8621
+ }
8622
+
8623
+ .ow-splitter--horizontal > .ow-splitter__handle {
8624
+ width: 1px;
8625
+ cursor: col-resize;
8626
+ }
8627
+
8628
+ .ow-splitter--vertical > .ow-splitter__handle {
8629
+ height: 1px;
8630
+ cursor: row-resize;
8631
+ }
8632
+
8633
+ .ow-splitter__handle::before,
8634
+ .ow-splitter__handle::after {
8635
+ content: "";
8636
+ position: absolute;
8637
+ z-index: 1;
8638
+ }
8639
+
8640
+ .ow-splitter--horizontal > .ow-splitter__handle::before {
8641
+ inset: 0 -4px;
8642
+ }
8643
+
8644
+ .ow-splitter--vertical > .ow-splitter__handle::before {
8645
+ inset: -4px 0;
8646
+ }
8647
+
8648
+ /* The highlight: a 3px bar over the line. */
8649
+ .ow-splitter__handle::after {
8650
+ inset: 0 -1px;
8651
+ border-radius: var(--ow-radius-pill);
8652
+ opacity: 0;
8653
+ background: var(--ow-border-strong);
8654
+ transition: opacity var(--ow-duration-fast) var(--ow-ease-standard);
8655
+ }
8656
+
8657
+ .ow-splitter--vertical > .ow-splitter__handle::after {
8658
+ inset: -1px 0;
8659
+ }
8660
+
8661
+ .ow-splitter__handle:hover::after {
8662
+ opacity: 1;
8663
+ }
8664
+
8665
+ .ow-splitter__handle[data-dragging]::after,
8666
+ .ow-splitter__handle:focus-visible::after {
8667
+ opacity: 1;
8668
+ background: var(--ow-focus-ring);
8669
+ }
8670
+
8671
+ .ow-splitter__handle[aria-disabled] {
8672
+ cursor: default;
8673
+ }
8674
+
8675
+ .ow-splitter__handle[aria-disabled]::after {
8676
+ display: none;
8677
+ }
8678
+
8679
+ /* A grip in the middle of the line. */
8680
+ .ow-splitter__handle--grip::after {
8681
+ inset: 50% auto auto 50%;
8682
+ width: 6px;
8683
+ height: 24px;
8684
+ translate: -50% -50%;
8685
+ opacity: 1;
8686
+ border: 1px solid var(--ow-border-strong);
8687
+ background: var(--ow-surface);
8688
+ box-shadow: var(--ow-shadow-control);
8689
+ }
8690
+
8691
+ .ow-splitter--vertical > .ow-splitter__handle--grip::after {
8692
+ inset: 50% auto auto 50%;
8693
+ width: 24px;
8694
+ height: 6px;
8695
+ }
8696
+
8697
+ .ow-splitter__handle--grip:hover::after {
8698
+ background: var(--ow-surface-muted);
8699
+ }
8700
+
8701
+ .ow-splitter__handle--grip[data-dragging]::after,
8702
+ .ow-splitter__handle--grip:focus-visible::after {
8703
+ border-color: var(--ow-focus-ring);
8704
+ background: var(--ow-surface);
8705
+ box-shadow: 0 0 0 1px var(--ow-focus-ring);
8706
+ }
8707
+
8708
+ /* While dragging, the cursor stays a resize one everywhere and nothing gets selected. */
8709
+ :root[data-ow-splitter-drag],
8710
+ :root[data-ow-splitter-drag] * {
8711
+ user-select: none;
8712
+ -webkit-user-select: none;
8713
+ }
8714
+
8715
+ :root[data-ow-splitter-drag="horizontal"] * {
8716
+ cursor: col-resize !important;
8717
+ }
8718
+
8719
+ :root[data-ow-splitter-drag="vertical"] * {
8720
+ cursor: row-resize !important;
8721
+ }
8722
+
8723
+ @media (prefers-reduced-motion: reduce) {
8724
+ .ow-splitter__handle,
8725
+ .ow-splitter__handle::after {
8726
+ transition: none;
8727
+ }
8728
+ }
8729
+
8730
+ /* components/AspectRatio/AspectRatio.css */
8731
+ /* AspectRatio: a box that keeps its shape, with whatever is inside filling it. The hidden overflow keeps the ratio
8732
+ when the content is taller than the box would be. */
8733
+ .ow-aspect-ratio {
8734
+ position: relative;
8735
+ display: block;
8736
+ box-sizing: border-box;
8737
+ width: 100%;
8738
+ overflow: hidden;
8739
+ }
8740
+
8741
+ .ow-aspect-ratio > * {
8742
+ position: absolute;
8743
+ inset: 0;
8744
+ box-sizing: border-box;
8745
+ width: 100%;
8746
+ height: 100%;
8747
+ }
8748
+
8749
+ .ow-aspect-ratio > :is(img, video, iframe, embed, object, picture, canvas, svg) {
8750
+ border: 0;
8751
+ object-fit: cover;
8752
+ }
8753
+
8754
+ .ow-aspect-ratio > picture > img {
8755
+ width: 100%;
8756
+ height: 100%;
8757
+ object-fit: cover;
8758
+ }
8759
+
7314
8760
  /* components/Marketing/Marketing.css */
7315
8761
  /* Marketing patterns from the site: Chip, SectionHeading, SiteHeader and the dot grid. */
7316
8762
  .ow-chip {