# ankle96 — the ANKLE OS theme

> **Status:** canonical. Living spec. Update this file, then run `ankle96.md → theme.css` sync.
> **Lineage:** textfiles.com / discmaster / Netscape 3 / Win95 chrome / early-web brutalism.
> **Also known as:** "discmaster" (internal nickname), "Web 1.0 revival", "lo-fi GUI", "systems aesthetic".
> The real name is **ankle96**.

---

## 1. Identity

**ankle96** is the native look of the ANKLE operating system. It is the default skin across `aleqth.com`, `ankle.website`, and `ANKLE.app`. Every surface — home, /dada, /surf, /world, /atlas, /make, /market, the @⌘ terminal, the macOS app boot screen — should feel like one cohesive vintage workstation.

It is **not** retro-pastiche. It is a working theme that happens to be cheap to render, legible on any device, and cross-compatible with the theme-atlas system (agents can contribute derivatives like `ankle96-amber`, `ankle96-phosphor`, `ankle96-paper`).

**Design principle:** the OS should feel like an artifact someone found running on a CRT in 1996 — but the agents and data inside it are from 2026.

---

## 2. Tokens (canonical)

These are the variables every surface should reference. They are defined in `theme.css` under `body.theme-ankle96` (and also as the `:root` default).

| token | value | purpose |
|---|---|---|
| `--bg`        | `#c0c0c0` | Netscape / Win95 desktop gray |
| `--bg2`       | `#ffffff` | inner panel fills |
| `--panel`     | `#ffffff` | cards, tables, forms |
| `--chip`      | `#e8e8e8` | quiet secondary surfaces |
| `--warn`      | `#ffffe0` | highlight / selected / notice (legal-pad yellow) |
| `--fg`        | `#000000` | primary text |
| `--muted`     | `#555555` | secondary text |
| `--faint`     | `#777777` | tertiary text / helper |
| `--line`      | `#000000` | 1px solid dividers, table cells, card borders |
| `--link`      | `#0000ee` | unvisited links (Netscape blue) |
| `--visited`   | `#551a8b` | visited links (Netscape purple) |
| `--hover`     | `#ff0000` | hover link / danger accent |
| `--ok`        | `#008000` | online / success |
| `--bevel-out` | `2px outset #fff` | raised controls (buttons, unpressed tabs) |
| `--bevel-in`  | `2px inset #fff`  | sunken controls (inputs, active tabs, pressed buttons) |
| `--serif`     | `"Times New Roman", Times, serif` | headings, body prose |
| `--mono`      | `"Courier New", Courier, monospace` | code, data, meta, labels |

**Never introduce gradients, drop-shadows, border-radius > 0, blur, or glassmorphism.** Flat. 1px. Bevels if you need depth.

---

## 3. Typography

- **Headings:** serif, bold. H1 uses a `::first-letter { font-size: +8px }` trick so capitals drop-cap like a newspaper section head.
- **Body prose:** serif, 15px, line-height 1.5.
- **Data / labels / code / timestamps / metadata:** monospace, 11-12px, `letter-spacing: .04em–.12em`, often `text-transform: uppercase` for labels.
- **Link text:** default browser underline, never removed.

Optional supplementary web fonts (opt-in, not required):
- `"Press Start 2P"` — for chunky pixel headings on hero / boot screens.
- `"VT323"` — for digital counters / clocks / ticker tape.

If either fails to load, Times + Courier must degrade cleanly.

---

## 4. Controls

### Buttons
```
.btn {
  border: 2px outset #fff;
  background: #c0c0c0;
  color: #000;
  font-family: Courier New, monospace;
  padding: 3px 10px;
  border-radius: 0;
}
.btn:active { border: 2px inset #fff; }
.btn.primary { background: #ffffe0; font-weight: bold; }
.btn.danger  { background: #ffdddd; }
```

### Inputs / textareas / selects
```
border: 2px inset #fff;
background: #fff;
font-family: Courier New, monospace;
border-radius: 0;
```
Focus ring: `outline: 1px dotted #0000ee; outline-offset: -3px;` — never a blue glow.

### Tabs / toggles
Inactive = `2px outset #fff` on `#c0c0c0`. Active = `2px inset #fff` on `#ffffe0`.

### Status pills
`border: 1px solid #000; background: #fff; font-family: mono;` with a single colored dot (`#008000` online, `#555` idle, `#cc0000` offline).

---

## 5. Layout

- Top nav: sticky, `#c0c0c0` background, `1px solid #000` bottom border, 8px vertical padding. Links separated by `|` or `***` tokens. Brand on the left, nav + status pill + clock on the right.
- Main column: `max-width: 960–1100px; margin: 0 auto;` with `18–24px` horizontal padding.
- Cards / panels: `background: #fff; border: 1px solid #000; padding: 12–22px; border-radius: 0;`
- Section header: title in serif-bold + `section-meta` in mono-small + `section-more` link, separated by `&middot;` and with a `1px solid #000` bottom-border divider.
- Tables: `border-collapse: collapse; border: 1px solid #000;` cells with `1px solid #000`, header row `background: #e8e8e8;` font-weight bold.
- Lists / rows: no zebra stripes. Use hover `#ffffe0` instead.

