@hiscovega/grisso 1.0.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.
@@ -0,0 +1,126 @@
1
+ import { simpleClass, complexClass } from "../generators.js";
2
+ export default function layout(config) {
3
+ const { columns, breakpoints, spacing } = config;
4
+ let css = "";
5
+ // display
6
+ const display = {
7
+ block: "block",
8
+ inline: "inline",
9
+ "inline-block": "inline-block",
10
+ flex: "flex",
11
+ "inline-flex": "inline-flex",
12
+ grid: "grid",
13
+ "inline-grid": "inline-grid",
14
+ "inline-table": "inline-table",
15
+ table: "table",
16
+ "table-row": "table-row",
17
+ "table-caption": "table-caption",
18
+ "table-cell": "table-cell",
19
+ "table-column": "table-column",
20
+ "table-column-group": "table-column-group",
21
+ "table-footer-group": "table-footer-group",
22
+ "table-header-group": "table-header-group",
23
+ "table-row-group": "table-row-group",
24
+ contents: "contents",
25
+ "flow-root": "flow-root",
26
+ "list-item": "list-item",
27
+ hidden: "none",
28
+ };
29
+ css += complexClass("", "display", display, breakpoints);
30
+ // columns (numeric)
31
+ for (let i = 1; i <= columns; i++) {
32
+ css += simpleClass(`columns-${i}`, "columns", String(i), breakpoints);
33
+ }
34
+ // columns (spacing tokens)
35
+ css += complexClass("columns-", "columns", spacing, breakpoints);
36
+ // float
37
+ const float = {
38
+ left: "left",
39
+ right: "right",
40
+ none: "none",
41
+ };
42
+ css += complexClass("float-", "float", float, breakpoints);
43
+ // clear
44
+ const clear = {
45
+ left: "left",
46
+ right: "right",
47
+ both: "both",
48
+ none: "none",
49
+ };
50
+ css += complexClass("clear-", "clear", clear, breakpoints);
51
+ // object-fit
52
+ const objectFit = {
53
+ contain: "contain",
54
+ cover: "cover",
55
+ fill: "fill",
56
+ none: "none",
57
+ "scale-down": "scale-down",
58
+ };
59
+ css += complexClass("object-", "object-fit", objectFit, breakpoints);
60
+ // object-position
61
+ const objectPosition = {
62
+ bottom: "bottom",
63
+ center: "center",
64
+ left: "left",
65
+ "left-bottom": "left bottom",
66
+ "left-top": "left top",
67
+ right: "right",
68
+ "right-bottom": "right bottom",
69
+ "right-top": "right top",
70
+ top: "top",
71
+ };
72
+ css += complexClass("object-", "object-position", objectPosition, breakpoints);
73
+ // overflow
74
+ const overflow = {
75
+ auto: "auto",
76
+ hidden: "hidden",
77
+ clip: "clip",
78
+ visible: "visible",
79
+ scroll: "scroll",
80
+ };
81
+ css += complexClass("overflow-", "overflow", overflow, breakpoints);
82
+ css += complexClass("overflow-x-", "overflow-x", overflow, breakpoints);
83
+ css += complexClass("overflow-y-", "overflow-y", overflow, breakpoints);
84
+ // position
85
+ const position = {
86
+ static: "static",
87
+ fixed: "fixed",
88
+ absolute: "absolute",
89
+ relative: "relative",
90
+ sticky: "sticky",
91
+ };
92
+ css += complexClass("", "position", position, breakpoints);
93
+ // visibility
94
+ css += simpleClass("visible", "visibility", "visible", breakpoints);
95
+ css += simpleClass("invisible", "visibility", "hidden", breakpoints);
96
+ css += simpleClass("collapse", "visibility", "collapse", breakpoints);
97
+ // z-index
98
+ const zIndex = {
99
+ auto: "auto",
100
+ "0": "0",
101
+ "1": "10",
102
+ "20": "20",
103
+ "30": "30",
104
+ "40": "40",
105
+ "50": "50",
106
+ };
107
+ const zIndexNeg = {
108
+ "1": "-10",
109
+ "20": "-20",
110
+ "30": "-30",
111
+ "40": "-40",
112
+ "50": "-50",
113
+ };
114
+ css += complexClass("z-", "z-index", zIndex, breakpoints);
115
+ css += complexClass("-z-", "z-index", zIndexNeg, breakpoints);
116
+ // top/right/bottom/left
117
+ css += simpleClass("top-0", "top", "0", breakpoints);
118
+ css += simpleClass("right-0", "right", "0", breakpoints);
119
+ css += simpleClass("bottom-0", "bottom", "0", breakpoints);
120
+ css += simpleClass("left-0", "left", "0", breakpoints);
121
+ css += complexClass("top-", "top", spacing, breakpoints);
122
+ css += complexClass("right-", "right", spacing, breakpoints);
123
+ css += complexClass("bottom-", "bottom", spacing, breakpoints);
124
+ css += complexClass("left-", "left", spacing, breakpoints);
125
+ return css;
126
+ }
@@ -0,0 +1,2 @@
1
+ import type { GrissoConfig } from "../types.js";
2
+ export default function sizing(config: GrissoConfig): string;
@@ -0,0 +1,39 @@
1
+ import { simpleClass, complexClass } from "../generators.js";
2
+ import { fractionPercent } from "../utils.js";
3
+ export default function sizing(config) {
4
+ const { columns, breakpoints } = config;
5
+ let css = "";
6
+ // width
7
+ const width = {
8
+ auto: "auto",
9
+ "0": "0",
10
+ full: "100%",
11
+ screen: "100vw",
12
+ min: "min-content",
13
+ max: "max-content",
14
+ fit: "fit-content",
15
+ };
16
+ css += complexClass("w-", "width", width, breakpoints);
17
+ for (let i = 1; i <= columns; i++) {
18
+ css += simpleClass(`w-${i}`, "width", fractionPercent(i, columns), breakpoints);
19
+ }
20
+ css += complexClass("min-w-", "min-width", width, breakpoints);
21
+ css += complexClass("max-w-", "max-width", width, breakpoints);
22
+ // height
23
+ const height = {
24
+ auto: "auto",
25
+ "0": "0",
26
+ full: "100%",
27
+ screen: "100vh",
28
+ min: "min-content",
29
+ max: "max-content",
30
+ fit: "fit-content",
31
+ };
32
+ css += complexClass("h-", "height", height, breakpoints);
33
+ for (let i = 1; i <= columns; i++) {
34
+ css += simpleClass(`h-${i}`, "height", fractionPercent(i, columns), breakpoints);
35
+ }
36
+ css += complexClass("min-h-", "min-height", height, breakpoints);
37
+ css += complexClass("max-h-", "max-height", height, breakpoints);
38
+ return css;
39
+ }
@@ -0,0 +1,2 @@
1
+ import type { GrissoConfig } from "../types.js";
2
+ export default function spacingPartial(config: GrissoConfig): string;
@@ -0,0 +1,24 @@
1
+ import { complexClass } from "../generators.js";
2
+ import { omit } from "../utils.js";
3
+ export default function spacingPartial(config) {
4
+ const { breakpoints, spacing } = config;
5
+ let css = "";
6
+ // margin (incluye "auto")
7
+ css += complexClass("m-", "margin", spacing, breakpoints);
8
+ css += complexClass("mt-", "margin-top", spacing, breakpoints);
9
+ css += complexClass("mr-", "margin-right", spacing, breakpoints);
10
+ css += complexClass("mb-", "margin-bottom", spacing, breakpoints);
11
+ css += complexClass("ml-", "margin-left", spacing, breakpoints);
12
+ css += complexClass("mx-", "margin-inline", spacing, breakpoints);
13
+ css += complexClass("my-", "margin-block", spacing, breakpoints);
14
+ // padding (sin "auto")
15
+ const padding = omit(spacing, "auto");
16
+ css += complexClass("p-", "padding", padding, breakpoints);
17
+ css += complexClass("pt-", "padding-top", padding, breakpoints);
18
+ css += complexClass("pr-", "padding-right", padding, breakpoints);
19
+ css += complexClass("pb-", "padding-bottom", padding, breakpoints);
20
+ css += complexClass("pl-", "padding-left", padding, breakpoints);
21
+ css += complexClass("px-", "padding-inline", padding, breakpoints);
22
+ css += complexClass("py-", "padding-block", padding, breakpoints);
23
+ return css;
24
+ }
@@ -0,0 +1,2 @@
1
+ import type { GrissoConfig } from "../types.js";
2
+ export default function typography(config: GrissoConfig): string;
@@ -0,0 +1,111 @@
1
+ import { simpleClass, complexClass, customClass } from "../generators.js";
2
+ import { omit } from "../utils.js";
3
+ export default function typography(config) {
4
+ const { breakpoints, foregroundColors, spacing } = config;
5
+ let css = "";
6
+ // text-color
7
+ css += complexClass("text-", "color", foregroundColors, breakpoints);
8
+ // text-align
9
+ const textAlign = {
10
+ left: "left",
11
+ center: "center",
12
+ right: "right",
13
+ justify: "justify",
14
+ start: "start",
15
+ end: "end",
16
+ };
17
+ css += complexClass("text-", "text-align", textAlign, breakpoints);
18
+ // text-transform
19
+ const textTransform = {
20
+ uppercase: "uppercase",
21
+ lowercase: "lowercase",
22
+ capitalize: "capitalize",
23
+ "normal-case": "none",
24
+ };
25
+ css += complexClass("", "text-transform", textTransform, breakpoints);
26
+ // text-overflow
27
+ const textOverflow = {
28
+ ellipsis: "ellipsis",
29
+ clip: "clip",
30
+ };
31
+ css += complexClass("text-", "text-overflow", textOverflow, breakpoints);
32
+ css += customClass("truncate", {
33
+ overflow: "hidden",
34
+ "text-overflow": "ellipsis",
35
+ "white-space": "nowrap",
36
+ }, breakpoints);
37
+ // vertical-align
38
+ const verticalAlign = {
39
+ baseline: "baseline",
40
+ top: "top",
41
+ middle: "middle",
42
+ bottom: "bottom",
43
+ "text-top": "text-top",
44
+ "text-bottom": "text-bottom",
45
+ sub: "sub",
46
+ super: "super",
47
+ };
48
+ css += complexClass("align-", "vertical-align", verticalAlign, breakpoints);
49
+ // white-space
50
+ const whiteSpace = {
51
+ normal: "normal",
52
+ nowrap: "nowrap",
53
+ pre: "pre",
54
+ "pre-line": "pre-line",
55
+ "pre-wrap": "pre-wrap",
56
+ "break-spaces": "break-spaces",
57
+ };
58
+ css += complexClass("whitespace-", "white-space", whiteSpace, breakpoints);
59
+ // word-break
60
+ const wordBreak = {
61
+ all: "break-all",
62
+ keep: "keep-all",
63
+ };
64
+ css += complexClass("break-", "word-break", wordBreak, breakpoints);
65
+ css += simpleClass("break-words", "overflow-wrap", "break-word", breakpoints);
66
+ css += customClass("break-normal", { "overflow-wrap": "normal", "word-break": "normal" }, breakpoints);
67
+ // font-smoothing
68
+ css += customClass("antialiased", {
69
+ "-webkit-font-smoothing": "antialiased",
70
+ "-moz-osx-font-smoothing": "grayscale",
71
+ }, breakpoints);
72
+ css += customClass("subpixel-antialiased", {
73
+ "-webkit-font-smoothing": "auto",
74
+ "-moz-osx-font-smoothing": "auto",
75
+ }, breakpoints);
76
+ // font-style
77
+ const fontStyle = {
78
+ italic: "italic",
79
+ "not-italic": "normal",
80
+ };
81
+ css += complexClass("", "font-style", fontStyle, breakpoints);
82
+ // font-weight
83
+ const fontWeight = {
84
+ thin: "100",
85
+ extralight: "200",
86
+ light: "200",
87
+ normal: "400",
88
+ medium: "500",
89
+ semibold: "600",
90
+ bold: "700",
91
+ extrabold: "800",
92
+ black: "900",
93
+ };
94
+ css += complexClass("font-", "font-weight", fontWeight, breakpoints);
95
+ // letter-spacing
96
+ const letterSpacing = omit(spacing, "auto");
97
+ css += complexClass("tracking-", "letter-spacing", letterSpacing, breakpoints);
98
+ // line-height
99
+ const lineHeight = omit(spacing, "auto", "zero");
100
+ const extendedLineHeight = {
101
+ ...lineHeight,
102
+ none: "1",
103
+ tight: "1.25",
104
+ snug: "1.3755",
105
+ normal: "1.5",
106
+ relaxed: "1.625",
107
+ loose: "2",
108
+ };
109
+ css += complexClass("leading-", "line-height", extendedLineHeight, breakpoints);
110
+ return css;
111
+ }
@@ -0,0 +1,8 @@
1
+ import type { GrissoConfig } from "./types.js";
2
+ /**
3
+ * Resuelve la configuración de Grisso.
4
+ * Patrón Tailwind v3:
5
+ * - Top-level keys reemplazan los defaults completamente
6
+ * - `extend` mergea superficialmente con defaults
7
+ */
8
+ export declare function resolveConfig(configPath?: string): Promise<GrissoConfig>;
@@ -0,0 +1,54 @@
1
+ import path from "node:path";
2
+ import { pathToFileURL } from "node:url";
3
+ import defaults from "./defaults.js";
4
+ /**
5
+ * Resuelve la configuración de Grisso.
6
+ * Patrón Tailwind v3:
7
+ * - Top-level keys reemplazan los defaults completamente
8
+ * - `extend` mergea superficialmente con defaults
9
+ */
10
+ export async function resolveConfig(configPath) {
11
+ let userConfig;
12
+ if (configPath) {
13
+ const resolved = path.resolve(configPath);
14
+ const mod = await import(pathToFileURL(resolved).href);
15
+ userConfig = mod.default;
16
+ }
17
+ else {
18
+ try {
19
+ const defaultPath = path.resolve(process.cwd(), "grisso.config.mjs");
20
+ const mod = await import(pathToFileURL(defaultPath).href);
21
+ userConfig = mod.default;
22
+ }
23
+ catch {
24
+ return { ...defaults };
25
+ }
26
+ }
27
+ const { extend, ...overrides } = userConfig;
28
+ // Top-level keys reemplazan defaults completamente
29
+ const config = { ...defaults };
30
+ for (const [key, value] of Object.entries(overrides)) {
31
+ if (key in config) {
32
+ config[key] = value;
33
+ }
34
+ }
35
+ // extend mergea superficialmente con defaults
36
+ if (extend && typeof extend === "object" && !Array.isArray(extend)) {
37
+ for (const [key, value] of Object.entries(extend)) {
38
+ const current = config[key];
39
+ if (key in config &&
40
+ typeof current === "object" &&
41
+ current !== null &&
42
+ !Array.isArray(current)) {
43
+ config[key] = {
44
+ ...current,
45
+ ...value,
46
+ };
47
+ }
48
+ else {
49
+ config[key] = value;
50
+ }
51
+ }
52
+ }
53
+ return config;
54
+ }
package/lib/types.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ /** Mapa de breakpoints: nombre → media query */
2
+ export type Breakpoints = Record<string, string>;
3
+ /** Mapa de tokens: nombre → valor CSS */
4
+ export type TokenMap = Record<string, string>;
5
+ /** Mapa de declaraciones CSS: propiedad → valor */
6
+ export type Declarations = Record<string, string>;
7
+ /** Configuración completa de Grisso */
8
+ export interface GrissoConfig {
9
+ columns: number;
10
+ breakpoints: Breakpoints;
11
+ spacing: TokenMap;
12
+ brandColors: TokenMap;
13
+ foregroundColors: TokenMap;
14
+ iconColors: TokenMap;
15
+ supportColors: TokenMap;
16
+ backgroundColors: TokenMap;
17
+ overlayColors: TokenMap;
18
+ borderWidth: TokenMap;
19
+ opacity: TokenMap;
20
+ shadows: TokenMap;
21
+ borderColors: TokenMap;
22
+ [key: string]: unknown;
23
+ }
24
+ /** Función parcial que genera CSS a partir de la config */
25
+ export type PartialFn = (config: GrissoConfig) => string;
package/lib/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/lib/utils.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { TokenMap } from "./types.js";
2
+ /**
3
+ * Elimina keys de un objeto.
4
+ * Equivalente a sass:map.remove()
5
+ */
6
+ export declare function omit(obj: TokenMap, ...keys: string[]): TokenMap;
7
+ /**
8
+ * Calcula un porcentaje con 10 decimales (paridad con Dart Sass).
9
+ * fractionPercent(1, 12) → "8.3333333333%"
10
+ * fractionPercent(3, 12) → "25%"
11
+ */
12
+ export declare function fractionPercent(numerator: number, denominator: number): string;
package/lib/utils.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Elimina keys de un objeto.
3
+ * Equivalente a sass:map.remove()
4
+ */
5
+ export function omit(obj, ...keys) {
6
+ const result = { ...obj };
7
+ for (const key of keys) {
8
+ delete result[key];
9
+ }
10
+ return result;
11
+ }
12
+ /**
13
+ * Calcula un porcentaje con 10 decimales (paridad con Dart Sass).
14
+ * fractionPercent(1, 12) → "8.3333333333%"
15
+ * fractionPercent(3, 12) → "25%"
16
+ */
17
+ export function fractionPercent(numerator, denominator) {
18
+ const value = ((numerator / denominator) * 100).toFixed(10);
19
+ return value.replace(/\.?0+$/, "") + "%";
20
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@hiscovega/grisso",
3
+ "description": "Griddo CSS utility class library",
4
+ "version": "1.0.0",
5
+ "license": "UNLICENSED",
6
+ "private": false,
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "style": "./dist/grisso.css"
11
+ },
12
+ "./plugin": "./plugin.js",
13
+ "./config": "./lib/defaults.js",
14
+ "./tokens-example.css": "./tokens-example.css"
15
+ },
16
+ "engines": {
17
+ "node": ">=24"
18
+ },
19
+ "files": [
20
+ "dist/",
21
+ "lib/",
22
+ "plugin.js",
23
+ "tokens-example.css",
24
+ "README.md"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsc && node scripts/build.js",
28
+ "typecheck": "tsc --noEmit",
29
+ "lint": "biome check .",
30
+ "lint:fix": "biome check --write .",
31
+ "playground": "npm run build && node scripts/build.js --config playground/grisso.config.mjs --content playground/index.html --content playground/example.module.css --output playground/grisso.css && open playground/index.html",
32
+ "prepublishOnly": "npm run build"
33
+ },
34
+ "dependencies": {
35
+ "@fullhuman/postcss-purgecss": "^6.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@biomejs/biome": "2.4.5",
39
+ "@types/node": "^25.3.3",
40
+ "postcss": "^8.4.47",
41
+ "postcss-cli": "^11.0.0",
42
+ "postcss-combine-duplicated-selectors": "^10.0.3",
43
+ "postcss-discard-empty": "^6.0.0",
44
+ "postcss-minify": "^1.1.0",
45
+ "postcss-preset-env": "^10.0.3",
46
+ "postcss-sort-media-queries": "^5.2.0",
47
+ "typescript": "^5.9.3"
48
+ }
49
+ }
package/plugin.js ADDED
@@ -0,0 +1,77 @@
1
+ import { generateCSS } from "./lib/index.js";
2
+
3
+ /**
4
+ * PostCSS plugin de Grisso.
5
+ * Genera CSS desde JS y aplica tree-shaking usando PurgeCSS
6
+ * si se pasan rutas de contenido.
7
+ *
8
+ * @param {Object} options
9
+ * @param {string[]} [options.content] - Rutas glob de archivos a escanear para tree-shaking.
10
+ * Si se omite, se incluye todo el CSS de Grisso (útil en desarrollo).
11
+ * @param {string} [options.config] - Ruta a grisso.config.mjs del consumidor.
12
+ *
13
+ * @example
14
+ * // postcss.config.js del proyecto consumidor
15
+ * import grisso from "@griddo/grisso/plugin";
16
+ * export default {
17
+ * plugins: [
18
+ * grisso({ content: ["./src/**\/*.{js,ts,jsx,tsx,css}"] })
19
+ * ]
20
+ * }
21
+ */
22
+ export default function grissoPlugin(options = {}) {
23
+ const { content, config: configPath } = options;
24
+
25
+ return {
26
+ postcssPlugin: "postcss-grisso",
27
+ async Once(root, { parse }) {
28
+ const grissoSource = await generateCSS(configPath);
29
+
30
+ if (!content || content.length === 0) {
31
+ // Sin tree-shaking: inyectar todo el CSS
32
+ const grissoRoot = parse(grissoSource);
33
+ grissoRoot.each((node) => root.prepend(node.clone()));
34
+ return;
35
+ }
36
+
37
+ // Con tree-shaking: usar PurgeCSS para eliminar clases no usadas
38
+ const { PurgeCSS } = await import("purgecss");
39
+
40
+ const purgecss = new PurgeCSS();
41
+ const [result] = await purgecss.purge({
42
+ content,
43
+ css: [{ raw: grissoSource }],
44
+ extractors: [
45
+ {
46
+ // Extractor para uso directo en HTML/JSX: class="flex gap-md"
47
+ extractor: (content) => content.match(/[A-Za-z0-9_-]+/g) || [],
48
+ extensions: ["html", "jsx", "tsx", "js", "ts"],
49
+ },
50
+ {
51
+ // Extractor para CSS Modules: composes: flex gap-md from global
52
+ extractor: (content) => {
53
+ const matches = content.match(/composes:\s*([^;]+)\s*from\s+global/g) || [];
54
+ const classes = [];
55
+ for (const match of matches) {
56
+ const classStr = match.replace(/composes:\s*/, "").replace(/\s*from\s+global/, "");
57
+ classes.push(...classStr.trim().split(/\s+/));
58
+ }
59
+ return classes;
60
+ },
61
+ extensions: ["css"],
62
+ },
63
+ ],
64
+ safelist: {
65
+ // Preservar clases de fondo (bg-) que pueden construirse dinámicamente
66
+ greedy: [/^bg-/],
67
+ },
68
+ });
69
+
70
+ const purgedCSS = result ? result.css : grissoSource;
71
+ const grissoRoot = parse(purgedCSS);
72
+ grissoRoot.each((node) => root.prepend(node.clone()));
73
+ },
74
+ };
75
+ }
76
+
77
+ grissoPlugin.postcss = true;
@@ -0,0 +1,80 @@
1
+ /* @griddo/grisso — tokens-example.css
2
+ Copia este archivo y adapta los valores a tu design system.
3
+ Define estas variables en :root o en el scope que prefieras.
4
+
5
+ Todas las clases de Grisso referencian estas custom properties,
6
+ por lo que cambiar estos valores afecta a toda la librería sin
7
+ necesidad de recompilar el SCSS.
8
+ */
9
+
10
+ :root {
11
+ /* ─── Spacing ─────────────────────────────────────────────── */
12
+ --spc-4xs: 2px;
13
+ --spc-3xs: 4px;
14
+ --spc-2xs: 8px;
15
+ --spc-xs: 12px;
16
+ --spc-sm: 16px;
17
+ --spc-md: 24px;
18
+ --spc-lg: 32px;
19
+ --spc-xl: 40px;
20
+ --spc-2xl: 48px;
21
+ --spc-3xl: 64px;
22
+ --spc-4xl: 80px;
23
+ --spc-5xl: 96px;
24
+
25
+ /* ─── Colors: texto ───────────────────────────────────────── */
26
+ --text-1: #111827;
27
+ --text-2: #374151;
28
+ --text-3: #6b7280;
29
+ --text-4: #9ca3af;
30
+
31
+ /* ─── Colors: fondo ───────────────────────────────────────── */
32
+ --bg-ui: #ffffff;
33
+ --bg-1: #f9fafb;
34
+ --bg-2: #f3f4f6;
35
+ --bg-3: #e5e7eb;
36
+ --bg-4: #d1d5db;
37
+ --bg-5: #9ca3af;
38
+ --bg-disabled: #e5e7eb;
39
+
40
+ /* ─── Colors: bordes ──────────────────────────────────────── */
41
+ --border-1: #e5e7eb;
42
+ --border-2: #d1d5db;
43
+ --border-3: #9ca3af;
44
+ --border-4: #6b7280;
45
+ --border-disabled: #d1d5db;
46
+
47
+ /* ─── Colors: iconos ──────────────────────────────────────── */
48
+ --icon-1: #111827;
49
+ --icon-2: #374151;
50
+ --icon-3: #6b7280;
51
+ --icon-4: #9ca3af;
52
+ --icon-disabled: #d1d5db;
53
+
54
+ /* ─── Colors: overlays ────────────────────────────────────── */
55
+ --overlay-1: rgba(0 0 0 / 0.1);
56
+ --overlay-2: rgba(0 0 0 / 0.2);
57
+ --overlay-3: rgba(0 0 0 / 0.4);
58
+ --overlay-4: rgba(0 0 0 / 0.7);
59
+
60
+ /* ─── Border widths ───────────────────────────────────────── */
61
+ --border-width-none: 0px;
62
+ --border-width-xs: 1px;
63
+ --border-width-sm: 2px;
64
+ --border-width-md: 4px;
65
+ --border-width-lg: 8px;
66
+
67
+ /* ─── Opacidad ────────────────────────────────────────────── */
68
+ --opacity-1: 0.1;
69
+ --opacity-2: 0.2;
70
+ --opacity-3: 0.4;
71
+ --opacity-4: 0.6;
72
+ --opacity-5: 0.75;
73
+ --opacity-6: 0.9;
74
+
75
+ /* ─── Sombras ─────────────────────────────────────────────── */
76
+ --box-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
77
+ --box-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
78
+ --box-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
79
+ --box-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
80
+ }