Add Quartz knowledge base site

This commit is contained in:
Meta Vens 2026-05-24 03:01:36 +01:00
commit 4607ce0adf
17 changed files with 880 additions and 8 deletions

24
.github/workflows/deploy-quartz.yml vendored Normal file
View file

@ -0,0 +1,24 @@
name: Deploy Quartz
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
deploy:
uses: GameCult/GameCult-Quartz/.github/workflows/quartz-pages.yml@main
with:
content-dir: .
overlay-dir: site
output-dir: quartz-site/public

2
.gitignore vendored
View file

@ -3,6 +3,8 @@ config/audio-field.json
logs/
*.log
*.tmp
.quartz-build/
quartz-site/
calibration/runs/
artifacts/drivers/
artifacts/asio/

View file

@ -50,11 +50,3 @@ corpus.
## Persistence And Identity
- [Mimir Face](docs/mimir-face.md)
- [Scratch](state/scratch.md)
- [AGENTS](AGENTS.md)
## Branding
- [Mimir Face Prompts](assets/branding/mimir-face-prompts.md)
- [Mimir Icon Prompts](assets/branding/mimir-icon-prompts.md)

12
index.md Normal file
View file

@ -0,0 +1,12 @@
# Mimir
Mimir is the local realtime field machine: cameras, microphones, speakers, timing
signals, and runtime evidence pulled into one coherent OBS-facing surface.
## Start Here
- [Current System Map](notes/current-system-map.md)
- [Perfect Machine Domain Index](docs/perfect-machine-domain-index.md)
- [Code Algorithm Map](docs/code-algorithm-map.md)
- [Implementation Plan](docs/implementation-plan.md)
- [Study Reading Guide](research/perfect-machine-study-2026-05-23/reading-guide.md)

50
scripts/quartz/quartz.ps1 Normal file
View file

@ -0,0 +1,50 @@
param(
[ValidateSet("build", "dev")]
[string]$Command = "dev"
)
$ErrorActionPreference = "Stop"
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$sharedQuartzRoot = if ($env:GAMECULT_QUARTZ_ROOT) {
$env:GAMECULT_QUARTZ_ROOT
} else {
Join-Path (Split-Path -Parent $repoRoot) "GameCult-Quartz"
}
$portableNodeRoot = Join-Path $repoRoot ".tools\node-v24.15.0-win-x64"
$portableNode = Join-Path $portableNodeRoot "node.exe"
if (Test-Path $portableNode) {
$node = $portableNode
$env:PATH = "$portableNodeRoot;$env:PATH"
} else {
$nodeCommand = Get-Command node -ErrorAction SilentlyContinue
if (-not $nodeCommand) {
throw "node was not found. Install Node.js or restore the portable runtime under .tools."
}
$node = $nodeCommand.Source
}
$env:npm_config_cache = Join-Path $repoRoot ".npm-cache"
if (-not (Test-Path $sharedQuartzRoot)) {
throw "GameCult-Quartz was not found at '$sharedQuartzRoot'. Clone it beside this repo or set GAMECULT_QUARTZ_ROOT."
}
$buildScript = Join-Path $sharedQuartzRoot "scripts\build-site.mjs"
if (-not (Test-Path $buildScript)) {
throw "GameCult-Quartz build script was not found at '$buildScript'."
}
$scriptArgs = @(
$buildScript,
$Command,
"--siteRoot", $repoRoot,
"--overlayDir", "site",
"--contentDir", ".",
"--outputDir", "quartz-site/public"
)
& $node @scriptArgs

17
site/README.md Normal file
View file

@ -0,0 +1,17 @@
# Mimir Quartz Site
Quartz overlay for the future `https://mimir.gamecult.org` knowledge base.
The content source is the repo root Obsidian vault; this `site/` directory owns
presentation, navigation, and static-site wiring.
The site follows the shared GameCult-Quartz deployment pattern:
- content directory: repo root (`.`)
- overlay directory: `site`
- output directory: `quartz-site/public`
- GitHub Pages host: `gamecult.github.io`
- custom domain: `mimir.gamecult.org`
The overlay intentionally excludes source/build/runtime folders from publishing
while keeping the docs, research notes, handoff notes, and vault index visible.

184
site/quartz.config.ts Normal file
View file

@ -0,0 +1,184 @@
import { QuartzConfig } from "./quartz/cfg";
import * as Plugin from "./quartz/plugins";
import { QuartzEmitterPlugin } from "./quartz/plugins/types";
import { Fragment, h } from "preact";
const MimirMeta: QuartzEmitterPlugin = () => ({
name: "MimirMeta",
async *emit() {},
async *partialEmit() {},
externalResources: () => ({
additionalHead: [
() =>
h(Fragment, {}, [
h("meta", {
property: "twitter:domain",
content: "mimir.gamecult.org",
}),
h("meta", {
property: "og:url",
content: "https://mimir.gamecult.org/",
}),
h("meta", {
property: "twitter:url",
content: "https://mimir.gamecult.org/",
}),
]),
],
}),
});
const config: QuartzConfig = {
configuration: {
pageTitle: "Mimir",
pageTitleSuffix: "",
enableSPA: true,
enablePopovers: true,
analytics: null,
locale: "en-GB",
baseUrl: "mimir.gamecult.org",
ignorePatterns: [
".git",
".github",
".obsidian",
".quartz-build",
".voidbot",
"AGENTS.md",
"assets/branding",
"assets/branding/**",
"artifacts",
"artifacts/**",
"bin",
"bin/**",
"calibration",
"calibration/**",
"config",
"config/**",
"faust",
"faust/**",
"logs",
"logs/**",
"native/**/build",
"native/**/target",
"node_modules",
"node_modules/**",
"obj",
"obj/**",
"quartz-site",
"quartz-site/**",
"research/**/mirrors",
"research/**/mirrors/**",
"scripts",
"scripts/**",
"site",
"site/**",
"src",
"src/**",
"state",
"state/**",
"target",
"target/**",
"tools",
"tools/**",
"**/*.slnx",
"**/*.csproj",
"**/*.vcxproj",
"**/*.filters",
"**/*.tlog",
"**/*.obj",
"**/*.dll",
"**/*.exe",
"**/*.lib",
"**/*.exp",
"**/*.jsonl",
"**/*.yaml",
"**/*.yml",
"**/*.toml",
"**/*.lock",
],
defaultDateType: "modified",
theme: {
fontOrigin: "googleFonts",
cdnCaching: true,
typography: {
header: {
name: "Montserrat",
weights: [100, 200, 300, 400, 600],
},
title: {
name: "Montserrat",
weights: [100, 200, 300],
},
body: {
name: "Ubuntu",
weights: [300, 400, 500, 700],
includeItalic: true,
},
code: "IBM Plex Mono",
},
colors: {
lightMode: {
light: "#05090d",
lightgray: "#111a20",
gray: "#6d8792",
darkgray: "#c4dce5",
dark: "#f3fbff",
secondary: "#64b7ff",
tertiary: "#9bd887",
highlight: "rgba(100, 183, 255, 0.14)",
textHighlight: "#9bd88755",
},
darkMode: {
light: "#05090d",
lightgray: "#111a20",
gray: "#6d8792",
darkgray: "#c4dce5",
dark: "#f3fbff",
secondary: "#64b7ff",
tertiary: "#9bd887",
highlight: "rgba(100, 183, 255, 0.14)",
textHighlight: "#9bd88755",
},
},
},
},
plugins: {
transformers: [
Plugin.FrontMatter(),
Plugin.CreatedModifiedDate({
priority: ["frontmatter", "git", "filesystem"],
}),
Plugin.SyntaxHighlighting({
theme: {
light: "github-dark",
dark: "github-dark",
},
keepBackground: false,
}),
Plugin.ObsidianFlavoredMarkdown({ enableInHtmlEmbed: false }),
Plugin.GitHubFlavoredMarkdown(),
Plugin.TableOfContents(),
Plugin.CrawlLinks({ markdownLinkResolution: "shortest" }),
Plugin.Description(),
Plugin.Latex({ renderEngine: "katex" }),
],
filters: [Plugin.RemoveDrafts()],
emitters: [
Plugin.AliasRedirects(),
Plugin.ComponentResources(),
Plugin.ContentPage(),
Plugin.FolderPage(),
Plugin.ContentIndex({
enableSiteMap: false,
enableRSS: false,
}),
Plugin.Assets(),
Plugin.Static(),
MimirMeta(),
Plugin.NotFoundPage(),
Plugin.CustomOgImages(),
],
},
};
export default config;

