Docs / v 1.0
The Wall City About Download Paper Models
Documentation / v 1.0

The Arthis.Land
Website Reference.

A complete technical and design reference for the Arthis.Land website — every page, every component, every animation, every visual rule. No credentials, no private data. Pure architecture.

Read time ≈ 18 min Sections 11 Last updated 2026

01Product Overview

Arthis.Land is a vertical-city / room-maker experience. The website is the storefront and lobby for the experience: it lets visitors discover the project, see the wall of community rooms ("games"), watch the city tower fill up, download the desktop build, and join a waitlist for the live drops.

The site is built as a multi-page static site (plain HTML files at root) with one heavy interactive React page (the Wall) and an embedded Unity WebGL build (the City viewer). It uses no bundler at runtime — React is loaded from a CDN and JSX is compiled in the browser by Babel Standalone. The development workflow uses Vite.

Visual identity in one line: brutalist red #E11D1D on near-black or off-white, retro pixel-display typography (Jersey 10 / Jersey 20), mono-spaced micro-labels (JetBrains Mono), with crisp 1px borders, hex / brick grids, vignettes, grain overlays, and clipped-corner buttons.

02Site Map

The site is structured as five primary surfaces plus an interactive React-driven sandbox folder used for design iteration.

RouteFilePurpose
/index.htmlThe Wall — interactive 900-brick gallery of rooms/games.
/about.htmlabout.htmlMarketing page: hero, stats, how it works, drop countdown, features, CTA, download.
/download.htmldownload.htmlDedicated download page with OS buttons and waitlist modal.
/documentationdocumentation/index.htmlThis page — technical and design reference.
/city/city/index.htmlThe City — embeds a Unity WebGL viewer inside an iframe with a loading veil.
/city/viewer/city/viewer/index.htmlBare Unity WebGL host (loader.js + canvas).
/Arthis.Land (Remix)/dev sandboxA duplicate of the Wall code used for live design tweaks via a floating tweaks panel.

Cross-page navigation is light — the footer on download.html links to About, The Wall, and City. The Wall page itself is intentionally chrome-free aside from the logo bubble.

03Tech Stack

The runtime stack is deliberately minimal so the site can be hosted as plain static files.

Note

No framework router, no SSR, no service worker. Pages are independent HTML documents that share the same asset folder.

04File & Folder Structure

Main index/ — tree
Main index/
├── index.html              ← The Wall (entry point)
├── about.html              ← Marketing/about page
├── download.html           ← Download + waitlist page
├── documentation/          ← This documentation site
├── package.json            ← Vite dev script only
├── app.jsx                 ← React app for the Wall
├── tweaks-panel.jsx        ← Floating dev tweaks panel
├── brick-data.js           ← Procedural brick generator
├── styles.css              ← Wall stylesheet
├── supabase-client.js      ← Data client
│
├── assets/
│   ├── arthis-logo.png
│   ├── LOGO-3Edited.png
│   ├── Design metaverse.png
│   ├── logo-splash-bottom.png
│   ├── logo-splash-center.png
│   └── loop.mp4
│
├── Assets made/
│   └── Jersey10-Regular.ttf
│
├── city/
│   ├── index.html
│   └── viewer/
│       ├── index.html
│       ├── Build/
│       └── StreamingAssets/
│
└── Arthis.Land (Remix)/    ← Dev sandbox copy of the Wall

The duplicated Arthis.Land (Remix)/ folder mirrors the production Wall so a designer can hot-tweak the layout via the in-page tweaks panel without affecting the live root files.

05Design System

5.1Color Tokens

The site has two color worlds — the dark world (Wall, Download, City) and the light world (About, Documentation).

Dark world (Wall) — four theme presets

ThemeAccentBackgroundPanel BGText
Ember (default)#ff3a2a#0a0807#141110#f5e8e2
Ash#e8e2d8#0a0a0a#161616#f0ece4
Rust#d96a3a#0c0805#1a120c#f0d9c8
Ink#ff2d2d#050507#0e0e14#e8e8f0

Light world (About / Docs) — swatches

