@lepid-labs/styles 1.0.0 → 1.0.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.
Files changed (50) hide show
  1. package/css.d.ts +8 -0
  2. package/luminous-precision/base.css +6 -2
  3. package/luminous-precision/components/badge.css +25 -0
  4. package/luminous-precision/components/button-group.css +130 -0
  5. package/luminous-precision/components/button-hold.css +112 -0
  6. package/luminous-precision/components/icon-button.css +71 -0
  7. package/luminous-precision/components/layout.css +348 -0
  8. package/luminous-precision/components/page.css +85 -0
  9. package/luminous-precision/components/pre.css +75 -0
  10. package/luminous-precision/components/shell.css +165 -0
  11. package/luminous-precision/components/status-card.css +159 -0
  12. package/luminous-precision/components/stepper.css +108 -0
  13. package/luminous-precision/components/table.css +20 -0
  14. package/luminous-precision/components/tabs.css +42 -0
  15. package/luminous-precision/design.md +64 -4
  16. package/luminous-precision/index.css +8 -0
  17. package/luminous-precision/tokens.css +6 -0
  18. package/neon-butterfly/base.css +6 -2
  19. package/neon-butterfly/components/badge.css +25 -0
  20. package/neon-butterfly/components/button-group.css +128 -0
  21. package/neon-butterfly/components/button-hold.css +112 -0
  22. package/neon-butterfly/components/icon-button.css +66 -0
  23. package/neon-butterfly/components/layout.css +348 -0
  24. package/neon-butterfly/components/page.css +85 -0
  25. package/neon-butterfly/components/pre.css +75 -0
  26. package/neon-butterfly/components/shell.css +196 -0
  27. package/neon-butterfly/components/status-card.css +156 -0
  28. package/neon-butterfly/components/stepper.css +107 -0
  29. package/neon-butterfly/components/table.css +20 -0
  30. package/neon-butterfly/components/tabs.css +42 -0
  31. package/neon-butterfly/design.md +60 -4
  32. package/neon-butterfly/index.css +8 -0
  33. package/neon-butterfly/tokens.css +6 -0
  34. package/package.json +58 -15
  35. package/summer-cloud/base.css +6 -2
  36. package/summer-cloud/components/badge.css +26 -0
  37. package/summer-cloud/components/button-group.css +131 -0
  38. package/summer-cloud/components/button-hold.css +132 -0
  39. package/summer-cloud/components/icon-button.css +76 -0
  40. package/summer-cloud/components/layout.css +348 -0
  41. package/summer-cloud/components/page.css +85 -0
  42. package/summer-cloud/components/pre.css +74 -0
  43. package/summer-cloud/components/shell.css +197 -0
  44. package/summer-cloud/components/status-card.css +158 -0
  45. package/summer-cloud/components/stepper.css +101 -0
  46. package/summer-cloud/components/table.css +20 -0
  47. package/summer-cloud/components/tabs.css +42 -0
  48. package/summer-cloud/design.md +64 -2
  49. package/summer-cloud/index.css +8 -0
  50. package/summer-cloud/tokens.css +6 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lepid-labs/styles",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Shared design-system styles: tokens, base styles, and component classes per theme.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -19,22 +19,65 @@
19
19
  "summer-cloud",
20
20
  "luminous-precision",
21
21
  "all.css",
22
- "manifest.json"
22
+ "manifest.json",
23
+ "css.d.ts"
23
24
  ],
