creoui 0.20.1

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.
@@ -0,0 +1,3984 @@
1
+ /**
2
+ * creoui — components.css
3
+ *
4
+ * Generated: concat of packages/web/src/components/*.css.
5
+ * Requires tokens.css to be imported first (CSS variables).
6
+ *
7
+ * Bundled files: _density.css, _focus.css, _kinetic.css, accordion.css, alert.css, avatar.css, badge.css, breadcrumbs.css, button.css, card.css, combobox.css, container.css, dialog.css, divider.css, drawer.css, empty-state.css, error-boundary.css, form-controls.css, form-field.css, grid.css, header.css, icon.css, input.css, menu.css, pagination.css, popover.css, progress.css, segmented.css, skeleton.css, stack.css, stepper.css, table.css, tabs.css, timeline.css, toast.css, tooltip.css
8
+ */
9
+
10
+ /* ================ _density.css ================ */
11
+ /**
12
+ * Density mode — 4 mode (app/read/editor/terminal) と直交する density axis
13
+ *
14
+ * `data-density="comfortable" | "default" | "compact" | "cozy"` を ancestor
15
+ * (body / region / container) に articulate して、 内部 component の spacing
16
+ * scale を一括 control する。 4 mode (Typography mode) と直交し、 同じ mode
17
+ * でも density で「呼吸量」 を切替可能。
18
+ *
19
+ * Usage:
20
+ * <body data-density="compact"> <!-- dense interface (data table / dashboard) -->
21
+ * <div class="creo-card">...</div>
22
+ * </body>
23
+ *
24
+ * <article data-density="comfortable"> <!-- reading-friendly section -->
25
+ * ...
26
+ * </article>
27
+ *
28
+ * 各 component は `var(--density-padding-scale, 1)` 等を calc で参照、 default
29
+ * (1) で current の articulate に変化なし、 attribute がつくと scale 適用。
30
+ *
31
+ * Cascade order: filename `_density.css` の `_` prefix で sort 最優先 (build:web
32
+ * concat alphabetical sort で _focus → _density → 他 component)。 inheritance
33
+ * 経由なので nested でも適切に override (子 [data-density] が孫 component の
34
+ * scale を上書き)。
35
+ */
36
+
37
+ /* Default — base scale 1 (現状維持) */
38
+ :where(:root) {
39
+ --density-padding-scale: 1;
40
+ --density-gap-scale: 1;
41
+ --density-min-height-scale: 1;
42
+ }
43
+
44
+ [data-density="comfortable"] {
45
+ --density-padding-scale: 1.25;
46
+ --density-gap-scale: 1.25;
47
+ --density-min-height-scale: 1.1;
48
+ }
49
+
50
+ [data-density="default"] {
51
+ --density-padding-scale: 1;
52
+ --density-gap-scale: 1;
53
+ --density-min-height-scale: 1;
54
+ }
55
+
56
+ [data-density="compact"] {
57
+ --density-padding-scale: 0.85;
58
+ --density-gap-scale: 0.85;
59
+ --density-min-height-scale: 0.95;
60
+ }
61
+
62
+ [data-density="cozy"] {
63
+ --density-padding-scale: 0.7;
64
+ --density-gap-scale: 0.7;
65
+ --density-min-height-scale: 0.85;
66
+ }
67
+
68
+ /* ================ _focus.css ================ */
69
+ /**
70
+ * Focus ring policy — `:focus-visible` based keyboard-only focus indicator
71
+ *
72
+ * creoui design system の a11y baseline (WCAG 2.4.7 Focus Visible /
73
+ * 2.4.11 Focus Appearance) を満たす component-agnostic policy。
74
+ *
75
+ * Aesthetic direction: Sophisticated layered (Apple HIG visionOS 26 +
76
+ * Linear "気づかれない polish" の hybrid):
77
+ * - outer 2px solid brand ring (--focus-ring-width / --color-focus-ring-color)
78
+ * - inner 4px halo (box-shadow with --color-focus-ring-halo alpha 0.18-0.20)
79
+ * - offset 2px from element border (要素を遮らず ring が呼吸)
80
+ * - 8 theme で brand hue と整合 (light theme は luminance DOWN、 dark theme は UP)
81
+ *
82
+ * Behavior:
83
+ * - keyboard-only via :focus-visible (mouse focus は ring 出さない、 Radix-pattern)
84
+ * - prefers-reduced-motion: ring 自体は表示 (a11y 最優先)、 transition のみ無効化
85
+ *
86
+ * Cascade order: filename `_focus.css` の `_` prefix で sort 最優先 (build:web の
87
+ * concat order が alphabetical)。 各 component CSS が後から個別 :focus-visible
88
+ * を override するのは原則禁止 (a11y consistency)、 例外時はコメントで articulate。
89
+ */
90
+
91
+ :where(
92
+ .creo-btn,
93
+ .creo-input,
94
+ .creo-checkbox-input,
95
+ .creo-radio-input,
96
+ .creo-switch-input,
97
+ .creo-tabs-tab,
98
+ .creo-segmented-option input,
99
+ .creo-pagination-item,
100
+ .creo-breadcrumbs-link,
101
+ .creo-accordion-summary,
102
+ .creo-menu-item,
103
+ .creo-combobox-input,
104
+ .creo-form-field-label,
105
+ .creo-alert-close,
106
+ .creo-toast-close,
107
+ .creo-drawer-close,
108
+ .creo-dialog-close,
109
+ .creo-popover-close,
110
+ a
111
+ ):focus-visible {
112
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--color-focus-ring-color);
113
+ outline-offset: var(--focus-ring-offset);
114
+ box-shadow: 0 0 0 var(--focus-ring-halo-width) var(--color-focus-ring-halo);
115
+ }
116
+
117
+ /* Native popover (button[popovertarget]) の focus-visible も同 policy */
118
+ [popover]:focus-visible,
119
+ button[popovertarget]:focus-visible {
120
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--color-focus-ring-color);
121
+ outline-offset: var(--focus-ring-offset);
122
+ box-shadow: 0 0 0 var(--focus-ring-halo-width) var(--color-focus-ring-halo);
123
+ }
124
+
125
+ /* Reduced-motion: ring 自体は表示 (a11y 最優先)、 transition 無効化のみ */
126
+ @media (prefers-reduced-motion: reduce) {
127
+ :where(
128
+ .creo-btn,
129
+ .creo-input,
130
+ .creo-checkbox-input,
131
+ .creo-radio-input,
132
+ .creo-switch-input,
133
+ .creo-tabs-tab,
134
+ .creo-segmented-option input,
135
+ .creo-pagination-item,
136
+ .creo-breadcrumbs-link,
137
+ .creo-accordion-summary,
138
+ .creo-menu-item,
139
+ .creo-combobox-input,
140
+ .creo-form-field-label,
141
+ a
142
+ ):focus-visible {
143
+ transition: none;
144
+ }
145
+ }
146
+
147
+ /* ================ _kinetic.css ================ */
148
+ /**
149
+ * Kinetic typography — display 限定 dynamic font effects
150
+ *
151
+ * 2026 trend (Linear / Vercel Geist Pixel / Tailwind Catalyst で再評価) を
152
+ * creoui に articulate するが、 **read / editor mode は触らない**。
153
+ * long-form reading では typography stability が最優先、 kinetic effects は
154
+ * subjective fatigue を生む。 hero / display / onboarding の page-level
155
+ * visual anchor 限定。
156
+ *
157
+ * Aesthetic constraints (avoid path):
158
+ * - read mode 侵食禁止 (Purple Haze report の avoid path articulate)
159
+ * - reduced-motion 環境では無効化必須
160
+ * - font-variation-settings は variable font (Inter Variable / Roboto Flex /
161
+ * Recursive 等) 採用時のみ機能、 fallback で stable
162
+ *
163
+ * Cascade order: filename `_kinetic.css` の `_` prefix で sort 上位
164
+ * (focus / density の後)。 utility class なので consumer が opt-in で使う。
165
+ */
166
+
167
+ /* ---------- Hero kinetic (hover で letter-spacing / font-weight 動的) ---------- */
168
+
169
+ .creo-kinetic-hero {
170
+ font-family: var(--typography-family-display);
171
+ font-size: var(--typography-display-l);
172
+ font-weight: var(--typography-weight-bold);
173
+ letter-spacing: -0.02em;
174
+ line-height: var(--typography-line-height-tight);
175
+ /* Variable font 対応 (font-variation-settings、 non-variable fallback で無視) */
176
+ font-variation-settings: "wght" 700, "slnt" 0;
177
+ transition: letter-spacing var(--motion-mapping-frame-morph-duration)
178
+ var(--motion-mapping-frame-morph-easing), font-variation-settings
179
+ var(--motion-mapping-frame-morph-duration) var(--motion-mapping-frame-morph-easing);
180
+ }
181
+
182
+ .creo-kinetic-hero:hover {
183
+ letter-spacing: -0.01em; /* 詰めから少し開く */
184
+ font-variation-settings: "wght" 800, "slnt" -2;
185
+ }
186
+
187
+ /* ---------- Display gradient (hero text gradient effect) ---------- */
188
+
189
+ .creo-kinetic-gradient {
190
+ font-family: var(--typography-family-display);
191
+ font-size: var(--typography-display-l);
192
+ font-weight: var(--typography-weight-bold);
193
+ background: linear-gradient(
194
+ 135deg,
195
+ var(--color-brand-primary) 0%,
196
+ var(--color-brand-secondary) 100%
197
+ );
198
+ background-clip: text;
199
+ -webkit-background-clip: text;
200
+ color: transparent;
201
+ -webkit-text-fill-color: transparent;
202
+ }
203
+
204
+ /* ---------- Reveal animation (page load 時に staggered fade-in) ---------- */
205
+
206
+ .creo-kinetic-reveal {
207
+ opacity: 0;
208
+ transform: translateY(8px);
209
+ animation: creoKineticReveal var(--motion-mapping-modal-enter-duration)
210
+ var(--motion-mapping-modal-enter-easing) forwards;
211
+ }
212
+
213
+ .creo-kinetic-reveal[data-delay="1"] {
214
+ animation-delay: 80ms;
215
+ }
216
+ .creo-kinetic-reveal[data-delay="2"] {
217
+ animation-delay: 160ms;
218
+ }
219
+ .creo-kinetic-reveal[data-delay="3"] {
220
+ animation-delay: 240ms;
221
+ }
222
+
223
+ @keyframes creoKineticReveal {
224
+ to {
225
+ opacity: 1;
226
+ transform: translateY(0);
227
+ }
228
+ }
229
+
230
+ /* ---------- Reduced-motion (a11y baseline) ---------- */
231
+
232
+ @media (prefers-reduced-motion: reduce) {
233
+ .creo-kinetic-hero,
234
+ .creo-kinetic-hero:hover {
235
+ transition: none;
236
+ letter-spacing: -0.02em;
237
+ font-variation-settings: "wght" 700, "slnt" 0;
238
+ }
239
+
240
+ .creo-kinetic-reveal {
241
+ opacity: 1;
242
+ transform: none;
243
+ animation: none;
244
+ }
245
+ }
246
+
247
+ /* ================ accordion.css ================ */
248
+ /**
249
+ * creoui — Accordion / Disclosure (native details/summary)
250
+ *
251
+ * ARIA / keyboard は browser native に任せる。CSS のみで styling + chevron rotate。
252
+ *
253
+ * Spec: docs/components/accordion.md
254
+ * Token: creoui/tokens.css (必須)
255
+ */
256
+
257
+ .creo-accordion {
258
+ display: block;
259
+ margin-bottom: var(--spacing-s);
260
+ }
261
+
262
+ /* bordered variant (default に見た目を与える) */
263
+ .creo-accordion[data-variant="bordered"],
264
+ .creo-accordion:not([data-variant]) {
265
+ background-color: var(--color-surface-surface);
266
+ border: 1px solid var(--color-surface-border);
267
+ border-radius: var(--radius-s);
268
+ padding: 0;
269
+ overflow: hidden;
270
+ }
271
+
272
+ .creo-accordion[data-variant="subtle"] {
273
+ background-color: var(--color-surface-bg-subtle);
274
+ border: none;
275
+ border-radius: var(--radius-s);
276
+ }
277
+
278
+ /* ---------- Summary (clickable header) ---------- */
279
+
280
+ .creo-accordion-summary {
281
+ display: flex;
282
+ align-items: center;
283
+ gap: var(--layout-gap-tight);
284
+ /* tight padding: dashboard 系で 5+ stack した時の縦窮屈さを抑える。
285
+ min-height (target-tap=44px) は desktop では過剰なので削除、 content 高さに従う。 */
286
+ padding: var(--spacing-xs) var(--spacing-s);
287
+ cursor: pointer;
288
+ user-select: none;
289
+ list-style: none; /* default chevron を消す */
290
+ transition: background-color var(--motion-mapping-hover-duration)
291
+ var(--motion-mapping-hover-easing);
292
+ }
293
+
294
+ /* Safari / Firefox の default marker を完全に消す */
295
+ .creo-accordion-summary::-webkit-details-marker {
296
+ display: none;
297
+ }
298
+ .creo-accordion-summary::marker {
299
+ display: none;
300
+ }
301
+
302
+ .creo-accordion-summary:hover {
303
+ background-color: var(--color-surface-bg-subtle);
304
+ }
305
+
306
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
307
+
308
+ /* Chevron (自前で挿入)
309
+ * - 細身の `›` (U+203A) でモダン、 ▸ より sharper な視覚
310
+ * - order: 99 + margin-left: auto で flex 末尾 = card 右端に配置
311
+ * (dashboard / Disclosure の慣習: 左 chevron は file tree、 右 chevron は state toggle)
312
+ * - color tertiary で薄め、 size md で視認性 */
313
+ .creo-accordion-summary::before {
314
+ content: "›";
315
+ display: inline-block;
316
+ flex-shrink: 0;
317
+ order: 99;
318
+ margin-left: auto;
319
+ color: var(--color-text-tertiary);
320
+ transform: rotate(0deg);
321
+ transition: transform var(--motion-mapping-toggle-duration) var(--motion-mapping-toggle-easing);
322
+ font-size: var(--typography-size-m);
323
+ line-height: 1;
324
+ }
325
+
326
+ .creo-accordion[open] .creo-accordion-summary::before {
327
+ transform: rotate(90deg);
328
+ }
329
+
330
+ /* ---------- Title ---------- */
331
+
332
+ .creo-accordion-title {
333
+ flex: 1;
334
+ font-size: var(--typography-size-m);
335
+ font-weight: var(--typography-weight-medium);
336
+ color: var(--color-text-primary);
337
+ min-width: 0;
338
+ }
339
+
340
+ /* ---------- Content (expanded body) ---------- */
341
+
342
+ .creo-accordion-content {
343
+ padding: var(--spacing-s) var(--spacing-m) var(--spacing-m);
344
+ font-size: var(--typography-size-m);
345
+ color: var(--color-text-primary);
346
+ line-height: var(--typography-line-height-normal);
347
+ }
348
+
349
+ .creo-accordion-content > * + * {
350
+ margin-top: var(--spacing-s);
351
+ }
352
+
353
+ /* ---------- Reduced motion ---------- */
354
+
355
+ @media (prefers-reduced-motion: reduce) {
356
+ .creo-accordion-summary::before {
357
+ transition: none;
358
+ }
359
+ }
360
+
361
+ /* ================ alert.css ================ */
362
+ /**
363
+ * creoui — Alert (inline persistent status)
364
+ *
365
+ * Spec: docs/components/alert.md
366
+ * Token: creoui/tokens.css (必須)
367
+ */
368
+
369
+ .creo-alert {
370
+ display: flex;
371
+ align-items: flex-start;
372
+ gap: var(--spacing-s);
373
+ padding: var(--spacing-s) var(--spacing-m);
374
+ border-radius: var(--radius-m);
375
+ border: 1px solid transparent;
376
+ color: var(--color-text-primary);
377
+ font-size: var(--typography-size-m);
378
+ }
379
+
380
+ /* ---------- Variants (default style = 15% tint bg) ---------- */
381
+
382
+ .creo-alert[data-variant="info"],
383
+ .creo-alert:not([data-variant]) {
384
+ background-color: color-mix(in oklch, var(--color-semantic-info) 15%, transparent);
385
+ border-color: color-mix(in oklch, var(--color-semantic-info) 30%, transparent);
386
+ }
387
+ .creo-alert[data-variant="info"] .creo-alert-icon {
388
+ color: var(--color-semantic-info);
389
+ }
390
+
391
+ .creo-alert[data-variant="success"] {
392
+ background-color: color-mix(in oklch, var(--color-semantic-success) 15%, transparent);
393
+ border-color: color-mix(in oklch, var(--color-semantic-success) 30%, transparent);
394
+ }
395
+ .creo-alert[data-variant="success"] .creo-alert-icon {
396
+ color: var(--color-semantic-success);
397
+ }
398
+
399
+ .creo-alert[data-variant="warning"] {
400
+ background-color: color-mix(in oklch, var(--color-semantic-warning) 15%, transparent);
401
+ border-color: color-mix(in oklch, var(--color-semantic-warning) 30%, transparent);
402
+ }
403
+ .creo-alert[data-variant="warning"] .creo-alert-icon {
404
+ color: var(--color-semantic-warning);
405
+ }
406
+
407
+ .creo-alert[data-variant="error"] {
408
+ background-color: color-mix(in oklch, var(--color-semantic-error) 15%, transparent);
409
+ border-color: color-mix(in oklch, var(--color-semantic-error) 30%, transparent);
410
+ }
411
+ .creo-alert[data-variant="error"] .creo-alert-icon {
412
+ color: var(--color-semantic-error);
413
+ }
414
+
415
+ /* ---------- Variant-style: subtle (border 強調、背景淡) ---------- */
416
+
417
+ .creo-alert[data-variant-style="subtle"] {
418
+ background-color: var(--color-surface-surface);
419
+ border-width: 1.5px;
420
+ }
421
+
422
+ /* ---------- Variant-style: banner (full-width、border-radius 0) ---------- */
423
+
424
+ .creo-alert[data-variant-style="banner"] {
425
+ border-radius: 0;
426
+ border-left: none;
427
+ border-right: none;
428
+ }
429
+
430
+ /* ---------- Slots ---------- */
431
+
432
+ .creo-alert-icon {
433
+ flex-shrink: 0;
434
+ font-size: var(--typography-title-card);
435
+ line-height: 1;
436
+ margin-top: 2px;
437
+ }
438
+
439
+ .creo-alert-content {
440
+ flex: 1;
441
+ display: flex;
442
+ flex-direction: column;
443
+ gap: 2px;
444
+ min-width: 0;
445
+ }
446
+
447
+ .creo-alert-content > strong {
448
+ font-size: var(--typography-size-m);
449
+ font-weight: var(--typography-weight-semibold);
450
+ }
451
+
452
+ .creo-alert-content > span {
453
+ font-size: var(--typography-body-helper);
454
+ color: var(--color-text-secondary);
455
+ line-height: var(--typography-line-height-normal);
456
+ }
457
+
458
+ .creo-alert-close {
459
+ flex-shrink: 0;
460
+ appearance: none;
461
+ background: transparent;
462
+ border: none;
463
+ padding: 2px var(--spacing-xs);
464
+ color: var(--color-text-tertiary);
465
+ font-size: var(--typography-size-m);
466
+ cursor: pointer;
467
+ border-radius: var(--radius-xs);
468
+ }
469
+ .creo-alert-close:hover {
470
+ color: var(--color-text-primary);
471
+ background-color: var(--color-surface-bg-subtle);
472
+ }
473
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
474
+
475
+ /* ================ avatar.css ================ */
476
+ /**
477
+ * creoui — Avatar component
478
+ *
479
+ * 円形 (or square) の image / initials container。
480
+ *
481
+ * Spec: docs/components/avatar.md
482
+ * Token: creoui/tokens.css (必須)
483
+ */
484
+
485
+ .creo-avatar {
486
+ display: inline-flex;
487
+ align-items: center;
488
+ justify-content: center;
489
+ flex-shrink: 0;
490
+ position: relative;
491
+ width: 32px;
492
+ height: 32px;
493
+ border-radius: var(--radius-full);
494
+ background-color: var(--color-brand-primary-subtle);
495
+ color: var(--color-text-primary);
496
+ overflow: hidden;
497
+ vertical-align: middle;
498
+ user-select: none;
499
+ }
500
+
501
+ /* ---------- Sizes ---------- */
502
+
503
+ .creo-avatar[data-size="s"] {
504
+ width: 24px;
505
+ height: 24px;
506
+ }
507
+ .creo-avatar[data-size="m"],
508
+ .creo-avatar:not([data-size]) {
509
+ width: 32px;
510
+ height: 32px;
511
+ }
512
+ .creo-avatar[data-size="l"] {
513
+ width: var(--layout-target-tap);
514
+ height: var(--layout-target-tap);
515
+ }
516
+ .creo-avatar[data-size="xl"] {
517
+ width: 64px;
518
+ height: 64px;
519
+ }
520
+
521
+ /* ---------- Shapes ---------- */
522
+
523
+ .creo-avatar[data-shape="square"] {
524
+ border-radius: var(--radius-s);
525
+ }
526
+
527
+ /* ---------- Image ---------- */
528
+
529
+ .creo-avatar-image {
530
+ width: 100%;
531
+ height: 100%;
532
+ object-fit: cover;
533
+ display: block;
534
+ }
535
+
536
+ /* ---------- Initials fallback ---------- */
537
+
538
+ .creo-avatar-initials {
539
+ font-family: inherit;
540
+ font-size: var(--typography-size-s);
541
+ font-weight: var(--typography-weight-semibold);
542
+ text-transform: uppercase;
543
+ letter-spacing: 0.02em;
544
+ }
545
+
546
+ .creo-avatar[data-size="s"] .creo-avatar-initials {
547
+ font-size: var(--typography-size-xs);
548
+ }
549
+ .creo-avatar[data-size="l"] .creo-avatar-initials {
550
+ font-size: var(--typography-size-m);
551
+ }
552
+ .creo-avatar[data-size="xl"] .creo-avatar-initials {
553
+ font-size: var(--typography-size-l);
554
+ }
555
+
556
+ /* ---------- Status dot ---------- */
557
+
558
+ .creo-avatar-status {
559
+ position: absolute;
560
+ right: 0;
561
+ bottom: 0;
562
+ width: 25%;
563
+ height: 25%;
564
+ min-width: 8px;
565
+ min-height: 8px;
566
+ border-radius: var(--radius-full);
567
+ border: 2px solid var(--color-surface-surface);
568
+ background-color: var(--color-text-tertiary); /* offline default */
569
+ }
570
+ .creo-avatar-status[data-status="online"] {
571
+ background-color: var(--color-semantic-success);
572
+ }
573
+ .creo-avatar-status[data-status="busy"] {
574
+ background-color: var(--color-semantic-error);
575
+ }
576
+ .creo-avatar-status[data-status="away"] {
577
+ background-color: var(--color-semantic-warning);
578
+ }
579
+
580
+ /* ================ badge.css ================ */
581
+ /**
582
+ * creoui — Badge component (pill-shaped status / count / tag)
583
+ *
584
+ * Spec: docs/components/badge.md
585
+ * Token: creoui/tokens.css (必須)
586
+ */
587
+
588
+ .creo-badge {
589
+ display: inline-flex;
590
+ align-items: center;
591
+ justify-content: center;
592
+ padding: 2px var(--spacing-xs);
593
+ font-family: inherit;
594
+ font-size: var(--typography-size-s);
595
+ font-weight: var(--typography-weight-medium);
596
+ line-height: 1;
597
+ border-radius: var(--radius-full);
598
+ white-space: nowrap;
599
+
600
+ /* default: neutral variant */
601
+ background-color: var(--color-surface-bg-subtle);
602
+ color: var(--color-text-secondary);
603
+ }
604
+
605
+ /* ---------- Variants ---------- */
606
+
607
+ .creo-badge[data-variant="brand"] {
608
+ background-color: var(--color-brand-primary-subtle);
609
+ color: var(--color-brand-primary);
610
+ }
611
+ .creo-badge[data-variant="success"] {
612
+ background-color: color-mix(in oklch, var(--color-semantic-success) 20%, transparent);
613
+ color: var(--color-semantic-success);
614
+ }
615
+ .creo-badge[data-variant="warning"] {
616
+ background-color: color-mix(in oklch, var(--color-semantic-warning) 20%, transparent);
617
+ color: var(--color-semantic-warning);
618
+ }
619
+ .creo-badge[data-variant="error"] {
620
+ background-color: color-mix(in oklch, var(--color-semantic-error) 20%, transparent);
621
+ color: var(--color-semantic-error);
622
+ }
623
+ .creo-badge[data-variant="info"] {
624
+ background-color: color-mix(in oklch, var(--color-semantic-info) 20%, transparent);
625
+ color: var(--color-semantic-info);
626
+ }
627
+
628
+ /* ---------- Sizes ---------- */
629
+
630
+ .creo-badge[data-size="s"] {
631
+ font-size: var(--typography-size-xs);
632
+ padding: 1px var(--spacing-xs);
633
+ }
634
+
635
+ /* ---------- Shapes ---------- */
636
+
637
+ .creo-badge[data-shape="square"] {
638
+ border-radius: var(--radius-xs);
639
+ }
640
+
641
+ /* ================ breadcrumbs.css ================ */
642
+ /**
643
+ * creoui — Breadcrumbs
644
+ *
645
+ * Spec: docs/components/breadcrumbs.md
646
+ * Token: creoui/tokens.css (必須)
647
+ */
648
+
649
+ .creo-breadcrumbs {
650
+ display: block;
651
+ font-size: var(--typography-size-s);
652
+ color: var(--color-text-secondary);
653
+ }
654
+
655
+ .creo-breadcrumbs[data-size="s"] {
656
+ font-size: var(--typography-size-xs);
657
+ }
658
+
659
+ .creo-breadcrumbs-list {
660
+ display: flex;
661
+ align-items: center;
662
+ flex-wrap: wrap;
663
+ gap: 0;
664
+ padding: 0;
665
+ margin: 0;
666
+ list-style: none;
667
+ }
668
+
669
+ .creo-breadcrumbs-item {
670
+ display: inline-flex;
671
+ align-items: center;
672
+ min-width: 0;
673
+ }
674
+
675
+ /* ---------- Separator (::after on item、最後の item には付けない) ---------- */
676
+
677
+ .creo-breadcrumbs-item:not([aria-current="page"])::after {
678
+ content: "›";
679
+ margin: 0 var(--spacing-xs);
680
+ color: var(--color-text-tertiary);
681
+ display: inline-block;
682
+ user-select: none;
683
+ }
684
+
685
+ .creo-breadcrumbs[data-separator="slash"] .creo-breadcrumbs-item:not([aria-current="page"])::after {
686
+ content: "/";
687
+ }
688
+
689
+ .creo-breadcrumbs[data-separator="dot"] .creo-breadcrumbs-item:not([aria-current="page"])::after {
690
+ content: "·";
691
+ }
692
+
693
+ /* ---------- Link ---------- */
694
+
695
+ .creo-breadcrumbs-link {
696
+ color: var(--color-text-secondary);
697
+ text-decoration: none;
698
+ padding: var(--spacing-xs) 0;
699
+ border-radius: var(--radius-xs);
700
+ transition: color var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing);
701
+
702
+ /* truncate support */
703
+ max-width: 240px;
704
+ overflow: hidden;
705
+ text-overflow: ellipsis;
706
+ white-space: nowrap;
707
+ }
708
+
709
+ .creo-breadcrumbs-link:hover {
710
+ color: var(--color-text-primary);
711
+ }
712
+
713
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
714
+
715
+ /* 現在 page: link じゃない (span)、font-weight 強調 */
716
+ .creo-breadcrumbs-item[aria-current="page"] > .creo-breadcrumbs-link,
717
+ .creo-breadcrumbs-item[aria-current="page"] > span {
718
+ color: var(--color-text-primary);
719
+ font-weight: var(--typography-weight-medium);
720
+ cursor: default;
721
+ }
722
+
723
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
724
+
725
+ @media (prefers-reduced-motion: reduce) {
726
+ .creo-breadcrumbs-link {
727
+ transition: none;
728
+ }
729
+ }
730
+
731
+ /* ================ button.css ================ */
732
+ /**
733
+ * creoui — Button component
734
+ *
735
+ * data attribute で variant / size を表現。`.creo-btn` base + `data-variant` + `data-size`。
736
+ * Default: primary / md。
737
+ *
738
+ * Spec: docs/components/button.md
739
+ * Token: creoui/tokens.css (必須)
740
+ *
741
+ * Usage:
742
+ * <button class="creo-btn" data-variant="primary">Label</button>
743
+ * <button class="creo-btn" data-variant="secondary" data-size="s">Small</button>
744
+ * <button class="creo-btn" data-variant="ghost" aria-pressed="true">Toggle</button>
745
+ */
746
+
747
+ .creo-btn {
748
+ /* Base layout — density scale (default 1) で全 spacing 系が ancestor の
749
+ [data-density] に応じて compact / comfortable / cozy に articulate 切替 */
750
+ display: inline-flex;
751
+ align-items: center;
752
+ justify-content: center;
753
+ gap: calc(var(--layout-gap-tight) * var(--density-gap-scale, 1));
754
+ min-height: calc(var(--layout-target-tap) * var(--density-min-height-scale, 1));
755
+ padding: calc(var(--spacing-s) * var(--density-padding-scale, 1))
756
+ calc(var(--spacing-m) * var(--density-padding-scale, 1));
757
+
758
+ /* Typography */
759
+ font-family: inherit;
760
+ font-size: var(--typography-size-m);
761
+ font-weight: var(--typography-weight-medium);
762
+ line-height: 1;
763
+ text-decoration: none;
764
+ white-space: nowrap;
765
+
766
+ /* Shape */
767
+ border: 1px solid transparent;
768
+ border-radius: var(--radius-s);
769
+
770
+ /* Default interaction */
771
+ cursor: pointer;
772
+ user-select: none;
773
+ transition: background-color var(--motion-mapping-hover-duration)
774
+ var(--motion-mapping-hover-easing), border-color var(--motion-mapping-hover-duration)
775
+ var(--motion-mapping-hover-easing), color var(--motion-mapping-hover-duration)
776
+ var(--motion-mapping-hover-easing), transform var(--motion-mapping-press-duration)
777
+ var(--motion-mapping-press-easing);
778
+
779
+ /* Default (primary) — variant で override される */
780
+ background-color: var(--color-brand-primary);
781
+ color: var(--color-surface-bg-base);
782
+ }
783
+
784
+ /* ---------- Variants ---------- */
785
+
786
+ .creo-btn[data-variant="primary"],
787
+ .creo-btn:not([data-variant]) {
788
+ background-color: var(--color-brand-primary);
789
+ border-color: var(--color-brand-primary);
790
+ color: var(--color-surface-bg-base);
791
+ }
792
+ .creo-btn[data-variant="primary"]:hover:not(:disabled),
793
+ .creo-btn:not([data-variant]):hover:not(:disabled) {
794
+ background-color: var(--color-brand-primary-hover);
795
+ border-color: var(--color-brand-primary-hover);
796
+ }
797
+ .creo-btn[data-variant="primary"]:active:not(:disabled),
798
+ .creo-btn:not([data-variant]):active:not(:disabled) {
799
+ background-color: var(--color-brand-primary-active);
800
+ border-color: var(--color-brand-primary-active);
801
+ transform: translateY(1px);
802
+ }
803
+
804
+ .creo-btn[data-variant="secondary"] {
805
+ background-color: var(--color-surface-surface);
806
+ border-color: var(--color-surface-border);
807
+ color: var(--color-text-primary);
808
+ }
809
+ .creo-btn[data-variant="secondary"]:hover:not(:disabled) {
810
+ background-color: var(--color-surface-bg-subtle);
811
+ border-color: var(--color-brand-primary);
812
+ }
813
+ .creo-btn[data-variant="secondary"]:active:not(:disabled) {
814
+ background-color: var(--color-surface-bg-subtle);
815
+ transform: translateY(1px);
816
+ }
817
+
818
+ .creo-btn[data-variant="ghost"] {
819
+ background-color: transparent;
820
+ border-color: transparent;
821
+ color: var(--color-text-primary);
822
+ }
823
+ .creo-btn[data-variant="ghost"]:hover:not(:disabled) {
824
+ background-color: var(--color-surface-bg-subtle);
825
+ }
826
+ .creo-btn[data-variant="ghost"]:active:not(:disabled) {
827
+ background-color: var(--color-surface-bg-subtle);
828
+ transform: translateY(1px);
829
+ }
830
+
831
+ /* ---------- Sizes ---------- */
832
+
833
+ .creo-btn[data-size="s"] {
834
+ min-height: var(--layout-target-focus);
835
+ padding: var(--spacing-xs) var(--spacing-s);
836
+ font-size: var(--typography-size-s);
837
+ border-radius: var(--radius-xs);
838
+ }
839
+
840
+ /* data-size="m" は base と同じ、明示しなくても OK だが editor-mode 親和で一応ルール定義 */
841
+ .creo-btn[data-size="m"] {
842
+ min-height: var(--layout-target-tap);
843
+ padding: var(--spacing-s) var(--spacing-m);
844
+ font-size: var(--typography-size-m);
845
+ border-radius: var(--radius-s);
846
+ }
847
+
848
+ .creo-btn[data-size="l"] {
849
+ min-height: calc(var(--layout-target-tap) * 1.15);
850
+ padding: var(--spacing-m) var(--spacing-l);
851
+ font-size: var(--typography-size-l);
852
+ border-radius: var(--radius-m);
853
+ }
854
+
855
+ /* ---------- State: disabled ---------- */
856
+
857
+ .creo-btn:disabled {
858
+ cursor: not-allowed;
859
+ opacity: 0.5;
860
+ pointer-events: none;
861
+ }
862
+
863
+ /* ---------- State: toggle (aria-pressed) ---------- */
864
+
865
+ .creo-btn[aria-pressed="true"] {
866
+ background-color: var(--color-brand-primary-active);
867
+ border-color: var(--color-brand-primary-active);
868
+ color: var(--color-surface-bg-base);
869
+ }
870
+ .creo-btn[data-variant="secondary"][aria-pressed="true"] {
871
+ background-color: var(--color-surface-bg-subtle);
872
+ border-color: var(--color-brand-primary);
873
+ color: var(--color-brand-primary);
874
+ }
875
+ .creo-btn[data-variant="ghost"][aria-pressed="true"] {
876
+ background-color: var(--color-surface-bg-subtle);
877
+ color: var(--color-brand-primary);
878
+ }
879
+
880
+ /* ---------- Focus ring ---------- */
881
+ /* :focus-visible policy は _focus.css に articulate (component-agnostic、 8 theme で
882
+ --color-focus-ring-color が brand と整合した luminance)。 component 個別 override
883
+ は原則禁止 (a11y consistency)、 例外時は _focus.css の articulate を参照。 */
884
+
885
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
886
+
887
+ @media (prefers-reduced-motion: reduce) {
888
+ .creo-btn {
889
+ transition: none;
890
+ transform: none;
891
+ }
892
+ }
893
+
894
+ /* ================ card.css ================ */
895
+ /**
896
+ * creoui — Card component
897
+ *
898
+ * `.creo-card` base + data-variant (default / elevated / outlined) + data-padding (s/m/lg)。
899
+ *
900
+ * Spec: docs/components/card.md
901
+ * Token: creoui/tokens.css (必須)
902
+ *
903
+ * Usage:
904
+ * <article class="creo-card">...</article>
905
+ * <article class="creo-card" data-variant="elevated" data-padding="l">...</article>
906
+ * <article class="creo-card" data-variant="outlined" data-interactive="true">...</article>
907
+ */
908
+
909
+ .creo-card {
910
+ /* density scale 適用 (default 1)、 ancestor [data-density] で切替 */
911
+ display: block;
912
+ background-color: var(--color-surface-surface);
913
+ border: 1px solid var(--color-surface-border);
914
+ border-radius: var(--radius-m);
915
+ padding: calc(var(--spacing-m) * var(--density-padding-scale, 1));
916
+ color: var(--color-text-primary);
917
+ transition: background-color var(--motion-mapping-hover-duration)
918
+ var(--motion-mapping-hover-easing), box-shadow var(--motion-mapping-hover-duration)
919
+ var(--motion-mapping-hover-easing), border-color var(--motion-mapping-hover-duration)
920
+ var(--motion-mapping-hover-easing), transform var(--motion-mapping-hover-duration)
921
+ var(--motion-mapping-hover-easing);
922
+ }
923
+
924
+ /* ---------- Variants ---------- */
925
+
926
+ .creo-card[data-variant="default"],
927
+ .creo-card:not([data-variant]) {
928
+ background-color: var(--color-surface-surface);
929
+ border-color: var(--color-surface-border);
930
+ box-shadow: var(--shadow-s);
931
+ }
932
+
933
+ .creo-card[data-variant="elevated"] {
934
+ background-color: var(--color-surface-surface);
935
+ border-color: transparent;
936
+ box-shadow: var(--shadow-m);
937
+ }
938
+
939
+ .creo-card[data-variant="outlined"] {
940
+ background-color: transparent;
941
+ border-color: var(--color-surface-border);
942
+ border-width: 1.5px;
943
+ box-shadow: none;
944
+ }
945
+
946
+ /* ---------- Padding sizes ---------- */
947
+
948
+ .creo-card[data-padding="s"] {
949
+ padding: var(--spacing-s);
950
+ }
951
+ .creo-card[data-padding="m"],
952
+ .creo-card:not([data-padding]) {
953
+ padding: var(--spacing-m);
954
+ }
955
+ .creo-card[data-padding="l"] {
956
+ padding: var(--spacing-l);
957
+ }
958
+
959
+ /* ---------- Interactive state ---------- */
960
+
961
+ .creo-card[data-interactive="true"] {
962
+ cursor: pointer;
963
+ }
964
+ .creo-card[data-interactive="true"]:hover {
965
+ border-color: var(--color-brand-primary);
966
+ transform: translateY(-1px);
967
+ }
968
+ .creo-card[data-interactive="true"][data-variant="elevated"]:hover {
969
+ box-shadow: var(--shadow-l);
970
+ }
971
+ .creo-card[data-interactive="true"]:active {
972
+ transform: translateY(0);
973
+ }
974
+
975
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
976
+
977
+ @media (prefers-reduced-motion: reduce) {
978
+ .creo-card {
979
+ transition: none;
980
+ transform: none;
981
+ }
982
+ }
983
+
984
+ /* ================ combobox.css ================ */
985
+ /**
986
+ * creoui — Combobox (`<input list>` + `<datalist>`)
987
+ *
988
+ * native datalist を使う小さい visual cue 追加のみ。`.creo-input` と組合せて使用。
989
+ *
990
+ * Spec: docs/components/combobox.md
991
+ * Token: creoui/tokens.css (必須)
992
+ */
993
+
994
+ .creo-combobox {
995
+ /* input right side に chevron room を確保 */
996
+ padding-right: var(--spacing-xl);
997
+
998
+ /* chevron icon を背景画像として描く (SVG inline、token 色追従) */
999
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="8" viewBox="0 0 12 8" fill="none"><path d="M1 1L6 6L11 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>');
1000
+ background-repeat: no-repeat;
1001
+ background-position: right var(--spacing-s) center;
1002
+ background-size: 12px 8px;
1003
+
1004
+ /* currentColor が使えないので、text-tertiary を指定 (hack: CSS mask 使うと完全追従できるが SVG で十分) */
1005
+ }
1006
+
1007
+ /* list opened 時 (focus) は chevron を反転させたい → native datalist は open state を
1008
+ CSS で知る術がないので省略。focus ring は .creo-input の :focus-visible で統一 */
1009
+
1010
+ /* RTL 対応 (right に chevron だと LTR 前提、RTL では left に) */
1011
+ [dir="rtl"] .creo-combobox {
1012
+ padding-right: var(--spacing-m);
1013
+ padding-left: var(--spacing-xl);
1014
+ background-position: left var(--spacing-s) center;
1015
+ }
1016
+
1017
+ /* ================ container.css ================ */
1018
+ /**
1019
+ * creoui — Container (max-width constraint + horizontal centering)
1020
+ *
1021
+ * page-level content の max-width / centering / side padding を 1 attribute で。
1022
+ * 5 size + full、 default m (768px)。 reading-friendly な breakpoint を意識。
1023
+ * 命名は spacing convention (xs/s/m/l/xl、 5 tier 統一) に揃える。
1024
+ *
1025
+ * Spec: docs/components/container.md
1026
+ * Token: creoui/tokens.css (必須)
1027
+ */
1028
+
1029
+ .creo-container {
1030
+ width: 100%;
1031
+ margin-left: auto;
1032
+ margin-right: auto;
1033
+ padding-left: var(--spacing-m);
1034
+ padding-right: var(--spacing-m);
1035
+ /* default m max-width = reading-friendly */
1036
+ max-width: var(--layout-container-m);
1037
+ }
1038
+
1039
+ /* ---------- Size variants (token-driven、 5 tier xs/s/m/l/xl + full) ---------- */
1040
+
1041
+ .creo-container[data-size="xs"] {
1042
+ max-width: var(--layout-container-xs);
1043
+ } /* extra-narrow、 minimal modal / single CTA */
1044
+ .creo-container[data-size="s"] {
1045
+ max-width: var(--layout-container-s);
1046
+ } /* 短文 / form column */
1047
+ .creo-container[data-size="m"] {
1048
+ max-width: var(--layout-container-m);
1049
+ } /* default、 reading-friendly */
1050
+ .creo-container[data-size="l"] {
1051
+ max-width: var(--layout-container-l);
1052
+ } /* dashboard / table */
1053
+ .creo-container[data-size="xl"] {
1054
+ max-width: var(--layout-container-xl);
1055
+ } /* hero / multi-column */
1056
+ .creo-container[data-size="full"] {
1057
+ max-width: 100%;
1058
+ } /* 全幅、 token 化不要 (semantic value) */
1059
+
1060
+ /* ---------- Padding override ---------- */
1061
+
1062
+ .creo-container[data-padding="none"] {
1063
+ padding-left: 0;
1064
+ padding-right: 0;
1065
+ }
1066
+ .creo-container[data-padding="s"] {
1067
+ padding-left: var(--spacing-s);
1068
+ padding-right: var(--spacing-s);
1069
+ }
1070
+ .creo-container[data-padding="l"] {
1071
+ padding-left: var(--spacing-l);
1072
+ padding-right: var(--spacing-l);
1073
+ }
1074
+
1075
+ /* ================ dialog.css ================ */
1076
+ /**
1077
+ * creoui — Dialog component (native <dialog> based)
1078
+ *
1079
+ * native `<dialog>` + `showModal()` で focus trap / Esc close / ARIA を browser に任せる。
1080
+ * consumer は JS で showModal() / close() を呼ぶだけ。
1081
+ *
1082
+ * Spec: docs/components/dialog.md
1083
+ * Token: creoui/tokens.css (必須)
1084
+ */
1085
+
1086
+ .creo-dialog {
1087
+ /* Reset native defaults */
1088
+ padding: 0;
1089
+ border: 1px solid var(--color-surface-border);
1090
+
1091
+ /* Shape */
1092
+ background-color: var(--color-surface-surface);
1093
+ color: var(--color-text-primary);
1094
+ border-radius: var(--radius-l);
1095
+ box-shadow: var(--shadow-l);
1096
+
1097
+ /* Width */
1098
+ width: min(90vw, 480px);
1099
+ max-height: 85vh;
1100
+ overflow: hidden;
1101
+
1102
+ /* Typography */
1103
+ font-family: inherit;
1104
+ font-size: var(--typography-size-m);
1105
+ line-height: var(--typography-line-height-normal);
1106
+
1107
+ /* Entrance (開いた時の軽い lift) */
1108
+ animation: creoDialogIn var(--motion-mapping-modal-enter-duration)
1109
+ var(--motion-mapping-modal-enter-easing);
1110
+ }
1111
+
1112
+ .creo-dialog::backdrop {
1113
+ background-color: var(--color-surface-scrim-modal);
1114
+ backdrop-filter: blur(4px);
1115
+ -webkit-backdrop-filter: blur(4px);
1116
+ }
1117
+
1118
+ @keyframes creoDialogIn {
1119
+ from {
1120
+ opacity: 0;
1121
+ transform: translateY(8px) scale(0.98);
1122
+ }
1123
+ to {
1124
+ opacity: 1;
1125
+ transform: translateY(0) scale(1);
1126
+ }
1127
+ }
1128
+
1129
+ /* ---------- Sizes ---------- */
1130
+
1131
+ .creo-dialog[data-size="s"] {
1132
+ width: min(90vw, 320px);
1133
+ }
1134
+ .creo-dialog[data-size="m"],
1135
+ .creo-dialog:not([data-size]) {
1136
+ width: min(90vw, 480px);
1137
+ }
1138
+ .creo-dialog[data-size="l"] {
1139
+ width: min(92vw, 720px);
1140
+ }
1141
+
1142
+ /* ---------- Slots ---------- */
1143
+
1144
+ .creo-dialog-header {
1145
+ display: flex;
1146
+ align-items: center;
1147
+ justify-content: space-between;
1148
+ gap: var(--spacing-s);
1149
+ padding: var(--spacing-s) var(--spacing-m);
1150
+ border-bottom: 1px solid var(--color-surface-border);
1151
+ }
1152
+
1153
+ .creo-dialog-title {
1154
+ margin: 0;
1155
+ font-size: var(--typography-title-subsection);
1156
+ font-weight: var(--typography-weight-semibold);
1157
+ color: var(--color-text-primary);
1158
+ line-height: 1.3;
1159
+ }
1160
+
1161
+ .creo-dialog[data-variant="destructive"] .creo-dialog-title {
1162
+ color: var(--color-semantic-error);
1163
+ }
1164
+
1165
+ .creo-dialog-body {
1166
+ padding: var(--spacing-m);
1167
+ overflow-y: auto;
1168
+ max-height: 60vh;
1169
+ }
1170
+
1171
+ .creo-dialog-body > * + * {
1172
+ margin-top: var(--spacing-s);
1173
+ }
1174
+
1175
+ .creo-dialog-footer {
1176
+ display: flex;
1177
+ align-items: center;
1178
+ justify-content: flex-end;
1179
+ gap: var(--layout-gap-tight);
1180
+ padding: var(--spacing-s) var(--spacing-m);
1181
+ border-top: 1px solid var(--color-surface-border);
1182
+ }
1183
+
1184
+ /* ---------- Closing (opt-in、consumer が .is-closing を付けて trigger) ---------- */
1185
+
1186
+ .creo-dialog.is-closing {
1187
+ animation: creoDialogOut var(--motion-mapping-modal-exit-duration)
1188
+ var(--motion-mapping-modal-exit-easing);
1189
+ }
1190
+
1191
+ @keyframes creoDialogOut {
1192
+ from {
1193
+ opacity: 1;
1194
+ transform: translateY(0) scale(1);
1195
+ }
1196
+ to {
1197
+ opacity: 0;
1198
+ transform: translateY(4px) scale(0.98);
1199
+ }
1200
+ }
1201
+
1202
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
1203
+
1204
+ @media (prefers-reduced-motion: reduce) {
1205
+ .creo-dialog,
1206
+ .creo-dialog.is-closing {
1207
+ animation: none;
1208
+ }
1209
+ }
1210
+
1211
+ /* ================ divider.css ================ */
1212
+ /**
1213
+ * creoui — Divider (visual / semantic separator)
1214
+ *
1215
+ * 区切り線 — section 間の視覚的境界。 native <hr> + class で a11y 自動。
1216
+ * orientation (horizontal / vertical)、 thickness (thin / thick)、 spacing 5-step。
1217
+ *
1218
+ * Spec: docs/components/divider.md
1219
+ * Token: creoui/tokens.css (必須)
1220
+ */
1221
+
1222
+ .creo-divider {
1223
+ border: 0;
1224
+ background-color: var(--color-surface-border);
1225
+ flex-shrink: 0;
1226
+ }
1227
+
1228
+ /* ---------- Orientation: horizontal (default) ---------- */
1229
+
1230
+ .creo-divider:not([data-orientation]),
1231
+ .creo-divider[data-orientation="horizontal"] {
1232
+ width: 100%;
1233
+ height: 1px;
1234
+ margin: var(--spacing-m) 0;
1235
+ }
1236
+
1237
+ .creo-divider[data-orientation="horizontal"][data-thickness="thick"] {
1238
+ height: 2px;
1239
+ }
1240
+
1241
+ /* ---------- Orientation: vertical ---------- */
1242
+
1243
+ .creo-divider[data-orientation="vertical"] {
1244
+ width: 1px;
1245
+ height: auto;
1246
+ align-self: stretch;
1247
+ margin: 0 var(--spacing-m);
1248
+ }
1249
+
1250
+ .creo-divider[data-orientation="vertical"][data-thickness="thick"] {
1251
+ width: 2px;
1252
+ }
1253
+
1254
+ /* ---------- Spacing override (5-step rule) ---------- */
1255
+
1256
+ .creo-divider[data-spacing="xs"][data-orientation="horizontal"],
1257
+ .creo-divider[data-spacing="xs"]:not([data-orientation]) {
1258
+ margin: var(--spacing-xs) 0;
1259
+ }
1260
+ .creo-divider[data-spacing="s"][data-orientation="horizontal"],
1261
+ .creo-divider[data-spacing="s"]:not([data-orientation]) {
1262
+ margin: var(--spacing-s) 0;
1263
+ }
1264
+ .creo-divider[data-spacing="m"][data-orientation="horizontal"],
1265
+ .creo-divider[data-spacing="m"]:not([data-orientation]) {
1266
+ margin: var(--spacing-m) 0;
1267
+ }
1268
+ .creo-divider[data-spacing="l"][data-orientation="horizontal"],
1269
+ .creo-divider[data-spacing="l"]:not([data-orientation]) {
1270
+ margin: var(--spacing-l) 0;
1271
+ }
1272
+ .creo-divider[data-spacing="xl"][data-orientation="horizontal"],
1273
+ .creo-divider[data-spacing="xl"]:not([data-orientation]) {
1274
+ margin: var(--spacing-xl) 0;
1275
+ }
1276
+
1277
+ .creo-divider[data-spacing="xs"][data-orientation="vertical"] {
1278
+ margin: 0 var(--spacing-xs);
1279
+ }
1280
+ .creo-divider[data-spacing="s"][data-orientation="vertical"] {
1281
+ margin: 0 var(--spacing-s);
1282
+ }
1283
+ .creo-divider[data-spacing="m"][data-orientation="vertical"] {
1284
+ margin: 0 var(--spacing-m);
1285
+ }
1286
+ .creo-divider[data-spacing="l"][data-orientation="vertical"] {
1287
+ margin: 0 var(--spacing-l);
1288
+ }
1289
+ .creo-divider[data-spacing="xl"][data-orientation="vertical"] {
1290
+ margin: 0 var(--spacing-xl);
1291
+ }
1292
+
1293
+ /* ---------- Variant: subtle (low-emphasis) ---------- */
1294
+
1295
+ .creo-divider[data-variant="subtle"] {
1296
+ background-color: var(--color-surface-bg-subtle);
1297
+ }
1298
+
1299
+ /* ================ drawer.css ================ */
1300
+ /**
1301
+ * creoui — Drawer (side sheet、Dialog の placement 版)
1302
+ *
1303
+ * Spec: docs/components/drawer.md
1304
+ * Token: creoui/tokens.css (必須)
1305
+ */
1306
+
1307
+ .creo-drawer {
1308
+ padding: 0;
1309
+ margin: 0;
1310
+ border: 1px solid var(--color-surface-border);
1311
+ background-color: var(--color-surface-surface);
1312
+ color: var(--color-text-primary);
1313
+ box-shadow: var(--shadow-xl, var(--shadow-l));
1314
+ overflow: hidden;
1315
+
1316
+ display: flex;
1317
+ flex-direction: column;
1318
+
1319
+ font-family: inherit;
1320
+ font-size: var(--typography-size-m);
1321
+ line-height: var(--typography-line-height-normal);
1322
+
1323
+ animation: creoDrawerInRight var(--motion-mapping-modal-enter-duration)
1324
+ var(--motion-mapping-modal-enter-easing);
1325
+ }
1326
+
1327
+ .creo-drawer::backdrop {
1328
+ background-color: var(--color-surface-scrim);
1329
+ backdrop-filter: blur(2px);
1330
+ -webkit-backdrop-filter: blur(2px);
1331
+ }
1332
+
1333
+ /* ---------- Placement ---------- */
1334
+
1335
+ /* Right (default) */
1336
+ .creo-drawer[data-placement="right"],
1337
+ .creo-drawer:not([data-placement]) {
1338
+ position: fixed;
1339
+ top: 0;
1340
+ right: 0;
1341
+ bottom: 0;
1342
+ height: 100vh;
1343
+ width: min(90vw, 400px);
1344
+ border-radius: 0;
1345
+ border-right: none;
1346
+ animation-name: creoDrawerInRight;
1347
+ }
1348
+
1349
+ .creo-drawer[data-placement="left"] {
1350
+ position: fixed;
1351
+ top: 0;
1352
+ left: 0;
1353
+ bottom: 0;
1354
+ height: 100vh;
1355
+ width: min(90vw, 400px);
1356
+ border-radius: 0;
1357
+ border-left: none;
1358
+ animation-name: creoDrawerInLeft;
1359
+ }
1360
+
1361
+ .creo-drawer[data-placement="top"] {
1362
+ position: fixed;
1363
+ top: 0;
1364
+ left: 0;
1365
+ right: 0;
1366
+ width: 100vw;
1367
+ height: min(70vh, 50vh);
1368
+ border-radius: 0;
1369
+ border-top: none;
1370
+ animation-name: creoDrawerInTop;
1371
+ }
1372
+
1373
+ .creo-drawer[data-placement="bottom"] {
1374
+ position: fixed;
1375
+ bottom: 0;
1376
+ left: 0;
1377
+ right: 0;
1378
+ top: auto;
1379
+ width: 100vw;
1380
+ height: min(70vh, 50vh);
1381
+ border-radius: 0;
1382
+ border-bottom: none;
1383
+ animation-name: creoDrawerInBottom;
1384
+ }
1385
+
1386
+ /* ---------- Sizes (horizontal = width / vertical = height) ---------- */
1387
+
1388
+ .creo-drawer[data-placement="right"][data-size="s"],
1389
+ .creo-drawer[data-placement="left"][data-size="s"] {
1390
+ width: min(90vw, 280px);
1391
+ }
1392
+ .creo-drawer[data-placement="right"][data-size="l"],
1393
+ .creo-drawer[data-placement="left"][data-size="l"] {
1394
+ width: min(92vw, 560px);
1395
+ }
1396
+ .creo-drawer[data-placement="right"][data-size="xl"],
1397
+ .creo-drawer[data-placement="left"][data-size="xl"] {
1398
+ width: min(94vw, 800px);
1399
+ }
1400
+
1401
+ .creo-drawer[data-placement="top"][data-size="s"],
1402
+ .creo-drawer[data-placement="bottom"][data-size="s"] {
1403
+ height: 40vh;
1404
+ }
1405
+ .creo-drawer[data-placement="top"][data-size="l"],
1406
+ .creo-drawer[data-placement="bottom"][data-size="l"] {
1407
+ height: 65vh;
1408
+ }
1409
+ .creo-drawer[data-placement="top"][data-size="xl"],
1410
+ .creo-drawer[data-placement="bottom"][data-size="xl"] {
1411
+ height: 80vh;
1412
+ }
1413
+
1414
+ /* ---------- Entrance animations (per placement) ---------- */
1415
+
1416
+ @keyframes creoDrawerInRight {
1417
+ from {
1418
+ transform: translateX(100%);
1419
+ opacity: 0;
1420
+ }
1421
+ to {
1422
+ transform: translateX(0);
1423
+ opacity: 1;
1424
+ }
1425
+ }
1426
+ @keyframes creoDrawerInLeft {
1427
+ from {
1428
+ transform: translateX(-100%);
1429
+ opacity: 0;
1430
+ }
1431
+ to {
1432
+ transform: translateX(0);
1433
+ opacity: 1;
1434
+ }
1435
+ }
1436
+ @keyframes creoDrawerInTop {
1437
+ from {
1438
+ transform: translateY(-100%);
1439
+ opacity: 0;
1440
+ }
1441
+ to {
1442
+ transform: translateY(0);
1443
+ opacity: 1;
1444
+ }
1445
+ }
1446
+ @keyframes creoDrawerInBottom {
1447
+ from {
1448
+ transform: translateY(100%);
1449
+ opacity: 0;
1450
+ }
1451
+ to {
1452
+ transform: translateY(0);
1453
+ opacity: 1;
1454
+ }
1455
+ }
1456
+
1457
+ @media (prefers-reduced-motion: reduce) {
1458
+ .creo-drawer {
1459
+ animation: none;
1460
+ }
1461
+ }
1462
+
1463
+ /* ---------- Slots ---------- */
1464
+
1465
+ .creo-drawer-header {
1466
+ display: flex;
1467
+ align-items: center;
1468
+ justify-content: space-between;
1469
+ gap: var(--spacing-s);
1470
+ padding: var(--spacing-s) var(--spacing-m);
1471
+ border-bottom: 1px solid var(--color-surface-border);
1472
+ flex-shrink: 0;
1473
+ }
1474
+
1475
+ .creo-drawer-title {
1476
+ margin: 0;
1477
+ font-size: var(--typography-title-subsection);
1478
+ font-weight: var(--typography-weight-semibold);
1479
+ color: var(--color-text-primary);
1480
+ line-height: 1.3;
1481
+ }
1482
+
1483
+ .creo-drawer-body {
1484
+ padding: var(--spacing-m);
1485
+ overflow-y: auto;
1486
+ flex: 1;
1487
+ min-height: 0;
1488
+ }
1489
+ .creo-drawer-body > * + * {
1490
+ margin-top: var(--spacing-s);
1491
+ }
1492
+
1493
+ .creo-drawer-footer {
1494
+ display: flex;
1495
+ align-items: center;
1496
+ justify-content: flex-end;
1497
+ gap: var(--layout-gap-tight);
1498
+ padding: var(--spacing-s) var(--spacing-m);
1499
+ border-top: 1px solid var(--color-surface-border);
1500
+ flex-shrink: 0;
1501
+ }
1502
+
1503
+ /* ================ empty-state.css ================ */
1504
+ /**
1505
+ * creoui — Empty state
1506
+ *
1507
+ * Spec: docs/components/empty-state.md
1508
+ * Token: creoui/tokens.css (必須)
1509
+ */
1510
+
1511
+ .creo-empty-state {
1512
+ display: flex;
1513
+ flex-direction: column;
1514
+ align-items: center;
1515
+ justify-content: center;
1516
+ text-align: center;
1517
+ gap: var(--spacing-s);
1518
+ padding: var(--spacing-xl);
1519
+ color: var(--color-text-primary);
1520
+ /* Subtle radial gradient bg で 「empty な空間に意図がある」 articulate。
1521
+ brand-primary-subtle を 8% mix で whisper、 over-articulate しない。 */
1522
+ background: radial-gradient(
1523
+ circle at 50% 30%,
1524
+ color-mix(in oklch, var(--color-brand-primary-subtle) 30%, transparent) 0%,
1525
+ transparent 60%
1526
+ );
1527
+ border-radius: var(--radius-l);
1528
+ }
1529
+
1530
+ /* ---------- Sizes ---------- */
1531
+
1532
+ .creo-empty-state[data-size="s"] {
1533
+ padding: var(--spacing-m);
1534
+ gap: var(--spacing-xs);
1535
+ }
1536
+
1537
+ .creo-empty-state[data-size="l"] {
1538
+ padding: calc(var(--spacing-xl) * 2) var(--spacing-xl);
1539
+ gap: var(--spacing-m);
1540
+ }
1541
+
1542
+ /* ---------- Icon (typography.icon の 5 tier xs/s/m/l/xl から l/m/xl を参照) ---------- */
1543
+
1544
+ .creo-empty-state-icon {
1545
+ font-size: var(--typography-icon-l);
1546
+ line-height: 1;
1547
+ /* Brand secondary で family identity を articulate (mint=violet、
1548
+ sora=cyan、 contrast=magenta、 oldschool=amber)、 opacity で whisper */
1549
+ color: var(--color-brand-secondary);
1550
+ opacity: 0.55;
1551
+ margin-bottom: var(--spacing-xs);
1552
+ user-select: none;
1553
+ }
1554
+
1555
+ .creo-empty-state[data-size="s"] .creo-empty-state-icon {
1556
+ font-size: var(--typography-icon-m);
1557
+ margin-bottom: 0;
1558
+ }
1559
+
1560
+ .creo-empty-state[data-size="l"] .creo-empty-state-icon {
1561
+ font-size: var(--typography-icon-xl);
1562
+ margin-bottom: var(--spacing-s);
1563
+ }
1564
+
1565
+ /* ---------- Title ---------- */
1566
+
1567
+ .creo-empty-state-title {
1568
+ margin: 0;
1569
+ font-size: var(--typography-title-subsection);
1570
+ font-weight: var(--typography-weight-semibold);
1571
+ color: var(--color-text-primary);
1572
+ line-height: 1.3;
1573
+ }
1574
+
1575
+ .creo-empty-state[data-size="s"] .creo-empty-state-title {
1576
+ font-size: var(--typography-title-card);
1577
+ }
1578
+
1579
+ .creo-empty-state[data-size="l"] .creo-empty-state-title {
1580
+ font-size: var(--typography-title-section);
1581
+ }
1582
+
1583
+ /* ---------- Description ---------- */
1584
+
1585
+ .creo-empty-state-description {
1586
+ margin: 0;
1587
+ font-size: var(--typography-size-m);
1588
+ color: var(--color-text-secondary);
1589
+ line-height: var(--typography-line-height-relaxed);
1590
+ max-width: 440px;
1591
+ }
1592
+
1593
+ .creo-empty-state[data-size="s"] .creo-empty-state-description {
1594
+ font-size: var(--typography-size-s);
1595
+ max-width: 320px;
1596
+ }
1597
+
1598
+ /* ---------- Actions ---------- */
1599
+
1600
+ .creo-empty-state-actions {
1601
+ display: flex;
1602
+ align-items: center;
1603
+ justify-content: center;
1604
+ gap: var(--layout-gap-tight);
1605
+ flex-wrap: wrap;
1606
+ margin-top: var(--spacing-s);
1607
+ }
1608
+
1609
+ /* ================ error-boundary.css ================ */
1610
+ /**
1611
+ * creoui — Error boundary state
1612
+ *
1613
+ * Spec: design system primitive (Phase 2-3 #3 で articulate)
1614
+ * Token: creoui/tokens.css (必須)
1615
+ *
1616
+ * Usage:
1617
+ * <div class="creo-error-boundary" role="alert" aria-live="assertive">
1618
+ * <span class="creo-error-boundary-icon" aria-hidden="true"></span>
1619
+ * <h3 class="creo-error-boundary-title">Something went wrong</h3>
1620
+ * <p class="creo-error-boundary-reason">Reason text...</p>
1621
+ * <div class="creo-error-boundary-actions">
1622
+ * <button class="creo-btn" data-variant="primary">Retry</button>
1623
+ * </div>
1624
+ * </div>
1625
+ *
1626
+ * Aesthetic:
1627
+ * semantic error 色 (subtle bg + text) と brand identity の dual layer。
1628
+ * 「壊れたが、 まだ Creo」 を articulate (purely error-tinted は anonymity、
1629
+ * brand layer を残すことで Creo ecosystem internal の error と認識される)。
1630
+ */
1631
+
1632
+ .creo-error-boundary {
1633
+ display: flex;
1634
+ flex-direction: column;
1635
+ align-items: center;
1636
+ justify-content: center;
1637
+ text-align: center;
1638
+ gap: var(--spacing-s);
1639
+ padding: var(--spacing-xl);
1640
+ color: var(--color-text-primary);
1641
+
1642
+ /* Dual layer bg: semantic error subtle (主) + brand primary subtle (whisper)。
1643
+ border は semantic error border (8% alpha) で identity 表現。 */
1644
+ background: linear-gradient(
1645
+ 135deg,
1646
+ color-mix(in oklch, var(--color-semantic-error-subtle) 70%, var(--color-surface-surface)) 0%,
1647
+ color-mix(in oklch, var(--color-brand-primary-subtle) 30%, var(--color-surface-surface)) 100%
1648
+ );
1649
+ border: 1px solid
1650
+ color-mix(in oklch, var(--color-semantic-error) 35%, var(--color-surface-border));
1651
+ border-radius: var(--radius-l);
1652
+ }
1653
+
1654
+ /* ---------- Sizes ---------- */
1655
+
1656
+ .creo-error-boundary[data-size="s"] {
1657
+ padding: var(--spacing-m);
1658
+ gap: var(--spacing-xs);
1659
+ border-radius: var(--radius-m);
1660
+ }
1661
+
1662
+ .creo-error-boundary[data-size="l"] {
1663
+ padding: calc(var(--spacing-xl) * 1.5) var(--spacing-xl);
1664
+ gap: var(--spacing-m);
1665
+ }
1666
+
1667
+ /* ---------- Icon ---------- */
1668
+
1669
+ .creo-error-boundary-icon {
1670
+ font-size: var(--typography-icon-l);
1671
+ line-height: 1;
1672
+ color: var(--color-semantic-error);
1673
+ margin-bottom: var(--spacing-xs);
1674
+ user-select: none;
1675
+ }
1676
+
1677
+ .creo-error-boundary[data-size="s"] .creo-error-boundary-icon {
1678
+ font-size: var(--typography-icon-m);
1679
+ margin-bottom: 0;
1680
+ }
1681
+
1682
+ .creo-error-boundary[data-size="l"] .creo-error-boundary-icon {
1683
+ font-size: var(--typography-icon-xl);
1684
+ margin-bottom: var(--spacing-s);
1685
+ }
1686
+
1687
+ /* ---------- Title ---------- */
1688
+
1689
+ .creo-error-boundary-title {
1690
+ margin: 0;
1691
+ font-size: var(--typography-title-subsection);
1692
+ font-weight: var(--typography-weight-semibold);
1693
+ color: var(--color-semantic-error-text);
1694
+ line-height: var(--typography-line-height-tight);
1695
+ }
1696
+
1697
+ .creo-error-boundary[data-size="s"] .creo-error-boundary-title {
1698
+ font-size: var(--typography-title-card);
1699
+ }
1700
+
1701
+ .creo-error-boundary[data-size="l"] .creo-error-boundary-title {
1702
+ font-size: var(--typography-title-section);
1703
+ }
1704
+
1705
+ /* ---------- Reason ---------- */
1706
+
1707
+ .creo-error-boundary-reason {
1708
+ margin: 0;
1709
+ font-size: var(--typography-body-default);
1710
+ color: var(--color-text-secondary);
1711
+ line-height: var(--typography-line-height-relaxed);
1712
+ max-width: 480px;
1713
+ }
1714
+
1715
+ .creo-error-boundary[data-size="s"] .creo-error-boundary-reason {
1716
+ font-size: var(--typography-body-helper);
1717
+ max-width: 320px;
1718
+ }
1719
+
1720
+ /* ---------- Detail (collapsible technical info、 dev mode 用) ---------- */
1721
+
1722
+ .creo-error-boundary-detail {
1723
+ margin-top: var(--spacing-s);
1724
+ text-align: left;
1725
+ width: 100%;
1726
+ max-width: 600px;
1727
+ }
1728
+
1729
+ .creo-error-boundary-detail summary {
1730
+ cursor: pointer;
1731
+ font-size: var(--typography-body-helper);
1732
+ color: var(--color-text-tertiary);
1733
+ font-family: var(--typography-family-mono);
1734
+ padding: var(--spacing-xs) var(--spacing-s);
1735
+ border-radius: var(--radius-xs);
1736
+ transition: background-color var(--motion-mapping-hover-duration)
1737
+ var(--motion-mapping-hover-easing), color var(--motion-mapping-hover-duration)
1738
+ var(--motion-mapping-hover-easing);
1739
+ }
1740
+
1741
+ .creo-error-boundary-detail summary:hover {
1742
+ background-color: var(--color-surface-bg-subtle);
1743
+ color: var(--color-text-primary);
1744
+ }
1745
+
1746
+ .creo-error-boundary-detail pre {
1747
+ margin: var(--spacing-xs) 0 0 0;
1748
+ padding: var(--spacing-s);
1749
+ font-family: var(--typography-family-mono);
1750
+ font-size: var(--typography-body-caption);
1751
+ background-color: var(--color-surface-bg-subtle);
1752
+ border: 1px solid var(--color-surface-border);
1753
+ border-radius: var(--radius-s);
1754
+ overflow-x: auto;
1755
+ color: var(--color-text-primary);
1756
+ }
1757
+
1758
+ /* ---------- Actions (CTA group) ---------- */
1759
+
1760
+ .creo-error-boundary-actions {
1761
+ display: flex;
1762
+ gap: var(--spacing-s);
1763
+ margin-top: var(--spacing-s);
1764
+ flex-wrap: wrap;
1765
+ justify-content: center;
1766
+ }
1767
+
1768
+ /* ---------- Reduced motion (a11y baseline) ---------- */
1769
+
1770
+ @media (prefers-reduced-motion: reduce) {
1771
+ .creo-error-boundary-detail summary {
1772
+ transition: none;
1773
+ }
1774
+ }
1775
+
1776
+ /* ================ form-controls.css ================ */
1777
+ /**
1778
+ * creoui — Form controls (Checkbox / Radio / Switch)
1779
+ *
1780
+ * native <input> を accent-color で brand 色に染める最小実装 + switch (native 非対応) の custom painting。
1781
+ *
1782
+ * Spec: docs/components/form-controls.md
1783
+ * Token: creoui/tokens.css (必須)
1784
+ */
1785
+
1786
+ /* ---------- Checkbox / Radio (label wrapper) ---------- */
1787
+
1788
+ .creo-checkbox,
1789
+ .creo-radio {
1790
+ display: inline-flex;
1791
+ align-items: center;
1792
+ gap: var(--layout-gap-tight);
1793
+ font-size: var(--typography-size-m);
1794
+ line-height: 1.4;
1795
+ color: var(--color-text-primary);
1796
+ cursor: pointer;
1797
+ user-select: none;
1798
+ }
1799
+
1800
+ .creo-checkbox-input,
1801
+ .creo-radio-input {
1802
+ accent-color: var(--color-brand-primary);
1803
+ width: 1.1em;
1804
+ height: 1.1em;
1805
+ cursor: pointer;
1806
+ margin: 0;
1807
+ flex-shrink: 0;
1808
+ }
1809
+
1810
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
1811
+
1812
+ .creo-checkbox-input:disabled,
1813
+ .creo-radio-input:disabled,
1814
+ .creo-checkbox:has(> .creo-checkbox-input:disabled),
1815
+ .creo-radio:has(> .creo-radio-input:disabled) {
1816
+ opacity: 0.5;
1817
+ cursor: not-allowed;
1818
+ }
1819
+
1820
+ /* ---------- Switch (custom toggle) ---------- */
1821
+
1822
+ .creo-switch {
1823
+ display: inline-flex;
1824
+ align-items: center;
1825
+ gap: var(--layout-gap-tight);
1826
+ font-size: var(--typography-size-m);
1827
+ line-height: 1.4;
1828
+ color: var(--color-text-primary);
1829
+ cursor: pointer;
1830
+ user-select: none;
1831
+ }
1832
+
1833
+ .creo-switch-input {
1834
+ /* native checkbox を隠す (visually-hidden、a11y 保持) */
1835
+ position: absolute;
1836
+ width: 1px;
1837
+ height: 1px;
1838
+ padding: 0;
1839
+ margin: -1px;
1840
+ overflow: hidden;
1841
+ clip: rect(0, 0, 0, 0);
1842
+ white-space: nowrap;
1843
+ border: 0;
1844
+ }
1845
+
1846
+ .creo-switch-track {
1847
+ display: inline-block;
1848
+ position: relative;
1849
+ width: 44px;
1850
+ height: 24px;
1851
+ background-color: var(--color-surface-bg-subtle);
1852
+ border: 1px solid var(--color-surface-border);
1853
+ border-radius: var(--radius-full);
1854
+ transition: background-color var(--motion-mapping-toggle-duration)
1855
+ var(--motion-mapping-toggle-easing), border-color var(--motion-mapping-toggle-duration)
1856
+ var(--motion-mapping-toggle-easing);
1857
+ flex-shrink: 0;
1858
+ }
1859
+
1860
+ .creo-switch-thumb {
1861
+ position: absolute;
1862
+ top: 2px;
1863
+ left: 2px;
1864
+ width: 18px;
1865
+ height: 18px;
1866
+ background-color: var(--color-surface-surface);
1867
+ border-radius: var(--radius-full);
1868
+ box-shadow: var(--shadow-s);
1869
+ transition: transform var(--motion-mapping-toggle-duration) var(--motion-mapping-toggle-easing);
1870
+ }
1871
+
1872
+ .creo-switch-input:checked ~ .creo-switch-track {
1873
+ background-color: var(--color-brand-primary);
1874
+ border-color: var(--color-brand-primary);
1875
+ }
1876
+
1877
+ .creo-switch-input:checked ~ .creo-switch-track .creo-switch-thumb {
1878
+ transform: translateX(20px);
1879
+ }
1880
+
1881
+ /* Switch の :focus-visible は track 側に ring を当てる必要があるため、 _focus.css
1882
+ の policy では cover できない (selector が `~` sibling 経由)。 個別 articulate
1883
+ を維持、 ただし新 token を使用。 */
1884
+ .creo-switch-input:focus-visible ~ .creo-switch-track {
1885
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--color-focus-ring-color);
1886
+ outline-offset: var(--focus-ring-offset);
1887
+ box-shadow: 0 0 0 var(--focus-ring-halo-width) var(--color-focus-ring-halo);
1888
+ }
1889
+
1890
+ .creo-switch-input:disabled ~ .creo-switch-track,
1891
+ .creo-switch:has(> .creo-switch-input:disabled) {
1892
+ opacity: 0.5;
1893
+ cursor: not-allowed;
1894
+ }
1895
+
1896
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
1897
+
1898
+ @media (prefers-reduced-motion: reduce) {
1899
+ .creo-switch-track,
1900
+ .creo-switch-thumb {
1901
+ transition: none;
1902
+ transform: none;
1903
+ }
1904
+ }
1905
+
1906
+ /* ================ form-field.css ================ */
1907
+ /**
1908
+ * creoui — FormField utility
1909
+ *
1910
+ * label + input + helper-text を垂直 stack で束ねる minimal wrapper。
1911
+ * component ではなく CSS class utility として提供。
1912
+ *
1913
+ * Spec: docs/components/form-field.md
1914
+ * Token: creoui/tokens.css (必須)
1915
+ */
1916
+
1917
+ .creo-form-field {
1918
+ display: grid;
1919
+ gap: var(--spacing-xs);
1920
+ }
1921
+
1922
+ .creo-form-field-label {
1923
+ font-size: var(--typography-body-helper);
1924
+ font-weight: var(--typography-weight-medium);
1925
+ color: var(--color-text-primary);
1926
+ line-height: var(--typography-line-height-normal);
1927
+ }
1928
+
1929
+ /* required モディファイア: label の末尾に * (semantic-error 色) を付与 */
1930
+ .creo-form-field-required::after {
1931
+ content: " *";
1932
+ color: var(--color-semantic-error);
1933
+ font-weight: var(--typography-weight-medium);
1934
+ }
1935
+
1936
+ /* ================ grid.css ================ */
1937
+ /**
1938
+ * creoui — Grid (CSS Grid layout primitive)
1939
+ *
1940
+ * 2D layout primitive。 column 数を `data-cols` で指定 (1/2/3/4/6/12)、 gap は spacing token、
1941
+ * responsive breakpoint は consumer 側で別途 (token として将来追加検討)。
1942
+ *
1943
+ * Spec: docs/components/grid.md
1944
+ * Token: creoui/tokens.css (必須)
1945
+ */
1946
+
1947
+ .creo-grid {
1948
+ display: grid;
1949
+ gap: var(--spacing-m);
1950
+ /* default 12 column (web standard) */
1951
+ grid-template-columns: repeat(12, 1fr);
1952
+ }
1953
+
1954
+ /* ---------- Column count ---------- */
1955
+
1956
+ .creo-grid[data-cols="1"] {
1957
+ grid-template-columns: 1fr;
1958
+ }
1959
+ .creo-grid[data-cols="2"] {
1960
+ grid-template-columns: repeat(2, 1fr);
1961
+ }
1962
+ .creo-grid[data-cols="3"] {
1963
+ grid-template-columns: repeat(3, 1fr);
1964
+ }
1965
+ .creo-grid[data-cols="4"] {
1966
+ grid-template-columns: repeat(4, 1fr);
1967
+ }
1968
+ .creo-grid[data-cols="6"] {
1969
+ grid-template-columns: repeat(6, 1fr);
1970
+ }
1971
+ .creo-grid[data-cols="12"] {
1972
+ grid-template-columns: repeat(12, 1fr);
1973
+ }
1974
+
1975
+ /* ---------- Gap (token-driven、 5-step rule) ---------- */
1976
+
1977
+ .creo-grid[data-gap="xs"] {
1978
+ gap: var(--spacing-xs);
1979
+ }
1980
+ .creo-grid[data-gap="s"] {
1981
+ gap: var(--spacing-s);
1982
+ }
1983
+ .creo-grid[data-gap="m"] {
1984
+ gap: var(--spacing-m);
1985
+ }
1986
+ .creo-grid[data-gap="l"] {
1987
+ gap: var(--spacing-l);
1988
+ }
1989
+ .creo-grid[data-gap="xl"] {
1990
+ gap: var(--spacing-xl);
1991
+ }
1992
+
1993
+ /* ---------- Auto-fit (responsive、 min-column-width 基準、 5 tier xs/s/m/l/xl) ---------- */
1994
+
1995
+ .creo-grid[data-cols="auto-xs"] {
1996
+ grid-template-columns: repeat(auto-fit, minmax(var(--layout-grid-col-min-xs), 1fr));
1997
+ }
1998
+ .creo-grid[data-cols="auto-s"] {
1999
+ grid-template-columns: repeat(auto-fit, minmax(var(--layout-grid-col-min-s), 1fr));
2000
+ }
2001
+ .creo-grid[data-cols="auto-m"] {
2002
+ grid-template-columns: repeat(auto-fit, minmax(var(--layout-grid-col-min-m), 1fr));
2003
+ }
2004
+ .creo-grid[data-cols="auto-l"] {
2005
+ grid-template-columns: repeat(auto-fit, minmax(var(--layout-grid-col-min-l), 1fr));
2006
+ }
2007
+ .creo-grid[data-cols="auto-xl"] {
2008
+ grid-template-columns: repeat(auto-fit, minmax(var(--layout-grid-col-min-xl), 1fr));
2009
+ }
2010
+
2011
+ /* ================ header.css ================ */
2012
+ /**
2013
+ * creoui — Header component
2014
+ *
2015
+ * `.creo-header` base + data-variant (app / marketing) + data-sticky + data-elevation。
2016
+ * Slot classes: `.creo-header-logo` / `.creo-header-nav` / `.creo-header-actions`。
2017
+ *
2018
+ * Spec: docs/components/header.md
2019
+ * Token: creoui/tokens.css (必須)
2020
+ *
2021
+ * Usage:
2022
+ * <header class="creo-header" data-variant="app" data-sticky="true">
2023
+ * <a class="creo-header-logo">…</a>
2024
+ * <nav class="creo-header-nav">…</nav>
2025
+ * <div class="creo-header-actions">…</div>
2026
+ * </header>
2027
+ */
2028
+
2029
+ .creo-header {
2030
+ display: flex;
2031
+ align-items: center;
2032
+ gap: var(--layout-gap-sibling);
2033
+ /* padding は spacing token (--spacing-s / --spacing-m) を直接参照。
2034
+ consumer は CSS scope (例: `.creo-header { --spacing-m: 14px }`) で override 可、
2035
+ これにより `.creo-header` 内の var(--spacing-m) は scope 値を pick up
2036
+ (= Project の Size Stepper / HEADER namespace から CSS variable を inject する経路)。 */
2037
+ padding: var(--spacing-s) var(--spacing-m);
2038
+ background-color: var(--color-surface-surface);
2039
+ color: var(--color-text-primary);
2040
+ border-bottom: 1px solid var(--color-surface-border);
2041
+ transition: background-color var(--motion-mapping-hover-duration)
2042
+ var(--motion-mapping-hover-easing), box-shadow var(--motion-mapping-hover-duration)
2043
+ var(--motion-mapping-hover-easing);
2044
+ }
2045
+
2046
+ /* ---------- Variants ---------- */
2047
+
2048
+ .creo-header[data-variant="marketing"] {
2049
+ padding: var(--spacing-m) var(--spacing-xl);
2050
+ min-height: 72px;
2051
+ background-color: var(--color-surface-bg-base);
2052
+ }
2053
+
2054
+ /* app (default) は base を使う */
2055
+
2056
+ /* ---------- Sticky ---------- */
2057
+
2058
+ .creo-header[data-sticky="true"] {
2059
+ position: sticky;
2060
+ top: 0;
2061
+ z-index: 50;
2062
+ backdrop-filter: blur(8px);
2063
+ -webkit-backdrop-filter: blur(8px);
2064
+ background-color: color-mix(in oklch, var(--color-surface-surface) 85%, transparent);
2065
+ }
2066
+
2067
+ .creo-header[data-variant="marketing"][data-sticky="true"] {
2068
+ background-color: color-mix(in oklch, var(--color-surface-bg-base) 85%, transparent);
2069
+ }
2070
+
2071
+ /* ---------- Elevation ---------- */
2072
+
2073
+ .creo-header[data-elevation="none"] {
2074
+ border-bottom: none;
2075
+ box-shadow: none;
2076
+ }
2077
+ .creo-header[data-elevation="s"],
2078
+ .creo-header:not([data-elevation]) {
2079
+ border-bottom: 1px solid var(--color-surface-border);
2080
+ box-shadow: none;
2081
+ }
2082
+ .creo-header[data-elevation="m"] {
2083
+ border-bottom: none;
2084
+ box-shadow: var(--shadow-s);
2085
+ }
2086
+
2087
+ /* ---------- Slots ---------- */
2088
+
2089
+ .creo-header-logo {
2090
+ display: inline-flex;
2091
+ align-items: center;
2092
+ gap: var(--layout-gap-tight);
2093
+ font-size: var(--typography-title-card);
2094
+ font-weight: var(--typography-weight-semibold);
2095
+ color: var(--color-text-primary);
2096
+ text-decoration: none;
2097
+ flex-shrink: 0;
2098
+ }
2099
+ .creo-header-logo:hover {
2100
+ color: var(--color-brand-primary);
2101
+ }
2102
+ .creo-header-logo img,
2103
+ .creo-header-logo svg {
2104
+ width: 1.5em;
2105
+ height: 1.5em;
2106
+ display: block;
2107
+ }
2108
+
2109
+ .creo-header-nav {
2110
+ display: flex;
2111
+ align-items: center;
2112
+ gap: var(--spacing-m);
2113
+ flex: 1;
2114
+ min-width: 0;
2115
+ /* nav を logo の直後から流す (app)、marketing では中央寄せも consumer で可 */
2116
+ }
2117
+ .creo-header-nav a {
2118
+ color: var(--color-text-secondary);
2119
+ text-decoration: none;
2120
+ font-size: var(--typography-size-m);
2121
+ font-weight: var(--typography-weight-regular);
2122
+ padding: var(--spacing-xs) var(--spacing-s);
2123
+ border-radius: var(--radius-xs);
2124
+ transition: color var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing),
2125
+ background-color var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing);
2126
+ }
2127
+ .creo-header-nav a:hover,
2128
+ .creo-header-nav a[aria-current="page"] {
2129
+ color: var(--color-text-primary);
2130
+ background-color: var(--color-surface-bg-subtle);
2131
+ }
2132
+
2133
+ .creo-header-actions {
2134
+ display: inline-flex;
2135
+ align-items: center;
2136
+ gap: var(--layout-gap-tight);
2137
+ flex-shrink: 0;
2138
+ margin-left: auto;
2139
+ }
2140
+
2141
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
2142
+
2143
+ @media (prefers-reduced-motion: reduce) {
2144
+ .creo-header,
2145
+ .creo-header-nav a {
2146
+ transition: none;
2147
+ transform: none;
2148
+ }
2149
+ }
2150
+
2151
+ /* ================ icon.css ================ */
2152
+ /**
2153
+ * creoui — Iconography primitive
2154
+ *
2155
+ * Spec: docs/components/icon.md (今後)
2156
+ * Token: creoui/tokens.css (必須)
2157
+ *
2158
+ * Usage:
2159
+ * <span class="creoui-icon" data-size="m"></span> <!-- Nerd Font glyph -->
2160
+ * <i class="creoui-icon" data-size="l">★</i> <!-- Unicode emoji -->
2161
+ *
2162
+ * Aesthetic:
2163
+ * typography.family.icon (Symbols Nerd Font + OS native emoji fallback) を
2164
+ * default font-stack、 typography.icon scale (xs/s/m/l/xl) で size articulate。
2165
+ * color は currentColor (consumer が container text-color から継承)、
2166
+ * icon-specific color が必要な場合は inline style で。
2167
+ *
2168
+ * Iconify icon (creoui-icons-web) との 差別化:
2169
+ * - .creoui-icon = Nerd Font glyph (font-based、 limit 10k icons、 single color)
2170
+ * - <Icon> from creoui-icons-web = Iconify SVG (multi-color、 dynamic、 flexible)
2171
+ *
2172
+ * Use case による選択:
2173
+ * - inline / dense / mono color → .creoui-icon (CSS-only、 軽量)
2174
+ * - hero / multi-color / specific brand icon → Iconify (multi-color、 SVG)
2175
+ */
2176
+
2177
+ .creoui-icon {
2178
+ display: inline-flex;
2179
+ align-items: center;
2180
+ justify-content: center;
2181
+ font-family: var(--typography-family-icon);
2182
+ font-size: var(--typography-icon-s);
2183
+ line-height: 1;
2184
+ color: currentColor;
2185
+ user-select: none;
2186
+ /* Vertical align with surrounding text */
2187
+ vertical-align: middle;
2188
+ /* Prevent emoji from being colored by font color */
2189
+ font-feature-settings: "liga" off;
2190
+ }
2191
+
2192
+ /* ---------- Sizes (typography.icon scale を bind) ---------- */
2193
+
2194
+ .creoui-icon[data-size="xs"] {
2195
+ font-size: var(--typography-icon-xs); /* 1rem (16px) — inline mark */
2196
+ }
2197
+
2198
+ .creoui-icon[data-size="s"],
2199
+ .creoui-icon:not([data-size]) {
2200
+ font-size: var(--typography-icon-s); /* 1.5rem (24px) — button leading */
2201
+ }
2202
+
2203
+ .creoui-icon[data-size="m"] {
2204
+ font-size: var(--typography-icon-m); /* 2.5rem (40px) — list item */
2205
+ }
2206
+
2207
+ .creoui-icon[data-size="l"] {
2208
+ font-size: var(--typography-icon-l); /* 4rem (64px) — empty-state default */
2209
+ }
2210
+
2211
+ .creoui-icon[data-size="xl"] {
2212
+ font-size: var(--typography-icon-xl); /* 6rem (96px) — hero / onboarding */
2213
+ }
2214
+
2215
+ /* ---------- Semantic variants (color override) ---------- */
2216
+
2217
+ .creoui-icon[data-variant="primary"] {
2218
+ color: var(--color-brand-primary);
2219
+ }
2220
+
2221
+ .creoui-icon[data-variant="secondary"] {
2222
+ color: var(--color-brand-secondary);
2223
+ }
2224
+
2225
+ .creoui-icon[data-variant="success"] {
2226
+ color: var(--color-semantic-success);
2227
+ }
2228
+
2229
+ .creoui-icon[data-variant="warning"] {
2230
+ color: var(--color-semantic-warning);
2231
+ }
2232
+
2233
+ .creoui-icon[data-variant="error"] {
2234
+ color: var(--color-semantic-error);
2235
+ }
2236
+
2237
+ .creoui-icon[data-variant="info"] {
2238
+ color: var(--color-semantic-info);
2239
+ }
2240
+
2241
+ .creoui-icon[data-variant="muted"] {
2242
+ color: var(--color-text-tertiary);
2243
+ opacity: 0.7;
2244
+ }
2245
+
2246
+ /* ================ input.css ================ */
2247
+ /**
2248
+ * creoui — Input component
2249
+ *
2250
+ * `.creo-input` base + data-variant (bordered / filled) + data-size (s/m/lg) + data-state (default/error)。
2251
+ *
2252
+ * Spec: docs/components/input.md
2253
+ * Token: creoui/tokens.css (必須)
2254
+ *
2255
+ * Usage:
2256
+ * <input class="creo-input" type="text">
2257
+ * <input class="creo-input" type="email" data-variant="filled" data-size="l">
2258
+ * <input class="creo-input" data-state="error" aria-invalid="true">
2259
+ */
2260
+
2261
+ .creo-input {
2262
+ /* density scale 適用 (default 1)、 ancestor [data-density] で切替 */
2263
+ display: block;
2264
+ width: 100%;
2265
+ min-height: calc(var(--layout-target-tap) * var(--density-min-height-scale, 1));
2266
+ padding: calc(var(--spacing-s) * var(--density-padding-scale, 1))
2267
+ calc(var(--spacing-m) * var(--density-padding-scale, 1));
2268
+ box-sizing: border-box;
2269
+
2270
+ font-family: inherit;
2271
+ font-size: var(--typography-size-m);
2272
+ font-weight: var(--typography-weight-regular);
2273
+ line-height: 1.4;
2274
+ color: var(--color-text-primary);
2275
+
2276
+ background-color: var(--color-surface-surface);
2277
+ border: 1px solid var(--color-surface-border);
2278
+ border-radius: var(--radius-s);
2279
+
2280
+ outline: none;
2281
+ transition: border-color var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing),
2282
+ background-color var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing),
2283
+ box-shadow var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing);
2284
+ }
2285
+
2286
+ .creo-input::placeholder {
2287
+ color: var(--color-text-tertiary);
2288
+ }
2289
+
2290
+ /* ---------- Variants ---------- */
2291
+
2292
+ .creo-input[data-variant="filled"] {
2293
+ background-color: var(--color-surface-bg-subtle);
2294
+ border-color: transparent;
2295
+ }
2296
+ .creo-input[data-variant="filled"]:hover:not(:disabled):not(:focus) {
2297
+ background-color: var(--color-surface-bg-subtle);
2298
+ }
2299
+
2300
+ /* bordered (default) は base を使う */
2301
+
2302
+ /* ---------- Sizes ---------- */
2303
+
2304
+ .creo-input[data-size="s"] {
2305
+ min-height: var(--layout-target-focus);
2306
+ padding: var(--spacing-xs) var(--spacing-s);
2307
+ font-size: var(--typography-size-s);
2308
+ border-radius: var(--radius-xs);
2309
+ }
2310
+ .creo-input[data-size="m"],
2311
+ .creo-input:not([data-size]) {
2312
+ min-height: var(--layout-target-tap);
2313
+ padding: var(--spacing-s) var(--spacing-m);
2314
+ font-size: var(--typography-size-m);
2315
+ border-radius: var(--radius-s);
2316
+ }
2317
+ .creo-input[data-size="l"] {
2318
+ min-height: calc(var(--layout-target-tap) * 1.15);
2319
+ padding: var(--spacing-m) var(--spacing-l);
2320
+ font-size: var(--typography-size-l);
2321
+ border-radius: var(--radius-m);
2322
+ }
2323
+
2324
+ /* ---------- State: focus ---------- */
2325
+ /* :focus は mouse + keyboard 両方で発火、 input 特有の "field active" feedback
2326
+ として border-color 変化を維持。 outline + halo 表現は _focus.css の policy
2327
+ (`:focus-visible`、 keyboard-only) が担う。 */
2328
+
2329
+ .creo-input:focus {
2330
+ border-color: var(--color-focus-ring-color);
2331
+ }
2332
+
2333
+ /* ---------- State: error ---------- */
2334
+
2335
+ .creo-input[data-state="error"],
2336
+ .creo-input[aria-invalid="true"] {
2337
+ border-color: var(--color-semantic-error);
2338
+ border-width: 1.5px;
2339
+ }
2340
+ .creo-input[data-state="error"]:focus-visible,
2341
+ .creo-input[aria-invalid="true"]:focus-visible {
2342
+ box-shadow: 0 0 0 2px color-mix(in oklch, var(--color-semantic-error) 25%, transparent);
2343
+ }
2344
+
2345
+ /* ---------- State: disabled / readonly ---------- */
2346
+
2347
+ .creo-input:disabled {
2348
+ cursor: not-allowed;
2349
+ opacity: 0.6;
2350
+ background-color: var(--color-surface-bg-subtle);
2351
+ }
2352
+ .creo-input:read-only:not(:disabled) {
2353
+ background-color: var(--color-surface-bg-subtle);
2354
+ color: var(--color-text-secondary);
2355
+ }
2356
+
2357
+ /* ---------- Helper text (label / error) ---------- */
2358
+
2359
+ .creo-helper-text {
2360
+ display: block;
2361
+ margin-top: var(--spacing-xs);
2362
+ font-size: var(--typography-body-caption);
2363
+ color: var(--color-text-tertiary);
2364
+ line-height: var(--typography-line-height-normal);
2365
+ }
2366
+ .creo-helper-text--error {
2367
+ color: var(--color-semantic-error);
2368
+ }
2369
+
2370
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
2371
+
2372
+ @media (prefers-reduced-motion: reduce) {
2373
+ .creo-input {
2374
+ transition: none;
2375
+ transform: none;
2376
+ }
2377
+ }
2378
+
2379
+ /* ================ menu.css ================ */
2380
+ /**
2381
+ * creoui — Menu (Dropdown, popover-based)
2382
+ *
2383
+ * native `popover` API を推奨。consumer は `<div popover="auto">` + `popovertarget` で
2384
+ * open/close 制御、JS 最小化。
2385
+ *
2386
+ * Spec: docs/components/menu.md
2387
+ * Token: creoui/tokens.css (必須)
2388
+ */
2389
+
2390
+ .creo-menu {
2391
+ /* popover 指定時は browser が position fixed + top-layer に配置するので、
2392
+ ここは box-style のみを指定。placement (position) は consumer 側 JS or
2393
+ data-placement + anchor positioning (browser 対応進行中) で後付け。 */
2394
+ min-width: 180px;
2395
+ padding: var(--spacing-xs);
2396
+ background-color: var(--color-surface-surface);
2397
+ border: 1px solid var(--color-surface-border);
2398
+ border-radius: var(--radius-m);
2399
+ box-shadow: var(--shadow-l);
2400
+ color: var(--color-text-primary);
2401
+ font-family: inherit;
2402
+ font-size: var(--typography-size-m);
2403
+
2404
+ /* popover 無しで手動配置する場合の保険 */
2405
+ position: absolute;
2406
+ margin: 0;
2407
+ }
2408
+
2409
+ /* popover backdrop: 薄く blur (native popover=auto の自動 backdrop) */
2410
+ .creo-menu::backdrop {
2411
+ background-color: transparent;
2412
+ }
2413
+
2414
+ /* ---------- Menu item ---------- */
2415
+
2416
+ .creo-menu-item {
2417
+ appearance: none;
2418
+ background: transparent;
2419
+ border: none;
2420
+ width: 100%;
2421
+ display: flex;
2422
+ align-items: center;
2423
+ gap: var(--layout-gap-tight);
2424
+ padding: var(--spacing-xs) var(--spacing-s);
2425
+ min-height: var(--layout-target-focus);
2426
+
2427
+ font-family: inherit;
2428
+ font-size: var(--typography-size-m);
2429
+ color: var(--color-text-primary);
2430
+ text-align: left;
2431
+ text-decoration: none;
2432
+ cursor: pointer;
2433
+ border-radius: var(--radius-xs);
2434
+
2435
+ transition: background-color var(--motion-mapping-hover-duration)
2436
+ var(--motion-mapping-hover-easing), color var(--motion-mapping-hover-duration)
2437
+ var(--motion-mapping-hover-easing);
2438
+ }
2439
+
2440
+ .creo-menu-item:hover:not(:disabled),
2441
+ .creo-menu-item:focus-visible {
2442
+ background-color: var(--color-surface-bg-subtle);
2443
+ outline: none;
2444
+ }
2445
+
2446
+ .creo-menu-item:disabled {
2447
+ opacity: 0.5;
2448
+ cursor: not-allowed;
2449
+ }
2450
+
2451
+ /* ---------- Destructive variant ---------- */
2452
+
2453
+ .creo-menu-item[data-variant="destructive"] {
2454
+ color: var(--color-semantic-error);
2455
+ }
2456
+ .creo-menu-item[data-variant="destructive"]:hover:not(:disabled),
2457
+ .creo-menu-item[data-variant="destructive"]:focus-visible {
2458
+ background-color: color-mix(in oklch, var(--color-semantic-error) 12%, transparent);
2459
+ }
2460
+
2461
+ /* ---------- Separator ---------- */
2462
+
2463
+ .creo-menu-separator {
2464
+ height: 1px;
2465
+ background-color: var(--color-surface-border);
2466
+ border: none;
2467
+ margin: var(--spacing-xs) 0;
2468
+ }
2469
+
2470
+ /* ---------- Group label ---------- */
2471
+
2472
+ .creo-menu-label {
2473
+ padding: var(--spacing-xs) var(--spacing-s) 2px;
2474
+ font-size: var(--typography-body-caption);
2475
+ font-weight: var(--typography-weight-medium);
2476
+ color: var(--color-text-tertiary);
2477
+ text-transform: uppercase;
2478
+ letter-spacing: 0.04em;
2479
+ user-select: none;
2480
+ }
2481
+
2482
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
2483
+
2484
+ @media (prefers-reduced-motion: reduce) {
2485
+ .creo-menu-item {
2486
+ transition: none;
2487
+ transform: none;
2488
+ }
2489
+ }
2490
+
2491
+ /* ================ pagination.css ================ */
2492
+ /**
2493
+ * creoui — Pagination
2494
+ *
2495
+ * Spec: docs/components/pagination.md
2496
+ * Token: creoui/tokens.css (必須)
2497
+ */
2498
+
2499
+ .creo-pagination {
2500
+ display: inline-flex;
2501
+ align-items: center;
2502
+ gap: var(--spacing-xs);
2503
+ }
2504
+
2505
+ .creo-pagination[data-variant="compact"] {
2506
+ gap: 0;
2507
+ }
2508
+
2509
+ .creo-pagination-list {
2510
+ display: inline-flex;
2511
+ align-items: center;
2512
+ gap: var(--spacing-xs);
2513
+ padding: 0;
2514
+ margin: 0;
2515
+ list-style: none;
2516
+ }
2517
+
2518
+ .creo-pagination[data-variant="compact"] .creo-pagination-list {
2519
+ gap: 0;
2520
+ }
2521
+
2522
+ .creo-pagination-list > li {
2523
+ list-style: none;
2524
+ }
2525
+
2526
+ /* ---------- Item (button) ---------- */
2527
+
2528
+ .creo-pagination-item {
2529
+ appearance: none;
2530
+ background: transparent;
2531
+ border: 1px solid transparent;
2532
+ min-width: var(--layout-target-focus);
2533
+ min-height: var(--layout-target-focus);
2534
+ padding: 0 var(--spacing-xs);
2535
+ border-radius: var(--radius-s);
2536
+
2537
+ display: inline-flex;
2538
+ align-items: center;
2539
+ justify-content: center;
2540
+
2541
+ font-family: inherit;
2542
+ font-size: var(--typography-size-m);
2543
+ font-weight: var(--typography-weight-medium);
2544
+ color: var(--color-text-secondary);
2545
+ cursor: pointer;
2546
+ user-select: none;
2547
+
2548
+ transition: background-color var(--motion-mapping-hover-duration)
2549
+ var(--motion-mapping-hover-easing), color var(--motion-mapping-hover-duration)
2550
+ var(--motion-mapping-hover-easing), border-color var(--motion-mapping-hover-duration)
2551
+ var(--motion-mapping-hover-easing);
2552
+ }
2553
+
2554
+ .creo-pagination-item:hover:not(:disabled):not([aria-current="page"]) {
2555
+ background-color: var(--color-surface-bg-subtle);
2556
+ color: var(--color-text-primary);
2557
+ }
2558
+
2559
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
2560
+
2561
+ .creo-pagination-item:disabled {
2562
+ opacity: 0.4;
2563
+ cursor: not-allowed;
2564
+ }
2565
+
2566
+ /* ---------- Active (aria-current=page) ---------- */
2567
+
2568
+ .creo-pagination-item[aria-current="page"] {
2569
+ background-color: var(--color-brand-primary);
2570
+ color: var(--color-surface-bg-base);
2571
+ border-color: var(--color-brand-primary);
2572
+ cursor: default;
2573
+ }
2574
+
2575
+ /* ---------- Sizes ---------- */
2576
+
2577
+ .creo-pagination[data-size="s"] .creo-pagination-item {
2578
+ min-width: 24px;
2579
+ min-height: 24px;
2580
+ font-size: var(--typography-size-s);
2581
+ padding: 0 6px;
2582
+ border-radius: var(--radius-xs);
2583
+ }
2584
+
2585
+ .creo-pagination[data-size="l"] .creo-pagination-item {
2586
+ min-width: var(--layout-target-tap);
2587
+ min-height: var(--layout-target-tap);
2588
+ font-size: var(--typography-size-l);
2589
+ padding: 0 var(--spacing-s);
2590
+ border-radius: var(--radius-m);
2591
+ }
2592
+
2593
+ /* ---------- Ellipsis ---------- */
2594
+
2595
+ .creo-pagination-ellipsis {
2596
+ display: inline-flex;
2597
+ align-items: center;
2598
+ justify-content: center;
2599
+ min-width: var(--layout-target-focus);
2600
+ color: var(--color-text-tertiary);
2601
+ user-select: none;
2602
+ font-weight: var(--typography-weight-medium);
2603
+ }
2604
+
2605
+ /* ---------- Prev/Next button 装飾 (data-action) ---------- */
2606
+
2607
+ .creo-pagination-item[data-action="prev"],
2608
+ .creo-pagination-item[data-action="next"] {
2609
+ color: var(--color-text-primary);
2610
+ }
2611
+
2612
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
2613
+
2614
+ @media (prefers-reduced-motion: reduce) {
2615
+ .creo-pagination-item {
2616
+ transition: none;
2617
+ transform: none;
2618
+ }
2619
+ }
2620
+
2621
+ /* ================ popover.css ================ */
2622
+ /**
2623
+ * creoui — Popover (interactive overlay)
2624
+ *
2625
+ * Menu は action list only、Dialog は重要決定 (modal)。Popover はその中間 —
2626
+ * 小さい interactive content (inline edit / preview / quick confirm)。
2627
+ *
2628
+ * native `popover="auto"` を推奨。browser が outside click / Esc を自動 handle。
2629
+ *
2630
+ * Spec: docs/components/popover.md
2631
+ * Token: creoui/tokens.css (必須)
2632
+ */
2633
+
2634
+ .creo-popover {
2635
+ /* popover 指定時は browser が top-layer に配置 */
2636
+ padding: 0;
2637
+ background-color: var(--color-surface-surface);
2638
+ color: var(--color-text-primary);
2639
+ border: 1px solid var(--color-surface-border);
2640
+ border-radius: var(--radius-m);
2641
+ box-shadow: var(--shadow-l);
2642
+ font-family: inherit;
2643
+ font-size: var(--typography-size-m);
2644
+ line-height: var(--typography-line-height-normal);
2645
+
2646
+ /* popover 無しで手動配置する場合の fallback */
2647
+ margin: 0;
2648
+ position: absolute;
2649
+ overflow: hidden;
2650
+
2651
+ /* Size default (md) */
2652
+ width: min(90vw, 320px);
2653
+ max-height: 70vh;
2654
+ display: flex;
2655
+ flex-direction: column;
2656
+ }
2657
+
2658
+ .creo-popover::backdrop {
2659
+ /* popover="auto" の backdrop を透過 (Dialog と違って dim しない) */
2660
+ background-color: transparent;
2661
+ }
2662
+
2663
+ /* ---------- Sizes ---------- */
2664
+
2665
+ .creo-popover[data-size="s"] {
2666
+ width: min(90vw, 240px);
2667
+ }
2668
+ .creo-popover[data-size="m"],
2669
+ .creo-popover:not([data-size]) {
2670
+ width: min(90vw, 320px);
2671
+ }
2672
+ .creo-popover[data-size="l"] {
2673
+ width: min(92vw, 480px);
2674
+ }
2675
+
2676
+ /* ---------- Variants ---------- */
2677
+
2678
+ .creo-popover[data-variant="muted"] {
2679
+ background-color: var(--color-surface-bg-subtle);
2680
+ }
2681
+
2682
+ /* ---------- Slots ---------- */
2683
+
2684
+ .creo-popover-header {
2685
+ padding: var(--spacing-s) var(--spacing-m);
2686
+ border-bottom: 1px solid var(--color-surface-border);
2687
+ }
2688
+
2689
+ .creo-popover-title {
2690
+ margin: 0;
2691
+ font-size: var(--typography-title-card);
2692
+ font-weight: var(--typography-weight-semibold);
2693
+ color: var(--color-text-primary);
2694
+ line-height: 1.3;
2695
+ }
2696
+
2697
+ .creo-popover-body {
2698
+ padding: var(--spacing-m);
2699
+ overflow-y: auto;
2700
+ flex: 1;
2701
+ min-height: 0;
2702
+ }
2703
+ .creo-popover-body > * + * {
2704
+ margin-top: var(--spacing-s);
2705
+ }
2706
+
2707
+ .creo-popover-footer {
2708
+ display: flex;
2709
+ align-items: center;
2710
+ justify-content: flex-end;
2711
+ gap: var(--layout-gap-tight);
2712
+ padding: var(--spacing-s) var(--spacing-m);
2713
+ border-top: 1px solid var(--color-surface-border);
2714
+ }
2715
+
2716
+ /* ---------- Entrance animation (gentle) ---------- */
2717
+
2718
+ .creo-popover:popover-open {
2719
+ animation: creoPopoverIn var(--motion-mapping-dropdown-duration)
2720
+ var(--motion-mapping-dropdown-easing);
2721
+ }
2722
+
2723
+ @keyframes creoPopoverIn {
2724
+ from {
2725
+ opacity: 0;
2726
+ transform: translateY(4px) scale(0.98);
2727
+ }
2728
+ to {
2729
+ opacity: 1;
2730
+ transform: translateY(0) scale(1);
2731
+ }
2732
+ }
2733
+
2734
+ @media (prefers-reduced-motion: reduce) {
2735
+ .creo-popover:popover-open {
2736
+ animation: none;
2737
+ }
2738
+ }
2739
+
2740
+ /* ================ progress.css ================ */
2741
+ /**
2742
+ * creoui — Progress bar + Spinner
2743
+ *
2744
+ * Spec: docs/components/progress.md
2745
+ * Token: creoui/tokens.css (必須)
2746
+ */
2747
+
2748
+ /* ================================================= */
2749
+ /* Progress (bar) */
2750
+ /* ================================================= */
2751
+
2752
+ .creo-progress {
2753
+ display: block;
2754
+ width: 100%;
2755
+ height: 8px;
2756
+ background-color: var(--color-surface-bg-subtle);
2757
+ border-radius: var(--radius-full);
2758
+ overflow: hidden;
2759
+ }
2760
+
2761
+ .creo-progress-fill {
2762
+ height: 100%;
2763
+ background-color: var(--color-brand-primary);
2764
+ border-radius: inherit;
2765
+ transition: width var(--motion-mapping-toggle-duration) var(--motion-mapping-toggle-easing);
2766
+ }
2767
+
2768
+ /* ---------- Sizes ---------- */
2769
+
2770
+ .creo-progress[data-size="s"] {
2771
+ height: 4px;
2772
+ }
2773
+ .creo-progress[data-size="l"] {
2774
+ height: 12px;
2775
+ }
2776
+
2777
+ /* ---------- Variants ---------- */
2778
+
2779
+ .creo-progress[data-variant="success"] .creo-progress-fill {
2780
+ background-color: var(--color-semantic-success);
2781
+ }
2782
+ .creo-progress[data-variant="warning"] .creo-progress-fill {
2783
+ background-color: var(--color-semantic-warning);
2784
+ }
2785
+ .creo-progress[data-variant="error"] .creo-progress-fill {
2786
+ background-color: var(--color-semantic-error);
2787
+ }
2788
+
2789
+ /* ---------- Indeterminate (流れる風アニメ) ---------- */
2790
+
2791
+ .creo-progress[data-indeterminate="true"] .creo-progress-fill {
2792
+ width: 40%;
2793
+ /* Note: indeterminate cycle 1.4s は keyframes 専用、 easing は mapping
2794
+ progress-indeterminate (linear) を使用すべきだが、 perceived motion 上
2795
+ in-out の方が「波打つ」 visible で good、 ここは override で残す。 */
2796
+ animation: creoProgressIndeterminate 1.4s var(--motion-easing-in-out) infinite;
2797
+ }
2798
+
2799
+ @keyframes creoProgressIndeterminate {
2800
+ 0% {
2801
+ transform: translateX(-100%);
2802
+ }
2803
+ 100% {
2804
+ transform: translateX(250%);
2805
+ }
2806
+ }
2807
+
2808
+ /* ================================================= */
2809
+ /* Spinner */
2810
+ /* ================================================= */
2811
+
2812
+ .creo-spinner {
2813
+ display: inline-block;
2814
+ width: 24px;
2815
+ height: 24px;
2816
+ border: 2px solid var(--color-surface-bg-subtle);
2817
+ border-top-color: var(--color-brand-primary);
2818
+ border-radius: var(--radius-full);
2819
+ animation: creoSpinnerRotate 900ms linear infinite;
2820
+ vertical-align: middle;
2821
+ }
2822
+
2823
+ @keyframes creoSpinnerRotate {
2824
+ to {
2825
+ transform: rotate(360deg);
2826
+ }
2827
+ }
2828
+
2829
+ /* ---------- Sizes ---------- */
2830
+
2831
+ .creo-spinner[data-size="s"] {
2832
+ width: 16px;
2833
+ height: 16px;
2834
+ border-width: 2px;
2835
+ }
2836
+ .creo-spinner[data-size="l"] {
2837
+ width: 40px;
2838
+ height: 40px;
2839
+ border-width: 3px;
2840
+ }
2841
+
2842
+ /* ---------- Variants ---------- */
2843
+
2844
+ .creo-spinner[data-variant="neutral"] {
2845
+ border-top-color: var(--color-text-secondary);
2846
+ }
2847
+
2848
+ /* ---------- Reduced motion ---------- */
2849
+
2850
+ @media (prefers-reduced-motion: reduce) {
2851
+ .creo-progress[data-indeterminate="true"] .creo-progress-fill {
2852
+ animation: none;
2853
+ width: 100%;
2854
+ opacity: 0.6;
2855
+ }
2856
+ .creo-spinner {
2857
+ animation-duration: 3000ms; /* 動きは残すが遅く */
2858
+ }
2859
+ }
2860
+
2861
+ /* ---------- visually-hidden helper (for SR-only text inside spinner/progress) ---------- */
2862
+
2863
+ .visually-hidden {
2864
+ position: absolute;
2865
+ width: 1px;
2866
+ height: 1px;
2867
+ padding: 0;
2868
+ margin: -1px;
2869
+ overflow: hidden;
2870
+ clip: rect(0, 0, 0, 0);
2871
+ white-space: nowrap;
2872
+ border: 0;
2873
+ }
2874
+
2875
+ /* ================ segmented.css ================ */
2876
+ /**
2877
+ * creoui — Segmented control
2878
+ *
2879
+ * 2-4 option の排他選択肢を横並びで表示。Tabs は view 切替、Segmented は state 値選択。
2880
+ *
2881
+ * Spec: docs/components/segmented.md
2882
+ * Token: creoui/tokens.css (必須)
2883
+ */
2884
+
2885
+ .creo-segmented {
2886
+ display: inline-flex;
2887
+ align-items: stretch;
2888
+ gap: var(--spacing-xs);
2889
+ padding: var(--spacing-xs);
2890
+ background-color: var(--color-surface-bg-subtle);
2891
+ border: 1px solid var(--color-surface-border);
2892
+ border-radius: var(--radius-m);
2893
+ }
2894
+
2895
+ .creo-segmented[data-width="full"] {
2896
+ display: flex;
2897
+ width: 100%;
2898
+ }
2899
+ .creo-segmented[data-width="full"] .creo-segmented-option {
2900
+ flex: 1;
2901
+ }
2902
+
2903
+ /* ---------- Option (base) ---------- */
2904
+
2905
+ .creo-segmented-option {
2906
+ appearance: none;
2907
+ background: transparent;
2908
+ border: none;
2909
+ padding: var(--spacing-xs) var(--spacing-m);
2910
+ min-height: var(--layout-target-focus);
2911
+
2912
+ display: inline-flex;
2913
+ align-items: center;
2914
+ justify-content: center;
2915
+ gap: var(--layout-gap-tight);
2916
+
2917
+ font-family: inherit;
2918
+ font-size: var(--typography-size-m);
2919
+ font-weight: var(--typography-weight-medium);
2920
+ color: var(--color-text-secondary);
2921
+
2922
+ cursor: pointer;
2923
+ border-radius: var(--radius-s);
2924
+ transition: background-color var(--motion-mapping-toggle-duration)
2925
+ var(--motion-mapping-toggle-easing), color var(--motion-mapping-toggle-duration)
2926
+ var(--motion-mapping-toggle-easing), box-shadow var(--motion-mapping-toggle-duration)
2927
+ var(--motion-mapping-toggle-easing);
2928
+ user-select: none;
2929
+ }
2930
+
2931
+ .creo-segmented-option:hover:not(:disabled) {
2932
+ color: var(--color-text-primary);
2933
+ }
2934
+
2935
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
2936
+
2937
+ .creo-segmented-option:disabled {
2938
+ opacity: 0.5;
2939
+ cursor: not-allowed;
2940
+ }
2941
+
2942
+ /* ---------- Active state (aria-pressed + :has(radio:checked)) ---------- */
2943
+
2944
+ .creo-segmented-option[aria-pressed="true"],
2945
+ .creo-segmented-option:has(> input[type="radio"]:checked) {
2946
+ background-color: var(--color-surface-surface);
2947
+ color: var(--color-brand-primary);
2948
+ box-shadow: var(--shadow-s);
2949
+ }
2950
+
2951
+ /* ---------- Radio inside (hide native input) ---------- */
2952
+
2953
+ .creo-segmented-option > input[type="radio"] {
2954
+ position: absolute;
2955
+ width: 1px;
2956
+ height: 1px;
2957
+ padding: 0;
2958
+ margin: -1px;
2959
+ overflow: hidden;
2960
+ clip: rect(0, 0, 0, 0);
2961
+ border: 0;
2962
+ }
2963
+
2964
+ /* ---------- Sizes ---------- */
2965
+
2966
+ .creo-segmented[data-size="s"] .creo-segmented-option {
2967
+ min-height: 24px;
2968
+ padding: 2px var(--spacing-s);
2969
+ font-size: var(--typography-size-s);
2970
+ }
2971
+ .creo-segmented[data-size="l"] .creo-segmented-option {
2972
+ min-height: var(--layout-target-tap);
2973
+ padding: var(--spacing-s) var(--spacing-l);
2974
+ font-size: var(--typography-size-l);
2975
+ }
2976
+
2977
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
2978
+
2979
+ @media (prefers-reduced-motion: reduce) {
2980
+ .creo-segmented-option {
2981
+ transition: none;
2982
+ transform: none;
2983
+ }
2984
+ }
2985
+
2986
+ /* ================ skeleton.css ================ */
2987
+ /**
2988
+ * creoui — Skeleton loader
2989
+ *
2990
+ * Spec: docs/components/skeleton.md
2991
+ * Token: creoui/tokens.css (必須)
2992
+ */
2993
+
2994
+ .creo-skeleton {
2995
+ display: inline-block;
2996
+ /* Shimmer は 4 family identity を articulate する peak tint を持つ:
2997
+ - bg-subtle (start) → brand-primary-subtle mix (peak) → bg-subtle (end)
2998
+ - mint なら mint tint shimmer、 sora なら cool blue、 contrast なら
2999
+ paradox violet、 oldschool なら olive。
3000
+ - color-mix で 60% brand-subtle + 40% bg-emphasis、 brand を主張しすぎず
3001
+ loading 中の identity を articulate。 */
3002
+ background: linear-gradient(
3003
+ 90deg,
3004
+ var(--color-surface-bg-subtle) 0%,
3005
+ color-mix(in oklch, var(--color-brand-primary-subtle) 60%, var(--color-surface-bg-emphasis)) 50%,
3006
+ var(--color-surface-bg-subtle) 100%
3007
+ );
3008
+ background-size: 200% 100%;
3009
+ /* Note: shimmer cycle 1.4s は keyframes 専用 (mapping lazy 480ms より長い、
3010
+ end-less perception)、 easing は mapping articulate 使用 */
3011
+ animation: creoSkeletonShimmer 1.4s var(--motion-mapping-skeleton-shimmer-easing) infinite;
3012
+ border-radius: var(--radius-s);
3013
+ width: 100%;
3014
+ height: 16px;
3015
+ vertical-align: middle;
3016
+ }
3017
+
3018
+ @keyframes creoSkeletonShimmer {
3019
+ 0% {
3020
+ background-position: 200% 0;
3021
+ }
3022
+ 100% {
3023
+ background-position: -200% 0;
3024
+ }
3025
+ }
3026
+
3027
+ /* ---------- Shapes ---------- */
3028
+
3029
+ .creo-skeleton[data-shape="text"] {
3030
+ display: block;
3031
+ height: 16px;
3032
+ border-radius: var(--radius-xs);
3033
+ margin-bottom: var(--spacing-xs);
3034
+ }
3035
+
3036
+ .creo-skeleton[data-shape="circle"] {
3037
+ width: 40px;
3038
+ height: 40px;
3039
+ border-radius: var(--radius-full);
3040
+ flex-shrink: 0;
3041
+ }
3042
+
3043
+ .creo-skeleton[data-shape="rect"],
3044
+ .creo-skeleton:not([data-shape]) {
3045
+ border-radius: var(--radius-s);
3046
+ }
3047
+
3048
+ /* ---------- Sizes (text / circle only) ---------- */
3049
+
3050
+ .creo-skeleton[data-shape="text"][data-size="s"] {
3051
+ height: 12px;
3052
+ }
3053
+ .creo-skeleton[data-shape="text"][data-size="l"] {
3054
+ height: 20px;
3055
+ }
3056
+
3057
+ .creo-skeleton[data-shape="circle"][data-size="s"] {
3058
+ width: 24px;
3059
+ height: 24px;
3060
+ }
3061
+ .creo-skeleton[data-shape="circle"][data-size="l"] {
3062
+ width: 64px;
3063
+ height: 64px;
3064
+ }
3065
+
3066
+ /* ---------- Reduced motion ---------- */
3067
+
3068
+ @media (prefers-reduced-motion: reduce) {
3069
+ .creo-skeleton {
3070
+ animation: none;
3071
+ background: var(--color-surface-bg-subtle);
3072
+ }
3073
+ }
3074
+
3075
+ /* ================ stack.css ================ */
3076
+ /**
3077
+ * creoui — Stack (vertical / horizontal flex layout primitive)
3078
+ *
3079
+ * 子要素を一方向に並べる最小 layout primitive。 default vertical (flex-direction column)、
3080
+ * `data-direction="horizontal"` で row。 gap / align / justify は token-driven。
3081
+ *
3082
+ * Spec: docs/components/stack.md
3083
+ * Token: creoui/tokens.css (必須)
3084
+ */
3085
+
3086
+ .creo-stack {
3087
+ display: flex;
3088
+ flex-direction: column;
3089
+ gap: var(--spacing-m);
3090
+ }
3091
+
3092
+ .creo-stack[data-direction="horizontal"] {
3093
+ flex-direction: row;
3094
+ }
3095
+
3096
+ /* ---------- Gap (token-driven、 5-step rule) ---------- */
3097
+
3098
+ .creo-stack[data-gap="xs"] {
3099
+ gap: var(--spacing-xs);
3100
+ }
3101
+ .creo-stack[data-gap="s"] {
3102
+ gap: var(--spacing-s);
3103
+ }
3104
+ .creo-stack[data-gap="m"] {
3105
+ gap: var(--spacing-m);
3106
+ }
3107
+ .creo-stack[data-gap="l"] {
3108
+ gap: var(--spacing-l);
3109
+ }
3110
+ .creo-stack[data-gap="xl"] {
3111
+ gap: var(--spacing-xl);
3112
+ }
3113
+
3114
+ /* ---------- Align (cross-axis) ---------- */
3115
+
3116
+ .creo-stack[data-align="start"] {
3117
+ align-items: flex-start;
3118
+ }
3119
+ .creo-stack[data-align="center"] {
3120
+ align-items: center;
3121
+ }
3122
+ .creo-stack[data-align="end"] {
3123
+ align-items: flex-end;
3124
+ }
3125
+ .creo-stack[data-align="stretch"] {
3126
+ align-items: stretch;
3127
+ }
3128
+
3129
+ /* ---------- Justify (main-axis) ---------- */
3130
+
3131
+ .creo-stack[data-justify="start"] {
3132
+ justify-content: flex-start;
3133
+ }
3134
+ .creo-stack[data-justify="center"] {
3135
+ justify-content: center;
3136
+ }
3137
+ .creo-stack[data-justify="end"] {
3138
+ justify-content: flex-end;
3139
+ }
3140
+ .creo-stack[data-justify="between"] {
3141
+ justify-content: space-between;
3142
+ }
3143
+ .creo-stack[data-justify="around"] {
3144
+ justify-content: space-around;
3145
+ }
3146
+
3147
+ /* ---------- Wrap (overflow handling) ---------- */
3148
+
3149
+ .creo-stack[data-wrap="true"] {
3150
+ flex-wrap: wrap;
3151
+ }
3152
+
3153
+ /* ================ stepper.css ================ */
3154
+ /**
3155
+ * creoui — Stepper (wizard / progress indicator)
3156
+ *
3157
+ * Spec: docs/components/stepper.md
3158
+ * Token: creoui/tokens.css (必須)
3159
+ */
3160
+
3161
+ .creo-stepper {
3162
+ display: flex;
3163
+ gap: var(--spacing-xs);
3164
+ padding: 0;
3165
+ margin: 0;
3166
+ list-style: none;
3167
+ }
3168
+
3169
+ .creo-stepper[data-orientation="horizontal"],
3170
+ .creo-stepper:not([data-orientation]) {
3171
+ flex-direction: row;
3172
+ align-items: flex-start;
3173
+ }
3174
+
3175
+ .creo-stepper[data-orientation="vertical"] {
3176
+ flex-direction: column;
3177
+ }
3178
+
3179
+ /* ---------- Item ---------- */
3180
+
3181
+ .creo-stepper-item {
3182
+ position: relative;
3183
+ display: grid;
3184
+ grid-template-columns: auto 1fr;
3185
+ grid-template-rows: auto auto;
3186
+ column-gap: var(--spacing-s);
3187
+ row-gap: 2px;
3188
+ align-items: center;
3189
+ flex: 1;
3190
+ min-width: 0;
3191
+ padding: 0;
3192
+ }
3193
+
3194
+ /* vertical の場合、item は row-wise に積む */
3195
+ .creo-stepper[data-orientation="vertical"] .creo-stepper-item {
3196
+ flex: 0 1 auto;
3197
+ padding-bottom: var(--spacing-m);
3198
+ }
3199
+
3200
+ /* connector: 次 item との繋ぎ線 */
3201
+ .creo-stepper-item:not(:last-child)::after {
3202
+ content: "";
3203
+ position: absolute;
3204
+ background-color: var(--color-surface-border);
3205
+ transition: background-color var(--motion-mapping-toggle-duration)
3206
+ var(--motion-mapping-toggle-easing);
3207
+ }
3208
+
3209
+ .creo-stepper[data-orientation="horizontal"] .creo-stepper-item:not(:last-child)::after,
3210
+ .creo-stepper:not([data-orientation]) .creo-stepper-item:not(:last-child)::after {
3211
+ left: calc(32px + var(--spacing-s));
3212
+ right: 0;
3213
+ top: 15px;
3214
+ height: 2px;
3215
+ }
3216
+
3217
+ .creo-stepper[data-orientation="vertical"] .creo-stepper-item:not(:last-child)::after {
3218
+ left: 15px;
3219
+ top: 32px;
3220
+ bottom: 0;
3221
+ width: 2px;
3222
+ }
3223
+
3224
+ /* completed item の connector は brand 色 */
3225
+ .creo-stepper-item[data-status="completed"]:not(:last-child)::after {
3226
+ background-color: var(--color-brand-primary);
3227
+ }
3228
+
3229
+ /* ---------- Marker ---------- */
3230
+
3231
+ .creo-stepper-marker {
3232
+ grid-row: 1 / span 2;
3233
+ grid-column: 1;
3234
+ display: inline-flex;
3235
+ align-items: center;
3236
+ justify-content: center;
3237
+ width: var(--layout-target-focus);
3238
+ height: var(--layout-target-focus);
3239
+ border-radius: var(--radius-full);
3240
+ background-color: var(--color-surface-bg-subtle);
3241
+ color: var(--color-text-tertiary);
3242
+ border: 2px solid var(--color-surface-border);
3243
+ font-size: var(--typography-size-s);
3244
+ font-weight: var(--typography-weight-semibold);
3245
+ line-height: 1;
3246
+ user-select: none;
3247
+ transition: background-color var(--motion-mapping-toggle-duration)
3248
+ var(--motion-mapping-toggle-easing), color var(--motion-mapping-toggle-duration)
3249
+ var(--motion-mapping-toggle-easing), border-color var(--motion-mapping-toggle-duration)
3250
+ var(--motion-mapping-toggle-easing);
3251
+ z-index: 1;
3252
+ }
3253
+
3254
+ /* Size variants */
3255
+ .creo-stepper[data-size="s"] .creo-stepper-marker {
3256
+ width: 24px;
3257
+ height: 24px;
3258
+ font-size: var(--typography-size-xs);
3259
+ }
3260
+
3261
+ /* ---------- Status colors ---------- */
3262
+
3263
+ .creo-stepper-item[data-status="completed"] .creo-stepper-marker {
3264
+ background-color: var(--color-brand-primary);
3265
+ color: var(--color-surface-bg-base);
3266
+ border-color: var(--color-brand-primary);
3267
+ }
3268
+
3269
+ .creo-stepper-item[data-status="current"] .creo-stepper-marker {
3270
+ background-color: var(--color-brand-primary);
3271
+ color: var(--color-surface-bg-base);
3272
+ border-color: var(--color-brand-primary);
3273
+ box-shadow: 0 0 0 4px color-mix(in oklch, var(--color-brand-primary) 20%, transparent);
3274
+ }
3275
+
3276
+ .creo-stepper-item[data-status="error"] .creo-stepper-marker {
3277
+ background-color: var(--color-semantic-error);
3278
+ color: var(--color-surface-bg-base);
3279
+ border-color: var(--color-semantic-error);
3280
+ }
3281
+
3282
+ /* ---------- Label + Description ---------- */
3283
+
3284
+ .creo-stepper-label {
3285
+ grid-row: 1;
3286
+ grid-column: 2;
3287
+ font-size: var(--typography-size-m);
3288
+ font-weight: var(--typography-weight-medium);
3289
+ color: var(--color-text-primary);
3290
+ line-height: 1.3;
3291
+ }
3292
+
3293
+ .creo-stepper-item[data-status="pending"] .creo-stepper-label {
3294
+ color: var(--color-text-secondary);
3295
+ }
3296
+
3297
+ .creo-stepper-description {
3298
+ grid-row: 2;
3299
+ grid-column: 2;
3300
+ font-size: var(--typography-body-caption);
3301
+ color: var(--color-text-secondary);
3302
+ line-height: var(--typography-line-height-normal);
3303
+ }
3304
+
3305
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
3306
+
3307
+ @media (prefers-reduced-motion: reduce) {
3308
+ .creo-stepper-item,
3309
+ .creo-stepper-item::after,
3310
+ .creo-stepper-marker {
3311
+ transition: none;
3312
+ transform: none;
3313
+ }
3314
+ }
3315
+
3316
+ /* ================ table.css ================ */
3317
+ /**
3318
+ * creoui — Table
3319
+ *
3320
+ * Spec: docs/components/table.md
3321
+ * Token: creoui/tokens.css (必須)
3322
+ */
3323
+
3324
+ .creo-table {
3325
+ width: 100%;
3326
+ border-collapse: separate;
3327
+ border-spacing: 0;
3328
+ font-family: inherit;
3329
+ font-size: var(--typography-size-m);
3330
+ color: var(--color-text-primary);
3331
+ background-color: var(--color-surface-surface);
3332
+ border: 1px solid var(--color-surface-border);
3333
+ border-radius: var(--radius-m);
3334
+ overflow: hidden;
3335
+ }
3336
+
3337
+ /* ---------- Head ---------- */
3338
+
3339
+ .creo-table-head .creo-table-row {
3340
+ background-color: var(--color-surface-bg-subtle);
3341
+ }
3342
+
3343
+ .creo-table-head .creo-table-cell {
3344
+ font-size: var(--typography-body-caption);
3345
+ font-weight: var(--typography-weight-medium);
3346
+ color: var(--color-text-secondary);
3347
+ text-transform: uppercase;
3348
+ letter-spacing: 0.04em;
3349
+ text-align: left;
3350
+ padding: var(--spacing-s) var(--spacing-m);
3351
+ border-bottom: 1px solid var(--color-surface-border);
3352
+ }
3353
+
3354
+ .creo-table[data-sticky-head="true"] .creo-table-head .creo-table-cell {
3355
+ position: sticky;
3356
+ top: 0;
3357
+ z-index: 1;
3358
+ }
3359
+
3360
+ /* ---------- Body cells ---------- */
3361
+
3362
+ .creo-table-cell {
3363
+ padding: var(--spacing-s) var(--spacing-m);
3364
+ border-bottom: 1px solid var(--color-surface-border-subtle, var(--color-surface-border));
3365
+ vertical-align: middle;
3366
+ }
3367
+
3368
+ /* 最終 row の下線を消す (radius を曇らせない) */
3369
+ .creo-table-body > .creo-table-row:last-child > .creo-table-cell {
3370
+ border-bottom: none;
3371
+ }
3372
+
3373
+ .creo-table-cell[data-align="center"] {
3374
+ text-align: center;
3375
+ }
3376
+ .creo-table-cell[data-align="end"] {
3377
+ text-align: right;
3378
+ }
3379
+
3380
+ /* ---------- Sizes ---------- */
3381
+
3382
+ .creo-table[data-size="s"] .creo-table-cell {
3383
+ padding: var(--spacing-xs) var(--spacing-s);
3384
+ font-size: var(--typography-size-s);
3385
+ }
3386
+ .creo-table[data-size="l"] .creo-table-cell {
3387
+ padding: var(--spacing-m) var(--spacing-l);
3388
+ font-size: var(--typography-size-l);
3389
+ }
3390
+
3391
+ /* ---------- Variants ---------- */
3392
+
3393
+ .creo-table[data-variant="striped"] .creo-table-body > .creo-table-row:nth-child(even) {
3394
+ background-color: var(--color-surface-bg-subtle);
3395
+ }
3396
+
3397
+ .creo-table[data-variant="bordered"] .creo-table-cell {
3398
+ border-right: 1px solid var(--color-surface-border-subtle, var(--color-surface-border));
3399
+ }
3400
+ .creo-table[data-variant="bordered"] .creo-table-cell:last-child {
3401
+ border-right: none;
3402
+ }
3403
+
3404
+ /* ---------- Row states ---------- */
3405
+
3406
+ .creo-table-body .creo-table-row:hover:not([data-selected="true"]):not([data-disabled="true"]) {
3407
+ background-color: var(--color-surface-bg-subtle);
3408
+ }
3409
+
3410
+ .creo-table-row[data-selected="true"] {
3411
+ background-color: var(--color-brand-primary-subtle);
3412
+ }
3413
+
3414
+ .creo-table-row[data-disabled="true"] {
3415
+ opacity: 0.5;
3416
+ pointer-events: none;
3417
+ }
3418
+
3419
+ /* ---------- Sortable headers ---------- */
3420
+
3421
+ .creo-table-sortable {
3422
+ cursor: pointer;
3423
+ user-select: none;
3424
+ position: relative;
3425
+ }
3426
+
3427
+ .creo-table-sortable::after {
3428
+ content: "↕";
3429
+ display: inline-block;
3430
+ margin-left: var(--spacing-xs);
3431
+ color: var(--color-text-tertiary);
3432
+ font-size: 0.85em;
3433
+ vertical-align: baseline;
3434
+ transition: color var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing),
3435
+ transform var(--motion-mapping-hover-duration) var(--motion-mapping-hover-easing);
3436
+ }
3437
+
3438
+ .creo-table-sortable[aria-sort="ascending"]::after {
3439
+ content: "▲";
3440
+ color: var(--color-brand-primary);
3441
+ }
3442
+
3443
+ .creo-table-sortable[aria-sort="descending"]::after {
3444
+ content: "▼";
3445
+ color: var(--color-brand-primary);
3446
+ }
3447
+
3448
+ .creo-table-sortable:hover::after {
3449
+ color: var(--color-text-primary);
3450
+ }
3451
+
3452
+ /* sortable cell の :focus-visible は cell 内側 (-2px offset) で articulate していたが、
3453
+ a11y consistency のため _focus.css policy (+2px offset) に委譲 — element 周囲 ring
3454
+ が standard、 内側 offset は anti-pattern。 */
3455
+ .creo-table-sortable:focus-visible {
3456
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--color-focus-ring-color);
3457
+ outline-offset: var(--focus-ring-offset);
3458
+ box-shadow: 0 0 0 var(--focus-ring-halo-width) var(--color-focus-ring-halo);
3459
+ }
3460
+
3461
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
3462
+
3463
+ @media (prefers-reduced-motion: reduce) {
3464
+ .creo-table-row,
3465
+ .creo-table-cell,
3466
+ .creo-table-sortable::after {
3467
+ transition: none;
3468
+ transform: none;
3469
+ }
3470
+ }
3471
+
3472
+ /* ================ tabs.css ================ */
3473
+ /**
3474
+ * creoui — Tabs component (ARIA tablist pattern)
3475
+ *
3476
+ * `.creo-tabs` wrapper + `.creo-tabs-list` (role=tablist) + `.creo-tabs-tab`
3477
+ * (role=tab) + `.creo-tabs-panel` (role=tabpanel)。active 判定は
3478
+ * `aria-selected="true"` を SSOT として CSS selector でスタイル切替。
3479
+ *
3480
+ * Spec: docs/components/tabs.md
3481
+ * Token: creoui/tokens.css (必須)
3482
+ */
3483
+
3484
+ .creo-tabs {
3485
+ display: block;
3486
+ }
3487
+
3488
+ /* ---------- Tab list (button 列) ---------- */
3489
+
3490
+ .creo-tabs-list {
3491
+ display: flex;
3492
+ gap: var(--spacing-xs);
3493
+ border-bottom: 1px solid var(--color-surface-border);
3494
+ overflow-x: auto;
3495
+ }
3496
+
3497
+ .creo-tabs[data-variant="pill"] .creo-tabs-list {
3498
+ border-bottom: none;
3499
+ padding: var(--spacing-xs);
3500
+ background-color: var(--color-surface-bg-subtle);
3501
+ border-radius: var(--radius-m);
3502
+ gap: var(--spacing-xs);
3503
+ }
3504
+
3505
+ /* ---------- Tab button (base) ---------- */
3506
+
3507
+ .creo-tabs-tab {
3508
+ appearance: none;
3509
+ background: transparent;
3510
+ border: none;
3511
+ padding: var(--spacing-s) var(--spacing-m);
3512
+ min-height: var(--layout-target-tap);
3513
+
3514
+ font-family: inherit;
3515
+ font-size: var(--typography-size-m);
3516
+ font-weight: var(--typography-weight-medium);
3517
+ color: var(--color-text-secondary);
3518
+ text-decoration: none;
3519
+ white-space: nowrap;
3520
+ cursor: pointer;
3521
+
3522
+ position: relative;
3523
+ transition: color var(--motion-mapping-toggle-duration) var(--motion-mapping-toggle-easing),
3524
+ background-color var(--motion-mapping-toggle-duration) var(--motion-mapping-toggle-easing);
3525
+ }
3526
+
3527
+ .creo-tabs-tab:hover:not(:disabled) {
3528
+ color: var(--color-text-primary);
3529
+ }
3530
+
3531
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
3532
+
3533
+ .creo-tabs-tab:disabled {
3534
+ cursor: not-allowed;
3535
+ opacity: 0.5;
3536
+ }
3537
+
3538
+ /* ---------- Active state (aria-selected=true) ---------- */
3539
+
3540
+ /* underline variant (default): 下線で active を示す */
3541
+ .creo-tabs[data-variant="underline"] .creo-tabs-tab[aria-selected="true"],
3542
+ .creo-tabs:not([data-variant]) .creo-tabs-tab[aria-selected="true"] {
3543
+ color: var(--color-brand-primary);
3544
+ }
3545
+ .creo-tabs[data-variant="underline"] .creo-tabs-tab[aria-selected="true"]::after,
3546
+ .creo-tabs:not([data-variant]) .creo-tabs-tab[aria-selected="true"]::after {
3547
+ content: "";
3548
+ position: absolute;
3549
+ left: var(--spacing-s);
3550
+ right: var(--spacing-s);
3551
+ bottom: -1px;
3552
+ height: 2px;
3553
+ background-color: var(--color-brand-primary);
3554
+ border-radius: var(--radius-xs);
3555
+ }
3556
+
3557
+ /* pill variant: background を埋めて active を示す */
3558
+ .creo-tabs[data-variant="pill"] .creo-tabs-tab {
3559
+ border-radius: var(--radius-s);
3560
+ }
3561
+ .creo-tabs[data-variant="pill"] .creo-tabs-tab[aria-selected="true"] {
3562
+ background-color: var(--color-brand-primary);
3563
+ color: var(--color-surface-bg-base);
3564
+ }
3565
+
3566
+ /* ---------- Sizes ---------- */
3567
+
3568
+ .creo-tabs[data-size="s"] .creo-tabs-tab {
3569
+ min-height: var(--layout-target-focus);
3570
+ padding: var(--spacing-xs) var(--spacing-s);
3571
+ font-size: var(--typography-size-s);
3572
+ }
3573
+ .creo-tabs[data-size="l"] .creo-tabs-tab {
3574
+ min-height: calc(var(--layout-target-tap) * 1.15);
3575
+ padding: var(--spacing-m) var(--spacing-l);
3576
+ font-size: var(--typography-size-l);
3577
+ }
3578
+
3579
+ /* ---------- Panel ---------- */
3580
+
3581
+ .creo-tabs-panel {
3582
+ padding: var(--spacing-m) 0;
3583
+ }
3584
+ .creo-tabs-panel[hidden] {
3585
+ display: none;
3586
+ }
3587
+
3588
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
3589
+
3590
+ @media (prefers-reduced-motion: reduce) {
3591
+ .creo-tabs-tab {
3592
+ transition: none;
3593
+ transform: none;
3594
+ }
3595
+ }
3596
+
3597
+ /* ================ timeline.css ================ */
3598
+ /**
3599
+ * creoui — Timeline (event / activity history)
3600
+ *
3601
+ * Spec: docs/components/timeline.md
3602
+ * Token: creoui/tokens.css (必須)
3603
+ */
3604
+
3605
+ .creo-timeline {
3606
+ display: flex;
3607
+ flex-direction: column;
3608
+ gap: var(--spacing-m);
3609
+ padding: 0;
3610
+ margin: 0;
3611
+ list-style: none;
3612
+ }
3613
+
3614
+ /* ---------- Item ---------- */
3615
+
3616
+ .creo-timeline-item {
3617
+ position: relative;
3618
+ display: grid;
3619
+ grid-template-columns: auto 1fr;
3620
+ column-gap: var(--spacing-s);
3621
+ padding: 0;
3622
+ }
3623
+
3624
+ /* connector: 次 item との縦線 */
3625
+ .creo-timeline-item:not(:last-child)::before {
3626
+ content: "";
3627
+ position: absolute;
3628
+ left: calc(32px / 2 - 1px);
3629
+ top: 32px;
3630
+ bottom: calc(-1 * var(--spacing-m));
3631
+ width: 2px;
3632
+ background-color: var(--color-surface-border);
3633
+ }
3634
+
3635
+ .creo-timeline[data-size="s"] .creo-timeline-item:not(:last-child)::before {
3636
+ left: calc(24px / 2 - 1px);
3637
+ top: 24px;
3638
+ }
3639
+
3640
+ /* ---------- Marker ---------- */
3641
+
3642
+ .creo-timeline-marker {
3643
+ grid-column: 1;
3644
+ grid-row: 1;
3645
+ display: inline-flex;
3646
+ align-items: center;
3647
+ justify-content: center;
3648
+ width: 32px;
3649
+ height: 32px;
3650
+ border-radius: var(--radius-full);
3651
+ background-color: var(--color-surface-bg-subtle);
3652
+ color: var(--color-text-primary);
3653
+ border: 2px solid var(--color-surface-border);
3654
+ font-size: var(--typography-size-s);
3655
+ font-weight: var(--typography-weight-semibold);
3656
+ line-height: 1;
3657
+ user-select: none;
3658
+ flex-shrink: 0;
3659
+ z-index: 1;
3660
+ }
3661
+
3662
+ .creo-timeline[data-size="s"] .creo-timeline-marker {
3663
+ width: 24px;
3664
+ height: 24px;
3665
+ font-size: var(--typography-size-xs);
3666
+ }
3667
+
3668
+ /* ---------- Variants (marker 色) ---------- */
3669
+
3670
+ .creo-timeline-item[data-variant="success"] .creo-timeline-marker {
3671
+ background-color: var(--color-semantic-success);
3672
+ color: var(--color-surface-bg-base);
3673
+ border-color: var(--color-semantic-success);
3674
+ }
3675
+ .creo-timeline-item[data-variant="warning"] .creo-timeline-marker {
3676
+ background-color: var(--color-semantic-warning);
3677
+ color: var(--color-surface-bg-base);
3678
+ border-color: var(--color-semantic-warning);
3679
+ }
3680
+ .creo-timeline-item[data-variant="error"] .creo-timeline-marker {
3681
+ background-color: var(--color-semantic-error);
3682
+ color: var(--color-surface-bg-base);
3683
+ border-color: var(--color-semantic-error);
3684
+ }
3685
+ .creo-timeline-item[data-variant="info"] .creo-timeline-marker {
3686
+ background-color: var(--color-semantic-info);
3687
+ color: var(--color-surface-bg-base);
3688
+ border-color: var(--color-semantic-info);
3689
+ }
3690
+
3691
+ /* ---------- Content ---------- */
3692
+
3693
+ .creo-timeline-content {
3694
+ grid-column: 2;
3695
+ grid-row: 1;
3696
+ display: flex;
3697
+ flex-direction: column;
3698
+ gap: 2px;
3699
+ min-width: 0;
3700
+ padding-top: 4px;
3701
+ }
3702
+
3703
+ .creo-timeline-title {
3704
+ font-size: var(--typography-size-m);
3705
+ font-weight: var(--typography-weight-medium);
3706
+ color: var(--color-text-primary);
3707
+ line-height: 1.4;
3708
+ }
3709
+
3710
+ .creo-timeline-meta {
3711
+ font-size: var(--typography-body-caption);
3712
+ color: var(--color-text-tertiary);
3713
+ line-height: var(--typography-line-height-normal);
3714
+ }
3715
+
3716
+ .creo-timeline-description {
3717
+ margin: var(--spacing-xs) 0 0 0;
3718
+ font-size: var(--typography-size-m);
3719
+ color: var(--color-text-secondary);
3720
+ line-height: var(--typography-line-height-normal);
3721
+ }
3722
+
3723
+ /* ================ toast.css ================ */
3724
+ /**
3725
+ * creoui — Toast + toast-region
3726
+ *
3727
+ * Spec: docs/components/toast.md
3728
+ * Token: creoui/tokens.css (必須)
3729
+ */
3730
+
3731
+ .creo-toast-region {
3732
+ position: fixed;
3733
+ display: flex;
3734
+ flex-direction: column;
3735
+ gap: var(--layout-gap-tight);
3736
+ padding: var(--spacing-m);
3737
+ pointer-events: none;
3738
+ z-index: 1000;
3739
+ max-width: min(420px, calc(100vw - var(--spacing-l)));
3740
+ }
3741
+
3742
+ /* Region placement */
3743
+ .creo-toast-region[data-placement="top-right"],
3744
+ .creo-toast-region:not([data-placement]) {
3745
+ top: 0;
3746
+ right: 0;
3747
+ }
3748
+ .creo-toast-region[data-placement="top-left"] {
3749
+ top: 0;
3750
+ left: 0;
3751
+ }
3752
+ .creo-toast-region[data-placement="top-center"] {
3753
+ top: 0;
3754
+ left: 50%;
3755
+ transform: translateX(-50%);
3756
+ }
3757
+ .creo-toast-region[data-placement="bottom-right"] {
3758
+ bottom: 0;
3759
+ right: 0;
3760
+ }
3761
+ .creo-toast-region[data-placement="bottom-left"] {
3762
+ bottom: 0;
3763
+ left: 0;
3764
+ }
3765
+ .creo-toast-region[data-placement="bottom-center"] {
3766
+ bottom: 0;
3767
+ left: 50%;
3768
+ transform: translateX(-50%);
3769
+ }
3770
+
3771
+ /* ---------- Toast (item) ---------- */
3772
+
3773
+ .creo-toast {
3774
+ pointer-events: auto;
3775
+ display: flex;
3776
+ align-items: flex-start;
3777
+ gap: var(--spacing-s);
3778
+ padding: var(--spacing-s) var(--spacing-m);
3779
+ background-color: var(--color-surface-surface);
3780
+ border: 1px solid var(--color-surface-border);
3781
+ border-radius: var(--radius-m);
3782
+ box-shadow: var(--shadow-m);
3783
+ color: var(--color-text-primary);
3784
+ animation: creoToastIn var(--motion-mapping-modal-enter-duration)
3785
+ var(--motion-mapping-modal-enter-easing);
3786
+ }
3787
+
3788
+ @keyframes creoToastIn {
3789
+ from {
3790
+ opacity: 0;
3791
+ transform: translateY(-8px);
3792
+ }
3793
+ to {
3794
+ opacity: 1;
3795
+ transform: translateY(0);
3796
+ }
3797
+ }
3798
+
3799
+ /* ---------- Variants ---------- */
3800
+
3801
+ .creo-toast[data-variant="success"] {
3802
+ border-color: var(--color-semantic-success);
3803
+ border-width: 1.5px;
3804
+ }
3805
+ .creo-toast[data-variant="success"] .creo-toast-icon {
3806
+ color: var(--color-semantic-success);
3807
+ }
3808
+
3809
+ .creo-toast[data-variant="warning"] {
3810
+ border-color: var(--color-semantic-warning);
3811
+ border-width: 1.5px;
3812
+ }
3813
+ .creo-toast[data-variant="warning"] .creo-toast-icon {
3814
+ color: var(--color-semantic-warning);
3815
+ }
3816
+
3817
+ .creo-toast[data-variant="error"] {
3818
+ border-color: var(--color-semantic-error);
3819
+ border-width: 1.5px;
3820
+ }
3821
+ .creo-toast[data-variant="error"] .creo-toast-icon {
3822
+ color: var(--color-semantic-error);
3823
+ }
3824
+
3825
+ .creo-toast[data-variant="info"] {
3826
+ border-color: var(--color-semantic-info);
3827
+ border-width: 1.5px;
3828
+ }
3829
+ .creo-toast[data-variant="info"] .creo-toast-icon {
3830
+ color: var(--color-semantic-info);
3831
+ }
3832
+
3833
+ /* ---------- Slots ---------- */
3834
+
3835
+ .creo-toast-icon {
3836
+ flex-shrink: 0;
3837
+ font-size: var(--typography-title-card);
3838
+ line-height: 1;
3839
+ margin-top: 2px;
3840
+ }
3841
+
3842
+ .creo-toast-content {
3843
+ flex: 1;
3844
+ display: flex;
3845
+ flex-direction: column;
3846
+ gap: 2px;
3847
+ min-width: 0;
3848
+ }
3849
+
3850
+ .creo-toast-content > strong {
3851
+ font-size: var(--typography-size-m);
3852
+ font-weight: var(--typography-weight-semibold);
3853
+ }
3854
+
3855
+ .creo-toast-content > span {
3856
+ font-size: var(--typography-body-helper);
3857
+ color: var(--color-text-secondary);
3858
+ line-height: var(--typography-line-height-normal);
3859
+ }
3860
+
3861
+ .creo-toast-close {
3862
+ flex-shrink: 0;
3863
+ appearance: none;
3864
+ background: transparent;
3865
+ border: none;
3866
+ padding: 2px var(--spacing-xs);
3867
+ color: var(--color-text-tertiary);
3868
+ font-size: var(--typography-size-m);
3869
+ cursor: pointer;
3870
+ border-radius: var(--radius-xs);
3871
+ }
3872
+ .creo-toast-close:hover {
3873
+ color: var(--color-text-primary);
3874
+ background-color: var(--color-surface-bg-subtle);
3875
+ }
3876
+ /* :focus-visible policy は _focus.css の component-agnostic articulate に委譲。 */
3877
+
3878
+ /* ---------- Reduced motion ---------- */
3879
+
3880
+ @media (prefers-reduced-motion: reduce) {
3881
+ .creo-toast {
3882
+ animation: none;
3883
+ }
3884
+ }
3885
+
3886
+ /* ================ tooltip.css ================ */
3887
+ /**
3888
+ * creoui — Tooltip (CSS-only, JS 不要)
3889
+ *
3890
+ * `.creo-tooltip` wrapper に hover / focus-within で `.creo-tooltip-content` が可視化。
3891
+ *
3892
+ * Spec: docs/components/tooltip.md
3893
+ * Token: creoui/tokens.css (必須)
3894
+ */
3895
+
3896
+ .creo-tooltip {
3897
+ position: relative;
3898
+ display: inline-flex;
3899
+ align-items: center;
3900
+ }
3901
+
3902
+ .creo-tooltip-content {
3903
+ position: absolute;
3904
+ left: 50%;
3905
+ bottom: calc(100% + var(--spacing-xs));
3906
+ transform: translateX(-50%) translateY(4px);
3907
+
3908
+ padding: var(--spacing-xs) var(--spacing-s);
3909
+ background-color: var(--color-surface-bg-emphasis);
3910
+ color: var(--color-text-primary);
3911
+ border-radius: var(--radius-xs);
3912
+ box-shadow: var(--shadow-m);
3913
+
3914
+ font-size: var(--typography-body-caption);
3915
+ font-weight: var(--typography-weight-regular);
3916
+ line-height: 1.4;
3917
+ white-space: nowrap;
3918
+ max-width: 280px;
3919
+
3920
+ opacity: 0;
3921
+ pointer-events: none;
3922
+ z-index: 100;
3923
+ transition: opacity var(--motion-mapping-dropdown-duration) var(--motion-mapping-dropdown-easing),
3924
+ transform var(--motion-mapping-dropdown-duration) var(--motion-mapping-dropdown-easing);
3925
+ }
3926
+
3927
+ /* ---------- Hover / focus-within で可視化 ---------- */
3928
+
3929
+ .creo-tooltip:hover > .creo-tooltip-content,
3930
+ .creo-tooltip:focus-within > .creo-tooltip-content {
3931
+ opacity: 1;
3932
+ transform: translateX(-50%) translateY(0);
3933
+ }
3934
+
3935
+ /* ---------- Placement ---------- */
3936
+
3937
+ .creo-tooltip-content[data-placement="bottom"] {
3938
+ top: calc(100% + var(--spacing-xs));
3939
+ bottom: auto;
3940
+ transform: translateX(-50%) translateY(-4px);
3941
+ }
3942
+ .creo-tooltip:hover > .creo-tooltip-content[data-placement="bottom"],
3943
+ .creo-tooltip:focus-within > .creo-tooltip-content[data-placement="bottom"] {
3944
+ transform: translateX(-50%) translateY(0);
3945
+ }
3946
+
3947
+ .creo-tooltip-content[data-placement="left"] {
3948
+ right: calc(100% + var(--spacing-xs));
3949
+ left: auto;
3950
+ top: 50%;
3951
+ bottom: auto;
3952
+ transform: translateY(-50%) translateX(4px);
3953
+ }
3954
+ .creo-tooltip:hover > .creo-tooltip-content[data-placement="left"],
3955
+ .creo-tooltip:focus-within > .creo-tooltip-content[data-placement="left"] {
3956
+ transform: translateY(-50%) translateX(0);
3957
+ }
3958
+
3959
+ .creo-tooltip-content[data-placement="right"] {
3960
+ left: calc(100% + var(--spacing-xs));
3961
+ top: 50%;
3962
+ bottom: auto;
3963
+ transform: translateY(-50%) translateX(-4px);
3964
+ }
3965
+ .creo-tooltip:hover > .creo-tooltip-content[data-placement="right"],
3966
+ .creo-tooltip:focus-within > .creo-tooltip-content[data-placement="right"] {
3967
+ transform: translateY(-50%) translateX(0);
3968
+ }
3969
+
3970
+ /* ---------- Inverse variant ---------- */
3971
+
3972
+ .creo-tooltip-content[data-variant="inverse"] {
3973
+ background-color: var(--color-text-primary);
3974
+ color: var(--color-surface-bg-base);
3975
+ }
3976
+
3977
+ /* ---------- Reduced motion (WCAG 2.1 SC 2.3.3 / SC 2.3.1) ---------- */
3978
+
3979
+ @media (prefers-reduced-motion: reduce) {
3980
+ .creo-tooltip-content {
3981
+ transition: none;
3982
+ }
3983
+ }
3984
+