@stnd/styles 0.5.2 → 0.5.4

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.
@@ -1,5 +1,27 @@
1
1
  @use "standard-00-variables" as *;
2
2
 
3
+ /**
4
+ * @component Rhythm
5
+ * @category Layout
6
+ * @description Vertical rhythm for any container: apply `.rhythm` and its
7
+ * children get consistent `margin-block-start` spacing with no per-element
8
+ * classes, heavier before headings and around block-level elements
9
+ * (tables, blockquotes, figures — the tags this cascades to are declared
10
+ * once in `_standard-00-variables.scss`, not here). `.flex > *` is zeroed
11
+ * out automatically so rhythm margins never stack with flex `gap`.
12
+ *
13
+ * @property .rhythm The container class. Sets `display: flow-root` so child margins cannot collapse out of it.
14
+ * @property .no-rhythm Zeroes `margin-block-start` on every descendant — a subtree-wide rhythm opt-out.
15
+ * @property --gap-multiplicator Rhythm multiplier factor for block-level spacing and heading exceptions.
16
+ * @property .flex > * Zeroes `margin-block-start` for flex children so margins do not stack with flex gap.
17
+ *
18
+ * @example html - Turn any container into a rhythm block
19
+ * <article class="rhythm">
20
+ * <h2>Heading</h2>
21
+ * <p>Spaced automatically — no margin utility classes needed.</p>
22
+ * </article>
23
+ */
24
+
3
25
  /* ===== BULLETPROOF RHYTHM SYSTEM ===== */
4
26
  /* Applied to any container — cascades to children via margin-block-start */
5
27
 
@@ -40,13 +62,13 @@
40
62
  //*
41
63
  > :where(:is(#{$rhythm-tags})) ~ :where(:is(h1, h2)) {
42
64
  margin-block-start: calc(
43
- var(--gap) * calc(var(--gap-multiplicator, 2) + 3)
65
+ var(--gap) * calc(var(--gap-multiplicator, 2) + 2)
44
66
  );
45
67
  }
46
68
 
47
69
  > :where(:is(#{$rhythm-tags})) ~ :where(:is(h3, h4, h5, h6)) {
48
70
  margin-block-start: calc(
49
- var(--gap) * calc(var(--gap-multiplicator, 2) + 2)
71
+ var(--gap) * calc(var(--gap-multiplicator, 2) + 1)
50
72
  );
51
73
  }
52
74
 
@@ -8,16 +8,20 @@
8
8
  * responsive content columns for sidebars, accents, and featured content.
9
9
  * Inspired by fine-art typography and classical book design principles.
10
10
  *
11
- * @prop {class} .prose Main article/content container for readable prose
12
- * @prop {class} .small Narrow sidebar width container
13
- * @prop {class} .accent Accent container with background color
14
- * @prop {class} .feature Featured content with larger spacing
15
- * @prop {class} .hero Full-width container
16
- * @prop {variable} --line-width-xs Extra small (24rem / 384px)
17
- * @prop {variable} --line-width-sm Small (32rem / 512px)
18
- * @prop {variable} --line-width-md Medium (42rem / 672px) - default
19
- * @prop {variable} --line-width-lg Large (50rem / 800px)
20
- * @prop {variable} --line-width-xl Extra large (60rem / 960px)
11
+ * @property .prose Main article/content grid container for readable prose with named tracks.
12
+ * @property .prose.left Left-aligned prose variant hugging the left edge.
13
+ * @property .small Narrow sidebar breakout column track.
14
+ * @property .editorial Editorial column breakout track (`minmax(0, var(--space-2))`).
15
+ * @property .feature Feature callout breakout track (`minmax(0, var(--space-4))`).
16
+ * @property .hero Full-bleed viewport width hero track (`minmax(0, 1fr)`).
17
+ * @property .full Full viewport width breakout track.
18
+ * @property --line-width Active reading column measure.
19
+ * @property --line-width-xs Extra small reading measure (24rem / 384px).
20
+ * @property --line-width-sm Small reading measure (32rem / 512px).
21
+ * @property --line-width-md Medium reading measure (42rem / 672px) - default.
22
+ * @property --line-width-lg Large reading measure (50rem / 800px).
23
+ * @property --line-width-xl Extra large reading measure (60rem / 960px).
24
+ * @property --body-max-width Overall page max-width constraint (900px).
21
25
  *
22
26
  * @example
23
27
  * // Standard article with proper reading width
@@ -136,28 +140,6 @@
136
140
  }
137
141
  }
