grailwind 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Paul Firmin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,72 @@
1
- # Temporary Holding Version
1
+ # Grailwind CSS
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Heraldic blazon for [Tailwind CSS](https://tailwindcss.com). Draw coats of
4
+ arms, or style anything else, in the language heralds have used for 800 years:
5
+
6
+ ```html
7
+ <div class="escutcheon azure chevron-or">
8
+ <div class="charges between">
9
+ <i class="mullet argent"></i>
10
+ <i class="mullet argent"></i>
11
+ <i class="mullet argent"></i>
12
+ </div>
13
+ </div>
14
+ ```
15
+
16
+ That's *Azure, a chevron Or between three mullets Argent*: a blue shield, a
17
+ gold chevron, and three silver stars around it.
18
+
19
+ **[Read the documentation](https://pafirmin.github.io/grailwind/)** for every class, with live examples.
20
+
21
+ > Grailwind is a light-hearted project at version 0.x, so class names may
22
+ > still change.
23
+
24
+ ## Install
25
+
26
+ Grailwind is a plugin for Tailwind CSS v4.
27
+
28
+ ```sh
29
+ npm install -D grailwind
30
+ ```
31
+
32
+ Import it after Tailwind:
33
+
34
+ ```css
35
+ @import "tailwindcss";
36
+ @import "grailwind";
37
+ ```
38
+
39
+ This adds the heraldic tinctures (`or`, `argent`, `gules`, `azure`, `vert`,
40
+ `purpure`, `sable`) alongside Tailwind's own colours.
41
+
42
+ For a more authentic experience, import `grailwind/strict` instead, and the
43
+ tinctures replace Tailwind's colours entirely.
44
+
45
+ ## What's included
46
+
47
+ - **Tinctures:** a tincture on its own sets the background (`azure`), and
48
+ Tailwind's prefixes work as usual (`text-or`).
49
+ - **The shield:** `escutcheon`, plus `bordure-*`.
50
+ - **Divided fields:** `per-pale-or-gules`, `quarterly-azure-argent`,
51
+ `gyronny-or-sable` and more, or `per-pale`, `per-fess` and `quarterly` for
52
+ layout.
53
+ - **Ordinaries:** `fess-or`, `chevron-gules`, `cross-argent`, `chief-azure`
54
+ and more.
55
+ - **Charges:** `mullet`, `fleur-de-lis`, `bezant` and more, arranged by
56
+ number, `in-pale`, `in-fess`, `in-bend` or `between` the ordinary, or
57
+ placed at a named point such as `in-dexter-chief`, and sized with
58
+ `charge-size-*`.
59
+ - **Your own charges:** any SVG, via `charge-[url(…)]`.
60
+
61
+ ## Development
62
+
63
+ ```sh
64
+ npm install
65
+ npm test # checks both the default and strict builds
66
+ npm run build # builds the docs site; `npm run dev` rebuilds on change
67
+ python3 -m http.server -d docs
68
+ ```
69
+
70
+ ## Licence
71
+
72
+ [MIT](LICENSE)
package/charges.js ADDED
@@ -0,0 +1,163 @@
1
+ /*
2
+ * Grailwind CSS: charges and their arrangement.
3
+ */
4
+ import plugin from "tailwindcss/plugin";
5
+
6
+ const star = (cx, cy, r, points = 5) => {
7
+ const coords = [];
8
+ for (let i = 0; i < points * 2; i++) {
9
+ const radius = i % 2 ? r * 0.382 : r;
10
+ const angle = (Math.PI / points) * i - Math.PI / 2;
11
+ coords.push(`${cx + radius * Math.cos(angle)},${cy + radius * Math.sin(angle)}`);
12
+ }
13
+ return `<polygon points="${coords.join(" ")}"/>`;
14
+ };
15
+
16
+ const SHAPES = {
17
+ roundel: `<circle cx="50" cy="50" r="46"/>`,
18
+ annulet: `<circle cx="50" cy="50" r="39" fill="none" stroke="#000" stroke-width="14"/>`,
19
+ mullet: star(50, 53, 48),
20
+ lozenge: `<polygon points="50,2 84,50 50,98 16,50"/>`,
21
+ billet: `<rect x="28" y="4" width="44" height="92"/>`,
22
+ crescent: `<mask id="m"><rect width="100" height="100" fill="#fff"/><circle cx="50" cy="35" r="35"/></mask><circle cx="50" cy="54" r="42" mask="url(#m)"/>`,
23
+ "fleur-de-lis": `
24
+ <path d="M50 2C61 16 64 36 55 56H45C36 36 39 16 50 2Z"/>
25
+ <path d="M55 56C57 38 70 24 84 26C97 29 99 46 89 52C92 44 87 37 80 39C71 42 66 50 66 56Z"/>
26
+ <path d="M45 56C43 38 30 24 16 26C3 29 1 46 11 52C8 44 13 37 20 39C29 42 34 50 34 56Z"/>
27
+ <rect x="28" y="56" width="44" height="9" rx="2"/>
28
+ <path d="M45 65H55C55 74 53 82 50 90C47 82 45 74 45 65Z"/>
29
+ <path d="M58 65C62 74 72 80 84 78C80 88 64 90 56 74Z"/>
30
+ <path d="M42 65C38 74 28 80 16 78C20 88 36 90 44 74Z"/>`,
31
+ };
32
+
33
+ // Roundels have their own names by tincture.
34
+ const ROUNDELS = {
35
+ bezant: "or",
36
+ plate: "argent",
37
+ torteau: "gules",
38
+ hurt: "azure",
39
+ pellet: "sable",
40
+ };
41
+
42
+ // Points as [left%, top%] of the shield, plus a charge size as % of its width.
43
+ // The default for each number of charges, e.g. three are placed 2 and 1.
44
+ const DEFAULTS = {
45
+ 1: { size: 50, points: [[50, 45]] },
46
+ 2: { size: 30, points: [[50, 24], [50, 66]] },
47
+ 3: { size: 28, points: [[28, 25], [72, 25], [50, 64]] },
48
+ 4: { size: 24, points: [[30, 24], [70, 24], [32, 60], [68, 60]] },
49
+ 6: { size: 20, points: [[20, 18], [50, 18], [80, 18], [35, 42], [65, 42], [50, 66]] },
50
+ };
51
+
52
+ // The points of the shield, for placing a single charge, e.g. `in-dexter-chief`.
53
+ const POINTS = {
54
+ "dexter-chief": [25, 17],
55
+ chief: [50, 15],
56
+ "sinister-chief": [75, 17],
57
+ "honour-point": [50, 30],
58
+ "fess-point": [50, 45],
59
+ "nombril-point": [50, 60],
60
+ "dexter-base": [30, 72],
61
+ base: [50, 84],
62
+ "sinister-base": [70, 72],
63
+ };
64
+ const POINT_SIZE = 22;
65
+
66
+ const ARRANGEMENTS = {
67
+ "in-pale": {
68
+ 2: { size: 30, points: [[50, 24], [50, 66]] },
69
+ 3: { size: 22, points: [[50, 16], [50, 43], [50, 70]] },
70
+ },
71
+ "in-fess": {
72
+ 2: { size: 30, points: [[30, 45], [70, 45]] },
73
+ 3: { size: 24, points: [[22, 45], [50, 45], [78, 45]] },
74
+ },
75
+ "in-bend": {
76
+ 2: { size: 28, points: [[30, 26], [70, 64]] },
77
+ 3: { size: 22, points: [[22, 16], [50, 45], [78, 74]] },
78
+ },
79
+ };
80
+
81
+ const svgUrl = (shape) =>
82
+ `url("data:image/svg+xml,${encodeURIComponent(
83
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">${shape}</svg>`,
84
+ )}")`;
85
+
86
+ const maskRules = (image) => ({
87
+ "mask-image": image,
88
+ "mask-size": "contain",
89
+ "mask-repeat": "no-repeat",
90
+ "mask-position": "center",
91
+ });
92
+
93
+ const place = ([left, top], size) => ({
94
+ left: `${left}%`,
95
+ top: `${top}%`,
96
+ width: `var(--charge-size, ${size}%)`,
97
+ });
98
+
99
+ const hasCount = (n) => `:has(> :nth-child(${n}):last-child)`;
100
+
101
+ export default plugin(({ addUtilities, matchUtilities }) => {
102
+ // User-defined charges from images
103
+ matchUtilities({ charge: maskRules }, { type: ["url"] });
104
+
105
+ const utilities = {};
106
+
107
+ for (const [name, shape] of Object.entries(SHAPES)) {
108
+ utilities[`.${name}`] = maskRules(svgUrl(shape));
109
+ }
110
+
111
+ for (const [name, tincture] of Object.entries(ROUNDELS)) {
112
+ utilities[`.${name}`] = {
113
+ ...maskRules(svgUrl(SHAPES.roundel)),
114
+ "background-color": `var(--color-${tincture})`,
115
+ };
116
+ }
117
+
118
+ // Defaults use :where() so arrangements and `between` always win.
119
+ const charges = {
120
+ position: "absolute",
121
+ inset: "var(--field-top, 0%) 0 0",
122
+ "& > *": {
123
+ position: "absolute",
124
+ "aspect-ratio": "1",
125
+ translate: "-50% -50%",
126
+ "object-fit": "contain",
127
+ },
128
+ };
129
+ for (const [count, { size, points }] of Object.entries(DEFAULTS)) {
130
+ points.forEach((point, i) => {
131
+ charges[`&:where(${hasCount(count)}) > :where(:nth-child(${i + 1}))`] =
132
+ place(point, size);
133
+ });
134
+ }
135
+ utilities[".charges"] = charges;
136
+
137
+ for (const [name, counts] of Object.entries(ARRANGEMENTS)) {
138
+ const arrangement = {};
139
+ for (const [count, { size, points }] of Object.entries(counts)) {
140
+ points.forEach((point, i) => {
141
+ arrangement[`&${hasCount(count)} > :nth-child(${i + 1})`] = place(point, size);
142
+ });
143
+ }
144
+ utilities[`.${name}`] = arrangement;
145
+ }
146
+
147
+ // Positions come from the ordinary on the shield (see ordinaries.js).
148
+ const between = {};
149
+ for (let i = 1; i <= 4; i++) {
150
+ between[`& > :nth-child(${i})`] = {
151
+ left: `var(--between-${i}-x)`,
152
+ top: `var(--between-${i}-y)`,
153
+ width: "var(--charge-size, var(--between-size))",
154
+ };
155
+ }
156
+ utilities[".between"] = between;
157
+
158
+ for (const [name, point] of Object.entries(POINTS)) {
159
+ utilities[`.in-${name}`] = { ".charges > &": place(point, POINT_SIZE) };
160
+ }
161
+
162
+ addUtilities(utilities);
163
+ });
package/divisions.js ADDED
@@ -0,0 +1,69 @@
1
+ /*
2
+ * Grailwind CSS: field divisions as decoration.
3
+ */
4
+ import plugin from "tailwindcss/plugin";
5
+
6
+ const TINCTURES = ["or", "argent", "gules", "azure", "vert", "purpure", "sable"];
7
+
8
+ // Each division maps (first, second) tincture colours to background rules.
9
+ const layer = (image) => ({ "background-image": image });
10
+
11
+ const DIVISIONS = {
12
+ // Vertical split: first on the dexter (viewer's left).
13
+ "per-pale": (a, b) => layer(`linear-gradient(to right, ${a} 50%, ${b} 50%)`),
14
+
15
+ // Horizontal split: first in chief.
16
+ "per-fess": (a, b) => layer(`linear-gradient(to bottom, ${a} 50%, ${b} 50%)`),
17
+
18
+ // Line from dexter chief to sinister base: first in the upper half.
19
+ // With a corner-to-corner gradient, the 50% line joins the other two corners.
20
+ "per-bend": (a, b) => layer(`linear-gradient(to bottom left, ${a} 50%, ${b} 50%)`),
21
+
22
+ // Line from sinister chief to dexter base: first in the upper half.
23
+ "per-bend-sinister": (a, b) =>
24
+ layer(`linear-gradient(to bottom right, ${a} 50%, ${b} 50%)`),
25
+
26
+ // Quarters 1 and 4 (dexter chief, sinister base) are the first tincture.
27
+ // Linear gradients rather than conic, which render jagged edges in some browsers.
28
+ quarterly: (a, b) => ({
29
+ "background-image": `linear-gradient(to right, ${a} 50%, ${b} 50%), linear-gradient(to right, ${b} 50%, ${a} 50%)`,
30
+ "background-size": "100% 50%, 100% 100%",
31
+ "background-position": "top, top",
32
+ "background-repeat": "no-repeat",
33
+ }),
34
+
35
+ // Gyronny of eight: each quarter split corner to corner. The first tincture
36
+ // is in the gyron just dexter of the top line. The background colour fills
37
+ // any sub-pixel seam between quarters.
38
+ gyronny: (a, b) => ({
39
+ "background-color": b,
40
+ "background-image": [
41
+ `linear-gradient(to bottom left, ${a} 50%, ${b} 50%)`,
42
+ `linear-gradient(to bottom right, ${b} 50%, ${a} 50%)`,
43
+ `linear-gradient(to bottom left, ${b} 50%, ${a} 50%)`,
44
+ `linear-gradient(to bottom right, ${a} 50%, ${b} 50%)`,
45
+ ].join(", "),
46
+ "background-size": "50% 50%",
47
+ "background-position": "left top, right top, right bottom, left bottom",
48
+ "background-repeat": "no-repeat",
49
+ }),
50
+ };
51
+
52
+ export default plugin(({ addUtilities }) => {
53
+ const utilities = {};
54
+
55
+ for (const [division, background] of Object.entries(DIVISIONS)) {
56
+ for (const first of TINCTURES) {
57
+ for (const second of TINCTURES) {
58
+ if (first === second) continue;
59
+
60
+ utilities[`.${division}-${first}-${second}`] = background(
61
+ `var(--color-${first})`,
62
+ `var(--color-${second})`,
63
+ );
64
+ }
65
+ }
66
+ }
67
+
68
+ addUtilities(utilities);
69
+ });
package/grailwind.css ADDED
@@ -0,0 +1,102 @@
1
+ /*
2
+ * Grailwind CSS: heraldic blazon for Tailwind v4.
3
+ *
4
+ * Import after Tailwind:
5
+ * @import "tailwindcss";
6
+ * @import "grailwind";
7
+ *
8
+ * Adds the tinctures alongside Tailwind's colours. For tinctures only,
9
+ * import "grailwind/strict" instead.
10
+ */
11
+
12
+ @plugin "./divisions.js";
13
+ @plugin "./ordinaries.js";
14
+ @plugin "./charges.js";
15
+
16
+ /* ---------------------------------------------------------------------------
17
+ * Tinctures
18
+ * ------------------------------------------------------------------------- */
19
+ @theme {
20
+ /* Metals */
21
+ --color-or: #f5c518;
22
+ --color-argent: #ffffff;
23
+
24
+ /* Colours */
25
+ --color-gules: #d21f1f;
26
+ --color-azure: #1f4fb0;
27
+ --color-vert: #1d8a3c;
28
+ --color-purpure: #7e3a8e;
29
+ --color-sable: #141414;
30
+ }
31
+
32
+ /* ---------------------------------------------------------------------------
33
+ * Bare tinctures
34
+ * ------------------------------------------------------------------------- */
35
+ @utility or { background-color: var(--color-or); }
36
+ @utility argent { background-color: var(--color-argent); }
37
+ @utility gules { background-color: var(--color-gules); }
38
+ @utility azure { background-color: var(--color-azure); }
39
+ @utility vert { background-color: var(--color-vert); }
40
+ @utility purpure { background-color: var(--color-purpure); }
41
+ @utility sable { background-color: var(--color-sable); }
42
+
43
+ /* ---------------------------------------------------------------------------
44
+ * Field divisions
45
+ * ------------------------------------------------------------------------- */
46
+
47
+ /* Per pale: split vertically into dexter | sinister. */
48
+ @utility per-pale {
49
+ display: grid;
50
+ grid-auto-flow: column;
51
+ grid-auto-columns: 1fr;
52
+ }
53
+
54
+ /* Per fess: split horizontally into chief / base. */
55
+ @utility per-fess {
56
+ display: grid;
57
+ grid-auto-flow: row;
58
+ grid-auto-rows: 1fr;
59
+ }
60
+
61
+ /* Quarterly: four quarters, numbered 1–4 across then down.
62
+ * Quarter 1 is dexter chief, i.e. the viewer's top left. */
63
+ @utility quarterly {
64
+ display: grid;
65
+ grid-template-columns: 1fr 1fr;
66
+ grid-template-rows: 1fr 1fr;
67
+ }
68
+
69
+ /* ---------------------------------------------------------------------------
70
+ * Subordinaries
71
+ * ------------------------------------------------------------------------- */
72
+
73
+ /* Bordure: a border in a given tincture, e.g. `bordure-or`. */
74
+ @utility bordure-* {
75
+ border-style: solid;
76
+ border-width: 0.75rem;
77
+ border-color: --value(--color-*);
78
+ }
79
+
80
+ /* ---------------------------------------------------------------------------
81
+ * The shield itself
82
+ * ------------------------------------------------------------------------- */
83
+
84
+ /* Escutcheon: a shield shape to draw arms in. */
85
+ @utility escutcheon {
86
+ position: relative;
87
+ aspect-ratio: 5 / 6;
88
+ overflow: hidden;
89
+ border-radius: 0 0 50% 50% / 0 0 45% 45%;
90
+ box-shadow: 0 0 0 2px var(--color-sable);
91
+ }
92
+
93
+ /* ---------------------------------------------------------------------------
94
+ * Charge size
95
+ * ------------------------------------------------------------------------- */
96
+
97
+ /* Charge width as a % of the shield, e.g. `charge-size-20` or `charge-size-[3rem]`.
98
+ * On a `charges` container it sizes every charge; on a charge, just that one. */
99
+ @utility charge-size-* {
100
+ --charge-size: calc(--value(integer) * 1%);
101
+ --charge-size: --value([percentage], [length]);
102
+ }
package/ordinaries.js ADDED
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Grailwind CSS: ordinaries, e.g. `fess-or`.
3
+ */
4
+ import plugin from "tailwindcss/plugin";
5
+
6
+ const TINCTURES = ["or", "argent", "gules", "azure", "vert", "purpure", "sable"];
7
+
8
+ const ORDINARIES = {
9
+ pale: "polygon(35% 0, 65% 0, 65% 100%, 35% 100%)",
10
+ fess: "polygon(0 30%, 100% 30%, 100% 60%, 0 60%)",
11
+ bend: "polygon(0 0, 20% 0, 100% 80%, 100% 100%, 80% 100%, 0 20%)",
12
+ "bend-sinister":
13
+ "polygon(100% 0, 80% 0, 0 80%, 0 100%, 20% 100%, 100% 20%)",
14
+ chevron: "polygon(50% 25%, 100% 75%, 100% 95%, 50% 45%, 0 95%, 0 75%)",
15
+ cross:
16
+ "polygon(40% 0, 60% 0, 60% 35%, 100% 35%, 100% 55%, 60% 55%, 60% 100%, 40% 100%, 40% 55%, 0 55%, 0 35%, 40% 35%)",
17
+ saltire:
18
+ "polygon(0 0, 15% 0, 50% 35%, 85% 0, 100% 0, 100% 15%, 65% 50%, 100% 85%, 100% 100%, 85% 100%, 50% 65%, 15% 100%, 0 100%, 0 85%, 35% 50%, 0 15%)",
19
+ pall: "polygon(0 0, 15% 0, 50% 35%, 85% 0, 100% 0, 100% 15%, 60% 50%, 60% 100%, 40% 100%, 40% 50%, 0 15%)",
20
+ chief: "polygon(0 0, 100% 0, 100% 30%, 0 30%)",
21
+ };
22
+
23
+ const PSEUDO = { chief: "&::after" };
24
+
25
+ // Where charges go for "between", as [left%, top%], plus their size as % of width.
26
+ const BETWEEN = {
27
+ pale: { size: 18, points: [[18, 42], [82, 42]] },
28
+ fess: { size: 20, points: [[30, 15], [70, 15], [50, 78]] },
29
+ bend: { size: 24, points: [[70, 26], [30, 68]] },
30
+ "bend-sinister": { size: 24, points: [[30, 26], [70, 68]] },
31
+ chevron: { size: 22, points: [[24, 22], [76, 22], [50, 70]] },
32
+ cross: { size: 18, points: [[20, 17], [80, 17], [24, 72], [76, 72]] },
33
+ saltire: { size: 16, points: [[50, 13], [14, 50], [86, 50], [50, 84]] },
34
+ pall: { size: 18, points: [[50, 11], [18, 56], [82, 56]] },
35
+ };
36
+
37
+ const betweenVars = ({ size, points }) => {
38
+ const vars = { "--between-size": `${size}%` };
39
+ points.forEach(([left, top], i) => {
40
+ vars[`--between-${i + 1}-x`] = `${left}%`;
41
+ vars[`--between-${i + 1}-y`] = `${top}%`;
42
+ });
43
+ return vars;
44
+ };
45
+
46
+ export default plugin(({ addUtilities }) => {
47
+ const utilities = {};
48
+
49
+ for (const [ordinary, shape] of Object.entries(ORDINARIES)) {
50
+ for (const tincture of TINCTURES) {
51
+ utilities[`.${ordinary}-${tincture}`] = {
52
+ position: "relative",
53
+ ...(BETWEEN[ordinary] && betweenVars(BETWEEN[ordinary])),
54
+ // With a chief, everything else is drawn in the field below it.
55
+ ...(ordinary === "chief" && { "--field-top": "30%" }),
56
+ [PSEUDO[ordinary] ?? "&::before"]: {
57
+ content: '""',
58
+ position: "absolute",
59
+ inset: ordinary === "chief" ? "0" : "var(--field-top, 0%) 0 0",
60
+ "background-color": `var(--color-${tincture})`,
61
+ "clip-path": shape,
62
+ },
63
+ };
64
+ }
65
+ }
66
+
67
+ addUtilities(utilities);
68
+ });
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "grailwind",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "scripts": {
5
+ "build": "tailwindcss -i docs/app.css -o docs/site.css",
6
+ "dev": "tailwindcss -i docs/app.css -o docs/site.css --watch",
7
+ "test": "node test/modes.mjs"
8
+ },
9
+ "keywords": [
10
+ "tailwindcss",
11
+ "tailwind",
12
+ "heraldry",
13
+ "blazon",
14
+ "css"
15
+ ],
16
+ "author": "Paul Firmin",
17
+ "license": "MIT",
18
+ "description": "Heraldic blazon for Tailwind CSS: tinctures, divisions, ordinaries and charges",
19
+ "devDependencies": {
20
+ "@tailwindcss/cli": "^4.3.3",
21
+ "tailwindcss": "^4.3.3"
22
+ },
23
+ "type": "module",
24
+ "style": "grailwind.css",
25
+ "exports": {
26
+ ".": {
27
+ "style": "./grailwind.css",
28
+ "default": "./grailwind.css"
29
+ },
30
+ "./strict": {
31
+ "style": "./strict.css",
32
+ "default": "./strict.css"
33
+ }
34
+ },
35
+ "files": [
36
+ "grailwind.css",
37
+ "divisions.js",
38
+ "ordinaries.js",
39
+ "charges.js",
40
+ "strict.css",
41
+ "palette-reset.css"
42
+ ],
43
+ "peerDependencies": {
44
+ "tailwindcss": "^4.0.0"
45
+ },
46
+ "homepage": "https://pafirmin.github.io/grailwind/",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/pafirmin/grailwind.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/pafirmin/grailwind/issues"
53
+ }
54
+ }
@@ -0,0 +1,4 @@
1
+ /* Removes Tailwind's colours. Used by strict.css. */
2
+ @theme {
3
+ --color-*: initial;
4
+ }
package/strict.css ADDED
@@ -0,0 +1,5 @@
1
+ /*
2
+ * Grailwind CSS, strict: the tinctures replace Tailwind's colours entirely.
3
+ */
4
+ @import "./palette-reset.css";
5
+ @import "./grailwind.css";