shopify-accelerate-app 1.1.9 → 1.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopify-accelerate-app",
3
- "version": "1.1.9",
3
+ "version": "1.2.11",
4
4
  "description": "Shopify App development with full Typescript Support",
5
5
  "author": "Felix Tellmann",
6
6
  "license": "MIT",
@@ -34,7 +34,9 @@
34
34
  "dependencies": {
35
35
  "@swc/core": "^1.9.3",
36
36
  "@swc/helpers": "^0.5.15",
37
- "@tailwindcss/cli": "^4.2.1",
37
+ "@tailwindcss/aspect-ratio": "^0.4.2",
38
+ "@tailwindcss/container-queries": "^0.1.1",
39
+ "autoprefixer": "^10.4.20",
38
40
  "chalk": "4.1.2",
39
41
  "commander": "^12.1.0",
40
42
  "dotenv-mono": "^1.3.14",
@@ -48,16 +50,18 @@
48
50
  "json2toml": "^6.1.1",
49
51
  "node-watch": "^0.7.4",
50
52
  "postcss": "^8.4.49",
53
+ "postcss-import": "^16.1.0",
51
54
  "preact": "^10.25.0",
52
55
  "prompts": "^2.4.2",
53
56
  "regenerator-runtime": "^0.14.1",
54
57
  "shopify-typed-node-api": "^2.1.1",
55
- "tailwindcss": "^4.0.0",
58
+ "tailwindcss": "0.0.0-insiders.6069a81",
59
+ "tailwindcss-container-queries-with-max-width": "^0.1.5",
56
60
  "toml": "^3.0.0",
57
61
  "ts-node": "^10.9.2",
58
62
  "tsconfig-paths": "^4.2.0",
59
63
  "zustand": "^5.0.1",
60
- "tw-animate-css": "^1.0.0"
64
+ "tailwindcss-animate": "^1.0.7"
61
65
  },
