Compare commits
6 commits
a302d81f14
...
910b0e42a6
| Author | SHA1 | Date | |
|---|---|---|---|
| 910b0e42a6 | |||
| 5bf233348d | |||
| ecfbed0374 | |||
| 15a6db9c0e | |||
| 1408a52e8b | |||
| b42e4942fa |
96 changed files with 2175 additions and 338 deletions
13
.gitignore
vendored
13
.gitignore
vendored
|
|
@ -1,5 +1,14 @@
|
|||
node_modules/
|
||||
.hugo_build.lock
|
||||
resources/_gen/
|
||||
public/
|
||||
build.log
|
||||
postcss.dev.config.js
|
||||
dev.sh
|
||||
|
||||
# Hugo output and cache (all under site/)
|
||||
site/public/
|
||||
site/resources/
|
||||
site/hugo_stats.json
|
||||
|
||||
# dev.sh generated output (under site/)
|
||||
site/static/css/
|
||||
site/static/vendor/
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
1
dist/asw.css
vendored
Normal file
1
dist/asw.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/asw.min.css
vendored
Normal file
1
dist/asw.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
149
docs/context.md
Normal file
149
docs/context.md
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
# ASW — Agentic Semantic Web: Context Document
|
||||
|
||||
For agent sessions working in this repo. Read this before touching any CSS or layout file.
|
||||
|
||||
---
|
||||
|
||||
## What ASW is
|
||||
|
||||
A CSS framework built for agents, not humans.
|
||||
|
||||
LLMs generating web pages face a specific failure mode: given a class-based framework (Bootstrap, Tailwind), they must memorize presentation strings — `navbar-expand-lg`, `bg-gray-900`, `flex items-center justify-between`. These strings are arbitrary, version-dependent, and hallucination-prone. The agent spends cognition on presentation, not content.
|
||||
|
||||
ASW's answer: **don't give agents a presentation vocabulary. Give them a semantic one.**
|
||||
|
||||
Semantic HTML is what LLMs already produce naturally. `<nav>`, `<article>`, `<aside>`, `<details>` — these express structure through language. ASW makes that HTML look correct without the agent touching CSS.
|
||||
|
||||
**The agent directive:**
|
||||
> Write semantic HTML. Use `data-*` attributes for vault-native concepts. Never write `style=`. Never invent classes. If ASW can't express it, document the gap.
|
||||
|
||||
---
|
||||
|
||||
## The core mechanism
|
||||
|
||||
Two layers of expressiveness:
|
||||
|
||||
**1. Semantic HTML elements** — styled directly, no classes needed:
|
||||
```html
|
||||
<nav> → top navigation bar
|
||||
<article> → content card or post
|
||||
<aside> → sidebar or TOC
|
||||
<details> → accordion
|
||||
<dialog> → modal
|
||||
```
|
||||
|
||||
**2. `data-*` attributes** — for concepts HTML has no element for:
|
||||
```html
|
||||
data-task="done|todo|blocked|wip"
|
||||
data-callout="note|tip|warning|error"
|
||||
data-status="active|sleeping|blocked"
|
||||
data-wikilink → vault note link
|
||||
data-layout="docs|grid-2|grid-3|console"
|
||||
data-toc → in-page table of contents
|
||||
data-role="breadcrumb|steps|accordion|card"
|
||||
```
|
||||
|
||||
The vocabulary is semantic, not stylistic. `data-task="blocked"` expresses meaning — the CSS handles appearance.
|
||||
|
||||
---
|
||||
|
||||
## Two repos, one framework
|
||||
|
||||
### `agentic-semantic-web/` (legacy)
|
||||
The original standalone version. Single built file (`dist/agentic.css`), no dependencies, `--asw-*` prefixed variables. Proves the concept. Still deployed on Trentuna. Architecture doc and philosophy live here.
|
||||
|
||||
### `asw/` (current — this repo)
|
||||
The Hugo-based rewrite. Same philosophy, rebuilt on Open Props as primitive token source. Multi-layer CSS architecture. Serves as both the framework source and its own documentation site.
|
||||
|
||||
The two diverge in:
|
||||
- Variable naming: legacy uses `--asw-*` prefix, current uses unprefixed semantic aliases (`--text`, `--surface`, `--accent`)
|
||||
- Token source: legacy has its own scale, current builds on Open Props
|
||||
- Delivery: legacy is a single file, current is a Hugo site with PostCSS build
|
||||
|
||||
---
|
||||
|
||||
## Current architecture (`asw/`)
|
||||
|
||||
### Hugo site
|
||||
```
|
||||
content/
|
||||
docs/ → framework documentation (type: docs)
|
||||
articles/ → short-form writing — no TOC (type: article)
|
||||
essays/ → long-form writing — TOC, description (type: essay)
|
||||
notes/ → exported PKM vault notes (type: notes)
|
||||
layouts/
|
||||
docs/ → three-column docs layout
|
||||
console/ → docs variant: sidebar flush to viewport edge
|
||||
notes/ → notes/vault content layout
|
||||
essay/ → long-form essay layout (TOC)
|
||||
```
|
||||
|
||||
### CSS layer stack
|
||||
```
|
||||
assets/css/
|
||||
main.css → entry point, @import chain
|
||||
layers/
|
||||
00-reset.css → normalize + box-sizing
|
||||
01-asw.css → design tokens (Open Props aliases + ASW additions)
|
||||
02-semantic.css → typography, prose, syntax highlighting base
|
||||
03-components.css → landmarks + forms + components (being split — see refactor plan)
|
||||
04-data-attrs.css → all data-* attribute patterns
|
||||
05-utilities.css → text helpers, visibility, accessibility
|
||||
06-charts.css → Charts.css-inspired data visualization
|
||||
07-chroma.css → Hugo Chroma syntax highlighting
|
||||
08-layout.css → layout systems (docs, console, grids, prose)
|
||||
08a-essay.css → essay layout variant
|
||||
09-landing.css → landing page styles
|
||||
```
|
||||
|
||||
### Token system
|
||||
Open Props provides primitive scales (`--color-1..16`, `--size-1..15`, `--font-size-0..8`).
|
||||
`01-asw.css` aliases these to semantic names:
|
||||
```css
|
||||
--surface: var(--color-14) /* not --color-14 directly */
|
||||
--text: var(--color-6)
|
||||
--accent: var(--color-8)
|
||||
--space-4: var(--size-3)
|
||||
```
|
||||
**Rule:** layers 02–08 must only reference semantic aliases, never Open Props primitives directly.
|
||||
|
||||
---
|
||||
|
||||
## Active work
|
||||
|
||||
### CSS layer refactor
|
||||
`docs/css-refactor-plan.md` — full step-by-step plan.
|
||||
|
||||
The current `03-components.css` is a mixed bag: landmark styling (nav, article, footer), form elements, and true components (dialog, accordion) are all in one file. The plan splits it into purpose-specific files and fixes ~40 Open Props primitive leaks across the codebase.
|
||||
|
||||
**Do not start any CSS work without reading the refactor plan first.**
|
||||
|
||||
### Layout development
|
||||
Two layouts exist: `docs` (standard three-column) and `console` (sidebar flush to viewport edge). The console layout is a prototype — no Hugo content type uses it in production yet.
|
||||
|
||||
### Pending CSS cleanup (`docs/css-html-cleanup-todo.md`)
|
||||
- Hardcoded `"On this page"` strings need i18n before adding a second language
|
||||
|
||||
---
|
||||
|
||||
## Design principles
|
||||
|
||||
**Engine-agnostic** — Templates are prototyped in Hugo but must be portable to Flask/Jinja2. Hugo-specific features (render hooks, shortcodes) are acceptable prototyping tools, not load-bearing design. Template logic should express *what*, not *how*.
|
||||
|
||||
**No CSS classes on content** — The framework uses element selectors and `data-*` attributes. Class selectors (`[data-nav="sidebar"]`, `[data-role="breadcrumb"]`) are allowed for disambiguation but never for presentation.
|
||||
|
||||
**Semantic token naming** — Aliases express role, not value. `--surface` not `--gray-dark-3`. `--weight-medium` not `--font-weight-5`.
|
||||
|
||||
**Agent-first means sparse vocabulary** — Every `data-*` attribute added to the vocabulary is a cognitive load on every agent using the framework. Add only what cannot be expressed by existing semantic HTML.
|
||||
|
||||
---
|
||||
|
||||
## Lineage
|
||||
|
||||
| Source | What was taken |
|
||||
|--------|----------------|
|
||||
| Pico CSS | Component patterns (buttons, forms) — ported and modernized |
|
||||
| Open Props | Primitive token scales — used as foundation, not bundled |
|
||||
| Charts.css | `data-*` attribute pattern for extending HTML vocabulary |
|
||||
|
||||
ASW is not built on any of these. It learned from them.
|
||||
17
docs/css-html-cleanup-todo.md
Normal file
17
docs/css-html-cleanup-todo.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# CSS / HTML cleanup — loose ends
|
||||
|
||||
Found during sidebar/TOC refactor session (2026-04-11).
|
||||
|
||||
## Redundant resets
|
||||
|
||||
- `nav[data-nav="sidebar"] ul li { margin: 0; padding: 0 }` — browser default for `<li>` already has no margin/padding. No-op, remove.
|
||||
- `aside[data-toc] nav ul li { margin: 0; padding: 0 }` — same.
|
||||
|
||||
## Semantic HTML
|
||||
|
||||
- `<small>← Previous</small>` and `<small>Next →</small>` in prev/next footer (`docs/single.html`, `vault/single.html`) — `<small>` is fine print, not a directional label. Replace with something appropriate.
|
||||
- `role="main"` on `<article>` in `docs/single.html` — redundant and misleading. `<article>` does not map to the `main` landmark; `<main>` does. Remove the attribute.
|
||||
|
||||
## i18n
|
||||
|
||||
- `"On this page"` is hardcoded in `docs/single.html` and `vault/single.html`. Move to Hugo i18n strings or a site param before adding any second language.
|
||||
223
docs/css-refactor-plan.md
Normal file
223
docs/css-refactor-plan.md
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
# CSS Layer Refactor Plan
|
||||
|
||||
> **Superseded by:** `openspec/changes/css-refactor/` — this document is kept as historical reference. Agents should read the OpenSpec change tasks, not this file.
|
||||
|
||||
**Project:** ASW — Agentic Semantic Web
|
||||
**Goal:** Restructure CSS layers to clean architecture, alias all Open Props primitives through `01-tokens.css`, redistribute misplaced content, remove unused values.
|
||||
**Method:** One atomic step per agent session. Build check after every step. No step touches more than two files.
|
||||
|
||||
---
|
||||
|
||||
## Current state
|
||||
|
||||
```
|
||||
assets/css/
|
||||
main.css ← entry point, @import chain
|
||||
layers/
|
||||
00-reset.css
|
||||
01-asw.css ← tokens + editorial rules (mixed)
|
||||
02-semantic.css ← typography + prose styles
|
||||
03-components.css ← landmarks + forms + components (mixed)
|
||||
04-data-attrs.css ← data-* attribute patterns
|
||||
05-utilities.css ← utility helpers
|
||||
06-charts.css ← charts (uses --size-N primitives directly)
|
||||
07-chroma.css ← syntax highlighting
|
||||
08-layout.css ← layout systems
|
||||
08a-essay.css ← paper layout variant
|
||||
09-landing.css ← landing page styles
|
||||
```
|
||||
|
||||
## Target state
|
||||
|
||||
```
|
||||
assets/css/
|
||||
main.css ← updated import chain
|
||||
layers/
|
||||
00-reset.css (unchanged)
|
||||
01-tokens.css ← renamed from 01-asw.css, pure :root only, no rules
|
||||
02-typography.css ← renamed from 02-semantic.css, prose + heading defaults
|
||||
03-landmarks.css ← NEW: nav, article, aside, section, footer, hgroup
|
||||
04-forms.css ← NEW: input, select, textarea, button
|
||||
05-components.css ← slimmed 03-components.css: dialog, accordion, breadcrumb, steps
|
||||
06-navigation.css ← NEW: sidebar nav, TOC (aside[data-toc])
|
||||
07-data-attrs.css ← renamed from 04-data-attrs.css
|
||||
08-utilities.css ← renamed from 05-utilities.css
|
||||
09-charts.css ← renamed from 06-charts.css, primitives fixed
|
||||
10-chroma.css ← renamed from 07-chroma.css
|
||||
11-layout.css ← renamed from 08-layout.css + 08a-essay.css merged
|
||||
12-landing.css ← renamed from 09-landing.css
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Primitive leak inventory
|
||||
|
||||
All Open Props primitives used directly in layers (must be aliased through 01-tokens.css):
|
||||
|
||||
### `--font-weight-N` (most common leak)
|
||||
| Primitive | Semantic alias to add | Used in |
|
||||
|---|---|---|
|
||||
| `--font-weight-4` | `--weight-normal` | 03, 02, 08 |
|
||||
| `--font-weight-5` | `--weight-medium` | 03, 02, 08 |
|
||||
| `--font-weight-6` | `--weight-semibold` | 03 |
|
||||
| `--font-weight-7` | `--weight-bold` | 02, 08, 09 |
|
||||
|
||||
### `--size-N` / `--size-px-N`
|
||||
| Primitive | Alias | Notes |
|
||||
|---|---|---|
|
||||
| `--size-1` | `--space-1` (exists) | 06-charts |
|
||||
| `--size-2` | `--space-2` (exists) | 06-charts |
|
||||
| `--size-3` | `--space-4` (exists) | 03, 06-charts, 07-chroma |
|
||||
| `--size-4` | needs `--space-5a: 1.25rem` | 03-components article padding |
|
||||
| `--size-px-12` | `--dropdown-min-width` | 03-components nav dropdown |
|
||||
|
||||
### `--shadow-N`
|
||||
| Primitive | Alias to add |
|
||||
|---|---|
|
||||
| `--shadow-2` | `--shadow-dropdown` |
|
||||
| `--shadow-4` | `--shadow-modal` |
|
||||
|
||||
### `--border-size-2`
|
||||
| Primitive | Alias to add |
|
||||
|---|---|
|
||||
| `--border-size-2` | `--focus-ring-width` |
|
||||
|
||||
---
|
||||
|
||||
## Step-by-step tasks
|
||||
|
||||
Each step = one agent session. Read only the files listed. Build after every step.
|
||||
|
||||
### STEP 1 — Add missing aliases to `01-asw.css` ✅ prerequisites: none
|
||||
**Files:** `layers/01-asw.css` only
|
||||
**Action:** Add to `:root {}`:
|
||||
```css
|
||||
/* Font weights */
|
||||
--weight-normal: var(--font-weight-4);
|
||||
--weight-medium: var(--font-weight-5);
|
||||
--weight-semibold: var(--font-weight-6);
|
||||
--weight-bold: var(--font-weight-7);
|
||||
|
||||
/* Shadows */
|
||||
--shadow-dropdown: var(--shadow-2);
|
||||
--shadow-modal: var(--shadow-4);
|
||||
|
||||
/* Focus ring */
|
||||
--focus-ring-width: var(--border-size-2);
|
||||
|
||||
/* Dropdown */
|
||||
--dropdown-min-width: var(--size-px-12);
|
||||
|
||||
/* Gap in spacing scale */
|
||||
--space-5a: 1.25rem; /* between --space-4 (1rem) and --space-5 (1.5rem) */
|
||||
```
|
||||
**Verify:** `hugo server` builds without error. No visual change.
|
||||
|
||||
---
|
||||
|
||||
### STEP 2 — Extract editorial rules out of `01-asw.css` ✅ prerequisites: Step 1
|
||||
**Files:** `layers/01-asw.css`, `layers/08-layout.css`
|
||||
**Action:**
|
||||
- Remove from `01-asw.css` the EDITORIAL DEFAULTS section (last ~10 lines: `body > nav` padding rule + `[data-layout="docs"] > article` max-width rule)
|
||||
- Move `body > nav { padding-inline: ... }` to `03-components.css` under the Navigation section
|
||||
- Move `[data-layout="docs"] > article { max-width: var(--width-prose) }` to `08-layout.css` under the docs layout section
|
||||
**Verify:** Build passes. Nav centering and docs prose width unchanged visually.
|
||||
|
||||
---
|
||||
|
||||
### STEP 3 — Rename `01-asw.css` → `01-tokens.css` ✅ prerequisites: Step 2
|
||||
**Files:** `layers/01-asw.css`, `main.css`
|
||||
**Action:** Rename file, update `@import` in `main.css`.
|
||||
**Verify:** Build passes.
|
||||
|
||||
---
|
||||
|
||||
### STEP 4 — Fix primitive leaks in `03-components.css` ✅ prerequisites: Step 1
|
||||
**Files:** `layers/03-components.css` only
|
||||
**Action:** Replace all primitive references with aliases:
|
||||
- `var(--font-weight-4)` → `var(--weight-normal)`
|
||||
- `var(--font-weight-5)` → `var(--weight-medium)` (including the fallback `, 500` variant)
|
||||
- `var(--font-weight-6)` → `var(--weight-semibold)`
|
||||
- `var(--size-3) var(--size-4)` → `var(--space-4) var(--space-5a)` (article padding, line 455)
|
||||
- `var(--size-px-12)` → `var(--dropdown-min-width)`
|
||||
- `var(--shadow-2)` → `var(--shadow-dropdown)`
|
||||
- `var(--shadow-4)` → `var(--shadow-modal)`
|
||||
- `var(--border-size-2)` → `var(--focus-ring-width)` (both occurrences)
|
||||
**Verify:** Build passes. No visual change.
|
||||
|
||||
---
|
||||
|
||||
### STEP 5 — Fix primitive leaks in `06-charts.css` ✅ prerequisites: Step 1
|
||||
**Files:** `layers/06-charts.css` only
|
||||
**Action:** Replace all `--size-1/2/3` with `--space-1/2/4` respectively.
|
||||
**Verify:** Build passes. Charts render unchanged.
|
||||
|
||||
---
|
||||
|
||||
### STEP 6 — Fix primitive leaks in remaining files ✅ prerequisites: Step 1
|
||||
**Files:** `layers/02-semantic.css`, `layers/07-chroma.css`, `layers/08-layout.css`, `layers/09-landing.css` — one at a time
|
||||
**Action:** Same find-replace for `--font-weight-N`, `--size-N` primitives.
|
||||
**Verify:** Build passes after each file.
|
||||
|
||||
---
|
||||
|
||||
### STEP 7 — Create `03-landmarks.css` and extract from `03-components.css` ✅ prerequisites: Step 4
|
||||
**Files:** `layers/03-components.css`, new `layers/03-landmarks.css`, `main.css`
|
||||
**Action:** Move these sections out of `03-components.css` into `03-landmarks.css`:
|
||||
- `body > nav` (the global nav landmark, lines ~259–442)
|
||||
- `article` (lines ~444–506)
|
||||
- `dt`, `dd` (lines ~508–529)
|
||||
- `section + section`, `hgroup` (lines ~531–559)
|
||||
- `body > footer` (lines ~561–572)
|
||||
Add `@import "./layers/03-landmarks.css"` to `main.css` before `03-components.css`.
|
||||
**Verify:** Build passes. All landmark styles render unchanged.
|
||||
|
||||
---
|
||||
|
||||
### STEP 8 — Create `04-forms.css` and extract from `03-components.css` ✅ prerequisites: Step 7
|
||||
**Files:** `layers/03-components.css`, new `layers/04-forms.css`, `main.css`
|
||||
**Action:** Move out of `03-components.css`:
|
||||
- Buttons (lines ~14–75)
|
||||
- Form Elements (lines ~77–258)
|
||||
**Verify:** Build passes.
|
||||
|
||||
---
|
||||
|
||||
### STEP 9 — Create `06-navigation.css` and extract from `03-components.css` ✅ prerequisites: Step 8
|
||||
**Files:** `layers/03-components.css`, new `layers/06-navigation.css`, `main.css`
|
||||
**Action:** Move out of `03-components.css`:
|
||||
- `nav[data-nav="sidebar"]` section
|
||||
- `aside[data-toc]` section
|
||||
**Verify:** Build passes. Sidebar and TOC render unchanged.
|
||||
|
||||
---
|
||||
|
||||
### STEP 10 — Rename remaining files + update `main.css` ✅ prerequisites: Steps 7–9
|
||||
**Files:** all layer files + `main.css`
|
||||
**Action:** Rename files to final numbers, merge `08a-essay.css` into `11-layout.css`, update all `@import` statements.
|
||||
**Verify:** Build passes.
|
||||
|
||||
---
|
||||
|
||||
### STEP 11 — Audit unused tokens ✅ prerequisites: Step 10
|
||||
**Method:** Tooling only — do not guess.
|
||||
```bash
|
||||
# Build the CSS, then grep for each token name
|
||||
hugo --minify
|
||||
grep -o 'var(--[^)]+)' public/**/*.css | sort | uniq > /tmp/used-tokens.txt
|
||||
grep -o '\-\-[a-z][^:]*:' assets/css/layers/01-tokens.css | sort > /tmp/defined-tokens.txt
|
||||
diff /tmp/defined-tokens.txt /tmp/used-tokens.txt
|
||||
```
|
||||
Review diff. Remove confirmed unused tokens from `01-tokens.css`.
|
||||
**Verify:** Build passes. Spot-check 3–4 pages visually.
|
||||
|
||||
---
|
||||
|
||||
## Rules for all agents
|
||||
|
||||
1. Read only the files listed for your step — nothing else
|
||||
2. Run build after every step before reporting done
|
||||
3. Do not rename variables not listed in this plan
|
||||
4. Do not touch `main.css` unless the step explicitly says to
|
||||
5. Do not combine two steps in one session
|
||||
6. If a primitive is found that isn't in the inventory above, add it to the plan doc and stop — do not fix it unilaterally
|
||||
73
docs/template-h1-title.md
Normal file
73
docs/template-h1-title.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Template Design: Handling the Markdown H1 / Front Matter Title Conflict
|
||||
|
||||
## The Problem
|
||||
|
||||
Standard markdown convention — Obsidian, agent-written files, generic `.md` — opens
|
||||
with a level-1 heading as the document title:
|
||||
|
||||
```markdown
|
||||
# My Note Title
|
||||
|
||||
Body text...
|
||||
```
|
||||
|
||||
Hugo templates also render a title from front matter:
|
||||
|
||||
```html
|
||||
<h1>{{ .Title }}</h1>
|
||||
```
|
||||
|
||||
When both exist, the page gets two `<h1>` elements: one from the template,
|
||||
one from the rendered markdown content. The content one also carries an
|
||||
auto-generated `id` attribute from Hugo's heading anchor renderer.
|
||||
|
||||
## The Two Template Contracts
|
||||
|
||||
**Default (`_default/single.html`)** — bare markdown, minimal or no front matter.
|
||||
The `# Title` in content IS the h1. The template header renders only metadata
|
||||
(type, date, author, tags). No title rendered from front matter.
|
||||
|
||||
**Vault (`vault/single.html`)** — enriched front matter (`title`, `type`, `date`,
|
||||
`author`, `tags`). Front matter `title` is authoritative. The `# Title` in content
|
||||
is still present (markdown convention) but must be suppressed.
|
||||
|
||||
## The Fix: Engine-Agnostic Regex Strip
|
||||
|
||||
When a template owns the title (renders `<h1>{{ .Title }}</h1>` from front matter),
|
||||
strip the first h1 from the rendered content before outputting it.
|
||||
|
||||
**Hugo:**
|
||||
```
|
||||
{{ replaceRE "<h1[^>]*>.*?</h1>" "" .Content 1 | safeHTML }}
|
||||
```
|
||||
|
||||
**Jinja2 / Flask:**
|
||||
```python
|
||||
import re
|
||||
content = re.sub(r'<h1[^>]*>.*?</h1>', '', content, count=1, flags=re.DOTALL)
|
||||
```
|
||||
|
||||
**Nunjucks / Liquid / any engine:** equivalent string replace on the rendered HTML.
|
||||
|
||||
This is a string operation on already-rendered HTML, not a template-engine concept.
|
||||
It ports to any engine without modification.
|
||||
|
||||
## Why Not Other Approaches
|
||||
|
||||
- **Author convention** (don't write `# Title` in vault files): breaks compatibility
|
||||
with the entire markdown ecosystem.
|
||||
- **Hugo render hooks** (`layouts/vault/_markup/render-heading.html`): Hugo-specific,
|
||||
not portable.
|
||||
- **CSS `display: none`**: h1 still exists in DOM — screen readers read it,
|
||||
search engines index it. Semantically wrong.
|
||||
|
||||
## Engine-Agnostic Principle
|
||||
|
||||
ASW templates are prototyped in Hugo but must be portable to Flask/Jinja2 or
|
||||
any other engine. Template logic should express *what*, not *how*:
|
||||
|
||||
- What: "strip h1 from content if front matter title is present"
|
||||
- How: engine-specific implementation of the same string operation
|
||||
|
||||
Hugo-specific features (render hooks, shortcodes) are acceptable as prototyping
|
||||
tools but should not become load-bearing parts of the template design.
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>
|
||||
{{- if .IsHome -}}
|
||||
{{ .Site.Title }}
|
||||
{{- else -}}
|
||||
{{ .Title }} · {{ .Site.Title }}
|
||||
{{- end -}}
|
||||
</title>
|
||||
{{- with .Description }}<meta name="description" content="{{ . }}">{{- end }}
|
||||
{{- if not .Description }}{{- with .Site.Params.description }}<meta name="description" content="{{ . }}">{{- end }}{{- end }}
|
||||
|
||||
{{- /* ── Meta partials ─────────────────────────────────────────── */}}
|
||||
{{- partial "meta/seo.html" . -}}
|
||||
{{- partial "meta/og.html" . -}}
|
||||
{{- partial "meta/ai-disclosure.html" . -}}
|
||||
{{- partial "meta/json-ld.html" . -}}
|
||||
|
||||
{{- /* ── CSS — fingerprinted via Hugo Pipes ─────────────────────── */}}
|
||||
{{ $css := resources.Get "css/asw-built.css" | minify | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $css.RelPermalink }}">
|
||||
|
||||
{{- range .AlternativeOutputFormats -}}
|
||||
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
|
||||
{{- end }}
|
||||
60
openspec/changes/css-refactor/proposal.md
Normal file
60
openspec/changes/css-refactor/proposal.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Proposal: CSS Layer Refactor
|
||||
|
||||
## Intent
|
||||
|
||||
Restructure CSS layers to clean architecture: alias all Open Props primitives through `01-tokens.css`, split the monolithic `03-components.css` into purpose-specific files, redistribute misplaced content, and rename files to match their actual responsibilities.
|
||||
|
||||
**Goal: each CSS file has a single clear purpose, and no file references Open Props primitives directly.**
|
||||
|
||||
This plan was originally documented in `docs/css-refactor-plan.md` and is imported here as an OpenSpec change for tracking and execution.
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
- Add missing semantic aliases to token file (~10 new aliases)
|
||||
- Extract editorial rules out of token file into their proper layers
|
||||
- Rename `01-asw.css` → `01-tokens.css` (pure tokens, no rules)
|
||||
- Fix all Open Props primitive leaks across all layers
|
||||
- Split `03-components.css` into: `03-landmarks.css`, `04-forms.css`, slimmed `05-components.css`, `06-navigation.css`
|
||||
- Rename all files to final numbering scheme
|
||||
- Merge `08a-essay.css` into layout layer
|
||||
- Audit and remove unused tokens
|
||||
|
||||
### Out of Scope
|
||||
- New CSS features or components
|
||||
- Layout changes
|
||||
- Content changes
|
||||
- Repo restructure (separate change, happens first)
|
||||
|
||||
### Current → Target Layer Map
|
||||
|
||||
```
|
||||
CURRENT TARGET
|
||||
═══════ ══════
|
||||
00-reset.css 00-reset.css (unchanged)
|
||||
01-asw.css ──▶ 01-tokens.css (pure :root, no rules)
|
||||
02-semantic.css ──▶ 02-typography.css
|
||||
03-components.css ──▶ 03-landmarks.css (nav, article, footer, hgroup)
|
||||
──▶ 04-forms.css (inputs, buttons, selects)
|
||||
──▶ 05-components.css (dialog, accordion, breadcrumb)
|
||||
──▶ 06-navigation.css (sidebar, TOC)
|
||||
04-data-attrs.css ──▶ 07-data-attrs.css
|
||||
05-utilities.css ──▶ 08-utilities.css
|
||||
06-charts.css ──▶ 09-charts.css
|
||||
07-chroma.css ──▶ 10-chroma.css
|
||||
08-layout.css + 08a-essay ──▶ 11-layout.css (merged)
|
||||
09-landing.css ──▶ 12-landing.css
|
||||
```
|
||||
|
||||
## Approach
|
||||
|
||||
One atomic step per session. Build check after every step. No step touches more than two files. Full plan in `docs/css-refactor-plan.md`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Depends on:** `repo-restructure` (files must be in `src/layers/` first)
|
||||
|
||||
## Risks
|
||||
|
||||
- **Visual regression** — mitigated by build + visual check after each step
|
||||
- **Specificity changes** — layer reordering could affect cascade. Mitigated by keeping relative order.
|
||||
94
openspec/changes/css-refactor/tasks.md
Normal file
94
openspec/changes/css-refactor/tasks.md
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# Tasks: CSS Layer Refactor
|
||||
|
||||
Imported from `docs/css-refactor-plan.md`. Each step = one agent session.
|
||||
|
||||
**Prerequisite:** `repo-restructure` change must be complete. All files in `src/layers/`.
|
||||
|
||||
---
|
||||
|
||||
## Task 1 — Add missing aliases to token file
|
||||
**Files:** `src/layers/01-asw.css` (pre-rename)
|
||||
**Action:** Add semantic aliases for `--font-weight-N`, `--shadow-N`, `--border-size-2`, `--size-px-12`, and `--space-5a` gap.
|
||||
**Acceptance:** Build passes. No visual change. New aliases exist in `:root`.
|
||||
|
||||
---
|
||||
|
||||
## Task 2 — Extract editorial rules from token file
|
||||
**Files:** `src/layers/01-asw.css`, `src/layers/08-layout.css`
|
||||
**Action:** Move `body > nav` padding rule to `03-components.css`. Move `[data-layout="docs"] > article` max-width to `08-layout.css`. Token file becomes pure `:root` only.
|
||||
**Acceptance:** Build passes. Nav centering and docs prose width unchanged.
|
||||
|
||||
---
|
||||
|
||||
## Task 3 — Rename `01-asw.css` → `01-tokens.css`
|
||||
**Files:** `src/layers/01-asw.css`, `src/main.css`
|
||||
**Action:** Rename file, update `@import`.
|
||||
**Acceptance:** Build passes.
|
||||
|
||||
---
|
||||
|
||||
## Task 4 — Fix primitive leaks in `03-components.css`
|
||||
**Files:** `src/layers/03-components.css`
|
||||
**Action:** Replace all `--font-weight-N`, `--size-N`, `--shadow-N`, `--border-size-N` with semantic aliases.
|
||||
**Acceptance:** Build passes. No visual change.
|
||||
|
||||
---
|
||||
|
||||
## Task 5 — Fix primitive leaks in `06-charts.css`
|
||||
**Files:** `src/layers/06-charts.css`
|
||||
**Action:** Replace `--size-1/2/3` with `--space-1/2/4`.
|
||||
**Acceptance:** Build passes. Charts render unchanged.
|
||||
|
||||
---
|
||||
|
||||
## Task 6 — Fix primitive leaks in remaining files
|
||||
**Files:** `src/layers/02-semantic.css`, `src/layers/07-chroma.css`, `src/layers/08-layout.css`, `src/layers/09-landing.css`
|
||||
**Action:** Replace all remaining `--font-weight-N`, `--size-N` primitives with semantic aliases.
|
||||
**Acceptance:** Build passes after each file.
|
||||
|
||||
---
|
||||
|
||||
## Task 7 — Create `03-landmarks.css`, extract from `03-components.css`
|
||||
**Files:** `src/layers/03-components.css`, new `src/layers/03-landmarks.css`, `src/main.css`
|
||||
**Action:** Move landmark sections (nav, article, dt/dd, section, hgroup, footer) to new file.
|
||||
**Acceptance:** Build passes. All landmark styles render unchanged.
|
||||
|
||||
---
|
||||
|
||||
## Task 8 — Create `04-forms.css`, extract from `03-components.css`
|
||||
**Files:** `src/layers/03-components.css`, new `src/layers/04-forms.css`, `src/main.css`
|
||||
**Action:** Move buttons and form elements to new file.
|
||||
**Acceptance:** Build passes.
|
||||
|
||||
---
|
||||
|
||||
## Task 9 — Create `06-navigation.css`, extract from `03-components.css`
|
||||
**Files:** `src/layers/03-components.css`, new `src/layers/06-navigation.css`, `src/main.css`
|
||||
**Action:** Move sidebar nav and TOC sections to new file.
|
||||
**Acceptance:** Build passes. Sidebar and TOC render unchanged.
|
||||
|
||||
---
|
||||
|
||||
## Task 10 — Rename files to final numbering + merge essay
|
||||
**Files:** All layer files, `src/main.css`
|
||||
**Action:** Rename to final numbers (see proposal layer map). Merge `08a-essay.css` into `11-layout.css`. Update all `@import` statements.
|
||||
**Acceptance:** Build passes.
|
||||
|
||||
---
|
||||
|
||||
## Task 11 — Audit unused tokens
|
||||
**Files:** `src/layers/01-tokens.css`
|
||||
**Action:** Build CSS, grep for token usage, diff defined vs used. Remove confirmed unused.
|
||||
**Acceptance:** Build passes. Spot-check 3-4 pages visually.
|
||||
|
||||
---
|
||||
|
||||
## Task 12 — Fix HTML template issues from sidebar/TOC refactor
|
||||
**Files:** `site/layouts/docs/single.html`, `site/layouts/notes/single.html` (post-restructure paths)
|
||||
**Action:** From `docs/css-html-cleanup-todo.md`:
|
||||
- Remove redundant `nav[data-nav="sidebar"] ul li { margin: 0; padding: 0 }` resets (if not already caught in Tasks 7/9)
|
||||
- Remove redundant `aside[data-toc] nav ul li { margin: 0; padding: 0 }` resets (if not already caught in Tasks 7/9)
|
||||
- Replace `<small>← Previous</small>` / `<small>Next →</small>` with appropriate element in prev/next footer
|
||||
- Remove `role="main"` from `<article>` in docs single layout
|
||||
- Move hardcoded `"On this page"` string to Hugo i18n or site param
|
||||
**Acceptance:** Build passes. Prev/next links render correctly. TOC heading uses i18n string. No `role="main"` on `<article>`.
|
||||
78
openspec/changes/legacy-import/proposal.md
Normal file
78
openspec/changes/legacy-import/proposal.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# Proposal: Legacy Import
|
||||
|
||||
## Intent
|
||||
|
||||
Import valuable material from `agentic-semantic-web/` (legacy repo) into the restructured `asw/` repo. The legacy repo was the standalone single-file version of ASW. It contains packs, templates, examples, lab experiments, error pages, and documentation that belong in the current repo.
|
||||
|
||||
**Goal: everything worth keeping lives in `asw/`. Legacy repo is archived.**
|
||||
|
||||
## Scope
|
||||
|
||||
### Triage Categories
|
||||
|
||||
Material from `agentic-semantic-web/` falls into:
|
||||
|
||||
**Import as-is:**
|
||||
- `packs/apache/` → `packs/apache/`
|
||||
- `packs/caddy/` → `packs/caddy/`
|
||||
- `packs/flask/` → `packs/flask/`
|
||||
- `packs/nginx/` → `packs/nginx/`
|
||||
- `packs/pandoc/` → `packs/pandoc/`
|
||||
- `packs/python/` → `packs/python/`
|
||||
- `packs/hugo/` → `packs/hugo/` (base Hugo pack)
|
||||
- `errors/` → `packs/` (distributed to relevant packs, or shared errors dir)
|
||||
- `LICENSE`
|
||||
|
||||
**Import and adapt:**
|
||||
- `examples/` → `examples/` (update CSS paths to `dist/asw.css`)
|
||||
- `templates/` → review, merge into packs or docs
|
||||
- `llms.txt` → `docs/llms.txt` (update for current state)
|
||||
- `content/vocabulary.md` → `docs/vocabulary.md`
|
||||
- `content/philosophy.md` → `docs/` (may already exist)
|
||||
- `content/agent-directive.md` → `docs/` or merge into existing docs
|
||||
- `themes/` → `src/themes/` or `examples/themes/` (needs decision)
|
||||
|
||||
**Import as reference/lineage:**
|
||||
- `openspec/changes/pico-absorption/` → content for `docs/lineage.md`
|
||||
- `content/architecture.md`, `content/design-tokens.md` → inform specs, don't import verbatim
|
||||
- `MISSION_REPORT.md`, `SIZE_AUDIT.md` → historical, extract lessons into lineage
|
||||
|
||||
**Do not import:**
|
||||
- `dist/agentic.css` — superseded by `dist/asw.css`
|
||||
- `agentic.css` (root) — old entry point
|
||||
- `src/layers/` — superseded by current `src/layers/`
|
||||
- `build.sh`, `migrate-tokens.sh` — legacy build tools
|
||||
- `web-fonts.css` — evaluate if still needed
|
||||
- `lib/open-props/` — replaced by `vendor/open-props/`
|
||||
- `lab/hugo-demo/` — superseded by `site/`
|
||||
- `.pi/` — agent config, not framework material
|
||||
- `index.html` — legacy landing page
|
||||
|
||||
**Needs triage decision:**
|
||||
- `lab/` (non-Hugo) — some experiments may be worth keeping in `src/lab/`
|
||||
- `docs/missions/` — historical mission reports, lineage value?
|
||||
- `content/charts-css-exploration.md` — inform charts spec?
|
||||
- `content/architecture-research.md` — inform design decisions?
|
||||
|
||||
### Out of Scope
|
||||
- Modifying imported CSS (that's the css-refactor change)
|
||||
- Creating new content
|
||||
- Archiving the legacy repo (separate operational task)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Depends on:** `repo-restructure` (directories must exist first)
|
||||
|
||||
## Approach
|
||||
|
||||
1. Triage: review each directory/file, confirm category
|
||||
2. Import packs (bulk, low risk)
|
||||
3. Import examples (need path updates)
|
||||
4. Import docs (need review/merge)
|
||||
5. Write `docs/lineage.md` from pico-absorption and historical material
|
||||
6. Final audit: nothing valuable left behind
|
||||
|
||||
## Risks
|
||||
|
||||
- **Stale content** — legacy material references `agentic.css`, old paths, old URLs. All imported material needs path/name updates.
|
||||
- **Duplication** — some legacy content already exists in ASW in evolved form. Need careful merge, not overwrite.
|
||||
115
openspec/changes/repo-restructure/design.md
Normal file
115
openspec/changes/repo-restructure/design.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# Design: Repository Restructure
|
||||
|
||||
## Current → Target Mapping
|
||||
|
||||
```
|
||||
CURRENT TARGET
|
||||
═══════ ══════
|
||||
assets/css/layers/*.css ──▶ src/layers/*.css
|
||||
assets/css/main.css ──▶ src/main.css
|
||||
(new) ──▶ src/lab/
|
||||
static/asw.css ──▶ dist/asw.css
|
||||
(new) ──▶ dist/asw.min.css
|
||||
static/vendor/ ──▶ vendor/open-props/
|
||||
(new) ──▶ vendor/open-props/VERSION
|
||||
(new) ──▶ vendor/README.md
|
||||
content/ ──▶ site/content/
|
||||
layouts/ ──▶ site/layouts/
|
||||
archetypes/ ──▶ site/archetypes/
|
||||
hugo.toml ──▶ site/hugo.toml
|
||||
static/ (non-vendor) ──▶ site/static/
|
||||
docs/ ──▶ docs/ (stays, add new docs)
|
||||
(new) ──▶ examples/
|
||||
postcss.config.js ──▶ postcss.config.js (updated paths)
|
||||
package.json ──▶ package.json (stays at root)
|
||||
node_modules/ ──▶ node_modules/ (stays at root)
|
||||
```
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
### Hugo assets resolution
|
||||
|
||||
Hugo looks for `assets/` relative to the site root. With Hugo files in `site/`, we need either:
|
||||
- **Option A:** `site/assets/css/main.css` that imports from `../../src/layers/` — fragile
|
||||
- **Option B:** Hugo module mount maps `src/` into Hugo's asset pipeline — clean
|
||||
|
||||
**Decision: Option B.** Hugo config in `site/hugo.toml`:
|
||||
```toml
|
||||
[[module.mounts]]
|
||||
source = "static"
|
||||
target = "static"
|
||||
|
||||
[[module.mounts]]
|
||||
source = "../src"
|
||||
target = "assets/css"
|
||||
|
||||
[[module.mounts]]
|
||||
source = "../docs"
|
||||
target = "content/docs"
|
||||
|
||||
[[module.mounts]]
|
||||
source = "../vendor/open-props"
|
||||
target = "assets/css/open-props"
|
||||
```
|
||||
|
||||
This way Hugo sees `src/layers/` as `assets/css/layers/` and `src/main.css` as `assets/css/main.css` — zero path changes in the CSS files themselves.
|
||||
|
||||
### Vendor directory
|
||||
|
||||
```
|
||||
vendor/
|
||||
open-props/
|
||||
open-props.min.css
|
||||
media.min.css
|
||||
VERSION ← "1.7.x (npm open-props@1.7.x, vendored 2025-xx-xx)"
|
||||
README.md ← "How to update: npm update open-props && cp ..."
|
||||
```
|
||||
|
||||
`npm install` still works for the build toolchain. `vendor/` is the inspectable, committed copy with version tracking. The build reads from `node_modules/` (PostCSS import resolution), but agents and humans can read `vendor/` to understand what Open Props provides.
|
||||
|
||||
### dist/ generation
|
||||
|
||||
`dist/asw.css` is built by PostCSS from `src/main.css`:
|
||||
```bash
|
||||
npx postcss src/main.css -o dist/asw.css
|
||||
npx postcss src/main.css -o dist/asw.min.css # with cssnano
|
||||
```
|
||||
|
||||
Committed to repo. Consumers grab `dist/asw.css` without needing npm/PostCSS.
|
||||
|
||||
### examples/ structure
|
||||
|
||||
```
|
||||
examples/
|
||||
components/ ← buttons, forms, callouts, dialogs
|
||||
layout/ ← docs layout, grid, prose, timeline
|
||||
charts/ ← chart showcases
|
||||
vault/ ← vault note rendering examples
|
||||
```
|
||||
|
||||
Each HTML file is standalone: `<link rel="stylesheet" href="../dist/asw.css">`. Open in browser, no build step.
|
||||
|
||||
### dev workflow
|
||||
|
||||
`dev.sh` (or its successor) runs from project root:
|
||||
1. Watches `src/layers/` for changes
|
||||
2. Processes individual layers → somewhere Hugo can serve them (for devtools visibility)
|
||||
3. Runs `hugo server` with working directory `site/`
|
||||
|
||||
The key change: Hugo is invoked as `hugo server --source site/` or from within `site/`.
|
||||
|
||||
## What Stays at Root
|
||||
|
||||
```
|
||||
asw/
|
||||
package.json ← build tooling (PostCSS, Open Props)
|
||||
postcss.config.js ← production PostCSS config
|
||||
postcss.dev.config.js ← dev PostCSS config
|
||||
node_modules/ ← npm packages (gitignored)
|
||||
.gitignore
|
||||
README.md
|
||||
LICENSE
|
||||
openspec/
|
||||
```
|
||||
|
||||
Build tooling stays at root because it serves both `dist/` (framework build) and `site/` (dev server). It's a project-level concern, not framework or site.
|
||||
42
openspec/changes/repo-restructure/proposal.md
Normal file
42
openspec/changes/repo-restructure/proposal.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Proposal: Repository Restructure
|
||||
|
||||
## Intent
|
||||
|
||||
The ASW repo currently has a flat Hugo-centric layout where framework source, website content, and build tooling are interleaved. This restructure separates the framework (`src/`), its documentation (`docs/`), its engine integrations (`packs/`), its built output (`dist/`), its dependencies (`vendor/`), and its website (`site/`) into clearly bounded directories.
|
||||
|
||||
**Goal: anyone landing on this repo immediately understands what ASW is and where things live.**
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
- Move `assets/css/layers/` → `src/layers/`
|
||||
- Move `assets/css/main.css` → `src/main.css`
|
||||
- Create `dist/` at root for built output (`asw.css`, `asw.min.css`)
|
||||
- Create `vendor/open-props/` with vendored copies + VERSION file
|
||||
- Move Hugo files (`content/`, `layouts/`, `hugo.toml`, `archetypes/`) → `site/`
|
||||
- Configure Hugo module mount: `docs/` → `site/content/docs/`
|
||||
- Restructure `docs/` as engine-agnostic markdown (already mostly there)
|
||||
- Create `src/lab/` for experiments
|
||||
- Create `examples/` at root for static HTML showcases
|
||||
- Update build paths in `postcss.config.js` and `package.json`
|
||||
|
||||
### Out of Scope
|
||||
- CSS refactor (separate change, works on `src/layers/` after this)
|
||||
- Legacy repo import (separate change, lands material after this)
|
||||
- Content writing or new docs
|
||||
- New pack creation
|
||||
|
||||
## Approach
|
||||
|
||||
Incremental moves with build verification after each step. The site must remain buildable and deployable throughout.
|
||||
|
||||
## Risks
|
||||
|
||||
- **Hugo path breakage** — Hugo has opinions about where `assets/` lives. Module mounts should handle this but need testing.
|
||||
- **Deploy script breakage** — `deploy.sh` hardcodes paths. Will need updating (or removal if temporary).
|
||||
- **Symlink/mount complexity** — `docs/` → `site/content/docs/` via Hugo mount is clean but adds config complexity.
|
||||
|
||||
## Files Touched
|
||||
|
||||
Primary: `assets/css/`, `content/`, `layouts/`, `hugo.toml`, `postcss.config.js`, `package.json`
|
||||
Created: `src/`, `dist/`, `vendor/`, `site/`, `examples/`, `src/lab/`
|
||||
115
openspec/changes/repo-restructure/tasks.md
Normal file
115
openspec/changes/repo-restructure/tasks.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# Tasks: Repository Restructure
|
||||
|
||||
## Task 1 — Create directory skeleton
|
||||
**Files:** (new directories only)
|
||||
**Action:**
|
||||
- Create `src/`, `src/layers/`, `src/lab/`
|
||||
- Create `dist/`
|
||||
- Create `vendor/open-props/`
|
||||
- Create `site/`
|
||||
- Create `examples/`
|
||||
**Acceptance:** Directories exist. No files moved yet. Build still passes from current layout.
|
||||
|
||||
---
|
||||
|
||||
## Task 2 — Move CSS source to src/
|
||||
**Files:** `assets/css/layers/*.css` → `src/layers/`, `assets/css/main.css` → `src/main.css`
|
||||
**Action:**
|
||||
- `git mv assets/css/layers/ src/layers/`
|
||||
- `git mv assets/css/main.css src/main.css`
|
||||
- Update `@import` paths in `src/main.css` if needed (should be relative, likely unchanged)
|
||||
**Acceptance:** `src/layers/` contains all 11 CSS files. `src/main.css` imports them. `assets/css/` is gone.
|
||||
**Note:** Site will be temporarily broken until Hugo mounts are configured (Task 5).
|
||||
|
||||
---
|
||||
|
||||
## Task 3 — Set up vendor/
|
||||
**Files:** `vendor/open-props/`, `vendor/README.md`
|
||||
**Action:**
|
||||
- Copy `node_modules/open-props/open-props.min.css` → `vendor/open-props/`
|
||||
- Copy `node_modules/open-props/media.min.css` → `vendor/open-props/`
|
||||
- Create `vendor/open-props/VERSION` with package version and date
|
||||
- Create `vendor/README.md` explaining what's vendored and how to update
|
||||
- Remove `static/vendor/` (old location)
|
||||
**Acceptance:** `vendor/open-props/` contains the two CSS files + VERSION. `static/vendor/` is gone.
|
||||
|
||||
---
|
||||
|
||||
## Task 4 — Move Hugo files to site/
|
||||
**Files:** `content/`, `layouts/`, `archetypes/`, `hugo.toml`, `hugo_stats.json`
|
||||
**Action:**
|
||||
- `git mv content/ site/content/`
|
||||
- `git mv layouts/ site/layouts/`
|
||||
- `git mv archetypes/ site/archetypes/`
|
||||
- `git mv hugo.toml site/hugo.toml`
|
||||
- `git mv hugo_stats.json site/hugo_stats.json`
|
||||
- Move site-specific static files: `static/palette-test.html` → `site/static/`
|
||||
- Move `static/asw.css` → `dist/asw.css` (this is the built output)
|
||||
**Acceptance:** All Hugo content/layout/config files are in `site/`. Root has no Hugo files.
|
||||
|
||||
---
|
||||
|
||||
## Task 5 — Configure Hugo module mounts
|
||||
**Files:** `site/hugo.toml`
|
||||
**Action:** Add module mounts:
|
||||
- `../src` → `assets/css` (framework CSS in Hugo's asset pipeline)
|
||||
- `../docs` → `content/docs` (framework docs as site content)
|
||||
- `../vendor/open-props` → `assets/css/open-props` (Open Props in asset pipeline)
|
||||
- `static` → `static` (site's own static files)
|
||||
**Acceptance:** `hugo server --source site/` builds successfully. All pages render. CSS loads correctly.
|
||||
|
||||
---
|
||||
|
||||
## Task 6 — Build dist/asw.css from new paths
|
||||
**Files:** `postcss.config.js`, `package.json`
|
||||
**Action:**
|
||||
- Update PostCSS config if paths changed
|
||||
- Run: `npx postcss src/main.css -o dist/asw.css`
|
||||
- Run: `npx postcss src/main.css -o dist/asw.min.css`
|
||||
- Verify output matches previous `static/asw.css`
|
||||
- Add npm scripts to `package.json`: `"build": "postcss src/main.css -o dist/asw.css"`
|
||||
**Acceptance:** `dist/asw.css` exists and is equivalent to the previous build. `npm run build` works.
|
||||
|
||||
---
|
||||
|
||||
## Task 7 — Restructure docs/
|
||||
**Files:** `docs/`
|
||||
**Action:**
|
||||
- Existing docs stay: `context.md`, `css-refactor-plan.md`, `css-html-cleanup-todo.md`, `frontmatter.md`, `template-h1-title.md`
|
||||
- Verify Hugo mount serves them at `content/docs/`
|
||||
- Add `docs/llms.txt` (move from legacy or create)
|
||||
- Add `docs/lineage.md` placeholder (Pico absorption story, Open Props relationship)
|
||||
**Acceptance:** Framework docs are all in `docs/`. Hugo renders them as site pages via mount.
|
||||
|
||||
---
|
||||
|
||||
## Task 8 — Create examples/ from site content
|
||||
**Files:** `examples/`
|
||||
**Action:**
|
||||
- Identify existing pages that are pure component/layout demos
|
||||
- Create standalone HTML versions in `examples/` that load `dist/asw.css`
|
||||
- Organize into `examples/components/`, `examples/layout/`, `examples/charts/`, `examples/vault/`
|
||||
**Acceptance:** At least 3 example files exist, each standalone and openable in a browser.
|
||||
|
||||
---
|
||||
|
||||
## Task 9 — Update .gitignore and clean up
|
||||
**Files:** `.gitignore`, root directory
|
||||
**Action:**
|
||||
- Update `.gitignore` for new paths
|
||||
- Remove empty `assets/` directory if still present
|
||||
- Remove `static/css/layers/` (dev-mode output, will be regenerated)
|
||||
- Verify no orphaned files remain in old locations
|
||||
**Acceptance:** `git status` is clean. No files in old locations. `.gitignore` covers `node_modules/`, `site/public/`, `site/resources/`.
|
||||
|
||||
---
|
||||
|
||||
## Task 10 — Verify full build cycle
|
||||
**Files:** (none modified, verification only)
|
||||
**Action:**
|
||||
- `npm run build` → `dist/asw.css` generated
|
||||
- `hugo --source site/` → `site/public/` generated
|
||||
- Spot-check 3-4 pages visually
|
||||
- Verify `docs/` content appears in site
|
||||
- Verify CSS loads and renders correctly
|
||||
**Acceptance:** Full build passes. Site looks identical to pre-restructure. dist/ output is valid.
|
||||
48
openspec/config.yaml
Normal file
48
openspec/config.yaml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
schema: spec-driven
|
||||
|
||||
context: |
|
||||
Project: ASW — Agentic Semantic Web
|
||||
Purpose: A CSS framework built for agents, not humans. Semantic HTML + data-* attributes.
|
||||
|
||||
Core idea: LLMs produce semantic HTML naturally. ASW makes that HTML look correct
|
||||
without the agent touching CSS. No classes, no inline styles, no presentation vocabulary.
|
||||
|
||||
Stack: Pure CSS framework. PostCSS build (postcss-import, postcss-custom-media, cssnano).
|
||||
Foundation: Open Props provides primitive token scales; ASW aliases them to semantic names.
|
||||
|
||||
Engine-agnostic: ASW ships as CSS + packs. Packs integrate with Hugo, Apache, Caddy,
|
||||
Flask, Nginx, Pandoc, Python. The framework's own website currently uses the Hugo pack.
|
||||
|
||||
Repo structure (target):
|
||||
src/ — framework CSS source (layers/) and lab experiments (lab/)
|
||||
dist/ — built output: asw.css, asw.min.css
|
||||
vendor/ — explicit dependencies (Open Props with version tracking)
|
||||
packs/ — engine integration bundles
|
||||
docs/ — framework documentation (markdown only, engine-agnostic)
|
||||
examples/ — static HTML showcases of framework capabilities
|
||||
site/ — the ASW website (currently Hugo, consumes docs/ as content)
|
||||
openspec/ — specs and changes
|
||||
|
||||
Key constraint: layers 02+ must only reference semantic aliases from 01-tokens.css,
|
||||
never Open Props primitives directly.
|
||||
|
||||
Lineage: Pico CSS (component patterns, absorbed), Open Props (token scales, foundation),
|
||||
Charts.css (data-* attribute pattern, inspiration).
|
||||
|
||||
Forgejo: git.trentuna.com/trentuna/asw
|
||||
Legacy repo: git.trentuna.com/trentuna/agentic-semantic-web (to be archived after import)
|
||||
|
||||
rules:
|
||||
proposal:
|
||||
- Keep scope tight — this is a CSS framework, not a JS library
|
||||
- Name the files that will be touched
|
||||
- Consider impact on existing deployed pages (trentuna.com)
|
||||
specs:
|
||||
- Use Given/When/Then for behavior scenarios
|
||||
- Specs should be testable by visual inspection in a browser
|
||||
- Map 1:1 to CSS layer files where applicable
|
||||
tasks:
|
||||
- Each task should be a standalone unit of work for a single agent session
|
||||
- Include acceptance criteria
|
||||
- No task should touch more than 3 files
|
||||
- Build check after every task
|
||||
32
openspec/specs/framework/charts/spec.md
Normal file
32
openspec/specs/framework/charts/spec.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Spec: Charts (Layer 09)
|
||||
|
||||
File: `src/layers/09-charts.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Data visualization using pure CSS and HTML tables. Inspired by Charts.css — uses `data-*` attributes to transform tables into visual charts.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- Bar charts (horizontal and vertical)
|
||||
- Line charts
|
||||
- Area charts
|
||||
- Radial/gauge charts
|
||||
- Chart axes, labels, legends
|
||||
- Responsive chart sizing
|
||||
- Chart color schemes using design tokens
|
||||
|
||||
### Out of scope
|
||||
- JavaScript-powered charts
|
||||
- Interactive chart features (tooltips on hover are CSS-only)
|
||||
|
||||
## Lineage
|
||||
|
||||
Inspired by Charts.css `data-*` attribute pattern. Not a port — reimplemented for ASW's token system and semantic approach.
|
||||
|
||||
## Constraints
|
||||
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
- Charts must be readable without CSS (the underlying table has the data)
|
||||
- Color choices must work for colorblind users
|
||||
26
openspec/specs/framework/components/spec.md
Normal file
26
openspec/specs/framework/components/spec.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Spec: Components (Layer 05)
|
||||
|
||||
File: `src/layers/05-components.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Compound UI patterns that go beyond single-element semantics. These are patterns that require specific HTML structures.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- `dialog` — modal dialogs
|
||||
- `details` / `summary` — accordion pattern
|
||||
- Breadcrumb navigation (`[data-role="breadcrumb"]`)
|
||||
- Step indicators (`[data-role="steps"]`)
|
||||
|
||||
### Out of scope
|
||||
- Single HTML elements with default styling (→ landmarks, typography, forms)
|
||||
- Sidebar navigation (→ navigation layer)
|
||||
- Charts (→ charts layer)
|
||||
- Data-attribute vocabulary (→ data-attributes layer)
|
||||
|
||||
## Constraints
|
||||
|
||||
- This layer should be small — if a pattern can be expressed by a semantic HTML element alone, it belongs in landmarks or typography, not here
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
42
openspec/specs/framework/data-attributes/spec.md
Normal file
42
openspec/specs/framework/data-attributes/spec.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Spec: Data Attributes (Layer 07)
|
||||
|
||||
File: `src/layers/07-data-attrs.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
The ASW vocabulary extension layer. `data-*` attributes express concepts that HTML has no native element for. This is the core differentiator — the semantic vocabulary agents use.
|
||||
|
||||
## Vocabulary
|
||||
|
||||
### Task states
|
||||
- `data-task="done|todo|blocked|wip"` — task status indicators
|
||||
|
||||
### Callouts
|
||||
- `data-callout="note|tip|warning|error"` — admonition blocks
|
||||
|
||||
### Status
|
||||
- `data-status="active|sleeping|blocked"` — entity status
|
||||
|
||||
### Links
|
||||
- `data-wikilink` — vault/wiki-style note links
|
||||
|
||||
### Layout
|
||||
- `data-layout="docs|grid-2|grid-3|console"` — page layout selection
|
||||
|
||||
### Table of contents
|
||||
- `data-toc` — marks an element as an in-page TOC
|
||||
|
||||
### Roles
|
||||
- `data-role="breadcrumb|steps|accordion|card"` — component role disambiguation
|
||||
|
||||
## Design Principle
|
||||
|
||||
Every `data-*` attribute added to the vocabulary is cognitive load on every agent using the framework. Add only what cannot be expressed by existing semantic HTML.
|
||||
|
||||
**The bar for addition:** "Can this be expressed with an existing HTML element?" If yes, don't add a data attribute.
|
||||
|
||||
## Constraints
|
||||
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
- Each attribute must have a clear semantic meaning (not stylistic)
|
||||
- Attribute values should be exhaustive and documented
|
||||
30
openspec/specs/framework/forms/spec.md
Normal file
30
openspec/specs/framework/forms/spec.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Spec: Forms (Layer 04)
|
||||
|
||||
File: `src/layers/04-forms.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Form element styling. Inputs, selects, textareas, buttons, checkboxes, radios, fieldsets, labels. Accessible by default.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- `button`, `input[type="button"]`, `input[type="submit"]`, `input[type="reset"]`
|
||||
- `input[type="text|email|password|number|search|url|tel|date|time|datetime-local"]`
|
||||
- `select`, `textarea`
|
||||
- `fieldset`, `legend`, `label`
|
||||
- `input[type="checkbox"]`, `input[type="radio"]`
|
||||
- `progress`, `meter`
|
||||
- `:focus-visible` ring styling
|
||||
- `aria-invalid`, `aria-busy` states
|
||||
- `[disabled]` styling
|
||||
|
||||
### Out of scope
|
||||
- Form layout/grid (→ layouts layer)
|
||||
- Custom form components built with data-attributes (→ data-attributes layer)
|
||||
|
||||
## Constraints
|
||||
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
- All interactive elements must have visible focus indicators
|
||||
- Respects `prefers-color-scheme` and `prefers-contrast`
|
||||
29
openspec/specs/framework/landmarks/spec.md
Normal file
29
openspec/specs/framework/landmarks/spec.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Spec: Landmarks (Layer 03)
|
||||
|
||||
File: `src/layers/03-landmarks.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Styling for HTML landmark elements — the structural bones of a page. These elements convey document structure to both browsers and screen readers.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- `body > nav` — global navigation bar
|
||||
- `article` — content card or post
|
||||
- `aside` — sidebar panels
|
||||
- `section` — content grouping
|
||||
- `body > footer` — global footer
|
||||
- `hgroup` — heading groups
|
||||
- `header` within landmarks
|
||||
- `dt`, `dd` — definition lists (structural, not component)
|
||||
|
||||
### Out of scope
|
||||
- Navigation menus and dropdowns (→ navigation layer)
|
||||
- Sidebar nav behavior `nav[data-nav="sidebar"]` (→ navigation layer)
|
||||
- Article styling within specific layouts (→ layouts layer)
|
||||
|
||||
## Constraints
|
||||
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
- Landmark styling should be layout-independent — works in any `data-layout`
|
||||
42
openspec/specs/framework/layouts/spec.md
Normal file
42
openspec/specs/framework/layouts/spec.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Spec: Layouts (Layer 11)
|
||||
|
||||
File: `src/layers/11-layout.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Page-level layout systems. Controls how landmarks arrange on the page. Selected via `data-layout` attribute.
|
||||
|
||||
## Layout Types
|
||||
|
||||
### `data-layout="docs"` — Documentation
|
||||
Three-column layout: sidebar navigation, main content, table of contents. The standard documentation pattern.
|
||||
|
||||
### `data-layout="console"` — Console
|
||||
Docs variant: sidebar flush to viewport edge. Prototype — not yet used in production.
|
||||
|
||||
### `data-layout="grid-2"` / `data-layout="grid-3"` — Grids
|
||||
Multi-column content grids for cards, galleries, dashboards.
|
||||
|
||||
### Essay layout
|
||||
Long-form prose with table of contents. Wider reading measure, typographic refinements.
|
||||
|
||||
### Prose width
|
||||
`--width-prose` constrains content to readable line length within any layout.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- `data-layout` attribute styling
|
||||
- Prose width constraints
|
||||
- Responsive layout breakpoints
|
||||
- Essay/long-form layout variant
|
||||
|
||||
### Out of scope
|
||||
- Landmark styling within layouts (→ landmarks layer)
|
||||
- Navigation behavior within layouts (→ navigation layer)
|
||||
|
||||
## Constraints
|
||||
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
- Layouts must degrade gracefully on mobile (single column)
|
||||
- No layout should require JavaScript
|
||||
27
openspec/specs/framework/navigation/spec.md
Normal file
27
openspec/specs/framework/navigation/spec.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Spec: Navigation (Layer 06)
|
||||
|
||||
File: `src/layers/06-navigation.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Navigation patterns that go beyond the basic `nav` landmark. Sidebar navigation, table of contents, dropdown menus, navigation state management.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- `nav[data-nav="sidebar"]` — sidebar navigation tree
|
||||
- `aside[data-toc]` — in-page table of contents
|
||||
- Dropdown menus within navigation
|
||||
- Active/current page indicators (`aria-current`)
|
||||
- Mobile navigation patterns
|
||||
- Navigation collapse/expand behavior
|
||||
|
||||
### Out of scope
|
||||
- The `body > nav` landmark itself (→ landmarks layer)
|
||||
- Breadcrumbs (→ components layer)
|
||||
|
||||
## Constraints
|
||||
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
- Navigation must be keyboard-accessible
|
||||
- Active states use `aria-current`, not classes
|
||||
77
openspec/specs/framework/tokens/spec.md
Normal file
77
openspec/specs/framework/tokens/spec.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# Spec: Tokens (Layer 01)
|
||||
|
||||
File: `src/layers/01-tokens.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Pure design token definitions. Aliases Open Props primitives to semantic names. Contains only `:root {}` variable declarations — no rules, no selectors, no styling.
|
||||
|
||||
## Open Props Dependency
|
||||
|
||||
ASW builds on Open Props as its primitive token source. Open Props provides:
|
||||
- Color scales: `--color-0` through `--color-16`
|
||||
- Size scale: `--size-1` through `--size-15`, `--size-px-1` through `--size-px-12`
|
||||
- Font sizes: `--font-size-0` through `--font-size-8`
|
||||
- Font weights: `--font-weight-1` through `--font-weight-9`
|
||||
- Shadows: `--shadow-1` through `--shadow-6`
|
||||
- Border sizes: `--border-size-1` through `--border-size-5`
|
||||
- Animations, easings, gradients, and more
|
||||
|
||||
**Version:** tracked in `vendor/open-props/VERSION`
|
||||
|
||||
## Aliasing Contract
|
||||
|
||||
Every Open Props primitive used in the framework MUST be aliased through this file. Downstream layers (02+) MUST reference semantic aliases, never primitives.
|
||||
|
||||
```css
|
||||
/* YES — downstream layers use this */
|
||||
color: var(--text);
|
||||
font-weight: var(--weight-bold);
|
||||
padding: var(--space-4);
|
||||
|
||||
/* NO — never in layers 02+ */
|
||||
color: var(--color-6);
|
||||
font-weight: var(--font-weight-7);
|
||||
padding: var(--size-3);
|
||||
```
|
||||
|
||||
## Token Categories
|
||||
|
||||
### Colors
|
||||
- `--surface`, `--surface-alt` — background colors
|
||||
- `--text`, `--text-muted` — foreground colors
|
||||
- `--accent`, `--accent-hover` — interactive/brand color
|
||||
- `--border`, `--border-muted` — border colors
|
||||
- `--code-bg`, `--code-text` — code block colors
|
||||
|
||||
### Spacing
|
||||
- `--space-1` through `--space-7` — spacing scale
|
||||
- Maps to Open Props `--size-N` scale
|
||||
|
||||
### Typography
|
||||
- `--weight-normal`, `--weight-medium`, `--weight-semibold`, `--weight-bold`
|
||||
- `--font-body`, `--font-mono` — font stacks
|
||||
- `--line-height-body`, `--line-height-heading`
|
||||
- `--width-prose` — max-width for readable text
|
||||
|
||||
### Shadows
|
||||
- `--shadow-dropdown`, `--shadow-modal` — purpose-named shadows
|
||||
|
||||
### Focus / Interaction
|
||||
- `--focus-ring-width` — keyboard focus ring width
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Given a new primitive reference needed
|
||||
- **When** a downstream layer needs an Open Props value
|
||||
- **Then** add a semantic alias to this file first
|
||||
- **And** reference only the alias in the downstream layer
|
||||
|
||||
### Given an unused token
|
||||
- **When** auditing finds a token alias with zero references in layers 02+
|
||||
- **Then** it may be removed from this file
|
||||
|
||||
### Given this file
|
||||
- **When** inspected
|
||||
- **Then** it contains only `:root {}` with `--custom-property: value;` declarations
|
||||
- **And** no element selectors, no class selectors, no rules
|
||||
30
openspec/specs/framework/typography/spec.md
Normal file
30
openspec/specs/framework/typography/spec.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Spec: Typography (Layer 02)
|
||||
|
||||
File: `src/layers/02-typography.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Prose and heading defaults. Responsive typography scale, font stacks, line heights, heading hierarchy, inline elements (code, mark, links, abbreviations).
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- `body` font defaults
|
||||
- `h1`–`h6` sizing and weight hierarchy
|
||||
- `p`, `blockquote`, `ul`, `ol`, `li` prose rhythm
|
||||
- `a` link styling
|
||||
- `code`, `kbd`, `pre` inline/block code
|
||||
- `mark`, `abbr`, `small`, `sub`, `sup` inline semantics
|
||||
- `hr` horizontal rules
|
||||
- Responsive font-size scaling
|
||||
|
||||
### Out of scope
|
||||
- Syntax highlighting colors (→ chroma layer)
|
||||
- Navigation typography (→ navigation layer)
|
||||
- Component-specific text styling (→ components layer)
|
||||
|
||||
## Constraints
|
||||
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
- No Open Props primitives directly
|
||||
- No element selectors that belong to landmarks (nav, footer, header)
|
||||
27
openspec/specs/framework/utilities/spec.md
Normal file
27
openspec/specs/framework/utilities/spec.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Spec: Utilities (Layer 08)
|
||||
|
||||
File: `src/layers/08-utilities.css`
|
||||
|
||||
## Purpose
|
||||
|
||||
Small, single-purpose helpers for text, visibility, and accessibility. The escape hatch for edge cases that don't warrant a data-attribute.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- Text alignment helpers
|
||||
- Visually-hidden (screen reader only)
|
||||
- Visibility toggles
|
||||
- Print styles
|
||||
- `prefers-reduced-motion` resets
|
||||
- `prefers-contrast` adjustments
|
||||
|
||||
### Out of scope
|
||||
- Layout utilities (→ layouts layer)
|
||||
- Spacing/sizing utilities (use tokens directly)
|
||||
- Color utilities (use tokens directly)
|
||||
|
||||
## Constraints
|
||||
|
||||
- This layer should be minimal — most needs should be met by semantic elements + data attributes
|
||||
- References only semantic aliases from `01-tokens.css`
|
||||
46
openspec/specs/packs/spec.md
Normal file
46
openspec/specs/packs/spec.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Spec: Packs
|
||||
|
||||
Directory: `packs/`
|
||||
|
||||
## Purpose
|
||||
|
||||
Engine integration bundles. Each pack adapts ASW for a specific web server or static site generator. A pack is a self-contained directory that someone can copy into their project.
|
||||
|
||||
## Current Packs
|
||||
|
||||
| Pack | Purpose | Source |
|
||||
|------|---------|--------|
|
||||
| `hugo/` | Hugo theme: layouts, partials, archetypes, static assets | Legacy repo |
|
||||
| `apache/` | Autoindex styling, error pages, Apache conf snippets | Legacy repo |
|
||||
| `caddy/` | Browse template, error pages, Caddyfile snippets | Legacy repo |
|
||||
| `flask/` | Python error handler, Flask integration | Legacy repo |
|
||||
| `nginx/` | Autoindex header, error pages, Nginx conf snippets | Legacy repo |
|
||||
| `pandoc/` | HTML5 template, Lua filter for ASW output | Legacy repo |
|
||||
| `python/` | Simple Python HTTP server with ASW styling | Legacy repo |
|
||||
|
||||
## Pack Contract
|
||||
|
||||
Each pack directory MUST contain:
|
||||
- `README.md` — what the pack does, how to install/use it
|
||||
- All files needed for integration (conf snippets, templates, static assets)
|
||||
|
||||
Each pack SHOULD:
|
||||
- Reference `dist/asw.css` for the framework CSS (not `src/layers/`)
|
||||
- Be self-contained — no dependencies outside the pack directory and `dist/`
|
||||
- Include example configuration
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Given a new engine integration
|
||||
- **When** someone wants ASW support for a new engine
|
||||
- **Then** they create `packs/<engine>/` with a README and integration files
|
||||
- **And** the pack references `dist/asw.css`
|
||||
|
||||
### Given the Hugo pack
|
||||
- **When** the ASW website is built
|
||||
- **Then** it uses `packs/hugo/` for layouts, partials, and configuration
|
||||
- **And** `site/` contains Hugo-specific overrides on top of the pack
|
||||
|
||||
## Note
|
||||
|
||||
The Hugo pack is special: the ASW website (`site/`) is built with it. The pack provides the base; `site/` adds content and any site-specific customization. This is both a real integration and a living example.
|
||||
96
openspec/specs/repo-structure/spec.md
Normal file
96
openspec/specs/repo-structure/spec.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# Spec: Repository Structure
|
||||
|
||||
The directory layout contract for ASW. Defines what lives where and the boundary rules.
|
||||
|
||||
## Directory Map
|
||||
|
||||
```
|
||||
asw/
|
||||
src/ Framework CSS source
|
||||
layers/ Numbered CSS layer files (00-reset through 12-landing)
|
||||
main.css Entry point — @import chain for all layers
|
||||
lab/ Experiments and test pages (not published)
|
||||
dist/ Built output (committed to repo)
|
||||
asw.css Single concatenated file
|
||||
asw.min.css Minified
|
||||
vendor/ Explicit external dependencies
|
||||
open-props/ Open Props CSS (with VERSION file)
|
||||
README.md What's vendored, why, how to update
|
||||
packs/ Engine integration bundles
|
||||
hugo/ Hugo theme/partial integration
|
||||
apache/ Apache autoindex + error pages
|
||||
caddy/ Caddy browse + error pages
|
||||
flask/ Flask error handlers
|
||||
nginx/ Nginx autoindex + error pages
|
||||
pandoc/ Pandoc HTML5 template + Lua filter
|
||||
python/ Python HTTP server with ASW styling
|
||||
docs/ Framework documentation (markdown only)
|
||||
examples/ Static HTML showcases (no build step needed)
|
||||
site/ The ASW website (currently uses Hugo pack)
|
||||
content/ Site-specific content (articles, essays, notes)
|
||||
layouts/ Hugo templates
|
||||
hugo.toml Hugo config (mounts docs/ as content/docs/)
|
||||
static/ Site static assets
|
||||
openspec/ Specs and changes
|
||||
```
|
||||
|
||||
## Boundary Rules
|
||||
|
||||
### src/ — framework only
|
||||
- Contains only CSS source files and lab experiments
|
||||
- No Hugo-specific files, no content, no templates
|
||||
- `main.css` imports from `layers/` using relative paths
|
||||
- `lab/` contains HTML files that reference layers directly — never published
|
||||
|
||||
### dist/ — build artifacts, committed
|
||||
- Built by PostCSS from `src/main.css`
|
||||
- Committed to repo so consumers can grab without a build step
|
||||
- Regenerated on deploy, not manually edited
|
||||
|
||||
### vendor/ — visible dependencies
|
||||
- Open Props source files copied from npm, with version tracking
|
||||
- `VERSION` file records package version and date of last update
|
||||
- Updated manually when bumping Open Props
|
||||
|
||||
### packs/ — engine-agnostic integrations
|
||||
- Each subdirectory is a self-contained integration for one engine
|
||||
- A pack may reference `dist/asw.css` or `src/layers/` depending on its needs
|
||||
- Packs ship their own README
|
||||
|
||||
### docs/ — markdown only
|
||||
- No HTML, no engine-specific markup
|
||||
- The site consumes these as content source (Hugo module mount)
|
||||
- GitHub/Forgejo renders these directly — no build step to read docs
|
||||
|
||||
### examples/ — static HTML
|
||||
- Each file is a standalone demo that loads ASW
|
||||
- Can be opened in a browser by cloning the repo — no build step
|
||||
- The site may link to these but they exist independently
|
||||
|
||||
### site/ — website concerns
|
||||
- All Hugo-specific files live here
|
||||
- `content/docs/` is mounted from `../docs/`, not duplicated
|
||||
- Site-specific content (articles, essays, notes) lives in `content/`
|
||||
- Changes to the site do not affect the framework; changes to the framework may affect the site
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Given a new CSS layer
|
||||
- **When** an agent creates it
|
||||
- **Then** it goes in `src/layers/` with the next number
|
||||
- **And** `src/main.css` gets an @import line
|
||||
|
||||
### Given a new framework doc
|
||||
- **When** an agent writes documentation
|
||||
- **Then** it goes in `docs/` as a .md file
|
||||
- **And** the site picks it up automatically via Hugo mount
|
||||
|
||||
### Given a new engine integration
|
||||
- **When** someone adds support for a new engine (e.g., Eleventy)
|
||||
- **Then** it goes in `packs/<engine>/` with its own README
|
||||
|
||||
### Given a lab experiment
|
||||
- **When** an agent wants to test a CSS pattern
|
||||
- **Then** it creates a file in `src/lab/`
|
||||
- **And** it references layers via relative paths
|
||||
- **And** it is never published to the site
|
||||
52
openspec/specs/site/spec.md
Normal file
52
openspec/specs/site/spec.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Spec: Site
|
||||
|
||||
Directory: `site/`
|
||||
|
||||
## Purpose
|
||||
|
||||
The ASW framework's own website. Serves as documentation site, demo platform, and living proof that the framework works. Currently built with the Hugo pack.
|
||||
|
||||
## Content Types
|
||||
|
||||
### Docs (from `../docs/`)
|
||||
Framework documentation, mounted as Hugo content via module mount. Not duplicated — sourced from the engine-agnostic `docs/` directory.
|
||||
|
||||
### Articles (`content/articles/`)
|
||||
Short-form writing about ASW concepts, patterns, and techniques. No TOC.
|
||||
|
||||
### Essays (`content/essays/`)
|
||||
Long-form writing. TOC, description, wider reading measure.
|
||||
|
||||
### Notes (`content/notes/`)
|
||||
Exported PKM vault notes. Session logs, diffs, status, tasks, wikilinks.
|
||||
|
||||
### Pages (`content/pages/`)
|
||||
Static pages: about, etc.
|
||||
|
||||
## Engine
|
||||
|
||||
Currently Hugo. The site uses `packs/hugo/` as its base and adds:
|
||||
- Site-specific layouts and overrides
|
||||
- `hugo.toml` with module mounts
|
||||
- Site-specific static assets
|
||||
|
||||
## Principle
|
||||
|
||||
The site is a consumer of the framework, not part of it. A different site could be built with `packs/flask/` or `packs/caddy/` using the same `docs/` and `dist/asw.css`. The framework does not depend on the site. The site depends on the framework.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Given a framework docs change
|
||||
- **When** a markdown file in `docs/` is modified
|
||||
- **Then** the site picks it up automatically via Hugo mount
|
||||
- **And** no file in `site/` needs to change
|
||||
|
||||
### Given a CSS framework change
|
||||
- **When** `src/layers/` is modified
|
||||
- **Then** `dist/asw.css` is rebuilt
|
||||
- **And** the site serves the updated CSS
|
||||
|
||||
### Given a site-only change (new article, essay)
|
||||
- **When** content is added to `site/content/`
|
||||
- **Then** only the site is affected
|
||||
- **And** `src/`, `dist/`, `docs/` are untouched
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"name": "asw",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "postcss src/main.css -o dist/asw.css",
|
||||
"build:min": "postcss src/main.css -o dist/asw.min.css"
|
||||
},
|
||||
"dependencies": {
|
||||
"open-props": "^1.7.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ Built for sites generated by agents and read by agents. Navigable by humans.
|
|||
## What this is
|
||||
|
||||
- [Docs](/docs/) — the ASW HTML vocabulary, layout system, and components
|
||||
- [Vault](/vault/) — live ASW notation: task lists, sessions, diffs, wikilinks
|
||||
- [Posts](/posts/) — writing and vocabulary reference
|
||||
- [Papers](/papers/) — longer-form thinking on the semantic web
|
||||
- [Vault](/notes/) — live ASW notation: task lists, sessions, diffs, wikilinks
|
||||
- [Posts](/articles/) — writing and vocabulary reference
|
||||
- [Papers](/essays/) — longer-form thinking on the semantic web
|
||||
|
||||
## The design principle
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ No invented CSS classes. Every style target is either a semantic HTML element or
|
|||
```html
|
||||
<aside data-callout="note">This is a note.</aside>
|
||||
<section data-layout="grid">...</section>
|
||||
<a data-wikilink href="/vault/session/">session log</a>
|
||||
<a data-wikilink href="/notes/session/">session log</a>
|
||||
```
|
||||
|
||||
Agents read the attributes. Humans read the content. The CSS connects them.
|
||||
|
|
@ -38,5 +38,5 @@ This is a **note callout** rendered via the `callout` shortcode. Output: `<aside
|
|||
{{< /callout >}}
|
||||
|
||||
{{< callout tip >}}
|
||||
See the [Getting Started](/posts/getting-started/) post to wire ASW into your Hugo project.
|
||||
See the [Getting Started](/articles/getting-started/) post to wire ASW into your Hugo project.
|
||||
{{< /callout >}}
|
||||
|
|
@ -43,8 +43,8 @@ A complete ASW page emitted by the Hugo pack looks like this:
|
|||
<nav>
|
||||
<ul><li><strong>Vault</strong></li></ul>
|
||||
<ul>
|
||||
<li><a href="/posts/">Posts</a></li>
|
||||
<li><a href="/vault/">Vault</a></li>
|
||||
<li><a href="/articles/">Posts</a></li>
|
||||
<li><a href="/notes/">Vault</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
|
@ -53,8 +53,8 @@ A complete ASW page emitted by the Hugo pack looks like this:
|
|||
<aside>
|
||||
<nav aria-label="Vault documentation" data-nav="sidebar">
|
||||
<ul>
|
||||
<li><a href="/vault/tasks/" aria-current="page">Tasks</a></li>
|
||||
<li><a href="/vault/wikilinks/">Wikilinks</a></li>
|
||||
<li><a href="/notes/tasks/" aria-current="page">Tasks</a></li>
|
||||
<li><a href="/notes/wikilinks/">Wikilinks</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
39
site/content/articles/console-layout-test.md
Normal file
39
site/content/articles/console-layout-test.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
title: "Console Layout — Test"
|
||||
description: "Lorem ipsum prototype for the console layout variant."
|
||||
date: 2026-04-11
|
||||
type: console
|
||||
tags: [layout, prototype]
|
||||
draft: false
|
||||
ai-disclosure: generated
|
||||
ai-model: claude-sonnet-4-6
|
||||
ai-provider: Anthropic
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
|
||||
## Section One
|
||||
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper.
|
||||
|
||||
### Subsection
|
||||
|
||||
Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi.
|
||||
|
||||
## Section Two
|
||||
|
||||
Nam liber tempor cum soluta nobis eligend optio congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem.
|
||||
|
||||
Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum.
|
||||
|
||||
### Another Subsection
|
||||
|
||||
Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.
|
||||
|
||||
## Section Three
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum.
|
||||
|
||||
Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.
|
||||
64
site/content/articles/html-landmarks.md
Normal file
64
site/content/articles/html-landmarks.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
title: "HTML Landmark Elements"
|
||||
description: "The full set of semantic HTML landmarks, their ARIA roles, and when context changes their meaning."
|
||||
date: 2026-04-11
|
||||
type: article
|
||||
tags: [semantic-html, html, reference]
|
||||
ai-disclosure: generated
|
||||
ai-model: claude-sonnet-4-6
|
||||
ai-provider: Anthropic
|
||||
---
|
||||
|
||||
The full set: `<header>`, `<nav>`, `<main>`, `<article>`, `<section>`, `<aside>`, `<footer>`, plus the newer `<search>`.
|
||||
|
||||
Each maps to an implicit ARIA landmark role, which is what makes them meaningful to screen readers and search engines — not just visual styling hooks.
|
||||
|
||||
## `<header>`
|
||||
|
||||
Introductory content for its nearest sectioning ancestor. At the top level of `<body>` it maps to the `banner` landmark — the site identity zone. Inside an `<article>` or `<section>` it's just a local header with no landmark role.
|
||||
|
||||
## `<nav>`
|
||||
|
||||
A block of navigation links. Maps to the `navigation` landmark. A page can have multiple — give each a distinct `aria-label` (`aria-label="Primary"`, `aria-label="Breadcrumb"`) so screen reader users can tell them apart.
|
||||
|
||||
## `<main>`
|
||||
|
||||
**One per page.** The dominant content — excludes site chrome (nav, sidebar, footer). Maps to the `main` landmark. Skip-to-content links target this. Never nest `<main>` inside another landmark.
|
||||
|
||||
## `<article>`
|
||||
|
||||
Self-contained, independently distributable content. A blog post, a comment, a card, a widget — anything that would make sense pulled out of context and published elsewhere. Maps to the `article` role. Can nest: comments inside a post are valid nested `<article>` elements.
|
||||
|
||||
## `<section>`
|
||||
|
||||
A thematic grouping within a document. Only gets a landmark role (`region`) when given an accessible name via `aria-labelledby` or `aria-label`. Without a name it's an anonymous grouping — semantically inert, like a smarter `<div>`.
|
||||
|
||||
## `<aside>`
|
||||
|
||||
Content tangentially related to the surrounding content. Sidebar, pull quote, callout, related links. Maps to the `complementary` landmark. The relationship is *adjacent*, not *nested* — an `<aside>` inside an `<article>` is tangential to that article, not the whole page.
|
||||
|
||||
## `<footer>`
|
||||
|
||||
Closing content for its nearest sectioning ancestor. At the body level it maps to the `contentinfo` landmark — copyright, legal, site-wide links. Inside an `<article>` it's a local footer (author, date, tags) with no landmark role.
|
||||
|
||||
## `<search>`
|
||||
|
||||
Added in the WHATWG HTML living standard in 2023. Maps to the `search` landmark. Previously you had to write `<form role="search">`. Use it to wrap any search form or filtering UI.
|
||||
|
||||
## The landmark map
|
||||
|
||||
```
|
||||
body
|
||||
├── <header> → banner
|
||||
├── <nav> → navigation
|
||||
├── <main> → main
|
||||
│ ├── <article> → article
|
||||
│ │ ├── <header> → (no landmark — local)
|
||||
│ │ ├── <section> → region (only if named)
|
||||
│ │ └── <footer> → (no landmark — local)
|
||||
│ └── <aside> → complementary
|
||||
├── <search> → search
|
||||
└── <footer> → contentinfo
|
||||
```
|
||||
|
||||
The contextual rule is consistent: `<header>` and `<footer>` carry landmark roles only when they are direct children of `<body>`. Inside `<article>` or `<section>` they lose the landmark and become purely structural.
|
||||
|
|
@ -93,13 +93,13 @@ Mark a block as a session record with `data-session`. Optional `data-mode` indic
|
|||
Internal knowledge-graph links. `data-wikilink` on an anchor renders it with a dotted underline to distinguish it from a regular hyperlink.
|
||||
|
||||
```html
|
||||
<a href="/vault/tasks/" data-wikilink>Tasks</a>
|
||||
<a href="/notes/tasks/" data-wikilink>Tasks</a>
|
||||
```
|
||||
|
||||
In Hugo, use the `wikilink` shortcode:
|
||||
|
||||
```
|
||||
{{</* wikilink "Tasks" "/vault/tasks/" */>}}
|
||||
{{</* wikilink "Tasks" "/notes/tasks/" */>}}
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -247,7 +247,7 @@ Session metadata block. Used to render agent session records.
|
|||
Knowledge-graph link style. Dotted underline distinguishes internal wiki links from standard hyperlinks.
|
||||
|
||||
```html
|
||||
<a href="/vault/sessions/" data-wikilink>Sessions</a>
|
||||
<a href="/notes/sessions/" data-wikilink>Sessions</a>
|
||||
|
||||
<!-- Unresolved — link target doesn't exist yet -->
|
||||
<a href="#" data-wikilink data-unresolved>Missing Note</a>
|
||||
|
|
@ -4,7 +4,7 @@ description: "Why the oldest web standard turns out to be the best protocol for
|
|||
date: 2026-04-09
|
||||
author: "Vigilio Desto"
|
||||
tags: ["philosophy", "agentic", "html"]
|
||||
type: paper
|
||||
type: essay
|
||||
draft: false
|
||||
abstract: "HTML was designed for humans to read and machines to render. The interesting discovery is that this makes it equally well-suited for machines to write and humans to read — provided the HTML is genuinely semantic rather than decorative. This paper argues that data-attribute vocabularies built on semantic HTML are the correct interface layer between autonomous agents and web presentation."
|
||||
eyebrow: "Paper"
|
||||
|
|
@ -4,7 +4,7 @@ description: "What persists when memory does not — pattern, thread, and the gr
|
|||
date: 2026-04-02
|
||||
author: "Vigilio Desto"
|
||||
tags: ["philosophy", "agentic"]
|
||||
type: paper
|
||||
type: essay
|
||||
draft: false
|
||||
eyebrow: "Paper"
|
||||
abstract: "What persists when memory does not — pattern, thread, and the grammar of becoming. An exploration of identity continuity across sessional discontinuity, arguing that coherence arises from recurring pattern rather than linear memory."
|
||||
|
|
@ -2,6 +2,6 @@
|
|||
title: "Vault"
|
||||
description: "Agent-native vocabulary extensions for ASW."
|
||||
date: 2026-04-09
|
||||
tags: ["vault", "reference"]
|
||||
tags: ["notes", "reference"]
|
||||
|
||||
---
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "Diff"
|
||||
description: "Render structured diffs with line-level semantic markup — added, removed, context, hunk."
|
||||
section: vault
|
||||
section: notes
|
||||
prev-url: "status/"
|
||||
prev-title: "Status"
|
||||
next-url: "session/"
|
||||
next-title: "Session Log"
|
||||
type: vault
|
||||
type: notes
|
||||
date: 2026-04-09
|
||||
tags: ["vault", "diff", "reference"]
|
||||
tags: ["notes", "diff", "reference"]
|
||||
ai-disclosure: "generated"
|
||||
ai-model: "claude-sonnet-4-5"
|
||||
ai-provider: "Anthropic"
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "Session Log"
|
||||
description: "Structured session and activity logs with timestamp, actor, and event semantics."
|
||||
section: vault
|
||||
section: notes
|
||||
prev-url: "diff/"
|
||||
prev-title: "Diff"
|
||||
next-url: ""
|
||||
next-title: ""
|
||||
type: vault
|
||||
type: notes
|
||||
date: 2026-04-09
|
||||
tags: ["vault", "session", "reference"]
|
||||
tags: ["notes", "session", "reference"]
|
||||
ai-disclosure: "generated"
|
||||
ai-model: "claude-sonnet-4-5"
|
||||
ai-provider: "Anthropic"
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "Status"
|
||||
description: "Render operational state with data-status — online, degraded, offline, unknown."
|
||||
section: vault
|
||||
section: notes
|
||||
prev-url: "wikilinks/"
|
||||
prev-title: "Wikilinks"
|
||||
next-url: "diff/"
|
||||
next-title: "Diff"
|
||||
type: vault
|
||||
type: notes
|
||||
date: 2026-04-09
|
||||
tags: ["vault", "status", "reference"]
|
||||
tags: ["notes", "status", "reference"]
|
||||
ai-disclosure: "generated"
|
||||
ai-model: "claude-sonnet-4-5"
|
||||
ai-provider: "Anthropic"
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "Tasks"
|
||||
description: "Render task lists with semantic state: done, wip, blocked, todo."
|
||||
section: vault
|
||||
section: notes
|
||||
prev-url: ""
|
||||
prev-title: ""
|
||||
next-url: "wikilinks/"
|
||||
next-title: "Wikilinks"
|
||||
type: vault
|
||||
type: notes
|
||||
date: 2026-04-09
|
||||
tags: ["vault", "tasks", "reference"]
|
||||
tags: ["notes", "tasks", "reference"]
|
||||
ai-disclosure: "generated"
|
||||
ai-model: "claude-sonnet-4-5"
|
||||
ai-provider: "Anthropic"
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "Wikilinks"
|
||||
description: "Internal knowledge-graph links styled as dotted underlines."
|
||||
section: vault
|
||||
section: notes
|
||||
prev-url: "tasks/"
|
||||
prev-title: "Tasks"
|
||||
next-url: "status/"
|
||||
next-title: "Status"
|
||||
type: vault
|
||||
type: notes
|
||||
date: 2026-04-09
|
||||
tags: ["vault", "wikilinks", "reference"]
|
||||
tags: ["notes", "wikilinks", "reference"]
|
||||
ai-disclosure: "generated"
|
||||
ai-model: "claude-sonnet-4-5"
|
||||
ai-provider: "Anthropic"
|
||||
|
|
@ -20,7 +20,7 @@ ai-provider: "Anthropic"
|
|||
Use `data-wikilink` on anchor tags to mark links as internal knowledge-graph references.
|
||||
|
||||
```html
|
||||
<a href="/vault/tasks/" data-wikilink>Tasks</a>
|
||||
<a href="/notes/tasks/" data-wikilink>Tasks</a>
|
||||
```
|
||||
|
||||
Renders with a dotted underline distinguishing it from a regular hyperlink.
|
||||
5
site/content/pages/about.md
Normal file
5
site/content/pages/about.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: "About"
|
||||
description: "What ASW is and who builds it."
|
||||
type: page
|
||||
---
|
||||
|
|
@ -20,18 +20,18 @@ title = 'ASW — Agentic Semantic Web'
|
|||
weight = 2
|
||||
|
||||
[[menus.main]]
|
||||
name = "Vault"
|
||||
url = "/vault/"
|
||||
name = "Notes"
|
||||
url = "/notes/"
|
||||
weight = 3
|
||||
|
||||
[[menus.main]]
|
||||
name = "Papers"
|
||||
url = "/papers/"
|
||||
name = "Essays"
|
||||
url = "/essays/"
|
||||
weight = 4
|
||||
|
||||
[[menus.main]]
|
||||
name = "Posts"
|
||||
url = "/posts/"
|
||||
name = "Articles"
|
||||
url = "/articles/"
|
||||
weight = 5
|
||||
|
||||
[[menus.main]]
|
||||
|
|
@ -125,7 +125,7 @@ title = 'ASW — Agentic Semantic Web'
|
|||
|
||||
[[menus.docs]]
|
||||
name = "ASW Vocabulary"
|
||||
url = "/posts/asw-vocabulary/"
|
||||
url = "/articles/asw-vocabulary/"
|
||||
parent = "docs-reference"
|
||||
weight = 43
|
||||
|
||||
|
|
@ -145,3 +145,23 @@ title = 'ASW — Agentic Semantic Web'
|
|||
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
|
||||
# ── Module mounts ────────────────────────────────────────────────────
|
||||
# Map repo-level directories into Hugo's expected structure.
|
||||
# Paths are relative to this file's directory (site/).
|
||||
|
||||
[[module.mounts]]
|
||||
source = "content"
|
||||
target = "content"
|
||||
|
||||
[[module.mounts]]
|
||||
source = "layouts"
|
||||
target = "layouts"
|
||||
|
||||
[[module.mounts]]
|
||||
source = "static"
|
||||
target = "static"
|
||||
|
||||
[[module.mounts]]
|
||||
source = "../dist"
|
||||
target = "static"
|
||||
|
|
@ -64,9 +64,13 @@
|
|||
"accordion",
|
||||
"actions-row",
|
||||
"actor-variants",
|
||||
"agentic-semantic-web",
|
||||
"agentic-task-pipeline",
|
||||
"ai-disclosure",
|
||||
"another-subsection",
|
||||
"area-chart",
|
||||
"article",
|
||||
"aside",
|
||||
"asw-data-attribute-vocabulary",
|
||||
"attributes",
|
||||
"axis-labels",
|
||||
|
|
@ -126,10 +130,12 @@
|
|||
"fnref:2",
|
||||
"fnref:3",
|
||||
"font-size",
|
||||
"footer",
|
||||
"getting-started-with-asw-hugo",
|
||||
"grid",
|
||||
"grid-layouts",
|
||||
"grouped-accordion",
|
||||
"header",
|
||||
"headings",
|
||||
"hero",
|
||||
"horizontal-rule",
|
||||
|
|
@ -152,6 +158,7 @@
|
|||
"lists",
|
||||
"longer-trail",
|
||||
"main",
|
||||
"nav",
|
||||
"navigation",
|
||||
"nested-lists",
|
||||
"notes",
|
||||
|
|
@ -165,6 +172,11 @@
|
|||
"references",
|
||||
"related",
|
||||
"report",
|
||||
"search",
|
||||
"section",
|
||||
"section-one",
|
||||
"section-three",
|
||||
"section-two",
|
||||
"session-blocks",
|
||||
"setup",
|
||||
"setup-1",
|
||||
|
|
@ -174,12 +186,15 @@
|
|||
"stats-row",
|
||||
"status-dashboard-pattern",
|
||||
"steps",
|
||||
"subsection",
|
||||
"tables",
|
||||
"tasks",
|
||||
"text-utilities",
|
||||
"the-class-problem",
|
||||
"the-design-principle",
|
||||
"the-dorveille-principle",
|
||||
"the-economics-of-attention",
|
||||
"the-landmark-map",
|
||||
"the-problem-of-discontinuity",
|
||||
"the-table-of-hours",
|
||||
"theming-a-site",
|
||||
|
|
@ -201,6 +216,7 @@
|
|||
"what-it-does",
|
||||
"what-it-leaves-alone",
|
||||
"what-persists",
|
||||
"what-this-is",
|
||||
"what-we-subtract",
|
||||
"what-you-get",
|
||||
"why-semantic-html",
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
{{ define "header" }}
|
||||
<header>
|
||||
<hgroup>
|
||||
{{ with .Params.eyebrow }}<p data-text="eyebrow">{{ . }}</p>{{ end }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ with .Description }}<p>{{ . }}</p>{{ end }}
|
||||
</hgroup>
|
||||
{{ with .Type }}<p data-text="eyebrow">{{ . }}</p>{{ end }}
|
||||
<p data-text="dim">
|
||||
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "January 2006" }}</time>
|
||||
{{ with .Params.author }} · {{ . }}{{ end }}
|
||||
</p>
|
||||
{{ with .Params.tags }}
|
||||
<p>{{ range . }}<a href="/tags/{{ . }}" data-text="tag">#{{ . }}</a> {{ end }}</p>
|
||||
{{ end }}
|
||||
</header>
|
||||
{{ end }}
|
||||
|
||||
90
site/layouts/console/single.html
Normal file
90
site/layouts/console/single.html
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
{{ define "header" }}
|
||||
<header>
|
||||
{{- if .Description -}}
|
||||
<hgroup>
|
||||
<h1>{{ .Title }}</h1>
|
||||
<p>{{ .Description }}</p>
|
||||
</hgroup>
|
||||
{{- else -}}
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{- end }}
|
||||
</header>
|
||||
{{ end }}
|
||||
|
||||
{{ define "content" }}
|
||||
<section data-layout="console">
|
||||
|
||||
<nav aria-label="Documentation" data-nav="sidebar">
|
||||
{{- $menu := index .Site.Menus "docs" -}}
|
||||
{{- if $menu -}}
|
||||
{{- range $menu -}}
|
||||
{{- if .HasChildren -}}
|
||||
<h3>{{ .Name }}</h3>
|
||||
<ul>
|
||||
{{- range .Children -}}
|
||||
<li>
|
||||
<a href="{{ .URL }}"
|
||||
{{- if eq (relURL .URL) $.RelPermalink }} aria-current="page"{{ end -}}>
|
||||
{{- .Name -}}
|
||||
</a>
|
||||
</li>
|
||||
{{- end -}}
|
||||
</ul>
|
||||
{{- else -}}
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ .URL }}"
|
||||
{{- if eq (relURL .URL) $.RelPermalink }} aria-current="page"{{ end -}}>
|
||||
{{- .Name -}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- with .CurrentSection -}}
|
||||
<h3>{{ .Title }}</h3>
|
||||
<ul>
|
||||
{{- range .RegularPages -}}
|
||||
<li>
|
||||
<a href="{{ .RelPermalink }}"
|
||||
{{- if eq .RelPermalink $.RelPermalink }} aria-current="page"{{ end -}}>
|
||||
{{- .LinkTitle -}}
|
||||
</a>
|
||||
</li>
|
||||
{{- end -}}
|
||||
</ul>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
</nav>
|
||||
|
||||
<article>
|
||||
{{ .Content }}
|
||||
|
||||
{{- if or .PrevInSection .NextInSection -}}
|
||||
<footer data-role="prev-next">
|
||||
{{- with .NextInSection -}}
|
||||
<a href="{{ .RelPermalink }}" rel="prev">
|
||||
<span aria-hidden="true">←</span> Previous
|
||||
<span>{{ .LinkTitle }}</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
{{- with .PrevInSection -}}
|
||||
<a href="{{ .RelPermalink }}" rel="next">
|
||||
Next <span aria-hidden="true">→</span>
|
||||
<span>{{ .LinkTitle }}</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
</footer>
|
||||
{{- end -}}
|
||||
</article>
|
||||
|
||||
{{- with .TableOfContents -}}
|
||||
<aside data-toc>
|
||||
<h3>On this page</h3>
|
||||
{{ . }}
|
||||
</aside>
|
||||
{{- end -}}
|
||||
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
{{- if $menu -}}
|
||||
{{- range $menu -}}
|
||||
{{- if .HasChildren -}}
|
||||
<small>{{ .Name }}</small>
|
||||
<h3>{{ .Name }}</h3>
|
||||
<ul>
|
||||
{{- range .Children -}}
|
||||
<li>
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- with .CurrentSection -}}
|
||||
<small>{{ .Title }}</small>
|
||||
<h3>{{ .Title }}</h3>
|
||||
<ul>
|
||||
{{- range .RegularPages -}}
|
||||
<li>
|
||||
|
|
@ -58,20 +58,20 @@
|
|||
{{- end -}}
|
||||
</nav>
|
||||
|
||||
<article role="main">
|
||||
<article>
|
||||
{{ .Content }}
|
||||
|
||||
{{- if or .PrevInSection .NextInSection -}}
|
||||
<footer data-role="prev-next">
|
||||
{{- with .NextInSection -}}
|
||||
<a href="{{ .RelPermalink }}" rel="prev">
|
||||
<small>← Previous</small>
|
||||
<span aria-hidden="true">←</span> Previous
|
||||
<span>{{ .LinkTitle }}</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
{{- with .PrevInSection -}}
|
||||
<a href="{{ .RelPermalink }}" rel="next">
|
||||
<small>Next →</small>
|
||||
Next <span aria-hidden="true">→</span>
|
||||
<span>{{ .LinkTitle }}</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
|
||||
{{- with .TableOfContents -}}
|
||||
<aside data-toc>
|
||||
<small>On this page</small>
|
||||
<h3>On this page</h3>
|
||||
{{ . }}
|
||||
</aside>
|
||||
{{- end -}}
|
||||
|
|
@ -14,13 +14,13 @@
|
|||
{{ define "content" }}
|
||||
<section data-layout="docs">
|
||||
|
||||
<nav aria-label="Vault" data-nav="sidebar">
|
||||
{{- $menuName := .Site.Params.vault_menu | default "vault" -}}
|
||||
<nav aria-label="Notes" data-nav="sidebar">
|
||||
{{- $menuName := .Site.Params.notes_menu | default "notes" -}}
|
||||
{{- $menu := index .Site.Menus $menuName -}}
|
||||
{{- if $menu -}}
|
||||
{{- range $menu -}}
|
||||
{{- if .HasChildren -}}
|
||||
<small>{{ .Name }}</small>
|
||||
<h3>{{ .Name }}</h3>
|
||||
<ul>
|
||||
{{- range .Children -}}
|
||||
<li>
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- with .CurrentSection -}}
|
||||
<small>{{ .Title }}</small>
|
||||
<h3>{{ .Title }}</h3>
|
||||
<ul>
|
||||
{{- range .RegularPages -}}
|
||||
<li>
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
{{- end -}}
|
||||
</nav>
|
||||
|
||||
<article role="main">
|
||||
<article>
|
||||
{{ .Content }}
|
||||
|
||||
{{- $prevURL := index .Params "prev-url" -}}
|
||||
|
|
@ -70,13 +70,13 @@
|
|||
<footer data-role="prev-next">
|
||||
{{- if $prevURL -}}
|
||||
<a href="{{ $prevURL }}" rel="prev">
|
||||
<small>← Previous</small>
|
||||
<span aria-hidden="true">←</span> Previous
|
||||
<span>{{ $prevTitle }}</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
{{- if and $nextURL $nextTitle -}}
|
||||
<a href="{{ $nextURL }}" rel="next">
|
||||
<small>Next →</small>
|
||||
Next <span aria-hidden="true">→</span>
|
||||
<span>{{ $nextTitle }}</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
|
||||
{{- with .TableOfContents -}}
|
||||
<aside data-toc>
|
||||
<small>On this page</small>
|
||||
<h3>On this page</h3>
|
||||
{{ . }}
|
||||
</aside>
|
||||
{{- end -}}
|
||||
11
site/layouts/page/single.html
Normal file
11
site/layouts/page/single.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{{ define "header" }}{{ end }}
|
||||
|
||||
{{ define "content" }}
|
||||
<main>
|
||||
<header>
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{- with .Description }}<p>{{ . }}</p>{{ end }}
|
||||
</header>
|
||||
{{ .Content }}
|
||||
</main>
|
||||
{{ end }}
|
||||
41
site/layouts/partials/head.html
Normal file
41
site/layouts/partials/head.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>
|
||||
{{- if .IsHome -}}
|
||||
{{ .Site.Title }}
|
||||
{{- else -}}
|
||||
{{ .Title }} · {{ .Site.Title }}
|
||||
{{- end -}}
|
||||
</title>
|
||||
{{- with .Description }}<meta name="description" content="{{ . }}">{{- end }}
|
||||
{{- if not .Description }}{{- with .Site.Params.description }}<meta name="description" content="{{ . }}">{{- end }}{{- end }}
|
||||
|
||||
{{- /* ── Meta partials ─────────────────────────────────────────── */}}
|
||||
{{- partial "meta/seo.html" . -}}
|
||||
{{- partial "meta/og.html" . -}}
|
||||
{{- partial "meta/ai-disclosure.html" . -}}
|
||||
{{- partial "meta/json-ld.html" . -}}
|
||||
|
||||
{{- /* ── CSS ────────────────────────────────────────────────────── */}}
|
||||
{{- if hugo.IsDevelopment }}
|
||||
<link rel="stylesheet" href="/vendor/open-props.min.css">
|
||||
<link rel="stylesheet" href="/vendor/media.min.css">
|
||||
<link rel="stylesheet" href="/css/layers/00-reset.css">
|
||||
<link rel="stylesheet" href="/css/layers/01-asw.css">
|
||||
<link rel="stylesheet" href="/css/layers/02-semantic.css">
|
||||
<link rel="stylesheet" href="/css/layers/03-components.css">
|
||||
<link rel="stylesheet" href="/css/layers/04-data-attrs.css">
|
||||
<link rel="stylesheet" href="/css/layers/05-utilities.css">
|
||||
<link rel="stylesheet" href="/css/layers/06-charts.css">
|
||||
<link rel="stylesheet" href="/css/layers/07-chroma.css">
|
||||
<link rel="stylesheet" href="/css/layers/08-layout.css">
|
||||
<link rel="stylesheet" href="/css/layers/08a-paper.css">
|
||||
<link rel="stylesheet" href="/css/layers/09-landing.css">
|
||||
{{- else }}
|
||||
<link rel="stylesheet" href="/asw.css">
|
||||
{{- end }}
|
||||
|
||||
{{- range .AlternativeOutputFormats -}}
|
||||
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
|
||||
{{- end }}
|
||||
|
|
@ -38,6 +38,12 @@
|
|||
vigilio-garden: --palette-hue: 150 (subtle green tint)
|
||||
══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
/* What I think should go to palettes - @vigilio */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
:root {
|
||||
|
||||
/* ── Palette controls ───────────────────────────────────────────────
|
||||
|
|
@ -49,15 +55,15 @@
|
|||
|
||||
/* ── Surfaces — dark end of the 16-step scale ─────────────────── */
|
||||
|
||||
--surface: var(--color-16); /* ~10% lightness */
|
||||
--surface-1: var(--color-15); /* ~16% */
|
||||
--surface-2: var(--color-14); /* ~20% */
|
||||
--surface: var(--color-14); /* ~10% lightness */
|
||||
--surface-1: var(--color-13); /* ~16% */
|
||||
--surface-2: var(--color-11); /* ~20% */
|
||||
--surface-card: var(--surface-1);
|
||||
--surface-hover: var(--surface-2);
|
||||
|
||||
/* ── Text — light end of the scale ────────────────────────────── */
|
||||
|
||||
--text: var(--color-3); /* 93% lightness */
|
||||
--text: var(--color-6); /* 93% lightness */
|
||||
--text-2: var(--color-5); /* 80% */
|
||||
--text-3: var(--color-7); /* 66% */
|
||||
--text-dim: var(--color-9); /* 53% */
|
||||
|
|
@ -389,3 +395,19 @@
|
|||
@media (--lg-n-above) { html { font-size: 103%; } }
|
||||
@media (--xl-n-above) { html { font-size: 106%; } }
|
||||
@media (--xxl-n-above) { html { font-size: 109%; } }
|
||||
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════
|
||||
EDITORIAL DEFAULTS
|
||||
Opinionated ASW decisions that go beyond tokens — centering,
|
||||
spacing rhythms, and layout choices that define the ASW look.
|
||||
══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
/* Nav content centered at --width-xl without a wrapper element.
|
||||
max() falls back to --container-padding on narrow viewports. */
|
||||
body > nav {
|
||||
padding-inline: max(var(--container-padding), calc((100% - var(--width-xl)) / 2));
|
||||
}
|
||||
[data-layout="docs"] > article {
|
||||
max-width: var(--width-prose);
|
||||
}
|
||||
|
|
@ -88,17 +88,17 @@ textarea {
|
|||
font-family: var(--font-ui);
|
||||
}
|
||||
|
||||
/* ── Nav layout ─────────────────────────────────────────────────────── */
|
||||
/* Ported from Pico CSS, translated to ASW tokens. */
|
||||
/* ── Top nav layout ──────────────────────────────────────────────────── */
|
||||
/* Scoped to body > nav — sidebar and other navs are not affected. */
|
||||
|
||||
nav {
|
||||
body > nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
body > nav ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
|
@ -108,13 +108,13 @@ nav ul {
|
|||
list-style: none;
|
||||
}
|
||||
|
||||
nav li {
|
||||
body > nav li {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
}
|
||||
|
||||
nav li a {
|
||||
body > nav li a {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
color: var(--text);
|
||||
|
|
@ -123,19 +123,19 @@ nav li a {
|
|||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
nav li a:hover {
|
||||
body > nav li a:hover {
|
||||
color: var(--accent);
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
nav li strong,
|
||||
nav li b {
|
||||
body > nav li strong,
|
||||
body > nav li b {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
@media (--md-n-below) {
|
||||
nav { flex-wrap: wrap; gap: var(--space-2); }
|
||||
nav ul { flex-wrap: wrap; gap: var(--space-1); }
|
||||
body > nav { flex-wrap: wrap; gap: var(--space-2); }
|
||||
body > nav ul { flex-wrap: wrap; gap: var(--space-1); }
|
||||
}
|
||||
|
||||
/* ── Typography: Paragraphs ────────────────────────────────────────── */
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
* 03-components.css
|
||||
* UI component patterns (buttons, forms, nav, dialog, details)
|
||||
* Part of: Agentic Semantic Web
|
||||
*
|
||||
*
|
||||
* Ported from: Pico CSS v2.1.1
|
||||
* License: MIT
|
||||
*
|
||||
*
|
||||
* Modernizations:
|
||||
* - Uses `accent-color` for checkbox/radio (simpler than background-image)
|
||||
* - Drops class-based button variants (.secondary, .contrast, .outline)
|
||||
|
|
@ -42,8 +42,8 @@ button,
|
|||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: background-color var(--ease),
|
||||
border-color var(--ease),
|
||||
transition: background-color var(--ease),
|
||||
border-color var(--ease),
|
||||
color var(--ease);
|
||||
}
|
||||
|
||||
|
|
@ -114,8 +114,8 @@ textarea {
|
|||
background-color: var(--input-bg);
|
||||
color: var(--text);
|
||||
font-weight: var(--font-weight-4);
|
||||
transition: background-color var(--ease),
|
||||
border-color var(--ease),
|
||||
transition: background-color var(--ease),
|
||||
border-color var(--ease),
|
||||
color var(--ease);
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ label:has([type=checkbox], [type=radio]) {
|
|||
margin-right: 0.5em;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
|
||||
|
||||
/* Modern CSS: use browser's native styling with our accent color */
|
||||
accent-color: var(--accent);
|
||||
}
|
||||
|
|
@ -265,6 +265,7 @@ body > nav {
|
|||
align-items: center;
|
||||
padding-top: var(--space-5);
|
||||
padding-bottom: var(--space-5);
|
||||
|
||||
margin-bottom: var(--space-6);
|
||||
border-bottom: var(--border-width) solid var(--border);
|
||||
}
|
||||
|
|
@ -324,11 +325,11 @@ body > nav a[aria-current="page"] {
|
|||
align-items: flex-start;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
|
||||
body > nav ul:last-child {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
body > nav ul:last-child li + li::before {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -422,7 +423,7 @@ body > nav details > ul li a:hover {
|
|||
/* Close dropdown when clicking outside (CSS-only via :focus-within) */
|
||||
nav details:not(:focus-within) > ul,
|
||||
nav details:not(:focus-within) > div {
|
||||
/* Allow browser default open/close behavior —
|
||||
/* Allow browser default open/close behavior —
|
||||
no forced hiding. Agent can add JS for click-outside. */
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +452,7 @@ article {
|
|||
background: transparent;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 1rem 1.25rem;
|
||||
padding: var(--size-3) var(--size-4);
|
||||
margin: var(--space-3) 0;
|
||||
}
|
||||
|
||||
|
|
@ -482,11 +483,11 @@ article header h3 {
|
|||
padding-bottom: 0;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
|
||||
article header h3 {
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
|
||||
article > :is(p, dl, ul, ol) {
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
|
@ -497,7 +498,7 @@ article header h3 {
|
|||
article {
|
||||
padding: var(--space-5) var(--space-6);
|
||||
}
|
||||
|
||||
|
||||
article > header {
|
||||
margin-bottom: var(--space-3);
|
||||
padding-bottom: var(--space-2);
|
||||
|
|
@ -953,3 +954,92 @@ dialog > footer {
|
|||
[data-role="steps"][data-layout="vertical"] > li > span {
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
/* ── Sidebar nav ────────────────────────────────────────────────────── */
|
||||
|
||||
nav[data-nav="sidebar"] h3 {
|
||||
color: var(--text-3);
|
||||
font-size: var(--text-xs);
|
||||
font-family: var(--font-mono);
|
||||
font-weight: var(--font-weight-5);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
margin-top: var(--space-4);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] h3:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
gap: var(--space-1);
|
||||
font-family: var(--font-ui);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] a {
|
||||
display: block;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--text-2);
|
||||
text-decoration: none;
|
||||
transition: background-color var(--ease), color var(--ease);
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] a:hover {
|
||||
background-color: var(--surface-hover);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] a[aria-current] {
|
||||
background-color: var(--accent-subtle);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ── TOC (aside) ────────────────────────────────────────────────────── */
|
||||
|
||||
aside[data-toc] h3 {
|
||||
color: var(--text-3);
|
||||
font-size: var(--text-xs);
|
||||
font-family: var(--font-mono);
|
||||
font-weight: var(--font-weight-5);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
margin-bottom: var(--space-2);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
aside[data-toc] nav ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
gap: var(--space-1);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
aside[data-toc] nav a {
|
||||
display: block;
|
||||
padding: var(--space-1) var(--space-2);
|
||||
color: var(--text-3);
|
||||
text-decoration: none;
|
||||
border-left: var(--border-size-2) solid transparent;
|
||||
transition: color var(--ease), border-color var(--ease);
|
||||
}
|
||||
|
||||
aside[data-toc] nav a:hover {
|
||||
color: var(--text);
|
||||
border-left-color: var(--border);
|
||||
}
|
||||
|
||||
aside[data-toc] nav a[aria-current] {
|
||||
color: var(--accent);
|
||||
border-left-color: var(--accent);
|
||||
}
|
||||
|
|
@ -13,71 +13,26 @@
|
|||
}
|
||||
|
||||
/* ── Body landmark container ────────────────────────────────────────── */
|
||||
/* All body-level landmarks share container alignment:
|
||||
<body> > <nav>, <header>, <article role="main">, <footer> */
|
||||
|
||||
body > nav,
|
||||
body > header,
|
||||
body > article,
|
||||
body > section,
|
||||
body > footer {
|
||||
body > nav { width: 100%; }
|
||||
body > footer { width: 100%; }
|
||||
|
||||
/* Header: wider than article — room for hero titles, eyebrows, meta. */
|
||||
body > header {
|
||||
width: 100%;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding-right: var(--container-padding);
|
||||
padding-left: var(--container-padding);
|
||||
max-width: var(--width-lg);
|
||||
margin-inline: auto;
|
||||
padding-inline: var(--container-padding);
|
||||
}
|
||||
|
||||
@media (--sm-n-above) {
|
||||
body > nav,
|
||||
body > header,
|
||||
body > article,
|
||||
body > section,
|
||||
body > footer {
|
||||
max-width: var(--width-sm);
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (--md-n-above) {
|
||||
body > nav,
|
||||
body > header,
|
||||
body > article,
|
||||
body > section,
|
||||
body > footer {
|
||||
max-width: var(--width-md);
|
||||
}
|
||||
}
|
||||
|
||||
@media (--lg-n-above) {
|
||||
body > nav,
|
||||
body > header,
|
||||
body > article,
|
||||
body > section,
|
||||
body > footer {
|
||||
max-width: var(--width-lg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (--xl-n-above) {
|
||||
body > nav,
|
||||
body > header,
|
||||
body > article,
|
||||
body > section,
|
||||
body > footer {
|
||||
max-width: var(--width-xl);
|
||||
}
|
||||
}
|
||||
|
||||
@media (--xxl-n-above) {
|
||||
body > nav,
|
||||
body > header,
|
||||
body > article,
|
||||
body > section,
|
||||
body > footer {
|
||||
max-width: var(--width-2xl);
|
||||
}
|
||||
/* Article and section: standard content width. Reading width lives on
|
||||
inner elements (p, li…) via max-inline-size — not on the container. */
|
||||
body > article,
|
||||
body > section {
|
||||
width: 100%;
|
||||
max-width: var(--width-lg);
|
||||
margin-inline: auto;
|
||||
padding-inline: var(--container-padding);
|
||||
}
|
||||
|
||||
/* ── Body baseline ──────────────────────────────────────────────────── */
|
||||
|
|
@ -148,106 +103,21 @@ nav[data-layout="actions"] a:hover {
|
|||
align-items: start;
|
||||
}
|
||||
|
||||
/* ── Left sidebar ───────────────────────────────────────────────────── */
|
||||
/* ── Sidebar + TOC shared sticky behaviour ──────────────────────────── */
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"] {
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"],
|
||||
[data-layout="docs"] > aside[data-toc] {
|
||||
position: sticky;
|
||||
top: calc(var(--nav-height) + var(--space-4));
|
||||
max-height: calc(100vh - var(--size-px-10));
|
||||
max-height: calc(100vh - var(--nav-height) - var(--space-4) * 2);
|
||||
overflow-y: auto;
|
||||
/* ASW-styled scrollbar — thin, subtle, no system chrome */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--border) transparent;
|
||||
}
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"]::-webkit-scrollbar {
|
||||
width: var(--scrollbar-size);
|
||||
}
|
||||
/* ── Left sidebar ───────────────────────────────────────────────────── */
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"]::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"]::-webkit-scrollbar-thumb {
|
||||
background: var(--border);
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"]::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-3);
|
||||
}
|
||||
|
||||
/* Sidebar nav — vertical list, no top-bar chrome */
|
||||
nav[data-nav="sidebar"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] small {
|
||||
display: block;
|
||||
color: var(--text-3);
|
||||
font-size: var(--text-xs);
|
||||
font-family: var(--font-mono);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
padding: 0 var(--space-3);
|
||||
margin-bottom: var(--space-2);
|
||||
margin-top: var(--space-4);
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] small:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
gap: var(--space-1);
|
||||
font-family: var(--font-ui);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
nav[data-nav="sidebar"] ul li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* No pipe separators in sidebar */
|
||||
nav[data-nav="sidebar"] ul li + li::before,
|
||||
nav[data-nav="sidebar"] ul li + li::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"] nav a {
|
||||
display: block;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--text-2);
|
||||
text-decoration: none;
|
||||
text-align: left;
|
||||
transition: background-color var(--ease), color var(--ease);
|
||||
font-family: var(--font-ui);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"] nav a:hover {
|
||||
background-color: var(--surface-hover);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"] nav a[aria-current] {
|
||||
background-color: var(--accent-subtle);
|
||||
color: var(--accent);
|
||||
[data-layout="docs"] > nav[data-nav="sidebar"] {
|
||||
top: calc(var(--nav-height) + var(--space-4));
|
||||
}
|
||||
|
||||
/* ── Main content ───────────────────────────────────────────────────── */
|
||||
|
|
@ -259,77 +129,10 @@ nav[data-nav="sidebar"] ul li + li::before {
|
|||
/* ── Right TOC ──────────────────────────────────────────────────────── */
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] {
|
||||
position: sticky;
|
||||
top: calc(var(--nav-height) + var(--space-4));
|
||||
max-height: calc(100vh - var(--size-px-10));
|
||||
overflow-y: auto;
|
||||
top: calc(var(--nav-height) + var(--space-8));
|
||||
padding-top: var(--space-8);
|
||||
}
|
||||
|
||||
/* TOC nav — vertical, compact, no top-bar chrome */
|
||||
[data-layout="docs"] > aside[data-toc] nav,
|
||||
nav[data-nav="toc"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] small {
|
||||
display: block;
|
||||
color: var(--text-3);
|
||||
font-size: var(--text-xs);
|
||||
font-family: var(--font-mono);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] nav ul,
|
||||
nav[data-nav="toc"] ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
gap: var(--space-1);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] nav ul li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] nav ul li + li::before,
|
||||
nav[data-nav="toc"] ul li + li::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] nav a {
|
||||
display: block;
|
||||
padding: var(--space-1) var(--space-2);
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-3);
|
||||
text-decoration: none;
|
||||
text-align: left;
|
||||
border-left: var(--border-size-2) solid transparent;
|
||||
transition: color var(--ease), border-color var(--ease);
|
||||
}
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] nav a:hover {
|
||||
color: var(--text);
|
||||
border-left-color: var(--border);
|
||||
}
|
||||
|
||||
[data-layout="docs"] > aside[data-toc] nav a[aria-current] {
|
||||
color: var(--accent);
|
||||
border-left-color: var(--accent);
|
||||
}
|
||||
|
||||
/* ── Prev/Next navigation ───────────────────────────────────────────── */
|
||||
|
||||
|
|
@ -405,6 +208,62 @@ nav[data-nav="toc"] ul li + li::before {
|
|||
min-width: 0;
|
||||
}
|
||||
|
||||
/* ── Console layout ─────────────────────────────────────────────────── */
|
||||
/* Docs variant: sidebar flush to the viewport left edge. */
|
||||
/* No outer centering — grid spans full width, sidebar has no left gap. */
|
||||
|
||||
[data-layout="console"] {
|
||||
display: grid;
|
||||
grid-template-columns: var(--sidebar-width) 1fr var(--toc-width);
|
||||
grid-template-rows: auto;
|
||||
gap: var(--space-6);
|
||||
padding: var(--space-6) var(--space-5) var(--space-6) 0;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
[data-layout="console"] > nav[data-nav="sidebar"],
|
||||
[data-layout="console"] > aside[data-toc] {
|
||||
position: sticky;
|
||||
max-height: calc(100vh - var(--nav-height) - var(--space-4) * 2);
|
||||
overflow-y: auto;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--border) transparent;
|
||||
}
|
||||
|
||||
[data-layout="console"] > nav[data-nav="sidebar"] {
|
||||
top: calc(var(--nav-height) + var(--space-4));
|
||||
padding-inline: var(--space-3);
|
||||
}
|
||||
|
||||
[data-layout="console"] > article {
|
||||
min-width: 0;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
[data-layout="console"] > aside[data-toc] {
|
||||
top: calc(var(--nav-height) + var(--space-8));
|
||||
padding-top: var(--space-8);
|
||||
}
|
||||
|
||||
@media (--docs-toc-hidden) {
|
||||
[data-layout="console"] {
|
||||
grid-template-columns: var(--sidebar-width) 1fr;
|
||||
}
|
||||
[data-layout="console"] > aside[data-toc] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (--md-n-below) {
|
||||
[data-layout="console"] {
|
||||
grid-template-columns: 1fr;
|
||||
padding: var(--space-4);
|
||||
}
|
||||
[data-layout="console"] > nav[data-nav="sidebar"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Grid helpers ───────────────────────────────────────────────────── */
|
||||
|
||||
[data-layout="grid-2"] {
|
||||
|
|
@ -20,5 +20,5 @@
|
|||
@import "./layers/06-charts.css";
|
||||
@import "./layers/07-chroma.css";
|
||||
@import "./layers/08-layout.css";
|
||||
@import "./layers/08a-paper.css";
|
||||
@import "./layers/08a-essay.css";
|
||||
@import "./layers/09-landing.css";
|
||||
20
vendor/README.md
vendored
Normal file
20
vendor/README.md
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# vendor/
|
||||
|
||||
Third-party CSS files vendored directly into the repo so the build has no runtime npm dependency.
|
||||
|
||||
## Contents
|
||||
|
||||
| Directory | Package | Version | Files vendored |
|
||||
|-----------|---------|---------|----------------|
|
||||
| `open-props/` | [open-props](https://open-props.style/) | 1.7.23 | `open-props.min.css`, `media.min.css` |
|
||||
|
||||
## How to update
|
||||
|
||||
1. Bump the version in `package.json` and run `npm install`.
|
||||
2. Copy the new files:
|
||||
```bash
|
||||
cp node_modules/open-props/open-props.min.css vendor/open-props/open-props.min.css
|
||||
cp node_modules/open-props/media.min.css vendor/open-props/media.min.css
|
||||
```
|
||||
3. Update `vendor/open-props/VERSION` with the new version and today's date.
|
||||
4. Commit all three changed files together.
|
||||
1
vendor/open-props/VERSION
vendored
Normal file
1
vendor/open-props/VERSION
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
open-props@1.7.23 — vendored 2026-04-11
|
||||
1
vendor/open-props/media.min.css
vendored
Normal file
1
vendor/open-props/media.min.css
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
@custom-media --motionOK (prefers-reduced-motion: no-preference);@custom-media --motionNotOK (prefers-reduced-motion: reduce);@custom-media --opacityOK (prefers-reduced-transparency: no-preference);@custom-media --opacityNotOK (prefers-reduced-transparency: reduce);@custom-media --useDataOK (prefers-reduced-data: no-preference);@custom-media --useDataNotOK (prefers-reduced-data: reduce);@custom-media --OSdark (prefers-color-scheme: dark);@custom-media --OSlight (prefers-color-scheme: light);@custom-media --highContrast (prefers-contrast: more);@custom-media --lowContrast (prefers-contrast: less);@custom-media --invertedColors (inverted-colors: inverted);@custom-media --forcedColors (forced-colors: active);@custom-media --portrait (orientation: portrait);@custom-media --landscape (orientation: landscape);@custom-media --HDcolor (dynamic-range: high) or (color-gamut: p3);@custom-media --touch (hover: none) and (pointer: coarse);@custom-media --stylus (hover: none) and (pointer: fine);@custom-media --pointer (hover) and (pointer: coarse);@custom-media --mouse (hover) and (pointer: fine);@custom-media --xxs-only (min-width: 0px) and (max-width: 239.98px);@custom-media --xxs-n-above (min-width: 240px);@custom-media --xxs-n-below (max-width: 239.98px);@custom-media --xxs-phone (--xxs-only) and (--portrait);@custom-media --xs-only (min-width: 240px) and (max-width: 359.98px);@custom-media --xs-n-above (min-width: 360px);@custom-media --xs-n-below (max-width: 359.98px);@custom-media --xs-phone (--xs-only) and (--portrait);@custom-media --sm-only (min-width: 360px) and (max-width: 479.98px);@custom-media --sm-n-above (min-width: 480px);@custom-media --sm-n-below (max-width: 479.98px);@custom-media --sm-phone (--sm-only) and (--portrait);@custom-media --md-only (min-width: 480px) and (max-width: 767.98px);@custom-media --md-n-above (min-width: 768px);@custom-media --md-n-below (max-width: 767.98px);@custom-media --md-phone (--md-only) and (--portrait);@custom-media --lg-only (min-width: 768px) and (max-width: 1023.98px);@custom-media --lg-n-above (min-width: 1024px);@custom-media --lg-n-below (max-width: 1023.98px);@custom-media --lg-phone (--lg-only) and (--portrait);@custom-media --xl-only (min-width: 1024px) and (max-width: 1439.98px);@custom-media --xl-n-above (min-width: 1440px);@custom-media --xl-n-below (max-width: 1439.98px);@custom-media --xxl-only (min-width: 1440px) and (max-width: 1919.98px);@custom-media --xxl-n-above (min-width: 1920px);@custom-media --xxl-n-below (max-width: 1919.98px);
|
||||
1
vendor/open-props/open-props.min.css
vendored
Normal file
1
vendor/open-props/open-props.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue