rebrand: Studio design system — near-black base, Signal Lime + Agent Violet accents, Inter/Space Grotesk/JetBrains Mono fonts

This commit is contained in:
2026-06-14 01:32:08 +01:00
parent b8c3fc473b
commit f42c76308c
17 changed files with 1104 additions and 920 deletions
+71 -59
View File
@@ -39,21 +39,26 @@
}
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
/* ── Self-contained post styles (Studio provides site chrome) ── */
/* ── Tinqs Studio brand — post styles ── */
:root {
--c-accent: #c9935a;
--c-accent-l: #d4a87c;
--c-bg: #0d1117;
--c-text: #e6edf3;
--c-muted: #9aa7b4;
--c-border: #2a3340;
--c-blue: #38bdf8;
--c-purple: #a855f7;
--c-gold: #f59e0b;
--c-code-bg: #1c2230;
--c-pre-bg: #0a0e14;
/* Studio near-black base */
--c-bg: #0B0C0E;
--c-bg-raised: #15171A;
/* Foreground */
--c-fg: #ECEEF1;
--c-muted: #8A95A3;
/* Family accents */
--c-lime: #B6FF3C;
--c-violet: #7C5CFF;
/* Borders */
--c-border: rgba(255,255,255,.07);
--c-border-strong: rgba(255,255,255,.12);
}
*, *::before, *::after { box-sizing: border-box; }
@@ -61,9 +66,10 @@
body {
margin: 0;
padding: 0;
background: transparent;
color: var(--c-text);
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
background: var(--c-bg);
color: var(--c-fg);
font-family: 'Inter', system-ui, -apple-system, sans-serif;
font-size: 16px;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
@@ -72,40 +78,42 @@
.post {
max-width: 720px;
margin: 0 auto;
padding: 40px 24px 48px;
padding: 48px 24px 60px;
}
/* ── Back link ── */
.post__back {
color: var(--c-blue);
color: var(--c-muted);
text-decoration: none;
font-size: 0.9rem;
font-size: 0.875rem;
display: inline-block;
margin-bottom: 24px;
transition: color 0.15s;
}
.post__back:hover { color: var(--c-purple); }
.post__back:hover { color: var(--c-lime); }
/* ── Gradient title ── */
/* ── Gradient title — lime → violet ── */
.post__title {
background: linear-gradient(90deg, #c9935a, #f59e0b 40%, #38bdf8);
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
background: linear-gradient(90deg, var(--c-lime), var(--c-violet));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-weight: 800;
font-weight: 700;
font-size: 2.2rem;
line-height: 1.25;
line-height: 1.2;
margin: 0 0 16px;
}
/* ── Date pill ── */
.post__date {
display: inline-block;
font-family: ui-monospace, 'SF Mono', 'Cascadia Code', Consolas, monospace;
font-family: 'JetBrains Mono', ui-monospace, 'SF Mono', Consolas, monospace;
font-size: 0.72rem;
letter-spacing: 0.22em;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--c-blue);
border: 1px solid rgba(147, 140, 129, 0.25);
color: var(--c-muted);
border: 1px solid var(--c-border);
border-radius: 999px;
padding: 4px 14px;
margin-bottom: 16px;
@@ -124,16 +132,20 @@
.post__body p { margin: 14px 0; }
.post__body h2 {
font-size: 1.7rem;
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
font-weight: 600;
font-size: 1.6rem;
margin: 54px 0 6px;
padding-left: 16px;
border-left: 4px solid var(--c-accent);
border-left: 4px solid var(--c-lime);
line-height: 1.3;
}
.post__body h3 {
color: var(--c-purple);
font-size: 1.18rem;
font-family: 'Space Grotesk', system-ui, -apple-system, sans-serif;
font-weight: 500;
color: var(--c-violet);
font-size: 1.15rem;
margin: 30px 0 4px;
}
@@ -143,27 +155,27 @@
/* ── Inline code ── */
.post__body code {
font-family: ui-monospace, 'SF Mono', 'Cascadia Code', Consolas, monospace;
font-size: 0.86em;
background: var(--c-code-bg);
color: #9fe6c0;
font-family: 'JetBrains Mono', ui-monospace, 'SF Mono', Consolas, monospace;
font-size: 0.84em;
background: var(--c-bg-raised);
color: var(--c-lime);
padding: 2px 6px;
border-radius: 5px;
border-radius: 4px;
border: 1px solid var(--c-border);
}
/* ── Code blocks ── */
.post__body pre {
background: var(--c-pre-bg);
background: var(--c-bg);
border: 1px solid var(--c-border);
border-radius: 10px;
border-radius: 8px;
padding: 16px 18px;
overflow-x: auto;
margin: 14px 0;
font-family: ui-monospace, 'SF Mono', 'Cascadia Code', Consolas, monospace;
font-size: 0.85rem;
font-family: 'JetBrains Mono', ui-monospace, 'SF Mono', Consolas, monospace;
font-size: 0.83rem;
line-height: 1.55;
color: var(--c-text);
color: var(--c-fg);
}
.post__body pre code {
@@ -177,22 +189,22 @@
/* ── Blockquote ── */
.post__body blockquote {
background: rgba(245, 158, 11, 0.08);
border: 1px solid rgba(245, 158, 11, 0.25);
border-left: 4px solid var(--c-gold);
border-radius: 0 12px 12px 0;
background: rgba(124, 92, 255, 0.06);
border: 1px solid rgba(124, 92, 255, 0.15);
border-left: 4px solid var(--c-violet);
border-radius: 0 8px 8px 0;
padding: 16px 18px;
margin: 18px 0;
color: #f4e3c4;
color: var(--c-fg);
font-size: 0.94rem;
}
/* ── Links ── */
.post__body a { color: var(--c-blue); }
.post__body a:hover { color: var(--c-purple); }
.post__body a { color: var(--c-lime); text-decoration: underline; text-underline-offset: 3px; }
.post__body a:hover { color: var(--c-violet); }
/* ── Strong ── */
.post__body strong { color: var(--c-gold); }
.post__body strong { color: var(--c-lime); font-weight: 600; }
/* ── HR ── */
.post__body hr {
@@ -233,8 +245,8 @@
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--c-accent);
color: var(--c-bg);
background: var(--c-violet);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
@@ -250,7 +262,7 @@
}
.post__author-name {
color: var(--c-text);
color: var(--c-fg);
font-weight: 600;
}
</style>
@@ -276,7 +288,7 @@
<p>The alternative — baking animations to vertex textures — works for static crowds but locks you out of per-instance variation. No blending, no phase offsets, no reactive behaviour.</p>
<p>What we need is simpler: <strong>share the skeleton, drive per-instance poses from a single animation, batch the draw call.</strong> That's what <code>agent_skinned</code> does.</p>
<h2>How it works: two classes, one texture</h2>
<p>The module lives in <code>modules/agent_skinned/</code> inside <a href="https://tinqs.com/tinqs/engine" style="color: var(--c-accent-l);">Tinqs Engine</a>. Two classes, one job:</p>
<p>The module lives in <code>modules/agent_skinned/</code> inside <a href="https://tinqs.com/tinqs/engine" style="color: var(--c-lime);">Tinqs Engine</a>. Two classes, one job:</p>
<h3><code>MultiSkinnedMeshInstance3D</code> — the data plane</h3>
<p>Holds the CPU-side bone matrices. Allocates an <code>ImageTexture</code> of size <code>[4 × max_bones, max_instances]</code> in RGBA32F — each texel is one column of a 4×4 bone matrix. For a 130-bone crocodile with 256 instances:</p>
<pre><code>Texture: 520 × 256 RGBA32F ≈ 2 MB</code></pre>
@@ -309,7 +321,7 @@ data.update() # upload only dirty instances, not the whole texture</code></pre
<p><strong>Bug 2: Bone matrices stored transposed.</strong> The data plane wrote basis rows (standard Godot <code>Transform3D.basis</code> is row-major), but the shader unpacked as columns. Every bone matrix was transposed — the mesh crumpled. Not a scale bug, not an orientation bug — a layout mismatch. Fixed by storing column-major, with a doctest to prevent regression.</p>
<p>The lesson: doctests catch logic. Rendering catches truth. You need both.</p>
<h2>What's driving it</h2>
<p>In <a href="https://www.arikigame.com" style="color: var(--c-accent-l);">Ariki</a>, the sim tracks animal migration across a 12km archipelago. <code>AnimalHerdRenderer.cs</code> groups sim <code>ViewerState.animals</code> by type, feeds positions to <code>skinned_herd.gd</code> (a reusable per-type herd backend), which drives the renderer. One <code>AnimationPlayer</code> animates a single driver skeleton; poses propagate to every instance.</p>
<p>In <a href="https://www.arikigame.com" style="color: var(--c-lime);">Ariki</a>, the sim tracks animal migration across a 12km archipelago. <code>AnimalHerdRenderer.cs</code> groups sim <code>ViewerState.animals</code> by type, feeds positions to <code>skinned_herd.gd</code> (a reusable per-type herd backend), which drives the renderer. One <code>AnimationPlayer</code> animates a single driver skeleton; poses propagate to every instance.</p>
<p>The crocodile herd scene is 25 instances, one draw call. The same pipeline projects to 2001,000 before the GPU budget even notices.</p>
<h2>What's deliberately not here</h2>
<ul>
@@ -321,12 +333,12 @@ data.update() # upload only dirty instances, not the whole texture</code></pre
<p>Pre-built editor binaries with <code>agent_skinned</code> baked in — no engine compile required:</p>
<p>| Platform | Binary | Engine commit |</p>
<p>|&mdash;&mdash;&mdash;-|&mdash;&mdash;&ndash;|&mdash;&mdash;&mdash;&mdash;&mdash;|</p>
<p>| <strong>macOS ARM64</strong> | <a href="https://tinqs.com/tinqs/builds/media/branch/main/engine/macos-arm64/tinqs.macos.editor.arm64.mono" style="color: var(--c-accent-l);"><code>tinqs.macos.editor.arm64.mono</code></a> | <code>4fe1323</code> (4.6.4, Xcode 26.3) |</p>
<p>| <strong>Windows x64</strong> | <a href="https://tinqs.com/tinqs/builds/media/branch/main/engine/windows-x64/tinqs.windows.editor.x86_64.mono.exe" style="color: var(--c-accent-l);"><code>tinqs.windows.editor.x86_64.mono.exe</code></a> | <code>64fb5cc</code> (4.6.4, MSVC 2022) |</p>
<p>All builds live in the public <a href="https://tinqs.com/tinqs/builds" style="color: var(--c-accent-l);"><code>tinqs/builds</code></a> repo — engine source is private, but the binaries are yours. See <a href="https://tinqs.com/tinqs/builds/src/branch/main/manifest.json" style="color: var(--c-accent-l);"><code>manifest.json</code></a> for checksums and build details.</p>
<p>The engine source lives in <a href="https://tinqs.com/tinqs/engine" style="color: var(--c-accent-l);"><code>tinqs/engine</code></a> (private). Module docs: <code>modules/agent_skinned/README.md</code> and <code>.agents/wiki/agent-skinned-gpu-herd.md</code>.</p>
<p>| <strong>macOS ARM64</strong> | <a href="https://tinqs.com/tinqs/builds/media/branch/main/engine/macos-arm64/tinqs.macos.editor.arm64.mono" style="color: var(--c-lime);"><code>tinqs.macos.editor.arm64.mono</code></a> | <code>4fe1323</code> (4.6.4, Xcode 26.3) |</p>
<p>| <strong>Windows x64</strong> | <a href="https://tinqs.com/tinqs/builds/media/branch/main/engine/windows-x64/tinqs.windows.editor.x86_64.mono.exe" style="color: var(--c-lime);"><code>tinqs.windows.editor.x86_64.mono.exe</code></a> | <code>64fb5cc</code> (4.6.4, MSVC 2022) |</p>
<p>All builds live in the public <a href="https://tinqs.com/tinqs/builds" style="color: var(--c-lime);"><code>tinqs/builds</code></a> repo — engine source is private, but the binaries are yours. See <a href="https://tinqs.com/tinqs/builds/src/branch/main/manifest.json" style="color: var(--c-lime);"><code>manifest.json</code></a> for checksums and build details.</p>
<p>The engine source lives in <a href="https://tinqs.com/tinqs/engine" style="color: var(--c-lime);"><code>tinqs/engine</code></a> (private). Module docs: <code>modules/agent_skinned/README.md</code> and <code>.agents/wiki/agent-skinned-gpu-herd.md</code>.</p>
<hr>
<p><strong>Related:</strong> <a href="fork-dont-build" style="color: var(--c-accent-l);">Fork, Don't Build</a> — why we modify existing platforms instead of building new ones. <a href="godot-optimisation" style="color: var(--c-accent-l);">Streaming a 12km Archipelago in Godot 4</a> — the terrain and vegetation streaming layers that work alongside this.</p>
<p><strong>Related:</strong> <a href="fork-dont-build" style="color: var(--c-lime);">Fork, Don't Build</a> — why we modify existing platforms instead of building new ones. <a href="godot-optimisation" style="color: var(--c-lime);">Streaming a 12km Archipelago in Godot 4</a> — the terrain and vegetation streaming layers that work alongside this.</p>
</div>
Before
After