Initial commit: TooraSt-wikijs

This commit is contained in:
2026-08-26 13:18:50 +10:00
commit e97f148ef6
3 changed files with 816 additions and 0 deletions

270
DESIGN.md Normal file
View File

@@ -0,0 +1,270 @@
---
version: alpha
name: Vodafone-design-analysis
description: An inspired interpretation of Vodafone's design language — a telecom super-brand whose web surface alternates between editorial photography hero bands with massive uppercase display headlines and clean white content bands, anchored by the company's signature scarlet red CTA and the proprietary Vodafone display sans set at impossibly heavy 800 weight.
colors:
primary: "#e60000"
on-primary: "#ffffff"
ink: "#25282b"
body: "#7e7e7e"
mute: "#bebebe"
canvas: "#ffffff"
canvas-soft: "#f2f2f2"
on-dark: "#ffffff"
typography:
display-hero:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 144px
fontWeight: 800
lineHeight: 114px
letterSpacing: -1px
display-xxl:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 126px
fontWeight: 800
lineHeight: 113px
letterSpacing: -1px
display-xl:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 90px
fontWeight: 800
lineHeight: 84px
display-lg:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 48px
fontWeight: 300
lineHeight: 52px
display-md:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 40px
fontWeight: 300
lineHeight: 44px
display-sm:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 32px
fontWeight: 700
lineHeight: 40px
display-xs:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 24px
fontWeight: 700
lineHeight: 24px
eyebrow-uppercase:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 16px
fontWeight: 800
lineHeight: 24px
body-lg:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 22px
fontWeight: 400
lineHeight: 24px
body-md:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 18px
fontWeight: 400
lineHeight: 28px
body-md-strong:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 18px
fontWeight: 600
lineHeight: 28px
body-sm:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 16px
fontWeight: 400
lineHeight: 20px
body-sm-strong:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 16px
fontWeight: 700
lineHeight: 22px
caption:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 14px
fontWeight: 400
lineHeight: 16px
caption-strong:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 14px
fontWeight: 700
lineHeight: 21px
caption-uppercase:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 12px
fontWeight: 600
lineHeight: 16px
letterSpacing: 0.5691px
button-md:
fontFamily: Vodafone, Vodafone Rg, Helvetica Neue, Arial, sans-serif
fontSize: 18px
fontWeight: 400
lineHeight: 28px
rounded:
none: 0px
xs: 1px
sm: 6px
card: 6px
pill-md: 32px
pill-lg: 60px
full: 9999px
spacing:
xxs: 2px
xs: 4px
sm: 8px
md: 12px
lg: 16px
xl: 20px
2xl: 24px
3xl: 32px
components:
nav-bar:
backgroundColor: "{colors.ink}"
textColor: "{colors.on-dark}"
typography: "{typography.body-sm}"
padding: "{spacing.lg} {spacing.3xl}"
nav-link:
textColor: "{colors.on-dark}"
typography: "{typography.body-sm}"
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
borderColor: "{colors.primary}"
typography: "{typography.button-md}"
rounded: "{rounded.pill-lg}"
padding: "{spacing.md} {spacing.2xl}"
button-outline-red:
backgroundColor: "{colors.canvas}"
textColor: "{colors.primary}"
borderColor: "{colors.primary}"
typography: "{typography.button-md}"
rounded: "{rounded.pill-lg}"
padding: "{spacing.md} {spacing.2xl}"
button-outline-dark:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.ink}"
typography: "{typography.button-md}"
rounded: "{rounded.pill-lg}"
padding: "{spacing.md} {spacing.2xl}"
button-icon-circular:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.canvas}"
rounded: "{rounded.full}"
text-input:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.ink}"
typography: "{typography.body-sm}"
rounded: "{rounded.sm}"
padding: "{spacing.md} {spacing.lg}"
badge-chip:
backgroundColor: "{colors.canvas-soft}"
textColor: "{colors.ink}"
typography: "{typography.caption-strong}"
rounded: "{rounded.pill-md}"
padding: "{spacing.xs} {spacing.md}"
card-content:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-md}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
card-hero:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.display-sm}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
hero-band-dark:
backgroundColor: "{colors.ink}"
textColor: "{colors.on-dark}"
typography: "{typography.display-hero}"
padding: "{spacing.3xl} {spacing.3xl}"
hero-band-red:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.display-xl}"
padding: "{spacing.3xl} {spacing.3xl}"
content-band-light:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.display-md}"
padding: "{spacing.3xl} {spacing.3xl}"
speechmark-logo-orb:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
rounded: "{rounded.sm}"
divider-on-dark:
borderColor: "{colors.on-dark}"
footer:
backgroundColor: "{colors.ink}"
textColor: "{colors.on-dark}"
typography: "{typography.body-sm}"
padding: "{spacing.3xl} {spacing.3xl}"
ex-pricing-tier:
description: "Default tier card. Mirrors card-content chrome with canvas-soft surface and a hairline border."
backgroundColor: "{colors.canvas-soft}"
textColor: "{colors.ink}"
borderColor: "{colors.mute}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
ex-pricing-tier-featured:
description: "Featured tier — polarity-flipped to ink with white text and white pill CTA inside."
backgroundColor: "{colors.ink}"
textColor: "{colors.on-primary}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
ex-product-selector:
description: "Tariff-tier picker — repurposed as the brand's plan selector with badge-chip chips inside the frame."
backgroundColor: "{colors.canvas-soft}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
ex-cart-drawer:
description: "Subscription summary — line items per tariff add-on, light hairline dividers."
backgroundColor: "{colors.canvas}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
item-divider: "{colors.mute}"
ex-app-shell-row:
description: "Sidebar nav row. Active state uses brand primary as a left-edge indicator bar."
backgroundColor: "{colors.canvas}"
activeIndicator: "{colors.primary}"
rounded: "{rounded.sm}"
padding: "{spacing.md} {spacing.lg}"
ex-data-table-cell:
description: "Default data-table cell chrome. Header uses caption-uppercase mono-style eyebrow; body uses body-sm."
headerBackground: "{colors.canvas-soft}"
headerTypography: "{typography.caption-uppercase}"
bodyTypography: "{typography.body-sm}"
cellPadding: "{spacing.md} {spacing.lg}"
rowBorder: "{colors.mute}"
ex-auth-form-card:
description: "Sign-in / sign-up card. Mirrors card-content chrome with text-input primitives inside."
backgroundColor: "{colors.canvas-soft}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
ex-modal-card:
description: "Modal dialog surface — same chrome as card-content; brand uses scrim, not card shadow."
backgroundColor: "{colors.canvas}"
rounded: "{rounded.card}"
padding: "{spacing.lg}"
ex-empty-state-card:
description: "Empty-state illustration frame on canvas-soft with generous interior padding."
backgroundColor: "{colors.canvas-soft}"
rounded: "{rounded.card}"
padding: "{spacing.3xl}"
captionTypography: "{typography.body-md}"
ex-toast:
description: "Toast notification surface — card-content shape with caption-strong body."
backgroundColor: "{colors.canvas}"
rounded: "{rounded.sm}"
padding: "{spacing.md} {spacing.lg}"
typography: "{typography.body-sm}"

