@yottagraph-app/aether-instructions 1.1.24 → 1.1.25
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/commands/update_branding.md +35 -87
- package/package.json +1 -1
- package/rules/branding.mdc +19 -27
- package/rules/design.mdc +2 -1
- package/skills/lovelace-branding/BRANDING.md +176 -0
- package/skills/lovelace-branding/SKILL.md +25 -0
- package/skills/lovelace-branding/assets/LL-logo-full-white-green.svg +35 -0
- package/skills/lovelace-branding/assets/LL-logo-full-wht.svg +39 -0
- package/skills/lovelace-branding/assets/LL-mark-green.svg +21 -0
- package/skills/lovelace-branding/assets/entity-styles.json +42 -0
- package/skills/lovelace-branding/assets/help-circle.svg +4 -0
- package/skills/lovelace-branding/fonts.md +147 -0
- package/skills/lovelace-branding/overview.md +136 -0
- package/skills/lovelace-branding/patterns.md +263 -0
|
@@ -1,123 +1,71 @@
|
|
|
1
1
|
# Update Branding
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Sync the project's branding implementation with the latest Lovelace branding skill guidelines.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
**Do not hardcode any local paths.** Always ask the user for the Lovelace repo location.
|
|
7
|
+
The `lovelace-branding` skill (`skills/lovelace-branding/`) is the single source of truth for Lovelace brand identity. This command reviews the project's branding implementation files and updates them to align with the skill.
|
|
10
8
|
|
|
11
9
|
---
|
|
12
10
|
|
|
13
|
-
## Step 1:
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
AskQuestion({
|
|
17
|
-
title: "Lovelace Repository Path",
|
|
18
|
-
questions: [
|
|
19
|
-
{
|
|
20
|
-
id: "repo-path",
|
|
21
|
-
prompt: "Where is your local clone of the Lovelace repository?",
|
|
22
|
-
options: [
|
|
23
|
-
{ id: "home-lovelace", label: "~/lovelace" },
|
|
24
|
-
{ id: "custom", label: "Other location (I'll specify)" }
|
|
25
|
-
]
|
|
26
|
-
}
|
|
27
|
-
]
|
|
28
|
-
})
|
|
29
|
-
```
|
|
11
|
+
## Step 1: Read the Branding Skill
|
|
30
12
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Expand `~` to the user's home directory. Store the result as `{repo}`.
|
|
13
|
+
Read the skill starting from `skills/lovelace-branding/SKILL.md`. It contains a file index that will direct you to the relevant reference files.
|
|
34
14
|
|
|
35
15
|
---
|
|
36
16
|
|
|
37
|
-
## Step 2:
|
|
38
|
-
|
|
39
|
-
Confirm the branding source directory exists:
|
|
17
|
+
## Step 2: Review Implementation Files
|
|
40
18
|
|
|
41
|
-
|
|
42
|
-
ls {repo}/moongoose/ui/news-ui/BRANDING.md
|
|
43
|
-
```
|
|
19
|
+
Read each of the project's branding implementation files and compare against the skill guidelines:
|
|
44
20
|
|
|
45
|
-
|
|
21
|
+
| File | What to check |
|
|
22
|
+
| --------------------------------- | --------------------------------------------------------------------------------- |
|
|
23
|
+
| `assets/brand-globals.css` | `:root` CSS variables match the skill's color and typography values |
|
|
24
|
+
| `assets/fonts.css` | `@font-face` declarations match the skill's font setup |
|
|
25
|
+
| `assets/theme-styles.css` | Theme utility classes align with the skill's CSS patterns |
|
|
26
|
+
| `composables/useLovelaceTheme.ts` | `themeColors` object matches the skill's color palette |
|
|
27
|
+
| `composables/useThemeClasses.ts` | Theme-aware utilities consistent with skill patterns |
|
|
28
|
+
| `nuxt.config.ts` | Vuetify theme colors match the skill; CSS array includes all branding stylesheets |
|
|
46
29
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
ls {repo}/moongoose/ui/news-ui/composables/useNewsTheme.ts
|
|
51
|
-
ls {repo}/moongoose/ui/news-ui/composables/useThemeClasses.ts
|
|
52
|
-
ls {repo}/moongoose/ui/news-ui/assets/theme-styles.css
|
|
53
|
-
ls {repo}/moongoose/ui/news-ui/assets/fonts.css
|
|
54
|
-
ls {repo}/moongoose/ui/news-ui/public/fonts/README.md
|
|
55
|
-
ls {repo}/moongoose/ui/news-ui/public/LL-logo-full-wht.svg
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Report any missing files. If critical files are missing (BRANDING.md, useNewsTheme.ts, theme-styles.css), stop. If optional files are missing (logo, fonts README), warn but continue.
|
|
30
|
+
For each file, note any discrepancies between the current implementation and the skill guidelines.
|
|
59
31
|
|
|
60
32
|
---
|
|
61
33
|
|
|
62
|
-
## Step 3:
|
|
34
|
+
## Step 3: Update Implementation
|
|
63
35
|
|
|
64
|
-
|
|
36
|
+
For each discrepancy found in Step 2, update the project file to align with the skill:
|
|
65
37
|
|
|
66
|
-
|
|
38
|
+
- **CSS variables**: Update hex values, add missing variables, remove obsolete ones
|
|
39
|
+
- **Color palette**: Update `themeColors` in `useLovelaceTheme.ts` to match
|
|
40
|
+
- **Typography**: Update font families, weights, and fallbacks as specified by the skill
|
|
41
|
+
- **Patterns**: Update theme utility classes to match the skill's CSS patterns
|
|
42
|
+
- **Vuetify theme**: Update `lovelaceDark` theme colors in `nuxt.config.ts` if needed
|
|
67
43
|
|
|
68
|
-
|
|
69
|
-
| -------------------------------- | ------------------------------------- |
|
|
70
|
-
| `BRANDING.md` | `branding/BRANDING.md` |
|
|
71
|
-
| `composables/useNewsTheme.ts` | `composables/useNewsTheme.ts` |
|
|
72
|
-
| `composables/useThemeClasses.ts` | `composables/useThemeClasses.ts` |
|
|
73
|
-
| `assets/theme-styles.css` | `assets/theme-styles.css` |
|
|
74
|
-
| `assets/fonts.css` | `assets/fonts.css` |
|
|
75
|
-
| `public/fonts/README.md` | `public/fonts/README.md` |
|
|
76
|
-
| `public/LL-logo-full-wht.svg` | `public/LL-logo-full-wht.svg` |
|
|
44
|
+
If the skill introduces new concepts not yet implemented in the project (new CSS variable namespaces, new utility classes, new patterns), add them.
|
|
77
45
|
|
|
78
|
-
|
|
46
|
+
If the project has customizations that intentionally diverge from the skill (e.g., project-specific semantic colors), preserve them but note the divergence.
|
|
79
47
|
|
|
80
48
|
---
|
|
81
49
|
|
|
82
|
-
## Step 4:
|
|
83
|
-
|
|
84
|
-
After copying, read through each copied file and check for new references that weren't present before:
|
|
50
|
+
## Step 4: Check Assets
|
|
85
51
|
|
|
86
|
-
|
|
52
|
+
Compare logo and asset files in `public/` against the skill's `assets/` directory (`skills/lovelace-branding/assets/`).
|
|
87
53
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- `@import` statements referencing files not in `assets/`
|
|
91
|
-
|
|
92
|
-
3. **Documentation references**: Check `BRANDING.md` for references to new files (logos, assets, CSS files) that should be copied.
|
|
93
|
-
|
|
94
|
-
**If new dependencies are found:**
|
|
95
|
-
|
|
96
|
-
- Static assets (images, SVGs, fonts) -> copy to `public/` in the equivalent subdirectory
|
|
97
|
-
- CSS files -> copy to `assets/`
|
|
98
|
-
- TypeScript/JS files -> copy to `composables/` or the equivalent directory
|
|
99
|
-
- Report what was copied to the user
|
|
54
|
+
- Copy any new or updated SVGs/assets from the skill to `public/`
|
|
55
|
+
- If existing assets differ, update them to the skill's versions
|
|
100
56
|
|
|
101
57
|
---
|
|
102
58
|
|
|
103
|
-
## Step 5: Verify
|
|
104
|
-
|
|
105
|
-
Check that the adapter (`composables/useCustomTheme.ts`) is still compatible:
|
|
106
|
-
|
|
107
|
-
1. Read `composables/useNewsTheme.ts` and check what it exports.
|
|
108
|
-
2. Read `composables/useCustomTheme.ts` and confirm it re-exports the expected interface.
|
|
109
|
-
3. If `useNewsTheme.ts` has added new named exports that aren't re-exported by the adapter, tell the user:
|
|
110
|
-
|
|
111
|
-
> `useNewsTheme.ts` has new exports that aren't exposed through `useCustomTheme.ts`: [list them]. You may want to add these to the adapter if components need them.
|
|
112
|
-
|
|
113
|
-
4. Check that `nuxt.config.ts` still includes the three CSS files:
|
|
59
|
+
## Step 5: Verify
|
|
114
60
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
61
|
+
1. Confirm `nuxt.config.ts` CSS array still includes all branding stylesheets:
|
|
62
|
+
```typescript
|
|
63
|
+
css: ['~/assets/fonts.css', '~/assets/brand-globals.css', '~/assets/theme-styles.css'];
|
|
64
|
+
```
|
|
65
|
+
2. Run `npm run build` to verify no compilation errors
|
|
118
66
|
|
|
119
67
|
---
|
|
120
68
|
|
|
121
69
|
## Step 6: Commit
|
|
122
70
|
|
|
123
|
-
Follow the `git-support.mdc` workflow to commit the
|
|
71
|
+
Follow the `git-support.mdc` workflow to commit the changes.
|
package/package.json
CHANGED
package/rules/branding.mdc
CHANGED
|
@@ -3,41 +3,33 @@ description: Apply when working on visual styling, colors, typography, theming,
|
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Lovelace
|
|
6
|
+
# Lovelace Branding
|
|
7
7
|
|
|
8
|
-
The
|
|
8
|
+
The `lovelace-branding` skill (`skills/lovelace-branding/`) is the single source of truth for all brand specifics -- colors, typography, patterns, assets, and usage guidelines. Read the skill before making branding decisions. Start with `SKILL.md` for the file index.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Theme
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- **Core colors**: Jet Black `#0A0A0A`, Pure White `#FFFFFF`, Cyber Green `#3FEA00`, Sonic Silver `#757575`
|
|
14
|
-
- **Secondary colors**: Electric Blue `#003BFF`, Blaze Orange `#FF5C00`
|
|
15
|
-
- **Semantic**: Amber `#FF9F0A` (warnings), Red `#EF4444` (errors)
|
|
16
|
-
- **Fonts**: FK Grotesk (body), FK Grotesk Mono (headlines, buttons, code). Falls back to Inter / system-ui. See `public/fonts/README.md` for setup.
|
|
17
|
-
- **Icons**: Material Design Icons (mdi) via Vuetify
|
|
12
|
+
Single dark theme. No light mode, no theme switching.
|
|
18
13
|
|
|
19
|
-
##
|
|
14
|
+
## Implementation Files
|
|
20
15
|
|
|
21
|
-
These files are
|
|
16
|
+
These files are project-owned. Consult the branding skill for the values and patterns they should implement.
|
|
22
17
|
|
|
23
|
-
| File |
|
|
24
|
-
|
|
25
|
-
| `
|
|
26
|
-
| `composables/useNewsTheme.ts` | Theme colors and CSS variable application |
|
|
27
|
-
| `composables/useThemeClasses.ts` | Theme-aware class utilities |
|
|
28
|
-
| `assets/theme-styles.css` | Theme CSS classes |
|
|
18
|
+
| File | Role |
|
|
19
|
+
|------|------|
|
|
20
|
+
| `assets/brand-globals.css` | `:root` CSS variables and global typography/layout |
|
|
29
21
|
| `assets/fonts.css` | `@font-face` declarations |
|
|
30
|
-
| `assets/
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
22
|
+
| `assets/theme-styles.css` | Theme-aware CSS utility classes |
|
|
23
|
+
| `composables/useLovelaceTheme.ts` | Theme color palette and Vuetify theme activation |
|
|
24
|
+
| `composables/useThemeClasses.ts` | Theme-aware class combination utilities |
|
|
33
25
|
|
|
34
|
-
##
|
|
26
|
+
## Integration
|
|
35
27
|
|
|
36
|
-
|
|
28
|
+
- Use `useLovelaceTheme()` or `useThemeClasses()` in components for theme colors and class utilities.
|
|
29
|
+
- The `lovelaceDark` Vuetify theme is defined in `nuxt.config.ts` under `vuetify.vuetifyOptions.theme`. It provides brand colors to all Vuetify components automatically. Component defaults are set under `vuetify.vuetifyOptions.defaults`.
|
|
30
|
+
- CSS variables (`--lv-*`) and theme classes (`.theme-*`) are available globally via the stylesheets listed above.
|
|
31
|
+
- `useLovelaceTheme` calls `theme.change('lovelaceDark')` to activate the Vuetify theme. This must match the theme name in `nuxt.config.ts`.
|
|
37
32
|
|
|
38
|
-
##
|
|
33
|
+
## Updating
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
- CSS variables (`--lv-green`, `--lv-black`, etc.) and theme classes (`.theme-card`, `.theme-text-primary`, etc.) are available globally.
|
|
42
|
-
- `useNewsTheme` calls `theme.change('lovelaceDark')` to activate the Vuetify theme. This must match the theme name in `nuxt.config.ts`.
|
|
43
|
-
- If you need to change how the branding integrates with Aether, modify the adapter -- not the branding files.
|
|
35
|
+
Run `/update_branding` to sync these files with the latest branding skill guidelines. The command reads the skill, compares each implementation file against the guidelines, and updates as needed.
|
package/rules/design.mdc
CHANGED
|
@@ -20,7 +20,8 @@ When building from a project brief or user request, feel free to:
|
|
|
20
20
|
|
|
21
21
|
- **Replace** `pages/index.vue` with the app's real home page
|
|
22
22
|
- **Remove** any pages that don't fit the app
|
|
23
|
-
- **Restructure** the navigation
|
|
23
|
+
- **Restructure** the navigation and layout entirely
|
|
24
|
+
- **Check** the branding is up to date with the `lovelace-branding` skill, and update as needed
|
|
24
25
|
- **Keep** the infrastructure: `composables/`, `server/api/kv/`, `agents/`
|
|
25
26
|
|
|
26
27
|
Do NOT treat the existing UI as something to preserve. Build what the
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Lovelace Brand R2 Guidelines
|
|
2
|
+
|
|
3
|
+
This document defines the visual identity for all Lovelace UI products (News UI, Ada Demo, etc.). It is derived from the Brand R2 review and serves as the single source of truth for colors, typography, iconography, and usage patterns.
|
|
4
|
+
|
|
5
|
+
## Color Palettes
|
|
6
|
+
|
|
7
|
+
### Core Palette
|
|
8
|
+
|
|
9
|
+
Jet Black, Pure White, Sonic Silver, and Cyber Green are Lovelace's core brand colors.
|
|
10
|
+
|
|
11
|
+
| Name | Hex | Usage |
|
|
12
|
+
|--------------|-----------|--------------------------------|
|
|
13
|
+
| Jet Black | `#0A0A0A` | Primary backgrounds |
|
|
14
|
+
| Pure White | `#FFFFFF` | Primary text on dark surfaces |
|
|
15
|
+
| Sonic Silver | `#757575` | Muted text, secondary elements |
|
|
16
|
+
| Cyber Green | `#3FEA00` | Primary accent, CTAs, success |
|
|
17
|
+
|
|
18
|
+
The palette can be extended with neutral greyscale tones ranging from Pure White `#FFF` to True Black `#000`. We use Jet Black `#0A0A0A` as our primary black for most purposes.
|
|
19
|
+
|
|
20
|
+
### Secondary Colors
|
|
21
|
+
|
|
22
|
+
Electric Blue and Blaze Orange are secondary colors to extend the branding.
|
|
23
|
+
|
|
24
|
+
| Name | Hex | Usage |
|
|
25
|
+
|---------------|-----------|-------------------------------------|
|
|
26
|
+
| Electric Blue | `#003BFF` | Accent, links, finance/data |
|
|
27
|
+
| Blaze Orange | `#FF5C00` | Warnings, highlights, secondary CTA |
|
|
28
|
+
|
|
29
|
+
### Semantic Colors
|
|
30
|
+
|
|
31
|
+
| Name | Hex | Usage |
|
|
32
|
+
|--------|-----------|----------|
|
|
33
|
+
| Amber | `#FF9F0A` | Warnings |
|
|
34
|
+
| Red | `#EF4444` | Errors |
|
|
35
|
+
|
|
36
|
+
### Color Ramps
|
|
37
|
+
|
|
38
|
+
Each color has a ramp from 50 (lightest) to 950 (darkest). The `/500` value is the base brand color. Colors go lighter (lower numbers) or darker (higher numbers) depending on context.
|
|
39
|
+
|
|
40
|
+
**Neutrals:**
|
|
41
|
+
|
|
42
|
+
| 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
|
|
43
|
+
|---------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|
|
|
44
|
+
| #FFFFFF | #F8F8F8 | #E6E6E6 | #D5D5D6 | #B1B1B1 | #757575 | #6C6C6C | #464646 | #222222 | #0A0A0A | #000000 |
|
|
45
|
+
|
|
46
|
+
**Green:**
|
|
47
|
+
|
|
48
|
+
| 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
|
|
49
|
+
|---------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|
|
|
50
|
+
| #DDFFD1 | #BBFFA3 | #99FF75 | #78FF47 | #57FF19 | #3FEA00 | #30BC00 | #238E00 | #166100 | #0B3300 | #010500 |
|
|
51
|
+
|
|
52
|
+
**Blue:**
|
|
53
|
+
|
|
54
|
+
| 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
|
|
55
|
+
|---------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|
|
|
56
|
+
| #E6EBFF | #BBC7FF | #8AA3FF | #6C80FF | #2E5DFF | #003BFF | #0230D0 | #0326A1 | #031B73 | #021146 | #010819 |
|
|
57
|
+
|
|
58
|
+
**Orange:**
|
|
59
|
+
|
|
60
|
+
| 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
|
|
61
|
+
|---------|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|
|
|
62
|
+
| #FFF0E6 | #FFD4B8 | #FFB78A | #FF989C | #FF7B2E | #FF5C00 | #D04E02 | #A13F03 | #732F03 | #461E02 | #190801 |
|
|
63
|
+
|
|
64
|
+
### Usage Proportions
|
|
65
|
+
|
|
66
|
+
The proportional usage of each color to the whole (approximate):
|
|
67
|
+
- Jet Black + Pure White: ~70% of surface area (dark backgrounds, white text)
|
|
68
|
+
- Cyber Green: ~15% (accents, interactive elements, success states)
|
|
69
|
+
- Sonic Silver: ~10% (muted text, borders, secondary elements)
|
|
70
|
+
- Electric Blue + Blaze Orange: ~5% (sparingly, for specific semantic purposes)
|
|
71
|
+
|
|
72
|
+
### Accessibility
|
|
73
|
+
|
|
74
|
+
All color pairings must meet WCAG AA contrast ratio at a minimum. Use the color ramps to find appropriate pairings:
|
|
75
|
+
- White text on Jet Black: passes AAA
|
|
76
|
+
- Cyber Green on Jet Black: passes AA
|
|
77
|
+
- Electric Blue on Jet Black: passes AA
|
|
78
|
+
|
|
79
|
+
Reference: https://accessibleweb.com/color-contrast-checker/
|
|
80
|
+
|
|
81
|
+
## Typography
|
|
82
|
+
|
|
83
|
+
### Font Families
|
|
84
|
+
|
|
85
|
+
| Role | Font | Fallbacks |
|
|
86
|
+
|-------------------|---------------------|----------------------------------------|
|
|
87
|
+
| Body / Primary | FK Grotesk | Inter, system-ui, sans-serif |
|
|
88
|
+
| Headlines | FK Grotesk SemiMono | Inter, system-ui, sans-serif |
|
|
89
|
+
| Subheaders | FK Grotesk SemiMono | Inter, system-ui, sans-serif |
|
|
90
|
+
| Buttons/Elements | FK Grotesk Mono | JetBrains Mono, Fira Code, monospace |
|
|
91
|
+
| Brand wordmark | Inter | system-ui, sans-serif |
|
|
92
|
+
| Code/Data | FK Grotesk Mono | JetBrains Mono, Fira Code, monospace |
|
|
93
|
+
|
|
94
|
+
FK Grotesk is a commercial font (licensed). Font files are **not committed to git**. See `public/fonts/README.md` for setup instructions.
|
|
95
|
+
|
|
96
|
+
### Type Hierarchy
|
|
97
|
+
|
|
98
|
+
| Level | Font | Weight | Style |
|
|
99
|
+
|--------------------------|-------------------|---------|------------|
|
|
100
|
+
| Headlines (h1) | FK Grotesk SemiMono | Regular | Normal |
|
|
101
|
+
| Subheaders (h2, h3) | FK Grotesk SemiMono | Regular | Normal |
|
|
102
|
+
| Body Copy | FK Grotesk | Regular | Normal |
|
|
103
|
+
| Body Strong / Highlighted | FK Grotesk | Strong (700) | Normal |
|
|
104
|
+
| Buttons & UI Elements | FK Grotesk Mono | Regular | UPPERCASE, letter-spacing 0.05em |
|
|
105
|
+
|
|
106
|
+
### CSS Variables
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
:root {
|
|
110
|
+
--font-primary: 'FK Grotesk', 'Inter', system-ui, -apple-system, sans-serif;
|
|
111
|
+
--font-headline: 'FK Grotesk Mono', 'Inter', system-ui, sans-serif;
|
|
112
|
+
--font-brand: 'Inter', system-ui, -apple-system, sans-serif;
|
|
113
|
+
--font-mono: 'FK Grotesk Mono', 'JetBrains Mono', 'Fira Code', monospace;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Iconography
|
|
118
|
+
|
|
119
|
+
We use the **IBM Carbon Design** icon kit -- an open-source, free icon kit with over 2,000 icons available.
|
|
120
|
+
|
|
121
|
+
Library: https://carbondesignsystem.com/elements/icons/library/
|
|
122
|
+
|
|
123
|
+
In practice, we currently use Material Design Icons (mdi) via Vuetify. Carbon icons can be adopted incrementally.
|
|
124
|
+
|
|
125
|
+
## Logo
|
|
126
|
+
|
|
127
|
+
The primary logo is the Lovelace wordmark with the circular green-dot badge:
|
|
128
|
+
- **White version** (for dark backgrounds): `LL-logo-full-wht.svg`
|
|
129
|
+
- Located in `public/LL-logo-full-wht.svg`
|
|
130
|
+
|
|
131
|
+
## Visual Effects (Optional)
|
|
132
|
+
|
|
133
|
+
These effects can be applied sparingly for branded sections:
|
|
134
|
+
|
|
135
|
+
- **Grid pattern**: Subtle grid lines at 20px intervals
|
|
136
|
+
- **Dot pattern**: Punch-card aesthetic with radial dots at 16px intervals
|
|
137
|
+
- **Glow effects**: Colored box-shadows (green, orange, blue) at 0.3 opacity
|
|
138
|
+
- **Text glow**: Green text-shadow for emphasis
|
|
139
|
+
|
|
140
|
+
## CSS Variable Reference
|
|
141
|
+
|
|
142
|
+
All Brand R2 CSS variables are defined in `app.vue` under `:root`:
|
|
143
|
+
|
|
144
|
+
```css
|
|
145
|
+
:root {
|
|
146
|
+
/* Core */
|
|
147
|
+
--lv-black: #0A0A0A;
|
|
148
|
+
--lv-surface: #141414;
|
|
149
|
+
--lv-surface-light: #1E1E1E;
|
|
150
|
+
--lv-white: #FFFFFF;
|
|
151
|
+
--lv-silver: #757575;
|
|
152
|
+
|
|
153
|
+
/* Primary */
|
|
154
|
+
--lv-green: #3FEA00;
|
|
155
|
+
--lv-green-dim: #30BC00;
|
|
156
|
+
--lv-green-light: #57FF19;
|
|
157
|
+
|
|
158
|
+
/* Secondary */
|
|
159
|
+
--lv-orange: #FF5C00;
|
|
160
|
+
--lv-orange-dim: #D04E02;
|
|
161
|
+
--lv-blue: #003BFF;
|
|
162
|
+
--lv-blue-dim: #0230D0;
|
|
163
|
+
--lv-blue-light: #2E5DFF;
|
|
164
|
+
|
|
165
|
+
/* Semantic */
|
|
166
|
+
--lv-yellow: #FF9F0A;
|
|
167
|
+
--lv-finance-blue: #003BFF;
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Implementation Notes
|
|
172
|
+
|
|
173
|
+
- The News UI uses a single dark theme ("brand") defined in `composables/useNewsTheme.ts`
|
|
174
|
+
- Theme-aware CSS utility classes are in `assets/theme-styles.css`
|
|
175
|
+
- The `useThemeClasses` composable provides pre-built class combinations for components
|
|
176
|
+
- Vuetify is configured with `defaultTheme: "dark"` in `nuxt.config.ts`
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lovelace-branding
|
|
3
|
+
description: Implement Lovelace brand identity in any UI project. Use for colors, typography, patterns, and visual guidelines.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Lovelace Branding Skill
|
|
7
|
+
|
|
8
|
+
Lovelace brand guidelines for implementing consistent visual identity across any UI project.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
- Implementing Lovelace visual identity in a new project
|
|
13
|
+
- Styling UI components to match Lovelace branding
|
|
14
|
+
- Setting up colors, fonts, or CSS variables
|
|
15
|
+
- Looking up brand guidelines or constraints
|
|
16
|
+
|
|
17
|
+
## Files
|
|
18
|
+
|
|
19
|
+
| File | Contents |
|
|
20
|
+
|------|----------|
|
|
21
|
+
| [overview.md](overview.md) | Quick reference: colors, fonts, CSS variables, key principles |
|
|
22
|
+
| [BRANDING.md](BRANDING.md) | Full brand guidelines with rationale and color ramps |
|
|
23
|
+
| [patterns.md](patterns.md) | Framework-agnostic CSS patterns (cards, buttons, tables) |
|
|
24
|
+
| [fonts.md](fonts.md) | FK Grotesk font setup and fallbacks |
|
|
25
|
+
| [assets/](assets/) | Logo SVGs, icons, and other brand assets |
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 643.71 84.78">
|
|
3
|
+
<defs>
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #3fea00;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.cls-2 {
|
|
10
|
+
fill: #fff;
|
|
11
|
+
}
|
|
12
|
+
</style>
|
|
13
|
+
</defs>
|
|
14
|
+
<g id="Layer_1-2" data-name="Layer 1">
|
|
15
|
+
<g>
|
|
16
|
+
<path class="cls-2" d="M108.53,69.1V5.86h18.75v56.13h34.92v16.48h-44.08c-6.08,0-9.58-3.19-9.58-9.37Z"/>
|
|
17
|
+
<path class="cls-2" d="M198.24,4.42c23.59,0,38.01,16.27,38.01,37.7s-14.42,37.8-38.01,37.8-38.21-16.27-38.21-37.8,14.52-37.7,38.21-37.7ZM198.24,62.92c12.57,0,18.75-7.62,18.75-20.81s-6.28-20.7-18.75-20.7-18.85,7.62-18.85,20.7,6.28,20.81,18.85,20.81Z"/>
|
|
18
|
+
<path class="cls-2" d="M229.96,5.86h19.88l20.6,65.82,20.6-65.82h19.67l-23.28,72.61h-34.3L229.96,5.86Z"/>
|
|
19
|
+
<path class="cls-2" d="M313.7,5.86h57.78v16.38h-38.93v12.15h33.78v15.45h-33.78v12.26h38.93v16.38h-57.78V5.86Z"/>
|
|
20
|
+
<path class="cls-2" d="M376.01,69.1V5.86h18.75v56.13h34.92v16.48h-44.08c-6.08,0-9.58-3.19-9.58-9.37Z"/>
|
|
21
|
+
<path class="cls-2" d="M455.94,5.86h34.3l23.17,72.61h-19.88l-6.8-21.94h-27.6l-6.8,21.94h-19.67l23.28-72.61ZM481.59,40.16l-8.65-27.71-8.65,27.71h17.3Z"/>
|
|
22
|
+
<path class="cls-2" d="M507.54,42.11c0-21.42,14.73-37.7,38.52-37.7,20.81,0,34.61,11.23,36.77,29.46h-19.26c-1.54-7.83-8.24-12.46-17.41-12.46-11.23,0-19.26,6.39-19.26,20.7s8.03,20.81,19.26,20.81c9.17,0,15.86-4.74,17.41-12.57h19.26c-2.16,18.33-15.96,29.56-36.77,29.56-23.79,0-38.52-16.27-38.52-37.8Z"/>
|
|
23
|
+
<path class="cls-2" d="M585.92,5.86h57.78v16.38h-38.93v12.15h33.78v15.45h-33.78v12.26h38.93v16.38h-57.78V5.86Z"/>
|
|
24
|
+
</g>
|
|
25
|
+
<path class="cls-1" d="M84.78,42.39h0c0,23.41-18.98,42.39-42.39,42.39h0C18.98,84.78,0,65.8,0,42.39h0C0,18.98,18.98,0,42.39,0h0c23.41,0,42.39,18.98,42.39,42.39Z"/>
|
|
26
|
+
<g>
|
|
27
|
+
<circle cx="67.39" cy="50.72" r="6.4"/>
|
|
28
|
+
<circle cx="67.39" cy="34.05" r="6.4"/>
|
|
29
|
+
<circle cx="50.72" cy="50.72" r="6.4"/>
|
|
30
|
+
<circle cx="34.05" cy="34.05" r="6.4"/>
|
|
31
|
+
<circle cx="17.39" cy="34.05" r="6.4"/>
|
|
32
|
+
<circle cx="17.39" cy="50.72" r="6.4"/>
|
|
33
|
+
</g>
|
|
34
|
+
</g>
|
|
35
|
+
</svg>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 643.71 84.78">
|
|
3
|
+
<defs>
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #e6e6e6;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.cls-2 {
|
|
10
|
+
fill: #3fea00;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.cls-3 {
|
|
14
|
+
fill: #fff;
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</defs>
|
|
18
|
+
<g id="Layer_1-2" data-name="Layer 1">
|
|
19
|
+
<g>
|
|
20
|
+
<path class="cls-3" d="M108.53,69.1V5.86h18.75v56.13h34.92v16.48h-44.08c-6.08,0-9.58-3.19-9.58-9.37Z"/>
|
|
21
|
+
<path class="cls-3" d="M198.24,4.42c23.59,0,38.01,16.27,38.01,37.7s-14.42,37.8-38.01,37.8-38.21-16.27-38.21-37.8,14.52-37.7,38.21-37.7ZM198.24,62.92c12.57,0,18.75-7.62,18.75-20.81s-6.28-20.7-18.75-20.7-18.85,7.62-18.85,20.7,6.28,20.81,18.85,20.81Z"/>
|
|
22
|
+
<path class="cls-3" d="M229.96,5.86h19.88l20.6,65.82,20.6-65.82h19.67l-23.28,72.61h-34.3L229.96,5.86Z"/>
|
|
23
|
+
<path class="cls-3" d="M313.7,5.86h57.78v16.38h-38.93v12.15h33.78v15.45h-33.78v12.26h38.93v16.38h-57.78V5.86Z"/>
|
|
24
|
+
<path class="cls-3" d="M376.01,69.1V5.86h18.75v56.13h34.92v16.48h-44.08c-6.08,0-9.58-3.19-9.58-9.37Z"/>
|
|
25
|
+
<path class="cls-3" d="M455.94,5.86h34.3l23.17,72.61h-19.88l-6.8-21.94h-27.6l-6.8,21.94h-19.67l23.28-72.61ZM481.59,40.16l-8.65-27.71-8.65,27.71h17.3Z"/>
|
|
26
|
+
<path class="cls-3" d="M507.54,42.11c0-21.42,14.73-37.7,38.52-37.7,20.81,0,34.61,11.23,36.77,29.46h-19.26c-1.54-7.83-8.24-12.46-17.41-12.46-11.23,0-19.26,6.39-19.26,20.7s8.03,20.81,19.26,20.81c9.17,0,15.86-4.74,17.41-12.57h19.26c-2.16,18.33-15.96,29.56-36.77,29.56-23.79,0-38.52-16.27-38.52-37.8Z"/>
|
|
27
|
+
<path class="cls-3" d="M585.92,5.86h57.78v16.38h-38.93v12.15h33.78v15.45h-33.78v12.26h38.93v16.38h-57.78V5.86Z"/>
|
|
28
|
+
</g>
|
|
29
|
+
<path class="cls-1" d="M84.78,42.39h0c0,23.41-18.98,42.39-42.39,42.39h0C18.98,84.78,0,65.8,0,42.39h0C0,18.98,18.98,0,42.39,0h0c23.41,0,42.39,18.98,42.39,42.39Z"/>
|
|
30
|
+
<g>
|
|
31
|
+
<circle class="cls-2" cx="67.39" cy="50.72" r="6.4"/>
|
|
32
|
+
<circle class="cls-2" cx="67.39" cy="34.05" r="6.4"/>
|
|
33
|
+
<circle class="cls-2" cx="50.72" cy="50.72" r="6.4"/>
|
|
34
|
+
<circle class="cls-2" cx="34.05" cy="34.05" r="6.4"/>
|
|
35
|
+
<circle class="cls-2" cx="17.39" cy="34.05" r="6.4"/>
|
|
36
|
+
<circle class="cls-2" cx="17.39" cy="50.72" r="6.4"/>
|
|
37
|
+
</g>
|
|
38
|
+
</g>
|
|
39
|
+
</svg>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 84.78 84.78">
|
|
3
|
+
<defs>
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #3fea00;
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
9
|
+
</defs>
|
|
10
|
+
<g id="Layer_1-2" data-name="Layer 1">
|
|
11
|
+
<path class="cls-1" d="M84.78,42.39h0c0,23.41-18.98,42.39-42.39,42.39h0C18.98,84.78,0,65.8,0,42.39h0C0,18.98,18.98,0,42.39,0h0c23.41,0,42.39,18.98,42.39,42.39Z"/>
|
|
12
|
+
<g>
|
|
13
|
+
<circle cx="67.39" cy="50.72" r="6.4"/>
|
|
14
|
+
<circle cx="67.39" cy="34.05" r="6.4"/>
|
|
15
|
+
<circle cx="50.72" cy="50.72" r="6.4"/>
|
|
16
|
+
<circle cx="34.05" cy="34.05" r="6.4"/>
|
|
17
|
+
<circle cx="17.39" cy="34.05" r="6.4"/>
|
|
18
|
+
<circle cx="17.39" cy="50.72" r="6.4"/>
|
|
19
|
+
</g>
|
|
20
|
+
</g>
|
|
21
|
+
</svg>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "Medium Red",
|
|
4
|
+
"color": "#FF0000",
|
|
5
|
+
"size": 20
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "Medium Green",
|
|
9
|
+
"color": "#00FF00",
|
|
10
|
+
"size": 20
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "Medium Blue",
|
|
14
|
+
"color": "#0000FF",
|
|
15
|
+
"size": 20
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Medium Yellow",
|
|
19
|
+
"color": "#FFFF00",
|
|
20
|
+
"size": 20
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Small Red",
|
|
24
|
+
"color": "#FF0000",
|
|
25
|
+
"size": 20
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "Small Green",
|
|
29
|
+
"color": "#00FF00",
|
|
30
|
+
"size": 20
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "Small Blue",
|
|
34
|
+
"color": "#0000FF",
|
|
35
|
+
"size": 20
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "Small Yellow",
|
|
39
|
+
"color": "#FFFF00",
|
|
40
|
+
"size": 20
|
|
41
|
+
}
|
|
42
|
+
]
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="main">
|
|
2
|
+
<path
|
|
3
|
+
d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Lovelace Font Setup
|
|
2
|
+
|
|
3
|
+
FK Grotesk is the primary font family for Lovelace branding. This document covers setup, fallbacks, and deployment considerations.
|
|
4
|
+
|
|
5
|
+
## Required Font Files
|
|
6
|
+
|
|
7
|
+
FK Grotesk is a commercial font. Font files are **not committed to git**.
|
|
8
|
+
|
|
9
|
+
### Minimum Required
|
|
10
|
+
|
|
11
|
+
At minimum, you need these three files:
|
|
12
|
+
|
|
13
|
+
- `FKGrotesk-Regular.otf` — Body text
|
|
14
|
+
- `FKGrotesk-Bold.otf` — Strong text
|
|
15
|
+
- `FKGroteskMono-Regular.otf` — Headlines, buttons, code
|
|
16
|
+
|
|
17
|
+
### Full Set (Optional)
|
|
18
|
+
|
|
19
|
+
**FK Grotesk (Proportional):**
|
|
20
|
+
- `FKGrotesk-Thin.otf`, `FKGrotesk-ThinItalic.otf`
|
|
21
|
+
- `FKGrotesk-Light.otf`, `FKGrotesk-LightItalic.otf`
|
|
22
|
+
- `FKGrotesk-Regular.otf`, `FKGrotesk-Italic.otf`
|
|
23
|
+
- `FKGrotesk-Medium.otf`, `FKGrotesk-MediumItalic.otf`
|
|
24
|
+
- `FKGrotesk-Bold.otf`, `FKGrotesk-BoldItalic.otf`
|
|
25
|
+
- `FKGrotesk-Black.otf`, `FKGrotesk-BlackItalic.otf`
|
|
26
|
+
|
|
27
|
+
**FK Grotesk Mono:**
|
|
28
|
+
- `FKGroteskMono-Thin.otf`, `FKGroteskMono-ThinItalic.otf`
|
|
29
|
+
- `FKGroteskMono-Light.otf`, `FKGroteskMono-LightItalic.otf`
|
|
30
|
+
- `FKGroteskMono-Regular.otf`, `FKGroteskMono-Italic.otf`
|
|
31
|
+
- `FKGroteskMono-Medium.otf`, `FKGroteskMono-MediumItalic.otf`
|
|
32
|
+
- `FKGroteskMono-Bold.otf`, `FKGroteskMono-BoldItalic.otf`
|
|
33
|
+
- `FKGroteskMono-Black.otf`, `FKGroteskMono-BlackItalic.otf`
|
|
34
|
+
|
|
35
|
+
## @font-face Declarations
|
|
36
|
+
|
|
37
|
+
```css
|
|
38
|
+
@font-face {
|
|
39
|
+
font-family: 'FK Grotesk';
|
|
40
|
+
src: url('/fonts/FKGrotesk-Regular.otf') format('opentype');
|
|
41
|
+
font-weight: 400;
|
|
42
|
+
font-style: normal;
|
|
43
|
+
font-display: swap;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@font-face {
|
|
47
|
+
font-family: 'FK Grotesk';
|
|
48
|
+
src: url('/fonts/FKGrotesk-Bold.otf') format('opentype');
|
|
49
|
+
font-weight: 700;
|
|
50
|
+
font-style: normal;
|
|
51
|
+
font-display: swap;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@font-face {
|
|
55
|
+
font-family: 'FK Grotesk Mono';
|
|
56
|
+
src: url('/fonts/FKGroteskMono-Regular.otf') format('opentype');
|
|
57
|
+
font-weight: 400;
|
|
58
|
+
font-style: normal;
|
|
59
|
+
font-display: swap;
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## CSS Variable Setup
|
|
64
|
+
|
|
65
|
+
```css
|
|
66
|
+
:root {
|
|
67
|
+
--font-primary: 'FK Grotesk', 'Inter', system-ui, -apple-system, sans-serif;
|
|
68
|
+
--font-headline: 'FK Grotesk Mono', 'Inter', system-ui, sans-serif;
|
|
69
|
+
--font-brand: 'Inter', system-ui, -apple-system, sans-serif;
|
|
70
|
+
--font-mono: 'FK Grotesk Mono', 'JetBrains Mono', 'Fira Code', monospace;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Fallback Strategy
|
|
75
|
+
|
|
76
|
+
When FK Grotesk is not available, the CSS falls back gracefully:
|
|
77
|
+
|
|
78
|
+
| Role | Primary | Fallback |
|
|
79
|
+
|------|---------|----------|
|
|
80
|
+
| Body text | FK Grotesk | Inter, system-ui |
|
|
81
|
+
| Headlines | FK Grotesk Mono | Inter, system-ui |
|
|
82
|
+
| Code/Buttons | FK Grotesk Mono | JetBrains Mono, Fira Code |
|
|
83
|
+
| Brand wordmark | Inter | system-ui |
|
|
84
|
+
|
|
85
|
+
**Inter** is a widely available system font on modern operating systems and provides a similar aesthetic to FK Grotesk.
|
|
86
|
+
|
|
87
|
+
**JetBrains Mono** is a free, open-source monospace font that works well as a fallback for FK Grotesk Mono.
|
|
88
|
+
|
|
89
|
+
## Usage Examples
|
|
90
|
+
|
|
91
|
+
```css
|
|
92
|
+
/* Body text */
|
|
93
|
+
body {
|
|
94
|
+
font-family: var(--font-primary);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Headlines */
|
|
98
|
+
h1, h2, h3 {
|
|
99
|
+
font-family: var(--font-headline);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Buttons */
|
|
103
|
+
button {
|
|
104
|
+
font-family: var(--font-mono);
|
|
105
|
+
text-transform: uppercase;
|
|
106
|
+
letter-spacing: 0.05em;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Code blocks */
|
|
110
|
+
code, pre {
|
|
111
|
+
font-family: var(--font-mono);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Deployment Considerations
|
|
116
|
+
|
|
117
|
+
### Static Hosting
|
|
118
|
+
|
|
119
|
+
Place font files in your `public/fonts/` directory. They'll be served as static assets.
|
|
120
|
+
|
|
121
|
+
### Docker
|
|
122
|
+
|
|
123
|
+
Include fonts in your Docker build. Since fonts are git-ignored, add them before building:
|
|
124
|
+
|
|
125
|
+
```dockerfile
|
|
126
|
+
COPY fonts/ /app/public/fonts/
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Cloud Run / Kubernetes
|
|
130
|
+
|
|
131
|
+
Options:
|
|
132
|
+
1. Copy fonts to the image before building
|
|
133
|
+
2. Mount fonts as a secret or ConfigMap volume
|
|
134
|
+
3. Fetch fonts from secure storage in a CI/CD step
|
|
135
|
+
|
|
136
|
+
### CI/CD
|
|
137
|
+
|
|
138
|
+
Add a step to fetch fonts from secure storage (e.g., GCS bucket, 1Password) before building:
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
- name: Fetch fonts
|
|
142
|
+
run: gsutil cp gs://your-bucket/fonts/*.otf public/fonts/
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Licensing
|
|
146
|
+
|
|
147
|
+
FK Grotesk requires a commercial license. Contact the font foundry for licensing terms. Do not commit font files to public repositories.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Lovelace Branding Quick Reference
|
|
2
|
+
|
|
3
|
+
Quick-start guide for implementing Lovelace visual identity.
|
|
4
|
+
|
|
5
|
+
## Key Principles
|
|
6
|
+
|
|
7
|
+
- **Dark-first**: Jet Black (#0A0A0A) backgrounds, white text
|
|
8
|
+
- **Green accents**: Cyber Green (#3FEA00) for interactive elements, CTAs, success states
|
|
9
|
+
- **WCAG AA accessibility**: All color pairings meet minimum contrast requirements
|
|
10
|
+
- **Monospace for emphasis**: FK Grotesk Mono for headlines, buttons, code
|
|
11
|
+
- **Minimal decoration**: Clean surfaces, subtle borders, purposeful color
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
Minimal CSS variable setup to get started:
|
|
16
|
+
|
|
17
|
+
```css
|
|
18
|
+
:root {
|
|
19
|
+
/* Core colors */
|
|
20
|
+
--lv-black: #0A0A0A;
|
|
21
|
+
--lv-white: #FFFFFF;
|
|
22
|
+
--lv-green: #3FEA00;
|
|
23
|
+
--lv-silver: #757575;
|
|
24
|
+
|
|
25
|
+
/* Surfaces */
|
|
26
|
+
--lv-surface: #141414;
|
|
27
|
+
--lv-surface-light: #1E1E1E;
|
|
28
|
+
|
|
29
|
+
/* Typography */
|
|
30
|
+
--font-primary: 'FK Grotesk', 'Inter', system-ui, sans-serif;
|
|
31
|
+
--font-headline: 'FK Grotesk Mono', 'Inter', system-ui, sans-serif;
|
|
32
|
+
--font-mono: 'FK Grotesk Mono', 'JetBrains Mono', monospace;
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Core Colors
|
|
37
|
+
|
|
38
|
+
| Name | Hex | CSS Variable | Usage |
|
|
39
|
+
|------|-----|--------------|-------|
|
|
40
|
+
| Jet Black | `#0A0A0A` | `--lv-black` | Primary backgrounds |
|
|
41
|
+
| Pure White | `#FFFFFF` | `--lv-white` | Primary text on dark surfaces |
|
|
42
|
+
| Sonic Silver | `#757575` | `--lv-silver` | Muted text, secondary elements |
|
|
43
|
+
| Cyber Green | `#3FEA00` | `--lv-green` | Primary accent, CTAs, success |
|
|
44
|
+
|
|
45
|
+
## Secondary Colors
|
|
46
|
+
|
|
47
|
+
| Name | Hex | CSS Variable | Usage |
|
|
48
|
+
|------|-----|--------------|-------|
|
|
49
|
+
| Electric Blue | `#003BFF` | `--lv-blue` | Accent, links, finance/data |
|
|
50
|
+
| Blaze Orange | `#FF5C00` | `--lv-orange` | Warnings, highlights, secondary CTA |
|
|
51
|
+
| Amber | `#FF9F0A` | `--lv-yellow` | Warnings |
|
|
52
|
+
| Red | `#EF4444` | — | Errors |
|
|
53
|
+
|
|
54
|
+
## Surface Colors
|
|
55
|
+
|
|
56
|
+
| Name | Hex | CSS Variable | Usage |
|
|
57
|
+
|------|-----|--------------|-------|
|
|
58
|
+
| Surface | `#141414` | `--lv-surface` | Card backgrounds, elevated surfaces |
|
|
59
|
+
| Surface Light | `#1E1E1E` | `--lv-surface-light` | Hover states, lighter panels |
|
|
60
|
+
| Panel | `#111111` | — | Table headers, dark panels |
|
|
61
|
+
| Border | `#2A2A2A` | — | Subtle borders |
|
|
62
|
+
|
|
63
|
+
## Color Usage Proportions
|
|
64
|
+
|
|
65
|
+
- **70%** — Jet Black + Pure White (dark backgrounds, white text)
|
|
66
|
+
- **15%** — Cyber Green (accents, interactive elements, success states)
|
|
67
|
+
- **10%** — Sonic Silver (muted text, borders, secondary elements)
|
|
68
|
+
- **5%** — Electric Blue + Blaze Orange (sparingly, for specific semantic purposes)
|
|
69
|
+
|
|
70
|
+
## Typography
|
|
71
|
+
|
|
72
|
+
### Font Families
|
|
73
|
+
|
|
74
|
+
| Role | Font | CSS Variable |
|
|
75
|
+
|------|------|--------------|
|
|
76
|
+
| Body / Primary | FK Grotesk | `--font-primary` |
|
|
77
|
+
| Headlines | FK Grotesk Mono | `--font-headline` |
|
|
78
|
+
| Buttons / Code | FK Grotesk Mono | `--font-mono` |
|
|
79
|
+
| Brand wordmark | Inter | `--font-brand` |
|
|
80
|
+
|
|
81
|
+
### Type Hierarchy
|
|
82
|
+
|
|
83
|
+
| Level | Font | Weight | Style |
|
|
84
|
+
|-------|------|--------|-------|
|
|
85
|
+
| Headlines (h1) | FK Grotesk Mono | Regular | Normal |
|
|
86
|
+
| Subheaders (h2, h3) | FK Grotesk Mono | Regular | Normal |
|
|
87
|
+
| Body Copy | FK Grotesk | Regular | Normal |
|
|
88
|
+
| Body Strong | FK Grotesk | Bold (700) | Normal |
|
|
89
|
+
| Buttons & UI | FK Grotesk Mono | Regular | UPPERCASE, letter-spacing 0.05em |
|
|
90
|
+
|
|
91
|
+
## Full CSS Variables
|
|
92
|
+
|
|
93
|
+
Complete `:root` block for all brand variables:
|
|
94
|
+
|
|
95
|
+
```css
|
|
96
|
+
:root {
|
|
97
|
+
/* Core */
|
|
98
|
+
--lv-black: #0A0A0A;
|
|
99
|
+
--lv-surface: #141414;
|
|
100
|
+
--lv-surface-light: #1E1E1E;
|
|
101
|
+
--lv-white: #FFFFFF;
|
|
102
|
+
--lv-silver: #757575;
|
|
103
|
+
|
|
104
|
+
/* Primary */
|
|
105
|
+
--lv-green: #3FEA00;
|
|
106
|
+
--lv-green-dim: #30BC00;
|
|
107
|
+
--lv-green-light: #57FF19;
|
|
108
|
+
|
|
109
|
+
/* Secondary */
|
|
110
|
+
--lv-orange: #FF5C00;
|
|
111
|
+
--lv-orange-dim: #D04E02;
|
|
112
|
+
--lv-blue: #003BFF;
|
|
113
|
+
--lv-blue-dim: #0230D0;
|
|
114
|
+
--lv-blue-light: #2E5DFF;
|
|
115
|
+
|
|
116
|
+
/* Semantic */
|
|
117
|
+
--lv-yellow: #FF9F0A;
|
|
118
|
+
--lv-finance-blue: #003BFF;
|
|
119
|
+
|
|
120
|
+
/* Typography */
|
|
121
|
+
--font-primary: 'FK Grotesk', 'Inter', system-ui, -apple-system, sans-serif;
|
|
122
|
+
--font-headline: 'FK Grotesk Mono', 'Inter', system-ui, sans-serif;
|
|
123
|
+
--font-brand: 'Inter', system-ui, -apple-system, sans-serif;
|
|
124
|
+
--font-mono: 'FK Grotesk Mono', 'JetBrains Mono', 'Fira Code', monospace;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Accessibility
|
|
129
|
+
|
|
130
|
+
All color pairings must meet WCAG AA contrast ratio at minimum:
|
|
131
|
+
|
|
132
|
+
- White text on Jet Black: **passes AAA**
|
|
133
|
+
- Cyber Green on Jet Black: **passes AA**
|
|
134
|
+
- Electric Blue on Jet Black: **passes AA**
|
|
135
|
+
|
|
136
|
+
Use the color ramps (see BRANDING.md) to find appropriate pairings for other combinations.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Lovelace CSS Patterns
|
|
2
|
+
|
|
3
|
+
Framework-agnostic CSS patterns for implementing Lovelace brand styling. These patterns are extracted from the News UI theme styles and can be adapted for React, Vue, Tailwind, or plain CSS.
|
|
4
|
+
|
|
5
|
+
## Card Styling
|
|
6
|
+
|
|
7
|
+
### Basic Card
|
|
8
|
+
|
|
9
|
+
```css
|
|
10
|
+
.card {
|
|
11
|
+
background-color: var(--lv-surface);
|
|
12
|
+
border: 1px solid #2A2A2A;
|
|
13
|
+
color: var(--lv-white);
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Card Header with Gradient
|
|
18
|
+
|
|
19
|
+
```css
|
|
20
|
+
.card-header {
|
|
21
|
+
background: linear-gradient(135deg, var(--lv-surface), var(--lv-surface-light));
|
|
22
|
+
border-bottom: 1px solid var(--lv-green-dim);
|
|
23
|
+
color: var(--lv-white);
|
|
24
|
+
padding: 12px 16px;
|
|
25
|
+
height: 56px;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Metric Card
|
|
30
|
+
|
|
31
|
+
```css
|
|
32
|
+
.metric-card {
|
|
33
|
+
background-color: var(--lv-surface);
|
|
34
|
+
border: 1px solid #2A2A2A;
|
|
35
|
+
color: var(--lv-white);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.metric-label {
|
|
39
|
+
color: #A0AEC0;
|
|
40
|
+
font-size: 0.875rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.metric-value {
|
|
44
|
+
color: var(--lv-white);
|
|
45
|
+
font-weight: 600;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Button Patterns
|
|
50
|
+
|
|
51
|
+
### Active/Selected Button
|
|
52
|
+
|
|
53
|
+
```css
|
|
54
|
+
.btn-active {
|
|
55
|
+
background-color: var(--lv-green);
|
|
56
|
+
color: var(--lv-black);
|
|
57
|
+
border-color: var(--lv-green);
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
box-shadow: 0 0 12px rgba(63, 234, 0, 0.3);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Inactive Button
|
|
64
|
+
|
|
65
|
+
```css
|
|
66
|
+
.btn-inactive {
|
|
67
|
+
background-color: transparent;
|
|
68
|
+
color: rgba(255, 255, 255, 0.9);
|
|
69
|
+
border: 1px solid #2A2A2A;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.btn-inactive:hover {
|
|
73
|
+
background-color: rgba(255, 255, 255, 0.1);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Button Group Sizing
|
|
78
|
+
|
|
79
|
+
```css
|
|
80
|
+
.btn-group .btn {
|
|
81
|
+
transition: all 0.2s ease;
|
|
82
|
+
border-radius: 4px;
|
|
83
|
+
padding: 0 16px;
|
|
84
|
+
min-height: 36px;
|
|
85
|
+
letter-spacing: normal;
|
|
86
|
+
text-transform: none;
|
|
87
|
+
font-weight: 500;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Data Table Patterns
|
|
92
|
+
|
|
93
|
+
```css
|
|
94
|
+
.data-table {
|
|
95
|
+
background-color: var(--lv-surface);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.data-table th {
|
|
99
|
+
background-color: #111111;
|
|
100
|
+
color: var(--lv-white);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.data-table td {
|
|
104
|
+
color: var(--lv-white);
|
|
105
|
+
border-bottom: 1px solid #2A2A2A;
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## List Patterns
|
|
110
|
+
|
|
111
|
+
### Interactive List
|
|
112
|
+
|
|
113
|
+
```css
|
|
114
|
+
.list {
|
|
115
|
+
background-color: transparent;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.list-item {
|
|
119
|
+
color: var(--lv-white);
|
|
120
|
+
background-color: transparent;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.list-item:hover {
|
|
124
|
+
background-color: var(--lv-surface-light);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### List Item States
|
|
129
|
+
|
|
130
|
+
```css
|
|
131
|
+
.list-item-title {
|
|
132
|
+
color: var(--lv-white);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.list-item-subtitle {
|
|
136
|
+
color: #A0AEC0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.list-item-disabled .list-item-title {
|
|
140
|
+
color: #A0AEC0;
|
|
141
|
+
opacity: 0.6;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Text Utility Classes
|
|
146
|
+
|
|
147
|
+
```css
|
|
148
|
+
.text-primary {
|
|
149
|
+
color: var(--lv-white);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.text-secondary {
|
|
153
|
+
color: #A0AEC0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.text-muted {
|
|
157
|
+
color: var(--lv-silver);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Background Colors
|
|
162
|
+
|
|
163
|
+
```css
|
|
164
|
+
.bg-surface {
|
|
165
|
+
background-color: var(--lv-surface);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.bg-card {
|
|
169
|
+
background-color: var(--lv-surface-light);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.bg-panel {
|
|
173
|
+
background-color: #111111;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Input Styling
|
|
178
|
+
|
|
179
|
+
```css
|
|
180
|
+
.input:focus {
|
|
181
|
+
background-color: rgba(255, 255, 255, 0.08);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.input {
|
|
185
|
+
color: white;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Visual Effects
|
|
190
|
+
|
|
191
|
+
### Glow Effects
|
|
192
|
+
|
|
193
|
+
```css
|
|
194
|
+
.glow-green {
|
|
195
|
+
box-shadow: 0 0 12px rgba(63, 234, 0, 0.3);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.glow-orange {
|
|
199
|
+
box-shadow: 0 0 12px rgba(255, 92, 0, 0.3);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.glow-blue {
|
|
203
|
+
box-shadow: 0 0 12px rgba(0, 59, 255, 0.3);
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Text Glow
|
|
208
|
+
|
|
209
|
+
```css
|
|
210
|
+
.text-glow {
|
|
211
|
+
text-shadow: 0 0 8px rgba(63, 234, 0, 0.5);
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Border Accent
|
|
216
|
+
|
|
217
|
+
```css
|
|
218
|
+
.border-accent {
|
|
219
|
+
border-color: var(--lv-green-dim);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## CSS Variable Naming Conventions
|
|
224
|
+
|
|
225
|
+
| Prefix | Purpose | Example |
|
|
226
|
+
|--------|---------|---------|
|
|
227
|
+
| `--lv-*` | Brand colors (static) | `--lv-green`, `--lv-surface` |
|
|
228
|
+
| `--theme-*` | Theme-aware aliases | `--theme-primary`, `--theme-text` |
|
|
229
|
+
| `--dynamic-*` | JS-set runtime values | `--dynamic-primary`, `--dynamic-surface` |
|
|
230
|
+
| `--font-*` | Typography | `--font-primary`, `--font-mono` |
|
|
231
|
+
|
|
232
|
+
## Framework Adaptation Notes
|
|
233
|
+
|
|
234
|
+
### React
|
|
235
|
+
|
|
236
|
+
Use CSS modules or styled-components. Import the CSS variables in your global styles.
|
|
237
|
+
|
|
238
|
+
### Vue
|
|
239
|
+
|
|
240
|
+
Use scoped styles with `<style scoped>`. The variables work naturally with Vue's reactivity.
|
|
241
|
+
|
|
242
|
+
### Tailwind
|
|
243
|
+
|
|
244
|
+
Extend your `tailwind.config.js` with the brand colors:
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
module.exports = {
|
|
248
|
+
theme: {
|
|
249
|
+
extend: {
|
|
250
|
+
colors: {
|
|
251
|
+
'lv-black': '#0A0A0A',
|
|
252
|
+
'lv-green': '#3FEA00',
|
|
253
|
+
'lv-surface': '#141414',
|
|
254
|
+
// ...
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Plain CSS
|
|
262
|
+
|
|
263
|
+
Include the CSS variables in your `:root` and use them directly.
|