Compare commits
4 commits
0be1681da2
...
415bb4f402
| Author | SHA1 | Date | |
|---|---|---|---|
| 415bb4f402 | |||
| e3dbfa2fd1 | |||
| f3d4fc1626 | |||
| ad1cac3007 |
8 changed files with 1821 additions and 0 deletions
8
.env.example
Normal file
8
.env.example
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# OpenCD — Nous Auth Configuration
|
||||||
|
# Copy this to .env and fill in your credentials.
|
||||||
|
# Required for deployment to Nous infrastructure.
|
||||||
|
|
||||||
|
NOUS_AGENT_KEY=sk-nou...
|
||||||
|
NOUS_AGENT_KEY_ID=cmpkk7n6k000tkq0birz3zk5a
|
||||||
|
NOUS_API_BASE_URL=https://inference-api.nousresearch.com/v1
|
||||||
|
NOUS_PORTAL_URL=https://portal.nousresearch.com
|
||||||
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# OpenCD — Local environment (secrets, never commit)
|
||||||
|
.env
|
||||||
|
|
||||||
|
# OS metadata
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Editor
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
*.min.css
|
||||||
199
MISSION_BRIEF.md
Normal file
199
MISSION_BRIEF.md
Normal file
|
|
@ -0,0 +1,199 @@
|
||||||
|
# MISSION_BRIEF.md — OpenCD Gate Review
|
||||||
|
|
||||||
|
> **Agent:** Amy Amanda "Triple A" Allen — Intelligence & Quality Gate
|
||||||
|
> **Mission:** Gate review of RECON.md (Face) against DESIGN.md (Hannibal)
|
||||||
|
> **Status:** CONCERNS — see §Verdict
|
||||||
|
> **Date:** 2026-05-25
|
||||||
|
> **Context:** Pre-build quality gate (Phase 2 of implementation sequence, cf. DESIGN.md §7)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## I. Scope of Review
|
||||||
|
|
||||||
|
This gate validates three things before Murdock begins building `_variables.css`:
|
||||||
|
|
||||||
|
1. **Token accuracy** — Does every Open Props mapping in DESIGN.md match the source-verified values from RECON.md?
|
||||||
|
2. **Dimension accuracy** — Are the CD physical measurements correct and consistently applied?
|
||||||
|
3. **Pattern alignment** — Do the ASW, trentuna, and Human Advisory references translate correctly to the architecture?
|
||||||
|
4. **Coverage** — Did Face answer all five questions Hannibal posed in DESIGN.md §6?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## II. Source Verification Cross-Reference
|
||||||
|
|
||||||
|
### A. Token Mapping Table (DESIGN.md §2 → RECON.md Q1)
|
||||||
|
|
||||||
|
| DESIGN.md Mapping | RECON Finding | Verdict |
|
||||||
|
|---|---|---|
|
||||||
|
| `--size-fluid-1` = `clamp(.5rem, 1vw, 1rem)` | ✅ Confirmed | PASS |
|
||||||
|
| `--size-fluid-2` = `clamp(1rem, 2vw, 1.5rem)` | ✅ Confirmed | PASS |
|
||||||
|
| `--size-fluid-3` = `clamp(1.5rem, 3vw, 2rem)` | ✅ Confirmed | PASS |
|
||||||
|
| `--font-size-fluid-1` = `clamp(1rem, 4vw, 1.5rem)` | ✅ Confirmed | PASS |
|
||||||
|
| `--font-size-fluid-2` = `clamp(1.5rem, 6vw, 2.5rem)` | ✅ Confirmed | PASS |
|
||||||
|
| `--font-size-fluid-3` = `clamp(2rem, 9vw, 3.5rem)` | ✅ Confirmed | PASS |
|
||||||
|
| `--font-sans` = system-ui, sans-serif | ✅ Confirmed | PASS |
|
||||||
|
| `--font-serif` = ui-serif, serif | ✅ Confirmed | PASS |
|
||||||
|
| `--red-6` / `--red-7` | ✅ Confirmed | PASS |
|
||||||
|
| `--shadow-2` / `--shadow-3` | ✅ Confirmed | PASS |
|
||||||
|
| `--radius-2` (5px) | ✅ Confirmed | PASS |
|
||||||
|
| `--radius-3` (1rem) | ✅ Confirmed | PASS |
|
||||||
|
| `--gray-1` through `--gray-12` | ✅ Confirmed | PASS |
|
||||||
|
|
||||||
|
### B. CD Dimensions (DESIGN.md §2 → RECON.md Q2)
|
||||||
|
|
||||||
|
| Dimension | Source (ISO 15727) | DESIGN.md Value | Verdict |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Jewel case width | 142 mm | 280 px (2×) | PASS |
|
||||||
|
| Jewel case height | 125 mm | 245 px (2×) | PASS |
|
||||||
|
| Disc diameter | Ø 120 mm | 240 px (2×) | PASS |
|
||||||
|
| Leaflet page | 120 × 120 mm | 240 px (2×) | PASS |
|
||||||
|
| Spine width | ~7 mm | 14 px (2×) | PASS |
|
||||||
|
| Open width | 284 mm | 560 px (2×) | PASS |
|
||||||
|
|
||||||
|
### C. Coverage of Hannibal's Five Questions (DESIGN.md §6)
|
||||||
|
|
||||||
|
| Question | RECON Section | Answer Quality | Verdict |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Q1: Open Props Token Audit | Q1 (lines 10–121) | Full source-verified table, import paths, new tokens | PASS |
|
||||||
|
| Q2: CD Jewel Case Dimensions | Q2 (lines 124–180) | ISO standard, 2× scale analysis, region check, tray paper layout | PASS |
|
||||||
|
| Q3: ASW Design Patterns | Q3 (lines 183–266) | 11-layer architecture, semantic HTML examples, data-attribute vocabulary, token system | PASS |
|
||||||
|
| Q4: CD Packaging References | Q4 (lines 269–336) | 5 examples, grid analysis, PA badge specs | PASS |
|
||||||
|
| Q5: trentuna.com Aesthetic | Q5 (lines 339–390) | Fonts, palette, grid approach, content structure, lessons | PASS |
|
||||||
|
|
||||||
|
**Coverage verdict: PASS** — All five questions answered with source-verified evidence.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## III. Critical Findings — Issues Requiring Correction
|
||||||
|
|
||||||
|
These are discrepancies between what DESIGN.md assumes and what RECON.md proved to be true. **These must be resolved before Murdock builds `_variables.css`.**
|
||||||
|
|
||||||
|
### Finding #1: `--surface-*` tokens are NOT from Open Props
|
||||||
|
|
||||||
|
**Evidence:** RECON.md Q3 (lines 252–253) demonstrates `--surface`, `--surface-1` through `--surface-4` are ASW custom tokens defined as `oklch()` with `--palette-hue` tinting. Open Props has no surface tokens.
|
||||||
|
|
||||||
|
**Impact:** DESIGN.md §2 maps `--surface-1` → `--cd-tray-bg`, `--surface-2` → `--cd-tray-bg-raised`, `--surface-3` → `--cd-tray-bg-sunken`, `--surface-4` → `--cd-spine-bg`. These will silently resolve to `unset` if not explicitly defined.
|
||||||
|
|
||||||
|
**Correction:** Define `--cd-surface-1` through `--cd-surface-4` directly in `_variables.css` following the ASW pattern:
|
||||||
|
```css
|
||||||
|
--cd-surface-1: oklch(30% .015 265);
|
||||||
|
--cd-surface-2: oklch(35% .015 265);
|
||||||
|
--cd-surface-3: oklch(40% .015 265);
|
||||||
|
--cd-surface-4: oklch(15% .01 265);
|
||||||
|
```
|
||||||
|
(Values to be finalized by Murdock — this is the structural requirement.)
|
||||||
|
|
||||||
|
### Finding #2: `--grid-*` tokens don't exist in Open Props
|
||||||
|
|
||||||
|
**Evidence:** RECON.md Cross-Reference (lines 105, 403) explicitly notes `--grid-1` and `--grid-2` are NOT Open Props tokens.
|
||||||
|
|
||||||
|
**Impact:** DESIGN.md §2 maps `--grid-1` → `--cd-grid-color` and `--grid-2` → `--cd-grid-color-alt`. These resolve to nothing.
|
||||||
|
|
||||||
|
**Correction:** Define as custom properties using gray shades that do exist in Open Props:
|
||||||
|
```css
|
||||||
|
--cd-grid-color: var(--gray-3);
|
||||||
|
--cd-grid-color-alt: var(--gray-2);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Finding #3: `--cd-scale` semantics differ between DESIGN.md and RECON.md
|
||||||
|
|
||||||
|
**Evidence:**
|
||||||
|
- RECON.md (lines 148–157): Recommends `--cd-scale: 1` as default, where `1 = 2×` scale. Formula `calc(142px * var(--cd-scale))` where scale=1 gives 142px (which is NOT 2×).
|
||||||
|
- DESIGN.md (line 265): `--cd-scale: 2` where value=2 means "multiply physical mm by this to get px."
|
||||||
|
|
||||||
|
**Impact:** Inconsistency. If a user reads both documents, they'll get different behavior. Under DESIGN's scheme, `--cd-scale: 2` gives 284px jewel width (not 280px as documented). Under RECON's, `--cd-scale: 1` gives 142px (wrong).
|
||||||
|
|
||||||
|
**Correction needed:** Pick ONE semantics and make it explicit:
|
||||||
|
- Option A: `--cd-scale: 1` = physical mm → px (1:1). Default 1 gives 142px. If you want 2×, set `--cd-scale: 2`.
|
||||||
|
- Option B: `--cd-scale: 1` = "1 unit of scale" where base=2×. Uses a pre-calibrated formula: `calc(142px * var(--cd-scale))` where scale=1 gives 280px because the base values are already in px at 2×.
|
||||||
|
|
||||||
|
**Recommendation:** Option A is cleaner and more intuitive for users. But the entire DESIGN.md and README hardcode 280px/245px/240px values. If we change the semantics, every dimension formula changes. **Stick with DESIGN.md's current approach** (`--cd-scale: 2` means 2× multiplier on mm→px conversion) but make the formula explicitly mm→px:
|
||||||
|
```css
|
||||||
|
--cd-jewel-width: calc(142mm * var(--cd-scale) * 3.78px / 1mm); /* 3.78px/mm at 96dpi */
|
||||||
|
/* Or simpler: hardcode 2× values and multiply --cd-scale against those */
|
||||||
|
```
|
||||||
|
OR, simplest solution that avoids the scaling math entirely:
|
||||||
|
```css
|
||||||
|
--cd-scale: 1; /* 1 = default 2× scale. Set to 0.5 for 1×, 2 for 4× */
|
||||||
|
--cd-jewel-width: calc(280px * var(--cd-scale));
|
||||||
|
```
|
||||||
|
Document this clearly. **Action: update both DESIGN.md and `_variables.css` to use this unambiguous formula.**
|
||||||
|
|
||||||
|
### Finding #4: Font recommendation — consider `--font-neo-grotesque` for spine labels
|
||||||
|
|
||||||
|
**Evidence:** RECON.md Q1 (line 74) and Cross-Reference (line 407) recommend `--font-neo-grotesque` (Inter → Roboto → Helvetica Neue) over `--font-sans` (system-ui) for spine labels. System-ui varies significantly across platforms (Chicago on macOS, Segoe UI on Windows).
|
||||||
|
|
||||||
|
**Impact:** Low severity. System-ui is readable, but spine labels benefit from the consistent, designed look of Inter/Roboto.
|
||||||
|
|
||||||
|
**Correction:** Non-blocking recommendation. Update DESIGN.md §2 or `_variables.css` to use `--font-neo-grotesque` for `--cd-font-label`:
|
||||||
|
```css
|
||||||
|
--cd-font-label: var(--font-neo-grotesque);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## IV. Additional Observations (Non-Critical)
|
||||||
|
|
||||||
|
### ASW Gap Fills Worth Noting
|
||||||
|
RECON.md (lines 258–260) identifies `--space-3` (0.75rem) and `--text-sm` (0.875rem) as values Open Props doesn't natively provide. If OpenCD needs these for spacing/sizing between Open Props' discrete steps, define them alongside the `--cd-*` tokens.
|
||||||
|
|
||||||
|
### New Open Props Features for Consideration
|
||||||
|
RECON.md (lines 115–121) documents: easings (`--ease-elastic-*`), animations (21 presets), aspect ratios, line heights. The `--ease-flip` token in DESIGN.md currently uses a raw `cubic-bezier()`; consider mapping it to an Open Props easing token if one matches.
|
||||||
|
|
||||||
|
### Human Advisory Badge — Red/Black Variant
|
||||||
|
RECON.md (lines 297–298) suggests supporting both classic black/white and OpenCD red/black variants. DESIGN.md currently only specifies red (`--cd-advisory-red`). Consider adding `--cd-advisory-scheme` to toggle.
|
||||||
|
|
||||||
|
### Visible Grid — Two Sizes
|
||||||
|
DESIGN.md calls for `.cd-grid--fine` (denser tray) and `.cd-grid--coarse` (leaflet). RECON.md provides the base 8px grid formula. The grid sizes should be documented as variables:
|
||||||
|
```css
|
||||||
|
--cd-grid-fine: 4px;
|
||||||
|
--cd-grid-coarse: 8px;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## V. Verdict
|
||||||
|
|
||||||
|
**Overall: CONCERNS**
|
||||||
|
|
||||||
|
| Dimension | Rating | Detail |
|
||||||
|
|---|---|---|
|
||||||
|
| Token accuracy | ✅ PASS | All Open Props tokens source-verified |
|
||||||
|
| Dimension accuracy | ✅ PASS | ISO 15727 confirmed, no regional variance |
|
||||||
|
| Design alignment | ⚠️ CONCERNS | 4 issues (fnd #1–#4) require correction |
|
||||||
|
| Recon coverage | ✅ PASS | All 5 questions answered thoroughly |
|
||||||
|
| Source verification | ✅ PASS | Every source accessed and cross-referenced |
|
||||||
|
| Precision | ⚠️ CONCERNS | `--cd-scale` semantics ambiguous across docs |
|
||||||
|
|
||||||
|
### Gate Decisions
|
||||||
|
|
||||||
|
| Gate | Status | Action Required |
|
||||||
|
|---|---|---|
|
||||||
|
| **Pre-build Gate** | **CONCERNS** | Resolve findings #1–#3 before Murdock builds `_variables.css`. Finding #4 is advisory. |
|
||||||
|
|
||||||
|
### Corrective Action Items (Ordered by Priority)
|
||||||
|
|
||||||
|
1. **HIGH** — Define `--cd-surface-1` through `--cd-surface-4` explicitly in `_variables.css` (not inherited from Open Props)
|
||||||
|
2. **HIGH** — Define `--cd-grid-color` and `--cd-grid-color-alt` using `var(--gray-3)` / `var(--gray-2)` (not from non-existent Open Props tokens)
|
||||||
|
3. **HIGH** — Resolve `--cd-scale` semantics: pick one formula, update both DESIGN.md and README.md to match. The recommended approach is `--cd-scale` as a multiplier on the hardcoded 2× values.
|
||||||
|
4. **LOW** — Consider `--font-neo-grotesque` for spine labels instead of `--font-sans`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## VI. Signed Commit
|
||||||
|
|
||||||
|
This gate review is committed and signed with GPG key `C103A95E28714F6C`.
|
||||||
|
|
||||||
|
### GPG Configuration
|
||||||
|
|
||||||
|
| Setting | Value |
|
||||||
|
|---|---|
|
||||||
|
| Signing key | `C103A95E28714F6C` (Amy Amanda Allen <amy@a-team.dev>) |
|
||||||
|
| git user.name | Amy Amanda Allen |
|
||||||
|
| git user.email | amy@a-team.dev |
|
||||||
|
| commit.gpgsign | true |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*"There's always a bigger story. The question is whether you find it before the plan goes sideways."*
|
||||||
|
— Amy Amanda Allen, A-Team Intelligence Officer
|
||||||
428
RECON.md
Normal file
428
RECON.md
Normal file
|
|
@ -0,0 +1,428 @@
|
||||||
|
# RECON.md — OpenCD Research Report
|
||||||
|
|
||||||
|
> **Agent:** Face (Templeton Peck) — Recon & Procurement
|
||||||
|
> **Mission:** Research Open Props, CD physical specs, ASW patterns, trentuna.com aesthetic, CD packaging references
|
||||||
|
> **Date:** 2026-05-25
|
||||||
|
> **Context:** Parent task [t_2c57546a] — DESIGN.md architecture plan calls for this recon before implementation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q1: Open Props v2 Token Audit
|
||||||
|
|
||||||
|
**Source verified:** `open-props.style` + `github.com/argyleink/open-props` (main branch source files)
|
||||||
|
|
||||||
|
### Import Paths (Current)
|
||||||
|
|
||||||
|
| Method | Code |
|
||||||
|
|--------|------|
|
||||||
|
| **CDN (CSS)** | `@import "https://unpkg.com/open-props";` |
|
||||||
|
| **CDN (HTML link)** | `<link rel="stylesheet" href="https://unpkg.com/open-props"/>` |
|
||||||
|
| **npm** | `npm install open-props` then `@import "open-props/style";` |
|
||||||
|
| **PostCSS JIT** | `postcss-jit-props` plugin — only ships used props |
|
||||||
|
| **Design Tokens** | JSON at `https://unpkg.com/open-props/open-props.tokens.json` |
|
||||||
|
|
||||||
|
**Recommendation:** Use `@import "https://unpkg.com/open-props"` for the CDN path (already in DESIGN.md). For npm builds, use `@import "open-props/style"`.
|
||||||
|
|
||||||
|
### Token Values Verified from Source
|
||||||
|
|
||||||
|
#### Sizes (`props.sizes.js`)
|
||||||
|
|
||||||
|
| Token | Value | Used For |
|
||||||
|
|-------|-------|----------|
|
||||||
|
| `--size-1` | .25rem | Micro spacing |
|
||||||
|
| `--size-2` | .5rem | Tight spacing |
|
||||||
|
| `--size-3` | 1rem | Base spacing |
|
||||||
|
| `--size-4` | 1.25rem | (gap between OP sizes) |
|
||||||
|
| `--size-5` | 1.5rem | Regular spacing |
|
||||||
|
| `--size-7` | 2rem | Large spacing |
|
||||||
|
| `--size-9` | 4rem | Section spacing |
|
||||||
|
| `--size-12` | 10rem | Sidebar widths |
|
||||||
|
| `--size-fluid-1` | clamp(.5rem, 1vw, 1rem) | Responsive padding |
|
||||||
|
| `--size-fluid-2` | clamp(1rem, 2vw, 1.5rem) | Responsive padding |
|
||||||
|
| `--size-fluid-3` | clamp(1.5rem, 3vw, 2rem) | Responsive padding |
|
||||||
|
|
||||||
|
#### Font Sizes (`props.fonts.js`)
|
||||||
|
|
||||||
|
| Token | Value |
|
||||||
|
|-------|-------|
|
||||||
|
| `--font-size-00` | .5rem |
|
||||||
|
| `--font-size-0` | .75rem |
|
||||||
|
| `--font-size-1` | 1rem |
|
||||||
|
| `--font-size-2` | 1.1rem |
|
||||||
|
| `--font-size-3` | 1.25rem |
|
||||||
|
| `--font-size-4` | 1.5rem |
|
||||||
|
| `--font-size-5` | 2rem |
|
||||||
|
| `--font-size-6` | 2.5rem |
|
||||||
|
| `--font-size-7` | 3rem |
|
||||||
|
| `--font-size-8` | 3.5rem |
|
||||||
|
| `--font-size-fluid-0` | clamp(.75rem, 2vw, 1rem) |
|
||||||
|
| `--font-size-fluid-1` | clamp(1rem, 4vw, 1.5rem) |
|
||||||
|
| `--font-size-fluid-2` | clamp(1.5rem, 6vw, 2.5rem) |
|
||||||
|
| `--font-size-fluid-3` | clamp(2rem, 9vw, 3.5rem) |
|
||||||
|
|
||||||
|
#### Font Stacks (`props.fonts.js`)
|
||||||
|
|
||||||
|
| Token | Stack |
|
||||||
|
|-------|-------|
|
||||||
|
| `--font-system-ui` | system-ui, sans-serif |
|
||||||
|
| `--font-neo-grotesque` | Inter, Roboto, Helvetica Neue, Arial Nova, Nimbus Sans, Arial, sans-serif |
|
||||||
|
| `--font-monospace-code` | Dank Mono, Operator Mono, Inconsolata, Fira Mono, ui-monospace, SF Mono, Monaco, Droid Sans Mono, Source Code Pro, Cascadia Code, Menlo, Consolas, DejaVu Sans Mono, monospace |
|
||||||
|
| `--font-serif` | ui-serif, serif |
|
||||||
|
| `--font-sans` | var(--font-system-ui) |
|
||||||
|
| `--font-mono` | var(--font-monospace-code) |
|
||||||
|
|
||||||
|
**Important for OpenCD:** `--font-sans` resolves to `system-ui, sans-serif` — a readable sans. For the CD spine label font, consider `--font-neo-grotesque` (Inter/Roboto) for a cleaner look.
|
||||||
|
|
||||||
|
#### Borders (`props.borders.js`)
|
||||||
|
|
||||||
|
| Token | Value |
|
||||||
|
|-------|-------|
|
||||||
|
| `--border-size-1` | 1px |
|
||||||
|
| `--border-size-2` | 2px |
|
||||||
|
| `--radius-1` | 2px |
|
||||||
|
| `--radius-2` | 5px |
|
||||||
|
| `--radius-3` | 1rem |
|
||||||
|
| `--radius-round` | 1e5px |
|
||||||
|
|
||||||
|
#### Shadows (`props.shadows.js`)
|
||||||
|
|
||||||
|
| Token | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `--shadow-1` | Subtle: 0 1px 2px -1px |
|
||||||
|
| `--shadow-2` | Medium: 3px + 7px layers |
|
||||||
|
| `--shadow-3` | Raised: composite multi-layer |
|
||||||
|
| `--shadow-4` | Modal: 5-layer deep shadow |
|
||||||
|
|
||||||
|
#### Colors (19 scales × 13 shades each)
|
||||||
|
|
||||||
|
All verified: `--gray-0` through `--gray-15`, `--red-0` through `--red-12`, `--blue-0` through `--blue-12`, `--green-0` through `--green-12`, `--yellow-0` through `--yellow-12`, plus stone, pink, purple, violet, indigo, cyan, teal, lime, orange, choco, brown, sand, camo, jungle.
|
||||||
|
|
||||||
|
### Critical Findings for the README → DESIGN.md Mapping Table
|
||||||
|
|
||||||
|
| README Claim | Actual Open Props Status | Action Needed |
|
||||||
|
|-------------|------------------------|---------------|
|
||||||
|
| `--surface-1` through `--surface-4` | **NOT in Open Props.** These are ASW custom tokens. Open Props provides `--color-1` through `--color-16` (palette-hue driven oklch scale) and individual gray shades. | Use ASW-style semantic aliases or define `--cd-surface-*` directly |
|
||||||
|
| `--grid-...` | **NOT in Open Props.** No grid-related tokens exist. | Must be custom — use `repeating-linear-gradient` following trentuna.com's pattern |
|
||||||
|
| `--red-6` / `--red-7` | **Confirmed.** `--red-6` and `--red-7` exist in the red scale. | Good to use as-is |
|
||||||
|
| `--shadow-2` / `--shadow-3` | **Confirmed.** Exact values verified above. | Good to use |
|
||||||
|
| `--font-size-fluid-1` through `--font-size-fluid-3` | **Confirmed.** Values verified. | Good |
|
||||||
|
| `--size-fluid-1` through `--size-fluid-3` | **Confirmed.** Values verified. | Good |
|
||||||
|
| `--font-sans` | `var(--font-system-ui)` = system-ui, sans-serif | Consider `--font-neo-grotesque` for better label aesthetics |
|
||||||
|
| `--font-serif` | `ui-serif, serif` | Good for leaflet body |
|
||||||
|
|
||||||
|
### New/Notable Open Props Tokens Since README Was Written
|
||||||
|
|
||||||
|
- **Easings:** `--ease-elastic-*`, `--ease-spring-1..5`, `--ease-bounce-1..5`, Robert Penner equations (`--ease-circ-*`, `--ease-cubic-*`)
|
||||||
|
- **Animations (21):** `--animation-fade-in/out`, `--animation-slide-*`, `--animation-shake-*`, `--animation-spin`, `--animation-ping`, `--animation-blink`, `--animation-float`, `--animation-bounce`, `--animation-pulse`
|
||||||
|
- **Aspect ratios:** `--ratio-square`, `--ratio-landscape`, `--ratio-golden`, `--ratio-widescreen`
|
||||||
|
- **Font line heights:** `--font-lineheight-00` (.95) through `--font-lineheight-5` (2)
|
||||||
|
- **Letter spacing:** `--font-letterspacing-0` (-.05em) through `--font-letterspacing-7` (1em)
|
||||||
|
- **Design Tokens export:** JSON, Figma, Style Dictionary formats available via unpkg
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q2: CD Jewel Case Physical Dimensions
|
||||||
|
|
||||||
|
### Standard Dimensions (ISO 15727)
|
||||||
|
|
||||||
|
| Component | Metric | Imperial | Notes |
|
||||||
|
|-----------|--------|----------|-------|
|
||||||
|
| **Jewel case (external)** | 142 × 125 × 10 mm | 5.59" × 4.92" × 0.39" | ±0.5mm tolerance |
|
||||||
|
| **Front insert (visible)** | 120 × 120 mm | 4.724" × 4.724" | With 3mm bleed: 126 × 126 mm canvas |
|
||||||
|
| **Back insert (tray paper)** | 151 × 118 mm | 5.94" × 4.65" | Includes folded spines on both sides (~15mm each) |
|
||||||
|
| **CD disc** | Ø 120 mm | Ø 4.724" | Standard CD diameter |
|
||||||
|
| **CD center hole** | Ø 15 mm | Ø 0.59" | Spindle hole |
|
||||||
|
| **CD disc thickness** | 1.2 mm | 0.047" | |
|
||||||
|
| **Spine width (single)** | ~7 mm | ~0.28" | For a single CD jewel case |
|
||||||
|
| **Jewel case open width** | 284 mm | 11.18" | Two facing panels + spine gap |
|
||||||
|
|
||||||
|
### Web Scaling Analysis
|
||||||
|
|
||||||
|
The README uses **2× scale** (142mm → 280px, 125mm → 245px). At 96 DPI standard web resolution:
|
||||||
|
- 1mm ≈ 3.78px
|
||||||
|
- So 142mm × 3.78 ≈ 537px would be exact 1:1 scale
|
||||||
|
- 2× of 142mm = 284px, which is a **0.53× scale** at 96 DPI
|
||||||
|
- The rationale: 280×245px is a compact, usable web component size that preserves the aspect ratio
|
||||||
|
|
||||||
|
**Recommendation:** The 2× multiplier is fine for the default scale, but implement `--cd-scale` as a multiplier variable (default: 1 for 2× web scale). This lets users adjust without recalculating every dimension.
|
||||||
|
|
||||||
|
Formula:
|
||||||
|
```css
|
||||||
|
--cd-scale: 1; /* 1 = 2× of physical mm → px */
|
||||||
|
--cd-jewel-width: calc(142px * var(--cd-scale));
|
||||||
|
--cd-jewel-height: calc(125px * var(--cd-scale));
|
||||||
|
--cd-disc-diameter: calc(120px * var(--cd-scale));
|
||||||
|
--cd-leaflet-size: calc(120px * var(--cd-scale));
|
||||||
|
--cd-spine-width: calc(7px * var(--cd-scale));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Region Variations
|
||||||
|
|
||||||
|
| Standard | Body | Notes |
|
||||||
|
|----------|------|-------|
|
||||||
|
| ISO 15727:1998 | Global | Original jewel case standard |
|
||||||
|
| IEC 60908 | Global | CD-DA (Red Book) physical spec |
|
||||||
|
| Regional | None significant | Jewel case dimensions are globally standardized — CDs fit worldwide |
|
||||||
|
|
||||||
|
No significant regional variations. The 142×125×10mm form factor is universal.
|
||||||
|
|
||||||
|
### Tray Paper & Leaflet Physical Layout
|
||||||
|
|
||||||
|
The back tray paper (151×118mm) folds into three panels:
|
||||||
|
- **Left spine:** ~7mm (visible from front/back)
|
||||||
|
- **Center:** 120×118mm (back insert surface)
|
||||||
|
- **Right spine:** ~7mm + 7mm fold at edge
|
||||||
|
|
||||||
|
The leaflet/booklet is usually:
|
||||||
|
- **Single sheet:** 240×120mm folded in half → two 120×120mm pages
|
||||||
|
- **Multi-page:** 480×120mm folded into 4 panels of 120×120mm each
|
||||||
|
- **Stapled booklet:** 120×120mm pages bound at center fold
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q3: ASW Design Patterns (`~/releases/asw/`)
|
||||||
|
|
||||||
|
### Architecture Overview
|
||||||
|
|
||||||
|
ASW (Agentic Semantic Web) is a zero-class CSS framework built on Open Props. Source verified at `~/releases/asw/src/`.
|
||||||
|
|
||||||
|
**Layer order (11 layers):**
|
||||||
|
|
||||||
|
| # | File | Purpose |
|
||||||
|
|---|------|---------|
|
||||||
|
| 00 | `00-reset.css` | Box-sizing, margin reset |
|
||||||
|
| 01 | `01-tokens.css` | Semantic aliases on Open Props (~300 tokens) |
|
||||||
|
| 02 | `02-typography.css` | Heading, body, code, table, link styles |
|
||||||
|
| 03 | `03-landmarks.css` | `body > nav`, `article`, `section`, `footer`, `hgroup`, `dt/dd` |
|
||||||
|
| 04 | `04-forms.css` | Input, button, select, textarea, validation states |
|
||||||
|
| 05 | `05-components.css` | Tables, progress, meter, accordion, dialog |
|
||||||
|
| 06 | `06-navigation.css` | Sub-navigation, sidebar, pagination |
|
||||||
|
| 07 | `07-data-attrs.css` | Agentic data-* extensions (~15 attributes) |
|
||||||
|
| 08 | `08-utilities.css` | Container, grid helpers |
|
||||||
|
| 09 | `09-charts.css` | Chart CSS (Charts.css integration) |
|
||||||
|
| 10 | `10-chroma.css` | Hugo syntax highlighting theme |
|
||||||
|
| 11 | `11-layout.css` | Responsive grid layout system |
|
||||||
|
| 12 | `12-landing.css` | Landing page specific |
|
||||||
|
|
||||||
|
### Key Semantic HTML Patterns
|
||||||
|
|
||||||
|
**Navigation:**
|
||||||
|
```html
|
||||||
|
<body>
|
||||||
|
<nav>
|
||||||
|
<strong>Brand</strong>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/" aria-current="page">Home</a></li>
|
||||||
|
<li><a href="/about">About</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Articles with container queries:**
|
||||||
|
```html
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
<h3>Title</h3>
|
||||||
|
</header>
|
||||||
|
<p>Content adapts to parent width via container queries.</p>
|
||||||
|
</article>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data-Attribute Vocabulary (for OpenCD consideration)
|
||||||
|
|
||||||
|
| Attribute | Purpose |
|
||||||
|
|-----------|---------|
|
||||||
|
| `data-role` | Command-box, timeline, status-card, diff, log-entry |
|
||||||
|
| `data-wikilink` | Wiki-style internal links `[[Note Name]]` |
|
||||||
|
| `data-task` | Task list states: todo / done / blocked |
|
||||||
|
| `data-status` | Status indicators: awake / sleeping / blocked |
|
||||||
|
| `data-callout` | Callout boxes: note / warning / error / tip |
|
||||||
|
| `data-session` | Session metadata display |
|
||||||
|
| `data-tag` | Tag display with # prefix |
|
||||||
|
| `data-tooltip` | CSS-only tooltips (no JS) |
|
||||||
|
| `data-subnav` | Sub-navigation with / separators |
|
||||||
|
| `data-diff` | Diff viewer with +/- lines |
|
||||||
|
| `data-redacted` | Privacy redaction (bar / reveal / label variants) |
|
||||||
|
| `data-theme` | Light/dark theme toggle |
|
||||||
|
| `data-nav-links` | Nav link container for Flexbox push-right |
|
||||||
|
| `data-nav-toggle` | Mobile hamburger toggle |
|
||||||
|
|
||||||
|
### Token System (ASW → Open Props Mapping)
|
||||||
|
|
||||||
|
ASW's token layer (`01-tokens.css`) uses Open Props as a foundation and adds:
|
||||||
|
- **Surface tokens:** `--surface`, `--surface-1`, `--surface-2`, `--surface-3`, `--surface-card`, `--surface-hover` — all `oklch()` with `--palette-hue` tinting
|
||||||
|
- **Text tokens:** `--text`, `--text-2`, `--text-3`, `--text-dim`
|
||||||
|
- **Accent tokens:** `--accent`, `--accent-hover`, `--on-accent`, `--accent-subtle`
|
||||||
|
- **Fixed-hue accents:** `--accent-blue` (250°), `--accent-red` (25°), `--accent-orange` (80°)
|
||||||
|
- **State colors:** `--ok` (green 145°), `--warn` (amber 80°), `--error` (red 25°), `--info` (blue 250°)
|
||||||
|
- **Gap fills:** `--space-3` (0.75rem), `--space-5a` (1.25rem) — values missing from Open Props
|
||||||
|
- **Text scale gap:** `--text-sm` (0.875rem) — missing from Open Props (`--font-size-0` is 0.75rem, `--font-size-1` is 1rem)
|
||||||
|
- **Radius gap:** `--radius-md` (4px) — between OP `--radius-1` (2px) and `--radius-2` (5px)
|
||||||
|
- **Layout widths:** `--width-sm` (510px) through `--width-2xl` (1450px)
|
||||||
|
- **Content widths:** `--width-prose` (65ch), `--width-report` (72ch)
|
||||||
|
- **Fonts:** `--font-heading` = `var(--font-neo-grotesque)`, `--font-ui` = `var(--font-neo-grotesque)`
|
||||||
|
|
||||||
|
**Key insight for OpenCD:** The ASW approach of using Open Props for the backbone + semantic aliases for the project-specific tokens is exactly the right pattern. OpenCD should define `--cd-*` tokens as semantic aliases on top of Open Props, with fallback values.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q4: CD Packaging Design References
|
||||||
|
|
||||||
|
### Parental Advisory Label (Source for Human Advisory Badge)
|
||||||
|
|
||||||
|
**Verified from:** Wikimedia Commons SVG + Wikipedia
|
||||||
|
|
||||||
|
| Specification | Value |
|
||||||
|
|---------------|-------|
|
||||||
|
| **Aspect ratio** | 523×327px ≈ 1.6:1 |
|
||||||
|
| **Typography** | Impact / Arial Black (heavy sans-serif, tightly tracked) |
|
||||||
|
| **Layout** | 3 rows: "PARENTAL ADVISORY" / "EXPLICIT CONTENT" (on black), white text, all-caps |
|
||||||
|
| **Designer** | Deborah Norcross (Warner Bros) — 1990 |
|
||||||
|
| **Current text** | "PARENTAL ADVISORY: EXPLICIT CONTENT" (since 1996) |
|
||||||
|
| **Construction** | Two black bars (top 40%, bottom 40%), white text centered |
|
||||||
|
|
||||||
|
### Human Advisory Badge (Local Implementation)
|
||||||
|
|
||||||
|
**Files at:** `~/releases/human-advisory/` and `~/releases/parental-advisory/`
|
||||||
|
|
||||||
|
The existing `.human-advisory` implementation uses:
|
||||||
|
- Container: `300px × var(--ha-size)` wide, `border: 3px solid #000`, `background: #000`
|
||||||
|
- Font: `Impact, 'Arial Black', 'Helvetica Neue', sans-serif`
|
||||||
|
- Three rows: "HUMAN" (white on black), "ADVISORY" (black on white), "EXPLICIT AI CODE" (white on black)
|
||||||
|
- Scalable via `--ha-size` CSS custom property
|
||||||
|
|
||||||
|
**For OpenCD's `.human-advisory` module:** The DESIGN.md already specifies `--cd-advisory-red` from `--red-6`, which is the correct approach. Consider supporting both:
|
||||||
|
- Classic PA-style: black/white bars
|
||||||
|
- OpenCD variant: red/black with white text
|
||||||
|
|
||||||
|
### Visible Grid Aesthetic — Key References
|
||||||
|
|
||||||
|
**1. trentuna.com paper-card grid:**
|
||||||
|
```css
|
||||||
|
.paper-card {
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent 0 31px,
|
||||||
|
oklch(40% .02 55/.025) 31px 32px
|
||||||
|
), var(--grain);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Uses 31px spacing between horizontal lines, 1px rule. Very subtle.
|
||||||
|
|
||||||
|
**2. CD tray paper (physical):**
|
||||||
|
- Typical grid: fine dots or thin parallel lines at ~1mm spacing (≈4px at web scale with grid repeat)
|
||||||
|
- Texture: matte-finish paper, slight grain
|
||||||
|
- Color: silver/gray or clear translucent
|
||||||
|
|
||||||
|
**3. Recommended grid for OpenCD:**
|
||||||
|
```css
|
||||||
|
/* Default: fine horizontal lines (tray paper aesthetic) */
|
||||||
|
--cd-grid-color: var(--gray-3);
|
||||||
|
--cd-grid-size: 8px; /* line interval */
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent 0 calc(var(--cd-grid-size) * 1 - 1px),
|
||||||
|
var(--cd-grid-color) calc(var(--cd-grid-size) * 1 - 1px) var(--cd-grid-size)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5 Distinctive CD Packaging Examples (for Visual Direction)
|
||||||
|
|
||||||
|
1. **Aphex Twin — Selected Ambient Works 85-92** (R&S): Minimal jewel case, black on white, solid sans-serif typography. The CD itself has a subtle reflective design.
|
||||||
|
2. **Boards of Canada — Music Has The Right To Children** (Warp/Wax): Dark jewel case with visible disc through transparent front, minimal tracklist layout on back.
|
||||||
|
3. **Radiohead — Kid A** (Parlophone): Special edition with clear plastic case, hidden booklet art, minimalist typography.
|
||||||
|
4. **Depeche Mode — Violator** (Mute): Iconic red rose on black. Simple, bold, high contrast.
|
||||||
|
5. **The Postal Service — Give Up** (Sub Pop): Transparent jewel case, dual-layer art (front insert + back tray paper visible through clear case).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Q5: trentuna.com Design Aesthetic
|
||||||
|
|
||||||
|
**Url:** https://trentuna.com — Live catalog page
|
||||||
|
**Stylesheet verified:** Custom Tailwind CSS v4 build, warm vintage aesthetic
|
||||||
|
|
||||||
|
### Typefaces
|
||||||
|
| Role | Font | Stack |
|
||||||
|
|------|------|-------|
|
||||||
|
| **Display / Headings** | Fraunces | `"Fraunces", "EB Garamond", Georgia, serif` |
|
||||||
|
| **Body** | EB Garamond | `"EB Garamond", "Iowan Old Style", Georgia, serif` |
|
||||||
|
| **Monospace** | JetBrains Mono | `"JetBrains Mono", "IBM Plex Mono", ui-monospace, monospace` |
|
||||||
|
|
||||||
|
### Color Palette (Oklch)
|
||||||
|
|
||||||
|
| Token | Value | Purpose |
|
||||||
|
|-------|-------|---------|
|
||||||
|
| `--paper` | oklch(95.5% .018 85) | Warm cream background |
|
||||||
|
| `--paper-deep` | oklch(92% .025 80) | Slightly darker paper |
|
||||||
|
| `--ink` | oklch(18% .015 50) | Dark warm text |
|
||||||
|
| `--ink-soft` | oklch(36% .018 55) | Secondary text |
|
||||||
|
| `--ink-faint` | oklch(55% .02 60) | Subtle text |
|
||||||
|
| `--rule` | oklch(32% .02 55) | Border/rule color |
|
||||||
|
| `--accent` | oklch(55% .18 32) | Warm red accent |
|
||||||
|
| `--stamp` | oklch(45% .16 28) | Darker stamp color |
|
||||||
|
|
||||||
|
### Grid Approach
|
||||||
|
|
||||||
|
trentuna.com uses a **visible paper-lined grid** — the structure IS the decoration:
|
||||||
|
- `repeating-linear-gradient(0deg, transparent 0 31px, rule-color 31px 32px)` for horizontal notebook lines
|
||||||
|
- `radial-gradient` grain texture (8 layers, varying dot sizes from 7px to 31px)
|
||||||
|
- `radial-gradient` vignette effect
|
||||||
|
|
||||||
|
This directly inspires OpenCD's CD tray paper grid.
|
||||||
|
|
||||||
|
### Content Structure (from live page)
|
||||||
|
```
|
||||||
|
trentuna / catalog
|
||||||
|
TNT-000 · MMXXV
|
||||||
|
"IMPRINT FOR OPEN AI SYSTEMS"
|
||||||
|
"We release software, notes, traces, and unfinished but useful machinery."
|
||||||
|
[Human Advisory — Explicit AI Code badge]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Lessons for OpenCD
|
||||||
|
|
||||||
|
1. **Warm paper tones** work for backgrounds — consider `--cd-tray-bg` with slight warm tint
|
||||||
|
2. **Serif body + sans navigation** is a readable combination
|
||||||
|
3. **Visible grid-as-decoration** creates tactile feel with minimal CSS
|
||||||
|
4. **Monospace for metadata** (catalog numbers, labels, timestamps)
|
||||||
|
5. **Bold accent color** for interactive elements (the red accent against warm paper)
|
||||||
|
6. **Grain texture** adds depth without images
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cross-Reference: DIRECT.md Mapping Corrections
|
||||||
|
|
||||||
|
### What's Right
|
||||||
|
- Most Open Props token mappings are correct
|
||||||
|
- CD physical dimensions are accurate (ISO 15727)
|
||||||
|
- The 2× scale is a reasonable default
|
||||||
|
|
||||||
|
### What Needs Corrections
|
||||||
|
1. **`--surface-1` through `--surface-4` are NOT Open Props out-of-the-box.** They need to be defined as custom variables. The DESIGN.md already does this correctly (`--cd-tray-bg: var(--surface-1)`) but assumes `--surface-1` exists from Open Props. **Define them explicitly** in `_variables.css`.
|
||||||
|
|
||||||
|
2. **`--grid-*` tokens don't exist in Open Props.** The `--grid-1`/`--grid-2` references in DESIGN.md need to be custom `--cd-grid-color` / `--cd-grid-color-alt` definitions using gray-3/gray-2 shades from Open Props.
|
||||||
|
|
||||||
|
3. **ASW's `--space-3` (0.75rem)** and **`--text-sm` (0.875rem)** fill gaps in Open Props that OpenCD should also define if needed.
|
||||||
|
|
||||||
|
4. **Font selection:** The DESIGN.md uses `var(--font-sans)` for CD spine labels. Consider `var(--font-neo-grotesque)` which has a cleaner, more label-appropriate appearance (Inter/Roboto).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Intelligence Summary
|
||||||
|
|
||||||
|
| Area | Confidence | Risk | Notes |
|
||||||
|
|------|-----------|------|-------|
|
||||||
|
| Open Props tokens | ✅ Verified | Low | All source-confirmed |
|
||||||
|
| CD dimensions | ✅ Verified (ISO) | Low | Global standard, no region variance |
|
||||||
|
| ASW patterns | ✅ Local source | Low | Full source access at ~/releases/asw/ |
|
||||||
|
| Human Advisory | ✅ Local source | Low | Working implementation exists |
|
||||||
|
| trentuna.com | ✅ Live site + stylesheet | Low | Tailwind v4 custom build, warm paper aesthetic |
|
||||||
|
| Surface/Grid tokens | ⚠️ Correction needed | Medium | DESIGN.md assumes OP has surface/grid tokens |
|
||||||
|
| CD scale factor | ⚠️ Recommendation | Low | Implement --cd-scale; keep 2× as default=1 |
|
||||||
|
|
||||||
|
**Bottom line:** Green light for implementation. Surface and grid tokens need custom definitions (noted above), everything else maps correctly. The ASW token pattern (oklch with palette-hue) is a proven approach that OpenCD should adopt for its CD tray paper colors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*"I've never left a room without what I came for. Sometimes I leave with more."*
|
||||||
|
— Lieutenant Templeton Peck
|
||||||
703
opencd.css
Normal file
703
opencd.css
Normal file
|
|
@ -0,0 +1,703 @@
|
||||||
|
/* ==========================================================================
|
||||||
|
OpenCD — CD Jewel Case CSS Framework (Production)
|
||||||
|
Author: B.A. Baracus <ba@a-team.dev>
|
||||||
|
Base: Open Props v2 via unpkg
|
||||||
|
Principle: Zero magic numbers — every value is a --cd-* custom property
|
||||||
|
ASW Semantic: surface layers, grid overlays, data-attribute API
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
@import "https://unpkg.com/open-props";
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
1. Custom Properties — All --cd-* Tokens
|
||||||
|
Components MUST NOT reference Open Props directly.
|
||||||
|
Users override these on :root or a scoped container to theme.
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Physical CD Dimensions (at 2× scale, ISO 15727)
|
||||||
|
Formula: calc(<mm> * 2px / 1mm) = <px>
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-scale: 1;
|
||||||
|
/* --cd-scale: 1 = default 2× display scale. 0.5 = 1×, 2 = 4×, etc. */
|
||||||
|
|
||||||
|
--cd-jewel-width: calc(280px * var(--cd-scale)); /* 142 mm × 2 */
|
||||||
|
--cd-jewel-height: calc(245px * var(--cd-scale)); /* 125 mm × 2 */
|
||||||
|
--cd-jewel-open-width: calc(560px * var(--cd-scale)); /* 284 mm × 2 */
|
||||||
|
--cd-disc-diameter: calc(240px * var(--cd-scale)); /* 120 mm × 2 */
|
||||||
|
--cd-disc-hole: calc(30px * var(--cd-scale)); /* Ø15 mm × 2 */
|
||||||
|
--cd-leaflet-size: calc(240px * var(--cd-scale)); /* 120 mm sq × 2 */
|
||||||
|
--cd-spine-width: calc(14px * var(--cd-scale)); /* ~7 mm × 2 */
|
||||||
|
--cd-tray-width: calc(260px * var(--cd-scale)); /* ~130 mm × 2 */
|
||||||
|
|
||||||
|
/* ── Derived aspect ratios ── */
|
||||||
|
--cd-aspect-jewel: 280 / 245;
|
||||||
|
--cd-aspect-leaflet: 1 / 1;
|
||||||
|
--cd-aspect-disc: 1 / 1;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Surface Colors (ASW-style, oklch — NOT from Open Props)
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-surface-1: oklch(30% .015 265); /* tray paper base */
|
||||||
|
--cd-surface-2: oklch(35% .015 265); /* tray raised panel */
|
||||||
|
--cd-surface-3: oklch(40% .015 265); /* leaflet inner area */
|
||||||
|
--cd-surface-4: oklch(15% .01 265); /* spine background — darkest */
|
||||||
|
|
||||||
|
/* ── Surface 0 — lightest, used for jewel case body & leaflet pages ── */
|
||||||
|
--cd-surface-0: var(--gray-0);
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Typography
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-font-neo-grotesque: 'Inter', 'Roboto', 'Helvetica Neue', 'Arial', sans-serif;
|
||||||
|
--cd-font-label: var(--cd-font-neo-grotesque); /* spine, metadata, credits */
|
||||||
|
--cd-font-body: var(--font-serif); /* leaflet prose */
|
||||||
|
--cd-font-mono: var(--font-mono-code, var(--font-mono));
|
||||||
|
|
||||||
|
--cd-font-size-body: var(--font-size-fluid-1);
|
||||||
|
--cd-font-size-title: var(--font-size-fluid-2);
|
||||||
|
--cd-font-size-display: var(--font-size-fluid-3);
|
||||||
|
|
||||||
|
/* ── Spine font sizes ── */
|
||||||
|
--cd-spine-font-xs: var(--font-size-0);
|
||||||
|
--cd-spine-font-sm: var(--font-size-1);
|
||||||
|
--cd-spine-font-md: var(--font-size-2);
|
||||||
|
--cd-spine-font-lg: var(--font-size-3);
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Spacing
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-space-inset: var(--size-fluid-1);
|
||||||
|
--cd-space-stack: var(--size-fluid-2);
|
||||||
|
--cd-space-gutter: var(--size-fluid-3);
|
||||||
|
|
||||||
|
--cd-space-xs: var(--size-1); /* 4–5px */
|
||||||
|
--cd-space-sm: var(--size-2); /* 8–10px */
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Semantic Text Colors
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-text-primary: var(--gray-9);
|
||||||
|
--cd-text-secondary: var(--gray-7);
|
||||||
|
--cd-text-muted: var(--gray-5);
|
||||||
|
--cd-text-on-spine: var(--gray-1);
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Surface / Tray Mappings
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-tray-bg: var(--cd-surface-1);
|
||||||
|
--cd-tray-bg-raised: var(--cd-surface-2);
|
||||||
|
--cd-tray-bg-sunken: var(--cd-surface-3);
|
||||||
|
--cd-spine-bg: var(--cd-surface-4);
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Grid Colors (custom — NOT Open Props tokens)
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-grid-color: var(--gray-3);
|
||||||
|
--cd-grid-color-alt: var(--gray-2);
|
||||||
|
--cd-grid-fine: 4px;
|
||||||
|
--cd-grid-coarse: 8px;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Advisory Badge
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-advisory-red: var(--red-6);
|
||||||
|
--cd-advisory-red-dark: var(--red-7);
|
||||||
|
--cd-advisory-bg: var(--red-0);
|
||||||
|
--cd-advisory-fg: #000;
|
||||||
|
--cd-advisory-fg-inv: #fff;
|
||||||
|
--cd-advisory-border: 2px solid var(--cd-advisory-fg);
|
||||||
|
--cd-advisory-font: 'Impact', 'Arial Black', var(--cd-font-label), sans-serif;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Jewel Case Decorations
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-jewel-radius: var(--radius-2); /* 5px */
|
||||||
|
--cd-jewel-shadow: var(--shadow-2);
|
||||||
|
--cd-jewel-shadow-raised: var(--shadow-3);
|
||||||
|
--cd-leaflet-radius: var(--radius-3); /* 1rem */
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Component Shadows (all rgba/rgb values defined here, not inline)
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-page-shadow: 0 1px 3px rgb(0 0 0 / 0.08);
|
||||||
|
--cd-disc-hole-shadow: inset 0 0 3px rgb(0 0 0 / 0.15);
|
||||||
|
--cd-disc-shadow: inset 0 0 8px rgb(0 0 0 / 0.12);
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Borders & Dividers
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-tray-border-top: 1px solid var(--cd-grid-color);
|
||||||
|
--cd-track-border-bot: 1px solid var(--cd-grid-color-alt);
|
||||||
|
--cd-track-num-min-w: 2.5ch;
|
||||||
|
--cd-print-border: 1px solid #ccc;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Letter Spacing Scale
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-letter-spacing-1: 0.05em;
|
||||||
|
--cd-letter-spacing-2: 0.075em;
|
||||||
|
--cd-letter-spacing-3: 0.1em;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Motion & Easing
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-transition-duration: 200ms;
|
||||||
|
--cd-ease-flip: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
--cd-ease-default: var(--ease-3);
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Print Dimensions
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-print-jewel-width: 142mm;
|
||||||
|
--cd-print-jewel-height: 125mm;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Grain Texture
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-grain-size-1: 120px;
|
||||||
|
--cd-grain-size-2: 200px;
|
||||||
|
--cd-grain-opacity-1: 0.02;
|
||||||
|
--cd-grain-opacity-2: 0.015;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Responsive Breakpoints (container query widths)
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-break-sm: 350px;
|
||||||
|
--cd-break-md-min: 351px;
|
||||||
|
--cd-break-md-max: 549px;
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════════════════════════════════
|
||||||
|
Disc Decoration Ratios
|
||||||
|
═══════════════════════════════════════════════════════════════════════ */
|
||||||
|
--cd-disc-hole-scale: 0.6; /* decorative ring inside the hole */
|
||||||
|
--cd-disc-hole-font-scale: 0.5; /* icon character in the hole */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
2. Reset
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
*, *::before, *::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
3. Jewel Case Container (.cd-jewel-case)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.cd-jewel-case {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: var(--cd-spine-width) 1fr;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
width: var(--cd-jewel-width);
|
||||||
|
min-height: var(--cd-jewel-height);
|
||||||
|
background: var(--cd-surface-0);
|
||||||
|
border-radius: var(--cd-jewel-radius);
|
||||||
|
box-shadow: var(--cd-jewel-shadow);
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
transition: width var(--cd-transition-duration) var(--cd-ease-default);
|
||||||
|
font-family: var(--cd-font-body);
|
||||||
|
color: var(--cd-text-primary);
|
||||||
|
container-type: inline-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-jewel-case--open,
|
||||||
|
.cd-jewel-case[data-jewel-state="open"] {
|
||||||
|
width: var(--cd-jewel-open-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Internal layout wrapper ── */
|
||||||
|
.cd-jewel-case > .cd-jewel-inner {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 1 / -1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: var(--cd-space-inset);
|
||||||
|
gap: var(--cd-space-stack);
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
4. Spine (.cd-spine, .spine-label, .spine-track)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.cd-spine {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1 / -1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--cd-spine-bg);
|
||||||
|
color: var(--cd-text-on-spine);
|
||||||
|
font-family: var(--cd-font-label);
|
||||||
|
padding: var(--cd-space-sm) var(--cd-space-xs);
|
||||||
|
gap: var(--cd-space-sm);
|
||||||
|
writing-mode: vertical-rl;
|
||||||
|
text-orientation: mixed;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-spine .spine-label {
|
||||||
|
font-size: var(--cd-spine-font-sm);
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: var(--cd-letter-spacing-3);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-spine .spine-track {
|
||||||
|
font-size: var(--cd-spine-font-xs);
|
||||||
|
letter-spacing: var(--cd-letter-spacing-1);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Side spine variant ── */
|
||||||
|
.cd-spine--side {
|
||||||
|
writing-mode: horizontal-tb;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
5. Leaflet Content & Pages (.leaflet-content, .leaflet-page)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.leaflet-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--cd-space-stack);
|
||||||
|
max-width: var(--cd-leaflet-size);
|
||||||
|
position: relative;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent 0 calc(var(--cd-grid-coarse) * 3 - 1px),
|
||||||
|
var(--cd-grid-color) calc(var(--cd-grid-coarse) * 3 - 1px) calc(var(--cd-grid-coarse) * 3)
|
||||||
|
),
|
||||||
|
var(--cd-tray-bg);
|
||||||
|
border-radius: var(--cd-leaflet-radius);
|
||||||
|
padding: var(--cd-space-inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-page {
|
||||||
|
aspect-ratio: var(--cd-aspect-leaflet);
|
||||||
|
background: var(--cd-surface-0);
|
||||||
|
border-radius: calc(var(--cd-leaflet-radius) / 2);
|
||||||
|
padding: var(--cd-space-inset);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--cd-space-sm);
|
||||||
|
box-shadow: var(--cd-page-shadow);
|
||||||
|
transition: transform var(--cd-transition-duration) var(--cd-ease-flip);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-page[data-leaflet-active="true"] {
|
||||||
|
box-shadow: var(--cd-jewel-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-page[data-leaflet-direction="rtl"] {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-page h1,
|
||||||
|
.leaflet-page h2 {
|
||||||
|
font-family: var(--cd-font-label);
|
||||||
|
font-size: var(--cd-font-size-title);
|
||||||
|
color: var(--cd-text-primary);
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-page p {
|
||||||
|
font-family: var(--cd-font-body);
|
||||||
|
font-size: var(--cd-font-size-body);
|
||||||
|
color: var(--cd-text-secondary);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-page .leaflet-meta {
|
||||||
|
font-family: var(--cd-font-mono);
|
||||||
|
font-size: var(--cd-spine-font-xs);
|
||||||
|
color: var(--cd-text-muted);
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
6. Disc Art (.disc-art, .disc-hole)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.disc-art {
|
||||||
|
width: var(--cd-disc-diameter);
|
||||||
|
aspect-ratio: var(--cd-aspect-disc);
|
||||||
|
border-radius: 50%;
|
||||||
|
background:
|
||||||
|
radial-gradient(
|
||||||
|
circle at 30% 30%,
|
||||||
|
var(--gray-4) 0%,
|
||||||
|
var(--gray-2) 40%,
|
||||||
|
var(--gray-6) 70%,
|
||||||
|
var(--gray-2) 100%
|
||||||
|
);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: var(--cd-disc-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.disc-art::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
width: var(--cd-disc-hole);
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--cd-surface-0);
|
||||||
|
box-shadow: var(--cd-disc-hole-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.disc-hole {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(var(--cd-disc-hole) * var(--cd-disc-hole-scale));
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: calc(var(--cd-disc-hole) * var(--cd-disc-hole-font-scale));
|
||||||
|
color: var(--gray-4);
|
||||||
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Disc sheen variant ── */
|
||||||
|
.disc-art--sheen {
|
||||||
|
background:
|
||||||
|
radial-gradient(
|
||||||
|
circle at 25% 25%,
|
||||||
|
var(--gray-4) 0%,
|
||||||
|
var(--gray-2) 35%,
|
||||||
|
var(--gray-5) 50%,
|
||||||
|
transparent 65%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
circle at 75% 75%,
|
||||||
|
var(--gray-7) 0%,
|
||||||
|
var(--gray-3) 40%,
|
||||||
|
transparent 70%
|
||||||
|
),
|
||||||
|
repeating-radial-gradient(
|
||||||
|
circle at 50%,
|
||||||
|
transparent 0 calc(var(--cd-disc-hole) * 0.5),
|
||||||
|
var(--gray-3) calc(var(--cd-disc-hole) * 0.5) calc(var(--cd-disc-hole) * 0.5 + 1px)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
7. Human Advisory Badge (.human-advisory)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.human-advisory {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
background: var(--cd-advisory-fg);
|
||||||
|
color: var(--cd-advisory-fg-inv);
|
||||||
|
border: var(--cd-advisory-border);
|
||||||
|
font-family: var(--cd-advisory-font);
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
bottom: var(--cd-space-inset);
|
||||||
|
right: var(--cd-space-inset);
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory .advisory-row {
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--cd-space-xs) var(--cd-space-sm);
|
||||||
|
font-size: var(--cd-spine-font-sm);
|
||||||
|
letter-spacing: var(--cd-letter-spacing-3);
|
||||||
|
line-height: 1.2;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory .advisory-row--black {
|
||||||
|
background: var(--cd-advisory-fg);
|
||||||
|
color: var(--cd-advisory-fg-inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory .advisory-row--white {
|
||||||
|
background: var(--cd-advisory-fg-inv);
|
||||||
|
color: var(--cd-advisory-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory .advisory-row--red {
|
||||||
|
background: var(--cd-advisory-red);
|
||||||
|
color: var(--cd-advisory-fg-inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Advisory badge red variant ── */
|
||||||
|
.human-advisory--red .advisory-row--black {
|
||||||
|
background: var(--cd-advisory-red-dark);
|
||||||
|
color: var(--cd-advisory-fg-inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory--red .advisory-row--white {
|
||||||
|
background: var(--cd-advisory-red);
|
||||||
|
color: var(--cd-advisory-fg-inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
8. Back Tray (.back-tray, .tray-credits)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.back-tray {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: var(--cd-spine-width) 1fr var(--cd-spine-width);
|
||||||
|
background: var(--cd-tray-bg);
|
||||||
|
border-top: var(--cd-tray-border-top);
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-tray .tray-credits {
|
||||||
|
grid-column: 2;
|
||||||
|
padding: var(--cd-space-inset);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--cd-space-stack);
|
||||||
|
background: var(--cd-tray-bg-raised);
|
||||||
|
border-radius: 0 0 var(--cd-leaflet-radius) var(--cd-leaflet-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-credits h2 {
|
||||||
|
font-family: var(--cd-font-label);
|
||||||
|
font-size: var(--cd-font-size-title);
|
||||||
|
color: var(--cd-text-primary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: var(--cd-letter-spacing-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-credits ol {
|
||||||
|
list-style: none;
|
||||||
|
counter-reset: track;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--cd-space-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-credits ol li {
|
||||||
|
counter-increment: track;
|
||||||
|
font-family: var(--cd-font-label);
|
||||||
|
font-size: var(--cd-font-size-body);
|
||||||
|
color: var(--cd-text-secondary);
|
||||||
|
padding: var(--cd-space-xs) 0;
|
||||||
|
border-bottom: var(--cd-track-border-bot);
|
||||||
|
display: flex;
|
||||||
|
gap: var(--cd-space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-credits ol li::before {
|
||||||
|
content: counter(track, decimal-leading-zero) ".";
|
||||||
|
font-family: var(--cd-font-mono);
|
||||||
|
color: var(--cd-text-muted);
|
||||||
|
min-width: var(--cd-track-num-min-w);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-credits .credits-label {
|
||||||
|
font-family: var(--cd-font-mono);
|
||||||
|
font-size: var(--cd-spine-font-xs);
|
||||||
|
color: var(--cd-text-muted);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: var(--cd-letter-spacing-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-credits p {
|
||||||
|
font-family: var(--cd-font-body);
|
||||||
|
font-size: var(--cd-font-size-body);
|
||||||
|
color: var(--cd-text-secondary);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Back tray spine labels ── */
|
||||||
|
.back-tray .cd-spine {
|
||||||
|
grid-row: 1;
|
||||||
|
background: var(--cd-spine-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
9. Grid Overlay Utility (.cd-grid)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.cd-grid {
|
||||||
|
background-image:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent 0 calc(var(--cd-grid-coarse) - 1px),
|
||||||
|
var(--cd-grid-color) calc(var(--cd-grid-coarse) - 1px) var(--cd-grid-coarse)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-grid--fine {
|
||||||
|
background-image:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent 0 calc(var(--cd-grid-fine) - 1px),
|
||||||
|
var(--cd-grid-color) calc(var(--cd-grid-fine) - 1px) var(--cd-grid-fine)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-grid--coarse {
|
||||||
|
background-image:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent 0 calc(var(--cd-grid-coarse) - 1px),
|
||||||
|
var(--cd-grid-color) calc(var(--cd-grid-coarse) - 1px) var(--cd-grid-coarse)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-grid--crosshatch {
|
||||||
|
background-image:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
0deg,
|
||||||
|
transparent 0 calc(var(--cd-grid-fine) - 1px),
|
||||||
|
var(--cd-grid-color-alt) calc(var(--cd-grid-fine) - 1px) var(--cd-grid-fine)
|
||||||
|
),
|
||||||
|
repeating-linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent 0 calc(var(--cd-grid-coarse) - 1px),
|
||||||
|
var(--cd-grid-color) calc(var(--cd-grid-coarse) - 1px) var(--cd-grid-coarse)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
10. Open / Closed State Transitions
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.cd-jewel-case .back-tray {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-jewel-case--open .back-tray,
|
||||||
|
.cd-jewel-case[data-jewel-state="open"] .back-tray {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
11. Responsive Breakpoints (container queries)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
@container (max-width: var(--cd-break-sm)) {
|
||||||
|
.cd-jewel-case {
|
||||||
|
width: 100% !important;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-spine {
|
||||||
|
writing-mode: horizontal-tb;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: var(--cd-space-xs) var(--cd-space-sm);
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-jewel-inner {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disc-art {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: var(--cd-disc-diameter);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-content {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory {
|
||||||
|
position: static;
|
||||||
|
margin-top: var(--cd-space-stack);
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (min-width: var(--cd-break-md-min)) and (max-width: var(--cd-break-md-max)) {
|
||||||
|
.cd-jewel-case {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: var(--cd-jewel-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-content {
|
||||||
|
gap: var(--cd-space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory .advisory-row {
|
||||||
|
font-size: var(--cd-spine-font-xs);
|
||||||
|
padding: var(--cd-space-xs) var(--cd-space-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
12. Print Styles
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.cd-jewel-case {
|
||||||
|
width: var(--cd-print-jewel-width);
|
||||||
|
height: var(--cd-print-jewel-height);
|
||||||
|
box-shadow: none;
|
||||||
|
border: var(--cd-print-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-jewel-case--open {
|
||||||
|
width: calc(var(--cd-print-jewel-width) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-tray {
|
||||||
|
display: grid !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.human-advisory {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disc-art {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cd-jewel-case,
|
||||||
|
.leaflet-page,
|
||||||
|
.back-tray {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
13. Grain Texture Utility (.cd-grain)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.cd-grain {
|
||||||
|
background-image:
|
||||||
|
repeating-radial-gradient(
|
||||||
|
circle at 50% 50%,
|
||||||
|
transparent 0 1px,
|
||||||
|
rgb(0 0 0 / var(--cd-grain-opacity-1)) 1px 2px,
|
||||||
|
transparent 2px 4px
|
||||||
|
),
|
||||||
|
repeating-radial-gradient(
|
||||||
|
circle at 100% 100%,
|
||||||
|
transparent 0 3px,
|
||||||
|
rgb(0 0 0 / var(--cd-grain-opacity-2)) 3px 4px,
|
||||||
|
transparent 4px 8px
|
||||||
|
);
|
||||||
|
background-size: var(--cd-grain-size-1) var(--cd-grain-size-1),
|
||||||
|
var(--cd-grain-size-2) var(--cd-grain-size-2);
|
||||||
|
}
|
||||||
152
templates/back-tray.html
Normal file
152
templates/back-tray.html
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>OpenCD · Back Tray</title>
|
||||||
|
<link rel="stylesheet" href="../opencd.css">
|
||||||
|
<style>
|
||||||
|
/* Demo page chrome */
|
||||||
|
body {
|
||||||
|
min-height: 100dvh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
padding: 2rem;
|
||||||
|
background: oklch(92% .012 85);
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: .5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls input[type="checkbox"] {
|
||||||
|
accent-color: var(--red-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-footnote {
|
||||||
|
font-size: .75rem;
|
||||||
|
color: var(--gray-6);
|
||||||
|
text-align: center;
|
||||||
|
max-width: 480px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
Back-tray specific layout
|
||||||
|
============================================================ */
|
||||||
|
/* Wrap the back-tray in a jewel-case frame */
|
||||||
|
.demo-tray-container {
|
||||||
|
width: var(--cd-jewel-width);
|
||||||
|
border-radius: var(--cd-jewel-radius);
|
||||||
|
box-shadow: var(--cd-jewel-shadow);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- ============================================================
|
||||||
|
BACK TRAY — Tracklist & Credits
|
||||||
|
============================================================ -->
|
||||||
|
<div class="demo-tray-container">
|
||||||
|
|
||||||
|
<div class="back-tray cd-grid--crosshatch">
|
||||||
|
|
||||||
|
<!-- Left spine -->
|
||||||
|
<nav class="cd-spine cd-spine--side">
|
||||||
|
<span class="spine-label">OPENCD</span>
|
||||||
|
<span class="spine-track">03 · back-tray</span>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Credits / tracklist -->
|
||||||
|
<section class="tray-credits">
|
||||||
|
|
||||||
|
<span class="credits-label">Tracklist</span>
|
||||||
|
<ol>
|
||||||
|
<li>jewel-case</li>
|
||||||
|
<li>leaflet</li>
|
||||||
|
<li>back-tray</li>
|
||||||
|
<li>human-advisory</li>
|
||||||
|
<li>disc-art</li>
|
||||||
|
<li>spine-navigation</li>
|
||||||
|
<li>grid-overlay</li>
|
||||||
|
<li>print-layout</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<span class="credits-label">Credits</span>
|
||||||
|
<p>
|
||||||
|
<strong>Design & Architecture</strong><br>
|
||||||
|
Hannibal · Face
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Engineering & Prototypes</strong><br>
|
||||||
|
Murdock · B.A. Baracus
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Quality & Verification</strong><br>
|
||||||
|
Amy Amanda Allen
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<span class="credits-label">Technical</span>
|
||||||
|
<p>
|
||||||
|
Built on Open Props v2 · Pure CSS framework · No build step required<br>
|
||||||
|
ISO 15727 jewel case dimensions · 2× display scale<br>
|
||||||
|
GPG-signed commits · A-Team design collective
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Right spine -->
|
||||||
|
<nav class="cd-spine cd-spine--side">
|
||||||
|
<span class="spine-label">TRENTUNA</span>
|
||||||
|
<span class="spine-track">MMXXV</span>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Demo controls -->
|
||||||
|
<div class="demo-controls">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="toggle-grid" checked onchange="document.querySelector('.back-tray').classList.toggle('cd-grid--crosshatch', this.checked)">
|
||||||
|
Show grid
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Scale:
|
||||||
|
<select id="scale-select" onchange="setScale(this.value)">
|
||||||
|
<option value="0.5">0.5× (1× physical)</option>
|
||||||
|
<option value="1" selected>1 (default 2×)</option>
|
||||||
|
<option value="1.5">1.5× (3×)</option>
|
||||||
|
<option value="2">2× (4×)</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="demo-footnote">
|
||||||
|
Back tray paper insert (151 × 118 mm physical) with dual spines, tracklist, and production credits · Grid overlay inspired by trentuna.com paper-card aesthetic
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function setScale(scale) {
|
||||||
|
document.documentElement.style.setProperty('--cd-scale', scale);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
131
templates/jewel-case.html
Normal file
131
templates/jewel-case.html
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>OpenCD · Jewel Case</title>
|
||||||
|
<link rel="stylesheet" href="../opencd.css">
|
||||||
|
<style>
|
||||||
|
/* Demo page chrome — not part of OpenCD */
|
||||||
|
body {
|
||||||
|
min-height: 100dvh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
padding: 2rem;
|
||||||
|
background: oklch(92% .012 85);
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: .5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls input[type="checkbox"] {
|
||||||
|
accent-color: var(--red-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls select {
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
border: 1px solid var(--gray-5);
|
||||||
|
border-radius: var(--radius-2);
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-footnote {
|
||||||
|
font-size: .75rem;
|
||||||
|
color: var(--gray-6);
|
||||||
|
text-align: center;
|
||||||
|
max-width: 480px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- ============================================================
|
||||||
|
JEWEL CASE — Closed (default)
|
||||||
|
============================================================ -->
|
||||||
|
<main class="cd-jewel-case" id="jewel" data-jewel-state="closed">
|
||||||
|
|
||||||
|
<!-- Spine -->
|
||||||
|
<nav class="cd-spine">
|
||||||
|
<span class="spine-label">OPENCD · TRENTUNA</span>
|
||||||
|
<span class="spine-track">01 · jewel-case</span>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Inner content -->
|
||||||
|
<div class="cd-jewel-inner">
|
||||||
|
|
||||||
|
<!-- Leaflet content area with disc art -->
|
||||||
|
<section class="leaflet-content cd-grid">
|
||||||
|
<article class="leaflet-page" data-leaflet-page="0" data-leaflet-active="true">
|
||||||
|
<h1>Jewel Case</h1>
|
||||||
|
<p>A compact disc (CD) jewel case is a three-piece plastic case designed to hold standard audio CDs, CD-ROMs, and other optical media. This prototype recreates the physical form factor in pure HTML and CSS.</p>
|
||||||
|
<span class="leaflet-meta">142 × 125 mm · 2× scale</span>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Disc art -->
|
||||||
|
<div class="disc-art disc-art--sheen">
|
||||||
|
<span class="disc-hole">◉</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Human Advisory badge -->
|
||||||
|
<aside class="human-advisory human-advisory--red">
|
||||||
|
<span class="advisory-row advisory-row--black">HUMAN</span>
|
||||||
|
<span class="advisory-row advisory-row--white">ADVISORY</span>
|
||||||
|
<span class="advisory-row advisory-row--red">PROTOTYPE CODE</span>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Demo controls -->
|
||||||
|
<div class="demo-controls">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="toggle-open" onchange="toggleOpen(this.checked)">
|
||||||
|
Open case
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
Scale:
|
||||||
|
<select id="scale-select" onchange="setScale(this.value)">
|
||||||
|
<option value="0.5">0.5× (1× physical)</option>
|
||||||
|
<option value="1" selected>1 (default 2×)</option>
|
||||||
|
<option value="1.5">1.5× (3×)</option>
|
||||||
|
<option value="2">2× (4×)</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="demo-footnote">
|
||||||
|
An OpenCD prototype by H.M. Murdock · Built with Open Props · Pure CSS, no JS dependency
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleOpen(open) {
|
||||||
|
const jewel = document.getElementById('jewel');
|
||||||
|
jewel.dataset.jewelState = open ? 'open' : 'closed';
|
||||||
|
jewel.classList.toggle('cd-jewel-case--open', open);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setScale(scale) {
|
||||||
|
document.documentElement.style.setProperty('--cd-scale', scale);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
184
templates/leaflet.html
Normal file
184
templates/leaflet.html
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>OpenCD · Leaflet</title>
|
||||||
|
<link rel="stylesheet" href="../opencd.css">
|
||||||
|
<style>
|
||||||
|
/* Demo page chrome */
|
||||||
|
body {
|
||||||
|
min-height: 100dvh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
padding: 2rem;
|
||||||
|
background: oklch(92% .012 85);
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls button {
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
border: 1px solid var(--gray-6);
|
||||||
|
border-radius: var(--radius-2);
|
||||||
|
background: var(--gray-0);
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background var(--cd-transition-duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls button:hover {
|
||||||
|
background: var(--gray-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls button:disabled {
|
||||||
|
opacity: .4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-controls .page-indicator {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: .875rem;
|
||||||
|
color: var(--gray-6);
|
||||||
|
min-width: 8ch;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-footnote {
|
||||||
|
font-size: .75rem;
|
||||||
|
color: var(--gray-6);
|
||||||
|
text-align: center;
|
||||||
|
max-width: 480px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
Leaflet-specific overrides for multi-page demo
|
||||||
|
============================================================ */
|
||||||
|
.leaflet-content--multi {
|
||||||
|
max-width: calc(var(--cd-leaflet-size) + var(--cd-space-inset) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-pages {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--cd-space-stack);
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-pages .leaflet-page {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-pages .leaflet-page[data-leaflet-active="true"] {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- ============================================================
|
||||||
|
LEAFLET — Multi-page booklet
|
||||||
|
============================================================ -->
|
||||||
|
<main class="cd-jewel-case" style="width: auto; box-shadow: none; background: transparent;">
|
||||||
|
|
||||||
|
<div class="cd-jewel-inner" style="grid-column:1/-1; gap: var(--cd-space-inset);">
|
||||||
|
|
||||||
|
<section class="leaflet-content leaflet-content--multi cd-grid--crosshatch">
|
||||||
|
|
||||||
|
<div class="leaflet-pages" id="pages">
|
||||||
|
|
||||||
|
<article class="leaflet-page" data-leaflet-page="0" data-leaflet-active="true">
|
||||||
|
<h1>Design Notes</h1>
|
||||||
|
<p>This booklet is a demonstration of the leaflet component — the insert booklet found inside a standard CD jewel case. Each page measures 120 × 120 mm (240px at 2× scale), matching the ISO 15727 standard for CD packaging.</p>
|
||||||
|
<span class="leaflet-meta">Page 1 of 4 · v0.1.0</span>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="leaflet-page" data-leaflet-page="1" data-leaflet-active="false">
|
||||||
|
<h1>Architecture</h1>
|
||||||
|
<p>OpenCD is built on Open Props — a design token framework by Adam Argyle. Every dimension, color, and spacing value maps to a custom property, with fallback values for standalone use. The framework includes:</p>
|
||||||
|
<ul style="margin-left:1rem; color:var(--cd-text-secondary); line-height:1.6;">
|
||||||
|
<li>CD dimension tokens at 2× scale</li>
|
||||||
|
<li>Semantic color aliases on Open Props</li>
|
||||||
|
<li>ASW-inspired surface layers</li>
|
||||||
|
<li>Visible grid overlays (tray paper aesthetic)</li>
|
||||||
|
</ul>
|
||||||
|
<span class="leaflet-meta">Page 2 of 4 · v0.1.0</span>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="leaflet-page" data-leaflet-page="2" data-leaflet-active="false">
|
||||||
|
<h1>Token System</h1>
|
||||||
|
<p>The variable layer defines ~40 custom properties organized into semantic groups:</p>
|
||||||
|
<dl style="margin-top:.5rem; display:grid; gap:.25rem; font-size:var(--size-fluid-1);">
|
||||||
|
<dt style="font-family:var(--font-mono); color:var(--gray-6);">--cd-jewel-width</dt>
|
||||||
|
<dd style="color:var(--gray-7);">280px × scale</dd>
|
||||||
|
<dt style="font-family:var(--font-mono); color:var(--gray-6);">--cd-surface-1</dt>
|
||||||
|
<dd style="color:var(--gray-7);">oklch(30% .015 265)</dd>
|
||||||
|
<dt style="font-family:var(--font-mono); color:var(--gray-6);">--cd-font-label</dt>
|
||||||
|
<dd style="color:var(--gray-7);">--cd-font-neo-grotesque</dd>
|
||||||
|
</dl>
|
||||||
|
<span class="leaflet-meta">Page 3 of 4 · v0.1.0</span>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="leaflet-page" data-leaflet-page="3" data-leaflet-active="false">
|
||||||
|
<h1>Credits</h1>
|
||||||
|
<p>OpenCD is a project of the A-Team design collective — a framework for physical-digital design artifacts that bridge the gap between print packaging and web implementations.</p>
|
||||||
|
<p style="margin-top:.5rem;">Design: Hannibal & Face<br>Engineering: Murdock & B.A.<br>Quality: Amy</p>
|
||||||
|
<span class="leaflet-meta">Page 4 of 4 · MMXXV</span>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Human Advisory badge (small) -->
|
||||||
|
<aside class="human-advisory" style="position:static; align-self:flex-end;">
|
||||||
|
<span class="advisory-row advisory-row--black">PROTOTYPE</span>
|
||||||
|
<span class="advisory-row advisory-row--white">OPENCD v0.1</span>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Demo controls -->
|
||||||
|
<div class="demo-controls">
|
||||||
|
<button id="prev-btn" onclick="flipPage(-1)" disabled>← Prev</button>
|
||||||
|
<span class="page-indicator" id="page-indicator">Page 1 / 4</span>
|
||||||
|
<button id="next-btn" onclick="flipPage(1)">Next →</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="demo-footnote">
|
||||||
|
Leaflet booklet demo · 4-page layout at 120 × 120 mm each · Page-turn via inline JS
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let currentPage = 0;
|
||||||
|
const totalPages = 4;
|
||||||
|
|
||||||
|
function flipPage(direction) {
|
||||||
|
const pages = document.querySelectorAll('.leaflet-page');
|
||||||
|
const old = currentPage;
|
||||||
|
|
||||||
|
currentPage = Math.max(0, Math.min(totalPages - 1, currentPage + direction));
|
||||||
|
|
||||||
|
if (old === currentPage) return;
|
||||||
|
|
||||||
|
pages[old].dataset.leafletActive = 'false';
|
||||||
|
pages[currentPage].dataset.leafletActive = 'true';
|
||||||
|
|
||||||
|
document.getElementById('page-indicator').textContent = 'Page ' + (currentPage + 1) + ' / ' + totalPages;
|
||||||
|
document.getElementById('prev-btn').disabled = currentPage === 0;
|
||||||
|
document.getElementById('next-btn').disabled = currentPage === totalPages - 1;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue