@anyblades/blades 2.3.2 → 2.4.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.
package/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # 🥷 *Bl*ades &nbsp;<img src='https://img.shields.io/npm/v/@anyblades/blades?label=&color=white'>
1
+ # 🥷 *Bl*ades &nbsp;![][B_NPM]
2
+
3
+ [B_NPM]: https://img.shields.io/npm/v/@anyblades/blades?label=&color=white
2
4
 
3
5
  <!--section:summary-->
4
6
 
@@ -59,7 +61,7 @@ Live example using <i class="fa-brands fa-tailwind-css"></i> Tailwind: https://g
59
61
  - https://github.com/getgrav/grav-theme-quark2 for Grav CMS v2
60
62
  - https://jekyll.blades.ninja/ starter <!--{.faded}-->
61
63
 
62
- ### Standalone version
64
+ ### Standalone versions
63
65
 
64
66
  - https://blades.ninja/css/standalone/
65
67
 
@@ -0,0 +1,9 @@
1
+ <ul>
2
+ {%- for link in links %}
3
+ <li>
4
+ <a href="{{ link.url }}" {% if link.url == current_url %}aria-current="page"{% endif %}>
5
+ {{- link.title | safe -}}
6
+ </a>
7
+ </li>
8
+ {%- endfor %}
9
+ </ul>
package/blades.gemspec CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "blades"
5
- spec.version = "2.3.2"
5
+ spec.version = "2.4.0"
6
+
6
7
  spec.authors = ["Anton Staroverov"]
7
-
8
- spec.summary = "Fully compatible and actively maintained successor to Pico CSS."
9
- spec.homepage = "https://github.com/anyblades/blades"
8
+ spec.homepage = "https://blades.ninja/"
10
9
  spec.license = "MIT"
10
+ spec.summary = "Fully compatible and actively maintained successor to Pico CSS."
11
11
 
12
12
  spec.files = Dir.glob("{_includes,css}/**/*")
13
13
  # puts "spec.files: #{spec.files.inspect}"
package/css/blades.css CHANGED
@@ -3498,11 +3498,7 @@ The `<pre><code>` blocks are Prism-compatible and support captions via `data-cap
3498
3498
  ```
3499
3499
  How it works:
3500
3500
  ```css */
3501
- pre {
3502
- padding: 1rem 1.5rem;
3503
- padding-inline-end: 2rem;
3504
- }
3505
- @media (max-width: 767px) {
3501
+ @media (width < 768px) {
3506
3502
  pre {
3507
3503
  border-radius: 0
3508
3504
  }
@@ -3515,9 +3511,6 @@ code[data-caption]::before {
3515
3511
  font-style: italic;
3516
3512
  opacity: 50%;
3517
3513
  }
3518
- code:where(pre > *) {
3519
- padding: 0;
3520
- }
3521
3514
  /*```
3522
3515
  \3c !--section--> */
3523
3516
  /* Forms */
@@ -3526,9 +3519,9 @@ code:where(pre > *) {
3526
3519
 
3527
3520
  First, we target either:
3528
3521
  1. `<label>` which `:has` inner form inputs (classless approach)
3529
- 2. or explicit `.has-float-label` class (alternative approach)
3522
+ 2. or explicit `.has-float-label` class (explicit approach)
3530
3523
  ```css */
3531
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
3524
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
3532
3525
  .has-float-label {
3533
3526
  display: block;
3534
3527
  position: relative;
@@ -3537,8 +3530,8 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
3537
3530
  ```
3538
3531
  Then, we define the default/fallback state (when the float label should be minimized):
3539
3532
  ```css */
3540
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
3541
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
3533
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
3534
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
3542
3535
  .has-float-label > span,
3543
3536
  .has-float-label label {
3544
3537
  position: absolute;
@@ -3551,21 +3544,21 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
3551
3544
  ```
3552
3545
  Finally, we detect if placeholder is shown, but not in focus. That means we can safely hide it, and enlarge the float label instead:
3553
3546
  ```css */
3554
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
3547
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
3555
3548
  opacity: 0;
3556
3549
  }
3557
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
3550
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
3558
3551
  opacity: 0;
3559
3552
  }
3560
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
3553
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
3561
3554
  opacity: 0;
3562
3555
  }
3563
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
3556
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
3564
3557
  font-size: inherit;
3565
3558
  opacity: 50%;
3566
3559
  }
3567
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
3568
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
3560
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
3561
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
3569
3562
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
3570
3563
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
3571
3564
  font-size: inherit;
@@ -3577,6 +3570,29 @@ The `:has(*:placeholder-shown:not(:focus))` trick allows this input state inform
3577
3570
 
3578
3571
  Historically, this was not possible: the float label had to be placed after the input field to be targeted using the `input:focus + label` selector.
3579
3572
  \3c !--section--> */
3573
+ /* Components */
3574
+ /*\3c !--section:docs-->
3575
+
3576
+ Use `dl.timeline` or wrap a `<dl>` with `.has-timeline` to style it as a
3577
+ vertical timeline — each `<dd>` gets a left border strip acting as the track:
3578
+
3579
+ <article class="has-timeline">
3580
+
3581
+ May 11, 2026
3582
+ : First Blades CSS stable release (v2.2.0).
3583
+
3584
+ Mar 15, 2025
3585
+ : Last Pico CSS update (v2.1.1).
3586
+
3587
+ </article>
3588
+
3589
+ \3c !--section:code-->```css */
3590
+ dl.timeline dd, .has-timeline > dl dd {
3591
+ margin-block: 0;
3592
+ padding: 0.25rem 0 0.75rem 1rem;
3593
+ border-inline-start: 0.25rem solid gray;
3594
+ }
3595
+ /*```*/
3580
3596
  /* Utilities */
3581
3597
  /* Extends https://github.com/picocss/pico/tree/main/scss/utilities
3582
3598
  \3c !--section:docs-->
@@ -3636,8 +3652,8 @@ How it works:
3636
3652
  \3c !--section:code-->
3637
3653
  ```css */
3638
3654
  /* Default/fallback state */
3639
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
3640
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
3655
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
3656
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
3641
3657
  .has-float-label > span,
3642
3658
  .has-float-label label {
3643
3659
  padding-inline-start: calc(1rem + 1px); /* match Pico's padding + border */
@@ -3645,9 +3661,9 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
3645
3661
  opacity: 75%;
3646
3662
  transition: all 0.25s;
3647
3663
  }
3648
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
3649
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
3650
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
3664
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
3665
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
3666
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
3651
3667
  .has-float-label input,
3652
3668
  .has-float-label textarea,
3653
3669
  .has-float-label select {
@@ -3655,21 +3671,21 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
3655
3671
  padding-inline-start: 1rem; /* match Pico */
3656
3672
  padding-block: 1.125rem 0.375rem; /* match Pico's total: 2 x 0.75rem = 1.5rem */
3657
3673
  }
3658
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
3674
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
3659
3675
  opacity: 100%;
3660
3676
  -moz-transition: all 0.25s;
3661
3677
  transition: all 0.25s;
3662
3678
  }
3663
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
3679
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
3664
3680
  opacity: 100%;
3665
3681
  transition: all 0.25s;
3666
3682
  }
3667
3683
  /* Enlarged state */
3668
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
3684
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
3669
3685
  padding-block: 0.75rem; /* match Pico */
3670
3686
  }
3671
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
3672
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
3687
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
3688
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
3673
3689
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
3674
3690
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
3675
3691
  padding-block: 0.75rem; /* match Pico */
