Dead code removed: - 05-utilities: grid-2/card-grid/stats block (superseded by 08-layout) - 02-semantic: dialog min-width:100% (conflicted with 03-components) - 02-semantic: hgroup p dead font-family, redundant nested list margin - All layers: [ai-disclosure] → [data-ai-disclosure] (bug fix) - table.striped → [data-table="striped"] (classless alignment) Ref cleanup: 12 --gray-N/--green-N/--blue-N replaced with semantic tokens. 24 refs marked TODO (syntax highlighting needs --syntax-* aliases).
953 lines
22 KiB
CSS
953 lines
22 KiB
CSS
/**
|
|
* 02-semantic.css
|
|
* Semantic HTML element styles
|
|
* Part of: Agentic Semantic Web
|
|
*
|
|
* Ported from: Pico CSS v2.1.1
|
|
* License: MIT
|
|
*
|
|
* This layer handles typography and semantic HTML elements.
|
|
* Classes are NOT supported—use semantic tags only.
|
|
*/
|
|
|
|
/* ── Typography: Headings ──────────────────────────────────────────── */
|
|
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
margin-top: 0;
|
|
margin-bottom: var(--type-space);
|
|
line-height: var(--leading-tight);
|
|
font-family: var(--font-heading);
|
|
text-wrap: balance;
|
|
}
|
|
|
|
h1 {
|
|
font-size: var(--h1-size);
|
|
color: var(--h1-color);
|
|
font-weight: var(--h1-weight);
|
|
}
|
|
|
|
h2 {
|
|
font-size: var(--h2-size);
|
|
color: var(--h2-color);
|
|
font-weight: var(--h2-weight);
|
|
}
|
|
|
|
h3 {
|
|
font-size: var(--h3-size);
|
|
color: var(--h3-color);
|
|
font-weight: var(--h3-weight);
|
|
}
|
|
|
|
h4 {
|
|
font-size: var(--h4-size);
|
|
color: var(--h4-color);
|
|
font-weight: var(--h4-weight);
|
|
}
|
|
|
|
h5 {
|
|
font-size: var(--h5-size);
|
|
color: var(--h5-color);
|
|
font-weight: var(--h5-weight);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
h6 {
|
|
font-size: var(--h6-size);
|
|
color: var(--h6-color);
|
|
font-weight: var(--h6-weight);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
}
|
|
|
|
/* Add spacing before headings that follow content elements */
|
|
:where(article, address, blockquote, dl, figure, form, ol, p, pre, table, ul) ~ :is(h1, h2, h3, h4, h5, h6) {
|
|
margin-top: var(--type-space-top);
|
|
}
|
|
|
|
/* ── Typography: UI elements — structural, navigational, informational ── */
|
|
/* These override the prose body font with the humanist sans UI stack. */
|
|
|
|
nav,
|
|
header,
|
|
footer,
|
|
label,
|
|
th,
|
|
caption,
|
|
small,
|
|
figcaption,
|
|
button,
|
|
input,
|
|
select,
|
|
textarea {
|
|
font-family: var(--font-ui);
|
|
}
|
|
|
|
/* ── Nav layout ─────────────────────────────────────────────────────── */
|
|
/* Ported from Pico CSS, translated to ASW tokens. */
|
|
|
|
nav {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
overflow: visible;
|
|
}
|
|
|
|
nav ul {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 0;
|
|
padding: 0;
|
|
margin: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
nav li {
|
|
display: inline-block;
|
|
margin: 0;
|
|
padding: var(--space-2) var(--space-3);
|
|
}
|
|
|
|
nav li a {
|
|
display: inline-block;
|
|
text-decoration: none;
|
|
color: var(--text);
|
|
padding: var(--space-2) var(--space-3);
|
|
margin: calc(var(--space-2) * -1) calc(var(--space-3) * -1);
|
|
border-radius: var(--radius-sm);
|
|
}
|
|
|
|
nav li a:hover {
|
|
color: var(--accent);
|
|
background: var(--surface-hover);
|
|
}
|
|
|
|
nav li strong,
|
|
nav li b {
|
|
color: var(--text);
|
|
}
|
|
|
|
@media (--md-n-below) {
|
|
nav { flex-wrap: wrap; gap: var(--space-2); }
|
|
nav ul { flex-wrap: wrap; gap: var(--space-1); }
|
|
}
|
|
|
|
/* ── Typography: Paragraphs ────────────────────────────────────────── */
|
|
|
|
p {
|
|
margin-top: 0;
|
|
margin-bottom: var(--type-space);
|
|
color: var(--text);
|
|
font-style: normal;
|
|
font-weight: var(--font-weight-4);
|
|
}
|
|
|
|
/* ── Typography: Lists ─────────────────────────────────────────────── */
|
|
|
|
address,
|
|
dl,
|
|
ol,
|
|
ul {
|
|
margin-top: 0;
|
|
margin-bottom: var(--type-space);
|
|
color: var(--text);
|
|
font-style: normal;
|
|
font-weight: var(--font-weight-4);
|
|
}
|
|
|
|
:where(ol, ul) li {
|
|
margin-bottom: calc(var(--type-space) * 0.25);
|
|
}
|
|
|
|
/* Nested lists: reduce spacing */
|
|
:where(dl, ol, ul) :where(dl, ol, ul) {
|
|
margin-top: calc(var(--type-space) * 0.25);
|
|
}
|
|
|
|
ul li {
|
|
list-style: square;
|
|
}
|
|
|
|
/* ── Typography: Blockquote ────────────────────────────────────────── */
|
|
|
|
blockquote {
|
|
display: block;
|
|
margin: var(--type-space) 0;
|
|
padding: var(--space-4);
|
|
border-right: none;
|
|
border-left: var(--space-1) solid var(--border);
|
|
border-inline-start: var(--space-1) solid var(--border);
|
|
border-inline-end: none;
|
|
}
|
|
|
|
blockquote footer {
|
|
margin-top: calc(var(--type-space) * 0.5);
|
|
color: var(--text-3);
|
|
}
|
|
|
|
/* ── Typography: Horizontal Rule ───────────────────────────────────── */
|
|
|
|
hr {
|
|
height: 0;
|
|
margin: var(--type-space) 0;
|
|
border: 0;
|
|
border-top: var(--border-width) solid var(--border);
|
|
color: inherit;
|
|
}
|
|
|
|
/* ── Typography: Inline Elements ───────────────────────────────────── */
|
|
|
|
b,
|
|
strong {
|
|
font-weight: bolder;
|
|
}
|
|
|
|
mark {
|
|
padding: 0.125rem 0.25rem;
|
|
background-color: var(--mark-bg);
|
|
color: var(--mark-color);
|
|
vertical-align: baseline;
|
|
}
|
|
|
|
ins {
|
|
color: var(--text-2);
|
|
text-decoration: none;
|
|
}
|
|
|
|
del {
|
|
color: var(--accent-red);
|
|
}
|
|
|
|
abbr[title] {
|
|
border-bottom: var(--border-size-1) dotted;
|
|
text-decoration: none;
|
|
cursor: help;
|
|
}
|
|
|
|
sub,
|
|
sup {
|
|
position: relative;
|
|
font-size: 0.75em;
|
|
line-height: 0;
|
|
vertical-align: baseline;
|
|
}
|
|
|
|
sub {
|
|
bottom: -0.25em;
|
|
}
|
|
|
|
sup {
|
|
top: -0.5em;
|
|
}
|
|
|
|
small {
|
|
font-size: 0.875em;
|
|
}
|
|
|
|
/* ── Links ─────────────────────────────────────────────────────────── */
|
|
|
|
:where(a:not([role=button])),
|
|
[role=link] {
|
|
|
|
|
|
|
|
outline: none;
|
|
background-color: transparent;
|
|
color: var(--link);
|
|
text-decoration: underline;
|
|
text-decoration-color: var(--link-underline);
|
|
text-underline-offset: 0.125em;
|
|
transition: background-color var(--ease),
|
|
color var(--ease),
|
|
text-decoration var(--ease),
|
|
box-shadow var(--ease);
|
|
}
|
|
|
|
:where(a:not([role=button])):is(:hover, :active, :focus),
|
|
[role=link]:is(:hover, :active, :focus) {
|
|
color: var(--link-hover);
|
|
text-decoration-color: var(--link-hover-underline);
|
|
}
|
|
|
|
:where(a:not([role=button])):focus-visible,
|
|
[role=link]:focus-visible {
|
|
box-shadow: 0 0 0 var(--outline-width) var(--link-focus);
|
|
}
|
|
|
|
/* ── Text Selection ────────────────────────────────────────────────── */
|
|
|
|
::selection {
|
|
background-color: var(--selection);
|
|
}
|
|
|
|
/* ── Tables ────────────────────────────────────────────────────────── */
|
|
|
|
:where(table) {
|
|
width: 100%;
|
|
margin-top: 0;
|
|
margin-bottom: var(--type-space);
|
|
border-collapse: collapse;
|
|
border-spacing: 0;
|
|
text-indent: 0;
|
|
color: var(--text);
|
|
font-style: normal;
|
|
font-weight: var(--font-weight-4);
|
|
}
|
|
|
|
th,
|
|
td {
|
|
padding: calc(var(--space-4) / 2) var(--space-4);
|
|
border-bottom: var(--border-width) solid var(--border);
|
|
background-color: transparent;
|
|
color: var(--text);
|
|
font-weight: var(--font-weight-4);
|
|
text-align: left;
|
|
}
|
|
|
|
thead th,
|
|
thead td {
|
|
font-weight: 600;
|
|
border-bottom-width: var(--border-size-2);
|
|
}
|
|
|
|
tfoot th,
|
|
tfoot td {
|
|
border-top: var(--border-width) solid var(--border);
|
|
border-bottom: 0;
|
|
}
|
|
|
|
/* Striped tables (class-based but useful) */
|
|
[data-table="striped"] tbody tr:nth-child(odd) th,
|
|
[data-table="striped"] tbody tr:nth-child(odd) td {
|
|
background-color: var(--table-stripe);
|
|
}
|
|
|
|
/* ── Code & Preformatted Text ──────────────────────────────────────── */
|
|
|
|
pre,
|
|
code,
|
|
kbd,
|
|
samp {
|
|
font-size: 0.875em;
|
|
font-family: var(--font-mono);
|
|
border-radius: var(--radius-md);
|
|
background: var(--surface-1);
|
|
color: var(--code-color);
|
|
font-weight: var(--font-weight-4);
|
|
line-height: initial;
|
|
}
|
|
|
|
/* Inline code elements */
|
|
code,
|
|
kbd,
|
|
samp {
|
|
display: inline-block;
|
|
padding: 0.375rem;
|
|
}
|
|
|
|
/* Code blocks */
|
|
pre {
|
|
display: block;
|
|
margin-top: 0;
|
|
margin-bottom: var(--space-4);
|
|
padding: var(--space-4);
|
|
overflow-x: auto;
|
|
-ms-overflow-style: scrollbar;
|
|
}
|
|
|
|
pre > code,
|
|
pre > samp {
|
|
display: block;
|
|
padding: 0;
|
|
background: none;
|
|
font-size: inherit;
|
|
font-family: inherit;
|
|
line-height: var(--leading);
|
|
}
|
|
|
|
/* Keyboard input */
|
|
kbd {
|
|
background-color: var(--kbd-bg);
|
|
color: var(--kbd-color);
|
|
vertical-align: baseline;
|
|
}
|
|
|
|
/* ── Prism.js Syntax Highlighting Theme ────────────────────────────── *
|
|
*
|
|
* These rules style Prism.js token classes using ASW tokens.
|
|
* agentic.css provides the theme; each page loads Prism via:
|
|
*
|
|
* <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css">
|
|
* <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
|
|
* <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
|
|
*
|
|
* The CDN theme's colors are overridden here. ASW tokens handle dark/light.
|
|
* ─────────────────────────────────────────────────────────────────── */
|
|
|
|
/* Reset Prism default background — pre already styled by ASW */
|
|
code[class*="language-"],
|
|
pre[class*="language-"] {
|
|
color: var(--code-color);
|
|
background: none;
|
|
text-shadow: none;
|
|
}
|
|
|
|
pre[class*="language-"] {
|
|
background: var(--surface-1);
|
|
}
|
|
|
|
/* Token colors — dark (default) */
|
|
.token.comment,
|
|
.token.prolog,
|
|
.token.doctype,
|
|
.token.cdata {
|
|
color: var(--gray-6); /* TODO: map to semantic token — no alias for gray-6 (between --text-3: gray-5 and --text-dim: gray-7) */
|
|
font-style: italic;
|
|
}
|
|
|
|
.token.punctuation {
|
|
color: var(--text-3); /* slightly muted */
|
|
}
|
|
|
|
.token.tag,
|
|
.token.deleted {
|
|
color: var(--red-4); /* TODO: map to semantic token — no alias for red-4 (--error=red-7, --callout-error=red-5; syntax highlight needs lighter shade) */
|
|
}
|
|
|
|
.token.attr-name,
|
|
.token.namespace {
|
|
color: var(--yellow-4); /* TODO: map to semantic token — no alias for yellow-4 (--warn=yellow-5 is close but one step darker) */
|
|
}
|
|
|
|
.token.string,
|
|
.token.attr-value,
|
|
.token.char,
|
|
.token.inserted {
|
|
color: var(--accent-hover); /* strings, values — --accent-hover = var(--green-4) */
|
|
}
|
|
|
|
.token.number,
|
|
.token.boolean,
|
|
.token.constant,
|
|
.token.symbol {
|
|
color: var(--orange-4); /* literals */
|
|
}
|
|
|
|
.token.selector,
|
|
.token.builtin {
|
|
color: var(--teal-4); /* CSS selectors, builtins */
|
|
}
|
|
|
|
.token.keyword,
|
|
.token.atrule {
|
|
color: var(--link-hover); /* keywords, @rules — --link-hover = var(--blue-4) */
|
|
}
|
|
|
|
.token.function,
|
|
.token.class-name {
|
|
color: var(--cyan-4); /* function/class names */
|
|
}
|
|
|
|
.token.property {
|
|
color: var(--info); /* object properties — --info = var(--blue-5) */
|
|
}
|
|
|
|
.token.operator,
|
|
.token.entity,
|
|
.token.url {
|
|
color: var(--text-2); /* operators */
|
|
}
|
|
|
|
.token.regex {
|
|
color: var(--orange-5); /* regex literals */
|
|
}
|
|
|
|
.token.important,
|
|
.token.variable {
|
|
color: var(--warn); /* !important, variables — --warn = var(--yellow-5) */
|
|
font-weight: var(--font-weight-5);
|
|
}
|
|
|
|
.token.bold { font-weight: var(--font-weight-7); }
|
|
.token.italic { font-style: italic; }
|
|
|
|
/* Light mode overrides */
|
|
@media (prefers-color-scheme: light) {
|
|
.token.comment,
|
|
.token.prolog,
|
|
.token.doctype,
|
|
.token.cdata { color: var(--gray-6); /* TODO: map to semantic token — no alias for gray-6 in light mode */ }
|
|
|
|
.token.punctuation { color: var(--gray-8); /* TODO: map to semantic token — no alias for gray-8 */ }
|
|
|
|
.token.tag,
|
|
.token.deleted { color: var(--red-8); /* TODO: map to semantic token — no alias for red-8 */ }
|
|
|
|
.token.attr-name,
|
|
.token.namespace { color: var(--yellow-9); /* TODO: map to semantic token — no alias for yellow-9 */ }
|
|
|
|
.token.string,
|
|
.token.attr-value,
|
|
.token.char,
|
|
.token.inserted { color: var(--green-8); /* TODO: map to semantic token — no alias for green-8 */ }
|
|
|
|
.token.number,
|
|
.token.boolean,
|
|
.token.constant,
|
|
.token.symbol { color: var(--orange-8); }
|
|
|
|
.token.selector,
|
|
.token.builtin { color: var(--teal-8); }
|
|
|
|
.token.keyword,
|
|
.token.atrule { color: var(--blue-8); /* TODO: map to semantic token — no alias for blue-8 */ }
|
|
|
|
.token.function,
|
|
.token.class-name { color: var(--cyan-9); }
|
|
|
|
.token.property { color: var(--blue-9); /* TODO: map to semantic token — no alias for blue-9 */ }
|
|
|
|
.token.operator,
|
|
.token.entity,
|
|
.token.url { color: var(--gray-8); /* TODO: map to semantic token — no alias for gray-8 in light mode */ }
|
|
|
|
.token.regex { color: var(--orange-7); }
|
|
|
|
.token.important,
|
|
.token.variable { color: var(--yellow-9); /* TODO: map to semantic token — no alias for yellow-9 */ }
|
|
}
|
|
|
|
/* ── Details / Summary ─────────────────────────────────────────────── */
|
|
|
|
details {
|
|
display: block;
|
|
margin-bottom: var(--space-4);
|
|
}
|
|
|
|
details summary {
|
|
line-height: 1rem;
|
|
list-style-type: none;
|
|
cursor: pointer;
|
|
transition: color var(--ease);
|
|
color: var(--accent);
|
|
}
|
|
|
|
/* Hide browser default marker */
|
|
details summary::-webkit-details-marker {
|
|
display: none;
|
|
}
|
|
|
|
details summary::marker {
|
|
display: none;
|
|
}
|
|
|
|
details summary::-moz-list-bullet {
|
|
list-style-type: none;
|
|
}
|
|
|
|
/* CSS-drawn chevron using Unicode character ▸ (U+25B8) */
|
|
details summary::after {
|
|
content: "▸";
|
|
display: inline-block;
|
|
width: 1rem;
|
|
height: 1rem;
|
|
margin-inline-start: calc(var(--space-4, 1rem) * 0.5);
|
|
float: right;
|
|
font-size: var(--text-sm);
|
|
line-height: 1rem;
|
|
text-align: center;
|
|
color: var(--text-3);
|
|
transform: rotate(90deg); /* Point down when closed */
|
|
transition: transform var(--ease);
|
|
}
|
|
|
|
details summary:focus {
|
|
outline: none;
|
|
}
|
|
|
|
details summary:focus-visible {
|
|
outline: var(--outline-width) solid var(--accent-focus);
|
|
outline-offset: calc(var(--space-4, 1rem) * 0.5);
|
|
color: var(--accordion-active);
|
|
}
|
|
|
|
/* Open state */
|
|
details[open] > summary {
|
|
margin-bottom: var(--space-4);
|
|
color: var(--text-3);
|
|
}
|
|
|
|
details[open] > summary::after {
|
|
transform: rotate(180deg); /* Point down when open */
|
|
}
|
|
|
|
/* ── Dialog / Modal ────────────────────────────────────────────────── */
|
|
|
|
dialog {
|
|
display: flex;
|
|
z-index: 999;
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: inherit;
|
|
min-width: auto;
|
|
height: inherit;
|
|
min-height: 100%;
|
|
padding: 0;
|
|
border: 0;
|
|
backdrop-filter: var(--modal-backdrop);
|
|
background-color: var(--modal-overlay);
|
|
color: var(--text);
|
|
}
|
|
|
|
dialog > article {
|
|
width: 100%;
|
|
max-height: calc(100vh - var(--space-4) * 2);
|
|
margin: var(--space-4);
|
|
overflow: auto;
|
|
}
|
|
|
|
/* Responsive max-widths for modal content */
|
|
@media (--sm-n-above) {
|
|
dialog > article {
|
|
max-width: var(--width-sm);
|
|
}
|
|
}
|
|
|
|
@media (--md-n-above) {
|
|
dialog > article {
|
|
max-width: var(--width-md);
|
|
}
|
|
}
|
|
|
|
/* Modal header */
|
|
dialog > article > header > * {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
dialog > article > header .close,
|
|
dialog > article > header :is(a, button)[rel=prev] {
|
|
margin: 0;
|
|
margin-left: var(--space-4);
|
|
padding: 0;
|
|
float: right;
|
|
}
|
|
|
|
/* Modal footer */
|
|
dialog > article > footer {
|
|
text-align: right;
|
|
}
|
|
|
|
dialog > article > footer button,
|
|
dialog > article > footer [role=button] {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
dialog > article > footer button:not(:first-of-type),
|
|
dialog > article > footer [role=button]:not(:first-of-type) {
|
|
margin-left: calc(var(--space-4) * 0.5);
|
|
}
|
|
|
|
/* Close button: Unicode ✕ (U+2715) instead of SVG */
|
|
dialog > article .close,
|
|
dialog > article :is(a, button)[rel=prev] {
|
|
display: block;
|
|
width: 1.5rem;
|
|
height: 1.5rem;
|
|
margin-top: calc(var(--space-4) * -0.5);
|
|
margin-bottom: var(--space-4);
|
|
margin-left: auto;
|
|
border: none;
|
|
background-color: transparent;
|
|
color: var(--text-3);
|
|
font-size: 1.5rem;
|
|
line-height: 1;
|
|
text-align: center;
|
|
opacity: 0.5;
|
|
transition: opacity var(--ease);
|
|
cursor: pointer;
|
|
}
|
|
|
|
dialog > article .close::before,
|
|
dialog > article :is(a, button)[rel=prev]::before {
|
|
content: "✕"; /* Unicode heavy multiplication X */
|
|
}
|
|
|
|
dialog > article .close:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
|
|
dialog > article :is(a, button)[rel=prev]:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Hidden state */
|
|
dialog:not([open]),
|
|
dialog[open=false] {
|
|
display: none;
|
|
}
|
|
|
|
/* Body scroll lock when modal is open */
|
|
.modal-is-open {
|
|
padding-right: var(--scrollbar-width, 0px);
|
|
overflow: hidden;
|
|
pointer-events: none;
|
|
touch-action: none;
|
|
}
|
|
|
|
.modal-is-open dialog {
|
|
pointer-events: auto;
|
|
touch-action: auto;
|
|
}
|
|
|
|
/* Animations (only if motion is not reduced) */
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
:where(.modal-is-opening, .modal-is-closing) dialog,
|
|
:where(.modal-is-opening, .modal-is-closing) dialog > article {
|
|
animation-duration: var(--duration-moderate-1);
|
|
animation-timing-function: ease-in-out;
|
|
animation-fill-mode: both;
|
|
}
|
|
|
|
:where(.modal-is-opening, .modal-is-closing) dialog {
|
|
animation-duration: var(--duration-gentle-2);
|
|
animation-name: modal-overlay;
|
|
}
|
|
|
|
:where(.modal-is-opening, .modal-is-closing) dialog > article {
|
|
animation-delay: var(--duration-moderate-1);
|
|
animation-name: modal;
|
|
}
|
|
|
|
.modal-is-closing dialog,
|
|
.modal-is-closing dialog > article {
|
|
animation-delay: 0s;
|
|
animation-direction: reverse;
|
|
}
|
|
|
|
@keyframes modal-overlay {
|
|
from {
|
|
backdrop-filter: none;
|
|
background-color: transparent;
|
|
}
|
|
}
|
|
|
|
@keyframes modal {
|
|
from {
|
|
transform: translateY(-100%);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Respect reduced motion: instant show/hide */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
dialog,
|
|
dialog > article {
|
|
animation: none !important;
|
|
transition: none !important;
|
|
}
|
|
}
|
|
|
|
/* ── Figure & Figcaption ───────────────────────────────────────────── */
|
|
|
|
figure {
|
|
display: block;
|
|
margin: 0;
|
|
margin-bottom: var(--space-4);
|
|
padding: 0;
|
|
}
|
|
|
|
figure figcaption {
|
|
padding: calc(var(--space-4) * 0.5) 0;
|
|
color: var(--text-3);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
/* ── Progress ──────────────────────────────────────────────────────── */
|
|
|
|
progress {
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
appearance: none;
|
|
display: inline-block;
|
|
vertical-align: baseline;
|
|
width: 100%;
|
|
height: 0.5rem;
|
|
margin-bottom: calc(var(--space-4) * 0.5);
|
|
overflow: hidden;
|
|
border: 0;
|
|
border-radius: var(--radius-md);
|
|
background-color: var(--track-bg);
|
|
color: var(--accent);
|
|
}
|
|
|
|
progress::-webkit-progress-bar {
|
|
border-radius: var(--radius-md);
|
|
background: none;
|
|
}
|
|
|
|
progress[value]::-webkit-progress-value {
|
|
background-color: var(--accent);
|
|
transition: inline-size var(--ease);
|
|
}
|
|
|
|
progress::-moz-progress-bar {
|
|
background-color: var(--accent);
|
|
}
|
|
|
|
/* Indeterminate progress (animated) - respect motion preferences */
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
progress:indeterminate {
|
|
background: var(--track-bg)
|
|
linear-gradient(to right,
|
|
var(--accent) 30%,
|
|
var(--track-bg) 30%)
|
|
top left / 150% 150% no-repeat;
|
|
animation: progress-indeterminate calc(var(--duration-gentle-2) * 2) linear infinite;
|
|
}
|
|
|
|
progress:indeterminate[value]::-webkit-progress-value {
|
|
background-color: transparent;
|
|
}
|
|
|
|
@keyframes progress-indeterminate {
|
|
0% {
|
|
background-position: 200% 0;
|
|
}
|
|
100% {
|
|
background-position: -200% 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
progress:indeterminate {
|
|
background: var(--track-bg);
|
|
}
|
|
}
|
|
|
|
/* ── Meter ─────────────────────────────────────────────────────────── */
|
|
|
|
meter {
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
appearance: none;
|
|
display: inline-block;
|
|
vertical-align: baseline;
|
|
width: 100%;
|
|
height: 0.5rem;
|
|
margin-bottom: calc(var(--space-4) * 0.5);
|
|
overflow: hidden;
|
|
border: 0;
|
|
border-radius: var(--radius-md);
|
|
background-color: var(--track-bg);
|
|
accent-color: var(--accent); /* Modern CSS: browser renders with our accent */
|
|
}
|
|
|
|
/* Webkit meter styling */
|
|
meter::-webkit-meter-bar {
|
|
border-radius: var(--radius-md);
|
|
background-color: var(--track-bg);
|
|
}
|
|
|
|
meter::-webkit-meter-optimum-value {
|
|
background-color: var(--accent);
|
|
}
|
|
|
|
meter::-webkit-meter-suboptimum-value {
|
|
background-color: var(--accent-blue);
|
|
}
|
|
|
|
meter::-webkit-meter-even-less-good-value {
|
|
background-color: var(--accent-red); /* Red-ish for bad values */
|
|
}
|
|
|
|
/* Firefox meter styling */
|
|
meter::-moz-meter-bar {
|
|
border-radius: var(--radius-md);
|
|
background-color: var(--accent);
|
|
}
|
|
|
|
meter:-moz-meter-optimum::-moz-meter-bar {
|
|
background-color: var(--accent);
|
|
}
|
|
|
|
meter:-moz-meter-sub-optimum::-moz-meter-bar {
|
|
background-color: var(--accent-blue);
|
|
}
|
|
|
|
meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
|
|
background-color: var(--accent-red);
|
|
}
|
|
|
|
/* ── Content Container ─────────────────────────────────────────────── */
|
|
/* body > nav, body > main, and body > footer share container alignment so agents
|
|
can write <body><nav>…<main>…<footer> and get consistent widths.
|
|
Scoped to body > nav/main/footer to avoid affecting nested elements
|
|
(breadcrumbs, pagination, mains inside grid layouts). */
|
|
|
|
body > nav,
|
|
body > main,
|
|
body > footer {
|
|
width: 100%;
|
|
margin-right: auto;
|
|
margin-left: auto;
|
|
padding-right: var(--space-4);
|
|
padding-left: var(--space-4);
|
|
}
|
|
|
|
/* Default: constrained container (replaces .container class) */
|
|
@media (--sm-n-above) {
|
|
body > nav,
|
|
body > main:not([data-layout="fluid"]),
|
|
body > footer {
|
|
max-width: var(--width-sm);
|
|
padding-right: 0;
|
|
padding-left: 0;
|
|
}
|
|
}
|
|
|
|
@media (--md-n-above) {
|
|
body > nav,
|
|
body > main:not([data-layout="fluid"]),
|
|
body > footer {
|
|
max-width: var(--width-md);
|
|
}
|
|
}
|
|
|
|
@media (--lg-n-above) {
|
|
body > nav,
|
|
body > main:not([data-layout="fluid"]),
|
|
body > footer {
|
|
max-width: var(--width-lg);
|
|
}
|
|
}
|
|
|
|
@media (--xl-n-above) {
|
|
body > nav,
|
|
body > main:not([data-layout="fluid"]),
|
|
body > footer {
|
|
max-width: var(--width-xl);
|
|
}
|
|
}
|
|
|
|
@media (--xxl-n-above) {
|
|
body > nav,
|
|
body > main:not([data-layout="fluid"]),
|
|
body > footer {
|
|
max-width: var(--width-2xl);
|
|
}
|
|
}
|
|
|
|
/* Full-width opt-out */
|
|
body > main[data-layout="fluid"] {
|
|
max-width: none;
|
|
}
|