stylelint-plugin-rhythmguard 1.4.0 → 1.4.2

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/CHANGELOG.md CHANGED
@@ -6,6 +6,30 @@ The format follows Keep a Changelog principles and semantic versioning.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.4.2] - 2026-02-21
10
+
11
+ ### Changed
12
+
13
+ - npm package artifact is now leaner by excluding non-runtime media assets from published files.
14
+ - README media links now use absolute GitHub URLs so npm README rendering remains intact without bundling local media files.
15
+ - Added a dedicated "Drop-In for Existing Projects" path with a single install command and a single config block.
16
+ - Added comparison and migration guidance:
17
+ - `docs/COMPARISON.md` (`defensive-css` vs `logical-css` vs Rhythmguard + migration recipes)
18
+ - `docs/ADOPTION_DIFFS.md` (real before/after excerpts from public codebases)
19
+ - Added Dev.to publishing assets:
20
+ - `docs/DEVTO_ORIGINAL_UPDATE_NOTE_2026-02-21.md`
21
+ - `docs/DEVTO_CONTINUATION_2026-02-21.md`
22
+
23
+ ## [1.4.1] - 2026-02-21
24
+
25
+ ### Fixed
26
+
27
+ - `properties` now correctly supports regex-like string entries (for example `"/^(margin|padding)$/"`) in rule options.
28
+ - Property matcher behavior is now deterministic for regex matchers with stateful `g`/`y` flags by normalizing stateful behavior during matching.
29
+ - Generic rule messaging for expanded property groups:
30
+ - `rhythmguard/use-scale` now reports off-scale values without spacing-only wording.
31
+ - `rhythmguard/prefer-token` now reports raw scale values without spacing-only wording.
32
+
9
33
  ## [1.4.0] - 2026-02-21
10
34
 
11
35
  ### Added
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="./assets/rhythmguard-banner.svg" width="100%" alt="Rhythmguard banner in Geist Pixel" />
2
+ <img src="https://raw.githubusercontent.com/petrilahdelma/stylelint-plugin-rhythmguard/main/assets/rhythmguard-banner.svg" width="100%" alt="Rhythmguard banner in Geist Pixel" />
3
3
  </p>
4
4
 
5
5
  # stylelint-plugin-rhythmguard
@@ -17,8 +17,8 @@ High-precision spacing governance for CSS and design systems.
17
17
  ## Demo
18
18
 
19
19
  <p align="center">
20
- <a href="./assets/rhythmguard-campaign-60s.webm">
21
- <img src="./assets/rhythmguard-campaign-60s.gif" width="100%" alt="Rhythmguard 60-second demo" />
20
+ <a href="https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/assets/rhythmguard-campaign-60s.webm">
21
+ <img src="https://raw.githubusercontent.com/petrilahdelma/stylelint-plugin-rhythmguard/main/assets/rhythmguard-campaign-60s.gif" width="100%" alt="Rhythmguard 60-second demo" />
22
22
  </a>
23
23
  </p>
24
24
 
@@ -35,7 +35,7 @@ It is built for teams that want:
35
35
  ## Rule Matrix
36
36
 
37
37
  <p align="center">
38
- <img src="./assets/rhythmguard-rules.svg" width="100%" alt="Rhythmguard rule matrix visual" />
38
+ <img src="https://raw.githubusercontent.com/petrilahdelma/stylelint-plugin-rhythmguard/main/assets/rhythmguard-rules.svg" width="100%" alt="Rhythmguard rule matrix visual" />
39
39
  </p>
40
40
 
41
41
  | Rule | What it does | Autofix |
@@ -50,6 +50,20 @@ It is built for teams that want:
50
50
  npm install --save-dev stylelint stylelint-plugin-rhythmguard
51
51
  ```
52
52
 
53
+ ## Drop-In for Existing Projects (Recommended)
54
+
55
+ If your project already uses Stylelint, you only need one command and one config block:
56
+
57
+ ```bash
58
+ npm install --save-dev stylelint-plugin-rhythmguard
59
+ ```
60
+
61
+ ```json
62
+ {
63
+ "extends": ["stylelint-plugin-rhythmguard/configs/recommended"]
64
+ }
65
+ ```
66
+
53
67
  ## Quick Start
54
68
 
55
69
  ### Recommended config
@@ -117,6 +131,12 @@ Stable shared config entry points:
117
131
  - `stylelint-plugin-rhythmguard/configs/logical`
118
132
  - `stylelint-plugin-rhythmguard/configs/migration`
119
133
 
134
+ ## Comparison and Migration Recipes
135
+
136
+ - Side-by-side tool fit guide with migration snippets: [`docs/COMPARISON.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/COMPARISON.md)
137
+ - Real-world before/after excerpts from public repos: [`docs/ADOPTION_DIFFS.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/ADOPTION_DIFFS.md)
138
+ - Distribution submissions to Stylelint discovery surfaces: [`docs/DISTRIBUTION.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/DISTRIBUTION.md)
139
+
120
140
  ### Full custom setup
121
141
 
