@howssatoshi/quantumcss 1.0.2 → 1.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/src/generator.js CHANGED
@@ -3,181 +3,190 @@ const path = require('path');
3
3
  const { glob } = require('glob');
4
4
  const { defaultTheme, utilityMaps } = require('./defaults');
5
5
 
6
- const breakpoints = {
7
- sm: '640px',
8
- md: '768px',
9
- lg: '1024px',
10
- xl: '1280px',
11
- };
6
+ const breakpoints = { sm: '640px', md: '768px', lg: '1024px', xl: '1280px', '2xl': '1536px' };
12
7
 
13
8
  function generateCSS(configPath) {
14
- delete require.cache[path.resolve(configPath)];
15
- const config = require(path.resolve(configPath));
9
+ const resolvedPath = path.resolve(configPath);
10
+ if (fs.existsSync(resolvedPath)) delete require.cache[resolvedPath];
11
+ const config = fs.existsSync(resolvedPath) ? require(resolvedPath) : { content: [], theme: {} };
16
12
 
17
- const contentPaths = config.content || [];
18
- const theme = { ...defaultTheme };
19
- if (config.theme) {
20
- if (config.theme.extend) {
21
- theme.colors = { ...theme.colors, ...config.theme.extend.colors };
22
- theme.spacing = { ...theme.spacing, ...config.theme.extend.spacing };
23
- theme.fontSize = { ...theme.fontSize, ...config.theme.extend.fontSize };
24
- theme.shadows = { ...theme.shadows, ...config.theme.extend.shadows };
25
- } else {
26
- Object.assign(theme, config.theme);
27
- }
13
+ const theme = JSON.parse(JSON.stringify(defaultTheme || {}));
14
+ theme.colors = theme.colors || {};
15
+ theme.spacing = theme.spacing || {};
16
+ theme.borderRadius = theme.borderRadius || {};
17
+ theme.fontSize = theme.fontSize || {};
18
+
19
+ if (config.theme && config.theme.extend) {
20
+ const ext = config.theme.extend;
21
+ if (ext.colors) Object.assign(theme.colors, ext.colors);
22
+ if (ext.spacing) Object.assign(theme.spacing, ext.spacing);
23
+ if (ext.borderRadius) Object.assign(theme.borderRadius, ext.borderRadius);
24
+ if (ext.fontSize) Object.assign(theme.fontSize, ext.fontSize);
28
25
  }
29
26
 
30
27
  const flattenedColors = {};
31
28
  Object.entries(theme.colors).forEach(([name, value]) => {
32
- if (typeof value === 'string') {
33
- flattenedColors[name] = value;
34
- } else {
35
- Object.entries(value).forEach(([shade, hex]) => {
36
- flattenedColors[`${name}-${shade}`] = hex;
37
- });
29
+ if (typeof value === 'string') flattenedColors[name] = value;
30
+ else {
31
+ Object.entries(value || {}).forEach(([shade, hex]) => { flattenedColors[`${name}-${shade}`] = hex; });
32
+ if (value && value['500']) flattenedColors[name] = value['500'];
38
33
  }
39
34
  });
40
35
 
41
- const files = contentPaths.flatMap(p => glob.sync(p));
36
+ function resolveColor(key) {
37
+ if (!key) return null;
38
+ if (flattenedColors[key]) return flattenedColors[key];
39
+ if (key.includes('/')) {
40
+ const [base, opacity] = key.split('/');
41
+ const color = flattenedColors[base] || flattenedColors[`${base}-500`];
42
+ if (color && color.startsWith('#')) {
43
+ const r = parseInt(color.slice(1, 3), 16), g = parseInt(color.slice(3, 5), 16), b = parseInt(color.slice(5, 7), 16);
44
+ return `rgba(${r}, ${g}, ${b}, ${parseInt(opacity) / 100})`;
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+
50
+ const files = (config.content || []).flatMap(p => glob.sync(p));
42
51
  const rawClasses = new Set();
52
+ const classAttrRegex = /class="([^"]+)"/g;
43
53
 
44
54
  files.forEach(file => {
45
- const content = fs.readFileSync(file, 'utf8');
46
- const matches = content.match(/[a-z0-9\-\/:]+/g);
47
- if (matches) {
48
- matches.forEach(cls => rawClasses.add(cls));
49
- }
55
+ try {
56
+ const content = fs.readFileSync(file, 'utf8');
57
+ let match;
58
+ while ((match = classAttrRegex.exec(content)) !== null) {
59
+ match[1].split(/\s+/).forEach(cls => { if (cls) rawClasses.add(cls); });
60
+ }
61
+ } catch (e) {}
50
62
  });
51
63
 
52
- let css = '/* Quantum CSS - High Performance Output */\n';
53
- css += '*, ::before, ::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: #e5e7eb; }\n';
54
- css += 'html { line-height: 1.5; -webkit-text-size-adjust: 100%; font-family: Inter, ui-sans-serif, system-ui, sans-serif; }\n';
55
- css += 'body { margin: 0; line-height: inherit; }\n';
56
- css += 'img { display: block; max-width: 100%; height: auto; }\n';
57
- css += 'button { cursor: pointer; background: transparent; padding: 0; color: inherit; font: inherit; }\n\n';
58
-
59
64
  const utilities = new Set();
60
- const responsiveUtils = { sm: new Set(), md: new Set(), lg: new Set(), xl: new Set() };
65
+ const responsiveUtils = { sm: new Set(), md: new Set(), lg: new Set(), xl: new Set(), '2xl': new Set() };
66
+
67
+ const sideMap = {
68
+ p: 'padding', pt: 'padding-top', pr: 'padding-right', pb: 'padding-bottom', pl: 'padding-left',
69
+ px: ['padding-left', 'padding-right'], py: ['padding-top', 'padding-bottom'],
70
+ m: 'margin', mt: 'margin-top', mr: 'margin-right', mb: 'margin-bottom', ml: 'margin-left',
71
+ mx: ['margin-left', 'margin-right'], my: ['margin-top', 'margin-bottom'],
72
+ w: 'width', h: 'height', top: 'top', right: 'right', bottom: 'bottom', left: 'left',
73
+ 'max-w': 'max-width', 'max-h': 'max-height', 'min-w': 'min-width', 'min-h': 'min-height',
74
+ gap: 'gap', 'gap-x': 'column-gap', 'gap-y': 'row-gap'
75
+ };
61
76
 
62
77
  function processClass(fullCls) {
63
- let cls = fullCls;
64
- let variant = null;
65
- let breakpoint = null;
66
-
78
+ let cls = fullCls, variant = null, breakpoint = null, isNeg = false;
79
+ if (cls.startsWith('-')) { isNeg = true; cls = cls.substring(1); }
67
80
  const parts = cls.split(':');
68
- if (parts.length > 1) {
69
- if (breakpoints[parts[0]]) {
70
- breakpoint = parts[0];
71
- cls = parts.slice(1).join(':');
72
- }
73
- const subParts = cls.split(':');
74
- if (subParts.length > 1) {
75
- variant = subParts[0];
76
- cls = subParts[1];
77
- } else if (!breakpoint) {
78
- variant = parts[0];
79
- cls = parts[1];
80
- }
81
+ let currentPart = 0;
82
+ while (currentPart < parts.length) {
83
+ const p = parts[currentPart];
84
+ if (breakpoints[p]) { breakpoint = p; }
85
+ else if (['hover', 'focus', 'placeholder', 'group-hover'].includes(p)) { variant = p; }
86
+ else { cls = parts.slice(currentPart).join(':'); break; }
87
+ currentPart++;
81
88
  }
82
89
 
83
- let property = null;
84
- let value = null;
85
-
90
+ let property = null, value = null, customSelector = null;
86
91
  if (utilityMaps[cls]) {
87
- if (typeof utilityMaps[cls] === 'object' && !Array.isArray(utilityMaps[cls])) {
88
- property = utilityMaps[cls].property;
89
- value = utilityMaps[cls].value;
90
- } else {
91
- property = utilityMaps[cls];
92
- }
92
+ const entry = utilityMaps[cls];
93
+ if (typeof entry === 'object' && !Array.isArray(entry)) { property = entry.property; value = entry.value; }
94
+ else { property = entry; }
93
95
  }
94
96
 
95
97
  if (!property || !value) {
96
98
  const cParts = cls.split('-');
97
- const prefix = cParts[0];
98
- const valKey = cParts.slice(1).join('-');
99
+ let prefix = cParts[0], valKey = cParts.slice(1).join('-');
100
+
101
+ if ((prefix === 'max' || prefix === 'min' || prefix === 'gap' || prefix === 'gap-x' || prefix === 'gap-y') && cParts[1]) {
102
+ if (['w', 'h', 'x', 'y'].includes(cParts[1])) {
103
+ prefix = `${cParts[0]}-${cParts[1]}`;
104
+ valKey = cParts.slice(2).join('-');
105
+ }
106
+ }
99
107
 
100
108
  if (prefix === 'text') {
101
- if (theme.fontSize[valKey]) { property = 'font-size'; value = theme.fontSize[valKey]; }
102
- else if (flattenedColors[valKey]) { property = 'color'; value = flattenedColors[valKey]; }
103
- } else if (prefix === 'bg') {
104
- property = 'background-color'; value = flattenedColors[valKey];
105
- } else if (prefix === 'shadow') {
106
- property = 'box-shadow'; value = theme.shadows[valKey] || theme.shadows.md;
109
+ if (theme.fontSize[valKey]) { property = ['font-size', 'line-height']; value = [theme.fontSize[valKey], (valKey.includes('xl') || parseInt(valKey) >= 3) ? '1.2' : '1.5']; }
110
+ else { const color = resolveColor(valKey); if (color) { property = 'color'; value = color; } }
111
+ } else if (prefix === 'bg') { const color = resolveColor(valKey); if (color) { property = 'background-color'; value = color; } }
112
+ else if (prefix === 'z') { property = 'z-index'; value = isNeg ? `-${valKey}` : valKey; }
113
+ else if (prefix === 'aspect') {
114
+ property = ['aspect-ratio', 'width', 'height'];
115
+ let ratio = 'auto';
116
+ if (valKey.startsWith('[') && valKey.endsWith(']')) ratio = valKey.slice(1, -1).replace(/\//g, ' / ');
117
+ else if (valKey === 'video') ratio = '16 / 9';
118
+ else if (valKey === 'square') ratio = '1 / 1';
119
+ else ratio = valKey.replace(/\//g, ' / ');
120
+ value = [ratio, '100%', 'auto'];
121
+ } else if (prefix === 'grid' && cParts[1] === 'cols') {
122
+ property = 'grid-template-columns'; value = `repeat(${cParts[2]}, minmax(0, 1fr))`;
123
+ } else if (prefix === 'col' && cParts[1] === 'span') {
124
+ property = 'grid-column'; value = `span ${cParts[2]} / span ${cParts[2]}`;
125
+ } else if (prefix === 'space') {
126
+ const amount = theme.spacing[cParts[2]] || `${parseInt(cParts[2]) * 0.25}rem`;
127
+ const escaped = fullCls.replace(/([:[\/])/g, '\\$1');
128
+ customSelector = `.${escaped} > * + *`;
129
+ property = cParts[1] === 'y' ? 'margin-top' : 'margin-left';
130
+ value = isNeg ? `-${amount}` : amount;
107
131
  } else if (prefix === 'rounded') {
108
132
  property = 'border-radius';
109
- if (valKey === 'lg') value = '0.5rem';
110
- else if (valKey === 'full') value = '9999px';
111
- else value = theme.spacing[valKey] || (valKey ? `${parseInt(valKey) * 0.125}rem` : '0.25rem');
112
- } else if (prefix === 'border') {
113
- if (flattenedColors[valKey]) {
114
- property = 'border-color'; value = flattenedColors[valKey];
115
- } else if (cParts[1] === 'l' || cParts[1] === 'r' || cParts[1] === 't' || cParts[1] === 'b') {
116
- const sideMap = { l: 'left', r: 'right', t: 'top', b: 'bottom' };
117
- property = `border-${sideMap[cParts[1]]}-width`;
118
- value = `${cParts[2]}px`;
119
- }
120
- } else if (prefix === 'gap') {
121
- property = 'gap'; value = theme.spacing[valKey] || (valKey ? (isNaN(valKey) ? valKey : `${valKey}rem`) : '0px');
122
- } else if (prefix === 'grid' && cParts[1] === 'cols') {
123
- property = 'grid-template-columns';
124
- value = `repeat(${cParts[2]}, minmax(0, 1fr))`;
125
- } else if (prefix === 'flex' && cParts[1] === 'row') {
126
- property = 'flex-direction';
127
- value = 'row';
128
- } else if (prefix === 'w' || prefix === 'h') {
129
- property = utilityMaps[prefix];
130
- if (valKey.includes('/')) {
131
- const [n, d] = valKey.split('/');
132
- value = `${(parseInt(n)/parseInt(d)*100).toFixed(2)}%`;
133
- } else {
134
- value = theme.spacing[valKey] || valKey;
135
- }
136
- } else if (utilityMaps[prefix]) {
137
- const mapEntry = utilityMaps[prefix];
138
- if (typeof mapEntry === 'object' && !Array.isArray(mapEntry)) {
139
- property = mapEntry.property;
140
- value = mapEntry.value;
141
- } else {
142
- property = mapEntry;
143
- value = theme.spacing[valKey] || valKey;
133
+ if (valKey.startsWith('[') && valKey.endsWith(']')) value = valKey.slice(1, -1);
134
+ else if (theme.borderRadius[valKey]) value = theme.borderRadius[valKey];
135
+ else {
136
+ const num = parseInt(valKey);
137
+ value = isNaN(num) ? '0.375rem' : `${num * 0.125}rem`;
144
138
  }
139
+ } else if (prefix === 'scale') {
140
+ property = 'transform';
141
+ value = `scale(${parseInt(valKey) / 100})`;
142
+ } else if (prefix === 'transition') {
143
+ property = 'transition-property';
144
+ if (valKey === 'all') value = 'all';
145
+ else if (valKey === 'colors') value = 'color, background-color, border-color, text-decoration-color, fill, stroke';
146
+ else if (valKey === 'transform') value = 'transform';
147
+ else value = valKey;
148
+ } else if (prefix === 'duration') {
149
+ property = 'transition-duration';
150
+ value = `${valKey}ms`;
151
+ } else if (sideMap[prefix]) {
152
+ property = sideMap[prefix];
153
+ let v = valKey;
154
+ if (v.startsWith('[') && v.endsWith(']')) v = v.slice(1, -1);
155
+ else if (v.includes('/')) v = `${(parseInt(v.split('/')[0])/parseInt(v.split('/')[1])*100).toFixed(2)}%`;
156
+ else v = theme.spacing[v] || v;
157
+ value = isNeg ? (Array.isArray(v) ? v.map(x => `-${x}`) : `-${v}`) : v;
158
+ } else if (prefix === 'border') {
159
+ const color = resolveColor(valKey);
160
+ if (color) { property = 'border-color'; value = color; }
161
+ else if (['l', 'r', 't', 'b'].includes(cParts[1])) {
162
+ const sideMapSide = { l: 'left', r: 'right', t: 'top', b: 'bottom' };
163
+ property = `border-${sideMapSide[cParts[1]]}-width`;
164
+ value = `${cParts[2]}px`;
165
+ } else if (!isNaN(parseInt(valKey))) { property = 'border-width'; value = `${parseInt(valKey)}px`; }
145
166
  }
146
167
  }
147
168
 
148
169
  if (property && value) {
149
- let selector = `.${fullCls.replace(/:/g, '\\:').replace(/\//g, '\\/')}`;
150
- if (variant === 'hover' || variant === 'focus') selector += `:${variant}`;
151
-
152
- let rules = '';
153
- if (Array.isArray(property)) {
154
- if (Array.isArray(value)) {
155
- rules = property.map((p, i) => ` ${p}: ${value[i]};`).join('\n');
156
- } else {
157
- rules = property.map(p => ` ${p}: ${value};`).join('\n');
158
- }
159
- } else {
160
- rules = ` ${property}: ${value};`;
161
- }
162
-
163
- const cssBlock = `${selector} {\n${rules}\n}\n`;
164
- if (breakpoint) { responsiveUtils[breakpoint].add(cssBlock); }
165
- else { utilities.add(cssBlock); }
170
+ const escapedFull = fullCls.replace(/([:[\/])/g, '\\$1');
171
+ let selector = customSelector || `.${escapedFull}`;
172
+ if (variant) { if (variant === 'group-hover') selector = `.group:hover ${selector}`; else selector += `:${variant}`}
173
+ let rules = Array.isArray(property) ? property.map((p, i) => ` ${p}: ${Array.isArray(value) ? value[i] : value};`).join('\n') : ` ${property}: ${value};`;
174
+ const block = `${selector} {
175
+ ${rules}
176
+ }
177
+ `;
178
+ if (breakpoint) responsiveUtils[breakpoint].add(block); else utilities.add(block);
166
179
  }
167
180
  }
168
181
 
169
182
  rawClasses.forEach(processClass);
170
-
171
- css += Array.from(utilities).join('\n');
183
+ let css = '/* Quantum CSS JIT Output */\n' + Array.from(utilities).join('\n');
172
184
  Object.entries(breakpoints).forEach(([name, width]) => {
173
185
  if (responsiveUtils[name].size > 0) {
174
- css += `\n@media (min-width: ${width}) {\n`;
175
- css += Array.from(responsiveUtils[name]).map(u => ' ' + u.replace(/\n/g, '\n ')).join('\n').trimEnd();
176
- css += '\n}\n';
186
+ css += `\n@media (min-width: ${width}) {\n${Array.from(responsiveUtils[name]).map(u => ' ' + u.replace(/\n/g, '\n ')).join('\n').trimEnd()}\n}\n`;
177
187
  }
178
188
  });
179
-
180
189
  return css;
181
190
  }
182
191
 
183
- module.exports = { generateCSS };
192
+ module.exports = { generateCSS };
@@ -189,12 +189,41 @@
189
189
  transition: all var(--duration-150) var(--ease-in-out);
190
190
  }
191
191
 
192
+ textarea.input {
193
+ min-height: 100px;
194
+ }
195
+
192
196
  .input:focus {
193
197
  outline: none;
194
198
  border-color: var(--color-primary);
195
199
  box-shadow: 0 0 0 3px var(--color-primary);
196
200
  }
197
201
 
202
+ /* Date & Time Input Specifics */
203
+ input[type="date"].input,
204
+ input[type="datetime-local"].input,
205
+ input[type="time"].input {
206
+ appearance: none;
207
+ -webkit-appearance: none;
208
+ min-height: 2.5rem;
209
+ display: inline-flex;
210
+ align-items: center;
211
+ }
212
+
213
+ /* Ensure dark-mode calendar picker */
214
+ .glass input[type="date"],
215
+ .starlight-card input[type="date"],
216
+ [class*="dark"] input[type="date"] {
217
+ color-scheme: dark;
218
+ }
219
+
220
+ /* Fix for alignment in flex containers */
221
+ input[type="date"]::-webkit-calendar-picker-indicator {
222
+ cursor: pointer;
223
+ filter: invert(0.5);
224
+ margin-left: 0.5rem;
225
+ }
226
+
198
227
  .input:disabled {
199
228
  background-color: #f3f4f6;
200
229
  color: #6b7280;
@@ -214,37 +243,45 @@
214
243
  .badge {
215
244
  display: inline-flex;
216
245
  align-items: center;
217
- padding: var(--space-1) var(--space-2);
218
- border-radius: var(--radius-full);
246
+ padding: 0.25rem 0.75rem;
247
+ border-radius: 0.375rem;
219
248
  font-size: 0.75rem;
220
- font-weight: 500;
249
+ font-weight: 600;
221
250
  text-transform: uppercase;
222
251
  letter-spacing: 0.05em;
252
+ border: 1px solid;
253
+ backdrop-filter: blur(4px);
254
+ -webkit-backdrop-filter: blur(4px);
223
255
  }
224
256
 
225
257
  .badge-primary {
226
- background-color: var(--color-primary-100);
227
- color: var(--color-primary-800);
258
+ background-color: rgba(0, 212, 255, 0.15);
259
+ color: #00d4ff;
260
+ border-color: rgba(0, 212, 255, 0.3);
228
261
  }
229
262
 
230
263
  .badge-secondary {
231
- background-color: #e5e7eb;
232
- color: #374151;
264
+ background-color: rgba(255, 255, 255, 0.05);
265
+ color: rgba(255, 255, 255, 0.8);
266
+ border-color: rgba(255, 255, 255, 0.1);
233
267
  }
234
268
 
235
269
  .badge-success {
236
- background-color: #d1fae5;
237
- color: #065f46;
270
+ background-color: rgba(16, 185, 129, 0.15);
271
+ color: #10b981;
272
+ border-color: rgba(16, 185, 129, 0.3);
238
273
  }
239
274
 
240
275
  .badge-warning {
241
- background-color: #fed7aa;
242
- color: #92400e;
276
+ background-color: rgba(245, 158, 11, 0.15);
277
+ color: #f59e0b;
278
+ border-color: rgba(245, 158, 11, 0.3);
243
279
  }
244
280
 
245
281
  .badge-error {
246
- background-color: #fee2e2;
247
- color: #991b1b;
282
+ background-color: rgba(239, 68, 68, 0.15);
283
+ color: #ef4444;
284
+ border-color: rgba(239, 68, 68, 0.3);
248
285
  }
249
286
 
250
287
  /* Alert Component */
@@ -303,8 +340,8 @@
303
340
  display: inline-block;
304
341
  width: 1.5rem;
305
342
  height: 1.5rem;
306
- border: 2px solid transparent;
307
- border-top-color: currentColor;
343
+ border: 2px solid rgba(255, 255, 255, 0.1);
344
+ border-top-color: var(--color-primary);
308
345
  border-radius: 50%;
309
346
  animation: spin 1s linear infinite;
310
347
  }
@@ -313,29 +350,24 @@
313
350
  to { transform: rotate(360deg); }
314
351
  }
315
352
 
316
- .spinner-sm {
317
- width: 1rem;
318
- height: 1rem;
319
- }
320
-
321
- .spinner-lg {
322
- width: 2rem;
323
- height: 2rem;
324
- }
325
-
326
353
  /* Skeleton Loading */
327
354
  .skeleton {
328
- background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
355
+ background: linear-gradient(90deg, rgba(255,255,255,0.05) 25%, rgba(255,255,255,0.1) 50%, rgba(255,255,255,0.05) 75%);
329
356
  background-size: 200% 100%;
330
- animation: loading 1.5s infinite;
357
+ animation: shimmer 2s infinite;
331
358
  border-radius: var(--radius-md);
332
359
  }
333
360
 
334
- @keyframes loading {
361
+ @keyframes shimmer {
335
362
  0% { background-position: 200% 0; }
336
363
  100% { background-position: -200% 0; }
337
364
  }
338
365
 
366
+ body.light-mode .skeleton {
367
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
368
+ background-size: 200% 100%;
369
+ }
370
+
339
371
  /* Tooltip Component */
340
372
  .tooltip {
341
373
  position: relative;
@@ -140,6 +140,18 @@ body {
140
140
  line-height: inherit;
141
141
  }
142
142
 
143
+ input, textarea, select, button {
144
+ font-family: inherit;
145
+ font-size: inherit;
146
+ line-height: inherit;
147
+ color: inherit;
148
+ }
149
+
150
+ textarea {
151
+ resize: vertical;
152
+ min-height: 5rem;
153
+ }
154
+
143
155
  /* Layout Utilities */
144
156
  .container {
145
157
  width: 100%;
@@ -262,7 +274,7 @@ body {
262
274
  .text-2xl { font-size: 1.5rem; line-height: 2rem; }
263
275
  .text-3xl { font-size: 1.875rem; line-height: 2.25rem; }
264
276
  .text-4xl { font-size: 2.25rem; line-height: 2.5rem; }
265
- .text-5xl { font-size: 3rem; line-height: 1; }
277
+ .text-5xl { font-size: 3rem; line-height: 1.2; }
266
278
 
267
279
  .font-light { font-weight: 300; }
268
280
  .font-normal { font-weight: 400; }
@@ -844,19 +856,19 @@ body {
844
856
  }
845
857
 
846
858
  /* Utility for Quick Prototyping */
847
- .q-prose {
859
+ .prose {
848
860
  max-width: 65ch;
849
861
  line-height: 1.75;
850
862
  }
851
863
 
852
- .q-prose h1 {
864
+ .prose h1 {
853
865
  font-size: 2.25rem;
854
866
  font-weight: 700;
855
867
  line-height: 1.25;
856
868
  margin-bottom: 1rem;
857
869
  }
858
870
 
859
- .q-prose h2 {
871
+ .prose h2 {
860
872
  font-size: 1.875rem;
861
873
  font-weight: 600;
862
874
  line-height: 1.25;
@@ -864,16 +876,16 @@ body {
864
876
  margin-bottom: 1rem;
865
877
  }
866
878
 
867
- .q-prose p {
879
+ .prose p {
868
880
  margin-bottom: 1rem;
869
881
  }
870
882
 
871
- .q-prose a {
883
+ .prose a {
872
884
  color: var(--color-primary);
873
885
  text-decoration: underline;
874
886
  }
875
887
 
876
- .q-prose a:hover {
888
+ .prose a:hover {
877
889
  color: var(--color-primary-600);
878
890
  }
879
891