70
site/quartz.layout.ts Normal file
View file

@ -0,0 +1,70 @@
import { PageLayout, SharedLayout } from "./quartz/cfg";
import * as Component from "./quartz/components";
import MimirMasthead from "./quartz/components/MimirMasthead";
import MimirOverviewSidebar from "./quartz/components/MimirOverviewSidebar";
import MimirThemeLock from "./quartz/components/MimirThemeLock";
const MimirGraphShell = Component.GameCultGraphSpaShell({
stylesheetHref:
"/static/epiphany-graph/assets/viewer.css?v=graph-mimir-20260524",
moduleSrc: "/static/epiphany-graph/assets/viewer.js?v=graph-mimir-20260524",
});
export const sharedPageComponents: SharedLayout = {
head: Component.Head(),
header: [MimirThemeLock(), MimirMasthead(), Component.Search()],
afterBody: [
Component.ConditionalRender({
component: MimirGraphShell,
condition: (page) =>
page.fileData.slug === "Mimir-Vault" || page.fileData.slug === "index",
}),
],
footer: Component.Footer({
links: {},
}),
};
export const defaultContentPageLayout: PageLayout = {
beforeBody: [
Component.ConditionalRender({
component: Component.Breadcrumbs({
rootName: "Mimir",
showCurrentPage: false,
showRoot: false,
}),
condition: (page) =>
page.fileData.slug !== "Mimir-Vault" && page.fileData.slug !== "index",
}),
Component.ConditionalRender({
component: Component.ArticleTitle(),
condition: (page) =>
!page.fileData.slug?.endsWith("/index") &&
page.fileData.slug !== "Mimir-Vault",
}),
Component.ConditionalRender({
component: Component.ContentMeta(),
condition: (page) =>
!page.fileData.slug?.endsWith("/index") &&
page.fileData.slug !== "Mimir-Vault",
}),
],
afterBody: [],
left: [MimirOverviewSidebar()],
right: [
Component.DesktopOnly(Component.TableOfContents()),
Component.Backlinks(),
],
};
export const defaultListPageLayout: PageLayout = {
beforeBody: [
Component.Breadcrumbs({
rootName: "Mimir",
showCurrentPage: false,
showRoot: false,
}),
],
left: [],
right: [],
};

View file

@ -0,0 +1,97 @@
import {
QuartzComponent,
QuartzComponentConstructor,
QuartzComponentProps,
} from "./types";
import { FullSlug, resolveRelative } from "../util/path";
type Route = {
label: string;
slug: FullSlug;
matches: string[];
};
const routes: Route[] = [
{
label: "Home",
slug: "Mimir-Vault" as FullSlug,
matches: ["Mimir-Vault", "index"],
},
{
label: "Docs",
slug: "docs/perfect-machine-domain-index" as FullSlug,
matches: ["docs"],
},
{
label: "Runtime",
slug: "notes/current-system-map" as FullSlug,
matches: ["notes", "state"],
},
{
label: "Research",
slug: "research/perfect-machine-study-2026-05-23/reading-guide" as FullSlug,
matches: ["research"],
},
{ label: "Native", slug: "native/README" as FullSlug, matches: ["native"] },
];
function isMatch(currentSlug: string, prefix: string) {
return currentSlug === prefix || currentSlug.startsWith(`${prefix}/`);
}
function pickActiveRoute(currentSlug: string) {
return routes
.flatMap((route) =>
route.matches
.filter((prefix) => isMatch(currentSlug, prefix))
.map((prefix) => ({ route, prefixLength: prefix.length })),
)
.sort((a, b) => b.prefixLength - a.prefixLength)[0]?.route;
}
export default (() => {
const MimirMasthead: QuartzComponent = ({
fileData,
}: QuartzComponentProps) => {
const currentSlug = fileData.slug ?? ("Mimir-Vault" as FullSlug);
const activeRoute = pickActiveRoute(currentSlug);
return (
<section class="mimir-titlebar">
<a
class="mimir-titlebar-logo"
href={resolveRelative(currentSlug, "Mimir-Vault" as FullSlug)}
aria-label="Mimir home"
>
<img src="/Mimir.png" alt="" />
</a>
<div class="mimir-titlebar-copy">
<p class="mimir-titlebar-title">
<a href={resolveRelative(currentSlug, "Mimir-Vault" as FullSlug)}>
Mimir
</a>
</p>
<p class="mimir-titlebar-tagline">
Realtime cameras, microphones, chirplets, and field evidence
organized into one coherent stream machine.
</p>
</div>
<nav class="mimir-titlebar-nav" aria-label="Mimir sections">
{routes.map((route) => {
const active = activeRoute?.slug === route.slug;
return (
<a
href={resolveRelative(currentSlug, route.slug)}
class={active ? "mimir-nav-chip active" : "mimir-nav-chip"}
>
{route.label}
</a>
);
})}
</nav>
</section>
);
};
return MimirMasthead;
}) satisfies QuartzComponentConstructor;

