@threadlabs/looma 0.11.3 → 0.11.5

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.
@@ -368,7 +368,7 @@ ol[data-v-0d86d58e] {
368
368
  display: none;
369
369
  }
370
370
 
371
- [data-component~="ui-button"][data-v-0c121308] {
371
+ [data-component~="ui-button"][data-v-6c8750a9] {
372
372
  --_hue: var(--ui-accent);
373
373
  --_hue-hover: var(--ui-accent-hover);
374
374
  --_hue-active: var(--ui-accent-active);
@@ -387,15 +387,15 @@ ol[data-v-0d86d58e] {
387
387
  vertical-align: middle;
388
388
  color: var(--_tone-text);
389
389
  }
390
- [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-0c121308] {
390
+ [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-6c8750a9] {
391
391
  justify-content: flex-start;
392
392
  text-align: start;
393
393
  }
394
- [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-0c121308] {
394
+ [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-6c8750a9] {
395
395
  display: flex;
396
396
  inline-size: 100%;
397
397
  }
398
- [data-component~="ui-button"][data-v-0c121308] {
398
+ [data-component~="ui-button"][data-v-6c8750a9] {
399
399
  appearance: none;
400
400
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
401
401
  border-style: solid;
@@ -420,17 +420,17 @@ ol[data-v-0d86d58e] {
420
420
  margin: 0;
421
421
  }
422
422
  @supports (text-box-trim: trim-both) {
423
- [data-component~="ui-button"][data-v-0c121308] {
423
+ [data-component~="ui-button"][data-v-6c8750a9] {
424
424
  text-box-trim: trim-both;
425
425
  text-box-edge: cap alphabetic;
426
426
  }
427
427
  }
428
- [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-0c121308] {
428
+ [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-6c8750a9] {
429
429
  min-block-size: var(--ui-control-size-sm);
430
430
  padding: var(--ui-space-1) var(--ui-space-2);
431
431
  font-size: var(--ui-font-size-sm);
432
432
  }
433
- [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-0c121308] {
433
+ [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-6c8750a9] {
434
434
  min-block-size: var(--ui-control-size-lg);
435
435
  padding: var(--ui-space-3) var(--ui-space-4);
436
436
  font-size: var(--ui-font-size-md);
@@ -438,29 +438,29 @@ ol[data-v-0d86d58e] {
438
438
 
439
439
  /* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
440
440
  is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */
441
- [data-component~="ui-button"][data-v-0c121308]:hover:not(:disabled, [aria-disabled="true"]) {
441
+ [data-component~="ui-button"][data-v-6c8750a9]:hover:not(:disabled, [aria-disabled="true"]) {
442
442
  border-color: var(--ui-button-hover-border, var(--_tone-hover));
443
443
  background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
444
444
  }
445
445
 
446
446
  /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
447
- [data-component~="ui-button"][data-v-0c121308]:active:not(:disabled, [aria-disabled="true"]) {
447
+ [data-component~="ui-button"][data-v-6c8750a9]:active:not(:disabled, [aria-disabled="true"]) {
448
448
  background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
449
449
  background-image: none;
450
450
  box-shadow: var(--ui-pressed);
451
451
  }
452
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-0c121308],
453
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-0c121308] {
452
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-6c8750a9],
453
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-6c8750a9] {
454
454
  border-color: var(--_tone);
455
455
  background-color: var(--_tone);
456
456
  color: var(--_on-tone);
457
457
  box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));
458
458
  }
459
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-0c121308], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-0c121308]):hover:not(:disabled, [aria-disabled="true"]) {
459
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-6c8750a9], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-6c8750a9]):hover:not(:disabled, [aria-disabled="true"]) {
460
460
  background-color: var(--_tone-hover);
461
461
  border-color: var(--_tone-hover);
462
462
  }
463
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-0c121308], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-0c121308]):active:not(:disabled, [aria-disabled="true"]) {
463
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-6c8750a9], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-6c8750a9]):active:not(:disabled, [aria-disabled="true"]) {
464
464
  background-color: var(--_tone-active);
465
465
  border-color: var(--_tone-active);
466
466
  background-image: none;
@@ -469,43 +469,43 @@ ol[data-v-0d86d58e] {
469
469
 
470
470
  /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
471
471
  destructive secondary action, not a special case. */
472
- [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-0c121308] {
472
+ [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-6c8750a9] {
473
473
  --_hue: var(--ui-text);
474
474
  --_hue-hover: var(--ui-text);
475
475
  --_hue-active: var(--ui-text);
476
476
  --_hue-text: var(--ui-text);
477
477
  --_on-hue: var(--ui-surface);
478
478
  }
479
- [data-component~="ui-button"][data-ui-button-state~="tone=danger"][data-v-0c121308],
480
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-0c121308] {
479
+ [data-component~="ui-button"][data-ui-button-state~="tone=danger"][data-v-6c8750a9],
480
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-6c8750a9] {
481
481
  --_hue: var(--ui-danger);
482
482
  --_hue-hover: var(--ui-danger-hover);
483
483
  --_hue-active: var(--ui-danger-hover);
484
484
  --_hue-text: var(--ui-danger-hover);
485
485
  --_on-hue: var(--ui-on-danger);
486
486
  }
487
- [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-0c121308] {
487
+ [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-6c8750a9] {
488
488
  --_hue: var(--ui-success);
489
489
  --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
490
490
  --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
491
491
  --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
492
492
  --_on-hue: var(--ui-surface);
493
493
  }
494
- [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-0c121308] {
494
+ [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-6c8750a9] {
495
495
  --_hue: var(--ui-warning);
496
496
  --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
497
497
  --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
498
498
  --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
499
499
  --_on-hue: var(--ui-surface);
500
500
  }
501
- [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-0c121308] {
501
+ [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-6c8750a9] {
502
502
  --_hue: var(--ui-info);
503
503
  --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
504
504
  --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
505
505
  --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
506
506
  --_on-hue: var(--ui-surface);
507
507
  }
508
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-0c121308] {
508
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-6c8750a9] {
509
509
  border-color: transparent;
510
510
  background: transparent;
511
511
  box-shadow: none;
@@ -513,24 +513,24 @@ ol[data-v-0d86d58e] {
513
513
  }
514
514
 
515
515
  /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
516
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-0c121308]:hover:not(:disabled, [aria-disabled="true"]) {
516
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-6c8750a9]:hover:not(:disabled, [aria-disabled="true"]) {
517
517
  background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
518
518
  border-color: transparent;
519
519
  }
520
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-0c121308]:active:not(:disabled, [aria-disabled="true"]) {
520
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-6c8750a9]:active:not(:disabled, [aria-disabled="true"]) {
521
521
  background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));
522
522
  border-color: transparent;
523
523
  box-shadow: var(--ui-pressed);
524
524
  }
525
525
 
526
526
  /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
527
- [data-component~="ui-button"][data-v-0c121308]:focus-visible {
527
+ [data-component~="ui-button"][data-v-6c8750a9]:focus-visible {
528
528
  outline: none;
529
529
  box-shadow:
530
530
  var(--ui-button-shadow, var(--ui-raised)),
531
531
  var(--ui-focus-halo);
532
532
  }
533
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-0c121308]:focus-visible {
533
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-6c8750a9]:focus-visible {
534
534
  box-shadow:
535
535
  var(--ui-button-solid-shadow, var(--ui-raised)),
536
536
  var(--ui-focus-halo);
@@ -540,7 +540,7 @@ ol[data-v-0d86d58e] {
540
540
  disabled outline is still an outline and a disabled ghost still has no edge. Intent goes — an
541
541
  unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
542
542
  highlight and shadow, because nothing that cannot be pressed should look raised. */
543
- [data-component~="ui-button"][data-v-0c121308]:is(:disabled, [aria-disabled="true"]) {
543
+ [data-component~="ui-button"][data-v-6c8750a9]:is(:disabled, [aria-disabled="true"]) {
544
544
  /* Derived from the tone itself, not from a separate disabled palette: faded toward the
545
545
  page, which desaturates it at the same time. Toward the page rather than toward white,
546
546
  so a dark theme dims where a light one lightens — the same rule, both schemes. */
@@ -557,7 +557,7 @@ ol[data-v-0d86d58e] {
557
557
  }
558
558
 
559
559
  /* A filled button keeps its fill, faded further so its text stays legible on it. */
560
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-0c121308], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-0c121308]):is(:disabled, [aria-disabled="true"]) {
560
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-6c8750a9], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-6c8750a9]):is(:disabled, [aria-disabled="true"]) {
561
561
  --_tone: color-mix(in oklab, var(--_hue) 34%, var(--ui-surface));
562
562
  }