Red#E11D1D
Red dark#9B0000
Red bright#CC1111
Bg#F8F8F8
Bg 2#EFEFEF
Bg 3#E4E4E4
Text#111111
Drop yellow#F0C040

A single conceptual --accent variable is threaded through every interactive surface; swapping it instantly re-skins buttons, focus rings, glow halos, and cursor outlines.

5.2Typography

The typographic system layers three voices:

  1. Display — pixel/retro. Jersey 10 and Jersey 20 for poster-scale headlines (DOWNLOAD, hero titles, modal "Almost there."). They lean nostalgic / arcade.
  2. Body — humanist sans. Inter at weights 300–900 carries paragraphs, lede copy, button names, stats.
  3. Micro / utility — monospaced. JetBrains Mono for eyebrows, version chips (/ V 2.4.1), tags, coordinates, kbd shortcuts, metadata rows. Always uppercase with letter-spacing: 0.18em–0.32em.

Display sizes use clamp(min, fluid, max) for responsive scaling — e.g. clamp(80px, 12vw, 196px) on the download title.

5.3Spatial / Layout Rules

5.4Iconography

All icons are inline SVGs — no external icon library. Conventions:

5.5Motion Tokens

A small set of easings and durations recurs across the site:

06The Wall — index.html

The Wall is the landing experience. It renders a 900-brick mosaic in running-bond pattern (every other row offset by half a brick width) and lets the user navigate it without scrolling.

Document structure

index.html
<head>
  <!-- OpenGraph for sharing, favicon, Google Fonts -->
  <link rel="stylesheet" href="styles.css?v=7">
  <style>/* per-page brick tint overrides */</style>
</head>
<body>
  <div id="root"></div>
  <script src="react.development.js"></script>
  <script src="react-dom.development.js"></script>
  <script src="babel.min.js"></script>
  <script src="supabase.min.js"></script>
  <script src="supabase-client.js"></script>
  <script src="brick-data.js"></script>
  <script type="text/babel" src="tweaks-panel.jsx"></script>
  <script type="text/babel" src="app.jsx"></script>
</body>
Critical

Script loading order matters: Supabase and the data file must execute before the React app mounts because app.jsx reads window.ARTHIS_DATA.

Behaviour

The Wall does not scroll. Instead, the cursor's distance from the center of the viewport drives a continuous pan velocity in the opposite direction — moving the mouse right reveals bricks to the right because the wall translates left. A central deadzone (default radius 60px, configurable 0–200) freezes panning so the user can rest the cursor.

Clicking a brick:

  1. Sets focusedId to that brick's id.
  2. Triggers a 700ms cubic-eased tween that translates the wall so the brick lands at screen center (or off-center left to make room for the detail panel on desktop).
  3. Scales the wall by 1.5× from origin (0,0).
  4. Animates the brick's outline to the accent color and adds a glow shadow.
  5. Marks geometrically adjacent bricks as --adjacent so they get a subtler highlight.
  6. Slides in the detail panel (<DetailPanel>) from the right.

Clicking the brick again, clicking off-brick, or pressing Escape un-focuses and resets the wall scale to . On touch devices the cursor-pan loop is replaced by classic drag-to-pan via pointerdown / pointermove / pointerup.

Pan clamping

The function clampPan() ensures the scaled wall edges always touch the viewport edges — no black gap can appear past the bricks. If the wall is smaller than the stage, it is centered; otherwise pan range is [stageW - scaledW, 0].

Components inside app.jsx

ComponentJob
AppRoot. Owns pan state, focus state, cursor state, RAF loop, touch handlers, and the tween.
BrickOne absolutely-positioned <button> with thumbnail, gradient shade, title, category chip, and pill-shaped PLAY button. Renders a blank decor brick when brick.blank is true.
DetailPanelFixed-position 380px-wide card on the right with hero art, category & year, title, stats (rating, plays, id), description, primary "PLAY NOW" + ghost "+ WISHLIST" buttons. On mobile docks as a bottom sheet.
PixelArrowCustom cursor — a rotating dashed ring whose size scales with pan intensity, plus a pixel-art arrow SVG rotated to face the motion. Hidden when a brick is focused.
TweaksPanelBottom-right floating dev panel exposed only when the host activates it.