View file

@ -0,0 +1,57 @@
import {
QuartzComponent,
QuartzComponentConstructor,
QuartzComponentProps,
} from "./types";
import { FullSlug, resolveRelative } from "../util/path";
type SidebarLink = {
label: string;
slug: FullSlug;
};
const links: SidebarLink[] = [
{ label: "Current System Map", slug: "notes/current-system-map" as FullSlug },
{ label: "Code Algorithm Map", slug: "docs/code-algorithm-map" as FullSlug },
{
label: "Perfect Machine Domain Index",
slug: "docs/perfect-machine-domain-index" as FullSlug,
},
{
label: "Study Reading Guide",
slug: "research/perfect-machine-study-2026-05-23/reading-guide" as FullSlug,
},
{
label: "Calibration Session Spec",
slug: "research/perfect-machine-study-2026-05-23/calibration-session-spec" as FullSlug,
},
{
label: "Fensalir Integration Map",
slug: "research/perfect-machine-study-2026-05-23/fensalir-integration-map" as FullSlug,
},
];
export default (() => {
const MimirOverviewSidebar: QuartzComponent = ({
fileData,
}: QuartzComponentProps) => {
const currentSlug = fileData.slug ?? ("Mimir-Vault" as FullSlug);
return (
<aside class="mimir-overview" aria-label="Mimir machine surface">
<p class="mimir-overview-title">Machine Surface</p>
<p class="mimir-overview-copy">
Start with the live map, then descend into the decoder, calibration,
native ingest, and Fensalir cuts.
</p>
<nav>
{links.map((link) => (
<a href={resolveRelative(currentSlug, link.slug)}>{link.label}</a>
))}
</nav>
</aside>
);
};
return MimirOverviewSidebar;
}) satisfies QuartzComponentConstructor;

View file

@ -0,0 +1,13 @@
import { QuartzComponent, QuartzComponentConstructor } from "./types";
export default (() => {
const MimirThemeLock: QuartzComponent = () => (
<script
dangerouslySetInnerHTML={{
__html: `document.documentElement.setAttribute("saved-theme", "dark")`,
}}
/>
);
return MimirThemeLock;
}) satisfies QuartzComponentConstructor;

View file

