gerillass 2.3.0 → 3.0.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.
Files changed (55) hide show
  1. package/README.md +46 -7
  2. package/SKILL.md +37 -12
  3. package/gerillass.json +527 -145
  4. package/package.json +1 -1
  5. package/scss/internal/_color-problem.scss +99 -0
  6. package/scss/internal/_color-stops-problem.scss +94 -0
  7. package/scss/internal/_condition-width.scss +22 -0
  8. package/scss/internal/_custom-property-in.scss +25 -0
  9. package/scss/internal/_gradient.scss +425 -0
  10. package/scss/internal/_image-value.scss +68 -0
  11. package/scss/internal/_is-condition-value.scss +94 -0
  12. package/scss/internal/_is-css-function.scss +21 -0
  13. package/scss/internal/_is-size.scss +22 -0
  14. package/scss/internal/_keyword-value.scss +76 -0
  15. package/scss/internal/_length-problem.scss +127 -0
  16. package/scss/internal/_sibling-index.scss +51 -0
  17. package/scss/internal/_words.scss +35 -0
  18. package/scss/library/_adaptive.scss +17 -0
  19. package/scss/library/_after.scss +2 -12
  20. package/scss/library/_background-dots.scss +36 -43
  21. package/scss/library/_background-image.scss +40 -52
  22. package/scss/library/_background-stripes.scss +40 -54
  23. package/scss/library/_before.scss +2 -12
  24. package/scss/library/_border-radius.scss +83 -0
  25. package/scss/library/_brand-logo.scss +10 -24
  26. package/scss/library/_breakpoint.scss +19 -26
  27. package/scss/library/_circle.scss +7 -0
  28. package/scss/library/_columnizer.scss +62 -2
  29. package/scss/library/_container-query.scss +13 -29
  30. package/scss/library/_container.scss +2 -19
  31. package/scss/library/_counter.scss +3 -14
  32. package/scss/library/_ellipsis.scss +78 -1
  33. package/scss/library/_except.scss +15 -0
  34. package/scss/library/_focus-ring.scss +29 -0
  35. package/scss/library/_font-face.scss +117 -1
  36. package/scss/library/_gradient.scss +31 -0
  37. package/scss/library/_index.scss +1 -2
  38. package/scss/library/_line-clamp.scss +2 -13
  39. package/scss/library/_only.scss +16 -0
  40. package/scss/library/_position.scss +34 -3
  41. package/scss/library/_remove.scss +1 -1
  42. package/scss/library/_resizable.scss +29 -2
  43. package/scss/library/_screen-agent.scss +8 -22
  44. package/scss/library/_sizer.scss +9 -0
  45. package/scss/library/_sprite.scss +65 -0
  46. package/scss/library/_text-gradient.scss +36 -18
  47. package/scss/library/_text-image.scss +2 -23
  48. package/scss/library/_text-stroke.scss +30 -0
  49. package/scss/library/_triangle.scss +25 -56
  50. package/scss/utilities/_gradient-value.scss +24 -0
  51. package/scss/utilities/_index.scss +1 -0
  52. package/scss/utilities/_validate-breakpoint.scss +32 -6
  53. package/scss/utilities/_validate-scissors.scss +7 -0
  54. package/scss/library/_linear-gradient.scss +0 -26
  55. package/scss/library/_radial-gradient.scss +0 -30
package/gerillass.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerillass",
3
- "version": "2.3.0",
3
+ "version": "3.0.0",
4
4
  "description": "Gerillass is an open-source toolkit that contains a set of Sass mixins to help designers and developers to create better, faster and consistent user interfaces.",
5
5
  "homepage": "https://gerillass.com",
6
6
  "documentation": "https://docs.gerillass.com",
@@ -8,7 +8,8 @@
8
8
  "load": {
9
9
  "packageImporter": "@use \"pkg:gerillass\" as *;",
10
10
  "bundler": "@use \"gerillass\" as *;",
11
- "loadPath": "@use \"gerillass\" as *; // with loadPaths: [\"node_modules/gerillass/scss\"]"
11
+ "loadPath": "@use \"gerillass\" as *; // with loadPaths: [\"node_modules/gerillass/scss\"]",
12
+ "rubygems": "@use \"gerillass\" as *; // the gerillass gem: Rails and Jekyll need no setup; plain Ruby passes Gerillass.load_path"
12
13
  },
13
14
  "members": [
14
15
  {
@@ -30,7 +31,12 @@
30
31
  ".wrap { @include adaptive; }",
31
32
  ".wrap { @include adaptive(16px); }"
32
33
  ],
33
- "rejects": []
34
+ "rejects": [
35
+ ".wrap { @include adaptive(auto); }",
36
+ ".wrap { @include adaptive(16); }",
37
+ ".wrap { @include adaptive(10deg); }",
38
+ ".wrap { @include adaptive(10px 20px); }"
39
+ ]
34
40
  },
35
41
  {
36
42
  "name": "after",
@@ -207,7 +213,7 @@
207
213
  "name": "$color",
208
214
  "default": "null",
209
215
  "accepts": [
210
- "one colour, or two for the diagonal variant",
216
+ "one colour, or two for the diagonal variant, each a colour, currentColor, a system colour or a function such as var() or light-dark()",
211
217
  "null for a translucent black"
212
218
  ]
213
219
  },
@@ -238,7 +244,7 @@
238
244
  "name": "$image",
239
245
  "default": "null",
240
246
  "accepts": [
241
- "an image path to sit behind the dots",
247
+ "an image path to sit behind the dots, written unquoted unless it holds a space, a parenthesis or a quote, which are quoted",
242
248
  "var(), url(), image-set() or a gradient, written as they are rather than wrapped in url()"
243
249
  ]
244
250
  }
@@ -258,7 +264,14 @@
258
264
  ".a { @include background-dots(red, 1em, 5em, maybe); }",
259
265
  ".a { @include background-dots(red, 1em, 5em, true, 42); }",
260
266
  ".a { @include background-dots(red, nonsense); }",
261
- ".a { @include background-dots(red, 1em, nonsense); }"
267
+ ".a { @include background-dots(red, 1em, nonsense); }",
268
+ ".a { @include background-dots(huge); }",
269
+ ".a { @include background-dots(red 10px); }",
270
+ ".a { @include background-dots(inherit); }",
271
+ ".a { @include background-dots(red, -1em); }",
272
+ ".a { @include background-dots(red, 10deg); }",
273
+ ".a { @include background-dots(red, 2); }",
274
+ ".a { @include background-dots(red, 1em, -5em); }"
262
275
  ]
263
276
  },
264
277
  {
@@ -269,7 +282,7 @@
269
282
  "name": "$image-url",
270
283
  "default": "null",
271
284
  "accepts": [
272
- "an image path",
285
+ "an image path, as a string; a list, a number, a colour or a boolean is refused",
273
286
  "null to filter the element itself instead",
274
287
  "var(), url(), image-set() or a gradient, written as they are rather than wrapped in url()"
275
288
  ]
@@ -278,15 +291,19 @@
278
291
  "name": "$filter-color",
279
292
  "default": "null",
280
293
  "accepts": [
281
- "one colour, or several for a gradient"
294
+ "one colour, or several colour stops for a gradient, in the forms the gradient mixin takes",
295
+ "with $image-url null, an image as the overlay layer too: a gradient, url(), image-set() or var()",
296
+ "a word that is not a colour, a quoted colour, a length and a CSS-wide keyword are refused"
282
297
  ]
283
298
  },
