@evolution-james/evolution-theme-engine 1.0.0 → 1.1.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.
package/README.md CHANGED
@@ -74,6 +74,8 @@ function MyHeader() {
74
74
 
75
75
  Use this when you want a complete, ready-made navbar with the theme selector pre-rendered inside it.
76
76
 
77
+ **Multi-page app** (standard `<a>` tags, full navigation):
78
+
77
79
  ```jsx
78
80
  import { ThemeNavBar } from '@evolution-james/evolution-theme-engine';
79
81
 
@@ -82,6 +84,7 @@ function App() {
82
84
  <>
83
85
  <ThemeNavBar
84
86
  title="My App"
87
+ titleHref="/"
85
88
  links={[
86
89
  { label: 'Home', href: '/' },
87
90
  { label: 'About', href: '/about' },
@@ -94,6 +97,33 @@ function App() {
94
97
  }
95
98
  ```
96
99
 
100
+ **Single-page app with React Router** (no page refreshes):
101
+
102
+ ```jsx
103
+ import { Link } from 'react-router-dom';
104
+ import { ThemeNavBar } from '@evolution-james/evolution-theme-engine';
105
+
106
+ function App() {
107
+ return (
108
+ <>
109
+ <ThemeNavBar
110
+ title="My App"
111
+ titleHref="/"
112
+ links={[
113
+ { label: 'Home', href: '/' },
114
+ { label: 'About', href: '/about' },
115
+ { label: 'Contact', href: '/contact' },
116
+ ]}
117
+ renderLink={(props) => (
118
+ <Link to={props.href} className={props.className}>{props.children}</Link>
119
+ )}
120
+ />
121
+ {/* rest of your app */}
122
+ </>
123
+ );
124
+ }
125
+ ```
126
+
97
127
  `ThemeNavBar` is intentionally barebones — it applies `var(--color-*)` variables for all colors, which means it automatically adapts to whichever theme is active.
98
128
 
99
129
  ---
@@ -142,6 +172,12 @@ From there, use the CSS variables anywhere in your own component styles:
142
172
  background-color: var(--color-card-bg);
143
173
  color: var(--color-text);
144
174
  border: 1px solid var(--color-card-border);
175
+ box-shadow: 0 2px 8px var(--color-shadow);
176
+ }
177
+
178
+ .my-card-subtitle {
179
+ color: var(--color-text-muted);
180
+ font-size: 0.875rem;
145
181
  }
146
182
 
147
183
  .my-button {
@@ -153,6 +189,12 @@ From there, use the CSS variables anywhere in your own component styles:
153
189
  color: var(--color-link);
154
190
  }
155
191
 
192
+ .my-input {
193
+ background-color: var(--color-input-bg);
194
+ border: 1px solid var(--color-input-border);
195
+ color: var(--color-text);
196
+ }
197
+
156
198
  hr {
157
199
  border-color: var(--color-divider);
158
200
  }
@@ -168,6 +210,7 @@ Because the variables are set on `<html>`, they cascade down to every element on
168
210
  |---|---|
169
211
  | `--color-bg` | Page / app background |
170
212
  | `--color-text` | Primary body text |
213
+ | `--color-text-muted` | Secondary / subtitle / caption text |
171
214
  | `--color-card-bg` | Card / panel surface background |
172
215
  | `--color-card-border` | Card / panel border color |
173
216
  | `--color-btn-dark-bg` | Background for "dark" style buttons |
@@ -175,6 +218,9 @@ Because the variables are set on `<html>`, they cascade down to every element on
175
218
  | `--color-btn-light-bg` | Background for "light" style buttons |
176
219
  | `--color-btn-light-text` | Text on "light" style buttons |
177
220
  | `--color-divider` | Horizontal rules / separators |
221
+ | `--color-input-bg` | Form input / textarea background |
222
+ | `--color-input-border` | Form input / textarea border |
223
+ | `--color-shadow` | Box shadow color |
178
224
  | `--color-primary` | Primary accent / brand color |