Visible-brick culling uses a 240px padding around the viewport: only bricks whose bounding box intersects [-pad, stageW + pad] × [-pad, stageH + pad] are rendered. Keeps DOM size bounded regardless of pan position.

Tweakable parameters (live, via the floating panel)

These are persisted via a postMessage protocol (__edit_mode_set_keys) handled by the parent host; the defaults are written between /*EDITMODE-BEGIN*/ … /*EDITMODE-END*/ comments in app.jsx.

07Procedural Wall Data — brick-data.js

The wall is not authored brick-by-brick. It is procedurally generated each load by buildBricks(), which is then exposed at window.ARTHIS_DATA.

Generation algorithm

  1. Define a deterministic PRNG: mulberry32(seed) returns a function producing repeatable floats in [0, 1).
  2. Pick a vocabulary of 80 evocative two-word titles ("Crimson Gambit", "Hollow Reach", "Iron Lullaby"…) and 15 categories (ADVENTURE, PUZZLE, ARCADE, STRATEGY…).
  3. Loop over 60 rows. Each row picks brick widths from [180, 220, 260, 300, 340, 380, 440] until the row hits target width. Every other row starts at offset -130 to create the running-bond pattern.
  4. For each brick, compute deterministic metadata from its id: hue, year (2018–2026), rating (3.2–5.0), plays (1k–100k), title, category.
  5. Generate a thumbnail SVG as a data: URI: diagonal linear gradient between two HSL stops, an abstract motif chosen from {rising sun arc, triangle range, vertical stripes, concentric rings, diagonal slash}, an SVG turbulence noise layer at opacity 0.4, and a 2-letter monogram glyph at opacity 0.18.
  6. After the real bricks, add a 3-brick-deep "ring" of blank: true decor bricks all around so the edge dissolves into pattern rather than ending abruptly.
  7. Normalize coordinates so the wall starts at (0, 0) and return { bricks, bounds }.

The procedural approach means no API call is needed to render the wall, the layout is stable across refreshes, and the visual diversity is essentially free.

08Wall Stylesheet — styles.css

The stylesheet is organized in labeled sections, top to bottom:

  1. :root — base CSS variables (--accent, --bg, --panel-bg, --text, --muted).
  2. Globals — reset, body, font stack: "Inter", system-ui, "Segoe UI", sans-serif.
  3. Blank bricks.brick--blank with double inset shadow, diagonal 2px-stripe pattern at 4% opacity, and a soft radial highlight in the upper-left.
  4. Stage — fixed viewport, cursor: none on desktop (custom pixel arrow replaces OS cursor), cursor: default on mobile.
  5. Bricksborder-radius: 2px, inset top/bottom highlights and shadows to create a physical brick edge; hover lifts by -2px and shows a 6px drop shadow + 1px white edge.
  6. Focused brick — outlined in 2px accent, with a 0 0 24px accent glow and a heavy 0 12px 40px drop shadow.
  7. Brick face elements: .brick__thumb, .brick__shade, .brick__title, .brick__cat, .brick__play.
  8. Vignette — radial-gradient darkening from center.
  9. Crosshair / Deadzone — faint dashed reticle markers (z-index 21–22).
  10. Pixel cursor.pix-cursor__ring (rotating dashed circle, ringSpin 8s linear infinite), .pix-cursor__arrow (drop-shadow filter in accent).
  11. Chrome overlays.chrome--logo, .chrome--hint, .chrome--coords.
  12. Detail panel — 380px right-docked card, slides in with detailIn keyframes.
  13. Mobile@media (max-width: 720px) collapses chrome, drops cursor to OS default, docks detail panel as a bottom sheet.

09Tweaks Panel — tweaks-panel.jsx

A reusable floating panel — a tiny on-canvas design system editor — used to let a designer tune live values without rebuilding.

What it provides

Host protocol

The panel listens for __activate_edit_mode / __deactivate_edit_mode from window.parent, posts __edit_mode_available on mount, and posts __edit_mode_dismissed when closed. This lets a parent host toggle the panel in sync with its own toolbar.

Visual design

