ply-css 1.4.1 → 1.6.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/CLAUDE.md CHANGED
@@ -7,7 +7,7 @@ This is the ply CSS framework repository. See **PLY.md** for the complete class
7
7
  **`ply-classes.json`** is the complete searchable reference. Before writing any custom CSS, search it first:
8
8
 
9
9
  - **`classes`** — Every ply class with category, description, and examples. Search here before inventing a class name.
10
- - **`customProperties`** — All 60+ `--ply-*` CSS variables organized by category (typography, background, text, borders, interactive, elevation, brand, palette) with light/dark values. Use these instead of hardcoding colors or font stacks.
10
+ - **`customProperties`** — All 120+ `--ply-*` CSS variables organized by category (typography, background, text, borders, interactive, elevation, brand, palette, color surfaces) with light/dark values. Use these instead of hardcoding colors or font stacks.
11
11
  - **`semanticElements`** — Every HTML element ply auto-styles (`<dialog>`, `<details>`, `<table>`, `<code>`, `<kbd>`, `<mark>`, `<progress>`, `<meter>`, etc.) with tips on usage. Check here before building a custom component — ply may already style the native element.
12
12
 
13
13
  **Rule: If you're about to write custom CSS, search `ply-classes.json` first.** If a class, variable, or semantic element already does what you need, use it.
@@ -28,7 +28,7 @@ ply automatically styles semantic HTML elements — `<nav>`, `<table>`, `<code>`
28
28
  8. **Use semantic HTML first** — ply auto-styles `<code>`, `<pre>`, `<kbd>`, `<blockquote>`, `<mark>`, `<table>`, `<details>`, `<dialog>`, `<nav>`, etc. Use native elements before creating custom classes.
29
29
  9. **Only use documented ply classes** — Do NOT invent class names. Search `ply-classes.json` to find the right class. See PLY.md for the full prose reference.
30
30
  10. **Dark mode is automatic** — Auto dark mode activates only when no `data-theme` attribute is set on `<html>`. Use `data-theme="dark"` for explicit dark mode, `data-theme="light"` for explicit light mode, or any custom value (e.g., `data-theme="warm"`) for a custom theme without dark-mode interference. Use `var(--ply-*)` custom properties for colors (see `customProperties` in the JSON), never hard-code values that break dark mode.