284
299
  {
285
300
  "name": "$filter-direction",
286
301
  "default": "null",
287
302
  "accepts": [
288
- "an angle such as 45deg",
289
- "a direction name such as top or bottom-left"
303
+ "a direction name such as top or bottom-left",
304
+ "an angle in deg, grad, rad or turn, or 0",
305
+ "\"to top\" or \"to left top\" as a string",
306
+ "var() or calc()"
290
307
  ]
291
308
  }
292
309
  ],
@@ -303,7 +320,14 @@
303
320
  "rejects": [
304
321
  ".a { @include background-image(\"/img/a.png\", (red, blue), sideways); }",
305
322
  ".a { @include background-image(\"/img/a.png\", rgba(0,0,0,0.5), sideways); }",
306
- ".a { @include background-image(null, rgba(0,0,0,0.5), sideways); }"
323
+ ".a { @include background-image(null, rgba(0,0,0,0.5), sideways); }",
324
+ ".a { @include background-image(16 9); }",
325
+ ".a { @include background-image(42); }",
326
+ ".a { @include background-image(\"/img/a.png\", huge); }",
327
+ ".a { @include background-image(\"/img/a.png\", (red, 10%)); }",
328
+ ".a { @include background-image(null, 10px); }",
329
+ ".a { @include background-image(null, inherit); }",
330
+ ".a { @include background-image(\"/img/a.png\", linear-gradient(to top, black, transparent)); }"
307
331
  ]
308
332
  },
309
333
  {
@@ -314,7 +338,7 @@
314
338
  "name": "$color",
315
339
  "default": "null",
316
340
  "accepts": [
317
- "one colour, or several for a multi-stripe pattern",
341
+ "one colour, or several for a multi-stripe pattern, each a colour, currentColor, a system colour or a function such as var() or color-mix()",
318
342
  "null for a translucent black"
319
343
  ]
320
344
  },
@@ -329,14 +353,16 @@
329
353
  "name": "$rotation",
330
354
  "default": "-45deg",
331
355
  "accepts": [
332
- "an angle; a unitless number is treated as degrees"
356
+ "an angle in deg, grad, rad or turn, in any case, written as it is",
357
+ "a unitless number, which is treated as degrees",
358
+ "any other unit, such as px or %, is refused, because the gradient would be dropped"
333
359
  ]
334
360
  },
335
361
  {
336
362
  "name": "$image",
337
363
  "default": "null",
338
364
  "accepts": [
339
- "an image path to sit behind the stripes",
365
+ "an image path to sit behind the stripes, written unquoted unless it holds a space, a parenthesis or a quote, which are quoted",
340
366
  "var(), url(), image-set() or a gradient, written as they are rather than wrapped in url()"
341
367
  ]
342
368
  }
@@ -353,7 +379,13 @@
353
379
  "rejects": [
354
380
  ".a { @include background-stripes(red, 2em, nonsense); }",
355
381
  ".a { @include background-stripes(red, 2em, -45deg, 42); }",
356
- ".a { @include background-stripes(red, nonsense); }"
382
+ ".a { @include background-stripes(red, nonsense); }",
383
+ ".a { @include background-stripes(red, 2em, -10px); }",
384
+ ".a { @include background-stripes(red, 2em, 10%); }",
385
+ ".a { @include background-stripes(huge); }",
386
+ ".a { @include background-stripes(red \"blue\"); }",
387
+ ".a { @include background-stripes(red, 10deg); }",
388
+ ".a { @include background-stripes(red, 2); }"
357
389
  ]
358
390
  },
359
391
  {
@@ -438,7 +470,13 @@
438
470
  ],
439
471
  "rejects": [
440
472
  ".a { @include border-radius(1px, 2px, 3px); }",
441
- ".a { @include border-radius(nonsense, 5px); }"
473
+ ".a { @include border-radius(nonsense, 5px); }",
474
+ ".a { @include border-radius(-4px); }",
475
+ ".a { @include border-radius(auto); }",
476
+ ".a { @include border-radius(10deg); }",
477
+ ".a { @include border-radius(1px 2px 3px 4px 5px); }",
478
+ ".a { @include border-radius(\"top\", 1px 2px 3px); }",
479
+ ".a { @include border-radius(1px, 2px, -3px, 4px); }"
442
480
  ]
443
481
  },
444
482
  {
@@ -463,7 +501,7 @@
463
501
  "name": "$image-url",
464
502
  "default": "null",
465
503
  "accepts": [
466
- "an image path",
504
+ "an image path, as a string; a list, a number, a colour or a boolean is refused",
467
505
  "var(), url(), image-set() or a gradient, written as they are rather than wrapped in url()"
468
506
  ]
469
507
  }
@@ -475,7 +513,13 @@
475
513
  ".logo { @include brand-logo(120px, 40px, \"/img/logo.svg\"); }",
476
514
  ".logo { @include brand-logo(120px, 40px, var(--logo)); }"
477
515
  ],
478
- "rejects": []
516
+ "rejects": [
517
+ ".logo { @include brand-logo(120px, 40px, \"/img/a.svg\" \"/img/b.svg\"); }",
518
+ ".logo { @include brand-logo(120px, 40px, true); }",
519
+ ".logo { @include brand-logo(huge, 40px); }",
520
+ ".logo { @include brand-logo(120px, 10deg); }",
521
+ ".logo { @include brand-logo(\"120px\", 40px); }"
522
+ ]
479
523
  },
480
524
  {
481
525
  "name": "breakpoint",
@@ -489,7 +533,8 @@
489
533
  "only plus a breakpoint, for exactly that width",
490
534
  "min or max plus a breakpoint",
491
535
  "between plus two breakpoints",
492
- "a start and an end value"
536
+ "a start and an end value",
537
+ "a breakpoint is a key from $map-for-breakpoints, or a length in any unit a width condition takes, 0 or a calculation; a percentage, a bare number, another unit and a word that is not a key are refused, because the query would never match"
493
538
  ]
494
539
  }
495
540
  ],
@@ -497,7 +542,7 @@
497
542
  "signature": "breakpoint($params...)",
498
543
  "summary": "Media query built from the breakpoint map, or from raw lengths.",
499
544
  "caveats": [
500
- "With one argument the query matches exactly that width, `(width: 768px)`, which is a single pixel, and the mixin prints a warning. Write `only` for that width, or `min`, `max` or a range for anything wider. 3.0.0 will refuse the one-argument form.",
545
+ "With one argument the query matches exactly that width, `(width: 768px)`, which is a single pixel, and the mixin prints a warning. Write `only` for that width, or `min`, `max` or a range for anything wider.",
501
546
  "Declarations written after the include, in the same rule, are emitted after the `@media` block and win over it. Write them before the include."
502
547
  ],
503
548
  "examples": [
@@ -509,7 +554,16 @@
509
554
  ".a { @include breakpoint(\"between\", \"medium\", \"large\") { color: red; } }",
510
555
  ".a { @include breakpoint() { color: red; } }",
511
556
  ".a { @include breakpoint(\"min\", var(--wide)) { color: red; } }",
512
- ".a { @include breakpoint(\"between\", var(--start) \"large\") { color: red; } }"
557
+ ".a { @include breakpoint(\"between\", var(--start) \"large\") { color: red; } }",
558
+ ".a { @include breakpoint(\"huge\") { color: red; } }",
559
+ ".a { @include breakpoint(\"min\", \"huge\") { color: red; } }",
560
+ ".a { @include breakpoint(\"min\", \"MEDIUM\") { color: red; } }",
561
+ ".a { @include breakpoint(\"between\", \"small\" \"huge\") { color: red; } }",
562
+ ".a { @include breakpoint(\"huge\", \"large\") { color: red; } }",
563
+ ".a { @include breakpoint(\"small\", \"huge\") { color: red; } }",
564
+ ".a { @include breakpoint(\"min\", 10deg) { color: red; } }",
565
+ ".a { @include breakpoint(\"max\", 50%) { color: red; } }",
566
+ ".a { @include breakpoint(\"only\", 768) { color: red; } }"
513
567
  ],
514
568
  "warns": [
515
569
  ".a { @include breakpoint(\"medium\") { color: red; } }"
@@ -582,7 +636,11 @@
582
636
  "examples": [
583
637
  ".dot { @include circle(24px); }"
584
638
  ],
585
- "rejects": []
639
+ "rejects": [
640
+ ".dot { @include circle(huge); }",
641
+ ".dot { @include circle(24); }",
642
+ ".dot { @include circle(-24px); }"
643
+ ]
586
644
  },
587
645
  {
588
646
  "name": "clearfix",
@@ -619,11 +677,17 @@
619
677
  ".grid { @include columnizer(3, 20px); }",
620
678
  ".grid { @include columnizer(3, 20px, true); }",
621
679
  ".grid { @include columnizer(3, var(--gap)); }",
622
- ".grid { @include columnizer(var(--cols)); }"
680
+ ".grid { @include columnizer(var(--cols)); }",
681
+ ".grid { @include columnizer(#{3}, 0); }"
623
682
  ],
624
683
  "rejects": [
625
684
  ".grid { @include columnizer(3, 20px, true, 9); }",
626
- ".grid { @include columnizer(3, nonsense); }"
685
+ ".grid { @include columnizer(3, nonsense); }",
686
+ ".grid { @include columnizer(3px); }",
687
+ ".grid { @include columnizer(auto); }",
688
+ ".grid { @include columnizer(3, 10deg); }",
689
+ ".grid { @include columnizer(3, 2); }",
690
+ ".grid { @include columnizer(3, red, true); }"
627
691
  ]
628
692
  },
629
693
  {
@@ -637,6 +701,7 @@
637
701
  "a size, for exactly that width, which prints a warning: write only instead",
638
702
  "two sizes for a range",
639
703
  "one of min, max, only or between followed by a size",
704
+ "a size is a key from $map-for-breakpoints, or a length in any unit a width condition takes, 0 or a calculation; a percentage, a bare number, another unit and a word that is not a key are refused, because the query would never match",
640
705
  "$name as a keyword, to query one named container"
641
706
  ]
642
707
  }
@@ -645,7 +710,7 @@
645
710
  "signature": "container-query($params...)",
646
711
  "summary": "A @container rule, taking the same argument shapes as breakpoint so the two read alike. Sizes may be a key from $map-for-breakpoints or a raw length, and a length is the common case because a container is usually narrower than the viewport. Nothing matches at all unless an ancestor was declared with the container mixin.",
647
712
  "caveats": [
648
- "A size on its own matches exactly that width, `(width: 400px)`, which is a single pixel, and the mixin prints a warning. Write `only` for that width, or `min`, `max` or a range for anything wider. 3.0.0 will refuse the one-argument form."
713
+ "A size on its own matches exactly that width, `(width: 400px)`, which is a single pixel, and the mixin prints a warning. Write `only` for that width, or `min`, `max` or a range for anything wider."
649
714
  ],
650
715
  "examples": [
651
716
  ".title { @include container-query(\"min\", 400px) { font-size: 2rem; } }",
@@ -664,7 +729,12 @@
664
729
  ".title { @include container-query(\"min\", 400px, $name: \"none\") { color: red; } }",
665
730
  ".title { @include container-query(\"min\", 400px, $name: \"not\") { color: red; } }",
666
731
  ".title { @include container-query(\"min\", 400px, $name: \"my card\") { color: red; } }",
667
- ".title { @include container-query(\"min\", 400px, $name: \"1card\") { color: red; } }"
732
+ ".title { @include container-query(\"min\", 400px, $name: \"1card\") { color: red; } }",
733
+ ".title { @include container-query(\"huge\") { color: red; } }",
734
+ ".title { @include container-query(\"min\", \"huge\") { color: red; } }",
735
+ ".title { @include container-query(\"max\", 400) { color: red; } }",
736
+ ".title { @include container-query(\"between\", 300px 10deg) { color: red; } }",
737
+ ".title { @include container-query(300px, 50%) { color: red; } }"
668
738
  ],
669
739
  "warns": [
670
740
  ".title { @include container-query(400px) { color: red; } }"
@@ -754,7 +824,10 @@
754
824
  "name": "$display",
755
825
  "default": "inline-block",
756
826
  "accepts": [
757
- "a display value"
827
+ "a display keyword, or two or three in any order naming at most one outer type, one inner type and list-item, such as inline flex",
828
+ "a vendor keyword such as -webkit-box, a CSS-wide keyword, or var()",
829
+ "null to leave display out",
830
+ "a quoted value is written without its quotes; a combination the browser drops, such as block inline, is refused"
758
831
  ]
759
832
  }
760
833
  ],
@@ -765,7 +838,16 @@
765
838
  ".a { @include ellipsis; }",
766
839
  ".a { @include ellipsis(200px); }"
767
840
  ],
768
- "rejects": []
841
+ "rejects": [
842
+ ".a { @include ellipsis(100%, huge); }",
843
+ ".a { @include ellipsis(100%, block inline); }",
844
+ ".a { @include ellipsis(100%, inline-block flow); }",
845
+ ".a { @include ellipsis(100%, 10px); }",
846
+ ".a { @include ellipsis(huge); }",
847
+ ".a { @include ellipsis(auto); }",
848
+ ".a { @include ellipsis(-10px); }",
849
+ ".a { @include ellipsis(200); }"
850
+ ]
769
851
  },
770
852
  {
771
853
  "name": "escape-to-parent",
@@ -797,23 +879,35 @@
797
879
  "name": "$params",
798
880
  "variadic": true,
799
881
  "accepts": [
800
- "a positive or negative index",
882
+ "a positive or negative index, a whole number other than 0; a unit or a fraction makes a selector the browser drops, and 0 excludes nothing, so both are refused",
883
+ "a multiple of n such as 3n, to exclude every third element; an offset such as 2n+1 is computed by Sass first and arrives as 3n",
801
884
  "first, last, odd or even",
802
885
  "a selector such as .foo",
803
- "several indexes"
886
+ "several indexes, all of them numbers"
804
887
  ]
805
888
  }
806
889
  ],
807
890
  "file": "scss/library/_except.scss",
808
891
  "signature": "except($params...)",
809
892
  "summary": "Selects every sibling except the ones named.",
893
+ "caveats": [
894
+ "An+B with an offset cannot be passed as a number: Sass does the arithmetic, so `except(2n+1)` becomes `3n` and excludes every third element, not the odd ones. Use `odd` or `even`, or a coefficient alone such as `3n`."
895
+ ],
810
896
  "examples": [
811
897
  ".a { @include except(\"first\") { margin: 0; } }",
812
898
  ".a { @include except(2) { margin: 0; } }",
813
- ".a { @include except(1, 3) { margin: 0; } }"
899
+ ".a { @include except(1, 3) { margin: 0; } }",
900
+ ".a { @include except(3n) { margin: 0; } }"
814
901
  ],
815
902
  "rejects": [
816
- ".a { @include except(#ff0000) { margin: 0; } }"
903
+ ".a { @include except(#ff0000) { margin: 0; } }",
904
+ ".a { @include except(10deg) { margin: 0; } }",
905
+ ".a { @include except(-10px) { margin: 0; } }",
906
+ ".a { @include except(1.5) { margin: 0; } }",
907
+ ".a { @include except(0) { margin: 0; } }",
908
+ ".a { @include except(0n) { margin: 0; } }",
909
+ ".a { @include except(1, 10deg) { margin: 0; } }",
910
+ ".a { @include except(2, \"first\") { margin: 0; } }"
817
911
  ]
818
912
  },
819
913
  {
@@ -838,7 +932,8 @@
838
932
  "name": "$color",
839
933
  "default": "currentColor",
840
934
  "accepts": [
841
- "any CSS colour, including currentColor and var()"
935
+ "a colour, currentColor, a system colour such as Highlight, or a function such as var() or color-mix()",
936
+ "a word that is not a colour, a quoted colour, a length and a CSS-wide keyword are refused, because the outline would be dropped"
842
937
  ]
843
938
  }
844
939
  ],
@@ -850,7 +945,16 @@
850
945
  ".card-link { @include focus-ring(3px, 4px, var(--focus)); }"
851
946
  ],
852
947
  "rejects": [
853
- "@include focus-ring;"
948
+ "@include focus-ring;",
949
+ ".button { @include focus-ring(2px, 2px, huge); }",
950
+ ".button { @include focus-ring(2px, 2px, \"red\"); }",
951
+ ".button { @include focus-ring(2px, 2px, 10px); }",
952
+ ".button { @include focus-ring(2px, 2px, inherit); }",
953
+ ".button { @include focus-ring(huge); }",
954
+ ".button { @include focus-ring(5%); }",
955
+ ".button { @include focus-ring(-2px); }",
956
+ ".button { @include focus-ring(2px, 5%); }",
957
+ ".button { @include focus-ring(2px, thin); }"
854
958
  ]
855
959
  },
856
960
  {
@@ -875,14 +979,17 @@
875
979
  "name": "$font-style",
876
980
  "default": "normal",
877
981
  "accepts": [
878
- "normal, italic or oblique, or a weight number"
982
+ "normal, italic, oblique or auto, or oblique with one or two angles from -90deg to 90deg",
983
+ "a number from 1 to 1000, which is read as the weight"
879
984
  ]
880
985
  },
881
986
  {
882
987
  "name": "$font-weight",
883
988
  "default": "400",
884
989
  "accepts": [
885
- "a weight"
990
+ "normal, bold, auto, or a number from 1 to 1000",
991
+ "two numbers for a variable font's range, such as 100 900",
992
+ "bolder, lighter and the CSS-wide keywords are refused, because a @font-face rule drops them"
886
993
  ]
887
994
  },
888
995
  {
@@ -908,7 +1015,9 @@
908
1015
  "@include font-face(\"Inter\", \"/fonts/inter\");",
909
1016
  "@include font-face(\"Inter\", \"/fonts/inter\", italic, 700, woff2 woff);",
910
1017
  "@include font-face(\"Readex Pro\", \"/fonts/readex\", $font-weight: 160 700, $file-formats: woff2, $font-display: swap);",
911
- "@include font-face(\"Inter\", \"/fonts/inter\", \"italic\", $font-weight: \"bold\", $file-formats: woff2);"
1018
+ "@include font-face(\"Inter\", \"/fonts/inter\", \"italic\", $font-weight: \"bold\", $file-formats: woff2);",
1019
+ "@include font-face(\"Inter\", \"/fonts/inter\", oblique 10deg 20deg, $font-weight: 450.5, $file-formats: woff2);",
1020
+ "@include font-face(\"Inter\", \"/fonts/inter\", auto, \"100 900\", $file-formats: woff2);"
912
1021
  ],
913
1022
  "rejects": [
914
1023
  ".a { @include font-face(\"Inter\", \"/fonts/inter\"); }",
@@ -926,7 +1035,125 @@
926
1035
  "@include font-face(\"Inter\", \"/fonts/inter\", $font-weight: 100 var(--max-weight), $file-formats: woff2);",
927
1036
  "@include font-face(sans-serif, \"/fonts/inter\", $file-formats: woff2);",
928
1037
  "@include font-face(inherit, \"/fonts/inter\", $file-formats: woff2);",
929
- "@include font-face(env(--font-family), \"/fonts/inter\", $file-formats: woff2);"
1038
+ "@include font-face(env(--font-family), \"/fonts/inter\", $file-formats: woff2);",
1039
+ "@include font-face(\"Inter\", \"/fonts/inter\", huge, $file-formats: woff2);",
1040
+ "@include font-face(\"Inter\", \"/fonts/inter\", oblique 100deg, $file-formats: woff2);",
1041
+ "@include font-face(\"Inter\", \"/fonts/inter\", inherit, $file-formats: woff2);",
1042
+ "@include font-face(\"Inter\", \"/fonts/inter\", $font-weight: huge, $file-formats: woff2);",
1043
+ "@include font-face(\"Inter\", \"/fonts/inter\", $font-weight: bolder, $file-formats: woff2);",
1044
+ "@include font-face(\"Inter\", \"/fonts/inter\", $font-weight: 0, $file-formats: woff2);",
1045
+ "@include font-face(\"Inter\", \"/fonts/inter\", $font-weight: 100 200 300, $file-formats: woff2);"
1046
+ ]
1047
+ },
1048
+ {
1049
+ "name": "gradient",
1050
+ "kind": "mixin",
1051
+ "arguments": [
1052
+ {
1053
+ "name": "$colors",
1054
+ "required": true,
1055
+ "accepts": [
1056
+ "one or more colour stops: a colour, or a colour with one or two positions, such as (red 0 10%) (blue 10% 100%)",
1057
+ "a position on its own between two colours, as a hint",
1058
+ "for a conic gradient the positions are angles or percentages, not lengths",
1059
+ "var() for a stop or the whole list",
1060
+ "a single colour warns, because browsers before Chrome 135, Firefox 136 and Safari 18.4 drop that gradient"
1061
+ ]
1062
+ },
1063
+ {
1064
+ "name": "$type",
1065
+ "default": "linear",
1066
+ "accepts": [
1067
+ "linear, the default",
1068
+ "radial",
1069
+ "conic"
1070
+ ]
1071
+ },
1072
+ {
1073
+ "name": "$direction",
1074
+ "default": "null",
1075
+ "accepts": [
1076
+ "linear only",
1077
+ "a direction name such as top or bottom-left",
1078
+ "an angle in deg, grad, rad or turn, or 0",
1079
+ "\"to top\" or \"to left top\" as a string",
1080
+ "var() or calc()"
1081
+ ]
1082
+ },
1083
+ {
1084
+ "name": "$shape",
1085
+ "default": "null",
1086
+ "accepts": [
1087
+ "radial only",
1088
+ "circle or ellipse, with an optional size as a string, such as \"circle 10px\""
1089
+ ]
1090
+ },
1091
+ {
1092
+ "name": "$position",
1093
+ "default": "null",
1094
+ "accepts": [
1095
+ "radial or conic",
1096
+ "a position name such as center or top-left",
1097
+ "at followed by a position, as a string, such as \"at 30% 40%\"; a radial gradient may put a size before it"
1098
+ ]
1099
+ },
1100
+ {
1101
+ "name": "$from",
1102
+ "default": "null",
1103
+ "accepts": [
1104
+ "conic only",
1105
+ "an angle in deg, grad, rad or turn, 0, or var()"
1106
+ ]
1107
+ },
1108
+ {
1109
+ "name": "$in",
1110
+ "default": "null",
1111
+ "accepts": [
1112
+ "a colour space: srgb, srgb-linear, display-p3, display-p3-linear, a98-rgb, prophoto-rgb, rec2020, lab, oklab, xyz, xyz-d50 or xyz-d65",
1113
+ "a polar space, hsl, hwb, lch or oklch, with an optional hue method as a string, such as \"oklch longer hue\"",
1114
+ "var()",
1115
+ "the gradient is written once without the space first, for a browser that does not know it"
1116
+ ]
1117
+ },
1118
+ {
1119
+ "name": "$repeating",
1120
+ "default": "false",
1121
+ "accepts": [
1122
+ "false, the default",
1123
+ "true, for a repeating gradient"
1124
+ ]
1125
+ }
1126
+ ],
1127
+ "file": "scss/library/_gradient.scss",
1128
+ "signature": "gradient($colors, $type: linear, $direction: null, $shape: null, $position: null, $from: null, $in: null, $repeating: false)",
1129
+ "summary": "A linear, radial or conic gradient as background-image, plain or repeating, with an optional colour interpolation space. Replaced linear-gradient and radial-gradient in 3.0.0.",
1130
+ "examples": [
1131
+ ".a { @include gradient((red, blue)); }",
1132
+ ".a { @include gradient((red, blue), $direction: \"top-right\"); }",
1133
+ ".a { @include gradient((red, blue), radial, $shape: circle, $position: \"top-left\"); }",
1134
+ ".a { @include gradient((teal 0 40%, purple 40% 75%, coral 75% 100%), conic); }",
1135
+ ".a { @include gradient((black 0 25%, white 0 50%), conic, $repeating: true); }",
1136
+ ".a { @include gradient((blue, yellow), $direction: right, $in: oklab); }"
1137
+ ],
1138
+ "rejects": [
1139
+ ".a { @include gradient((red, blue), sideways); }",
1140
+ ".a { @include gradient((red, blue), $direction: 10px); }",
1141
+ ".a { @include gradient((red, blue), $direction: \"to center\"); }",
1142
+ ".a { @include gradient((red, blue), radial, $direction: top); }",
1143
+ ".a { @include gradient((red, blue), $shape: circle); }",
1144
+ ".a { @include gradient((red, blue), $position: center); }",
1145
+ ".a { @include gradient((red, blue), $from: 45deg); }",
1146
+ ".a { @include gradient((red, blue), conic, $from: 10px); }",
1147
+ ".a { @include gradient((red, blue), conic, $position: \"closest-side at center\"); }",
1148
+ ".a { @include gradient((red 10px, blue), conic); }",
1149
+ ".a { @include gradient((red, blue), radial, $shape: \"circle 10%\"); }",
1150
+ ".a { @include gradient((huge, blue)); }",
1151
+ ".a { @include gradient((red, blue), $in: rgb); }",
1152
+ ".a { @include gradient((red, blue), $in: \"oklab longer hue\"); }",
1153
+ ".a { @include gradient((red, blue), $repeating: yes); }"
1154
+ ],
1155
+ "warns": [
1156
+ ".a { @include gradient(red); }"
930
1157
  ]
931
1158
  },
932
1159
  {
@@ -985,38 +1212,6 @@
985
1212
  ".a { @include line-clamp(url(a.png)); }"
986
1213
  ]
987
1214
  },
988
- {
989
- "name": "linear-gradient",
990
- "kind": "mixin",
991
- "arguments": [
992
- {
993
- "name": "$direction",
994
- "required": true,
995
- "accepts": [
996
- "a direction name such as top or bottom-left",
997
- "an angle such as 45deg"
998
- ]
999
- },
1000
- {
1001
- "name": "$colors",
1002
- "required": true,
1003
- "accepts": [
1004
- "two or more colours"
1005
- ]
1006
- }
1007
- ],
1008
- "file": "scss/library/_linear-gradient.scss",
1009
- "signature": "linear-gradient($direction, $colors)",
1010
- "summary": "Linear gradient background from a direction name or an angle.",
1011
- "examples": [
1012
- ".a { @include linear-gradient(\"top\", (red, blue)); }",
1013
- ".a { @include linear-gradient(45deg, (red, blue)); }"
1014
- ],
1015
- "rejects": [
1016
- ".a { @include linear-gradient(sideways, (red, blue)); }",
1017
- ".a { @include linear-gradient(true, (red, blue)); }"
1018
- ]
1019
- },
1020
1215
  {
1021
1216
  "name": "loadify",
1022
1217
  "kind": "mixin",
@@ -1070,23 +1265,35 @@
1070
1265
  "name": "$params",
1071
1266
  "variadic": true,
1072
1267
  "accepts": [
1073
- "a positive or negative index",
1268
+ "a positive or negative index, a whole number other than 0; a unit or a fraction makes a selector the browser drops, and 0 matches nothing, so both are refused",
1269
+ "a multiple of n such as 3n, for every third element; an offset such as 2n+1 is computed by Sass first and arrives as 3n",
1074
1270
  "first, last, odd or even",
1075
1271
  "a selector such as .foo",
1076
- "several indexes"
1272
+ "several indexes, all of them numbers"
1077
1273
  ]
1078
1274
  }
1079
1275
  ],
1080
1276
  "file": "scss/library/_only.scss",
1081
1277
  "signature": "only($params...)",
1082
1278
  "summary": "Selects only the siblings named.",
1279
+ "caveats": [
1280
+ "An+B with an offset cannot be passed as a number: Sass does the arithmetic, so `only(2n+1)` becomes `3n` and selects every third element, not the odd ones. Use `odd` or `even`, or a coefficient alone such as `3n`."
1281
+ ],
1083
1282
  "examples": [
1084
1283
  ".a { @include only(\"first\") { margin: 0; } }",
1085
1284
  ".a { @include only(-1) { margin: 0; } }",
1086
- ".a { @include only(1, 3) { margin: 0; } }"
1285
+ ".a { @include only(1, 3) { margin: 0; } }",
1286
+ ".a { @include only(3n) { margin: 0; } }"
1087
1287
  ],
1088
1288
  "rejects": [
1089
- ".a { @include only(#ff0000) { margin: 0; } }"
1289
+ ".a { @include only(#ff0000) { margin: 0; } }",
1290
+ ".a { @include only(10deg) { margin: 0; } }",
1291
+ ".a { @include only(-10px) { margin: 0; } }",
1292
+ ".a { @include only(1.5) { margin: 0; } }",
1293
+ ".a { @include only(0) { margin: 0; } }",
1294
+ ".a { @include only(0n) { margin: 0; } }",
1295
+ ".a { @include only(1, 10deg) { margin: 0; } }",
1296
+ ".a { @include only(2, \"first\") { margin: 0; } }"
1090
1297
  ]
1091
1298
  },
1092
1299
  {
@@ -1121,7 +1328,10 @@
1121
1328
  "name": "$position",
1122
1329
  "default": "absolute",
1123
1330
  "accepts": [
1124
- "any CSS position value"
1331
+ "static, relative, absolute, fixed or sticky, in any case, or a vendor keyword such as -webkit-sticky",
1332
+ "a CSS-wide keyword or var()",
1333
+ "null to leave position out",
1334
+ "a quoted keyword is written without its quotes; any other word is refused, because the declaration would be dropped"
1125
1335
  ]
1126
1336
  },
