Checkpoint: nature palette, toolbar fix, hero placeholder

This commit is contained in:
Tolaria 2026-06-03 12:07:53 +08:00
parent 99ab200398
commit b9dda6802a
6 changed files with 611 additions and 4 deletions

Binary file not shown.

161
docs/javascripts/extra.js Normal file
View file

@ -0,0 +1,161 @@
/**
* God Spark Zensical Theme Kit (JS)
* Zero dependencies. ~1.5 KB minified.
*
* Features
* IntersectionObserver scroll-reveal (class: .godspark-reveal)
* Optional cursor glow (enable via [godspark-glow] attribute)
* Reduced-motion fallback baked in
*/
;(function () {
'use strict';
/* ── Reduced-motion preference (shared) ── */
const prefersReducedMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches;
/* ── 1. Scroll Reveal via IntersectionObserver ── */
function initScrollReveal () {
if (prefersReducedMotion) return; // already handled in CSS
const reveals = document.querySelectorAll('.godspark-reveal');
if (!reveals.length) return;
// Respect any user-set threshold via CSS variable, default 12%
const threshold = parseFloat(
getComputedStyle(document.documentElement)
.getPropertyValue('--godspark-reveal-threshold')
) || 0.12;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
observer.unobserve(entry.target); // fire once
}
});
},
{ threshold, rootMargin: '0px 0px -40px 0px' }
);
reveals.forEach((el) => observer.observe(el));
}
/* ── 2. Cursor Glow ── */
function initCursorGlow () {
// Only run if [godspark-glow] is present on <html> or <body>
if (!document.documentElement.hasAttribute('godspark-glow') &&
!document.body.hasAttribute('godspark-glow')) {
return;
}
if (prefersReducedMotion) return; // CSS already hides it
// Add a class for the CSS ::after pseudo-element to pick up
document.documentElement.classList.add('godspark-glow-active');
const glow = document.querySelector('.godspark-glow-active::after');
// We track position via a CSS custom property on the root element,
// letting the ::after pseudo consume it.
const styleEl = document.createElement('style');
styleEl.id = 'godspark-glow-dynamic';
document.head.appendChild(styleEl);
let mouseX = -400;
let mouseY = -400;
let rafPending = false;
function setGlowPosition (x, y) {
mouseX = x;
mouseY = y;
updateGlowStyle();
}
function updateGlowStyle () {
styleEl.textContent = `
:root {
--godspark-cursor-x: ${mouseX}px;
--godspark-cursor-y: ${mouseY}px;
}
`;
}
// Generate a unique glow element per page to act as the cursor-follower
const cursorEl = document.createElement('div');
cursorEl.setAttribute('aria-hidden', 'true');
cursorEl.className = 'godspark-cursor-glow';
cursorEl.style.cssText = `
position: fixed;
left: ${mouseX}px;
top: ${mouseY}px;
width: 380px;
height: 380px;
border-radius: 50%;
pointer-events: none;
z-index: 999999;
background: radial-gradient(circle,
rgba(195,174,214,0.22) 0%,
rgba(184,169,232,0.08) 35%,
transparent 70%
);
transform: translate(-50%, -50%);
touch-action: none;
will-change: left, top;
transition: none;
`;
document.body.appendChild(cursorEl);
function onPointerMove (e) {
if (rafPending) return;
rafPending = true;
requestAnimationFrame(() => {
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
cursorEl.style.left = clientX + 'px';
cursorEl.style.top = clientY + 'px';
rafPending = false;
});
}
function onPointerLeave () {
cursorEl.style.opacity = '0';
}
function onPointerEnter () {
cursorEl.style.opacity = '1';
}
document.addEventListener('mousemove', onPointerMove, { passive: true });
document.addEventListener('touchmove', onPointerMove, { passive: true });
document.addEventListener('mouseleave', onPointerLeave);
document.addEventListener('mouseenter', onPointerEnter);
// Hide on idle after 4 s
let idleTimer;
function resetIdle () {
clearTimeout(idleTimer);
cursorEl.style.opacity = '1';
idleTimer = setTimeout(() => {
cursorEl.style.opacity = '0';
}, 4000);
}
document.addEventListener('mousemove', resetIdle, { passive: true });
resetIdle();
}
/* ── Boot ── */
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', boot);
} else {
boot();
}
function boot () {
initScrollReveal();
initCursorGlow();
}
})();

