From a13e8f56c989e003707e9564900b46e72760278e Mon Sep 17 00:00:00 2001 From: zeyyadroku-maker Date: Mon, 22 Jun 2026 03:28:21 -0400 Subject: [PATCH 1/6] Update team and game mode copy --- site/about.html | 11 +++++------ site/home.html | 18 +++++++----------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/site/about.html b/site/about.html index 5616419..9434398 100644 --- a/site/about.html +++ b/site/about.html @@ -100,14 +100,13 @@

Communities & servers

The team

- Heredita is being built by a tiny crew of map nerds. Art and worldbuilding by - the Heredita team; design and code by the rest of us. We're not Roblox β€” yet β€” but - we're aiming at the same kind of "open table" for our corner of the internet. + Heredita is built by four individuals, Whirl, Digi, Legi and Hilmi. Our goal is to create a platform for history, geography, and political enthusiasts who wish to live the experience of ruling a country or participating in politics with the fun that a videogame provides.

- Want to follow along, complain about a brush, or pitch a feature? - Reach out through our official support channel, review the Terms & Conditions, - or just keep checking the Updates page. + We provide a platform that allows for mappers to create, for historians to thrive and for political enthusiasts to participate! +

+

+ Our small team came together through the internet, and we hope that those who come on our game are also able to form tight bonds. That is what Heredita is about, its not just about conquest or war, it is about unity and creating things worth sharing.

diff --git a/site/home.html b/site/home.html index 2e3a687..9947858 100644 --- a/site/home.html +++ b/site/home.html @@ -71,24 +71,20 @@

Game Modes

- Sandbox -

Free Paint

-

Solo on the map. No dice, no chat β€” just chalk, borders, and ideas.

+

Historical

+

Relive real history by guiding nations through historical events, politics, warfare, and expansion.

- Roleplay

Alternate History

-

Pick a year, change one event, and watch the cascade.

+

Rewrite the past and explore endless "what if" scenarios as every decision reshapes the course of history.

- Soonβ„’ -

Multiplayer Servers

-

Join other historians. Dice rolls, treaties, betrayals. Coming soon.

+

Freepaint

+

Create freely on the map with no rules, no dice, and complete control over every territory.

- Soonβ„’ -

Community Worlds

-

Custom rulesets shared by players. Coming soon.

+

Customs / Fantasy

+

Design your own worlds, nations, and stories, then bring them to life through strategy, diplomacy, and imagination.

From 3a9e3212283cc239f2eda88cacad311d18d200c8 Mon Sep 17 00:00:00 2001 From: Zeyy21 Date: Tue, 28 Jul 2026 23:25:59 +0400 Subject: [PATCH 2/6] Redesign site chrome, rebuild navigation, rename copyright holder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copyright/corporate - Footer on all 13 pages now reads "Β© 2026 Anywhere Connection Corporation" - Terms names the operating entity in Β§1 and as the acting party in the sections where it matters (data collection, IP licence, refunds and their discretion, security, termination, liability, governing law) Design system - Border language now carries meaning: solid hairline = shipped, dashed = not built yet (locked / coming soon), accent = current. Previously every element had the same 2px dash, so nothing had hierarchy. - Type reduced from 5 faces to 3 with defined roles: Caveat for display, Special Elite (already imported, never used) for typewritten metadata, Cabin for body and controls - Stylesheet rewritten as one system instead of an override layer; the old file had a "polish layer" appended and a second .topbar .inner block overriding the first - Dropped the emoji-as-icon set, the tilt-everything treatment and the drifting particle effect (which only ran on two pages) Navigation - New js/nav.js replaces social-nav.js: icon tabs with a sliding chalk marker, dropdown panels, consolidated account menu, mobile drawer with inline accordions - Header markup is identical across pages so active state can't drift Play page - Launch panel rebuilt: copy and CTA on one side, the actual board bled to the card edge on the other, replacing a single oversized button centred in an empty card Fixes found along the way - Chat was blank for guests: the sign-in gate is injected after app.js has swept for .reveal elements, so it stayed at opacity 0 (pre-existing) - Account menu showed "Sign in" and "Sign out" at once; display:flex on menu items beat the hidden attribute - Empty required fields flagged red on load; :invalid -> :user-invalid - .text-center rule was missing, so centred headings sat left - Footer floated mid-page on short pages; body is now a sticky-footer column - Nav marker never positioned when the page loaded in a background tab (requestAnimationFrame doesn't fire there) Copy rewritten around specifics already in the patch notes (2d6 annexations, brush capped at 13, 1936/1945/1991 starts, 30-player servers). Co-Authored-By: Claude Opus 5 --- .claude/launch.json | 11 + .gitignore | 3 + README.md | 44 +- scripts/dev-server.js | 62 + site/about.html | 161 +- site/avatar.html | 131 +- site/chat.html | 97 +- site/css/chalkboard.css | 3694 +++++++++++++++++++-------------------- site/friends.html | 104 +- site/home.html | 149 +- site/index.html | 51 +- site/js/app.js | 56 +- site/js/avatar.js | 8 +- site/js/chat.js | 54 +- site/js/friends.js | 4 +- site/js/nav.js | 275 +++ site/js/social-nav.js | 177 -- site/membership.html | 125 +- site/play.html | 169 +- site/search.html | 116 +- site/settings.html | 104 +- site/store.html | 177 +- site/terms.html | 152 +- site/updates.html | 103 +- 24 files changed, 3203 insertions(+), 2824 deletions(-) create mode 100644 .claude/launch.json create mode 100644 scripts/dev-server.js create mode 100644 site/js/nav.js delete mode 100644 site/js/social-nav.js diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..c6c4b69 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "heredita-site", + "runtimeExecutable": "node", + "runtimeArgs": ["scripts/dev-server.js", "8765"], + "port": 8765 + } + ] +} diff --git a/.gitignore b/.gitignore index 97aad37..ac2ea16 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ node_modules/ # Local Netlify folder .netlify + +# Machine-local Claude Code permission state (launch.json is shared, this isn't) +.claude/settings.local.json diff --git a/README.md b/README.md index c157755..59b73b3 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,15 @@ Plain HTML + CSS + vanilla JS. No build step. ## Local dev ```bash -cd site -python -m http.server 8000 -# open http://localhost:8000/ +cd site && python3 -m http.server 8000 +``` + +Then open . There's also a dependency-free Node +equivalent, which serves with caching disabled so edits show up on a plain +reload: + +```bash +node scripts/dev-server.js 8765 ``` ## Deploy @@ -34,9 +40,35 @@ site/ β”œβ”€β”€ home.html dashboard β”œβ”€β”€ play.html launch page + preview footage carousel β”œβ”€β”€ about.html mission + features -β”œβ”€β”€ updates.html patch notes -β”œβ”€β”€ terms.html placeholder T&C +β”œβ”€β”€ updates.html patch notes, rendered from content/updates.json +β”œβ”€β”€ terms.html T&C β”œβ”€β”€ css/chalkboard.css -β”œβ”€β”€ js/app.js PLAY_URL points to app.heredita.net +β”œβ”€β”€ js/app.js session, play CTAs, carousel; PLAY_URL β†’ app.heredita.net +β”œβ”€β”€ js/nav.js top-nav behaviour (sliding marker, menus, mobile drawer) └── assets/ logos + 5 screenshots ``` + +## Design conventions + +The chalkboard theme leans on one rule that keeps the whole site legible at a +glance: + +| Border | Means | +| --- | --- | +| Solid hairline | A real, finished thing | +| **Dashed** | A sketch β€” locked, unbuilt, coming soon | +| Accent solid | The thing you're on right now | + +So dashes are never decoration. If something is dashed, it isn't shipped yet. + +Type has three roles: **Caveat** for display headings and the brand, **Special +Elite** for typewritten metadata (dates, versions, stamps, kickers), and +**Cabin** for body copy and every control. + +The header markup is duplicated verbatim across pages (no build step, by +design) β€” `js/nav.js` only enhances it, so the nav still works with JS off. If +you change a nav item, change it in every page. + +## Legal + +Heredita is operated by Anywhere Connection Corporation. diff --git a/scripts/dev-server.js b/scripts/dev-server.js new file mode 100644 index 0000000..0ffa7e7 --- /dev/null +++ b/scripts/dev-server.js @@ -0,0 +1,62 @@ +/* Static file server for local development. + * + * `python -m http.server` is the simpler option and is what the README + * suggests, but Python 3.9 resolves os.getcwd() while parsing its own + * arguments, so it refuses to start when the launcher's working directory + * isn't readable. This has no such problem and needs no dependencies. + * + * node scripts/dev-server.js [port] + */ +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +const ROOT = path.join(__dirname, '..', 'site'); +const PORT = Number(process.argv[2]) || 8765; + +const TYPES = { + '.html': 'text/html; charset=utf-8', + '.css': 'text/css; charset=utf-8', + '.js': 'text/javascript; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.svg': 'image/svg+xml', + '.png': 'image/png', + '.webp': 'image/webp', + '.ico': 'image/x-icon', + '.txt': 'text/plain; charset=utf-8', + '.yml': 'text/yaml; charset=utf-8' +}; + +http.createServer((req, res) => { + let urlPath; + try { + urlPath = decodeURIComponent(req.url.split('?')[0]); + } catch { + res.writeHead(400).end('bad request'); + return; + } + if (urlPath.endsWith('/')) urlPath += 'index.html'; + + const file = path.join(ROOT, path.normalize(urlPath)); + // path.normalize collapses ".." β€” re-check so a crafted URL can't escape. + if (file !== ROOT && !file.startsWith(ROOT + path.sep)) { + res.writeHead(403).end('forbidden'); + return; + } + + fs.readFile(file, (err, buf) => { + if (err) { + res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' }); + res.end('404 ' + urlPath); + return; + } + res.writeHead(200, { + 'Content-Type': TYPES[path.extname(file).toLowerCase()] || 'application/octet-stream', + // No caching, so edits show up on reload without a hard refresh. + 'Cache-Control': 'no-store' + }); + res.end(buf); + }); +}).listen(PORT, () => { + console.log('Heredita dev server β†’ http://localhost:' + PORT + '/'); +}); diff --git a/site/about.html b/site/about.html index 9434398..f73b04e 100644 --- a/site/about.html +++ b/site/about.html @@ -5,46 +5,63 @@ Heredita β€” About Us - +
-
-
- - + -
-
- - 0 - coming soon + Pre-alpha + + + + + + + +
+ + 0 + + + - - - - - -
@@ -54,66 +71,78 @@
Heredita

About Heredita

-

- A playground for geography, history and political enjoyers β€” built on chalk, dice, and the - stubborn belief that everyone deserves to redraw a border at least once. +

+ A chalkboard for people who argue about borders. Four of us build it.

-

Our Mission

+

Why it exists

- Heredita exists so people who love maps can do something with that love. - We want a place where a 1936 Poland enjoyer, a Roman restorationist and an - alt-history Byzantine fan can sit at the same chalkboard and argue with dice in their hand. + Plenty of map games let you move armies. Very few let you sit down with five other people, + talk for twenty minutes about whether Poland gets to keep Silesia, and then settle it with + a roll everyone can see. +

+

+ That conversation is the game. The map is just where it gets recorded.

-

What is Heredita?

+

What you actually do

-

Roleplay, not RTS

-

You don't move units. You paint borders, declare intent, and let the chat and the dice decide who lives and who annexes.

+

Paint, don't march

+

There are no units to shuffle. You take a brush to the border and redraw it, found a city, or put a nation back on the map that hasn't been there since 1795.

-

Paint the map

-

Brush tools let you redraw, found cities, restore old nations, or invent ones that never existed. The map is the canvas.

+

Rolls stay honest

+

Annexations are 2d6 in front of everyone. Nobody loses a province to a formula they can't see, and nobody wins one either.

-

Custom nations & cultures

-

Design your own flag, language, government, founding myth. Drop them on the map and see how the neighbors react.

+

Invent the rest

+

Flag, government, founding year, the myth you tell about it. Drop it on the map and see how long the neighbours pretend to take it seriously.

-

Alternate timelines

-

Pick a year, change one thing, and play the cascade. Restore Constantinople. Keep Poland off the partition table. Or invent something the textbooks never saw.

+

Change one thing

+

Pick 1936, 1945 or 1991, alter a single decision, and play out what follows. Most of our best games came from someone refusing to sign something.

-

Dice + Chat

-

Outcomes lean on dice rolls and live conversation with other players, governed by a clear set of rules. No black-box combat formulas.

+

Talk it out

+

Chat is in the same window as the map, so treaties, threats and outright lying all happen while you're looking at the thing you're fighting over.

-

Communities & servers

-

Spin up your own server, write your own rules, host your own timeline. Form subgroups, hold congresses, sign treaties.

+

Run your own

+

Host a server, write house rules, hold a congress, keep a hundred-year campaign going. We'd rather you did that than played ours.

-

The team

+

The team

- Heredita is built by four individuals, Whirl, Digi, Legi and Hilmi. Our goal is to create a platform for history, geography, and political enthusiasts who wish to live the experience of ruling a country or participating in politics with the fun that a videogame provides. + Heredita is made by four people β€” Whirl, Digi, Legi and Hilmi. We met on the internet + arguing about maps, which is roughly how everyone here ends up meeting.

- We provide a platform that allows for mappers to create, for historians to thrive and for political enthusiasts to participate! + We wanted somewhere history, geography and politics people could run a country without + it turning into a spreadsheet. Mappers get to draw, historians get to be pedantic, and + the politics enjoyers get an audience.

- Our small team came together through the internet, and we hope that those who come on our game are also able to form tight bonds. That is what Heredita is about, its not just about conquest or war, it is about unity and creating things worth sharing. + The part we care most about isn't the conquest. It's the group of people who keep showing + up to the same server on a Sunday. +

+

+ Heredita is operated by Anywhere Connection Corporation.

-

Ready to draw?

-

No download. No commitment. Just a chalkboard and a continent.

- β–Ά Open the playtest +

Come draw something

+

The playtest is free and open, and you don't need an account to try it.

+ + + Open the playtest +
@@ -121,18 +150,18 @@

Ready to draw?

- - - - - + + + + + diff --git a/site/avatar.html b/site/avatar.html index d4d23de..d8f8d09 100644 --- a/site/avatar.html +++ b/site/avatar.html @@ -5,46 +5,63 @@ Heredita β€” Avatar - +
-
-
- - + -
-
- - 0 - coming soon + Pre-alpha + + + + + + + +
+ + 0 + + + - - - - - -
@@ -52,8 +69,8 @@
-

Avatar Customizer πŸ”’ Coming Soon

- preview only β€” saving disabled +

Your countryball

+ Preview only β€” saving is off
@@ -74,12 +91,12 @@

Country

β€”

- - + + reset

- Your countryball appears in the top-right of every page across Heredita. + This is what sits in the top-right corner of every page, and next to your name in chat.

@@ -109,12 +126,12 @@

Prop

-

To Be Added Soon

- more flags, hats & props arriving with the Store +

Still on the drawing board

+ Arriving with the store
-

Flags in the pipeline

+

Flags in the queue

?
ArgentinaSoonβ„’
?
South AfricaSoonβ„’
@@ -130,7 +147,7 @@

Fla
+ many more
v0.5

-

Alt-history pipeline

+

Alt-history queue

?
Republic of VeniceSoonβ„’
?
Mongol EmpireSoonβ„’
@@ -140,23 +157,23 @@

?
Aztec EmpireSoonβ„’

-

New accessories

+

New accessories

-
πŸŽ“
Graduation capSoonβ„’
-
β›‘
Pith helmetSoonβ„’
-
πŸ“œ
Treaty scrollSoonβ„’
-
πŸ—‘
Saber propSoonβ„’
-
πŸͺ–
Beret variantsSoonβ„’
+
?
Graduation capSoonβ„’
+
?
Pith helmetSoonβ„’
+
?
Treaty scrollSoonβ„’
+
?
Saber propSoonβ„’
+
?
Beret variantsSoonβ„’
+
Frames & bannersStore launch

- Want a specific country or accessory next? Pitch us via the contact link. + Want a particular flag next? Ask in the support channel and it usually gets drawn.

-

- Browse what's planned in the Store β€” items unlock as they ship. +

+ Everything planned is listed in the store. Items unlock as they ship.

@@ -164,18 +181,18 @@