173
create-toora-pages.py Normal file
View File

@@ -0,0 +1,173 @@
#!/usr/bin/env python3
"""Create Toora pages in Wiki.js via GraphQL API."""
import json, sys
JWT = sys.argv[1] if len(sys.argv) > 1 else ""
pages = [
{
"title": "Toora Home",
"path": "home",
"tags": ["home", "toora"],
"desc": "Household knowledge base home",
"content": (
'<div class="vf-hero-dark">'
'<div class="eyebrow">Household Knowledge Base</div>'
'<h1 class="display-hero">TOORA</h1>'
'<p class="body-lg">Everything about our home — how things work, what we use, and how to fix it.</p>'
'</div>'
'<div class="vf-band-light">'
'<span class="vf-section-label">Home Notes</span>'
'<div class="vf-grid">'
'<div class="vf-card"><div class="vf-card-title">📺 Entertainment</div><div class="vf-card-desc">TV, streaming, music, and internet services for the home.</div></div>'
'<div class="vf-card"><div class="vf-card-title">💡 Lights</div><div class="vf-card-desc">Lighting controls, switches, and smart bulbs.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🍳 Kitchen</div><div class="vf-card-desc">Composting system, appliances, and kitchen setup.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🌱 Garden</div><div class="vf-card-desc">BBQ, fires, and outdoor living.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🐾 Pets</div><div class="vf-card-desc">Dogs and fish — care routines and setups.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🧺 Laundry</div><div class="vf-card-desc">Washer and drier — usage and maintenance.</div></div>'
'</div></div>'
)
},
{
"title": "Entertainment",
"path": "entertainment",
"tags": ["entertainment", "tv", "music", "internet"],
"desc": "TV, streaming, music and internet",
"content": (
'<div class="vf-band-light">'
'<div class="eyebrow">Section</div>'
'<h1 class="display-xl">ENTERTAINMENT</h1>'
'<p class="body-lg">TV and streaming setup, music systems, and home internet.</p>'
'</div>'
'<div class="vf-band-light">'
'<span class="vf-section-label">Topics</span>'
'<div class="vf-grid-3">'
'<div class="vf-card"><div class="vf-card-title">📺 TV &amp; Streaming</div><div class="vf-card-desc">Television setup, streaming services, subscriptions, and devices.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🎵 Music</div><div class="vf-card-desc">Music systems, speakers, playlists, and audio setup.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🌐 Internet</div><div class="vf-card-desc">Home internet, WiFi, router, and network services.</div></div>'
'</div></div>'
)
},
{
"title": "Lights",
"path": "lights",
"tags": ["lights", "switches"],
"desc": "Lighting controls and switches",
"content": (
'<div class="vf-band-light">'
'<div class="eyebrow">Section</div>'
'<h1 class="display-xl">LIGHTS</h1>'
'<p class="body-lg">Lighting around the home — controls, switches, and smart options.</p>'
'</div>'
'<div class="vf-band-light">'
'<span class="vf-section-label">Topics</span>'
'<div class="vf-grid-3">'
'<div class="vf-card"><div class="vf-card-title">🎛 Controlling</div><div class="vf-card-desc">Smart controls, dimmers, timers, and automation.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🔘 Switches</div><div class="vf-card-desc">Wall switches, smart switches, and wiring notes.</div></div>'
'</div></div>'
)
},
{
"title": "Kitchen",
"path": "kitchen",
"tags": ["kitchen", "compost", "appliances"],
"desc": "Composting and kitchen appliances",
"content": (
'<div class="vf-band-light">'
'<div class="eyebrow">Section</div>'
'<h1 class="display-xl">KITCHEN</h1>'
'<p class="body-lg">Compost system and kitchen appliances.</p>'
'</div>'
'<div class="vf-band-light">'
'<span class="vf-section-label">Topics</span>'
'<div class="vf-grid-3">'
'<div class="vf-card"><div class="vf-card-title">🌿 Compost</div><div class="vf-card-desc">Composting system, what goes in, and maintenance.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🔌 Appliances</div><div class="vf-card-desc">Kitchen appliances, usage, and care.</div></div>'
'</div></div>'
)
},
{
"title": "Garden",
"path": "garden",
"tags": ["garden", "bbq", "fires"],
"desc": "Outdoor living — BBQ and fires",
"content": (
'<div class="vf-band-light">'
'<div class="eyebrow">Section</div>'
'<h1 class="display-xl">GARDEN</h1>'
'<p class="body-lg">Outdoor living — BBQ, fires, and garden setup.</p>'
'</div>'
'<div class="vf-band-light">'
'<span class="vf-section-label">Topics</span>'
'<div class="vf-grid-3">'
'<div class="vf-card"><div class="vf-card-title">🍖 BBQ</div><div class="vf-card-desc">BBQ setup, care, and usage.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🔥 Fires</div><div class="vf-card-desc">Fire pits and outdoor heating.</div></div>'
'</div></div>'
)
},
{
"title": "Pets",
"path": "pets",
"tags": ["pets", "dogs", "fish"],
"desc": "Pet care — dogs and fish",
"content": (
'<div class="vf-band-light">'
'<div class="eyebrow">Section</div>'
'<h1 class="display-xl">PETS</h1>'
'<p class="body-lg">Our pets and how we care for them.</p>'
'</div>'
'<div class="vf-band-light">'
'<span class="vf-section-label">Topics</span>'
'<div class="vf-grid-3">'
'<div class="vf-card"><div class="vf-card-title">🐕 Dogs</div><div class="vf-card-desc">Dog care, feeding, and routines.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🐟 Fish</div><div class="vf-card-desc">Fish tank setup, feeding, and maintenance.</div></div>'
'</div></div>'
)
},
{
"title": "Laundry",
"path": "laundry",
"tags": ["laundry", "washer", "drier"],
"desc": "Washer and drier notes",
"content": (
'<div class="vf-band-light">'
'<div class="eyebrow">Section</div>'
'<h1 class="display-xl">LAUNDRY</h1>'
'<p class="body-lg">Laundry appliances — washer and drier.</p>'
'</div>'
'<div class="vf-band-light">'
'<span class="vf-section-label">Topics</span>'
'<div class="vf-grid-3">'
'<div class="vf-card"><div class="vf-card-title">🌀 Washer</div><div class="vf-card-desc">Washing machine usage, programs, and maintenance.</div></div>'
'<div class="vf-card"><div class="vf-card-title">🌬 Drier</div><div class="vf-card-desc">Drier usage, settings, and lint care.</div></div>'
'</div></div>'
)
}
]
mutations = []
for idx, p in enumerate(pages):
content_escaped = p['content'].replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')
tag_str = json.dumps(p['tags'])
mutation = f''' p{idx}: pages {{
create(
title: "{p['title']}"
path: "{p['path']}"
content: "{content_escaped}"
editor: "wysiwyg"
isPublished: true
isPrivate: false
locale: "en"
tags: {tag_str}
description: "{p['desc']}"
) {{
page {{ id path title }}
responseResult {{ succeeded message }}
}}
}}'''
mutations.append(mutation)
query = 'mutation {\n' + '\n'.join(mutations) + '\n}'
payload = {"query": query}
print(json.dumps(payload))
PYEOF