1127
1337
  {
@@ -1151,48 +1361,21 @@
1151
1361
  ".a { @include position(absolute, null 16px 16px 16px); }",
1152
1362
  ".a { @include position(absolute, 0 null null 0); }",
1153
1363
  ".badge { @include position(absolute, 0 auto auto 1rem, $logical: true); }",
1154
- ".a { @include position(absolute, 0, $logical: null); }"
1155
- ],
1156
- "rejects": [
1157
- ".badge { @include position(absolute, 0, $logical: yes); }"
1158
- ]
1159
- },
1160
- {
1161
- "name": "radial-gradient",
1162
- "kind": "mixin",
1163
- "arguments": [
1164
- {
1165
- "name": "$shape",
1166
- "required": true,
1167
- "accepts": [
1168
- "circle or ellipse"
1169
- ]
1170
- },
1171
- {
1172
- "name": "$position",
1173
- "required": true,
1174
- "accepts": [
1175
- "a position name such as center or top-left",
1176
- "a raw CSS position"
1177
- ]
1178
- },
1179
- {
1180
- "name": "$colors",
1181
- "required": true,
1182
- "accepts": [
1183
- "two or more colours"
1184
- ]
1185
- }
1186
- ],
1187
- "file": "scss/library/_radial-gradient.scss",
1188
- "signature": "radial-gradient($shape, $position, $colors)",
1189
- "summary": "Radial gradient background from a shape and a position.",
1190
- "examples": [
1191
- ".a { @include radial-gradient(circle, \"center\", (red, blue)); }"
1364
+ ".a { @include position(absolute, 0, $logical: null); }",
1365
+ ".a { @include position(absolute, #{16}px AUTO revert-layer); }",
1366
+ ".tip { @include position(absolute, anchor(bottom) null null anchor(left)); }"
1192
1367
  ],
1193
1368
  "rejects": [
1194
- ".a { @include radial-gradient(42, \"center\", (red, blue)); }",
1195
- ".a { @include radial-gradient(circle, 42, (red, blue)); }"
1369
+ ".badge { @include position(absolute, 0, $logical: yes); }",
1370
+ ".a { @include position(huge, 0); }",
1371
+ ".a { @include position(10px, 0); }",
1372
+ ".a { @include position(\"absolute fixed\", 0); }",
1373
+ ".a { @include position(absolute, 5); }",
1374
+ ".a { @include position(absolute, 0 10deg); }",
1375
+ ".a { @include position(absolute, none); }",
1376
+ ".a { @include position(absolute, red); }",
1377
+ ".a { @include position(absolute, \"10px\"); }",
1378
+ ".a { @include position(absolute, url(a.png)); }"
1196
1379
  ]
1197
1380
  },
1198
1381
  {
@@ -1215,7 +1398,7 @@
1215
1398
  "signature": "remove($params...)",
1216
1399
  "summary": "Hides an element outright, or within a media query: from a breakpoint up with min, up to it with max, or between two breakpoints. One breakpoint on its own hides the element at exactly that width, a single pixel, and prints a warning: pass only for that.",
1217
1400
  "caveats": [
1218
- "With one argument the element is hidden at exactly that width, `(width: 768px)`, which is a single pixel, and the mixin prints a warning. Write `only` for that width, or `min`, `max` or a range for anything wider. 3.0.0 will refuse the one-argument form.",
1401
+ "With one argument the element is hidden at exactly that width, `(width: 768px)`, which is a single pixel, and the mixin prints a warning. Write `only` for that width, or `min`, `max` or a range for anything wider.",
1219
1402
  "A `display` written after the include, in the same rule, is emitted after the `@media` block and wins over it. Write it before the include."
1220
1403
  ],
1221
1404
  "examples": [
@@ -1227,7 +1410,10 @@
1227
1410
  ],
1228
1411
  "rejects": [
1229
1412
  ".a { @include remove(a, b, c); }",
1230
- ".a { @include remove(\"max\", var(--narrow)); }"
1413
+ ".a { @include remove(\"max\", var(--narrow)); }",
1414
+ ".a { @include remove(\"huge\"); }",
1415
+ ".a { @include remove(\"min\", \"huge\"); }",
1416
+ ".a { @include remove(\"huge\", \"large\"); }"
1231
1417
  ],
1232
1418
  "warns": [
1233
1419
  ".a { @include remove(\"medium\"); }"
@@ -1267,14 +1453,16 @@
1267
1453
  "name": "$direction",
1268
1454
  "default": "both",
1269
1455
  "accepts": [
1270
- "a CSS resize value such as both, horizontal, vertical or none"
1456
+ "none, both, horizontal, vertical, block, inline or auto, in any case",
1457
+ "a CSS-wide keyword, var(), or null to leave resize out; a quoted keyword is written without its quotes"
1271
1458
  ]
1272
1459
  },
1273
1460
  {
1274
1461
  "name": "$overflow",
1275
1462
  "default": "auto",
1276
1463
  "accepts": [
1277
- "a CSS overflow value"
1464
+ "one or two of visible, hidden, clip, scroll, auto and overlay, such as hidden auto",
1465
+ "a CSS-wide keyword on its own, var(), or null to leave overflow out; a quoted value is written without its quotes"
1278
1466
  ]
1279
1467
  }
1280
1468
  ],
@@ -1285,7 +1473,12 @@
1285
1473
  ".a { @include resizable; }",
1286
1474
  ".a { @include resizable(vertical, scroll); }"
1287
1475
  ],
1288
- "rejects": []
1476
+ "rejects": [
1477
+ ".a { @include resizable(huge); }",
1478
+ ".a { @include resizable(both, huge); }",
1479
+ ".a { @include resizable(both, hidden hidden hidden); }",
1480
+ ".a { @include resizable(both, inherit auto); }"
1481
+ ]
1289
1482
  },
1290
1483
  {
1291
1484
  "name": "responsive-image",
@@ -1321,7 +1514,9 @@
1321
1514
  ],
1322
1515
  "rejects": [
1323
1516
  ".a { @include scissors(5px 10px); }",
1324
- ".a { @include scissors(nonsense); }"
1517
+ ".a { @include scissors(nonsense); }",
1518
+ ".a { @include scissors(10deg); }",
1519
+ ".a { @include scissors(4px 8px 12px 1x); }"
1325
1520
  ]
1326
1521
  },
1327
1522
  {
@@ -1333,7 +1528,7 @@
1333
1528
  "required": true,
1334
1529
  "accepts": [
1335
1530
  "1x, 2x or 3x",
1336
- "a raw resolution such as 120dpi"
1531
+ "a raw resolution in dpi, dpcm, dppx or x, such as 120dpi, or a calculation; a bare number, a length and a negative resolution are refused, because the query would never match"
1337
1532
  ]
1338
1533
  }
1339
1534
  ],
@@ -1344,7 +1539,11 @@
1344
1539
  ".a { @include screen-agent(\"2x\") { background-image: url(\"/img/a@2x.png\"); } }"
1345
1540
  ],
1346
1541
  "rejects": [
1347
- ".a { @include screen-agent(var(--density)) { color: red; } }"
1542
+ ".a { @include screen-agent(var(--density)) { color: red; } }",
1543
+ ".a { @include screen-agent(\"huge\") { color: red; } }",
1544
+ ".a { @include screen-agent(2) { color: red; } }",
1545
+ ".a { @include screen-agent(10px) { color: red; } }",
1546
+ ".a { @include screen-agent(-1dppx) { color: red; } }"
1348
1547
  ]
1349
1548
  },
