@donkit-ai/design-system 0.2.10 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -15
- package/package.json +1 -1
- package/src/components/Accordion.jsx +2 -1
- package/src/components/Alert.jsx +3 -2
- package/src/components/CodeAccordion.jsx +2 -1
- package/src/components/Modal.jsx +2 -1
- package/src/components/Select.jsx +2 -1
- package/src/components/Stepper.css +8 -4
- package/src/components/Stepper.jsx +2 -1
- package/src/components/Textarea.css +17 -13
- package/src/index.js +1 -0
- package/src/styles/iconSizes.js +13 -0
- package/src/styles/tokens.css +14 -7
package/README.md
CHANGED
|
@@ -89,19 +89,30 @@ function MyComponent() {
|
|
|
89
89
|
|
|
90
90
|
#### Размеры иконок
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
Размеры иконок стандартизированы с помощью констант:
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
```javascript
|
|
95
|
+
import { iconSizes } from '@donkit-ai/design-system';
|
|
96
|
+
|
|
97
|
+
// iconSizes = { xs: 16, s: 20, m: 24, l: 28 }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Соответствие размеров компонентам:**
|
|
101
|
+
|
|
102
|
+
- **16px (xs)** - очень мелкие элементы
|
|
103
|
+
- **20px (s)** - компактные элементы
|
|
95
104
|
- Small кнопки (`size="small"`)
|
|
96
105
|
- Tabs (вкладки)
|
|
97
106
|
- Modal (иконка закрытия)
|
|
107
|
+
- Accordion, CodeAccordion
|
|
98
108
|
|
|
99
|
-
- **24px** - стандартные элементы
|
|
109
|
+
- **24px (m)** - стандартные элементы
|
|
100
110
|
- Medium кнопки (`size="medium"`, по умолчанию)
|
|
101
111
|
- Input (иконки в полях ввода)
|
|
102
112
|
- Alert (иконки статусов)
|
|
113
|
+
- Select (иконка выпадающего списка)
|
|
103
114
|
|
|
104
|
-
- **28px** - крупные элементы
|
|
115
|
+
- **28px (l)** - крупные элементы
|
|
105
116
|
- Large кнопки (`size="large"`)
|
|
106
117
|
|
|
107
118
|
**Всегда используется `strokeWidth={1.5}`** для единообразия дизайна.
|
|
@@ -110,30 +121,31 @@ function MyComponent() {
|
|
|
110
121
|
|
|
111
122
|
```javascript
|
|
112
123
|
import { Mail, Search, Eye, EyeOff, AlertCircle, Check, X } from 'lucide-react';
|
|
124
|
+
import { iconSizes } from '@donkit-ai/design-system';
|
|
113
125
|
|
|
114
126
|
// Small button / Tabs / Modal
|
|
115
|
-
<Button size="small" icon={<Mail size={
|
|
127
|
+
<Button size="small" icon={<Mail size={iconSizes.s} strokeWidth={1.5} />}>
|
|
116
128
|
Send
|
|
117
129
|
</Button>
|
|
118
|
-
<Tab icon={<AlertCircle size={
|
|
130
|
+
<Tab icon={<AlertCircle size={iconSizes.s} strokeWidth={1.5} />}>
|
|
119
131
|
Alerts
|
|
120
132
|
</Tab>
|
|
121
133
|
|
|
122
134
|
// Medium button / Input / Alert
|
|
123
|
-
<Button size="medium" icon={<Search size={
|
|
135
|
+
<Button size="medium" icon={<Search size={iconSizes.m} strokeWidth={1.5} />}>
|
|
124
136
|
Search
|
|
125
137
|
</Button>
|
|
126
138
|
<Input
|
|
127
|
-
icon={<Search size={
|
|
139
|
+
icon={<Search size={iconSizes.m} strokeWidth={1.5} />}
|
|
128
140
|
placeholder="Search..."
|
|
129
141
|
/>
|
|
130
142
|
<Alert
|
|
131
143
|
type="success"
|
|
132
|
-
icon={<Check size={
|
|
144
|
+
icon={<Check size={iconSizes.m} strokeWidth={1.5} />}
|
|
133
145
|
/>
|
|
134
146
|
|
|
135
147
|
// Large button
|
|
136
|
-
<Button size="large" icon={<Mail size={
|
|
148
|
+
<Button size="large" icon={<Mail size={iconSizes.l} strokeWidth={1.5} />}>
|
|
137
149
|
Send Email
|
|
138
150
|
</Button>
|
|
139
151
|
```
|
|
@@ -154,9 +166,9 @@ document.documentElement.setAttribute('data-theme', 'light');
|
|
|
154
166
|
|
|
155
167
|
#### Базовые примитивы
|
|
156
168
|
- `--color-white`: #FFFAFA
|
|
157
|
-
- `--color-white-65/50/40/20/15/13/06`: rgba с прозрачностью 65%, 50%, 40%, 20%, 15%, 13%, 6%
|
|
169
|
+
- `--color-white-95/92/65/50/40/20/15/13/06`: rgba с прозрачностью 95%, 92%, 65%, 50%, 40%, 20%, 15%, 13%, 6%
|
|
158
170
|
- `--color-black`: #0E0F11
|
|
159
|
-
- `--color-black-65/60/50/40/20/10/08/04`: rgba с прозрачностью 65%, 60%, 50%, 40%, 20%, 10%, 8%, 4%
|
|
171
|
+
- `--color-black-95/65/60/50/40/20/10/08/04`: rgba с прозрачностью 95%, 65%, 60%, 50%, 40%, 20%, 10%, 8%, 4%
|
|
160
172
|
- `--color-red`: #EA6464
|
|
161
173
|
- `--color-red-90`: rgba с прозрачностью 90%
|
|
162
174
|
|
|
@@ -170,7 +182,7 @@ document.documentElement.setAttribute('data-theme', 'light');
|
|
|
170
182
|
- `--color-border` - границы
|
|
171
183
|
- `--color-border-hover` - границы при hover (Dark: white-40, Light: black-40)
|
|
172
184
|
- `--color-border-selected` - границы выбранного элемента (Dark: white-50, Light: black-50)
|
|
173
|
-
- `--color-txt-icon-1` - основной текст/иконки (
|
|
185
|
+
- `--color-txt-icon-1` - основной текст/иконки (Dark: white-92, Light: black-95)
|
|
174
186
|
- `--color-txt-icon-2` - вторичный текст/иконки (65%)
|
|
175
187
|
- `--color-accent` - акцентный цвет
|
|
176
188
|
- `--color-accent-hover` - акцент при hover
|
|
@@ -203,7 +215,7 @@ document.documentElement.setAttribute('data-theme', 'light');
|
|
|
203
215
|
- `--font-size-h1`: 32px → 40px → 40px
|
|
204
216
|
- `--font-size-h2`: 28px → 36px → 36px
|
|
205
217
|
- `--font-size-h3`: 24px → 28px → 28px
|
|
206
|
-
- `--font-size-h4`:
|
|
218
|
+
- `--font-size-h4`: 20px → 24px → 24px
|
|
207
219
|
- `--font-size-p1`: 16px → 18px → 18px
|
|
208
220
|
- `--font-size-p2`: 14px → 16px → 16px
|
|
209
221
|
- `--font-size-p3`: 12px → 14px → 14px
|
|
@@ -214,7 +226,7 @@ document.documentElement.setAttribute('data-theme', 'light');
|
|
|
214
226
|
- Меньше 14px → +6% (0.06em)
|
|
215
227
|
|
|
216
228
|
Адаптивные значения трекинга:
|
|
217
|
-
- `--letter-spacing-h4`: 0
|
|
229
|
+
- `--letter-spacing-h4`: 0 → 0 → 0 (20px / 24px / 24px - без трекинга)
|
|
218
230
|
- `--letter-spacing-p1`: 0.02em → 0.02em → 0.02em (16px / 18px / 18px)
|
|
219
231
|
- `--letter-spacing-p2`: 0.04em → 0.02em → 0.02em (14px / 16px / 16px)
|
|
220
232
|
- `--letter-spacing-p3`: 0.06em → 0.04em → 0.04em (12px / 14px / 14px)
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { ChevronDown } from 'lucide-react';
|
|
3
|
+
import { iconSizes } from '../styles/iconSizes';
|
|
3
4
|
import './Accordion.css';
|
|
4
5
|
|
|
5
6
|
export function Accordion({
|
|
@@ -20,7 +21,7 @@ export function Accordion({
|
|
|
20
21
|
>
|
|
21
22
|
<span className="ds-accordion__title">{title}</span>
|
|
22
23
|
<ChevronDown
|
|
23
|
-
size={
|
|
24
|
+
size={iconSizes.s}
|
|
24
25
|
strokeWidth={1.5}
|
|
25
26
|
className={`ds-accordion__icon ${isExpanded ? 'ds-accordion__icon--expanded' : ''}`}
|
|
26
27
|
/>
|
package/src/components/Alert.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Info, CheckCircle, AlertTriangle, XCircle, X } from 'lucide-react';
|
|
3
|
+
import { iconSizes } from '../styles/iconSizes';
|
|
3
4
|
import './Alert.css';
|
|
4
5
|
|
|
5
6
|
const ICON_MAP = {
|
|
@@ -24,7 +25,7 @@ export function Alert({
|
|
|
24
25
|
<div className={`ds-alert ds-alert--${variant} ${!title ? 'ds-alert--no-title' : ''}`} role={alertRole} {...props}>
|
|
25
26
|
{Icon && (
|
|
26
27
|
<div className="ds-alert__icon">
|
|
27
|
-
<Icon size={
|
|
28
|
+
<Icon size={iconSizes.m} strokeWidth={1.5} />
|
|
28
29
|
</div>
|
|
29
30
|
)}
|
|
30
31
|
<div className="ds-alert__content">
|
|
@@ -38,7 +39,7 @@ export function Alert({
|
|
|
38
39
|
onClick={onClose}
|
|
39
40
|
aria-label="Close alert"
|
|
40
41
|
>
|
|
41
|
-
<X size={
|
|
42
|
+
<X size={iconSizes.m} strokeWidth={1.5} />
|
|
42
43
|
</button>
|
|
43
44
|
)}
|
|
44
45
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { ChevronDown } from 'lucide-react';
|
|
3
|
+
import { iconSizes } from '../styles/iconSizes';
|
|
3
4
|
import './CodeAccordion.css';
|
|
4
5
|
|
|
5
6
|
export function CodeAccordion({
|
|
@@ -20,7 +21,7 @@ export function CodeAccordion({
|
|
|
20
21
|
>
|
|
21
22
|
<span className="ds-code-accordion__title">{title}</span>
|
|
22
23
|
<ChevronDown
|
|
23
|
-
size={
|
|
24
|
+
size={iconSizes.s}
|
|
24
25
|
strokeWidth={1.5}
|
|
25
26
|
className={`ds-code-accordion__icon ${isExpanded ? 'ds-code-accordion__icon--expanded' : ''}`}
|
|
26
27
|
/>
|
package/src/components/Modal.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
2
|
import { X } from 'lucide-react';
|
|
3
|
+
import { iconSizes } from '../styles/iconSizes';
|
|
3
4
|
import { Button } from './Button';
|
|
4
5
|
import './Modal.css';
|
|
5
6
|
|
|
@@ -52,7 +53,7 @@ export function Modal({
|
|
|
52
53
|
<Button
|
|
53
54
|
variant="ghost"
|
|
54
55
|
size="small"
|
|
55
|
-
icon={<X size={
|
|
56
|
+
icon={<X size={iconSizes.s} strokeWidth={1.5} />}
|
|
56
57
|
onClick={onClose}
|
|
57
58
|
aria-label="Close modal"
|
|
58
59
|
/>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState, useRef, useEffect } from 'react';
|
|
2
2
|
import { ChevronDown } from 'lucide-react';
|
|
3
|
+
import { iconSizes } from '../styles/iconSizes';
|
|
3
4
|
import './Select.css';
|
|
4
5
|
|
|
5
6
|
export function Select({
|
|
@@ -52,7 +53,7 @@ export function Select({
|
|
|
52
53
|
}, [isOpen]);
|
|
53
54
|
|
|
54
55
|
const selectedOption = options.find(opt => opt.value === value);
|
|
55
|
-
const iconSize = size === 'small' ?
|
|
56
|
+
const iconSize = size === 'small' ? iconSizes.s : iconSizes.m;
|
|
56
57
|
|
|
57
58
|
return (
|
|
58
59
|
<div className={`ds-select-wrapper ${fullWidth ? 'ds-select-wrapper--full' : ''} ${disabled ? 'ds-select-wrapper--disabled' : ''}`}>
|
|
@@ -99,28 +99,32 @@
|
|
|
99
99
|
/* Sizes */
|
|
100
100
|
|
|
101
101
|
/* Small */
|
|
102
|
+
.ds-stepper--small {
|
|
103
|
+
height: var(--height-s);
|
|
104
|
+
}
|
|
105
|
+
|
|
102
106
|
.ds-stepper--small .ds-stepper-button {
|
|
103
107
|
width: var(--height-s);
|
|
104
|
-
height: var(--height-s);
|
|
105
108
|
padding: 0;
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
.ds-stepper--small .ds-stepper-input {
|
|
109
|
-
height: var(--height-s);
|
|
110
112
|
font-size: var(--font-size-p2);
|
|
111
113
|
letter-spacing: var(--letter-spacing-p2);
|
|
112
114
|
padding: 0 var(--space-xs);
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
/* Medium */
|
|
118
|
+
.ds-stepper--medium {
|
|
119
|
+
height: var(--height-m);
|
|
120
|
+
}
|
|
121
|
+
|
|
116
122
|
.ds-stepper--medium .ds-stepper-button {
|
|
117
123
|
width: var(--height-m);
|
|
118
|
-
height: var(--height-m);
|
|
119
124
|
padding: 0;
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
.ds-stepper--medium .ds-stepper-input {
|
|
123
|
-
height: var(--height-m);
|
|
124
128
|
font-size: var(--font-size-p1);
|
|
125
129
|
letter-spacing: var(--letter-spacing-p1);
|
|
126
130
|
padding: 0 var(--space-s);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Minus, Plus } from 'lucide-react';
|
|
3
|
+
import { iconSizes } from '../styles/iconSizes';
|
|
3
4
|
import './Stepper.css';
|
|
4
5
|
|
|
5
6
|
export function Stepper({
|
|
@@ -56,7 +57,7 @@ export function Stepper({
|
|
|
56
57
|
disabled && 'ds-stepper--disabled',
|
|
57
58
|
].filter(Boolean).join(' ');
|
|
58
59
|
|
|
59
|
-
const iconSize = size === 'small' ?
|
|
60
|
+
const iconSize = size === 'small' ? iconSizes.s : iconSizes.m;
|
|
60
61
|
|
|
61
62
|
return (
|
|
62
63
|
<div className={className}>
|
|
@@ -28,27 +28,31 @@
|
|
|
28
28
|
transition: border-color var(--transition-normal);
|
|
29
29
|
line-height: 1.5;
|
|
30
30
|
resize: vertical;
|
|
31
|
-
/* Кастомный resize handle */
|
|
31
|
+
/* Кастомный resize handle - 2 диагональные линии */
|
|
32
32
|
background:
|
|
33
|
-
linear-gradient(
|
|
34
|
-
linear-gradient(
|
|
33
|
+
linear-gradient(315deg, transparent 5px, var(--color-border) 5px, var(--color-border) 6px, transparent 6px),
|
|
34
|
+
linear-gradient(315deg, transparent 10px, var(--color-border) 10px, var(--color-border) 11px, transparent 11px);
|
|
35
35
|
background-repeat: no-repeat;
|
|
36
36
|
background-position: bottom right;
|
|
37
|
-
background-size:
|
|
37
|
+
background-size: 16px 16px;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.ds-textarea::placeholder {
|
|
41
41
|
color: var(--color-txt-icon-2);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
.ds-textarea::-webkit-resizer {
|
|
45
|
+
display: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
44
48
|
.ds-textarea:hover:not(:disabled) {
|
|
45
49
|
border-color: var(--color-border-hover);
|
|
46
50
|
background:
|
|
47
|
-
linear-gradient(
|
|
48
|
-
linear-gradient(
|
|
51
|
+
linear-gradient(315deg, transparent 5px, var(--color-border-hover) 5px, var(--color-border-hover) 6px, transparent 6px),
|
|
52
|
+
linear-gradient(315deg, transparent 10px, var(--color-border-hover) 10px, var(--color-border-hover) 11px, transparent 11px);
|
|
49
53
|
background-repeat: no-repeat;
|
|
50
54
|
background-position: bottom right;
|
|
51
|
-
background-size:
|
|
55
|
+
background-size: 16px 16px;
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
.ds-textarea:focus,
|
|
@@ -56,11 +60,11 @@
|
|
|
56
60
|
outline: none;
|
|
57
61
|
border-color: var(--color-border-hover);
|
|
58
62
|
background:
|
|
59
|
-
linear-gradient(
|
|
60
|
-
linear-gradient(
|
|
63
|
+
linear-gradient(315deg, transparent 5px, var(--color-border-hover) 5px, var(--color-border-hover) 6px, transparent 6px),
|
|
64
|
+
linear-gradient(315deg, transparent 10px, var(--color-border-hover) 10px, var(--color-border-hover) 11px, transparent 11px);
|
|
61
65
|
background-repeat: no-repeat;
|
|
62
66
|
background-position: bottom right;
|
|
63
|
-
background-size:
|
|
67
|
+
background-size: 16px 16px;
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
.ds-textarea:disabled {
|
|
@@ -70,11 +74,11 @@
|
|
|
70
74
|
.ds-textarea--error {
|
|
71
75
|
border-color: var(--color-error);
|
|
72
76
|
background:
|
|
73
|
-
linear-gradient(
|
|
74
|
-
linear-gradient(
|
|
77
|
+
linear-gradient(315deg, transparent 5px, var(--color-error) 5px, var(--color-error) 6px, transparent 6px),
|
|
78
|
+
linear-gradient(315deg, transparent 10px, var(--color-error) 10px, var(--color-error) 11px, transparent 11px);
|
|
75
79
|
background-repeat: no-repeat;
|
|
76
80
|
background-position: bottom right;
|
|
77
|
-
background-size:
|
|
81
|
+
background-size: 16px 16px;
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
.ds-textarea--no-resize {
|
package/src/index.js
CHANGED
package/src/styles/tokens.css
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
/* Color primitives - white */
|
|
12
12
|
--color-white: #FFFAFA;
|
|
13
13
|
--color-white-95: rgba(255, 250, 250, 0.95);
|
|
14
|
+
--color-white-92: rgba(255, 250, 250, 0.92);
|
|
14
15
|
--color-white-65: rgba(255, 250, 250, 0.65);
|
|
15
16
|
--color-white-50: rgba(255, 250, 250, 0.5);
|
|
16
17
|
--color-white-40: rgba(255, 250, 250, 0.4);
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
--color-border: var(--color-white-20);
|
|
68
69
|
--color-border-hover: var(--color-white-40);
|
|
69
70
|
--color-border-selected: var(--color-white-50);
|
|
70
|
-
--color-txt-icon-1: var(--color-white-
|
|
71
|
+
--color-txt-icon-1: var(--color-white-92);
|
|
71
72
|
--color-txt-icon-2: var(--color-white-65);
|
|
72
73
|
--color-accent: var(--color-red);
|
|
73
74
|
--color-accent-hover: var(--color-red-90);
|
|
@@ -173,6 +174,12 @@
|
|
|
173
174
|
--height-s: 32px;
|
|
174
175
|
--height-m: 44px;
|
|
175
176
|
--height-l: 56px;
|
|
177
|
+
|
|
178
|
+
/* Icon sizes */
|
|
179
|
+
--icon-xs: 16px;
|
|
180
|
+
--icon-s: 20px;
|
|
181
|
+
--icon-m: 24px;
|
|
182
|
+
--icon-l: 28px;
|
|
176
183
|
}
|
|
177
184
|
|
|
178
185
|
:root {
|
|
@@ -188,7 +195,7 @@
|
|
|
188
195
|
--font-size-h1: 32px;
|
|
189
196
|
--font-size-h2: 28px;
|
|
190
197
|
--font-size-h3: 24px;
|
|
191
|
-
--font-size-h4:
|
|
198
|
+
--font-size-h4: 20px;
|
|
192
199
|
--font-size-p1: 16px;
|
|
193
200
|
--font-size-p2: 14px;
|
|
194
201
|
--font-size-p3: 12px;
|
|
@@ -197,7 +204,7 @@
|
|
|
197
204
|
--letter-spacing-h1: 0;
|
|
198
205
|
--letter-spacing-h2: 0;
|
|
199
206
|
--letter-spacing-h3: 0;
|
|
200
|
-
--letter-spacing-h4: 0
|
|
207
|
+
--letter-spacing-h4: 0; /* 20px → no tracking */
|
|
201
208
|
--letter-spacing-p1: 0.02em; /* 16px → +2% */
|
|
202
209
|
--letter-spacing-p2: 0.04em; /* 14px → +4% */
|
|
203
210
|
--letter-spacing-p3: 0.06em; /* 12px → +6% */
|
|
@@ -209,12 +216,12 @@
|
|
|
209
216
|
--font-size-h1: 40px;
|
|
210
217
|
--font-size-h2: 36px;
|
|
211
218
|
--font-size-h3: 28px;
|
|
212
|
-
--font-size-h4:
|
|
219
|
+
--font-size-h4: 24px;
|
|
213
220
|
--font-size-p1: 18px;
|
|
214
221
|
--font-size-p2: 16px;
|
|
215
222
|
--font-size-p3: 14px;
|
|
216
223
|
|
|
217
|
-
--letter-spacing-h4: 0; /*
|
|
224
|
+
--letter-spacing-h4: 0; /* 24px → no tracking */
|
|
218
225
|
--letter-spacing-p1: 0.02em; /* 18px → +2% */
|
|
219
226
|
--letter-spacing-p2: 0.02em; /* 16px → +2% */
|
|
220
227
|
--letter-spacing-p3: 0.04em; /* 14px → +4% */
|
|
@@ -227,12 +234,12 @@
|
|
|
227
234
|
--font-size-h1: 40px;
|
|
228
235
|
--font-size-h2: 36px;
|
|
229
236
|
--font-size-h3: 28px;
|
|
230
|
-
--font-size-h4:
|
|
237
|
+
--font-size-h4: 24px;
|
|
231
238
|
--font-size-p1: 18px;
|
|
232
239
|
--font-size-p2: 16px;
|
|
233
240
|
--font-size-p3: 14px;
|
|
234
241
|
|
|
235
|
-
--letter-spacing-h4: 0; /*
|
|
242
|
+
--letter-spacing-h4: 0; /* 24px → no tracking */
|
|
236
243
|
--letter-spacing-p1: 0.02em; /* 18px → +2% */
|
|
237
244
|
--letter-spacing-p2: 0.02em; /* 16px → +2% */
|
|
238
245
|
--letter-spacing-p3: 0.04em; /* 14px → +4% */
|