563
563
 
@@ -565,19 +565,34 @@ ol[data-v-0d86d58e] {
565
565
  it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
566
566
  the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
567
567
  hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
568
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-0c121308]:is(:disabled, [aria-disabled="true"]) {
568
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-6c8750a9]:is(:disabled, [aria-disabled="true"]) {
569
569
  background-color: oklch(from var(--_tone) l c h / 14%);
570
570
  border-color: transparent;
571
571
  }
572
572
  @media (pointer: coarse) {
573
- [data-component~="ui-button"][data-v-0c121308] {
573
+ [data-component~="ui-button"][data-v-6c8750a9] {
574
574
  min-block-size: var(--ui-control-min-block-size);
575
575
  }
576
576
  }
577
577
 
578
+ /* Under touch, every button's press lands within the control minimum: an invisible hit area,
579
+ centred on it, like IconButton's. A standalone link-style button (a "See all" beside a
580
+ heading) is a target of its own, not text, so it gets one too. */
581
+ html[data-ui-input-modality="touch"] [data-component~="ui-button"][data-v-6c8750a9] {
582
+ position: relative;
583
+ }
584
+ html[data-ui-input-modality="touch"] [data-component~="ui-button"][data-v-6c8750a9]::after {
585
+ position: absolute;
586
+ inset: 50% auto auto 50%;
587
+ inline-size: max(100%, var(--ui-control-min-block-size));
588
+ block-size: max(100%, var(--ui-control-min-block-size));
589
+ transform: translate(-50%, -50%);
590
+ content: "";
591
+ }
592
+
578
593
  /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under
579
594
  WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */
580
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-0c121308] {
595
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-6c8750a9] {
581
596
  display: inline;
582
597
  min-block-size: 0;
583
598
  padding: 0;
@@ -595,22 +610,22 @@ ol[data-v-0d86d58e] {
595
610
  color var(--ui-motion-fast) var(--ui-motion-ease),
596
611
  text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
597
612
  }
598
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-0c121308]:hover:not(:disabled, [aria-disabled="true"]) {
613
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-6c8750a9]:hover:not(:disabled, [aria-disabled="true"]) {
599
614
  color: var(--ui-button-link-hover-text, var(--ui-text-primary));
600
615
  text-decoration-color: currentColor;
601
616
  background: none;
602
617
  transform: none;
603
618
  }