24
25
  "exports": {
25
- "./all": "./all.css",
26
+ "./all": {
27
+ "types": "./css.d.ts",
28
+ "default": "./all.css"
29
+ },
26
30
  "./manifest": "./manifest.json",
27
- "./neon-butterfly": "./neon-butterfly/index.css",
28
- "./neon-butterfly/tokens": "./neon-butterfly/tokens.css",
29
- "./neon-butterfly/base": "./neon-butterfly/base.css",
30
- "./neon-butterfly/components/*": "./neon-butterfly/components/*.css",
31
- "./summer-cloud": "./summer-cloud/index.css",
32
- "./summer-cloud/tokens": "./summer-cloud/tokens.css",
33
- "./summer-cloud/base": "./summer-cloud/base.css",
34
- "./summer-cloud/components/*": "./summer-cloud/components/*.css",
35
- "./luminous-precision": "./luminous-precision/index.css",
36
- "./luminous-precision/tokens": "./luminous-precision/tokens.css",
37
- "./luminous-precision/base": "./luminous-precision/base.css",
38
- "./luminous-precision/components/*": "./luminous-precision/components/*.css"
31
+ "./neon-butterfly": {
32
+ "types": "./css.d.ts",
33
+ "default": "./neon-butterfly/index.css"
34
+ },
35
+ "./neon-butterfly/tokens": {
36
+ "types": "./css.d.ts",
37
+ "default": "./neon-butterfly/tokens.css"
38
+ },
39
+ "./neon-butterfly/base": {
40
+ "types": "./css.d.ts",
41
+ "default": "./neon-butterfly/base.css"
42
+ },
43
+ "./neon-butterfly/components/*": {
44
+ "types": "./css.d.ts",
45
+ "default": "./neon-butterfly/components/*.css"
46
+ },
47
+ "./summer-cloud": {
48
+ "types": "./css.d.ts",
49
+ "default": "./summer-cloud/index.css"
50
+ },
51
+ "./summer-cloud/tokens": {
52
+ "types": "./css.d.ts",
53
+ "default": "./summer-cloud/tokens.css"
54
+ },
55
+ "./summer-cloud/base": {
56
+ "types": "./css.d.ts",
57
+ "default": "./summer-cloud/base.css"
58
+ },
59
+ "./summer-cloud/components/*": {
60
+ "types": "./css.d.ts",
61
+ "default": "./summer-cloud/components/*.css"
62
+ },
63
+ "./luminous-precision": {
64
+ "types": "./css.d.ts",
65
+ "default": "./luminous-precision/index.css"
66
+ },
67
+ "./luminous-precision/tokens": {
68
+ "types": "./css.d.ts",
69
+ "default": "./luminous-precision/tokens.css"
70
+ },
71
+ "./luminous-precision/base": {
72
+ "types": "./css.d.ts",
73
+ "default": "./luminous-precision/base.css"
74
+ },
75
+ "./luminous-precision/components/*": {
76
+ "types": "./css.d.ts",
77
+ "default": "./luminous-precision/components/*.css"
78
+ }
79
+ },
80
+ "devDependencies": {
81
+ "typescript": "^5.7.0"
39
82
  }
40
83
  }
@@ -35,8 +35,12 @@
35
35
 
