lostcoords-ui 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +364 -96
  3. data/app/assets/tailwind/lostcoords/ui/avatar.css +6 -6
  4. data/app/assets/tailwind/lostcoords/ui/base.css +45 -0
  5. data/app/assets/tailwind/lostcoords/ui/card.css +23 -22
  6. data/app/assets/tailwind/lostcoords/ui/choice.css +39 -0
  7. data/app/assets/tailwind/lostcoords/ui/code-block.css +10 -0
  8. data/app/assets/tailwind/lostcoords/ui/{disclosure.css → collapsible.css} +6 -6
  9. data/app/assets/tailwind/lostcoords/ui/components/code-block.css +5 -0
  10. data/app/assets/tailwind/lostcoords/ui/components/collapsible.css +5 -0
  11. data/app/assets/tailwind/lostcoords/ui/components/dialog.css +9 -0
  12. data/app/assets/tailwind/lostcoords/ui/components/emoji-picker.css +5 -0
  13. data/app/assets/tailwind/lostcoords/ui/components/menu.css +5 -0
  14. data/app/assets/tailwind/lostcoords/ui/components/prose.css +3 -0
  15. data/app/assets/tailwind/lostcoords/ui/components/table.css +3 -0
  16. data/app/assets/tailwind/lostcoords/ui/components/toast.css +5 -0
  17. data/app/assets/tailwind/lostcoords/ui/components/tooltip.css +4 -0
  18. data/app/assets/tailwind/lostcoords/ui/components.css +12 -0
  19. data/app/assets/tailwind/lostcoords/ui/copy-button.css +9 -9
  20. data/app/assets/tailwind/lostcoords/ui/core.css +21 -0
  21. data/app/assets/tailwind/lostcoords/ui/dialog.css +17 -17
  22. data/app/assets/tailwind/lostcoords/ui/emoji-picker.css +86 -88
  23. data/app/assets/tailwind/lostcoords/ui/field.css +2 -2
  24. data/app/assets/tailwind/lostcoords/ui/glass.css +9 -8
  25. data/app/assets/tailwind/lostcoords/ui/layout.css +2 -2
  26. data/app/assets/tailwind/lostcoords/ui/popover.css +14 -14
  27. data/app/assets/tailwind/lostcoords/ui/prose.css +66 -0
  28. data/app/assets/tailwind/lostcoords/ui/sheet.css +62 -63
  29. data/app/assets/tailwind/lostcoords/ui/squircle.css +7 -27
  30. data/app/assets/tailwind/lostcoords/ui/table.css +51 -0
  31. data/app/assets/tailwind/lostcoords/ui/theme.css +209 -225
  32. data/app/assets/tailwind/lostcoords/ui/toast.css +23 -0
  33. data/app/assets/tailwind/lostcoords/ui/tooltip.css +51 -0
  34. data/app/assets/tailwind/lostcoords/ui/typography.css +31 -61
  35. data/app/assets/tailwind/lostcoords/ui/ui.css +2 -21
  36. data/app/assets/tailwind/lostcoords/ui/utilities.css +14 -22
  37. data/app/helpers/lostcoords/ui/badge_helper.rb +67 -110
  38. data/app/helpers/lostcoords/ui/button_helper.rb +44 -35
  39. data/app/helpers/lostcoords/ui/card_helper.rb +9 -52
  40. data/app/helpers/lostcoords/ui/choice_helper.rb +87 -0
  41. data/app/helpers/lostcoords/ui/code_block_helper.rb +22 -0
  42. data/app/helpers/lostcoords/ui/collapsible_helper.rb +9 -0
  43. data/app/helpers/lostcoords/ui/copy_button_helper.rb +7 -7
  44. data/app/helpers/lostcoords/ui/description_list_helper.rb +12 -0
  45. data/app/helpers/lostcoords/ui/dialog_helper.rb +15 -17
  46. data/app/helpers/lostcoords/ui/emoji_picker_helper.rb +6 -0
  47. data/app/helpers/lostcoords/ui/feedback_helper.rb +25 -6
  48. data/app/helpers/lostcoords/ui/form_helper.rb +36 -59
  49. data/app/helpers/lostcoords/ui/glass_helper.rb +7 -7
  50. data/app/helpers/lostcoords/ui/layout_helper.rb +13 -11
  51. data/app/helpers/lostcoords/ui/menu_helper.rb +45 -10
  52. data/app/helpers/lostcoords/ui/navigation_helper.rb +144 -0
  53. data/app/helpers/lostcoords/ui/primitives_helper.rb +39 -61
  54. data/app/helpers/lostcoords/ui/reading_helper.rb +2 -2
  55. data/app/helpers/lostcoords/ui/render_attributes_helper.rb +17 -1
  56. data/app/helpers/lostcoords/ui/sheet_helper.rb +7 -45
  57. data/app/helpers/lostcoords/ui/structures_helper.rb +26 -125
  58. data/app/helpers/lostcoords/ui/table_helper.rb +11 -0
  59. data/app/helpers/lostcoords/ui/tailwind_helper.rb +13 -4
  60. data/app/helpers/lostcoords/ui/toast_helper.rb +22 -0
  61. data/app/helpers/lostcoords/ui/tooltip_helper.rb +17 -0
  62. data/app/helpers/lostcoords/ui/typography_helper.rb +41 -11
  63. data/app/javascript/lostcoords/ui/controllers/lc_code_block_controller.js +23 -0
  64. data/app/javascript/lostcoords/ui/controllers/{disclosure_controller.js → lc_collapsible_controller.js} +4 -4
  65. data/app/javascript/lostcoords/ui/controllers/{confirm_dialog_controller.js → lc_confirm_dialog_controller.js} +4 -4
  66. data/app/javascript/lostcoords/ui/controllers/{modal_controller.js → lc_dialog_controller.js} +1 -1
  67. data/app/javascript/lostcoords/ui/controllers/{emoji_picker_controller.js → lc_emoji_picker_controller.js} +38 -10
  68. data/app/javascript/lostcoords/ui/controllers/lc_kbd_controller.js +12 -0
  69. data/app/javascript/lostcoords/ui/controllers/{row_menu_controller.js → lc_menu_controller.js} +25 -3
  70. data/app/javascript/lostcoords/ui/controllers/{ui_popover_controller.js → lc_popover_controller.js} +1 -1
  71. data/app/javascript/lostcoords/ui/controllers/{ui_selection_controller.js → lc_selection_controller.js} +7 -15
  72. data/app/javascript/lostcoords/ui/controllers/{sheet_controller.js → lc_sheet_controller.js} +17 -17
  73. data/app/javascript/lostcoords/ui/controllers/lc_shortcut_controller.js +45 -0
  74. data/app/javascript/lostcoords/ui/controllers/lc_tabs_controller.js +42 -0
  75. data/app/javascript/lostcoords/ui/controllers/{toast_controller.js → lc_toast_controller.js} +2 -2
  76. data/app/javascript/lostcoords/ui/controllers/lc_toast_region_controller.js +62 -0
  77. data/app/javascript/lostcoords/ui/controllers/lc_tooltip_controller.js +54 -0
  78. data/app/javascript/lostcoords/ui/helpers/catalog_picker.js +77 -25
  79. data/app/javascript/lostcoords/ui/helpers/context_dialog.js +6 -6
  80. data/app/javascript/lostcoords/ui/helpers/dialog.js +2 -2
  81. data/app/javascript/lostcoords/ui/helpers/dismiss_stack.js +30 -7
  82. data/app/javascript/lostcoords/ui/helpers/floating_panel.js +7 -8
  83. data/app/javascript/lostcoords/ui/helpers/menu_keys.js +19 -18
  84. data/app/javascript/lostcoords/ui/helpers/roving_focus.js +175 -0
  85. data/app/javascript/lostcoords/ui/helpers/sheet_motion.js +4 -4
  86. data/app/javascript/lostcoords/ui/helpers/shortcuts.js +162 -0
  87. data/app/javascript/lostcoords/ui/helpers/top_layer.js +48 -10
  88. data/app/javascript/lostcoords/ui/index.js +57 -0
  89. data/app/views/lostcoords/ui/components/_emoji_picker.html.erb +46 -46
  90. data/app/views/lostcoords/ui/components/_emoji_picker_grid.html.erb +3 -3
  91. data/app/views/lostcoords/ui/components/_lc_code_block.html.erb +18 -0
  92. data/app/views/lostcoords/ui/components/_lc_collapsible.html.erb +5 -0
  93. data/app/views/lostcoords/ui/components/_lc_dialog.html.erb +11 -8
  94. data/app/views/lostcoords/ui/components/_lc_floating_panel.html.erb +8 -0
  95. data/config/importmap.rb +10 -2
  96. data/config/locales/en.yml +23 -0
  97. data/config/locales/es.yml +23 -0
  98. data/config/locales/ja.yml +23 -0
  99. data/lib/lostcoords/ui/action_view.rb +6 -3
  100. data/lib/lostcoords/ui/builders.rb +2 -2
  101. data/lib/lostcoords/ui/form_builder.rb +126 -0
  102. data/lib/lostcoords/ui/parts.rb +154 -0
  103. data/lib/lostcoords/ui/stylesheets.rb +25 -0
  104. data/lib/lostcoords/ui/tokens.rb +24 -1
  105. data/lib/lostcoords/ui/version.rb +1 -1
  106. data/lib/tasks/lostcoords_ui.rake +11 -0
  107. metadata +54 -21
  108. data/app/assets/tailwind/lostcoords/ui/reading.css +0 -60
  109. data/app/views/lostcoords/ui/components/_form_alert.html.erb +0 -4
  110. data/app/views/lostcoords/ui/components/_lc_disclosure.html.erb +0 -5
  111. data/app/views/lostcoords/ui/components/_skeleton.html.erb +0 -4
  112. data/app/views/lostcoords/ui/components/_spinner.html.erb +0 -10
  113. data/app/views/lostcoords/ui/components/_ui_floating_panel.html.erb +0 -8
  114. data/config/helper_renames.json +0 -113
  115. data/script/migrate_helpers.rb +0 -136
  116. /data/app/javascript/lostcoords/ui/controllers/{ui_copy_controller.js → lc_copy_controller.js} +0 -0
  117. /data/app/javascript/lostcoords/ui/controllers/{ui_toggle_controller.js → lc_toggle_controller.js} +0 -0
