From b602a8d54e36501db7f08cea1ce3640277c79066 Mon Sep 17 00:00:00 2001 From: Ludo Date: Sat, 11 Apr 2026 15:26:02 +0200 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20CSS=20tasks=201-6=20=E2=80=94?= =?UTF-8?q?=20add=20token=20aliases,=20fix=20all=20primitive=20leaks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename 01-asw.css → 01-tokens.css (pure :root, no rules) - Add semantic aliases: --weight-*, --shadow-*, --focus-ring-width, --dropdown-min-width, --space-5a, --weight-light, --border-width-thick - Extract editorial rules from token file to components/layout - Replace all Open Props primitives in layers 02-09 with semantic aliases - Zero primitive leaks remain outside 01-tokens.css Co-Authored-By: Claude Opus 4.6 (1M context) --- src/layers/{01-asw.css => 01-tokens.css} | 37 +++++++++++++---------- src/layers/02-semantic.css | 18 +++++------ src/layers/03-components.css | 38 ++++++++++++++---------- src/layers/04-data-attrs.css | 14 ++++----- src/layers/05-utilities.css | 10 +++---- src/layers/06-charts.css | 34 ++++++++++----------- src/layers/07-chroma.css | 4 +-- src/layers/08-layout.css | 11 +++---- src/layers/08a-essay.css | 2 +- src/layers/09-landing.css | 2 +- src/main.css | 2 +- 11 files changed, 92 insertions(+), 80 deletions(-) rename src/layers/{01-asw.css => 01-tokens.css} (96%) diff --git a/src/layers/01-asw.css b/src/layers/01-tokens.css similarity index 96% rename from src/layers/01-asw.css rename to src/layers/01-tokens.css index b73ed12..035004d 100644 --- a/src/layers/01-asw.css +++ b/src/layers/01-tokens.css @@ -266,6 +266,27 @@ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 115, 115)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + /* Font weights */ + --weight-light: var(--font-weight-2); + --weight-normal: var(--font-weight-4); + --weight-medium: var(--font-weight-5); + --weight-semibold: var(--font-weight-6); + --weight-bold: var(--font-weight-7); + + /* Shadows */ + --shadow-dropdown: var(--shadow-2); + --shadow-modal: var(--shadow-4); + + /* Focus ring */ + --focus-ring-width: var(--border-size-2); + --border-width-thick: var(--border-size-3); + + /* Dropdown */ + --dropdown-min-width: var(--size-px-12); + + /* Gap in spacing scale */ + --space-5a: 1.25rem; /* between --space-4 (1rem) and --space-5 (1.5rem) */ + /* ══════════════════════════════════════════════════════════════════ AGENT-NATIVE TOKENS @@ -395,19 +416,3 @@ @media (--lg-n-above) { html { font-size: 103%; } } @media (--xl-n-above) { html { font-size: 106%; } } @media (--xxl-n-above) { html { font-size: 109%; } } - - -/* ══════════════════════════════════════════════════════════════════ - EDITORIAL DEFAULTS - Opinionated ASW decisions that go beyond tokens — centering, - spacing rhythms, and layout choices that define the ASW look. - ══════════════════════════════════════════════════════════════════ */ - -/* Nav content centered at --width-xl without a wrapper element. - max() falls back to --container-padding on narrow viewports. */ -body > nav { - padding-inline: max(var(--container-padding), calc((100% - var(--width-xl)) / 2)); -} -[data-layout="docs"] > article { - max-width: var(--width-prose); -} diff --git a/src/layers/02-semantic.css b/src/layers/02-semantic.css index 3c93523..f3391e2 100644 --- a/src/layers/02-semantic.css +++ b/src/layers/02-semantic.css @@ -145,7 +145,7 @@ p { margin-bottom: var(--type-space); color: var(--text); font-style: normal; - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); } /* ── Typography: Lists ─────────────────────────────────────────────── */ @@ -158,7 +158,7 @@ ul { margin-bottom: var(--type-space); color: var(--text); font-style: normal; - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); } :where(ol, ul) li { @@ -225,7 +225,7 @@ del { } abbr[title] { - border-bottom: var(--border-size-1) dotted; + border-bottom: var(--border-width) dotted; text-decoration: none; cursor: help; } @@ -297,7 +297,7 @@ small { text-indent: 0; color: var(--text); font-style: normal; - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); } th, @@ -306,14 +306,14 @@ td { border-bottom: var(--border-width) solid var(--border); background-color: transparent; color: var(--text); - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); text-align: left; } thead th, thead td { font-weight: 600; - border-bottom-width: var(--border-size-2); + border-bottom-width: var(--focus-ring-width); } tfoot th, @@ -339,7 +339,7 @@ samp { border-radius: var(--radius-md); background: var(--surface-1); color: var(--code-color); - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); line-height: initial; } @@ -471,10 +471,10 @@ pre[class*="language-"] { .token.important, .token.variable { color: var(--syntax-variable); - font-weight: var(--font-weight-5); + font-weight: var(--weight-medium); } -.token.bold { font-weight: var(--font-weight-7); } +.token.bold { font-weight: var(--weight-bold); } .token.italic { font-style: italic; } /* Light mode overrides */ diff --git a/src/layers/03-components.css b/src/layers/03-components.css index f27fa01..f89a6b4 100644 --- a/src/layers/03-components.css +++ b/src/layers/03-components.css @@ -35,7 +35,7 @@ button, outline: none; background-color: var(--surface); color: var(--text); - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); font-size: var(--text-base); line-height: var(--leading); text-align: center; @@ -100,7 +100,7 @@ label { display: block; margin-bottom: calc(var(--space-4) * 0.375); color: var(--text); - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); } input:not([type=checkbox], [type=radio], [type=range], [type=file]), @@ -113,7 +113,7 @@ textarea { outline: none; background-color: var(--input-bg); color: var(--text); - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); transition: background-color var(--ease), border-color var(--ease), color var(--ease); @@ -259,6 +259,12 @@ label > :where(input, select, textarea) { /* ── Navigation ────────────────────────────────────────────────────────*/ /* Semantic nav: */ +/* Nav content centered at --width-xl without a wrapper element. + max() falls back to --container-padding on narrow viewports. */ +body > nav { + padding-inline: max(var(--container-padding), calc((100% - var(--width-xl)) / 2)); +} + body > nav { display: flex; justify-content: space-between; @@ -382,13 +388,13 @@ body > nav details > div { position: absolute; top: calc(100% + 0.5rem); left: 0; - min-width: var(--size-px-12); + min-width: var(--dropdown-min-width); padding: 0.5rem 0; margin: 0; background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius-md); - box-shadow: var(--shadow-2); + box-shadow: var(--shadow-dropdown); z-index: 20; list-style: none; display: flex; @@ -452,7 +458,7 @@ article { background: transparent; border: 1px solid var(--border); border-radius: var(--radius-md); - padding: var(--size-3) var(--size-4); + padding: var(--space-4) var(--space-5a); margin: var(--space-3) 0; } @@ -601,7 +607,7 @@ details:not(nav details) > summary { padding: var(--space-3) var(--space-4); font-family: var(--font-ui); font-size: var(--text-base); - font-weight: var(--font-weight-5, 500); + font-weight: var(--weight-medium); color: var(--text); cursor: pointer; list-style: none; @@ -687,7 +693,7 @@ dialog { border-radius: var(--radius-md); background: var(--surface-1); color: var(--text); - box-shadow: var(--shadow-4); + box-shadow: var(--shadow-modal); z-index: var(--layer-4); max-width: min(90vw, 42rem); max-height: min(90vh, 40rem); @@ -779,7 +785,7 @@ dialog > footer { color: var(--text-3); padding-inline: var(--space-2); user-select: none; - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); } [data-role="breadcrumb"] a { @@ -795,7 +801,7 @@ dialog > footer { /* Current page: plain text, full colour, no link underline */ [data-role="breadcrumb"] [aria-current="page"] { color: var(--text); - font-weight: var(--font-weight-5); + font-weight: var(--weight-medium); } @@ -861,7 +867,7 @@ dialog > footer { justify-content: center; font-family: var(--font-mono); font-size: var(--text-xs); - font-weight: var(--font-weight-6); + font-weight: var(--weight-semibold); z-index: 1; /* default (pending) colours — overridden below */ background: var(--surface-card); @@ -902,12 +908,12 @@ dialog > footer { background: var(--accent); border-color: var(--accent); color: var(--on-accent); - box-shadow: 0 0 0 var(--border-size-2) var(--accent-focus); + box-shadow: 0 0 0 var(--focus-ring-width) var(--accent-focus); } [data-role="steps"] > [data-status="active"] > span { color: var(--text); - font-weight: var(--font-weight-5); + font-weight: var(--weight-medium); } /* pending is the default — no additional rules needed */ @@ -961,7 +967,7 @@ nav[data-nav="sidebar"] h3 { color: var(--text-3); font-size: var(--text-xs); font-family: var(--font-mono); - font-weight: var(--font-weight-5); + font-weight: var(--weight-medium); text-transform: uppercase; letter-spacing: 0.08em; margin-top: var(--space-4); @@ -1008,7 +1014,7 @@ aside[data-toc] h3 { color: var(--text-3); font-size: var(--text-xs); font-family: var(--font-mono); - font-weight: var(--font-weight-5); + font-weight: var(--weight-medium); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: var(--space-2); @@ -1030,7 +1036,7 @@ aside[data-toc] nav a { padding: var(--space-1) var(--space-2); color: var(--text-3); text-decoration: none; - border-left: var(--border-size-2) solid transparent; + border-left: var(--focus-ring-width) solid transparent; transition: color var(--ease), border-color var(--ease); } diff --git a/src/layers/04-data-attrs.css b/src/layers/04-data-attrs.css index 9170033..8b5897c 100644 --- a/src/layers/04-data-attrs.css +++ b/src/layers/04-data-attrs.css @@ -522,7 +522,7 @@ position: fixed; top: 0; left: 0; - height: var(--border-size-2); + height: var(--focus-ring-width); background: var(--accent); z-index: 9999; /* Subtle shadow so bar is visible on light pages too */ @@ -546,7 +546,7 @@ /* Subtle accent on AI-generated sections — light left border indicator */ [data-ai-disclosure] { - border-left: var(--border-size-2) solid transparent; + border-left: var(--focus-ring-width) solid transparent; padding-left: var(--space-3); } @@ -561,7 +561,7 @@ /* Autonomous — more distinct: full accent treatment */ [data-ai-disclosure="autonomous"] { border-left-color: var(--accent); - border-left-width: var(--border-size-2); + border-left-width: var(--focus-ring-width); } /* Mixed — yellow/amber to signal blended provenance */ @@ -649,14 +649,14 @@ a[data-role="secondary"]:hover { [data-size="xs"] { font-size: var(--font-size-00, 0.6rem); - padding: var(--size-1) var(--size-2); - gap: var(--size-1); + padding: var(--space-1) var(--space-2); + gap: var(--space-1); } [data-size="sm"] { font-size: var(--text-xs); - padding: var(--size-1) var(--size-3); - gap: var(--size-2); + padding: var(--space-1) var(--space-4); + gap: var(--space-2); } /* md is the default — explicit reset for override contexts */ diff --git a/src/layers/05-utilities.css b/src/layers/05-utilities.css index 53c3030..b410b0a 100644 --- a/src/layers/05-utilities.css +++ b/src/layers/05-utilities.css @@ -111,7 +111,7 @@ dl[data-layout="inline"] dd { height: 1em; margin-right: 0.5em; vertical-align: -0.125em; - border: var(--border-size-2) solid currentColor; + border: var(--focus-ring-width) solid currentColor; border-top-color: transparent; border-radius: 50%; } @@ -175,7 +175,7 @@ dl[data-layout="inline"] dd { --border-color-subtle: var(--border-subtle); --text-primary: var(--hc-text); --text-secondary: var(--text-2); - --border-width: var(--border-size-2); + --border-width: var(--focus-ring-width); } /* Thicker borders on interactive elements */ @@ -185,13 +185,13 @@ dl[data-layout="inline"] dd { select, textarea, [data-wikilink] { - border-width: var(--border-size-2); + border-width: var(--focus-ring-width); } /* Stronger focus indicators */ :focus-visible { - outline-width: var(--border-size-3); - outline-offset: var(--border-size-3); + outline-width: var(--border-width-thick); + outline-offset: var(--border-width-thick); } } diff --git a/src/layers/06-charts.css b/src/layers/06-charts.css index 9af3fb6..3cdda19 100644 --- a/src/layers/06-charts.css +++ b/src/layers/06-charts.css @@ -69,7 +69,7 @@ font-size: var(--text-sm); color: var(--text-3); text-align: start; - padding-block-end: var(--size-3); + padding-block-end: var(--space-4); caption-side: top; } @@ -118,7 +118,7 @@ [data-chart="bar"] tr { display: flex; align-items: center; - gap: var(--size-3); + gap: var(--space-4); } /* Row label (th) */ @@ -130,7 +130,7 @@ max-inline-size: 8rem; text-align: end; padding-block: 0; - padding-inline: var(--size-2) 0; + padding-inline: var(--space-2) 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -227,7 +227,7 @@ justify-content: flex-end; flex: 1; block-size: 100%; - gap: var(--size-1); + gap: var(--space-1); } /* Column label (th) at the bottom */ @@ -241,10 +241,10 @@ text-overflow: ellipsis; max-inline-size: 100%; padding: 0; - padding-block-start: var(--size-1); + padding-block-start: var(--space-1); /* Move below axis */ order: 2; - margin-block-start: var(--size-2); + margin-block-start: var(--space-2); } /* Data cell — the column bar */ @@ -285,7 +285,7 @@ [data-chart="column"][data-chart-labels] thead { display: flex; justify-content: space-around; - margin-block-end: var(--size-2); + margin-block-end: var(--space-2); } [data-chart="column"][data-chart-labels] thead th { @@ -332,7 +332,7 @@ color: var(--chart-label); text-align: center; order: 2; - padding-block-start: var(--size-1); + padding-block-start: var(--space-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -390,7 +390,7 @@ color: var(--chart-label); text-align: center; order: 2; - padding-block-start: var(--size-1); + padding-block-start: var(--space-1); white-space: nowrap; } @@ -456,9 +456,9 @@ [data-chart="pie"] thead { display: flex; flex-wrap: wrap; - gap: var(--size-2); + gap: var(--space-2); justify-content: center; - margin-block-end: var(--size-3); + margin-block-end: var(--space-4); } [data-chart="pie"] thead th { @@ -549,7 +549,7 @@ display: inline-flex; flex-direction: column; align-items: center; - gap: var(--size-2); + gap: var(--space-2); } [data-chart="radial"] caption { @@ -557,7 +557,7 @@ color: var(--chart-label); text-align: center; caption-side: bottom; - padding-block-start: var(--size-2); + padding-block-start: var(--space-2); } [data-chart="radial"] tbody { display: flex; } @@ -666,7 +666,7 @@ justify-content: flex-end; flex: 1; block-size: 100%; - gap: var(--size-1); + gap: var(--space-1); } /* Remaining-work bar — red, with ideal line overlay above it */ @@ -693,10 +693,10 @@ color: var(--chart-label); text-align: center; order: 2; - padding-block-start: var(--size-1); + padding-block-start: var(--space-1); white-space: nowrap; padding: 0; - margin-block-start: var(--size-2); + margin-block-start: var(--space-2); } /* ── Spacing modifiers for area and line (port from bar/column) ──── */ @@ -749,7 +749,7 @@ [data-chart="bar"][data-chart-labels] thead { display: block; - margin-block-end: var(--size-2); + margin-block-end: var(--space-2); } [data-chart="bar"][data-chart-labels] thead th { diff --git a/src/layers/07-chroma.css b/src/layers/07-chroma.css index e3e6628..8acad83 100644 --- a/src/layers/07-chroma.css +++ b/src/layers/07-chroma.css @@ -18,7 +18,7 @@ .chroma pre { background: var(--surface-2); - padding: var(--size-3); + padding: var(--space-4); border-radius: var(--radius-2); overflow-x: auto; margin: 0; @@ -134,5 +134,5 @@ .chroma .lnt { color: var(--text-3); user-select: none; - padding-inline-end: var(--size-3); + padding-inline-end: var(--space-4); } diff --git a/src/layers/08-layout.css b/src/layers/08-layout.css index b298466..17e362d 100644 --- a/src/layers/08-layout.css +++ b/src/layers/08-layout.css @@ -40,7 +40,7 @@ body > section { body { background-color: var(--surface); color: var(--text); - font-weight: var(--font-weight-4); + font-weight: var(--weight-normal); line-height: var(--leading); font-variant-emoji: text; /* render emoji as monochrome glyphs, not OS pictographs */ min-height: 100vh; @@ -202,9 +202,10 @@ nav[data-layout="actions"] a:hover { } } -/* Allow article as content column in docs layout — override body > article container sizing */ +/* Article content column: reading-optimised prose width. + Overrides body > article container sizing from 08-layout.css. */ [data-layout="docs"] > article { - max-width: none; + max-width: var(--width-prose); min-width: 0; } @@ -299,7 +300,7 @@ nav[data-layout="actions"] a:hover { [data-layout="stats"] .value { font-family: var(--font-mono); font-size: var(--text-3xl); - font-weight: var(--font-weight-7); + font-weight: var(--weight-bold); color: var(--accent); display: block; } @@ -349,7 +350,7 @@ article[data-layout="prose"], left: 0.6rem; top: 0.5rem; bottom: 0.5rem; - width: var(--border-size-1); + width: var(--border-width); background: var(--border); } diff --git a/src/layers/08a-essay.css b/src/layers/08a-essay.css index 2e1e612..d2e884e 100644 --- a/src/layers/08a-essay.css +++ b/src/layers/08a-essay.css @@ -23,7 +23,7 @@ article[data-paper] > header { article[data-paper] > header h1 { font-size: clamp(1.6rem, 4vw, 2.4rem); - font-weight: var(--font-weight-3); + font-weight: var(--weight-light); letter-spacing: -0.02em; line-height: 1.15; margin-bottom: var(--space-4); diff --git a/src/layers/09-landing.css b/src/layers/09-landing.css index a2a2b9c..6f49e9f 100644 --- a/src/layers/09-landing.css +++ b/src/layers/09-landing.css @@ -44,7 +44,7 @@ [data-layout="hero"] h1 { font-size: clamp(2.6rem, 6vw, 4.5rem); - font-weight: var(--font-weight-2); + font-weight: var(--weight-light); letter-spacing: -0.025em; line-height: 1.05; margin-bottom: var(--space-4); diff --git a/src/main.css b/src/main.css index 2303e92..6fef13b 100644 --- a/src/main.css +++ b/src/main.css @@ -12,7 +12,7 @@ /* 2. Framework layers */ @import "./layers/00-reset.css"; -@import "./layers/01-asw.css"; +@import "./layers/01-tokens.css"; @import "./layers/02-semantic.css"; @import "./layers/03-components.css"; @import "./layers/04-data-attrs.css"; From 9ace9ea2bb251b9a3ab460fbbe1930c93da35221 Mon Sep 17 00:00:00 2001 From: Ludo Date: Sat, 11 Apr 2026 15:29:35 +0200 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20CSS=20tasks=207-9=20=E2=80=94?= =?UTF-8?q?=20split=20components=20into=20landmarks,=20forms,=20navigation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract from monolithic 03-components.css: - 03-landmarks.css: nav, article, section, hgroup, dt/dd, footer - 04-forms.css: buttons, inputs, selects, checkboxes, validation - 06-navigation.css: sidebar nav, TOC aside 03-components.css retains: accordion, dialog, breadcrumb, steps. All files will be renumbered to final scheme in next task. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/layers/03-components.css | 670 +---------------------------------- src/layers/03-landmarks.css | 328 +++++++++++++++++ src/layers/04-forms.css | 250 +++++++++++++ src/layers/06-navigation.css | 96 +++++ src/main.css | 3 + 5 files changed, 683 insertions(+), 664 deletions(-) create mode 100644 src/layers/03-landmarks.css create mode 100644 src/layers/04-forms.css create mode 100644 src/layers/06-navigation.css diff --git a/src/layers/03-components.css b/src/layers/03-components.css index f89a6b4..3156d03 100644 --- a/src/layers/03-components.css +++ b/src/layers/03-components.css @@ -1,585 +1,16 @@ /** - * 03-components.css - * UI component patterns (buttons, forms, nav, dialog, details) + * 03-components.css → will become 05-components.css in Task 10 + * Compound UI patterns: accordion, dialog, breadcrumb, steps. * Part of: Agentic Semantic Web * - * Ported from: Pico CSS v2.1.1 - * License: MIT - * - * Modernizations: - * - Uses `accent-color` for checkbox/radio (simpler than background-image) - * - Drops class-based button variants (.secondary, .contrast, .outline) + * Buttons/forms extracted to 04-forms.css + * Landmarks extracted to 03-landmarks.css + * Sidebar/TOC extracted to 06-navigation.css */ -/* ── Buttons ───────────────────────────────────────────────────────────*/ - -button { - margin: 0; - overflow: visible; - font-family: inherit; - text-transform: none; -} - -button, -[type=submit], -[type=reset], -[type=button], -[role=button] { - - - - display: inline-block; - padding: var(--input-py) var(--input-px); - border: var(--border-width) solid var(--border); - border-radius: var(--radius-md); - outline: none; - background-color: var(--surface); - color: var(--text); - font-weight: var(--weight-normal); - font-size: var(--text-base); - line-height: var(--leading); - text-align: center; - text-decoration: none; - cursor: pointer; - user-select: none; - transition: background-color var(--ease), - border-color var(--ease), - color var(--ease); -} - -button:is(:hover, :active, :focus-visible), -[type=submit]:is(:hover, :active, :focus-visible), -[type=reset]:is(:hover, :active, :focus-visible), -[type=button]:is(:hover, :active, :focus-visible), -[role=button]:is(:hover, :active, :focus-visible) { - background-color: var(--surface-hover); - border-color: var(--border); - color: var(--text); -} - -button:focus-visible, -[type=submit]:focus-visible, -[type=reset]:focus-visible, -[type=button]:focus-visible, -[role=button]:focus-visible { - box-shadow: 0 0 0 var(--outline-width) var(--accent-focus); -} - -button[disabled], -[type=submit][disabled], -[type=reset][disabled], -[type=button][disabled], -[role=button][disabled] { - opacity: 0.5; - pointer-events: none; -} - -/* ── Form Elements ─────────────────────────────────────────────────────*/ - -input, -optgroup, -select, -textarea { - margin: 0; - font-size: var(--text-base); - line-height: var(--leading); - font-family: inherit; - letter-spacing: inherit; -} - -fieldset { - width: 100%; - margin: 0; - margin-bottom: var(--space-4); - padding: 0; - border: 0; -} - -fieldset legend, -label { - display: block; - margin-bottom: calc(var(--space-4) * 0.375); - color: var(--text); - font-weight: var(--weight-normal); -} - -input:not([type=checkbox], [type=radio], [type=range], [type=file]), -select, -textarea { - width: 100%; - padding: var(--input-py) var(--input-px); - border: var(--border-width) solid var(--input-border); - border-radius: var(--radius-md); - outline: none; - background-color: var(--input-bg); - color: var(--text); - font-weight: var(--weight-normal); - transition: background-color var(--ease), - border-color var(--ease), - color var(--ease); -} - -input:not([type=checkbox], [type=radio], [type=range], [type=file], [readonly]):is(:active, :focus-visible), -select:not([readonly]):is(:active, :focus-visible), -textarea:not([readonly]):is(:active, :focus-visible) { - border-color: var(--accent); - background-color: var(--input-active-bg); -} - -input:not([type=checkbox], [type=radio], [type=range], [type=file], [readonly]):focus-visible, -select:not([readonly]):focus-visible, -textarea:not([readonly]):focus-visible { - box-shadow: 0 0 0 var(--outline-width) var(--accent); -} - -input:not([type=checkbox], [type=radio], [type=range], [type=file])[disabled], -select[disabled], -textarea[disabled] { - opacity: var(--disabled-opacity); - pointer-events: none; -} - -input::placeholder, -textarea::placeholder, -select:invalid { - color: var(--text-3); - opacity: 1; -} - -input:not([type=checkbox], [type=radio]), -select, -textarea { - margin-bottom: var(--space-4); -} - -/* ── Select Dropdown ───────────────────────────────────────────────────*/ - -select:not([multiple], [size]) { - padding-right: calc(var(--input-px) + 1.5rem); - background-image: var(--icon-chevron); - background-position: center right 0.75rem; - background-size: 1rem auto; - background-repeat: no-repeat; -} - -select[multiple] option:checked { - background: var(--input-selected); - color: var(--text); -} - -/* ── Textarea ──────────────────────────────────────────────────────────*/ - -textarea { - display: block; - resize: vertical; -} - -/* ── Checkboxes & Radios (Modern CSS) ──────────────────────────────────*/ - -label:has([type=checkbox], [type=radio]) { - width: fit-content; - cursor: pointer; -} - -[type=checkbox], -[type=radio] { - width: 1.25em; - height: 1.25em; - margin-top: -0.125em; - margin-right: 0.5em; - vertical-align: middle; - cursor: pointer; - - /* Modern CSS: use browser's native styling with our accent color */ - accent-color: var(--accent); -} - -[type=checkbox] ~ label, -[type=radio] ~ label { - display: inline-block; - margin-bottom: 0; - cursor: pointer; -} - -[type=checkbox] ~ label:not(:last-of-type), -[type=radio] ~ label:not(:last-of-type) { - margin-right: 1em; -} - -/* ── Validation States ─────────────────────────────────────────────────*/ - -input[aria-invalid=false], -select[aria-invalid=false], -textarea[aria-invalid=false] { - border-color: var(--accent); -} - -input[aria-invalid=false]:is(:active, :focus-visible), -select[aria-invalid=false]:is(:active, :focus-visible), -textarea[aria-invalid=false]:is(:active, :focus-visible) { - border-color: var(--accent-hover); - box-shadow: 0 0 0 var(--outline-width) var(--accent-focus) !important; -} - -input[aria-invalid=true], -select[aria-invalid=true], -textarea[aria-invalid=true] { - border-color: var(--error); -} - -input[aria-invalid=true]:is(:active, :focus-visible), -select[aria-invalid=true]:is(:active, :focus-visible), -textarea[aria-invalid=true]:is(:active, :focus-visible) { - border-color: var(--error-active); - box-shadow: 0 0 0 var(--outline-width) var(--error-focus) !important; -} - -/* ── Helper Text ───────────────────────────────────────────────────────*/ - -:where(input, select, textarea, fieldset) + small { - display: block; - width: 100%; - margin-top: calc(var(--space-4) * -0.75); - margin-bottom: var(--space-4); - color: var(--text-3); -} - -:where(input, select, textarea, fieldset)[aria-invalid=false] + small { - color: var(--accent); -} - -:where(input, select, textarea, fieldset)[aria-invalid=true] + small { - color: var(--accent-red); -} - -label > :where(input, select, textarea) { - margin-top: calc(var(--space-4) * 0.25); -} - -/* ── Navigation ────────────────────────────────────────────────────────*/ -/* Semantic nav: */ - -/* Nav content centered at --width-xl without a wrapper element. - max() falls back to --container-padding on narrow viewports. */ -body > nav { - padding-inline: max(var(--container-padding), calc((100% - var(--width-xl)) / 2)); -} - -body > nav { - display: flex; - justify-content: space-between; - align-items: center; - padding-top: var(--space-5); - padding-bottom: var(--space-5); - - margin-bottom: var(--space-6); - border-bottom: var(--border-width) solid var(--border); -} - -body > nav strong { - font-family: var(--font-mono); - font-weight: 700; - font-size: var(--text-base); - letter-spacing: -0.03em; -} - -body > nav ul { - list-style: none; - display: flex; - gap: 0; - margin: 0; - padding: 0; - font-family: var(--font-mono); - font-size: var(--text-sm); -} - -body > nav ul li { - list-style: none; - margin: 0; - padding: 0; -} - -body > nav ul li + li::before { - content: "|"; - color: var(--text-dim); - margin: 0 0.75rem; -} - -body > nav a { - color: var(--text-2); - text-decoration: none; - transition: color var(--ease); -} - -body > nav a:hover, -body > nav a[aria-current="page"] { - color: var(--text); -} - -/* Medium screens: allow links to wrap */ -@media (--nav-compact) { - body > nav ul { - flex-wrap: wrap; - gap: 0.25rem 0; - } -} - -/* Small screens: stack brand above links */ -@media (--md-n-below) { - body > nav { - flex-direction: column; - align-items: flex-start; - gap: var(--space-2); - } - - body > nav ul:last-child { - flex-wrap: wrap; - } - - body > nav ul:last-child li + li::before { - display: none; - } -} - -/* ── Nav Dropdown ──────────────────────────────────────────────────────*/ -/*
inside