357
docs/stylesheets/extra.css Normal file
View file

@ -0,0 +1,357 @@
/*
* God Spark Zensical Theme Kit
* Nature/consciousness theme: legible, calm, organic
*/
/* ─── Design Tokens ─── */
:root {
--godspark-bg: #f6fbf7; /* soft morning mist */
--godspark-surface: #ffffff;
--godspark-text: #1f2e1d; /* deep forest text */
--godspark-text-muted: #4f5d4b;
--godspark-primary: #6b8f71; /* sage */
--godspark-secondary: #a3c4a8; /* leaf mist */
--godspark-tertiary: #e8d5b7; /* warm sand */
--godspark-accent: #8da87d; /* moss */
--godspark-iridescent: linear-gradient(135deg, #e8f0e8, #c8d9c4, #a3c4a8, #d4cfb8, #c2d1c0);
--godspark-aurora: linear-gradient(160deg,
#f4f9f1 0%, #eaf2e4 25%, #f7f4ed 50%, #eef1f0 75%, #f6fbf7 100%);
--godspark-card-bg: rgba(255, 255, 255, 0.78);
--godspark-card-border: rgba(107, 143, 113, 0.22);
--godspark-glow: rgba(141, 168, 125, 0.35);
--godspark-glow-intense: rgba(107, 143, 113, 0.75);
--godspark-duration: 0.7s;
--godspark-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
--godspark-distance: 24px;
}
/* ─── Base atmosphere ─── */
body {
background-color: var(--godspark-bg);
background-image: var(--godspark-aurora);
background-size: 400% 400%;
background-attachment: fixed;
color: var(--godspark-text);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Subtle animated aurora — reduced-motion safe */
@media (prefers-reduced-motion: no-preference) {
body {
animation: godspark-breathe 28s ease-in-out infinite;
}
@keyframes godspark-breathe {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
}
/* ─── Typography (solid, legible, no cycling) ─── */
h1, h2, h3, h4, h5, h6,
.zensical article h1,
.zensical article h2,
.zensical article h3 {
font-weight: 650;
letter-spacing: -0.015em;
line-height: 1.2;
color: var(--godspark-text);
}
a {
color: var(--godspark-primary);
text-decoration-thickness: 1px;
text-underline-offset: 3px;
transition: color 0.25s var(--godspark-ease), text-decoration-color 0.25s;
}
a:hover {
color: var(--godspark-accent);
}
/* ─── Layout helpers ─── */
.zensical article,
.zensical .content,
main,
article {
position: relative;
z-index: 1;
}
.zensical article > *,
.zensical .content > *,
main > *,
article > *,
section {
position: relative;
z-index: 1;
}
/* ─── Cards ─── */
.zensical .card,
.zensical article section,
section.card,
div.card,
article.card {
background: var(--godspark-card-bg);
border: 1px solid var(--godspark-card-border);
border-radius: 18px;
backdrop-filter: blur(12px) saturate(130%);
-webkit-backdrop-filter: blur(12px) saturate(130%);
padding: 1.6rem 1.8rem;
box-shadow:
0 4px 20px rgba(107, 143, 113, 0.08),
0 1px 3px rgba(0, 0, 0, 0.03);
transition:
transform var(--godspark-duration) var(--godspark-ease),
box-shadow var(--godspark-duration) var(--godspark-ease),
border-color 0.3s ease;
}
.zensical .card:hover,
section.card:hover,
div.card:hover,
article.card:hover {
transform: translateY(-3px);
box-shadow:
0 12px 36px rgba(107, 143, 113, 0.14),
0 2px 6px rgba(0, 0, 0, 0.04);
border-color: rgba(107, 143, 113, 0.45);
}
/* ─── Code blocks — careful not to break Zensical toolbars ─── */
pre {
background: rgba(255, 255, 255, 0.82);
border: 1px solid var(--godspark-card-border);
border-radius: 14px;
padding: 1.1rem 1.3rem;
}
code, kbd {
background: rgba(107, 143, 113, 0.10);
border: 1px solid rgba(107, 143, 113, 0.18);
border-radius: 7px;
color: var(--godspark-text);
}
/* ─── Blockquotes ─── */
blockquote {
border-left: 3px solid var(--godspark-secondary);
background: rgba(141, 168, 125, 0.08);
border-radius: 0 12px 12px 0;
padding: 0.9rem 1.2rem;
margin: 1.4rem 0;
color: var(--godspark-text-muted);
font-style: italic;
}
/* ─── HR divider ─── */
hr {
border: none;
height: 1px;
background: linear-gradient(90deg,
transparent,
var(--godspark-primary),
var(--godspark-secondary),
transparent);
margin: 2.4rem 0;
}
/* ─── Tables ─── */
table {
border-collapse: separate;
border-spacing: 0;
border-radius: 14px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(107, 143, 113, 0.07);
}
th {
background: linear-gradient(135deg, var(--godspark-primary), var(--godspark-accent));
color: #fff;
font-weight: 550;
}
td {
background: var(--godspark-surface);
border-bottom: 1px solid rgba(107, 143, 113, 0.12);
}
/* ─── CTA buttons only (not Zensical toolbar icons) ─── */
button.cta,
a.cta,
.zensical .cta,
button[class*="godspark"],
a[class*="godspark"] {
background: linear-gradient(135deg, var(--godspark-primary), var(--godspark-accent));
color: #fff;
font-weight: 550;
border: none;
border-radius: 50px;
padding: 0.55em 1.5em;
cursor: pointer;
transition: opacity 0.25s, box-shadow 0.25s;
text-decoration: none;
display: inline-block;
}
button.cta:hover,
a.cta:hover,
.zensical .cta:hover,
button[class*="godspark"]:hover,
a[class*="godspark"]:hover {
opacity: 0.92;
box-shadow: 0 4px 18px var(--godspark-glow);
}
/* ─── Scroll reveal ─── */
.godspark-reveal {
opacity: 0;
transform: translateY(var(--godspark-distance));
transition:
opacity var(--godspark-duration) var(--godspark-ease),
transform var(--godspark-duration) var(--godspark-ease);
}
.godspark-reveal.is-visible {
opacity: 1;
transform: translateY(0);
}
.godspark-reveal.is-visible > * {
opacity: 0;
transform: translateY(var(--godspark-distance));
transition:
opacity var(--godspark-duration) var(--godspark-ease),
transform var(--godspark-duration) var(--godspark-ease);
}
.godspark-reveal.is-visible > *:nth-child(1) { transition-delay: 0.00s; }
.godspark-reveal.is-visible > *:nth-child(2) { transition-delay: 0.08s; }
.godspark-reveal.is-visible > *:nth-child(3) { transition-delay: 0.16s; }
.godspark-reveal.is-visible > *:nth-child(4) { transition-delay: 0.24s; }
.godspark-reveal.is-visible > *:nth-child(5) { transition-delay: 0.32s; }
.godspark-reveal.is-visible > *:nth-child(6) { transition-delay: 0.40s; }
.godspark-reveal.is-visible > * {
opacity: 1;
transform: translateY(0);
}
/* ─── Tone: disable cycling header colors ─── */
.md-header, .md-header__inner, .md-header__button, .md-icon {
animation: none !important;
}
/* ─── Tone: disable header color cycling backgrounds ─── */
[data-md-color-component="header"] {
animation: none !important;
}
/* ─── Tone: no shimmer on headings ─── */
h1, h2, h3, h4, h5, h6,
.zensical article h1,
.zensical article h2,
.zensical article h3 {
animation: none !important;
background: none !important;
-webkit-text-fill-color: var(--godspark-text) !important;
background-clip: unset !important;
color: var(--godspark-text);
}
/* ─── Cursor glow (opt-in via attribute) ─── */
[godspark-glow]::after,
.godspark-glow-active::after {
content: "";
position: fixed;
width: 360px;
height: 360px;
border-radius: 50%;
pointer-events: none;
z-index: 999999;
background: radial-gradient(
circle,
rgba(141, 168, 125, 0.22) 0%,
rgba(107, 143, 113, 0.08) 35%,
transparent 70%
);
transform: translate(-50%, -50%);
transition: opacity 0.4s ease;
opacity: 0;
will-change: transform, opacity;
}
[godspark-glow]::after,
.godspark-glow-active::after {
opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
[godspark-glow]::after,
.godspark-glow-active::after {
display: none !important;
}
.godspark-reveal {
opacity: 1;
transform: none;
transition: none;
}
.godspark-reveal.is-visible > * {
opacity: 1;
transform: none;
transition: none;
}
}
/* ─── Selection ─── */
::selection {
background: var(--godspark-primary);
color: #fff;
}
:focus-visible {
outline: 2px solid var(--godspark-primary);
outline-offset: 3px;
border-radius: 4px;
}
/* ─── Scrollbar ─── */
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background: var(--godspark-bg);
}
::-webkit-scrollbar-thumb {
background: linear-gradient(180deg,
var(--godspark-primary),
var(--godspark-accent),
var(--godspark-secondary));
border-radius: 99px;
}
/* ─── Print ─── */
@media print {
body {
background: #fff !important;
color: #000 !important;
}
h1, h2, h3, h4, h5, h6 {
color: #000 !important;
}
.godspark-glow-active::after,
[godspark-glow]::after { display: none !important; }
}
/* ─── Hero image on homepage ─── */
.godspark-hero {
margin: 1.2rem 0 2rem;
border-radius: 22px;
overflow: hidden;
border: 1px solid var(--godspark-card-border);
background:
linear-gradient(180deg, rgba(255,255,255,0.55), rgba(255,255,255,0.35)),
var(--godspark-aurora);
background-blend-mode: overlay;
backdrop-filter: blur(10px) saturate(120%);
-webkit-backdrop-filter: blur(10px) saturate(120%);
}
.godspark-hero img {
display: block;
width: 100%;
height: auto;
max-height: 360px;
object-fit: cover;
}
.godspark-hero figcaption {
padding: 0.8rem 1rem;
color: var(--godspark-text-muted);
font-size: 0.92rem;
}

View file

@ -0,0 +1,72 @@
# Zensical Consciousness Theme — Plan & Prompt Document
## 1. Goal
Build a nature/consciousness-themed, beautiful, pastel/iridescent, performance-safe theme
for a multi-contributor Zensical awareness site about reigniting the God Spark within.
## 2. What we learned from Zensical customization
- Theme extension is mostly additive:
- `zensical.toml``extra_css` for extra stylesheets.
- Page templates can be overridden by placing matching files under `overrides/`.
- Site theming is largely controlled by palette/color attributes:
- `data-md-color-scheme`
- `data-md-color-primary`
- `data-md-color-accent`
- `extra.css` is the safest layer; it shouldnt break Zensical if it only adds selectors
and doesnt overwrite core layout-critical rules blindly.
- We should keep JS minimal, lazy-friendly, and nonblocking for contributors.
## 3. Non-goals / constraints
- No TypeScript/React build pipeline rerouting.
- No breaking built-in Zensical navigation/search/skip behavior.
- No space/technology motif — instead: botanical/organic/aurora/nature.
- Animations must respect load speed and reduced-motion.
- Theme should still be readable as Markdown documentation after styling.
## 4. Adapting MotionSites-style prompts for Kimi
From the example landing-page prompts:
- Use: typography system, motion patterns, component thinking, copy composition.
- Remove: React/TS/Vite/Framer Motion specifics.
- Replace with: plain HTML/CSS + minimal vanilla JS utilities that Zensical can load.
## 5. Ready-to-run Kimi prompt (refined)
You are a web designer specializing in calm, premium editorial interfaces.
Create a Zensical theme add-on for a consciousness/awakening awareness site.
Theme name placeholder: "God Spark". Site title is temporary and may change later.
Constraints:
- Output must be plain HTML/CSS/JS only.
- Must work as a Zensical `extra.css` drop-in plus optional `overrides/` partials.
- Do NOT use React, TypeScript, Tailwind build, Framer Motion, or shadcn/ui.
- Do NOT break Zensical core behavior.
- Performance-first: no heavy dependencies; any JS should be small and optional.
- Accessibility-first: readable contrast, reduced-motion safe, semantic markup.
Design brief:
- Aesthetic: futuristic pastel + iridescent, but inspired by nature rather than space/tech.
Soft aurora-like gradients, botanical motifs, dappled-light effects, gentle watercolor-like transitions.
- Color palette references: soft lavender, mist, pearl, sage, blush, iris, morning frost.
- Typography: elegant serif headings, clean sans-serif body. Use standard system fonts or
Google Fonts loaded with `preconnect` if needed.
- Contributions UI must remain friendly for many contributors: simple class names, clear areas
to edit content blocks, great default headings, friendly call-to-action language.
Functional requirements:
1) Provide one CSS file intended as Zensical's `extra.css` entry.
2) Provide optional HTML/JS micro-animations:
- fade-up reveal on scroll via IntersectionObserver
- soft parallax cursor glow (optional, turned off by default)
3) Provide at least 2 override template examples for `overrides/` (e.g., `main.html`, `footer.html`)
that layer glass surfaces and brand text without removing existing placeholders.
4) Include README with install steps, customization guidance, and contributor notes.
## 6. Execution plan
1. Create an isolated sandbox outside the project.
2. Generate theme kit using the prompt above with Kimi.
3. Review generated files for Zensical safety before pulling into the project.
4. Keep the prompt in `docs/zensical-theme-plan.md` for refinement.
## 7. Where this is saved
- Path: `/home/a/w/up/docs/zensical-theme-plan.md`
- Reuse by updating this file and rerunning Kimi from the same sandboxed branch/tree.