@@ -3712,6 +3728,14 @@ a:not([href^="#"]) {
3712
3728
  a:not([href^="#"]):hover {
3713
3729
  text-decoration-thickness: 2px;
3714
3730
  }
3731
+ h1,
3732
+ h2,
3733
+ h3,
3734
+ h4,
3735
+ h5,
3736
+ h6 {
3737
+ text-wrap: balance;
3738
+ }
3715
3739
  h1 {
3716
3740
  margin-bottom: 1rem; /* for tw-typography */
3717
3741
  font-size: 2.5em; /* for pico.css & tw-typography */
@@ -3722,10 +3746,20 @@ hr {
3722
3746
  ul ul {
3723
3747
  font-size: 87.5%;
3724
3748
  }
3749
+ dl dt {
3750
+ margin-block: 0.25rem;
3751
+ font-weight: 500;
3752
+ }
3753
+ dl dd {
3754
+ margin-block-end: 1rem;
3755
+ }
3725
3756
  pre small {
3726
3757
  font-weight: lighter;
3727
3758
  opacity: 75%;
3728
3759
  }
3760
+ pre:has(code) {
3761
+ background: #181c25 !important;
3762
+ }
3729
3763
  table th {
3730
3764
  font-weight: bold;
3731
3765
  vertical-align: bottom;
@@ -0,0 +1,54 @@
1
+ /*\3c !--section:docs-->
2
+
3
+ ### `sup`er &nbsp; and &nbsp; `sub`headings
4
+
5
+ <article><br>
6
+
7
+ # <sup style>Parent page</sup> Page title <sub style>Subtitle</sub>
8
+
9
+ </article>
10
+
11
+ How it works:
12
+ ```css */
13
+ sup[style] {
14
+ display: block;
15
+ font-size: 0.75rem;
16
+ letter-spacing: 0.0625em;
17
+ text-transform: uppercase;
18
+ }
19
+ sub[style] {
20
+ display: block;
21
+ bottom: 0;
22
+ font-weight: 300;
23
+ line-height: 1.1;
24
+ opacity: 75%;
25
+ }
26
+ sub[style]:where(h1 > *) {
27
+ font-size: 50%;
28
+ }
29
+ /*```
30
+
31
+ ### `.opt`ional content
32
+
33
+ How it works:
34
+ ```css */
35
+ @media (width < 1024px) {
36
+ .opt {
37
+ display: none
38
+ }
39
+ }
40
+ /*```
41
+
42
+ ### Nicer GitHub favicons
43
+
44
+ How it works:
45
+ ```css */
46
+ img[src*="?domain=github.com&"] {
47
+ border-radius: 50%;
48
+ }
49
+ @media (prefers-color-scheme: dark) {
50
+ img[src*="?domain=github.com&"] {
51
+ filter: invert(1)
52
+ }
53
+ }
54
+ /*```*/
@@ -551,12 +551,7 @@ The `<pre><code>` blocks are Prism-compatible and support captions via `data-cap
551
551
  How it works:
552
552
  ```css */
553
553
 
554
- pre {
555
- padding: 1rem 1.5rem;
556
- padding-inline-end: 2rem;
557
- }
558
-
559
- @media (max-width: 767px) {
554
+ @media (width < 768px) {
560
555
 
561
556
  pre {
562
557
  border-radius: 0
@@ -573,10 +568,6 @@ code[data-caption]::before {
573
568
  opacity: 50%;
574
569
  }
575
570
 
576
- code:where(pre > *) {
577
- padding: 0;
578
- }
579
-
580
571
  /*```
581
572
  \3c !--section--> */
582
573
 
@@ -587,10 +578,10 @@ code:where(pre > *) {
587
578
 
588
579
  First, we target either:
589
580
  1. `<label>` which `:has` inner form inputs (classless approach)
590
- 2. or explicit `.has-float-label` class (alternative approach)
581
+ 2. or explicit `.has-float-label` class (explicit approach)
591
582
  ```css */
592
583
 
593
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
584
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
594
585
  .has-float-label {
595
586
  display: block;
596
587
  position: relative;
@@ -601,8 +592,8 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
601
592
  Then, we define the default/fallback state (when the float label should be minimized):
602
593
  ```css */
603
594
 
604
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
605
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
595
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
596
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
606
597
  .has-float-label > span,
607
598
  .has-float-label label {
608
599
  position: absolute;
@@ -617,25 +608,25 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
617
608
  Finally, we detect if placeholder is shown, but not in focus. That means we can safely hide it, and enlarge the float label instead:
618
609
  ```css */
619
610
 
620
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
611
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
621
612
  opacity: 0;
622
613
  }
623
614
 
624
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
615
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
625
616
  opacity: 0;
626
617
  }
627
618
 
628
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
619
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
629
620
  opacity: 0;
630
621
  }
631
622
 
632
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
623
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
633
624
  font-size: inherit;
634
625
  opacity: 50%;
635
626
  }
636
627
 
637
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
638
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
628
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
629
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
639
630
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
640
631
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
641
632
  font-size: inherit;
@@ -649,6 +640,33 @@ The `:has(*:placeholder-shown:not(:focus))` trick allows this input state inform
649
640
  Historically, this was not possible: the float label had to be placed after the input field to be targeted using the `input:focus + label` selector.
650
641
  \3c !--section--> */
651
642
 
643
+ /* Components */
644
+
645
+ /*\3c !--section:docs-->
646
+
647
+ Use `dl.timeline` or wrap a `<dl>` with `.has-timeline` to style it as a
648
+ vertical timeline — each `<dd>` gets a left border strip acting as the track:
649
+
650
+ <article class="has-timeline">
651
+
652
+ May 11, 2026
653
+ : First Blades CSS stable release (v2.2.0).
654
+
655
+ Mar 15, 2025
656
+ : Last Pico CSS update (v2.1.1).
657
+
658
+ </article>
659
+
660
+ \3c !--section:code-->```css */
661
+
662
+ dl.timeline dd, .has-timeline > dl dd {
663
+ margin-block: 0;
664
+ padding: 0.25rem 0 0.75rem 1rem;
665
+ border-inline-start: 0.25rem solid gray;
666
+ }
667
+
668
+ /*```*/
669
+
652
670
  /* Utilities */
653
671
 
654
672
  /* Extends https://github.com/picocss/pico/tree/main/scss/utilities
@@ -551,12 +551,7 @@ The `<pre><code>` blocks are Prism-compatible and support captions via `data-cap
551
551
  How it works:
552
552
  ```css */
553
553
 
554
- pre {
555
- padding: 1rem 1.5rem;
556
- padding-inline-end: 2rem;
557
- }
558
-
559
- @media (max-width: 767px) {
554
+ @media (width < 768px) {
560
555
 
561
556
  pre {
562
557
  border-radius: 0
@@ -573,10 +568,6 @@ code[data-caption]::before {
573
568
  opacity: 50%;
574
569
  }
575
570
 
576
- code:where(pre > *) {
577
- padding: 0;
578
- }
579
-
580
571
  /*```
581
572
  \3c !--section--> */
582
573
 
@@ -587,10 +578,10 @@ code:where(pre > *) {
587
578
 
588
579
  First, we target either:
589
580
  1. `<label>` which `:has` inner form inputs (classless approach)
590
- 2. or explicit `.has-float-label` class (alternative approach)
581
+ 2. or explicit `.has-float-label` class (explicit approach)
591
582
  ```css */
592
583
 
593
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
584
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
594
585
  .has-float-label {
595
586
  display: block;
596
587
  position: relative;
@@ -601,8 +592,8 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
601
592
  Then, we define the default/fallback state (when the float label should be minimized):
602
593
  ```css */
603
594
 
604
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
605
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
595
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
596
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
606
597
  .has-float-label > span,
607
598
  .has-float-label label {
608
599
  position: absolute;
@@ -617,25 +608,25 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
617
608
  Finally, we detect if placeholder is shown, but not in focus. That means we can safely hide it, and enlarge the float label instead:
618
609
  ```css */
619
610
 
620
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
611
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
621
612
  opacity: 0;
622
613
  }
623
614
 
624
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
615
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
625
616
  opacity: 0;
626
617
  }
627
618
 
628
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
619
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
629
620
  opacity: 0;
630
621
  }
631
622
 
632
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
623
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
633
624
  font-size: inherit;
634
625
  opacity: 50%;
635
626
  }
636
627
 
637
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
638
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
628
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
629
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
639
630
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
640
631
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
641
632
  font-size: inherit;
@@ -649,6 +640,33 @@ The `:has(*:placeholder-shown:not(:focus))` trick allows this input state inform
649
640
  Historically, this was not possible: the float label had to be placed after the input field to be targeted using the `input:focus + label` selector.
650
641
  \3c !--section--> */
651
642
 
643
+ /* Components */
644
+
645
+ /*\3c !--section:docs-->
646
+
647
+ Use `dl.timeline` or wrap a `<dl>` with `.has-timeline` to style it as a
648
+ vertical timeline — each `<dd>` gets a left border strip acting as the track:
649
+
650
+ <article class="has-timeline">
651
+
652
+ May 11, 2026
653
+ : First Blades CSS stable release (v2.2.0).
654
+
655
+ Mar 15, 2025
656
+ : Last Pico CSS update (v2.1.1).
657
+
658
+ </article>
659
+
660
+ \3c !--section:code-->```css */
661
+
662
+ dl.timeline dd, .has-timeline > dl dd {
663
+ margin-block: 0;
664
+ padding: 0.25rem 0 0.75rem 1rem;
665
+ border-inline-start: 0.25rem solid gray;
666
+ }
667
+
668
+ /*```*/
669
+
652
670
  /* Utilities */
653
671
 
654
672
  /* Extends https://github.com/picocss/pico/tree/main/scss/utilities
@@ -725,8 +743,8 @@ How it works:
725
743
 
726
744
  /* Default/fallback state */
727
745
 
728
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
729
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
746
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
747
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
730
748
  .has-float-label > span,
731
749
  .has-float-label label {
732
750
  padding-inline-start: calc(1rem + 1px); /* match Pico's padding + border */
@@ -735,9 +753,9 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
735
753
  transition: all 0.25s;
736
754
  }
737
755
 
738
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
739
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
740
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
756
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
757
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
758
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
741
759
  .has-float-label input,
742
760
  .has-float-label textarea,
743
761
  .has-float-label select {
@@ -746,25 +764,25 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
746
764
  padding-block: 1.125rem 0.375rem; /* match Pico's total: 2 x 0.75rem = 1.5rem */
747
765
  }
748
766
 
749
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
767
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
750
768
  opacity: 100%;
751
769
  -moz-transition: all 0.25s;
752
770
  transition: all 0.25s;
753
771
  }
754
772
 
755
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
773
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
756
774
  opacity: 100%;
757
775
  transition: all 0.25s;
758
776
  }
759
777
 
760
778
  /* Enlarged state */
761
779
 
762
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
780
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
763
781
  padding-block: 0.75rem; /* match Pico */
764
782
  }
765
783
 
766
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
767
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
784
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
785
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
768
786
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
769
787
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
770
788
  padding-block: 0.75rem; /* match Pico */
@@ -815,6 +833,15 @@ a:not([href^="#"]):hover {
815
833
  text-decoration-thickness: 2px;
816
834
  }
817
835
 
836
+ h1,
837
+ h2,
838
+ h3,
839
+ h4,
840
+ h5,
841
+ h6 {
842
+ text-wrap: balance;
843
+ }
844
+
818
845
  h1 {
819
846
  margin-bottom: 1rem; /* for tw-typography */
820
847
  font-size: 2.5em; /* for pico.css & tw-typography */
@@ -828,11 +855,24 @@ ul ul {
828
855
  font-size: 87.5%;
829
856
  }
830
857
 
858
+ dl dt {
859
+ margin-block: 0.25rem;
860
+ font-weight: 500;
861
+ }
862
+
863
+ dl dd {
864
+ margin-block-end: 1rem;
865
+ }
866
+
831
867
  pre small {
832
868
  font-weight: lighter;
833
869
  opacity: 75%;
834
870
  }
835
871
 
872
+ pre:has(code) {
873
+ background: #181c25 !important;
874
+ }
875
+
836
876
  table th {
837
877
  font-weight: bold;
838
878
  vertical-align: bottom;
@@ -2,8 +2,8 @@
2
2
  \3c !--section:code-->
3
3
  ```css */
4
4
  /* Default/fallback state */
5
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
6
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
5
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
6
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
7
7
  .has-float-label > span,
8
8
  .has-float-label label {
9
9
  padding-inline-start: calc(1rem + 1px); /* match Pico's padding + border */
@@ -11,9 +11,9 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
11
11
  opacity: 75%;
12
12
  transition: all 0.25s;
13
13
  }
14
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
15
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
16
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
14
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
15
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
16
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
17
17
  .has-float-label input,
18
18
  .has-float-label textarea,
19
19
  .has-float-label select {
@@ -21,21 +21,21 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
21
21
  padding-inline-start: 1rem; /* match Pico */
22
22
  padding-block: 1.125rem 0.375rem; /* match Pico's total: 2 x 0.75rem = 1.5rem */
23
23
  }
24
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
24
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
25
25
  opacity: 100%;
26
26
  -moz-transition: all 0.25s;
27
27
  transition: all 0.25s;
28
28
  }
29
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
29
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
30
30
  opacity: 100%;
31
31
  transition: all 0.25s;
32
32
  }
33
33
  /* Enlarged state */
34
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
34
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
35
35
  padding-block: 0.75rem; /* match Pico */
36
36
  }
37
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
38
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
37
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
38
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
39
39
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
40
40
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
41
41
  padding-block: 0.75rem; /* match Pico */
@@ -78,6 +78,14 @@ a:not([href^="#"]) {
78
78
  a:not([href^="#"]):hover {
79
79
  text-decoration-thickness: 2px;
80
80
  }
81
+ h1,
82
+ h2,
83
+ h3,
84
+ h4,
85
+ h5,
86
+ h6 {
87
+ text-wrap: balance;
88
+ }
81
89
  h1 {
82
90
  margin-bottom: 1rem; /* for tw-typography */
83
91
  font-size: 2.5em; /* for pico.css & tw-typography */
@@ -88,10 +96,20 @@ hr {
88
96
  ul ul {
89
97
  font-size: 87.5%;
90
98
  }
99
+ dl dt {
100
+ margin-block: 0.25rem;
101
+ font-weight: 500;
102
+ }
103
+ dl dd {
104
+ margin-block-end: 1rem;
105
+ }
91
106
  pre small {
92
107
  font-weight: lighter;
93
108
  opacity: 75%;
94
109
  }
110
+ pre:has(code) {
111
+ background: #181c25 !important;
112
+ }
95
113
  table th {
96
114
  font-weight: bold;
97
115
  vertical-align: bottom;
@@ -3,9 +3,9 @@
3
3
 
4
4
  First, we target either:
5
5
  1. `<label>` which `:has` inner form inputs (classless approach)
6
- 2. or explicit `.has-float-label` class (alternative approach)
6
+ 2. or explicit `.has-float-label` class (explicit approach)
7
7
  ```css */
8
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
8
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
9
9
  .has-float-label {
10
10
  display: block;
11
11
  position: relative;
@@ -14,8 +14,8 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
14
14
  ```
15
15
  Then, we define the default/fallback state (when the float label should be minimized):
16
16
  ```css */
17
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
18
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
17
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
18
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
19
19
  .has-float-label > span,
20
20
  .has-float-label label {
21
21
  position: absolute;
@@ -28,21 +28,21 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
28
28
  ```
29
29
  Finally, we detect if placeholder is shown, but not in focus. That means we can safely hide it, and enlarge the float label instead:
30
30
  ```css */
31
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
31
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
32
32
  opacity: 0;
33
33
  }
34
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
34
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
35
35
  opacity: 0;
36
36
  }
37
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
37
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
38
38
  opacity: 0;
39
39
  }
40
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
40
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
41
41
  font-size: inherit;
42
42
  opacity: 50%;
43
43
  }
44
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
45
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
44
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
45
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
46
46
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
47
47
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
48
48
  font-size: inherit;
@@ -4,9 +4,9 @@
4
4
 
5
5
  First, we target either:
6
6
  1. `<label>` which `:has` inner form inputs (classless approach)
7
- 2. or explicit `.has-float-label` class (alternative approach)
7
+ 2. or explicit `.has-float-label` class (explicit approach)
8
8
  ```css */
9
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
9
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
10
10
  .has-float-label {
11
11
  display: block;
12
12
  position: relative;
@@ -15,8 +15,8 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
15
15
  ```
16
16
  Then, we define the default/fallback state (when the float label should be minimized):
17
17
  ```css */
18
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
19
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
18
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
19
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
20
20
  .has-float-label > span,
21
21
  .has-float-label label {
22
22
  position: absolute;
@@ -29,21 +29,21 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
29
29
  ```
30
30
  Finally, we detect if placeholder is shown, but not in focus. That means we can safely hide it, and enlarge the float label instead:
31
31
  ```css */
32
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
32
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::-moz-placeholder, .has-float-label *:placeholder-shown:not(:focus)::-moz-placeholder {
33
33
  opacity: 0;
34
34
  }
35
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
35
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:-moz-placeholder:not(:focus)::placeholder, .has-float-label *:-moz-placeholder:not(:focus)::placeholder {
36
36
  opacity: 0;
37
37
  }
38
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
38
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) *:placeholder-shown:not(:focus)::placeholder, .has-float-label *:placeholder-shown:not(:focus)::placeholder {
39
39
  opacity: 0;
40
40
  }
41
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
41
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
42
42
  font-size: inherit;
43
43
  opacity: 50%;
44
44
  }
45
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
46
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
45
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
46
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
47
47
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
48
48
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
49
49
  font-size: inherit;
@@ -56,8 +56,8 @@ The `:has(*:placeholder-shown:not(:focus))` trick allows this input state inform
56
56
  Historically, this was not possible: the float label had to be placed after the input field to be targeted using the `input:focus + label` selector.
57
57
  \3c !--section--> */
58
58
  /* Default/fallback state */
59
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
60
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
59
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
60
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
61
61
  .has-float-label > span,
62
62
  .has-float-label label {
63
63
  padding-inline-start: calc(1rem + 1px); /* match Pico's padding + border */
@@ -65,9 +65,9 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
65
65
  opacity: 75%;
66
66
  transition: all 0.25s;
67
67
  }
68
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
69
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
70
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
68
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
69
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
70
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
71
71
  .has-float-label input,
72
72
  .has-float-label textarea,
73
73
  .has-float-label select {
@@ -75,21 +75,21 @@ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea
75
75
  padding-inline-start: 1rem; /* match Pico */
76
76
  padding-block: 1.125rem 0.375rem; /* match Pico's total: 2 x 0.75rem = 1.5rem */
77
77
  }
78
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
78
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
79
79
  opacity: 100%;
80
80
  -moz-transition: all 0.25s;
81
81
  transition: all 0.25s;
82
82
  }
83
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
83
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
84
84
  opacity: 100%;
85
85
  transition: all 0.25s;
86
86
  }
87
87
  /* Enlarged state */
88
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
88
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
89
89
  padding-block: 0.75rem; /* match Pico */
90
90
  }
91
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
92
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
91
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
92
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
93
93
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
94
94
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
95
95
  padding-block: 0.75rem; /* match Pico */
@@ -1,6 +1,6 @@
1
1
  /* Default/fallback state */
2
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
3
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
2
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) > span,
3
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) label,
4
4
  .has-float-label > span,
5
5
  .has-float-label label {
6
6
  padding-inline-start: calc(1rem + 1px); /* match Pico's padding + border */
@@ -8,9 +8,9 @@
8
8
  opacity: 75%;
9
9
  transition: all 0.25s;
10
10
  }
11
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
12
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
13
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
11
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input,
12
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea,
13
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select,
14
14
  .has-float-label input,
15
15
  .has-float-label textarea,
16
16
  .has-float-label select {
@@ -18,21 +18,21 @@
18
18
  padding-inline-start: 1rem; /* match Pico */
19
19
  padding-block: 1.125rem 0.375rem; /* match Pico's total: 2 x 0.75rem = 1.5rem */
20
20
  }
21
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
21
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::-moz-placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::-moz-placeholder, .has-float-label input::-moz-placeholder, .has-float-label textarea::-moz-placeholder, .has-float-label select::-moz-placeholder {
22
22
  opacity: 100%;
23
23
  -moz-transition: all 0.25s;
24
24
  transition: all 0.25s;
25
25
  }
26
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
26
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) input::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) textarea::placeholder, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) select::placeholder, .has-float-label input::placeholder, .has-float-label textarea::placeholder, .has-float-label select::placeholder {
27
27
  opacity: 100%;
28
28
  transition: all 0.25s;
29
29
  }
30
30
  /* Enlarged state */
31
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
31
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) > span, label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:-moz-placeholder:not(:focus)) label, .has-float-label:has(*:-moz-placeholder:not(:focus)) > span, .has-float-label:has(*:-moz-placeholder:not(:focus)) label {
32
32
  padding-block: 0.75rem; /* match Pico */
33
33
  }
34
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
35
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
34
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) > span,
35
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select):has(*:placeholder-shown:not(:focus)) label,
36
36
  .has-float-label:has(*:placeholder-shown:not(:focus)) > span,
37
37
  .has-float-label:has(*:placeholder-shown:not(:focus)) label {
38
38
  padding-block: 0.75rem; /* match Pico */
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "@anyblades/blades",
3
- "version": "2.3.2",
4
- "description": "Fully compatible and actively maintained successor to Pico CSS.",
3
+ "version": "2.4.0",
5
4
  "exports": {
6
5
  ".": "./src/blades.css",
7
6
  "./standalone": "./src/blades.standalone.css",
@@ -9,25 +8,13 @@
9
8
  "./standalone/theme": "./src/blades.standalone.theme.css",
10
9
  "./float-label": "./src/float-label.css"
11
10
  },
11
+ "=== DEV ONLY": "===",
12
12
  "scripts": {
13
13
  "postcss": "postcss './src/!(_)*.css' --dir ./css/",
14
14
  "build": "npm run postcss -- --no-map",
15
15
  "start": "npm run postcss -- --watch",
16
16
  "prepublishOnly": "npm run build"
17
17
  },
18
- "repository": {
19
- "type": "git",
20
- "url": "git+https://github.com/anyblades/blades.git"
21
- },
22
- "keywords": [
23
- "css",
24
- "utilities",
25
- "helpers",
26
- "atomic",
27
- "cdn"
28
- ],
29
- "author": "Anton Staroverov",
30
- "license": "MIT",
31
18
  "devDependencies": {
32
19
  "@anyblades/pico": "^2.3.0",
33
20
  "autoprefixer": "^10.5.0",
@@ -37,5 +24,26 @@
37
24
  "postcss-import": "^16.1.1",
38
25
  "postcss-nested": "^7.0.2",
39
26
  "prettier-plugin-jinja-template": "^2.1.0"
40
- }
41
- }
27
+ },
28
+ "=== METADATA": "A-Z",
29
+ "author": "Anton Staroverov",
30
+ "description": "Fully compatible and actively maintained successor to Pico CSS.",
31
+ "keywords": [
32
+ "blades",
33
+ "classless",
34
+ "css-framework",
35
+ "css",
36
+ "dark-mode",
37
+ "dark-theme",
38
+ "lightweight",
39
+ "minimal",
40
+ "native-html",
41
+ "semantic"
42
+ ],
43
+ "license": "MIT",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/anyblades/blades.git"
47
+ },
48
+ "===": "==="
49
+ }
@@ -0,0 +1,54 @@
1
+ /*<!--section:docs-->
2
+
3
+ ### `sup`er &nbsp; and &nbsp; `sub`headings
4
+
5
+ <article><br>
6
+
7
+ # <sup style>Parent page</sup> Page title <sub style>Subtitle</sub>
8
+
9
+ </article>
10
+
11
+ How it works:
12
+ ```css */
13
+ sup[style] {
14
+ display: block;
15
+ font-size: 0.75rem;
16
+ letter-spacing: 0.0625em;
17
+ text-transform: uppercase;
18
+ }
19
+ sub[style] {
20
+ display: block;
21
+ line-height: 1.1;
22
+ bottom: 0;
23
+ font-weight: 300;
24
+ opacity: 75%;
25
+
26
+ &:where(h1 > *) {
27
+ font-size: 50%;
28
+ }
29
+ }
30
+ /*```
31
+
32
+ ### `.opt`ional content
33
+
34
+ How it works:
35
+ ```css */
36
+ .opt {
37
+ @media (width < 1024px) {
38
+ display: none;
39
+ }
40
+ }
41
+ /*```
42
+
43
+ ### Nicer GitHub favicons
44
+
45
+ How it works:
46
+ ```css */
47
+ img[src*="?domain=github.com&"] {
48
+ border-radius: 50%;
49
+
50
+ @media (prefers-color-scheme: dark) {
51
+ filter: invert(1);
52
+ }
53
+ }
54
+ /*```*/
@@ -14,5 +14,8 @@
14
14
  /* Forms */
15
15
  @import "./float-label.core";
16
16
 
17
+ /* Components */
18
+ @import "./components/_timeline";
19
+
17
20
  /* Utilities */
18
21
  @import "./_utilities";
@@ -45,6 +45,14 @@ a {
45
45
  }
46
46
  }
47
47
 
48
+ h1,
49
+ h2,
50
+ h3,
51
+ h4,
52
+ h5,
53
+ h6 {
54
+ text-wrap: balance;
55
+ }
48
56
  h1 {
49
57
  font-size: 2.5em; /* for pico.css & tw-typography */
50
58
  margin-bottom: 1rem; /* for tw-typography */
@@ -60,11 +68,24 @@ ul {
60
68
  }
61
69
  }
62
70
 
71
+ dl {
72
+ dt {
73
+ margin-block: 0.25rem;
74
+ font-weight: 500;
75
+ }
76
+ dd {
77
+ margin-block-end: 1rem;
78
+ }
79
+ }
80
+
63
81
  pre {
64
82
  small {
65
83
  opacity: 75%;
66
84
  font-weight: lighter;
67
85
  }
86
+ &:has(code) {
87
+ background: #181c25 !important;
88
+ }
68
89
  }
69
90
 
70
91
  table {
@@ -0,0 +1,25 @@
1
+ /*<!--section:docs-->
2
+
3
+ Use `dl.timeline` or wrap a `<dl>` with `.has-timeline` to style it as a
4
+ vertical timeline — each `<dd>` gets a left border strip acting as the track:
5
+
6
+ <article class="has-timeline">
7
+
8
+ May 11, 2026
9
+ : First Blades CSS stable release (v2.2.0).
10
+
11
+ Mar 15, 2025
12
+ : Last Pico CSS update (v2.1.1).
13
+
14
+ </article>
15
+
16
+ <!--section:code-->```css */
17
+ dl.timeline,
18
+ .has-timeline > dl {
19
+ dd {
20
+ padding: 0.25rem 0 0.75rem 1rem;
21
+ margin-block: 0;
22
+ border-inline-start: 0.25rem solid gray;
23
+ }
24
+ }
25
+ /*```*/
@@ -14,10 +14,7 @@ The `<pre><code>` blocks are Prism-compatible and support captions via `data-cap
14
14
  How it works:
15
15
  ```css */
16
16
  pre {
17
- padding: 1rem 1.5rem;
18
- padding-inline-end: 2rem;
19
-
20
- @media (max-width: 767px) {
17
+ @media (width < 768px) {
21
18
  border-radius: 0;
22
19
  }
23
20
  }
@@ -33,10 +30,6 @@ code {
33
30
  font-style: italic;
34
31
  }
35
32
  }
36
-
37
- &:where(pre > *) {
38
- padding: 0;
39
- }
40
33
  }
41
34
  /*```
42
35
  <!--section--> */
@@ -3,9 +3,9 @@
3
3
 
4
4
  First, we target either:
5
5
  1. `<label>` which `:has` inner form inputs (classless approach)
6
- 2. or explicit `.has-float-label` class (alternative approach)
6
+ 2. or explicit `.has-float-label` class (explicit approach)
7
7
  ```css */
8
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
8
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
9
9
  .has-float-label {
10
10
  display: block;
11
11
  position: relative;
@@ -1,4 +1,4 @@
1
- label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
1
+ label:has(> span):has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
2
2
  .has-float-label {
3
3
  /* Default/fallback state */
4
4
  > span,