604
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-0c121308]:active:not(:disabled, [aria-disabled="true"]) {
619
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-6c8750a9]:active:not(:disabled, [aria-disabled="true"]) {
605
620
  background: none;
606
621
  transform: none;
607
622
  }
608
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-0c121308]:is(:disabled, [aria-disabled="true"]) {
623
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-6c8750a9]:is(:disabled, [aria-disabled="true"]) {
609
624
  background: none;
610
625
  border-color: transparent;
611
626
  color: var(--ui-button-disabled-text, var(--ui-disabled-text));
612
627
  }
613
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-0c121308]:focus-visible {
628
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-6c8750a9]:focus-visible {
614
629
  box-shadow: none;
615
630
  /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
616
631
  outline: 2px solid var(--ui-focus-ring);
@@ -618,11 +633,11 @@ ol[data-v-0d86d58e] {
618
633
  }
619
634
 
620
635
  /* A component that sets its display still honours the hidden attribute on its root. */
621
- [data-component~="ui-button"][hidden][data-v-0c121308] {
636
+ [data-component~="ui-button"][hidden][data-v-6c8750a9] {
622
637
  display: none;
623
638
  }
624
639
 
625
- [data-component~="ui-callout"][data-v-2fd6ab30] {
640
+ [data-component~="ui-callout"][data-v-36fb7e55] {
626
641
  --_callout-surface: var(--ui-info-soft);
627
642
  --_callout-border: var(--ui-info-solid);
628
643
  --_callout-icon: var(--ui-info-solid);
@@ -648,43 +663,51 @@ ol[data-v-0d86d58e] {
648
663
  }
649
664
 
650
665
  /* One line box tall, so the icon centres on the first line of text. */
651
- .icon[data-v-2fd6ab30] {
666
+ .icon[data-v-36fb7e55] {
652
667
  display: grid;
653
668
  place-items: center;
654
669
  inline-size: var(--ui-callout-icon-column, 1.125rem);
655
670
  block-size: 1lh;
656
671
  color: var(--ui-callout-icon, var(--_callout-icon));
657
672
  }
658
- .icon svg[data-v-2fd6ab30] {
673
+ .icon svg[data-v-36fb7e55] {
659
674
  inline-size: var(--ui-callout-icon-size, 1.125rem);
660
675
  block-size: var(--ui-callout-icon-size, 1.125rem);
661
676
  }
662
- .content[data-v-2fd6ab30] {
677
+ .content[data-v-36fb7e55] {
663
678
  min-inline-size: 0;
664
679
  }
665
- [data-component~="ui-callout"][data-ui-callout-state~="tone=note"][data-v-2fd6ab30] {
680
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=note"][data-v-36fb7e55] {
666
681
  --_callout-surface: var(--ui-surface-muted);
667
682
  --_callout-border: var(--ui-border-strong);
668
683
  --_callout-icon: var(--ui-text-secondary);
669
684
  }
670
- [data-component~="ui-callout"][data-ui-callout-state~="tone=warning"][data-v-2fd6ab30] {
685
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=warning"][data-v-36fb7e55] {
671
686
  --_callout-surface: var(--ui-warning-soft);
672
687
  --_callout-border: var(--ui-warning-solid);
673
688
  --_callout-icon: var(--ui-warning-solid);
674
689
  }
675
- [data-component~="ui-callout"][data-ui-callout-state~="tone=success"][data-v-2fd6ab30] {
690
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=success"][data-v-36fb7e55] {
676
691
  --_callout-surface: var(--ui-success-soft);
677
692
  --_callout-border: var(--ui-success-solid);
678
693
  --_callout-icon: var(--ui-success-solid);
679
694
  }
680
- [data-component~="ui-callout"][data-ui-callout-state~="tone=danger"][data-v-2fd6ab30] {
695
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=danger"][data-v-36fb7e55] {
681
696
  --_callout-surface: var(--ui-danger-soft);
682
697
  --_callout-border: var(--ui-danger-solid);
683
698
  --_callout-icon: var(--ui-danger-solid);
684
699
  }
685
700
 
701
+ /* A link in the callout's text is underlined, so it reads as a link by more than colour. */
702
+ .content a[data-v-36fb7e55-s] {
703
+ color: var(--ui-accent-active);
704
+ text-decoration: underline;
705
+ text-decoration-thickness: 0.06em;
706
+ text-underline-offset: 0.18em;
707
+ }
708
+
686
709
  /* A component that sets its display still honours the hidden attribute on its root. */
687
- [data-component~="ui-callout"][hidden][data-v-2fd6ab30] {
710
+ [data-component~="ui-callout"][hidden][data-v-36fb7e55] {
688
711
  display: none;
689
712
  }
690
713
 
@@ -2869,7 +2892,7 @@ svg[data-v-dc9b5621-s] {
2869
2892
  display: none;
2870
2893
  }
2871
2894
 
2872
- [data-component~="ui-form-field"][data-v-eba1e76b] {
2895
+ [data-component~="ui-form-field"][data-v-4df6c2a6] {
2873
2896
  display: grid;
2874
2897
  gap: var(--ui-space-2);
2875
2898
  min-inline-size: 0;
@@ -2879,30 +2902,32 @@ svg[data-v-dc9b5621-s] {
2879
2902
 
2880
2903
  /* Each named region styles whatever fills it, however it was slotted (slot="…" in HTML, #label
2881
2904
  in Vue), and generates no box of its own, so an empty region adds no gap. */
2882
- .label[data-v-eba1e76b],
2883
- .help[data-v-eba1e76b],
2884
- .error[data-v-eba1e76b] {
2905
+ .label[data-v-4df6c2a6],
2906
+ .help[data-v-4df6c2a6],
2907
+ .error[data-v-4df6c2a6] {
2885
2908
  display: contents;
2886
2909
  }
2887
- .label[data-v-eba1e76b] {
2910
+ .label[data-v-4df6c2a6] {
2888
2911
  color: var(--ui-text-secondary);
2889
2912
  font-size: var(--ui-font-size-sm);
2890
2913
  }
2891
- .help[data-v-eba1e76b] {
2914
+ .help[data-v-4df6c2a6] {
2892
2915
  color: var(--ui-text-muted);
2893
2916
  font-size: var(--ui-font-size-sm);
2894
2917
  line-height: var(--ui-line-height-md);
2895
2918
  }
2896
- .help > [data-v-eba1e76b-s] {
2919
+ .help > [data-v-4df6c2a6-s] {
2897
2920
  min-block-size: var(--ui-form-field-help-min-block-size, 0);
2898
2921
  }
2899
- .error[data-v-eba1e76b],[role="alert"][data-v-eba1e76b-s] {
2900
- color: var(--ui-accent-active);
2922
+
2923
+ /* An error reads in the danger colour, the one the invalid control's border takes. */
2924
+ .error[data-v-4df6c2a6],[role="alert"][data-v-4df6c2a6-s] {
2925
+ color: var(--ui-danger);
2901
2926
  font-size: var(--ui-font-size-sm);
2902
2927
  }
2903
2928
 
2904
2929
  /* A component that sets its display still honours the hidden attribute on its root. */
2905
- [data-component~="ui-form-field"][hidden][data-v-eba1e76b] {
2930
+ [data-component~="ui-form-field"][hidden][data-v-4df6c2a6] {
2906
2931
  display: none;
2907
2932
  }
2908
2933
 
@@ -3123,7 +3148,7 @@ svg[data-v-bcedd63e-s] {
3123
3148
  display: none;
3124
3149
  }
3125
3150
 
3126
- [data-component~="ui-input"][data-v-12ffae5a] {
3151
+ [data-component~="ui-input"][data-v-c19f8322] {
3127
3152
  box-sizing: border-box;
3128
3153
  display: inline-block;
3129
3154
  inline-size: 100%;
@@ -3146,21 +3171,21 @@ svg[data-v-bcedd63e-s] {
3146
3171
  }
3147
3172
 
3148
3173
  /* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */
3149
- [data-component~="ui-input"][data-v-12ffae5a]::selection {
3174
+ [data-component~="ui-input"][data-v-c19f8322]::selection {
3150
3175
  background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
3151
3176
  color: inherit;
3152
3177
  }
3153
- [data-component~="ui-input"][data-v-12ffae5a]::placeholder {
3178
+ [data-component~="ui-input"][data-v-c19f8322]::placeholder {
3154
3179
  color: var(--ui-control-placeholder, var(--ui-text-secondary));
3155
3180
  opacity: 1;
3156
3181
  }
3157
- [data-component~="ui-input"][data-v-12ffae5a]:hover:not(:focus):not(:disabled) {
3182
+ [data-component~="ui-input"][data-v-c19f8322]:hover:not(:focus):not(:disabled) {
3158
3183
  border-color: var(
3159
3184
  --ui-input-border-hover,
3160
3185
  var(--ui-control-border-hover, var(--ui-text-secondary))
3161
3186
  );
3162
3187
  }
3163
- [data-component~="ui-input"][data-v-12ffae5a]:focus-visible {
3188
+ [data-component~="ui-input"][data-v-c19f8322]:focus-visible {
3164
3189
  border-color: var(--ui-input-focus-border, var(--ui-control-focus, var(--ui-accent-solid)));
3165
3190
  outline: none;
3166
3191
  box-shadow: var(
@@ -3171,16 +3196,18 @@ svg[data-v-bcedd63e-s] {
3171
3196
  }
3172
3197
 
3173
3198
  /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
3174
- [data-component~="ui-input"][aria-invalid="true"][data-v-12ffae5a],
3175
- [data-component~="ui-input"][data-v-12ffae5a]:is(:user-invalid, [data-user-invalid]) {
3176
- border-color: var(--ui-danger-solid);
3199
+ [data-component~="ui-input"][aria-invalid="true"][data-v-c19f8322],
3200
+ [data-component~="ui-input"][data-v-c19f8322]:is(:user-invalid, [data-user-invalid]) {
3201
+ border-color: var(--ui-input-invalid-border, var(--ui-danger-solid));
3177
3202
  }
3178
- [data-component~="ui-input"][data-v-12ffae5a]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
3179
- box-shadow:
3203
+ [data-component~="ui-input"][data-v-c19f8322]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
3204
+ box-shadow: var(
3205
+ --ui-input-invalid-focus-shadow,
3180
3206
  var(--ui-control-inset),
3181
- 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent);
3207
+ 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent)
3208
+ );
3182
3209
  }
3183
- [data-component~="ui-input"][data-v-12ffae5a]:disabled {
3210
+ [data-component~="ui-input"][data-v-c19f8322]:disabled {
3184
3211
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
3185
3212
  color: var(--ui-text-muted);
3186
3213
  box-shadow: none;
@@ -3191,7 +3218,7 @@ svg[data-v-bcedd63e-s] {
3191
3218
  * scroll vertically inside the field. Native inputs already center their single line. */
3192
3219
 
3193
3220
  /* A component that sets its display still honours the hidden attribute on its root. */
3194
- [data-component~="ui-input"][hidden][data-v-12ffae5a] {
3221
+ [data-component~="ui-input"][hidden][data-v-c19f8322] {
3195
3222
  display: none;
3196
3223
  }
3197
3224
 
@@ -3201,10 +3228,12 @@ svg[data-v-bcedd63e-s] {
3201
3228
  its custom properties, so it is still the one ui-input, with its form behaviour intact. The
3202
3229
  affixes are plain text beside the input, so name the input with a label that says what the
3203
3230
  whole value is. */
3204
- [data-component~="ui-input-group"][data-v-0a135fc1] {
3231
+ [data-component~="ui-input-group"][data-v-42ff173c] {
3205
3232
  --ui-input-border: transparent;
3206
3233
  --ui-input-border-hover: transparent;
3207
3234
  --ui-input-focus-border: transparent;
3235
+ --ui-input-invalid-border: transparent;
3236
+ --ui-input-invalid-focus-shadow: none;
3208
3237
  --ui-input-shadow: none;
3209
3238
  --ui-input-focus-shadow: none;
3210
3239
  --ui-input-radius: 0;
@@ -3225,28 +3254,28 @@ svg[data-v-bcedd63e-s] {
3225
3254
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
3226
3255
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
3227
3256
  }
3228
- [data-component~="ui-input-group"][data-v-0a135fc1]:hover:not(:focus-within) {
3257
+ [data-component~="ui-input-group"][data-v-42ff173c]:hover:not(:focus-within) {
3229
3258
  border-color: var(--ui-text-secondary);
3230
3259
  }
3231
- [data-component~="ui-input-group"][data-v-0a135fc1]:focus-within {
3260
+ [data-component~="ui-input-group"][data-v-42ff173c]:focus-within {
3232
3261
  border-color: var(--ui-accent-solid);
3233
3262
  box-shadow:
3234
3263
  var(--ui-control-inset),
3235
3264
  var(--ui-control-focus-halo-shadow);
3236
3265
  }
3237
- [data-component~="ui-input-group"][data-v-0a135fc1]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
3266
+ [data-component~="ui-input-group"][data-v-42ff173c]:has([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])) {
3238
3267
  border-color: var(--ui-danger-solid);
3239
3268
  }
3240
- [data-component~="ui-input-group"][data-ui-input-group-state~="disabled"][data-v-0a135fc1] {
3269
+ [data-component~="ui-input-group"][data-ui-input-group-state~="disabled"][data-v-42ff173c] {
3241
3270
  background: var(--ui-surface-muted);
3242
3271
  box-shadow: none;
3243
3272
  }
3244
- .field[data-v-0a135fc1] {
3273
+ .field[data-v-42ff173c] {
3245
3274
  display: flex;
3246
3275
  flex: 1;
3247
3276
  min-inline-size: 0;
3248
3277
  }
3249
- .affix[data-v-0a135fc1] {
3278
+ .affix[data-v-42ff173c] {
3250
3279
  display: inline-flex;
3251
3280
  flex: none;
3252
3281
  align-items: center;
@@ -3256,12 +3285,12 @@ svg[data-v-bcedd63e-s] {
3256
3285
  font-size: var(--ui-font-size-sm);
3257
3286
  white-space: nowrap;
3258
3287
  }
3259
- .affix[data-v-0a135fc1]:empty {
3288
+ .affix[data-v-42ff173c]:empty {
3260
3289
  display: none;
3261
3290
  }
3262
3291
 
3263
3292
  /* A component that sets its display still honours the hidden attribute on its root. */
3264
- [data-component~="ui-input-group"][hidden][data-v-0a135fc1] {
3293
+ [data-component~="ui-input-group"][hidden][data-v-42ff173c] {
3265
3294
  display: none;
3266
3295
  }
3267
3296
 
@@ -4788,72 +4817,81 @@ input[data-v-26ab3add], input[data-v-26ab3add]::after {
4788
4817
 
4789
4818
  /* Running text, set on the type scale and in a tone that says what it is, so a view never styles
4790
4819
  text of its own. The root is a paragraph unless as= names a span, div, small, strong, or label. */
4791
- [data-component~="ui-text"][data-v-70a75450] {
4820
+ [data-component~="ui-text"][data-v-b83a3ab9] {
4792
4821
  margin: 0;
4793
4822
  min-inline-size: 0;
4794
4823
  color: var(--ui-text-primary);
4795
4824
  text-align: start;
4796
4825
  }
4797
- [data-component~="ui-text"][data-ui-text-state~="size=xs"][data-v-70a75450] {
4826
+ [data-component~="ui-text"][data-ui-text-state~="size=xs"][data-v-b83a3ab9] {
4798
4827
  font-size: var(--ui-font-size-xs);
4799
4828
  line-height: var(--ui-line-height);
4800
4829
  }
4801
- [data-component~="ui-text"][data-ui-text-state~="size=sm"][data-v-70a75450] {
4830
+ [data-component~="ui-text"][data-ui-text-state~="size=sm"][data-v-b83a3ab9] {
4802
4831
  font-size: var(--ui-font-size-sm);
4803
4832
  line-height: var(--ui-line-height);
4804
4833
  }
4805
- [data-component~="ui-text"][data-ui-text-state~="size=md"][data-v-70a75450] {
4834
+ [data-component~="ui-text"][data-ui-text-state~="size=md"][data-v-b83a3ab9] {
4806
4835
  font-size: var(--ui-font-size-md);
4807
4836
  line-height: var(--ui-line-height);
4808
4837
  }
4809
- [data-component~="ui-text"][data-ui-text-state~="size=lg"][data-v-70a75450] {
4838
+ [data-component~="ui-text"][data-ui-text-state~="size=lg"][data-v-b83a3ab9] {
4810
4839
  font-size: var(--ui-font-size-lg);
4811
4840
  line-height: var(--ui-line-height-relaxed);
4812
4841
  }
4813
- [data-component~="ui-text"][data-ui-text-state~="tone=secondary"][data-v-70a75450] {
4842
+ [data-component~="ui-text"][data-ui-text-state~="tone=secondary"][data-v-b83a3ab9] {
4814
4843
  color: var(--ui-text-secondary);
4815
4844
  }
4816
- [data-component~="ui-text"][data-ui-text-state~="tone=muted"][data-v-70a75450] {
4845
+ [data-component~="ui-text"][data-ui-text-state~="tone=muted"][data-v-b83a3ab9] {
4817
4846
  color: var(--ui-text-muted);
4818
4847
  }
4819
- [data-component~="ui-text"][data-ui-text-state~="tone=accent"][data-v-70a75450] {
4848
+ [data-component~="ui-text"][data-ui-text-state~="tone=accent"][data-v-b83a3ab9] {
4820
4849
  color: var(--ui-accent-active);
4821
4850
  }
4822
- [data-component~="ui-text"][data-ui-text-state~="tone=danger"][data-v-70a75450] {
4851
+ [data-component~="ui-text"][data-ui-text-state~="tone=danger"][data-v-b83a3ab9] {
4823
4852
  color: var(--ui-danger);
4824
4853
  }
4825
- [data-component~="ui-text"][data-ui-text-state~="tone=success"][data-v-70a75450] {
4854
+ [data-component~="ui-text"][data-ui-text-state~="tone=success"][data-v-b83a3ab9] {
4826
4855
  color: var(--ui-success);
4827
4856
  }
4828
- [data-component~="ui-text"][data-ui-text-state~="weight=normal"][data-v-70a75450] {
4857
+ [data-component~="ui-text"][data-ui-text-state~="weight=normal"][data-v-b83a3ab9] {
4829
4858
  font-weight: var(--ui-font-normal);
4830
4859
  }
4831
- [data-component~="ui-text"][data-ui-text-state~="weight=medium"][data-v-70a75450] {
4860
+ [data-component~="ui-text"][data-ui-text-state~="weight=medium"][data-v-b83a3ab9] {
4832
4861
  font-weight: var(--ui-font-medium);
4833
4862
  }
4834
- [data-component~="ui-text"][data-ui-text-state~="weight=semibold"][data-v-70a75450] {
4863
+ [data-component~="ui-text"][data-ui-text-state~="weight=semibold"][data-v-b83a3ab9] {
4835
4864
  font-weight: var(--ui-font-semibold);
4836
4865
  }
4837
- [data-component~="ui-text"][data-ui-text-state~="variant=eyebrow"][data-v-70a75450] {
4866
+ [data-component~="ui-text"][data-ui-text-state~="variant=eyebrow"][data-v-b83a3ab9] {
4838
4867
  font-size: var(--ui-font-size-xs);
4839
4868
  font-weight: var(--ui-font-semibold);
4840
4869
  letter-spacing: 0.06em;
4841
4870
  text-transform: uppercase;
4842
4871
  }
4843
- [data-component~="ui-text"][data-ui-text-state~="variant=code"][data-v-70a75450] {
4872
+ [data-component~="ui-text"][data-ui-text-state~="variant=code"][data-v-b83a3ab9] {
4844
4873
  font-family: var(--ui-font-family-mono);
4845
4874
  }
4846
- [data-component~="ui-text"][data-ui-text-state~="truncate"][data-v-70a75450] {
4875
+
4876
+ /* A link in running text is underlined, so it stands apart from the words around it by more than
4877
+ colour. */
4878
+ [data-component~="ui-text"] a[data-v-b83a3ab9-s] {
4879
+ color: var(--ui-accent-active);
4880
+ text-decoration: underline;
4881
+ text-decoration-thickness: 0.06em;
4882
+ text-underline-offset: 0.18em;
4883
+ }
4884
+ [data-component~="ui-text"][data-ui-text-state~="truncate"][data-v-b83a3ab9] {
4847
4885
  overflow: hidden;
4848
4886
  text-overflow: ellipsis;
4849
4887
  white-space: nowrap;
4850
4888
  }
4851
- [data-component~="ui-text"][data-ui-text-state~="align=center"][data-v-70a75450] {
4889
+ [data-component~="ui-text"][data-ui-text-state~="align=center"][data-v-b83a3ab9] {
4852
4890
  text-align: center;
4853
4891
  }
4854
4892
 
4855
4893
  /* A component that sets its display still honours the hidden attribute on its root. */
4856
- [data-component~="ui-text"][hidden][data-v-70a75450] {
4894
+ [data-component~="ui-text"][hidden][data-v-b83a3ab9] {
4857
4895
  display: none;
4858
4896
  }
4859
4897