@@ -1,255 +1,239 @@
1
+ /* Every public setting lives in this file. Hosts override the plain custom
2
+ properties in :root or html[data-theme="dark"] after importing the library;
3
+ the @theme blocks only map those properties to Tailwind utilities. */
4
+
1
5
  @theme inline {
2
- --color-paper: var(--paper);
3
- --color-paper-2: var(--paper-2);
4
- --color-paper-3: var(--paper-3);
5
- --color-ink: var(--ink);
6
- --color-ink-2: var(--ink-2);
7
- --color-ink-3: var(--ink-3);
8
- --color-ink-on-accent: var(--ink-on-accent);
9
- --color-hairline: var(--hairline);
10
-
11
- --color-sky: var(--sky);
12
- --color-sky-deep: var(--sky-deep);
13
- --color-sky-soft: var(--sky-soft);
6
+ --color-background: var(--background);
7
+ --color-foreground: var(--foreground);
8
+ --color-card: var(--card);
9
+ --color-card-foreground: var(--card-foreground);
10
+ --color-popover: var(--popover);
11
+ --color-popover-foreground: var(--popover-foreground);
12
+ --color-primary: var(--primary);
13
+ --color-primary-foreground: var(--primary-foreground);
14
+ --color-secondary: var(--secondary);
15
+ --color-secondary-foreground: var(--secondary-foreground);
16
+ --color-muted: var(--muted);
17
+ --color-muted-foreground: var(--muted-foreground);
18
+
19
+ /* Muted fills that a card switches to stay visible on it (card.css): bg-tile for choice tiles,
20
+ alerts, neutral badges, skeletons and key hints; bg-track for toggle group tracks. */
21
+ --color-tile: var(--lc-tile-bg, var(--muted));
22
+ --color-track: var(--lc-track-bg, var(--muted));
14
23
  --color-accent: var(--accent);
15
- --color-leaf: var(--leaf);
16
- --color-leaf-soft: var(--leaf-soft);
17
- --color-gold: var(--gold);
18
- --color-gold-soft: var(--gold-soft);
19
- --color-berry: var(--berry);
20
- --color-berry-soft: var(--berry-soft);
21
- --color-danger: var(--danger);
22
- --color-danger-soft: var(--danger-soft);
23
-
24
- --font-display: var(--f-display);
25
- --font-body: var(--f-body);
26
- --font-mono: var(--f-mono);
24
+ --color-accent-foreground: var(--accent-foreground);
25
+ --color-destructive: var(--destructive);
26
+ --color-success: var(--success);
27
+ --color-warning: var(--warning);
28
+ --color-border: var(--border);
29
+ --color-input: var(--input);
30
+
31
+ /* Unset by default, so the ring follows a scoped --primary. */
32
+ --color-ring: var(--ring, color-mix(in oklab, var(--primary) 50%, transparent));
33
+
34
+ --color-primary-soft: color-mix(in oklab, var(--primary) 12%, var(--background));
35
+ --color-success-soft: color-mix(in oklab, var(--success) 12%, var(--background));
36
+ --color-warning-soft: color-mix(in oklab, var(--warning) 12%, var(--background));
37
+ --color-destructive-soft: color-mix(in oklab, var(--destructive) 12%, var(--background));
38
+
39
+ /* One --radius drives every corner, as in shadcn. The default reproduces
40
+ Tailwind's own scale, so host rounded-* classes keep their sizes until the
41
+ knob moves. rounded-pill collapses to square corners when --radius is 0. */
42
+ --radius-sm: calc(var(--radius) * 0.5 * var(--lc-corner-scale, 1));
43
+ --radius-md: calc(var(--radius) * 0.75 * var(--lc-corner-scale, 1));
44
+ --radius-lg: calc(var(--radius) * var(--lc-corner-scale, 1));
45
+ --radius-xl: calc(var(--radius) * 1.5 * var(--lc-corner-scale, 1));
46
+ --radius-2xl: calc(var(--radius) * 2 * var(--lc-corner-scale, 1));
47
+ --radius-3xl: calc(var(--radius) * 3 * var(--lc-corner-scale, 1));
48
+ --radius-pill: calc(var(--radius) * 1000);
49
+
50
+ /* Semantic spacing: gap-related, p-inset, gap-section and so on. Components
51
+ never set outer margin; these gaps belong to the layout around them. */
52
+ --spacing-tight: calc(var(--spacing) * 1 * var(--lc-density));
53
+ --spacing-related: calc(var(--spacing) * 2 * var(--lc-density));
54
+ --spacing-heading: calc(var(--spacing) * 3 * var(--lc-density));
55
+ --spacing-content: calc(var(--spacing) * 4 * var(--lc-density));
56
+ --spacing-inset: var(--lc-inset);
57
+ --spacing-section: calc(var(--spacing) * 8 * var(--lc-density));
58
+ --spacing-gutter: var(--lc-gutter);
59
+
60
+ /* Buttons, inputs, selects and icon buttons share these heights. */
61
+ --spacing-control-sm: var(--lc-control-sm);
62
+ --spacing-control-md: var(--lc-control-md);
63
+ --spacing-control-lg: var(--lc-control-lg);
64
+
65
+ /* In-page layers: z-raised lifts content over its neighbours, z-sticky keeps
66
+ app chrome above content. Overlays need no z-index; see --lc-z-popover. */
67
+ --z-index-raised: var(--lc-z-raised);
68
+ --z-index-sticky: var(--lc-z-sticky);
27
69
  }