1350
1549
  {
@@ -1373,7 +1572,13 @@
1373
1572
  ".a { @include sizer(40px); }",
1374
1573
  ".a { @include sizer(120px, 40px); }"
1375
1574
  ],
1376
- "rejects": []
1575
+ "rejects": [
1576
+ ".a { @include sizer(huge); }",
1577
+ ".a { @include sizer(40); }",
1578
+ ".a { @include sizer(120px, 10deg); }",
1579
+ ".a { @include sizer(-40px); }",
1580
+ ".a { @include sizer(\"40px\"); }"
1581
+ ]
1377
1582
  },
1378
1583
  {
1379
1584
  "name": "smartphone",
@@ -1418,7 +1623,7 @@
1418
1623
  "accepts": [
1419
1624
  "an image path ending in .png, .jpg or .svg",
1420
1625
  "a background position",
1421
- "both, image first"
1626
+ "both, image first, where the image is one path as a string"
1422
1627
  ]
1423
1628
  }
1424
1629
  ],
@@ -1431,7 +1636,14 @@
1431
1636
  ".icon { @include sprite(0 -40px); }"
1432
1637
  ],
1433
1638
  "rejects": [
1434
- ".icon { @include sprite(\"/img/sprite.txt\"); }"
1639
+ ".icon { @include sprite(\"/img/sprite.txt\"); }",
1640
+ ".icon { @include sprite(\"/img/a.png\" \"/img/b.png\", 0 -40px); }",
1641
+ ".icon { @include sprite(42, 0 -40px); }",
1642
+ ".icon { @include sprite(0 red); }",
1643
+ ".icon { @include sprite(\"/img/sprite.png\", 10deg); }",
1644
+ ".icon { @include sprite(\"/img/sprite.png\", 1); }",
1645
+ ".icon { @include sprite(\"/img/sprite.png\", 10px 20px 30px 40px); }",
1646
+ ".icon { @include sprite(\"/img/sprite.png\", auto); }"
1435
1647
  ]
1436
1648
  },
1437
1649
  {
@@ -1495,29 +1707,89 @@
1495
1707
  "kind": "mixin",
1496
1708
  "arguments": [
1497
1709
  {
1498
- "name": "$direction",
1710
+ "name": "$colors",
1499
1711
  "required": true,
1500
1712
  "accepts": [
1713
+ "one or more colour stops, in the forms the gradient mixin takes",
1714
+ "a stop the browser drops is refused, because the gradient and the transparent text would go with it",
1715
+ "a single colour warns"
1716
+ ]
1717
+ },
1718
+ {
1719
+ "name": "$type",
1720
+ "default": "linear",
1721
+ "accepts": [
1722
+ "linear, the default",
1723
+ "radial",
1724
+ "conic"
1725
+ ]
1726
+ },
1727
+ {
1728
+ "name": "$direction",
1729
+ "default": "null",
1730
+ "accepts": [
1731
+ "linear only",
1501
1732
  "a direction name such as top or bottom-left",
1502
- "an angle such as 45deg"
1733
+ "an angle in deg, grad, rad or turn, or 0",
1734
+ "\"to top\" or \"to left top\" as a string",
1735
+ "var() or calc()"
1503
1736
  ]
1504
1737
  },
1505
1738
  {
1506
- "name": "$colors",
1507
- "required": true,
1739
+ "name": "$shape",
1740
+ "default": "null",
1508
1741
  "accepts": [
1509
- "two or more colours"
1742
+ "radial only, circle or ellipse with an optional size"
1743
+ ]
1744
+ },
1745
+ {
1746
+ "name": "$position",
1747
+ "default": "null",
1748
+ "accepts": [
1749
+ "radial or conic, a position name or at followed by a position"
1750
+ ]
1751
+ },
1752
+ {
1753
+ "name": "$from",
1754
+ "default": "null",
1755
+ "accepts": [
1756
+ "conic only, an angle"
1757
+ ]
1758
+ },
1759
+ {
1760
+ "name": "$in",
1761
+ "default": "null",
1762
+ "accepts": [
1763
+ "a colour space such as oklab, or a polar one with a hue method",
1764
+ "the gradient is written once without the space first, for a browser that does not know it"
1765
+ ]
1766
+ },
1767
+ {
1768
+ "name": "$repeating",
1769
+ "default": "false",
1770
+ "accepts": [
1771
+ "false, the default",
1772
+ "true"
1510
1773
  ]
1511
1774
  }
1512
1775
  ],
1513
1776
  "file": "scss/library/_text-gradient.scss",
1514
- "signature": "text-gradient($direction, $colors)",
1515
- "summary": "Applies a linear gradient to the text itself via background-clip.",
1777
+ "signature": "text-gradient($colors, $type: linear, $direction: null, $shape: null, $position: null, $from: null, $in: null, $repeating: false)",
1778
+ "summary": "Fills the text with a gradient through background-clip: text. It takes the gradient mixin's arguments, colours first: a linear, radial or conic gradient, plain or repeating, with an optional colour space.",
1516
1779
  "examples": [
1517
- ".a { @include text-gradient(\"top\", (red, blue)); }"
1780
+ ".a { @include text-gradient((red, blue), $direction: top); }",
1781
+ ".a { @include text-gradient(blue yellow, $direction: right, $in: oklab); }",
1782
+ ".a { @include text-gradient(red yellow lime cyan blue magenta red, conic); }"
1518
1783
  ],
1519
1784
  "rejects": [
1520
- ".a { @include text-gradient(sideways, (red, blue)); }"
1785
+ ".a { @include text-gradient(\"top\", (red, blue)); }",
1786
+ ".a { @include text-gradient(red blue, $direction: sideways); }",
1787
+ ".a { @include text-gradient((huge, blue)); }",
1788
+ ".a { @include text-gradient((\"red\", blue)); }",
1789
+ ".a { @include text-gradient(red blue, $from: 45deg); }"
1790
+ ],
1791
+ "warns": [
1792
+ ".a { @include text-gradient(red); }"
1521
1793
  ]
1522
1794
  },
1523
1795
  {
@@ -1528,7 +1800,7 @@
1528
1800
  "name": "$image",
1529
1801
  "default": "null",
1530
1802
  "accepts": [
1531
- "an image path",
1803
+ "an image path, as a string; a list, a number, a colour or a boolean is refused",
1532
1804
  "var(), url(), image-set() or a gradient, written as they are rather than wrapped in url()"
1533
1805
  ]
1534
1806
  }
@@ -1540,7 +1812,10 @@
1540
1812
  ".a { @include text-image(\"/img/t.png\"); }",
1541
1813
  ".a { @include text-image(var(--texture)); }"
1542
1814
  ],
1543
- "rejects": []
1815
+ "rejects": [
1816
+ ".a { @include text-image(16 9); }",
1817
+ ".a { @include text-image(#ff0000); }"
1818
+ ]
1544
1819
  },
1545
1820
  {
1546
1821
  "name": "text-selection",
@@ -1597,14 +1872,16 @@
1597
1872
  "name": "$fallback-color",
1598
1873
  "default": "black",
1599
1874
  "accepts": [
1600
- "a colour for browsers without text-stroke"
1875
+ "a colour for browsers without text-stroke",
1876
+ "each colour accepts a colour, currentColor, a system colour, a function such as var() or light-dark(), a CSS-wide keyword, or null to leave its declaration out"
1601
1877
  ]
1602
1878
  },
