@abstractdata/starlight-theme 0.2.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 +43 -0
- package/package.json +49 -0
- package/src/assets/abstract-data-logo.png +0 -0
- package/src/assets/ad-mark.svg +26 -0
- package/src/components/Footer.astro +22 -0
- package/src/components/Glitch.astro +36 -0
- package/src/components/Hero.astro +170 -0
- package/src/components/SocialIcons.astro +27 -0
- package/src/index.ts +142 -0
- package/src/shiki/abstract-data-dark.ts +103 -0
- package/src/shiki/abstract-data-light.ts +103 -0
- package/src/shiki/index.ts +24 -0
- package/src/styles/hud.css +229 -0
- package/src/styles/theme.css +380 -0
- package/src/types.d.ts +16 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @abstractdata/starlight-theme
|
|
2
|
+
|
|
3
|
+
Branded Astro Starlight theme by Abstract Data. HUD and Calm surfaces, light + dark, motion-aware.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @abstractdata/starlight-theme
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Use
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// astro.config.mjs
|
|
15
|
+
import { defineConfig } from 'astro/config';
|
|
16
|
+
import starlight from '@astrojs/starlight';
|
|
17
|
+
import abstractData from '@abstractdata/starlight-theme';
|
|
18
|
+
|
|
19
|
+
export default defineConfig({
|
|
20
|
+
integrations: [
|
|
21
|
+
starlight({
|
|
22
|
+
title: 'Your Docs',
|
|
23
|
+
plugins: [abstractData({ motion: 'full' })],
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Options
|
|
30
|
+
|
|
31
|
+
| Option | Type | Default | Description |
|
|
32
|
+
|--------|------|---------|-------------|
|
|
33
|
+
| `motion` | `'full' \| 'calm'` | `'full'` | HUD = animated hexagon grid, scanline, holographic shimmer, glitch. Calm = same palette, no animations. |
|
|
34
|
+
| `credit` | `'auto' \| 'hide'` | `'auto'` | _(Round 3b)_ Show "Built by Abstract Data" in footer. Set `'hide'` for white-label client work. |
|
|
35
|
+
|
|
36
|
+
`motion: 'full'` automatically collapses to Calm behavior when the user's OS reports `prefers-reduced-motion: reduce`. No additional config required.
|
|
37
|
+
|
|
38
|
+
## Brand
|
|
39
|
+
|
|
40
|
+
- Cyan `#00D9FF` · Gold `#D4AF37` · Burgundy `#8B2635`
|
|
41
|
+
- Display Orbitron · Body Inter · Mono JetBrains Mono
|
|
42
|
+
|
|
43
|
+
See the repo root `README.md` for full brand reference.
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@abstractdata/starlight-theme",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Branded Astro Starlight theme by Abstract Data — HUD and Calm surfaces, light + dark, motion-aware.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.ts",
|
|
7
|
+
"types": "./src/index.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./src/index.ts",
|
|
10
|
+
"./types": "./src/types.d.ts",
|
|
11
|
+
"./shiki": "./src/shiki/index.ts",
|
|
12
|
+
"./styles/*": "./src/styles/*",
|
|
13
|
+
"./components/*": "./src/components/*",
|
|
14
|
+
"./assets/*": "./src/assets/*"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"src/"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"astro",
|
|
24
|
+
"starlight",
|
|
25
|
+
"starlight-theme",
|
|
26
|
+
"documentation",
|
|
27
|
+
"abstract-data"
|
|
28
|
+
],
|
|
29
|
+
"homepage": "https://github.com/Abstract-Data/abstract-data-doc-theme",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/Abstract-Data/abstract-data-doc-theme.git",
|
|
33
|
+
"directory": "packages/starlight-theme"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"author": "Abstract Data <dev@abstractdata.io>",
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@astrojs/starlight": ">=0.32.0",
|
|
42
|
+
"astro": ">=5.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@astrojs/starlight": "^0.34.0",
|
|
46
|
+
"astro": "^5.10.0",
|
|
47
|
+
"typescript": "^5.6.0"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<style>
|
|
3
|
+
@media (prefers-color-scheme: light) {
|
|
4
|
+
.background { fill: black; }
|
|
5
|
+
.foreground { fill: white; }
|
|
6
|
+
}
|
|
7
|
+
@media (prefers-color-scheme: dark) {
|
|
8
|
+
.background { fill: white; }
|
|
9
|
+
.foreground { fill: black; }
|
|
10
|
+
}
|
|
11
|
+
</style>
|
|
12
|
+
<g clip-path="url(#clip0_7960_43945)">
|
|
13
|
+
<rect class="background" width="180" height="180" rx="37" />
|
|
14
|
+
<g style="transform: scale(95%); transform-origin: center">
|
|
15
|
+
<path class="foreground"
|
|
16
|
+
d="M101.141 53H136.632C151.023 53 162.689 64.6662 162.689 79.0573V112.904H148.112V79.0573C148.112 78.7105 148.098 78.3662 148.072 78.0251L112.581 112.898C112.701 112.902 112.821 112.904 112.941 112.904H148.112V126.672H112.941C98.5504 126.672 86.5638 114.891 86.5638 100.5V66.7434H101.141V100.5C101.141 101.15 101.191 101.792 101.289 102.422L137.56 66.7816C137.255 66.7563 136.945 66.7434 136.632 66.7434H101.141V53Z" />
|
|
17
|
+
<path class="foreground"
|
|
18
|
+
d="M65.2926 124.136L14 66.7372H34.6355L64.7495 100.436V66.7372H80.1365V118.47C80.1365 126.278 70.4953 129.958 65.2926 124.136Z" />
|
|
19
|
+
</g>
|
|
20
|
+
</g>
|
|
21
|
+
<defs>
|
|
22
|
+
<clipPath id="clip0_7960_43945">
|
|
23
|
+
<rect width="180" height="180" fill="white" />
|
|
24
|
+
</clipPath>
|
|
25
|
+
</defs>
|
|
26
|
+
</svg>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Override of Starlight's <Footer /> slot.
|
|
4
|
+
* Renders the default footer (edit link, last updated, pagination),
|
|
5
|
+
* then appends a "Built by Abstract Data" credit unless the theme
|
|
6
|
+
* was configured with `credit: 'hide'` (white-label mode).
|
|
7
|
+
*/
|
|
8
|
+
import type { Props } from '@astrojs/starlight/props';
|
|
9
|
+
import Default from '@astrojs/starlight/components/Footer.astro';
|
|
10
|
+
import { config } from 'virtual:abstractdata/config';
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<Default {...Astro.props} />
|
|
14
|
+
|
|
15
|
+
{
|
|
16
|
+
config.credit !== 'hide' && (
|
|
17
|
+
<div class="ad-credit" role="contentinfo">
|
|
18
|
+
<span>Built by</span>
|
|
19
|
+
<a href="https://abstractdata.io" rel="noopener">Abstract Data</a>
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* <Glitch /> — inline glitch text.
|
|
4
|
+
*
|
|
5
|
+
* Two ways to use it (both work in MDX):
|
|
6
|
+
*
|
|
7
|
+
* <Glitch text="ABSTRACT DATA" />
|
|
8
|
+
* <Glitch>some content</Glitch>
|
|
9
|
+
*
|
|
10
|
+
* The styling lives in `hud.css` — the glitch only animates when the
|
|
11
|
+
* theme is loaded with `motion: 'full'`. Under `motion: 'calm'` the
|
|
12
|
+
* text renders cleanly with no animation.
|
|
13
|
+
*/
|
|
14
|
+
interface Props {
|
|
15
|
+
/** Text to render. If omitted, the default slot is used. */
|
|
16
|
+
text?: string;
|
|
17
|
+
/** Render as block element instead of inline. */
|
|
18
|
+
block?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { text, block = false } = Astro.props;
|
|
22
|
+
const tag = block ? 'div' : 'span';
|
|
23
|
+
const content = text ?? '';
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
{
|
|
27
|
+
block ? (
|
|
28
|
+
<div class="ad-glitch" data-text={content}>
|
|
29
|
+
{text ?? <slot />}
|
|
30
|
+
</div>
|
|
31
|
+
) : (
|
|
32
|
+
<span class="ad-glitch" data-text={content}>
|
|
33
|
+
{text ?? <slot />}
|
|
34
|
+
</span>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* <Hero /> — branded splash hero for the docs landing page.
|
|
4
|
+
*
|
|
5
|
+
* Uses Astro's <Image> component for the logo so it goes through the asset
|
|
6
|
+
* pipeline (lazy loading, optimized format, no perf warnings).
|
|
7
|
+
*
|
|
8
|
+
* Use it in `src/content/docs/index.mdx` like this:
|
|
9
|
+
*
|
|
10
|
+
* import { Image } from 'astro:assets';
|
|
11
|
+
* import logo from '../../assets/your-logo.png';
|
|
12
|
+
* import Hero from '@abstractdata/starlight-theme/components/Hero.astro';
|
|
13
|
+
*
|
|
14
|
+
* <Hero
|
|
15
|
+
* title="Your title"
|
|
16
|
+
* tagline="Your tagline"
|
|
17
|
+
* image={logo}
|
|
18
|
+
* primary={{ text: 'Get Started', href: '/quickstart/' }}
|
|
19
|
+
* secondary={{ text: 'GitHub', href: 'https://github.com/...' }}
|
|
20
|
+
* />
|
|
21
|
+
*/
|
|
22
|
+
import { Image } from 'astro:assets';
|
|
23
|
+
import type { ImageMetadata } from 'astro';
|
|
24
|
+
|
|
25
|
+
interface Action {
|
|
26
|
+
text: string;
|
|
27
|
+
href: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface Props {
|
|
31
|
+
title: string;
|
|
32
|
+
tagline?: string;
|
|
33
|
+
image: ImageMetadata;
|
|
34
|
+
alt?: string;
|
|
35
|
+
primary?: Action;
|
|
36
|
+
secondary?: Action;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { title, tagline, image, alt = title, primary, secondary } = Astro.props;
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
<section class="ad-hero-section">
|
|
43
|
+
<div class="ad-hero-content">
|
|
44
|
+
<h1 class="ad-hero-title">{title}</h1>
|
|
45
|
+
{tagline && <p class="ad-hero-tagline">{tagline}</p>}
|
|
46
|
+
{(primary || secondary) && (
|
|
47
|
+
<div class="ad-hero-actions">
|
|
48
|
+
{primary && (
|
|
49
|
+
<a class="ad-hero-btn ad-hero-btn-primary" href={primary.href}>
|
|
50
|
+
{primary.text}
|
|
51
|
+
</a>
|
|
52
|
+
)}
|
|
53
|
+
{secondary && (
|
|
54
|
+
<a class="ad-hero-btn ad-hero-btn-secondary" href={secondary.href}>
|
|
55
|
+
{secondary.text}
|
|
56
|
+
</a>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
</div>
|
|
61
|
+
<div class="ad-hero-image">
|
|
62
|
+
<Image
|
|
63
|
+
src={image}
|
|
64
|
+
alt={alt}
|
|
65
|
+
widths={[180, 360, 540, 720]}
|
|
66
|
+
sizes="(min-width: 1024px) 360px, 50vw"
|
|
67
|
+
loading="eager"
|
|
68
|
+
decoding="sync"
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
|
|
73
|
+
<style>
|
|
74
|
+
.ad-hero-section {
|
|
75
|
+
display: grid;
|
|
76
|
+
grid-template-columns: 1fr;
|
|
77
|
+
gap: 2.5rem;
|
|
78
|
+
align-items: center;
|
|
79
|
+
padding: 2rem 0 3rem;
|
|
80
|
+
}
|
|
81
|
+
@media (min-width: 768px) {
|
|
82
|
+
.ad-hero-section {
|
|
83
|
+
grid-template-columns: 1fr auto;
|
|
84
|
+
gap: 3.5rem;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
.ad-hero-content { min-width: 0; }
|
|
88
|
+
.ad-hero-title {
|
|
89
|
+
font-family: 'Orbitron', sans-serif;
|
|
90
|
+
font-weight: 700;
|
|
91
|
+
font-size: clamp(2rem, 5vw, 3.5rem);
|
|
92
|
+
line-height: 1.05;
|
|
93
|
+
margin: 0 0 1rem;
|
|
94
|
+
color: var(--sl-color-text);
|
|
95
|
+
letter-spacing: 0.01em;
|
|
96
|
+
position: relative;
|
|
97
|
+
padding-left: 14px;
|
|
98
|
+
}
|
|
99
|
+
.ad-hero-title::before {
|
|
100
|
+
content: '';
|
|
101
|
+
position: absolute;
|
|
102
|
+
left: 0;
|
|
103
|
+
top: 0.2em;
|
|
104
|
+
bottom: 0.2em;
|
|
105
|
+
width: 3px;
|
|
106
|
+
background: linear-gradient(180deg, var(--ad-cyan), var(--ad-gold));
|
|
107
|
+
}
|
|
108
|
+
:global(:root[data-theme='light']) .ad-hero-title::before {
|
|
109
|
+
background: linear-gradient(180deg, var(--ad-cyan-deep), var(--ad-burgundy));
|
|
110
|
+
}
|
|
111
|
+
.ad-hero-tagline {
|
|
112
|
+
font-size: 1.05rem;
|
|
113
|
+
line-height: 1.55;
|
|
114
|
+
color: var(--sl-color-gray-3);
|
|
115
|
+
margin: 0 0 1.75rem;
|
|
116
|
+
max-width: 38ch;
|
|
117
|
+
}
|
|
118
|
+
.ad-hero-actions {
|
|
119
|
+
display: flex;
|
|
120
|
+
gap: 0.75rem;
|
|
121
|
+
flex-wrap: wrap;
|
|
122
|
+
}
|
|
123
|
+
.ad-hero-btn {
|
|
124
|
+
font-family: 'Orbitron', sans-serif;
|
|
125
|
+
font-size: 0.8rem;
|
|
126
|
+
letter-spacing: 0.12em;
|
|
127
|
+
text-transform: uppercase;
|
|
128
|
+
padding: 0.7rem 1.25rem;
|
|
129
|
+
border-radius: 6px;
|
|
130
|
+
text-decoration: none;
|
|
131
|
+
border: 1px solid;
|
|
132
|
+
transition: box-shadow .15s, background .15s;
|
|
133
|
+
}
|
|
134
|
+
.ad-hero-btn-primary {
|
|
135
|
+
background: var(--ad-cyan);
|
|
136
|
+
color: var(--ad-charcoal);
|
|
137
|
+
border-color: var(--ad-cyan);
|
|
138
|
+
}
|
|
139
|
+
.ad-hero-btn-primary:hover {
|
|
140
|
+
box-shadow: 0 0 24px rgba(0, 217, 255, 0.5);
|
|
141
|
+
}
|
|
142
|
+
.ad-hero-btn-secondary {
|
|
143
|
+
background: transparent;
|
|
144
|
+
color: var(--ad-gold);
|
|
145
|
+
border-color: var(--ad-gold);
|
|
146
|
+
}
|
|
147
|
+
.ad-hero-btn-secondary:hover {
|
|
148
|
+
background: rgba(212, 175, 55, 0.10);
|
|
149
|
+
}
|
|
150
|
+
:global(:root[data-theme='light']) .ad-hero-btn-primary {
|
|
151
|
+
background: var(--ad-cyan-deep);
|
|
152
|
+
color: #ffffff;
|
|
153
|
+
border-color: var(--ad-cyan-deep);
|
|
154
|
+
}
|
|
155
|
+
:global(:root[data-theme='light']) .ad-hero-btn-secondary {
|
|
156
|
+
color: var(--ad-burgundy-deep);
|
|
157
|
+
border-color: var(--ad-burgundy-deep);
|
|
158
|
+
}
|
|
159
|
+
:global(:root[data-theme='light']) .ad-hero-btn-secondary:hover {
|
|
160
|
+
background: rgba(122, 31, 44, 0.06);
|
|
161
|
+
}
|
|
162
|
+
.ad-hero-image img {
|
|
163
|
+
max-width: 360px;
|
|
164
|
+
height: auto;
|
|
165
|
+
filter: drop-shadow(0 0 24px rgba(0, 217, 255, 0.35));
|
|
166
|
+
}
|
|
167
|
+
:global(:root[data-theme='light']) .ad-hero-image img {
|
|
168
|
+
filter: drop-shadow(0 4px 16px rgba(122, 31, 44, 0.20));
|
|
169
|
+
}
|
|
170
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Override of Starlight's <SocialIcons /> slot.
|
|
4
|
+
* Renders the default content, then appends the Abstract Data version chip
|
|
5
|
+
* if `version` is configured on the theme plugin.
|
|
6
|
+
*
|
|
7
|
+
* The chip carries the `ad-version-chip` class. When `motion: 'full'`,
|
|
8
|
+
* `hud.css` adds an idle glitch-pulse + a hover-triggered glitch.
|
|
9
|
+
*/
|
|
10
|
+
import type { Props } from '@astrojs/starlight/props';
|
|
11
|
+
import Default from '@astrojs/starlight/components/SocialIcons.astro';
|
|
12
|
+
import { config } from 'virtual:abstractdata/config';
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<Default {...Astro.props} />
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
config.version && (
|
|
19
|
+
<span
|
|
20
|
+
class="ad-version-chip"
|
|
21
|
+
data-text={config.version}
|
|
22
|
+
aria-label={`Version ${config.version}`}
|
|
23
|
+
>
|
|
24
|
+
{config.version}
|
|
25
|
+
</span>
|
|
26
|
+
)
|
|
27
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { StarlightPlugin } from '@astrojs/starlight/types';
|
|
2
|
+
import { abstractDataDark } from './shiki/abstract-data-dark.ts';
|
|
3
|
+
import { abstractDataLight } from './shiki/abstract-data-light.ts';
|
|
4
|
+
|
|
5
|
+
export interface AbstractDataThemeConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Visual motion intensity.
|
|
8
|
+
* - `full` (default): HUD surface — animated hex grid, holographic shimmer,
|
|
9
|
+
* glitch pulse on the version chip.
|
|
10
|
+
* - `calm`: Blueprint surface — same palette and fonts, no animations.
|
|
11
|
+
*
|
|
12
|
+
* `full` automatically degrades to `calm` behavior when the user's OS reports
|
|
13
|
+
* `prefers-reduced-motion: reduce`.
|
|
14
|
+
*/
|
|
15
|
+
motion?: 'full' | 'calm';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* "Built by Abstract Data" credit in the footer.
|
|
19
|
+
* - `auto` (default): show the credit (recommended for Abstract Data properties).
|
|
20
|
+
* - `hide`: omit entirely (white-label client work).
|
|
21
|
+
*/
|
|
22
|
+
credit?: 'auto' | 'hide';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Optional version string shown as a chip next to the social icons.
|
|
26
|
+
* When set under `motion: 'full'`, the chip carries a glitch pulse plus
|
|
27
|
+
* a hover-triggered glitch effect. Leave undefined to hide it entirely.
|
|
28
|
+
*
|
|
29
|
+
* @example "v1.4.2"
|
|
30
|
+
*/
|
|
31
|
+
version?: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Apply the branded Shiki / expressive-code themes (cyan/gold/burgundy
|
|
35
|
+
* tokens). Defaults to `true`. Set `false` if you want to ship your own
|
|
36
|
+
* `expressiveCode.themes` in `astro.config.mjs`.
|
|
37
|
+
*/
|
|
38
|
+
shiki?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const PLUGIN_NAME = '@abstractdata/starlight-theme';
|
|
42
|
+
const VIRTUAL_ID = 'virtual:abstractdata/config';
|
|
43
|
+
const RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_ID}`;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Abstract Data Starlight theme plugin.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```js
|
|
50
|
+
* // astro.config.mjs
|
|
51
|
+
* import abstractData from '@abstractdata/starlight-theme';
|
|
52
|
+
*
|
|
53
|
+
* starlight({
|
|
54
|
+
* plugins: [abstractData({ motion: 'full', version: 'v1.4.2' })],
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export default function abstractDataTheme(
|
|
59
|
+
opts: AbstractDataThemeConfig = {},
|
|
60
|
+
): StarlightPlugin {
|
|
61
|
+
const motion = opts.motion ?? 'full';
|
|
62
|
+
const credit = opts.credit ?? 'auto';
|
|
63
|
+
const version = opts.version ?? null;
|
|
64
|
+
const shiki = opts.shiki ?? true;
|
|
65
|
+
|
|
66
|
+
const runtimeConfig = JSON.stringify({ motion, credit, version });
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
name: PLUGIN_NAME,
|
|
70
|
+
hooks: {
|
|
71
|
+
'config:setup'({ updateConfig, addIntegration, logger }) {
|
|
72
|
+
const customCss: string[] = [
|
|
73
|
+
'@abstractdata/starlight-theme/styles/theme.css',
|
|
74
|
+
];
|
|
75
|
+
if (motion === 'full') {
|
|
76
|
+
customCss.push('@abstractdata/starlight-theme/styles/hud.css');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const updates: Parameters<typeof updateConfig>[0] = {
|
|
80
|
+
customCss,
|
|
81
|
+
components: {
|
|
82
|
+
SocialIcons:
|
|
83
|
+
'@abstractdata/starlight-theme/components/SocialIcons.astro',
|
|
84
|
+
Footer:
|
|
85
|
+
'@abstractdata/starlight-theme/components/Footer.astro',
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
if (shiki) {
|
|
90
|
+
// Branded code-block syntax. First theme = dark, second = light;
|
|
91
|
+
// expressive-code auto-switches based on Starlight's data-theme.
|
|
92
|
+
updates.expressiveCode = {
|
|
93
|
+
themes: [abstractDataDark, abstractDataLight],
|
|
94
|
+
styleOverrides: {
|
|
95
|
+
borderRadius: '8px',
|
|
96
|
+
borderColor: 'var(--sl-color-hairline)',
|
|
97
|
+
codeFontFamily: "'JetBrains Mono', ui-monospace, monospace",
|
|
98
|
+
uiFontFamily: "'Inter', system-ui, sans-serif",
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
updateConfig(updates);
|
|
104
|
+
|
|
105
|
+
// Inject the runtime config as a Vite virtual module so components
|
|
106
|
+
// (SocialIcons, Footer, Glitch) can import it without a build step.
|
|
107
|
+
addIntegration({
|
|
108
|
+
name: '@abstractdata/starlight-theme/runtime',
|
|
109
|
+
hooks: {
|
|
110
|
+
'astro:config:setup': ({ updateConfig: updateAstroConfig }) => {
|
|
111
|
+
updateAstroConfig({
|
|
112
|
+
vite: {
|
|
113
|
+
plugins: [
|
|
114
|
+
{
|
|
115
|
+
name: 'abstractdata-virtual-config',
|
|
116
|
+
resolveId(id) {
|
|
117
|
+
if (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID;
|
|
118
|
+
return null;
|
|
119
|
+
},
|
|
120
|
+
load(id) {
|
|
121
|
+
if (id === RESOLVED_VIRTUAL_ID) {
|
|
122
|
+
return `export const config = ${runtimeConfig};`;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
logger.info(
|
|
135
|
+
`Abstract Data theme · motion: ${motion} · credit: ${credit}` +
|
|
136
|
+
(version ? ` · version: ${version}` : '') +
|
|
137
|
+
(shiki ? ' · shiki: branded' : ' · shiki: user-managed'),
|
|
138
|
+
);
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract Data — Shiki dark theme.
|
|
3
|
+
* Used by expressive-code in HUD/Calm dark mode.
|
|
4
|
+
*/
|
|
5
|
+
export const abstractDataDark = {
|
|
6
|
+
name: 'abstract-data-dark',
|
|
7
|
+
type: 'dark',
|
|
8
|
+
semanticHighlighting: true,
|
|
9
|
+
colors: {
|
|
10
|
+
'editor.background': '#0c0d11',
|
|
11
|
+
'editor.foreground': '#f0f0f5',
|
|
12
|
+
'editor.lineHighlightBackground': '#14151a',
|
|
13
|
+
'editorLineNumber.foreground': '#5a5b62',
|
|
14
|
+
'editorLineNumber.activeForeground': '#00d9ff',
|
|
15
|
+
'editor.selectionBackground': '#00d9ff2e',
|
|
16
|
+
'editor.findMatchHighlightBackground': '#d4af3733',
|
|
17
|
+
},
|
|
18
|
+
tokenColors: [
|
|
19
|
+
{
|
|
20
|
+
scope: ['comment', 'punctuation.definition.comment'],
|
|
21
|
+
settings: { foreground: '#5a5b62', fontStyle: 'italic' },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
scope: [
|
|
25
|
+
'keyword',
|
|
26
|
+
'storage',
|
|
27
|
+
'storage.type',
|
|
28
|
+
'storage.modifier',
|
|
29
|
+
'keyword.control',
|
|
30
|
+
'keyword.operator.new',
|
|
31
|
+
'keyword.operator.expression',
|
|
32
|
+
],
|
|
33
|
+
settings: { foreground: '#00d9ff' },
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
scope: [
|
|
37
|
+
'string',
|
|
38
|
+
'string.quoted',
|
|
39
|
+
'string.template',
|
|
40
|
+
'punctuation.definition.string',
|
|
41
|
+
],
|
|
42
|
+
settings: { foreground: '#d4af37' },
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
scope: ['constant.numeric', 'constant.language', 'constant.character'],
|
|
46
|
+
settings: { foreground: '#c04a5b' },
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
scope: [
|
|
50
|
+
'entity.name.function',
|
|
51
|
+
'support.function',
|
|
52
|
+
'meta.function-call entity.name.function',
|
|
53
|
+
],
|
|
54
|
+
settings: { foreground: '#c0e0ff' },
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
scope: ['variable', 'variable.parameter', 'variable.other'],
|
|
58
|
+
settings: { foreground: '#f0f0f5' },
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
scope: ['entity.name.type', 'support.type', 'support.class', 'entity.name.class'],
|
|
62
|
+
settings: { foreground: '#d4af37' },
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
scope: ['entity.name.tag', 'meta.tag'],
|
|
66
|
+
settings: { foreground: '#00d9ff' },
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
scope: ['entity.other.attribute-name'],
|
|
70
|
+
settings: { foreground: '#d4af37' },
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
scope: ['punctuation', 'meta.brace', 'meta.delimiter'],
|
|
74
|
+
settings: { foreground: '#8a8a93' },
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
scope: ['keyword.operator', 'meta.operator'],
|
|
78
|
+
settings: { foreground: '#8a8a93' },
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
scope: ['markup.heading'],
|
|
82
|
+
settings: { foreground: '#00d9ff', fontStyle: 'bold' },
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
scope: ['markup.bold'],
|
|
86
|
+
settings: { fontStyle: 'bold' },
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
scope: ['markup.italic'],
|
|
90
|
+
settings: { fontStyle: 'italic' },
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
scope: ['markup.inserted'],
|
|
94
|
+
settings: { foreground: '#00d9ff' },
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
scope: ['markup.deleted'],
|
|
98
|
+
settings: { foreground: '#c04a5b' },
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
} as const;
|
|
102
|
+
|
|
103
|
+
export default abstractDataDark;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract Data — Shiki light theme.
|
|
3
|
+
* Used by expressive-code in HUD/Calm light mode.
|
|
4
|
+
*/
|
|
5
|
+
export const abstractDataLight = {
|
|
6
|
+
name: 'abstract-data-light',
|
|
7
|
+
type: 'light',
|
|
8
|
+
semanticHighlighting: true,
|
|
9
|
+
colors: {
|
|
10
|
+
'editor.background': '#f4efe5',
|
|
11
|
+
'editor.foreground': '#1a1a1a',
|
|
12
|
+
'editor.lineHighlightBackground': '#ece5d5',
|
|
13
|
+
'editorLineNumber.foreground': '#8e8a7e',
|
|
14
|
+
'editorLineNumber.activeForeground': '#7a1f2c',
|
|
15
|
+
'editor.selectionBackground': '#007a8e2e',
|
|
16
|
+
'editor.findMatchHighlightBackground': '#8a6d1f40',
|
|
17
|
+
},
|
|
18
|
+
tokenColors: [
|
|
19
|
+
{
|
|
20
|
+
scope: ['comment', 'punctuation.definition.comment'],
|
|
21
|
+
settings: { foreground: '#8e8a7e', fontStyle: 'italic' },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
scope: [
|
|
25
|
+
'keyword',
|
|
26
|
+
'storage',
|
|
27
|
+
'storage.type',
|
|
28
|
+
'storage.modifier',
|
|
29
|
+
'keyword.control',
|
|
30
|
+
'keyword.operator.new',
|
|
31
|
+
'keyword.operator.expression',
|
|
32
|
+
],
|
|
33
|
+
settings: { foreground: '#7a1f2c' },
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
scope: [
|
|
37
|
+
'string',
|
|
38
|
+
'string.quoted',
|
|
39
|
+
'string.template',
|
|
40
|
+
'punctuation.definition.string',
|
|
41
|
+
],
|
|
42
|
+
settings: { foreground: '#8a6d1f' },
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
scope: ['constant.numeric', 'constant.language', 'constant.character'],
|
|
46
|
+
settings: { foreground: '#7a1f2c' },
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
scope: [
|
|
50
|
+
'entity.name.function',
|
|
51
|
+
'support.function',
|
|
52
|
+
'meta.function-call entity.name.function',
|
|
53
|
+
],
|
|
54
|
+
settings: { foreground: '#007a8e' },
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
scope: ['variable', 'variable.parameter', 'variable.other'],
|
|
58
|
+
settings: { foreground: '#1a1a1a' },
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
scope: ['entity.name.type', 'support.type', 'support.class', 'entity.name.class'],
|
|
62
|
+
settings: { foreground: '#8a6d1f' },
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
scope: ['entity.name.tag', 'meta.tag'],
|
|
66
|
+
settings: { foreground: '#7a1f2c' },
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
scope: ['entity.other.attribute-name'],
|
|
70
|
+
settings: { foreground: '#007a8e' },
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
scope: ['punctuation', 'meta.brace', 'meta.delimiter'],
|
|
74
|
+
settings: { foreground: '#5e5e66' },
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
scope: ['keyword.operator', 'meta.operator'],
|
|
78
|
+
settings: { foreground: '#5e5e66' },
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
scope: ['markup.heading'],
|
|
82
|
+
settings: { foreground: '#7a1f2c', fontStyle: 'bold' },
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
scope: ['markup.bold'],
|
|
86
|
+
settings: { fontStyle: 'bold' },
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
scope: ['markup.italic'],
|
|
90
|
+
settings: { fontStyle: 'italic' },
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
scope: ['markup.inserted'],
|
|
94
|
+
settings: { foreground: '#007a8e' },
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
scope: ['markup.deleted'],
|
|
98
|
+
settings: { foreground: '#7a1f2c' },
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
} as const;
|
|
102
|
+
|
|
103
|
+
export default abstractDataLight;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branded Shiki / expressive-code themes.
|
|
3
|
+
*
|
|
4
|
+
* The theme plugin applies these by default. Consumers can opt out by
|
|
5
|
+
* passing their own `expressiveCode.themes` in `astro.config.mjs` —
|
|
6
|
+
* Starlight's config wins over plugin defaults.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```js
|
|
10
|
+
* import { abstractDataThemes } from '@abstractdata/starlight-theme/shiki';
|
|
11
|
+
*
|
|
12
|
+
* starlight({
|
|
13
|
+
* expressiveCode: { themes: abstractDataThemes },
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export { abstractDataDark } from './abstract-data-dark.ts';
|
|
18
|
+
export { abstractDataLight } from './abstract-data-light.ts';
|
|
19
|
+
|
|
20
|
+
import { abstractDataDark } from './abstract-data-dark.ts';
|
|
21
|
+
import { abstractDataLight } from './abstract-data-light.ts';
|
|
22
|
+
|
|
23
|
+
/** Tuple [dark, light] suitable for Starlight's `expressiveCode.themes`. */
|
|
24
|
+
export const abstractDataThemes = [abstractDataDark, abstractDataLight] as const;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
@abstractdata/starlight-theme — hud.css
|
|
3
|
+
Loaded only when motion: 'full'. Animated decoration on top of theme.css.
|
|
4
|
+
Auto-collapses via @media (prefers-reduced-motion: reduce).
|
|
5
|
+
============================================================ */
|
|
6
|
+
|
|
7
|
+
/* ------------------------------------------------------------
|
|
8
|
+
Hexagon grid background on main content
|
|
9
|
+
------------------------------------------------------------ */
|
|
10
|
+
.main-frame .main-pane,
|
|
11
|
+
[data-has-toc] .main-pane {
|
|
12
|
+
position: relative;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.main-frame .main-pane::before {
|
|
16
|
+
content: '';
|
|
17
|
+
position: absolute;
|
|
18
|
+
inset: 0;
|
|
19
|
+
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='87' viewBox='0 0 100 87'><path d='M25 0L50 14.43V43.3L25 57.74L0 43.3V14.43L25 0Z M75 0L100 14.43V43.3L75 57.74L50 43.3V14.43L75 0Z M50 43.3L75 57.74V86.6L50 101L25 86.6V57.74L50 43.3Z' fill='none' stroke='%2300d9ff' stroke-width='0.5' opacity='0.18'/></svg>");
|
|
20
|
+
background-size: 100px 87px;
|
|
21
|
+
pointer-events: none;
|
|
22
|
+
z-index: 0;
|
|
23
|
+
opacity: 0.55;
|
|
24
|
+
animation: ad-hex-pulse 5s ease-in-out infinite;
|
|
25
|
+
}
|
|
26
|
+
:root[data-theme='light'] .main-frame .main-pane::before {
|
|
27
|
+
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='87' viewBox='0 0 100 87'><path d='M25 0L50 14.43V43.3L25 57.74L0 43.3V14.43L25 0Z M75 0L100 14.43V43.3L75 57.74L50 43.3V14.43L75 0Z M50 43.3L75 57.74V86.6L50 101L25 86.6V57.74L50 43.3Z' fill='none' stroke='%237a1f2c' stroke-width='0.5' opacity='0.18'/></svg>");
|
|
28
|
+
opacity: 1;
|
|
29
|
+
animation: none; /* hex pulse off in light — feels more refined */
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.main-frame .main-pane > * {
|
|
33
|
+
position: relative;
|
|
34
|
+
z-index: 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* ------------------------------------------------------------
|
|
38
|
+
H1 cyan glow + underline fade (covers content h1 and hero h1)
|
|
39
|
+
------------------------------------------------------------ */
|
|
40
|
+
.sl-markdown-content > h1:first-child,
|
|
41
|
+
.content-panel h1[data-page-title],
|
|
42
|
+
.hero h1 {
|
|
43
|
+
text-shadow: 0 0 14px rgba(0, 217, 255, 0.45),
|
|
44
|
+
0 0 28px rgba(0, 217, 255, 0.18);
|
|
45
|
+
}
|
|
46
|
+
.sl-markdown-content > h1:first-child::after,
|
|
47
|
+
.content-panel h1[data-page-title]::after,
|
|
48
|
+
.hero h1::after {
|
|
49
|
+
content: '';
|
|
50
|
+
position: absolute;
|
|
51
|
+
left: 14px;
|
|
52
|
+
right: 0;
|
|
53
|
+
bottom: -8px;
|
|
54
|
+
height: 1px;
|
|
55
|
+
background: linear-gradient(90deg, var(--ad-cyan), transparent);
|
|
56
|
+
opacity: 0.7;
|
|
57
|
+
box-shadow: 0 0 8px rgba(0, 217, 255, 0.5);
|
|
58
|
+
}
|
|
59
|
+
:root[data-theme='light'] .sl-markdown-content > h1:first-child,
|
|
60
|
+
:root[data-theme='light'] .content-panel h1[data-page-title],
|
|
61
|
+
:root[data-theme='light'] .hero h1 {
|
|
62
|
+
text-shadow: none;
|
|
63
|
+
}
|
|
64
|
+
:root[data-theme='light'] .sl-markdown-content > h1:first-child::after,
|
|
65
|
+
:root[data-theme='light'] .content-panel h1[data-page-title]::after,
|
|
66
|
+
:root[data-theme='light'] .hero h1::after {
|
|
67
|
+
background: linear-gradient(90deg, var(--ad-burgundy), transparent);
|
|
68
|
+
opacity: 0.45;
|
|
69
|
+
box-shadow: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* ------------------------------------------------------------
|
|
73
|
+
Active sidebar item — inset glow
|
|
74
|
+
------------------------------------------------------------ */
|
|
75
|
+
.sidebar-pane a[aria-current='page'] {
|
|
76
|
+
box-shadow: inset 0 0 16px rgba(0, 217, 255, 0.18);
|
|
77
|
+
text-shadow: 0 0 8px rgba(0, 217, 255, 0.4);
|
|
78
|
+
}
|
|
79
|
+
:root[data-theme='light'] .sidebar-pane a[aria-current='page'] {
|
|
80
|
+
box-shadow: inset 0 0 12px rgba(0, 122, 142, 0.12);
|
|
81
|
+
text-shadow: none;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* ------------------------------------------------------------
|
|
85
|
+
Code blocks — holographic shimmer + cyan halo
|
|
86
|
+
------------------------------------------------------------ */
|
|
87
|
+
.expressive-code .frame {
|
|
88
|
+
position: relative;
|
|
89
|
+
box-shadow: 0 0 28px rgba(0, 217, 255, 0.12),
|
|
90
|
+
0 0 0 1px rgba(0, 217, 255, 0.18);
|
|
91
|
+
}
|
|
92
|
+
.expressive-code .frame::after {
|
|
93
|
+
content: '';
|
|
94
|
+
position: absolute;
|
|
95
|
+
inset: 0;
|
|
96
|
+
background: linear-gradient(105deg,
|
|
97
|
+
transparent 30%,
|
|
98
|
+
rgba(0, 217, 255, 0.08) 50%,
|
|
99
|
+
transparent 70%);
|
|
100
|
+
background-size: 200% 100%;
|
|
101
|
+
pointer-events: none;
|
|
102
|
+
animation: ad-holographic-shift 6s linear infinite;
|
|
103
|
+
border-radius: inherit;
|
|
104
|
+
}
|
|
105
|
+
:root[data-theme='light'] .expressive-code .frame {
|
|
106
|
+
box-shadow: 0 0 18px rgba(122, 31, 44, 0.06),
|
|
107
|
+
0 0 0 1px rgba(122, 31, 44, 0.12);
|
|
108
|
+
}
|
|
109
|
+
:root[data-theme='light'] .expressive-code .frame::after {
|
|
110
|
+
background: linear-gradient(105deg,
|
|
111
|
+
transparent 30%,
|
|
112
|
+
rgba(122, 31, 44, 0.05) 50%,
|
|
113
|
+
transparent 70%);
|
|
114
|
+
background-size: 200% 100%;
|
|
115
|
+
animation: ad-holographic-shift 8s linear infinite;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* ------------------------------------------------------------
|
|
119
|
+
Callouts — matching color glow
|
|
120
|
+
------------------------------------------------------------ */
|
|
121
|
+
.starlight-aside--tip,
|
|
122
|
+
.starlight-aside--note { box-shadow: 0 0 16px rgba(0, 217, 255, 0.10); }
|
|
123
|
+
.starlight-aside--caution { box-shadow: 0 0 16px rgba(212, 175, 55, 0.10); }
|
|
124
|
+
.starlight-aside--danger { box-shadow: 0 0 16px rgba(192, 74, 91, 0.14); }
|
|
125
|
+
|
|
126
|
+
/* ------------------------------------------------------------
|
|
127
|
+
Animations
|
|
128
|
+
------------------------------------------------------------ */
|
|
129
|
+
@keyframes ad-hex-pulse {
|
|
130
|
+
0%, 100% { opacity: 0.45; }
|
|
131
|
+
50% { opacity: 0.75; }
|
|
132
|
+
}
|
|
133
|
+
@keyframes ad-holographic-shift {
|
|
134
|
+
0% { background-position: -100% 0; }
|
|
135
|
+
100% { background-position: 200% 0; }
|
|
136
|
+
}
|
|
137
|
+
@keyframes ad-glitch-text {
|
|
138
|
+
0%, 95%, 100% { text-shadow: none; }
|
|
139
|
+
96% { text-shadow: -1px 0 var(--ad-magenta), 1px 0 var(--ad-cyan); }
|
|
140
|
+
97% { text-shadow: 1px 0 var(--ad-magenta), -1px 0 var(--ad-cyan); }
|
|
141
|
+
98% { text-shadow: -1px 0 var(--ad-cyan), 1px 0 var(--ad-magenta); }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* ------------------------------------------------------------
|
|
145
|
+
Version chip — gold glow + 9s glitch pulse + hover-trigger
|
|
146
|
+
------------------------------------------------------------ */
|
|
147
|
+
.ad-version-chip {
|
|
148
|
+
box-shadow: 0 0 12px rgba(212, 175, 55, 0.4);
|
|
149
|
+
animation: ad-version-glitch-pulse 9s infinite;
|
|
150
|
+
}
|
|
151
|
+
.ad-version-chip:hover {
|
|
152
|
+
animation: ad-glitch-text 0.4s steps(2);
|
|
153
|
+
}
|
|
154
|
+
:root[data-theme='light'] .ad-version-chip {
|
|
155
|
+
box-shadow: 0 0 10px rgba(138, 109, 31, 0.25);
|
|
156
|
+
animation: none; /* idle pulse off in light mode — feels more refined */
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@keyframes ad-version-glitch-pulse {
|
|
160
|
+
0%, 95%, 100% { text-shadow: none; }
|
|
161
|
+
96% { text-shadow: -1px 0 var(--ad-magenta), 1px 0 var(--ad-cyan); }
|
|
162
|
+
97% { text-shadow: 1px 0 var(--ad-magenta), -1px 0 var(--ad-cyan); }
|
|
163
|
+
98% { text-shadow: -1px 0 var(--ad-cyan), 1px 0 var(--ad-magenta); }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* ------------------------------------------------------------
|
|
167
|
+
<Glitch /> — RGB-channel split with clip-path animation
|
|
168
|
+
------------------------------------------------------------ */
|
|
169
|
+
.ad-glitch::before,
|
|
170
|
+
.ad-glitch::after {
|
|
171
|
+
content: attr(data-text);
|
|
172
|
+
position: absolute;
|
|
173
|
+
top: 0;
|
|
174
|
+
left: 0;
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: 100%;
|
|
177
|
+
opacity: 0.85;
|
|
178
|
+
pointer-events: none;
|
|
179
|
+
}
|
|
180
|
+
.ad-glitch::before {
|
|
181
|
+
color: var(--ad-magenta);
|
|
182
|
+
animation: ad-glitch-clip-a 3s steps(1) infinite;
|
|
183
|
+
}
|
|
184
|
+
.ad-glitch::after {
|
|
185
|
+
color: var(--ad-cyan);
|
|
186
|
+
animation: ad-glitch-clip-b 3s steps(1) infinite;
|
|
187
|
+
}
|
|
188
|
+
:root[data-theme='light'] .ad-glitch::before {
|
|
189
|
+
color: var(--ad-burgundy);
|
|
190
|
+
}
|
|
191
|
+
:root[data-theme='light'] .ad-glitch::after {
|
|
192
|
+
color: var(--ad-cyan-deep);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@keyframes ad-glitch-clip-a {
|
|
196
|
+
0%, 90%, 100% { transform: translate(0); clip-path: inset(100% 0 0 0); }
|
|
197
|
+
91% { transform: translate(-2px, 1px); clip-path: inset(20% 0 60% 0); }
|
|
198
|
+
93% { transform: translate(2px, -1px); clip-path: inset(60% 0 20% 0); }
|
|
199
|
+
95% { transform: translate(-1px, -1px); clip-path: inset(40% 0 40% 0); }
|
|
200
|
+
97% { transform: translate(1px, 0); clip-path: inset(10% 0 80% 0); }
|
|
201
|
+
}
|
|
202
|
+
@keyframes ad-glitch-clip-b {
|
|
203
|
+
0%, 90%, 100% { transform: translate(0); clip-path: inset(100% 0 0 0); }
|
|
204
|
+
91% { transform: translate(2px, -1px); clip-path: inset(60% 0 20% 0); }
|
|
205
|
+
93% { transform: translate(-2px, 1px); clip-path: inset(20% 0 60% 0); }
|
|
206
|
+
95% { transform: translate(1px, 1px); clip-path: inset(50% 0 30% 0); }
|
|
207
|
+
97% { transform: translate(-1px, 0); clip-path: inset(70% 0 10% 0); }
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* ------------------------------------------------------------
|
|
211
|
+
prefers-reduced-motion: collapse to Calm behavior
|
|
212
|
+
------------------------------------------------------------ */
|
|
213
|
+
@media (prefers-reduced-motion: reduce) {
|
|
214
|
+
.main-frame .main-pane::before,
|
|
215
|
+
.expressive-code .frame::after,
|
|
216
|
+
.ad-version-chip,
|
|
217
|
+
.ad-glitch::before,
|
|
218
|
+
.ad-glitch::after {
|
|
219
|
+
animation: none !important;
|
|
220
|
+
}
|
|
221
|
+
.ad-glitch::before,
|
|
222
|
+
.ad-glitch::after {
|
|
223
|
+
display: none;
|
|
224
|
+
}
|
|
225
|
+
.sl-markdown-content > h1:first-child,
|
|
226
|
+
.content-panel h1[data-page-title] {
|
|
227
|
+
text-shadow: none;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
@abstractdata/starlight-theme — theme.css
|
|
3
|
+
Always loaded. Brand palette, typography, signature decoration.
|
|
4
|
+
============================================================ */
|
|
5
|
+
|
|
6
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Orbitron:wght@500;600;700;800&display=swap');
|
|
7
|
+
|
|
8
|
+
/* ------------------------------------------------------------
|
|
9
|
+
Palette tokens — overridden onto Starlight's CSS vars
|
|
10
|
+
------------------------------------------------------------ */
|
|
11
|
+
:root {
|
|
12
|
+
/* Brand atoms (always available regardless of theme) */
|
|
13
|
+
--ad-cyan: #00d9ff;
|
|
14
|
+
--ad-cyan-deep: #007a8e;
|
|
15
|
+
--ad-gold: #d4af37;
|
|
16
|
+
--ad-gold-deep: #8a6d1f;
|
|
17
|
+
--ad-burgundy: #8b2635;
|
|
18
|
+
--ad-burgundy-deep: #7a1f2c;
|
|
19
|
+
--ad-magenta: #ff00de;
|
|
20
|
+
--ad-charcoal: #0a0a0a;
|
|
21
|
+
--ad-surface-dark: #101116;
|
|
22
|
+
--ad-cream: #faf7f2;
|
|
23
|
+
|
|
24
|
+
/* Typography */
|
|
25
|
+
--sl-font: 'Inter', system-ui, -apple-system, sans-serif;
|
|
26
|
+
--sl-font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
|
|
27
|
+
--ad-font-display: 'Orbitron', sans-serif;
|
|
28
|
+
|
|
29
|
+
/* Sizing tweaks */
|
|
30
|
+
--sl-content-width: 52rem;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* ------------------------------------------------------------
|
|
34
|
+
Dark theme (HUD Dark / Calm Dark — same palette)
|
|
35
|
+
------------------------------------------------------------ */
|
|
36
|
+
:root[data-theme='dark'] {
|
|
37
|
+
--sl-color-accent-low: rgba(0, 217, 255, 0.10);
|
|
38
|
+
--sl-color-accent: var(--ad-cyan);
|
|
39
|
+
--sl-color-accent-high: var(--ad-cyan);
|
|
40
|
+
--sl-color-text-accent: var(--ad-cyan);
|
|
41
|
+
|
|
42
|
+
--sl-color-bg: var(--ad-charcoal);
|
|
43
|
+
--sl-color-bg-nav: var(--ad-surface-dark);
|
|
44
|
+
--sl-color-bg-sidebar: var(--ad-surface-dark);
|
|
45
|
+
--sl-color-bg-inline-code: #14151a;
|
|
46
|
+
--sl-color-hairline: #2a2c34;
|
|
47
|
+
--sl-color-hairline-light: #25262d;
|
|
48
|
+
--sl-color-hairline-shade: #1a1b20;
|
|
49
|
+
|
|
50
|
+
--sl-color-text: #f0f0f5;
|
|
51
|
+
--sl-color-text-invert: var(--ad-charcoal);
|
|
52
|
+
--sl-color-gray-1: #ffffff;
|
|
53
|
+
--sl-color-gray-2: #d8d8df;
|
|
54
|
+
--sl-color-gray-3: #b8b8c0;
|
|
55
|
+
--sl-color-gray-4: #8a8a93;
|
|
56
|
+
--sl-color-gray-5: #5a5b62;
|
|
57
|
+
--sl-color-gray-6: #2a2c34;
|
|
58
|
+
|
|
59
|
+
--ad-text-dim: #8a8a93;
|
|
60
|
+
--ad-callout-cyan-bg: rgba(0, 217, 255, 0.06);
|
|
61
|
+
--ad-callout-gold-bg: rgba(212, 175, 55, 0.06);
|
|
62
|
+
--ad-callout-burgundy-bg: rgba(192, 74, 91, 0.08);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* ------------------------------------------------------------
|
|
66
|
+
Light theme (cream / burgundy / deeper teal)
|
|
67
|
+
------------------------------------------------------------ */
|
|
68
|
+
:root[data-theme='light'] {
|
|
69
|
+
--sl-color-accent-low: rgba(0, 122, 142, 0.10);
|
|
70
|
+
--sl-color-accent: var(--ad-cyan-deep);
|
|
71
|
+
--sl-color-accent-high: var(--ad-cyan-deep);
|
|
72
|
+
--sl-color-text-accent: var(--ad-cyan-deep);
|
|
73
|
+
|
|
74
|
+
--sl-color-bg: var(--ad-cream);
|
|
75
|
+
--sl-color-bg-nav: #ffffff;
|
|
76
|
+
--sl-color-bg-sidebar: #ffffff;
|
|
77
|
+
--sl-color-bg-inline-code: #f4efe5;
|
|
78
|
+
--sl-color-hairline: #d8d0bf;
|
|
79
|
+
--sl-color-hairline-light: #e6dfd1;
|
|
80
|
+
--sl-color-hairline-shade: #ece5d5;
|
|
81
|
+
|
|
82
|
+
--sl-color-text: #18181c;
|
|
83
|
+
--sl-color-text-invert: #ffffff;
|
|
84
|
+
--sl-color-gray-1: #0a0a0a;
|
|
85
|
+
--sl-color-gray-2: #18181c;
|
|
86
|
+
--sl-color-gray-3: #2a2a30;
|
|
87
|
+
--sl-color-gray-4: #5e5e66;
|
|
88
|
+
--sl-color-gray-5: #8e8a7e;
|
|
89
|
+
--sl-color-gray-6: #d8d0bf;
|
|
90
|
+
|
|
91
|
+
--ad-text-dim: #5e5e66;
|
|
92
|
+
--ad-callout-cyan-bg: rgba(0, 122, 142, 0.06);
|
|
93
|
+
--ad-callout-gold-bg: rgba(138, 109, 31, 0.08);
|
|
94
|
+
--ad-callout-burgundy-bg: rgba(122, 31, 44, 0.06);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* ------------------------------------------------------------
|
|
98
|
+
Display typography — Orbitron on hero + h1/h2 only
|
|
99
|
+
(h3+ stays in Inter for body readability)
|
|
100
|
+
------------------------------------------------------------ */
|
|
101
|
+
.sl-markdown-content h1,
|
|
102
|
+
.sl-markdown-content h2,
|
|
103
|
+
header.header .site-title,
|
|
104
|
+
.sidebar-pane .group-label,
|
|
105
|
+
.content-panel h1[data-page-title] {
|
|
106
|
+
font-family: var(--ad-font-display);
|
|
107
|
+
letter-spacing: 0.01em;
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Site title in top nav */
|
|
112
|
+
header.header .site-title {
|
|
113
|
+
font-size: 0.85rem;
|
|
114
|
+
letter-spacing: 0.16em;
|
|
115
|
+
text-transform: uppercase;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* Sidebar group labels */
|
|
119
|
+
.sidebar-pane .group-label,
|
|
120
|
+
.sidebar-pane .group-label > span {
|
|
121
|
+
font-family: var(--ad-font-display);
|
|
122
|
+
font-size: 0.7rem;
|
|
123
|
+
letter-spacing: 0.16em;
|
|
124
|
+
text-transform: uppercase;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* ------------------------------------------------------------
|
|
128
|
+
H1 signature: cyan→gold gradient bracket bar on the left
|
|
129
|
+
------------------------------------------------------------ */
|
|
130
|
+
.sl-markdown-content > h1:first-child,
|
|
131
|
+
.content-panel h1[data-page-title],
|
|
132
|
+
.hero h1 {
|
|
133
|
+
position: relative;
|
|
134
|
+
padding-left: 14px;
|
|
135
|
+
}
|
|
136
|
+
.sl-markdown-content > h1:first-child::before,
|
|
137
|
+
.content-panel h1[data-page-title]::before,
|
|
138
|
+
.hero h1::before {
|
|
139
|
+
content: '';
|
|
140
|
+
position: absolute;
|
|
141
|
+
left: 0;
|
|
142
|
+
top: 0.3em;
|
|
143
|
+
bottom: 0.3em;
|
|
144
|
+
width: 3px;
|
|
145
|
+
background: linear-gradient(180deg, var(--ad-cyan), var(--ad-gold));
|
|
146
|
+
}
|
|
147
|
+
:root[data-theme='light'] .sl-markdown-content > h1:first-child::before,
|
|
148
|
+
:root[data-theme='light'] .content-panel h1[data-page-title]::before,
|
|
149
|
+
:root[data-theme='light'] .hero h1::before {
|
|
150
|
+
background: linear-gradient(180deg, var(--ad-cyan-deep), var(--ad-burgundy));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* ------------------------------------------------------------
|
|
154
|
+
Inline code — gold on dark, burgundy on light
|
|
155
|
+
------------------------------------------------------------ */
|
|
156
|
+
.sl-markdown-content :not(pre) > code {
|
|
157
|
+
color: var(--ad-gold);
|
|
158
|
+
border: 1px solid var(--sl-color-hairline);
|
|
159
|
+
border-radius: 4px;
|
|
160
|
+
padding: 1px 6px;
|
|
161
|
+
font-size: 0.9em;
|
|
162
|
+
}
|
|
163
|
+
:root[data-theme='light'] .sl-markdown-content :not(pre) > code {
|
|
164
|
+
color: var(--ad-burgundy-deep);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* ------------------------------------------------------------
|
|
168
|
+
Callouts (asides) — branded variants
|
|
169
|
+
------------------------------------------------------------ */
|
|
170
|
+
.starlight-aside {
|
|
171
|
+
border-left-width: 3px;
|
|
172
|
+
border-radius: 8px;
|
|
173
|
+
background: var(--ad-callout-cyan-bg);
|
|
174
|
+
}
|
|
175
|
+
.starlight-aside--tip { border-color: var(--ad-cyan); background: var(--ad-callout-cyan-bg); }
|
|
176
|
+
.starlight-aside--note { border-color: var(--ad-cyan); background: var(--ad-callout-cyan-bg); }
|
|
177
|
+
.starlight-aside--caution { border-color: var(--ad-gold); background: var(--ad-callout-gold-bg); }
|
|
178
|
+
.starlight-aside--danger { border-color: var(--ad-burgundy); background: var(--ad-callout-burgundy-bg); }
|
|
179
|
+
:root[data-theme='light'] .starlight-aside--tip,
|
|
180
|
+
:root[data-theme='light'] .starlight-aside--note { border-color: var(--ad-cyan-deep); }
|
|
181
|
+
:root[data-theme='light'] .starlight-aside--caution { border-color: var(--ad-gold-deep); }
|
|
182
|
+
:root[data-theme='light'] .starlight-aside--danger { border-color: var(--ad-burgundy-deep); }
|
|
183
|
+
|
|
184
|
+
.starlight-aside__title {
|
|
185
|
+
font-family: var(--ad-font-display);
|
|
186
|
+
font-size: 0.7rem;
|
|
187
|
+
letter-spacing: 0.16em;
|
|
188
|
+
text-transform: uppercase;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* ------------------------------------------------------------
|
|
192
|
+
Code blocks — bracket dot indicator + cyan border accent
|
|
193
|
+
------------------------------------------------------------ */
|
|
194
|
+
.expressive-code .frame.is-terminal,
|
|
195
|
+
.expressive-code .frame.has-title {
|
|
196
|
+
border: 1px solid var(--sl-color-hairline);
|
|
197
|
+
border-radius: 8px;
|
|
198
|
+
overflow: hidden;
|
|
199
|
+
}
|
|
200
|
+
.expressive-code .frame .header {
|
|
201
|
+
font-family: var(--sl-font-mono);
|
|
202
|
+
font-size: 0.7rem;
|
|
203
|
+
letter-spacing: 0.05em;
|
|
204
|
+
border-bottom: 1px solid var(--sl-color-hairline);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* ------------------------------------------------------------
|
|
208
|
+
Sidebar — active item with cyan border + faint fill
|
|
209
|
+
------------------------------------------------------------ */
|
|
210
|
+
.sidebar-pane a[aria-current='page'] {
|
|
211
|
+
color: var(--ad-cyan);
|
|
212
|
+
border-left: 2px solid var(--ad-cyan);
|
|
213
|
+
background: var(--sl-color-accent-low);
|
|
214
|
+
font-weight: 500;
|
|
215
|
+
}
|
|
216
|
+
:root[data-theme='light'] .sidebar-pane a[aria-current='page'] {
|
|
217
|
+
color: var(--ad-cyan-deep);
|
|
218
|
+
border-left-color: var(--ad-cyan-deep);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* ------------------------------------------------------------
|
|
222
|
+
Search box — bracket frame motif
|
|
223
|
+
------------------------------------------------------------ */
|
|
224
|
+
site-search button[data-open-modal] {
|
|
225
|
+
border: 1px solid var(--sl-color-hairline);
|
|
226
|
+
border-radius: 6px;
|
|
227
|
+
font-family: var(--sl-font-mono);
|
|
228
|
+
}
|
|
229
|
+
site-search button[data-open-modal] kbd {
|
|
230
|
+
font-family: var(--sl-font-mono);
|
|
231
|
+
font-size: 0.65rem;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* ------------------------------------------------------------
|
|
235
|
+
Version chip — outlined gold pill in the header
|
|
236
|
+
(Static look. HUD layers on glitch in hud.css.)
|
|
237
|
+
------------------------------------------------------------ */
|
|
238
|
+
.ad-version-chip {
|
|
239
|
+
display: inline-flex;
|
|
240
|
+
align-items: center;
|
|
241
|
+
font-family: var(--sl-font-mono);
|
|
242
|
+
font-size: 0.7rem;
|
|
243
|
+
padding: 3px 8px;
|
|
244
|
+
margin-left: 8px;
|
|
245
|
+
color: var(--ad-gold);
|
|
246
|
+
border: 1px solid var(--ad-gold);
|
|
247
|
+
border-radius: 4px;
|
|
248
|
+
letter-spacing: 0.04em;
|
|
249
|
+
user-select: none;
|
|
250
|
+
cursor: default;
|
|
251
|
+
position: relative;
|
|
252
|
+
}
|
|
253
|
+
:root[data-theme='light'] .ad-version-chip {
|
|
254
|
+
color: var(--ad-gold-deep);
|
|
255
|
+
border-color: var(--ad-gold-deep);
|
|
256
|
+
background: rgba(138, 109, 31, 0.08);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* ------------------------------------------------------------
|
|
260
|
+
"Built by Abstract Data" credit
|
|
261
|
+
Hidden when the plugin is configured with `credit: 'hide'`.
|
|
262
|
+
------------------------------------------------------------ */
|
|
263
|
+
.ad-credit {
|
|
264
|
+
margin-top: 1.5rem;
|
|
265
|
+
padding-top: 1rem;
|
|
266
|
+
border-top: 1px solid var(--sl-color-hairline-light);
|
|
267
|
+
font-family: var(--ad-font-display);
|
|
268
|
+
font-size: 0.7rem;
|
|
269
|
+
letter-spacing: 0.16em;
|
|
270
|
+
text-transform: uppercase;
|
|
271
|
+
color: var(--sl-color-gray-4);
|
|
272
|
+
display: flex;
|
|
273
|
+
gap: 6px;
|
|
274
|
+
align-items: center;
|
|
275
|
+
}
|
|
276
|
+
.ad-credit a {
|
|
277
|
+
color: var(--ad-cyan);
|
|
278
|
+
text-decoration: none;
|
|
279
|
+
font-weight: 600;
|
|
280
|
+
}
|
|
281
|
+
.ad-credit a:hover { text-decoration: underline; }
|
|
282
|
+
:root[data-theme='light'] .ad-credit a { color: var(--ad-cyan-deep); }
|
|
283
|
+
|
|
284
|
+
/* ------------------------------------------------------------
|
|
285
|
+
<Glitch /> base — clean render under motion: 'calm'
|
|
286
|
+
HUD layers on the actual glitch animation in hud.css.
|
|
287
|
+
------------------------------------------------------------ */
|
|
288
|
+
.ad-glitch {
|
|
289
|
+
position: relative;
|
|
290
|
+
display: inline-block;
|
|
291
|
+
font-family: var(--ad-font-display);
|
|
292
|
+
font-weight: 700;
|
|
293
|
+
letter-spacing: 0.02em;
|
|
294
|
+
color: var(--ad-cyan);
|
|
295
|
+
}
|
|
296
|
+
:root[data-theme='light'] .ad-glitch {
|
|
297
|
+
color: var(--ad-burgundy);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* ------------------------------------------------------------
|
|
301
|
+
Splash page hero — constrain logo width on wide screens
|
|
302
|
+
------------------------------------------------------------ */
|
|
303
|
+
.hero .hero-html img,
|
|
304
|
+
.hero img[alt][src] {
|
|
305
|
+
max-width: 360px;
|
|
306
|
+
width: 100%;
|
|
307
|
+
height: auto;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* ------------------------------------------------------------
|
|
311
|
+
Hero action buttons — primary cyan, secondary gold ghost
|
|
312
|
+
(Starlight uses .sl-link-button.primary / .secondary inside .hero .actions)
|
|
313
|
+
------------------------------------------------------------ */
|
|
314
|
+
.hero .actions .sl-link-button.primary {
|
|
315
|
+
background: var(--ad-cyan);
|
|
316
|
+
color: var(--ad-charcoal);
|
|
317
|
+
border: 1px solid var(--ad-cyan);
|
|
318
|
+
font-family: var(--ad-font-display);
|
|
319
|
+
font-size: 0.8rem;
|
|
320
|
+
letter-spacing: 0.12em;
|
|
321
|
+
text-transform: uppercase;
|
|
322
|
+
}
|
|
323
|
+
.hero .actions .sl-link-button.primary:hover {
|
|
324
|
+
box-shadow: 0 0 24px rgba(0, 217, 255, 0.5);
|
|
325
|
+
}
|
|
326
|
+
.hero .actions .sl-link-button.secondary,
|
|
327
|
+
.hero .actions .sl-link-button.minimal {
|
|
328
|
+
background: transparent;
|
|
329
|
+
color: var(--ad-gold);
|
|
330
|
+
border: 1px solid var(--ad-gold);
|
|
331
|
+
font-family: var(--ad-font-display);
|
|
332
|
+
font-size: 0.8rem;
|
|
333
|
+
letter-spacing: 0.12em;
|
|
334
|
+
text-transform: uppercase;
|
|
335
|
+
}
|
|
336
|
+
.hero .actions .sl-link-button.secondary:hover,
|
|
337
|
+
.hero .actions .sl-link-button.minimal:hover {
|
|
338
|
+
background: rgba(212, 175, 55, 0.10);
|
|
339
|
+
color: var(--ad-gold);
|
|
340
|
+
}
|
|
341
|
+
:root[data-theme='light'] .hero .actions .sl-link-button.primary {
|
|
342
|
+
background: var(--ad-cyan-deep);
|
|
343
|
+
color: #ffffff;
|
|
344
|
+
border-color: var(--ad-cyan-deep);
|
|
345
|
+
}
|
|
346
|
+
:root[data-theme='light'] .hero .actions .sl-link-button.secondary,
|
|
347
|
+
:root[data-theme='light'] .hero .actions .sl-link-button.minimal {
|
|
348
|
+
color: var(--ad-burgundy-deep);
|
|
349
|
+
border-color: var(--ad-burgundy-deep);
|
|
350
|
+
}
|
|
351
|
+
:root[data-theme='light'] .hero .actions .sl-link-button.secondary:hover,
|
|
352
|
+
:root[data-theme='light'] .hero .actions .sl-link-button.minimal:hover {
|
|
353
|
+
background: rgba(122, 31, 44, 0.06);
|
|
354
|
+
color: var(--ad-burgundy-deep);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* ------------------------------------------------------------
|
|
358
|
+
"On this page" right sidebar (TOC) — branded
|
|
359
|
+
------------------------------------------------------------ */
|
|
360
|
+
.right-sidebar h2,
|
|
361
|
+
.right-sidebar-panel h2 {
|
|
362
|
+
font-family: var(--ad-font-display);
|
|
363
|
+
font-size: 0.7rem;
|
|
364
|
+
font-weight: 700;
|
|
365
|
+
letter-spacing: 0.16em;
|
|
366
|
+
text-transform: uppercase;
|
|
367
|
+
color: var(--sl-color-gray-3);
|
|
368
|
+
}
|
|
369
|
+
.right-sidebar a[aria-current='true'],
|
|
370
|
+
starlight-toc a[aria-current='true'] {
|
|
371
|
+
color: var(--ad-cyan);
|
|
372
|
+
border-left: 2px solid var(--ad-cyan);
|
|
373
|
+
padding-left: 8px;
|
|
374
|
+
margin-left: -10px;
|
|
375
|
+
}
|
|
376
|
+
:root[data-theme='light'] .right-sidebar a[aria-current='true'],
|
|
377
|
+
:root[data-theme='light'] starlight-toc a[aria-current='true'] {
|
|
378
|
+
color: var(--ad-cyan-deep);
|
|
379
|
+
border-left-color: var(--ad-cyan-deep);
|
|
380
|
+
}
|
package/src/types.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Virtual module exposed by @abstractdata/starlight-theme.
|
|
3
|
+
* Available inside Astro components after the plugin is registered.
|
|
4
|
+
*
|
|
5
|
+
* Reference this in your project's `env.d.ts`:
|
|
6
|
+
* ```ts
|
|
7
|
+
* /// <reference types="@abstractdata/starlight-theme/types" />
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
declare module 'virtual:abstractdata/config' {
|
|
11
|
+
export const config: {
|
|
12
|
+
motion: 'full' | 'calm';
|
|
13
|
+
credit: 'auto' | 'hide';
|
|
14
|
+
version: string | null;
|
|
15
|
+
};
|
|
16
|
+
}
|