28
70
 
29
71
  @theme {
30
- --text-xs--line-height: initial;
31
- --text-sm--line-height: initial;
32
- --text-base--line-height: initial;
33
- --text-lg--line-height: initial;
34
- --text-xl--line-height: initial;
35
- --text-2xl--line-height: initial;
36
-
37
- --z-index-above: 1;
38
- --z-index-raised: 2;
39
- --z-index-art: 3;
40
-
41
- --z-index-sticky-action: 10;
42
- --z-index-float: 10;
43
-
44
- --z-index-nav: 20;
45
- --z-index-nav-popover: 30;
46
- --z-index-popover: 30;
47
- --z-index-mobile-nav: 40;
48
- --z-index-mobile-action: 50;
49
- --z-index-prompt: 51;
50
-
51
- --z-index-overlay: 60;
52
- --z-index-overlay-panel: 61;
53
- --z-index-toast: 70;
54
-
55
- --ease-out: cubic-bezier(0.3, 0, 0, 1);
56
- --ease-out-long: cubic-bezier(0.2, 0.7, 0, 1);
57
- --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
58
- --ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
59
-
60
- --sheet-duration: 500ms;
61
-
62
- --sheet-offscreen: calc(100% + 2rem);
63
- --ease-out-overshoot-subtle: cubic-bezier(0.25, 1.25, 0.5, 1);
64
- --ease-spring: cubic-bezier(0.34, 1.45, 0.64, 1);
65
- --color-scrim-dock: rgb(10 14 24 / 0.22);
72
+ --font-display: var(--font-sans);
73
+ --font-japanese: "Hiragino Sans", "Yu Gothic", "YuGothic", "Meiryo", ui-sans-serif, system-ui, sans-serif;
74
+
75
+ /* Type roles. Each sets size, line height, tracking and weight together. */
76
+ --text-display: 2.25rem;
77
+ --text-display--line-height: 2.5rem;
78
+ --text-display--letter-spacing: -0.025em;
79
+ --text-display--font-weight: 700;
80
+ --text-title: 1.875rem;
81
+ --text-title--line-height: 2.25rem;
82
+ --text-title--letter-spacing: -0.025em;
83
+ --text-title--font-weight: 700;
84
+ --text-heading: 1.25rem;
85
+ --text-heading--line-height: 1.75rem;
86
+ --text-heading--letter-spacing: -0.02em;
87
+ --text-heading--font-weight: 700;
88
+ --text-subheading: 1.125rem;
89
+ --text-subheading--line-height: 1.5rem;
90
+ --text-subheading--letter-spacing: -0.015em;
91
+ --text-subheading--font-weight: 650;
92
+ --text-body: 1rem;
93
+ --text-body--line-height: 1.5rem;
94
+ --text-small: 0.875rem;
95
+ --text-small--line-height: 1.25rem;
96
+ --text-label: 0.875rem;
97
+ --text-label--line-height: 1.25rem;
98
+ --text-label--font-weight: 500;
99
+ --text-caption: 0.75rem;
100
+ --text-caption--line-height: 1rem;
101
+
102
+ --container-page: 75rem;
103
+ --container-reading: 65ch;
104
+ --container-form: 32rem;
66
105
  }