View file

@ -1 +1,14 @@
Hi # _{site title here}_
<figure class="godspark-hero" markdown="1">
<img src="assets/images/hero.jpg" alt="Hero" />
<figcaption>Nature is the oldest teacher of awareness.</figcaption>
</figure>
## Welcome
This is the beginning of something conscious.
- Contribute freely
- Share what calls to you
- Let the theme grow with the content

View file

@ -57,7 +57,7 @@ Copyright &copy; 2026 The authors
# #
# Read more: https://zensical.org/docs/customization/#additional-css # Read more: https://zensical.org/docs/customization/#additional-css
# #
#extra_css = ["stylesheets/extra.css"] extra_css = ["stylesheets/extra.css"]
# With the `extra_javascript` option you can add your own JavaScript to your # With the `extra_javascript` option you can add your own JavaScript to your
# project to customize the behavior according to your needs. # project to customize the behavior according to your needs.
@ -65,7 +65,7 @@ Copyright &copy; 2026 The authors
# The path provided should be relative to the "docs_dir". # The path provided should be relative to the "docs_dir".
# #
# Read more: https://zensical.org/docs/customization/#additional-javascript # Read more: https://zensical.org/docs/customization/#additional-javascript
#extra_javascript = ["javascripts/extra.js"] extra_javascript = ["javascripts/extra.js"]
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Section for configuring theme options # Section for configuring theme options
@ -83,7 +83,7 @@ Copyright &copy; 2026 The authors
# Read more: # Read more:
# - https://zensical.org/docs/customization/#extending-the-theme # - https://zensical.org/docs/customization/#extending-the-theme
# #
#custom_dir = "overrides" custom_dir = "overrides"
# With the "favicon" option you can set your own image to use as the icon # With the "favicon" option you can set your own image to use as the icon
# browsers will use in the browser title bar or tab bar. The path provided # browsers will use in the browser title bar or tab bar. The path provided
@ -289,11 +289,15 @@ features = [
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
[[project.theme.palette]] [[project.theme.palette]]
scheme = "default" scheme = "default"
primary = "green"
accent = "teal"
toggle.icon = "lucide/sun" toggle.icon = "lucide/sun"
toggle.name = "Switch to dark mode" toggle.name = "Switch to dark mode"
[[project.theme.palette]] [[project.theme.palette]]
scheme = "slate" scheme = "slate"
primary = "green"
accent = "teal"
toggle.icon = "lucide/moon" toggle.icon = "lucide/moon"
toggle.name = "Switch to light mode" toggle.name = "Switch to light mode"