1603
1879
  {
1604
1880
  "name": "$color",
1605
1881
  "default": "transparent",
1606
1882
  "accepts": [
1607
- "the text fill colour"
1883
+ "the text fill colour",
1884
+ "a word that is not a colour, a quoted colour, a length or two colours are refused"
1608
1885
  ]
1609
1886
  },
1610
1887
  {
@@ -1629,7 +1906,16 @@
1629
1906
  ".a { @include text-stroke; }",
1630
1907
  ".a { @include text-stroke(black, transparent, red, 2px); }"
1631
1908
  ],
1632
- "rejects": []
1909
+ "rejects": [
1910
+ ".a { @include text-stroke(huge); }",
1911
+ ".a { @include text-stroke(black, \"red\"); }",
1912
+ ".a { @include text-stroke(black, transparent, 10px); }",
1913
+ ".a { @include text-stroke(black, transparent, red blue); }",
1914
+ ".a { @include text-stroke(black, transparent, red, huge); }",
1915
+ ".a { @include text-stroke(black, transparent, red, 5%); }",
1916
+ ".a { @include text-stroke(black, transparent, red, -1px); }",
1917
+ ".a { @include text-stroke(black, transparent, red, 2); }"
1918
+ ]
1633
1919
  },
1634
1920
  {
1635
1921
  "name": "tokens",
@@ -1698,7 +1984,9 @@
1698
1984
  "accepts": [
1699
1985
  "a Sass colour, such as red, #333 or oklch(70% 0.1 200)",
1700
1986
  "currentColor",
1701
- "var(), color-mix() or light-dark(), which CSS resolves"
1987
+ "a system colour such as Canvas",
1988
+ "var(), color-mix(), light-dark(), contrast-color() or rgb(from ...), which CSS resolves",
1989
+ "a CSS-wide keyword is refused, because it is invalid inside the border-color shorthand"
1702
1990
  ]
1703
1991
  },
1704
1992
  {
@@ -1727,7 +2015,13 @@
1727
2015
  ".caret { @include triangle(sideways); }",
1728
2016
  ".caret { @include triangle(\"top\", notacolor); }",
1729
2017
  ".caret { @include triangle(\"top\", url(a.png)); }",
1730
- ".caret { @include triangle(\"top\", red, nonsense); }"
2018
+ ".caret { @include triangle(\"top\", red, nonsense); }",
2019
+ ".caret { @include triangle(\"top\", -webkit-fill-available); }",
2020
+ ".caret { @include triangle(\"top\", red, 5%); }",
2021
+ ".caret { @include triangle(\"top\", red, -10px); }",
2022
+ ".caret { @include triangle(\"top\", red, thin); }",
2023
+ ".caret { @include triangle(\"top\", red, 10); }",
2024
+ ".caret { @include triangle(\"top\", red, 10px 10deg); }"
1731
2025
  ]
1732
2026
  },
1733
2027
  {
@@ -1971,6 +2265,90 @@
1971
2265
  ],
1972
2266
  "rejects": []
1973
2267
  },
2268
+ {
2269
+ "name": "gradientValue",
2270
+ "kind": "function",
2271
+ "arguments": [
2272
+ {
2273
+ "name": "$colors",
2274
+ "required": true,
2275
+ "accepts": [
2276
+ "the colour stops, in the forms the gradient mixin takes",
2277
+ "a single colour warns, because browsers before Chrome 135, Firefox 136 and Safari 18.4 drop that gradient"
2278
+ ]
2279
+ },
2280
+ {
2281
+ "name": "$type",
2282
+ "default": "linear",
2283
+ "accepts": [
2284
+ "linear, the default",
2285
+ "radial",
2286
+ "conic"
2287
+ ]
2288
+ },
2289
+ {
2290
+ "name": "$direction",
2291
+ "default": "null",
2292
+ "accepts": [
2293
+ "linear only, in the forms the gradient mixin takes"
2294
+ ]
2295
+ },
2296
+ {
2297
+ "name": "$shape",
2298
+ "default": "null",
2299
+ "accepts": [
2300
+ "radial only, circle or ellipse with an optional size"
2301
+ ]
2302
+ },
2303
+ {
2304
+ "name": "$position",
2305
+ "default": "null",
2306
+ "accepts": [
2307
+ "radial or conic, a position name or at followed by a position"
2308
+ ]
2309
+ },
2310
+ {
2311
+ "name": "$from",
2312
+ "default": "null",
2313
+ "accepts": [
2314
+ "conic only, an angle"
2315
+ ]
2316
+ },
2317
+ {
2318
+ "name": "$in",
2319
+ "default": "null",
2320
+ "accepts": [
2321
+ "a colour space, with a hue method for a polar one",
2322
+ "var()"
2323
+ ]
2324
+ },
2325
+ {
2326
+ "name": "$repeating",
2327
+ "default": "false",
2328
+ "accepts": [
2329
+ "false, the default",
2330
+ "true"
2331
+ ]
2332
+ }
2333
+ ],
2334
+ "file": "scss/utilities/_gradient-value.scss",
2335
+ "signature": "gradientValue($colors, $type: linear, $direction: null, $shape: null, $position: null, $from: null, $in: null, $repeating: false)",
2336
+ "summary": "The gradient mixin's gradient as a value, for layering it with an image in one background-image, or using it as a mask-image or border-image. It takes the same arguments and refuses the same input, but cannot write the fallback the mixin writes before a gradient with $in.",
2337
+ "examples": [
2338
+ ".a { background-image: gradientValue((rgba(0, 0, 0, 0.75), transparent), $direction: top), url(\"/img/hero.jpg\"); }",
2339
+ ".a { mask-image: gradientValue((#000 60%, transparent)); }",
2340
+ ".a { border: 4px solid; border-image: gradientValue((red, blue), $direction: right) 1; }"
2341
+ ],
2342
+ "rejects": [
2343
+ ".a { background-image: gradientValue((red, blue), $direction: sideways); }",
2344
+ ".a { background-image: gradientValue((red, blue), $shape: circle); }",
2345
+ ".a { background-image: gradientValue((red 10px, blue), conic); }",
2346
+ ".a { background-image: gradientValue((red, blue), $in: rgb); }"
2347
+ ],
2348
+ "warns": [
2349
+ ".a { background-image: gradientValue(red); }"
2350
+ ]
2351
+ },
1974
2352
  {
1975
2353
  "name": "isColor",
1976
2354
  "kind": "function",
@@ -2246,17 +2624,21 @@
2246
2624
  "name": "$value",
2247
2625
  "required": true,
2248
2626
  "accepts": [
2249
- "a key from $map-for-breakpoints, or a raw length"
2627
+ "a key from $map-for-breakpoints",
2628
+ "a length, a percentage or a CSS function such as var() or min(), returned as it is"
2250
2629
  ]
2251
2630
  }
2252
2631
  ],
2253
2632
  "file": "scss/utilities/_validate-breakpoint.scss",
2254
2633
  "signature": "validateBreakpoint($value)",
2255
- "summary": "Resolves a breakpoint name to its width, passing other values through.",
2634
+ "summary": "Resolves a breakpoint name to its width, passing a length, a percentage or a CSS function through, and refusing a word that is not a key.",
2256
2635
  "examples": [
2257
2636
  ".a { width: validateBreakpoint(\"medium\"); }"
2258
2637
  ],
2259
- "rejects": []
2638
+ "rejects": [
2639
+ ".a { width: validateBreakpoint(\"huge\"); }",
2640
+ ".a { width: validateBreakpoint(\"small\" \"medium\"); }"
2641
+ ]
2260
2642
  },
2261
2643
  {
2262
2644
  "name": "validateLength",