diff --git a/public/art/castledrop-logo.png b/public/art/castledrop-logo.png new file mode 100644 index 0000000..5f66e66 Binary files /dev/null and b/public/art/castledrop-logo.png differ diff --git a/public/art/crystal.svg b/public/art/crystal.svg new file mode 100644 index 0000000..f3dde10 --- /dev/null +++ b/public/art/crystal.svg @@ -0,0 +1 @@ +Crystal \ No newline at end of file diff --git a/public/art/dragon.svg b/public/art/dragon.svg new file mode 100644 index 0000000..a9b023c --- /dev/null +++ b/public/art/dragon.svg @@ -0,0 +1 @@ +Dragon \ No newline at end of file diff --git a/public/art/goblin.svg b/public/art/goblin.svg new file mode 100644 index 0000000..45849b3 --- /dev/null +++ b/public/art/goblin.svg @@ -0,0 +1 @@ +Goblin \ No newline at end of file diff --git a/public/art/hills-far.svg b/public/art/hills-far.svg new file mode 100644 index 0000000..de54639 --- /dev/null +++ b/public/art/hills-far.svg @@ -0,0 +1 @@ +Hills Far \ No newline at end of file diff --git a/public/art/hills-near.svg b/public/art/hills-near.svg new file mode 100644 index 0000000..c0cc01d --- /dev/null +++ b/public/art/hills-near.svg @@ -0,0 +1 @@ +Hills Near \ No newline at end of file diff --git a/public/art/prizm-logo.png b/public/art/prizm-logo.png new file mode 100644 index 0000000..0bf8d3b Binary files /dev/null and b/public/art/prizm-logo.png differ diff --git a/public/art/revik-title.png b/public/art/revik-title.png new file mode 100644 index 0000000..8af8fba Binary files /dev/null and b/public/art/revik-title.png differ diff --git a/public/art/sources.json b/public/art/sources.json new file mode 100644 index 0000000..d1dda31 --- /dev/null +++ b/public/art/sources.json @@ -0,0 +1,45 @@ +{ + "description": "Original game art; vector frames exported with Spritesmith svg.", + "vector_sources": [ + { + "game": "castledrop", + "source": "art/dragon.py", + "animation": "fly", + "frame": 0, + "file": "dragon.svg" + }, + { + "game": "castledrop", + "source": "art/grunt.py", + "animation": "idle", + "frame": 0, + "file": "goblin.svg" + }, + { + "game": "castledrop", + "source": "art/backdrop/hills.py", + "animation": "far", + "frame": 0, + "file": "hills-far.svg" + }, + { + "game": "castledrop", + "source": "art/backdrop/hills.py", + "animation": "near", + "frame": 0, + "file": "hills-near.svg" + }, + { + "game": "prizm", + "source": "art/crystal.py", + "animation": "purple", + "frame": 0, + "file": "crystal.svg" + } + ], + "images": { + "castledrop-logo.png": "castledrop/godot_client/src/assets/sprites/ui/title_logo.png", + "prizm-logo.png": "prizm/godot_client/src/static/assets/ui/title_logo.png", + "revik-title.png": "fieldsofrevik/godot_client/src/assets/ui/title/title-concept-2.png" + } +} diff --git a/src/components/Entry.astro b/src/components/Entry.astro index 44ee25c..2ad6353 100644 --- a/src/components/Entry.astro +++ b/src/components/Entry.astro @@ -3,6 +3,7 @@ import octicons from '@primer/octicons'; interface Props { name: string; + id?: string; tagline: string; meta: string; status: string; @@ -13,7 +14,7 @@ interface Props { links?: { href: string; label: string }[]; } -const { name, tagline, meta, status, available = false, command, commandNote, links = [] } = Astro.props; +const { id, name, tagline, meta, status, available = false, command, commandNote, links = [] } = Astro.props; const icon = (n: keyof typeof octicons, size = 16) => octicons[n].toSVG({ width: size, height: size }); // An external link is anything that leaves this site. It gets the outward @@ -21,38 +22,36 @@ const icon = (n: keyof typeof octicons, size = 16) => octicons[n].toSVG({ width: const isExternal = (href: string) => href.startsWith('http'); --- -
+

{name}

{tagline}

-

{status}

+

+ {status} +

{meta}

- { - command && ( -
- {command} - {commandNote &&

{commandNote}

} -
- ) - } + {command && ( +
+ {command} + {commandNote &&

{commandNote}

} +
+ )} - { - links.length > 0 && ( - - ) - } + {links.length > 0 && ( + + )}
@@ -60,47 +59,173 @@ const isExternal = (href: string) => href.startsWith('http'); /* The head column is fixed rather than fractional. It holds four short lines whatever the width, so giving it a share of the row would only buy it blank space next to a body that could have used it. */ - .entry { display: grid; grid-template-columns: 300px minmax(0, 1fr); align-items: start; border-bottom: 1px solid var(--line-soft); padding: 44px 0; gap: 64px; } - .entry:first-of-type { border-top: 1px solid var(--line-soft); } + .entry { + display: grid; + grid-template-columns: 300px minmax(0, 1fr); + align-items: start; + border-bottom: 1px solid var(--line-soft); + padding: 44px 0; + gap: 64px; + } + .entry:first-of-type { + border-top: 1px solid var(--line-soft); + } - .entry-head h2 { margin: 0 0 8px; color: var(--bone); font-size: 30px; font-weight: 580; letter-spacing: -.045em; } - .tagline { margin: 0 0 20px; color: var(--paper); font-size: 14px; font-weight: 500; } - .status { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; color: var(--faint); font: 600 10px var(--mono); letter-spacing: .08em; text-transform: uppercase; } + .entry-head h2 { + margin: 0 0 8px; + color: var(--bone); + font-size: 30px; + font-weight: 580; + letter-spacing: -0.045em; + } + .tagline { + margin: 0 0 20px; + color: var(--paper); + font-size: 14px; + font-weight: 500; + } + .status { + display: flex; + align-items: center; + gap: 8px; + margin: 0 0 6px; + color: var(--faint); + font: 600 10px var(--mono); + letter-spacing: 0.08em; + text-transform: uppercase; + } /* Hollow by default, filled only for something you can actually run today. Two states, told apart by fill rather than by colour, so the difference survives greyscale and colour blindness both. */ - .status span { width: 7px; height: 7px; border-radius: 50%; border: 1px solid var(--faint); } - .status[data-available] { color: var(--bone); } - .status[data-available] span { border-color: var(--bone); background: var(--bone); box-shadow: 0 0 0 4px rgba(247, 242, 233, .1); } - .meta { margin: 0; color: var(--faint); font: 500 10px var(--mono); letter-spacing: .05em; text-transform: uppercase; } + .status span { + width: 7px; + height: 7px; + border-radius: 50%; + border: 1px solid var(--faint); + } + .status[data-available] { + color: var(--bone); + } + .status[data-available] span { + border-color: var(--bone); + background: var(--bone); + box-shadow: 0 0 0 4px rgba(247, 242, 233, 0.1); + } + .meta { + margin: 0; + color: var(--faint); + font: 500 10px var(--mono); + letter-spacing: 0.05em; + text-transform: uppercase; + } - .entry-body :global(p) { max-width: 700px; margin: 0 0 14px; color: var(--quiet); font-size: 14.5px; line-height: 1.72; } - .entry-body :global(p:last-of-type) { margin-bottom: 0; } - .entry-body :global(code) { border-radius: 3px; background: #333131; padding: 1px 5px; color: #d6d1cb; font: 12.5px var(--mono); } + .entry-body :global(p) { + max-width: 700px; + margin: 0 0 14px; + color: var(--quiet); + font-size: 14.5px; + line-height: 1.72; + } + .entry-body :global(p:last-of-type) { + margin-bottom: 0; + } + .entry-body :global(code) { + border-radius: 3px; + background: #e2e9d7; + padding: 1px 5px; + color: #596452; + font: 12.5px var(--mono); + } - .command { margin-top: 24px; } + .command { + margin-top: 24px; + } /* Sized to the command, not to the column: a one-line install stretched the full width of a wide screen reads as an empty box with text in the corner. */ - .command code { display: block; width: max-content; max-width: 100%; overflow-x: auto; border: 1px solid var(--line); border-radius: 5px; background: var(--ink-deep); padding: 13px 16px; color: var(--paper); font: 500 12.5px/1 var(--mono); white-space: nowrap; } - .command p { margin: 10px 0 0; color: var(--faint); font: 500 10px var(--mono); letter-spacing: .05em; text-transform: uppercase; } + .command code { + display: block; + width: max-content; + max-width: 100%; + overflow-x: auto; + border: 1px solid var(--line); + border-radius: 5px; + background: var(--ink-deep); + padding: 13px 16px; + color: var(--paper); + font: 500 12.5px/1 var(--mono); + white-space: nowrap; + } + .command p { + margin: 10px 0 0; + color: var(--faint); + font: 500 10px var(--mono); + letter-spacing: 0.05em; + text-transform: uppercase; + } - .links { display: flex; flex-wrap: wrap; gap: 22px; margin-top: 26px; } - .links a { display: inline-flex; align-items: center; gap: 7px; color: var(--paper); border-bottom: 1px solid var(--line); padding: 6px 0; font-size: 13px; font-weight: 650; text-decoration: none; transition: border-color .15s ease; } - .links a:hover { border-bottom-color: var(--paper); } - .links .icon { color: var(--quiet); } + .links { + display: flex; + flex-wrap: wrap; + gap: 22px; + margin-top: 26px; + } + .links a { + display: inline-flex; + align-items: center; + gap: 7px; + color: var(--paper); + border-bottom: 1px solid var(--line); + padding: 6px 0; + font-size: 13px; + font-weight: 650; + text-decoration: none; + transition: border-color 0.15s ease; + } + .links a:hover { + border-bottom-color: var(--paper); + } + .links .icon { + color: var(--quiet); + } @media (max-width: 980px) { - .entry { grid-template-columns: 1fr; gap: 22px; padding: 36px 0; } + .entry { + grid-template-columns: 1fr; + gap: 22px; + padding: 36px 0; + } } @media (max-width: 600px) { - .entry-head h2 { font-size: 25px; } - .entry-body :global(p) { font-size: 13.5px; } - .command code { font-size: 10.5px; padding: 11px 13px; } - .links { gap: 16px; } + .entry-head h2 { + font-size: 25px; + } + .entry-body :global(p) { + font-size: 13.5px; + } + .command code { + font-size: 10.5px; + padding: 11px 13px; + } + .links { + gap: 16px; + } } - .entry { gap: 50px; padding: 48px 0; } - .entry-head h2 { font-family: Georgia,serif; color: #e7af78; font-size: 36px; } - .links a { color: #c9d8c2; } - @media (max-width: 980px) { .entry { gap: 24px; } } - + .entry { + gap: 50px; + padding: 48px 0; + } + .entry-head h2 { + font-family: Georgia, serif; + color: #3e5e40; + font-size: 36px; + } + .links a { + color: #3e5e40; + } + @media (max-width: 980px) { + .entry { + gap: 24px; + } + } + diff --git a/src/layouts/Full.astro b/src/layouts/Full.astro index 26ba345..50a6c50 100644 --- a/src/layouts/Full.astro +++ b/src/layouts/Full.astro @@ -10,7 +10,7 @@ interface Props { const { title = 'Avior Studio', - description = 'Avior Studio builds developer tools for Godot and the games behind them — GDAM, gdlint, fourteen Godot 4 addons, termcade, Castle Drop, Prizm and Fields of Revik.', + description = 'Independent games and useful developer tools. Play termcade and Fields of Revik, explore Castle Drop and Prizm, and meet the tools behind the work.', path = Astro.url.pathname, } = Astro.props; @@ -42,7 +42,7 @@ const structuredData = { - + diff --git a/src/pages/devtools.astro b/src/pages/devtools.astro index b1786b9..cfdc3d4 100644 --- a/src/pages/devtools.astro +++ b/src/pages/devtools.astro @@ -1,10 +1,6 @@ --- -import octicons from '@primer/octicons'; -import Entry from '../components/Entry.astro'; import Full from '../layouts/Full.astro'; -const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ width: size, height: size }); - // The addons GDAM was built to carry. Listed alphabetically rather than by // importance: fourteen is enough that a reader needs to be able to find one, // and a ranking here would be an editorial claim the repositories cannot back. @@ -90,184 +86,404 @@ const addons = [
-
-

Devtools

-

Two tools, fourteen addons.

-

- All of it came out of the games. GDAM installs and pins the addons those projects share; - gdlint keeps the GDScript around them honest. The tools are one static binary each, with no - runtime, no daemon and nothing to sign up for. The addons are what they were built to carry. +

+

THE STUDIO WORKBENCH

+

+ Less friction. +
+ More making. +

+

+ Tools that grew out of the games. Install the addons, check the scripts, and get back to the part you came to + build.

- -
- -

- Install, link, remove and publish Godot addons from GitHub release assets, through a small - CLI and the public registry at app.gdam.dev. gdam init writes a manifest into your - project; gdam add @user/addon and gdam install keep that manifest - in sync with what is actually sitting under the addons directory. -

+ +
+
+

03 / ORIGINAL GAME ART

+

+ One drawing. +
+ More than one screen. +

- Four rules ship enabled and the other twelve wait to be asked for in - gdlint.json, because the rest is house style. It is deliberately not an - architecture checker: directory naming, import direction and autoload ownership change per - project, and a hygiene tool that guessed at them would be wrong everywhere but home. + Spritesmith authors vector artwork in Python and exports it for the games. Its SVG export brings the same + shapes to the web, at any size.

- +

The Castle Drop dragon and Prizm crystal here are original frames from their game art.

+
+
+ Castle Drop's red dragon + Prizm's purple crystal +
- -
-
+
+
-

Addons

-

The fourteen on the registry.

-

- Each one was factored out of a game the third time a project here needed the same thing. - They are Godot 4, MIT, and published to app.gdam.dev, and every one of them draws its - boundary in the same place: the addon owns the mechanism, the game owns the policy. -

+

GODOT 4 / MIT

+

+ Fourteen pieces +
+ for your own game. +

-
- gdam install @aviorstudio/<name> -

Same for all fourteen · or copy addon/ in by hand and enable the plugin

+
+

Small addons, each with one job. Explore the source or find them on the GDAM registry.

+ Open the registry ↗
-
- { - addons.map((addon) => ( - -

{addon.name}

-

{addon.tagline}

-

- {addon.cli &&

{addon.cli}

} - - Source - -
- )) - } + {addons.map((addon, index) => ( +
+ {String(index + 1).padStart(2, '0')} +

{addon.name}

+

{addon.tagline}

+
+ What it does +

+ {addon.cli && {addon.cli}} +

+ Source ↗ +
+ ))}
- -
-

- Both tools and every addon on this page are used daily on the Godot projects listed under - Games — that is the whole reason they exist, and the reason they keep - getting fixed. -

- See the games +
+

See what they make possible.

+ Explore the games ↗
- + diff --git a/src/pages/games.astro b/src/pages/games.astro index 5d3a7f5..c32d709 100644 --- a/src/pages/games.astro +++ b/src/pages/games.astro @@ -8,19 +8,40 @@ const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({
-

Games

-

One you can play, three on the way.

+

+ Games +

+

+ Step into another world. +

- A terminal arcade that is public and installable today, and three Godot projects at - different distances from done. The three are private repositories for now — what follows is - what they are, not a release date. + Play the terminal arcade or enter Fields of Revik in your browser. Castle Drop and Prizm are prototypes: + glimpses of the worlds taking shape in the studio.

+
octicons[name].toSVG({ links={[{ href: 'https://github.com/aviorstudio/termcade', label: 'Source on GitHub' }]} >

- Classic games rendered at sub-cell resolution with block pixels, so a terminal cell becomes - a 2×2 or 2×3 grid of pixels and the playfield gets sharper than the font should allow. It - ships with Asteroid, Tetris and Brickough, playable offline the moment it starts. + Classic games rendered at sub-cell resolution with block pixels, so a terminal cell becomes a 2×2 or 2×3 grid + of pixels and the playfield gets sharper than the font should allow. It ships with Asteroid, Tetris and + Brickough, playable offline the moment it starts.

- The arcade compiles no games into itself. Every game is a sandboxed WebAssembly package - running under wazero with no filesystem and no network, so a broken one shows up dimmed on - the menu with its reason rather than taking the arcade down. The same binary is the dev - kit: termcade dev new you/mygame scaffolds one, termcade dev build + The arcade compiles no games into itself. Every game is a sandboxed WebAssembly package running under wazero + with no filesystem and no network, so a broken one shows up dimmed on the menu with its reason rather than + taking the arcade down. The same binary is the dev kit: termcade dev new you/mygame scaffolds + one, termcade dev build packages it, and anyone can publish for players to termcade add.

- A castle defense where the physics is the game rather than the garnish. Clear a siege, - draft a tower, place it on a rampart slot, then use that tower's abilities to amplify - what you were already doing by hand — grabbing attackers, throwing them, and turning - enemies into collisions with each other. + A castle defense where the physics is the game rather than the garnish. Clear a siege, draft a tower, place it + on a rampart slot, then use that tower's abilities to amplify what you were already doing by hand — grabbing + attackers, throwing them, and turning enemies into collisions with each other.

- Progression is castle upgrades only; there is no meta-currency layer bolted on beside it. - Waves, enemies, towers and tuning are all authored as Godot resources in the Inspector, - so the balance lives in the editor rather than in code. + Progression is castle upgrades only; there is no meta-currency layer bolted on beside it. Waves, enemies, + towers and tuning are all authored as Godot resources in the Inspector, so the balance lives in the editor + rather than in code.

- Spend limited colour mana to cast prism spells into empty drawer slots, then drag those - prisms onto the board so beams from the transmitters bend into the receivers that need - them. Rooms are authored as scenes in the editor, and the beam simulation resolves each - board from the pieces you have placed. + Spend limited colour mana to cast prism spells into empty drawer slots, then drag those prisms onto the board + so beams from the transmitters bend into the receivers that need them. Rooms are authored as scenes in the + editor, and the beam simulation resolves each board from the pieces you have placed.

- Deliberately mechanics-first: no avatar to move, no combat, no health, no timer and no - fail state in the MVP. The whole puzzle is what light does when you put something in - front of it. + Deliberately mechanics-first: no avatar to move, no combat, no health, no timer and no fail state in the MVP. + The whole puzzle is what light does when you put something in front of it.

@@ -88,62 +108,210 @@ const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ name="Fields of Revik" tagline="Tactics card game" status="In development" - meta="Godot 4 · private repository · site live" - links={[{ href: 'https://www.fieldsofrevik.com', label: 'fieldsofrevik.com' }]} + available={true} + meta="Godot 4 · browser game" + links={[{ href: 'https://app.revik.gg', label: 'Play in your browser' }]} >

- A tactics card game on a coloured tile board, with animal factions — outlaw raccoons, - monastic bears, and more — whose identity comes from their mana costs rather than a - faction tag, so custom decks are first-class rather than a mode. + A tactics card game on a coloured tile board, with animal factions — outlaw raccoons, monastic bears, and more + — whose identity comes from their mana costs rather than a faction tag, so custom decks are first-class rather + than a mode.

- Offline play against the machine and online play against a person run the same rules: the - deterministic gameplay lives in one shared core used by both the client and a headless - Godot server, and online matches are fully server-authoritative. The client never gets to - decide what happened. + Offline play against the machine and online play against a person run the same rules: the deterministic + gameplay lives in one shared core used by both the client and a headless Godot server, and online matches are + fully server-authoritative. The client never gets to decide what happened.

- The three Godot projects run on the studio's own devtools — GDAM pins the addons they share, - gdlint checks the GDScript. + The three Godot projects run on the studio's own devtools — GDAM pins the addons they share, gdlint checks the + GDScript.

- See the devtools + + See the devtools +
+ h1 { + font-family: Georgia, serif; + font-size: clamp(52px, 6vw, 84px); + color: #3e5e40; + } + .entry-list { + border-top: 1px solid #6a5142; + } + diff --git a/src/pages/index.astro b/src/pages/index.astro index c93d244..7f6e817 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,237 +1,546 @@ --- -import octicons from '@primer/octicons'; import Full from '../layouts/Full.astro'; - -const icon = (name: keyof typeof octicons, size = 16) => octicons[name].toSVG({ width: size, height: size }); - -// The two doors, and what is actually behind each one. Naming the contents -// here rather than saying "and more" means the index never promises a page -// something is not on. -const doors = [ - { - href: '/devtools', - kicker: 'Devtools', - title: 'Two tools and what they carry', - copy: 'A package manager for Godot addons, a hygiene checker for the GDScript around them, and the fourteen addons on the registry that the games here share. All open source, and all of it exists because the games needed it.', - items: [ - { name: 'GDAM', note: 'Godot addon manager and registry' }, - { name: 'gdlint', note: 'GDScript hygiene checker' }, - { name: '14 addons', note: 'Godot 4 · MIT · on app.gdam.dev' }, - ], - }, - { - href: '/games', - kicker: 'Games', - title: 'One playable, three in progress', - copy: 'A terminal arcade you can run right now, and three Godot projects at various distances from done — castle defense, light puzzles, and a tactics card game.', - items: [ - { name: 'termcade', note: 'Terminal arcade · playable now' }, - { name: 'Castle Drop', note: 'Physics castle defense · prototype' }, - { name: 'Prizm', note: 'Light puzzle · prototype' }, - { name: 'Fields of Revik', note: 'Tactics card game · in development' }, - ], - }, -]; ---
-
-
-

Avior Studio

-

We build the tools we needed first.

-

- A package manager and a linter, written because three Godot projects here were sharing - addons and conventions and nothing was keeping them straight. They turned out to be - useful outside those projects, so they went out. +

+
+

INDEPENDENT GAMES & DEVELOPER TOOLS

+

+ Small worlds. +
+ Big possibilities. +

+

+ Games worth getting lost in. +
+ Tools that help us get there.

- + + A fox knight overlooking the colourful hex-tile valley of Fields of Revik +
+ FIELDS OF REVIK + Enter the valley ↗
+
+
+
+
+

Worlds in the making

+ All games ↗
- -
- -
- { - doors.map((door) => ( - -

{door.kicker}

-

{door.title}

-

{door.copy}

-
    - {door.items.map((item) => ( -
  • - {item.name} - {item.note} -
  • - ))} -
- - Open {door.kicker.toLowerCase()} - -
- )) - } +
+
+

PLAY SOMETHING RIGHT NOW

+

+ An arcade. +
+ In your terminal. +

+

Asteroid, Tetris and Brickough. A small collection of classics, rendered in the place you already work.

+ + Meet termcade ↗ + +
+
- -
-
- 01 -
-

The tools came out of the games

-

- Castle Drop, Prizm and Fields of Revik all pull the same addons and follow the same - script conventions. GDAM installs and pins those addons from a registry; gdlint keeps - the GDScript around them honest. Neither was a product idea — they were the parts that - kept going wrong, and the fourteen addons on the registry were factored out the same - way, on the third time a project needed the same thing. -

-
-
-
- 02 -
-

Published when it is useful to someone else

-

- The tools, the addons and the arcade are public and installable in one command. The - Godot games stay private until there is something worth playing — a repository nobody - can run is not a release, and a link to one is not an announcement. -

-
-
-
- 03 -
-

Godot 4, Go, and pages that ship no JavaScript

-

- The games are Godot 4. The tools, the arcade and the registry APIs are Go, built as - single static binaries. The sites — this one included — are static Astro with no - client-side runtime at all. -

+
+
+

FROM THE WORKBENCH

+

+ Better tools. +
+ More time to play. +

+

+ The games share more than a studio. Their addons, script checks and vector artwork grow from the same + workbench. +

+ Explore the devtools ↗ +
+
-
- -
-

Two tools.
Fourteen addons.
Four games.

-
- diff --git a/src/styles/global.css b/src/styles/global.css index aba73c4..621d136 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -1,35 +1,21 @@ -/* Fonts are the platform's own, not fetched. The stacks below reach for the - native UI sans and native monospace of each platform, so the site loads what - the reader already has, makes no third-party request, sends nobody's IP to a - font CDN, and needs no CSP exception to do it. */ - -/* The background is the logo's own backdrop, #252424, sampled out of - src/assets/aviorstudio-logo.png. The mark ships with that colour baked in - behind it, so matching it exactly is what lets the ibis sit on the page - instead of inside a visible square. - - Everything else here is greyscale on purpose. Each product has a colour of - its own -- gdlint wears the Godot editor blue, gdam.dev its slate, Revik its - parchment -- and a studio that invented a seventh would be competing with - the six things it exists to point at. So this site brings no hue and lets - the products keep theirs. */ +/* The studio folio uses warm paper and forest tones; each game keeps its own original artwork. */ :root { - --ink: #252424; - --ink-deep: #1c1b1b; - --raised: #2c2b2b; - --line: #3b3939; - --line-soft: #333131; - --paper: #ece9e4; - --bone: #f7f2e9; - --quiet: #a29d97; - --faint: #7c7772; + --ink: #f4f3eb; + --ink-deep: #e8ecdf; + --raised: #eaeee2; + --line: #c6cebd; + --line-soft: #dce1d3; + --paper: #253729; + --bone: #253729; + --quiet: #596452; + --faint: #67705e; --sans: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif; --mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace; font-family: var(--sans); background: var(--ink); color: var(--paper); font-synthesis: none; - color-scheme: dark; + color-scheme: light; } * {