diff --git a/src/layers/01-tokens.css b/src/layers/01-asw.css similarity index 96% rename from src/layers/01-tokens.css rename to src/layers/01-asw.css index 035004d..b73ed12 100644 --- a/src/layers/01-tokens.css +++ b/src/layers/01-asw.css @@ -266,27 +266,6 @@ --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 @@ -416,3 +395,19 @@ @media (--lg-n-above) { html { font-size: 103%; } } @media (--xl-n-above) { html { font-size: 106%; } } @media (--xxl-n-above) { html { font-size: 109%; } } + + +/* ══════════════════════════════════════════════════════════════════ + EDITORIAL DEFAULTS + Opinionated ASW decisions that go beyond tokens — centering, + spacing rhythms, and layout choices that define the ASW look. + ══════════════════════════════════════════════════════════════════ */ + +/* Nav content centered at --width-xl without a wrapper element. + max() falls back to --container-padding on narrow viewports. */ +body > nav { + padding-inline: max(var(--container-padding), calc((100% - var(--width-xl)) / 2)); +} +[data-layout="docs"] > article { + max-width: var(--width-prose); +} diff --git a/src/layers/02-typography.css b/src/layers/02-semantic.css similarity index 98% rename from src/layers/02-typography.css rename to src/layers/02-semantic.css index f3391e2..3c93523 100644 --- a/src/layers/02-typography.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(--weight-normal); + font-weight: var(--font-weight-4); } /* ── Typography: Lists ─────────────────────────────────────────────── */ @@ -158,7 +158,7 @@ ul { margin-bottom: var(--type-space); color: var(--text); font-style: normal; - font-weight: var(--weight-normal); + font-weight: var(--font-weight-4); } :where(ol, ul) li { @@ -225,7 +225,7 @@ del { } abbr[title] { - border-bottom: var(--border-width) dotted; + border-bottom: var(--border-size-1) dotted; text-decoration: none; cursor: help; } @@ -297,7 +297,7 @@ small { text-indent: 0; color: var(--text); font-style: normal; - font-weight: var(--weight-normal); + font-weight: var(--font-weight-4); } th, @@ -306,14 +306,14 @@ td { border-bottom: var(--border-width) solid var(--border); background-color: transparent; color: var(--text); - font-weight: var(--weight-normal); + font-weight: var(--font-weight-4); text-align: left; } thead th, thead td { font-weight: 600; - border-bottom-width: var(--focus-ring-width); + border-bottom-width: var(--border-size-2); } tfoot th, @@ -339,7 +339,7 @@ samp { border-radius: var(--radius-md); background: var(--surface-1); color: var(--code-color); - font-weight: var(--weight-normal); + font-weight: var(--font-weight-4); line-height: initial; } @@ -471,10 +471,10 @@ pre[class*="language-"] { .token.important, .token.variable { color: var(--syntax-variable); - font-weight: var(--weight-medium); + font-weight: var(--font-weight-5); } -.token.bold { font-weight: var(--weight-bold); } +.token.bold { font-weight: var(--font-weight-7); } .token.italic { font-style: italic; } /* Light mode overrides */ diff --git a/src/layers/03-components.css b/src/layers/03-components.css new file mode 100644 index 0000000..f27fa01 --- /dev/null +++ b/src/layers/03-components.css @@ -0,0 +1,1045 @@ +/** + * 03-components.css + * UI component patterns (buttons, forms, nav, dialog, details) + * Part of: Agentic Semantic Web + * + * Ported from: Pico CSS v2.1.1 + * License: MIT + * + * Modernizations: + * - Uses `accent-color` for checkbox/radio (simpler than background-image) + * - Drops class-based button variants (.secondary, .contrast, .outline) + */ + +/* ── 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(--font-weight-4); + 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(--font-weight-4); +} + +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(--font-weight-4); + 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: */ + +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