62
66
  "devDependencies": {
63
67
  "@types/inquirer": "^9.0.7",
@@ -28,9 +28,6 @@ export const transformClassNameStrings = (stringContent, final = false, cssOutpu
28
28
  }
29
29
  const classNameString = special ? stringContent.split(" ") : stringContent.replace(/\s+/gi, " ").split(" ");
30
30
 
31
- // v4 prefix uses colon separator (tw:flex) instead of dash (tw-flex)
32
- const prefix_sep = `${prefix}:`;
33
-
34
31
  const prefixedClassNames = classNameString.map((className) => {
35
32
  if (!className.trim()) return className;
36
33
 
@@ -47,17 +44,17 @@ export const transformClassNameStrings = (stringContent, final = false, cssOutpu
47
44
  }
48
45
  if (
49
46
  final &&
50
- (str.startsWith(prefix_sep) || str.startsWith(`!${prefix_sep}`)) &&
47
+ (str.startsWith(`${prefix}-`) || str.startsWith(`!${prefix}-`)) &&
51
48
  !cssOutput?.includes(str.replace(/([@()%,/.[\]])/gi, "\\$1"))
52
49
  ) {
53
50
  notCSSClasses.set(str, str.replace(/([@()%,/.[\]])/gi, "\\$1"));
54
- return str.replace(prefix_sep, "").replace(`!${prefix_sep}`, "");
51
+ return str.replace(`${prefix}-`, "").replace(`!${prefix}-`, "");
55
52
  }
56
- if (index === arr.length - 1 && !str.startsWith(prefix_sep) && !str.startsWith(`!${prefix_sep}`)) {
53
+ if (index === arr.length - 1 && !str.startsWith(`${prefix}-`) && !str.startsWith(`!${prefix}-`)) {
57
54
  if (/^!/gi.test(str)) {
58
- return `!${prefix_sep}${str.replace(/^!/gi, "")}`;
55
+ return `!${prefix}-${str.replace(/^!/gi, "")}`;
59
56
  }
60
- return `${prefix_sep}${str}`;
57
+ return `${prefix}-${str}`;
61
58
  }
62
59
  return str;
63
60
  })
@@ -65,21 +62,21 @@ export const transformClassNameStrings = (stringContent, final = false, cssOutpu
65
62
  }
66
63
  if (
67
64
  final &&
68
- (className.startsWith(prefix_sep) || className.startsWith(`!${prefix_sep}`)) &&
65
+ (className.startsWith(`${prefix}-`) || className.startsWith(`!${prefix}-`)) &&
69
66
  !cssOutput?.includes(`${className.replace(/([@()%,/.[\]])/gi, "\\$1")} `) &&
70
67
  !cssOutput?.includes(`${className.replace(/([@()%,/.[\]])/gi, "\\$1")}:`)
71
68
  ) {
72
69
  notCSSClasses.set(className, className.replace(/([@()%,/.[\]])/gi, "\\$1"));
73
- return className.replace(prefix_sep, "").replace(`!${prefix_sep}`, "");
70
+ return className.replace(`${prefix}-`, "").replace(`!${prefix}-`, "");
74
71
  }
75
72
 
76
- if (className.startsWith(prefix_sep) || className.startsWith(`!${prefix_sep}`)) {
73
+ if (className.startsWith(`${prefix}-`) || className.startsWith(`!${prefix}-`)) {
77
74
  return className;
78
75
  } else {
79
76
  if (/^!/gi.test(className)) {
80
- return `!${prefix_sep}${className.replace(/^!/gi, "")}`;
77
+ return `!${prefix}-${className.replace(/^!/gi, "")}`;
81
78
  }
82
- return `${prefix_sep}${className}`;
79
+ return `${prefix}-${className}`;
83
80
  }
84
81
  });
85
82
 
@@ -295,7 +295,8 @@ export const generateLiquidFiles = (final?: boolean, cssOutput?: string) => {
295
295
  const mergedTranslations = mergeLocales(translations, defaultSourceTranslations);
296
296
 
297
297
  const translationsJs = `<script>
298
- window._listify_translations = ${JSON.stringify(transformTranslations(mergedTranslations), undefined, 2)};
298
+ window.__listify = window.__listify || {};
299
+ window.__listify.translations = ${JSON.stringify(transformTranslations(mergedTranslations), undefined, 2)};
299
300
  </script>
300
301
  `;
301
302
 
@@ -306,11 +307,6 @@ export const generateLiquidFiles = (final?: boolean, cssOutput?: string) => {
306
307
  .replace(/`/gi, '"')
307
308
  .replace(/}\n/gi, "};\n")
308
309
  .replace(/\n\n/gi, "\n")};
309
- declare global {
310
- interface Window {
311
- _listify_translations?: Translations;
312
- }
313
- }
314
310
  `;
315
311
 
316
312
  writeCompareFile(
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ plugins: {
3
+ "postcss-import": {},
4
+ "tailwindcss/nesting": {},
5
+ tailwindcss: {},
6
+ autoprefixer: {},
7
+ },
8
+ };
@@ -1,5 +1,5 @@
1
+ // import { require } from "../../require";
1
2
  import child_process from "child_process";
2
- import esbuild from "esbuild";
3
3
  import fs from "fs";
4
4
  import path from "path";
5
5
  import { config, root_dir } from "../../shopify-accelerate-app";
@@ -7,165 +7,49 @@ import { writeCompareFile } from "../utils/fs";
7
7
 
8
8
  const watch = require("node-watch");
9
9
 
10
- /**
11
- * Generates the Tailwind v4 input CSS dynamically.
12
- * Combines the base config with conditional prefix/important options
13
- * and the user's _tailwind.css file.
14
- */
15
- const generateInputCSS = (base_css_path: string, user_css_path: string): string => {
16
- const { package_root } = config;
17
-
18
- const prefix = process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX;
19
- const important = process.env.SHOPIFY_ACCELERATE_TAILWIND_IMPORTANT;
20
-
21
- // Build the @import "tailwindcss" line with options
22
- // In v4, we import theme, preflight, and utilities as individual layers
23
- const tailwind_import_options: string[] = [];
24
- if (prefix) {
25
- tailwind_import_options.push(`prefix(${prefix})`);
26
- }
27
-
28
- // Resolve tailwindcss paths to absolute so they work from the generated file's location
29
- const tw_theme_path = path.join(package_root, "node_modules/tailwindcss/theme.css").replace(/\\/g, "/");
30
- const tw_preflight_path = path.join(package_root, "node_modules/tailwindcss/preflight.css").replace(/\\/g, "/");
31
- const tw_utilities_path = path.join(package_root, "node_modules/tailwindcss/utilities.css").replace(/\\/g, "/");
32
-
33
- let tailwind_import: string;
34
- if (important || tailwind_import_options.length > 0) {
35
- // When using prefix/important, import layers individually with options
36
- const theme_options = prefix ? ` prefix(${prefix})` : "";
37
- const utilities_options_parts: string[] = [];
38
- if (prefix) utilities_options_parts.push(`prefix(${prefix})`);
39
- if (important) utilities_options_parts.push(`important(${important})`);
40
- const utilities_options = utilities_options_parts.length > 0 ? ` ${utilities_options_parts.join(" ")}` : "";
41
-
42
- tailwind_import = [
43
- `@layer theme, base, components;`,
44
- `@import "${tw_theme_path}" layer(theme)${theme_options} source(none);`,
45
- `@import "${tw_preflight_path}" layer(base) source(none);`,
46
- `/* Utilities are NOT in a @layer so they keep normal cascade priority (like v3) and can override other libraries */`,
47
- `@import "${tw_utilities_path}"${utilities_options};`,
48
- ].join("\n");
49
- } else {
50
- // No prefix or important — simple imports
51
- tailwind_import = [
52
- `@layer theme, base, components;`,
53
- `@import "${tw_theme_path}" layer(theme) source(none);`,
54
- `@import "${tw_preflight_path}" layer(base) source(none);`,
55
- `/* Utilities are NOT in a @layer so they keep normal cascade priority (like v3) and can override other libraries */`,
56
- `@import "${tw_utilities_path}";`,
57
- ].join("\n");
58
- }
59
-
60
- // Source paths for content detection — resolve to absolute so they work from the generated file's location
61
- const extension_path_raw = process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH ?? "";
62
- const extension_path_abs = extension_path_raw ? path.resolve(root_dir, extension_path_raw).replace(/\\/g, "/") : "";
63
- const source_directive = extension_path_abs ? `@source "${extension_path_abs}/**/*.{html,liquid,js}";` : "";
64
-
65
- console.log({ source_directive });
66
-
67
- // Safelist equivalent via @source inline()
68
- const safelist_prefix = prefix ? `${prefix}:` : "";
69
- // eslint-disable-next-line max-len
70
- const safelist = `@source inline("${safelist_prefix}inset-0 ${safelist_prefix}pointer-events-none [&>*]:${safelist_prefix}pointer-events-auto");`;
71
-
72
- // Read the base CSS config (theme, variants, utilities, plugins)
73
- // Resolve bare package imports and relative paths to absolute so they work from the generated file's location
74
- const tw_animate_path = path.join(package_root, "node_modules/tw-animate-css/dist/tw-animate.css").replace(/\\/g, "/");
75
- const base_css_dir = path.dirname(base_css_path).replace(/\\/g, "/");
76
- const base_css = fs
77
- .readFileSync(base_css_path, { encoding: "utf-8" })
78
- .replace('@import "tw-animate-css"', `@import "${tw_animate_path}"`)
79
- .replace(/@plugin "\.\/([^"]+)"/g, `@plugin "${base_css_dir}/$1"`);
80
-
81
- // Read the user's _tailwind.css
82
- const user_css = fs.readFileSync(user_css_path, { encoding: "utf-8" });
83
-
84
- return [
85
- `/* Auto-generated Tailwind v4 input — do not edit */`,
86
- tailwind_import,
87
- ``,
88
- base_css,
89
- ``,
90
- source_directive,
91
- safelist,
92
- ``,
93
- `/* User styles */`,
94
- user_css,
95
- ].join("\n");
96
- };
97
-
98
- /**
99
- * Generates a `tailwind.config.css` at the consuming project root so that
100
- * IntelliJ / WebStorm's Tailwind Language Server can discover all custom
101
- * theme tokens, variants, and utilities for autocomplete.
102
- *
103
- * The file is NOT used by the build — it exists solely for IDE support.
104
- * Uses `writeCompareFile` to avoid unnecessary file-change events.
105
- */
106
- const generateIDEConfig = (base_css_import_path: string): void => {
107
- const ide_config_path = path.join(process.cwd(), "tailwind.config.css");
108
-
109
- const content = [
110
- `/* Auto-generated by shopify-accelerate-app for IDE autocomplete.`,
111
- ` This file is NOT used by the build — it exists solely so IntelliJ/WebStorm`,
112
- ` can provide Tailwind CSS class autocomplete with all custom theme values,`,
113
- ` variants, and utilities.`,
114
- ``,
115
- ` Do not edit — it will be regenerated on next \`dev\` start. */`,
116
- `@import "tailwindcss";`,
117
- `@import "${base_css_import_path}";`,
118
- ].join("\n");
119
-
120
- writeCompareFile(ide_config_path, content);
121
- };
122
-
123
10
  export const runTailwindCSSWatcher = () => {
124
11
  const { package_root } = config;
125
12
 
126
- const user_css_path = path.join(root_dir, "assets", "_tailwind.css");
127
- const input_exists = fs.existsSync(user_css_path);
13
+ const hasConfig = fs.existsSync(path.join(root_dir, "tailwind.config.js"));
14
+ const hasPostCss = fs.existsSync(path.join(root_dir, "postcss.config.js"));
15
+ const inputFile = fs.existsSync(path.join(root_dir, `assets`, `_tailwind.css`));
16
+ const resetInputFile = fs.existsSync(path.join(root_dir, `assets`, `_reset.css`));
128
17
 
129
- if (!input_exists) {
18
+ if (!inputFile) {
130
19
  console.log("Tailwind Input file not found");
131
20
  return;
132
21
  }
133
22
 
134
- const base_css_path = path.join(package_root, "src/tailwind/tailwind-base.css");
135
-
136
- // Generate IDE config for Tailwind autocomplete in IntelliJ/WebStorm
137
- generateIDEConfig("shopify-accelerate-app/src/tailwind/tailwind-base.css");
138
- const generated_input_path = path.join(config.extension_path, "assets", "_tailwind_generated.css");
139
- const pre_sort_path = path.join(config.extension_path, "assets", "tailwind_pre_sort.css");
140
-
141
- // Generate the combined input CSS
142
- const input_css = generateInputCSS(base_css_path, user_css_path);
143
- fs.writeFileSync(generated_input_path, input_css);
23
+ const filePath = path.join(config.extension_path, `assets`, `tailwind_pre_sort.css`);
144
24
 
145
25
  /*= =============== Tailwind Watcher ================ */
146
- console.log(`Tailwind v4 input: ${generated_input_path}`);
147
- console.log(`Tailwind v4 output: ${pre_sort_path}`);
148
- child_process.spawn("npx", ["@tailwindcss/cli", "-i", generated_input_path, "-o", pre_sort_path, "--watch"], {
149
- shell: true,
150
- stdio: "inherit",
151
- });
152
-
153
- // Regenerate input CSS when user's _tailwind.css changes
154
- watch(path.join(root_dir, "assets"), { recursive: false }, (evt: string, name: string) => {
155
- if (!name.match(/_tailwind\.css$/)) return;
156
- try {
157
- const updated_css = generateInputCSS(base_css_path, user_css_path);
158
- fs.writeFileSync(generated_input_path, updated_css);
159
- } catch (err) {
160
- console.log(err);
26
+ console.log(path.join(root_dir, `assets`, `_tailwind.css`));
27
+ console.log(path.join(package_root, `src/tailwind/tailwind.config.js`));
28
+ child_process.spawn(
29
+ "npx",
30
+ [
31
+ "tailwindcss",
32
+ "--config",
33
+ /*hasConfig ? "tailwind.config.js" :*/ path.join(package_root, `src/tailwind/tailwind.config.js`),
34
+ "--postcss",
35
+ /*hasPostCss ? "postcss.config.js" : */ path.join(package_root, `src/tailwind/postcss.config.js`),
36
+ "-i",
37
+ path.join(root_dir, `assets`, `_tailwind.css`),
38
+ "-o",
39
+ filePath,
40
+ "--watch",
41
+ ],
42
+ {
43
+ shell: true,
44
+ stdio: "inherit",
161
45
  }
162
- });
46
+ );
163
47
 
164
48
  /*= =============== Tailwind Plugin Order ================ */
165
- watch(path.join(config.extension_path, "assets"), { recursive: false }, async (evt: string, name: string) => {
49
+ watch(path.join(config.extension_path, "assets"), { recursive: false }, async (evt, name) => {
166
50
  try {
167
- if (!name.match(/tailwind_pre_sort.css$/) || !fs.existsSync(pre_sort_path)) return;
168
- const file = fs.readFileSync(pre_sort_path, { encoding: "utf-8" });
51
+ if (!name.match(/tailwind_pre_sort.css$/) || !fs.existsSync(filePath)) return;
52
+ const file = fs.readFileSync(filePath, { encoding: "utf-8" });
169
53
 
170
54
  const top = file
171
55
  .split(/\n}/gi)
@@ -177,48 +61,44 @@ export const runTailwindCSSWatcher = () => {
177
61
  .join("\n}")}\n`;
178
62
  const content = top + bottom;
179
63
 
180
- const classes_in_order: string[] = [];
181
- const omit_compound_classes = [":not", ":where", ">", "*", ","];
64
+ const classesInOrder = [];
65
+ const omitCompoundClasses = [":not", ":where", ">", "*", ","];
182
66
 
183
67
  content.split("\n").forEach((line) => {
184
68
  if (!line.startsWith(".")) {
185
69
  return;
186
70
  }
187
71
 
188
- let write_out = true;
72
+ let writeOut = true;
189
73
 
190
- omit_compound_classes.forEach((class_to_omit) => {
191
- if (line.includes(class_to_omit)) {
192
- write_out = false;
74
+ omitCompoundClasses.forEach((classToOmit) => {
75
+ if (line.includes(classToOmit)) {
76
+ writeOut = false;
193
77
  return;
194
78
  }
195
79
  });
196
80
 
197
- if (write_out) {
198
- const final_class_name = line.replace(/\./g, "").replace(/{/g, "").replace(/}/g, "").replace(/\\/g, "").trim();
199
- if (final_class_name !== "") {
200
- classes_in_order.push(`${final_class_name}`);
81
+ if (writeOut) {
82
+ const finalClassName = line.replace(/\./g, "").replace(/{/g, "").replace(/}/g, "").replace(/\\/g, "").trim();
83
+ if (finalClassName !== "") {
84
+ classesInOrder.push(`${finalClassName}`);
201
85
  }
202
86
  }
203
87
  });
204
88
 
205
- // Minify CSS after class extraction to reduce output size (~80KB ~30KB)
206
- const minified = (await esbuild.transform(content, { loader: "css", minify: true })).code;
207
-
208
- writeCompareFile(path.join(config.extension_path, `assets/tailwind.css`), minified);
89
+ writeCompareFile(path.join(config.extension_path, `assets/tailwind.css`), content);
209
90
 
210
91
  if (process.env.SHOPIFY_ACCELERATE_THEME_OUTPUT_PATH) {
211
- writeCompareFile(path.join(config.theme_output_path, `assets/listify-dev-tailwind.css`), minified);
92
+ writeCompareFile(path.join(config.theme_output_path, `assets/listify-dev-tailwind.css`), content);
212
93
  }
213
94
 
214
- // v4 prefix uses colon separator (tw:flex) instead of dash (tw-flex)
215
95
  writeCompareFile(
216
96
  path.join(process.cwd(), ".tailwindorder"),
217
- classes_in_order
97
+ classesInOrder
218
98
  .join("\n")
219
99
  .replace(
220
100
  new RegExp(
221
- `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}:` : ""}`,
101
+ `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}`,
222
102
  "gi"
223
103
  ),
224
104
  ""
@@ -0,0 +1,513 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ // eslint-disable-next-line node/no-unpublished-require
3
+ // import { require } from "../../require";
4
+ const { defaultExtractor: createDefaultExtractor } = require("tailwindcss/lib/lib/defaultExtractor");
5
+
6
+ const { default: resolveConfig } = require("tailwindcss/lib/util/resolveConfig");
7
+ const plugin = require("tailwindcss/plugin");
8
+ import { dotenvLoad } from "dotenv-mono";
9
+
10
+ const dotenv = dotenvLoad(); // Dotenv instance
11
+
12
+ /** Generate a full shade scale (50–950 + DEFAULT) from a CSS variable name */
13
+ function createColorScale(cssVar) {
14
+ const scale = { DEFAULT: `rgb(var(${cssVar}) / <alpha-value>)` };
15
+ for (const shade of [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]) {
16
+ scale[shade] = `rgb(var(${cssVar}-${shade}) / <alpha-value>)`;
17
+ }
18
+ return scale;
19
+ }
20
+
21
+ /*const defaultExtractor = createDefaultExtractor({
22
+ tailwindConfig: resolveConfig([
23
+ {
24
+ content: [
25
+ `${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.{html,liquid,js,json}`,
26
+ `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.css`,
27
+ `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.css`,
28
+ ],
29
+ },
30
+ ]),
31
+ });
32
+
33
+ const extractor = (content) => {
34
+ return defaultExtractor(content).map((cls) => {
35
+ console.log({ class: cls });
36
+ return `tw-${cls}`;
37
+ });
38
+ };*/
39
+
40
+ module.exports = {
41
+ content: {
42
+ files: [
43
+ `${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/**/*.{html,liquid,js,json}`,
44
+ `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.css`,
45
+ `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**/!*.css`,
46
+ ],
47
+ extract: {
48
+ // ts: extractor,
49
+ // tsx: extractor,
50
+ // html: extractor,
51
+ // liquid: (content) => {
52
+ // console.log({ content });
53
+ // return content;
54
+ // },
55
+ // js: extractor,
56
+ // json: extractor,
57
+ },
58
+ },
59
+ safelist: [
60
+ `!${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}fixed`,
61
+ `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}inset-0`,
62
+ `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}pointer-events-none`,
63
+ `${
64
+ process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""
65
+ }[&>*]:pointer-events-auto`,
66
+ ],
67
+ darkMode: "class", // or 'media' or 'class'
68
+ // important: true,
69
+ important: process.env.SHOPIFY_ACCELERATE_TAILWIND_IMPORTANT,
70
+ prefix: process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : undefined,
71
+ corePlugins: {
72
+ preflight: false,
73
+ },
74
+ mode: "jit",
75
+ theme: {
76
+ borderRadius: {
77
+ none: "0px",
78
+ sm: "2px",
79
+ DEFAULT: "4px",
80
+ md: "6px",
81
+ lg: "8px",
82
+ xl: "12px",
83
+ "2xl": "16px",
84
+ "3xl": "24px",
85
+ full: "9999px",
86
+ 0: "0px",
87
+ 1: "1px",
88
+ 2: "2px",
89
+ 3: "3px",
90
+ 4: "4px",
91
+ 5: "5px",
92
+ 6: "6px",
93
+ 7: "7px",
94
+ 8: "8px",
95
+ 9: "9px",
96
+ 10: "10px",
97
+ 11: "11px",
98
+ 12: "12px",
99
+ 13: "13px",
100
+ 14: "14px",
101
+ 15: "15px",
102
+ 16: "16px",
103
+ 17: "17px",
104
+ 18: "18px",
105
+ 19: "19px",
106
+ 20: "20px",
107
+ 21: "21px",
108
+ 22: "22px",
109
+ 23: "23px",
110
+ 24: "24px",
111
+ "theme-card": "var(--lx-card-radius)",
112
+ "theme-card-sm": "var(--lx-card-radius-sm)",
113
+ "theme-icon": "var(--lx-icon-radius)",
114
+ "theme-input": "var(--lx-input-radius, 6px)",
115
+ },
116
+ borderWidth: {
117
+ DEFAULT: "1px",
118
+ 0: "0px",
119
+ 2: "2px",
120
+ 3: "3px",
121
+ 4: "4px",
122
+ theme: "var(--lx-border-width)",
123
+ "theme-primary": "var(--lx-border-width-primary)",
124
+ },
125
+ columns: {
126
+ auto: "auto",
127
+ 1: "1",
128
+ 2: "2",
129
+ 3: "3",
130
+ 4: "4",
131
+ 5: "5",
132
+ 6: "6",
133
+ 7: "7",
134
+ 8: "8",
135
+ 9: "9",
136
+ 10: "10",
137
+ 11: "11",
138
+ 12: "12",
139
+ "3xs": "256px",
140
+ "2xs": "288px",
141
+ xs: "320px",
142
+ sm: "384px",
143
+ md: "448px",
144
+ lg: "512px",
145
+ xl: "576px",
146
+ "2xl": "672px",
147
+ "3xl": "768px",
148
+ "4xl": "896px",
149
+ "5xl": "1024px",
150
+ "6xl": "1152px",
151
+ "7xl": "1280px",
152
+ "8xl": "1440px",
153
+ },
154
+ fontSize: {
155
+ 8: ["9px", "1.55"],
156
+ 9: ["9px", "1.5"],
157
+ 10: ["10px", "1.5"],
158
+ 11: ["11px", "1.5"],
159
+ 12: ["12px", "1.5"],
160
+ 13: ["13px", "1.5"],
161
+ 14: ["14px", "1.5"],
162
+ 15: ["15px", "1.5"],
163
+ 16: ["16px", "1.5"],
164
+ 17: ["17px", "1.5"],
165
+ 18: ["18px", "1.45"],
166
+ 19: ["19px", "1.45"],
167
+ 20: ["20px", "1.45"],
168
+ 21: ["21px", "1.45"],
169
+ 22: ["22px", "1.4"],
170
+ 23: ["23px", "1.4"],
171
+ 24: ["24px", "1.4"],
172
+ xs: ["12px", { lineHeight: "16px" }],
173
+ sm: ["14px", { lineHeight: "20px" }],
174
+ base: ["16px", { lineHeight: "24px" }],
175
+ lg: ["18px", { lineHeight: "28px" }],
176
+ xl: ["20px", { lineHeight: "28px" }],
177
+ "2xl": ["24px", { lineHeight: "32px" }],
178
+ "3xl": ["30px", { lineHeight: "36px" }],
179
+ "4xl": ["36px", { lineHeight: "36px" }],
180
+ "5xl": ["48px", { lineHeight: "1" }],
181
+ "6xl": ["60px", { lineHeight: "1" }],
182
+ "7xl": ["72px", { lineHeight: "1" }],
183
+ "8xl": ["96px", { lineHeight: "1" }],
184
+ "9xl": ["144px", { lineHeight: "1" }],
185
+ },
186
+ lineHeight: {
187
+ 1: "1",
188
+ none: "1",
189
+ tight: "1.25",
190
+ snug: "1.375",
191
+ normal: "1.5",
192
+ relaxed: "1.625",
193
+ loose: "2",
194
+ 3: "12px",
195
+ 4: "16px",
196
+ 5: "20px",
197
+ 6: "24px",
198
+ 7: "28px",
199
+ 8: "32px",
200
+ 9: "36px",
201
+ 10: "40px",
202
+ },
203
+ maxWidth: ({ theme, breakpoints }) => ({
204
+ none: "none",
205
+ 0: "0px",
206
+ xs: "320px",
207
+ sm: "384px",
208
+ md: "448px",
209
+ lg: "512px",
210
+ xl: "576px",
211
+ "2xl": "672px",
212
+ "3xl": "768px",
213
+ "4xl": "896px",
214
+ "5xl": "1024px",
215
+ "6xl": "1152px",
216
+ "7xl": "1280px",
217
+ full: "100%",
218
+ min: "min-content",
219
+ max: "max-content",
220
+ fit: "fit-content",
221
+ prose: "65ch",
222
+ ...breakpoints(theme("screens")),
223
+ }),
224
+ spacing: {
225
+ px: "1px",
226
+ 0: "0",
227
+ 0.5: "2px",
228
+ 1: "4px",
229
+ 1.5: "6px",
230
+ 2: "8px",
231
+ 2.5: "10px",
232
+ 3: "12px",
233
+ 3.5: "14px",
234
+ 4: "16px",
235
+ 4.5: "18px",
236
+ 5: "20px",
237
+ 5.5: "22px",
238
+ 6: "24px",
239
+ 6.5: "26px",
240
+ 7: "28px",
241
+ 8: "32px",
242
+ 9: "36px",
243
+ 10: "40px",
244
+ 11: "44px",
245
+ 12: "48px",
246
+ 14: "56px",
247
+ 16: "64px",
248
+ 20: "80px",
249
+ 24: "96px",
250
+ 28: "112px",
251
+ 32: "128px",
252
+ 36: "144px",
253
+ 40: "160px",
254
+ 44: "176px",
255
+ 48: "192px",
256
+ 52: "208px",
257
+ 56: "224px",
258
+ 60: "240px",
259
+ 64: "256px",
260
+ 72: "288px",
261
+ 80: "320px",
262
+ 96: "384px",
263
+ },
264
+ extend: {
265
+ transitionTimingFunction: {
266
+ "slide-in": "cubic-bezier(0.32, 0.72, 0, 1)",
267
+ },
268
+ screens: {
269
+ xxs: "373px" /* tiny phone*/,
270
+ xs: "427px" /*smaller than iphone pro max*/,
271
+ },
272
+ containers: {
273
+ xxs: "373px" /* tiny phone*/,
274
+ xs: "427px" /*smaller than iphone pro max*/,
275
+ sm: "640px",
276
+ md: "768px",
277
+ lg: "1024px",
278
+ xl: "1280px",
279
+ "2xl": "1536px",
280
+ "max-xxs": "-373px" /* tiny phone*/,
281
+ "max-xs": "-427px" /*smaller than iphone pro max*/,
282
+ "max-sm": "-640px",
283
+ "max-md": "-768px",
284
+ "max-lg": "-1024px",
285
+ "max-xl": "-1280px",
286
+ "max-2xl": "-1536px",
287
+ },
288
+ fontSize: {
289
+ 8: ["9px", "1.55"],
290
+ 9: ["9px", "1.5"],
291
+ 10: ["10px", "1.5"],
292
+ 11: ["11px", "1.5"],
293
+ 12: ["12px", "1.5"],
294
+ 13: ["13px", "1.5"],
295
+ 14: ["14px", "1.5"],
296
+ 15: ["15px", "1.5"],
297
+ 16: ["16px", "1.5"],
298
+ 17: ["17px", "1.5"],
299
+ 18: ["18px", "1.45"],
300
+ 19: ["19px", "1.45"],
301
+ 20: ["20px", "1.45"],
302
+ 21: ["21px", "1.45"],
303
+ 22: ["22px", "1.4"],
304
+ 23: ["23px", "1.4"],
305
+ 24: ["24px", "1.4"],
306
+ },
307
+ maxWidth: {
308
+ "8xl": "90rem",
309
+ },
310
+ boxShadow: {
311
+ "invert-sm": "0 -1px 2px 0 rgb(0 0 0 / 0.05)",
312
+ invert: "0 -3px 5px 1px rgb(0 0 0 / 0.03), 0 -2px 4px 2px rgb(0 0 0 / 0.03)",
313
+ "invert-md": "0 -4px 6px 1px rgb(0 0 0 / 0.07), 0 -2px 4px 2px rgb(0 0 0 / 0.07)",
314
+ "invert-lg": "0 -10px 15px 3px rgb(0 0 0 / 0.1), 0 -4px 6px 4px rgb(0 0 0 / 0.1)",
315
+ "invert-xl": "0 -20px 25px 5px rgb(0 0 0 / 0.1), 0 -8px 10px 6px rgb(0 0 0 / 0.1)",
316
+ "invert-2xl": "0 -25px 50px 12px rgb(0 0 0 / 0.25)",
317
+ },
318
+ keyframes: {
319
+ slide: {
320
+ "0%, 100%": { transform: "translate3d(0,0,0)" },
321
+ "100%": { transform: "translate3d(-50%,0,0)" },
322
+ },
323
+ marquee1: {
324
+ "0%, 100%": { transform: "translate3d(0,0,0)" },
325
+ "100%": { transform: "translate3d(-100%,0,0)" },
326
+ },
327
+ marquee2: {
328
+ "0%, 100%": { transform: "translate3d(100%,0,0)" },
329
+ "100%": { transform: "translate3d(0,0,0)" },
330
+ },
331
+ circle: {
332
+ "0%": { strokeDashoffset: "90" },
333
+ "100%": { strokeDashoffset: "0" },
334
+ },
335
+ dot: {
336
+ "0%,95%": { fill: "transparent", stroke: "currentColor", strokeOpacity: "0.1" },
337
+ "100%": { fill: "currentColor", stroke: "transparent", strokeOpacity: "0" },
338
+ },
339
+ typewriter: {
340
+ "0%, 100%": { opacity: "1" },
341
+ "50%": { opacity: "0" },
342
+ },
343
+ "pulse-bg": {
344
+ "50%": { "--tw-bg-opacity": "0.5" },
345
+ },
346
+ shake: {
347
+ "0%, 100%": { transform: "translateX(0)" },
348
+ "20%, 60%": { transform: "translateX(-4px)" },
349
+ "40%, 80%": { transform: "translateX(4px)" },
350
+ },
351
+ },
352
+ animation: {
353
+ slide: "slide 30s linear infinite",
354
+ marquee1: "marquee1 30s linear infinite",
355
+ marquee2: "marquee2 30s linear infinite",
356
+ circle: "circle 8.1s linear",
357
+ dot: "dot 8.1s linear",
358
+ typewriter: "typewriter 0.5s linear infinite",
359
+ "pulse-bg": "pulse-bg 1s cubic-bezier(0.4, 0, 0.6, 1) infinite",
360
+ shake: "shake 0.4s ease-in-out",
361
+ },
362
+ colors: {
363
+ theme: {
364
+ primary: { ...createColorScale("--lx-color-primary"), contrast: "rgb(var(--lx-color-primary-contrast) / <alpha-value>)" },
365
+ accent: createColorScale("--lx-color-accent"),
366
+ "trigger-bg": "rgb(var(--lx-color-trigger-bg) / <alpha-value>)",
367
+ "trigger-text": "rgb(var(--lx-color-trigger-text) / <alpha-value>)",
368
+ bg: "rgb(var(--lx-color-bg) / <alpha-value>)",
369
+ text: "rgb(var(--lx-color-text) / <alpha-value>)",
370
+ "button-bg": "rgb(var(--lx-color-button-bg) / <alpha-value>)",
371
+ "button-text": "rgb(var(--lx-color-button-text) / <alpha-value>)",
372
+ },
373
+ },
374
+ },
375
+ variants: {
376
+ extend: {},
377
+ },
378
+ },
379
+ plugins: [
380
+ require("autoprefixer"),
381
+ require("@tailwindcss/aspect-ratio"),
382
+ require("tailwindcss-container-queries-with-max-width"),
383
+ require("tailwindcss-animate"),
384
+ // require("@tailwindcss/forms"),
385
+ plugin(({ addVariant, addUtilities, matchUtilities, theme }) => {
386
+ addVariant("svg", ["& svg"]);
387
+ addVariant("hfa", ["&:hover", "&:focus", "&:active"]);
388
+ addVariant("hfw", ["&:hover", "&:focus-visible", "&:focus-within"]);
389
+ addVariant("hfwa", ["&:hover", "&:focus-visible", "&:focus-within", "&:active"]);
390
+ addVariant("hfwaa", ["&:hover", "&:focus-visible", "&:focus-within", "&:active", "&.active"]);
391
+ addVariant("hfva", ["&:hover", "&:focus", "&:focus-visible", "&:active"]);
392
+ addVariant("ha", ["&:hover", "&:active"]);
393
+ addVariant("hf", ["&:hover", "&:focus-visible"]);
394
+ addVariant("fa", ["&:focus", "&:active"]);
395
+ addVariant("f", ["&:focus"]);
396
+ addVariant("fw", ["&:focus-within"]);
397
+ addVariant("fv", ["&:focus-visible"]);
398
+ addVariant("h", ["&:hover"]);
399
+ addVariant("d", [".dark &"]);
400
+ addVariant("ac", ["&.active"]);
401
+ addVariant("b", ["&::before"]);
402
+ addVariant("a", ["&::after"]);
403
+ addVariant("not-prose", [":not(.prose &)&"]);
404
+ addVariant("hfaa", ["&:hover", "&:focus", "&:active", "&.active"]);
405
+ addVariant("hfvaa", ["&:hover", "&:focus", "&:focus-visible", "&:active", "&.active"]);
406
+ addVariant("group-hfa", [".group:hover &", ".group:focus &", ".group:active &"]);
407
+ addVariant("group-hf", [".group:hover &", ".group:focus &"]);
408
+ addVariant("group-ac", [".group.active &"]);
409
+
410
+ addVariant("group-hfva", [".group:hover &", ".group:focus-visible &", ".group:active &"]);
411
+ addVariant("group-hfwa", [".group:hover &", ".group:focus-visible &", ".group:focus-within &", ".group:active &"]);
412
+ addVariant("group-hfw", [".group:hover &", ".group:focus-visible &", ".group:focus-within &"]);
413
+ addVariant("peer-hfwa", [".peer:hover ~ &", ".peer:focus-visible ~ &", ".peer:focus-within ~ &", ".peer:active ~ &"]);
414
+ addVariant("peer-fw", [".peer:focus-within ~ &"]);
415
+ matchUtilities(
416
+ {
417
+ "top-spacing": (value) => ({
418
+ top: `calc(${theme("spacing.top-bar-spacing")} + ${value})`,
419
+ }),
420
+ },
421
+ { values: theme("spacing") }
422
+ );
423
+ matchUtilities({
424
+ bgi: (value) => ({
425
+ background: value,
426
+ }),
427
+ });
428
+ matchUtilities(
429
+ {
430
+ "auto-col-flow": (value) => {
431
+ if (value?.includes("/")) {
432
+ const [cols, gap] = value.split("/");
433
+ const calculatedGap = /^(\d|\.)*$/gi.test(gap?.trim()) ? `${+gap * 4}px` : gap;
434
+
435
+ return {
436
+ gridAutoFlow: "column",
437
+ gridAutoColumns: ` calc((100% - (${calculatedGap} * (${cols} - 1))) / ${cols})`,
438
+ columnGap: `${calculatedGap}`,
439
+ };
440
+ }
441
+ return {
442
+ gridAutoFlow: "column",
443
+ gridAutoColumns: `${value}`,
444
+ };
445
+ },
446
+ },
447
+ { values: theme("width") }
448
+ );
449
+ matchUtilities(
450
+ {
451
+ "border-w": (value) => ({ borderWidth: value }),
452
+ },
453
+ { values: theme("borderWidth") }
454
+ );
455
+ matchUtilities(
456
+ {
457
+ "border-x-w": (value) => ({ borderLeftWidth: value, borderRightWidth: value }),
458
+ },
459
+ { values: theme("borderWidth") }
460
+ );
461
+ matchUtilities(
462
+ {
463
+ "border-y-w": (value) => ({ borderTopWidth: value, borderBottomWidth: value }),
464
+ },
465
+ { values: theme("borderWidth") }
466
+ );
467
+ matchUtilities(
468
+ {
469
+ "border-t-w": (value) => ({ borderTopWidth: value }),
470
+ },
471
+ { values: theme("borderWidth") }
472
+ );
473
+ matchUtilities(
474
+ {
475
+ "border-r-w": (value) => ({ borderRightWidth: value }),
476
+ },
477
+ { values: theme("borderWidth") }
478
+ );
479
+ matchUtilities(
480
+ {
481
+ "border-b-w": (value) => ({ borderBottomWidth: value }),
482
+ },
483
+ { values: theme("borderWidth") }
484
+ );
485
+ matchUtilities(
486
+ {
487
+ "border-l-w": (value) => ({ borderLeftWidth: value }),
488
+ },
489
+ { values: theme("borderWidth") }
490
+ );
491
+ addUtilities({
492
+ ".shape-geometric-precision": {
493
+ "shape-rendering": "geometricPrecision",
494
+ },
495
+ ".open-quote": {
496
+ content: "open-quote",
497
+ },
498
+ ".close-quote": {
499
+ content: "close-quote",
500
+ },
501
+ ".leading-0": {
502
+ "line-height": "0",
503
+ },
504
+ ".animation-pause": {
505
+ "animation-play-state": "paused",
506
+ },
507
+ ".animation-play": {
508
+ "animation-play-state": "running",
509
+ },
510
+ });
511
+ }),
512
+ ],
513
+ };
@@ -1,12 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "mcp__claude_ai_Context7__resolve-library-id",
5
- "WebSearch",
6
- "WebFetch(domain:kitemetric.com)",
7
- "WebFetch(domain:www.jetbrains.com)",
8
- "WebFetch(domain:github.com)",
9
- "Bash(cd:*)"
10
- ]
11
- }
12
- }
@@ -1,25 +0,0 @@
1
- const plugin = require("tailwindcss/plugin");
2
-
3
- module.exports = plugin(({ matchUtilities, theme }) => {
4
- matchUtilities(
5
- {
6
- "auto-col-flow": (value) => {
7
- if (value?.includes("/")) {
8
- const [cols, gap] = value.split("/");
9
- const calculatedGap = /^(\d|\.)*$/gi.test(gap?.trim()) ? `${+gap * 4}px` : gap;
10
-
11
- return {
12
- gridAutoFlow: "column",
13
- gridAutoColumns: `calc((100% - (${calculatedGap} * (${cols} - 1))) / ${cols})`,
14
- columnGap: calculatedGap,
15
- };
16
- }
17
- return {
18
- gridAutoFlow: "column",
19
- gridAutoColumns: value,
20
- };
21
- },
22
- },
23
- { values: theme("width") }
24
- );
25
- });
@@ -1,330 +0,0 @@
1
- /* ============================================================
2
- Tailwind CSS v4 — Base Configuration
3
- This file is used as a template. At runtime, tailwind-watch.ts
4
- generates the final input CSS by prepending prefix/important
5
- options and appending the user's _tailwind.css via @import.
6
- ============================================================ */
7
-
8
- /* The @import "tailwindcss" line is generated dynamically in tailwind-watch.ts
9
- to support conditional prefix() and important() options. */
10
-
11
- /* --- Animations (replaces tailwindcss-animate) --- */
12
- @import "tw-animate-css";
13
-
14
- /* --- Theme Overrides --- */
15
- @theme {
16
- /* ---- Spacing (4px base) ---- */
17
- --spacing: 4px;
18
- --spacing-px: 1px;
19
- --spacing-0: 0;
20
- --spacing-0_5: 2px;
21
- --spacing-1: 4px;
22
- --spacing-1_5: 6px;
23
- --spacing-2: 8px;
24
- --spacing-2_5: 10px;
25
- --spacing-3: 12px;
26
- --spacing-3_5: 14px;
27
- --spacing-4: 16px;
28
- --spacing-5: 20px;
29
- --spacing-6: 24px;
30
- --spacing-7: 28px;
31
- --spacing-8: 32px;
32
- --spacing-9: 36px;
33
- --spacing-10: 40px;
34
- --spacing-11: 44px;
35
- --spacing-12: 48px;
36
- --spacing-14: 56px;
37
- --spacing-16: 64px;
38
- --spacing-20: 80px;
39
- --spacing-24: 96px;
40
- --spacing-28: 112px;
41
- --spacing-32: 128px;
42
- --spacing-36: 144px;
43
- --spacing-40: 160px;
44
- --spacing-44: 176px;
45
- --spacing-48: 192px;
46
- --spacing-52: 208px;
47
- --spacing-56: 224px;
48
- --spacing-60: 240px;
49
- --spacing-64: 256px;
50
- --spacing-72: 288px;
51
- --spacing-80: 320px;
52
- --spacing-96: 384px;
53
-
54
- /* ---- Border Radius ---- */
55
- --radius-none: 0px;
56
- --radius-xs: 2px;
57
- --radius-sm: 2px;
58
- --radius-DEFAULT: 4px;
59
- --radius-md: 6px;
60
- --radius-lg: 8px;
61
- --radius-xl: 12px;
62
- --radius-2xl: 16px;
63
- --radius-3xl: 24px;
64
- --radius-full: 9999px;
65
-
66
- /* ---- Font Size ---- */
67
- --text-8: 9px;
68
- --text-8--line-height: 1.55;
69
- --text-9: 9px;
70
- --text-9--line-height: 1.5;
71
- --text-10: 10px;
72
- --text-10--line-height: 1.5;
73
- --text-11: 11px;
74
- --text-11--line-height: 1.5;
75
- --text-12: 12px;
76
- --text-12--line-height: 1.5;
77
- --text-13: 13px;
78
- --text-13--line-height: 1.5;
79
- --text-14: 14px;
80
- --text-14--line-height: 1.5;
81
- --text-15: 15px;
82
- --text-15--line-height: 1.5;
83
- --text-16: 16px;
84
- --text-16--line-height: 1.5;
85
- --text-17: 17px;
86
- --text-17--line-height: 1.5;
87
- --text-18: 18px;
88
- --text-18--line-height: 1.45;
89
- --text-19: 19px;
90
- --text-19--line-height: 1.45;
91
- --text-20: 20px;
92
- --text-20--line-height: 1.45;
93
- --text-21: 21px;
94
- --text-21--line-height: 1.45;
95
- --text-22: 22px;
96
- --text-22--line-height: 1.4;
97
- --text-23: 23px;
98
- --text-23--line-height: 1.4;
99
- --text-24: 24px;
100
- --text-24--line-height: 1.4;
101
- --text-xs: 12px;
102
- --text-xs--line-height: 16px;
103
- --text-sm: 14px;
104
- --text-sm--line-height: 20px;
105
- --text-base: 16px;
106
- --text-base--line-height: 24px;
107
- --text-lg: 18px;
108
- --text-lg--line-height: 28px;
109
- --text-xl: 20px;
110
- --text-xl--line-height: 28px;
111
- --text-2xl: 24px;
112
- --text-2xl--line-height: 32px;
113
- --text-3xl: 30px;
114
- --text-3xl--line-height: 36px;
115
- --text-4xl: 36px;
116
- --text-4xl--line-height: 36px;
117
- --text-5xl: 48px;
118
- --text-5xl--line-height: 1;
119
- --text-6xl: 60px;
120
- --text-6xl--line-height: 1;
121
- --text-7xl: 72px;
122
- --text-7xl--line-height: 1;
123
- --text-8xl: 96px;
124
- --text-8xl--line-height: 1;
125
- --text-9xl: 144px;
126
- --text-9xl--line-height: 1;
127
-
128
- /* ---- Line Height ---- */
129
- --leading-none: 1;
130
- --leading-tight: 1.25;
131
- --leading-snug: 1.375;
132
- --leading-normal: 1.5;
133
- --leading-relaxed: 1.625;
134
- --leading-loose: 2;
135
- --leading-3: 12px;
136
- --leading-4: 16px;
137
- --leading-5: 20px;
138
- --leading-6: 24px;
139
- --leading-7: 28px;
140
- --leading-8: 32px;
141
- --leading-9: 36px;
142
- --leading-10: 40px;
143
-
144
- /* ---- Columns ---- */
145
- --columns-auto: auto;
146
- --columns-1: 1;
147
- --columns-2: 2;
148
- --columns-3: 3;
149
- --columns-4: 4;
150
- --columns-5: 5;
151
- --columns-6: 6;
152
- --columns-7: 7;
153
- --columns-8: 8;
154
- --columns-9: 9;
155
- --columns-10: 10;
156
- --columns-11: 11;
157
- --columns-12: 12;
158
- --columns-3xs: 256px;
159
- --columns-2xs: 288px;
160
- --columns-xs: 320px;
161
- --columns-sm: 384px;
162
- --columns-md: 448px;
163
- --columns-lg: 512px;
164
- --columns-xl: 576px;
165
- --columns-2xl: 672px;
166
- --columns-3xl: 768px;
167
- --columns-4xl: 896px;
168
- --columns-5xl: 1024px;
169
- --columns-6xl: 1152px;
170
- --columns-7xl: 1280px;
171
- --columns-8xl: 1440px;
172
-
173
- /* ---- Max Width ---- */
174
- --max-width-none: none;
175
- --max-width-0: 0px;
176
- --max-width-xs: 320px;
177
- --max-width-sm: 384px;
178
- --max-width-md: 448px;
179
- --max-width-lg: 512px;
180
- --max-width-xl: 576px;
181
- --max-width-2xl: 672px;
182
- --max-width-3xl: 768px;
183
- --max-width-4xl: 896px;
184
- --max-width-5xl: 1024px;
185
- --max-width-6xl: 1152px;
186
- --max-width-7xl: 1280px;
187
- --max-width-8xl: 90rem;
188
- --max-width-full: 100%;
189
- --max-width-min: min-content;
190
- --max-width-max: max-content;
191
- --max-width-fit: fit-content;
192
- --max-width-prose: 65ch;
193
-
194
- /* ---- Screens ---- */
195
- --breakpoint-xxs: 373px;
196
- --breakpoint-xs: 427px;
197
-
198
- /* ---- Containers ---- */
199
- --container-xxs: 373px;
200
- --container-xs: 427px;
201
-
202
- /* ---- Box Shadow (custom) ---- */
203
- --shadow-invert-sm: 0 -1px 2px 0 rgb(0 0 0 / 0.05);
204
- --shadow-invert: 0 -3px 5px 1px rgb(0 0 0 / 0.03), 0 -2px 4px 2px rgb(0 0 0 / 0.03);
205
- --shadow-invert-md: 0 -4px 6px 1px rgb(0 0 0 / 0.07), 0 -2px 4px 2px rgb(0 0 0 / 0.07);
206
- --shadow-invert-lg: 0 -10px 15px 3px rgb(0 0 0 / 0.1), 0 -4px 6px 4px rgb(0 0 0 / 0.1);
207
- --shadow-invert-xl: 0 -20px 25px 5px rgb(0 0 0 / 0.1), 0 -8px 10px 6px rgb(0 0 0 / 0.1);
208
- --shadow-invert-2xl: 0 -25px 50px 12px rgb(0 0 0 / 0.25);
209
-
210
- /* ---- Keyframes ---- */
211
- --animate-slide: slide 30s linear infinite;
212
- --animate-marquee1: marquee1 30s linear infinite;
213
- --animate-marquee2: marquee2 30s linear infinite;
214
- --animate-circle: circle 8.1s linear;
215
- --animate-dot: dot 8.1s linear;
216
- --animate-typewriter: typewriter 0.5s linear infinite;
217
- --animate-pulse-bg: pulse-bg 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
218
-
219
- /* ---- Colors ---- */
220
- /* v4 uses CSS color-mix for opacity — define base colors as rgb() */
221
- --color-theme-trigger-bg: rgb(var(--lx-color-trigger-bg));
222
- --color-theme-trigger-text: rgb(var(--lx-color-trigger-text));
223
- --color-theme-bg: rgb(var(--lx-color-bg));
224
- --color-theme-text: rgb(var(--lx-color-text));
225
- --color-theme-button-bg: rgb(var(--lx-color-button-bg));
226
- --color-theme-button-text: rgb(var(--lx-color-button-text));
227
- }
228
-
229
- @keyframes slide {
230
- 0%, 100% { transform: translate3d(0, 0, 0); }
231
- 100% { transform: translate3d(-50%, 0, 0); }
232
- }
233
-
234
- @keyframes marquee1 {
235
- 0%, 100% { transform: translate3d(0, 0, 0); }
236
- 100% { transform: translate3d(-100%, 0, 0); }
237
- }
238
-
239
- @keyframes marquee2 {
240
- 0%, 100% { transform: translate3d(100%, 0, 0); }
241
- 100% { transform: translate3d(0, 0, 0); }
242
- }
243
-
244
- @keyframes circle {
245
- 0% { stroke-dashoffset: 90; }
246
- 100% { stroke-dashoffset: 0; }
247
- }
248
-
249
- @keyframes dot {
250
- 0%, 95% { fill: transparent; stroke: currentColor; stroke-opacity: 0.1; }
251
- 100% { fill: currentColor; stroke: transparent; stroke-opacity: 0; }
252
- }
253
-
254
- @keyframes typewriter {
255
- 0%, 100% { opacity: 1; }
256
- 50% { opacity: 0; }
257
- }
258
-
259
- @keyframes pulse-bg {
260
- 50% { --tw-bg-opacity: 0.5; }
261
- }
262
-
263
- /* --- Custom Variants (replaces addVariant calls) --- */
264
- @custom-variant svg (& svg);
265
- @custom-variant hfa (&:hover, &:focus, &:active);
266
- @custom-variant hfw (&:hover, &:focus-visible, &:focus-within);
267
- @custom-variant hfwa (&:hover, &:focus-visible, &:focus-within, &:active);
268
- @custom-variant hfwaa (&:hover, &:focus-visible, &:focus-within, &:active, &.active);
269
- @custom-variant hfva (&:hover, &:focus, &:focus-visible, &:active);
270
- @custom-variant ha (&:hover, &:active);
271
- @custom-variant hf (&:hover, &:focus-visible);
272
- @custom-variant fa (&:focus, &:active);
273
- @custom-variant f (&:focus);
274
- @custom-variant fw (&:focus-within);
275
- @custom-variant fv (&:focus-visible);
276
- @custom-variant h (&:hover);
277
- @custom-variant d (.dark &);
278
- @custom-variant ac (&.active);
279
- @custom-variant b (&::before);
280
- @custom-variant a (&::after);
281
- @custom-variant not-prose (:not(.prose &)&);
282
- @custom-variant hfaa (&:hover, &:focus, &:active, &.active);
283
- @custom-variant hfvaa (&:hover, &:focus, &:focus-visible, &:active, &.active);
284
- @custom-variant group-hfa (.group:hover &, .group:focus &, .group:active &);
285
- @custom-variant group-hf (.group:hover &, .group:focus &);
286
- @custom-variant group-ac (.group.active &);
287
- @custom-variant group-hfva (.group:hover &, .group:focus-visible &, .group:active &);
288
- @custom-variant group-hfwa (.group:hover &, .group:focus-visible &, .group:focus-within &, .group:active &);
289
- @custom-variant group-hfw (.group:hover &, .group:focus-visible &, .group:focus-within &);
290
- @custom-variant peer-hfwa (.peer:hover ~ &, .peer:focus-visible ~ &, .peer:focus-within ~ &, .peer:active ~ &);
291
- @custom-variant peer-fw (.peer:focus-within ~ &);
292
-
293
- /* --- Dark mode as class-based --- */
294
- @custom-variant dark (&:where(.dark *));
295
-
296
- /* --- Custom Utilities (replaces addUtilities calls) --- */
297
- @utility shape-geometric-precision {
298
- shape-rendering: geometricPrecision;
299
- }
300
-
301
- @utility open-quote {
302
- content: open-quote;
303
- }
304
-
305
- @utility close-quote {
306
- content: close-quote;
307
- }
308
-
309
- @utility leading-0 {
310
- line-height: 0;
311
- }
312
-
313
- @utility animation-pause {
314
- animation-play-state: paused;
315
- }
316
-
317
- @utility animation-play {
318
- animation-play-state: running;
319
- }
320
-
321
- /* --- Dynamic Utilities --- */
322
-
323
- /* top-spacing: top = var(--spacing-top-bar-spacing) + spacing value */
324
- @utility top-spacing-* {
325
- top: calc(var(--spacing-top-bar) + --value(--spacing-*));
326
- top: calc(var(--spacing-top-bar) + --value([length]));
327
- }
328
-
329
- /* auto-col-flow loaded via JS plugin for complex logic */
330
- @plugin "./plugins/auto-col-flow.js";