67
106
 
68
107
  @custom-variant dark (&:where(html[data-theme="dark"], html[data-theme="dark"] *));
69
108
 
70
- @theme {
71
- --animate-alert-in: alert-in 360ms var(--ease-out-expo) both;
72
-
73
- @keyframes alert-in {
74
- from { opacity: 0; transform: translateY(-0.25rem); }
75
- }
76
- }
77
-
78
109
  @layer theme {
79
110
  :root {
80
- --ui-motion-quick: 140ms;
81
- --ui-motion-control: 180ms;
82
- --ui-motion-feedback: 160ms;
83
- --ui-press-scale: 0.96;
84
-
85
- --lch-sky: 55.6% 0.176 256.6;
86
- --lch-sky-deep: 51.5% 0.169 259.2;
87
- --lch-leaf: 58.6% 0.089 144.3;
88
- --lch-gold: 73.8% 0.130 86;
89
- --lch-berry: 63.5% 0.151 41.4;
90
-
91
- --paper: oklch(100% 0 0deg);
92
- --paper-2: oklch(97.6% 0.003 264.5deg);
93
- --paper-3: oklch(95.2% 0.006 264.5deg);
94
- --ink: oklch(23.1% 0.010 268.2deg);
95
- --ink-2: oklch(39.4% 0.012 267deg);
96
- --ink-3: oklch(52.0% 0.014 267deg);
97
- --ink-on-accent: #fff;
98
- --hairline: oklch(93.1% 0.006 264.5deg);
99
-
100
- --scrim: color-mix(in oklab, var(--ink) 55%, transparent);
101
- --scrim-soft: color-mix(in oklab, var(--ink) 12%, transparent);
102
-
103
- --scrim-sheet: rgb(0 0 0 / 0.28);
104
-
105
- --sky: oklch(var(--lch-sky));
106
- --sky-deep: oklch(var(--lch-sky-deep));
107
- --sky-soft: oklch(95.2% 0.023 258.4deg);
108
- --accent: var(--sky-deep);
109
-
110
- --leaf: oklch(var(--lch-leaf));
111
- --leaf-soft: oklch(95.0% 0.015 136deg);
112
- --gold: oklch(var(--lch-gold));
113
- --gold-soft: oklch(95.5% 0.040 88deg);
114
- --berry: oklch(var(--lch-berry));
115
- --berry-soft: oklch(95.4% 0.020 58deg);
116
- --danger: var(--berry);
117
- --danger-soft: var(--berry-soft);
118
-
119
- --f-display: ui-sans-serif, system-ui, sans-serif;
120
- --f-body: ui-sans-serif, system-ui, sans-serif;
121
- --f-japanese: "Hiragino Sans", "Yu Gothic", "YuGothic", "Meiryo", ui-sans-serif, system-ui, sans-serif;
122
- --f-mono: ui-monospace, "SFMono-Regular", "SF Mono", menlo, consolas, monospace;
123
-
124
- --shadow-sm: 0 1px 2px rgb(16 24 40 / 0.05);
125
- --shadow:
126
- 0 1px 3px rgb(16 24 40 / 0.05),
127
- 0 8px 24px -8px rgb(16 24 40 / 0.09);
128
- --shadow-lg:
129
- 0 1px 3px rgb(16 24 40 / 0.06),
130
- 0 24px 48px -12px rgb(16 24 40 / 0.18);
131
-
132
- --glass-fill: color-mix(in oklab, var(--paper) 74%, transparent);
133
- --glass-edge: rgb(255 255 255 / 0.4);
134
- --glass-bar-edge: var(--glass-edge);
135
- --glass-rim:
111
+ --radius: 0.5rem;
112
+ --lc-density: 1;
113
+ --lc-inset: calc(var(--spacing) * 5 * var(--lc-density));
114
+ --lc-gutter: clamp(1rem, 3vw, 1.5rem);
115
+ --lc-control-sm: calc(var(--spacing) * 8 * var(--lc-density));
116
+ --lc-control-md: calc(var(--spacing) * 10 * var(--lc-density));
117
+ --lc-control-lg: calc(var(--spacing) * 12 * var(--lc-density));
118
+
119
+ --lc-motion-quick: 140ms;
120
+ --lc-motion-control: 180ms;
121
+ --lc-motion-feedback: 160ms;
122
+ --lc-press-scale: 0.96;
123
+ --lc-ease-out: cubic-bezier(0.3, 0, 0, 1);
124
+ --lc-ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
125
+ --lc-ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
126
+ --lc-sheet-duration: 500ms;
127
+ --lc-sheet-offscreen: calc(100% + 2rem);
128
+
129
+ --lc-z-raised: 1;
130
+ --lc-z-sticky: 20;
131
+
132
+ /* Dialogs, sheets, menus, popovers, tooltips and toasts open in the
133
+ browser's top layer, above every z-index. These order them only where
134
+ the Popover API is missing. */
135
+ --lc-z-popover: 30;
136
+ --lc-z-overlay: 60;
137
+ --lc-z-toast: 70;
138
+
139
+ --background: oklch(100% 0 0deg);
140
+ --foreground: oklch(23.1% 0 0deg);
141
+
142
+ /* Cards and secondary buttons follow --muted and --accent unless set. */
143
+ --card: var(--muted);
144
+ --card-foreground: var(--foreground);
145
+ --popover: var(--background);
146
+ --popover-foreground: var(--foreground);
147
+ --primary: oklch(23.1% 0 0deg);
148
+ --primary-foreground: #fff;
149
+ --secondary: var(--accent);
150
+ --secondary-foreground: var(--foreground);
151
+ --muted: oklch(97.6% 0 0deg);
152
+ --muted-foreground: oklch(48% 0 0deg);
153
+ --accent: oklch(95.2% 0 0deg);
154
+ --accent-foreground: var(--foreground);
155
+ --destructive: oklch(50% 0.151 41.4deg);
156
+ --success: oklch(48% 0.089 144.3deg);
157
+ --warning: oklch(48% 0.090 86deg);
158
+ --border: oklch(93.1% 0 0deg);
159
+ --input: color-mix(in oklab, var(--foreground) 8%, var(--accent));
160
+
161
+ --lc-scrim: color-mix(in oklab, var(--foreground) 55%, transparent);
162
+ --lc-scrim-soft: color-mix(in oklab, var(--foreground) 12%, transparent);
163
+ --lc-scrim-sheet: rgb(0 0 0 / 0.28);
164
+ --lc-input-hover: color-mix(in oklab, var(--foreground) 13%, var(--accent));
165
+
166
+ --lc-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05);
167
+ --lc-shadow:
168
+ 0 1px 3px rgb(0 0 0 / 0.05),
169
+ 0 8px 24px -8px rgb(0 0 0 / 0.09);
170
+ --lc-shadow-lg:
171
+ 0 1px 3px rgb(0 0 0 / 0.06),
172
+ 0 24px 48px -12px rgb(0 0 0 / 0.18);
173
+
174
+ --lc-glass-fill: color-mix(in oklab, var(--background) 74%, transparent);
175
+ --lc-glass-edge: rgb(255 255 255 / 0.4);
176
+ --lc-glass-bar-edge: var(--lc-glass-edge);
177
+ --lc-glass-rim:
136
178
  inset 0 1px 0 rgb(255 255 255 / 0.6),
137
179
  inset 0 0 0 1px rgb(255 255 255 / 0.22);
138
- --glass-shadow: var(--glass-rim), var(--shadow);
180
+ --lc-glass-shadow: var(--lc-glass-rim), var(--lc-shadow);
139
181
 
140
- --glass-hud-fill:
182
+ --lc-glass-hud-fill:
141
183
  linear-gradient(rgb(255 255 255 / 0.6), rgb(255 255 255 / 0) 60%),
142
- color-mix(in oklab, var(--paper) 82%, transparent);
143
- --glass-hud-ink: var(--ink);
144
- --glass-hud-solid: var(--paper);
145
- --glass-hud-shadow:
146
- inset 0 0 0 1px rgb(16 24 40 / 0.08),
147
- 0 1px 2px rgb(16 24 40 / 0.06),
148
- 0 6px 16px -6px rgb(16 24 40 / 0.16);
149
-
150
- --pill-rim: linear-gradient(135deg, #fff 0%, #dcdce0 30%, #f7f7f8 55%, #c9c9ce 100%);
151
- --pill-surface: linear-gradient(#fff, #f1f1f4);
152
- --pill-light: inset 0 1px 0 #fff, inset 0 -1px 1px rgb(0 0 0 / 0.06);
153
- --pill-depth: 0 1px 1px rgb(0 0 0 / 0.08), 0 8px 18px -6px rgb(0 0 0 / 0.18);
154
-
155
- --focus-halo-color: color-mix(in oklab, var(--sky) 50%, transparent);
156
- --focus-halo: 0 0 0 calc(var(--spacing) * 0.5) var(--focus-halo-color);
157
-
158
- color-scheme: light;
159
-
160
- }
161
-
162
- html:lang(ja) {
163
- --f-display: var(--f-japanese);
164
- --f-body: var(--f-japanese);
184
+ color-mix(in oklab, var(--background) 82%, transparent);
185
+ --lc-glass-hud-ink: var(--foreground);
186
+ --lc-glass-hud-solid: var(--background);
187
+ --lc-glass-hud-shadow:
188
+ inset 0 0 0 1px rgb(0 0 0 / 0.08),
189
+ 0 1px 2px rgb(0 0 0 / 0.06),
190
+ 0 6px 16px -6px rgb(0 0 0 / 0.16);
191
+
192
+ /* Touch targets stay at least 40 and 44px. */
193
+ @media (pointer: coarse) {
194
+ --lc-control-sm: max(2.5rem, calc(var(--spacing) * 8 * var(--lc-density)));
195
+ --lc-control-md: max(2.75rem, calc(var(--spacing) * 10 * var(--lc-density)));
196
+ }
165
197
  }
166
198
 
167
199
  html[data-theme="dark"] {
168
- color-scheme: dark;
169
-
170
- --paper: oklch(20.5% 0.002 75deg);
171
- --paper-2: oklch(24.2% 0.003 75deg);
172
- --paper-3: oklch(28.4% 0.004 75deg);
173
- --ink: oklch(91.5% 0.006 85deg);
174
- --ink-2: color-mix(in oklab, var(--ink) 76%, var(--paper));
175
- --ink-3: color-mix(in oklab, var(--ink) 68%, var(--paper));
176
- --hairline: color-mix(in oklab, var(--ink) 16%, transparent);
177
-
178
- --scrim: rgb(0 0 0 / 0.6);
179
- --scrim-soft: rgb(0 0 0 / 0.32);
180
-
181
- --ink-on-accent: var(--paper);
182
- --sky: oklch(65.5% 0.150 255deg);
183
- --sky-deep: oklch(61.5% 0.155 257deg);
184
- --sky-soft: color-mix(in oklab, var(--sky) 18%, var(--paper));
185
- --accent: var(--sky);
186
-
187
- --leaf-soft: color-mix(in oklab, var(--leaf) 16%, var(--paper));
188
- --gold-soft: color-mix(in oklab, var(--gold) 16%, var(--paper));
189
- --berry-soft: color-mix(in oklab, var(--berry) 16%, var(--paper));
190
-
191
- --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.2);
192
- --shadow:
200
+ --background: oklch(20.5% 0 0deg);
201
+ --foreground: oklch(91.5% 0 0deg);
202
+ --primary: oklch(91.5% 0 0deg);
203
+ --primary-foreground: var(--background);
204
+ --muted: oklch(24.2% 0 0deg);
205
+ --muted-foreground: color-mix(in oklab, var(--foreground) 76%, var(--background));
206
+ --accent: oklch(28.4% 0 0deg);
207
+ --destructive: oklch(78% 0.120 41.4deg);
208
+ --success: oklch(78% 0.089 144.3deg);
209
+ --warning: oklch(80% 0.110 86deg);
210
+ --border: color-mix(in oklab, var(--foreground) 16%, transparent);
211
+
212
+ --lc-scrim: rgb(0 0 0 / 0.6);
213
+ --lc-scrim-soft: rgb(0 0 0 / 0.32);
214
+
215
+ --lc-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.2);
216
+ --lc-shadow:
193
217
  0 1px 2px rgb(0 0 0 / 0.16),
194
218
  0 8px 24px -8px rgb(0 0 0 / 0.32);
195
- --shadow-lg:
219
+ --lc-shadow-lg:
196
220
  0 1px 3px rgb(0 0 0 / 0.2),
197
221
  0 24px 48px -12px rgb(0 0 0 / 0.55);
198
222
 
199
- --glass-fill: color-mix(in oklab, var(--paper) 80%, transparent);
200
- --glass-edge: transparent;
201
- --glass-rim: 0 0 #0000;
202
- --glass-bar-edge: rgb(255 255 255 / 0.06);
203
- --glass-shadow: 0 1px 3px rgb(0 0 0 / 0.04), 0 4px 12px rgb(0 0 0 / 0.03);
204
- --glass-hud-fill:
223
+ --lc-glass-fill: color-mix(in oklab, var(--background) 80%, transparent);
224
+ --lc-glass-edge: transparent;
225
+ --lc-glass-rim: 0 0 #0000;
226
+ --lc-glass-bar-edge: rgb(255 255 255 / 0.06);
227
+ --lc-glass-shadow: 0 1px 3px rgb(0 0 0 / 0.04), 0 4px 12px rgb(0 0 0 / 0.03);
228
+ --lc-glass-hud-fill:
205
229
  linear-gradient(rgb(255 255 255 / 0.06), rgb(255 255 255 / 0) 60%),
206
- color-mix(in oklab, var(--paper-3) 90%, transparent);
207
- --glass-hud-solid: var(--paper-3);
208
- --glass-hud-shadow:
230
+ color-mix(in oklab, var(--accent) 90%, transparent);
231
+ --lc-glass-hud-solid: var(--accent);
232
+ --lc-glass-hud-shadow:
209
233
  inset 0 1px 0 rgb(255 255 255 / 0.1),
210
234
  inset 0 0 0 1px rgb(255 255 255 / 0.1),
211
235
  0 8px 20px -8px rgb(0 0 0 / 0.6);
212
-
213
- --pill-rim: linear-gradient(135deg, rgb(255 255 255 / 0.22) 0%, rgb(255 255 255 / 0.06) 30%, rgb(255 255 255 / 0.12) 55%, rgb(0 0 0 / 0.3) 100%);
214
- --pill-surface: linear-gradient(var(--paper-3), var(--paper-2));
215
- --pill-light: inset 0 1px 0 rgb(255 255 255 / 0.08), inset 0 -1px 1px rgb(0 0 0 / 0.2);
216
- --pill-depth: 0 1px 1px rgb(0 0 0 / 0.3), 0 8px 18px -6px rgb(0 0 0 / 0.5);
217
236
  }