36
36
  /* Opt-in page background: the sky gradient. Flat --ld-bg is also correct, but
37
37
  * the gradient is the signature — the theme reads as "airy" only against it.
38
- * Apply to <body>, or to the attributed container itself. */
39
- :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-bg {
38
+ * Apply to <body>, or to the attributed container itself. An app shell
39
+ * (.ld-shell) always paints it, and so does the <body> around one, so the
40
+ * page stays covered past the shell (overscroll, short pages). */
41
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-bg,
42
+ :where(html[data-ld-style="summer-cloud"]) body:has(.ld-shell),
43
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-shell {
40
44
  background: linear-gradient(135deg, var(--ld-sky-start) 0%, var(--ld-sky-end) 100%);
41
45
  background-attachment: fixed;
42
46
  }
@@ -21,6 +21,32 @@
21
21
  :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-badge--warning { background: var(--ld-warning); border-color: transparent; color: #241a00; }
22
22
  :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-badge--danger { background: var(--ld-danger); border-color: transparent; color: #4a0000; }
23
23
 
24
+ /* Compact size — dashboard pills inside .ld-status-card__meta and row trails. */
25
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-badge--sm {
26
+ padding: 0.125rem 0.375rem;
27
+ gap: 2px;
28
+ font-size: 9px;
29
+ letter-spacing: 0.06em;
30
+ }
31
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-badge[href] { text-decoration: none; }
32
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-badge[href]:hover { filter: brightness(1.1); }
33
+
34
+ /* Pulse — the one solid, glowing call to action (work is waiting on you). */
35
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-badge--pulse {
36
+ background: var(--ld-warning);
37
+ border-color: transparent;
38
+ color: #241a00;
39
+ box-shadow: 0 0 8px color-mix(in srgb, var(--ld-warning) 60%, transparent);
40
+ animation: ld-sc-badge-pulse 2s ease-in-out infinite;
41
+ }
42
+ @keyframes ld-sc-badge-pulse {
43
+ 0%, 100% { box-shadow: 0 0 6px color-mix(in srgb, var(--ld-warning) 50%, transparent); }
44
+ 50% { box-shadow: 0 0 16px color-mix(in srgb, var(--ld-warning) 90%, transparent); }
45
+ }
46
+ @media (prefers-reduced-motion: reduce) {
47
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-badge--pulse { animation: none; }
48
+ }
49
+
24
50
  /* Chip — the filter variant: outlined until selected. */
25
51
  :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-chip {
26
52
  display: inline-flex;
@@ -0,0 +1,131 @@
1
+ /* summer-cloud — button group: a long glass pill; segments are pills inside
2
+ * it and the pressed one floats up as a white chip with violet text. */
3
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group {
4
+ display: inline-flex;
5
+ align-items: stretch;
6
+ gap: var(--ld-space-1);
7
+ max-width: 100%;
8
+ padding: var(--ld-space-1);
9
+ background: rgba(255, 255, 255, 0.4);
10
+ border: 1px solid var(--ld-border);
11
+ border-radius: var(--ld-radius-pill);
12
+ }
13
+ /* --block: fill the row, equal-width segments */
14
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group--block {
15
+ display: flex;
16
+ }
17
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group--block > .ld-btn {
18
+ flex: 1 1 0;
19
+ }
20
+
21
+ /* segments: the pill is the chrome, so the button drops its own */
22
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn {
23
+ padding-block: var(--ld-space-2);
24
+ background: transparent;
25
+ border-color: transparent;
26
+ box-shadow: none;
27
+ color: var(--ld-faint);
28
+ font-weight: var(--ld-font-weight-medium);
29
+ white-space: nowrap;
30
+ }
31
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--sm {
32
+ padding-block: 0.25rem;
33
+ }
34
+ /* variants tint the label only — a solid fill would break the pill */
35
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--primary {
36
+ color: var(--ld-primary);
37
+ }
38
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--accent {
39
+ color: var(--ld-accent-deep);
40
+ }
41
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--danger {
42
+ color: var(--ld-danger-deep);
43
+ }
44
+ /* no hover scale inside the pill — neighbours would overlap; the press stays */
45
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn:hover,
46
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn:focus-visible {
47
+ background: var(--ld-sky-tint);
48
+ border-color: transparent;
49
+ box-shadow: none;
50
+ color: var(--ld-primary);
51
+ transform: none;
52
+ }
53
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--accent:hover,
54
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--accent:focus-visible {
55
+ color: var(--ld-accent-deep);
56
+ }
57
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--danger:hover,
58
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--danger:focus-visible {
59
+ color: var(--ld-danger-deep);
60
+ }
61
+
62
+ /* pressed segment (toggle / segmented use): the floating white chip */
63
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn--active,
64
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn[aria-pressed="true"] {
65
+ background: var(--ld-surface);
66
+ color: var(--ld-primary);
67
+ font-weight: var(--ld-font-weight-bold);
68
+ box-shadow: 0 2px 8px var(--ld-primary-border);
69
+ }
70
+ /* after the pressed rule so the focus ring survives on the pressed segment */
71
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn:focus-visible {
72
+ box-shadow: 0 0 0 4px var(--ld-accent-glow);
73
+ }
74
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn:active {
75
+ transform: scale(0.97);
76
+ }
77
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group > .ld-btn:disabled {
78
+ background: transparent;
79
+ color: var(--ld-faint);
80
+ transform: none;
81
+ }
82
+
83
+ /* Sliding pill: with exactly one pressed segment, its chrome moves to one
84
+ * chip on the track, pinned to the segment by anchor positioning, so a
85
+ * change of selection travels instead of blinking. Its inline edges transition
86
+ * separately — with data-ld-dir ("forward" | "back", set by ButtonGroup) the
87
+ * edge nearer the target leads and the far edge trails, stretching the pill
88
+ * across the gap; without it the pill just slides. Several pressed segments
89
+ * (multi-toggle), or no anchor positioning, keep the per-segment chrome above. */
90
+ @supports (anchor-name: --ld-a) and (anchor-scope: --ld-a) {
91
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group {
92
+ position: relative;
93
+ isolation: isolate;
94
+ anchor-scope: --ld-btn-group-active;
95
+ }
96
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group:not(:has(> :is(.ld-btn--active, .ld-btn[aria-pressed="true"]) ~ :is(.ld-btn--active, .ld-btn[aria-pressed="true"]))) > :is(.ld-btn--active, .ld-btn[aria-pressed="true"]) {
97
+ anchor-name: --ld-btn-group-active;
98
+ background: transparent;
99
+ box-shadow: none;
100
+ }
101
+ /* same weight as the rule above, so the focus ring survives on the pressed segment */
102
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group:not(:has(> :is(.ld-btn--active, .ld-btn[aria-pressed="true"]) ~ :is(.ld-btn--active, .ld-btn[aria-pressed="true"]))) > :is(.ld-btn--active, .ld-btn[aria-pressed="true"]):focus-visible {
103
+ box-shadow: 0 0 0 4px var(--ld-accent-glow);
104
+ }
105
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group:where(:has(> :is(.ld-btn--active, .ld-btn[aria-pressed="true"])):not(:has(> :is(.ld-btn--active, .ld-btn[aria-pressed="true"]) ~ :is(.ld-btn--active, .ld-btn[aria-pressed="true"]))))::before {
106
+ content: "";
107
+ position: absolute;
108
+ z-index: -1;
109
+ position-anchor: --ld-btn-group-active;
110
+ inset-block: anchor(top) anchor(bottom);
111
+ inset-inline: anchor(start) anchor(end);
112
+ background: var(--ld-surface);
113
+ border-radius: var(--ld-radius-pill);
114
+ box-shadow: 0 2px 8px var(--ld-primary-border);
115
+ pointer-events: none;
116
+ transition: inset-inline-start var(--ld-slide-lead), inset-inline-end var(--ld-slide-lead);
117
+ }
118
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group[data-ld-dir="forward"]::before {
119
+ transition: inset-inline-start var(--ld-slide-trail), inset-inline-end var(--ld-slide-lead);
120
+ }
121
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group[data-ld-dir="back"]::before {
122
+ transition: inset-inline-start var(--ld-slide-lead), inset-inline-end var(--ld-slide-trail);
123
+ }
124
+ }
125
+
126
+ @media (prefers-reduced-motion: reduce) {
127
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group::before,
128
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn-group[data-ld-dir]::before {
129
+ transition: none;
130
+ }
131
+ }
@@ -0,0 +1,132 @@
1
+ /* summer-cloud — hold-to-confirm button: violet ring on a bouncy glass pill
2
+ *
3
+ * Contract: .ld-btn--hold composes with .ld-btn and any variant. The consumer
4
+ * writes one number, --ld-hold in [0, 1]; the ring fill is pure CSS.
5
+ * data-ld-hold="holding" | "fired" carries the behavioural state.
6
+ */
7
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold {
8
+ --ld-hold: 0;
9
+ --ld-hold-color: var(--ld-on-surface); /* neutral on its own */
10
+ position: relative;
11
+ gap: var(--ld-space-3);
12
+ padding: var(--ld-space-2) var(--ld-space-3) var(--ld-space-2) var(--ld-space-2);
13
+ text-align: left;
14
+ user-select: none;
15
+ -webkit-user-select: none;
16
+ touch-action: none; /* a touch hold must not turn into a scroll */
17
+ }
18
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold.ld-btn--primary {
19
+ --ld-hold-color: var(--ld-primary);
20
+ }
21
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold.ld-btn--accent {
22
+ --ld-hold-color: var(--ld-accent);
23
+ }
24
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold.ld-btn--danger {
25
+ --ld-hold-color: var(--ld-primary);
26
+ }
27
+
28
+ /* On the hold composition the ring and hint carry the danger state, so the
29
+ * pill stays glass: a violet ring on the solid red CTA would fight it, and the
30
+ * ring track would vanish. Deep red text keeps the intent legible. */
31
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold.ld-btn--danger,
32
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold.ld-btn--danger:hover,
33
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold.ld-btn--danger:focus-visible {
34
+ background: rgba(255, 255, 255, 0.5);
35
+ border-color: var(--ld-outline);
36
+ color: var(--ld-danger-deep);
37
+ box-shadow: none;
38
+ }
39
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold.ld-btn--danger:focus-visible {
40
+ box-shadow: 0 0 0 4px var(--ld-accent-glow);
41
+ }
42
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold:active {
43
+ transform: none; /* the ring is the press feedback */
44
+ }
45
+
46
+ /* ring: the icon well, wrapped by a conic fill masked to a 3px stroke */
47
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn__ring {
48
+ position: relative;
49
+ display: inline-grid;
50
+ place-items: center;
51
+ flex: none;
52
+ width: 2.25rem;
53
+ height: 2.25rem;
54
+ border-radius: 50%;
55
+ background: var(--ld-surface-sunken);
56
+ color: var(--ld-hold-color);
57
+ }
58
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn__ring::before {
59
+ content: "";
60
+ position: absolute;
61
+ inset: 0;
62
+ border-radius: 50%;
63
+ background: conic-gradient(var(--ld-hold-color) calc(var(--ld-hold) * 360deg), var(--ld-outline) 0);
64
+ -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
65
+ mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
66
+ }
67
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn__ring > svg {
68
+ width: 1rem;
69
+ height: 1rem;
70
+ }
71
+
72
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn__body {
73
+ display: flex;
74
+ flex-direction: column;
75
+ align-items: flex-start;
76
+ gap: 0.125rem;
77
+ line-height: 1.2;
78
+ }
79
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn__label {
80
+ font-weight: var(--ld-font-weight-bold);
81
+ }
82
+ /* the hint and meter restate the ring, so state is never color-only */
83
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn__hint {
84
+ font-size: 11px;
85
+ font-weight: var(--ld-font-weight);
86
+ letter-spacing: normal;
87
+ text-transform: none;
88
+ color: var(--ld-faint);
89
+ }
90
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn__meter {
91
+ margin-left: auto;
92
+ min-width: 3.5ch;
93
+ text-align: right;
94
+ font-family: var(--ld-font-mono);
95
+ font-variant-numeric: tabular-nums;
96
+ font-size: 12px;
97
+ color: var(--ld-faint);
98
+ }
99
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold[data-ld-hold="holding"] .ld-btn__meter {
100
+ color: var(--ld-hold-color);
101
+ }
102
+
103
+ /* fired: the post-commit flash */
104
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold[data-ld-hold="fired"] {
105
+ animation: ld-sc-hold-fired 0.5s var(--ld-ease-bounce);
106
+ }
107
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold[data-ld-hold="fired"] .ld-btn__ring {
108
+ box-shadow: 0 0 16px color-mix(in srgb, var(--ld-hold-color) 55%, transparent);
109
+ }
110
+ @keyframes ld-sc-hold-fired {
111
+ 0% {
112
+ transform: scale(1);
113
+ }
114
+ 40% {
115
+ transform: scale(1.06);
116
+ }
117
+ 100% {
118
+ transform: scale(1);
119
+ }
120
+ }
121
+
122
+ /* reduced motion: the ring still fills (it is the state, not decoration);
123
+ * only the flash and glow go */
124
+ @media (prefers-reduced-motion: reduce) {
125
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold[data-ld-hold="fired"] {
126
+ animation: none;
127
+ box-shadow: none;
128
+ }
129
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-btn--hold[data-ld-hold="fired"] .ld-btn__ring {
130
+ box-shadow: none;
131
+ }
132
+ }
@@ -0,0 +1,76 @@
1
+ /* summer-cloud — icon button: round chromeless pill that fills sky-white and bounces on hover.
2
+ * Icon-only control (<button> or <a>): give it an accessible name (aria-label).
3
+ * Active/current: .ld-icon-btn--active, [aria-pressed="true"], [aria-current="page"]. */
4
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn {
5
+ display: inline-flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ flex: none;
9
+ width: 2rem;
10
+ height: 2rem;
11
+ padding: 0;
12
+ background: none;
13
+ border: none;
14
+ border-radius: var(--ld-radius-pill);
15
+ color: var(--ld-faint);
16
+ font: inherit;
17
+ line-height: 1;
18
+ text-decoration: none;
19
+ cursor: pointer;
20
+ transition: background var(--ld-transition), color var(--ld-transition), box-shadow 0.2s ease, transform 0.2s var(--ld-ease-bounce);
21
+ }
22
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn > svg {
23
+ width: 1.25em;
24
+ height: 1.25em;
25
+ flex: none;
26
+ }
27
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:hover,
28
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:focus-visible {
29
+ background: var(--ld-sky-tint);
30
+ color: var(--ld-primary);
31
+ transform: scale(1.06);
32
+ outline: none;
33
+ }
34
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:focus-visible {
35
+ box-shadow: 0 0 0 4px var(--ld-accent-glow);
36
+ }
37
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:active:not(:disabled) {
38
+ transform: scale(0.92);
39
+ }
40
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn--active,
41
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn[aria-pressed="true"],
42
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn[aria-current="page"] {
43
+ background: var(--ld-sky-tint);
44
+ color: var(--ld-primary);
45
+ }
46
+
47
+ /* danger: destructive action (delete, remove) — faint at rest, red on hover */
48
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn--danger:hover,
49
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn--danger:focus-visible {
50
+ color: var(--ld-danger-deep);
51
+ }
52
+
53
+ /* disabled: dimmed and inert — hover never lights it; [aria-disabled] covers <a> */
54
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:disabled,
55
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn[aria-disabled="true"] {
56
+ opacity: 0.4;
57
+ color: var(--ld-faint);
58
+ background: none;
59
+ box-shadow: none;
60
+ transform: none;
61
+ cursor: not-allowed;
62
+ }
63
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn[aria-disabled="true"] {
64
+ pointer-events: none;
65
+ }
66
+
67
+ @media (prefers-reduced-motion: reduce) {
68
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn {
69
+ transition: none;
70
+ }
71
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:hover,
72
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:focus-visible,
73
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-icon-btn:active:not(:disabled) {
74
+ transform: none;
75
+ }
76
+ }