@ -0,0 +1,326 @@
@use "./base.scss";
@use "./variables.scss" as *;
:root,
:root[saved-theme="light"],
:root[saved-theme="dark"] {
color-scheme: dark;
}
body {
background:
radial-gradient(
circle at 72% 10%,
rgba(100, 183, 255, 0.18),
transparent 18%
),
radial-gradient(
circle at 16% 12%,
rgba(155, 216, 135, 0.11),
transparent 24%
),
radial-gradient(
circle at 50% 0%,
rgba(255, 174, 88, 0.09),
transparent 30%
),
linear-gradient(180deg, #03070d 0%, #061018 46%, #08120d 100%);
color: var(--darkgray);
}
.page {
position: relative;
max-width: 1680px;
padding: 0 1.2rem 2.5rem;
}
.page::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
background-image:
linear-gradient(rgba(100, 183, 255, 0.035) 1px, transparent 1px),
linear-gradient(90deg, rgba(155, 216, 135, 0.03) 1px, transparent 1px);
background-size: 28px 28px;
mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.72), transparent 95%);
opacity: 0.72;
}
.page > #quartz-body .center,
.page > #quartz-body footer {
max-width: none;
}
.page > #quartz-body .left.sidebar {
gap: 0;
padding: 2.4rem 1rem 0 0;
background: transparent;
border: none;
box-shadow: none;
backdrop-filter: none;
}
.page > #quartz-body .center > .page-header {
margin-top: 2.4rem;
}
.page > #quartz-body .center header {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 1rem 1.25rem;
align-items: start;
margin: 0 0 1rem;
padding: 1rem 1.15rem 1.05rem;
border: 1px solid rgba(100, 183, 255, 0.16);
border-radius: 22px;
background:
radial-gradient(
circle at 82% 50%,
rgba(100, 183, 255, 0.15),
transparent 22%
),
linear-gradient(135deg, rgba(7, 12, 19, 0.98), rgba(8, 18, 14, 0.95));
box-shadow:
0 20px 44px rgba(0, 0, 0, 0.24),
inset 0 1px 0 rgba(255, 255, 255, 0.03);
overflow: hidden;
}
.page > #quartz-body .center header > .search {
max-width: 9rem;
width: 100%;
justify-self: end;
}
.mimir-titlebar {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
gap: 0.75rem 1rem;
min-width: 0;
}
.mimir-titlebar-logo {
grid-row: 1 / span 2;
display: block;
width: clamp(4.2rem, 8vw, 6.4rem);
aspect-ratio: 1;
align-self: start;
}
.mimir-titlebar-logo img {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
.mimir-titlebar-copy {
display: flex;
flex-direction: column;
gap: 0.18rem;
}
.mimir-titlebar-title,
.mimir-titlebar-title a {
margin: 0;
color: var(--dark);
font-family: var(--titleFont);
font-size: clamp(2.1rem, 4vw, 3.3rem);
font-weight: 200;
line-height: 0.92;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.mimir-titlebar-tagline {
margin: 0;
color: rgba(196, 220, 229, 0.84);
font-family: var(--titleFont);
font-size: 0.88rem;
font-weight: 200;
letter-spacing: 0.02em;
line-height: 1.4;
max-width: 76ch;
}
.mimir-titlebar-nav {
grid-column: 2;
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
}
.mimir-nav-chip {
display: inline-flex;
align-items: center;
min-height: 2.15rem;
padding: 0.3rem 0.8rem;
border-radius: 999px;
border: 1px solid rgba(100, 183, 255, 0.2);
background: rgba(100, 183, 255, 0.07);
color: #e8f7ff;
font-family: var(--titleFont);
font-size: 0.92rem;
font-weight: 300;
letter-spacing: 0.02em;
}
.mimir-nav-chip:hover,
.mimir-nav-chip.active {
background: rgba(155, 216, 135, 0.14);
border-color: rgba(155, 216, 135, 0.42);
color: #f2ffe8;
}
.article-title,
article > h1,
article > h2,
article > h3,
article > h4,
article > h5,
article > h6 {
font-family: var(--titleFont);
letter-spacing: 0.015em;
}
.article-title {
margin: 0;
font-size: clamp(2rem, 3vw, 2.85rem);
font-weight: 200;
line-height: 0.96;
}
.page > #quartz-body .center > article {
position: relative;
background:
linear-gradient(180deg, rgba(9, 16, 22, 0.98), rgba(7, 14, 11, 0.96)),
linear-gradient(
180deg,
rgba(100, 183, 255, 0.02),
rgba(155, 216, 135, 0.02)
);
border: 1px solid rgba(100, 183, 255, 0.1);
border-radius: 24px;
box-shadow:
0 24px 52px rgba(0, 0, 0, 0.26),
inset 0 1px 0 rgba(255, 255, 255, 0.03);
padding: 1.45rem 1.7rem 1.9rem;
overflow: hidden;
}
body[data-slug="Mimir-Vault"] .page > #quartz-body .center > article {
padding-top: 0;
}
.mimir-hero-canvas {
display: block;
width: calc(100% + 3.4rem);
margin: 0 -1.7rem 1.35rem;
min-height: 360px;
border-bottom: 1px solid rgba(100, 183, 255, 0.12);
background: #03070d;
}
.page > #quartz-body .right.sidebar {
gap: 1rem;
padding: 2.4rem 0 0 1rem;
background: transparent;
border: none;
box-shadow: none;
backdrop-filter: none;
}
.toc,
.backlinks,
.mimir-overview {
border: 1px solid rgba(100, 183, 255, 0.12);
border-radius: 20px;
background: linear-gradient(
180deg,
rgba(9, 16, 22, 0.9),
rgba(7, 14, 11, 0.82)
);
box-shadow:
0 18px 40px rgba(0, 0, 0, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.03);
padding: 1rem;
}
.mimir-overview-title {
margin: 0 0 0.35rem;
color: var(--secondary);
font-family: var(--titleFont);
font-size: 0.78rem;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.mimir-overview-copy {
margin: 0 0 0.9rem;
color: rgba(196, 220, 229, 0.78);
font-size: 0.9rem;
line-height: 1.5;
}
.mimir-overview nav {
display: grid;
gap: 0.45rem;
}
.mimir-overview a {
display: block;
color: #e8f7ff;
border: 1px solid rgba(100, 183, 255, 0.12);
border-radius: 14px;
padding: 0.55rem 0.65rem;
background: rgba(100, 183, 255, 0.05);
}
.mimir-overview a:hover {
border-color: rgba(155, 216, 135, 0.36);
background: rgba(155, 216, 135, 0.1);
}
article strong {
color: #f5fbff;
}
article table {
border-color: rgba(100, 183, 255, 0.16);
}
article tr,
article td,
article th {
border-color: rgba(100, 183, 255, 0.12);
}
@media all and not ($desktop) {
.page > #quartz-body .center header {
grid-template-columns: minmax(0, 1fr);
}
.page > #quartz-body .center header > .search {
justify-self: stretch;
max-width: none;
}
.mimir-hero-canvas {
width: calc(100% + 2rem);
margin-inline: -1rem;
}
.mimir-titlebar {
grid-template-columns: minmax(0, 1fr);
}
.mimir-titlebar-logo {
grid-row: auto;
width: 4.4rem;
}
.mimir-titlebar-nav {
grid-column: auto;
}
}

