Add dorveille article and full Hugo site scaffold
- 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.
This commit is contained in:
parent
a899f13ae6
commit
880a17f33a
24 changed files with 7315 additions and 0 deletions
761
assets/css/layers/06-charts.css
Normal file
761
assets/css/layers/06-charts.css
Normal file
|
|
@ -0,0 +1,761 @@
|
|||
/**
|
||||
* 06-charts.css
|
||||
* Data-driven charts from semantic HTML tables.
|
||||
* Absorbed from Charts.css — class API converted to data-attributes.
|
||||
*
|
||||
* Core vocabulary:
|
||||
* data-chart="bar|column|line|area|pie" — chart type
|
||||
* data-chart-labels — show axis labels (thead)
|
||||
* data-chart-spacing="1–5" — gap between bars (default 2)
|
||||
* data-chart-stacked — stacked multi-dataset mode
|
||||
* style="--size: 0.8" — data injection on <td> (legal exception)
|
||||
* style="--color: #hex" — per-row color override on <tr>
|
||||
*
|
||||
* Pragmatic exception: style="--size: N" and style="--color: X" on table cells
|
||||
* are DATA injection, not presentation — they bind numeric values to CSS.
|
||||
* This is the one place ASW permits inline style attributes.
|
||||
*
|
||||
* Chart dimensions:
|
||||
* --chart-height Bar chart: bar thickness. Column chart: chart height.
|
||||
* --chart-bar-size Column chart: bar width.
|
||||
* --chart-gap Gap between data points.
|
||||
*
|
||||
* Lineage: Charts.css (MIT) — converted class API to data-attribute API.
|
||||
* Reference: chartscss.org
|
||||
*/
|
||||
|
||||
@layer charts {
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Shared chart tokens
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart] {
|
||||
|
||||
/* Data series colors — cycle via nth-child in each chart type */
|
||||
--chart-color-1: var(--accent); /* green */
|
||||
--chart-color-2: var(--accent-blue); /* blue */
|
||||
--chart-color-3: var(--accent-orange); /* orange */
|
||||
--chart-color-4: var(--accent-red); /* red */
|
||||
--chart-color-5: var(--purple-5, #ae3ec9);
|
||||
--chart-color-6: var(--cyan-5, #15aabf);
|
||||
--chart-color-7: var(--pink-5, #e64980);
|
||||
--chart-color-8: var(--teal-5, #0ca678);
|
||||
|
||||
/* Layout */
|
||||
--chart-height: 200px; /* column chart area height */
|
||||
--chart-bar-size: 2rem; /* column bar width / bar chart bar height */
|
||||
--chart-gap: 6px; /* spacing between data points */
|
||||
|
||||
/* Axis / labels */
|
||||
--chart-axis: var(--border);
|
||||
--chart-axis-width: 2px;
|
||||
--chart-label: var(--text-3);
|
||||
--chart-label-size: var(--text-xs);
|
||||
|
||||
/* Bar styling */
|
||||
--chart-radius: var(--radius-2);
|
||||
|
||||
/* Reset table styles — <table> is presentational structure here */
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
[data-chart] caption {
|
||||
display: block;
|
||||
font-size: var(--text-sm);
|
||||
color: var(--text-3);
|
||||
text-align: start;
|
||||
padding-block-end: var(--size-3);
|
||||
caption-side: top;
|
||||
}
|
||||
|
||||
/* thead: hidden by default, shown with data-chart-labels */
|
||||
[data-chart] thead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-chart][data-chart-labels] thead {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* tbody: each chart type overrides this */
|
||||
[data-chart] tbody {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Bar chart — horizontal bars
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Structure:
|
||||
<table data-chart="bar">
|
||||
<caption>Title</caption>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Label</th>
|
||||
<td style="--size: 0.8">80%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
The bar width = 100% × --size. Bar is a ::before pseudo on td.
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="bar"] tbody {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--chart-gap);
|
||||
|
||||
/* Left axis line */
|
||||
border-inline-start: var(--chart-axis-width) solid var(--chart-axis);
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
[data-chart="bar"] tr {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--size-3);
|
||||
}
|
||||
|
||||
/* Row label (th) */
|
||||
[data-chart="bar"] th[scope="row"] {
|
||||
font-size: var(--chart-label-size);
|
||||
font-weight: 400;
|
||||
color: var(--chart-label);
|
||||
min-inline-size: 5rem;
|
||||
max-inline-size: 8rem;
|
||||
text-align: end;
|
||||
padding-block: 0;
|
||||
padding-inline: var(--size-2) 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Data cell — the track */
|
||||
[data-chart="bar"] td {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
block-size: var(--chart-bar-size);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* The bar itself — ::before */
|
||||
[data-chart="bar"] td::before {
|
||||
content: "";
|
||||
display: block;
|
||||
block-size: 100%;
|
||||
inline-size: calc(100% * var(--size, 0.5));
|
||||
background: var(--color, var(--chart-color-1));
|
||||
border-radius: 0 var(--chart-radius) var(--chart-radius) 0;
|
||||
transition: opacity var(--ease), inline-size var(--duration-moderate-1) var(--ease-3, ease-out);
|
||||
}
|
||||
|
||||
[data-chart="bar"] td:hover::before {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Data label (text inside/after bar) */
|
||||
[data-chart="bar"] td::after {
|
||||
content: attr(data-value);
|
||||
position: absolute;
|
||||
inset-inline-start: calc(100% * var(--size, 0.5) + 0.35rem);
|
||||
font-size: var(--chart-label-size);
|
||||
color: var(--text-3);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Color cycling for multi-series */
|
||||
[data-chart="bar"] tr:nth-child(1) td::before { background: var(--color, var(--chart-color-1)); }
|
||||
[data-chart="bar"] tr:nth-child(2) td::before { background: var(--color, var(--chart-color-2)); }
|
||||
[data-chart="bar"] tr:nth-child(3) td::before { background: var(--color, var(--chart-color-3)); }
|
||||
[data-chart="bar"] tr:nth-child(4) td::before { background: var(--color, var(--chart-color-4)); }
|
||||
[data-chart="bar"] tr:nth-child(5) td::before { background: var(--color, var(--chart-color-5)); }
|
||||
[data-chart="bar"] tr:nth-child(6) td::before { background: var(--color, var(--chart-color-6)); }
|
||||
[data-chart="bar"] tr:nth-child(7) td::before { background: var(--color, var(--chart-color-7)); }
|
||||
[data-chart="bar"] tr:nth-child(8) td::before { background: var(--color, var(--chart-color-8)); }
|
||||
[data-chart="bar"] tr:nth-child(n+9) td::before { background: var(--color, var(--chart-color-1)); }
|
||||
|
||||
/* ── Spacing modifiers ──────────────────────────────────── */
|
||||
[data-chart="bar"][data-chart-spacing="1"] tbody { gap: 2px; }
|
||||
[data-chart="bar"][data-chart-spacing="2"] tbody { gap: 6px; }
|
||||
[data-chart="bar"][data-chart-spacing="3"] tbody { gap: 10px; }
|
||||
[data-chart="bar"][data-chart-spacing="4"] tbody { gap: 16px; }
|
||||
[data-chart="bar"][data-chart-spacing="5"] tbody { gap: 24px; }
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Column chart — vertical bars
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Structure:
|
||||
<table data-chart="column">
|
||||
<caption>Title</caption>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Jan</th>
|
||||
<td style="--size: 0.6">60</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
The chart area is --chart-height. Each column height = --chart-height × --size.
|
||||
Columns sit at the bottom of the chart area (flex-end alignment).
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="column"] tbody {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
gap: var(--chart-gap);
|
||||
block-size: var(--chart-height);
|
||||
border-block-end: var(--chart-axis-width) solid var(--chart-axis);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[data-chart="column"] tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
block-size: 100%;
|
||||
gap: var(--size-1);
|
||||
}
|
||||
|
||||
/* Column label (th) at the bottom */
|
||||
[data-chart="column"] th[scope="row"] {
|
||||
font-size: var(--chart-label-size);
|
||||
font-weight: 400;
|
||||
color: var(--chart-label);
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-inline-size: 100%;
|
||||
padding: 0;
|
||||
padding-block-start: var(--size-1);
|
||||
/* Move below axis */
|
||||
order: 2;
|
||||
margin-block-start: var(--size-2);
|
||||
}
|
||||
|
||||
/* Data cell — the column bar */
|
||||
[data-chart="column"] td {
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
block-size: calc(var(--chart-height) * var(--size, 0.5));
|
||||
padding: 0;
|
||||
order: 1;
|
||||
transition: block-size var(--duration-moderate-1) var(--ease-3, ease-out);
|
||||
border-radius: var(--chart-radius) var(--chart-radius) 0 0;
|
||||
}
|
||||
|
||||
/* Color cycling for columns */
|
||||
[data-chart="column"] tr:nth-child(1) td { background: var(--color, var(--chart-color-1)); }
|
||||
[data-chart="column"] tr:nth-child(2) td { background: var(--color, var(--chart-color-2)); }
|
||||
[data-chart="column"] tr:nth-child(3) td { background: var(--color, var(--chart-color-3)); }
|
||||
[data-chart="column"] tr:nth-child(4) td { background: var(--color, var(--chart-color-4)); }
|
||||
[data-chart="column"] tr:nth-child(5) td { background: var(--color, var(--chart-color-5)); }
|
||||
[data-chart="column"] tr:nth-child(6) td { background: var(--color, var(--chart-color-6)); }
|
||||
[data-chart="column"] tr:nth-child(7) td { background: var(--color, var(--chart-color-7)); }
|
||||
[data-chart="column"] tr:nth-child(8) td { background: var(--color, var(--chart-color-8)); }
|
||||
[data-chart="column"] tr:nth-child(n+9) td { background: var(--color, var(--chart-color-1)); }
|
||||
|
||||
[data-chart="column"] td:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* ── Spacing modifiers ──────────────────────────────────── */
|
||||
[data-chart="column"][data-chart-spacing="1"] tbody { gap: 2px; }
|
||||
[data-chart="column"][data-chart-spacing="2"] tbody { gap: 6px; }
|
||||
[data-chart="column"][data-chart-spacing="3"] tbody { gap: 12px; }
|
||||
[data-chart="column"][data-chart-spacing="4"] tbody { gap: 20px; }
|
||||
[data-chart="column"][data-chart-spacing="5"] tbody { gap: 32px; }
|
||||
|
||||
/* ── Column chart labels ───────────────────────────────── */
|
||||
/* When data-chart-labels present, show thead as axis header */
|
||||
[data-chart="column"][data-chart-labels] thead {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-block-end: var(--size-2);
|
||||
}
|
||||
|
||||
[data-chart="column"][data-chart-labels] thead th {
|
||||
font-size: var(--chart-label-size);
|
||||
color: var(--chart-label);
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Area chart — filled area from baseline
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CSS-only area charts use linear-gradient on the td background.
|
||||
Each point's area = --size fraction of the column height.
|
||||
|
||||
Structure identical to column — but cells connect visually.
|
||||
The visual connection requires identical widths and no gap (or clip).
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="area"] tbody {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
block-size: var(--chart-height);
|
||||
border-block-end: var(--chart-axis-width) solid var(--chart-axis);
|
||||
gap: 0; /* no gap — cells must connect */
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[data-chart="area"] tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
[data-chart="area"] th[scope="row"] {
|
||||
font-size: var(--chart-label-size);
|
||||
font-weight: 400;
|
||||
color: var(--chart-label);
|
||||
text-align: center;
|
||||
order: 2;
|
||||
padding-block-start: var(--size-1);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Area cell — filled gradient from --size down to baseline */
|
||||
[data-chart="area"] td {
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
block-size: calc(var(--chart-height) * var(--size, 0.5));
|
||||
padding: 0;
|
||||
order: 1;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
var(--chart-color-1) 0%,
|
||||
color-mix(in oklch, var(--chart-color-1), transparent 70%) 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Line chart — dots connected by a visual line
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CSS-only: we use the column approach but mark the top with a dot (::after)
|
||||
and use a border-top line to simulate connection between points.
|
||||
True line interpolation requires JavaScript or SVG.
|
||||
|
||||
What we ship: column bars in outline/transparent mode with an accent dot
|
||||
at the top — semantic, readable, no JS.
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="line"] tbody {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
block-size: var(--chart-height);
|
||||
border-block-end: var(--chart-axis-width) solid var(--chart-axis);
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[data-chart="line"] tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
[data-chart="line"] th[scope="row"] {
|
||||
font-size: var(--chart-label-size);
|
||||
font-weight: 400;
|
||||
color: var(--chart-label);
|
||||
text-align: center;
|
||||
order: 2;
|
||||
padding-block-start: var(--size-1);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Line chart cell — transparent bar with accent top border + dot */
|
||||
[data-chart="line"] td {
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
block-size: calc(var(--chart-height) * var(--size, 0.5));
|
||||
padding: 0;
|
||||
order: 1;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
color-mix(in oklch, var(--chart-color-1), transparent 80%) 0%,
|
||||
transparent 60%
|
||||
);
|
||||
border-block-start: 2px solid var(--chart-color-1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Dot at data point */
|
||||
[data-chart="line"] td::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
inset-block-start: -5px;
|
||||
inset-inline-start: 50%;
|
||||
translate: -50% 0;
|
||||
inline-size: 8px;
|
||||
block-size: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--chart-color-1);
|
||||
border: 2px solid var(--surface);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Pie chart — conic-gradient segments
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CSS-only pie charts use conic-gradient on a single element.
|
||||
Each segment's arc = --size × 360deg.
|
||||
Requires stacking values in CSS — not practical to automate per-row.
|
||||
|
||||
For agent use: pie charts work best with explicit conic-gradient
|
||||
set as a custom property. The data-chart="pie" wrapper provides
|
||||
the shape and size; the agent sets --pie-segments.
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="pie"] {
|
||||
--pie-size: min(200px, 100%);
|
||||
--pie-segments: conic-gradient(
|
||||
var(--chart-color-1) 0% 25%,
|
||||
var(--chart-color-2) 25% 50%,
|
||||
var(--chart-color-3) 50% 75%,
|
||||
var(--chart-color-4) 75% 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* Pie uses a generated element — hide table structure visually */
|
||||
[data-chart="pie"] tbody { display: none; }
|
||||
|
||||
/* Show caption + legend from thead */
|
||||
[data-chart="pie"] thead {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--size-2);
|
||||
justify-content: center;
|
||||
margin-block-end: var(--size-3);
|
||||
}
|
||||
|
||||
[data-chart="pie"] thead th {
|
||||
font-size: var(--chart-label-size);
|
||||
color: var(--chart-label);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* The pie rendered as ::before on the table element */
|
||||
[data-chart="pie"]::before {
|
||||
content: "";
|
||||
display: block;
|
||||
inline-size: var(--pie-size);
|
||||
block-size: var(--pie-size);
|
||||
border-radius: 50%;
|
||||
background: var(--pie-segments);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Stacked bars — data-chart-stacked modifier
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
When multiple <td> in one <tr>, stack them.
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="bar"][data-chart-stacked] td {
|
||||
/* Multiple tds per row — share the bar track inline */
|
||||
display: inline-block;
|
||||
inline-size: calc(100% * var(--size, 0.2));
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
[data-chart="bar"][data-chart-stacked] td::before {
|
||||
display: none; /* td IS the bar in stacked mode */
|
||||
}
|
||||
|
||||
[data-chart="bar"][data-chart-stacked] td:first-of-type {
|
||||
border-radius: 0 0 0 0;
|
||||
}
|
||||
|
||||
[data-chart="bar"][data-chart-stacked] td:last-of-type {
|
||||
border-radius: 0 var(--chart-radius) var(--chart-radius) 0;
|
||||
}
|
||||
|
||||
/* Stacked color cycling */
|
||||
[data-chart][data-chart-stacked] td:nth-of-type(1) { background: var(--chart-color-1); }
|
||||
[data-chart][data-chart-stacked] td:nth-of-type(2) { background: var(--chart-color-2); }
|
||||
[data-chart][data-chart-stacked] td:nth-of-type(3) { background: var(--chart-color-3); }
|
||||
[data-chart][data-chart-stacked] td:nth-of-type(4) { background: var(--chart-color-4); }
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Accessibility
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
/* Ensure cell content (the data value) is readable for screen readers
|
||||
but visually hidden inside the bar — text is in aria / caption */
|
||||
[data-chart="bar"] td,
|
||||
[data-chart="column"] td {
|
||||
font-size: var(--chart-label-size);
|
||||
color: transparent; /* data visible to SR, hidden visually */
|
||||
}
|
||||
|
||||
/* Respect user preference — no transitions */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
[data-chart] td,
|
||||
[data-chart] td::before {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Radial chart — circular gauge
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Structure:
|
||||
<table data-chart="radial" style="--size: 0.72">
|
||||
<caption>Token budget used</caption>
|
||||
<tbody><tr><td><span>72%</span></td></tr></tbody>
|
||||
</table>
|
||||
|
||||
The gauge is a conic-gradient on the td element.
|
||||
--size (0–1) drives the arc: --size × 360deg = colored portion.
|
||||
::before pseudo creates a donut hole cutout over the gradient.
|
||||
<span> inside td floats the value text above the donut via z-index.
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="radial"] {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--size-2);
|
||||
}
|
||||
|
||||
[data-chart="radial"] caption {
|
||||
font-size: var(--chart-label-size);
|
||||
color: var(--chart-label);
|
||||
text-align: center;
|
||||
caption-side: bottom;
|
||||
padding-block-start: var(--size-2);
|
||||
}
|
||||
|
||||
[data-chart="radial"] tbody { display: flex; }
|
||||
[data-chart="radial"] tr { display: flex; }
|
||||
|
||||
/* The gauge circle */
|
||||
[data-chart="radial"] td {
|
||||
position: relative;
|
||||
width: var(--chart-radial-size);
|
||||
height: var(--chart-radial-size);
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(
|
||||
var(--color, var(--chart-color-1)) 0deg calc(var(--size, 0.5) * 360deg),
|
||||
var(--surface-1, var(--gray-15)) 0deg
|
||||
);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: transparent; /* data readable by SR, hidden visually */
|
||||
}
|
||||
|
||||
/* Donut hole */
|
||||
[data-chart="radial"] td::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: var(--chart-radial-inset);
|
||||
border-radius: 50%;
|
||||
background: var(--surface);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* Value text centered in the donut hole */
|
||||
[data-chart="radial"] td span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: var(--text-xs);
|
||||
font-family: var(--font-mono);
|
||||
color: var(--text);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Status color variants */
|
||||
[data-chart="radial"][data-status="warning"] td {
|
||||
background: conic-gradient(
|
||||
var(--accent-orange, #f08c00) 0deg calc(var(--size, 0.5) * 360deg),
|
||||
var(--surface-1, #111111) 0deg
|
||||
);
|
||||
}
|
||||
|
||||
[data-chart="radial"][data-status="danger"] td {
|
||||
background: conic-gradient(
|
||||
var(--accent-red, #e03131) 0deg calc(var(--size, 0.5) * 360deg),
|
||||
var(--surface-1, #111111) 0deg
|
||||
);
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════════════════════
|
||||
Burndown chart — sprint burndown with CSS ideal-line overlay
|
||||
══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Structure: same as column chart, but:
|
||||
- Bars use --accent-red (remaining work = red)
|
||||
- tbody::after renders a diagonal linear-gradient as the ideal-line
|
||||
- Ideal line runs top-left to bottom-right: full work at start → zero at end
|
||||
|
||||
<table data-chart="burndown">
|
||||
<caption>Sprint burndown</caption>
|
||||
<tbody>
|
||||
<tr><th scope="row">D1</th><td style="--size: 0.95">19</td></tr>
|
||||
...
|
||||
</tbody>
|
||||
</table>
|
||||
══════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
[data-chart="burndown"] tbody {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
block-size: var(--chart-height);
|
||||
border-block-end: var(--chart-axis-width) solid var(--chart-axis);
|
||||
position: relative; /* required for ::after overlay */
|
||||
gap: var(--chart-gap);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Ideal-line overlay — diagonal gradient = ideal burn velocity */
|
||||
[data-chart="burndown"] tbody::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(
|
||||
to bottom right,
|
||||
color-mix(in oklch, var(--chart-color-2, var(--accent-blue, #4dabf7)), transparent 20%) 0%,
|
||||
transparent 100%
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
[data-chart="burndown"] tr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
block-size: 100%;
|
||||
gap: var(--size-1);
|
||||
}
|
||||
|
||||
/* Remaining-work bar — red, with ideal line overlay above it */
|
||||
[data-chart="burndown"] td {
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
block-size: calc(var(--chart-height) * var(--size, 0.5));
|
||||
background: color-mix(in oklch, var(--chart-color-4, var(--accent-red, #e03131)), transparent 25%);
|
||||
border-radius: var(--chart-radius) var(--chart-radius) 0 0;
|
||||
order: 1;
|
||||
padding: 0;
|
||||
border: none;
|
||||
color: transparent;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
transition: opacity var(--ease);
|
||||
}
|
||||
|
||||
[data-chart="burndown"] td:hover { opacity: 0.85; }
|
||||
|
||||
[data-chart="burndown"] th[scope="row"] {
|
||||
font-size: var(--chart-label-size);
|
||||
font-weight: 400;
|
||||
color: var(--chart-label);
|
||||
text-align: center;
|
||||
order: 2;
|
||||
padding-block-start: var(--size-1);
|
||||
white-space: nowrap;
|
||||
padding: 0;
|
||||
margin-block-start: var(--size-2);
|
||||
}
|
||||
|
||||
/* ── Spacing modifiers for area and line (port from bar/column) ──── */
|
||||
|
||||
[data-chart="area"][data-chart-spacing="1"] tbody { gap: 0; }
|
||||
[data-chart="area"][data-chart-spacing="2"] tbody { gap: 2px; }
|
||||
[data-chart="area"][data-chart-spacing="3"] tbody { gap: 6px; }
|
||||
[data-chart="area"][data-chart-spacing="4"] tbody { gap: 12px; }
|
||||
[data-chart="area"][data-chart-spacing="5"] tbody { gap: 20px; }
|
||||
|
||||
[data-chart="line"][data-chart-spacing="1"] tbody { gap: 0; }
|
||||
[data-chart="line"][data-chart-spacing="2"] tbody { gap: 2px; }
|
||||
[data-chart="line"][data-chart-spacing="3"] tbody { gap: 6px; }
|
||||
[data-chart="line"][data-chart-spacing="4"] tbody { gap: 12px; }
|
||||
[data-chart="line"][data-chart-spacing="5"] tbody { gap: 20px; }
|
||||
|
||||
/* ── data-chart-reverse modifier ────────────────────────────────── */
|
||||
|
||||
[data-chart="bar"][data-chart-reverse] tbody {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
[data-chart="column"][data-chart-reverse] tbody {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
/* ── data-chart-stacked on column ───────────────────────────────── */
|
||||
|
||||
[data-chart="column"][data-chart-stacked] tr {
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
[data-chart="column"][data-chart-stacked] td {
|
||||
flex: 1;
|
||||
border-radius: 0;
|
||||
block-size: calc(var(--chart-height) * var(--size, 0.2));
|
||||
}
|
||||
|
||||
[data-chart="column"][data-chart-stacked] td:first-of-type {
|
||||
border-radius: var(--chart-radius) 0 0 0;
|
||||
}
|
||||
|
||||
[data-chart="column"][data-chart-stacked] td:last-of-type {
|
||||
border-radius: 0 var(--chart-radius) 0 0;
|
||||
}
|
||||
|
||||
/* ── data-chart-labels on bar ────────────────────────────────────── */
|
||||
|
||||
[data-chart="bar"][data-chart-labels] thead {
|
||||
display: block;
|
||||
margin-block-end: var(--size-2);
|
||||
}
|
||||
|
||||
[data-chart="bar"][data-chart-labels] thead th {
|
||||
font-size: var(--chart-label-size);
|
||||
color: var(--chart-label);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
} /* end @layer charts */
|
||||
Loading…
Add table
Add a link
Reference in a new issue