31
- 11. **Icons** — Use [Feather Icons](https://feathericons.com) as the preferred icon library. Any icon library works, but Feather pairs well with ply's aesthetic.
31
+ 11. **Icons** — Use [Lucide](https://lucide.dev) as the preferred icon library. Any icon library works, but Lucide pairs well with ply's aesthetic. For icon + text buttons, place the icon before or after the label — the button's built-in `inline-flex` layout with `gap: 0.5em` handles alignment automatically. Use `btn-icon` only for icon-only buttons (no visible text).
32
32
  12. **Container queries** — Use `container-query` on a parent element and `container-tablet-unit-*`, `container-phone-unit-*`, etc. for component-level responsive behavior (responds to parent width, not viewport). See PLY.md for details.
33
33
 
34
34
  ## Custom Themes
@@ -50,6 +50,8 @@ Create a custom theme by defining a `data-theme` value and overriding `--ply-*`
50
50
  --ply-btn-default-bg-active: #7c2d12;
51
51
  --ply-btn-secondary-bg: #78350f;
52
52
  --ply-btn-border-radius: 0.5rem;
53
+ --ply-btn-font-size: 0.875rem; /* button text size */
54
+ --ply-btn-gap: 0.375rem; /* icon-to-text gap */
53
55
  --ply-nav-bg: #fef3c7;
54
56
  --ply-nav-border: #f59e0b;
55
57
 
package/PLY.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # PLY — AI-Ready CSS Framework
2
2
 
3
- ply is a ratio-based, flexbox CSS framework with dark mode, accessibility defaults, and a small footprint (18.5KB gzip full, ~15KB core). 457 utility classes, 100+ CSS custom properties, 13 auto-styled semantic elements.
3
+ ply is a ratio-based, flexbox CSS framework with dark mode, accessibility defaults, and a small footprint (~21KB gzip full, ~17KB core). 458 utility classes, 120+ CSS custom properties, 13 auto-styled semantic elements.
4
4
 
5
5
  **Differentiators:** Small bundle, AI-parseable class system, accessible out of the box, dark mode built-in.
6
6
 
@@ -8,8 +8,8 @@ ply is a ratio-based, flexbox CSS framework with dark mode, accessibility defaul
8
8
 
9
9
  **`ply-classes.json`** is the complete searchable reference. Before writing any custom CSS, search it first:
10
10
 
11
- - **`classes`** — Every ply class (457) with category, description, and usage examples. Search here before inventing a class name or writing a custom style.
12
- - **`customProperties`** — All `--ply-*` CSS variables organized by category (background, text, borders, interactive, forms, code, tables, buttons, navigation, elevation, brand, palette). Each entry includes light and dark mode values. Use these instead of hardcoding colors.
11
+ - **`classes`** — Every ply class (458) with category, description, and usage examples. Search here before inventing a class name or writing a custom style.
12
+ - **`customProperties`** — All `--ply-*` CSS variables organized by category (background, text, borders, interactive, forms, code, tables, buttons, navigation, elevation, brand, palette, colorSurfaces, spacing). Each entry includes light and dark mode values. Use these instead of hardcoding colors.
13
13
  - **`semanticElements`** — Every HTML element ply auto-styles (`<dialog>`, `<details>`, `<table>`, `<code>`, `<kbd>`, `<mark>`, `<progress>`, `<meter>`, headings, form controls) with styling details and usage tips. Check here before building a custom component.
14
14
 
15
15
  The JSON is the source of truth. If a class, variable, or semantic element already does what you need, use it instead of writing custom CSS.
@@ -33,6 +33,8 @@ Create a custom theme by defining a `data-theme` value and overriding `--ply-*`
33
33
  --ply-btn-default-bg-active: #7c2d12;
34
34
  --ply-btn-secondary-bg: #78350f;
35
35
  --ply-btn-border-radius: 0.5rem;
36
+ --ply-btn-font-size: 0.875rem; /* button text size — default 1em inherits from context */
37
+ --ply-btn-gap: 0.375rem; /* icon-to-text gap — default 0.5em */
36
38
  --ply-nav-bg: #fef3c7;
37
39
  --ply-nav-border: #f59e0b;
38
40
 
@@ -55,6 +57,33 @@ See `customProperties` in `ply-classes.json` for the full list of overridable va
55
57
 
56
58
  ply uses `color-mix()` to auto-compute hover/active button states from your base color. This works in all modern browsers (Chrome 111+, Firefox 113+, Safari 16.4+, Edge 111+). On older browsers (pre-2023), `color-mix()` is ignored and the fallback hex values from ply's default theme are used instead. For custom themes targeting legacy browsers, also set `--ply-btn-default-bg-hover`, `--ply-btn-default-bg-active`, `--ply-btn-secondary-bg-hover`, and `--ply-btn-secondary-bg-active` explicitly. In modern browsers, `color-mix()` overrides these fallbacks automatically.
57
59
 
60
+ ## Color Surfaces
61
+
62
+ Theme-aware surface and border colors for building colored cards, badges, and alerts that work in both light and dark mode. Available for all 10 palette colors: blue, red, green, yellow, indigo, purple, pink, orange, teal, cyan.
63
+
64
+ | Variable | Light Mode | Dark Mode | Use |
65
+ |---|---|---|---|
66
+ | `--ply-{color}-surface` | Pastel | Dark muted | Card/badge background |
67
+ | `--ply-{color}-border` | Light tint | Medium dark | Colored borders |
68
+ | `--ply-{color}-1` | Base | Lighter | Text on surface, icons |
69
+ | `--ply-{color}-2` | Darker | Medium | Emphasis |
70
+ | `--ply-{color}-3` | Darkest | Lightest | Subtle accent |
71
+
72
+ ```css
73
+ /* Theme-aware colored card */
74
+ .card-info {
75
+ background: var(--ply-blue-surface);
76
+ border: 1px solid var(--ply-blue-border);
77
+ color: var(--ply-blue-1);
78
+ }
79
+
80
+ .card-danger {
81
+ background: var(--ply-red-surface);
82
+ border: 1px solid var(--ply-red-border);
83
+ color: var(--ply-red-1);
84
+ }
85
+ ```
86
+
58
87
  ## Philosophy: Start Semantic
59
88
 
60
89
  ply automatically styles semantic HTML elements — tables, code blocks, blockquotes, navs, details/summary, dialogs, progress bars, meters, forms, and more. Before reaching for a `<div>` with a custom class, check if a semantic element already does what you need. Custom styling is fine when you need it, but start with what HTML and ply give you for free.
@@ -117,15 +146,16 @@ Note: The CDN approach gives you ply's classes and dark mode, but you won't have
117
146
 
118
147
  ## Icons
119
148
 
120
- ply does not include icons. [Feather Icons](https://feathericons.com) is the recommended icon library — it's lightweight, clean, and pairs well with ply's aesthetic. Any icon library works.
149
+ ply does not include icons. [Lucide](https://lucide.dev) is the recommended icon library — it's lightweight, clean, and pairs well with ply's aesthetic. Any icon library works.
121
150
 
122
151
  ```html
123
- <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
124
- <script>feather.replace();</script>
152
+ <!-- CDN -->
153
+ <script src="https://cdn.jsdelivr.net/npm/lucide@latest/dist/umd/lucide.min.js"></script>
154
+ <script>lucide.createIcons();</script>
125
155
 
126
156
  <!-- Usage -->
127
- <i data-feather="check"></i> Saved
128
- <button class="btn btn-blue"><i data-feather="send"></i> Send</button>
157
+ <i data-lucide="check"></i> Saved
158
+ <button class="btn btn-primary"><i data-lucide="send"></i> Send</button>
129
159
  ```
130
160
 
131
161
  ## Dark Mode
@@ -219,7 +249,61 @@ All classes, CSS custom properties, and semantic element styles are documented i
219
249
 
220
250
  - **`btn-icon`** — Icon-only button modifier. Equal padding for a square aspect ratio. Always add `aria-label` (no visible text).
221
251
  - Combine with `btn-ghost` for toolbar-style icon buttons. Combine with size modifiers (`btn-sm`, `btn-xs`) for smaller icons.
222
- - For icon + text buttons, use a regular `btn` with an inline SVG no `btn-icon` needed.
252
+ - **Icon + text buttons** Place the icon before or after the label text inside a regular `btn`. The button automatically uses `inline-flex` with `align-items: center` and `gap: 0.5em`, so icon and text are vertically centered with consistent spacing. No extra classes needed.
253
+
254
+ ```html
255
+ <!-- Icon left -->
256
+ <button class="btn btn-primary">
257
+ <i data-lucide="save"></i> Save
258
+ </button>
259
+
260
+ <!-- Icon right -->
261
+ <button class="btn btn-secondary">
262
+ Next <i data-lucide="arrow-right"></i>
263
+ </button>
264
+
265
+ <!-- Icon-only (always include aria-label) -->
266
+ <button class="btn btn-ghost btn-icon" aria-label="Delete">
267
+ <i data-lucide="trash-2"></i>
268
+ </button>
269
+
270
+ <!-- Size variants work the same way -->
271
+ <button class="btn btn-primary btn-sm">
272
+ <i data-lucide="download"></i> Export
273
+ </button>
274
+ ```
275
+
276
+ ### Button Groups
277
+
278
+ Wrap buttons in `.btn-group` for a flex row with consistent gap and connected border-radius on the outer edges.
279
+
280
+ - **`btn-group`** — Default: buttons with `0.5rem` gap between them.
281
+ - **`btn-group joined`** — No gap; buttons connect as a single unit with a 1px divider between them. Use for segmented controls, toolbars, and pagination-style groups.
282
+ - **`align-right`** / **`align-left`** / **`align-center`** — Justify the group within its container.
283
+ - **`fill-width`** — Stretch all buttons to share equal width.
284
+ - **`rounded`** — Larger border-radius on the outer edges.
285
+
286
+ ```html
287
+ <!-- Default: gapped -->
288
+ <div class="btn-group">
289
+ <button class="btn btn-primary">Save</button>
290
+ <button class="btn">Cancel</button>
291
+ </div>
292
+
293
+ <!-- Joined: connected, no gap -->
294
+ <div class="btn-group joined">
295
+ <button class="btn">Week</button>
296
+ <button class="btn btn-primary">Month</button>
297
+ <button class="btn">Year</button>
298
+ </div>
299
+
300
+ <!-- Joined icon toolbar -->
301
+ <div class="btn-group joined">
302
+ <button class="btn btn-ghost btn-icon" aria-label="Bold"><i data-lucide="bold"></i></button>
303
+ <button class="btn btn-ghost btn-icon" aria-label="Italic"><i data-lucide="italic"></i></button>
304
+ <button class="btn btn-ghost btn-icon" aria-label="Underline"><i data-lucide="underline"></i></button>
305
+ </div>
306
+ ```
223
307
 
224
308
  ## Common Patterns
225
309
 
@@ -640,7 +724,7 @@ Ready-to-use HTML examples are in the `snippets/` directory:
640
724
 
641
725
  | Bundle | Includes | Size (gzip) |
642
726
  |--------|----------|-------------|
643
- | `ply.min.css` | Everything | 18.5KB |
727
+ | `ply.min.css` | Everything | ~21KB |
644
728
  | `ply-core.min.css` | Grid, buttons, forms, nav, alerts, tables, typography, essential helpers | ~17KB |
645
- | `ply-essentials.min.css` | Grid, helpers, alignments, blocks only | ~6KB |
646
- | `ply-helpers.min.css` | Helper utilities only | ~4KB |
729
+ | `ply-essentials.min.css` | Grid, helpers, alignments, blocks only | ~7KB |
730
+ | `ply-helpers.min.css` | Helper utilities only | ~5KB |
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A ratio-based, AI-ready CSS framework with dark mode, accessibility, and a small footprint.
4
4
 
5
- **18.5KB gzipped. No JavaScript. No build step. One `<link>` tag.**
5
+ **~21KB gzipped. No JavaScript. No build step. One `<link>` tag.**
6
6
 
7
7
  ## Install
8
8
 
@@ -37,7 +37,7 @@ CSS frameworks were designed for humans reading documentation. But increasingly,
37
37
  - **Start semantic** — ply automatically styles `<nav>`, `<table>`, `<code>`, `<blockquote>`, `<details>`, `<dialog>`, and more. Start with what HTML gives you, then reach for classes when you need them.
38
38
  - **AI-native** — ships with `PLY.md` (AI instruction file) and `ply-classes.json` (machine-readable class reference). Class names are predictable: `.alert-blue`, `.btn-sm`, `.unit-50`.
39
39
  - **Accessible by default** — `:focus-visible` outlines on all interactive elements (including `<summary>` and legacy components), `prefers-reduced-motion`, `prefers-color-scheme` dark mode, semantic HTML styling, WCAG AA contrast in both light and dark themes. Published [VPAT 2.5](https://plycss.com/docs/vpat) documenting conformance against all WCAG 2.1 Level A and AA criteria.
40
- - **Small footprint** — 18.5KB gzipped (full), ~15KB (core). No JavaScript runtime, no build step, no tree-shaking.
40
+ - **Small footprint** — ~21KB gzipped (full), ~17KB (core). No JavaScript runtime, no build step, no tree-shaking.
41
41
  - **Ratio-based grid** — think in percentages, not arbitrary columns. `unit-50` is 50%, `unit-33` is 33%. Responsive prefixes: `tablet-unit-*`, `phone-unit-*`.
42
42
  - **Custom theming** — override `--ply-*` CSS custom properties to create any theme. Light and dark modes built in.
43
43
 
@@ -114,11 +114,11 @@ See `snippets/custom-theme.html` for a full working example.
114
114
 
115
115
  ## Icons
116
116
 
117
- ply doesn't include icons. [Feather Icons](https://feathericons.com) is recommended — lightweight, clean, and pairs well with ply. Any icon library works.
117
+ ply doesn't include icons. [Lucide](https://lucide.dev) is recommended — lightweight, clean, and pairs well with ply. Any icon library works.
118
118
 
119
119
  ```html
120
- <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
121
- <script>feather.replace();</script>
120
+ <script src="https://cdn.jsdelivr.net/npm/lucide@latest/dist/umd/lucide.min.js"></script>
121
+ <script>lucide.createIcons();</script>
122
122
  ```
123
123
 
124
124
  ## AI Integration
@@ -151,7 +151,7 @@ ply targets ADA Title II (28 CFR Part 35) / WCAG 2.1 AA compliance at the framew
151
151
 
152
152
  ## Documentation
153
153
 
154
- Full interactive docs at [plyCSS.com](https://plycss.com) — browse every class with live examples, search the entire framework, and copy-paste code snippets.
154
+ Full interactive docs at [plycss.com](https://plycss.com) — browse every class with live examples, search the entire framework, and copy-paste code snippets.
155
155
 
156
156
  ## Roadmap
157
157
 
@@ -70,6 +70,26 @@
70
70
  --ply-bg-yellow: #f1c21b;
71
71
  --ply-bg-yellow-hover: #d2a106;
72
72
  --ply-bg-yellow-active: #b28600;
73
+ --ply-blue-surface: #d3e3fb;
74
+ --ply-red-surface: #f8d5d8;
75
+ --ply-green-surface: #d5ecd9;
76
+ --ply-yellow-surface: #fff4cc;
77
+ --ply-indigo-surface: #e0e7ff;
78
+ --ply-purple-surface: #ede9fe;
79
+ --ply-pink-surface: #fce7f3;
80
+ --ply-orange-surface: #ffedd5;
81
+ --ply-teal-surface: #ccfbf1;
82
+ --ply-cyan-surface: #cffafe;
83
+ --ply-blue-border: #92baf6;
84
+ --ply-red-border: #ef969d;
85
+ --ply-green-border: #96cfa1;
86
+ --ply-yellow-border: #ffe480;
87
+ --ply-indigo-border: #a5b4fc;
88
+ --ply-purple-border: #c4b5fd;
89
+ --ply-pink-border: #f9a8d4;
90
+ --ply-orange-border: #fdba74;
91
+ --ply-teal-border: #5eead4;
92
+ --ply-cyan-border: #67e8f9;
73
93
  --ply-blue-1: #0f62fe;
74
94
  --ply-blue-2: #0043ce;
75
95
  --ply-blue-3: #002d9c;
@@ -125,9 +145,9 @@
125
145
  --ply-color-text-inverse: #161616;
126
146
  --ply-border-color: #393939;
127
147
  --ply-border-strong: #6f6f6f;
128
- --ply-color-link: var(--ply-btn-default-bg);
148
+ --ply-color-link: #4589ff;
129
149
  --ply-color-link-hover: #619bff;
130
- --ply-color-link-hover: color-mix(in oklch, var(--ply-btn-default-bg), white 15%);
150
+ --ply-color-link-hover: color-mix(in oklch, #4589ff, white 15%);
131
151
  --ply-color-focus: #0f62fe;
132
152
  --ply-color-field-bg: #262626;
133
153
  --ply-color-input-border: #6f6f6f;
@@ -164,6 +184,26 @@
164
184
  --ply-shadow-2: 0 2px 8px rgba(0, 0, 0, 0.3);
165
185
  --ply-shadow-3: 0 4px 24px rgba(0, 0, 0, 0.4);
166
186
  --ply-bg-glass: rgba(38, 38, 38, 0.25);
187
+ --ply-blue-surface: #1a2744;
188
+ --ply-red-surface: #3b1c1e;
189
+ --ply-green-surface: #1a2e1e;
190
+ --ply-yellow-surface: #332b10;
191
+ --ply-indigo-surface: #1e1b4b;
192
+ --ply-purple-surface: #2e1065;
193
+ --ply-pink-surface: #3b0a2a;
194
+ --ply-orange-surface: #331a08;
195
+ --ply-teal-surface: #132f2e;
196
+ --ply-cyan-surface: #133040;
197
+ --ply-blue-border: #1a52a5;
198
+ --ply-red-border: #b2232f;
199
+ --ply-green-border: #237f35;
200
+ --ply-yellow-border: #cca000;
201
+ --ply-indigo-border: #3730a3;
202
+ --ply-purple-border: #5b21b6;
203
+ --ply-pink-border: #9d174d;
204
+ --ply-orange-border: #c2410c;
205
+ --ply-teal-border: #0f766e;
206
+ --ply-cyan-border: #0e7490;
167
207
  --ply-bg-blue: #0f62fe;
168
208
  --ply-bg-blue-hover: #0043ce;
169
209
  --ply-bg-blue-active: #002d9c;
@@ -221,9 +261,9 @@
221
261
  --ply-color-text-inverse: #161616;
222
262
  --ply-border-color: #393939;
223
263
  --ply-border-strong: #6f6f6f;
224
- --ply-color-link: var(--ply-btn-default-bg);
264
+ --ply-color-link: #4589ff;
225
265
  --ply-color-link-hover: #619bff;
226
- --ply-color-link-hover: color-mix(in oklch, var(--ply-btn-default-bg), white 15%);
266
+ --ply-color-link-hover: color-mix(in oklch, #4589ff, white 15%);
227
267
  --ply-color-focus: #0f62fe;
228
268
  --ply-color-field-bg: #262626;
229
269
  --ply-color-input-border: #6f6f6f;
@@ -260,6 +300,26 @@
260
300
  --ply-shadow-2: 0 2px 8px rgba(0, 0, 0, 0.3);
261
301
  --ply-shadow-3: 0 4px 24px rgba(0, 0, 0, 0.4);
262
302
  --ply-bg-glass: rgba(38, 38, 38, 0.25);
303
+ --ply-blue-surface: #1a2744;
304
+ --ply-red-surface: #3b1c1e;
305
+ --ply-green-surface: #1a2e1e;
306
+ --ply-yellow-surface: #332b10;
307
+ --ply-indigo-surface: #1e1b4b;
308
+ --ply-purple-surface: #2e1065;
309
+ --ply-pink-surface: #3b0a2a;
310
+ --ply-orange-surface: #331a08;
311
+ --ply-teal-surface: #132f2e;
312
+ --ply-cyan-surface: #133040;
313
+ --ply-blue-border: #1a52a5;
314
+ --ply-red-border: #b2232f;
315
+ --ply-green-border: #237f35;
316
+ --ply-yellow-border: #cca000;
317
+ --ply-indigo-border: #3730a3;
318
+ --ply-purple-border: #5b21b6;
319
+ --ply-pink-border: #9d174d;
320
+ --ply-orange-border: #c2410c;
321
+ --ply-teal-border: #0f766e;
322
+ --ply-cyan-border: #0e7490;
263
323
  --ply-bg-blue: #0f62fe;
264
324
  --ply-bg-blue-hover: #0043ce;
265
325
  --ply-bg-blue-active: #002d9c;
@@ -1853,7 +1913,7 @@ table tfoot td {
1853
1913
  .units-row.reverse-direction, .units-row.right-to-left {
1854
1914
  flex-direction: row-reverse;
1855
1915
  }
1856
- .units-row.split {
1916
+ .units-row.joined, .units-row.split {
1857
1917
  --units-gap: 0px;
1858
1918
  gap: 0;
1859
1919
  }
@@ -4389,13 +4449,15 @@ input[type=button].btn,
4389
4449
  input[type=reset].btn,
4390
4450
  button.btn {
4391
4451
  transition: all 150ms ease-in-out, transform 50ms ease, background 150ms ease-in-out;
4392
- display: inline-block;
4452
+ display: inline-flex;
4393
4453
  vertical-align: top;
4454
+ align-items: center;
4455
+ justify-content: center;
4456
+ gap: var(--ply-btn-gap, 0.5em);
4394
4457
  font-family: var(--ply-font-body, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji);
4395
- font-size: 1em;
4458
+ font-size: var(--ply-btn-font-size, 1em);
4396
4459
  font-weight: 400;
4397
4460
  line-height: 1.5rem;
4398
- text-align: center;
4399
4461
  text-decoration: none;
4400
4462
  color: var(--ply-btn-secondary-color, var(--ply-color-text-inverse, #fff));
4401
4463
  -webkit-appearance: none;
@@ -5342,6 +5404,10 @@ button.btn-white.btn-outline.btn-active {
5342
5404
  .btn-group .btn:last-child {
5343
5405
  border-radius: 0 0.125rem 0.125rem 0;
5344
5406
  }
5407
+ .btn-single.joined,
5408
+ .btn-group.joined {
5409
+ gap: 0;
5410
+ }
5345
5411
  .btn-single.rounded .btn:first-child,
5346
5412
  .btn-single.rounded .input-search:first-child,
5347
5413
  .btn-group.rounded .btn:first-child,