View file

@ -0,0 +1 @@

1
static/epiphany-graph/assets/react.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
html,body,#root{width:100%;min-height:100%;margin:0}body{background:radial-gradient(circle at 72% 12%,rgba(255,174,88,.16),transparent 24%),radial-gradient(circle at 10% 18%,rgba(142,223,176,.16),transparent 28%),linear-gradient(180deg,#03070d,#07110f 52%,#091712);color:#effcf8;font-family:Ubuntu,Segoe UI,sans-serif}.gamecult-epiphany-graph-app{box-sizing:border-box;width:100vw;min-height:100vh;padding:0}.gamecult-epiphany-graph-app *{box-sizing:border-box}.gamecult-epiphany-graph-root{position:fixed;inset:0;z-index:1000;width:100vw;height:100vh;min-height:100vh;margin:0!important;border:0!important;border-radius:0!important;background:#03070d}.gamecult-graph-error{white-space:pre-wrap;color:#fecaca;background:#450a0a99;border:1px solid rgba(248,113,113,.45);border-radius:16px;padding:16px}.gamecult-graph-loading{display:grid;min-height:320px;place-items:center;color:#cfeee4;font-size:.95rem}body.gamecult-graph-spa-active{overflow:hidden}.gamecult-graph-shell{width:100vw;height:100vh}.gamecult-graph-shell .epiphany-graph-overlay-panel{opacity:.25;transition:opacity .16s ease,transform .16s ease,box-shadow .16s ease}.gamecult-graph-shell .epiphany-graph-overlay-panel:hover,.gamecult-graph-shell .epiphany-graph-overlay-panel:focus-within{opacity:1;transform:translateY(-1px)}.gamecult-graph-shell aside.epiphany-graph-overlay-panel>section{display:none!important}.gamecult-graph-shell aside.epiphany-graph-overlay-panel>section:last-child{display:grid!important;grid-row:1 / -1}.gamecult-expanded-article-node{box-sizing:border-box;padding:var(--node-pad-y, .62rem) var(--node-pad-x, .82rem);scrollbar-color:rgba(142,223,176,.58) rgba(3,7,13,.32);transition:border-radius .12s ease,box-shadow .12s ease,padding .12s ease,opacity .12s ease}.gamecult-expanded-article-node .gamecult-spa-panel{max-height:none;overflow:visible}.gamecult-spa-panel{min-height:0;max-height:100%;overflow:auto;color:#effcf8}.gamecult-spa-panel h1{max-height:var(--node-title-max-height, 1.12em);margin:0;overflow:hidden;color:#f7fffb;font-size:var(--node-title-size, 1.08rem);line-height:1.04;letter-spacing:0}.gamecult-spa-kicker{margin:0 0 var(--node-kicker-margin, .12rem);color:#8edfb0;font-size:.76rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;opacity:var(--node-preview, 0);transition:opacity .12s ease}.gamecult-spa-summary,.gamecult-spa-status{color:#effcf8c2;line-height:1.55;max-height:var(--node-preview-height, 0rem);margin-block:var(--node-status-margin, 0rem);overflow:hidden;opacity:var(--node-preview, 0)}.gamecult-spa-status{margin:1rem 0;padding:.75rem .9rem;border:1px solid rgba(142,223,176,.16);border-radius:16px;background:#03070d73}.gamecult-spa-status-error{color:#fecaca;border-color:#f8717159}.gamecult-spa-article-header{display:grid;grid-template-columns:var(--node-badge-size, 3rem) minmax(0,1fr);align-items:center;gap:var(--node-panel-gap, .72rem);min-height:var(--node-badge-size, 3rem);margin-bottom:var(--node-header-margin, 0rem)}.gamecult-spa-node-badge{display:grid;width:var(--node-badge-size, 3rem);height:var(--node-badge-size, 3rem);place-items:center;border-radius:999px;background:linear-gradient(160deg,#69e2ef,#c2f5f0);color:#08313a;font-size:var(--node-title-size, 1.08rem);font-weight:900;line-height:1;box-shadow:inset 0 0 0 1px #ffffff47,0 0 var(--node-badge-glow, 1rem) #5eead44d}.gamecult-spa-title-cluster{min-width:0}.gamecult-spa-actions{display:flex;gap:.6rem;flex-wrap:wrap}.gamecult-spa-actions a,.gamecult-spa-note-list button{border:1px solid rgba(142,223,176,.18);border-radius:16px;background:#8edfb014;color:#effcf8}.gamecult-spa-actions a{padding:.5rem .7rem;text-decoration:none}.gamecult-spa-article{color:#effcf8db;line-height:1.65;max-height:var(--node-article-height, 0rem);overflow:hidden;opacity:var(--node-article, 0);transform:translateY(var(--node-article-offset, .65rem));transition:opacity .12s ease,transform .12s ease}.gamecult-spa-article h1{display:none}.gamecult-spa-article h2,.gamecult-spa-article h3{color:#f7fffb;line-height:1.12}.gamecult-spa-article a{color:#ffe0a8}.gamecult-spa-article img{max-width:100%;border-radius:18px}.gamecult-spa-note-list{display:grid;gap:.7rem;max-height:var(--node-note-list-height, 0rem);overflow:hidden;opacity:var(--node-article, 0)}.gamecult-spa-note-list button{display:grid;gap:.35rem;padding:.85rem;text-align:left;cursor:pointer}.gamecult-spa-note-list button:hover{border-color:#ffae5861;background:#ffae581c}.gamecult-spa-note-list strong{color:#f7fffb}.gamecult-spa-note-list span{color:#effcf8ad;font-size:.92rem;line-height:1.45}@media(max-width:900px){.gamecult-graph-shell aside.epiphany-graph-overlay-panel{left:12px;right:12px;top:auto!important;bottom:12px!important;width:auto!important;max-height:48vh}}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>gamecult Fractal Eusocial Web</title>
<script type="module" crossorigin src="./assets/viewer.js"></script>
<link rel="modulepreload" crossorigin href="./assets/react.js">
<link rel="stylesheet" crossorigin href="./assets/viewer.css">
</head>
<body>
<div class="gamecult-epiphany-graph-root"></div>
</body>
</html>