@webority/theme 0.13.5 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -552,7 +552,7 @@
552
552
  }
553
553
  .file-input:focus-within {
554
554
  background: var(--color-surface);
555
- border-color: var(--wui-primary-30);
555
+ border-color: var(--color-focus-border);
556
556
  box-shadow: none;
557
557
  }
558
558
  .file-input-btn {
@@ -614,7 +614,7 @@
614
614
  .file-input.file-input-tall:focus-within,
615
615
  .file-input.file-input-tall:active,
616
616
  .file-input.file-input-tall.dragging {
617
- border-color: var(--wui-primary-30);
617
+ border-color: var(--color-focus-border);
618
618
  background: var(--color-surface);
619
619
  box-shadow: none;
620
620
  }
@@ -664,7 +664,7 @@
664
664
  background: var(--color-bg-muted);
665
665
  }
666
666
  .file-input.file-input-tall.has-files.dragging {
667
- border-color: var(--wui-primary-30);
667
+ border-color: var(--color-focus-border);
668
668
  background: var(--color-surface);
669
669
  }
670
670
  // Width presets — put a .file-w-* class on the field (React className / Razor class) to cap the
@@ -820,7 +820,9 @@
820
820
  gap: 8px;
821
821
  padding: 9px 18px;
822
822
  background: rgba(255, 255, 255, 0.96);
823
- color: var(--color-text);
823
+ // The pill stays white in every theme, so its ink is fixed too: --color-text flips light in
824
+ // dark mode and would vanish on the white pill.
825
+ color: var(--wui-text-heading);
824
826
  font-size: 14px;
825
827
  font-weight: 600;
826
828
  border-radius: 999px;
@@ -316,18 +316,23 @@
316
316
  // keeps a non-square source whole rather than cropping it.
317
317
  .wui-confirm-icon img {
318
318
  display: block;
319
- width: 80px;
320
- height: 80px;
319
+ width: var(--wui-confirm-icon-size, 80px);
320
+ height: var(--wui-confirm-icon-size, 80px);
321
321
  object-fit: contain;
322
322
  }
323
- // Icon size tracks the copy: a title+message dialog keeps the full 80px badge (set on
324
- // the element), but a lone title (no message) is one line and gets a smaller badge.
325
- // `.wui-confirm-msg` is a real element rendered only when a message exists, so `:has()`
326
- // is reliable here; CSS width/height override the SVG's own width/height attributes.
323
+ .wui-confirm-icon svg {
324
+ width: var(--wui-confirm-icon-size, 80px);
325
+ height: var(--wui-confirm-icon-size, 80px);
326
+ }
327
+ // Icon size tracks the copy: a title+message dialog keeps the full 80px badge, but a lone
328
+ // title (no message) is one line and gets a smaller badge. `.wui-confirm-msg` is a real
329
+ // element rendered only when a message exists, so `:has()` is reliable here; CSS width/height
330
+ // override the SVG's own width/height attributes. An explicit iconSize / icon-size sets
331
+ // --wui-confirm-icon-size on the badge and wins in both cases.
327
332
  .wui-confirm-content:not(:has(.wui-confirm-msg)) .wui-confirm-icon svg,
328
333
  .wui-confirm-content:not(:has(.wui-confirm-msg)) .wui-confirm-icon img {
329
- width: 56px;
330
- height: 56px;
334
+ width: var(--wui-confirm-icon-size, 56px);
335
+ height: var(--wui-confirm-icon-size, 56px);
331
336
  }
332
337
  .wui-confirm-title {
333
338
  margin: 0 0 10px;
@@ -432,15 +432,43 @@
432
432
  // custom class both put on Bootstrap's `.popover` panel.
433
433
  // The card surface — header and body alike — is pure white, lifted off the page with the shared
434
434
  // overlay shadow (the one ink menus/popovers/modals use; not a hand-rolled per-component shadow).
435
- .pw-popover {
435
+ // The field help popover (AppInfoTip, `.infotip-popover`) shares the same card, so the two
436
+ // help surfaces a form shows read as one family.
437
+ .pw-popover,
438
+ .infotip-popover {
436
439
  --bs-popover-bg: var(--wui-bg-light);
437
440
  --bs-popover-header-bg: var(--wui-bg-light);
441
+ // A 14px heading: one step above the 13px body, so the card reads as help, not a dialog.
442
+ --bs-popover-header-font-size: 14px;
438
443
  box-shadow: var(--wui-shadow-overlay);
439
444
  }
440
- .pw-popover .popover-body {
445
+ .pw-popover .popover-body,
446
+ .infotip-popover .popover-body {
441
447
  padding: 14px 16px;
448
+ }
449
+ .pw-popover .popover-body {
442
450
  min-width: 232px;
443
451
  }
452
+ // AppInfoTip `width`: how wide the help card may grow before its text wraps. md is Bootstrap's
453
+ // own 276px, so leaving the prop out changes nothing. It sets the MAX width, so a short tip stays
454
+ // as narrow as its text.
455
+ .infotip-popover-sm {
456
+ --bs-popover-max-width: 220px;
457
+ }
458
+ .infotip-popover-lg {
459
+ --bs-popover-max-width: 360px;
460
+ }
461
+ .infotip-popover-xl {
462
+ --bs-popover-max-width: 480px;
463
+ }
464
+ // Help prose takes the checklist's type: 13px medium in the subtle ink. It keeps a little more
465
+ // leading than a one-line rule because it wraps into a paragraph.
466
+ .infotip-popover .popover-body {
467
+ font-size: 13px;
468
+ line-height: 1.5;
469
+ font-weight: 500;
470
+ color: var(--color-text-subtle);
471
+ }
444
472
  .pw-criteria {
445
473
  list-style: none;
446
474
  margin: 0;
@@ -482,17 +510,20 @@
482
510
  color: var(--color-text-subtle);
483
511
  --pw-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8'%3E%3Ccircle cx='12' cy='12' r='8.25'/%3E%3C/svg%3E");
484
512
  }
485
- // Met: success-green — a filled circle with a knocked-out check.
513
+ // Met: the bright success fill — a filled circle with a knocked-out check. The rule text takes the
514
+ // same fill rather than --color-success-text, a deliberate choice for the brighter look; it sits
515
+ // under AA text contrast on a white card.
486
516
  .pw-criteria .pw-rule.met {
487
- color: var(--color-success-text);
517
+ color: var(--wui-success-active);
488
518
  --pw-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' fill-rule='evenodd' d='M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm4.03-11.28a.9.9 0 0 0-1.32-1.22l-4.02 4.35-1.4-1.5a.9.9 0 1 0-1.32 1.22l2.06 2.22a.9.9 0 0 0 1.32 0l4.68-5.07Z' clip-rule='evenodd'/%3E%3C/svg%3E");
489
519
  }
490
- // The checklist opens with a PLAIN FADE only — no drop / zoom / scale. It opts out of the shared
520
+ // The checklist and the field help tip open with a PLAIN FADE only — no drop / zoom / scale. It opts out of the shared
491
521
  // menu-open motion (_menu-motion.scss animates every `.popover.show`) and lets Bootstrap's own
492
522
  // `.fade` opacity transition carry the fade in and out. Both surfaces render `.popover.pw-popover`
493
523
  // (React via react-bootstrap's Popover, Razor via Bootstrap's popover), so this makes the two
494
524
  // identical. Higher specificity than `.popover.show` so it wins regardless of partial load order.
495
- .popover.pw-popover.show {
525
+ .popover.pw-popover.show,
526
+ .popover.infotip-popover.show {
496
527
  animation: none;
497
528
  scale: none;
498
529
  translate: none;
@@ -560,6 +591,16 @@
560
591
  border-bottom: 1px solid var(--color-border);
561
592
  }
562
593
 
594
+ // The track. Bootstrap's default is --bs-secondary-bg, which is near-white on a white card in
595
+ // light mode and the card surface itself in dark mode, so the empty part of the bar disappeared
596
+ // in both. Set on .progress because Bootstrap declares --bs-progress-bg there, not on :root.
597
+ .progress {
598
+ --bs-progress-bg: var(--color-progress-track);
599
+ // The showLabel text inside the bar: white on the light-mode fills, a dark ink on the bright
600
+ // dark-mode fills (white reaches only 2.3:1 to 3.9:1 on those).
601
+ --bs-progress-bar-color: var(--color-progress-label);
602
+ }
603
+
563
604
  // Determinate progress-bar fill tones (AppProgress / AppMeter / <app-progress>) — the fill sits
564
605
  // in Bootstrap's .progress track; only the bar colour is brand-toned.
565
606
  //
@@ -568,17 +609,21 @@
568
609
  // --wui-danger (#F8285A) fails AA (2.78:1 / 3.86:1). The -strong fills clear it (both ~5.8:1),
569
610
  // the same trick btn-danger uses. info/warning/neutral stay on their mid tones (info/neutral
570
611
  // pass with white; warning is not shown with a white label).
612
+ //
613
+ // They read the --color-*-strong aliases, not --wui-*-strong, because dark mode remaps the
614
+ // aliases to the bright fills: the deep fills sink into the dark track (about 2:1). The label
615
+ // flips to a dark ink there (--color-progress-label), which clears AA on all five dark fills.
571
616
  .wui-progress-info {
572
617
  background-color: var(--color-info);
573
618
  }
574
619
  .wui-progress-success {
575
- background-color: var(--wui-success-strong);
620
+ background-color: var(--color-success-strong);
576
621
  }
577
622
  .wui-progress-warning {
578
623
  background-color: var(--color-warning);
579
624
  }
580
625
  .wui-progress-danger {
581
- background-color: var(--wui-danger-strong);
626
+ background-color: var(--color-danger-strong);
582
627
  }
583
628
  .wui-progress-neutral {
584
629
  background-color: var(--color-text-subtle);
@@ -668,187 +713,10 @@
668
713
  }
669
714
  }
670
715
 
671
- // Callout — a soft branded aside that EXPLAINS something and stays (distinct from
672
- // `.alert`, which reports a state). A thick coloured LEFT edge reads as an aside; a
673
- // circular icon badge + optional coloured heading keep it visually in the alert family.
674
- // One local `--callout-accent`/-border/-bg triad, swapped per tone, drives the left
675
- // edge, the icon badge fill, the heading colour, and the compact body text.
676
- .info-callout {
677
- --callout-accent: var(--color-info-active);
678
- // AA-safe text colour for the heading / compact body / <strong> (the vivid --callout-accent
679
- // is fine for the badge fill, left edge and halo, but fails AA as text on the soft bg).
680
- --callout-text: var(--color-info-text);
681
- --callout-border: var(--color-info-30);
682
- --callout-bg: var(--color-info-10);
683
-
684
- display: flex;
685
- align-items: center;
686
- // On phones the trailing action drops onto its own row BELOW the content (the flex `gap`
687
- // supplies the vertical space) so a button never crushes the message into a sliver; from md
688
- // up it sits inline at the right — a VIEWPORT rule, not the callout's own width. See the
689
- // `.info-callout-action` breakpoint below.
690
- flex-wrap: wrap;
691
- gap: 12px;
692
- padding: 14px 18px;
693
- border: 1px solid var(--callout-border);
694
- // A thick coloured left edge — the callout's signature aside marker.
695
- border-left: 4px solid var(--callout-accent);
696
- border-radius: 8px;
697
- background: var(--callout-bg);
698
- font-size: 14px;
699
- // Sub-content (the body/subtitle) reads at #252F4A / 400; the heading and the
700
- // compact-size text override colour + weight below.
701
- font-weight: 400;
702
- line-height: 1.5;
703
- color: var(--wui-text-1);
704
- }
705
- .info-callout.tone-success {
706
- --callout-accent: var(--color-success-active);
707
- --callout-text: var(--color-success-text);
708
- --callout-border: var(--color-success-30);
709
- --callout-bg: var(--color-success-10);
710
- }
711
- .info-callout.tone-warning {
712
- --callout-accent: var(--color-warning-active);
713
- --callout-text: var(--color-warning-text);
714
- --callout-border: var(--color-warning-30);
715
- --callout-bg: var(--color-warning-10);
716
- }
717
- .info-callout.tone-danger {
718
- --callout-accent: var(--color-danger-active);
719
- --callout-text: var(--color-danger-text);
720
- --callout-border: var(--color-danger-30);
721
- --callout-bg: var(--color-danger-10);
722
- }
723
-
724
- // Borderless variant (`bordered={false}` / `bordered="false"`): drop the soft ring AND
725
- // the thick tone-coloured left edge, keeping only the tint fill. Colours go `transparent`
726
- // rather than the widths to 0 so the box keeps its 1px / 4px-left footprint — nothing
727
- // shifts when toggling the border on and off. Mirrors `.alert-borderless`.
728
- .info-callout-borderless {
729
- border-color: transparent;
730
- }
731
-
732
- // The leading glyph is a solid circular badge — tone fill, white glyph centred, with a
733
- // soft 3px same-colour halo ring. Base is the single-content size (20px badge / 20px
734
- // glyph); a title+body stack steps it up to 24px. The badge stays VERTICALLY CENTRED
735
- // against the whole block in both cases (align-items: center on .info-callout).
736
- .info-callout-icon {
737
- flex: none;
738
- display: inline-flex;
739
- align-items: center;
740
- justify-content: center;
741
- width: 20px;
742
- height: 20px;
743
- border-radius: 50%;
744
- background: var(--callout-accent);
745
- color: #fff;
746
- // 4px translucent ring in the badge's own colour — the "outer shadow".
747
- box-shadow: 0 0 0 4px color-mix(in srgb, var(--callout-accent) 20%, transparent);
748
-
749
- .wui-icon {
750
- line-height: 1;
751
- }
752
- }
753
- // A title+body stack gets the larger badge (24px / 22px glyph).
754
- .info-callout-stack .info-callout-icon {
755
- width: 24px;
756
- height: 24px;
757
- }
758
-
759
- // Custom image in the badge (icon replacement): the image fills the circle, so drop the
760
- // tone fill and clip it round. Applies to both AppCallout and AppAlert badges.
761
- .info-callout-icon-image,
762
- .alert-icon-image {
763
- background: transparent;
764
- overflow: hidden;
765
- }
766
- .info-callout-icon img,
767
- .alert-icon img {
768
- width: 100%;
769
- height: 100%;
770
- object-fit: cover;
771
- border-radius: 50%;
772
- }
773
-
774
- .info-callout-content {
775
- // Grows to fill the row so a trailing action (and the dismiss ×) sit at the right edge.
776
- flex: 1 1 auto;
777
- min-width: 0;
778
- font-size: 12px;
779
- }
780
- // Trailing action slot — a button (or any node). Mobile-first: on phones it takes its own full
781
- // row below the content (left-aligned there); from md up it collapses to its natural width and
782
- // sits inline at the right edge of the content row.
783
- .info-callout-action {
784
- flex: 1 1 100%;
785
- align-self: center;
786
- display: flex;
787
- justify-content: flex-start;
788
- align-items: center;
789
- gap: 8px;
790
- }
791
- // From md up the row never wraps — the content shrinks to seat the action inline at the right,
792
- // so a button stays beside the text on any large screen, even when the callout sits in a narrow
793
- // column (the wrap-below is a phones-only treatment).
794
- @include media-breakpoint-up(md) {
795
- .info-callout {
796
- flex-wrap: nowrap;
797
- }
798
- .info-callout-action {
799
- flex: none;
800
- justify-content: initial;
801
- margin-left: auto;
802
- }
803
- }
804
- .info-callout-heading {
805
- font-size: 14px;
806
- font-weight: 600;
807
- line-height: 1.3;
808
- margin-bottom: 1px;
809
- color: var(--callout-text);
810
- }
811
- .info-callout strong {
812
- font-weight: 700;
813
- color: var(--callout-text);
814
- }
815
-
816
- // Optional dismiss × — pushed to the right edge, vertically centred, subtle.
817
- .info-callout-close {
818
- flex: none;
819
- align-self: center;
820
- margin-left: auto;
821
- display: inline-flex;
822
- align-items: center;
823
- justify-content: center;
824
- padding: 4px;
825
- border: none;
826
- background: transparent;
827
- color: var(--color-text-muted);
828
- cursor: pointer;
829
- opacity: 0.7;
830
- border-radius: var(--radius-sm);
831
- transition: opacity 0.15s;
832
- }
833
- .info-callout-close:hover {
834
- opacity: 1;
835
- }
836
- .info-callout-close:focus-visible {
837
- outline: 2px solid currentColor;
838
- outline-offset: 2px;
839
- }
840
-
841
- // Compact size — a single tinted line: tighter padding and the body text itself carries
842
- // the tone colour. The badge stays the single-content 20px base.
843
- .info-callout-sm {
844
- padding: 9px 14px;
845
- gap: 10px;
846
- font-weight: 600;
847
- color: var(--callout-text);
848
- }
849
-
850
- // AppAlert — a soft tinted status banner with a filled circular icon badge and a
851
- // coloured heading line. Bootstrap styles the base `.alert`; these rules set the
716
+ // AppAlert — a soft tinted banner with a filled circular icon badge and a
717
+ // coloured heading line. It reports a state (role="alert"/"status") or, with
718
+ // role="none", explains part of the page; `accent`, `size="sm"` and `action` give it the
719
+ // thick left edge, the compact line and the trailing button for that second job. Bootstrap styles the base `.alert`; these rules set the
852
720
  // per-variant surface (soft-tint background, soft border, dark body text), lay out
853
721
  // the icon column, turn the leading glyph into a solid circular badge, and colour
854
722
  // the heading to the variant. Only the heading takes the variant colour — the body
@@ -860,30 +728,41 @@
860
728
  border-width: 1px;
861
729
  }
862
730
 
863
- // Per-variant surface: soft tint fill + soft border; body text stays dark ink.
731
+ // Per-variant surface: soft tint fill + a -50 border (deep enough to read beside the accent
732
+ // edge); body text stays ink. Every colour comes from a --color-* token that the dark theme
733
+ // remaps (_wui-aliases.scss), so the alert flips with the page in every dark path, the manual
734
+ // data-theme attribute and the auto media query alike, with no per-component dark rules.
864
735
  .alert-info {
865
- --bs-alert-bg: var(--wui-info-10);
866
- --bs-alert-border-color: var(--wui-info-30);
867
- --bs-alert-color: var(--wui-text-1);
736
+ --bs-alert-bg: var(--color-info-soft);
737
+ --bs-alert-border-color: var(--color-info-50);
738
+ --bs-alert-color: var(--color-text-body);
868
739
  --alert-accent: var(--wui-info-active);
740
+ // AA-safe text colour for the heading and an accented <strong>.
741
+ --alert-text: var(--color-info-text-on-soft);
869
742
  }
870
743
  .alert-success {
871
- --bs-alert-bg: var(--wui-success-10);
872
- --bs-alert-border-color: var(--wui-success-30);
873
- --bs-alert-color: var(--wui-text-1);
744
+ --bs-alert-bg: var(--color-success-soft);
745
+ --bs-alert-border-color: var(--color-success-50);
746
+ --bs-alert-color: var(--color-text-body);
874
747
  --alert-accent: var(--wui-success-active);
748
+ // AA-safe text colour for the heading and an accented <strong>.
749
+ --alert-text: var(--color-success-text-on-soft);
875
750
  }
876
751
  .alert-warning {
877
- --bs-alert-bg: var(--wui-warning-10);
878
- --bs-alert-border-color: var(--wui-warning-30);
879
- --bs-alert-color: var(--wui-text-1);
752
+ --bs-alert-bg: var(--color-warning-soft);
753
+ --bs-alert-border-color: var(--color-warning-50);
754
+ --bs-alert-color: var(--color-text-body);
880
755
  --alert-accent: var(--wui-warning-active);
756
+ // AA-safe text colour for the heading and an accented <strong>.
757
+ --alert-text: var(--color-warning-text-on-soft);
881
758
  }
882
759
  .alert-danger {
883
- --bs-alert-bg: var(--wui-danger-10);
884
- --bs-alert-border-color: var(--wui-danger-30);
885
- --bs-alert-color: var(--wui-text-1);
760
+ --bs-alert-bg: var(--color-danger-soft);
761
+ --bs-alert-border-color: var(--color-danger-50);
762
+ --bs-alert-color: var(--color-text-body);
886
763
  --alert-accent: var(--wui-danger-active);
764
+ // AA-safe text colour for the heading and an accented <strong>.
765
+ --alert-text: var(--color-danger-text-on-soft);
887
766
  }
888
767
 
889
768
  // Borderless variant (`bordered={false}` / `bordered="false"`): drop the soft ring and
@@ -893,6 +772,73 @@
893
772
  border-color: transparent;
894
773
  }
895
774
 
775
+ // Accent (`accent`): a thick variant-coloured LEFT edge that marks the alert as an aside,
776
+ // flush with the container's outer edge, corners included.
777
+ // A real border cannot do this: a 4px border-left meeting 1px top/bottom borders on a rounded
778
+ // corner is mitred into a point, and an inset shadow drawn inside a 1px border leaves that
779
+ // border curving round the corner outside the edge. So the accent alert has no border at all:
780
+ // the soft ring is an inset 1px shadow, and the accent is a second inset shadow listed first,
781
+ // so it paints over the ring along the left side and fills the corners out to the edge.
782
+ // Padding grows by the 1px the border no longer takes (and by the 4px edge on the left), so
783
+ // the box and its text sit exactly where a bordered alert's do.
784
+ .alert-accent {
785
+ --alert-ring: var(--bs-alert-border-color);
786
+ border-width: 0;
787
+ box-shadow:
788
+ inset 4px 0 0 var(--alert-accent),
789
+ inset 0 0 0 1px var(--alert-ring);
790
+ padding: 17px 19px 17px 22px;
791
+ }
792
+ // `bordered={false}`: only the ring goes; the edge stays.
793
+ .alert-accent.alert-borderless {
794
+ --alert-ring: transparent;
795
+ }
796
+ .alert-accent strong {
797
+ font-weight: 700;
798
+ color: var(--alert-text);
799
+ }
800
+
801
+ // Compact size (`size="sm"`): a single tinted line with tighter padding. The body keeps the
802
+ // same dark ink and regular weight as md (only the heading is bold and variant-coloured); the
803
+ // badge stays the single-line 20px base.
804
+ .alert-sm {
805
+ padding: 9px 14px;
806
+ }
807
+ .alert-sm.alert-has-icon {
808
+ gap: 10px;
809
+ }
810
+ .alert-sm .alert-content {
811
+ font-size: 11px;
812
+ }
813
+
814
+ // Trailing action (`action`): a button or any node. Mobile-first, it takes its own full
815
+ // row below the content; from md up it sits inline at the right edge. A viewport rule,
816
+ // not the alert's own width, so a button never crushes the message on a phone.
817
+ .alert-has-action {
818
+ display: flex;
819
+ align-items: center;
820
+ flex-wrap: wrap;
821
+ gap: 12px;
822
+ }
823
+ .alert-has-action .alert-content {
824
+ flex: 1 1 auto;
825
+ }
826
+ .alert-action {
827
+ flex: 1 1 100%;
828
+ display: flex;
829
+ align-items: center;
830
+ gap: 8px;
831
+ }
832
+ @include media-breakpoint-up(md) {
833
+ .alert-has-action {
834
+ flex-wrap: nowrap;
835
+ }
836
+ .alert-action {
837
+ flex: none;
838
+ margin-left: auto;
839
+ }
840
+ }
841
+
896
842
  .alert-has-icon {
897
843
  display: flex;
898
844
  // Single-line alerts (a lone body, or a lone title) read best with the badge
@@ -913,6 +859,21 @@
913
859
  // a soft 3px same-colour halo ring around it. Base size is the SINGLE-line badge (20px,
914
860
  // 20px glyph); the .alert-stack override above enlarges it when a title and body appear
915
861
  // together. (The glyph itself is a Bootstrap Icons font `<i>` sized by the component.)
862
+ // Custom image in the badge (icon replacement): the image fills the circle, so drop the
863
+ // variant fill and the halo ring and clip it round. Compound selector so it beats the
864
+ // .alert-icon rule below, which sets both.
865
+ .alert-icon.alert-icon-image {
866
+ background: transparent;
867
+ box-shadow: none;
868
+ overflow: hidden;
869
+ }
870
+ .alert-icon img {
871
+ width: 100%;
872
+ height: 100%;
873
+ object-fit: cover;
874
+ border-radius: 50%;
875
+ }
876
+
916
877
  .alert-icon {
917
878
  flex: none;
918
879
  display: inline-flex;
@@ -948,16 +909,54 @@
948
909
  // Use the AA-safe `-text` tokens (not the vivid `-active`, which fails AA as text on
949
910
  // the soft `-10` background); the badge fill / halo keep the vivid `-active`.
950
911
  .alert-info .alert-heading {
951
- color: var(--wui-info-text);
912
+ color: var(--alert-text);
952
913
  }
953
914
  .alert-success .alert-heading {
954
- color: var(--wui-success-text);
915
+ color: var(--alert-text);
955
916
  }
956
917
  .alert-warning .alert-heading {
957
- color: var(--wui-warning-text);
918
+ color: var(--alert-text);
958
919
  }
959
920
  .alert-danger .alert-heading {
960
- color: var(--wui-danger-text);
921
+ color: var(--alert-text);
922
+ }
923
+
924
+ // Heading and body type step with the size: sm 13px / 11px, md 14px / 12px (the base above),
925
+ // lg 16px / 14px. Declared after the base heading rule so these override it.
926
+ .alert-sm .alert-heading {
927
+ font-size: 13px;
928
+ }
929
+
930
+ // Large size (`size="lg"`): roomier padding, a larger heading and body, and a larger badge
931
+ // (28px, or 32px for a title+body stack). Declared after the heading and stack rules so it
932
+ // overrides them.
933
+ .alert-lg {
934
+ padding: 20px 22px;
935
+ }
936
+ .alert-lg.alert-has-icon {
937
+ gap: 16px;
938
+ }
939
+ .alert-lg .alert-heading {
940
+ font-size: 16px;
941
+ }
942
+ .alert-lg .alert-content {
943
+ font-size: 14px;
944
+ }
945
+ .alert-lg.alert-has-icon .alert-icon {
946
+ width: 28px;
947
+ height: 28px;
948
+ }
949
+ .alert-lg.alert-has-icon.alert-stack .alert-icon {
950
+ width: 32px;
951
+ height: 32px;
952
+ }
953
+ // The accent's padding per size: the size's own padding + the 1px the border no longer takes,
954
+ // + the 4px edge on the left. Two-class selectors, so they beat the size blocks above.
955
+ .alert-accent.alert-sm {
956
+ padding: 10px 15px 10px 18px;
957
+ }
958
+ .alert-accent.alert-lg {
959
+ padding: 21px 23px 21px 26px;
961
960
  }
962
961
 
963
962
  // The body's trailing paragraph shouldn't add space below the alert.
@@ -971,6 +970,14 @@
971
970
  .alert-dismissible {
972
971
  padding-right: 52px;
973
972
  }
973
+ // An accent alert has no 1px border, so it takes the missing pixel back on the right.
974
+ .alert-accent.alert-dismissible {
975
+ padding-right: 53px;
976
+ }
977
+ // The dismiss × is Bootstrap's ink-dark glyph; the token whitens it on a dark page.
978
+ .alert .btn-close {
979
+ filter: var(--color-close-filter);
980
+ }
974
981
  // Centre the dismiss × vertically rather than pinning it to the top corner.
975
982
  .alert-dismissible .btn-close {
976
983
  top: 50%;
@@ -45,7 +45,7 @@
45
45
  .workspace-switcher-trigger[aria-expanded="true"] {
46
46
  outline: none;
47
47
  background: var(--color-surface);
48
- border-color: var(--wui-primary-30);
48
+ border-color: var(--color-focus-border);
49
49
  box-shadow: none;
50
50
  }
51
51
  .workspace-switcher-trigger.is-compact {