slidev-theme-entaina 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Entaina
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # slidev-theme-entaina
2
+
3
+ Tema de marca Entaina para [Slidev](https://sli.dev): look dirigido por tokens (mapeados del design system oficial), chrome de navegación propio y las tres variantes de pilar. Light-only por diseño.
4
+
5
+ ## Uso
6
+
7
+ ```bash
8
+ npm i -D slidev-theme-entaina
9
+ # o, mientras no esté publicado en npm:
10
+ npm i -D github:Entaina/slidev-theme-entaina
11
+ ```
12
+
13
+ ```yaml
14
+ ---
15
+ theme: slidev-theme-entaina
16
+ ---
17
+ ```
18
+
19
+ Las fuentes (Lato, Comfortaa, JetBrains Mono, pesos 300–700) llegan como defaults del tema; el deck no necesita bloque `fonts:`.
20
+
21
+ ## Qué incluye
22
+
23
+ - **`styles/tokens.css`** — la paleta Entaina como defaults en `:root`, más las variantes de pilar: `htmlAttrs: { data-theme: technology | innovation | people }` en el headmatter del deck.
24
+ - **`styles/base.css`** — el look, 100% sobre tokens: atmósfera por layout, escala display, kickers `.eyebrow`/`.cover-kicker`, cover/section/quote estilizados, splits a sangre con `.panel .panel-before/.panel-after`, tablas, la portada oscura `layout: cover` + `class: bleed` (con `.bleed-note`), y el reveal de entrada escalonado (respeta `prefers-reduced-motion` y print).
25
+ - **`global-top.vue`** — chrome de navegación: barra de progreso, bolitas laterales que se expanden al hover mostrando títulos, flechas anterior/siguiente y contador `n / total · %`. Se oculta en export y en modo presentador. Teclado, transiciones, overview (`o`) y export siguen siendo de Slidev.
26
+ - **Componentes** (clases sobre HTML plano en las slides):
27
+ - KPI dashboard: `<div class="kpi-grid"><div class="kpi"><b>247</b><span>etiqueta</span></div>…</div>` — cifras display con rotación de colores de pilar, etiquetas mono; valores hero breves (≤6 caracteres).
28
+ - Código: los bloques fenced van en caja navy de marca con tokens oscuros (`setup/shiki.ts`, one-dark-pro en ambos esquemas) y soportan el resaltado de líneas de Slidev (` ```ts {2-3} `). Chip de fichero flotante: `<div class="code-file">worker.ts</div>` justo antes del fence.
29
+ - Kickers semánticos opt-in: `.eyebrow.success` / `.danger` / `.warning` — solo cuando el contenido afirma un estado.
30
+
31
+ ## Personalización
32
+
33
+ El contrato son 27 tokens CSS (ver `styles/tokens.css` y `test/contract.test.mjs`). Para otra paleta, redefine los tokens en el `style.css` del proyecto — las variables cascadan, no hay que tocar el tema:
34
+
35
+ ```css
36
+ /* style.css del deck: ejemplo de paleta alternativa */
37
+ :root {
38
+ --bg: #ffffff;
39
+ --accent: #2563eb;
40
+ /* …resto del contrato… */
41
+ }
42
+ ```
43
+
44
+ Reglas propias del deck: en su `style.css`, en rem ajustado al lienzo 980×552 de Slidev (nunca vw/vh — el lienzo escala con un transform y las unidades de viewport se escalan doble).
45
+
46
+ ### Qué pilar usar
47
+
48
+ - **Technology** (default): contenido técnico u operativo — sistemas, código, datos. En caso de duda, este.
49
+ - **Innovation** (`data-theme: innovation`): lo nuevo — estrategia, propuestas, visión, roadmaps.
50
+ - **People** (`data-theme: people`): personas en el centro — formación, talento, cultura, onboarding.
51
+
52
+ Un pilar por deck (los tres colores de pilar siguen disponibles como acentos en todas las variantes), y los colores semánticos (`--green/--red/--orange`) siguen significando estado, no pilar.
53
+
54
+ ## Notas
55
+
56
+ - Dos internals de Slidev ya resueltos por el CSS: `layout: two-cols` renderiza la clase `.two-columns` (slots en `.col-left`/`.col-right`) y `layout: cover` envuelve el contenido en un `div.my-auto`.
57
+ - Las bolitas toman los títulos del primer heading de cada slide; si el heading va dentro de HTML crudo, añade `title:` al frontmatter de esa slide.
58
+ - Export: el reveal de entrada anima al montar; si `slidev export` captura a medias, añade `--wait 1000`.
59
+
60
+ ## Desarrollo
61
+
62
+ ```bash
63
+ npm install
64
+ npm run dev # example.md con theme: ./
65
+ npm test # contrato de tokens (node --test, sin dependencias)
66
+ ```
package/example.md ADDED
@@ -0,0 +1,149 @@
1
+ ---
2
+ theme: ./
3
+ title: Entaina · Slidev theme
4
+ mdc: true
5
+ ---
6
+
7
+ <div class="cover-kicker">SLIDEV-THEME-ENTAINA</div>
8
+
9
+ # El tema Entaina<br>para Slidev
10
+
11
+ <div class="cover-line">Look dirigido por tokens, chrome de navegación y las tres variantes de pilar.</div>
12
+
13
+ <div class="cover-orbit" aria-hidden="true"><span>tokens</span><i></i><span>layouts</span><i></i><b>chrome</b></div>
14
+
15
+ <!--
16
+ Duración estimada: 30 s.
17
+ Portada: kicker mono, display Comfortaa, órbita decorativa.
18
+ -->
19
+
20
+ ---
21
+ layout: section
22
+ ---
23
+
24
+ # Todo sale<br>de los tokens
25
+
26
+ Cambiar de paleta es redefinir variables — nada más.
27
+
28
+ <!--
29
+ Duración estimada: 20 s.
30
+ Divisoria con barra de acento.
31
+ -->
32
+
33
+ ---
34
+ layout: two-cols
35
+ layoutClass: gap-0
36
+ title: Split a sangre
37
+ ---
38
+
39
+ <div class="panel panel-before">
40
+ <div class="eyebrow">Antes</div>
41
+ <h1>Estilos<br>por deck</h1>
42
+ <p>Cada presentación reinventaba su look y su navegación.</p>
43
+ </div>
44
+
45
+ ::right::
46
+
47
+ <div class="panel panel-after">
48
+ <div class="eyebrow success">Ahora</div>
49
+ <h1>Un theme<br>versionado</h1>
50
+ <p>Un paquete lo aporta todo; el deck solo trae contenido.</p>
51
+ </div>
52
+
53
+ <!--
54
+ Duración estimada: 40 s.
55
+ Split edge-to-edge con .panel; el eyebrow del panel derecho va en verde.
56
+ -->
57
+
58
+ ---
59
+ title: Tabla y eyebrow
60
+ ---
61
+
62
+ <div class="eyebrow">Contrato</div>
63
+
64
+ # Qué aporta el theme
65
+
66
+ | Pieza | Dónde vive |
67
+ |---|---|
68
+ | Paleta + variantes de pilar | `styles/tokens.css` |
69
+ | Look base (layouts, tablas, bleed) | `styles/base.css` |
70
+ | Chrome de navegación | `global-top.vue` |
71
+ | Fuentes por defecto | `package.json` → `slidev.defaults` |
72
+
73
+ <!--
74
+ Duración estimada: 40 s.
75
+ Tabla estilizada por el theme: cabecera acento, zebra.
76
+ -->
77
+
78
+ ---
79
+ title: Dashboard KPI
80
+ ---
81
+
82
+ <div class="eyebrow">Dashboard</div>
83
+
84
+ # Los valores hero, breves
85
+
86
+ <div class="kpi-grid">
87
+ <div class="kpi"><b>6</b><span>KPIs máximo</span></div>
88
+ <div class="kpi"><b>≤6</b><span>caracteres hero</span></div>
89
+ <div class="kpi"><b>3</b><span>colores de pilar</span></div>
90
+ <div class="kpi"><b>scan</b><span>no lectura lineal</span></div>
91
+ <div class="kpi"><b>1</b><span>heading</span></div>
92
+ <div class="kpi"><b>100%</b><span>desde tokens</span></div>
93
+ </div>
94
+
95
+ <!--
96
+ Duración estimada: 30 s.
97
+ Dashboard: cifras display con rotación de pilares, etiquetas mono.
98
+ -->
99
+
100
+ ---
101
+ title: Snippet de código
102
+ ---
103
+
104
+ <div class="eyebrow">Code</div>
105
+
106
+ # Un punto de código, con foco
107
+
108
+ <div class="code-file">slide.ts</div>
109
+
110
+ ```ts {2-3}
111
+ export function slide(content: Content): Slide {
112
+ const focal = content.mainIdea() // una sola idea
113
+ return compose(focal, content.supports.slice(0, 6))
114
+ }
115
+ ```
116
+
117
+ <!--
118
+ Duración estimada: 30 s.
119
+ Caja navy de marca con chip de fichero flotante; tokens Shiki oscuros del theme.
120
+ -->
121
+
122
+ ---
123
+ layout: quote
124
+ ---
125
+
126
+ # El deck trae el contenido; el theme, todo lo demás.
127
+
128
+ Principio del tema
129
+
130
+ <!--
131
+ Duración estimada: 20 s.
132
+ Cita con comilla gigante; sin comillas literales en el texto.
133
+ -->
134
+
135
+ ---
136
+ layout: cover
137
+ class: bleed
138
+ ---
139
+
140
+ <div class="cover-kicker">Cierre</div>
141
+
142
+ # Un activo de marca,<br>con ciclo de versión propio
143
+
144
+ <div class="bleed-note">npm i -D slidev-theme-entaina · <strong>theme: slidev-theme-entaina</strong></div>
145
+
146
+ <!--
147
+ Duración estimada: 30 s.
148
+ Full-bleed oscuro con rejilla en perspectiva y nota mono.
149
+ -->
package/global-top.vue ADDED
@@ -0,0 +1,157 @@
1
+ <!--
2
+ slidev-theme-entaina — deck navigation chrome: top progress bar, right-hand
3
+ slide dots that expand on hover to show slide titles, prev/next arrows
4
+ (bottom left) and a counter with reading percent (bottom right). Hidden in
5
+ print/export and presenter mode. Styled through the theme tokens.
6
+ -->
7
+ <script setup lang="ts">
8
+ import { computed } from 'vue'
9
+ import { useNav } from '@slidev/client'
10
+
11
+ const nav = useNav()
12
+ const current = computed(() => nav.currentPage.value)
13
+ const total = computed(() => nav.total.value)
14
+ const pct = computed(() => Math.round((current.value / total.value) * 100))
15
+ const hidden = computed(() => nav.isPrintMode.value || (nav as any).isPresenter?.value)
16
+ const titles = computed(() =>
17
+ nav.slides.value.map((s: any, i: number) => {
18
+ const raw = s?.meta?.slide?.title || `Diapositiva ${i + 1}`
19
+ const clean = raw.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim()
20
+ return clean.length > 46 ? `${clean.slice(0, 45)}…` : clean
21
+ }),
22
+ )
23
+ </script>
24
+
25
+ <template>
26
+ <div v-if="!hidden" class="deck-chrome">
27
+ <div class="deck-progress" :style="{ width: pct + '%' }" />
28
+ <nav class="deck-dots" aria-label="Navegación por diapositivas">
29
+ <button
30
+ v-for="(t, i) in titles"
31
+ :key="i"
32
+ type="button"
33
+ class="deck-dot"
34
+ :aria-current="current === i + 1 ? 'true' : 'false'"
35
+ :aria-label="`Ir a ${t}`"
36
+ @click="nav.go(i + 1)"
37
+ >
38
+ <span class="deck-dot-label">{{ t }}</span>
39
+ </button>
40
+ </nav>
41
+ <div class="deck-arrows">
42
+ <button type="button" class="deck-arrow" :disabled="current <= 1" aria-label="Anterior" @click="nav.prev()">←</button>
43
+ <button type="button" class="deck-arrow" :disabled="current >= total" aria-label="Siguiente" @click="nav.next()">→</button>
44
+ </div>
45
+ <div class="deck-counter">{{ current }} / {{ total }} · {{ pct }}%</div>
46
+ </div>
47
+ </template>
48
+
49
+ <style scoped>
50
+ .deck-chrome {
51
+ font-family: var(--font-mono);
52
+ inset: 0;
53
+ pointer-events: none;
54
+ position: fixed;
55
+ z-index: 60;
56
+ }
57
+ .deck-progress {
58
+ background: var(--accent);
59
+ height: 4px;
60
+ left: 0;
61
+ position: absolute;
62
+ top: 0;
63
+ transition: width 0.3s ease;
64
+ }
65
+ .deck-dots {
66
+ backdrop-filter: blur(5px);
67
+ background: color-mix(in srgb, var(--bg) 70%, transparent);
68
+ border-radius: 20px;
69
+ display: flex;
70
+ flex-direction: column;
71
+ gap: 5px;
72
+ max-height: 70dvh;
73
+ overflow: hidden auto;
74
+ padding: 7px;
75
+ pointer-events: auto;
76
+ position: absolute;
77
+ right: 14px;
78
+ top: 50%;
79
+ transform: translateY(-50%);
80
+ transition: width 0.2s;
81
+ width: 34px;
82
+ }
83
+ .deck-dots:hover,
84
+ .deck-dots:focus-within {
85
+ border-radius: 16px;
86
+ width: min(240px, 40vw);
87
+ }
88
+ .deck-dot {
89
+ align-items: center;
90
+ background: transparent;
91
+ border: 0;
92
+ border-radius: 15px;
93
+ color: var(--text-dim);
94
+ cursor: pointer;
95
+ display: grid;
96
+ font: 500 11px var(--font-mono);
97
+ gap: 0;
98
+ grid-template-columns: 8px minmax(0, 1fr);
99
+ min-height: 24px;
100
+ padding: 6px;
101
+ text-align: left;
102
+ }
103
+ .deck-dot::before {
104
+ background: currentColor;
105
+ border-radius: 50%;
106
+ content: '';
107
+ height: 8px;
108
+ width: 8px;
109
+ }
110
+ .deck-dot-label {
111
+ max-width: 0;
112
+ opacity: 0;
113
+ overflow: hidden;
114
+ text-overflow: ellipsis;
115
+ white-space: nowrap;
116
+ }
117
+ .deck-dots:hover .deck-dot,
118
+ .deck-dots:focus-within .deck-dot { gap: 9px; }
119
+ .deck-dots:hover .deck-dot-label,
120
+ .deck-dots:focus-within .deck-dot-label { max-width: 200px; opacity: 1; }
121
+ .deck-dot[aria-current='true'] { background: var(--accent-dim); color: var(--accent); }
122
+ .deck-dot:focus-visible,
123
+ .deck-arrow:focus-visible { outline: 3px solid var(--node-b); outline-offset: 2px; }
124
+
125
+ .deck-arrows {
126
+ bottom: 12px;
127
+ display: flex;
128
+ gap: 6px;
129
+ left: 20px;
130
+ pointer-events: auto;
131
+ position: absolute;
132
+ }
133
+ .deck-arrow {
134
+ background: color-mix(in srgb, var(--surface-elevated) 80%, transparent);
135
+ border: 1px solid var(--border-bright);
136
+ border-radius: 50%;
137
+ color: var(--accent-dark, var(--accent));
138
+ cursor: pointer;
139
+ display: grid;
140
+ font-size: 14px;
141
+ height: 30px;
142
+ place-items: center;
143
+ width: 30px;
144
+ }
145
+ .deck-arrow:hover:not(:disabled) { background: var(--accent-dim); }
146
+ .deck-arrow:disabled { cursor: default; opacity: 0.35; }
147
+
148
+ .deck-counter {
149
+ bottom: 16px;
150
+ color: var(--text-dim);
151
+ font-size: 11px;
152
+ font-weight: 500;
153
+ position: absolute;
154
+ right: 20px;
155
+ text-shadow: 0 1px 3px color-mix(in srgb, var(--bg) 60%, transparent);
156
+ }
157
+ </style>
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "slidev-theme-entaina",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "packageManager": "npm@11.19.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "description": "Entaina brand theme for Slidev: token-driven look, deck navigation chrome, and the three pillar variants (technology, innovation, people).",
10
+ "keywords": [
11
+ "slidev-theme",
12
+ "slidev",
13
+ "entaina"
14
+ ],
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/Entaina/slidev-theme-entaina.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/Entaina/slidev-theme-entaina/issues"
22
+ },
23
+ "homepage": "https://github.com/Entaina/slidev-theme-entaina#readme",
24
+ "files": [
25
+ "styles",
26
+ "setup",
27
+ "global-top.vue",
28
+ "example.md",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "engines": {
33
+ "node": ">=18.0.0",
34
+ "slidev": ">=0.48.0"
35
+ },
36
+ "slidev": {
37
+ "defaults": {
38
+ "fonts": {
39
+ "sans": "Lato",
40
+ "serif": "Comfortaa",
41
+ "mono": "JetBrains Mono",
42
+ "weights": "300,400,500,600,700"
43
+ }
44
+ },
45
+ "colorSchema": "light"
46
+ },
47
+ "scripts": {
48
+ "dev": "slidev example.md --open",
49
+ "build": "slidev build example.md",
50
+ "export": "slidev export example.md",
51
+ "test": "node --test test/"
52
+ },
53
+ "devDependencies": {
54
+ "@slidev/cli": "latest"
55
+ }
56
+ }
package/setup/shiki.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { defineShikiSetup } from '@slidev/types'
2
+
3
+ // Dark token theme on both schemes: code sits in the brand navy box
4
+ // (--code-bg) whatever the deck's color scheme, per the Entaina look.
5
+ export default defineShikiSetup(() => ({
6
+ themes: {
7
+ dark: 'one-dark-pro',
8
+ light: 'one-dark-pro',
9
+ },
10
+ }))
@@ -0,0 +1,379 @@
1
+ /*
2
+ * slidev-theme-entaina — base look. Theme-agnostic: styles only through the
3
+ * token contract defined in ./tokens.css (see README). Sizing is in rem tuned
4
+ * to Slidev's 980×552 canvas — vw/vh double-scale under Slidev's transform.
5
+ * Slidev internals accounted for: `layout: two-cols` renders as .two-columns
6
+ * (slots in .col-left/.col-right); `layout: cover` wraps content in div.my-auto.
7
+ */
8
+
9
+ /* Layout ground — this is a standalone theme with no slidev-theme-default
10
+ underneath, so the base sizing/padding every layout assumes lives here. */
11
+ .slidev-layout {
12
+ background: var(--bg);
13
+ color: var(--text);
14
+ font-family: var(--font-body);
15
+ box-sizing: border-box;
16
+ height: 100%;
17
+ padding: 2.5rem 3.5rem;
18
+ }
19
+
20
+ .slidev-layout h1,
21
+ .slidev-layout h2,
22
+ .slidev-layout h3 {
23
+ font-family: var(--font-display);
24
+ color: var(--text);
25
+ text-wrap: balance;
26
+ }
27
+
28
+ .slidev-layout code,
29
+ .slidev-layout pre {
30
+ font-family: var(--font-mono);
31
+ }
32
+
33
+ .slidev-layout a { color: var(--accent); }
34
+ .slidev-layout strong { color: var(--accent-dark, var(--accent)); }
35
+ .slidev-layout blockquote {
36
+ border-left: 3px solid var(--accent);
37
+ background: var(--accent-dim);
38
+ color: var(--text-dim);
39
+ }
40
+
41
+ /* ---------- Atmosphere & typography ---------- */
42
+ .slidev-layout {
43
+ background-image: radial-gradient(ellipse at 12% 88%, var(--accent-dim), transparent 42%);
44
+ overflow: hidden;
45
+ position: relative;
46
+ }
47
+ .slidev-layout.two-columns,
48
+ .slidev-layout.quote {
49
+ background-image: radial-gradient(ellipse at 88% 18%, var(--node-b-dim), transparent 38%);
50
+ }
51
+ .slidev-layout.default {
52
+ display: flex;
53
+ flex-direction: column;
54
+ justify-content: center;
55
+ }
56
+
57
+ .slidev-layout h1 { font-size: 2.55rem; font-weight: 700; letter-spacing: -0.03em; line-height: 1.12; }
58
+ .slidev-layout p { color: var(--text-dim); font-size: 1.02rem; line-height: 1.5; }
59
+ .slidev-layout small { font-family: var(--font-mono); }
60
+
61
+ .cover-kicker,
62
+ .eyebrow {
63
+ color: var(--accent);
64
+ font-family: var(--font-mono);
65
+ font-size: 0.68rem;
66
+ font-weight: 600;
67
+ letter-spacing: 0.14em;
68
+ margin-bottom: 0.9rem;
69
+ text-transform: uppercase;
70
+ }
71
+ .eyebrow + h1 { margin-top: 0; }
72
+ .figure-caption { color: var(--text-dim); font-family: var(--font-mono); font-size: 0.66rem; margin-top: 0.9rem; }
73
+
74
+ /* ---------- Cover (title) ---------- */
75
+ .slidev-layout.cover {
76
+ align-items: center;
77
+ background-image:
78
+ radial-gradient(circle at 50% 38%, var(--node-a-dim), transparent 35%),
79
+ radial-gradient(var(--border) 1px, transparent 1px);
80
+ background-size: auto, 26px 26px;
81
+ display: flex;
82
+ flex-direction: column;
83
+ justify-content: center;
84
+ text-align: center;
85
+ }
86
+ .slidev-layout.cover h1 {
87
+ font-size: 3.8rem;
88
+ letter-spacing: -0.045em;
89
+ line-height: 1.02;
90
+ margin: 0.4rem auto 0;
91
+ max-width: 20ch;
92
+ text-wrap: balance;
93
+ }
94
+ .cover-line {
95
+ color: var(--text-dim);
96
+ font-size: 1.15rem;
97
+ line-height: 1.55;
98
+ margin: 1.5rem auto 0;
99
+ max-width: 44ch;
100
+ }
101
+ .cover-orbit {
102
+ align-items: center;
103
+ color: var(--text-dim);
104
+ display: flex;
105
+ font-family: var(--font-mono);
106
+ font-size: 0.62rem;
107
+ font-weight: 600;
108
+ gap: 0.7rem;
109
+ justify-content: center;
110
+ letter-spacing: 0.1em;
111
+ margin-top: 2.4rem;
112
+ text-transform: uppercase;
113
+ }
114
+ .cover-orbit i { border-top: 2px dashed var(--accent); opacity: 0.7; width: 2.2rem; }
115
+ .cover-orbit span {
116
+ background: var(--surface-elevated);
117
+ border: 1px solid var(--border);
118
+ border-radius: 999px;
119
+ box-shadow: 0 0 0 5px var(--accent-dim);
120
+ padding: 0.35rem 0.7rem;
121
+ }
122
+ .cover-orbit b { background: var(--accent); border-radius: 999px; color: var(--bg); padding: 0.4rem 0.8rem; }
123
+
124
+ /* ---------- Section divider ---------- */
125
+ .slidev-layout.section {
126
+ display: flex;
127
+ flex-direction: column;
128
+ justify-content: center;
129
+ }
130
+ .slidev-layout.section h1 {
131
+ font-size: 3.3rem;
132
+ letter-spacing: -0.04em;
133
+ line-height: 1.05;
134
+ text-align: left;
135
+ }
136
+ .slidev-layout.section h1::before {
137
+ background: var(--accent);
138
+ border-radius: 999px;
139
+ content: '';
140
+ display: block;
141
+ height: 5px;
142
+ margin-bottom: 1.4rem;
143
+ width: 3.2rem;
144
+ }
145
+ .slidev-layout.section p { font-size: 1.15rem; margin-left: 0; margin-top: 1.1rem; max-width: 40ch; padding-left: 0; text-align: left; }
146
+
147
+ /* ---------- Quote ---------- */
148
+ .slidev-layout.quote {
149
+ align-items: center;
150
+ display: flex;
151
+ flex-direction: column;
152
+ justify-content: center;
153
+ padding-inline: 4.5rem;
154
+ text-align: center;
155
+ }
156
+ .slidev-layout.quote h1::before {
157
+ color: var(--accent);
158
+ content: '\201C';
159
+ display: block;
160
+ font-family: Georgia, serif;
161
+ font-size: 6.5rem;
162
+ font-style: normal;
163
+ line-height: 0.55;
164
+ margin-bottom: 1.2rem;
165
+ opacity: 0.18;
166
+ }
167
+ .slidev-layout.quote h1 {
168
+ font-family: var(--font-display);
169
+ font-size: 1.85rem;
170
+ font-style: italic;
171
+ font-weight: 500;
172
+ letter-spacing: -0.01em;
173
+ line-height: 1.35;
174
+ max-width: 36ch;
175
+ text-wrap: balance;
176
+ }
177
+ .slidev-layout.quote p {
178
+ color: var(--text-dim);
179
+ font-family: var(--font-mono);
180
+ font-size: 0.66rem;
181
+ font-weight: 600;
182
+ letter-spacing: 0.12em;
183
+ margin-top: 1.6rem;
184
+ text-transform: uppercase;
185
+ }
186
+
187
+ /* ---------- Two-cols: centered columns; `.panel` children go edge to edge ---------- */
188
+ .slidev-layout.two-columns > .col-left,
189
+ .slidev-layout.two-columns > .col-right {
190
+ display: flex;
191
+ flex-direction: column;
192
+ justify-content: center;
193
+ min-width: 0;
194
+ }
195
+ .slidev-layout.two-columns:has(.panel) {
196
+ background-image: none;
197
+ column-gap: 0;
198
+ padding: 0;
199
+ }
200
+ .slidev-layout.two-columns:has(.panel) > div { height: 100%; }
201
+ .panel {
202
+ box-sizing: border-box;
203
+ display: flex;
204
+ flex-direction: column;
205
+ height: 100%;
206
+ justify-content: center;
207
+ padding: 2.6rem 3rem;
208
+ }
209
+ .panel h1 { font-size: 2.45rem; line-height: 1.1; margin: 0.55rem 0 0.9rem; }
210
+ .panel p { font-size: 1rem; line-height: 1.45; max-width: 24ch; }
211
+ .panel-before { background: var(--surface); }
212
+ .panel-after { background: var(--surface2); }
213
+ .panel-before .eyebrow { color: var(--text-dim); }
214
+ /* Semantic kicker colors are opt-in: structure never implies a verdict. */
215
+ .eyebrow.success { color: var(--green); }
216
+ .eyebrow.danger { color: var(--red); }
217
+ .eyebrow.warning { color: var(--orange); }
218
+
219
+ /* ---------- Tables ---------- */
220
+ .slidev-layout table { border-collapse: collapse; font-size: 0.8rem; margin-top: 0.9rem; width: 100%; }
221
+ .slidev-layout th {
222
+ background: var(--accent);
223
+ color: var(--bg);
224
+ font-family: var(--font-mono);
225
+ font-size: 0.56rem;
226
+ letter-spacing: 0.07em;
227
+ padding: 0.6rem 0.75rem;
228
+ text-align: left;
229
+ text-transform: uppercase;
230
+ }
231
+ .slidev-layout td { border-bottom: 1px solid var(--border); color: var(--text-dim); padding: 0.55rem 0.75rem; }
232
+ .slidev-layout tr:nth-child(even) td { background: var(--surface-elevated); }
233
+
234
+ /* ---------- Full-bleed cover variant: `layout: cover` + `class: bleed` ---------- */
235
+ .slidev-layout.cover.bleed {
236
+ align-items: flex-start;
237
+ background:
238
+ radial-gradient(circle at 80% 20%, color-mix(in srgb, var(--node-b) 55%, transparent), transparent 30%),
239
+ radial-gradient(circle at 22% 28%, color-mix(in srgb, var(--node-a) 70%, transparent), transparent 38%),
240
+ linear-gradient(135deg, var(--code-bg), var(--accent-dark, var(--accent)));
241
+ color: #fff;
242
+ justify-content: flex-end;
243
+ padding: 3rem 3.5rem;
244
+ text-align: left;
245
+ }
246
+ .slidev-layout.cover.bleed::before {
247
+ background-image:
248
+ linear-gradient(90deg, transparent 49.3%, rgba(255, 255, 255, 0.6) 49.3%, rgba(255, 255, 255, 0.6) 50.7%, transparent 50.7%),
249
+ linear-gradient(0deg, transparent 49.3%, rgba(255, 255, 255, 0.6) 49.3%, rgba(255, 255, 255, 0.6) 50.7%, transparent 50.7%);
250
+ background-size: 110px 110px;
251
+ content: '';
252
+ inset: 0;
253
+ opacity: 0.34;
254
+ pointer-events: none;
255
+ position: absolute;
256
+ transform: perspective(500px) rotateX(52deg) scale(1.7);
257
+ transform-origin: bottom;
258
+ z-index: 0;
259
+ }
260
+ .slidev-layout.cover.bleed > * { position: relative; z-index: 1; }
261
+ .slidev-layout.cover.bleed > div { margin-bottom: 0; margin-top: auto; }
262
+ .slidev-layout.cover.bleed h1 {
263
+ color: #fff;
264
+ font-size: 2.9rem;
265
+ letter-spacing: -0.04em;
266
+ margin: 0.4rem 0 0;
267
+ max-width: none;
268
+ text-align: left;
269
+ }
270
+ .slidev-layout.cover.bleed p { color: rgba(255, 255, 255, 0.8); }
271
+ .slidev-layout.cover.bleed .cover-kicker,
272
+ .slidev-layout.cover.bleed .eyebrow { color: rgba(255, 255, 255, 0.78); }
273
+ .bleed-note {
274
+ background: rgba(0, 0, 0, 0.15);
275
+ border: 1px solid rgba(255, 255, 255, 0.45);
276
+ border-radius: 0.6rem;
277
+ color: rgba(255, 255, 255, 0.88);
278
+ display: inline-block;
279
+ font-family: var(--font-mono);
280
+ font-size: 0.92rem;
281
+ line-height: 1.5;
282
+ margin-top: 1.5rem;
283
+ padding: 0.8rem 1.05rem;
284
+ }
285
+ .bleed-note strong { color: #fff; }
286
+
287
+ /* ---------- Components ---------- */
288
+ /* KPI dashboard: <div class="kpi-grid"> <div class="kpi"><b>247</b><span>label</span></div> … </div>
289
+ Hero values short (≤6 chars); pillar colors rotate per card. */
290
+ .kpi-grid {
291
+ display: grid;
292
+ gap: 1.1rem;
293
+ grid-template-columns: repeat(3, 1fr);
294
+ margin-top: 1.6rem;
295
+ }
296
+ .kpi {
297
+ background: var(--surface);
298
+ border: 1px solid var(--border);
299
+ border-radius: 0.9rem;
300
+ min-width: 0;
301
+ padding: 1.2rem 1.1rem;
302
+ }
303
+ .kpi b {
304
+ color: var(--accent-dark, var(--accent));
305
+ display: block;
306
+ font-family: var(--font-display);
307
+ font-size: 3rem;
308
+ font-weight: 700;
309
+ letter-spacing: -0.07em;
310
+ line-height: 1;
311
+ }
312
+ .kpi:nth-child(3n+2) b { color: var(--node-b); }
313
+ .kpi:nth-child(3n) b { color: var(--node-c); }
314
+ .kpi span {
315
+ color: var(--text-dim);
316
+ display: block;
317
+ font-family: var(--font-mono);
318
+ font-size: 0.68rem;
319
+ font-weight: 600;
320
+ letter-spacing: 0.08em;
321
+ margin-top: 0.6rem;
322
+ text-transform: uppercase;
323
+ }
324
+
325
+ /* Code blocks: Shiki tokens come from setup/shiki.ts (dark, brand-adjacent);
326
+ the box itself is the Entaina navy. background needs !important because
327
+ Shiki inlines its theme's background on the <pre>. */
328
+ .slidev-layout .slidev-code,
329
+ .slidev-layout pre.shiki {
330
+ background: var(--code-bg) !important;
331
+ border-radius: 1rem;
332
+ box-shadow: 0 12px 32px color-mix(in srgb, var(--code-bg) 18%, transparent);
333
+ font-size: 0.92rem;
334
+ line-height: 1.6;
335
+ padding: 1.4rem 1.6rem;
336
+ }
337
+ /* Floating filename chip — place immediately before the fence:
338
+ <div class="code-file">worker.ts</div> */
339
+ .code-file {
340
+ background: var(--accent);
341
+ border-radius: 0.35rem;
342
+ color: var(--bg);
343
+ display: block;
344
+ font: 600 0.68rem var(--font-mono);
345
+ margin-bottom: -0.85rem;
346
+ margin-left: 1.2rem;
347
+ padding: 0.3rem 0.65rem;
348
+ position: relative;
349
+ width: fit-content;
350
+ z-index: 1;
351
+ }
352
+
353
+ /* ---------- Staggered reveal on slide entry ---------- */
354
+ @media (prefers-reduced-motion: no-preference) {
355
+ .slidev-layout > *,
356
+ .slidev-layout > .my-auto > * { animation: ve-reveal 0.5s ease both; }
357
+ .slidev-layout > .my-auto { animation: none; }
358
+ .slidev-layout > *:nth-child(2),
359
+ .slidev-layout > .my-auto > *:nth-child(2) { animation-delay: 0.1s; }
360
+ .slidev-layout > *:nth-child(3),
361
+ .slidev-layout > .my-auto > *:nth-child(3) { animation-delay: 0.2s; }
362
+ .slidev-layout > *:nth-child(4),
363
+ .slidev-layout > .my-auto > *:nth-child(4) { animation-delay: 0.3s; }
364
+ .slidev-layout > *:nth-child(5),
365
+ .slidev-layout > .my-auto > *:nth-child(5) { animation-delay: 0.4s; }
366
+ }
367
+ @keyframes ve-reveal {
368
+ from { opacity: 0; transform: translateY(16px); }
369
+ }
370
+ @media print {
371
+ .slidev-layout > *,
372
+ .slidev-layout > .my-auto > * { animation: none !important; }
373
+ }
374
+
375
+ /* ---------- Short-viewport adjustments ---------- */
376
+ @media (max-height: 600px) {
377
+ .cover-orbit { margin-top: 1.2rem; }
378
+ .panel { padding: 1.6rem 2.2rem; }
379
+ }
@@ -0,0 +1,2 @@
1
+ import './tokens.css'
2
+ import './base.css'
@@ -0,0 +1,80 @@
1
+ /*
2
+ * Entaina — default theme.
3
+ * Mapped from the official tokens at https://design-system.entaina.ai/ (Style Dictionary).
4
+ * Light-only by design: treating single-theme as deliberate is correct for this theme.
5
+ * Do not wrap these values in prefers-color-scheme media queries.
6
+ *
7
+ * Fonts (Google Fonts):
8
+ * <link href="https://fonts.googleapis.com/css2?family=Comfortaa:wght@400;500;600;700&family=Lato:ital,wght@0,300;0,400;0,700;1,400&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
9
+ * Comfortaa is the display face (headings, labels); Lato is the body face.
10
+ * Entaina does not define a mono face; JetBrains Mono is this theme.s choice.
11
+ */
12
+
13
+ :root {
14
+ --font-display: 'Comfortaa', sans-serif;
15
+ --font-body: 'Lato', sans-serif;
16
+ --font-mono: 'JetBrains Mono', 'SF Mono', monospace;
17
+
18
+ /* Ground — Technology pillar (hoki) is the default */
19
+ --bg: #f1f6fa; /* hoki-50 */
20
+ --surface: #f5f5f5; /* chicago-50 */
21
+ --surface2: #e8e8e8; /* chicago-100 (surface-alt) */
22
+ --surface-elevated: #ffffff;
23
+ --border: #d4d4d4; /* chicago-200 */
24
+ --border-bright: #bababa; /* chicago-300 */
25
+ --text: #353535; /* chicago-900 */
26
+ --text-dim: #717171; /* chicago-600; chicago-500 #898989 fails small-text contrast on light surfaces */
27
+
28
+ /* Accent — primary pillar color */
29
+ --accent: #6b859f; /* hoki-500 */
30
+ --accent-dark: #4d6073; /* hoki-700 */
31
+ --accent-dim: rgba(107, 133, 159, 0.12);
32
+
33
+ /* Diagram node colors — the three Entaina pillars, always present */
34
+ --node-a: #6b859f; /* Technology (hoki-500) */
35
+ --node-a-dim: rgba(107, 133, 159, 0.12);
36
+ --node-b: #de865c; /* Innovation (copperfield-400) */
37
+ --node-b-dim: rgba(222, 134, 92, 0.14);
38
+ --node-c: #bd9947; /* People (golden-tainoi-400; the 200 base is too pale for strokes on light) */
39
+ --node-c-dim: rgba(248, 207, 115, 0.20);
40
+
41
+ /* Semantic status */
42
+ --green: #008d3d; /* success */
43
+ --green-dim: rgba(0, 141, 61, 0.10);
44
+ --red: #e7000b; /* danger-600; the base #fb2c36 is for fills, not small text */
45
+ --red-dim: rgba(251, 44, 54, 0.10);
46
+ --orange: #ca3500; /* warning-dark for text; base warning is #ff8904 */
47
+ --orange-dim: rgba(255, 137, 4, 0.14);
48
+ --info: #585eca; /* blue-600 */
49
+ --info-dim: rgba(88, 94, 202, 0.10);
50
+
51
+ /* Code blocks */
52
+ --code-bg: #2f324a; /* blue-900 */
53
+ --code-text: #e0e5ff; /* blue-100 */
54
+ }
55
+
56
+ /* Innovation pillar variant — copperfield leads */
57
+ [data-theme="innovation"] {
58
+ --bg: #fff1e8; /* copperfield-50 */
59
+ --accent: #c37149; /* copperfield-500; the official primary #de865c stays for fills via --node-b */
60
+ --accent-dark: #834e35; /* copperfield-700 */
61
+ --accent-dim: rgba(222, 134, 92, 0.14);
62
+ --node-a: #de865c;
63
+ --node-a-dim: rgba(222, 134, 92, 0.14);
64
+ --node-b: #6b859f;
65
+ --node-b-dim: rgba(107, 133, 159, 0.12);
66
+ }
67
+
68
+ /* People pillar variant — golden tainoi leads */
69
+ [data-theme="people"] {
70
+ --bg: #fff4d0; /* golden-tainoi-50 */
71
+ --accent: #a3853f; /* golden-tainoi-500 for readable accents */
72
+ --accent-dark: #6d5b35; /* golden-tainoi-700 */
73
+ --accent-dim: rgba(248, 207, 115, 0.24);
74
+ --node-a: #bd9947;
75
+ --node-a-dim: rgba(248, 207, 115, 0.20);
76
+ --node-b: #de865c;
77
+ --node-b-dim: rgba(222, 134, 92, 0.14);
78
+ --node-c: #6b859f;
79
+ --node-c-dim: rgba(107, 133, 159, 0.12);
80
+ }