From caacae52bbc39642bea6d5b4ef49f02c24935f5d Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 18 May 2026 01:26:44 +0100 Subject: [PATCH] Add Zyphos Quartz site --- .github/workflows/deploy-quartz.yml | 24 ++ .gitignore | 2 + Eusocial Interbeing/index.md | 27 +- Eusocial Interbeing/static/icon.png | Bin 0 -> 2064 bytes README.md | 7 + site/README.md | 15 + site/quartz.config.ts | 141 +++++++++ site/quartz.layout.ts | 53 ++++ site/quartz/components/ZyphosHeroScript.tsx | 118 ++++++++ site/quartz/components/ZyphosMasthead.tsx | 83 ++++++ .../components/ZyphosOverviewSidebar.tsx | 37 +++ site/quartz/components/ZyphosThemeLock.tsx | 13 + site/quartz/styles/custom.scss | 274 ++++++++++++++++++ state/evidence.jsonl | 1 + state/map.yaml | 2 + 15 files changed, 788 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/deploy-quartz.yml create mode 100644 Eusocial Interbeing/static/icon.png create mode 100644 site/README.md create mode 100644 site/quartz.config.ts create mode 100644 site/quartz.layout.ts create mode 100644 site/quartz/components/ZyphosHeroScript.tsx create mode 100644 site/quartz/components/ZyphosMasthead.tsx create mode 100644 site/quartz/components/ZyphosOverviewSidebar.tsx create mode 100644 site/quartz/components/ZyphosThemeLock.tsx create mode 100644 site/quartz/styles/custom.scss diff --git a/.github/workflows/deploy-quartz.yml b/.github/workflows/deploy-quartz.yml new file mode 100644 index 0000000..3595c22 --- /dev/null +++ b/.github/workflows/deploy-quartz.yml @@ -0,0 +1,24 @@ +name: Deploy Quartz + +on: + push: + branches: + - master + 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: Eusocial Interbeing + overlay-dir: site + output-dir: quartz-site/public diff --git a/.gitignore b/.gitignore index 4225627..36a2103 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ state/scratch-compaction-*.md /.rag/ /.tools/ /.npm-cache/ +/.quartz-build/ +/quartz-site/ diff --git a/Eusocial Interbeing/index.md b/Eusocial Interbeing/index.md index 5e027d0..2ed77d3 100644 --- a/Eusocial Interbeing/index.md +++ b/Eusocial Interbeing/index.md @@ -1,24 +1,33 @@ -# Eusocial Interbeing +# Zyphos -This setting centers on eusocial inter-species dynamics: civilizations that do not merely live in ecosystems, but negotiate with reproductive sites, memory-bearing forests, immune networks, migratory herds, pollinating castes, fungal archives, and engineered idea-organisms. +*A close-binary living world for the Aquarium demo, with names waiting for Weksa to earn them.* + +Zyphos is one member of a tightly bound terrestrial binary. Its slightly smaller twin, [[World/Zyphos Umbros Binary System|Umbros]], hangs in the sky as a fixed planetary presence. The primary star is dim, the habitable zone is close, and the biosphere has learned to treat light as a scarce civic resource rather than wallpaper. + +This site collects the setting work behind the Zyphos demo: the physics-constrained world model, the mutable-memory biosphere, the civilizations shaped by ecological contracts, the Aquarium rendering surface, and the future Weksa language work that will name the world from inside its inhabitants' ontologies. ## Core Premise -On one continent, the [[Airawa]] once lived in tight ecological reciprocity with [[Mother Trees]]. Their societies stored communal memory in tree networks that demanded nutrients, ritual labor, and political deference in return. One Airawa tribe created the [[Biological Memetic Engine]] to break that dependency. The tool worked too well. It became the foundation of the [[Airawa Empire]], a eugenics-obsessed biopunk state whose rulers can impose doctrine through the continent's connected living networks. +Zyphos life is founded on [[Ecology/Mutable Memory Endosymbiosis|mutable memory endosymbiosis]]. Every cell carries a memory-bearing symbiont. Sentience is not reserved for human-shaped minds; it gradients through cells, tissues, organisms, colonies, routes, forests, reefs, and landscapes. -On another continent, where Airawa never evolved or migrated, the [[Sa'auei'a]] developed a highly advanced nomadic civilization. They organize in squad-sized family units, keep [[Breeding Grounds]] sacred and communal, and bargain with ecologies that remember generosity. +On one continent, the [[Species/Airawa|Airawa]] once lived in tight ecological reciprocity with [[Species/Mother Trees|Mother Trees]]. Their societies stored communal memory in tree networks that demanded nutrients, ritual labor, and political deference in return. One Airawa tribe created the [[Technologies/Biological Memetic Engine|Biological Memetic Engine]] to break that dependency. The tool worked too well. It became the foundation of the [[Civilizations/Airawa Empire|Airawa Empire]], a eugenics-obsessed biopunk state whose rulers can impose doctrine through the continent's connected living networks. -## Main Paths +On another continent, where Airawa never evolved or migrated, the [[Species/Sa'auei'a|Sa'auei'a]] developed a highly advanced nomadic civilization. They organize in squad-sized family units, keep [[Ecology/Breeding Grounds|Breeding Grounds]] sacred and communal, and bargain with ecologies that remember generosity. +## Project Surfaces + +- [[World/Zyphos Simulation Brief]] +- [[World/Zyphos Umbros Binary System]] +- [[Ecology/Mutable Memory Endosymbiosis]] +- [[Ecology/Zyphos Biosphere Examples]] - [[World/index]] +- [[Ecology/index]] - [[Species/index]] - [[Civilizations/index]] -- [[Ecology/index]] - [[Technologies/index]] -- [[Conflicts/index]] -- [[Themes/index]] -- [[Inspirations/index]] ## Current Design Rule Every major institution should be legible as an ecological deal, a reproductive pressure, a memory technology, or a path-dependent consequence. If it is just a normal state wearing wet architecture, cut it until the wound has a purpose. + +Physics is design authority. If the orbital math or energy budget tightens the image, the world bends. The bruise is usually where the better idea lives. diff --git a/Eusocial Interbeing/static/icon.png b/Eusocial Interbeing/static/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fcf45ec66bfc41e99c39b987a9fcb222ced227c1 GIT binary patch literal 2064 zcmV+r2=DiaP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D2c=0wK~#8N?V4L` z7DW`tNqittAY4R6AY6DI!!Yf}rIhAe0ucE%t^2BDbb#REUTODoqe# zrUxrA6mL6IWpqcQP8AAA_|pX98wXJ+@?*>ATo`TFq7*Us!Wd(MB(oH;XX zyIb0K6sb%*-jHgv3BVgtjWz*zL#ojx0B>k5I`!x$`iz|5(525n?U~k~)dXnY@pf_l z)E7ne?mAJ>c+-=4d%qT==Di{X;$y@?>;k}%^pXmZTlc-o(Z$sl#Efm9Ilyr)#*{a= zi=M;AXk$i6qymf>*h`Eb-dBF&_x@uuT#nD)SuLXg(ZIh;;5%@fzO(%JRT&Zdxu{55 zfFb>Qh=Zk%39)~s!#@XJ5PRznxE#N0NSgLtKM*+?tGBquh+|nKCBXdjLE`Uy(>3RJ z9Q#TdU398N9If3hHqCiR+}5G9_Wd9X&Y0mu(Zc=TL@q*T0dk(a&*eBl&aXQ4lem7Q z$Z3Bs=V5J(pulNLp7^}A+uhnTVF@Jw!k*7Ops_SV4i)lqeyBUmmd` zlmN%qr)$ogsj2XF9<*$qrj2C-Y6UCMks-Y`r)b?*)gRINIL}Yda8-buAp8F4Ma521Om-<) z3&4}##n0C{p^r#F8NAUAs!h|2i;N)Yb0P3?xUfBOn5zNp{wfV9YP>ET#!m42p(Wb7C$M$$@od3%IAB7i6lCca7hOW2gtk3Z z1{MHehIOdc_Jxf%oGf12@tP>V{HdsHIcNm^W9DRP_NdT# zVbuJ5={VVli3+k!CKLdfmu4Nwi3S}zFHg21^trPfI8XaOX1B2BZOvIfijQs+gC~yG zYy&u5QuyO{)CowWXhXupS%QB@#a940Pelg?Rl^EVfcC{Jmy18DvNWdw*1Q__;}&IU z&e`zvnkAZza2R$VLe+LuiWCigB6tb_XDRFvX1t%Gf|3sE{QS(JV(qLE@{`y7vnmTT zhr;mk?sZyzAY1rOfSg5<;FTOb1)#NMI(R@FIs4TYwC|Zn&zq$=k__2fi(TVW$eY$Y zU9R9hf%gHU0C1SX$8?baHPMHh!238@yWD{&P?IA~mMPRRS(qsFW4Z8tqX1a@ehxxu z^h0^x$FWU#L0NnDW6`1eo$?)&{ZTOS_XCOoBuw6C6kvGP0{I2XtQ;uq*H2)UxZzPU zrDTD84;_y1$!!3X3rt67qX4*=^jkM1kSRH;#; zSx2AOsnJsawFu(b6+4695&;i9^SEYg9AJy3U4SP!*hxNMS#ukKrvQMG3&6Ukb`%_F z-%m3(4#wvdN;~qDdkRbv&s$yu7J$IO>fJ!W>6`M74(jve5LXolHe9Y3B~52V z{)t~)lY*VVFXTDa0uVzp=l&;x0-^-D0)jmC`ZCS%FjV|pEjC^`D%Lii5vAwde`Y7f ztyrf`KoCL;04V!TE8peh1QW$)uSmn;Kv2rgUlJwfE^A{sW1jgzWNvz2{_M5K2O%i| zFv~DN-43z+VEasTy=}wFrWPsSn&xvd^ee9&l9wYi0bUhg5RwuAP(JY54dgSsD`W`2 z@m-@f(?%|ymd|hgu})hK0J)`0-vRQy*zWj6hz&^#K&2+uKJO!NgA-LkTy^pTxx-NP zhbZ9hvmt2#u=XelOtm3H>9mU3H(herkhB0mHOTAkjldZ`%qemD#$_^+ zf(jm#NCW^Bl1P4uGIHmhz2zn8`fvAWj;f#^_kTF@^7r^HIU6DqK)ppqVU$P&0wpu* zd5-Dt0OUL(&2(28hR6f}>R*s-L;egyfS;;3jf0SNlH7tAcpIz<55ldbG*X>|eq uZ?p-(8&Zun0eC~I(Ix ({ + name: "ZyphosFavicons", + async *emit() {}, + async *partialEmit() {}, + externalResources: () => ({ + additionalHead: [ + () => + h(Fragment, {}, [ + h("meta", { property: "twitter:domain", content: "zyphos.gamecult.org" }), + h("meta", { property: "og:url", content: "https://zyphos.gamecult.org/" }), + h("meta", { property: "twitter:url", content: "https://zyphos.gamecult.org/" }), + ]), + ], + }), +}) + +const ZyphosHeroResources: QuartzEmitterPlugin = () => ({ + name: "ZyphosHeroResources", + async *emit() {}, + async *partialEmit() {}, + externalResources: () => ({ + js: [ + { + script: zyphosHeroScript, + loadTime: "afterDOMReady", + contentType: "inline", + spaPreserve: true, + }, + ], + }), +}) + +const config: QuartzConfig = { + configuration: { + pageTitle: "Zyphos", + pageTitleSuffix: "", + enableSPA: true, + enablePopovers: true, + analytics: null, + locale: "en-GB", + baseUrl: "zyphos.gamecult.org", + ignorePatterns: [ + "private", + "templates", + ".obsidian", + "Inspirations", + "Inspirations/**", + ], + 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: "#07110f", + lightgray: "#16251f", + gray: "#668077", + darkgray: "#bdd4ca", + dark: "#effcf8", + secondary: "#ffae58", + tertiary: "#8edfb0", + highlight: "rgba(142, 223, 176, 0.14)", + textHighlight: "#ffae5855", + }, + darkMode: { + light: "#07110f", + lightgray: "#16251f", + gray: "#668077", + darkgray: "#bdd4ca", + dark: "#effcf8", + secondary: "#ffae58", + tertiary: "#8edfb0", + highlight: "rgba(142, 223, 176, 0.14)", + textHighlight: "#ffae5855", + }, + }, + }, + }, + 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(), + ZyphosFavicons(), + ZyphosHeroResources(), + Plugin.NotFoundPage(), + Plugin.CustomOgImages(), + ], + }, +} + +export default config diff --git a/site/quartz.layout.ts b/site/quartz.layout.ts new file mode 100644 index 0000000..d78d433 --- /dev/null +++ b/site/quartz.layout.ts @@ -0,0 +1,53 @@ +import { PageLayout, SharedLayout } from "./quartz/cfg" +import * as Component from "./quartz/components" +import ZyphosMasthead from "./quartz/components/ZyphosMasthead" +import ZyphosOverviewSidebar from "./quartz/components/ZyphosOverviewSidebar" +import ZyphosThemeLock from "./quartz/components/ZyphosThemeLock" + +export const sharedPageComponents: SharedLayout = { + head: Component.Head(), + header: [ZyphosThemeLock(), ZyphosMasthead(), Component.Search()], + afterBody: [], + footer: Component.Footer({ + links: {}, + }), +} + +export const defaultContentPageLayout: PageLayout = { + beforeBody: [ + Component.ConditionalRender({ + component: Component.Breadcrumbs({ + rootName: "Zyphos", + showCurrentPage: false, + showRoot: false, + }), + condition: (page) => page.fileData.slug !== "index", + }), + Component.ConditionalRender({ + component: Component.ArticleTitle(), + condition: (page) => !page.fileData.slug?.endsWith("/index") && page.fileData.slug !== "index", + }), + Component.ConditionalRender({ + component: Component.ContentMeta(), + condition: (page) => !page.fileData.slug?.endsWith("/index") && page.fileData.slug !== "index", + }), + ], + afterBody: [], + left: [ZyphosOverviewSidebar()], + right: [ + Component.DesktopOnly(Component.TableOfContents()), + Component.Backlinks(), + ], +} + +export const defaultListPageLayout: PageLayout = { + beforeBody: [ + Component.Breadcrumbs({ + rootName: "Zyphos", + showCurrentPage: false, + showRoot: false, + }), + ], + left: [], + right: [], +} diff --git a/site/quartz/components/ZyphosHeroScript.tsx b/site/quartz/components/ZyphosHeroScript.tsx new file mode 100644 index 0000000..d2feb5e --- /dev/null +++ b/site/quartz/components/ZyphosHeroScript.tsx @@ -0,0 +1,118 @@ +import { QuartzComponent, QuartzComponentConstructor } from "./types" + +export const zyphosHeroScript = String.raw` +function bootZyphosHero() { + const home = document.querySelector("body[data-slug='index'] article") + if (!home || home.querySelector(".zyphos-hero-canvas")) return + + const canvas = document.createElement("canvas") + canvas.className = "zyphos-hero-canvas" + canvas.setAttribute("aria-hidden", "true") + home.prepend(canvas) + + const context = canvas.getContext("2d") + + function resize() { + const rect = home.getBoundingClientRect() + const ratio = Math.min(window.devicePixelRatio || 1, 2) + canvas.width = Math.max(1, Math.floor(rect.width * ratio)) + canvas.height = Math.floor(Math.min(window.innerHeight * 0.72, 620) * ratio) + canvas.style.height = Math.floor(canvas.height / ratio) + "px" + context.setTransform(ratio, 0, 0, ratio, 0, 0) + } + + function drawPlanet(x, y, radius, colors, time, shadow) { + const gradient = context.createRadialGradient(x - radius * 0.32, y - radius * 0.35, 0, x, y, radius) + gradient.addColorStop(0, colors[0]) + gradient.addColorStop(0.5, colors[1]) + gradient.addColorStop(1, colors[2]) + context.fillStyle = gradient + context.beginPath() + context.arc(x, y, radius, 0, Math.PI * 2) + context.fill() + + const eclipse = context.createRadialGradient(x + Math.cos(time) * radius * 0.3, y, 0, x, y, radius * 1.2) + eclipse.addColorStop(0, shadow) + eclipse.addColorStop(1, "rgba(0, 0, 0, 0)") + context.fillStyle = eclipse + context.beginPath() + context.arc(x, y, radius, 0, Math.PI * 2) + context.fill() + + context.strokeStyle = "rgba(142, 223, 176, 0.18)" + for (let i = 0; i < 5; i += 1) { + context.beginPath() + context.ellipse(x, y + Math.sin(i * 1.6) * radius * 0.42, radius * (0.44 + i * 0.05), radius * 0.08, i * 0.28, 0, Math.PI * 2) + context.stroke() + } + } + + function frame(now) { + const width = canvas.clientWidth + const height = canvas.clientHeight + const t = now * 0.00025 + context.clearRect(0, 0, width, height) + + const star = context.createRadialGradient(width * 0.78, height * 0.18, 0, width * 0.78, height * 0.18, width * 0.55) + star.addColorStop(0, "rgba(255, 174, 88, 0.22)") + star.addColorStop(1, "rgba(255, 174, 88, 0)") + context.fillStyle = star + context.fillRect(0, 0, width, height) + + context.strokeStyle = "rgba(115, 198, 227, 0.11)" + for (let i = 0; i < 7; i += 1) { + const y = height * (0.2 + i * 0.09) + Math.sin(t * 2 + i) * 6 + context.beginPath() + context.moveTo(0, y) + context.bezierCurveTo(width * 0.35, y - 30, width * 0.62, y + 36, width, y - 12) + context.stroke() + } + + const zr = Math.min(width, height) * 0.21 + const zx = width * 0.68 + const zy = height * 0.62 + const ur = zr * 0.62 + const ux = zx - zr * 1.85 + const uy = zy - zr * 0.7 + + context.strokeStyle = "rgba(239, 252, 248, 0.15)" + context.beginPath() + context.moveTo(ux, uy) + context.lineTo(zx, zy) + context.stroke() + + drawPlanet(ux, uy, ur, ["#7d8899", "#2c3a4a", "#070b11"], t + 1.2, "rgba(0, 0, 0, 0.6)") + drawPlanet(zx, zy, zr, ["#c7f7d0", "#28726c", "#06131b"], t, "rgba(0, 0, 0, 0.42)") + + context.fillStyle = "rgba(142, 223, 176, 0.62)" + for (let i = 0; i < 56; i += 1) { + const angle = i * 2.399 + t * 0.35 + const r = zr * (0.18 + ((i * 37) % 100) / 140) + const x = zx + Math.cos(angle) * r * 0.82 + const y = zy + Math.sin(angle) * r * 0.38 + const pulse = 1 + Math.sin(now * 0.002 + i) * 0.8 + context.beginPath() + context.arc(x, y, Math.max(0.7, pulse), 0, Math.PI * 2) + context.fill() + } + + requestAnimationFrame(frame) + } + + resize() + window.addEventListener("resize", resize) + requestAnimationFrame(frame) +} + +document.addEventListener("nav", bootZyphosHero) +document.addEventListener("DOMContentLoaded", bootZyphosHero) +bootZyphosHero() +` + +export default (() => { + const ZyphosHeroScript: QuartzComponent = () => ( +