218
- }
219
-
220
- @layer base {
221
- body {
222
- background-color: var(--paper);
223
- color: var(--ink);
224
- font-family: var(--f-body);
225
- line-height: 1.5;
226
- }
227
-
228
- :is(h1, h2, h3, h4, h5) {
229
- font-family: var(--f-display);
230
- line-height: 1.2;
231
- color: var(--ink);
232
- }
233
-
234
- button { cursor: pointer; background: none; }
235
-
236
- dialog { background: transparent; color: inherit; }
237
237
 
238
- :where([popover]) { color: inherit; }
239
-
240
- :is(a, button, input, textarea, select, summary, [tabindex]):focus-visible,
241
- label:has(input.sr-only:focus-visible) {
242
- outline: calc(var(--spacing) * 0.5) solid var(--focus-halo-color);
243
- outline-offset: 0;
244
- }
245
-
246
- dialog:focus-visible { outline: none; }
247
-
248
- @media (prefers-reduced-motion: reduce) {
249
- *, *::before, *::after {
250
- animation-duration: 0.01ms !important;
251
- animation-iteration-count: 1 !important;
252
- transition-duration: 0.01ms !important;
253
- }
254
- }
238
+ html:lang(ja) { --font-sans: var(--font-japanese); }
255
239
  }