Frosted glass: rgba(250,249,247,0.78) background, backdrop-filter: blur(24px) saturate(160%), 0.5px translucent border, soft inset highlight, 14px radius, 280px wide, drag-by-header to move. Form controls are 26px tall, 7px radius, 0.5px borders. Sliders are 4px tall with 14px white circular thumbs and crisp inset shadows.

10Marketing — about.html

A single long-scroll marketing page. Distinct sections, animated on scroll, each with its own visual treatment.

Section list (top to bottom)

  1. #hero — Full-viewport hero, off-white background, with a <canvas> ambient particle field, a subtle drifting red CSS grid, a floating 120×120 logo, a pulsing red badge pill, hero title with blinking dot, two CTAs (parallelogram red primary + ghost), and a scroll hint.
  2. #stats — Horizontal four-column stat bar with red separators. 2.5rem red numerics, 0.8rem letter-spaced gray labels.
  3. #how — Saturated red #E11D1D background. Two-column grid: a 4-step list (Watch the Drop → Claim → Build → Explore) and an animated building tower showing .owned / .locked / default rooms.
  4. #drop — Drop schedule with a four-segment countdown and upcoming drops list. Uses the yellow accent #F0C040 exclusively.
  5. #explore — Six-card feature grid: Co-Op Exploration, Full Customisation, Scarce Supply, Social Hub, Prestige Address, Live Events.
  6. #cta — Email waitlist input with success state.
  7. #download — Mirror of the standalone download page.

Animation philosophy

Most elements have either anim-fade-left, anim-scale, or anim-fade-in classes toggled .visible by an IntersectionObserver as they enter the viewport. The result is a calm cascade: nothing jumps, everything settles into place.

11Download — download.html

A focused, dark, cinematic page for the download CTA.

Layered composition (back to front, by z-index)

LayerElementPurpose
0<video class="bg-video">Looping background footage of the world.
1.bg-tintTwo stacked linear gradients darkening the edges.
2.grainSVG turbulence noise at 6% opacity, mix-blend-mode: overlay.
3.hex-layerAnimated hexagonal grid (canvas).
5.contentEyebrow, title, logo, lede, buttons, meta.

Hex canvas animation

The hex grid uses a flat-topped hexagon tiling. Each hex has its own pulse phase, offset by its distance from the canvas center plus a tiny per-cell jitter. The phase cycles through: FADE_IN (60)HOLD (180)FADE_OUT (60)GAP_OFF (80). During fade phases both opacity and scale ease via -(cos(πt) - 1) / 2. Active hexes draw a white-filled fill at 10% alpha and a 1px stroke at 55%. Result: a slow radial wave like a heartbeat city map.

Buttons

Two buttons, rendered as wide rectangular cards with 28×28 OS icons (Windows tiles, Apple silhouette), an uppercase mono micro-label ("DOWNLOAD FOR"), a 14–18px humanist OS name ("Windows 10 / 11", "macOS · Universal"), and a right-arrow that nudges right on hover. The primary is solid red on red border; the alternate is frosted glass.

"Coming soon" modal

Triggered by either button. A .modal-backdrop with backdrop-filter: blur(10px), a 560px panel that slides up and scales in, eyebrow with pulsing red dot, headline "Almost there.", and email capture. Valid submit stores the email locally (localStorage.setItem('arthis_notify_email', v)) and switches to green-bordered success. Invalid emails shake the form with a 280ms keyframe.

12City Shell — city/index.html

A minimal shell whose only job is to host the Unity WebGL iframe and gracefully manage the cold-start delay.

Reveal flow

13Unity Viewer — city/viewer/index.html

Bare-minimum page. Dark background #231F20. A single full-viewport <canvas id="unity-canvas">.

city/viewer/index.html
createUnityInstance(canvas, {
  dataUrl:            'Build/ArthisLand(viewer)(unitybuild).data.gz',
  frameworkUrl:       'Build/ArthisLand(viewer)(unitybuild).framework.js.gz',
  codeUrl:            'Build/ArthisLand(viewer)(unitybuild).wasm.gz',
  streamingAssetsUrl: 'StreamingAssets',
  companyName:        'DefaultCompany',
  productName:        'ArthisLand(viewer)',
  productVersion:     '0.1.0',
  matchWebGLToCanvasSize: true,
})
.then(() => window.parent.postMessage({ type: 'unity-ready' }, '*'))
.catch(message => {
  window.parent.postMessage({ type: 'unity-ready' }, '*');  // unblock the shell anyway
  alert(message);
});

