diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7ac3703 --- /dev/null +++ b/.env.example @@ -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 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c1a9b1b --- /dev/null +++ b/.gitignore @@ -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 \ No newline at end of file diff --git a/opencd.css b/opencd.css index 1042f8e..e3a3c73 100644 --- a/opencd.css +++ b/opencd.css @@ -1,97 +1,178 @@ /* ========================================================================== - OpenCD — Jewel Case CSS Framework - Prototype: single-file system - Author: H.M. Murdock + OpenCD — CD Jewel Case CSS Framework (Production) + Author: B.A. Baracus 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 — CD Dimension & Design Tokens + 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 { - /* ── Scale ── - --cd-scale: 1 → default 2× display scale (280px = 142mm at 2×) - Set to 0.5 for 1× (physical mm → px at 96dpi), 2 for 4×, etc. - */ + /* ═══════════════════════════════════════════════════════════════════════ + Physical CD Dimensions (at 2× scale, ISO 15727) + Formula: calc( * 2px / 1mm) = + ═══════════════════════════════════════════════════════════════════════ */ --cd-scale: 1; + /* --cd-scale: 1 = default 2× display scale. 0.5 = 1×, 2 = 4×, etc. */ - /* ── Physical CD Dimensions (at 2× scale) ── */ - --cd-jewel-width: calc(280px * var(--cd-scale)); - --cd-jewel-height: calc(245px * var(--cd-scale)); - --cd-jewel-open-width: calc(560px * var(--cd-scale)); - --cd-disc-diameter: calc(240px * var(--cd-scale)); - --cd-disc-hole: calc(30px * var(--cd-scale)); /* Ø15mm × 2 */ - --cd-leaflet-size: calc(240px * var(--cd-scale)); - --cd-spine-width: calc(14px * var(--cd-scale)); - --cd-tray-width: calc(260px * var(--cd-scale)); + --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, NOT from Open Props — Amy finding #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 */ - /* ── Typography ── */ - --cd-font-label: var(--font-neo-grotesque); /* Inter/Roboto stack — Amy finding #4 */ - --cd-font-body: var(--font-serif); + /* ── 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); - /* ── Spacing insets ── */ + /* ── 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); - /* ── Semantic Text Colors ── */ + --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); + /* ═══════════════════════════════════════════════════════════════════════ + 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, Amy finding #2) ── */ + /* ═══════════════════════════════════════════════════════════════════════ + 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 ── */ + /* ═══════════════════════════════════════════════════════════════════════ + 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 ── */ + /* ═══════════════════════════════════════════════════════════════════════ + 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 */ - /* ── Spine Typography ── */ - --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); + /* ═══════════════════════════════════════════════════════════════════════ + 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); - /* ── Motion & Print ── */ + /* ═══════════════════════════════════════════════════════════════════════ + 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-print-jewel-width: 142mm; - --cd-print-jewel-height: 125mm; + --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 */ } /* ========================================================================== @@ -105,7 +186,7 @@ } /* ========================================================================== - 3. Jewel Case Container + 3. Jewel Case Container (.cd-jewel-case) ========================================================================== */ .cd-jewel-case { @@ -114,21 +195,18 @@ grid-template-rows: auto 1fr; width: var(--cd-jewel-width); min-height: var(--cd-jewel-height); - background: var(--gray-0); + 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(--ease-3); + 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 { - width: var(--cd-jewel-open-width); -} - +.cd-jewel-case--open, .cd-jewel-case[data-jewel-state="open"] { width: var(--cd-jewel-open-width); } @@ -145,7 +223,7 @@ } /* ========================================================================== - 4. Spine + 4. Spine (.cd-spine, .spine-label, .spine-track) ========================================================================== */ .cd-spine { @@ -158,8 +236,8 @@ background: var(--cd-spine-bg); color: var(--cd-text-on-spine); font-family: var(--cd-font-label); - padding: var(--size-2) var(--size-1); - gap: var(--size-2); + padding: var(--cd-space-sm) var(--cd-space-xs); + gap: var(--cd-space-sm); writing-mode: vertical-rl; text-orientation: mixed; user-select: none; @@ -168,13 +246,13 @@ .cd-spine .spine-label { font-size: var(--cd-spine-font-sm); font-weight: 600; - letter-spacing: var(--font-letterspacing-3, 0.1em); + letter-spacing: var(--cd-letter-spacing-3); text-transform: uppercase; } .cd-spine .spine-track { font-size: var(--cd-spine-font-xs); - letter-spacing: var(--font-letterspacing-1, 0.05em); + letter-spacing: var(--cd-letter-spacing-1); opacity: 0.8; } @@ -185,7 +263,7 @@ } /* ========================================================================== - 5. Leaflet Content & Pages + 5. Leaflet Content & Pages (.leaflet-content, .leaflet-page) ========================================================================== */ .leaflet-content { @@ -207,13 +285,13 @@ .leaflet-page { aspect-ratio: var(--cd-aspect-leaflet); - background: var(--gray-0); + 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(--size-2); - box-shadow: 0 1px 3px rgba(0,0,0,.08); + gap: var(--cd-space-sm); + box-shadow: var(--cd-page-shadow); transition: transform var(--cd-transition-duration) var(--cd-ease-flip); position: relative; } @@ -249,7 +327,7 @@ } /* ========================================================================== - 6. Disc Art + 6. Disc Art (.disc-art, .disc-hole) ========================================================================== */ .disc-art { @@ -268,7 +346,7 @@ align-items: center; justify-content: center; position: relative; - box-shadow: inset 0 0 8px rgba(0,0,0,.12); + box-shadow: var(--cd-disc-shadow); } .disc-art::before { @@ -277,25 +355,25 @@ width: var(--cd-disc-hole); aspect-ratio: 1; border-radius: 50%; - background: var(--gray-0); - box-shadow: inset 0 0 3px rgba(0,0,0,.15); + background: var(--cd-surface-0); + box-shadow: var(--cd-disc-hole-shadow); } .disc-hole { position: absolute; - width: calc(var(--cd-disc-hole) * 0.6); + 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) * 0.5); + font-size: calc(var(--cd-disc-hole) * var(--cd-disc-hole-font-scale)); color: var(--gray-4); z-index: 1; pointer-events: none; } -/* ── Disc art variants ── */ +/* ── Disc sheen variant ── */ .disc-art--sheen { background: radial-gradient( @@ -319,17 +397,17 @@ } /* ========================================================================== - 7. Human Advisory Badge + 7. Human Advisory Badge (.human-advisory) ========================================================================== */ .human-advisory { display: flex; flex-direction: column; align-items: center; - background: #000; - color: #fff; - border: 2px solid #000; - font-family: Impact, "Arial Black", var(--cd-font-label), sans-serif; + 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; @@ -342,48 +420,48 @@ .human-advisory .advisory-row { width: 100%; - padding: var(--size-1) var(--size-3); + padding: var(--cd-space-xs) var(--cd-space-sm); font-size: var(--cd-spine-font-sm); - letter-spacing: var(--font-letterspacing-3, 0.1em); + letter-spacing: var(--cd-letter-spacing-3); line-height: 1.2; white-space: nowrap; } .human-advisory .advisory-row--black { - background: #000; - color: #fff; + background: var(--cd-advisory-fg); + color: var(--cd-advisory-fg-inv); } .human-advisory .advisory-row--white { - background: #fff; - color: #000; + background: var(--cd-advisory-fg-inv); + color: var(--cd-advisory-fg); } .human-advisory .advisory-row--red { background: var(--cd-advisory-red); - color: #fff; + color: var(--cd-advisory-fg-inv); } -/* ── Human Advisory variants ── */ +/* ── Advisory badge red variant ── */ .human-advisory--red .advisory-row--black { background: var(--cd-advisory-red-dark); - color: #fff; + color: var(--cd-advisory-fg-inv); } .human-advisory--red .advisory-row--white { background: var(--cd-advisory-red); - color: #fff; + color: var(--cd-advisory-fg-inv); } /* ========================================================================== - 8. Back Tray + 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: 1px solid var(--cd-grid-color); + border-top: var(--cd-tray-border-top); padding: 0; position: relative; } @@ -403,7 +481,7 @@ font-size: var(--cd-font-size-title); color: var(--cd-text-primary); text-transform: uppercase; - letter-spacing: var(--font-letterspacing-2, 0.075em); + letter-spacing: var(--cd-letter-spacing-2); } .tray-credits ol { @@ -411,7 +489,7 @@ counter-reset: track; display: flex; flex-direction: column; - gap: var(--size-1); + gap: var(--cd-space-xs); } .tray-credits ol li { @@ -419,17 +497,17 @@ font-family: var(--cd-font-label); font-size: var(--cd-font-size-body); color: var(--cd-text-secondary); - padding: var(--size-1) 0; - border-bottom: 1px solid var(--cd-grid-color-alt); + padding: var(--cd-space-xs) 0; + border-bottom: var(--cd-track-border-bot); display: flex; - gap: var(--size-2); + 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: 2.5ch; + min-width: var(--cd-track-num-min-w); } .tray-credits .credits-label { @@ -437,7 +515,7 @@ font-size: var(--cd-spine-font-xs); color: var(--cd-text-muted); text-transform: uppercase; - letter-spacing: var(--font-letterspacing-1, 0.05em); + letter-spacing: var(--cd-letter-spacing-1); } .tray-credits p { @@ -454,7 +532,7 @@ } /* ========================================================================== - 9. Grid Overlay Utility + 9. Grid Overlay Utility (.cd-grid) ========================================================================== */ .cd-grid { @@ -512,10 +590,10 @@ } /* ========================================================================== - 11. Responsive Breakpoints (Open Props container queries) + 11. Responsive Breakpoints (container queries) ========================================================================== */ -@container (max-width: 350px) { +@container (max-width: var(--cd-break-sm)) { .cd-jewel-case { width: 100% !important; grid-template-columns: 1fr; @@ -524,7 +602,7 @@ .cd-spine { writing-mode: horizontal-tb; flex-direction: row; - padding: var(--size-1) var(--size-2); + padding: var(--cd-space-xs) var(--cd-space-sm); grid-column: 1; grid-row: 1; } @@ -551,19 +629,19 @@ } } -@container (min-width: 351px) and (max-width: 549px) { +@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(--size-2); + gap: var(--cd-space-sm); } .human-advisory .advisory-row { font-size: var(--cd-spine-font-xs); - padding: var(--size-1) var(--size-2); + padding: var(--cd-space-xs) var(--cd-space-sm); } } @@ -576,7 +654,7 @@ width: var(--cd-print-jewel-width); height: var(--cd-print-jewel-height); box-shadow: none; - border: 1px solid #ccc; + border: var(--cd-print-border); } .cd-jewel-case--open { @@ -603,21 +681,23 @@ } /* ========================================================================== - 13. Grain Texture Utility + 13. Grain Texture Utility (.cd-grain) ========================================================================== */ .cd-grain { - background-image: repeating-radial-gradient( - circle at 50% 50%, - transparent 0 1px, - rgba(0,0,0,.02) 1px 2px, - transparent 2px 4px - ), - repeating-radial-gradient( - circle at 100% 100%, - transparent 0 3px, - rgba(0,0,0,.015) 3px 4px, - transparent 4px 8px - ); - background-size: 120px 120px, 200px 200px; + 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); } \ No newline at end of file diff --git a/templates/back-tray.html b/templates/back-tray.html index 3539ff0..a6c4ec9 100644 --- a/templates/back-tray.html +++ b/templates/back-tray.html @@ -16,7 +16,7 @@ gap: 2rem; padding: 2rem; background: oklch(92% .012 85); - font-family: var(--font-system-ui); + font-family: var(--font-sans); } .demo-controls { diff --git a/templates/jewel-case.html b/templates/jewel-case.html index 2cd6c99..47ed3ae 100644 --- a/templates/jewel-case.html +++ b/templates/jewel-case.html @@ -16,7 +16,7 @@ gap: 2rem; padding: 2rem; background: oklch(92% .012 85); - font-family: var(--font-system-ui); + font-family: var(--font-sans); } .demo-controls { diff --git a/templates/leaflet.html b/templates/leaflet.html index 766fbfb..b75b41a 100644 --- a/templates/leaflet.html +++ b/templates/leaflet.html @@ -16,7 +16,7 @@ gap: 2rem; padding: 2rem; background: oklch(92% .012 85); - font-family: var(--font-system-ui); + font-family: var(--font-sans); } .demo-controls { @@ -125,7 +125,7 @@
--cd-surface-1
oklch(30% .015 265)
--cd-font-label
-
font-neo-grotesque
+
--cd-font-neo-grotesque
Page 3 of 4 · v0.1.0