138
142
 
139
- /* =========================== */
140
- /* TYPOGRAPHIC NUANCES */
141
- /* =========================== */
142
- .video-container {
143
- position: relative;
144
- padding-bottom: 56.25%;
145
- /* 16:9 aspect ratio */
146
- height: 0;
147
- overflow: hidden;
148
- border-radius: var(--radius);
149
- box-shadow: var(--shadow-raised);
150
-
151
- iframe {
152
- position: absolute;
153
- top: 0;
154
- left: 0;
155
- width: 100%;
156
- height: 100%;
157
- border: 0;
158
- }
159
- }
160
-
161
143
  /* Image gallery layout */
162
144
  &:not(.no-grid) {
163
145
  p:has(img),
@@ -1,5 +1,23 @@
1
1
  @use "standard-00-variables" as *;
2
2
 
3
+ /**
4
+ * @component Base
5
+ * @category Foundation
6
+ * @description Document root and page chrome, zero classes required: html
7
+ * typography and font features, body padding/max-width/centering, a
8
+ * global reading-measure cap applied to text elements site-wide (not just
9
+ * inside `.prose`), theme-transition rules, and selection/mark highlights.
10
+ *
11
+ * @property html Root element establishing background color, foreground text color, font smoothing, and smooth scrolling.
12
+ * @property body Document container centered at `--body-max-width` with responsive padding and scroll margins.
13
+ * @property .no-body-margin Full-bleed helper applied to `<header>` or `<footer>` to extend edge-to-edge past body padding.
14
+ * @property .container-hero Hero section container with vertical padding and hairline borders.
15
+ * @property ::selection Custom highlight selection using subtle yellow background tint and accent text color.
16
+ *
17
+ * @example html - Full-bleed footer inside a normally-padded body
18
+ * <footer class="no-body-margin">Full-width footer content</footer>
19
+ */
20
+
3
21
  /* =========================== */
4
22
  /* BASE (HTML ROOT) */
5
23
  /* =========================== */
@@ -127,24 +145,12 @@ hr {
127
145
  block-size: var(--stroke-width, 1px);
128
146
  }
129
147
 
130
- /* Mark highlighting */
131
- mark {
132
- background: oklch(from var(--color-yellow) l c h / 0.3);
133
- color: color-mix(in oklch, var(--color-yellow) 30%, var(--color-foreground));
134
- padding: var(--trim);
135
- padding-top: 0.1em;
136
- }
137
-
138
148
  /* =========================== */
139
149
  /* LAYOUT */
140
150
  /* =========================== */
141
151
 
142
152
  section.container-hero {
143
153
  padding-block: var(--space-2);
144
- /* --border currently resolves to `none` — see the AUDIT FLAG in
145
- _standard-02-color.scss (duplicate --border declaration, "0 solid
146
- transparent" then "none" wins). This section's top/bottom border is
147
- invisible today as a result — real-world impact of that flag. */
148
154
  border-top: var(--border);
149
155
  border-bottom: var(--border);
150
156
  box-shadow: var(--shadow);
@@ -169,37 +175,23 @@ dt {
169
175
  /* BODY PADDING NEGATION */
170
176
  /* =========================== */
171
177
 
172
- /**
173
- * AUDIT NOTE (2026-07-14): this docblock previously described a
174
- * .negate-body-padding / .negate-body-padding-full / .negate-body-padding-bottom
175
- * API — those class names don't exist anywhere in this file or the
176
- * codebase (grepped), never did as far as git history in this session
177
- * shows. The real, implemented class is .no-body-margin, and it's far
178
- * narrower than "footers, headers, or other elements" implied: it only
179
- * matches <footer>/<header> that are DIRECT children of <body> AND the
180
- * first/last element of that type (body > footer.no-body-margin:last-of-type
181
- * / body > header.no-body-margin:first-of-type). Neither the old
182
- * (fictional) nor the real class name is used anywhere in apps/ today —
183
- * corrected the docs to match reality rather than delete the utility.
184
- *
185
- * Utilities to negate body padding for a direct-child header/footer that
186
- * should extend to the viewport edges.
187
- *
188
- * .no-body-margin — on a <footer> or <header> that is a direct child of
189
- * <body> and the last/first element of its type, respectively. Negates
190
- * horizontal body padding (both variants); the footer variant also
191
- * negates the extra 1.5× bottom padding, the header variant the top.
192
- *
193
- * Usage:
194
- * <footer class="no-body-margin">
195
- * Full-width footer content
196
- * </footer>
197
- */
198
-
199
- /**
200
- * Negate horizontal body padding (left/right)
201
- * Allows full-width backgrounds while keeping vertical padding
202
- */
178
+ /* AUDIT NOTE (2026-07-14): this doc previously described a
179
+ .negate-body-padding / .negate-body-padding-full / .negate-body-padding-bottom
180
+ API — those class names don't exist anywhere in this file or the
181
+ codebase (grepped), never did as far as git history in this session
182
+ shows. The real, implemented class is .no-body-margin, and it's far
183
+ narrower than "footers, headers, or other elements" implied: it only
184
+ matches <footer>/<header> that are DIRECT children of <body> AND the
185
+ first/last element of that type. Neither the old (fictional) nor the
186
+ real class name is used anywhere in apps/ today — corrected the docs
187
+ to match reality rather than delete the utility. Moved into the
188
+ @component block above so its example HTML sits inside a fenced
189
+ @example instead of bare in a comment — the previous version was
190
+ valid enough HTML that it would have rendered live on the docs page,
191
+ not shown as a code sample. */
192
+
193
+ /* Negate horizontal body padding (left/right) — allows full-width
194
+ backgrounds while keeping vertical padding. */
203
195
 
204
196
  body > footer.no-body-margin:last-of-type,
205
197
  body > header.no-body-margin:first-of-type {
@@ -211,11 +203,9 @@ body > header.no-body-margin:first-of-type {
211
203
  }
212
204
  }
213
205
 
214
- /**
215
- * Negate bottom body padding (extra 1.5× multiplier)
216
- * Removes the generous bottom padding applied to body elements
217
- * Useful when you want footer to sit flush at bottom
218
- */
206
+ /* Negate bottom body padding (extra 1.5× multiplier) — removes the
207
+ generous bottom padding applied to body elements, for a footer that
208
+ should sit flush at the bottom. */
219
209
  body > footer.no-body-margin:last-of-type {
220
210
  margin-block-end: calc(var(--gap-body) * -1.5);
221
211
 
@@ -1,19 +1,26 @@
1
1
  @use "standard-00-variables" as *;
2
2
 
3
- /* =========================== */
4
- /* MEDIA */
5
- /* =========================== */
3
+ /**
4
+ * @component Media & Embeds
5
+ * @category Content
6
+ * @description Responsive media containers for images, native video, audio players,
7
+ * and iframes. Applies theme borders, elevation shadows, and rounded corners by default.
8
+ *
9
+ * @property img Responsive image with theme radius and raised surface shadow.
10
+ * @property video Native video element with border and elevation.
11
+ * @property .video-container Responsive 16:9 media embed container for videos and iframes.
12
+ * @property .stnd-icon Icon container unsetting default media borders and shadows to inherit currentColor.
13
+ * @property figure Grid container for media and associated captions.
14
+ * @property figcaption Centered italic caption text for figures.
15
+ * @property img.fx Image explicitly styled with theme border and radius.
16
+ * @property img.nofx Image stripping borders, shadows, and radii.
17
+ */
6
18
 
7
- /* --border currently resolves to `none` everywhere it's used in this file
8
- (3 places) — see the AUDIT FLAG in _standard-02-color.scss (duplicate
9
- --border declaration; the "none" copy wins). Media elements here get no
10
- visible border as a result. */
11
19
  img,
12
20
  video,
13
21
  audio,
14
22
  iframe,
15
- .video,
16
- .video-container {
23
+ .video {
17
24
  max-width: 100%;
18
25
  border-radius: var(--radius);
19
26
  box-shadow: var(--shadow-raised);
@@ -23,33 +30,26 @@ iframe,
23
30
  }
24
31
 
25
32
  /* =========================== */
26
- /* TYPOGRAPHIC NUANCES */
33
+ /* VIDEO EMBEDS */
27
34
  /* =========================== */
28
- .video-container:has(video) {
35
+ .video-container {
29
36
  position: relative;
30
- /* Unlike the iframe variant in _standard-06-prose.scss, this one holds a
31
- native <video> element, which has real intrinsic dimensions — the
32
- legacy padding-bottom:56.25% aspect-ratio hack (disabled below) isn't
33
- needed the way it is for iframes. */
34
- /* padding-bottom: 56.25% — 16:9 aspect ratio, disabled, see above */
35
- border: none;
36
- box-shadow: none;
37
+ aspect-ratio: 16 / 9;
38
+ width: 100%;
39
+ max-width: 100%;
37
40
  overflow: hidden;
38
- background: transparent;
41
+ border-radius: var(--radius);
42
+ box-shadow: var(--shadow-raised);
43
+ border: var(--border);
44
+ background: var(--color-surface);
39
45
 
46
+ iframe,
40
47
  video {
41
- border-radius: var(--radius);
42
- border: var(--border);
43
- box-shadow: var(--shadow-raised);
44
- }
45
-
46
- iframe {
47
- position: absolute;
48
- top: 0;
49
- left: 0;
50
48
  width: 100%;
51
49
  height: 100%;
52
50
  border: 0;
51
+ display: block;
52
+ object-fit: cover;
53
53
  }
54
54
  }
55
55
 
@@ -84,12 +84,17 @@ figcaption {
84
84
  }
85
85
 
86
86
  /**
87
- * @component Image System
87
+ * @component Image Zoom & Lightbox
88
+ * @category Content
88
89
  * @description Responsive image handling with interactive zoom functionality.
89
- * This system is progressively enhanced. Without JavaScript, it provides a
90
- * basic zoom-on-click-and-hold. With JavaScript, it provides a full
91
- * feature-rich lightbox experience.
90
+ * Progressively enhanced: without JavaScript, provides click-and-hold zoom.
91
+ * With JavaScript, provides a full frosted-glass lightbox experience.
92
92
  *
93
+ * @property html:not(.js-image-zoom-enabled) img:active Fallback CSS-only zoom on click-and-hold.
94
+ * @property .image-zoom-overlay Fullscreen glassmorphic lightbox overlay created dynamically by JS.
95
+ * @property .image-zoom-overlay.is-visible Active visible state for the lightbox overlay.
96
+ * @property html.image-zoomed-active Body scroll lock class applied when lightbox is active.
97
+ * @property [data-no-zoom] Attribute to prevent zoom interaction on icons or avatars.
93
98
  * @since 0.1.0
94
99
  */
95
100
 
@@ -1,5 +1,26 @@
1
1
  @use "standard-00-variables" as *;
2
2
 
3
+ /**
4
+ * @component Lists
5
+ * @category Content
6
+ * @description Replaces native `<ul>`/`<ol>` markers with custom
7
+ * absolutely-positioned bullets and tabular-nums counters, and spaces items
8
+ * apart via `li + li`. Four density/marker classes are opt-in.
9
+ *
10
+ * @property .no-bullet Hides markers and removes inline padding; cascades to nested lists.
11
+ * @property .tight Tightens list item vertical spacing to `--space-d3`.
12
+ * @property .compact Tightens list item vertical spacing to `--space-d2`.
13
+ * @property .relaxed Widens list item vertical spacing to `--space-2`.
14
+ * @property .task-list-item Applied to task list items (`- [ ]`), displaying interactive or static checkbox.
15
+ * @property .task-field Inline badge representation for Dataview-style `[key:: value]` metadata.
16
+ *
17
+ * @example html - What `- [ ] Ship it [priority:: 1]` becomes
18
+ * <li class="task-list-item">
19
+ * <input type="checkbox" disabled> Ship it
20
+ * <span class="task-field" data-field="priority">priority: 1</span>
21
+ * </li>
22
+ */
23
+
3
24
  /* =========================== */
4
25
  /* LISTS */
5
26
  /* =========================== */
@@ -13,7 +34,7 @@ ol {
13
34
  /* Nested lists */
14
35
  li > ul,
15
36
  li > ol {
16
- padding-inline-start: var(--space);
37
+ padding-inline: var(--space);
17
38
  margin-block-start: var(--space-d2);
18
39
  margin-block-end: 0;
19
40
  }
@@ -26,7 +47,7 @@ li {
26
47
  }
27
48
 
28
49
  li + li {
29
- margin-block-start: var(--space);
50
+ margin-block-start: var(--space-d2);
30
51
  }
31
52
 
32
53
  /* Unordered list bullets */
@@ -83,32 +104,55 @@ ol:where(.flex, [style*="display: flex"], [style*="display:flex"]) li {
83
104
  }
84
105
  }
85
106
 
86
- /* AUDIT FLAG (2026-07-14): .compact and .relaxed are bare, unnamespaced
87
- class names also defined in _standard-50-utilities.scss (different
88
- rules) and — for .compact/.relaxed specifically — in
89
- _standard-04-grid.scss as .grid.compact/.grid.relaxed (qualified, so
90
- that one doesn't collide). An element with class="compact" containing
91
- <li> children gets BOTH this file's li+li spacing AND whatever
92
- _standard-50-utilities.scss's .compact does, unconditionally — no way
93
- to opt into one without the other. Flagging the collision rather than
94
- renaming; not obvious which file should own the name. (The dead
95
- --base-gap sub-issue previously flagged here has been cleaned up: the
96
- declarations were removed from this file and from
97
- _standard-50-utilities.scss.) */
98
- .compact {
99
- li + li {
100
- margin-block-start: var(--space-d2);
101
- }
107
+ /* FIXED (2026-09-05) — was a bare, unnamespaced .compact/.relaxed that
108
+ collided with _standard-50-utilities.scss's line-height utilities of the
109
+ same name: any element with class="compact" containing <li> children got
110
+ this file's li+li spacing unconditionally, whether or not it was
111
+ actually a list. Qualified to :is(ul, ol) instead, matching the pattern
112
+ _standard-04-grid.scss already uses for its own .compact/.relaxed
113
+ (:is(.grid, [class^="grid-"]).compact) — same class name, each scope's
114
+ meaning applies only in its own context. A <ul class="compact"> now
115
+ picks up both this file's tight item spacing AND utilities.scss's
116
+ compact line-height, which is the combination you'd actually want. */
117
+ :is(ul, ol).compact li + li {
118
+ margin-block-start: var(--space-d2);
102
119
  }
103
120
 
104
- .tight {
105
- li {
106
- margin-block-end: var(--space-d3);
107
- }
121
+ :is(ul, ol).tight li {
122
+ margin-block-end: var(--space-d3);
123
+ }
124
+
125
+ :is(ul, ol).relaxed li {
126
+ margin-block-end: var(--space-2);
108
127
  }
109
128
 
110
- .relaxed {
111
- li {
112
- margin-block-end: var(--space-2);
129
+ /* =========================== */
130
+ /* TASK LISTS */
131
+ /* =========================== */
132
+
133
+ /* Rendered by @stnd/press's typography-tasks plugin from `- [ ]` / `- [x]` —
134
+ the checkbox replaces the bullet, it doesn't sit alongside it. */
135
+ .task-list-item {
136
+ &::before {
137
+ display: none;
138
+ }
139
+
140
+ input[type="checkbox"] {
141
+ margin-inline-end: var(--space-d3);
142
+ vertical-align: -0.15em;
143
+ accent-color: var(--color-accent);
113
144
  }
114
145
  }
146
+
147
+ /* Dataview-style `[key:: value]` inline fields, tagged by the same plugin. */
148
+ .task-field {
149
+ display: inline-block;
150
+ font-family: var(--font-monospace);
151
+ font-size: var(--size-3xs);
152
+ color: var(--color-subtle);
153
+ background: var(--color-surface);
154
+ border: var(--border);
155
+ border-radius: var(--radius-sm);
156
+ padding: 0 var(--space-d4);
157
+ margin-inline-end: var(--space-d6);
158
+ }
@@ -1,5 +1,30 @@
1
1
  @use "standard-00-variables" as *;
2
2
 
3
+ /**
4
+ * @component Tables
5
+ * @category Content
6
+ * @description A bare `<table>` gets full styling with no class required:
7
+ * collapsed borders, uppercase small-caps headers, compact cell padding.
8
+ * `.striped` and `.numeric` are the only two opt-in classes.
9
+ *
10
+ * @property table Zero-class collapsed table layout with hairline borders and compact padding.
11
+ * @property th Uppercase small-caps table header with surface background and subtle tracking.
12
+ * @property caption Bold caption element positioned above table with rhythm padding.
13
+ * @property .striped Zebra-stripes even `<tbody>` rows with a 3% foreground tint.
14
+ * @property .numeric Right-aligns content and switches on tabular-nums for numeric columns.
15
+ * @property .properties Table variant keeping leading identifier/token columns unwrapped.
16
+ *
17
+ * @example html - Bare table, zero classes
18
+ * <table>
19
+ * <thead>
20
+ * <tr><th>Name</th><th class="numeric">Count</th></tr>
21
+ * </thead>
22
+ * <tbody>
23
+ * <tr><td>Widgets</td><td class="numeric">42</td></tr>
24
+ * </tbody>
25
+ * </table>
26
+ */
27
+
3
28
  /* =========================== */
4
29
  /* TABLES */
5
30
  /* =========================== */
@@ -20,12 +45,11 @@ tr {
20
45
  th,
21
46
  td {
22
47
  text-align: left;
23
- /* --border currently resolves to `none` — see the AUDIT FLAG in
24
- _standard-02-color.scss (duplicate --border declaration). */
25
48
  border: var(--border);
26
49
  line-height: var(--line-height-compact);
27
50
  padding: var(--space-d2);
28
51
  font-size: var(--size-sm);
52
+ vertical-align: top;
29
53
  /* Fixed 2026-07-14 — was an invalid unitless min-height, now derives a
30
54
  real length from the line-height already set above. */
31
55
  min-height: calc(1em * var(--line-height-compact));
@@ -34,9 +58,12 @@ td {
34
58
  th {
35
59
  font-weight: var(--font-weight-bold, 600);
36
60
  transition: background var(--transition);
37
- background: var(--color-surface-low);
61
+ background: var(--color-surface);
38
62
  text-transform: uppercase;
39
- letter-spacing: 0.05em;
63
+ letter-spacing: 0.06em;
64
+ font-size: var(--size-3xs);
65
+ color: var(--color-muted);
66
+ vertical-align: middle;
40
67
  }
41
68
  caption {
42
69
  font-weight: var(--font-weight-bold, bold);
@@ -54,3 +81,17 @@ caption {
54
81
  .striped tbody tr:nth-child(even) {
55
82
  background: oklch(from var(--color-foreground) l c h / 0.03);
56
83
  }
84
+
85
+ /* Property & token dictionaries (prevents key column from wrapping) */
86
+ .properties {
87
+ th:not(:last-child),
88
+ td:not(:last-child) {
89
+ white-space: nowrap;
90
+ width: 1%;
91
+ }
92
+
93
+ th:last-child,
94
+ td:last-child {
95
+ width: 100%;
96
+ }
97
+ }
@@ -1,5 +1,35 @@
1
1
  @use "standard-00-variables" as *;
2
2
 
3
+ /**
4
+ * @component Forms
5
+ * @category Content
6
+ * @description Zero-class styling for every native form control:
7
+ * `fieldset`/`legend` layout, text inputs, textarea, a custom-drawn select,
8
+ * checkbox/radio, an ARIA switch variant, and a range slider — plus the
9
+ * adjacency rules that space form parts apart from each other and from
10
+ * whatever follows them.
11
+ *
12
+ * @property fieldset Container grouping form controls with hairline border, radius, and subtle surface background tint.
13
+ * @property legend Bold legend label nested within fieldset.
14
+ * @property input, textarea Zero-class text controls with interface typography, raised shadow, and accent focus rings.
15
+ * @property select Custom styled dropdown with double-chevron indicator and rhythm-aligned padding.
16
+ * @property input[role=switch] Accessible toggle switch with animated sliding thumb.
17
+ * @property --switch-height Primary height sizing knob for toggle switch controls.
18
+ * @property --switch-width Width sizing token for toggle switches (`calc(var(--switch-height) * 2)`).
19
+ * @property --switch-padding Inset padding controlling the toggle switch thumb gap (`2px`).
20
+ * @property --slider-value Percentage value driving custom filled range slider tracks.
21
+ *
22
+ * @example html - A switch (role=switch on a checkbox)
23
+ * <input type="checkbox" role="switch">
24
+ *
25
+ * @example html - Fieldset with adjacent button spacing
26
+ * <fieldset>
27
+ * <legend>Notifications</legend>
28
+ * <label><input type="checkbox"> Email me</label>
29
+ * </fieldset>
30
+ * <button>Save</button>
31
+ */
32
+
3
33
  /* =========================== */
4
34
  /* FORMS */
5
35
  /* =========================== */
@@ -49,8 +79,7 @@ textarea {
49
79
  border-radius: var(--radius-sm);
50
80
  color: var(--color-foreground);
51
81
  background: var(--color-surface);
52
- /* shadcn-style raised effect. --border currently resolves to `none` —
53
- see the AUDIT FLAG in _standard-02-color.scss. */
82
+ /* shadcn-style raised effect. */
54
83
  border: var(--border);
55
84
  box-shadow: var(--shadow-raised);
56
85
  /* Transparent outline at full width reserves the space a real focus
@@ -1,7 +1,88 @@
1
1
  @use "standard-00-variables" as *;
2
- /* Note: General color utilities (.text-muted, .text-subtle, .text-accent, .bg-surface, .border-*) */
3
- /* moved to _standard-50-utilities.scss for better layer organization (comment said
4
- "standard-98-utilities.scss" — that file doesn't exist, fixed the reference) */
2
+
3
+ /**
4
+ * @component Code Layout & Highlighting
5
+ * @category Content
6
+ * @description Code block container layout, copy buttons, and PrismJS syntax highlighting theme.
7
+ *
8
+ * @property .stnd-code-block Styled code block container with copy button and inset shadows.
9
+ * @property .copy-button Floating copy action button inside code blocks.
10
+ * @property pre Preformatted code block with compact leading and hover transitions.
11
+ * @property .token.keyword Keywords and control-flow statements (`--color-red`).
12
+ * @property .token.string Quoted strings and attribute values (`--color-green`).
13
+ * @property .token.number Numeric literals and boolean values (`--color-cyan`).
14
+ * @property .token.function Function declarations and method invocations (`--color-yellow`).
15
+ * @property .token.property Object keys and CSS property names (`--color-orange`).
16
+ * @property .token.punctuation Brackets, parens, delimiters, and operators (`--color-muted`).
17
+ * @property .token.comment Code comments rendered in muted italic typography (`--color-subtle`).
18
+ * @property .language-* Per-language syntax overrides for YAML, Markdown, Shell/Bash, and Nunjucks.
19
+ *
20
+ * @example html - Standard code block with copy button
21
+ * <div class="stnd-code-block">
22
+ * <button class="copy-button">Copy</button>
23
+ * <pre><code class="language-bash">npm install @stnd/core</code></pre>
24
+ * </div>
25
+ */
26
+
27
+ /* =========================== */
28
+ /* CODE BLOCK CONTAINER */
29
+ /* =========================== */
30
+
31
+ .stnd-code-block {
32
+ position: relative;
33
+ background: var(--color-surface);
34
+ border-radius: var(--radius-sm);
35
+ box-shadow: var(--shadow-inset), var(--shadow-ring);
36
+ transition: all var(--transition);
37
+
38
+ pre {
39
+ padding: var(--space);
40
+ background: transparent;
41
+ box-shadow: none;
42
+ border: none;
43
+ margin: var(--stroke-width);
44
+ overflow-x: auto;
45
+ position: static;
46
+ }
47
+
48
+ &:hover .copy-button {
49
+ opacity: 1;
50
+ }
51
+ }
52
+
53
+ .copy-button {
54
+ position: absolute;
55
+ top: var(--leading);
56
+ right: var(--leading);
57
+ opacity: 0;
58
+
59
+ &:hover {
60
+ opacity: 1 !important;
61
+ color: var(--color-on-accent);
62
+ background-color: var(--color-accent);
63
+ }
64
+
65
+ &.copied {
66
+ color: var(--color-success, #22c55e) !important;
67
+ }
68
+
69
+ &.failed {
70
+ color: var(--color-error, #ef4444) !important;
71
+ }
72
+ }
73
+
74
+ pre {
75
+ line-height: var(--line-height-compact);
76
+
77
+ code {
78
+ opacity: 0.85;
79
+ transition: opacity var(--transition);
80
+ }
81
+
82
+ &:hover code {
83
+ opacity: 1;
84
+ }
85
+ }
5
86
 
6
87
  /* PrismJS syntax highlighting - Language agnostic tokens */
7
88