- - - - - + + + + + diff --git a/site/chat.html b/site/chat.html index 27eaed9..dd210c1 100644 --- a/site/chat.html +++ b/site/chat.html @@ -5,46 +5,63 @@ Heredita β€” Chat - +
-
-
- - + -
-
- - 0 - coming soon + Pre-alpha + + + + + + + +
+ + 0 + + + - - - - - -
@@ -59,19 +76,19 @@ - - - - - - + + + + + + diff --git a/site/css/chalkboard.css b/site/css/chalkboard.css index 12f74a8..b6380aa 100644 --- a/site/css/chalkboard.css +++ b/site/css/chalkboard.css @@ -1,166 +1,217 @@ /* ========================================================= - HEREDITA β€” Chalkboard Theme - Shared across all pages. + HEREDITA β€” Chalkboard + ----------------------------------------------------------- + One rule runs through this whole file: + + SOLID line = a real, finished thing + DASHED line = a sketch β€” locked, unbuilt, coming soon + ACCENT line = the thing you're on right now + + Dashes carry meaning here, so they are never decoration. ========================================================= */ -@import url('https://fonts.googleapis.com/css2?family=Caveat:wght@500;700&family=Patrick+Hand&family=Architects+Daughter&family=Kalam:wght@300;400;700&family=Special+Elite&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Caveat:wght@600;700&family=Cabin:wght@400;500;600;700&family=Special+Elite&display=swap'); :root { - /* Chalkboard greens */ + /* Board */ --board-1: #1e3a2a; --board-2: #16291f; --board-3: #0f2018; - --board-edge: #0a160f; + --board-4: #0a160f; + --board-ink: #07110b; /* Chalk */ - --chalk: #f4f1e6; - --chalk-soft: #e8e3d2; - --chalk-faded: rgba(244, 241, 230, 0.55); - --chalk-dust: rgba(244, 241, 230, 0.10); - - /* Accent (from logo) */ - --accent: #d97a3d; - --accent-soft: #e89968; - --accent-deep: #b35d28; - - /* Tier colors */ - --tier-guest-fg: #c9d1c2; - --tier-guest-bg: rgba(180, 192, 170, 0.18); - --tier-guest-bd: rgba(201, 209, 194, 0.55); - - --tier-regular-fg: #f4f1e6; - --tier-regular-bg: rgba(244, 241, 230, 0.14); - --tier-regular-bd: rgba(244, 241, 230, 0.65); - - --tier-emperor-fg: #fff0c6; - --tier-emperor-bg: linear-gradient(135deg, rgba(255,210,80,0.30), rgba(217,122,61,0.30)); - --tier-emperor-bd: #f4c95d; - - /* Wood / frame */ - --wood-1: #5b3a1f; - --wood-2: #3a2510; - - /* Sizing */ - --radius: 14px; + --chalk: #f4f1e6; + --chalk-soft: #ddd8c6; + --chalk-dim: #a8b0a0; + --chalk-ghost: rgba(244, 241, 230, 0.42); + + /* Coloured chalk β€” used sparingly, like the real box of it */ + --accent: #d97a3d; + --accent-soft: #ea9a63; + --accent-deep: #a8511f; + --chalk-blue: #8fc2e0; + --chalk-red: #e08272; + --chalk-gold: #f0c661; + + /* Chalk tray */ + --wood-1: #6b4526; + --wood-2: #3d2612; + + /* Line hierarchy */ + --rule: 1px solid rgba(244, 241, 230, 0.13); + --rule-strong: 1px solid rgba(244, 241, 230, 0.26); + --sketch: 2px dashed rgba(244, 241, 230, 0.38); + + /* Type */ + --font-display: 'Caveat', 'Segoe Script', cursive; + --font-stamp: 'Special Elite', 'Courier New', monospace; + --font-body: 'Cabin', system-ui, -apple-system, 'Segoe UI', sans-serif; + + /* Shape */ + --r-sm: 8px; + --r: 12px; + --r-lg: 18px; --maxw: 1180px; - --shadow-chalk: 0 0 0 2px rgba(244,241,230,0.06), - 0 12px 32px rgba(0,0,0,0.45); - /* Z scale */ - --z-nav: 30; + /* Depth */ + --lift-1: 0 1px 0 rgba(244,241,230,0.05) inset, 0 10px 24px -16px rgba(0,0,0,0.9); + --lift-2: 0 1px 0 rgba(244,241,230,0.07) inset, 0 22px 44px -22px rgba(0,0,0,0.95); + --lift-3: 0 28px 60px -24px rgba(0,0,0,0.95); + + /* Rhythm */ + --gap: 16px; + --sec: clamp(38px, 6vw, 66px); + + /* Stacking */ + --z-nav: 40; + --z-menu: 60; --z-overlay: 80; --z-toast: 90; + + --ease: cubic-bezier(.22, .8, .2, 1); } -* { box-sizing: border-box; } +*, *::before, *::after { box-sizing: border-box; } -html, body { - margin: 0; - padding: 0; - min-height: 100%; - font-family: 'Architects Daughter', 'Kalam', 'Patrick Hand', system-ui, sans-serif; - color: var(--chalk); - background-color: var(--board-2); - font-size: 19px; - line-height: 1.6; - letter-spacing: 0.15px; - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; -} +html { -webkit-text-size-adjust: 100%; } + +/* Components below set `display` on elements that JS also toggles with the + `hidden` attribute β€” which would otherwise lose to any class selector. */ +[hidden] { display: none !important; } -/* Chalkboard background β€” layered greens + SVG noise */ body { + margin: 0; + font-family: var(--font-body); + font-size: 17px; + line-height: 1.62; + color: var(--chalk-soft); + background-color: var(--board-2); background-image: - radial-gradient(ellipse 120% 80% at 20% 10%, rgba(255,255,255,0.05), transparent 60%), - radial-gradient(ellipse 90% 60% at 80% 90%, rgba(0,0,0,0.45), transparent 70%), - radial-gradient(ellipse 60% 40% at 50% 50%, var(--board-1), var(--board-2) 60%, var(--board-3) 100%); - position: relative; + radial-gradient(ellipse 120% 80% at 22% 6%, rgba(255,255,255,0.055), transparent 58%), + radial-gradient(ellipse 90% 65% at 82% 96%, rgba(0,0,0,0.5), transparent 70%), + radial-gradient(ellipse 65% 45% at 50% 45%, var(--board-1), var(--board-2) 58%, var(--board-3) 100%); overflow-x: hidden; + position: relative; + -webkit-font-smoothing: antialiased; + + /* Sticky footer: short pages (chat, friends, settings) would otherwise + leave the footer stranded halfway down the viewport. */ + min-height: 100vh; + display: flex; + flex-direction: column; } -/* Chalk-dust grain overlay */ +/* width:100% matters β€” as a column flex item, `.container`'s `margin: 0 auto` + would otherwise shrink main to its content width and collapse the grids. */ +body > main { flex: 1 0 auto; width: 100%; } +body > .site-footer { flex: 0 0 auto; } + +/* Slate grain. Fixed so it reads as the surface, not the content. */ body::before { content: ""; - position: fixed; - inset: 0; - pointer-events: none; - z-index: 1; - opacity: 0.35; + position: fixed; inset: 0; + pointer-events: none; z-index: 0; + opacity: 0.3; mix-blend-mode: overlay; - background-image: url("data:image/svg+xml;utf8,"); + background-image: url("data:image/svg+xml;utf8,"); } -/* Subtle chalk smudges */ +/* Ghosts of things wiped off the board */ body::after { content: ""; - position: fixed; - inset: 0; - pointer-events: none; - z-index: 1; + position: fixed; inset: 0; + pointer-events: none; z-index: 0; background: - radial-gradient(circle at 12% 22%, rgba(244,241,230,0.05) 0, transparent 18%), - radial-gradient(circle at 78% 12%, rgba(244,241,230,0.04) 0, transparent 14%), - radial-gradient(circle at 30% 88%, rgba(244,241,230,0.05) 0, transparent 22%), - radial-gradient(circle at 90% 78%, rgba(244,241,230,0.04) 0, transparent 18%); + radial-gradient(ellipse 22% 9% at 14% 24%, rgba(244,241,230,0.045), transparent 70%), + radial-gradient(ellipse 16% 7% at 79% 13%, rgba(244,241,230,0.035), transparent 70%), + radial-gradient(ellipse 26% 10% at 32% 86%, rgba(244,241,230,0.04), transparent 70%), + radial-gradient(ellipse 18% 8% at 91% 74%, rgba(244,241,230,0.03), transparent 70%); } -main, header, footer, section, .container { - position: relative; - z-index: 2; -} +main, header, footer, section, .container { position: relative; z-index: 1; } + + +/* ========================================================= + TYPE + Caveat writes. Special Elite stamps. Cabin explains. + ========================================================= */ -/* ============= Typography ============= */ h1, h2, h3, h4 { - font-family: 'Caveat', 'Patrick Hand', cursive; - color: var(--chalk); - text-shadow: - 0 1px 0 rgba(0,0,0,0.25), - 0 0 14px rgba(244,241,230,0.10); - margin: 0 0 .4em; - letter-spacing: 0.5px; + font-family: var(--font-display); font-weight: 700; + color: var(--chalk); + margin: 0 0 .38em; + line-height: 1.08; + letter-spacing: 0.4px; + text-shadow: 0 1px 0 rgba(0,0,0,0.3), 0 0 18px rgba(244,241,230,0.09); } -h1 { font-size: clamp(2.2rem, 4.8vw, 3.6rem); line-height: 1.05; } -h2 { font-size: clamp(1.7rem, 3vw, 2.4rem); } -h3 { font-size: clamp(1.3rem, 2vw, 1.6rem); } +h1 { font-size: clamp(2.4rem, 5.2vw, 3.9rem); } +h2 { font-size: clamp(1.85rem, 3.2vw, 2.6rem); } +h3 { font-size: clamp(1.3rem, 2vw, 1.65rem); } +h4 { font-size: 1.2rem; } -h1.tilt-l, h2.tilt-l, h3.tilt-l { transform: rotate(-1.2deg); } -h1.tilt-r, h2.tilt-r, h3.tilt-r { transform: rotate(1deg); } - -p, li, label, input, span, div, td, th { - font-family: 'Architects Daughter', 'Kalam', cursive; -} +/* Exactly one hand-tilt per page, on the h1. Any more and it looks + like a filter rather than a hand. */ +h1.tilt-l { transform: rotate(-0.7deg); } +h1.tilt-r { transform: rotate(0.5deg); } +h2.tilt-l, h2.tilt-r, h3.tilt-l, h3.tilt-r { transform: none; } -p { color: var(--chalk-soft); max-width: 70ch; } -/* When a paragraph sits inside a centered block, also center the - paragraph element itself so the 70ch max-width doesn't pin it left. */ -.text-center > p, -.text-center p { - margin-left: auto; - margin-right: auto; -} -li { color: var(--chalk-soft); } +p { margin: 0 0 1em; max-width: 68ch; } +p:last-child { margin-bottom: 0; } -/* Buttons + tags keep the playful Caveat for chunky chalk feel */ -button, .btn, .tag, .version, .coin-chip, .user-chip, .auth-tabs button, .brand-name { - font-family: 'Caveat', 'Architects Daughter', cursive; -} +/* A centred paragraph still has a 68ch measure, so the *block* has to be + centred too β€” otherwise the text centres inside a box that's sitting off + to the left. Covers both `.text-center p` and `p.text-center`. */ +.text-center p, +p.text-center, +.text-center > * { margin-left: auto; margin-right: auto; } -/* Labels: Patrick Hand reads slightly chunkier β€” good for form labels */ -.field label { font-family: 'Patrick Hand', 'Caveat', cursive; } +strong { color: var(--chalk); font-weight: 600; } +em { color: var(--chalk); } a { color: var(--chalk); text-decoration: none; - border-bottom: 1.5px dashed var(--chalk-faded); - padding-bottom: 1px; - transition: color .2s, border-color .2s; + border-bottom: 1px solid rgba(244,241,230,0.35); + transition: color .18s, border-color .18s; } a:hover { color: var(--accent-soft); border-bottom-color: var(--accent); } -a:focus-visible { outline: 2px dashed var(--accent); outline-offset: 3px; border-radius: 4px; } +a:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; + border-radius: 3px; +} + +code { + font-family: var(--font-stamp); + font-size: 0.92em; + color: var(--accent-soft); +} + +.muted { color: var(--chalk-dim); } +.accent { color: var(--accent-soft); } + +/* Typewritten metadata: dates, versions, statuses, section kickers. */ +.kicker, .stamp, .version, .date, .badge, .cs-eta, .brand-tag { + font-family: var(--font-stamp); + letter-spacing: 0.08em; + text-transform: uppercase; + font-size: 0.72rem; +} + +.kicker { + display: block; + color: var(--accent-soft); + margin-bottom: 6px; +} + + +/* ========================================================= + LAYOUT + ========================================================= */ -/* ============= Layout helpers ============= */ .container { max-width: var(--maxw); margin: 0 auto; @@ -172,908 +223,1199 @@ a:focus-visible { outline: 2px dashed var(--accent); outline-offset: 3px; border .spacer { flex: 1; } .center { display: flex; align-items: center; justify-content: center; } .text-center { text-align: center; } -.muted { color: var(--chalk-faded); } -.accent { color: var(--accent-soft); } -/* ============= Chalk cards ============= */ +.section-title { + display: flex; + align-items: baseline; + gap: 16px; + flex-wrap: wrap; + margin: var(--sec) 0 4px; +} +.section-title h1, .section-title h2 { margin: 0; } +.section-title .muted, +.section-title .see-all { + font-family: var(--font-stamp); + font-size: 0.72rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} +.section-title .see-all { margin-left: auto; border-bottom-color: transparent; } +.section-title .see-all:hover { border-bottom-color: var(--accent); } + +/* A chalk line drawn under section headings β€” the one signature flourish. */ +.section-title::after { + content: ""; + flex: 0 0 100%; + height: 2px; + margin-top: 10px; + background: linear-gradient(90deg, + rgba(244,241,230,0.34) 0%, + rgba(244,241,230,0.14) 42%, + transparent 78%); + transform-origin: left center; + transform: scaleX(var(--rule-scale, 1)); + transition: transform .7s var(--ease); +} +.section-title.reveal::after { --rule-scale: 0; } +.section-title.reveal.in::after { --rule-scale: 1; } + + +/* ========================================================= + CARDS + Solid edge = finished. `.sketch` = not built yet. + ========================================================= */ + .chalk-card { position: relative; + padding: 26px; + border: var(--rule); + border-radius: var(--r); background: - linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.32)), - radial-gradient(ellipse at top, rgba(244,241,230,0.04), transparent 60%); - border-radius: var(--radius); - padding: 28px; - box-shadow: var(--shadow-chalk); + linear-gradient(180deg, rgba(244,241,230,0.05), rgba(0,0,0,0.10) 40%, rgba(0,0,0,0.24)), + rgba(10, 22, 15, 0.34); + box-shadow: var(--lift-1); + transition: border-color .25s var(--ease), + box-shadow .25s var(--ease), + transform .25s var(--ease), + background .25s var(--ease); +} + +.chalk-card.flat { background: rgba(0,0,0,0.22); box-shadow: none; } + +/* Not built yet. Chalk outline, nothing filled in. */ +.chalk-card.sketch, +.mode-card.disabled, +.coming-soon-tile, +.store-item.sketch { + border: var(--sketch); + background: + repeating-linear-gradient(-45deg, rgba(244,241,230,0.028) 0 9px, transparent 9px 18px), + rgba(0,0,0,0.2); + box-shadow: none; } -.chalk-card::before { - content: ""; - position: absolute; - inset: 6px; - border: 2px dashed rgba(244,241,230,0.55); - border-radius: calc(var(--radius) - 4px); - pointer-events: none; - opacity: .85; +/* Interactive cards. Note the border-bottom reset β€” these are anchors, and + the global link underline would otherwise cut across the card edge. */ +a.chalk-card, button.chalk-card, .mode-card:not(.disabled) { + cursor: pointer; + border-bottom: var(--rule); + text-align: left; + color: inherit; +} +a.chalk-card { display: block; } +a.chalk-card:hover, +button.chalk-card:hover, +.mode-card:not(.disabled):hover, +.about-grid .chalk-card:hover, +.faq-grid .chalk-card:hover, +.update-entry:hover { + transform: translateY(-3px); + border-color: rgba(244,241,230,0.3); + box-shadow: var(--lift-2); } +a.chalk-card:active, .mode-card:not(.disabled):active { + transform: translateY(-1px); + transition-duration: .08s; +} +a.chalk-card:focus-visible, button.chalk-card:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; +} + -.chalk-card.tight { padding: 18px; } -.chalk-card.flat::before { border-style: solid; opacity: .35; } +/* ========================================================= + BUTTONS + ========================================================= */ -/* ============= Chalk buttons ============= */ .btn { - --bg: transparent; - --fg: var(--chalk); - --bd: var(--chalk); display: inline-flex; align-items: center; justify-content: center; - gap: 10px; - font-family: 'Caveat', cursive; + gap: 9px; + font-family: var(--font-body); font-weight: 700; - font-size: 1.4rem; - letter-spacing: 0.5px; - color: var(--fg); - background: var(--bg); - border: 2.5px dashed var(--bd); - border-radius: 12px; - padding: 12px 26px; + font-size: 0.95rem; + letter-spacing: 0.015em; + color: var(--chalk); + background: rgba(244,241,230,0.05); + border: var(--rule-strong); + border-radius: 10px; + padding: 11px 22px; cursor: pointer; text-decoration: none; - transition: background .18s ease, color .18s ease, transform .18s ease, border-style .18s ease; - text-shadow: 0 1px 0 rgba(0,0,0,0.18); - position: relative; user-select: none; + transition: background .16s, border-color .16s, color .16s, transform .12s, box-shadow .16s; } - -.btn:hover:not(:disabled) { - background: var(--chalk); - color: var(--board-2); - border-style: solid; - transform: rotate(-0.5deg); - text-shadow: none; +.btn:hover:not(:disabled):not([aria-disabled="true"]) { + background: rgba(244,241,230,0.12); + border-color: rgba(244,241,230,0.5); + color: #fff; } +.btn:active:not(:disabled) { transform: translateY(1px); } +.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; } +.btn:disabled { opacity: 0.4; cursor: not-allowed; } -.btn:active:not(:disabled) { transform: rotate(0.4deg) scale(0.98); } - -.btn:focus-visible { outline: 3px dashed var(--accent); outline-offset: 4px; } - -.btn:disabled { - opacity: 0.45; - cursor: not-allowed; - filter: grayscale(0.4); -} +.btn svg { width: 17px; height: 17px; flex: 0 0 auto; } +/* Primary β€” a painted key with a hard edge underneath, like a game button */ .btn-primary { - --bg: var(--accent); - --fg: var(--board-3); - --bd: var(--chalk); - border-style: solid; - box-shadow: 0 4px 0 var(--accent-deep), 0 8px 18px rgba(0,0,0,0.35); -} -.btn-primary:hover:not(:disabled) { - background: var(--accent-soft); - color: var(--board-3); - transform: translateY(-2px) rotate(-0.4deg); - box-shadow: 0 6px 0 var(--accent-deep), 0 12px 22px rgba(0,0,0,0.45); + color: var(--board-ink); + background: linear-gradient(180deg, var(--accent-soft), var(--accent)); + border: 1px solid rgba(255, 220, 180, 0.55); + box-shadow: 0 3px 0 var(--accent-deep), 0 12px 26px -12px rgba(217,122,61,0.85); +} +.btn-primary:hover:not(:disabled):not([aria-disabled="true"]) { + color: var(--board-ink); + background: linear-gradient(180deg, #f2ab77, var(--accent-soft)); + transform: translateY(-2px); + box-shadow: 0 5px 0 var(--accent-deep), 0 18px 34px -12px rgba(217,122,61,0.95); } .btn-primary:active:not(:disabled) { - transform: translateY(1px); - box-shadow: 0 2px 0 var(--accent-deep), 0 4px 10px rgba(0,0,0,0.35); -} - -.btn-ghost { font-size: 1.1rem; padding: 8px 16px; border-width: 2px; } - -.btn-huge { - font-size: 2.6rem; - padding: 28px 72px; - border-radius: 18px; + transform: translateY(2px); + box-shadow: 0 1px 0 var(--accent-deep), 0 6px 14px -8px rgba(0,0,0,0.8); } -/* ============= Inputs ============= */ -.field { - display: flex; - flex-direction: column; - gap: 6px; - margin-bottom: 14px; -} -.field label { - font-family: 'Caveat', cursive; - font-size: 1.25rem; - color: var(--chalk); +.btn-ghost { + background: transparent; + border-color: transparent; + color: var(--chalk-dim); + padding: 9px 14px; } -.field input, .field select { - font-family: 'Patrick Hand', cursive; - font-size: 1.1rem; +.btn-ghost:hover:not(:disabled) { + background: rgba(244,241,230,0.07); + border-color: transparent; color: var(--chalk); - background: rgba(0,0,0,0.28); - border: 2px dashed rgba(244,241,230,0.55); - border-radius: 10px; - padding: 10px 14px; - outline: none; - transition: border-color .2s, background .2s; } -.field input::placeholder { color: var(--chalk-faded); } -.field input:focus, .field select:focus { - border-color: var(--accent); - border-style: solid; - background: rgba(0,0,0,0.40); + + + +/* Locked controls read as sketches too */ +.btn.locked, .btn.emperor-locked, .tier-switch button.locked { + border-style: dashed; + opacity: 0.62; + cursor: not-allowed; } -.field input:invalid:not(:placeholder-shown) { - border-color: #e07a7a; +.btn.locked:hover, .btn.emperor-locked:hover, .tier-switch button.locked:hover { + transform: none; + background: rgba(244,241,230,0.05); } -/* Checkbox */ -.checkbox { - display: flex; - align-items: flex-start; - gap: 10px; - cursor: pointer; - font-size: 1rem; + +/* ========================================================= + CHIPS, BADGES, STAMPS + ========================================================= */ + +.badge, .lock-badge, .price-pill, .lock-pill { + display: inline-flex; + align-items: center; + gap: 6px; + width: max-content; + padding: 3px 10px; + border-radius: 999px; + line-height: 1.5; } -.checkbox input { appearance: none; -webkit-appearance: none; margin: 0; } -.checkbox .box { - width: 22px; height: 22px; flex: 0 0 22px; - border: 2.5px dashed var(--chalk); - border-radius: 4px; - display: inline-flex; align-items: center; justify-content: center; - margin-top: 2px; - transition: background .15s, border-color .15s; + +/* "Coming soon" everywhere reads as a sketch */ +.badge, .lock-badge, .lock-pill { + font-family: var(--font-stamp); + font-size: 0.66rem; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--accent-soft); + background: rgba(217,122,61,0.12); + border: 1px dashed rgba(217,122,61,0.6); } -.checkbox input:checked + .box { - background: var(--accent); - border-color: var(--chalk); - border-style: solid; +.lock-pill { margin-left: 10px; vertical-align: middle; } + + +.price-pill { + font-family: var(--font-stamp); + font-size: 0.72rem; + color: var(--chalk-dim); + border: var(--rule); } -.checkbox input:checked + .box::after { - content: "βœ“"; - font-family: 'Caveat', cursive; - color: var(--board-3); - font-weight: 700; - font-size: 18px; - line-height: 1; +.price-pill .coin, .coin-chip .coin { + width: 13px; height: 13px; + border-radius: 50%; + background: radial-gradient(circle at 34% 32%, #ffe9a8, var(--chalk-gold) 52%, #b8862a); + box-shadow: 0 0 0 1px rgba(0,0,0,0.4); + flex: 0 0 auto; } -.checkbox input:focus-visible + .box { outline: 2px dashed var(--accent); outline-offset: 2px; } -/* ============= Top Navigation ============= */ + + +/* ========================================================= + TOP BAR + The nav is the spine of the site, so it gets real chrome: + icon tabs, and a chalk dash that slides to whatever you point at. + ========================================================= */ + .topbar { position: sticky; top: 0; z-index: var(--z-nav); - background: - linear-gradient(180deg, rgba(10,22,15,0.92), rgba(10,22,15,0.78)); - backdrop-filter: blur(6px); - border-bottom: 2px dashed rgba(244,241,230,0.25); + background: linear-gradient(180deg, rgba(7,17,11,0.96), rgba(7,17,11,0.86)); + backdrop-filter: blur(12px) saturate(1.15); + -webkit-backdrop-filter: blur(12px) saturate(1.15); + border-bottom: 1px solid rgba(244,241,230,0.12); + box-shadow: 0 1px 0 rgba(244,241,230,0.045), 0 14px 34px -24px #000; } -.topbar .inner { + +.topbar-inner, .topbar .inner { max-width: var(--maxw); margin: 0 auto; + padding: 9px 24px; display: flex; align-items: center; - gap: 14px; - padding: 10px 20px; -} -.topbar .brand { - display: flex; align-items: center; gap: 10px; - border: none; -} -.topbar .brand img { width: 38px; height: 38px; object-fit: contain; } -.topbar .brand .brand-name { - font-family: 'Caveat', cursive; font-weight: 700; font-size: 1.5rem; color: var(--chalk); -} -.topbar nav { display: flex; gap: 14px; } -.topbar nav a { - border: none; - font-size: 1.05rem; - padding: 6px 10px; - border-radius: 8px; - color: var(--chalk-soft); + gap: 16px; } -.topbar nav a:hover { background: rgba(244,241,230,0.08); color: var(--chalk); } -.topbar nav a.active { color: var(--accent-soft); } -.coin-chip { - display: inline-flex; align-items: center; gap: 8px; - background: linear-gradient(180deg, var(--accent), var(--accent-deep)); - color: var(--board-3); - font-family: 'Caveat', cursive; font-weight: 700; - padding: 6px 12px; border-radius: 999px; - border: 2px solid rgba(244,241,230,0.85); - font-size: 1.05rem; - box-shadow: 0 4px 0 rgba(0,0,0,0.35); -} -.coin-chip .coin { - display: inline-block; width: 18px; height: 18px; - background: radial-gradient(circle at 35% 35%, #fff2b3, var(--accent) 60%, var(--accent-deep)); - border-radius: 50%; - border: 1.5px solid var(--board-3); +/* --- Brand --- */ +.brand { + display: flex; + align-items: center; + gap: 10px; + border-bottom: none; + flex: 0 0 auto; } -.coin-chip .soon { - font-size: .75rem; color: rgba(15,32,24,0.7); margin-left: 6px; - font-family: 'Patrick Hand', cursive; +.brand:hover { color: var(--chalk); } +.brand-mark, .topbar .brand img { + width: 34px; height: 34px; + object-fit: contain; + transition: transform .4s var(--ease); } - -.user-chip { - display: inline-flex; align-items: center; gap: 8px; - padding: 5px 12px; - border: 2px dashed rgba(244,241,230,0.55); - border-radius: 999px; +.brand:hover .brand-mark { transform: rotate(-7deg) scale(1.07); } +.brand-text { display: flex; flex-direction: column; line-height: 1; gap: 3px; } +.brand-name { + font-family: var(--font-display); + font-weight: 700; + font-size: 1.55rem; color: var(--chalk); - font-family: 'Caveat', cursive; - font-size: 1.15rem; + line-height: 0.9; } -.user-chip .avatar { - width: 26px; height: 26px; border-radius: 50%; - background: linear-gradient(135deg, var(--accent), var(--accent-deep)); - border: 1.5px solid var(--chalk); - display: inline-flex; align-items: center; justify-content: center; - color: var(--board-3); font-weight: 700; font-size: .9rem; +.brand-tag { + font-size: 0.55rem; + color: var(--accent-soft); + opacity: 0.85; } -/* ============= Footer ============= */ -.site-footer { - margin-top: 60px; - padding: 26px 24px 40px; - border-top: 2px dashed rgba(244,241,230,0.25); - background: rgba(10,22,15,0.6); - color: var(--chalk-faded); - font-size: 0.95rem; +/* --- Tabs --- */ +.primary-nav { + position: relative; + display: flex; + align-items: center; + gap: 1px; + flex: 1 1 auto; + min-width: 0; } -.site-footer .footer-inner { - max-width: var(--maxw); - margin: 0 auto; - display: flex; flex-wrap: wrap; gap: 14px; align-items: center; + +.nav-tab { + position: relative; + display: inline-flex; + align-items: center; + gap: 8px; + padding: 9px 13px; + border: none; + border-bottom: none; + border-radius: var(--r-sm); + background: transparent; + font-family: var(--font-body); + font-weight: 600; + font-size: 0.94rem; + letter-spacing: 0.01em; + color: var(--chalk-dim); + cursor: pointer; + white-space: nowrap; + transition: color .18s, background .18s; } -.site-footer a { color: var(--chalk-soft); font-size: 0.95rem; } -.site-footer .footer-links { display: flex; gap: 18px; flex-wrap: wrap; } -.site-footer .footer-meta { margin-left: auto; opacity: 0.7; } +.nav-tab svg { width: 16px; height: 16px; flex: 0 0 auto; opacity: 0.55; transition: opacity .18s var(--ease), transform .3s var(--ease); } +.nav-tab:hover, .nav-tab:focus-visible { color: var(--chalk); background: rgba(244,241,230,0.07); } +.nav-tab:hover svg, .nav-tab:focus-visible svg { opacity: 1; transform: translateY(-1px); } +.nav-tab.active { color: var(--chalk); } +.nav-tab.active svg { opacity: 1; color: var(--accent-soft); } +.nav-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; } -/* ============= Chalk dust floating particles ============= */ -.chalk-dust { - position: fixed; inset: 0; pointer-events: none; z-index: 1; overflow: hidden; +.nav-tab .caret { + width: 11px; height: 11px; + opacity: 0.55; + transition: transform .28s var(--ease), opacity .18s; } -.chalk-dust span { +.nav-group.open > .nav-tab .caret { transform: rotate(180deg); } +.nav-group.open > .nav-tab { color: var(--chalk); background: rgba(244,241,230,0.07); } + +/* The sliding chalk dash. Follows the pointer, snaps back to the + current page when you stop pointing at anything. */ +.nav-marker { position: absolute; - bottom: -20px; - width: 4px; height: 4px; border-radius: 50%; - background: var(--chalk); - opacity: 0.25; - animation: drift linear infinite; - filter: blur(0.5px); + left: 0; bottom: -4px; + height: 3px; + width: 0; + border-radius: 2px; + pointer-events: none; + opacity: 0; + background: repeating-linear-gradient(90deg, + var(--accent) 0 7px, rgba(217,122,61,0.22) 7px 11px); + transition: transform .34s var(--ease), + width .34s var(--ease), + opacity .2s ease, + background .2s ease; } -@keyframes drift { - 0% { transform: translate(0, 0); opacity: 0; } - 10% { opacity: 0.35; } - 100% { transform: translate(var(--dx, 40px), -110vh); opacity: 0; } +.primary-nav.marker-live .nav-marker { opacity: 1; } +.primary-nav.marker-hover .nav-marker { + background: repeating-linear-gradient(90deg, + var(--chalk) 0 7px, rgba(244,241,230,0.18) 7px 11px); } -/* ============= Loading overlay ============= */ -.loading-overlay { - position: fixed; inset: 0; - background: rgba(10,22,15,0.92); - z-index: var(--z-overlay); - display: none; - align-items: center; justify-content: center; - flex-direction: column; gap: 24px; - text-align: center; +/* --- Dropdown panels --- */ +.nav-group { position: relative; display: flex; align-items: center; } + +.nav-menu { + position: absolute; + top: calc(100% + 16px); + left: 50%; + min-width: 250px; + padding: 7px; + display: flex; + flex-direction: column; + gap: 1px; + border: var(--rule-strong); + border-radius: var(--r-lg); + background: linear-gradient(180deg, #172c20, #0b1a11); + box-shadow: var(--lift-3), 0 0 0 1px rgba(0,0,0,0.5); + z-index: var(--z-menu); + opacity: 0; + visibility: hidden; + transform: translate(-50%, -8px) scale(0.97); + transform-origin: top center; + transition: opacity .18s ease, transform .26s var(--ease), visibility .26s; } -.loading-overlay.show { display: flex; } -.loading-overlay .spinner { - width: 64px; height: 64px; - border: 4px dashed var(--chalk); - border-top-color: var(--accent); - border-radius: 50%; - animation: spin 1.4s linear infinite; +.nav-group.open > .nav-menu { + opacity: 1; + visibility: visible; + transform: translate(-50%, 0) scale(1); } -@keyframes spin { to { transform: rotate(360deg); } } -.loading-overlay h2 { - font-family: 'Caveat', cursive; - font-size: 2.2rem; +.nav-menu.align-right { + left: auto; right: 0; + transform: translate(0, -8px) scale(0.97); + transform-origin: top right; } +.nav-group.open > .nav-menu.align-right { transform: translate(0, 0) scale(1); } -/* ============= Auth specific ============= */ -.auth-wrap { - min-height: calc(100vh - 100px); - display: flex; flex-direction: column; align-items: center; - padding: 28px 20px; -} -.auth-logo { - width: clamp(220px, 30vw, 360px); - margin: 12px auto 18px; - filter: drop-shadow(0 10px 22px rgba(0,0,0,0.55)); - user-select: none; +/* chalk notch pointing back at the tab */ +.nav-menu::before { + content: ""; + position: absolute; + top: -7px; + left: var(--notch, 50%); + margin-left: -6px; + width: 12px; height: 12px; + transform: rotate(45deg); + background: #172c20; + border-left: var(--rule-strong); + border-top: var(--rule-strong); + border-top-left-radius: 3px; } -.auth-tagline { - text-align: center; - font-family: 'Caveat', cursive; - font-size: clamp(1.4rem, 2.5vw, 2rem); + +.nav-menu a, .nav-menu button { + display: flex; + align-items: center; + gap: 12px; + width: 100%; + padding: 10px 12px; + border: 1px solid transparent; + border-radius: 10px; + background: transparent; + font-family: var(--font-body); + font-size: 0.93rem; + font-weight: 500; color: var(--chalk-soft); - margin: 0 0 22px; - transform: rotate(-0.6deg); + text-align: left; + cursor: pointer; + white-space: nowrap; + transition: background .15s, color .15s, border-color .15s, transform .15s var(--ease); } -.auth-card { - width: 100%; - max-width: 460px; +.nav-menu a:hover, .nav-menu a:focus-visible, +.nav-menu button:hover, .nav-menu button:focus-visible { + background: rgba(244,241,230,0.08); + border-color: rgba(244,241,230,0.16); + color: var(--chalk); + outline: none; + transform: translateX(2px); +} +.nav-menu a.active { + color: var(--accent-soft); + background: rgba(217,122,61,0.14); + border-color: rgba(217,122,61,0.5); +} +.nav-menu .sp-icon, .nav-menu .mi-icon { + width: 19px; height: 19px; + flex: 0 0 19px; + display: inline-flex; align-items: center; justify-content: center; + opacity: 0.75; +} +.nav-menu .sp-icon svg, .nav-menu .mi-icon svg { width: 19px; height: 19px; } +.nav-menu a:hover .sp-icon, .nav-menu a:hover .mi-icon { opacity: 1; } +.nav-menu .sp-label { flex: 1; min-width: 0; line-height: 1.2; } +.nav-menu .sp-sub { + display: block; + font-size: 0.74rem; + color: var(--chalk-dim); + margin-top: 2px; } -.auth-tabs { +.nav-menu .menu-rule { + height: 1px; + margin: 5px 8px; + background: rgba(244,241,230,0.12); +} +.nav-menu .menu-head { + font-family: var(--font-stamp); + font-size: 0.62rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--chalk-dim); + padding: 7px 12px 4px; +} + +/* --- Right-hand cluster --- */ +.topbar-right { display: flex; - gap: 8px; - margin-bottom: 18px; - border-bottom: 2px dashed rgba(244,241,230,0.35); - padding-bottom: 6px; + align-items: center; + gap: 9px; + flex: 0 0 auto; + margin-left: auto; } -.auth-tabs button { - flex: 1; - background: transparent; - border: none; - color: var(--chalk-faded); - font-family: 'Caveat', cursive; - font-size: 1.5rem; - font-weight: 700; - padding: 6px 10px; + +.coin-chip { + display: inline-flex; + align-items: center; + gap: 7px; + padding: 5px 12px; + border-radius: 999px; + border: 1px dashed rgba(240, 198, 97, 0.45); + background: rgba(240, 198, 97, 0.09); + color: var(--chalk-gold); + font-family: var(--font-stamp); + font-size: 0.78rem; + cursor: default; +} +.coin-chip .soon { + font-size: 0.6rem; + letter-spacing: 0.1em; + text-transform: uppercase; + opacity: 0.6; +} + +/* Name + tier + avatar, one control */ +.user-chip, .player-chip { + display: inline-flex; + align-items: center; + gap: 9px; + padding: 4px 10px 4px 5px; + border: var(--rule); + border-radius: 999px; + background: rgba(244,241,230,0.04); cursor: pointer; - border-radius: 8px; + font-family: var(--font-body); + transition: background .16s, border-color .16s; +} +.user-chip:hover, .nav-group.open > .user-chip { + background: rgba(244,241,230,0.1); + border-color: rgba(244,241,230,0.28); +} +.user-chip .avatar { + width: 29px; height: 29px; + flex: 0 0 29px; + border-radius: 50%; + display: inline-flex; align-items: center; justify-content: center; + background: linear-gradient(140deg, var(--accent-soft), var(--accent-deep)); + color: var(--board-ink); + font-family: var(--font-display); + font-weight: 700; + font-size: 1rem; + border: 1px solid rgba(244,241,230,0.5); + overflow: hidden; } -.auth-tabs button.active { +.user-chip .avatar.countryball { + background: none; border: none; padding: 0; + width: 30px; height: 30px; flex-basis: 30px; + overflow: visible; +} +.user-chip .avatar.countryball svg { width: 100%; height: 100%; display: block; } + +.user-block { + display: inline-flex; + flex-direction: column; + align-items: flex-start; + gap: 1px; + line-height: 1.1; +} +.user-block .name { + font-size: 0.86rem; + font-weight: 600; color: var(--chalk); - background: rgba(244,241,230,0.08); + max-width: 130px; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.form-actions { display: flex; flex-direction: column; gap: 12px; margin-top: 8px; } -.form-actions .row-or { - text-align: center; - font-family: 'Caveat', cursive; - color: var(--chalk-faded); - position: relative; - margin: 4px 0; +.tier-badge { + display: inline-flex; + align-items: center; + gap: 4px; + font-family: var(--font-stamp); + font-size: 0.6rem; + letter-spacing: 0.1em; + text-transform: uppercase; + line-height: 1.4; + padding: 0 7px; + border-radius: 999px; + border: 1px solid rgba(201,209,194,0.4); + background: rgba(180,192,170,0.14); + color: var(--chalk-dim); + text-decoration: none; + border-bottom-width: 1px; +} +.tier-badge[data-tier="regular"] { + border-color: rgba(244,241,230,0.5); + background: rgba(244,241,230,0.12); + color: var(--chalk); } -.form-actions .row-or::before, -.form-actions .row-or::after { - content: ""; position: absolute; top: 50%; width: 38%; height: 1px; - border-top: 2px dashed rgba(244,241,230,0.30); +.tier-badge[data-tier="emperor"] { + border-color: var(--chalk-gold); + background: linear-gradient(135deg, rgba(240,198,97,0.3), rgba(217,122,61,0.3)); + color: #ffeec2; + box-shadow: 0 0 14px rgba(240,198,97,0.28); +} +.tier-badge .crown { + width: 11px; height: 11px; + background: currentColor; + -webkit-mask: url("data:image/svg+xml;utf8,") center/contain no-repeat; + mask: url("data:image/svg+xml;utf8,") center/contain no-repeat; } -.form-actions .row-or::before { left: 0; } -.form-actions .row-or::after { right: 0; } -/* ============= Hero on home / play ============= */ -.hero-card { +/* --- Hamburger --- */ +.nav-toggle { + display: none; + width: 38px; height: 34px; + padding: 0; + border: var(--rule-strong); + border-radius: var(--r-sm); + background: transparent; + cursor: pointer; position: relative; - overflow: hidden; - padding: 36px; - display: flex; gap: 28px; align-items: center; - background: - linear-gradient(120deg, rgba(217,122,61,0.18), rgba(0,0,0,0.35)), - radial-gradient(ellipse at left, rgba(244,241,230,0.06), transparent 60%); + flex: 0 0 auto; } -.hero-card .hero-text { flex: 1; min-width: 0; } -.hero-card .hero-text h1 { margin-bottom: 8px; } -.hero-card .hero-art { - flex: 0 0 280px; - height: 180px; - border-radius: 12px; - background: url('../assets/screenshot-1945.png') center/cover no-repeat; - border: 2px dashed rgba(244,241,230,0.55); - box-shadow: 0 10px 24px rgba(0,0,0,0.5); +.nav-toggle span, .nav-toggle::before, .nav-toggle::after { + content: ""; + position: absolute; + left: 9px; right: 9px; + height: 2px; + border-radius: 2px; + background: var(--chalk); + transition: transform .3s var(--ease), opacity .18s; } +.nav-toggle::before { top: 10px; } +.nav-toggle span { top: 16px; } +.nav-toggle::after { top: 22px; } +.topbar.menu-open .nav-toggle::before { transform: translateY(6px) rotate(45deg); } +.topbar.menu-open .nav-toggle span { opacity: 0; } +.topbar.menu-open .nav-toggle::after { transform: translateY(-6px) rotate(-45deg); } -/* Mode cards */ -.mode-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); - gap: 18px; - margin-top: 18px; + +/* ========================================================= + FOOTER + ========================================================= */ + +.site-footer { + margin-top: var(--sec); + padding: 26px 24px 38px; + border-top: var(--rule); + background: rgba(7,17,11,0.55); + color: var(--chalk-dim); + font-size: 0.88rem; } -.mode-card { - padding: 22px; - cursor: pointer; - transition: transform .2s ease, border-color .2s; +.site-footer .footer-inner { + max-width: var(--maxw); + margin: 0 auto; + display: flex; flex-wrap: wrap; gap: 14px 24px; align-items: center; } -.mode-card:hover { transform: translateY(-3px) rotate(-0.4deg); } -.mode-card h3 { margin: 0 0 6px; } -.mode-card .tag { - display: inline-block; - font-size: .85rem; - padding: 2px 10px; - border: 1.5px dashed var(--chalk-faded); - border-radius: 999px; +.site-footer .footer-links { display: flex; gap: 22px; flex-wrap: wrap; } +.site-footer a { color: var(--chalk-soft); - margin-bottom: 8px; + font-size: 0.88rem; + border-bottom-color: transparent; } -.mode-card.disabled { opacity: 0.65; cursor: not-allowed; } - -/* Section heading */ -.section-title { - display: flex; align-items: baseline; gap: 14px; margin: 36px 0 6px; +.site-footer a:hover { border-bottom-color: var(--accent); } +.site-footer .footer-meta { + margin-left: auto; + font-family: var(--font-stamp); + font-size: 0.72rem; + letter-spacing: 0.04em; + opacity: 0.75; } -.section-title h2 { margin: 0; } -.section-title .see-all { font-size: 1rem; } -/* Gallery */ -.gallery { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); - gap: 14px; - margin-top: 18px; -} -.gallery .shot { - position: relative; - height: 160px; + +/* ========================================================= + FORMS + ========================================================= */ + +input, select, textarea, button { font-family: inherit; font-size: inherit; } + +.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 15px; } +.field label { + font-family: var(--font-stamp); + font-size: 0.7rem; + letter-spacing: 0.09em; + text-transform: uppercase; + color: var(--chalk-dim); +} + +.field input, .field select, +.country-search, .settings-row select, .settings-row input[type="text"], +.chat-new-dm input, .chat-composer input, .text-input { + font-family: var(--font-body); + font-size: 0.98rem; + color: var(--chalk); + background: rgba(0,0,0,0.32); + border: var(--rule-strong); border-radius: 10px; - background-size: cover; - background-position: center; - border: 2px dashed rgba(244,241,230,0.5); - box-shadow: 0 6px 16px rgba(0,0,0,0.45); - transition: transform .2s; - cursor: zoom-in; + padding: 11px 14px; + outline: none; + width: 100%; + transition: border-color .18s, background .18s, box-shadow .18s; } -.gallery .shot:hover { transform: rotate(-0.6deg) scale(1.02); } -.gallery .shot.tall { height: 220px; } +.field input::placeholder, .text-input::placeholder, +.country-search::placeholder, .chat-composer input::placeholder { color: var(--chalk-ghost); } -/* Updates strip */ -.updates-strip { - display: flex; align-items: center; gap: 14px; - padding: 14px 20px; - margin-top: 12px; -} -.updates-strip .label { - font-family: 'Caveat', cursive; - font-size: 1.4rem; - color: var(--accent-soft); +.field input:focus, .field select:focus, +.country-search:focus, .settings-row select:focus, .settings-row input:focus, +.chat-new-dm input:focus, .chat-composer input:focus, .text-input:focus { + border-color: var(--accent); + background: rgba(0,0,0,0.44); + box-shadow: 0 0 0 3px rgba(217,122,61,0.2); } +/* :user-invalid, not :invalid β€” an untouched empty required field (the date + picker, "confirm password") is invalid from page load and shouldn't be + scolding anyone before they've typed. */ +.field input:user-invalid { border-color: var(--chalk-red); } +.field input:disabled, .chat-composer input:disabled { opacity: 0.5; cursor: not-allowed; } -/* Updates timeline */ -.timeline { display: flex; flex-direction: column; gap: 22px; margin-top: 18px; } -.update-entry { padding: 24px; } -.update-entry .meta { - display: flex; align-items: center; gap: 12px; margin-bottom: 8px; flex-wrap: wrap; +.checkbox { + display: flex; align-items: flex-start; gap: 10px; + cursor: pointer; + font-size: 0.92rem; + color: var(--chalk-soft); } -.update-entry .version { - font-family: 'Caveat', cursive; font-size: 1.5rem; - color: var(--chalk); padding: 2px 12px; - background: rgba(217,122,61,0.25); - border: 2px dashed var(--accent); - border-radius: 8px; -} -.update-entry .date { color: var(--chalk-faded); font-size: 1rem; } -.update-entry ul { padding-left: 22px; margin: 8px 0 0; } -.update-entry li { margin-bottom: 4px; } - -/* Terms */ -.tos-doc { max-width: 820px; margin: 0 auto; } -.tos-doc h2 { margin-top: 30px; } -.tos-doc h3 { - margin-top: 20px; - font-size: clamp(1.15rem, 1.7vw, 1.4rem); - color: var(--accent-soft); +.checkbox input { appearance: none; -webkit-appearance: none; margin: 0; } +.checkbox .box { + width: 21px; height: 21px; flex: 0 0 21px; + margin-top: 1px; + border: var(--rule-strong); + border-radius: 5px; + display: inline-flex; align-items: center; justify-content: center; + transition: background .15s, border-color .15s; } -.tos-doc .placeholder { font-style: italic; color: var(--chalk-faded); } -.tos-doc p, .tos-doc li { max-width: none; } -.tos-doc ul { padding-left: 22px; margin: 8px 0 0; } -.tos-doc ul li { margin-bottom: 6px; } - -/* Effective-date / lead line under the Terms title */ -.tos-doc .tos-meta { - display: flex; flex-wrap: wrap; gap: 6px 16px; - margin: 0 0 6px; color: var(--chalk-faded); +.checkbox input:checked + .box { background: var(--accent); border-color: var(--accent-soft); } +.checkbox input:checked + .box::after { + content: ""; + width: 11px; height: 6px; + border-left: 2.5px solid var(--board-ink); + border-bottom: 2.5px solid var(--board-ink); + transform: rotate(-45deg) translate(1px, -1px); } +.checkbox input:focus-visible + .box { outline: 2px solid var(--accent); outline-offset: 2px; } -/* In-page table of contents */ -.tos-toc { - margin-top: 18px; - padding: 16px 20px; +/* Segmented controls β€” auth tabs, country tabs, tier switch */ +.auth-tabs, .country-tabs, .tier-switch { + display: flex; + gap: 4px; + padding: 4px; + border: var(--rule); + border-radius: 12px; + background: rgba(0,0,0,0.28); + margin-bottom: 18px; } -.tos-toc h2 { margin: 0 0 8px; font-size: 1.5rem; } -.tos-toc ol { - columns: 2; column-gap: 28px; - padding-left: 20px; margin: 0; +.auth-tabs button, .country-tabs button, .tier-switch button { + flex: 1; + padding: 9px 12px; + border: 1px solid transparent; + border-radius: 9px; + background: transparent; + font-family: var(--font-body); + font-weight: 600; + font-size: 0.92rem; + color: var(--chalk-dim); + cursor: pointer; + transition: background .18s var(--ease), color .18s, border-color .18s; } -.tos-toc li { margin-bottom: 4px; break-inside: avoid; } -@media (max-width: 560px) { .tos-toc ol { columns: 1; } } - -/* Highlighted legal callout (e.g. GDPR note) */ -.tos-doc .legal-note { - margin-top: 26px; - padding: 16px 20px; - border: 2px dashed var(--accent); - border-radius: 10px; - background: rgba(217,122,61,0.10); +.auth-tabs button:hover, .country-tabs button:hover, .tier-switch button:hover { + color: var(--chalk); + background: rgba(244,241,230,0.06); } -.tos-doc .legal-note .legal-tag { - display: inline-block; - font-family: 'Caveat', cursive; - font-size: 1.3rem; - color: var(--accent-soft); - margin-bottom: 4px; +.auth-tabs button.active, .country-tabs button.active, .tier-switch button.active { + color: var(--chalk); + background: rgba(244,241,230,0.11); + border-color: rgba(244,241,230,0.2); + box-shadow: 0 2px 8px -4px #000; } - -/* About page */ -.about-hero { - text-align: center; padding: 40px 24px 28px; +.tier-switch { margin: 8px 0 0; } +.tier-switch button[data-tier="emperor"].active { + background: linear-gradient(135deg, rgba(240,198,97,0.28), rgba(217,122,61,0.28)); + border-color: var(--chalk-gold); + color: #ffeec2; } -.about-hero h1 { font-size: clamp(2.6rem, 6vw, 4rem); } -.about-grid { - display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); - gap: 18px; margin-top: 20px; + +.form-actions { display: flex; flex-direction: column; gap: 11px; margin-top: 4px; } +.form-actions .btn { width: 100%; } +.form-actions .row-or { + position: relative; + text-align: center; + font-family: var(--font-stamp); + font-size: 0.64rem; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--chalk-dim); + margin: 2px 0; +} +.form-actions .row-or::before, .form-actions .row-or::after { + content: ""; + position: absolute; top: 50%; + width: calc(50% - 26px); height: 1px; + background: rgba(244,241,230,0.16); } +.form-actions .row-or::before { left: 0; } +.form-actions .row-or::after { right: 0; } -/* Play page */ -.play-screen { - min-height: calc(100vh - 100px); - display: flex; flex-direction: column; - align-items: center; justify-content: center; - text-align: center; gap: 24px; - padding: 40px 24px; +/* Toggle */ +.toggle { position: relative; width: 48px; height: 26px; display: inline-block; flex: 0 0 auto; } +.toggle input { opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; } +.toggle .track { + position: absolute; inset: 0; + background: rgba(0,0,0,0.5); + border: var(--rule-strong); + border-radius: 999px; + transition: background .2s, border-color .2s; +} +.toggle .thumb { + position: absolute; top: 3px; left: 3px; + width: 18px; height: 18px; + background: var(--chalk-dim); + border-radius: 50%; + transition: transform .26s var(--ease), background .2s; } -.play-screen h1 { font-size: clamp(2.5rem, 6vw, 4.5rem); margin-bottom: 0; } -.play-screen .subtitle { font-size: 1.25rem; color: var(--chalk-faded); } +.toggle input:checked + .track { background: rgba(217,122,61,0.4); border-color: var(--accent); } +.toggle input:checked + .track + .thumb { transform: translateX(22px); background: var(--accent-soft); } +.toggle input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 3px; } -/* Toast */ -.toast { - position: fixed; left: 50%; bottom: 30px; transform: translateX(-50%); - background: rgba(0,0,0,0.85); - color: var(--chalk); - font-family: 'Patrick Hand', cursive; - font-size: 1.05rem; - padding: 12px 22px; - border: 2px dashed var(--chalk); - border-radius: 10px; - z-index: var(--z-toast); - opacity: 0; pointer-events: none; - transition: opacity .25s ease, transform .25s ease; -} -.toast.show { opacity: 1; transform: translateX(-50%) translateY(-6px); } - -/* ============= Responsive ============= */ -@media (max-width: 760px) { - body { font-size: 17px; } - .topbar .inner { padding: 8px 12px; gap: 6px; } - .topbar nav { display: none; } - .topbar.mobile-open nav { - display: flex; flex-direction: column; align-items: flex-start; - position: absolute; top: 100%; left: 0; right: 0; - padding: 12px 16px; - background: rgba(10,22,15,0.97); - border-bottom: 2px dashed rgba(244,241,230,0.25); - } - .nav-toggle { display: inline-flex !important; } - /* Tighten the right cluster β€” much smaller chips + icon button */ - .topbar .topbar-left { gap: 8px; } - .topbar .topbar-right { gap: 6px; } - .topbar .topbar-right::before { display: none; } +/* ========================================================= + AUTH LANDING + ========================================================= */ - .topbar .brand img { width: 32px; height: 32px; } - .topbar .brand .brand-name { font-size: 1.2rem; } +.auth-wrap { + display: grid; + grid-template-columns: 1fr 460px; + align-items: center; + gap: clamp(28px, 6vw, 76px); + padding: 48px 24px 40px; + max-width: 1080px; +} - .coin-chip { - padding: 3px 8px; - font-size: 0.85rem; - border-width: 1.5px; - box-shadow: 0 2px 0 rgba(0,0,0,0.3); - } - .coin-chip .coin { width: 14px; height: 14px; } - .coin-chip .soon { display: none; } +.auth-pitch { max-width: 520px; } +.auth-logo { + width: clamp(230px, 26vw, 340px); + display: block; + margin: 0 0 6px -6px; + filter: drop-shadow(0 12px 26px rgba(0,0,0,0.6)); + user-select: none; +} +.auth-tagline { + font-family: var(--font-display); + font-size: clamp(1.5rem, 2.6vw, 2.05rem); + color: var(--chalk); + margin: 0 0 22px; + line-height: 1.2; +} +.auth-facts { + list-style: none; + padding: 0; + margin: 22px 0 0; + display: flex; + flex-direction: column; + gap: 11px; + border-top: var(--rule); + padding-top: 20px; +} +.auth-facts li { + display: flex; + align-items: flex-start; + gap: 12px; + color: var(--chalk-soft); + font-size: 0.95rem; +} +.auth-facts svg { + width: 19px; height: 19px; + flex: 0 0 19px; + margin-top: 2px; + color: var(--accent-soft); +} +.auth-facts strong { display: block; color: var(--chalk); font-weight: 600; } - .user-chip { - padding: 3px 8px; - gap: 6px; - border-width: 1.5px; - } - .user-chip .avatar { - width: 22px; height: 22px; - font-size: 0.75rem; - } - .user-chip .avatar.countryball { width: 24px; height: 24px; } - .user-block .name { font-size: 0.95rem; } - .tier-badge { font-size: 0.75rem; padding: 0 6px; } - - /* The settings gear was 38Γ—38 on desktop β€” way too much on mobile. */ - .btn-icon { - width: 30px; height: 30px; - border-width: 1.5px; - } - .btn-icon svg { width: 14px; height: 14px; } +.auth-card { width: 100%; padding: 30px 28px; } +.auth-card h2 { font-size: 1.9rem; } +.auth-panel[hidden] { display: none; } - .hero-card { flex-direction: column; padding: 24px; } - .hero-card .hero-art { width: 100%; flex: none; } - .auth-card { padding: 20px; } - .btn-huge { font-size: 2rem; padding: 22px 48px; } - .site-footer .footer-inner { flex-direction: column; align-items: flex-start; gap: 8px; } - .site-footer .footer-meta { margin-left: 0; } +.auth-shot { + margin-top: 26px; + border: var(--rule-strong); + border-radius: var(--r); + overflow: hidden; + box-shadow: var(--lift-2); + aspect-ratio: 16 / 8; + background: url('../assets/screenshot-1945.png') center/cover no-repeat; + position: relative; } - -/* Even tighter for very narrow screens */ -@media (max-width: 420px) { - .topbar .inner { padding: 6px 10px; gap: 4px; } - .topbar .brand .brand-name { display: none; } - .coin-chip { padding: 2px 7px; } - .user-block .name { max-width: 80px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.auth-shot::after { + content: ""; + position: absolute; inset: 0; + background: linear-gradient(180deg, transparent 40%, rgba(7,17,11,0.75)); } -.nav-toggle { - display: none; - background: transparent; - color: var(--chalk); - border: 2px dashed var(--chalk); - border-radius: 8px; - padding: 4px 10px; - font-family: 'Caveat', cursive; - font-size: 1.2rem; - cursor: pointer; +@media (max-width: 900px) { + .auth-wrap { + grid-template-columns: 1fr; + justify-items: center; + text-align: center; + padding-top: 34px; + } + .auth-pitch { max-width: 560px; } + .auth-logo { margin: 0 auto 6px; } + .auth-facts { text-align: left; } + .auth-shot { display: none; } + .auth-card { max-width: 460px; } } -/* ============================================================ - POLISH LAYER β€” micro-interactions, hover states, scroll fades - ============================================================ */ -/* Cards: lift + soft glow on every chalk-card by default - (mode-card, about-grid items, update entries all inherit this) */ -.chalk-card { - transition: transform .25s cubic-bezier(.2,.7,.2,1), - box-shadow .25s ease, - border-color .25s ease; - will-change: transform; -} -.chalk-card.interactive, -a.chalk-card, -button.chalk-card { +/* ========================================================= + HERO + ========================================================= */ + +.hero-card { + display: grid; + grid-template-columns: 1fr 300px; + gap: 30px; + align-items: center; + padding: 34px; + overflow: hidden; + background: + linear-gradient(115deg, rgba(217,122,61,0.16), rgba(0,0,0,0.28) 55%), + linear-gradient(180deg, rgba(244,241,230,0.05), rgba(0,0,0,0.24)), + rgba(10,22,15,0.4); +} +.hero-card .hero-text { min-width: 0; } +.hero-card .hero-text h1 { margin-bottom: 10px; } +.hero-card .hero-art { + display: block; + height: 178px; + border: var(--rule-strong); + border-bottom: none; + border-radius: var(--r); + background: url('../assets/screenshot-1945.png') center/cover no-repeat; + box-shadow: var(--lift-2); cursor: pointer; + transition: transform .35s var(--ease), box-shadow .35s var(--ease); } -.chalk-card.interactive:hover, -a.chalk-card:hover, -button.chalk-card:hover, -.mode-card:not(.disabled):hover, -.about-grid .chalk-card:hover, -.update-entry:hover { - transform: translateY(-4px) rotate(-0.35deg); - box-shadow: - 0 0 0 2px rgba(244,241,230,0.10), - 0 18px 40px rgba(0,0,0,0.55), - 0 0 24px rgba(217,122,61,0.18); -} -.chalk-card.interactive:hover::before, -a.chalk-card:hover::before, -.mode-card:not(.disabled):hover::before, -.about-grid .chalk-card:hover::before, -.update-entry:hover::before { - border-color: var(--accent); - animation: chalk-jitter 0.5s ease-in-out; +.hero-card .hero-art:hover { + transform: scale(1.025) rotate(-0.8deg); + box-shadow: var(--lift-3); } -@keyframes chalk-jitter { - 0%, 100% { transform: rotate(0); } - 25% { transform: rotate(0.4deg); } - 75% { transform: rotate(-0.3deg); } + +/* The tray the chalk actually sits in. Used once per page, under the hero. */ +.chalk-tray { + position: relative; + height: 15px; + margin: -1px auto 0; + max-width: calc(100% - 26px); + border-radius: 0 0 9px 9px; + background: linear-gradient(180deg, var(--wood-1) 0%, #56361b 45%, var(--wood-2) 100%); + box-shadow: 0 7px 16px -8px rgba(0,0,0,0.9), inset 0 1px 0 rgba(255,220,180,0.18); +} +.chalk-tray::before { + content: ""; + position: absolute; + left: 34px; top: -5px; + width: 52px; height: 7px; + border-radius: 3px; + background: linear-gradient(180deg, #fdfaf0, #cfc9b4); + box-shadow: 0 1px 2px rgba(0,0,0,0.5); + transform: rotate(-0.7deg); +} +.chalk-tray::after { + content: ""; + position: absolute; + right: 40px; top: -7px; + width: 34px; height: 9px; + border-radius: 2px; + background: linear-gradient(180deg, #5d6a76, #38424c); + box-shadow: 0 1px 2px rgba(0,0,0,0.5); + transform: rotate(0.6deg); } -/* Active press */ -.chalk-card.interactive:active, -a.chalk-card:active, -.mode-card:not(.disabled):active { - transform: translateY(-1px) rotate(0); - transition-duration: .08s; +@media (max-width: 780px) { + .hero-card { grid-template-columns: 1fr; padding: 24px; } + .hero-card .hero-art { height: 150px; } + .chalk-tray::after { display: none; } } -/* Mode card title underline animation */ -.mode-card h3 { - display: inline-block; + +/* ========================================================= + MODE CARDS + ========================================================= */ + +.mode-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); + gap: 16px; + margin-top: 20px; +} + +.chalk-card.mode-card { position: relative; + padding: 22px; + display: flex; + flex-direction: column; + gap: 7px; + overflow: hidden; } +.mode-card .mode-era { + font-family: var(--font-stamp); + font-size: 0.62rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--accent-soft); + order: -1; +} +.mode-card h3 { margin: 0; position: relative; align-self: flex-start; } .mode-card h3::after { content: ""; position: absolute; - left: 0; right: 100%; bottom: -2px; - height: 2px; + left: 0; bottom: -3px; + height: 2px; width: 100%; background: var(--accent); - transition: right .35s cubic-bezier(.2,.7,.2,1); border-radius: 2px; + transform: scaleX(0); + transform-origin: left center; + transition: transform .38s var(--ease); } -.mode-card:not(.disabled):hover h3::after { right: 0; } +.mode-card:not(.disabled):hover h3::after { transform: scaleX(1); } +.mode-card p { margin: 0; font-size: 0.94rem; color: var(--chalk-soft); } -/* About-grid icons */ -.about-grid .chalk-card { - position: relative; - overflow: hidden; -} -.about-grid .chalk-card::after { - content: ""; +.mode-card.disabled { cursor: not-allowed; } +.mode-card.disabled h3, .mode-card.disabled p { color: var(--chalk-dim); } +.mode-card.disabled .mode-era { color: var(--chalk-dim); } +.mode-card .mode-flag { position: absolute; - right: -30px; top: -30px; - width: 120px; height: 120px; - background: radial-gradient(circle at center, rgba(217,122,61,0.18), transparent 65%); - opacity: 0; - transition: opacity .35s ease, transform .5s ease; - pointer-events: none; + top: 14px; right: 14px; + font-family: var(--font-stamp); + font-size: 0.58rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--chalk-dim); + border: 1px dashed rgba(244,241,230,0.35); + border-radius: 3px; + padding: 1px 7px; + transform: rotate(3deg); } -.about-grid .chalk-card:hover::after { - opacity: 1; - transform: scale(1.15) rotate(15deg); + + +/* ========================================================= + FEATURE GRID (about / play) + ========================================================= */ + +/* Capped at three so the feature sets stay balanced: Play's trio fills one + row, About's six read as 3 + 3 rather than a stranded 4 + 2. */ +.about-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 16px; + margin-top: 20px; } +.about-grid .chalk-card { padding: 22px; } .about-grid h3 { - display: flex; align-items: center; gap: 10px; + display: flex; + align-items: center; + gap: 11px; + font-size: 1.35rem; + margin: 0 0 8px; } .about-grid h3 .ico { - display: inline-flex; align-items: center; justify-content: center; + display: inline-flex; + align-items: center; justify-content: center; width: 34px; height: 34px; - border: 2px dashed var(--accent); - border-radius: 8px; + flex: 0 0 34px; + border: var(--rule-strong); + border-radius: 9px; color: var(--accent-soft); - font-size: 1.2rem; - transition: transform .3s ease, background .3s ease; + background: rgba(217,122,61,0.09); + transition: transform .3s var(--ease), background .3s, border-color .3s; } +.about-grid h3 .ico svg { width: 18px; height: 18px; } .about-grid .chalk-card:hover h3 .ico { - transform: rotate(-8deg) scale(1.1); - background: rgba(217,122,61,0.15); + transform: rotate(-7deg); + background: rgba(217,122,61,0.2); + border-color: var(--accent); } +.about-grid p { margin: 0; font-size: 0.94rem; } -/* Buttons β€” subtle hover wobble + glow */ -.btn-primary { - position: relative; -} -.btn-primary::after { - content: ""; - position: absolute; - inset: -6px; - border-radius: 14px; - background: radial-gradient(circle, rgba(217,122,61,0.35), transparent 70%); - opacity: 0; - transition: opacity .3s ease; - z-index: -1; - pointer-events: none; -} -.btn-primary:hover:not(:disabled)::after { opacity: 1; } +.about-hero { text-align: center; padding: 46px 24px 12px; } +.about-hero p { margin-left: auto; margin-right: auto; } -/* Footer link hover β€” chalk underline grow */ -.site-footer a, -.topbar nav a { - position: relative; - border-bottom: none; -} -.site-footer a::after, -.topbar nav a::after { - content: ""; - position: absolute; - left: 8px; right: 8px; - bottom: 0; - height: 2px; - background-image: linear-gradient(to right, var(--chalk) 60%, transparent 60%); - background-size: 8px 2px; - transform: scaleX(0); - transform-origin: left center; - transition: transform .3s cubic-bezier(.2,.7,.2,1); -} -.site-footer a:hover::after, -.topbar nav a:hover::after, -.topbar nav a.active::after { transform: scaleX(1); } -.topbar nav a.active::after { background-image: linear-gradient(to right, var(--accent) 60%, transparent 60%); } -/* Logo subtle float in topbar */ -.topbar .brand img { - transition: transform .35s ease; +/* ========================================================= + UPDATES + ========================================================= */ + +.updates-strip { + display: flex; + align-items: center; + gap: 16px; + padding: 15px 20px; + margin-top: 18px; + border-left: 3px solid var(--accent); + text-decoration: none; + flex-wrap: wrap; } -.topbar .brand:hover img { - transform: rotate(-6deg) scale(1.08); +.updates-strip .label { + font-family: var(--font-stamp); + font-size: 0.78rem; + letter-spacing: 0.06em; + color: var(--accent-soft); } +.updates-strip .muted { font-size: 0.93rem; } -/* Auth logo gentle breathing */ -.auth-logo { - animation: breathe 6s ease-in-out infinite; +.timeline { display: flex; flex-direction: column; gap: 18px; margin-top: 20px; } +.update-entry { padding: 24px; border-left: 3px solid rgba(217,122,61,0.55); } +.update-entry .meta { + display: flex; align-items: center; gap: 12px; flex-wrap: wrap; + margin-bottom: 6px; } -@keyframes breathe { - 0%, 100% { transform: translateY(0) rotate(0); } - 50% { transform: translateY(-4px) rotate(-0.4deg); } +.update-entry .version { + color: var(--accent-soft); + border: 1px solid rgba(217,122,61,0.5); + background: rgba(217,122,61,0.12); + border-radius: 4px; + padding: 1px 9px; + font-size: 0.72rem; } +.update-entry .date { color: var(--chalk-dim); font-size: 0.68rem; } +.update-entry .meta .muted { font-size: 0.86rem; text-transform: none; letter-spacing: 0; } +.update-entry h2 { font-size: 1.7rem; margin: 0 0 8px; } +.update-entry ul { padding-left: 20px; margin: 10px 0 0; } +.update-entry li { margin-bottom: 5px; font-size: 0.95rem; } +.update-entry li::marker { color: var(--accent); } -/* Input focus shimmer */ -.field input:focus, .field select:focus { - box-shadow: 0 0 0 3px rgba(217,122,61,0.25); -} -/* Reveal-on-scroll */ -.reveal { - opacity: 0; - transform: translateY(20px); - transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.2,1); -} -.reveal.in { - opacity: 1; - transform: translateY(0); -} -.reveal.delay-1 { transition-delay: .08s; } -.reveal.delay-2 { transition-delay: .16s; } -.reveal.delay-3 { transition-delay: .24s; } -.reveal.delay-4 { transition-delay: .32s; } +/* ========================================================= + PREVIEW SHOWCASE + ========================================================= */ -/* ============================================================ - PREVIEW FOOTAGE SHOWCASE - ============================================================ */ .preview-showcase { - position: relative; display: grid; - grid-template-columns: 1fr 280px; - gap: 20px; - padding: 22px; - margin-top: 18px; + grid-template-columns: 1fr 250px; + gap: 18px; + padding: 18px; + margin-top: 20px; } .preview-stage { position: relative; aspect-ratio: 16 / 9; - border-radius: 12px; + border-radius: var(--r); overflow: hidden; background: #000; - border: 2px dashed rgba(244,241,230,0.55); - box-shadow: 0 14px 36px rgba(0,0,0,0.55), inset 0 0 0 1px rgba(0,0,0,0.5); + border: var(--rule-strong); + box-shadow: var(--lift-2); } .preview-stage .slide { - position: absolute; - inset: 0; - background-size: cover; - background-position: center; + position: absolute; inset: 0; + background-size: cover; background-position: center; opacity: 0; - transform: scale(1.04); - transition: opacity .6s ease, transform 6s ease-out; -} -.preview-stage .slide.active { - opacity: 1; - transform: scale(1.0); + transform: scale(1.05); + transition: opacity .6s ease, transform 6.5s ease-out; } +.preview-stage .slide.active { opacity: 1; transform: scale(1); } + .preview-stage .stage-overlay { - position: absolute; - left: 0; right: 0; bottom: 0; - padding: 18px 20px; - background: linear-gradient(180deg, transparent, rgba(0,0,0,0.85)); - color: var(--chalk); + position: absolute; left: 0; right: 0; bottom: 0; + padding: 30px 20px 16px; + background: linear-gradient(180deg, transparent, rgba(0,0,0,0.88)); pointer-events: none; } .preview-stage .stage-overlay .caption { - font-family: 'Caveat', cursive; - font-size: 1.6rem; + font-family: var(--font-display); + font-size: 1.55rem; + color: var(--chalk); + margin: 0 0 2px; line-height: 1.1; - margin: 0 0 4px; - text-shadow: 0 2px 6px rgba(0,0,0,0.8); + text-shadow: 0 2px 8px rgba(0,0,0,0.9); } .preview-stage .stage-overlay .sub { - font-size: 1rem; + margin: 0; + font-size: 0.85rem; color: var(--chalk-soft); - opacity: 0.9; } .preview-stage .tag-live { - position: absolute; - top: 12px; left: 12px; + position: absolute; top: 12px; left: 12px; + font-family: var(--font-stamp); + font-size: 0.62rem; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--board-ink); background: var(--accent); - color: var(--board-3); - padding: 4px 10px; - border-radius: 6px; - font-family: 'Caveat', cursive; - font-weight: 700; - font-size: 1rem; - border: 2px solid var(--chalk); + padding: 3px 9px; + border-radius: 4px; pointer-events: none; } .preview-stage .stage-nav { position: absolute; - top: 50%; transform: translateY(-50%); - width: 40px; height: 40px; - background: rgba(15,32,24,0.7); - border: 2px dashed var(--chalk); - color: var(--chalk); + top: 50%; + width: 38px; height: 38px; + transform: translateY(-50%); + border: var(--rule-strong); border-radius: 50%; + background: rgba(7,17,11,0.78); + backdrop-filter: blur(4px); + color: var(--chalk); + font-size: 1.3rem; + line-height: 1; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; - font-family: 'Caveat', cursive; - font-size: 1.6rem; - font-weight: 700; opacity: 0; - transition: opacity .25s ease, background .2s, transform .2s; + transition: opacity .25s, background .18s, transform .18s; z-index: 3; } -.preview-stage:hover .stage-nav { opacity: 1; } -.preview-stage .stage-nav:hover { background: var(--accent); color: var(--board-3); transform: translateY(-50%) scale(1.08); } +.preview-stage:hover .stage-nav, +.preview-stage:focus-within .stage-nav { opacity: 1; } +.preview-stage .stage-nav:hover { + background: var(--accent); + color: var(--board-ink); + transform: translateY(-50%) scale(1.08); +} .preview-stage .stage-nav.prev { left: 12px; } .preview-stage .stage-nav.next { right: 12px; } +.preview-progress { + position: absolute; left: 0; right: 0; bottom: 0; + height: 3px; + background: rgba(0,0,0,0.5); + z-index: 2; +} +.preview-progress .bar { + height: 100%; width: 0; + background: var(--accent); + transition: width 80ms linear; +} + .preview-thumbs { - display: flex; - flex-direction: column; - gap: 10px; + display: flex; flex-direction: column; gap: 9px; max-height: 100%; overflow-y: auto; padding-right: 4px; @@ -1081,1313 +1423,895 @@ a.chalk-card:active, .preview-thumbs .thumb { position: relative; flex: 0 0 auto; - height: 70px; - border-radius: 8px; - border: 2px dashed rgba(244,241,230,0.35); - background-size: cover; - background-position: center; + height: 64px; + border-radius: var(--r-sm); + border: var(--rule); + background-size: cover; background-position: center; cursor: pointer; - transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease; overflow: hidden; + transition: transform .2s var(--ease), border-color .2s, box-shadow .2s; } .preview-thumbs .thumb::after { content: ""; position: absolute; inset: 0; - background: rgba(0,0,0,0.35); - transition: background .2s ease; + background: rgba(0,0,0,0.5); + transition: background .2s; } -.preview-thumbs .thumb:hover { transform: translateX(-4px); border-color: var(--chalk); } -.preview-thumbs .thumb:hover::after { background: rgba(0,0,0,0.1); } +.preview-thumbs .thumb:hover { border-color: rgba(244,241,230,0.4); transform: translateX(-3px); } +.preview-thumbs .thumb:hover::after { background: rgba(0,0,0,0.18); } .preview-thumbs .thumb.active { border-color: var(--accent); - border-style: solid; - box-shadow: 0 0 0 2px rgba(217,122,61,0.35), 0 8px 18px rgba(0,0,0,0.5); - transform: translateX(-6px); + box-shadow: 0 0 0 1px var(--accent), var(--lift-1); + transform: translateX(-5px); } -.preview-thumbs .thumb.active::after { background: transparent; } +.preview-thumbs .thumb.active::after { background: rgba(0,0,0,0.05); } .preview-thumbs .thumb .label { - position: absolute; left: 8px; bottom: 6px; right: 8px; - font-family: 'Caveat', cursive; - font-size: 1rem; - color: var(--chalk); - text-shadow: 0 1px 3px rgba(0,0,0,0.9); + position: absolute; left: 9px; right: 9px; bottom: 6px; z-index: 2; + font-family: var(--font-stamp); + font-size: 0.62rem; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--chalk); + text-shadow: 0 1px 4px rgba(0,0,0,1); } +.preview-thumbs::-webkit-scrollbar { width: 6px; height: 6px; } +.preview-thumbs::-webkit-scrollbar-thumb { background: rgba(244,241,230,0.2); border-radius: 6px; } -.preview-progress { - position: absolute; - left: 0; right: 0; bottom: 0; - height: 3px; - background: rgba(0,0,0,0.4); - z-index: 2; +@media (max-width: 880px) { + .preview-showcase { grid-template-columns: 1fr; } + .preview-thumbs { flex-direction: row; overflow-x: auto; padding-bottom: 6px; } + .preview-thumbs .thumb { flex: 0 0 132px; height: 74px; } + .preview-thumbs .thumb:hover, .preview-thumbs .thumb.active { transform: translateY(-3px); } } -.preview-progress .bar { - height: 100%; - width: 0%; - background: var(--accent); - transition: width 80ms linear; + + +/* ========================================================= + PLAY + ========================================================= */ + +/* Launch panel β€” the copy holds one side, the actual board holds the other. + A single centred button in an empty card is a poster, not a game page. */ +.launch-panel { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); + align-items: stretch; + padding: 0; + margin-top: 26px; + overflow: hidden; } -/* Lightbox */ -.lightbox { - position: fixed; inset: 0; - background: rgba(10,22,15,0.94); - z-index: var(--z-overlay); - display: flex; align-items: center; justify-content: center; - cursor: zoom-out; - animation: fade-in .25s ease; +.launch-copy { + padding: clamp(28px, 3.4vw, 48px); + display: flex; + flex-direction: column; + justify-content: center; + min-width: 0; } -.lightbox img { - max-width: 92vw; - max-height: 88vh; - border: 2px dashed var(--chalk); - border-radius: 10px; - box-shadow: 0 20px 60px rgba(0,0,0,0.7); +.launch-copy h1 { + margin: 0 0 12px; + font-size: clamp(2.4rem, 4.2vw, 3.5rem); } -.lightbox .close { - position: absolute; - top: 18px; right: 22px; - width: 44px; height: 44px; - display: inline-flex; align-items: center; justify-content: center; - border: 2px dashed var(--chalk); - border-radius: 50%; - background: transparent; - color: var(--chalk); - cursor: pointer; - font-family: 'Caveat', cursive; - font-size: 1.6rem; +.launch-copy .lede { + font-size: 1.04rem; + color: var(--chalk-soft); + max-width: 40ch; + margin: 0 0 28px; } -.lightbox .close:hover { background: var(--chalk); color: var(--board-3); } -@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } -/* Make hero art look photo-framed and clickable */ -.hero-card .hero-art { - cursor: pointer; - transition: transform .35s ease, box-shadow .35s ease; +.launch-actions { + display: flex; + align-items: center; + gap: 16px; + flex-wrap: wrap; } -.hero-card .hero-art:hover { - transform: rotate(-1.2deg) scale(1.02); - box-shadow: 0 16px 38px rgba(0,0,0,0.6); +.btn-launch { + font-size: 1.12rem; + padding: 15px 34px; + border-radius: 12px; } - -/* Preview responsive */ -@media (max-width: 860px) { - .preview-showcase { - grid-template-columns: 1fr; - } - .preview-thumbs { - flex-direction: row; - overflow-x: auto; - overflow-y: hidden; - padding-bottom: 6px; - } - .preview-thumbs .thumb { - flex: 0 0 140px; - height: 80px; - } - .preview-thumbs .thumb:hover, - .preview-thumbs .thumb.active { - transform: translateY(-4px); - } +.btn-launch svg { width: 19px; height: 19px; } +.launch-note { + font-family: var(--font-stamp); + font-size: 0.66rem; + letter-spacing: 0.06em; + color: var(--chalk-dim); } -/* ============================================================ - STORE / MARKETPLACE - ============================================================ */ -.store-grid { +/* Spec list, not a marketing stat bar */ +.launch-spec { display: grid; - grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); - gap: 18px; - margin-top: 18px; -} -.store-item { - position: relative; - padding: 18px; - display: flex; flex-direction: column; gap: 10px; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 15px 28px; + margin: 30px 0 0; + padding-top: 22px; + border-top: var(--rule); +} +.launch-spec div { min-width: 0; } +.launch-spec dt { + font-family: var(--font-stamp); + font-size: 0.6rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--chalk-dim); + margin-bottom: 3px; +} +.launch-spec dd { + margin: 0; + font-size: 0.95rem; + font-weight: 600; + color: var(--chalk); } -.store-item .thumb { + +/* The board itself, bled to the card edge */ +.launch-plate { position: relative; - height: 130px; - border-radius: 10px; - border: 2px dashed rgba(244,241,230,0.45); - background: linear-gradient(160deg, rgba(217,122,61,0.18), rgba(0,0,0,0.35)); - display: flex; align-items: center; justify-content: center; + min-height: 380px; overflow: hidden; } -.store-item .thumb svg { width: 78%; height: 78%; } -.store-item h3 { - font-family: 'Caveat', cursive; - margin: 0; - font-size: 1.5rem; +.launch-plate img { + position: absolute; + inset: 0; + width: 100%; height: 100%; + object-fit: cover; + object-position: 60% center; } -.store-item p { - font-size: 1rem; - margin: 0; - color: var(--chalk-soft); - min-height: 2.6em; +/* Fade the inner edge into the board so the plate reads as part of the card + rather than a screenshot pasted on top of it. */ +.launch-plate::before { + content: ""; + position: absolute; inset: 0; z-index: 1; + background: linear-gradient(90deg, + rgba(10,22,15,0.97) 0%, + rgba(10,22,15,0.55) 20%, + rgba(10,22,15,0) 52%); } -.store-item .row-bottom { - display: flex; align-items: center; justify-content: space-between; gap: 8px; - margin-top: auto; +.launch-plate::after { + content: ""; + position: absolute; inset: 0; z-index: 1; + background: linear-gradient(0deg, rgba(7,17,11,0.65), transparent 42%); } -.lock-badge { - display: inline-flex; align-items: center; gap: 6px; - background: rgba(0,0,0,0.45); - border: 1.5px dashed var(--chalk-faded); +.plate-caption { + position: absolute; + right: 16px; bottom: 13px; z-index: 2; + font-family: var(--font-stamp); + font-size: 0.62rem; + letter-spacing: 0.1em; + text-transform: uppercase; color: var(--chalk-soft); - font-family: 'Caveat', cursive; - font-size: 1rem; - padding: 3px 10px; - border-radius: 999px; + text-shadow: 0 1px 5px rgba(0,0,0,0.95); } -.lock-badge::before { - content: ""; - width: 12px; height: 14px; - background: currentColor; - -webkit-mask: url("data:image/svg+xml;utf8,") center/contain no-repeat; - mask: url("data:image/svg+xml;utf8,") center/contain no-repeat; - display: inline-block; -} -.price-pill { - display: inline-flex; align-items: center; gap: 6px; - font-family: 'Caveat', cursive; - font-size: 1.1rem; - color: var(--chalk-faded); - padding: 4px 10px; - border: 1.5px dashed var(--chalk-faded); - border-radius: 999px; + +@media (max-width: 900px) { + .launch-panel { grid-template-columns: 1fr; } + .launch-plate { + order: -1; + min-height: 0; + aspect-ratio: 16 / 8; + } + .launch-plate::before { + background: linear-gradient(0deg, rgba(10,22,15,0.95) 0%, rgba(10,22,15,0) 58%); + } } -.price-pill .coin { - display: inline-block; width: 14px; height: 14px; border-radius: 50%; - background: radial-gradient(circle at 35% 35%, #fff2b3, var(--accent) 60%, var(--accent-deep)); - border: 1.5px solid var(--board-3); +@media (max-width: 520px) { + .launch-spec { grid-template-columns: 1fr; gap: 13px; } } + + +/* ========================================================= + STORE + ========================================================= */ + .store-featured { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 18px; - margin-top: 18px; + gap: 16px; + margin-top: 20px; } .store-featured .featured-card { position: relative; padding: 24px; - min-height: 220px; + min-height: 218px; display: flex; flex-direction: column; gap: 10px; - background: - linear-gradient(135deg, rgba(217,122,61,0.28), rgba(0,0,0,0.45)), - radial-gradient(ellipse at top right, rgba(244,241,230,0.08), transparent 60%); overflow: hidden; + border: var(--sketch); + background: + linear-gradient(135deg, rgba(217,122,61,0.2), rgba(0,0,0,0.4)), + rgba(10,22,15,0.4); } +.store-featured .featured-card h3 { font-size: 1.6rem; margin: 0; } +.store-featured .featured-card p { font-size: 0.93rem; } .store-featured .featured-card .glyph { position: absolute; - right: -20px; bottom: -20px; - width: 180px; height: 180px; - opacity: .18; + right: -22px; bottom: -22px; + width: 172px; height: 172px; + opacity: 0.14; pointer-events: none; } -.store-featured .featured-card h3 { - font-family: 'Caveat', cursive; font-size: 1.9rem; margin: 0; + +.store-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(216px, 1fr)); + gap: 16px; + margin-top: 20px; +} +.store-item { + position: relative; + padding: 16px; + display: flex; flex-direction: column; gap: 10px; + border: var(--sketch); + background: rgba(0,0,0,0.2); } -.store-featured .featured-card .badge { - display: inline-block; - background: var(--accent); - color: var(--board-3); - font-family: 'Caveat', cursive; - font-weight: 700; - font-size: .9rem; - padding: 2px 10px; - border-radius: 6px; - border: 2px solid var(--chalk); - width: max-content; +.store-item .thumb { + height: 124px; + border-radius: var(--r-sm); + border: var(--rule); + background: + repeating-linear-gradient(-45deg, rgba(244,241,230,0.03) 0 9px, transparent 9px 18px), + linear-gradient(160deg, rgba(217,122,61,0.14), rgba(0,0,0,0.3)); + display: flex; align-items: center; justify-content: center; + overflow: hidden; +} +.store-item .thumb svg { width: 74%; height: 74%; } +.store-item h3 { margin: 0; font-size: 1.35rem; } +.store-item p { margin: 0; font-size: 0.88rem; color: var(--chalk-dim); min-height: 2.4em; } +.store-item .row-bottom { + display: flex; align-items: center; justify-content: space-between; + gap: 8px; margin-top: auto; } -/* ============================================================ + +/* ========================================================= MEMBERSHIP - ============================================================ */ + ========================================================= */ + .tier-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); - gap: 20px; - margin-top: 18px; + grid-template-columns: repeat(auto-fit, minmax(262px, 1fr)); + gap: 18px; + margin-top: 22px; align-items: stretch; } .tier-card { position: relative; - padding: 28px 26px; - display: flex; flex-direction: column; gap: 14px; + padding: 28px 24px; + display: flex; flex-direction: column; gap: 12px; overflow: hidden; } -.tier-card .tier-name { - font-family: 'Caveat', cursive; - font-size: 2.6rem; - margin: 0; - line-height: 1; -} -.tier-card .tier-tagline { - color: var(--chalk-faded); - font-size: 1.05rem; - margin: 0; -} +.tier-card .tier-name { font-size: 2.3rem; margin: 0; line-height: 1; } +.tier-card .tier-tagline { color: var(--chalk-dim); font-size: 0.94rem; margin: 0; } .tier-card .tier-price { - font-family: 'Caveat', cursive; - font-size: 2.2rem; + font-family: var(--font-display); + font-size: 2rem; color: var(--chalk); - margin: 6px 0 2px; + margin: 4px 0 0; line-height: 1; } .tier-card .tier-price small { display: block; - font-size: 1rem; - color: var(--chalk-faded); - margin-top: 4px; - font-family: 'Architects Daughter', cursive; + margin-top: 6px; + font-family: var(--font-stamp); + font-size: 0.64rem; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--chalk-dim); } .tier-card ul { list-style: none; - padding: 0; margin: 6px 0 0; - display: flex; flex-direction: column; gap: 8px; + padding: 0; + margin: 8px 0 0; + display: flex; flex-direction: column; gap: 9px; + border-top: var(--rule); + padding-top: 16px; } .tier-card ul li { position: relative; - padding-left: 28px; + padding-left: 26px; + font-size: 0.93rem; color: var(--chalk-soft); - font-size: 1rem; } .tier-card ul li::before { content: ""; - position: absolute; left: 0; top: 4px; - width: 18px; height: 18px; - background: var(--accent); - border-radius: 50%; - border: 2px dashed var(--chalk); - box-sizing: border-box; -} -.tier-card ul li::after { - content: "βœ“"; - position: absolute; left: 3px; top: 1px; - font-family: 'Caveat', cursive; - color: var(--board-3); - font-weight: 700; - font-size: 14px; - line-height: 1.2; + position: absolute; left: 0; top: 7px; + width: 11px; height: 6px; + border-left: 2px solid var(--accent); + border-bottom: 2px solid var(--accent); + transform: rotate(-45deg); +} +.tier-card ul li.muted-perk { color: var(--chalk-dim); opacity: 0.6; } +.tier-card ul li.muted-perk::before { + border: none; + width: 10px; height: 2px; + top: 11px; + background: var(--chalk-dim); + transform: none; } -.tier-card ul li.muted-perk { color: var(--chalk-faded); opacity: .7; } -.tier-card ul li.muted-perk::before { background: transparent; border-style: solid; } -.tier-card ul li.muted-perk::after { content: ""; } - -.tier-card .tier-cta { margin-top: auto; } +.tier-card .tier-cta { margin-top: auto; padding-top: 6px; } +.tier-card .tier-cta .btn { width: 100%; } .tier-card.featured { - border: none; + border-color: rgba(217,122,61,0.6); background: - linear-gradient(160deg, rgba(217,122,61,0.30), rgba(0,0,0,0.40)), - radial-gradient(ellipse at top, rgba(244,241,230,0.10), transparent 60%); - transform: translateY(-6px); + linear-gradient(165deg, rgba(217,122,61,0.2), rgba(0,0,0,0.32)), + rgba(10,22,15,0.4); + box-shadow: var(--lift-2), 0 0 40px -18px rgba(217,122,61,0.7); } -.tier-card.featured::before { border-color: var(--accent); } .tier-card .ribbon { position: absolute; - top: 14px; right: -38px; + top: 15px; right: -36px; + padding: 3px 42px; + transform: rotate(38deg); background: var(--accent); - color: var(--board-3); - font-family: 'Caveat', cursive; - font-weight: 700; - padding: 4px 44px; - transform: rotate(35deg); - border-top: 2px solid var(--chalk); - border-bottom: 2px solid var(--chalk); - font-size: 1rem; - box-shadow: 0 4px 10px rgba(0,0,0,0.5); - letter-spacing: 0.5px; + color: var(--board-ink); + font-family: var(--font-stamp); + font-size: 0.6rem; + letter-spacing: 0.12em; + text-transform: uppercase; + box-shadow: 0 4px 12px rgba(0,0,0,0.55); +} +.tier-card .tier-name .badge-inline { + display: inline-block; + vertical-align: middle; + margin-left: 8px; + font-family: var(--font-stamp); + font-size: 0.6rem; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--chalk-dim); + border: var(--rule-strong); + border-radius: 999px; + padding: 2px 9px; +} +.btn.current-tier { + background: rgba(217,122,61,0.14); + border: 1px solid var(--accent); + color: var(--accent-soft); + box-shadow: none; + cursor: default; + pointer-events: none; } .faq-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(278px, 1fr)); gap: 16px; - margin-top: 18px; -} -.faq-grid .chalk-card h3 { - font-family: 'Caveat', cursive; - font-size: 1.5rem; - margin: 0 0 6px; - color: var(--accent-soft); + margin-top: 20px; } +.faq-grid .chalk-card h3 { font-size: 1.3rem; margin: 0 0 6px; color: var(--accent-soft); } +.faq-grid p { margin: 0; font-size: 0.93rem; } -/* ============================================================ + +/* ========================================================= AVATAR CUSTOMIZER - ============================================================ */ + ========================================================= */ + .avatar-layout { display: grid; - grid-template-columns: 300px 1fr 300px; + grid-template-columns: 288px 1fr 288px; gap: 18px; - margin-top: 18px; + margin-top: 22px; align-items: start; } .avatar-col { padding: 18px; } -.avatar-col h3 { - font-family: 'Caveat', cursive; - font-size: 1.6rem; - margin: 0 0 10px; -} - -.country-search { - width: 100%; - font-family: 'Architects Daughter', cursive; - color: var(--chalk); - background: rgba(0,0,0,0.30); - border: 2px dashed rgba(244,241,230,0.45); - border-radius: 10px; - padding: 8px 12px; - margin-bottom: 10px; - font-size: 1rem; -} -.country-search:focus { - outline: none; border-color: var(--accent); border-style: solid; - box-shadow: 0 0 0 3px rgba(217,122,61,0.25); -} -.country-tabs { - display: flex; gap: 8px; margin-bottom: 10px; -} -.country-tabs button { - flex: 1; - background: transparent; - border: 2px dashed rgba(244,241,230,0.40); - color: var(--chalk-soft); - font-family: 'Caveat', cursive; - font-size: 1.15rem; - border-radius: 8px; - padding: 4px 8px; - cursor: pointer; -} -.country-tabs button.active { - border-color: var(--accent); - border-style: solid; - color: var(--chalk); - background: rgba(217,122,61,0.18); -} +.avatar-col h3 { font-size: 1.4rem; margin: 0 0 12px; } +.country-search { margin-bottom: 10px; } +.country-tabs { margin-bottom: 12px; } .country-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; - max-height: 560px; + max-height: 540px; overflow-y: auto; - padding: 4px 8px 4px 2px; + padding: 2px 6px 2px 2px; } .country-chip { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 6px 8px; - border-radius: 12px; - border: 2px dashed transparent; - background: rgba(0,0,0,0.22); + min-height: 94px; + border: 1px solid transparent; + border-radius: var(--r-sm); + background: rgba(0,0,0,0.24); cursor: pointer; - transition: transform .15s ease, border-color .15s ease, background .15s ease; - min-height: 96px; + transition: transform .15s var(--ease), border-color .15s, background .15s; } .country-chip:hover { - background: rgba(244,241,230,0.08); + background: rgba(244,241,230,0.07); + border-color: rgba(244,241,230,0.25); transform: translateY(-2px); - border-color: rgba(244,241,230,0.35); } .country-chip.active { border-color: var(--accent); - border-style: solid; - background: rgba(217,122,61,0.20); - box-shadow: 0 0 0 2px rgba(217,122,61,0.30), 0 6px 14px rgba(0,0,0,0.4); + background: rgba(217,122,61,0.18); + box-shadow: 0 0 0 1px var(--accent); } .country-chip.locked { - opacity: 0.55; + border: var(--sketch); + opacity: 0.5; cursor: not-allowed; - filter: grayscale(0.5); -} -.country-chip.locked:hover { - transform: none; - background: rgba(0,0,0,0.22); - border-color: transparent; -} -.country-chip.locked svg { - filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5)) grayscale(0.5); -} -.country-chip.locked .name { - color: var(--chalk-faded); -} -.country-chip svg { - flex: 0 0 auto; - filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5)); + filter: grayscale(0.6); } +.country-chip.locked:hover { transform: none; background: rgba(0,0,0,0.24); } +.country-chip svg { flex: 0 0 auto; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.55)); } .country-chip .name { - font-family: 'Architects Daughter', 'Kalam', cursive; - font-size: 0.92rem; - font-weight: 700; - color: #ffffff; + font-family: var(--font-body); + font-size: 0.8rem; + font-weight: 600; + color: #fff; text-align: center; - line-height: 1.15; - letter-spacing: 0.2px; - /* keep names crisp regardless of background β€” chalkboard-flavored stroke */ - text-shadow: - 0 0 1px rgba(0,0,0,0.95), - 0 1px 2px rgba(0,0,0,0.85), - 0 0 6px rgba(0,0,0,0.55); - word-break: break-word; - hyphens: auto; + line-height: 1.2; + text-shadow: 0 1px 3px rgba(0,0,0,0.95); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; max-width: 100%; + word-break: break-word; } -.country-chip.active .name { color: #fff8e0; } -.country-grid::-webkit-scrollbar { width: 8px; } -.country-grid::-webkit-scrollbar-track { background: rgba(0,0,0,0.2); border-radius: 8px; } -.country-grid::-webkit-scrollbar-thumb { - background: rgba(244,241,230,0.25); border-radius: 8px; -} +.country-grid::-webkit-scrollbar { width: 6px; } +.country-grid::-webkit-scrollbar-thumb { background: rgba(244,241,230,0.2); border-radius: 6px; } -/* preview pane */ -.avatar-preview { - display: flex; flex-direction: column; align-items: center; gap: 14px; - text-align: center; -} -.avatar-preview .country-name { - font-family: 'Caveat', cursive; - font-size: 2.2rem; - margin: 0; -} -.avatar-stage { - width: min(360px, 75vw); - aspect-ratio: 1 / 1; - position: relative; -} +.avatar-preview { display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; } +.avatar-preview .country-name { font-size: 2rem; margin: 0; } +.avatar-stage { width: min(340px, 74vw); aspect-ratio: 1; position: relative; } .avatar-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; } -.avatar-saved-pulse { animation: saved-pulse .8s ease; } -@keyframes saved-pulse { - 0% { transform: scale(1); } - 35% { transform: scale(1.05) rotate(-3deg); } - 100% { transform: scale(1); } -} -/* accessory tile grid */ .acc-section { margin-bottom: 16px; } .acc-section h4 { - font-family: 'Caveat', cursive; - font-size: 1.25rem; - margin: 0 0 6px; - color: var(--accent-soft); -} -.acc-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 8px; -} + font-family: var(--font-stamp); + font-size: 0.66rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--chalk-dim); + margin: 0 0 7px; +} +.acc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; } .acc-tile { - aspect-ratio: 1 / 1; - border: 2px dashed rgba(244,241,230,0.40); - border-radius: 10px; - background: rgba(0,0,0,0.25); + position: relative; + aspect-ratio: 1; + border: var(--rule); + border-radius: var(--r-sm); + background: rgba(0,0,0,0.26); display: flex; align-items: center; justify-content: center; cursor: pointer; - transition: transform .15s ease, border-color .15s ease, background .15s ease; - position: relative; -} -.acc-tile:hover { transform: translateY(-2px); background: rgba(244,241,230,0.06); } -.acc-tile.active { - border-color: var(--accent); - background: rgba(217,122,61,0.18); + transition: transform .15s var(--ease), border-color .15s, background .15s; } +.acc-tile:hover { transform: translateY(-2px); background: rgba(244,241,230,0.07); } +.acc-tile.active { border-color: var(--accent); background: rgba(217,122,61,0.18); } .acc-tile.locked { - opacity: 0.5; + border: var(--sketch); + opacity: 0.45; cursor: not-allowed; - filter: grayscale(0.5); - position: relative; -} -.acc-tile.locked:hover { - transform: none; - background: rgba(0,0,0,0.25); - border-color: rgba(244,241,230,0.40); -} -.acc-tile .acc-lock { - position: absolute; - right: 4px; top: 4px; - font-size: 0.75rem; - line-height: 1; - filter: none; -} -.acc-tile svg { width: 60%; height: 60%; } -.acc-tile .none-x { - font-family: 'Caveat', cursive; - font-size: 1.4rem; - color: var(--chalk-faded); -} -.acc-tile.active .none-x { color: var(--chalk); } - -/* mini countryball in user-chip */ -.user-chip .avatar.countryball { - background: none; - border: none; - padding: 0; - width: 30px; height: 30px; - overflow: visible; -} -.user-chip .avatar.countryball svg { - width: 100%; height: 100%; - display: block; -} - -@media (max-width: 980px) { - .avatar-layout { - grid-template-columns: 1fr; - } - .avatar-stage { width: min(280px, 70vw); } - .country-grid { - grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); - max-height: 360px; - } -} - -/* ============================================================ - TOPBAR β€” split into left (brand + nav) and right (account) - ============================================================ */ -.topbar .inner { - display: flex; - align-items: center; - /* hard split: left cluster pushes right, right cluster pinned to far right */ - justify-content: space-between; - gap: 24px; -} -.topbar .topbar-left, -.topbar .topbar-right { - display: flex; - align-items: center; - gap: 12px; - flex-wrap: nowrap; -} -.topbar .topbar-left { flex: 1 1 auto; min-width: 0; } -.topbar .topbar-right { flex: 0 0 auto; } - -/* visual divider chalk dash between the halves on wide screens */ -.topbar .topbar-right::before { - content: ""; - display: inline-block; - width: 2px; height: 28px; - border-left: 2px dashed rgba(244,241,230,0.25); - margin-right: 4px; -} - -/* TIER BADGE β€” sits inside user-chip, replaces direct membership link */ -.tier-badge { - display: inline-flex; - align-items: center; - gap: 4px; - font-family: 'Caveat', cursive; - font-weight: 700; - font-size: 0.95rem; - padding: 2px 10px; - border-radius: 999px; - border: 1.5px dashed var(--tier-guest-bd); - background: var(--tier-guest-bg); - color: var(--tier-guest-fg); - text-decoration: none; - letter-spacing: 0.3px; - transition: transform .15s ease, box-shadow .15s ease, background .15s ease; - line-height: 1.1; - cursor: pointer; -} -.tier-badge:hover { transform: translateY(-1px); } -.tier-badge[data-tier="regular"] { - border-color: var(--tier-regular-bd); - background: var(--tier-regular-bg); - color: var(--tier-regular-fg); -} -.tier-badge[data-tier="emperor"] { - border-color: var(--tier-emperor-bd); - border-style: solid; - background: var(--tier-emperor-bg); - color: var(--tier-emperor-fg); - text-shadow: 0 1px 2px rgba(0,0,0,0.6); - box-shadow: 0 0 0 1px rgba(244,201,93,0.45), 0 0 16px rgba(255,210,80,0.30); -} -.tier-badge[data-tier="emperor"]:hover { - box-shadow: 0 0 0 1px rgba(244,201,93,0.6), 0 0 22px rgba(255,210,80,0.5); -} -.tier-badge .crown { - display: inline-block; - width: 12px; height: 12px; - background: currentColor; - -webkit-mask: url("data:image/svg+xml;utf8,") center/contain no-repeat; - mask: url("data:image/svg+xml;utf8,") center/contain no-repeat; -} - -/* Username inside user-chip β€” make name + tier badge sit nicely */ -.user-chip { - gap: 8px; -} -.user-chip .name { line-height: 1.1; } -.user-chip a.tier-badge { border-bottom: none; } - -/* The username chip itself becomes a wrapper for name+tier on the right side */ -.user-block { - display: inline-flex; - flex-direction: column; - align-items: flex-start; - gap: 2px; - line-height: 1.1; -} -.user-block .name { - font-family: 'Caveat', cursive; - font-size: 1.15rem; - color: var(--chalk); -} - -/* Settings icon button */ -.btn-icon { - width: 38px; height: 38px; - display: inline-flex; align-items: center; justify-content: center; - border: 2px dashed rgba(244,241,230,0.55); - border-radius: 50%; - background: transparent; - color: var(--chalk); - cursor: pointer; - transition: transform .18s ease, background .18s ease, border-color .18s ease; - padding: 0; -} -.btn-icon:hover { - background: rgba(244,241,230,0.10); - transform: rotate(35deg); - border-color: var(--accent); -} -.btn-icon svg { width: 18px; height: 18px; } -.btn-icon:focus-visible { outline: 2px dashed var(--accent); outline-offset: 3px; } - -/* ============================================================ - SETTINGS PAGE - ============================================================ */ -.settings-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 18px; - margin-top: 18px; -} -.settings-card h3 { - font-family: 'Caveat', cursive; - font-size: 1.6rem; - margin: 0 0 4px; -} -.settings-row { - display: flex; align-items: center; gap: 12px; - padding: 10px 0; - border-top: 1px dashed rgba(244,241,230,0.20); -} -.settings-row:first-of-type { border-top: none; } -.settings-row .label { - flex: 1; min-width: 0; -} -.settings-row .label .key { - display: block; - font-family: 'Patrick Hand', cursive; - font-size: 1.1rem; - color: var(--chalk); -} -.settings-row .label .desc { - display: block; - font-size: 0.92rem; - color: var(--chalk-faded); -} -.settings-row select, -.settings-row input[type="text"] { - font-family: 'Architects Daughter', cursive; - color: var(--chalk); - background: rgba(0,0,0,0.30); - border: 2px dashed rgba(244,241,230,0.45); - border-radius: 8px; - padding: 6px 10px; - font-size: 1rem; - min-width: 140px; -} -.settings-row select:focus, -.settings-row input:focus { - outline: none; border-color: var(--accent); border-style: solid; -} - -/* tier switcher chips on settings */ -.tier-switch { - display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; -} -.tier-switch button { - font-family: 'Caveat', cursive; - font-weight: 700; - font-size: 1.1rem; - padding: 6px 14px; - border-radius: 999px; - border: 2px dashed rgba(244,241,230,0.40); - background: rgba(0,0,0,0.25); - color: var(--chalk-soft); - cursor: pointer; - transition: all .15s ease; -} -.tier-switch button[data-tier="guest"].active { background: var(--tier-guest-bg); color: var(--tier-guest-fg); border-color: var(--tier-guest-bd); border-style: solid; } -.tier-switch button[data-tier="regular"].active { background: var(--tier-regular-bg); color: var(--tier-regular-fg); border-color: var(--tier-regular-bd); border-style: solid; } -.tier-switch button[data-tier="emperor"].active { background: var(--tier-emperor-bg); color: var(--tier-emperor-fg); border-color: var(--tier-emperor-bd); border-style: solid; box-shadow: 0 0 12px rgba(255,210,80,0.3); } - -/* Toggle switch */ -.toggle { - position: relative; width: 50px; height: 26px; - display: inline-block; - flex: 0 0 auto; -} -.toggle input { opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; } -.toggle .track { - position: absolute; inset: 0; - background: rgba(0,0,0,0.45); - border: 2px dashed rgba(244,241,230,0.40); - border-radius: 999px; - transition: background .2s, border-color .2s; + filter: grayscale(0.6); } -.toggle .thumb { - position: absolute; - top: 2px; left: 2px; - width: 18px; height: 18px; - background: var(--chalk); - border-radius: 50%; - transition: transform .25s cubic-bezier(.2,.7,.2,1), background .2s; +.acc-tile.locked:hover { transform: none; background: rgba(0,0,0,0.26); } +.acc-tile .acc-lock { + position: absolute; right: 4px; top: 4px; + width: 12px; height: 12px; + color: var(--chalk-dim); + filter: none; } -.toggle input:checked + .track { background: rgba(217,122,61,0.35); border-color: var(--accent); border-style: solid; } -.toggle input:checked + .track + .thumb { transform: translateX(24px); background: var(--accent-soft); } -.toggle input:focus-visible + .track { outline: 2px dashed var(--accent); outline-offset: 3px; } +.acc-tile .acc-lock svg { width: 12px; height: 12px; display: block; } +.acc-tile svg { width: 58%; height: 58%; } +.acc-tile .none-x { font-family: var(--font-stamp); font-size: 0.7rem; color: var(--chalk-dim); } -/* ============================================================ - COMING-SOON AVATARS GRID - ============================================================ */ .coming-soon-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); - gap: 12px; + grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); + gap: 10px; margin-top: 14px; } .coming-soon-tile { - aspect-ratio: 1 / 1.15; - border: 2px dashed rgba(244,241,230,0.30); - border-radius: 12px; - background: - repeating-linear-gradient(45deg, rgba(244,241,230,0.04) 0 8px, transparent 8px 16px), - rgba(0,0,0,0.25); + aspect-ratio: 1 / 1.12; + border-radius: var(--r-sm); display: flex; flex-direction: column; align-items: center; justify-content: center; - gap: 8px; + gap: 7px; text-align: center; padding: 10px 6px; - position: relative; - overflow: hidden; } .coming-soon-tile .silhouette { - width: 56px; height: 56px; + width: 50px; height: 50px; border-radius: 50%; - background: rgba(244,241,230,0.15); - border: 2px dashed rgba(244,241,230,0.45); + border: var(--sketch); + background: rgba(244,241,230,0.05); display: flex; align-items: center; justify-content: center; - font-family: 'Caveat', cursive; - font-size: 1.8rem; - color: rgba(244,241,230,0.5); + font-family: var(--font-display); + font-size: 1.5rem; + color: var(--chalk-ghost); } -.coming-soon-tile .cs-label { - font-family: 'Architects Daughter', cursive; +.coming-soon-tile .cs-label { font-size: 0.82rem; color: var(--chalk-soft); line-height: 1.2; } +.coming-soon-tile .cs-eta { font-size: 0.6rem; color: var(--accent-soft); } + +@media (max-width: 1000px) { + .avatar-layout { grid-template-columns: 1fr; } + .avatar-stage { width: min(270px, 68vw); } + .country-grid { grid-template-columns: repeat(auto-fill, minmax(108px, 1fr)); max-height: 340px; } +} + + +/* ========================================================= + SETTINGS + ========================================================= */ + +.settings-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(288px, 1fr)); + gap: 18px; + margin-top: 22px; +} +.settings-card h3 { font-size: 1.45rem; margin: 0 0 4px; } +.settings-row { + display: flex; align-items: center; gap: 14px; + padding: 13px 0; + border-top: var(--rule); +} +.settings-row:first-of-type { border-top: none; } +.settings-row .label { flex: 1; min-width: 0; } +.settings-row .label .key { display: block; font-size: 0.97rem; color: var(--chalk); font-weight: 600; } +.settings-row .label .desc { display: block; font-size: 0.85rem; color: var(--chalk-dim); } +.settings-row select, .settings-row input[type="text"] { + width: auto; + min-width: 150px; + padding: 8px 12px; font-size: 0.9rem; - color: var(--chalk-soft); - line-height: 1.15; } -.coming-soon-tile .cs-eta { - font-family: 'Caveat', cursive; - font-size: 0.95rem; + + +/* ========================================================= + TERMS + ========================================================= */ + +.tos-doc { max-width: 840px; margin: 26px auto 0; padding: 34px clamp(22px, 4vw, 44px); } +.tos-doc h1 { font-size: clamp(2.1rem, 4vw, 3rem); } +.tos-doc h2 { + margin-top: 34px; + font-size: 1.7rem; + padding-top: 14px; + border-top: var(--rule); +} +.tos-doc h3 { + margin-top: 20px; + font-family: var(--font-body); + font-weight: 700; + font-size: 1rem; + letter-spacing: 0.01em; color: var(--accent-soft); + text-shadow: none; } +.tos-doc p, .tos-doc li { max-width: 74ch; font-size: 0.96rem; } +.tos-doc ul { padding-left: 20px; } +.tos-doc ul li { margin-bottom: 6px; } +.tos-doc .placeholder { font-style: italic; color: var(--chalk-dim); } -/* Tier label INSIDE the tier card */ -.tier-card .tier-name .badge-inline { - display: inline-block; - vertical-align: middle; - font-family: 'Patrick Hand', cursive; - font-size: 0.85rem; - margin-left: 8px; - padding: 2px 10px; - border-radius: 999px; - border: 1.5px dashed currentColor; - color: var(--chalk-faded); - letter-spacing: 0.3px; -} +.tos-doc .tos-meta { + display: flex; flex-wrap: wrap; gap: 4px 22px; + margin: 0 0 8px; + font-family: var(--font-stamp); + font-size: 0.7rem; + letter-spacing: 0.04em; + color: var(--chalk-dim); +} + +.tos-toc { margin-top: 22px; padding: 18px 22px; } +.tos-toc h2 { margin: 0 0 10px; font-size: 1.35rem; border-top: none; padding-top: 0; } +.tos-toc ol { columns: 2; column-gap: 30px; padding-left: 20px; margin: 0; } +.tos-toc li { margin-bottom: 5px; break-inside: avoid; font-size: 0.92rem; } +.tos-toc a { border-bottom-color: transparent; } +.tos-toc a:hover { border-bottom-color: var(--accent); } +@media (max-width: 620px) { .tos-toc ol { columns: 1; } } -/* Responsive nav: hide secondary nav text in cramped widths */ -@media (max-width: 880px) { - .topbar .topbar-right::before { display: none; } - .user-block .name { font-size: 1.05rem; } - .tier-badge { font-size: 0.85rem; padding: 1px 8px; } +.tos-doc .legal-note { + margin-top: 28px; + padding: 18px 22px; + border: 1px solid rgba(217,122,61,0.5); + border-left: 3px solid var(--accent); + border-radius: var(--r-sm); + background: rgba(217,122,61,0.08); } +.tos-doc .legal-note .legal-tag { + display: block; + font-family: var(--font-stamp); + font-size: 0.64rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--accent-soft); + margin-bottom: 6px; +} + + +/* ========================================================= + CHAT / FRIENDS / SEARCH + ========================================================= */ -/* ============================================================ - CHAT PAGE - ============================================================ */ .chat-layout { display: grid; - grid-template-columns: 260px 1fr; + grid-template-columns: 250px 1fr; gap: 18px; - margin-top: 18px; + margin-top: 22px; align-items: start; } -.chat-sidebar { - padding: 16px 14px; - position: sticky; - top: 84px; -} -.chat-room-list { - list-style: none; - padding: 0; margin: 0 0 8px; - display: flex; flex-direction: column; gap: 4px; -} +.chat-sidebar { padding: 15px 13px; position: sticky; top: 78px; } +.chat-room-list { list-style: none; padding: 0; margin: 0 0 8px; display: flex; flex-direction: column; gap: 3px; } .chat-room-btn { width: 100%; - display: flex; align-items: center; gap: 8px; + display: flex; align-items: center; gap: 9px; text-align: left; + padding: 8px 11px; + border: 1px solid transparent; + border-radius: var(--r-sm); background: transparent; - border: 2px dashed transparent; - color: var(--chalk-soft); - font-family: 'Architects Daughter', cursive; - font-size: 1rem; - padding: 6px 10px; - border-radius: 8px; + color: var(--chalk-dim); + font-size: 0.92rem; cursor: pointer; - transition: background .15s, border-color .15s, color .15s; -} -.chat-room-btn:hover { - background: rgba(244,241,230,0.06); - color: var(--chalk); + transition: background .15s, color .15s, border-color .15s; } +.chat-room-btn:hover { background: rgba(244,241,230,0.07); color: var(--chalk); } .chat-room-btn.active { - background: rgba(217,122,61,0.18); + background: rgba(217,122,61,0.16); border-color: var(--accent); - border-style: solid; color: var(--chalk); } .chat-room-btn .dot { - width: 8px; height: 8px; border-radius: 50%; - background: var(--chalk-faded); + width: 7px; height: 7px; border-radius: 50%; + background: var(--chalk-dim); flex: 0 0 auto; } -.chat-room-btn.active .dot { background: var(--accent); box-shadow: 0 0 6px var(--accent); } -.chat-new-dm { - display: flex; gap: 6px; margin-top: 8px; -} -.chat-new-dm input { - flex: 1; min-width: 0; - font-family: 'Architects Daughter', cursive; - background: rgba(0,0,0,0.30); - color: var(--chalk); - border: 2px dashed rgba(244,241,230,0.45); - border-radius: 8px; - padding: 6px 10px; - font-size: .95rem; -} -.chat-new-dm input:focus { outline: none; border-color: var(--accent); border-style: solid; } -.chat-new-dm button { padding: 4px 12px; font-size: 1.2rem; } +.chat-room-btn.active .dot { background: var(--accent); box-shadow: 0 0 7px var(--accent); } +.chat-new-dm { display: flex; gap: 6px; margin-top: 10px; } +.chat-new-dm input { flex: 1; min-width: 0; padding: 8px 11px; font-size: 0.88rem; } +.chat-new-dm button { padding: 6px 13px; } .chat-main { display: flex; flex-direction: column; - height: calc(100vh - 140px); - min-height: 520px; - padding: 14px; + height: calc(100vh - 150px); + min-height: 500px; + padding: 15px; } .chat-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; - border-bottom: 2px dashed rgba(244,241,230,0.25); - padding-bottom: 10px; margin-bottom: 10px; + padding-bottom: 11px; margin-bottom: 10px; + border-bottom: var(--rule); } -.chat-header .chat-me { font-size: .95rem; } +.chat-header .chat-me { font-size: 0.85rem; color: var(--chalk-dim); } .chat-messages { flex: 1; min-height: 0; overflow-y: auto; padding: 6px 4px; display: flex; flex-direction: column; gap: 10px; } -.chat-messages::-webkit-scrollbar { width: 8px; } -.chat-messages::-webkit-scrollbar-thumb { background: rgba(244,241,230,0.25); border-radius: 8px; } -.chat-msg { - display: flex; flex-direction: column; - max-width: 78%; - align-self: flex-start; -} +.chat-messages::-webkit-scrollbar { width: 6px; } +.chat-messages::-webkit-scrollbar-thumb { background: rgba(244,241,230,0.2); border-radius: 6px; } +.chat-msg { display: flex; flex-direction: column; max-width: 76%; align-self: flex-start; } .chat-msg.me { align-self: flex-end; align-items: flex-end; } .chat-from { - font-family: 'Caveat', cursive; - font-size: .95rem; + font-family: var(--font-stamp); + font-size: 0.64rem; + letter-spacing: 0.08em; + text-transform: uppercase; color: var(--accent-soft); - padding: 0 6px 2px; + padding: 0 4px 3px; } .chat-bubble { - background: rgba(244,241,230,0.10); - border: 2px dashed rgba(244,241,230,0.30); - border-radius: 12px; - padding: 8px 12px; - font-family: 'Architects Daughter', cursive; + padding: 9px 13px; + border: var(--rule); + border-radius: var(--r); + background: rgba(244,241,230,0.07); color: var(--chalk); + font-size: 0.95rem; line-height: 1.45; white-space: pre-wrap; word-wrap: break-word; } .chat-msg.me .chat-bubble { - background: rgba(217,122,61,0.22); - border-color: var(--accent); - border-style: solid; -} -.chat-time { - font-size: .75rem; - color: var(--chalk-faded); - padding: 2px 6px 0; + background: rgba(217,122,61,0.2); + border-color: rgba(217,122,61,0.55); } +.chat-time { font-size: 0.68rem; color: var(--chalk-dim); padding: 3px 5px 0; } .chat-composer { display: flex; gap: 8px; - padding-top: 10px; - border-top: 2px dashed rgba(244,241,230,0.25); - margin-top: 8px; -} -.chat-composer input { - flex: 1; min-width: 0; - font-family: 'Architects Daughter', cursive; - font-size: 1.05rem; - background: rgba(0,0,0,0.30); - color: var(--chalk); - border: 2px dashed rgba(244,241,230,0.45); - border-radius: 10px; - padding: 10px 14px; + padding-top: 11px; margin-top: 8px; + border-top: var(--rule); } -.chat-composer input:focus { outline: none; border-color: var(--accent); border-style: solid; } -.chat-composer input:disabled { opacity: 0.55; cursor: not-allowed; } +.chat-composer input { flex: 1; min-width: 0; } + +/* Friend / search result rows */ +.fr-panel { padding: 16px 18px; } +.fr-panel + .fr-panel { margin-top: 14px; } +.rname { font-weight: 600; color: var(--chalk); } -@media (max-width: 760px) { +@media (max-width: 800px) { .chat-layout { grid-template-columns: 1fr; } .chat-sidebar { position: static; } .chat-main { height: auto; min-height: 420px; } } -/* ============================================================ - SOCIAL POPOVER β€” body-attached chalkboard panel - Toggle lives in the topbar nav; the menu itself is appended to - by JS (position: fixed) so it escapes the topbar's flex - cascade and can never collide with surrounding link styles. - ============================================================ */ -/* Toggle button inside the nav β€” styled to match sibling links */ -.topbar nav .social-toggle { - background: transparent; - border: none; - color: var(--chalk-soft); - font-family: 'Architects Daughter', cursive; - font-size: 1.05rem; - padding: 6px 12px; - border-radius: 8px; - cursor: pointer; - letter-spacing: 0.2px; - line-height: 1.4; - display: inline-flex; - align-items: center; - gap: 6px; - position: relative; - transition: background .15s ease, color .15s ease; +/* ========================================================= + OVERLAYS + ========================================================= */ + +.loading-overlay { + position: fixed; inset: 0; + z-index: var(--z-overlay); + background: rgba(7,17,11,0.95); + backdrop-filter: blur(6px); + display: none; + align-items: center; justify-content: center; + flex-direction: column; gap: 22px; + text-align: center; } -.topbar nav .social-toggle:hover, -.topbar nav .social-toggle[aria-expanded="true"], -.topbar nav .social-toggle.has-active { - background: rgba(244,241,230,0.10); - color: var(--chalk); +.loading-overlay.show { display: flex; } +.loading-overlay .spinner { + width: 58px; height: 58px; + border: 3px solid rgba(244,241,230,0.16); + border-top-color: var(--accent); + border-radius: 50%; + animation: spin 1s linear infinite; } -.topbar nav .social-toggle .caret { - width: 10px; height: 10px; - flex: 0 0 10px; - transition: transform .25s cubic-bezier(.2,.7,.2,1); -} -.topbar nav .social-toggle[aria-expanded="true"] .caret { - transform: rotate(180deg); -} -/* Hide the chalk-underline ::after that .topbar nav a uses */ -.topbar nav .social-toggle::after, -.topbar nav .social-toggle::before { - content: none !important; - display: none !important; -} - -/* The popover panel β€” lives directly under */ -.social-popover { - position: fixed; - top: 0; left: 0; - min-width: 220px; - background: linear-gradient(180deg, rgba(15,32,24,0.985), rgba(10,22,15,0.985)); - border: 2.5px dashed rgba(244,241,230,0.55); - border-radius: 14px; - padding: 8px; - display: flex; - flex-direction: column; - gap: 2px; - z-index: 1000; - box-shadow: - 0 0 0 1px rgba(244,241,230,0.08), - 0 18px 38px rgba(0,0,0,0.65), - 0 0 24px rgba(217,122,61,0.10); - /* enter animation */ - opacity: 0; - transform: translateY(-6px) scale(0.96); - transform-origin: top center; - pointer-events: none; - transition: opacity .18s ease, transform .22s cubic-bezier(.2,.7,.2,1); +@keyframes spin { to { transform: rotate(360deg); } } +.loading-overlay h2 { font-size: 2rem; margin: 0; } +.loading-overlay p { font-family: var(--font-stamp); font-size: 0.76rem; letter-spacing: 0.06em; } + +.lightbox { + position: fixed; inset: 0; + z-index: var(--z-overlay); + background: rgba(7,17,11,0.95); + backdrop-filter: blur(5px); + display: flex; align-items: center; justify-content: center; + cursor: zoom-out; + animation: fade-in .22s ease; } -.social-popover.open { - opacity: 1; - transform: translateY(0) scale(1); - pointer-events: auto; +.lightbox img { + max-width: 92vw; max-height: 88vh; + border: var(--rule-strong); + border-radius: var(--r); + box-shadow: var(--lift-3); } - -/* Little chalk-arrow notch pointing back at the toggle */ -.social-popover::before { - content: ""; - position: absolute; - top: -8px; - left: var(--arrow-x, 50%); - transform: translateX(-50%) rotate(45deg); - width: 12px; height: 12px; - background: rgba(15,32,24,0.99); - border-left: 2.5px dashed rgba(244,241,230,0.55); - border-top: 2.5px dashed rgba(244,241,230,0.55); - border-top-left-radius: 3px; +.lightbox .close { + position: absolute; top: 18px; right: 22px; + width: 42px; height: 42px; + display: inline-flex; align-items: center; justify-content: center; + border: var(--rule-strong); + border-radius: 50%; + background: rgba(0,0,0,0.4); + color: var(--chalk); + font-size: 1.2rem; + cursor: pointer; } +.lightbox .close:hover { background: var(--chalk); color: var(--board-ink); } +@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } -/* Items */ -.social-popover a { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 12px; - font-family: 'Architects Daughter', cursive; - font-size: 1.05rem; - color: var(--chalk-soft); - text-decoration: none; - border: 1.5px dashed transparent; +.toast { + position: fixed; left: 50%; bottom: 30px; + z-index: var(--z-toast); + transform: translateX(-50%) translateY(8px); + padding: 12px 20px; + border: var(--rule-strong); border-radius: 10px; - line-height: 1.2; - white-space: nowrap; - transition: background .15s ease, color .15s ease, border-color .15s ease, transform .15s ease; -} -.social-popover a:hover, -.social-popover a:focus-visible { - background: rgba(244,241,230,0.08); + background: rgba(7,17,11,0.96); color: var(--chalk); - border-color: rgba(244,241,230,0.30); - outline: none; - transform: translateX(2px); -} -.social-popover a.active { - color: var(--accent-soft); - background: rgba(217,122,61,0.16); - border-color: var(--accent); - border-style: solid; -} -.social-popover .sp-icon { - width: 20px; height: 20px; - flex: 0 0 20px; - display: inline-flex; - align-items: center; - justify-content: center; - color: currentColor; - opacity: 0.9; -} -.social-popover .sp-icon svg { width: 20px; height: 20px; display: block; } -.social-popover .sp-label { flex: 1; min-width: 0; } -.social-popover .sp-sub { - display: block; - font-size: .8rem; - color: var(--chalk-faded); - font-family: 'Architects Daughter', cursive; - margin-top: 1px; - line-height: 1.1; + font-size: 0.92rem; + box-shadow: var(--lift-2); + opacity: 0; + pointer-events: none; + transition: opacity .24s ease, transform .24s var(--ease); } +.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); } -/* Reduced motion */ -@media (prefers-reduced-motion: reduce) { - .social-popover { transition: opacity .1s ease; transform: none; } - .social-popover.open { transform: none; } -} -/* ============================================================ - LOCK PILL β€” small inline πŸ”’ badge for section titles - ============================================================ */ -.lock-pill { - display: inline-flex; - align-items: center; - gap: 4px; - vertical-align: middle; - font-family: 'Caveat', cursive; - font-weight: 700; - font-size: 0.95rem; - padding: 2px 12px; - margin-left: 8px; - border-radius: 999px; - background: rgba(217,122,61,0.18); - border: 1.5px dashed var(--accent); - color: var(--accent-soft); - letter-spacing: 0.3px; - line-height: 1.3; - text-shadow: none; - white-space: nowrap; -} -/* ============================================================ - LOCK OVERLAY β€” placeholder paywall / coming-soon gate - Wrap any block in
+ add a child -
…
as a sibling AFTER the content. - ============================================================ */ -.lock-wrap { - position: relative; - /* keep underlying content visible but unreachable */ -} -.lock-wrap > .lock-target { - filter: blur(3px) saturate(0.85); - opacity: 0.55; - pointer-events: none; - user-select: none; - /* prevent keyboard focus reaching locked content */ -} -.lock-overlay { - position: absolute; - inset: 0; - z-index: 5; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - gap: 14px; - padding: 32px 24px; - background: - radial-gradient(ellipse at center, rgba(15,32,24,0.55), rgba(15,32,24,0.85)); - border-radius: var(--radius); - pointer-events: auto; - backdrop-filter: blur(2px); -} -.lock-overlay::before { - content: ""; - position: absolute; - inset: 18px; - border: 3px dashed rgba(244,241,230,0.55); - border-radius: calc(var(--radius) - 4px); - pointer-events: none; - animation: lock-pulse 3s ease-in-out infinite; -} -@keyframes lock-pulse { - 0%, 100% { opacity: 0.55; transform: rotate(-0.3deg); } - 50% { opacity: 0.85; transform: rotate(0.3deg); } -} +/* ========================================================= + MOTION + ========================================================= */ -.lock-overlay .lock-icon { - width: clamp(96px, 14vw, 160px); - height: auto; - filter: drop-shadow(0 8px 18px rgba(0,0,0,0.5)); -} -.lock-overlay .lock-icon .body { - fill: rgba(244,241,230,0.92); - stroke: var(--board-3); - stroke-width: 4; -} -.lock-overlay .lock-icon .shackle { - fill: none; - stroke: rgba(244,241,230,0.92); - stroke-width: 14; - stroke-linecap: round; - /* slight chalk wobble using dasharray */ - stroke-dasharray: 220; - stroke-dashoffset: 0; -} -.lock-overlay .lock-icon .keyhole { - fill: var(--board-3); -} -.lock-overlay .lock-icon .accent { - fill: var(--accent); - opacity: 0.85; -} -.lock-overlay h2 { - font-family: 'Caveat', cursive; - font-size: clamp(2rem, 4vw, 3rem); - margin: 0; - color: var(--chalk); - text-shadow: 0 2px 8px rgba(0,0,0,0.7); -} -.lock-overlay p { - font-family: 'Architects Daughter', cursive; - color: var(--chalk-soft); - font-size: 1.05rem; - max-width: 46ch; - margin: 0; -} -.lock-overlay .lock-actions { - display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; - margin-top: 6px; -} -.lock-overlay .lock-stamp { - position: absolute; - top: 14px; right: 14px; - background: var(--accent); - color: var(--board-3); - font-family: 'Caveat', cursive; - font-weight: 700; - padding: 4px 14px; - border-radius: 999px; - border: 2px solid var(--chalk); - font-size: 0.95rem; - transform: rotate(8deg); - letter-spacing: 0.4px; - box-shadow: 0 4px 12px rgba(0,0,0,0.5); +.reveal { + opacity: 0; + transform: translateY(16px); + transition: opacity .55s ease, transform .55s var(--ease); } +.reveal.in { opacity: 1; transform: none; } +.reveal.delay-1 { transition-delay: .06s; } +.reveal.delay-2 { transition-delay: .12s; } +.reveal.delay-3 { transition-delay: .18s; } +.reveal.delay-4 { transition-delay: .24s; } -/* Locked tier chip / button β€” universal lock affordance */ -.tier-switch button.locked, -.tier-card .btn.locked, -.tier-card .btn.emperor-locked { - position: relative; - cursor: not-allowed; - opacity: 0.6; - filter: grayscale(0.4); -} -.tier-switch button.locked::after, -.tier-card .btn.locked::after, -.tier-card .btn.emperor-locked::after { - content: "πŸ”’"; - margin-left: 6px; - font-size: 0.9em; - filter: none; -} -.tier-switch button.locked:hover, -.tier-card .btn.locked:hover, -.tier-card .btn.emperor-locked:hover { - transform: none; - background: transparent; - color: var(--chalk-soft); +/* ========================================================= + RESPONSIVE + ========================================================= */ + +@media (max-width: 1040px) { + .nav-tab { padding: 9px 10px; font-size: 0.9rem; } + .nav-tab svg { display: none; } +} + +@media (max-width: 900px) { + .topbar-inner, .topbar .inner { padding: 8px 16px; gap: 10px; } + .nav-toggle { display: block; order: 3; } + .brand { order: 1; } + .topbar-right { order: 2; margin-left: auto; } + + .primary-nav { + order: 4; + position: absolute; + top: 100%; left: 0; right: 0; + flex-direction: column; + align-items: stretch; + gap: 2px; + padding: 10px 14px 16px; + background: linear-gradient(180deg, #0d1c13, #0a160f); + border-bottom: var(--rule-strong); + box-shadow: var(--lift-3); + /* collapsed */ + max-height: 0; + overflow: hidden; + opacity: 0; + visibility: hidden; + transition: max-height .34s var(--ease), opacity .22s ease, padding .34s var(--ease), visibility .34s; + } + .topbar.menu-open .primary-nav { + max-height: 78vh; + overflow-y: auto; + opacity: 1; + visibility: visible; + } + .nav-tab { justify-content: flex-start; padding: 12px 14px; font-size: 1rem; } + .nav-tab svg { display: inline-flex; } + .nav-marker { display: none; } + + /* Dropdowns become inline accordions on mobile */ + .nav-group { display: block; } + .nav-group > .nav-tab { width: 100%; } + .nav-menu { + position: static; + transform: none; + min-width: 0; + margin: 2px 0 6px 14px; + box-shadow: none; + background: rgba(0,0,0,0.28); + max-height: 0; + padding: 0 7px; + overflow: hidden; + visibility: visible; + opacity: 1; + border-color: transparent; + transition: max-height .3s var(--ease), padding .3s var(--ease), border-color .2s; + } + .nav-group.open > .nav-menu { + transform: none; + max-height: 340px; + padding: 7px; + border-color: rgba(244,241,230,0.16); + } + .nav-menu::before { display: none; } + .nav-menu.align-right { transform: none; } + + .user-block .name { max-width: 88px; } + .coin-chip .soon { display: none; } } -/* Current tier badge (on Membership CTA) */ -.tier-card .btn.current-tier { - background: rgba(217,122,61,0.15); - border-color: var(--accent); - border-style: solid; - color: var(--accent-soft); - cursor: default; - pointer-events: none; +@media (max-width: 620px) { + body { font-size: 16px; } + .brand-name { font-size: 1.3rem; } + .brand-mark, .topbar .brand img { width: 30px; height: 30px; } + .coin-chip { padding: 4px 9px; font-size: 0.72rem; } + .user-chip { padding: 3px 8px 3px 4px; } + .user-block .name { max-width: 70px; font-size: 0.8rem; } + .site-footer .footer-inner { flex-direction: column; align-items: flex-start; } + .site-footer .footer-meta { margin-left: 0; } } -.tier-card .btn.current-tier:hover { - transform: none; - background: rgba(217,122,61,0.15); + +@media (max-width: 420px) { + .brand-text { display: none; } } -/* Reduced motion */ + @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } - .chalk-dust { display: none; } .reveal { opacity: 1; transform: none; } + .section-title.reveal::after { --rule-scale: 1; } } diff --git a/site/friends.html b/site/friends.html index c976b54..0dad64e 100644 --- a/site/friends.html +++ b/site/friends.html @@ -5,46 +5,63 @@ Heredita β€” Friends - +
-
-
- - + -
-
- - 0 - coming soon + Pre-alpha + + + + + + + +
+ + 0 + + + - - - - - -
@@ -53,13 +70,12 @@

Friends

- your roster
-

- All footage from the pre-alpha build. Art & maps by the Heredita team. +

+ Everything above is from the pre-alpha build, so expect it to look different next month. + Maps and art drawn in-house.

@@ -174,18 +203,18 @@

Preview Footage

- - - - - + + + + + diff --git a/site/index.html b/site/index.html index a206905..48f952e 100644 --- a/site/index.html +++ b/site/index.html @@ -6,16 +6,37 @@ Heredita β€” Roleplay the World - + - +
- -

Roll the dice. Paint the map. Rewrite history.

+ +
+ +

Roll the dice. Paint the map. Rewrite history.

+ +
    +
  • + + Runs in the browser. No launcher, no download, no patcher. +
  • +
  • + + Start in 1936, 1945 or 1991. Play the century straight, or break it on turn one. +
  • +
  • + + Every roll is public. Annexations are 2d6 in the open β€” no hidden combat math. +
  • +
+ + +
-

Join the timeline

+ Free while it's in pre-alpha +

Pick up the chalk

@@ -78,21 +99,20 @@

Join the time onclick="document.querySelector('[data-tab=signup]').click()">Create a new account

+

+ Guest sessions play the same game. An account just keeps your profile between devices. +

- -

- By continuing you confirm you've read our Terms & Conditions. -

@@ -121,9 +141,10 @@

Join the time - - - - + + + + + diff --git a/site/js/app.js b/site/js/app.js index 8a4ed86..a6516f4 100644 --- a/site/js/app.js +++ b/site/js/app.js @@ -113,7 +113,7 @@ openPaywall({ title: 'Emperor β€” Locked', body: 'Emperor opens with the paid release. We\'ll notify you the moment it ships.', - primaryLabel: 'πŸ”” Notify me' + primaryLabel: 'Notify me' }); } else if (verdict.reason === 'needs-signup') { openTierGate({ @@ -158,7 +158,7 @@ -

${title || 'Locked'}

+

${title || 'Locked'}

${body || ''}

@@ -195,7 +195,7 @@ -

${title || 'Locked'}

+

${title || 'Locked'}

${body || 'This feature is locked until the paid release.'}

@@ -241,7 +241,7 @@ localStorage.setItem('heredita.avatar', JSON.stringify(next)); s.freeHatClaimed = true; setSession(s); - setTimeout(() => toast('🎩 Free top hat unlocked β€” enjoy until Aug 28!'), 400); + setTimeout(() => toast('Free top hat unlocked β€” yours until 28 August.'), 400); } catch (_) {} } @@ -273,28 +273,6 @@ document.body.appendChild(lb); } - // ---------- floating chalk dust ---------- - function spawnChalkDust(count = 22) { - if (matchMedia('(prefers-reduced-motion: reduce)').matches) return; - const layer = document.createElement('div'); - layer.className = 'chalk-dust'; - for (let i = 0; i < count; i++) { - const s = document.createElement('span'); - const size = 2 + Math.random() * 4; - const dur = 12 + Math.random() * 22; - const delay = -Math.random() * dur; - s.style.left = Math.random() * 100 + 'vw'; - s.style.width = size + 'px'; - s.style.height = size + 'px'; - s.style.setProperty('--dx', (Math.random() * 120 - 60) + 'px'); - s.style.animationDuration = dur + 's'; - s.style.animationDelay = delay + 's'; - s.style.opacity = (0.10 + Math.random() * 0.35).toFixed(2); - layer.appendChild(s); - } - document.body.appendChild(layer); - } - // ---------- reveal on scroll ---------- let _revealIO = null; function wireReveal() { @@ -319,15 +297,9 @@ // Public hook so dynamically-injected cards can be picked up after fetch. window.HereditaApp = Object.assign(window.HereditaApp || {}, { rewireReveal: wireReveal }); - // ---------- top nav (mobile) ---------- - function wireNavToggle() { - const bar = $('.topbar'); - const btn = $('.nav-toggle'); - if (bar && btn) { - btn.addEventListener('click', () => bar.classList.toggle('mobile-open')); - } - renderUserChip(); - } + // ---------- top nav ---------- + // Drawer, dropdowns and the sliding marker all live in nav.js. This only + // fills in who's signed in. function renderUserChip() { const s = getSession(); @@ -338,12 +310,15 @@ const av = $('.user-chip .avatar'); if (av && !av.classList.contains('countryball')) av.textContent = name.charAt(0).toUpperCase(); - // new structure: .user-block with name + tier-badge + // .user-block holds the name + the tier badge; the whole chip is the + // button that opens the account menu, so the badge is just a label. $$('.user-chip .name').forEach(el => { el.textContent = name; }); $$('.user-chip .tier-badge').forEach(el => { + // For guests the badge just repeats the name ("Guest" over "GUEST"), so + // it only earns its space once there's a real tier to show. + el.hidden = (tier === 'guest'); el.setAttribute('data-tier', tier); - el.setAttribute('href', 'membership.html'); - el.setAttribute('aria-label', 'Membership tier: ' + TIER_LABEL[tier]); + el.setAttribute('title', 'Membership tier: ' + TIER_LABEL[tier]); el.innerHTML = (tier === 'emperor' ? '' : '') + TIER_LABEL[tier]; }); } @@ -715,7 +690,7 @@ // Token's gone β€” clean up. clearSession(); renderUserChip(); - toast('Your session expired β€” please sign in again.'); + toast('Session expired β€” please sign in again.'); } catch (_) {} } @@ -726,7 +701,7 @@ // Mirror local session into the shared .heredita.net cookie so the // game app on app.heredita.net auto-recognizes the signed-in user. syncCookieOnLoad(); - wireNavToggle(); + renderUserChip(); // Verify any stored game-API token in the background (non-blocking). verifyStoredToken(); wirePlayCtas(); @@ -734,6 +709,5 @@ wireHomePage(); wirePreviewShowcase(); wireReveal(); - if (document.body.classList.contains('with-dust')) spawnChalkDust(); }); })(); diff --git a/site/js/avatar.js b/site/js/avatar.js index 7d0aba0..9477f23 100644 --- a/site/js/avatar.js +++ b/site/js/avatar.js @@ -459,7 +459,7 @@ return ` `; }).join('') || `

No countries match "${search}".

`; @@ -490,7 +490,7 @@ return ` `; }).join(''); @@ -509,7 +509,7 @@ function flashLockMsg(msg) { let t = document.querySelector('.toast'); if (!t) { t = document.createElement('div'); t.className = 'toast'; document.body.appendChild(t); } - t.textContent = 'πŸ”’ ' + msg; + t.textContent = msg; t.classList.add('show'); clearTimeout(t._lockT); t._lockT = setTimeout(() => t.classList.remove('show'), 1800); @@ -555,7 +555,7 @@ // toast const t = document.createElement('div'); t.className = 'toast show'; - t.textContent = 'βœ“ Avatar saved!'; + t.textContent = 'βœ“ Avatar saved.'; document.body.appendChild(t); setTimeout(() => t.remove(), 1800); renderUserChips(); diff --git a/site/js/chat.js b/site/js/chat.js index cac3427..c23a6ef 100644 --- a/site/js/chat.js +++ b/site/js/chat.js @@ -79,30 +79,42 @@ mountUI({ db, dbm, username, session }); } + // chat.js is a module, so it runs after app.js has already swept the page + // for .reveal elements. Anything we inject here needs the sweep re-run or it + // stays at opacity 0 forever. + function setRoot(html) { + const root = document.getElementById('chatRoot'); + root.innerHTML = html; + if (window.HereditaApp && typeof window.HereditaApp.rewireReveal === 'function') { + window.HereditaApp.rewireReveal(); + } else { + root.querySelectorAll('.reveal').forEach(el => el.classList.add('in')); + } + return root; + } + // ---- Sign-in gate shown to guests and signed-out users function renderSignInGate(isGuest) { - const root = document.getElementById('chatRoot'); - root.innerHTML = ` + setRoot(`
-

Sign in to chat

+

Sign in to chat

${isGuest - ? "Guest sessions can't post in chat. Create a free account to join the conversation." - : "Chat is for signed-in Heredita members. Make a free account or sign in to join."} + ? "Guests can play, but the rooms need an account. Making one is free." + : "The rooms are for account holders. Sign in, or make one β€” it takes a minute."}

-
`; + `); } // ---- Setup screen shown when config is still the placeholder function renderSetupNotice() { - const root = document.getElementById('chatRoot'); - root.innerHTML = ` + setRoot(`
-

Chat not yet configured

+

Chat isn't wired up yet

The chat backend uses Firebase Realtime Database (free tier). Set it up in ~5 minutes β€” instructions are inside @@ -111,16 +123,15 @@

Once you paste your Firebase config and push, this page becomes a live chat.

-
`; + `); } function renderError(msg) { - const root = document.getElementById('chatRoot'); - root.innerHTML = ` + setRoot(`
-

Chat unavailable

+

Chat is down

${escapeHtml(msg)}

-
`; + `); } // ---- DMs: list of usernames we've started a conversation with, persisted @@ -136,18 +147,17 @@ } function mountUI({ db, dbm, username, session }) { - const root = document.getElementById('chatRoot'); - root.innerHTML = ` + setRoot(`
-

Community Chat

- real-time Β· signed in as ${escapeHtml(username)} +

Chat

+ signed in as ${escapeHtml(username)}
- `; + `); // ---- Render the room + DM lists const roomListEl = document.getElementById('roomList'); diff --git a/site/js/friends.js b/site/js/friends.js index 8f9465a..77c23ad 100644 --- a/site/js/friends.js +++ b/site/js/friends.js @@ -154,9 +154,9 @@ return `
- ${escapeHtml(initial)} + ${escapeHtml(initial)}
-
${escapeHtml(u.username)}
+
${escapeHtml(u.username)}
${escapeHtml(rankLabel(rank))}
diff --git a/site/js/nav.js b/site/js/nav.js new file mode 100644 index 0000000..98fc731 --- /dev/null +++ b/site/js/nav.js @@ -0,0 +1,275 @@ +/* Heredita β€” top navigation behaviour. + * + * Three things live here: + * 1. the chalk dash that slides between tabs + * 2. the dropdown panels (Social, account) + * 3. the mobile drawer + * + * The markup itself is plain HTML in every page β€” this file only + * enhances it, so the nav still works with JS off. + */ +(function () { + 'use strict'; + + var MOBILE = '(max-width: 900px)'; + var nav, marker, topbar; + var groups = []; + + document.addEventListener('DOMContentLoaded', init); + + function init() { + topbar = document.querySelector('.topbar'); + if (!topbar) return; + nav = topbar.querySelector('.primary-nav'); + + markActiveTab(); + initMarker(); + initDropdowns(); + initDrawer(); + initAccountMenu(); + } + + function isMobile() { return window.matchMedia(MOBILE).matches; } + + // --------------------------------------------------------- + // Active tab β€” derived from the URL so no page can get it wrong + // --------------------------------------------------------- + function markActiveTab() { + if (!nav) return; + var here = (location.pathname.split('/').pop() || 'index.html').toLowerCase(); + + nav.querySelectorAll('a.nav-tab').forEach(function (a) { + var target = (a.getAttribute('href') || '').split('/').pop().toLowerCase(); + var on = target === here; + a.classList.toggle('active', on); + if (on) a.setAttribute('aria-current', 'page'); + else a.removeAttribute('aria-current'); + }); + + // A dropdown's toggle lights up when you're on one of its pages. + nav.querySelectorAll('.nav-group').forEach(function (group) { + var toggle = group.querySelector(':scope > .nav-tab'); + var hit = null; + group.querySelectorAll('.nav-menu a').forEach(function (a) { + var target = (a.getAttribute('href') || '').split('/').pop().toLowerCase(); + if (target === here) { + a.classList.add('active'); + a.setAttribute('aria-current', 'page'); + hit = a; + } + }); + if (toggle) toggle.classList.toggle('active', !!hit); + }); + } + + // --------------------------------------------------------- + // Sliding chalk dash + // --------------------------------------------------------- + function initMarker() { + if (!nav) return; + marker = nav.querySelector('.nav-marker'); + if (!marker) return; + + // `instant` places the dash without sliding it in from x=0, which is what + // we want for the initial placement and after a resize. + function settle(instant) { + if (instant) marker.style.transition = 'none'; + moveMarker(nav.querySelector('.nav-tab.active'), false); + if (instant) { + void marker.offsetWidth; // flush, so the next move animates again + marker.style.transition = ''; + } + } + + nav.addEventListener('pointerenter', function (e) { + var tab = e.target.closest ? e.target.closest('.nav-tab') : null; + if (tab) moveMarker(tab, true); + }, true); + + nav.addEventListener('focusin', function (e) { + var tab = e.target.closest('.nav-tab'); + if (tab) moveMarker(tab, true); + }); + + nav.addEventListener('pointerleave', settle); + nav.addEventListener('focusout', function () { + // Let focus land somewhere before deciding where the dash goes. + setTimeout(function () { + if (!nav.contains(document.activeElement)) settle(); + }, 0); + }); + + window.addEventListener('resize', function () { settle(true); }); + + // Place it synchronously. requestAnimationFrame never fires while the tab + // is in the background, and a nav that only appears once you've looked at + // it is worse than one that appears a frame early. + settle(true); + nav.classList.add('marker-live'); + + // Web fonts land after first paint and change every tab's width. + if (document.fonts && document.fonts.ready) { + document.fonts.ready.then(function () { settle(true); }); + } + } + + function moveMarker(tab, hovering) { + if (!marker || !nav) return; + if (isMobile()) return; + if (!tab) { marker.style.width = '0px'; return; } + + var navBox = nav.getBoundingClientRect(); + var tabBox = tab.getBoundingClientRect(); + // Inset a little so the dash reads as an underline, not a bar. + var inset = 9; + marker.style.width = Math.max(0, tabBox.width - inset * 2) + 'px'; + marker.style.transform = 'translateX(' + (tabBox.left - navBox.left + inset) + 'px)'; + nav.classList.toggle('marker-hover', !!hovering); + } + + // --------------------------------------------------------- + // Dropdowns + // --------------------------------------------------------- + function initDropdowns() { + groups = Array.prototype.slice.call(topbar.querySelectorAll('.nav-group')); + + groups.forEach(function (group) { + var toggle = group.querySelector(':scope > .nav-tab, :scope > .user-chip'); + var menu = group.querySelector(':scope > .nav-menu'); + if (!toggle || !menu) return; + + toggle.setAttribute('aria-expanded', 'false'); + if (menu.id) toggle.setAttribute('aria-controls', menu.id); + + toggle.addEventListener('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + toggleGroup(group, !group.classList.contains('open')); + }); + + toggle.addEventListener('keydown', function (e) { + if (e.key === 'ArrowDown') { + e.preventDefault(); + toggleGroup(group, true); + focusItem(menu, 0); + } + }); + + menu.addEventListener('keydown', function (e) { + var items = itemsOf(menu); + var i = items.indexOf(document.activeElement); + if (e.key === 'ArrowDown') { e.preventDefault(); focusItem(menu, i + 1); } + else if (e.key === 'ArrowUp') { e.preventDefault(); focusItem(menu, i - 1); } + else if (e.key === 'Escape') { closeAll(); toggle.focus(); } + else if (e.key === 'Tab' && !e.shiftKey && i === items.length - 1) closeAll(); + }); + }); + + document.addEventListener('click', function (e) { + if (!topbar.contains(e.target)) closeAll(); + }); + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape') closeAll(); + }); + } + + function toggleGroup(group, open) { + groups.forEach(function (g) { + if (g !== group) setOpen(g, false); + }); + setOpen(group, open); + } + + function setOpen(group, open) { + group.classList.toggle('open', open); + var toggle = group.querySelector(':scope > .nav-tab, :scope > .user-chip'); + if (toggle) toggle.setAttribute('aria-expanded', String(open)); + if (open) pointNotch(group); + } + + function closeAll() { groups.forEach(function (g) { setOpen(g, false); }); } + + // Aim the little chalk notch at the middle of whatever opened the menu. + function pointNotch(group) { + if (isMobile()) return; + var toggle = group.querySelector(':scope > .nav-tab, :scope > .user-chip'); + var menu = group.querySelector(':scope > .nav-menu'); + if (!toggle || !menu) return; + var t = toggle.getBoundingClientRect(); + var m = menu.getBoundingClientRect(); + var x = Math.max(16, Math.min(m.width - 16, t.left + t.width / 2 - m.left)); + menu.style.setProperty('--notch', x + 'px'); + } + + function itemsOf(menu) { + return Array.prototype.slice.call(menu.querySelectorAll('a, button')) + .filter(function (el) { return el.offsetParent !== null; }); + } + + function focusItem(menu, i) { + var items = itemsOf(menu); + if (!items.length) return; + items[(i + items.length) % items.length].focus(); + } + + // --------------------------------------------------------- + // Mobile drawer + // --------------------------------------------------------- + function initDrawer() { + var btn = topbar.querySelector('.nav-toggle'); + if (!btn) return; + + btn.setAttribute('aria-expanded', 'false'); + btn.addEventListener('click', function (e) { + e.stopPropagation(); + var open = !topbar.classList.contains('menu-open'); + topbar.classList.toggle('menu-open', open); + btn.setAttribute('aria-expanded', String(open)); + if (!open) closeAll(); + }); + + // Tapping a destination closes the drawer. + if (nav) { + nav.addEventListener('click', function (e) { + if (e.target.closest('a')) closeDrawer(btn); + }); + } + + document.addEventListener('click', function (e) { + if (!topbar.contains(e.target)) closeDrawer(btn); + }); + + window.addEventListener('resize', function () { + if (!isMobile()) closeDrawer(btn); + }); + } + + function closeDrawer(btn) { + topbar.classList.remove('menu-open'); + if (btn) btn.setAttribute('aria-expanded', 'false'); + } + + // --------------------------------------------------------- + // Account menu β€” swaps sign-in / sign-out to match the session + // --------------------------------------------------------- + function initAccountMenu() { + var menu = topbar.querySelector('#accountMenu'); + if (!menu) return; + var S = window.HereditaSession; + var signedIn = !!(S && S.isSignedIn && S.isSignedIn()); + + var out = menu.querySelector('[data-account-signout]'); + var into = menu.querySelector('[data-account-signin]'); + if (out) out.hidden = !signedIn; + if (into) into.hidden = signedIn; + + if (out) { + out.addEventListener('click', function () { + if (!S) return; + S.clear(); + try { localStorage.removeItem('heredita.avatar'); } catch (_) {} + location.href = 'index.html'; + }); + } + } +})(); diff --git a/site/js/social-nav.js b/site/js/social-nav.js deleted file mode 100644 index a788df8..0000000 --- a/site/js/social-nav.js +++ /dev/null @@ -1,177 +0,0 @@ -/* Social popover β€” injects a "Social β–Ύ" button into the primary nav and - * mounts a body-attached popover panel beneath it. - * - * Why body-attached: the topbar's nav uses display:flex with its own per- - * link padding, animated chalk underlines, etc. Putting the menu inside - * the nav fights that cascade. Attaching to with position:fixed - * sidesteps every collision and lets the panel be styled as a first-class - * chalkboard card. - * - * Pages opt in by declaring
-

- Want to preview a tier? Use the Settings page to switch your local profile. -

-
-

FAQ

- questions we keep getting +

Questions we keep getting

What's the difference between Guest and Regular?

-

Gameplay is exactly the same. Regular members get a profile, monthly Heredita Coins, and the free seasonal hat β€” but you can do everything Regular can do as a Guest, minus the goodies.

+

The game is identical. Regular gets you a profile that survives a browser wipe, monthly coins, and the seasonal hat. That is the whole difference.

The free hat β€” really free?

-

Yes. Every Regular account auto-claims a top hat the first time they open the site. It stays on your avatar forever, but the claim window closes Aug 28, 2026.

+

Yes. It claims itself the first time a Regular account opens the site, and it stays on your countryball afterwards. The window shuts 28 August 2026.

What can Emperor do that Regular can't?

@@ -154,19 +167,19 @@

Will my saves stay forever?

- - - - - + + + + + - - - - + + + + + diff --git a/site/search.html b/site/search.html index 5abca75..e3d7ac4 100644 --- a/site/search.html +++ b/site/search.html @@ -5,46 +5,63 @@ Heredita β€” Find Player - +
-
-
- - + -
-
- - 0 - coming soon + Pre-alpha + + + + + + + +
+ + 0 + + + - - - - - -
@@ -52,20 +69,19 @@
-

Find a Player

- search by exact username +

Find a player

+ Exact usernames only
+ class="text-input" style="flex: 1; min-width: 220px;" />

- Exact usernames only β€” the Heredita API does not yet expose fuzzy / partial search. - If the player exists, a friend request is sent immediately. + Partial search is not wired up yet, so spelling counts. If the name exists, a friend request goes out straight away.

@@ -75,7 +91,7 @@

Find a Player

@@ -92,7 +108,7 @@

Player search arrives with the real la
-

Tips

+

Tips

  • Usernames are case-sensitive.
  • You can't friend yourself.
  • @@ -105,19 +121,19 @@

    Tips

    - - - - - + + + + + - - - - + + + + + - - - - + + + + + diff --git a/site/terms.html b/site/terms.html index f4e8fca..ce36fae 100644 --- a/site/terms.html +++ b/site/terms.html @@ -5,7 +5,7 @@ Heredita β€” Terms & Conditions - +