179
225
  | `--color-on-primary` | Text rendered on top of `--color-primary` |
180
226
  | `--color-link` | Hyperlink color |
@@ -318,7 +364,9 @@ registerTheme('ocean', {
318
364
  | Prop | Type | Default | Description |
319
365
  |---|---|---|---|
320
366
  | `title` | `string` | `'My App'` | Brand text shown on the left of the navbar. |
321
- | `links` | `Array<{ label, href }>` | Placeholder links | Navigation links rendered in the center. |
367
+ | `titleHref` | `string` | `undefined` | If provided, the brand text becomes a link pointing to this URL. Omit to render a plain `<span>`. |
368
+ | `links` | `Array<{ label, href, onClick? }>` | Placeholder links | Navigation links rendered in the center. If an entry includes `onClick`, the default browser navigation is prevented and `onClick` is called instead — use this for SPA navigation (e.g. React Router's `navigate()`). |
369
+ | `renderLink` | `(props) => ReactNode` | `undefined` | Render prop for full control over link rendering. `props` contains `href`, `children`, and `className`. Applied to both the title link and all nav links. Use this for React Router: return `<Link to={props.href} className={props.className}>{props.children}</Link>`. Takes precedence over individual `onClick` handlers. |
322
370
  | `themes` | `object` | All 5 built-in themes | Forwarded to the internal `<ThemeSelector>`. |
323
371
  | `className` | `string` | `''` | Extra CSS classes added to the `<nav>` (alongside `etn-navbar`). |
324
372
  | `style` | `object` | `{}` | Inline styles for the `<nav>`. |
@@ -28,11 +28,24 @@ var _jsxRuntime = require("react/jsx-runtime");
28
28
  * title (string) — Brand/title text shown on the
29
29
  * left side of the navbar.
30
30
  * Defaults to 'My App'.
31
+ * titleHref (string) — If provided, wraps the brand
32
+ * text in a link pointing to this
33
+ * URL. Omit to render a plain <span>.
31
34
  * links (Array<object>) — Navigation links rendered to
32
35
  * the right of the title. Each
33
- * entry: { label, href }.
34
- * Defaults to a few placeholder
35
- * links.
36
+ * entry: { label, href, onClick? }.
37
+ * If onClick is provided, the default
38
+ * browser navigation is prevented and
39
+ * onClick is called instead — use this
40
+ * for programmatic SPA navigation.
41
+ * Defaults to a few placeholder links.
42
+ * renderLink (function) — Optional render prop for full
43
+ * control over link rendering. Useful
44
+ * for React Router: pass a function
45
+ * ({ href, children, className }) =>
46
+ * ReactNode and return a <Link>
47
+ * component. Applied to both the
48
+ * title link and all nav links.
36
49
  * themes (object) — Forwarded to <ThemeSelector>.
37
50
  * Defaults to all 5 built-in themes.
38
51
  * className (string) — Extra class(es) added to the
@@ -40,15 +53,29 @@ var _jsxRuntime = require("react/jsx-runtime");
40
53
  * 'etn-navbar'.
41
54
  * style (object) — Inline styles for the root <nav>.
42
55
  *
43
- * Usage:
44
- * import { ThemeNavBar } from 'evolution-theme-engine';
56
+ * Usage — plain HTML (multi-page app):
57
+ * <ThemeNavBar
58
+ * title="My Cool App"
59
+ * titleHref="/"
60
+ * links={[
61
+ * { label: 'Home', href: '/' },
62
+ * { label: 'About', href: '/about' },
63
+ * ]}
64
+ * />
65
+ *
66
+ * Usage — React Router (SPA, no page refreshes):
67
+ * import { Link } from 'react-router-dom';
45
68
  *
46
69
  * <ThemeNavBar
47
70
  * title="My Cool App"
71
+ * titleHref="/"
48
72
  * links={[
49
73
  * { label: 'Home', href: '/' },
50
74
  * { label: 'About', href: '/about' },
51
75
  * ]}
76
+ * renderLink={(props) => (
77
+ * <Link to={props.href} className={props.className}>{props.children}</Link>
78
+ * )}
52
79
  * />
53
80
  * ============================================================
54
81
  */
@@ -66,28 +93,47 @@ var DEFAULT_LINKS = [{
66
93
  function ThemeNavBar(_ref) {
67
94
  var _ref$title = _ref.title,
68
95
  title = _ref$title === void 0 ? 'My App' : _ref$title,
96
+ titleHref = _ref.titleHref,
69
97
  _ref$links = _ref.links,
70
98
  links = _ref$links === void 0 ? DEFAULT_LINKS : _ref$links,
71
99
  themes = _ref.themes,
72
100
  _ref$className = _ref.className,
73
101
  className = _ref$className === void 0 ? '' : _ref$className,
74
102
  _ref$style = _ref.style,
75
- style = _ref$style === void 0 ? {} : _ref$style;
103
+ style = _ref$style === void 0 ? {} : _ref$style,
104
+ renderLink = _ref.renderLink;
76
105
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("nav", {
77
106
  className: "etn-navbar".concat(className ? " ".concat(className) : ''),
78
107
  style: style,
79
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
108
+ children: [titleHref ? renderLink ? renderLink({
109
+ href: titleHref,
110
+ children: title,
111
+ className: 'etn-navbar-brand'
112
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
113
+ href: titleHref,
114
+ className: "etn-navbar-brand",
115
+ children: title
116
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
80
117
  className: "etn-navbar-brand",
81
118
  children: title
82
119
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
83
120
  className: "etn-navbar-links",
84
121
  children: links.map(function (_ref2) {
85
122
  var label = _ref2.label,
86
- href = _ref2.href;
123
+ href = _ref2.href,
124
+ onClick = _ref2.onClick;
87
125
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
88
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
126
+ children: renderLink ? renderLink({
127
+ href: href,
128
+ children: label,
129
+ className: 'etn-navbar-link'
130
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
89
131
  href: href,
90
132
  className: "etn-navbar-link",
133
+ onClick: onClick ? function (e) {
134
+ e.preventDefault();
135
+ onClick(e);
136
+ } : undefined,
91
137
  children: label
92
138
  })
93
139
  }, label);
@@ -29,19 +29,23 @@
29
29
  * ──────────────────────
30
30
  * --color-bg Page / app background
31
31
  * --color-text Primary body text
32
+ * --color-text-muted Secondary / subtitle / caption text
32
33
  * --color-card-bg Card / panel surface background
33
- * --color-card-border Card / panel border colour
34
+ * --color-card-border Card / panel border color
34
35
  * --color-btn-dark-bg Background for "dark" style buttons
35
36
  * --color-btn-dark-text Text on "dark" style buttons
36
37
  * --color-btn-light-bg Background for "light" style buttons
37
38
  * --color-btn-light-text Text on "light" style buttons
38
39
  * --color-divider Horizontal rules / separators
39
- * --color-primary Primary accent / brand colour
40
+ * --color-input-bg Form input / textarea background
41
+ * --color-input-border Form input / textarea border
42
+ * --color-shadow Box shadow color
43
+ * --color-primary Primary accent / brand color
40
44
  * --color-on-primary Text drawn on top of --color-primary
41
- * --color-link Hyperlink colour
45
+ * --color-link Hyperlink color
42
46
  * --color-hover-bg Subtle hover-state background tint
43
47
  * --color-code-bg Code block background
44
- * --color-code-text Code block text colour
48
+ * --color-code-text Code block text color
45
49
  *
46
50
  * ADDING A CUSTOM THEME (CSS approach)
47
51
  * ─────────────────────────────────────
@@ -73,6 +77,7 @@
73
77
  :root {
74
78
  --color-bg: #f8f9fa;
75
79
  --color-text: #212529;
80
+ --color-text-muted: #6c757d;
76
81
  --color-card-bg: #ffffff;
77
82
  --color-card-border: #dee2e6;
78
83
  --color-btn-dark-bg: #f8f9fa;
@@ -80,10 +85,13 @@
80
85
  --color-btn-light-bg: #ffffff;
81
86
  --color-btn-light-text: #212529;
82
87
  --color-divider: #dee2e6;
88
+ --color-input-bg: #ffffff;
89
+ --color-input-border: #ced4da;
90
+ --color-shadow: rgba(0, 0, 0, 0.10);
83
91
 
84
92
  --color-primary: #1976d2;
85
93
  --color-on-primary: #ffffff;
86
- --color-link: #a435f0;
94
+ --color-link: #4a90e2;
87
95
  --color-hover-bg: rgba(25, 118, 210, 0.08);
88
96
  --color-code-bg: #282c34;
89
97
  --color-code-text: #ffffff;
@@ -93,6 +101,7 @@
93
101
  [data-theme="dark"] {
94
102
  --color-bg: #212529;
95
103
  --color-text: #f8f9fa;
104
+ --color-text-muted: #9ca3af;
96
105
  --color-card-bg: #343a40;
97
106
  --color-card-border: #444444;
98
107
  --color-btn-dark-bg: #f8f9fa;
@@ -100,6 +109,9 @@
100
109
  --color-btn-light-bg: #343a40;
101
110
  --color-btn-light-text: #f8f9fa;
102
111
  --color-divider: #444444;
112
+ --color-input-bg: #2d3238;
113
+ --color-input-border: #555555;
114
+ --color-shadow: rgba(0, 0, 0, 0.40);
103
115
 
104
116
  --color-primary: #90caf9;
105
117
  --color-on-primary: #212529;
@@ -116,6 +128,7 @@
116
128
  [data-theme="forest"] {
117
129
  --color-bg: #1b2e22;
118
130
  --color-text: #cde8d4;
131
+ --color-text-muted: #8aad95;
119
132
  --color-card-bg: #243c2b;
120
133
  --color-card-border: #3a5c44;
121
134
  --color-btn-dark-bg: #3a5c44;
@@ -123,6 +136,9 @@
123
136
  --color-btn-light-bg: #243c2b;
124
137
  --color-btn-light-text: #cde8d4;
125
138
  --color-divider: #3a5c44;
139
+ --color-input-bg: #1f3526;
140
+ --color-input-border: #3a5c44;
141
+ --color-shadow: rgba(0, 0, 0, 0.35);
126
142
 
127
143
  --color-primary: #4caf70;
128
144
  --color-on-primary: #1b2e22;
@@ -139,6 +155,7 @@
139
155
  [data-theme="tron"] {
140
156
  --color-bg: #0f172a;
141
157
  --color-text: #67e8f9;
158
+ --color-text-muted: #38bcd4;
142
159
  --color-card-bg: #1e293b;
143
160
  --color-card-border: #67e8f9;
144
161
  --color-btn-dark-bg: #0ea5e9;
@@ -146,6 +163,9 @@
146
163
  --color-btn-light-bg: #1e293b;
147
164
  --color-btn-light-text: #67e8f9;
148
165
  --color-divider: #0ea5e9;
166
+ --color-input-bg: #162236;
167
+ --color-input-border: #38bcd4;
168
+ --color-shadow: rgba(14, 165, 233, 0.15);
149
169
 
150
170
  --color-primary: #0ea5e9;
151
171
  --color-on-primary: #0f172a;
@@ -158,11 +178,12 @@
158
178
  /* --- Midnight Theme ---
159
179
  * A deep night-sky palette: near-black background, muted
160
180
  * blue-grey text, teal (#5ce1b5) primary accent, and
161
- * light-blue (#8bd4ff) link colour.
181
+ * light-blue (#8bd4ff) link color.
162
182
  */
163
183
  [data-theme="midnight"] {
164
184
  --color-bg: #0b1016;
165
185
  --color-text: #e7edf2;
186
+ --color-text-muted: #8fa9be;
166
187
  --color-card-bg: #131c28;
167
188
  --color-card-border: #263141;
168
189
  --color-btn-dark-bg: #263141;
@@ -170,6 +191,9 @@
170
191
  --color-btn-light-bg: #0f151e;
171
192
  --color-btn-light-text: #e7edf2;
172
193
  --color-divider: #263141;
194
+ --color-input-bg: #0f1a26;
195
+ --color-input-border: #2a3e52;
196
+ --color-shadow: rgba(0, 0, 0, 0.45);
173
197
 
174
198
  --color-primary: #5ce1b5;
175
199
  --color-on-primary: #0b1016;
@@ -219,6 +243,7 @@ html {
219
243
  font-size: 1.1rem;
220
244
  font-weight: 700;
221
245
  color: var(--color-text);
246
+ text-decoration: none;
222
247
  white-space: nowrap;
223
248
  flex-shrink: 0;
224
249
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolution-james/evolution-theme-engine",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A plug-and-play React theme engine with CSS variable-based theming, localStorage persistence, and optional navbar component.",
5
5
  "keywords": [
6
6
  "react",
@@ -19,11 +19,24 @@
19
19
  * title (string) — Brand/title text shown on the
20
20
  * left side of the navbar.
21
21
  * Defaults to 'My App'.
22
+ * titleHref (string) — If provided, wraps the brand
23
+ * text in a link pointing to this
24
+ * URL. Omit to render a plain <span>.
22
25
  * links (Array<object>) — Navigation links rendered to
23
26
  * the right of the title. Each
24
- * entry: { label, href }.
25
- * Defaults to a few placeholder
26
- * links.
27
+ * entry: { label, href, onClick? }.
28
+ * If onClick is provided, the default
29
+ * browser navigation is prevented and
30
+ * onClick is called instead — use this
31
+ * for programmatic SPA navigation.
32
+ * Defaults to a few placeholder links.
33
+ * renderLink (function) — Optional render prop for full
34
+ * control over link rendering. Useful
35
+ * for React Router: pass a function
36
+ * ({ href, children, className }) =>
37
+ * ReactNode and return a <Link>
38
+ * component. Applied to both the
39
+ * title link and all nav links.
27
40
  * themes (object) — Forwarded to <ThemeSelector>.
28
41
  * Defaults to all 5 built-in themes.
29
42
  * className (string) — Extra class(es) added to the
@@ -31,15 +44,29 @@
31
44
  * 'etn-navbar'.
32
45
  * style (object) — Inline styles for the root <nav>.
33
46
  *
34
- * Usage:
35
- * import { ThemeNavBar } from 'evolution-theme-engine';
47
+ * Usage — plain HTML (multi-page app):
48
+ * <ThemeNavBar
49
+ * title="My Cool App"
50
+ * titleHref="/"
51
+ * links={[
52
+ * { label: 'Home', href: '/' },
53
+ * { label: 'About', href: '/about' },
54
+ * ]}
55
+ * />
56
+ *
57
+ * Usage — React Router (SPA, no page refreshes):
58
+ * import { Link } from 'react-router-dom';
36
59
  *
37
60
  * <ThemeNavBar
38
61
  * title="My Cool App"
62
+ * titleHref="/"
39
63
  * links={[
40
64
  * { label: 'Home', href: '/' },
41
65
  * { label: 'About', href: '/about' },
42
66
  * ]}
67
+ * renderLink={(props) => (
68
+ * <Link to={props.href} className={props.className}>{props.children}</Link>
69
+ * )}
43
70
  * />
44
71
  * ============================================================
45
72
  */
@@ -55,26 +82,44 @@ const DEFAULT_LINKS = [
55
82
 
56
83
  export function ThemeNavBar({
57
84
  title = 'My App',
85
+ titleHref,
58
86
  links = DEFAULT_LINKS,
59
87
  themes,
60
88
  className = '',
61
89
  style = {},
90
+ renderLink,
62
91
  }) {
63
92
  return (
64
93
  <nav
65
94
  className={`etn-navbar${className ? ` ${className}` : ''}`}
66
95
  style={style}
67
96
  >
68
- {/* Left side: brand/title */}
69
- <span className="etn-navbar-brand">{title}</span>
97
+ {/* Left side: brand/title — link if titleHref is set, plain span otherwise */}
98
+ {titleHref ? (
99
+ renderLink ? (
100
+ renderLink({ href: titleHref, children: title, className: 'etn-navbar-brand' })
101
+ ) : (
102
+ <a href={titleHref} className="etn-navbar-brand">{title}</a>
103
+ )
104
+ ) : (
105
+ <span className="etn-navbar-brand">{title}</span>
106
+ )}
70
107
 
71
108
  {/* Center: navigation links */}
72
109
  <ul className="etn-navbar-links">
73
- {links.map(({ label, href }) => (
110
+ {links.map(({ label, href, onClick }) => (
74
111
  <li key={label}>
75
- <a href={href} className="etn-navbar-link">
76
- {label}
77
- </a>
112
+ {renderLink ? (
113
+ renderLink({ href, children: label, className: 'etn-navbar-link' })
114
+ ) : (
115
+ <a
116
+ href={href}
117
+ className="etn-navbar-link"
118
+ onClick={onClick ? (e) => { e.preventDefault(); onClick(e); } : undefined}
119
+ >
120
+ {label}
121
+ </a>
122
+ )}
78
123
  </li>
79
124
  ))}
80
125
  </ul>
@@ -29,19 +29,23 @@
29
29
  * ──────────────────────
30
30
  * --color-bg Page / app background
31
31
  * --color-text Primary body text
32
+ * --color-text-muted Secondary / subtitle / caption text
32
33
  * --color-card-bg Card / panel surface background
33
- * --color-card-border Card / panel border colour
34
+ * --color-card-border Card / panel border color
34
35
  * --color-btn-dark-bg Background for "dark" style buttons
35
36
  * --color-btn-dark-text Text on "dark" style buttons
36
37
  * --color-btn-light-bg Background for "light" style buttons
37
38
  * --color-btn-light-text Text on "light" style buttons
38
39
  * --color-divider Horizontal rules / separators
39
- * --color-primary Primary accent / brand colour
40
+ * --color-input-bg Form input / textarea background
41
+ * --color-input-border Form input / textarea border
42
+ * --color-shadow Box shadow color
43
+ * --color-primary Primary accent / brand color
40
44
  * --color-on-primary Text drawn on top of --color-primary
41
- * --color-link Hyperlink colour
45
+ * --color-link Hyperlink color
42
46
  * --color-hover-bg Subtle hover-state background tint
43
47
  * --color-code-bg Code block background
44
- * --color-code-text Code block text colour
48
+ * --color-code-text Code block text color
45
49
  *
46
50
  * ADDING A CUSTOM THEME (CSS approach)
47
51
  * ─────────────────────────────────────
@@ -73,6 +77,7 @@
73
77
  :root {
74
78
  --color-bg: #f8f9fa;
75
79
  --color-text: #212529;
80
+ --color-text-muted: #6c757d;
76
81
  --color-card-bg: #ffffff;
77
82
  --color-card-border: #dee2e6;
78
83
  --color-btn-dark-bg: #f8f9fa;
@@ -80,10 +85,13 @@
80
85
  --color-btn-light-bg: #ffffff;
81
86
  --color-btn-light-text: #212529;
82
87
  --color-divider: #dee2e6;
88
+ --color-input-bg: #ffffff;
89
+ --color-input-border: #ced4da;
90
+ --color-shadow: rgba(0, 0, 0, 0.10);
83
91
 
84
92
  --color-primary: #1976d2;
85
93
  --color-on-primary: #ffffff;
86
- --color-link: #a435f0;
94
+ --color-link: #4a90e2;
87
95
  --color-hover-bg: rgba(25, 118, 210, 0.08);
88
96
  --color-code-bg: #282c34;
89
97
  --color-code-text: #ffffff;
@@ -93,6 +101,7 @@
93
101
  [data-theme="dark"] {
94
102
  --color-bg: #212529;
95
103
  --color-text: #f8f9fa;
104
+ --color-text-muted: #9ca3af;
96
105
  --color-card-bg: #343a40;
97
106
  --color-card-border: #444444;
98
107
  --color-btn-dark-bg: #f8f9fa;
@@ -100,6 +109,9 @@
100
109
  --color-btn-light-bg: #343a40;
101
110
  --color-btn-light-text: #f8f9fa;
102
111
  --color-divider: #444444;
112
+ --color-input-bg: #2d3238;
113
+ --color-input-border: #555555;
114
+ --color-shadow: rgba(0, 0, 0, 0.40);
103
115
 
104
116
  --color-primary: #90caf9;
105
117
  --color-on-primary: #212529;
@@ -116,6 +128,7 @@
116
128
  [data-theme="forest"] {
117
129
  --color-bg: #1b2e22;
118
130
  --color-text: #cde8d4;
131
+ --color-text-muted: #8aad95;
119
132
  --color-card-bg: #243c2b;
120
133
  --color-card-border: #3a5c44;
121
134
  --color-btn-dark-bg: #3a5c44;
@@ -123,6 +136,9 @@
123
136
  --color-btn-light-bg: #243c2b;
124
137
  --color-btn-light-text: #cde8d4;
125
138
  --color-divider: #3a5c44;
139
+ --color-input-bg: #1f3526;
140
+ --color-input-border: #3a5c44;
141
+ --color-shadow: rgba(0, 0, 0, 0.35);
126
142
 
127
143
  --color-primary: #4caf70;
128
144
  --color-on-primary: #1b2e22;
@@ -139,6 +155,7 @@
139
155
  [data-theme="tron"] {
140
156
  --color-bg: #0f172a;
141
157
  --color-text: #67e8f9;
158
+ --color-text-muted: #38bcd4;
142
159
  --color-card-bg: #1e293b;
143
160
  --color-card-border: #67e8f9;
144
161
  --color-btn-dark-bg: #0ea5e9;
@@ -146,6 +163,9 @@
146
163
  --color-btn-light-bg: #1e293b;
147
164
  --color-btn-light-text: #67e8f9;
148
165
  --color-divider: #0ea5e9;
166
+ --color-input-bg: #162236;
167
+ --color-input-border: #38bcd4;
168
+ --color-shadow: rgba(14, 165, 233, 0.15);
149
169
 
150
170
  --color-primary: #0ea5e9;
151
171
  --color-on-primary: #0f172a;
@@ -158,11 +178,12 @@
158
178
  /* --- Midnight Theme ---
159
179
  * A deep night-sky palette: near-black background, muted
160
180
  * blue-grey text, teal (#5ce1b5) primary accent, and
161
- * light-blue (#8bd4ff) link colour.
181
+ * light-blue (#8bd4ff) link color.
162
182
  */
163
183
  [data-theme="midnight"] {
164
184
  --color-bg: #0b1016;
165
185
  --color-text: #e7edf2;
186
+ --color-text-muted: #8fa9be;
166
187
  --color-card-bg: #131c28;
167
188
  --color-card-border: #263141;
168
189
  --color-btn-dark-bg: #263141;
@@ -170,6 +191,9 @@
170
191
  --color-btn-light-bg: #0f151e;
171
192
  --color-btn-light-text: #e7edf2;
172
193
  --color-divider: #263141;
194
+ --color-input-bg: #0f1a26;
195
+ --color-input-border: #2a3e52;
196
+ --color-shadow: rgba(0, 0, 0, 0.45);
173
197
 
174
198
  --color-primary: #5ce1b5;
175
199
  --color-on-primary: #0b1016;
@@ -219,6 +243,7 @@ html {
219
243
  font-size: 1.1rem;
220
244
  font-weight: 700;
221
245
  color: var(--color-text);
246
+ text-decoration: none;
222
247
  white-space: nowrap;
223
248
  flex-shrink: 0;
224
249
  }