@@ -0,0 +1,23 @@
1
+ @layer components {
2
+ /* lc-toast-region opens it as a popover; these rules also override the
3
+ popover defaults, which would centre it and hide it while closed. */
4
+ .lc-toast-region {
5
+ position: fixed;
6
+ inset: auto var(--spacing-gutter) var(--spacing-gutter) auto;
7
+ z-index: var(--lc-z-toast);
8
+ display: flex;
9
+ flex-direction: column;
10
+ align-items: flex-end;
11
+ gap: var(--spacing-related);
12
+ max-inline-size: calc(100vw - var(--spacing-gutter) * 2);
13
+ margin: 0;
14
+ padding: 0;
15
+ overflow: visible;
16
+ border: 0;
17
+ background: none;
18
+ color: inherit;
19
+
20
+ &:dir(rtl) { inset: auto auto var(--spacing-gutter) var(--spacing-gutter); }
21
+ &:empty { display: none; }
22
+ }
23
+ }
@@ -0,0 +1,51 @@
1
+ @layer components {
2
+ /* lc-tooltip lifts the content into the top layer while it shows. Without
3
+ JavaScript or the Popover API it shows in place, over its neighbours. */
4
+ .lc-tooltip__content {
5
+ position: absolute;
6
+ inset-block-end: calc(100% + var(--spacing-related));
7
+ inset-inline-start: 50%;
8
+ z-index: var(--lc-z-popover);
9
+ inline-size: max-content;
10
+ max-inline-size: min(16rem, calc(100vw - 2rem));
11
+ overflow: visible;
12
+ padding: var(--spacing-tight) var(--spacing-related);
13
+ border: 0;
14
+ border-radius: var(--radius-md);
15
+ background: var(--foreground);
16
+ color: var(--background);
17
+ font-size: var(--text-caption);
18
+ line-height: var(--text-caption--line-height);
19
+ font-weight: 500;
20
+ text-align: center;
21
+ pointer-events: none;
22
+ opacity: 0;
23
+ visibility: hidden;
24
+ translate: -50% 0;
25
+
26
+ /* allow-discrete keeps a lifted tooltip in the top layer while it fades out. */
27
+ transition:
28
+ opacity 120ms var(--lc-ease-out),
29
+ visibility 120ms,
30
+ display 120ms allow-discrete,
31
+ overlay 120ms allow-discrete;
32
+
33
+ &:dir(rtl) { translate: 50% 0; }
34
+ }
35
+
36
+ .lc-tooltip[data-side="bottom"] > .lc-tooltip__content {
37
+ inset-block: calc(100% + var(--spacing-related)) auto;
38
+ }
39
+
40
+ .lc-tooltip:is([data-open], :hover, :has(:focus-visible)) > .lc-tooltip__content {
41
+ opacity: 1;
42
+ visibility: visible;
43
+ transition-delay: 300ms;
44
+ }
45
+
46
+ .lc-tooltip[data-dismissed] > .lc-tooltip__content {
47
+ opacity: 0;
48
+ visibility: hidden;
49
+ transition: none;
50
+ }
51
+ }
@@ -1,81 +1,51 @@
1
+ /* Type roles are utilities from theme.css (text-title, text-heading, text-body
2
+ …). These classes add what a role cannot carry: the display family, wrapping
3
+ and Japanese line breaking. */
1
4
  @layer components {
2
- :where(.ui-heading) {
3
- font-family: var(--font-display, var(--font-body, inherit));
4
- font-weight: var(--ui-heading-weight, 700);
5
- letter-spacing: var(--ui-heading-tracking, -0.025em);
5
+ :where(.lc-heading) {
6
+ font-family: var(--font-display);
6
7
  overflow-wrap: anywhere;
7
8
  text-wrap: balance;
8
9
  }
9
10
 
10
- :where(.ui-heading-page) {
11
- font-size: var(--ui-heading-page-size, 1.875rem);
12
- line-height: var(--ui-heading-page-line-height, 2.25rem);
13
- }
14
-
15
- :where(.ui-heading-section) {
16
- font-size: var(--ui-heading-section-size, 1.25rem);
17
- line-height: var(--ui-heading-section-line-height, 1.5rem);
18
- }
19
-
20
- :where(.ui-heading-card) {
21
- font-size: var(--ui-heading-card-size, 1.125rem);
22
- line-height: var(--ui-heading-card-line-height, 1.5rem);
23
- }
24
-
25
- :where(.ui-heading:lang(ja)) {
26
- letter-spacing: var(--ui-heading-ja-tracking, 0);
27
- line-break: strict;
28
- }
29
-
30
- :where(.ui-text) {
31
- font-family: var(--font-body, inherit);
32
- font-weight: var(--ui-text-weight, 400);
33
- letter-spacing: var(--ui-text-tracking, normal);
11
+ :where(.lc-text) {
34
12
  overflow-wrap: anywhere;
35
13
  }
36
14
 
37
- :where(.ui-text-body) {
38
- font-size: var(--ui-text-body-size, 1rem);
39
- line-height: var(--ui-text-body-line-height, 1.5rem);
40
- }
41
-
42
- :where(.ui-text-small) {
43
- font-size: var(--ui-text-small-size, 0.875rem);
44
- line-height: var(--ui-text-small-line-height, 1.25rem);
45
- }
46
-
47
- :where(.ui-text-caption) {
48
- font-size: var(--ui-text-caption-size, 0.75rem);
49
- line-height: var(--ui-text-caption-line-height, 1rem);
50
- }
51
-
52
- :where(.ui-text:lang(ja)) {
15
+ /* Type role utilities read --tw-tracking first, so this wins over their tracking. */
16
+ :where(.lc-heading, .lc-text):lang(ja) {
17
+ --tw-tracking: 0;
53
18
  line-break: strict;
54
19
  }
55
20
 
56
21
  @supports (word-break: auto-phrase) {
57
- :where(.ui-heading:lang(ja)) {
22
+ :where(.lc-heading:lang(ja)) {
58
23
  word-break: auto-phrase;
59
24
  }
60
25
  }
61
26
  }
62
27
 
63
- @layer utilities {
64
- :where(code):not(:where(pre code)),
65
- .ui-prose :where(code):not(:where(pre code)) {
66
- font-family: var(--f-mono);
67
- font-size: 0.875em;
68
- font-weight: inherit;
69
- line-height: inherit;
70
- color: var(--ink);
71
- background-color: var(--paper-3);
72
- border-radius: var(--radius-sm);
73
- padding: 0.125em 0.375em;
74
- overflow-wrap: anywhere;
28
+ /* Trims the space above the cap height and below the baseline, so padding and
29
+ gaps measure the visible text. Browsers without text-box keep the leading. */
30
+ @utility lc-trim {
31
+ text-box: trim-both cap alphabetic; /* browser-compat: enhancement */
32
+ }
75
33
 
76
- &::before,
77
- &::after {
78
- content: none;
79
- }
34
+ /* Inline code inside running text. base.css applies it to every <code>; prose.css
35
+ applies it inside .lc-prose. */
36
+ @utility lc-inline-code {
37
+ font-family: var(--font-mono);
38
+ font-size: 0.875em;
39
+ font-weight: inherit;
40
+ line-height: inherit;
41
+ color: var(--foreground);
42
+ background-color: var(--accent);
43
+ border-radius: var(--radius-sm);
44
+ padding: 0.125em 0.375em;
45
+ overflow-wrap: anywhere;
46
+
47
+ &::before,
48
+ &::after {
49
+ content: none;
80
50
  }
81
51
  }