@tangle-network/charts 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -121,3 +121,11 @@ Intervals arrive with their recorded bounds, confidence level and method; neithe
121
121
  Optional annotations carry independent recorded facts, such as all checks passing.
122
122
  Hover or focus a mark for its value, observation count, interval and annotation.
123
123
  The data table retains missing positions and full labels.
124
+
125
+ ### Plots without visible report controls
126
+
127
+ Use `renderFigure(figure, noteNumber, { presentation: "plot" })` to show the responsive plot alone.
128
+ The complete data table remains available to assistive technology.
129
+ This presentation has no visible finding, method text, disclosure or table control.
130
+ Vertical plot axes use larger tick labels.
131
+ The existing report and chart presentations keep their output and paper behavior.
package/dist/figure.css CHANGED
@@ -319,3 +319,11 @@
319
319
 
320
320
  .tgc-scalar-table { min-width: 620px; }
321
321
  .tgc-scalar-table tbody th { min-width: 180px; max-width: 260px; }
322
+
323
+ /* Plot presentation keeps the same complete data available to assistive technology. */
324
+ .tgc-accessible-data { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
325
+ .tgc-figure-plot .tgc-vertical > text.tgc-num { font-size: 15px; }
326
+ .tgc-figure-plot .tgc-wide, .tgc-figure-plot .tgc-narrow { overflow-x: auto; }
327
+
328
+ .tgc-figure-plot .tgc-wide-fallback svg { min-width: var(--tgc-fallback-width); }
329
+ .tgc-wide-fallback:focus-visible { outline: 2px solid var(--chart-accent); outline-offset: 2px; }
package/dist/index.d.ts CHANGED
@@ -134,8 +134,8 @@ export declare function isRefusal(value: Figure | Refusal): value is Refusal;
134
134
  //#endregion
135
135
  //#region src/block.d.ts
136
136
  interface RenderFigureOptions {
137
- /** Plot first, with interpretation and source details in a closed disclosure. */
138
- presentation?: "chart";
137
+ /** Chart uses a closed data disclosure; plot keeps only the SVG and accessible data. */
138
+ presentation?: "chart" | "plot";
139
139
  }
140
140
  export declare function renderFigure(f: Figure, noteNumber: number, options?: RenderFigureOptions): string;
141
141
  /** Numbered notes for `figures`, in the order their blocks were numbered (1-based). */
package/dist/index.js CHANGED
@@ -301,6 +301,47 @@ function capitalize(text) {
301
301
  return text.charAt(0).toUpperCase() + text.slice(1);
302
302
  }
303
303
  //#endregion
304
+ //#region src/svg.ts
305
+ /**
306
+ * SVG marks. Every mark carries a class and `figure.css` maps classes to the
307
+ * `--chart-*` tokens, so a render holds no colour and follows the page theme.
308
+ * Geometry stays in attributes, so an SVG shown without the stylesheet keeps
309
+ * its layout.
310
+ */
311
+ const r2 = (n) => Math.round(n * 100) / 100;
312
+ function svgRoot(width, height, inner) {
313
+ const h = Math.ceil(height);
314
+ return `<svg class="tgc-svg" xmlns="http://www.w3.org/2000/svg" width="${width}" height="${h}" viewBox="0 0 ${width} ${h}" aria-hidden="true" focusable="false">${inner}</svg>`;
315
+ }
316
+ /** A horizontal bar anchored at `x`, square at the baseline, 4 px round at the data end. */
317
+ function hbar(x, y, w, h, cls) {
318
+ if (w <= 0) return "";
319
+ const r = Math.min(4, h / 2, w);
320
+ return `<path class="${cls}" d="M${r2(x)} ${r2(y)}h${r2(w - r)}a${r} ${r} 0 0 1 ${r} ${r}v${r2(h - 2 * r)}a${r} ${r} 0 0 1 -${r} ${r}h-${r2(w - r)}z"/>`;
321
+ }
322
+ function rect(x, y, w, h, cls, extra = "") {
323
+ if (w <= 0 || h <= 0) return "";
324
+ return `<rect class="${cls}" x="${r2(x)}" y="${r2(y)}" width="${r2(w)}" height="${r2(h)}"${extra ? ` ${extra}` : ""}/>`;
325
+ }
326
+ function line(x1, y1, x2, y2, cls) {
327
+ return `<line class="${cls}" x1="${r2(x1)}" y1="${r2(y1)}" x2="${r2(x2)}" y2="${r2(y2)}"/>`;
328
+ }
329
+ function circle(cx, cy, r, cls) {
330
+ return `<circle class="${cls}" cx="${r2(cx)}" cy="${r2(cy)}" r="${r}"/>`;
331
+ }
332
+ function polyline(points, cls) {
333
+ return `<polyline class="${cls}" points="${points.map(([x, y]) => `${r2(x)},${r2(y)}`).join(" ")}"/>`;
334
+ }
335
+ function text(x, y, value, o = {}) {
336
+ const anchor = o.anchor && o.anchor !== "start" ? ` text-anchor="${o.anchor}"` : "";
337
+ const weight = o.weight === 600 ? ` font-weight="600"` : "";
338
+ return `<text class="${o.cls ?? "tgc-ink"}" x="${r2(x)}" y="${r2(y)}" font-size="${o.size ?? 12}"${anchor}${weight}>${esc(value)}</text>`;
339
+ }
340
+ /** A group whose `<title>` is the hover text for everything inside it. */
341
+ function titled(title, inner) {
342
+ return `<g><title>${esc(title)}</title>${inner}</g>`;
343
+ }
344
+ //#endregion
304
345
  //#region src/block.ts
305
346
  /**
306
347
  * The figure block: one markup for every figure on every surface.
@@ -312,10 +353,18 @@ function capitalize(text) {
312
353
  */
313
354
  const slug = (id) => id.replace(/[^a-z0-9-]+/gi, "-").toLowerCase();
314
355
  function renderFigure(f, noteNumber, options = {}) {
315
- if (options.presentation !== void 0 && options.presentation !== "chart") throw new Error("renderFigure: unknown presentation.");
356
+ if (options.presentation !== void 0 && options.presentation !== "chart" && options.presentation !== "plot") throw new Error("renderFigure: unknown presentation.");
316
357
  const id = slug(f.id);
317
358
  const plotLabel = `${f.finding} ${f.lede}`;
318
359
  const narrow = f.svg.narrow ? `<div class="tgc-narrow">${f.svg.narrow}</div>` : `<div class="tgc-narrow tgc-narrow-table">${f.table}</div>`;
360
+ if (options.presentation === "plot") {
361
+ const phonePlot = f.svg.narrow ? `<div class="tgc-narrow">${f.svg.narrow}</div>` : `<div class="tgc-narrow tgc-wide-fallback" role="region" aria-label="${esc(f.finding)} chart" tabindex="0" style="--tgc-fallback-width:720px">${f.svg.wide}</div>`;
362
+ return [
363
+ `<figure class="tgc-figure tgc-figure-chart tgc-figure-plot" id="fig-${id}" aria-label="${esc(f.finding)}">`,
364
+ `<div class="tgc-plot" role="${f.svg.interactive ? "group" : "img"}" aria-label="${esc(plotLabel)}"><div class="tgc-wide">${f.svg.wide}</div>${phonePlot}</div>`,
365
+ `<div class="tgc-accessible-data">${f.table}</div></figure>`
366
+ ].join("");
367
+ }
319
368
  if (options.presentation === "chart") return [
320
369
  `<figure class="tgc-figure tgc-figure-chart" id="fig-${id}" aria-label="${esc(f.finding)}">`,
321
370
  `<div class="tgc-plot" id="ref-${noteNumber}" role="group" aria-label="${esc(plotLabel)}"><div class="tgc-wide">${f.svg.wide}</div>${narrow}</div>`,
@@ -359,47 +408,6 @@ function renderRefusals(refusals) {
359
408
  return `<ul class="tgc-refusals">${refusals.map((r) => `<li>${esc(r.refused)}</li>`).join("")}</ul>`;
360
409
  }
361
410
  //#endregion
362
- //#region src/svg.ts
363
- /**
364
- * SVG marks. Every mark carries a class and `figure.css` maps classes to the
365
- * `--chart-*` tokens, so a render holds no colour and follows the page theme.
366
- * Geometry stays in attributes, so an SVG shown without the stylesheet keeps
367
- * its layout.
368
- */
369
- const r2 = (n) => Math.round(n * 100) / 100;
370
- function svgRoot(width, height, inner) {
371
- const h = Math.ceil(height);
372
- return `<svg class="tgc-svg" xmlns="http://www.w3.org/2000/svg" width="${width}" height="${h}" viewBox="0 0 ${width} ${h}" aria-hidden="true" focusable="false">${inner}</svg>`;
373
- }
374
- /** A horizontal bar anchored at `x`, square at the baseline, 4 px round at the data end. */
375
- function hbar(x, y, w, h, cls) {
376
- if (w <= 0) return "";
377
- const r = Math.min(4, h / 2, w);
378
- return `<path class="${cls}" d="M${r2(x)} ${r2(y)}h${r2(w - r)}a${r} ${r} 0 0 1 ${r} ${r}v${r2(h - 2 * r)}a${r} ${r} 0 0 1 -${r} ${r}h-${r2(w - r)}z"/>`;
379
- }
380
- function rect(x, y, w, h, cls, extra = "") {
381
- if (w <= 0 || h <= 0) return "";
382
- return `<rect class="${cls}" x="${r2(x)}" y="${r2(y)}" width="${r2(w)}" height="${r2(h)}"${extra ? ` ${extra}` : ""}/>`;
383
- }
384
- function line(x1, y1, x2, y2, cls) {
385
- return `<line class="${cls}" x1="${r2(x1)}" y1="${r2(y1)}" x2="${r2(x2)}" y2="${r2(y2)}"/>`;
386
- }
387
- function circle(cx, cy, r, cls) {
388
- return `<circle class="${cls}" cx="${r2(cx)}" cy="${r2(cy)}" r="${r}"/>`;
389
- }
390
- function polyline(points, cls) {
391
- return `<polyline class="${cls}" points="${points.map(([x, y]) => `${r2(x)},${r2(y)}`).join(" ")}"/>`;
392
- }
393
- function text(x, y, value, o = {}) {
394
- const anchor = o.anchor && o.anchor !== "start" ? ` text-anchor="${o.anchor}"` : "";
395
- const weight = o.weight === 600 ? ` font-weight="600"` : "";
396
- return `<text class="${o.cls ?? "tgc-ink"}" x="${r2(x)}" y="${r2(y)}" font-size="${o.size ?? 12}"${anchor}${weight}>${esc(value)}</text>`;
397
- }
398
- /** A group whose `<title>` is the hover text for everything inside it. */
399
- function titled(title, inner) {
400
- return `<g><title>${esc(title)}</title>${inner}</g>`;
401
- }
402
- //#endregion
403
411
  //#region src/table.ts
404
412
  /** A plain HTML table: the accessible form of a figure and its phone view. */
405
413
  function table(caption, columns, rows) {
@@ -1263,7 +1271,7 @@ function plot$1(costed, unplaced, drawLine, o) {
1263
1271
  //#endregion
1264
1272
  //#region src/css.generated.ts
1265
1273
  /** The figure block and mark styles (src/figure.css), for documents that inline their CSS. */
1266
- const figureCss = "/* @tangle-network/charts — figure block and mark styles.\n *\n * Every colour is a --chart-* token from @tangle-network/brand tokens.css, so a\n * figure follows the page theme. A standalone document without brand tokens\n * embeds `chartTokensCss` first. Fonts fall back to Inter and JetBrains Mono.\n *\n * Each figure carries a 720 px and a 358 px render. The swap follows the\n * figure's own width (a container query), so a narrow column shows the phone\n * render even on a wide screen. */\n\n.tgc-figure {\n margin: 32px 0 0;\n padding: 0;\n max-width: 720px;\n color: var(--chart-ink);\n font-family: var(--font-sans, Inter, ui-sans-serif, system-ui, sans-serif);\n}\n\n.tgc-finding {\n margin: 0 0 8px;\n font-size: 16px;\n line-height: 24px;\n font-weight: 600;\n color: var(--chart-ink);\n}\n\n.tgc-noteref {\n margin-left: 2px;\n font-size: 12px;\n font-weight: 400;\n color: var(--chart-ink-muted);\n text-decoration: none;\n font-family: var(--font-mono, \"JetBrains Mono\", ui-monospace, monospace);\n}\n.tgc-noteref:hover,\n.tgc-noteref:focus-visible {\n color: var(--chart-accent);\n text-decoration: underline;\n}\n\n.tgc-lede {\n margin: 0 0 16px;\n font-size: 14px;\n line-height: 22px;\n color: var(--text-secondary, var(--chart-ink));\n}\n\n.tgc-plot {\n container-type: inline-size;\n}\n.tgc-wide svg,\n.tgc-narrow svg {\n display: block;\n overflow: visible;\n}\n.tgc-narrow {\n display: none;\n}\n.tgc-narrow svg {\n max-width: 100%;\n height: auto;\n}\n@container (max-width: 719.98px) {\n .tgc-wide {\n display: none;\n }\n .tgc-narrow {\n display: block;\n }\n}\n\n.tgc-read {\n margin: 8px 0 0;\n font-size: 12px;\n line-height: 16px;\n color: var(--chart-ink-muted);\n}\n\n.tgc-data {\n margin: 8px 0 0;\n font-size: 12px;\n line-height: 16px;\n}\n.tgc-data > summary {\n cursor: pointer;\n color: var(--chart-ink-muted);\n width: fit-content;\n}\n.tgc-data > summary:hover {\n color: var(--chart-ink);\n}\n.tgc-data[open] > summary {\n margin-bottom: 8px;\n}\n\n.tgc-scroll {\n overflow-x: auto;\n}\n.tgc-scroll:focus-visible {\n outline: 2px solid var(--chart-accent);\n outline-offset: 2px;\n}\n\n.tgc-table {\n border-collapse: collapse;\n min-width: 100%;\n font-size: 12px;\n line-height: 16px;\n color: var(--chart-ink);\n /* A host page's table rules must not restyle the figure's table. */\n border: 0;\n border-radius: 0;\n background: none;\n}\n.tgc-table caption {\n text-align: left;\n padding: 0 0 8px;\n color: var(--chart-ink-muted);\n}\n.tgc-table th,\n.tgc-table td {\n padding: 6px 12px 6px 0;\n border-bottom: 1px solid var(--chart-rule);\n text-align: left;\n vertical-align: top;\n font-weight: 400;\n font-size: inherit;\n color: inherit;\n background: none;\n text-transform: none;\n letter-spacing: normal;\n}\n.tgc-table thead th {\n color: var(--chart-ink-muted);\n white-space: nowrap;\n}\n.tgc-table tbody th {\n position: sticky;\n left: 0;\n background: var(--chart-canvas, var(--depth-1, transparent));\n}\n.tgc-table .tgc-n {\n font-family: var(--font-mono, \"JetBrains Mono\", ui-monospace, monospace);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.tgc-table thead .tgc-n {\n font-family: inherit;\n}\n.tgc-table tbody tr:hover {\n background: var(--chart-shade);\n}\n.tgc-narrow-table .tgc-table {\n display: block;\n overflow-x: auto;\n}\n\n.tgc-notes {\n margin: 16px 0 0;\n padding-left: 20px;\n font-size: 12px;\n line-height: 16px;\n color: var(--chart-ink-muted);\n}\n.tgc-notes li {\n margin: 0 0 8px;\n padding-left: 4px;\n}\n.tgc-notes li:target {\n color: var(--chart-ink);\n}\n.tgc-backlink {\n color: var(--chart-ink-muted);\n text-decoration: none;\n}\n\n.tgc-refusals {\n margin: 8px 0 0;\n padding-left: 20px;\n font-size: 14px;\n line-height: 22px;\n color: var(--chart-ink-muted);\n}\n\n/* Marks */\n.tgc-svg {\n font-family: var(--font-sans, Inter, ui-sans-serif, system-ui, sans-serif);\n}\n.tgc-svg .tgc-num {\n font-family: var(--font-mono, \"JetBrains Mono\", ui-monospace, monospace);\n font-variant-numeric: tabular-nums;\n}\n.tgc-ink {\n fill: var(--chart-ink);\n}\n.tgc-ink-muted {\n fill: var(--chart-ink-muted);\n}\n.tgc-bar,\n.tgc-ci,\n.tgc-pt-front {\n fill: var(--chart-accent);\n}\n.tgc-gridline {\n stroke: var(--chart-grid);\n stroke-width: 1;\n}\n.tgc-rule {\n stroke: var(--chart-rule);\n stroke-width: 1;\n}\n.tgc-axis,\n.tgc-zero {\n stroke: var(--chart-muted);\n stroke-width: 1;\n}\n.tgc-whisker,\n.tgc-tick {\n stroke: var(--chart-ink);\n stroke-width: 1.5;\n stroke-linecap: round;\n}\n.tgc-threshold {\n stroke: var(--chart-ink);\n stroke-width: 1.5;\n stroke-dasharray: 3 3;\n}\n.tgc-front-line {\n fill: none;\n stroke: var(--chart-ink);\n stroke-width: 1.5;\n stroke-linejoin: round;\n}\n.tgc-pt,\n.tgc-open {\n fill: none;\n stroke: var(--chart-muted);\n stroke-width: 1.5;\n}\n.tgc-pt-est {\n fill: none;\n stroke: var(--chart-accent);\n stroke-width: 2;\n}\n.tgc-pt-ci,\n.tgc-strike {\n stroke: var(--chart-muted);\n stroke-width: 1.5;\n}\n.tgc-leader {\n stroke: var(--chart-muted);\n stroke-width: 1;\n}\n.tgc-ci-exact,\n.tgc-dot {\n fill: var(--chart-muted);\n}\n.tgc-dashed {\n stroke-dasharray: 2 2;\n}\n.tgc-tier-c {\n fill: var(--chart-tier-c);\n}\n.tgc-tier-b {\n fill: var(--chart-tier-b);\n}\n.tgc-tier-a {\n fill: var(--chart-tier-a);\n}\n.tgc-tier-s {\n fill: var(--chart-tier-s);\n}\n/* Neutral tint for counts: never the accent, capped at half strength so ink keeps 6:1. */\n.tgc-tint {\n fill: color-mix(in srgb, var(--chart-muted) calc(var(--s, 0) * 50%), transparent);\n}\n\n@media print {\n .tgc-plot {\n container-type: normal;\n }\n .tgc-wide {\n display: block;\n }\n .tgc-narrow {\n display: none;\n }\n .tgc-wide svg {\n width: 100%;\n height: auto;\n }\n .tgc-figure {\n break-inside: avoid;\n }\n}\n\n/* Chart-led surfaces keep supporting text in the native disclosure. */\n.tgc-figure-chart { max-width: none; margin: 0; }\n.tgc-figure-chart .tgc-wide svg { width: 100%; height: auto; }\n.tgc-wide:has(.tgc-vertical), .tgc-narrow:has(.tgc-vertical) { overflow-x: auto; }\n.tgc-vertical { width: 100%; }\n.tgc-narrow .tgc-vertical { max-width: none; }\n.tgc-column-hit { fill: transparent; stroke: transparent; stroke-width: 2; }\n.tgc-column:focus-visible { outline: none; }\n.tgc-column:focus-visible .tgc-column-hit { stroke: var(--chart-accent); }\n.tgc-vertical-bar { fill: var(--chart-accent); }\n/* Identity assets keep their approved colors on a white plate in either theme. */\n.tgc-logo-plate { fill: #fff; stroke: var(--chart-rule); }\n.tgc-column-tip { opacity: 0; pointer-events: none; }\n.tgc-tip-bg { fill: var(--chart-ink); }\n.tgc-tip-ink { fill: var(--chart-canvas); }\n\n.tgc-series-line { fill: none; stroke: var(--chart-accent); stroke-width: 2; stroke-linejoin: round; }\n.tgc-series-point { fill: var(--chart-accent); stroke: var(--chart-canvas); stroke-width: 1; }\n.tgc-series-hit { fill: transparent; stroke: transparent; }\n.tgc-series-observation:focus-visible { outline: none; }\n.tgc-series-observation:focus-visible .tgc-series-hit { stroke: var(--chart-ink); stroke-width: 2; }\n.tgc-series-tip { opacity: 0; pointer-events: none; }\n\n.tgc-scalar-table { min-width: 620px; }\n.tgc-scalar-table tbody th { min-width: 180px; max-width: 260px; }\n";
1274
+ const figureCss = "/* @tangle-network/charts — figure block and mark styles.\n *\n * Every colour is a --chart-* token from @tangle-network/brand tokens.css, so a\n * figure follows the page theme. A standalone document without brand tokens\n * embeds `chartTokensCss` first. Fonts fall back to Inter and JetBrains Mono.\n *\n * Each figure carries a 720 px and a 358 px render. The swap follows the\n * figure's own width (a container query), so a narrow column shows the phone\n * render even on a wide screen. */\n\n.tgc-figure {\n margin: 32px 0 0;\n padding: 0;\n max-width: 720px;\n color: var(--chart-ink);\n font-family: var(--font-sans, Inter, ui-sans-serif, system-ui, sans-serif);\n}\n\n.tgc-finding {\n margin: 0 0 8px;\n font-size: 16px;\n line-height: 24px;\n font-weight: 600;\n color: var(--chart-ink);\n}\n\n.tgc-noteref {\n margin-left: 2px;\n font-size: 12px;\n font-weight: 400;\n color: var(--chart-ink-muted);\n text-decoration: none;\n font-family: var(--font-mono, \"JetBrains Mono\", ui-monospace, monospace);\n}\n.tgc-noteref:hover,\n.tgc-noteref:focus-visible {\n color: var(--chart-accent);\n text-decoration: underline;\n}\n\n.tgc-lede {\n margin: 0 0 16px;\n font-size: 14px;\n line-height: 22px;\n color: var(--text-secondary, var(--chart-ink));\n}\n\n.tgc-plot {\n container-type: inline-size;\n}\n.tgc-wide svg,\n.tgc-narrow svg {\n display: block;\n overflow: visible;\n}\n.tgc-narrow {\n display: none;\n}\n.tgc-narrow svg {\n max-width: 100%;\n height: auto;\n}\n@container (max-width: 719.98px) {\n .tgc-wide {\n display: none;\n }\n .tgc-narrow {\n display: block;\n }\n}\n\n.tgc-read {\n margin: 8px 0 0;\n font-size: 12px;\n line-height: 16px;\n color: var(--chart-ink-muted);\n}\n\n.tgc-data {\n margin: 8px 0 0;\n font-size: 12px;\n line-height: 16px;\n}\n.tgc-data > summary {\n cursor: pointer;\n color: var(--chart-ink-muted);\n width: fit-content;\n}\n.tgc-data > summary:hover {\n color: var(--chart-ink);\n}\n.tgc-data[open] > summary {\n margin-bottom: 8px;\n}\n\n.tgc-scroll {\n overflow-x: auto;\n}\n.tgc-scroll:focus-visible {\n outline: 2px solid var(--chart-accent);\n outline-offset: 2px;\n}\n\n.tgc-table {\n border-collapse: collapse;\n min-width: 100%;\n font-size: 12px;\n line-height: 16px;\n color: var(--chart-ink);\n /* A host page's table rules must not restyle the figure's table. */\n border: 0;\n border-radius: 0;\n background: none;\n}\n.tgc-table caption {\n text-align: left;\n padding: 0 0 8px;\n color: var(--chart-ink-muted);\n}\n.tgc-table th,\n.tgc-table td {\n padding: 6px 12px 6px 0;\n border-bottom: 1px solid var(--chart-rule);\n text-align: left;\n vertical-align: top;\n font-weight: 400;\n font-size: inherit;\n color: inherit;\n background: none;\n text-transform: none;\n letter-spacing: normal;\n}\n.tgc-table thead th {\n color: var(--chart-ink-muted);\n white-space: nowrap;\n}\n.tgc-table tbody th {\n position: sticky;\n left: 0;\n background: var(--chart-canvas, var(--depth-1, transparent));\n}\n.tgc-table .tgc-n {\n font-family: var(--font-mono, \"JetBrains Mono\", ui-monospace, monospace);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.tgc-table thead .tgc-n {\n font-family: inherit;\n}\n.tgc-table tbody tr:hover {\n background: var(--chart-shade);\n}\n.tgc-narrow-table .tgc-table {\n display: block;\n overflow-x: auto;\n}\n\n.tgc-notes {\n margin: 16px 0 0;\n padding-left: 20px;\n font-size: 12px;\n line-height: 16px;\n color: var(--chart-ink-muted);\n}\n.tgc-notes li {\n margin: 0 0 8px;\n padding-left: 4px;\n}\n.tgc-notes li:target {\n color: var(--chart-ink);\n}\n.tgc-backlink {\n color: var(--chart-ink-muted);\n text-decoration: none;\n}\n\n.tgc-refusals {\n margin: 8px 0 0;\n padding-left: 20px;\n font-size: 14px;\n line-height: 22px;\n color: var(--chart-ink-muted);\n}\n\n/* Marks */\n.tgc-svg {\n font-family: var(--font-sans, Inter, ui-sans-serif, system-ui, sans-serif);\n}\n.tgc-svg .tgc-num {\n font-family: var(--font-mono, \"JetBrains Mono\", ui-monospace, monospace);\n font-variant-numeric: tabular-nums;\n}\n.tgc-ink {\n fill: var(--chart-ink);\n}\n.tgc-ink-muted {\n fill: var(--chart-ink-muted);\n}\n.tgc-bar,\n.tgc-ci,\n.tgc-pt-front {\n fill: var(--chart-accent);\n}\n.tgc-gridline {\n stroke: var(--chart-grid);\n stroke-width: 1;\n}\n.tgc-rule {\n stroke: var(--chart-rule);\n stroke-width: 1;\n}\n.tgc-axis,\n.tgc-zero {\n stroke: var(--chart-muted);\n stroke-width: 1;\n}\n.tgc-whisker,\n.tgc-tick {\n stroke: var(--chart-ink);\n stroke-width: 1.5;\n stroke-linecap: round;\n}\n.tgc-threshold {\n stroke: var(--chart-ink);\n stroke-width: 1.5;\n stroke-dasharray: 3 3;\n}\n.tgc-front-line {\n fill: none;\n stroke: var(--chart-ink);\n stroke-width: 1.5;\n stroke-linejoin: round;\n}\n.tgc-pt,\n.tgc-open {\n fill: none;\n stroke: var(--chart-muted);\n stroke-width: 1.5;\n}\n.tgc-pt-est {\n fill: none;\n stroke: var(--chart-accent);\n stroke-width: 2;\n}\n.tgc-pt-ci,\n.tgc-strike {\n stroke: var(--chart-muted);\n stroke-width: 1.5;\n}\n.tgc-leader {\n stroke: var(--chart-muted);\n stroke-width: 1;\n}\n.tgc-ci-exact,\n.tgc-dot {\n fill: var(--chart-muted);\n}\n.tgc-dashed {\n stroke-dasharray: 2 2;\n}\n.tgc-tier-c {\n fill: var(--chart-tier-c);\n}\n.tgc-tier-b {\n fill: var(--chart-tier-b);\n}\n.tgc-tier-a {\n fill: var(--chart-tier-a);\n}\n.tgc-tier-s {\n fill: var(--chart-tier-s);\n}\n/* Neutral tint for counts: never the accent, capped at half strength so ink keeps 6:1. */\n.tgc-tint {\n fill: color-mix(in srgb, var(--chart-muted) calc(var(--s, 0) * 50%), transparent);\n}\n\n@media print {\n .tgc-plot {\n container-type: normal;\n }\n .tgc-wide {\n display: block;\n }\n .tgc-narrow {\n display: none;\n }\n .tgc-wide svg {\n width: 100%;\n height: auto;\n }\n .tgc-figure {\n break-inside: avoid;\n }\n}\n\n/* Chart-led surfaces keep supporting text in the native disclosure. */\n.tgc-figure-chart { max-width: none; margin: 0; }\n.tgc-figure-chart .tgc-wide svg { width: 100%; height: auto; }\n.tgc-wide:has(.tgc-vertical), .tgc-narrow:has(.tgc-vertical) { overflow-x: auto; }\n.tgc-vertical { width: 100%; }\n.tgc-narrow .tgc-vertical { max-width: none; }\n.tgc-column-hit { fill: transparent; stroke: transparent; stroke-width: 2; }\n.tgc-column:focus-visible { outline: none; }\n.tgc-column:focus-visible .tgc-column-hit { stroke: var(--chart-accent); }\n.tgc-vertical-bar { fill: var(--chart-accent); }\n/* Identity assets keep their approved colors on a white plate in either theme. */\n.tgc-logo-plate { fill: #fff; stroke: var(--chart-rule); }\n.tgc-column-tip { opacity: 0; pointer-events: none; }\n.tgc-tip-bg { fill: var(--chart-ink); }\n.tgc-tip-ink { fill: var(--chart-canvas); }\n\n.tgc-series-line { fill: none; stroke: var(--chart-accent); stroke-width: 2; stroke-linejoin: round; }\n.tgc-series-point { fill: var(--chart-accent); stroke: var(--chart-canvas); stroke-width: 1; }\n.tgc-series-hit { fill: transparent; stroke: transparent; }\n.tgc-series-observation:focus-visible { outline: none; }\n.tgc-series-observation:focus-visible .tgc-series-hit { stroke: var(--chart-ink); stroke-width: 2; }\n.tgc-series-tip { opacity: 0; pointer-events: none; }\n\n.tgc-scalar-table { min-width: 620px; }\n.tgc-scalar-table tbody th { min-width: 180px; max-width: 260px; }\n\n/* Plot presentation keeps the same complete data available to assistive technology. */\n.tgc-accessible-data { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }\n.tgc-figure-plot .tgc-vertical > text.tgc-num { font-size: 15px; }\n.tgc-figure-plot .tgc-wide, .tgc-figure-plot .tgc-narrow { overflow-x: auto; }\n\n.tgc-figure-plot .tgc-wide-fallback svg { min-width: var(--tgc-fallback-width); }\n.tgc-wide-fallback:focus-visible { outline: 2px solid var(--chart-accent); outline-offset: 2px; }\n";
1267
1275
  /** --chart-* resolved per theme, for documents without brand tokens: light, dark by preference or [data-theme="dark"], light in print. */
1268
1276
  const chartTokensCss = ":root{--chart-ink:#2d2d2d;--chart-ink-muted:#686868;--chart-muted:#787878;--chart-grid:#f2f2f2;--chart-rule:#d0d0d0;--chart-shade:rgba(76, 63, 198, 0.06);--chart-accent:hsl(246 54% 51%);--chart-tier-c:#9b9ef0;--chart-tier-b:#7c7fe3;--chart-tier-a:#5b5bd6;--chart-tier-s:#272962;--chart-canvas:#ffffff;color-scheme:light}\n@media (prefers-color-scheme: dark){:root:not([data-theme=\"light\"]){--chart-ink:#e6e6e6;--chart-ink-muted:#a5a5a5;--chart-muted:#8e8e8e;--chart-grid:#353535;--chart-rule:#4c4c4c;--chart-shade:rgba(165, 180, 252, 0.07);--chart-accent:#818CF8;--chart-tier-c:#4a4a95;--chart-tier-b:#5b5bd6;--chart-tier-a:#8b87f0;--chart-tier-s:#b1a9ff;--chart-canvas:#161616;color-scheme:dark}}\n:root[data-theme=\"dark\"]{--chart-ink:#e6e6e6;--chart-ink-muted:#a5a5a5;--chart-muted:#8e8e8e;--chart-grid:#353535;--chart-rule:#4c4c4c;--chart-shade:rgba(165, 180, 252, 0.07);--chart-accent:#818CF8;--chart-tier-c:#4a4a95;--chart-tier-b:#5b5bd6;--chart-tier-a:#8b87f0;--chart-tier-s:#b1a9ff;--chart-canvas:#161616;color-scheme:dark}\n@media print{:root,:root:not([data-theme=\"light\"]),:root[data-theme=\"dark\"]{--chart-ink:#2d2d2d;--chart-ink-muted:#686868;--chart-muted:#787878;--chart-grid:#f2f2f2;--chart-rule:#d0d0d0;--chart-shade:rgba(76, 63, 198, 0.06);--chart-accent:hsl(246 54% 51%);--chart-tier-c:#9b9ef0;--chart-tier-b:#7c7fe3;--chart-tier-a:#5b5bd6;--chart-tier-s:#272962;--chart-canvas:#ffffff;color-scheme:light}}";
1269
1277
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/charts",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Benchmark figures as static SVG and HTML tables: ranked rates, cost frontier, comparison intervals, task matrix and breakdown. Draws from producer data and refuses what it cannot draw honestly.",
5
5
  "type": "module",
6
6
  "license": "MIT",