122
142
  ```json
@@ -349,8 +369,8 @@ Options:
349
369
  | `mathFunctionArguments` | `Record<mathFn, number[]>` | `{}` | Restricts linting to specific 1-based argument indexes per math function |
350
370
  | `ignoreMathFunctionArguments` | `Record<mathFn, number[]>` | `{}` | Excludes specific 1-based argument indexes per math function |
351
371
  | `propertyGroups` | `Array<'spacing' \| 'radius' \| 'typography' \| 'size'>` | `['spacing']` | Selects built-in property groups when `properties` is not provided |
352
- | `properties` | `Array<string|RegExp>` | built-in spacing patterns | Override targeted property set; string values must be supported spacing property names |
353
- | `propertyScales` | `Record<propertyOrRegex, scaleOrPreset>` | `{}` | Per-property scale overrides (supports exact names or `/regex/flags` keys) |
372
+ | `properties` | `Array<string|RegExp>` | built-in spacing patterns | Override targeted property set; string values may be supported property names or regex-like strings (`/pattern/flags`) |
373
+ | `propertyScales` | `Record<propertyOrRegex, scaleOrPreset>` | `{}` | Per-property scale overrides (supports exact names or `/regex/flags` keys; stateful `g`/`y` flags are normalized for deterministic matching) |
354
374
 
355
375
  ### `rhythmguard/prefer-token`
356
376
 
@@ -395,8 +415,8 @@ Options:
395
415
  | `tailwindConfigPath` | `string` | `null` | Path to Tailwind config used by `tokenMapFromTailwindSpacing` (`.js`, `.cjs`, `.mjs`) |
396
416
  | `ignoreValues` | `string[]` | CSS global keywords + `auto` | Skips keyword literals |
397
417
  | `propertyGroups` | `Array<'spacing' \| 'radius' \| 'typography' \| 'size'>` | `['spacing']` | Selects built-in property groups when `properties` is not provided |
398
- | `properties` | `Array<string|RegExp>` | built-in spacing patterns | Override targeted property set; string values must be supported spacing property names |
399
- | `propertyScales` | `Record<propertyOrRegex, scaleOrPreset>` | `{}` | Per-property scale overrides for numeric migration mode |
418
+ | `properties` | `Array<string|RegExp>` | built-in spacing patterns | Override targeted property set; string values may be supported property names or regex-like strings (`/pattern/flags`) |
419
+ | `propertyScales` | `Record<propertyOrRegex, scaleOrPreset>` | `{}` | Per-property scale overrides for numeric migration mode (stateful `g`/`y` flags are normalized for deterministic matching) |
400
420
 
401
421
  ### `rhythmguard/no-offscale-transform`
402
422
 
@@ -545,6 +565,21 @@ Detailed methodology and custom args are documented in [`docs/BENCHMARKING.md`](
545
565
  ## Article
546
566
 
547
567
  - Dev.to: [Enforcing your spacing standards with Rhythmguard](https://dev.to/petrilahdelma/enforcing-your-spacing-standards-with-rhythmguard-a-custom-stylelint-plugin-1ojj)
568
+ - Original article update note (Feb 21, 2026): [`docs/DEVTO_ORIGINAL_UPDATE_NOTE_2026-02-21.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/DEVTO_ORIGINAL_UPDATE_NOTE_2026-02-21.md)
569
+ - Continuation draft (ready to publish): [`docs/DEVTO_CONTINUATION_2026-02-21.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/DEVTO_CONTINUATION_2026-02-21.md)
570
+
571
+ ## Used by and Community Examples
572
+
573
+ Public codebases currently used for production migration examples:
574
+
575
+ - [PetriLahdelma/digitaltableteur-nextjs](https://github.com/PetriLahdelma/digitaltableteur-nextjs)
576
+ - [PetriLahdelma/digitaltableteur](https://github.com/PetriLahdelma/digitaltableteur)
577
+
578
+ Want your team listed here?
579
+
580
+ 1. Open an issue with `used-by` in the title.
581
+ 2. Include one before/after diff and your Rhythmguard config.
582
+ 3. Add migration notes (false positives, rules enabled, rollout phase).
548
583
 
549
584
  ## Release Workflow
550
585
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stylelint-plugin-rhythmguard",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Stylelint plugin for spacing scale, token enforcement, and Tailwind class-string governance",
5
5
  "keywords": [
6
6
  "stylelint",
@@ -68,7 +68,6 @@
68
68
  }
69
69
  },
70
70
  "files": [
71
- "assets",
72
71
  "scales",
73
72
  "schemas",
74
73
  "src",
@@ -34,7 +34,7 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
34
34
  invalidPreset: (presetName, presetNames) =>
35
35
  `Unknown scale preset "${presetName}". Available presets: ${presetNames.join(', ')}.`,
36
36
  rejected: (value) =>
37
- `Unexpected raw spacing value "${value}". Use design tokens for spacing decisions.`,
37
+ `Unexpected raw scale value "${value}". Use design tokens for scale decisions.`,
38
38
  });
39
39
 
40
40
  function applyNegativeToken(replacement, parsedLength) {
@@ -35,7 +35,7 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
35
35
  invalidPreset: (presetName, presetNames) =>
36
36
  `Unknown scale preset "${presetName}". Available presets: ${presetNames.join(', ')}.`,
37
37
  rejected: (value, lower, upper) =>
38
- `Unexpected off-scale spacing value "${value}". Use spacing scale values (nearest: ${lower} or ${upper}).`,
38
+ `Unexpected off-scale value "${value}". Use scale values (nearest: ${lower} or ${upper}).`,
39
39
  });
40
40
 
41
41
  function getFixedNodeValue(parsedLength, nearestPx, options) {
@@ -102,6 +102,19 @@ function parseRegexLikeString(value) {
102
102
  }
103
103
  }
104
104
 
105
+ function toStableRegex(regex) {
106
+ if (!(regex instanceof RegExp)) {
107
+ return null;
108
+ }
109
+
110
+ if (!regex.global && !regex.sticky) {
111
+ return regex;
112
+ }
113
+
114
+ const stableFlags = regex.flags.replace(/[gy]/g, '');
115
+ return new RegExp(regex.source, stableFlags);
116
+ }
117
+
105
118
  function isPropertyPatternEntry(value) {
106
119
  if (value instanceof RegExp) {
107
120
  return true;
@@ -300,7 +313,9 @@ function normalizePropertyGroups(rawGroups) {
300
313
 
301
314
  function resolvePropertyPatterns(options) {
302
315
  if (Array.isArray(options.properties)) {
303
- return options.properties;
316
+ return options.properties
317
+ .map((entry) => compilePropertyMatcher(entry))
318
+ .filter((entry) => entry !== null);
304
319
  }
305
320
 
306
321
  const groups = normalizePropertyGroups(options.propertyGroups);
@@ -315,7 +330,7 @@ function resolvePropertyPatterns(options) {
315
330
 
316
331
  function compilePropertyMatcher(entry) {
317
332
  if (entry instanceof RegExp) {
318
- return entry;
333
+ return toStableRegex(entry);
319
334
  }
320
335
 
321
336
  if (!isNonEmptyString(entry)) {
@@ -325,7 +340,7 @@ function compilePropertyMatcher(entry) {
325
340
  const trimmed = entry.trim();
326
341
  const parsedRegex = parseRegexLikeString(trimmed);
327
342
  if (parsedRegex) {
328
- return parsedRegex;
343
+ return toStableRegex(parsedRegex);
329
344
  }
330
345
 
331
346
  return trimmed.toLowerCase();
@@ -655,6 +670,10 @@ function resolvePropertyScale(prop, options) {
655
670
 
656
671
  for (const override of options.propertyScaleOverrides) {
657
672
  if (override.matcher instanceof RegExp) {
673
+ if (override.matcher.global || override.matcher.sticky) {
674
+ override.matcher.lastIndex = 0;
675
+ }
676
+
658
677
  if (override.matcher.test(prop)) {
659
678
  return override.scale;
660
679
  }
@@ -11,6 +11,10 @@ function propertyMatches(prop, patterns) {
11
11
  const normalized = prop.toLowerCase();
12
12
  return patterns.some((pattern) => {
13
13
  if (pattern instanceof RegExp) {
14
+ if (pattern.global || pattern.sticky) {
15
+ pattern.lastIndex = 0;
16
+ }
17
+
14
18
  return pattern.test(normalized);
15
19
  }
16
20
 
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,42 +0,0 @@
1
- <svg width="1400" height="420" viewBox="0 0 1400 420" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc">
2
- <title id="title">Rhythmguard</title>
3
- <desc id="desc">Black and white banner using Geist Pixel font.</desc>
4
- <defs>
5
- <style>
6
- @font-face {
7
- font-family: 'GeistPixel';
8
- src: url("data:font/woff2;base64,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") format('woff2');
9
- font-weight: 400;
10
- font-style: normal;
11
- }
12
- .bg { fill: #000; }
13
- .fg { fill: #fff; }
14
- .line { stroke: #fff; stroke-width: 2; }
15
- .stroke { stroke: #fff; stroke-width: 3; fill: none; }
16
- .title { font-family: 'GeistPixel', monospace; font-size: 86px; letter-spacing: 1px; }
17
- .subtitle { font-family: 'GeistPixel', monospace; font-size: 24px; letter-spacing: 1px; }
18
- .meta { font-family: 'GeistPixel', monospace; font-size: 18px; }
19
- </style>
20
- </defs>
21
-
22
- <rect class="bg" x="0" y="0" width="1400" height="420" />
23
- <rect class="stroke" x="18" y="18" width="1364" height="384" />
24
-
25
- <line class="line" x1="18" y1="96" x2="1382" y2="96" />
26
- <line class="line" x1="18" y1="324" x2="1382" y2="324" />
27
-
28
- <text class="meta fg" x="42" y="68">STYLELINT PLUGIN · SPACING GOVERNANCE · TOKEN-FIRST</text>
29
-
30
- <text class="title fg" x="42" y="222">RHYTHMGUARD</text>
31
- <text class="subtitle fg" x="42" y="275">NO RANDOM 13PX. SCALE OR TOKEN. PERIOD.</text>
32
-
33
- <g>
34
- <rect class="stroke" x="1010" y="130" width="330" height="170" />
35
- <text class="meta fg" x="1034" y="168">RULES</text>
36
- <text class="meta fg" x="1034" y="202">1. use-scale</text>
37
- <text class="meta fg" x="1034" y="232">2. prefer-token</text>
38
- <text class="meta fg" x="1034" y="262">3. no-offscale-transform</text>
39
- </g>
40
-
41
- <text class="meta fg" x="42" y="370">REAL-WORLD TOOLING / COPYRIGHT (C) 2026 PETRI LAHDELMA</text>
42
- </svg>
@@ -1,322 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Rhythmguard 60s Campaign Frame</title>
7
- <style>
8
- @font-face {
9
- font-family: "GeistPixel";
10
- src: url("../node_modules/geist/dist/fonts/geist-pixel/GeistPixel-Line.woff2") format("woff2");
11
- font-weight: 400;
12
- font-style: normal;
13
- }
14
-
15
- :root {
16
- --bg: #000;
17
- --fg: #fff;
18
- }
19
-
20
- * {
21
- box-sizing: border-box;
22
- }
23
-
24
- html,
25
- body {
26
- width: 1920px;
27
- height: 1080px;
28
- margin: 0;
29
- padding: 0;
30
- overflow: hidden;
31
- background: var(--bg);
32
- color: var(--fg);
33
- font-family: "GeistPixel", monospace;
34
- }
35
-
36
- body {
37
- padding: 28px;
38
- }
39
-
40
- .frame {
41
- width: 100%;
42
- height: 100%;
43
- border: 4px solid var(--fg);
44
- display: grid;
45
- grid-template-rows: 118px 1fr 110px;
46
- }
47
-
48
- .header {
49
- border-bottom: 2px solid var(--fg);
50
- display: flex;
51
- align-items: center;
52
- justify-content: space-between;
53
- padding: 0 30px;
54
- font-size: 34px;
55
- letter-spacing: 0.5px;
56
- }
57
-
58
- .main {
59
- display: grid;
60
- grid-template-columns: minmax(0, 2.1fr) minmax(0, 1fr);
61
- gap: 28px;
62
- padding: 28px 30px;
63
- }
64
-
65
- .hero {
66
- border: 2px solid var(--fg);
67
- padding: 26px;
68
- display: grid;
69
- grid-template-rows: auto auto auto 1fr;
70
- gap: 18px;
71
- }
72
-
73
- .kicker {
74
- font-size: 30px;
75
- letter-spacing: 0.8px;
76
- margin: 0;
77
- }
78
-
79
- .title {
80
- font-size: 96px;
81
- letter-spacing: 1px;
82
- line-height: 1;
83
- margin: 0;
84
- }
85
-
86
- .subtitle {
87
- font-size: 42px;
88
- letter-spacing: 0.8px;
89
- margin: 0;
90
- }
91
-
92
- .terminal {
93
- border: 2px solid var(--fg);
94
- display: grid;
95
- grid-template-rows: 50px 1fr;
96
- min-height: 360px;
97
- }
98
-
99
- .terminal-bar {
100
- border-bottom: 2px solid var(--fg);
101
- display: flex;
102
- align-items: center;
103
- justify-content: space-between;
104
- padding: 0 16px;
105
- font-size: 24px;
106
- }
107
-
108
- .terminal-dots {
109
- display: flex;
110
- gap: 10px;
111
- }
112
-
113
- .terminal-dot {
114
- width: 12px;
115
- height: 12px;
116
- border: 2px solid var(--fg);
117
- }
118
-
119
- pre {
120
- margin: 0;
121
- padding: 16px;
122
- font-family: "GeistPixel", monospace;
123
- font-size: 30px;
124
- line-height: 1.45;
125
- white-space: pre-wrap;
126
- }
127
-
128
- .side {
129
- display: grid;
130
- grid-template-rows: 1fr 1fr;
131
- gap: 18px;
132
- }
133
-
134
- .card {
135
- border: 2px solid var(--fg);
136
- padding: 18px;
137
- display: grid;
138
- grid-template-rows: auto 1fr;
139
- gap: 12px;
140
- }
141
-
142
- .card h2 {
143
- margin: 0;
144
- font-size: 36px;
145
- letter-spacing: 0.8px;
146
- }
147
-
148
- .rules {
149
- margin: 0;
150
- padding-left: 24px;
151
- font-size: 31px;
152
- line-height: 1.5;
153
- }
154
-
155
- .meta {
156
- margin: 0;
157
- font-size: 30px;
158
- line-height: 1.5;
159
- }
160
-
161
- .footer {
162
- border-top: 2px solid var(--fg);
163
- display: flex;
164
- align-items: center;
165
- justify-content: space-between;
166
- padding: 0 30px;
167
- font-size: 30px;
168
- }
169
- </style>
170
- </head>
171
- <body>
172
- <div class="frame">
173
- <header class="header">
174
- <div id="step">STEP 1 / 6</div>
175
- <div>Rhythmguard</div>
176
- </header>
177
- <main class="main">
178
- <section class="hero">
179
- <p class="kicker" id="kicker">INSTALL + STRICT CONFIG</p>
180
- <h1 class="title" id="title">NO RANDOM 13PX.</h1>
181
- <p class="subtitle" id="subtitle">SCALE OR TOKEN. PERIOD.</p>
182
- <div class="terminal">
183
- <div class="terminal-bar">
184
- <div class="terminal-dots">
185
- <span class="terminal-dot"></span>
186
- <span class="terminal-dot"></span>
187
- <span class="terminal-dot"></span>
188
- </div>
189
- <span id="terminal-title">terminal // setup</span>
190
- </div>
191
- <pre id="code"></pre>
192
- </div>
193
- </section>
194
- <aside class="side">
195
- <section class="card">
196
- <h2>RULES</h2>
197
- <ul class="rules">
198
- <li>use-scale</li>
199
- <li>prefer-token</li>
200
- <li>no-offscale-transform</li>
201
- </ul>
202
- </section>
203
- <section class="card">
204
- <h2>WHY</h2>
205
- <p class="meta" id="why"></p>
206
- </section>
207
- </aside>
208
- </main>
209
- <footer class="footer">
210
- <div>stylelint-plugin-rhythmguard</div>
211
- </footer>
212
- </div>
213
-
214
- <script>
215
- const scenes = [
216
- {
217
- kicker: "INSTALL + STRICT CONFIG",
218
- title: "NO RANDOM 13PX.",
219
- subtitle: "SCALE OR TOKEN. PERIOD.",
220
- terminalTitle: "terminal // setup",
221
- code: [
222
- "$ npm i -D stylelint stylelint-plugin-rhythmguard",
223
- "$ cat .stylelintrc.json",
224
- "{",
225
- ' "extends": ["stylelint-plugin-rhythmguard/configs/strict"]',
226
- "}",
227
- '$ npx stylelint "src/**/*.css"',
228
- ],
229
- why: "Shared config replaces ad-hoc spacing rules across files.",
230
- },
231
- {
232
- kicker: "RULE 1 // USE-SCALE",
233
- title: "LOCK TO SCALE.",
234
- subtitle: "EVERY SPACING VALUE GETS CHECKED.",
235
- terminalTitle: "report // use-scale",
236
- code: [
237
- "Button.css:12",
238
- " Expected spacing from configured scale.",
239
- " ✕ margin-top: 13px",
240
- " ✓ margin-top: 12px",
241
- "",
242
- "Autofix maps to nearest safe scale step.",
243
- ],
244
- why: "Scale discipline keeps layouts predictable in large systems.",
245
- },
246
- {
247
- kicker: "RULE 2 // PREFER-TOKEN",
248
- title: "TOKENS FIRST.",
249
- subtitle: "RAW PIXELS BECOME DESIGN TOKENS.",
250
- terminalTitle: "report // prefer-token",
251
- code: [
252
- "Card.css:8",
253
- " Expected token, not raw literal.",
254
- " ✕ padding: 16px",
255
- " ✓ padding: var(--space-4)",
256
- "",
257
- "tokenMap applies safe automatic replacements.",
258
- ],
259
- why: "Token usage makes theme changes and audits low-risk.",
260
- },
261
- {
262
- kicker: "RULE 3 // TRANSFORM OFFSETS",
263
- title: "MOTION IN RHYTHM.",
264
- subtitle: "TRANSLATES STAY ON THE SAME SCALE.",
265
- terminalTitle: "report // no-offscale-transform",
266
- code: [
267
- "Toast.css:22",
268
- " Off-scale translate value detected.",
269
- " ✕ transform: translateY(7px)",
270
- " ✓ transform: translateY(8px)",
271
- "",
272
- "Motion offsets align with layout spacing values.",
273
- ],
274
- why: "Spacing + motion consistency improves visual quality.",
275
- },
276
- {
277
- kicker: "AUTOFIX WORKFLOW",
278
- title: "FIX FAST, SAFELY.",
279
- subtitle: "MIGRATE LEGACY CSS WITHOUT DRAMA.",
280
- terminalTitle: "autofix // migration",
281
- code: [
282
- "$ npx stylelint \"src/**/*.css\" --fix",
283
- "Applied fixes:",
284
- " - use-scale: 124",
285
- " - prefer-token: 98",
286
- " - no-offscale-transform: 19",
287
- "",
288
- "Review diff and ship.",
289
- ],
290
- why: "Autofix handles repetitive cleanup at production scale.",
291
- },
292
- {
293
- kicker: "READY TO SHIP",
294
- title: "RHYTHMGUARD",
295
- subtitle: "SPACING GOVERNANCE FOR REAL-WORLD TEAMS.",
296
- terminalTitle: "next // adopt",
297
- code: [
298
- "Extends available:",
299
- " - configs/recommended",
300
- " - configs/strict",
301
- " - configs/tailwind",
302
- "",
303
- "No random spacing values in production CSS.",
304
- ],
305
- why: "Consistent spacing rules reduce regressions release after release.",
306
- },
307
- ];
308
-
309
- const sceneQuery = Number(new URLSearchParams(window.location.search).get("scene") || "1");
310
- const index = Math.min(Math.max(sceneQuery, 1), scenes.length) - 1;
311
- const scene = scenes[index];
312
-
313
- document.getElementById("step").textContent = `STEP ${index + 1} / ${scenes.length}`;
314
- document.getElementById("kicker").textContent = scene.kicker;
315
- document.getElementById("title").textContent = scene.title;
316
- document.getElementById("subtitle").textContent = scene.subtitle;
317
- document.getElementById("terminal-title").textContent = scene.terminalTitle;
318
- document.getElementById("code").textContent = scene.code.join("\n");
319
- document.getElementById("why").textContent = scene.why;
320
- </script>
321
- </body>
322
- </html>
Binary file
@@ -1,45 +0,0 @@
1
- <svg width="1400" height="560" viewBox="0 0 1400 560" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc">
2
- <title id="title">Rhythmguard Rule Matrix</title>
3
- <desc id="desc">Rule coverage matrix visual in black and white with Geist Pixel font.</desc>
4
- <defs>
5
- <style>
6
- @font-face {
7
- font-family: 'GeistPixel';
8
- src: url("data:font/woff2;base64,d09GMgABAAAAAEcQABIAAAABdhgAAEalAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoEeG5xYHI5EBmAAii4IdAmcDBEICoTYcISEEgE2AiQDjwALh0IABCA/bWV0YSAFihIHmHEMgT1bu0ZxgW3T4hl2OzCh193uFmzcgbuleIki5C7gLnc7EEH130iGqqpeE+QYozHfA7G+zCCEUqjECrgWsSMuhdipEiuVIpMEc6VL3cLjUsQrlvs7wrPTNG98/fk9/vE91OxLWYEK3IEMdECt07bW0YoVtuFuld/+RAwMNa4ofvAMMk2NrXAGXl2zMPbF9M+cZ/RzzPbO9QkhBAOLAbtlLUrxeBlTQg/P2+bPue/tsouIpaESgw0baEeDDUtfOyFop1kIClmKDUtpiK2mNZOoMWiAiIUY0E4MoJ8007pfhX8ejr3nvr+wQozi4awTjFtsKQDw3wD/9ASv5Sx0pqT6+p74lzp1X6SExuysAsJN1OWX5BAtY0E6GUdIUvpfXfq/LNuHFJajkw+kILv3AwQ+enu7jOm2uB2m+P/p6vO+KqmkFlCVoCW1uqTG+QgLnA3tmtqs5flO1ynwRD6OAWjWxBFgTDQTGlHw9NrSYFMpMHqTyre6ABk2pKOEbdYEpaOidlFvV32tMX+q9VN5UvXhuf6d1UqQbULsJMhP7W5N9aVf2pDvSiilEpvSSwwSZJmQOypmJEpvezuDX1uvD+pWY+/kthKNzcmdSiYuyOjT2KBTh0ZHV6LRF9fPX2ODKxSg51+TdUTBlYL526NMzORyUCnyjUveBCJBIaBqov0/m2k7f1Y7Z8k4h4orVBDbCwCXKVM0q9nV7e2OVvZJBulkks6WD22vTAcmwR0H4fWIpYGgwjJAHXOZqk1lxC5d7dRNyrR1ih7/V2fVWpG/M7OAPuSFppEzR+VC0V1TJdL3/E1kOe+CN+ssIMf2guWZxeqAyrsSuKMOqKhqhtA2tHdta/4VCCdhnyyQiSmMXOZH06+kqt794xBnHBIyTARsho44EWjrl/TuS92lS3Oz8Y9DCHRKpZ5Rt/RnY7g7usyEGEADQkzIHlsAD/6r+X7SyK/kLR5Idv+Qp7x18pMN2AIewNK6fUfWTMsunhAG3guKv9fU9+EsXJoeQlzjmpxkmD3M8Tvff/7PmqHnPl5bbSOiRkRERY3eqKioOGrb9/X8uj/f97DN2oGqwKZBGqTmFNJQ99XnfT6V8/de/GsHeBAMBh8Gg8EgGASDIAiCYBAc/CHmrHbwavbuvmT2gimWREQDghUsIKIMiDRpg0pTE7MHeYTBHwCYy1ADsYhYwnbEDnZiyOIQ4givI97kG8R3fId4qDpI9dSR1KkujNZrPdJGbUTarM1I27QN6VMVY+mavkIqUxlCGMAPCMRg9Kk+AxXocxwIS1f1hYoQ4CuAEEz/fU8k4UmQeEYO1osXkWe0/777Gvtm3aVXxQhThUStdRROX0ONMV6sNIvkACAADG6+bECcEuJZ8XxaPg7xolgoFi3eDQwuDHd4jJPqiBL08Yj3AHD1Nljv7PRwEY5763hAUOH95pGGDiPjU4eTwdaJh44Y9qdjJsNTI0mkdT7sL1aorMQChEEKN9uQvMtZiIcmHPGrvQRpxhQinfUpRZTqAaLCCkDyrTOpb4GIM/yJOM8dpG4FIm1QdcRbXESc5AwiHxuQhhJXuYPkJAfJJRfSxOQPwFg9YIMVb72GDz4AAFB5svKk460smRm5FuqVhJpXbqIzhhnGSUX9Sk2YmJCKEbhTpHDBn4hRuzvAKnBn7v+m2u9UFzShaRh3kjtCWNd8R3W+Ls3YqkU43JPdA/c6T3MY6aGNBTLuiOd2kmbq0h/cM+aGYwdr9nPHuqduD4G1++ikAVgSKib4crSyhFcZ3oTTUAoP0S9HkKPypJzI7wj4gbsHhNUZARXQoy66tr236yGDrx4iwCAjOYgziz9LWEJ9XuV1GnCd2zxDKd/QxN+yaVM91SNcoXXUHYMfogoQQGNVCBWmTq7w7JAtrWITnV6AiffwJh8ySC6FjE6nEz0yJ1RfIaQQr/p2CPBFcb7t1RD2Cy8L9/EDb/7vhU2tbWpjU0hIoX2VeduXab1Ib3NN9/IqI8dz+qz+fg386Ap0tvR/0cJV/YZ9nrp8RfvMfdOru+qy5zWMqInoYYrZkqXL4ghHeZPrlPIdP/CL6qtpoQxV0CVrPYjaTOGOeMCQDmrIouI6FT+0caq+HampnRQq3wathpLKClgcJSpepeJNKk5TUUrFQyp+4VolKMvyW+qPm42TFc7HZ1Z6ZtfO8M6F+pgLdj4889Izqzjzh2f865n+fQn4mBtVO2fiURxPnXWdKRm+zhROLDwv1ojigaDpHVIc/R8Ujj1Cxsb98pSHztRIJyFnU1fKxNzHA4lOe41EZzwtFz3ppRk0vt/s8TAD2bR0JOWHGlyoTg1idWfLgB/obKJWoP+WaOeYJvKN2gNjOuLRbKum8wKLvooNt0Q4w7kkIh3RuMce/5pofHMWHatPPmAVh1Phpp+9jNwDhXMCAwdvYnscNe1N5DQomgUkdrLHL6ZAUXx2S+ocHdYeiJaZO0XYbRfBnMEcAXZnO5wkYsSWu5jHLTVBntlqZzbGOPxE0P3AgMkcW6eCR/ZZKCZFtS+abCfa8aolUpHTzrBTgDKUqBNcNmTydPoxlst+z15DapIObZdssqJWjvzsn0XHivp4lp1vTXQ4HU4zYf9ZH8gHunJCqkPO260QHpU0z97RaOzbYx+yXMGMy/zt6HGMfcI+Zedo8412a6KNXGik6NY28kmmY9E8uwi3kAkyZ2y7SWtidPmhFiiBtj/2O/uW/cC+p/UUf1cgMV19q+WyopBzhFR2y5gz9TWP7UdqN48tV9hR08HxnRN4mP/Q/FrZucYNzP6IHILNCYNNbQzl0AaT1Vq24hYJb2UgcLZJiYjM1QeLMsvQZpSiHCbCZBIm0kRkeCFPJiqzzJZW9RUGzy4/SaEGD8YcAsMzCyfhgOshqmiHo08b5h4BkiBAtGCUlW0yOKyPoAQrmBbccy/pJwg3n3ZsdB1AG8B9GwH7kYSd3qUPFZwa439P+BZWUWArgKeuyupWQKhBSgggWLdf9AHGGKyKV01sx8qf26p+d2ayOVZsfWoXCvrFEzHw5rqblEkgneDDusgteFUMnyzMYLTpq9KUNu6/s8lR489VdOVUkNLIlZsnPOSQcesID+USFDOboGylVJHZX4S7SQeXAYLuJcHINkzhVXarETS3EtHPDLeZa4yX3zEzRhCAc9602kMDTnJWS5REPoXc4B4V/MifPJadNJSfMqqtQDUrRJ3rUf88RTaxeLVjTpwE/R0X5wboaXySVmhL/KPvoqxpr8DRvn5VQEeSnriDXuGEt4ST5c/M/nAjdD75db9CwZn69iQugEIhVdeodYc6pdSrWFPJw9T0IEa/agcgQFY5FiDzFANI5QixHGhp7NQAnN10mWgUgpgpzk+byzY+BOOaTPNSdpdxqApjDBjxIBZZwlqaBsYrAM2gerAj6ldi9I5yr9Rho8vyu0+9P9vk2+Tb5Nt4bPbZpNnss8k/iXxA1OB+IqGqUFNwCD6CU3DRKiaT1jLzaW0zl9YxGbSuSaP1jJcGmBRaH8BXtruMpBnsaH+qQ2UlN/b3gDXjqwp+VOVPNapTg5rUQmYfDmROUh2ZDG4AH/oGbWkKX22RQgpkQhLa44T/Q8yPmpsjRcYkzmzM/DUM3XyBzCsYs85MzjdgmVWenyCe0GaSWH/yX/Qr2Aqra3q6jDmLgyUsVT0F6IsJnDnhZrawlW1sX/xcnAqtbe1qX4c6spA5gUwaFbxaFHZkTzwpSGeRKbVYVjNCLFz1xlzDbRWrWcNa1rGeDWxkE8Zcxrf6aqCGCtQzaqRnFVTjmkTwzsI0rVnNC65FLWtV69oUUr9f2s8smhDTcbpNr+k/Q2fURM3EiZ0ZqKykRv806uNPZHJOuM8J15k7XRME8dMZkAWyQQ6QE6PvaFUYO4nsx7v1ZdWulrGcFaxkvVcBXzBY3KEAdR0GC6GODWpEIxvcFwgpQiT0QT27qWQaB0UuCH21U3f0r9UYOF9kqVe9/4JMfyK9YGnVXD7HcIpcHl2fqV7RO0hZSNkI83mF6UFXJtN7FefTNtViCxFX7kSwmSDG7/yLHlEMkkUpGJ4FfJCMK8+JOehtgFvc01Xs13EzzbXQUisGqWcDgXBynRvc5Ba3VQ+jBmrGqKGaMwpUMKNn1IJRI7Vk9KxaMQqqNaPGtWHUpBCM6qk9o1EN+SyUbynsPd7KTCxUKGgnjGQ0i+wT7uEQFsKP7iK74l72sZ8DHIz4LVbu34osWZhQ7bTXQUeddNZFmK5WVx0k0vOivEAZY0Cx0n+be8QoLFA99WRrbfXpqjox5Go9FqUa23CWptbHDgyhdmIIzSP3NQwJ9q6z/k/dheE6oh0BAtxEPjZr27RoCw4w60w0GMY9sybrWG+JUx6CylEKurVSUUf9PJwn6N9YPz29C3ZE64KwHeBIUQZBrLUWrJLaWIintqPB7+smluDEn3aes6haalPXejW44SW0qM3aphnyQ1ax6+x57MvsW+zn3OA293jC1/yt/MP8K/wbTdu8vnlH89XmL82/dKNL3ehO+3pe36J7va8Pbd5qr/N2tx9pn24/256033asE13YJV3ZNd3pJsdd2GSo+sV3L9QffMM/h/+wYQCgcQG34V2U0Tk36V479CDdalrGD1hxwm+yH3FwwR1hCV+munnVxL/S/Ln5pwZd6Frrl7SbdSdkp93Sfrg9aj/Tkjl/2TdFAeuxHlxVJQqebq/8jhtx19PJNasGYWE+hif7n2x5svhJJuD+eQBx9Lu/wwXH3u/ZWV4B5UnlMVBerdy33FV2rex22ctlB8qyoGxj2YqyuZ9Rn91wz//Lv4qHwZW50onYBLymjhNg+k7kTJ6kmT3ZAOa8yQVAx7xsrplbYO7I+Q3Z4KWm3DwAHWS+MQ9JMFwW4fK4BBU1ShDLrfeZRhfd3Ka0Wa9pYfOa0cwmt12RxTa2qT1fVHu0S7s1vkyiKn9qE0BTzbQWqqtweuijr0FGGytStCnizJYsTboFJRXTrA5rWje++WmvSskpTnNu/mrFErzD3c+A+kP/+46/eSSHnKoiP9VUYqv1Ygc1pnFt1FZt0jat0WJd0xKFldYhxbVU97RC+zWyUd3UK1rUxL7SiLqWnqdhDW8CHwwOquDElx81aER9GhJIp6VmTdRjoGEGG2Kkoe1khBniTTNdhjH+Yh+71rG/vbSXgxzmBO/zFu/wLhfJ5zMu8AZf8YAyyvmG+8riayr5P094qqq+VzVc7MciG7cDVOMYNXmZWrxCdY5Th9eoy+s8y0me4T2CfEAD3ibYxzR3hpY+oYWzhPApbZwnzBU6u0QXl+koj7YKeU4R3blGTzfo7Ra93CTCbfopYYB79Pclw1Xg8T9G+Zbn/cgLfibKT4zzKxP9wQS/M95vxPiXqf5hVjaJiQSPScpiZvBihpdyMSd/5sqsFouqw8JqY7ObSf4k1n+6q+sqUam+1C3lKV8FuqJCXVKuPtVlfaaLuqoiFdNKDqn5SskHb26Nfci8qjO/GvKW2uxSeqnk1mqdJrVey/Se3tBbekcn9YHe15t6W+/qhHZon/ayWHVJuAO8VnPuEYLKGeI8PDiyl4sKakXMOSDFoGMV51Vm2r7xDBg5aDykiYl8uYbMzRecu5+J5bGoaXkt3UOCqfI/BjHoL3TuPA+8AKTjHhAoxwAaRF4HmFGvPmAZWZ5ZpTJ0RhRJco6VlShWdZtgdHgqpCSMRmUJvz7tGWOUI97qnqdi7jNl7NwTtUljX8Ti2sQUuE4r6yvISkfcZGnKlDqpjSou5eV1Yin8XMP9n33zZpomiwnOQfJYyvZ/pU2z+34WrnfHWnDzsi4uXX8xqRAqS5rswqRVPK/P66GfwWQt3Xe3RgktD3VBsiZCfVWMVhcsNDMXMUWKFsBtAs5IgD9FDngyevKsXOegrz6baxt6ZstioDZrD7I1SIU0WsA2MhG4KkvBpd2EKyMxGZ3nDQwDjuOlDuni6vaiKLKOu11HmEjiI4aTBXbb+0m6vMIR6jpvK7i/l/Ku6+5bUvMmBAcJ1I4iV6MmFXANcRr0wFyOYisUl1EFkLHAemuwD4a47UDcSN0rZWhxzaEn+YUJsmX35TE3tYTp4xmgSdzwgwglYweVO5Xn7FErQHCVZdLJIsuu98JY7wxCuCjoPj+Wit3jypqSLiiP+g8AEnpQhrVutZ2lU2Ad7CbvpLcNH8iaytgBgzIO5AwYipClz7k5y2IZjRwGtzzXdyjvI9dF8yDXHPqdLOQpSxcK+Xmk0yyYL4ep8sHYHpEe6ukQFfvtpS8HwTznXYTi4UumQoGOcgsmGuxG8nr2RcFUrFkB5MqDFSlYaveAOTIarmL3LRoQyrW9/iIHdTsiYk6V8cGNLM3IwRnE6blk3DnTClCUY5CA3R4Rw6utbG78A3ZwmCjIKBMyMpKWWGGUfFWrIeShCJ0Y7YFK8wZ2aymm+avd9C5QMRXK2qEqRlTDDI1gC41ijsawjcaxgyawiyZxDE3heG/daF9MECf8cphUhuDH1Ll/wCimVCy/s8+k+JY/L5hobkRZbXE/sHsRZBBjKXggYBoESBBQBwEKBPggoAECmiCgBQLaIApmG2kHL5ozZ2qhjHTER+4NY8js+C03b5gbMLeR2i8YkVliZsNaNnWRT15dd7bwLLo7XDPOwfCbWLTQrjaWD9KTXZs9S45KllywbORlO3qtmBvQyEH1DwrqZqmErlD5cUGl/be6WZexbPULsmqklZkl3yeAymZgzQzz7cC6UQikxWH5DVMZVJQMUz4gp84EP3XfRzrTImnuluDyMvbriOVSm8ybDVCJqs8SruDKwF9TMBpnkgarblZF2m4dZ7DVVYZFR3Bk1M0XwvWlfLCXzri4K5wp9u+OvsRltyRB0kl9v06zNEgzV89Ln7JFjYdTXio2leU1xKk4r+dYXPNAUdmdkK/TsukkCZpuX74ElXmXWTxuXV8DDmUXwlZF42rkw/0aYaVZxrWsjlVtxALbtGgSdLN98Gv7tZSy4yNBzJ2C1YAx6tklyS1T7F4RuE9DadX/e1UFXZpocOU8Rw3qfTrHKD2acOi7mNPl6K+7Vy8PuU7Ph524nc9xtz9otMFsKunPWqW0624tSWvDOo8lHfilevl9d914p5ik9Z8wNWwOSq+837A16IS04+1udutGJhwaMs/owAeVser2WSgtpGR0Ahusw6q0MtTNqsyHTU1wFY9rfHRvF7Mhzaxja9ojW9103tjp5q3J6Kg3bA5spB0PpFs3r15X21RnwIm7vAJ4e5juucWVZqvts3Ja8aypgKVitOZD5w0bFbroC5UD5TYy7XJs571sBnceF7XpqukBDstL4nXIDdGBjAXENylsIiA5kKngP23OJPlPZhKyE5lLyO8SFhKKE1lKrnL1BqNycFQHshZQ36SIjYDmQLaCu91EA9E5eboT2Uvo7xIOEoYTOUp+Y1Nl9eY9wb54zjXVe8164OT0vedzH8gsmlw2rB7ZZbgu203Z1xZeMXcrxr7h0HB85MQ8leO5HC/leF3AreHe8HjkBp/l9lVu3+X2s4Bvw69B/vxP0fTJY+7/jjP2nzPrIKl3nlkcEBti1XdPN+7/Q+EUI9CQEADoVwDAvwGobfBQCLz4W/AP2M8CszVY0yX+g442kVUqU9LshxtI6O053aMlTvl8Tix9Ff+cDHe4VCaw4uxPLSmzrNVuVlUpUjwkAnW6G/KzLfXBTRJng9uQexq79Otf1loU1pZzjw/tkwpSxdi5vWCNT4oOmj+Q4lSlWyqs/4s52oIWpenDLeKz1w+WOCUJ9w3qwUF0erDnksa+ZkIEmDOnQUuJ00jkGKNCCU1C0zreFeGl6z8/wwIAh5VcEiFCml8iEKL7l0gJA8AelxnJWVTOThMQmkvBAJbBjG+3ZE6Ni9YWFjx9JnIkkJC4jy3zAS5ahQw1PDBI2DAQweenyukgqjbI0TlDDqDyBOe5U410a1UUZWigsih5EIxu4A7hOMIQC6KXAfvfhtz07649fLePgAFgH4rcJ1Fpe4emj5ETfQkouaUG1QPmUCRUrGgbYprZ+QIb0sn5nAN14sECFbaiyharZomz9XAyNq5CTZ+jbhj1ZmW9eQZEb2e0HK9WjSYLM0rPs5aU6Yz3++B2SLs7i4tcmvJHGsoRoihayjZyRp/Hrnnr9INAv+TljP0+4amGPmdVQO4Mhq3rBNs/3FvGbLYf26Vf19bXybWHETN+CvAP+GEdPdgLJiwlhp+h6bvQRKtxsPawJSszsin01O2Npny6z7Jtz8qvoXvrIBbXGyxfZSSq4B0felZKEWl9XUZgPKWfrKam515ORhE68zWz/dYISTeZdXoUTFJ8BtIMaQnvCdpkIuUF5RTaguIQ1RRLxzvpgj6FFovYTjQOpMFBboRSD3O7tEa27h6lJ3iKniw6qYOiorJyP2Iy4jRWlVPWC2b4PEUjpgnAT/wZGzA5WRUquQHdOL58FPdz4fIF35C+U5hey0I+Td19mXK60WB8C9VG5ptBzih881OQmDAdbYaNNaSrQXCjD9jDpE4YUivimkByG1DeZPO2yYDYD1w1qJolB1JSKLrp8yFp4n5Rnkva1bNLm9dkanukRaAbs0ENM0l0DQvJPZyqYr5fMUt8/30bE2IN/KkVq3tQXlQX3WCas4auvXBCFe0BgWddGLsUJ/BIVoSnyapijSBxZuP8ztHeuf9yoG/nl74vTy3O9sooWRRqY0Enbm7YyXXpYKMClpaEWjH7eGoSQNxawprcjTzdTSERVnoIkxVGmouU6dAT7se86bWsn0fCcV9Q4v765F9jLW0AGkL/Wa0K6LrU9W/2zcnCD1jZGaxlTjiBgORyRtuXqWbQVN7ZD3b/FbV5LqkuFMvOSVYry1ALq+RO+RGT1HSQ0EdoLy9OraXgW6eo4k6A3IBl2QChju3bdMuqkkRPeAtznjB107bDdzjJdzObVEeK9pPd48mmYK93iNol3sODsdr+6Nx414vVT9ohEGXC1XgyrA2qfSMyb2sxOeCLb9nAWJZBeE018g7KuDYeot136L+3iA6kYs4lCkWqF6D95wC23PdpyFHTGCzU3nYKYTO+sJ/htsIaBcyzVKZNA9jYVNSU3Q7lzSWevaRvBu9T28gFxFHEydz7wo+ETvez0lI+alZeYMcm97op7eP4w5oK4X8vC3UQilsMFPs6uMorKn7FKJ6V46NmSGLpWuMEx8nLWz12NBEBxo4fnLDlefOuoD07u25nAqNoz2lv5keW2E6/W74VUwXAGXz7iv21I3Z9M2yO9MU1StvxhQMhyaoWB1A92ZVv2BxRS71FjsVPaPi34CZpEI8mBUw4mowelFwNNDCC+lzlbbhb2U8hogtzo8QItY4OLQ06P9nfkfkVZ19bX5WLduA+Bb5KiRDX+kFBl60SrYg2HNFHPkzpunGqe8BWaT50EPbzKZjvCXqxpqyzAE2BZ5XzxzJujW0Kz6uILu3T0ErjyO+yE8S2ztbnc8TdqlgkNkplW0wfWKTVun0pQOh567d79mztMosg6pB4S4q6OyaZtlDX3bMa8J7TvGvc0Xn9K+DsDOt91V2WYF7lPHNbyJYngzlnOlPb0SMy8QCcNISjNfP65ofcapv/mWE8FPRds/sn7g9oTHwmbEyja8ghAby1I+oJ/gL9883A2x+ZcVR84JE592vNp8yHySYqp343+nhIGXAub+h2f81niBcRzHd3TE159PyeY6eD4grR+fJ1DFBDHZjqpCrdGiGpJvXKRM6SRezmvsrLLJGKu8l0tMW/0x9npCfySeRrEmjIetYhAd3Unw2UpHuNjqajz7M+8B23p7XK0WjhqzCuYwHDPIMbx7XzVNsS2F871k7oRU+CKwjPiD2xSSiJjalVMv+jXxwzVvd3/CpzM5803b5A8XJrplhkuBEU+AULcV2URQxGFWzSWRWPZZ5I+j9Z568p9Smf3patcnp3PE48Nc+944Fe31GVe17rsR257PYZFCGjAN1xsYllePW9XvoT90ccDNE3GkraM5hGucUbb6RwwxtPzXMWiuApKG0n1MANYwR70GDkwlM2etxQitS/edHrT/fqUeNOeEwrm5li6tH6wI/DIiRRpZcPrqFSHhGfi0czn8GPfNlgqXrKIbuo4FBSAvv+0K0iPdu9sHkd+6zPGYzzFM70Jova533n3dTN9MQz2Olu12qDPZc9Mvc7VyYl6uqW2Su/lFegwyqJRpyh7Ueb6HD4l0owot+90qjl38ledG6ZBVbqy56PrJZ3FI/f9PMcvwsP3CwgrUmhXND6xj1bFiEJf1O/+ImJnxLGHJ5O+yveT16GFb2FAYFxuDWoqkg0gwIAOtVlHvuyKyb5yNKhY/QAY0FQKkPuS/CJbsYcTFx4wbodd2BkGPn07VOKWAwd1wevGXjJ/0JqFPPa3+ValHmxI0bTBb0Mz8+JhJmYIqKgMhF3FI7SZDifUjqIx11DSHV3f78eJHrQ8qzmRuqfF5VD6Rn6EFWR2aw8yqKGkNK60ebYJ+u4duTSO/Lf/HGx2Mdjz6gSz0ZgwE9YDjK1MTTH2fXXvG9vKBKGkm78dM9d5ZFTb9oI1z7v+9ar2ddZ4ACoZfqm7wb/EXG2oeceNY/lFXN9rHlU6z6W/BRV1ipFpzJnPXUYtbLAmCBkk+G/+iWoBY6wteUUvZ2FWmnxWkhma0O2PJK/ggEH2rYu+VMNomWS3pg+nECbL9M+ZVwagcGsYGoT1rVeE7oEXrHFTgBfxFYnpQidouoshS3hFEkX/YhfHmHgVwhZNbXQITVnHl4jZ+/miuArxQIr5FawKU6RdnTLEUstT7Lw38lAD0a8aW46VNKNudZAc0OB/hIhLPu9MQ2UWcdsM2hymdhoEh4sKnG6s91oaWwI+IqhyH7O+99JWaCCKH51VBH5ia2zU9RvWbebUn8syOVmz1MvHRrqu1Ncgb4upBbUlBsbvS4wD3mAM0pR7IZ5KzrMhimwOz2zrGZx8rPIQbEbjWqw2vdmiqFMWdWEQAwuOyX/Ls9UkPFGbEMhalbLzc4IE9UkT4Y0y45G16Vr+8VO9hA/q+GMm0fBWo5ur+BYgPPr8G3o0zNMAMNBuUJ2GKDLxM6spIPNTVGUByTsEXEkR53rVIwncmuUZtieq/+agdZ2dwaLgs9Ucm/DvoFMtYleY8MqT0a6pd7f+BYOsEAzfWsvq+Jz90xtYy9cBWNBvZuSfmdQMoD6EQ1tCjNUNfFENsY6KklUHVKz1uDMYiMVtk1vBaLy1z8LS5s3cORjxblrEug20GzdJ0erJh5tM4VKXbkawBkKcQ2JrRGcdW4qlYYR2w6kWAqiaKIboUxJDPGGXkKiQErfzrfdka1G++kAzKU2TCc3aFPdOKbN7rdkb7ZFzVF+B8NT68xbFSnwKXSxXQEUbkdDUK9TCOt9NpOh3AlzzMKegMc1dk18ZrMJrLI9mg1DlEQjTS9VC8ve8t7Wju/y+04AOh7/SqrHkBje0rRjw5OsXgiOVk7aMXCK0bLdTS2zmHRIK2BuRYMZxGJjc+atFk1xrGwYlPKqOm/19ExrwdnYjK6wW4cOf6rQg3PHfTBmKzNcACROddLjTMCAQCGWpGBe5ElRij9mLivx8kkDsuElvOXaNJlNVy28X6w9/6VbYIbTf1a8d+X21znDhxNA32hUFsAQ8fYMH0mGhwkfFQDv1oJvQJI8iU/OcFkOJJnDEDd1TEbs4GFjZSNvjMZuoC6N5W0mOsWddciHE3uESh578JA602WHAzuxW4jYahcpdI0iahXBLrZcsusEE4e1f87i0PvGYTvVIP8vI/dxdqsxYf8wXILRJsRfEBKrfYHJH4bZ1AlqGOTrdKY4IgM+sA92szBt583jNgN+HmwxPNM7D60APPm5sBePFQqqCyqhljDBt6n+mrSLS/tyCRcCbi1Q/QjheF/argVzV8+Kc0B+/pWdPZu69nM1jMVFw/74kshqDeYhJiWIW42sQJvLX+jkdslpZSMGo1/wM3EiABHolFSLRdqvdwdISTPQpPEcRCKFGmVSlZPWpE6WaIeLdVgbeKnMAgUdW6oqsPv5jz6bPXLMnYW73UWxIiYI+0k54UxnC5FEy0yzzyo0TDY2tbzmaTKyiFoCYiCERJ1ay6QwYHKHVEEbqNQdlOvkeNvwYu77O0S89Sy8C4i9nmCJNF0T0V+KZdqSkTWy9vtEQjR4u7HtAKEqcBorcekG18cDwIaXlZkimBiLktBW6edxg4T7wjVTuHAtQ+VgWPQdt0110phhNQUMGla9ncC15L3lhm8oZX9ISl9zkBwpzHpg94Leem3bFos/7AmffwIGokeYdn+xCtvQi+Zqu4xnN/L7pQp7jQmOvQ5UEyZXjYOdHqyrZgogqvdiWw+8OzBfE7+NV6fCWYhX9cCGYGeenIOzIxC7mD9NwMJgxsvxVF4K+m4k/Q3Y5o0SpAosMI9NrBOovTWEAG1bRGDlCCs4giqBcIvw+wQcODrz6xUNzzkQ8TYOqTJchs5Zz1SORH6YUyUzgi9WHIDQCmjEnkn0T4QYO2jJyAuE4AEBwP0F9bmr6bPxszfi4nbwFKsFF4+ceO5wIWgdr4XYp9R5G06B+6GyDgoYO0x5UpYA6Bmu5WD0gQM+A+8YGCd1Rq3Drn5SYpe5gFZ8j/G4ar+UZebIduCbT6rNo4XgnM1y09svDqnGlBI8llQlglHxfKI926sJV7688Q+pmhPoF0l//wVAm+YYFCPP21DJXol1ohm+UTYxASMq8StJdh9rv2YvHIWVupg1+2KIPawkhyHddztgvq1fQWtJBEmuPBlR2/qBIc1P4PhVrTwFti2BHSJ2KzpMg37lLG8vLpn7WU2qYUPyu1RZTqFwly3RfKw0yElWBx9I+wmSJof5Lq0IMDjRplHZmTsSBJm2EuKiZOxLQCjJYdj+YRO5WksI57kr3Ho/C05o8l2u7qTUSxO4126noy7cVDZDr6wv8L2Z1IGMtC+/mwPP749NbGpoUK9pOlybUIsPFpgJErFc571VhyeY99wdYwYMBgMbNMJIkVmhinEMj82ia+ed3qvEbmGNmHhDLxIQHsAhg3VFDa3gnDcivkzKYgRA06UTt4xPk9qnV1xJRljUsQJsgixS0EvSnnvownowupv3B7E7W/AqQooU/Jqcqc2D7oUn1JCN+rG10qhpxeBKXPCwN2xzNAx2RW85gsDZszDdEA+qjcUWyE4BoCvsZMjiCZLEllXFU8UknkpYW89QH2QFGVtkIk0mcdLwxinIAD+OtFu+WOI8pkpVE67IEID490mp3yErdhhG85ORaTNgM6205LEcEHBniWgsD7ZRG+awyvNx6hhtkq6ms3eKvlsyhCoQwcBkjm1nAOQwYAcyG3te7M1j91m29ogmXpqDUw8UCWEzldHAGEZQw2nl5sa/cxnHFrMfzriVAKOIslU8+yLBzF3XlNhUfqFP3pT2g7nKM+7JQYek7iCQU8dX//NLf6ZqNi0YiAcan+caj/6HLuqOyZ5dimExU/26dpj3PA/TeDOHQqfbkHJAW3hyc12ewpQqIAQY1lA6kEB6gk0tJrQEvikgKsc2qftCpGh7f8RxJsZwi+vyFaEw9N8sHG8sG2flaHhR70j2QYAHx6B98CYSXn/Fg0nq0BVtdbDRRWQaWPI9U8kz4BmKgqSJcXOIm42M3rpq0wEnC6VJ1QOIPjWppIqcUNKWGrOViPQKKHdYQeKcRc7weLBVvCnTKFdB36kEK9/RGeNQHOHErLKe7WqOPPHXJjRE7UxhcEqrs0grpCggMXl2puKCSqu7g7YTZ+gH5xLCVf/UCFjkvoEgOtq7ZxZhfKu47wkNV1QlGbS5rWU978efUV/GSwFGf53KS58QQUQfqhiRUKAz4leVPCV1tgfGr8ERQggYqgmZIRafFZIgdzwzkPCiZcVQysLQQHma4R7ZudnG5t/UYjtiG3a8rX4XdxObWXMm4+aEcQf3MZ12x2gB17Iq62x3HGh0SDbDiOC7V8/MjhMWPfKoTCAbztmFgLenuezEioVH0v9xTkdD2Q/Ym74Rq/7F+ZFUpVWAYLL6HoZDZPgvRpiZVkwoGbOEhDZKmNDQ1mLSicMHGDTWcM3gzE5kfmOsQ/OGbYqcaJWa7oMQV+neaq4/mPIcrHjukGZ9iHPl01apcQ3l7nqiWfSceJtfpLSw+nT/ZERBzcMn+LQtUw4LB52CYZwxVwwsLXcm2zeEhQUNswv72piOagJzDgXfaQY1hNsBiLf/h67TRVESV4Bcts2uRloCiyw2369xWdMa1iumPwwpvMwXwobRKvDyChvURaqxHaLyaCIurfWL/+gWpGXj5caqq6QVGrWEREQ7yn9Xl7DeEph+vnZHxOWuioSW9/wCHdyw/yr9UxmjDGw8NAthCQOSP58MfzMSGsi5HtyalD/tyZlxYHZLmufIMUDCtWm7Jx/dDrpUvYjneBwjZ92fRgD1X0So7nSPtMxf3HeTBvg5vdEuAWxleR5TgW/fjOxO1zGC5r02YLGyOuR/4mvtYuKe5FrM8UixNDUET/yO21zTbp1ppEupq8ZSY+FNfy1EfOMFNIlYPh+wXby4PYuCGfZp4hK5H7JQ5E8eAXzvkvjeE6Eq9SMRX9VG+kSjpDUlvW0E/KQ6V3K5hw4qwB8tzetkcHQKIeMh6cMB4JoGXTgIh/xWeG5wyUrukrovCq4MOHELEvp4lLuk0QcyXsYzIsBplU6J9gzpr3Z+XbgSt5XsZ5E85GBf7O5Rizf8ahPO4oxYAVFSc3WHRWSwQVIVmR8VnxvLUsW6kiSjdKyS0q0OdHIhHMZBLjmRCvB7DcQvbhiHWqNKXWbHtayeN8GggFg4oq32mjnsdVWKdmCIqdd0tjaxo3Haxx5XasVkh+GMfEZhLE6BCuQP5WQWUnAKL/at0HxBAodVSZO0pb9YwL0k6qm6jpqEXWcmE2R3zXZHqxwTtyGcnHVdlo5RZMsfm7Q8etFwguFCnEirUb1Hen7JN4jPJJ9e5gxEMqsVhIH94h3dsgmTJk1bxcTtkKYQ8DmhzUpemGuhrKX4nZysgxmnnmQHsgNaJbVaj0I9K+M/iyah/N62tH98kGA52KsMzN22BpadbxQp8nJcMAegGljnVLPumYUZo1BDqBvigNEwK8h7xCKUo6TnKs2EAOZDP6qBW9DuNeVNvlegYyTML1BBFNlygrArH13558aU0ZHUti/fAkZSSR8jo4BscUpMpCyZ8apwQLgkhIXji9Q6NSR0E0jbWDaFtxiO3AhDwNoToD4xbMseH6uJEcfvgoMZdNIgNhuJniFTblReHcn+Wne4UBtP1/62hrlkQojNRCx1SFd2wA9hnMbMmN0ILTnwBzJrMWYB96zRSAcHeqWy8L151fgQKMxidHaaRQRs/x21dMk5m2LVYReL6rIe4+s6RSmHpHYamMqZPjPXNr+t+1877K9VF8BXH0XopZD0gWeWnUAtmCkGfXWyiCdZwtw2RxNDSpyHmWUR4bTi2eOYnWXaNb0DhcoG+Gu0RnEw8p0Zpin/MztM23B6ZqVEvz6rYofHXUyBzS3Bv05dFdOwm6aMgqXBH8IxnHo9GI+Kd1i2HGhO0gzcYyV/R3g2yuU/HHbBj5SkkKo8ujf7Bbyihx+wp9v1a+300ls5/viYJ6ZuSrqhn4uiXvwAPRUhuEU7I0CIj0wUwAr5FHXa6scxulJVbsQq2VYXEyGxTxcVuqH8vPPj9/o60HDUDU64SAp0PWN1lIl7XGC5oPaW+uXpBj+cGLW5rBanjAptkFAuZWL9ZksVzWTyZNf9eQHEVIn09uY8XPvXT+urAKpNZe8DTmcah/CcLKxKJUkTwNfHu90hi4BbrO5Hrpy4g+umhUBaKgbHiIc2teceAmVOKTI7B5YxL4BEeGhu/ExxkidQv+viJWuiln+Pc+mCDdu9AjgeVT++dRDxNMsR6Ru/dJFBNM42bQ9wavprMizY1KHEvwjNQ0XMuw1SVBQbZs4BIVso/uzD4cNsFH1ISrRSVv1QDbkzyyWUljXLPgo6EcrUERAM5Mvuq9IOy+MQtjWKjZsUXmqxMM7sw23BAuHCfSJIuCiP22vyei71Fy+XdNBbOHuT8sagROUb5e0tQT55hEx10MiCbJ4XgNZFwCuTeJcKvYR30FHOh5e4EsWwfzPot+E/JRfX/f0egG4yOfrJ3uiFhkjm8sb2+Fyol0oCu79CxDm/iCTgHHrLlxObq6DjjTg7Nm5uDEL8FOAY0feXzuweaSkSFZURWenvh8iwM2I2JOc/rxf9VYI1abvWcYScY+fT9S4LfxnlUqm7SBeSG7NoeY6iJtLQl7ioFPYc4FbExIlV9Lka9mFxvRefpsBeEKWU9rUKYNTmLTH4qTw409jV0ecNd7nnWCA6Hz6lDLp1QpEiVGE1fFP16Ya+YVHtpjnTxEOkgLeUjFeBRIldcDb6+oKm1OBSUhdrwcuahZszV8spDIzAdKmAnkD+nOaj3ia1RCCAqOMZOpmoC/X2V+gf4Dn9GjRp1fbrBDohqQJF5HhL+GmW/RU4jFrQDVZWbImLyvmXPqytU2YeifkN/pwDqMLdx84wSNtePP96Um9hnj6aUUE74EYxcZOtYQqfcPdKf86TqSLc5njVIRnbIo+4M9dt78lBoo00kttxEPxMdQt3JGHLXfv/9hzbUjFN8a9epEfhjTcpaHmcsPzHSOHhMpVOpyVNPlBx3tb/yQIfG5zZmlDViHTsk7j7Anjkzd8ombbOREquPjYbgxHsyaNIyZ8kh8OO3MIOh9BNaJ5bj8Jf6ZkM9tQK+hHcS27XiV3zXUcPLIn7S3YVz5zOdaTsNqV79cmig8q0m6zyFw4WaD1i7LDi8xwcje0LCNr1CXacbHGLTFrWGaXf0PP4rruKSx2e56mVOEz9XTe6krir+UY86S3cZXfVx1iMudcpMrRQo3bJNWJRu6q/5TLBCOSjfCrI8VzOmpfIXvMiXqFgOy2UG2oEb85Ve93OC4uFdX6hWJmw5mVehyuRv92d8nXuv0i2wzNF5ACCNGXFfYu1d0mc1IvaAbvbAVWDAVMEkG7lZhEHAyCAR9kBbJod3OQ4VAfh8MxVKoD2I5jCkN06w4TuWQxmv6DyJNZaUFnSx7uASIW9PMR41hGniktYgium69mKRxxT0JoOJ7ha6GFK/PQFRRGcDtl9LyHYd7a+MFdQGJRBTlyghaeFnGKUHsxbnk82y6+e8wrT6+3IywpG2pFb29GhYDSPXrOIbKtAo0R7SkZwij2F7bhW7LjhBeNmjztSMG7quGCciRt+sb2Jf5ni9AHd5DuV6fgF8sXNFqp98aIOeSa91WIO+wV4wt1cL4URRQ/gSmHB0ci5/yLZlJhzsSmyl3XtLUOkQ7DK8RL8Agh3cYOH5OiSRO+aeSAUOjxTTDZgZY69eQz25hcnuFnYbHjBH2SVmepg4hznDcewLDwAQf4cIWxwouCVbgG9sfNhPCjmQSG9qOTInx9jEX6FHcVxKEaLgkc+UOTljgJPGHL1q7z8gn6230z23iSuFuwMVq63UtE3JZgr5nmFLXW2pQIt8Sv26Tbj0w0SPfA5xfgzKXToeNG5eGUKy2s5tyUp5s8vAHdqB1fIz3ggDwKFsff6CAop9VALrqr96fnF6KrzarK9fLSsBOviJbhauP4pasF4PuOryYR5Vz323Qs1dwdJS/SpRPArdun5i6Unr1lKqpg3yPe8KG3BK6RT2z/szX9gF5WkKvYvVvEvl0gsFkEBVuQro79/zm6nAq+DcRO8RCuDj/ij/iUvaM1sjw4hPprqkfeIOC5OCW/ZrHToSAvkfJPaA7+AnPD1gIpipg55kV8WMe2jZBqkenm0kVXzihapJi3x3Hd2at746MruVv1Mq/59L1R9lHnv4iLVJ0AhggIE6RAWqymCziwlNTRVU68pAQpTW1hNT/pqNZ3+fdTxaJyIQaKGh0vL7QRzqo1nyVN7BkdYOOCjUEXxg6NKgI+AoXqw5gSHBBX6iHf0WILlK6eLgr/iLIgkysGkMh3ndrB8ptepgJP66JNDtGjJYzmVYM00CTxjeQYVfA7M4Sv1yu7PbaGDUDmDnNz0PKzcV3Co/F9rtss4hfSyfI/VE8LJt4k7RAVjVcwv8cv8Ci/kRbzY+fwvkd6//b244NLT242e+GT+8viPn796+qRy89Gnvfwnb/V85P9f2X/flp375f9vgMfHheXBgAHor96VBMNkPLuNv1zM8b3qZx5q9jD7egQO4RAOnUMC26k8PB9gO1opKWG/F/nYPdTstqxsE++9aSZg0QQ53eEn4uT3AgCO0cWbFCIZuQIYanyNfd0r7mSzwywzFF12ooBitxEomtskNZfF8Ariqyq4FoXM0x2z20JBnWVgLu9VhFfgUHKjQ/4Aw3uJJQ/p9wTvzSIqziFq/FqakJnsOcj2e7181P+wmF6WM/S8znr8cyYDg9HVibmdqEilFMFGUmJyqA155gShYU40M0LIKRAn0mzLrVGixklKHS+qPCdNpFwdqHnyRrfmtqJ+Dnsvw1ubrkAdmvdkxs8xS4mwuVu301D5N8B2rPfw5FAj2LcJjZXqt+0Tb9PL+EXj9kvZ7GQQEDkKGhKoYk50yD4mSk48bHrY78k6oTTWvwO0ln8qU/M5TRMjri4Tb7mEItd9yMjZxPDUBf5ygL3MwR10QdDtELr0MiXVXPRP2o6v0UvQ8SbIG51E3zyeOPc/OLwRb5I0j57Tp98Pvblj45+SUtwL85jqsodZUus9w/uEocabhm9xH09R9ZiiEnhrC9htlJHchmMFHm4f3lxyYfhd4b5jSOw0nK+d9bTmR187unragVFLuBxmngYGtmstnPBaIiTTeSA9maXEmZopgJVbFfJN2/OCG1jYz7mgLFIrS3ZJEQjXKukaIC9eKLU5/zqwq8lklRI1BMiFcw5GFsUrtZyDfx2YseFazg0UJcKLbgchrlEiUDpV52519Xsi3gFLiRuMH8DIyBSGCVquKHKybGGtaBc0cuzRil5JfuD5KwYVhVEQrhjVFCdR/L+bTEgm8jFFROgBLHfH5LpOD8fZcvfmzYJEXReFUlHkebZtGMB8VW/hNxepZecFTutpMymqoirHKld5lkYykknshV4Y+LZru87IsAxLmODgcWPnbrvxo7DfGAhwl21X9hE5y/nLm3iNNwW9otOS6znuwOto82be3Fm8oRJZrqiWlGYqXTFbUV5k+Yw5erGmcVmMD2pKZ7S1i7Ks+q2qalXtXfn/+9zlukltlyvXs907VjvkXdjbhpb6vmrdinI4pfKowtQvto6eGm2beBQxKtADy7SyIKO1NDftYFe7s0NFj5y5P+NucKkYUbCMFzxMnkuuKFmnKy6zRB4UlJ0ab/G8zPKDpr3ha7s1efuemZzmgq7f7RvR3+XG7Xl/62+23H92lDO6nTJJn1pNRUd262o+8i4rHpA3CzvuR55/kFC0kHMeqyg+yEit8iVPi76N79Js13aw63f+xgY59XNAQcRAB2Dj730qqxxu1sSt06dh0xuRlmHSku4zlOX9THm+yvcGtj4MRp9LpV88/oAOjwfuOQQmVyVRJCUZyUlhGddNpujTiKK4LymOr8d7fal5rvVq7Ae8DpaKOz23st6wC1bFcZJmp67q8R+sJJH9hKS8Ls0N6zn6MCXPHFsFKUkl1GyjpzfxpCeSqYLUzdj/LCiV9hrT9Hq6B2pXPvS2H5FuIJTbYk0ShmH2Npnmytx7b/x2rCMbLSKBGHYXsUSRRJBKFzj6ZHbheX6vyPdP+3ujq5lR6KlsPzv4F8g5ugp7j461biQleFyKfncjkHoSkqiv6zobczjH7WNy6+1zV13WIOl6z339ruoFOnM72S0ic1gka9iDNZVoPuGyemzKG06EnpGn1G6pOI4kHJhbsZ4HOxICGAKeEedsA8Z4bxJnfJ+VsV/dnsU3xajV7OsIaL0lWQGDmDIl54LxA8fFRO5mo9S0PGHp8sxxWETiONroPMlsF/t3uljObcUX/vcuFRbFPYh428qoO2l6K/X9x7xQnj/xs3odT1PVZ6TUVmpq7vE9s1ZeHS8AyB7X6Prb4BhHPgMy2fPkbJBCHCdp/HsjmJgrT+MckGkkTdVmC/hNqnS/sskwolv1sr35FUsqtqo1Hxfjxya8XjmyC6qCDS5cGHjPQixcFDFKYFpfwVPke/5jgYRnk7V1p7qJMQ/udpBj/1ZfQ8W4vZE8zzaEZLb//bsDCw8gBi8Sm8KYlKTy1CuMTEgjTpMOHGQh9nisCHK3b9LyNWmmkRh4zwaweDJIQiRRJCUZyqXu9o9FA407wJocCC7QCGJ7RjwSp69liY05nLB6lyzPfqfJtI69yH2wiiapPZORkoZMifa0s006MiNzzwLT8C7JYNUtxyZJDbX+6KZdodVoN/4WcVdBjAj9JdbrOVbYbkKcswOcsW/FcL8w3AoDwq57tPOAWeGPfYQRcp5xMkARhvF6DrNrv3JLcxQ8Y6IKZkWJlMmmktzhel2ecrl+zl6Opd2wwm5FVJ1vSk7tJx7NJRXjcbGpJGf0NuMOti8ZinAb/neU6716DIeyqsrNypDMhiWITQSjpizXRnsm2SKmaWzibQ/PMPd/UZbFxoVmLmegDT5wuUOQgEKqPsgKrSA0GtmbSnKH62M34qMa1z2qKIePR/C5p5/VbmsZ6RK/Gwanj7hde86r2v6AJUAUCUtPzHhCNgk1ktxyhJWOSs/8tByCMAw2CDreO+m39b5jrnI1dCJCyIOBTtAWzEhGsRWZprPbcRKp16Nfw8qX/PdakR2VhZpNHKptoCnE8bgqQDzRl2VPxy/egH5Tf2s62N0Bw27RAjGIq9ZMOtKTUTxWNH+g5/veJokvmdqfHrRBjJIMH4dzZKeuiq2L2XooqSrarRRQCBDYS14fPCXs8TdXNes7gK8PNQk0TSz+6zfXVZZUBtot+VHAiQFA8L9iyR0RWp9ORt/FfPcFonL76ASZIJ6bGYsc/5J0GYCFEJfYVMDRTVyBH+Lr/EFm+4K//xeBrL0SdmHq5tLfhh5TCbCwQXiQzYe6yIwlowPmQ6Gyl0edIWB+jAHDKHpdbh9Wmr+Xoths51NsvKHpWOIK5+qCA4ULZhgDxochlCWoHle/SO/Ck/mjYxCRJn7M5zBiKqxAZdcjjnO2nr9bB9vVattoWuYVowesDO1LV92VDcDx83nzl4gCFRfZV4Pco3THJG70Vd643wBdWHOCWw2OTnhBI3+1WEhWF6Uy+xkqGG9A7xQXFrQXdc9qsKZtrwPrnwtA2ycvrxsLca8cwQjLTN11bYEbGNl5V1kJ6S0fuf52F/ON0b7dgBJ+X6uB/H5vNfQbjPvEeykOGCOg3ibcIO67ilIpxi6tu7CVl7ILw3yQzcdewxDwgHJuc04fYE7BDcY3VsiJh8Z3IaK28MH6p8ZATvTqSP4JApXLRV//0ovRBpNoI1gJa37YCBAAEAgo/t5Tsr3tOUnzTlhX/ljIdmecBYcIctZh8Oeew6Kzh3Vt3eEgqkYOJ42U5nAxom2ae0Usd1QhrKd1/chRtSbT2eFP2CLKUZ261oZONXBZR44R1LRecwjfxVkw4gWwxCKwxRJwiBWrxkld62f6SZZiHq+ZppshTZCO2usoTJDIISQEBklY5alT1VFmmitBEhd5JUsEj5uE/3Qf6dLMkMwrVZCW6T+VJkWqcNppZ7qZy38uXay24iSbpZ0MCbziVkidVrdTpplQ0/jQbGna5s2t1YZNj2ezm2P4p6ZLlySGVwdttX+c250oY/TjsZQ3PlVDWZTcS8+0sINYB+2ZTBNTP0k2I67TvtYZoWY3ZZ3P7SBMqASxLu5c4arLqRUd0u6Js8Xz+n4yfc+mYziZKeRULH1pvGQ9MIl5Zb83EYNs1nMeb9dWbCRpa06/zRdlaTuRsopcbZLrN8daNi2ZI2YTE7ScJJlZqzl7cGyCeEHSPYtnXpM2tO8bawiPICOlxNJrbE8aC8k7kZxxuLkGtNlMjAzWM68jiZW0ZOZcp1yUBkkfo2V9ysIzjxUlb0uXmVGo2x7sdkxPyB82TXpE1yatig7q+a1J0jARV5OqY6pDUpFBTipLN0sspT5D4qYq99HRe1rlQDOXZGRRQKw3ZctBnLfYQnPBnlBJfE750CKX3L6npYR8XeSyqnBFfqqav6rRSmv/qrpqqKZq0abaqkOI6lLI51zlEV+ongJUn9AaqCFtC6TdkzwNwwPa63A3T2tzmo6KKGa662paM1t5m3fo5Cc661LzgmshrJYq+P+TPUXrWohCm5sj31A7N5nh1vNCrZM61dlzwtWlsLrWTXd6+EHP+Vjh6k7PevjmjpO0CPkf0771q38DGtigBjekoQ3L0/BGNLJRjW5MY4vU38yeL8qLkiT2QtFmm+UQAwz0VJDcuMYb1ITEQwZLaSKv1CZ5qclNaWoxhhjqP8UWV3wJhjWt6TxukybDnGZIb2aJvViS4c1qdslGlGJkL+Ut1f8YZXRppZdhrjHmWSDT/OY012EWepexfibS881rfgtElelrHmthi6zlhRZriZYSbVHLWMJSFmu5VmilVmk144xvjdZqndYzwUQ/agNntFGbmNRmvtUWbdU2bdcO7VSWdilbu7VHe7VP+3VAB3VIh3VER3VMx3VCL+sVvarX9Lre0Jt6i/N8yn4O6G29o3f1HnupRW3qUJd6BFCfBjQkUO/rpD7gLH/yF3/rQ32kU1g6TQ2q8QyNeB2bozRxhDxWU5WTmvRWXWd4j/fp28dUwY/JpuolQj6fcZIP+JCPeJXXyOEcDnyd0FmaclvDKtazTp+wgeXK0Tmm+I5l5Oq8PmUFn+CjXFaShT+/8CunCLKZxp5lJzvYzsvEOEYf29inPPawm+PKJxsXF/SZLqhAF3VJl3VFhfpcV/WFilSsa7quG7qpW7rNad3RXZXoS93TVypVmcp1Xw/0P1Xoa32jb/WdvmcT9+hnI2Xc4T5f8hV3KaGUcj18dzFhkcykmXr6SeppiAs88j2T+Mr3pF1t/kk7OX+Gc3SlKfwE+GP8hXCLw04ebrVyYSC0dTSstIl9s12g25YV7Xy+Sq3wQ/HuuxWgfA/QdXk0/Drwa49BVO2ZHSrQvqGVuPQ8TBPtCFn1fFu2mZWl78e3qqchHUgTiYeNDlX8QmNxvNe6cWLZH1MQpa4DaWJOSu/huZk43+E8Lfh7VReVjyCxTR9OFy3DfY+sSaYVC3fXVyWbVVvd1dbiKtJhF6+s7eFNtcLm4+WN0PJXbqvPPqgiyIRdF++k2KQdd6R9QXdX9pQfIiGW2TGtz/sAG43Ij2yRdTM0f3j0bG8PRNEhCsxAiwp3iL7a4npq9ia30OapzMFE26D44UzrFxYjLUAwg+vDDLRRqCNDCB3qvkp833WuQs0wwlS4MI8zUpSDTcH+hlzow/OI9Usr4V0YJsh9lwEAkQvcFZGcGoIEGZT8fG241Kt1aqeWyaslWN2y7q1Dy/m/0RxorkcFfa+up2GuuL723Q/kBBy/khfw1vajD74bBSI/UFw7fkuiZI6A+oXSYAoppDx1UzcX82ru5uJP4MdP9FvzF2qtWvUV8KUHRGk0vo0sMAcekAnQjMa8LwOEGQgKOh10OtSWliNgM0SIqIkaEBFAAAJELAM5vvYOorQ2MEUHotIzsQOxVXZQqxR+srld9INwtMJDcJmAMfFRzYkcycZS2+dWlNqd1P6KKfJ203TlF0yR95emDDZxSQjA1YWZK+fDryz14c7XfR98EQl0H4wRfhDFUCXysBH8+gTXKjQBxkq2OgMRRnkaaCQpdDJ1r4lhcH5s5R0nhlyU8M2OvJFdLx9O0ZRzN0K3f1nEdQtzcvPCwiD3sNOf2jgCJZ+ZMSxoYzCJAtZ715Ny5LuhHQ/pP2tRl1mV4pDUKz1yqH6Ck8gNACr4Tm5HSSqvyHJG9EfwM9A0CgkmcDz+PEoS+zLsFBfHRL8rbRr3ju4+6HtT3sWn70naNbRoHb/4o852M1dNH8sXW62bCRH1Hd/t2/ds1Qh3YJ/Hooo4VbtEJCU0T5vvpf+7zbRmdPQ7EWuiwYmvtBydcuE9jv7jGr7bwn/UGdcSZDcGcZFKMvF7Pgozwc7aDsu/9SlVrnzH3viuiY5/3xHvpH9/AAAA") format('woff2');
9
- font-weight: 400;
10
- font-style: normal;
11
- }
12
- .bg { fill: #000; }
13
- .fg { fill: #fff; }
14
- .stroke { stroke: #fff; stroke-width: 2; fill: none; }
15
- .title { font-family: 'GeistPixel', monospace; font-size: 46px; }
16
- .label { font-family: 'GeistPixel', monospace; font-size: 20px; dominant-baseline: middle; }
17
- .body { font-family: 'GeistPixel', monospace; font-size: 18px; dominant-baseline: middle; }
18
- </style>
19
- </defs>
20
-
21
- <rect class="bg" x="0" y="0" width="1400" height="560"/>
22
- <rect class="stroke" x="18" y="18" width="1364" height="524"/>
23
-
24
- <text class="title fg" x="42" y="76">RHYTHMGUARD RULE MATRIX</text>
25
-
26
- <rect class="stroke" x="42" y="110" width="1316" height="96"/>
27
- <text class="label fg" x="68" y="158">RULE</text>
28
- <text class="label fg" x="418" y="158">WHAT IT ENFORCES</text>
29
- <text class="label fg" x="940" y="158">FIX STRATEGY</text>
30
-
31
- <rect class="stroke" x="42" y="206" width="1316" height="106"/>
32
- <text class="body fg" x="68" y="259">rhythmguard/use-scale</text>
33
- <text class="body fg" x="418" y="259">Spacing values must be on your scale</text>
34
- <text class="body fg" x="940" y="259">Nearest safe scale value</text>
35
-
36
- <rect class="stroke" x="42" y="312" width="1316" height="106"/>
37
- <text class="body fg" x="68" y="365">rhythmguard/prefer-token</text>
38
- <text class="body fg" x="418" y="365">Raw spacing replaced by tokens</text>
39
- <text class="body fg" x="940" y="365">tokenMap-guided replacement</text>
40
-
41
- <rect class="stroke" x="42" y="418" width="1316" height="106"/>
42
- <text class="body fg" x="68" y="471">rhythmguard/no-offscale-transform</text>
43
- <text class="body fg" x="418" y="471">translate() motion offset on scale</text>
44
- <text class="body fg" x="940" y="471">Nearest translate value</text>
45
- </svg>