373
toora-global.css Normal file
View File

@@ -0,0 +1,373 @@
/* ════════════════════════════════════════
TOORA Wiki Global Stylesheet
Vodafone-inspired design language
════════════════════════════════════════ */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700;800&display=swap');
/* ═══ DESIGN TOKENS ═══ */
:root {
/* Colors */
--primary: #e60000;
--on-primary: #ffffff;
--ink: #25282b;
--body: #7e7e7e;
--mute: #bebebe;
--canvas: #ffffff;
--canvas-soft: #f2f2f2;
--on-dark: #ffffff;
/* Typography */
--font-display: 'Inter', 'Vodafone', 'Helvetica Neue', Arial, sans-serif;
/* Radius */
--radius-none: 0px;
--radius-card: 6px;
--radius-pill-md: 32px;
--radius-pill-lg: 60px;
--radius-full: 9999px;
/* Spacing */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 12px;
--space-lg: 16px;
--space-xl: 20px;
--space-2xl: 24px;
--space-3xl: 32px;
}
/* ═══ RESET ═══ */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
box-shadow: none !important;
}
html {
background: var(--canvas);
color: var(--ink);
font-family: var(--font-display);
font-size: 16px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
body {
background: var(--canvas);
color: var(--ink);
min-height: 100vh;
}
/* ═══ TYPOGRAPHY ═══ */
.display-hero {
font-size: clamp(64px, 10vw, 144px);
font-weight: 800;
line-height: 0.8;
letter-spacing: -1px;
text-transform: uppercase;
color: var(--ink);
}
.display-xxl {
font-size: clamp(56px, 8vw, 126px);
font-weight: 800;
line-height: 0.9;
letter-spacing: -1px;
text-transform: uppercase;
color: var(--ink);
}
.display-xl {
font-size: clamp(48px, 7vw, 90px);
font-weight: 800;
line-height: 0.94;
text-transform: uppercase;
color: var(--ink);
}
.display-lg {
font-size: 48px;
font-weight: 300;
line-height: 1.08;
color: var(--ink);
}
.display-md {
font-size: 40px;
font-weight: 300;
line-height: 1.1;
color: var(--ink);
}
.display-sm {
font-size: 32px;
font-weight: 700;
line-height: 1.25;
color: var(--ink);
}
.display-xs {
font-size: 24px;
font-weight: 700;
line-height: 1;
color: var(--ink);
}
.eyebrow {
font-size: 16px;
font-weight: 800;
text-transform: uppercase;
line-height: 1.5;
color: var(--primary);
letter-spacing: 0.5px;
}
.body-lg {
font-size: 22px;
font-weight: 400;
line-height: 1.4;
color: var(--ink);
}
.body-md {
font-size: 18px;
font-weight: 400;
line-height: 1.55;
color: var(--ink);
}
.body-sm {
font-size: 16px;
font-weight: 400;
line-height: 1.4;
color: var(--body);
}
.caption-uppercase {
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.57px;
color: var(--body);
}
/* ═══ BUTTONS — Vodafone pill system ═══ */
.btn, .vf-btn {
display: inline-flex;
align-items: center;
justify-content: center;
font-family: var(--font-display);
font-size: 18px;
font-weight: 400;
line-height: 1;
border-radius: var(--radius-pill-lg);
padding: var(--space-md) var(--space-2xl);
cursor: pointer;
text-decoration: none;
border: 1px solid;
transition: opacity 0.2s ease, transform 0.2s ease;
white-space: nowrap;
}
.btn:hover, .vf-btn:hover { opacity: 0.85; }
.btn:active, .vf-btn:active { transform: scale(0.98); }
.vf-btn-primary {
background: var(--primary);
color: var(--on-primary);
border-color: var(--primary);
}
.vf-btn-outline-red {
background: var(--canvas);
color: var(--primary);
border-color: var(--primary);
}
.vf-btn-outline-dark {
background: var(--canvas);
color: var(--ink);
border-color: var(--ink);
}
/* ═══ BADGES / CHIPS ═══ */
.vf-badge {
display: inline-block;
background: var(--canvas-soft);
color: var(--ink);
font-family: var(--font-display);
font-size: 14px;
font-weight: 700;
border-radius: var(--radius-pill-md);
padding: var(--space-xs) var(--space-md);
line-height: 1.5;
}
/* ═══ CARDS — 6px radius ═══ */
.vf-card {
background: var(--canvas);
color: var(--ink);
border-radius: var(--radius-card);
padding: var(--space-lg);
border: 1px solid var(--mute);
transition: border-color 0.2s ease;
}
.vf-card:hover { border-color: var(--ink); }
.vf-card-soft {
background: var(--canvas-soft);
border: 1px solid var(--mute);
}
.vf-card-title {
font-size: 32px;
font-weight: 700;
line-height: 1.25;
color: var(--ink);
margin-bottom: var(--space-sm);
}
.vf-card-desc {
font-size: 16px;
font-weight: 400;
line-height: 1.4;
color: var(--body);
}
/* ═══ HERO BANDS ═══ */
.vf-hero-dark {
background: var(--ink);
color: var(--on-dark);
padding: var(--space-3xl);
}
.vf-hero-dark .display-hero,
.vf-hero-dark .display-xxl,
.vf-hero-dark .display-xl { color: var(--on-dark); }
.vf-hero-dark .eyebrow { color: var(--primary); }
.vf-hero-dark .body-lg { color: var(--on-dark); }
.vf-hero-red {
background: var(--primary);
color: var(--on-primary);
padding: var(--space-3xl);
}
.vf-hero-red .display-hero,
.vf-hero-red .display-xxl,
.vf-hero-red .display-xl { color: var(--on-primary); }
.vf-band-light {
background: var(--canvas);
color: var(--ink);
padding: var(--space-3xl);
}
/* ═══ NAV BAR ═══ */
.vf-nav {
background: var(--ink);
color: var(--on-dark);
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-lg) var(--space-3xl);
position: sticky;
top: 0;
z-index: 100;
}
.vf-nav .vf-nav-brand {
font-family: var(--font-display);
font-size: 24px;
font-weight: 800;
color: var(--on-dark);
text-transform: uppercase;
letter-spacing: 0.5px;
text-decoration: none;
}
.vf-nav .vf-nav-brand .speechmark {
display: inline-block;
background: var(--primary);
color: var(--on-primary);
border-radius: var(--radius-card);
width: 32px;
height: 32px;
text-align: center;
line-height: 32px;
font-size: 20px;
margin-right: 8px;
font-weight: 800;
}
.vf-nav .vf-nav-links {
display: flex;
gap: var(--space-2xl);
list-style: none;
margin: 0;
padding: 0;
}
.vf-nav .vf-nav-links a {
font-family: var(--font-display);
font-size: 16px;
font-weight: 400;
color: var(--on-dark);
text-decoration: none;
opacity: 0.85;
transition: opacity 0.2s;
}
.vf-nav .vf-nav-links a:hover { opacity: 1; }
/* ═══ GRIDS ═══ */
.vf-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-lg);
}
.vf-grid-3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-lg);
}
/* ═══ SECTION LABEL ═══ */
.vf-section-label {
font-size: 16px;
font-weight: 800;
text-transform: uppercase;
color: var(--primary);
margin-bottom: var(--space-xl);
display: block;
}
/* ═══ FOOTER ═══ */
.vf-footer {
background: var(--ink);
color: var(--on-dark);
padding: var(--space-3xl);
text-align: center;
font-size: 14px;
opacity: 0.85;
}
/* ═══ WIKI.JS OVERRIDES ═══ */
body, .content, .page-content, .main-panel {
background: var(--canvas) !important;
color: var(--ink) !important;
}
h1, h2, h3, h4, h5, h6 {
color: var(--ink) !important;
font-family: var(--font-display) !important;
}
a {
color: var(--primary) !important;
}
.wiki-logo img, .navbar-brand img, [class*="logo"] img {
display: none !important;
}
.wiki-logo:after, .navbar-brand:after {
content: "TOORA";
font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif;
font-size: 20px;
font-weight: 800;
letter-spacing: 0.5px;
text-transform: uppercase;
color: #ffffff;
white-space: nowrap;
}
.navbar, .navbar-default, .navbar-primary {
background: var(--ink) !important;
border-bottom: none !important;
box-shadow: none !important;
}
/* ═══ RESPONSIVE ═══ */
@media (max-width: 1024px) {
.vf-grid-3 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 768px) {
.vf-grid, .vf-grid-3 { grid-template-columns: 1fr; }
.vf-nav .vf-nav-links { display: none; }
.display-lg { font-size: 36px; }
.display-md { font-size: 32px; }
.display-sm { font-size: 28px; }
}