A single global UNITY_MOBILE_BREAKPOINT = 900 is set before the loader so the Unity build can adapt its input mode.

14Cross-Cutting Concerns

Responsiveness Strategy

Accessibility

Performance Notes

Data & Persistence

Open Graph / Social

index.html — <head>
<meta property="og:title"       content="ARTHIS.land - The Wall" />
<meta property="og:description" content="Explore the vertical city of Arthis." />
<meta property="og:image"       content="https://arthis.land/assets/LOGO-3Edited.png" />
<meta property="og:url"         content="https://arthis.land/" />
<meta property="og:type"        content="website" />

15State Machines

The Wall — Focus / Pan

┌──────────────┐ │ IDLE │ │ (no focus) │ └──────┬───────┘ mouse moves │ brick click in viewport │ ───────────────► centerBrick(b) ▼ │ ↓ ┌──────────────┐ │ ┌──────────────┐ │ PANNING │◄───┘ │ TWEENING │ │ (cursor- │ │ (700ms) │ │ driven) │ └──────┬───────┘ └──────┬───────┘ │ tween end │ ▼ │ ┌───────────────────────────────┐ │ │ FOCUSED │ │ │ - wallScale = 1.5 │ │ │ - detail panel visible │ │ │ - cursor hidden │ │ │ - panning disabled │ │ └─┬────────┬────────────────────┘ │ click │ click │ Escape / click off │ off │ same │ ◄─────────────┘ brick ◄──────────────────── setFocusedId(null)

City — Iframe Reveal

INITIAL: veil opaque, header off-screen, iframe loading │ │ postMessage 'unity-ready' | 12s elapsed | 30s elapsed ▼ ▼ ▼ reveal() — runs at most once │ ▼ veil → opacity 0 (0.55s) +80ms → header.classList.add('is-ready') veil 'transitionend' → display: none, .game-wrap top = 52px

Download Modal

CLOSED ──(click .js-download)──► OPENING ──(form submit valid)──► SUCCESS ▲ │ │ │ │ invalid │ │ ▼ │ │ SHAKE FORM │ │ │ │ └────(close / backdrop / Esc)────┴──────────────────────────────────┘

16How to Read the Codebase

A short, ordered reading list for a new contributor:

  1. Open index.html — see what scripts load and in what order.
  2. Read brick-data.js from buildBricks() downward — understand the wall's geometry.
  3. Read app.jsx from the bottom (ReactDOM.createRoot) upward — App is the heart.
  4. Skim styles.css for the visual contract (brick, focus, vignette, detail panel).
  5. Read tweaks-panel.jsx only if you need to wire new tweak controls.
  6. Open about.html and download.html — self-contained, no JSX, plain <style> + <script> per file.
  7. Open city/index.html to understand the iframe reveal contract.
  8. The Unity build is opaque from the website's point of view — only the unity-ready postMessage matters.

17Glossary

TermMeaning
BrickA single tile on the Wall. Real bricks are interactive; blank bricks are decorative edge filler.
WallThe entire 900-brick mosaic. A scaled, translated <div> that holds every brick.
StageThe fixed viewport container holding the Wall, vignette, deadzone indicator, and cursor.
DeadzoneCentral circular region where cursor movement does NOT pan the Wall. Lets the user rest.
Running bondMasonry pattern where every other row is offset by half a brick.
Detail panelThe 380px card that slides in when a brick is focused.
Tweaks panelThe floating, draggable design-time control panel.
ChromeNon-interactive overlays (logo, kbd hint, coords HUD) at z-index 40.
VignetteThe radial darkening mask over the stage.
CityThe Unity WebGL experience embedded under /city/.
DropA scheduled release of new rooms.
RoomEquivalent to a "brick" in marketing copy; a player-built space.
End of documentation · v 1.0