- content/dorveille.md: 'On the Craft of Invisible Systems' - assets/css/: ASW layer system (00-reset through 09-landing + Open Props) - layouts/: baseof, single, list, index — semantic HTML, no classes - hugo.toml: baseURL asw.trentuna.com, PostCSS + minify pipeline - package.json: postcss-import, postcss-custom-media, cssnano - .gitignore: excludes public/, node_modules, build artifacts Site builds to public/ via hugo --minify. nginx serves public/ statically.
274 lines
7.5 KiB
CSS
274 lines
7.5 KiB
CSS
/**
|
|
* 05-utilities.css
|
|
* Utility patterns (layout helpers, text modifiers, responsive utilities)
|
|
* Part of: Agentic Semantic Web
|
|
*/
|
|
|
|
@layer utilities {
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════
|
|
Text utilities
|
|
══════════════════════════════════════════════════════════════════════════ */
|
|
|
|
[data-text~="mono"] {
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
[data-text~="dim"] {
|
|
color: var(--text-3);
|
|
}
|
|
|
|
[data-text~="accent"] {
|
|
color: var(--accent);
|
|
}
|
|
|
|
[data-text~="small"] {
|
|
font-size: var(--text-xs);
|
|
}
|
|
|
|
/* Eyebrow — small monospace uppercase accent label above a heading */
|
|
[data-text~="eyebrow"] {
|
|
display: block;
|
|
font-family: var(--font-mono);
|
|
font-size: var(--text-xs);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: var(--accent);
|
|
margin-bottom: var(--space-2);
|
|
}
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════
|
|
Layout utilities
|
|
══════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/* Max-width content column — constrains fluid sections to readable width */
|
|
[data-wrap] {
|
|
max-width: var(--width-content);
|
|
margin-inline: auto;
|
|
padding-inline: var(--space-5);
|
|
}
|
|
|
|
/* Grid layout with responsive stacking */
|
|
[data-layout="grid-2"] {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 1rem;
|
|
}
|
|
|
|
@media (--md-n-below) {
|
|
[data-layout="grid-2"] {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
/* Card grid — responsive wrap for article cards */
|
|
[data-layout="card-grid"] {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
[data-layout="card-grid"] > * {
|
|
flex: 1 1 calc(50% - 0.75rem);
|
|
min-width: var(--size-px-13);
|
|
}
|
|
|
|
@media (--md-n-below) {
|
|
[data-layout="card-grid"] > * {
|
|
flex-basis: 100%;
|
|
}
|
|
}
|
|
|
|
/* Stats bar — horizontal row of key-value metrics */
|
|
[data-layout="stats"] {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0;
|
|
}
|
|
|
|
[data-layout="stats"] > * {
|
|
flex: 1 1 0;
|
|
min-width: 5rem;
|
|
padding: 0.75rem 0;
|
|
text-align: center;
|
|
border-right: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
[data-layout="stats"] > *:last-child {
|
|
border-right: none;
|
|
}
|
|
|
|
[data-layout="stats"] .value {
|
|
display: block;
|
|
font-family: var(--font-mono);
|
|
font-size: 1.5rem;
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
[data-layout="stats"] .label {
|
|
display: block;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.65rem;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--text-3);
|
|
margin-top: 0.2rem;
|
|
}
|
|
|
|
@media (--sm-n-below) {
|
|
[data-layout="stats"] > * {
|
|
flex-basis: 33%;
|
|
border-right: none;
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
}
|
|
}
|
|
|
|
/* Inline definition lists */
|
|
dl[data-layout="inline"] {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 0.15rem 1rem;
|
|
align-items: baseline;
|
|
}
|
|
|
|
dl[data-layout="inline"] dt,
|
|
dl[data-layout="inline"] dd {
|
|
margin: 0;
|
|
padding: 0;
|
|
margin-inline-start: 0;
|
|
}
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════
|
|
Responsive visibility
|
|
══════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/* Hide on mobile */
|
|
[data-visible="desktop"] {
|
|
display: none;
|
|
}
|
|
|
|
@media (--md-n-above) {
|
|
[data-visible="desktop"] {
|
|
display: initial;
|
|
}
|
|
}
|
|
|
|
/* Hide on desktop */
|
|
[data-visible="mobile"] {
|
|
display: initial;
|
|
}
|
|
|
|
@media (--md-n-above) {
|
|
[data-visible="mobile"] {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════
|
|
Loading indicator — aria-busy
|
|
Usage: <button aria-busy="true">Loading…</button>
|
|
<section aria-busy="true">Content loading…</section>
|
|
══════════════════════════════════════════════════════════════════════════ */
|
|
|
|
@keyframes spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
[aria-busy="true"] {
|
|
cursor: progress;
|
|
}
|
|
|
|
/* Inline spinner before text in buttons and interactive elements */
|
|
:is(button, [role="button"], a)[aria-busy="true"]::before {
|
|
content: "";
|
|
display: inline-block;
|
|
width: 1em;
|
|
height: 1em;
|
|
margin-right: 0.5em;
|
|
vertical-align: -0.125em;
|
|
border: var(--border-size-2) solid currentColor;
|
|
border-top-color: transparent;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
/* Disable interaction on busy buttons */
|
|
:is(button, [role="button"])[aria-busy="true"] {
|
|
pointer-events: none;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
/* Block-level busy: overlay spinner centered */
|
|
:is(section, article, main, div)[aria-busy="true"] {
|
|
position: relative;
|
|
min-height: 3rem;
|
|
}
|
|
|
|
:is(section, article, main, div)[aria-busy="true"]::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
width: 1.5rem;
|
|
height: 1.5rem;
|
|
margin: -0.75rem 0 0 -0.75rem;
|
|
border: 2px solid var(--text-3);
|
|
border-top-color: transparent;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
/* Spinner rotation — guarded: skip for users who prefer reduced motion */
|
|
@media (--motionOK) {
|
|
:is(button, [role="button"], a)[aria-busy="true"]::before {
|
|
animation: spin var(--spinner-duration) linear infinite;
|
|
}
|
|
|
|
:is(section, article, main, div)[aria-busy="true"]::after {
|
|
animation: spin var(--spinner-duration) linear infinite;
|
|
}
|
|
}
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════
|
|
Accessibility enhancements
|
|
══════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/* Disable all transitions and animations for reduced motion preference */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
scroll-behavior: auto !important;
|
|
}
|
|
}
|
|
|
|
/* Increase contrast for high-contrast preference */
|
|
@media (prefers-contrast: more) {
|
|
:root {
|
|
--border-color: var(--gray-10);
|
|
--border-color-subtle: var(--gray-12);
|
|
--text-primary: var(--gray-0);
|
|
--text-secondary: var(--gray-3);
|
|
--border-width: var(--border-size-2);
|
|
}
|
|
|
|
/* Thicker borders on interactive elements */
|
|
a,
|
|
button,
|
|
input,
|
|
select,
|
|
textarea,
|
|
[data-wikilink] {
|
|
border-width: var(--border-size-2);
|
|
}
|
|
|
|
/* Stronger focus indicators */
|
|
:focus-visible {
|
|
outline-width: var(--border-size-3);
|
|
outline-offset: var(--border-size-3);
|
|
}
|
|
}
|
|
|
|
} /* end @layer utilities */
|