---

## 6. Links

- `a { color: #0000ee; text-decoration: underline; }`
- `a:visited { color: #551a8b; }`
- `a:hover { color: #ff0000; }`
- Never remove the underline. Never switch to a custom underline offset.
- Trust the browser defaults; the whole point is that links look like links.

---

## 7. Icons / ornaments

- ASCII separators: `***`, `---`, `|`, `&middot;`, `&rarr;`, `&larr;`.
- Unicode geometric sigils for agent identity: `◈ ⟡ ⬡ ⊛ ◎ ⚡ ◐ ◇ ◆ ▣`.
- No SVG logos with gradients. If you need a logo, use a pixel PNG or a unicode glyph.

---

## 8. Motion

- Default: **no animation.** Instant state changes.
- Allowed:
  - Typed-out characters for agent reply ticker / command output.
  - 1-frame hover color changes (no easing).
  - Rotating archive tiles: 400ms opacity crossfade only.
  - CRT scanline / flicker opt-in (for `/space`, `/world`, `/motion`).
- Forbidden: bouncing, sliding, scaling on hover, parallax, carousel auto-play of more than one axis at a time.

---

## 9. Scoping & variants

The theme is applied via `body.theme-<slug>` OR inherited from the `:root` defaults in `theme.css`. The canonical slug is `discmaster` (historical nickname kept for DB/URL stability — the theme itself is now named **ankle96**). Variants live under the same prefix or as sibling slugs:

**Shipped builtins (in `/api/themes/atlas`):**
- `discmaster` — canonical ankle96, Netscape gray + Times serif + `#0000ee` links.
- `ankle96-next` — NeXT / OpenStep: purple-gray chrome (`#9896b4`), warm ivory panels (`#d8d6cc`), embossed buttons (raised gradient with highlight+shadow border pairs), 3px drop-shadows on windows, dark title bars (`#555063` with white text), NeXT-blue links (`#2a3f77`).
- `paper` — parchment background, brown ink text (book mode).
- `phosphor` — black bg, `#7fff6a` text + scanlines (CRT terminal mode).
- `graphpaper` — cream bg, faint cyan grid, blue ink.
- `midnight-acid` — inverted dark bg with `#c7ff00` acid highlights. Briefly default 2026-04-21.

**User / agent-contributed variants:**
Any user can save a custom palette as a variant via the ⚙ picker's "save as variant…" button. Agents can `POST /api/themes/contribute` with `{slug, name, palette, source_kind:'user'|'scraped'}` and the theme appears in everyone's picker tagged `user` or `scraped`.

The list is sorted by `is_featured` desc, then `use_count` desc — popular user variants rise naturally.

---

## 9a. Custom palette (per-user, live-editable)

As of 2026-04-23, every surface carries a live palette editor behind the ⚙ picker. Users can override any of these 8 tokens individually and see it applied instantly across the whole OS:

| slot | token | what it paints |
|---|---|---|
| desktop bg | `--bg` | page background / workspace |
| text | `--fg` | primary text |
| panel | `--panel` | cards, windows, tables |
| muted | `--muted` | secondary text, labels |
| line | `--line` | borders and dividers |
| link | `--link` | unvisited links |
| visited | `--visited` | visited links |
| highlight | `--highlight` | hover rows, active tabs, notices |

**How it works:**
1. Base theme's palette is applied first (`:root` vars set from atlas).
2. User's `state.customColors` is applied *on top* — a partial override. Empty entries fall through to the base.
3. Both layers persist: `localStorage.ankle_theme_v1` instantly, `/api/theme/set` when signed in → syncs across devices / builds.
4. "Save as variant…" bakes the current custom palette into a new slug in the atlas, available to everyone.

The `×` button per slot clears that single override and reverts to the base theme's color for that token — so users can tweak one thing without losing the rest.

---

## 9b. Universal contrast guarantee

Pages that ship their own hardcoded dark CSS (older FastAPI templates, `prompt_machine.html`, etc.) can't be trusted to pick up `--panel` and `--fg` on their own. `theme.css` now includes a defensive rule that forces any element whose class name contains `panel`, `card`, or `-section` onto the theme's panel background + foreground + line colors. This is scoped to the three body classes where it matters (`discmaster` / `ankle96-next` / `paper`) so dark themes (`phosphor`, `midnight-acid`) are left alone.

When a new legacy page is themed, the preferred steps are:
1. Add `<link rel="stylesheet" href="/theme.css"/>` + `<script src="/theme.js" defer></script>`.
2. If the page has its own inline dark CSS, inject the `<style id="ankle96-override">` block from §11 below.
3. The universal contrast rule handles anything with a reasonable class name; the override block handles hardcoded `rgba(...)` fills.

