@ekonavi/theme 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +188 -0
- package/package.json +56 -0
- package/src/index.css +31 -0
- package/src/shadcn-base.css +35 -0
- package/src/tailwind.css +101 -0
- package/src/tokens/colors.css +36 -0
- package/src/tokens/earthy.css +75 -0
- package/src/tokens/extras.css +214 -0
- package/src/tokens/forest.css +75 -0
- package/src/tokens/index.css +6 -0
- package/src/tokens/spacing.css +44 -0
- package/src/tokens/typography.css +44 -0
- package/src/utilities.css +192 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
|
+
|
|
5
|
+
### [0.1.4](https://github.com/Ekonavi/ekonavi-theme/compare/v0.1.3...v0.1.4) (2026-03-06)
|
|
6
|
+
|
|
7
|
+
### [0.1.3](https://github.com/Ekonavi/ekonavi-theme/compare/v0.1.2...v0.1.3) (2026-03-06)
|
|
8
|
+
|
|
9
|
+
### [0.1.2](https://github.com/Ekonavi/ekonavi-theme/compare/v0.1.1...v0.1.2) (2026-03-06)
|
|
10
|
+
|
|
11
|
+
### 0.1.1 (2026-03-06)
|
|
12
|
+
|
|
13
|
+
## [1.0.0] - 2026-03-06
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Brand color palette from Ekonavi style guide (Clara Goldenstein refresh)
|
|
17
|
+
- Forest theme (light + dark modes) — green-dominant
|
|
18
|
+
- Earthy theme (light + dark modes) — brown/amber-dominant
|
|
19
|
+
- Extra themes preserved from existing codebase: Air, Sea, Midnight (light + dark)
|
|
20
|
+
- Typography tokens (Josefin Sans body, Bryndan Write display)
|
|
21
|
+
- Spacing, radius, sidebar, and z-index tokens
|
|
22
|
+
- Tailwind CSS 4 `@theme inline` integration
|
|
23
|
+
- shadcn/ui base layer styles
|
|
24
|
+
- Shared utility classes: scrollbar, radio chips, product grid, WCM overlay, mobile optimization
|
|
25
|
+
- Brand palette exposed as Tailwind utilities (`bg-eko-sage`, `text-eko-amber`, etc.)
|
|
26
|
+
- `@custom-variant dark` for Tailwind 4 dark mode
|
|
27
|
+
- Animation keyframes: `scaleUp`, `gradient-border`
|
|
28
|
+
- Full package exports for granular imports
|
|
29
|
+
- Claude Code migration instructions
|
package/README.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# @ekonavi/theme
|
|
2
|
+
|
|
3
|
+
Shared design tokens, themes, and Tailwind CSS 4 integration for all Ekonavi apps.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides a single source of truth for:
|
|
8
|
+
- **Brand color palette** (greens, earths, neutrals)
|
|
9
|
+
- **Theme variants** (forest + earthy, each with light/dark modes)
|
|
10
|
+
- **Tailwind 4 `@theme inline`** integration (CSS vars → utility classes)
|
|
11
|
+
- **shadcn/ui base layer** (border, body, heading defaults)
|
|
12
|
+
- **Shared utility classes** (scrollbar, radio chips, product grid, etc.)
|
|
13
|
+
|
|
14
|
+
**No compiled CSS is shipped.** Each consuming app runs its own Tailwind 4 build, avoiding class collisions entirely.
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### 1. Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @ekonavi/theme
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Import in your app's `globals.css`
|
|
25
|
+
|
|
26
|
+
```css
|
|
27
|
+
@import "tailwindcss";
|
|
28
|
+
@import "tw-animate-css";
|
|
29
|
+
@import "@ekonavi/theme";
|
|
30
|
+
|
|
31
|
+
/* Tell Tailwind 4 to scan the theme package for class usage */
|
|
32
|
+
@source '../node_modules/@ekonavi/theme';
|
|
33
|
+
|
|
34
|
+
/* App-specific styles below */
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2b. Add Vite alias (required)
|
|
38
|
+
|
|
39
|
+
CSS `@import` cannot resolve Node.js package exports. Add aliases to `vite.config.ts`:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// vite.config.ts
|
|
43
|
+
resolve: {
|
|
44
|
+
alias: {
|
|
45
|
+
'@ekonavi/theme/extras.css': path.resolve(__dirname, 'node_modules/@ekonavi/theme/src/tokens/extras.css'),
|
|
46
|
+
'@ekonavi/theme': path.resolve(__dirname, 'node_modules/@ekonavi/theme/src/index.css'),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Apply a theme class
|
|
52
|
+
|
|
53
|
+
Add one of these classes to your `<html>` element:
|
|
54
|
+
|
|
55
|
+
| Class | Description |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `forest-light` | Green dominant, light mode |
|
|
58
|
+
| `forest-dark` | Green dominant, dark mode |
|
|
59
|
+
| `earthy-light` | Brown/amber dominant, light mode |
|
|
60
|
+
| `earthy-dark` | Brown/amber dominant, dark mode |
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
// Next.js layout.tsx example
|
|
64
|
+
export default function RootLayout({ children }) {
|
|
65
|
+
return (
|
|
66
|
+
<html className="forest-light">
|
|
67
|
+
<body>{children}</body>
|
|
68
|
+
</html>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 4. Theme switching with next-themes
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { ThemeProvider } from "next-themes";
|
|
77
|
+
|
|
78
|
+
// Map next-themes values to CSS classes
|
|
79
|
+
const themeMap = {
|
|
80
|
+
"forest-light": "forest-light",
|
|
81
|
+
"forest-dark": "forest-dark",
|
|
82
|
+
"earthy-light": "earthy-light",
|
|
83
|
+
"earthy-dark": "earthy-dark",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export function Providers({ children }) {
|
|
87
|
+
return (
|
|
88
|
+
<ThemeProvider
|
|
89
|
+
attribute="class"
|
|
90
|
+
themes={Object.keys(themeMap)}
|
|
91
|
+
defaultTheme="forest-light"
|
|
92
|
+
>
|
|
93
|
+
{children}
|
|
94
|
+
</ThemeProvider>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Available Exports
|
|
100
|
+
|
|
101
|
+
| Import Path | Contents |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `@ekonavi/theme` | Everything (tokens + tailwind + base + utilities) |
|
|
104
|
+
| `@ekonavi/theme/tokens` | All token files only (no utilities/base) |
|
|
105
|
+
| `@ekonavi/theme/tokens/colors` | Brand color palette only |
|
|
106
|
+
| `@ekonavi/theme/tokens/forest` | Forest theme vars only |
|
|
107
|
+
| `@ekonavi/theme/tokens/earthy` | Earthy theme vars only |
|
|
108
|
+
| `@ekonavi/theme/tokens/typography` | Font definitions only |
|
|
109
|
+
| `@ekonavi/theme/tokens/spacing` | Spacing/radius/layout only |
|
|
110
|
+
| `@ekonavi/theme/extras.css` | Air, Sea, Midnight themes |
|
|
111
|
+
| `@ekonavi/theme/tailwind.css` | `@theme inline` block only |
|
|
112
|
+
| `@ekonavi/theme/shadcn-base.css` | Base layer only |
|
|
113
|
+
| `@ekonavi/theme/utilities.css` | Utility classes only |
|
|
114
|
+
|
|
115
|
+
## Brand Palette Utilities
|
|
116
|
+
|
|
117
|
+
In addition to semantic colors (`bg-primary`, `text-foreground`, etc.), the theme exposes brand colors directly:
|
|
118
|
+
|
|
119
|
+
```html
|
|
120
|
+
<div class="bg-eko-sage text-eko-deep-green">Sage background</div>
|
|
121
|
+
<div class="bg-eko-amber text-white">Amber CTA</div>
|
|
122
|
+
<div class="border-eko-dark-teal">Teal border</div>
|
|
123
|
+
<div class="bg-eko-gold">Gold badge</div>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Available: `eko-sage`, `eko-deep-green`, `eko-dark-teal`, `eko-light-green`, `eko-dark-green-bg`, `eko-amber`, `eko-coral`, `eko-earth-brown`, `eko-cream`, `eko-gold`, `eko-warm-beige`
|
|
127
|
+
|
|
128
|
+
## Typography
|
|
129
|
+
|
|
130
|
+
Fonts are defined as CSS custom properties. Load them in your app:
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
// Next.js app/layout.tsx
|
|
134
|
+
import { Josefin_Sans } from "next/font/google";
|
|
135
|
+
|
|
136
|
+
const josefin = Josefin_Sans({
|
|
137
|
+
subsets: ["latin"],
|
|
138
|
+
variable: "--font-josefin",
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
export default function RootLayout({ children }) {
|
|
142
|
+
return (
|
|
143
|
+
<html className={`forest-light ${josefin.variable}`}>
|
|
144
|
+
<body>{children}</body>
|
|
145
|
+
</html>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Fonts Reference
|
|
151
|
+
|
|
152
|
+
- **Body:** Josefin Sans (Google Fonts)
|
|
153
|
+
- **Display/Headings:** Bryndan Write (custom — load via `@font-face`)
|
|
154
|
+
|
|
155
|
+
## Local Development
|
|
156
|
+
|
|
157
|
+
When working on the theme package alongside an app:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Option A: pnpm link
|
|
161
|
+
cd ekonavi-theme && pnpm link --global
|
|
162
|
+
cd ../your-app && pnpm link --global @ekonavi/theme
|
|
163
|
+
|
|
164
|
+
# Option B: yalc (more reliable)
|
|
165
|
+
cd ekonavi-theme && yalc publish
|
|
166
|
+
cd ../your-app && yalc add @ekonavi/theme
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## File Structure
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
@ekonavi/theme/
|
|
173
|
+
├── src/
|
|
174
|
+
│ ├── tokens/
|
|
175
|
+
│ │ ├── colors.css ← brand palette (--eko-sage, --eko-amber, etc.)
|
|
176
|
+
│ │ ├── forest.css ← .forest-light, .forest-dark
|
|
177
|
+
│ │ ├── earthy.css ← .earthy-light, .earthy-dark
|
|
178
|
+
│ │ ├── extras.css ← .air-*, .sea-*, .midnight-*
|
|
179
|
+
│ │ ├── typography.css ← font families, sizes, weights
|
|
180
|
+
│ │ ├── spacing.css ← radius, sidebar, z-index
|
|
181
|
+
│ │ └── index.css ← imports all tokens
|
|
182
|
+
│ ├── tailwind.css ← @theme inline block
|
|
183
|
+
│ ├── shadcn-base.css ← @layer base rules
|
|
184
|
+
│ ├── utilities.css ← shared utility classes
|
|
185
|
+
│ └── index.css ← main entry point
|
|
186
|
+
├── package.json
|
|
187
|
+
└── README.md
|
|
188
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ekonavi/theme",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Shared design tokens, themes, and Tailwind 4 integration for all Ekonavi apps",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.css",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.css",
|
|
9
|
+
"./tokens": "./src/tokens/index.css",
|
|
10
|
+
"./tokens/colors": "./src/tokens/colors.css",
|
|
11
|
+
"./tokens/forest": "./src/tokens/forest.css",
|
|
12
|
+
"./tokens/earthy": "./src/tokens/earthy.css",
|
|
13
|
+
"./tokens/typography": "./src/tokens/typography.css",
|
|
14
|
+
"./tokens/spacing": "./src/tokens/spacing.css",
|
|
15
|
+
"./extras.css": "./src/tokens/extras.css",
|
|
16
|
+
"./layers": "./src/tokens/spacing.css",
|
|
17
|
+
"./tailwind.css": "./src/tailwind.css",
|
|
18
|
+
"./shadcn-base.css": "./src/shadcn-base.css",
|
|
19
|
+
"./utilities.css": "./src/utilities.css"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"src",
|
|
23
|
+
"README.md",
|
|
24
|
+
"CHANGELOG.md"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"registry": "https://registry.npmjs.org/",
|
|
28
|
+
"access": "restricted"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/Ekonavi/ekonavi-theme.git"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"tailwindcss": ">=4.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"standard-version": "^9.5.0"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"ekonavi",
|
|
42
|
+
"design-system",
|
|
43
|
+
"tailwind",
|
|
44
|
+
"css-variables",
|
|
45
|
+
"shadcn",
|
|
46
|
+
"theme"
|
|
47
|
+
],
|
|
48
|
+
"author": "Ekonavi",
|
|
49
|
+
"license": "UNLICENSED",
|
|
50
|
+
"scripts": {
|
|
51
|
+
"release": "standard-version",
|
|
52
|
+
"release:patch": "standard-version --release-as patch",
|
|
53
|
+
"release:minor": "standard-version --release-as minor",
|
|
54
|
+
"release:major": "standard-version --release-as major"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/index.css
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme */
|
|
3
|
+
/* Shared design system for all Ekonavi apps */
|
|
4
|
+
/* */
|
|
5
|
+
/* Usage in consuming app's globals.css: */
|
|
6
|
+
/* */
|
|
7
|
+
/* @import "tailwindcss"; */
|
|
8
|
+
/* @import "tw-animate-css"; */
|
|
9
|
+
/* @import "@ekonavi/theme"; */
|
|
10
|
+
/* */
|
|
11
|
+
/* Then apply a theme class to <html>: */
|
|
12
|
+
/* <html class="forest-light"> */
|
|
13
|
+
/* <html class="forest-dark"> */
|
|
14
|
+
/* <html class="earthy-light"> */
|
|
15
|
+
/* <html class="earthy-dark"> */
|
|
16
|
+
/* */
|
|
17
|
+
/* For extra themes (air, sea, midnight): */
|
|
18
|
+
/* @import "@ekonavi/theme/extras.css"; */
|
|
19
|
+
/* ============================================== */
|
|
20
|
+
|
|
21
|
+
/* 1. Design tokens (CSS custom properties) */
|
|
22
|
+
@import "./tokens/index.css";
|
|
23
|
+
|
|
24
|
+
/* 2. Tailwind 4 theme integration (@theme inline) */
|
|
25
|
+
@import "./tailwind.css";
|
|
26
|
+
|
|
27
|
+
/* 3. shadcn/ui base layer */
|
|
28
|
+
@import "./shadcn-base.css";
|
|
29
|
+
|
|
30
|
+
/* 4. Shared utility classes */
|
|
31
|
+
@import "./utilities.css";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — shadcn Base Layer */
|
|
3
|
+
/* Global base styles for shadcn/ui compatibility */
|
|
4
|
+
/* ============================================== */
|
|
5
|
+
|
|
6
|
+
@layer base {
|
|
7
|
+
* {
|
|
8
|
+
@apply border-border outline-ring/50;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
body {
|
|
12
|
+
@apply bg-background text-foreground;
|
|
13
|
+
font-family: var(--font-body);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* ---- Heading defaults ---- */
|
|
17
|
+
h1 {
|
|
18
|
+
@apply text-xl font-bold uppercase;
|
|
19
|
+
font-family: var(--font-display);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
h2 {
|
|
23
|
+
@apply text-lg font-bold uppercase;
|
|
24
|
+
font-family: var(--font-display);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
h3 {
|
|
28
|
+
@apply text-sm text-muted-foreground mb-0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* ---- Link defaults ---- */
|
|
32
|
+
a {
|
|
33
|
+
@apply cursor-pointer;
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/tailwind.css
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Tailwind 4 Integration */
|
|
3
|
+
/* Maps CSS custom properties → Tailwind utilities */
|
|
4
|
+
/* Uses @theme inline (Tailwind v4 CSS-first API) */
|
|
5
|
+
/* ============================================== */
|
|
6
|
+
|
|
7
|
+
@theme inline {
|
|
8
|
+
/* ---- Core semantic colors ---- */
|
|
9
|
+
--color-background: var(--color-background);
|
|
10
|
+
--color-foreground: var(--color-foreground);
|
|
11
|
+
--color-card: var(--color-card);
|
|
12
|
+
--color-card-foreground: var(--color-card-foreground);
|
|
13
|
+
--color-popover: var(--color-popover);
|
|
14
|
+
--color-popover-foreground: var(--color-popover-foreground);
|
|
15
|
+
--color-primary: var(--color-primary);
|
|
16
|
+
--color-primary-foreground: var(--color-primary-foreground);
|
|
17
|
+
--color-secondary: var(--color-secondary);
|
|
18
|
+
--color-secondary-foreground: var(--color-secondary-foreground);
|
|
19
|
+
--color-muted: var(--color-muted);
|
|
20
|
+
--color-muted-foreground: var(--color-muted-foreground);
|
|
21
|
+
--color-accent: var(--color-accent);
|
|
22
|
+
--color-accent-foreground: var(--color-accent-foreground);
|
|
23
|
+
--color-destructive: var(--color-destructive);
|
|
24
|
+
--color-destructive-foreground: var(--color-destructive-foreground);
|
|
25
|
+
--color-border: var(--color-border);
|
|
26
|
+
--color-input: var(--color-input);
|
|
27
|
+
--color-ring: var(--color-ring);
|
|
28
|
+
|
|
29
|
+
/* ---- Chart colors ---- */
|
|
30
|
+
--color-chart-1: var(--color-chart-1);
|
|
31
|
+
--color-chart-2: var(--color-chart-2);
|
|
32
|
+
--color-chart-3: var(--color-chart-3);
|
|
33
|
+
--color-chart-4: var(--color-chart-4);
|
|
34
|
+
--color-chart-5: var(--color-chart-5);
|
|
35
|
+
|
|
36
|
+
/* ---- Custom Ekonavi tokens ---- */
|
|
37
|
+
--color-background-tone: var(--color-background-tone);
|
|
38
|
+
--color-line: var(--color-line);
|
|
39
|
+
--color-offwhite: var(--color-offwhite);
|
|
40
|
+
--color-translucent-object: var(--color-translucent-object);
|
|
41
|
+
--color-translucent-object-selected: var(--color-translucent-object-selected);
|
|
42
|
+
--color-translucent-object-selected-overlayed: var(--color-translucent-object-selected-overlayed);
|
|
43
|
+
|
|
44
|
+
/* ---- Brand palette as utilities ---- */
|
|
45
|
+
/* Usage: bg-eko-sage, text-eko-deep-green, border-eko-amber, etc. */
|
|
46
|
+
--color-eko-sage: var(--eko-sage);
|
|
47
|
+
--color-eko-deep-green: var(--eko-deep-green);
|
|
48
|
+
--color-eko-dark-teal: var(--eko-dark-teal);
|
|
49
|
+
--color-eko-light-green: var(--eko-light-green);
|
|
50
|
+
--color-eko-dark-green-bg: var(--eko-dark-green-bg);
|
|
51
|
+
--color-eko-amber: var(--eko-amber);
|
|
52
|
+
--color-eko-coral: var(--eko-coral);
|
|
53
|
+
--color-eko-earth-brown: var(--eko-earth-brown);
|
|
54
|
+
--color-eko-cream: var(--eko-cream);
|
|
55
|
+
--color-eko-gold: var(--eko-gold);
|
|
56
|
+
--color-eko-warm-beige: var(--eko-warm-beige);
|
|
57
|
+
|
|
58
|
+
/* ---- Sidebar (shadcn sidebar compat) ---- */
|
|
59
|
+
--color-sidebar: var(--sidebar);
|
|
60
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
61
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
62
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
63
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
64
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
65
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
66
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
67
|
+
|
|
68
|
+
/* ---- Radius ---- */
|
|
69
|
+
--radius-sm: var(--radius-sm);
|
|
70
|
+
--radius-md: var(--radius-md);
|
|
71
|
+
--radius-lg: var(--radius-lg);
|
|
72
|
+
--radius-xl: var(--radius-xl);
|
|
73
|
+
|
|
74
|
+
/* ---- Typography ---- */
|
|
75
|
+
--font-body: var(--font-body);
|
|
76
|
+
--font-display: var(--font-display);
|
|
77
|
+
--font-mono: var(--font-mono);
|
|
78
|
+
|
|
79
|
+
/* ---- Animations ---- */
|
|
80
|
+
--animate-scale-up: scaleUp 0.3s ease-out forwards;
|
|
81
|
+
--animate-gradient-border: gradient-border 3s linear infinite;
|
|
82
|
+
|
|
83
|
+
@keyframes scaleUp {
|
|
84
|
+
0% {
|
|
85
|
+
transform: scale(0.7);
|
|
86
|
+
opacity: 0;
|
|
87
|
+
}
|
|
88
|
+
100% {
|
|
89
|
+
transform: scale(1);
|
|
90
|
+
opacity: 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@keyframes gradient-border {
|
|
95
|
+
0% { background-position: 0% 50%; }
|
|
96
|
+
100% { background-position: 200% 50%; }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Dark mode variant for Tailwind 4 */
|
|
101
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Brand Color Palette */
|
|
3
|
+
/* Source: Ekonavi Style Guide (Clara Goldenstein) */
|
|
4
|
+
/* ============================================== */
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
/* ---- Greens ---- */
|
|
8
|
+
--eko-sage: #A8C8B1;
|
|
9
|
+
--eko-deep-green: #2D502F;
|
|
10
|
+
--eko-dark-teal: #00634D;
|
|
11
|
+
--eko-mint: #9D4F14; /* used as forest muted reference */
|
|
12
|
+
--eko-light-green: #B8DAC1;
|
|
13
|
+
--eko-dark-green-bg: #0D3D33;
|
|
14
|
+
|
|
15
|
+
/* ---- Earths ---- */
|
|
16
|
+
--eko-amber: #E28509;
|
|
17
|
+
--eko-coral: #FF914D;
|
|
18
|
+
--eko-earth-brown: #9D4F14;
|
|
19
|
+
--eko-cream: #EFEDE7;
|
|
20
|
+
--eko-gold: #FFDE59;
|
|
21
|
+
--eko-warm-beige: #F0E0C8;
|
|
22
|
+
|
|
23
|
+
/* ---- Neutrals ---- */
|
|
24
|
+
--eko-white: #FFFFFF;
|
|
25
|
+
--eko-offwhite: #FAFAFA;
|
|
26
|
+
--eko-gray-100: #F5F5F5;
|
|
27
|
+
--eko-gray-200: #E5E5E5;
|
|
28
|
+
--eko-gray-500: #737373;
|
|
29
|
+
--eko-gray-800: #262626;
|
|
30
|
+
--eko-black: #0A0A0A;
|
|
31
|
+
|
|
32
|
+
/* ---- Shared layout ---- */
|
|
33
|
+
--radius: 0.5rem;
|
|
34
|
+
--header-height: 68px;
|
|
35
|
+
--footer-height: 88px;
|
|
36
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Earthy Theme */
|
|
3
|
+
/* Brown/amber-dominant theme for warm contexts */
|
|
4
|
+
/* Modes: .earthy-light, .earthy-dark */
|
|
5
|
+
/* ============================================== */
|
|
6
|
+
|
|
7
|
+
/* ---- EARTHY LIGHT ---- */
|
|
8
|
+
.earthy-light {
|
|
9
|
+
--color-background: hsl(37, 20%, 82%);
|
|
10
|
+
--color-foreground: hsl(39, 72%, 13%);
|
|
11
|
+
--color-card: hsl(42, 56%, 93%);
|
|
12
|
+
--color-card-foreground: hsl(88 15% 11%);
|
|
13
|
+
--color-popover: hsl(0 0% 100%);
|
|
14
|
+
--color-popover-foreground: hsl(88 15% 11%);
|
|
15
|
+
--color-primary: hsl(0, 0%, 100%);
|
|
16
|
+
--color-primary-foreground: hsl(88 15% 11%);
|
|
17
|
+
--color-secondary: hsl(31, 58%, 92%);
|
|
18
|
+
--color-secondary-foreground: hsl(88 15% 11%);
|
|
19
|
+
--color-muted: hsl(0 0% 96.1%);
|
|
20
|
+
--color-muted-foreground: hsl(88 15% 11% / 0.7);
|
|
21
|
+
--color-accent: hsl(0 0% 96.1%);
|
|
22
|
+
--color-accent-foreground: hsl(88 15% 11%);
|
|
23
|
+
--color-destructive: hsl(0 84.2% 60.2%);
|
|
24
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
25
|
+
--color-border: hsl(88 15% 11%);
|
|
26
|
+
--color-input: hsla(0, 0%, 100%, 0.8);
|
|
27
|
+
--color-ring: hsl(0 0% 3.9%);
|
|
28
|
+
--color-chart-1: hsl(12 76% 61%);
|
|
29
|
+
--color-chart-2: hsl(173 58% 39%);
|
|
30
|
+
--color-chart-3: hsl(197 37% 24%);
|
|
31
|
+
--color-chart-4: hsl(43 74% 66%);
|
|
32
|
+
--color-chart-5: hsl(27 87% 67%);
|
|
33
|
+
|
|
34
|
+
--color-background-tone: hsl(0 0% 98%);
|
|
35
|
+
--color-translucent-object: hsla(0 0% 100% / 0.1);
|
|
36
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.2);
|
|
37
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.3);
|
|
38
|
+
--color-line: hsl(0 0% 89.8%);
|
|
39
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ---- EARTHY DARK ---- */
|
|
43
|
+
.earthy-dark {
|
|
44
|
+
--color-background: hsl(30, 15%, 8%);
|
|
45
|
+
--color-foreground: hsl(0 0% 98%);
|
|
46
|
+
--color-card: hsl(30, 15%, 12%);
|
|
47
|
+
--color-card-foreground: hsl(0 0% 98%);
|
|
48
|
+
--color-popover: hsl(30, 15%, 12%);
|
|
49
|
+
--color-popover-foreground: hsl(0 0% 98%);
|
|
50
|
+
--color-primary: hsl(27 87% 67%);
|
|
51
|
+
--color-primary-foreground: hsl(30, 15%, 8%);
|
|
52
|
+
--color-secondary: hsl(30, 15%, 18%);
|
|
53
|
+
--color-secondary-foreground: hsl(0 0% 98%);
|
|
54
|
+
--color-muted: hsl(30, 15%, 18%);
|
|
55
|
+
--color-muted-foreground: hsl(0 0% 63.9%);
|
|
56
|
+
--color-accent: hsl(30, 15%, 18%);
|
|
57
|
+
--color-accent-foreground: hsl(0 0% 98%);
|
|
58
|
+
--color-destructive: hsl(0 62.8% 30.6%);
|
|
59
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
60
|
+
--color-border: hsl(30, 15%, 18%);
|
|
61
|
+
--color-input: hsl(30, 15%, 18%);
|
|
62
|
+
--color-ring: hsl(27 87% 67%);
|
|
63
|
+
--color-chart-1: hsl(27 87% 67%);
|
|
64
|
+
--color-chart-2: hsl(173 58% 39%);
|
|
65
|
+
--color-chart-3: hsl(43 74% 66%);
|
|
66
|
+
--color-chart-4: hsl(12 76% 61%);
|
|
67
|
+
--color-chart-5: hsl(197 37% 24%);
|
|
68
|
+
|
|
69
|
+
--color-background-tone: hsl(0 0% 7%);
|
|
70
|
+
--color-translucent-object: hsla(0 0% 100% / 0.05);
|
|
71
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.1);
|
|
72
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.15);
|
|
73
|
+
--color-line: hsl(30, 15%, 18%);
|
|
74
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
75
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Extra Themes */
|
|
3
|
+
/* Optional themes preserved from existing apps */
|
|
4
|
+
/* Import separately if needed: */
|
|
5
|
+
/* @import "@ekonavi/theme/extras.css"; */
|
|
6
|
+
/* ============================================== */
|
|
7
|
+
|
|
8
|
+
/* ===== AIR THEME ===== */
|
|
9
|
+
.air-light {
|
|
10
|
+
--color-background: hsl(0, 0%, 97%);
|
|
11
|
+
--color-foreground: hsl(0, 0%, 9%);
|
|
12
|
+
--color-card: hsl(0 0% 100%);
|
|
13
|
+
--color-card-foreground: hsl(0, 0%, 9%);
|
|
14
|
+
--color-popover: hsl(0 0% 100%);
|
|
15
|
+
--color-popover-foreground: hsl(0, 0%, 9%);
|
|
16
|
+
--color-primary: hsl(0, 0%, 85%);
|
|
17
|
+
--color-primary-foreground: hsl(0, 0%, 100%);
|
|
18
|
+
--color-secondary: hsl(0 0% 96.1%);
|
|
19
|
+
--color-secondary-foreground: hsl(0, 0%, 9%);
|
|
20
|
+
--color-muted: hsl(0 0% 96.1%);
|
|
21
|
+
--color-muted-foreground: hsl(0, 0%, 30%);
|
|
22
|
+
--color-accent: hsl(0 0% 96.1%);
|
|
23
|
+
--color-accent-foreground: hsl(0, 0%, 9%);
|
|
24
|
+
--color-destructive: hsl(0, 71%, 70%);
|
|
25
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
26
|
+
--color-border: hsl(0, 0%, 22%);
|
|
27
|
+
--color-input: hsl(0, 0%, 84%);
|
|
28
|
+
--color-ring: hsl(0, 0%, 9%);
|
|
29
|
+
--color-chart-1: hsl(220, 70%, 50%);
|
|
30
|
+
--color-chart-2: hsl(160, 60%, 45%);
|
|
31
|
+
--color-chart-3: hsl(30, 80%, 55%);
|
|
32
|
+
--color-chart-4: hsl(280, 65%, 60%);
|
|
33
|
+
--color-chart-5: hsl(340, 75%, 55%);
|
|
34
|
+
|
|
35
|
+
--color-background-tone: hsl(0 0% 98%);
|
|
36
|
+
--color-translucent-object: hsla(0 0% 100% / 0.1);
|
|
37
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.2);
|
|
38
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.3);
|
|
39
|
+
--color-line: hsl(0 0% 89.8%);
|
|
40
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.air-dark {
|
|
44
|
+
--color-background: hsl(0, 0%, 9%);
|
|
45
|
+
--color-foreground: hsl(0 0% 98%);
|
|
46
|
+
--color-card: hsl(0, 0%, 14%);
|
|
47
|
+
--color-card-foreground: hsl(0 0% 98%);
|
|
48
|
+
--color-popover: hsl(0, 0%, 14%);
|
|
49
|
+
--color-popover-foreground: hsl(0 0% 98%);
|
|
50
|
+
--color-primary: hsl(0 0% 98%);
|
|
51
|
+
--color-primary-foreground: hsl(0, 0%, 9%);
|
|
52
|
+
--color-secondary: hsl(0, 0%, 20%);
|
|
53
|
+
--color-secondary-foreground: hsl(0 0% 98%);
|
|
54
|
+
--color-muted: hsl(0, 0%, 20%);
|
|
55
|
+
--color-muted-foreground: hsl(0 0% 63.9%);
|
|
56
|
+
--color-accent: hsl(0, 0%, 20%);
|
|
57
|
+
--color-accent-foreground: hsl(0 0% 98%);
|
|
58
|
+
--color-destructive: hsl(0 62.8% 30.6%);
|
|
59
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
60
|
+
--color-border: hsl(0, 0%, 20%);
|
|
61
|
+
--color-input: hsl(0, 0%, 20%);
|
|
62
|
+
--color-ring: hsl(0 0% 98%);
|
|
63
|
+
--color-chart-1: hsl(220, 80%, 60%);
|
|
64
|
+
--color-chart-2: hsl(160, 70%, 55%);
|
|
65
|
+
--color-chart-3: hsl(30, 90%, 65%);
|
|
66
|
+
--color-chart-4: hsl(280, 75%, 70%);
|
|
67
|
+
--color-chart-5: hsl(340, 85%, 65%);
|
|
68
|
+
|
|
69
|
+
--color-background-tone: hsl(0 0% 7%);
|
|
70
|
+
--color-translucent-object: hsla(0 0% 100% / 0.05);
|
|
71
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.1);
|
|
72
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.15);
|
|
73
|
+
--color-line: hsl(0, 0%, 20%);
|
|
74
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* ===== SEA THEME ===== */
|
|
78
|
+
.sea-light {
|
|
79
|
+
--color-background: hsl(174, 40%, 90%);
|
|
80
|
+
--color-foreground: hsl(173, 43%, 22%);
|
|
81
|
+
--color-foreground-active: hsl(174, 100%, 27%);
|
|
82
|
+
--color-card: hsl(0 0% 100%);
|
|
83
|
+
--color-card-foreground: hsl(174, 80%, 12%);
|
|
84
|
+
--color-popover: hsl(0 0% 100%);
|
|
85
|
+
--color-popover-foreground: hsl(174, 80%, 12%);
|
|
86
|
+
--color-primary: hsl(189, 48%, 87%);
|
|
87
|
+
--color-primary-foreground: hsl(174, 80%, 12%);
|
|
88
|
+
--color-secondary: hsl(188, 42%, 80%);
|
|
89
|
+
--color-secondary-foreground: hsl(174, 80%, 12%);
|
|
90
|
+
--color-muted: hsl(0 0% 96.1%);
|
|
91
|
+
--color-muted-foreground: hsl(174, 80%, 12% / 0.7);
|
|
92
|
+
--color-accent: hsl(0 0% 96.1%);
|
|
93
|
+
--color-accent-foreground: hsl(174, 80%, 12%);
|
|
94
|
+
--color-destructive: hsl(338, 67%, 47%);
|
|
95
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
96
|
+
--color-border: hsl(173, 43%, 22%);
|
|
97
|
+
--color-input: hsl(174, 40%, 86%);
|
|
98
|
+
--color-ring: hsl(174, 100%, 35%);
|
|
99
|
+
--color-chart-1: hsl(174, 70%, 40%);
|
|
100
|
+
--color-chart-2: hsl(166, 60%, 40%);
|
|
101
|
+
--color-chart-3: hsl(190, 80%, 45%);
|
|
102
|
+
--color-chart-4: hsl(43 74% 66%);
|
|
103
|
+
--color-chart-5: hsl(27 87% 67%);
|
|
104
|
+
|
|
105
|
+
--color-background-tone: hsl(0 0% 98%);
|
|
106
|
+
--color-translucent-object: hsla(0 0% 100% / 0.1);
|
|
107
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.2);
|
|
108
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.3);
|
|
109
|
+
--color-line: hsl(0 0% 89.8%);
|
|
110
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.sea-dark {
|
|
114
|
+
--color-background: hsl(174, 30%, 8%);
|
|
115
|
+
--color-foreground: hsl(0 0% 98%);
|
|
116
|
+
--color-card: hsl(174, 30%, 12%);
|
|
117
|
+
--color-card-foreground: hsl(0 0% 98%);
|
|
118
|
+
--color-popover: hsl(174, 30%, 12%);
|
|
119
|
+
--color-popover-foreground: hsl(0 0% 98%);
|
|
120
|
+
--color-primary: hsl(174, 100%, 50%);
|
|
121
|
+
--color-primary-foreground: hsl(174, 30%, 8%);
|
|
122
|
+
--color-secondary: hsl(174, 30%, 18%);
|
|
123
|
+
--color-secondary-foreground: hsl(0 0% 98%);
|
|
124
|
+
--color-muted: hsl(174, 30%, 18%);
|
|
125
|
+
--color-muted-foreground: hsl(0 0% 63.9%);
|
|
126
|
+
--color-accent: hsl(174, 30%, 18%);
|
|
127
|
+
--color-accent-foreground: hsl(0 0% 98%);
|
|
128
|
+
--color-destructive: hsl(0 62.8% 30.6%);
|
|
129
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
130
|
+
--color-border: hsl(174, 30%, 18%);
|
|
131
|
+
--color-input: hsl(174, 30%, 18%);
|
|
132
|
+
--color-ring: hsl(174, 100%, 50%);
|
|
133
|
+
--color-chart-1: hsl(174, 100%, 50%);
|
|
134
|
+
--color-chart-2: hsl(166, 80%, 55%);
|
|
135
|
+
--color-chart-3: hsl(190, 100%, 55%);
|
|
136
|
+
--color-chart-4: hsl(43 94% 76%);
|
|
137
|
+
--color-chart-5: hsl(27 97% 77%);
|
|
138
|
+
|
|
139
|
+
--color-background-tone: hsl(0 0% 7%);
|
|
140
|
+
--color-translucent-object: hsla(0 0% 100% / 0.05);
|
|
141
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.1);
|
|
142
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.15);
|
|
143
|
+
--color-line: hsl(174, 30%, 18%);
|
|
144
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* ===== MIDNIGHT THEME ===== */
|
|
148
|
+
.midnight-light {
|
|
149
|
+
--color-background: hsl(220, 20%, 94%);
|
|
150
|
+
--color-foreground: hsl(220, 40%, 15%);
|
|
151
|
+
--color-card: hsl(0 0% 100%);
|
|
152
|
+
--color-card-foreground: hsl(220, 40%, 15%);
|
|
153
|
+
--color-popover: hsl(0 0% 100%);
|
|
154
|
+
--color-popover-foreground: hsl(220, 40%, 15%);
|
|
155
|
+
--color-primary: hsl(0, 0%, 100%);
|
|
156
|
+
--color-primary-foreground: hsl(220, 40%, 15%);
|
|
157
|
+
--color-secondary: hsl(0 0% 96.1%);
|
|
158
|
+
--color-secondary-foreground: hsl(220, 40%, 15%);
|
|
159
|
+
--color-muted: hsl(0 0% 96.1%);
|
|
160
|
+
--color-muted-foreground: hsl(220, 40%, 15% / 0.7);
|
|
161
|
+
--color-accent: hsl(0 0% 96.1%);
|
|
162
|
+
--color-accent-foreground: hsl(220, 40%, 15%);
|
|
163
|
+
--color-destructive: hsl(0 84.2% 60.2%);
|
|
164
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
165
|
+
--color-border: hsl(220, 40%, 15%);
|
|
166
|
+
--color-input: hsl(220, 20%, 90%);
|
|
167
|
+
--color-ring: hsl(220, 80%, 45%);
|
|
168
|
+
--color-chart-1: hsl(220, 70%, 50%);
|
|
169
|
+
--color-chart-2: hsl(200, 70%, 50%);
|
|
170
|
+
--color-chart-3: hsl(240, 70%, 60%);
|
|
171
|
+
--color-chart-4: hsl(43 74% 66%);
|
|
172
|
+
--color-chart-5: hsl(27 87% 67%);
|
|
173
|
+
|
|
174
|
+
--color-background-tone: hsl(0 0% 98%);
|
|
175
|
+
--color-translucent-object: hsla(0 0% 100% / 0.1);
|
|
176
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.2);
|
|
177
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.3);
|
|
178
|
+
--color-line: hsl(0 0% 89.8%);
|
|
179
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.midnight-dark {
|
|
183
|
+
--color-background: hsl(220, 30%, 6%);
|
|
184
|
+
--color-foreground: hsl(0 0% 98%);
|
|
185
|
+
--color-card: hsl(220, 30%, 10%);
|
|
186
|
+
--color-card-foreground: hsl(0 0% 98%);
|
|
187
|
+
--color-popover: hsl(220, 30%, 10%);
|
|
188
|
+
--color-popover-foreground: hsl(0 0% 98%);
|
|
189
|
+
--color-primary: hsl(220, 100%, 60%);
|
|
190
|
+
--color-primary-foreground: hsl(220, 30%, 6%);
|
|
191
|
+
--color-secondary: hsl(220, 30%, 16%);
|
|
192
|
+
--color-secondary-foreground: hsl(0 0% 98%);
|
|
193
|
+
--color-muted: hsl(220, 30%, 16%);
|
|
194
|
+
--color-muted-foreground: hsl(0 0% 63.9%);
|
|
195
|
+
--color-accent: hsl(220, 30%, 16%);
|
|
196
|
+
--color-accent-foreground: hsl(0 0% 98%);
|
|
197
|
+
--color-destructive: hsl(0 62.8% 30.6%);
|
|
198
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
199
|
+
--color-border: hsl(220, 30%, 16%);
|
|
200
|
+
--color-input: hsl(220, 30%, 16%);
|
|
201
|
+
--color-ring: hsl(220, 100%, 60%);
|
|
202
|
+
--color-chart-1: hsl(220, 100%, 60%);
|
|
203
|
+
--color-chart-2: hsl(200, 100%, 55%);
|
|
204
|
+
--color-chart-3: hsl(240, 100%, 70%);
|
|
205
|
+
--color-chart-4: hsl(43 94% 76%);
|
|
206
|
+
--color-chart-5: hsl(27 97% 77%);
|
|
207
|
+
|
|
208
|
+
--color-background-tone: hsl(0 0% 7%);
|
|
209
|
+
--color-translucent-object: hsla(0 0% 100% / 0.05);
|
|
210
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.1);
|
|
211
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.15);
|
|
212
|
+
--color-line: hsl(220, 30%, 16%);
|
|
213
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
214
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Forest Theme */
|
|
3
|
+
/* Green-dominant theme for nature/eco contexts */
|
|
4
|
+
/* Modes: .forest-light, .forest-dark */
|
|
5
|
+
/* ============================================== */
|
|
6
|
+
|
|
7
|
+
/* ---- FOREST LIGHT ---- */
|
|
8
|
+
.forest-light {
|
|
9
|
+
--color-background: hsl(135, 31%, 75%);
|
|
10
|
+
--color-foreground: hsl(120, 60%, 15%);
|
|
11
|
+
--color-card: #ffffff;
|
|
12
|
+
--color-card-foreground: hsl(120, 60%, 15%);
|
|
13
|
+
--color-popover: hsl(0 0% 100%);
|
|
14
|
+
--color-popover-foreground: hsl(120, 60%, 15%);
|
|
15
|
+
--color-primary: hsl(0, 0%, 100%);
|
|
16
|
+
--color-primary-foreground: hsl(120, 60%, 15%);
|
|
17
|
+
--color-secondary: hsl(134, 42%, 81%);
|
|
18
|
+
--color-secondary-foreground: hsl(120, 60%, 15%);
|
|
19
|
+
--color-muted: hsl(0 0% 96.1%);
|
|
20
|
+
--color-muted-foreground: hsl(120, 60%, 15% / 0.7);
|
|
21
|
+
--color-accent: hsl(99, 46%, 84%);
|
|
22
|
+
--color-accent-foreground: hsl(141, 56%, 28%);
|
|
23
|
+
--color-destructive: hsl(0 52.8% 40.6%);
|
|
24
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
25
|
+
--color-border: hsl(120, 60%, 15%);
|
|
26
|
+
--color-input: hsl(0, 0%, 100%);
|
|
27
|
+
--color-ring: hsl(120, 100%, 25%);
|
|
28
|
+
--color-chart-1: hsl(120, 60%, 40%);
|
|
29
|
+
--color-chart-2: hsl(173 58% 39%);
|
|
30
|
+
--color-chart-3: hsl(88, 50%, 45%);
|
|
31
|
+
--color-chart-4: hsl(43 74% 66%);
|
|
32
|
+
--color-chart-5: hsl(27 87% 67%);
|
|
33
|
+
|
|
34
|
+
--color-background-tone: hsl(0 0% 98%);
|
|
35
|
+
--color-translucent-object: hsla(0 0% 100% / 0.1);
|
|
36
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.2);
|
|
37
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.3);
|
|
38
|
+
--color-line: hsl(0 0% 89.8%);
|
|
39
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ---- FOREST DARK ---- */
|
|
43
|
+
.forest-dark {
|
|
44
|
+
--color-background: hsl(120, 25%, 8%);
|
|
45
|
+
--color-foreground: hsl(0 0% 98%);
|
|
46
|
+
--color-card: hsl(120, 25%, 12%);
|
|
47
|
+
--color-card-foreground: hsl(0 0% 98%);
|
|
48
|
+
--color-popover: hsl(120, 25%, 12%);
|
|
49
|
+
--color-popover-foreground: hsl(0 0% 98%);
|
|
50
|
+
--color-primary: hsl(120, 100%, 50%);
|
|
51
|
+
--color-primary-foreground: hsl(120, 25%, 8%);
|
|
52
|
+
--color-secondary: hsl(120, 25%, 18%);
|
|
53
|
+
--color-secondary-foreground: hsl(0 0% 98%);
|
|
54
|
+
--color-muted: hsl(120, 25%, 18%);
|
|
55
|
+
--color-muted-foreground: hsl(0 0% 63.9%);
|
|
56
|
+
--color-accent: hsl(120, 25%, 18%);
|
|
57
|
+
--color-accent-foreground: hsl(0 0% 98%);
|
|
58
|
+
--color-destructive: hsl(0 62.8% 30.6%);
|
|
59
|
+
--color-destructive-foreground: hsl(0 0% 98%);
|
|
60
|
+
--color-border: hsl(120, 25%, 18%);
|
|
61
|
+
--color-input: hsl(120, 25%, 18%);
|
|
62
|
+
--color-ring: hsl(120, 100%, 50%);
|
|
63
|
+
--color-chart-1: hsl(120, 100%, 50%);
|
|
64
|
+
--color-chart-2: hsl(173 58% 50%);
|
|
65
|
+
--color-chart-3: hsl(88, 70%, 55%);
|
|
66
|
+
--color-chart-4: hsl(43 84% 76%);
|
|
67
|
+
--color-chart-5: hsl(27 97% 77%);
|
|
68
|
+
|
|
69
|
+
--color-background-tone: hsl(0 0% 7%);
|
|
70
|
+
--color-translucent-object: hsla(0 0% 100% / 0.05);
|
|
71
|
+
--color-translucent-object-selected: hsla(0 0% 100% / 0.1);
|
|
72
|
+
--color-translucent-object-selected-overlayed: hsla(0 0% 100% / 0.15);
|
|
73
|
+
--color-line: hsl(120, 25%, 18%);
|
|
74
|
+
--color-offwhite: hsl(0 0% 98%);
|
|
75
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Spacing & Layout */
|
|
3
|
+
/* Shared sizing, radius, stacking layers */
|
|
4
|
+
/* ============================================== */
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
/* Border radius scale */
|
|
8
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
9
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
10
|
+
--radius-lg: var(--radius);
|
|
11
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
12
|
+
--radius-2xl: calc(var(--radius) + 8px);
|
|
13
|
+
--radius-full: 9999px;
|
|
14
|
+
|
|
15
|
+
/* Sidebar (for admin/dashboard layouts) */
|
|
16
|
+
--sidebar-width: 280px;
|
|
17
|
+
--sidebar-width-collapsed: 68px;
|
|
18
|
+
|
|
19
|
+
/* Sidebar theme (matches shadcn sidebar) */
|
|
20
|
+
--sidebar: var(--color-card);
|
|
21
|
+
--sidebar-foreground: var(--color-card-foreground);
|
|
22
|
+
--sidebar-primary: var(--color-primary);
|
|
23
|
+
--sidebar-primary-foreground: var(--color-primary-foreground);
|
|
24
|
+
--sidebar-accent: var(--color-accent);
|
|
25
|
+
--sidebar-accent-foreground: var(--color-accent-foreground);
|
|
26
|
+
--sidebar-border: var(--color-border);
|
|
27
|
+
--sidebar-ring: var(--color-ring);
|
|
28
|
+
|
|
29
|
+
/* Stacking layers — single ascending scale for all apps */
|
|
30
|
+
--layer-canvas: 0; /* 3D canvas / background */
|
|
31
|
+
--layer-scene: 10; /* in-scene controls, absolute positioned UI */
|
|
32
|
+
--layer-hud: 100; /* always-visible HUD chrome: version badge, theme toggle */
|
|
33
|
+
--layer-sidebar: 150; /* sidebar navigation */
|
|
34
|
+
--layer-sheet: 200; /* sheet/drawer backdrops */
|
|
35
|
+
--layer-sheet-content: 201; /* sheet/drawer content panels */
|
|
36
|
+
--layer-dropdown: 300; /* select menus, dropdown menus */
|
|
37
|
+
--layer-modal: 400; /* dialog/alert-dialog backdrop */
|
|
38
|
+
--layer-modal-content: 401; /* dialog/alert-dialog content */
|
|
39
|
+
--layer-overlay: 500; /* full-screen AR / SIMS / ATO overlays */
|
|
40
|
+
--layer-overlay-action: 501; /* close buttons etc. inside overlays */
|
|
41
|
+
--layer-floating: 600; /* PIP windows, params widget, global loader */
|
|
42
|
+
--layer-debug: 700; /* dev-only debug panels */
|
|
43
|
+
--layer-toast: 2147483647; /* always on top — browser INT_MAX */
|
|
44
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Typography */
|
|
3
|
+
/* Fonts: Josefin Sans (body), Bryndan Write (h) */
|
|
4
|
+
/* ============================================== */
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* FONT LOADING:
|
|
8
|
+
* - For Next.js apps: use next/font/google for Josefin Sans
|
|
9
|
+
* - Bryndan Write is a custom font — load via @font-face in the app
|
|
10
|
+
* - This file defines the CSS custom properties only
|
|
11
|
+
*
|
|
12
|
+
* Example next/font setup:
|
|
13
|
+
* const josefin = Josefin_Sans({ subsets: ['latin'], variable: '--font-josefin' });
|
|
14
|
+
* <html className={josefin.variable}>
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
:root {
|
|
18
|
+
/* Font family stacks */
|
|
19
|
+
--font-body: 'Josefin Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
|
|
20
|
+
--font-display: 'Bryndan Write', 'Josefin Sans', ui-serif, Georgia, serif;
|
|
21
|
+
--font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
22
|
+
|
|
23
|
+
/* Font sizes — modular scale */
|
|
24
|
+
--text-xs: 0.75rem; /* 12px */
|
|
25
|
+
--text-sm: 0.875rem; /* 14px */
|
|
26
|
+
--text-base: 1rem; /* 16px */
|
|
27
|
+
--text-lg: 1.125rem; /* 18px */
|
|
28
|
+
--text-xl: 1.25rem; /* 20px */
|
|
29
|
+
--text-2xl: 1.5rem; /* 24px */
|
|
30
|
+
--text-3xl: 1.875rem; /* 30px */
|
|
31
|
+
--text-4xl: 2.25rem; /* 36px */
|
|
32
|
+
|
|
33
|
+
/* Line heights */
|
|
34
|
+
--leading-tight: 1.25;
|
|
35
|
+
--leading-normal: 1.5;
|
|
36
|
+
--leading-relaxed: 1.625;
|
|
37
|
+
|
|
38
|
+
/* Font weights */
|
|
39
|
+
--font-light: 300;
|
|
40
|
+
--font-regular: 400;
|
|
41
|
+
--font-medium: 500;
|
|
42
|
+
--font-semibold: 600;
|
|
43
|
+
--font-bold: 700;
|
|
44
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/* ============================================== */
|
|
2
|
+
/* @ekonavi/theme — Shared Utilities */
|
|
3
|
+
/* Reusable utility classes across all Ekonavi apps */
|
|
4
|
+
/* ============================================== */
|
|
5
|
+
|
|
6
|
+
@layer utilities {
|
|
7
|
+
/* ---- Aspect ratio placeholders ---- */
|
|
8
|
+
.placeholder {
|
|
9
|
+
@apply h-0 relative pt-[100%];
|
|
10
|
+
}
|
|
11
|
+
.placeholder-md {
|
|
12
|
+
@apply !pt-[54%];
|
|
13
|
+
}
|
|
14
|
+
.placeholder-lg {
|
|
15
|
+
@apply !pt-[44%];
|
|
16
|
+
}
|
|
17
|
+
.placeholder-xl {
|
|
18
|
+
@apply !pt-[33%];
|
|
19
|
+
}
|
|
20
|
+
.placeholder-2xl {
|
|
21
|
+
@apply !pt-[30%];
|
|
22
|
+
}
|
|
23
|
+
.placeholder > img {
|
|
24
|
+
@apply absolute top-0 left-0 w-full h-full;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* ---- Text alignment ---- */
|
|
28
|
+
.text-justify-center {
|
|
29
|
+
text-align-last: center;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* ---- Scrollbar control ---- */
|
|
33
|
+
/* Chrome, Safari and Opera */
|
|
34
|
+
.no-scrollbar::-webkit-scrollbar {
|
|
35
|
+
display: none;
|
|
36
|
+
}
|
|
37
|
+
.no-scrollbar {
|
|
38
|
+
-ms-overflow-style: none; /* IE and Edge */
|
|
39
|
+
scrollbar-width: none; /* Firefox */
|
|
40
|
+
}
|
|
41
|
+
.thin-scrollbar::-webkit-scrollbar {
|
|
42
|
+
width: 3px;
|
|
43
|
+
}
|
|
44
|
+
.med-scrollbar::-webkit-scrollbar {
|
|
45
|
+
width: 7px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* ---- Border utilities ---- */
|
|
49
|
+
.leve-border-bottom-light {
|
|
50
|
+
@apply border-b-[1px] border-b-white/30;
|
|
51
|
+
}
|
|
52
|
+
.leve-border-bottom-dark {
|
|
53
|
+
@apply border-b-[1px] border-b-black/5;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* ---- Mobile performance optimization ---- */
|
|
57
|
+
.mobile-optimized,
|
|
58
|
+
.mobile-optimized > * {
|
|
59
|
+
transition-duration: 0ms !important;
|
|
60
|
+
box-shadow: none !important;
|
|
61
|
+
opacity: 1 !important;
|
|
62
|
+
border-radius: 0 !important;
|
|
63
|
+
backdrop-filter: none !important;
|
|
64
|
+
background-image: none !important;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* ---- Tap highlight removal (mobile) ---- */
|
|
68
|
+
.no-tap-highlight {
|
|
69
|
+
-webkit-tap-highlight-color: transparent;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* ============================================== */
|
|
74
|
+
/* Chip-style radio items (shared @ekonavi/forms) */
|
|
75
|
+
/* ============================================== */
|
|
76
|
+
|
|
77
|
+
/* RadioGroup with icons uses grid layout */
|
|
78
|
+
.radio-group-with-icons {
|
|
79
|
+
@apply grid grid-cols-2 gap-2;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Base chip style for radio items with icons */
|
|
83
|
+
.radio-chip {
|
|
84
|
+
@apply bg-white/50 rounded-2xl cursor-pointer border-2 border-transparent transition-all relative;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Selected chip style */
|
|
88
|
+
.radio-chip-selected {
|
|
89
|
+
@apply border-2 border-foreground bg-white;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Hide the flex container wrapping to make chip fully clickable */
|
|
93
|
+
.radio-chip > div.flex {
|
|
94
|
+
@apply contents;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Make label fill entire chip for full clickability */
|
|
98
|
+
.radio-chip label {
|
|
99
|
+
@apply flex items-center w-full px-3 py-2 cursor-pointer min-h-[2.5rem];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Two-column layout: icon fixed width, text fills remaining space */
|
|
103
|
+
.radio-chip label > div {
|
|
104
|
+
@apply flex items-center gap-2 w-full;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.radio-option-icon {
|
|
108
|
+
@apply flex-shrink-0 text-lg;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.radio-option-label {
|
|
112
|
+
@apply flex-1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Fallback: :has() selectors for older class structure */
|
|
116
|
+
[role="radiogroup"]:has(.radio-option-icon) {
|
|
117
|
+
@apply grid grid-cols-2 gap-2;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.radio-item-container:has(.radio-option-icon) {
|
|
121
|
+
@apply bg-white/50 rounded-2xl cursor-pointer border-2 border-transparent transition-all relative;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.radio-item-container:has(.radio-option-icon):has(button[data-state="checked"]) {
|
|
125
|
+
@apply border-2 border-foreground bg-white;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.radio-item-container:has(.radio-option-icon) button[role="radio"] {
|
|
129
|
+
@apply hidden;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.radio-item-container:has(.radio-option-icon) > div.flex {
|
|
133
|
+
@apply contents;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.radio-item-container:has(.radio-option-icon) label {
|
|
137
|
+
@apply flex items-center w-full px-3 py-2 cursor-pointer min-h-[2.5rem];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.radio-item-container:has(.radio-option-icon) label > div {
|
|
141
|
+
@apply flex items-center gap-2 w-full;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* ============================================== */
|
|
145
|
+
/* Product grid layout (marketplace/faz) */
|
|
146
|
+
/* ============================================== */
|
|
147
|
+
|
|
148
|
+
.product-grid {
|
|
149
|
+
display: grid;
|
|
150
|
+
grid-template-columns: 1fr;
|
|
151
|
+
gap: 1.5rem;
|
|
152
|
+
grid-template-areas:
|
|
153
|
+
"images"
|
|
154
|
+
"details"
|
|
155
|
+
"specifications"
|
|
156
|
+
"actions"
|
|
157
|
+
"project-info"
|
|
158
|
+
"tags"
|
|
159
|
+
"delivery";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@media (min-width: 800px) {
|
|
163
|
+
.product-grid {
|
|
164
|
+
grid-template-columns: 1fr 1fr;
|
|
165
|
+
grid-template-rows: auto auto auto auto auto auto;
|
|
166
|
+
gap: 3rem;
|
|
167
|
+
grid-template-areas:
|
|
168
|
+
"images details"
|
|
169
|
+
"images specifications"
|
|
170
|
+
"project-info actions"
|
|
171
|
+
"project-info tags"
|
|
172
|
+
". delivery";
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.grid-images { grid-area: images; }
|
|
177
|
+
.grid-details { grid-area: details; }
|
|
178
|
+
.grid-specifications { grid-area: specifications; }
|
|
179
|
+
.grid-actions { grid-area: actions; }
|
|
180
|
+
.grid-project-info { grid-area: project-info; }
|
|
181
|
+
.grid-tags { grid-area: tags; }
|
|
182
|
+
.grid-delivery { grid-area: delivery; }
|
|
183
|
+
.grid-other-products { grid-area: other-products; }
|
|
184
|
+
|
|
185
|
+
/* ============================================== */
|
|
186
|
+
/* WalletConnect modal override */
|
|
187
|
+
/* ============================================== */
|
|
188
|
+
|
|
189
|
+
.wcm-overlay {
|
|
190
|
+
z-index: var(--layer-toast) !important;
|
|
191
|
+
background-color: #3c6344 !important;
|
|
192
|
+
}
|