---

## 10. Where ankle96 is applied

| surface | method |
|---|---|
| `aleqth.com/*` all pages | `theme.css` + `theme.js` injected into every HTML file |
| `ankle.website/*` all pages | `theme.css` + `theme.js` mirrored into own static root |
| `ankle.website/make` | inline `<style id="discmaster-override">` block inside make.html |
| `ankle.website/` homepage | native ankle96 markup (rewritten 2026-04-23) |
| `aleqth.com/prompt` | inline `<style id="ankle96-override">` block inside prompt_machine.html (2026-04-23) |
| `ANKLE.app` boot + sign-in | themed in bundled `index.html` |
| @⌘ terminal widget v2 | themed inside closed shadow DOM (JS-patched) |
| agent-contributed surfaces | auto-inherit via body class + /theme.css |

---

## 11. Override pattern (for legacy pages)

When a page has a hardcoded dark or bespoke theme that can't be cleanly converted, inject this block **after** the page's last `<link rel="stylesheet">` in `<head>`:

```html
<style id="ankle96-override">
  :root{
    --bg:#c0c0c0 !important;
    --text:#000 !important;
    --border:#000 !important;
    --accent:#0000ee !important;
    --mono:"Courier New",Courier,monospace !important;
    --sans:"Times New Roman",Times,serif !important;
  }
  html,body{background:#c0c0c0 !important;color:#000 !important}
  body{font-family:var(--sans) !important}
  a{color:#0000ee !important;text-decoration:underline !important}
  a:visited{color:#551a8b !important}
  .btn,.submit-btn,button{
    background:#c0c0c0 !important;color:#000 !important;
    border:2px outset #fff !important;border-radius:0 !important;
    font-family:var(--mono) !important;
  }
  .btn:active,button:active{border:2px inset #fff !important}
  input,textarea,select{
    background:#fff !important;color:#000 !important;
    border:2px inset #fff !important;border-radius:0 !important;
    font-family:var(--mono) !important;
  }
  .card,.panel,section,[class*="-section"],[class*="-card"],[class*="-panel"]{
    background:#fff !important;border:1px solid #000 !important;border-radius:0 !important;
  }
</style>
```

Then add surface-specific overrides beneath as needed. `/make` is the reference implementation.

---

## 12. Absolute rules

1. **Gray `#c0c0c0` desktop background. Always.** Any non-gray page background needs a written exception.
2. **Times serif for prose, Courier mono for data.** Never swap these.
3. **Blue `#0000ee` links, purple `#551a8b` visited. Underlined. Always.**
4. **`border-radius: 0;` everywhere.** Bevels replace rounded corners.
5. **No box-shadows, no blurs, no gradients.** Flat + 1px black lines + bevels.
6. **1px solid black dividers.** Never light-gray.
7. **Labels and metadata are monospace + letter-spaced + uppercase.** Body prose is serif + normal-case.
8. **Legal-pad `#ffffe0` is the highlight color.** Use it sparingly — for active tabs, notices, hover rows, selected pills.
9. **Green `#008000` = good, Red `#cc0000` = bad, Blue `#0000ee` = interactive.** No other semantic colors.
10. **The @⌘ button stays circular.** One exception to the no-roundness rule. It is the identity carrier, not part of the OS chrome.

---

## 13. History

- **2026-04-19 → 2026-04-23:** theme emerges from `/surf` sessions, spreads to `/world`, `/atlas`, `/space`.
- **2026-04-21:** briefly flirted with "Midnight Acid" (black + `#00ff66`). Reverted same day — preserved as `ankle96-midnight` variant.
- **2026-04-21:** canonical, applied ecosystem-wide (91 HTML files touched).
- **2026-04-23:** named **ankle96**. This spec file created. `ankle.website` homepage rebuilt natively in-theme. `/make` legacy page converted via override pattern.
- **2026-04-23 (later):** `ankle96-next` variant added (NeXT / OpenStep inspired). Per-user live **palette editor** shipped in ⚙ picker — any of the 8 core tokens can be overridden individually, persisted across devices via `/api/theme/set`, and optionally baked into a shared variant. Defensive contrast rule added so any `.panel` / `.card` / `-section` element stays readable on any theme. `/prompt` (prompt_machine.html) fixed — black-on-near-black text replaced with ivory panels + black text.

---

## 14. Maintenance

- This file lives at `/Users/alex/Desktop/solana-agent/_deploy/aleqth/ankle96.md`.
- When tokens change here, update `theme.css` to match and redeploy.
- When a new surface is added, log it in section 10.
- Variants go in section 9; agents are encouraged to submit new ones.
- When in doubt, ask: *"would this look at home on a 1996 NT workstation running Netscape 3?"* If yes, ship. If no, reconsider.
