@theme-registry/refract 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 +10 -5
- package/dist/build.cjs.js +1 -1
- package/dist/build.cjs.js.map +1 -1
- package/dist/build.esm.js +1 -1
- package/dist/build.esm.js.map +1 -1
- package/dist/cli.js +326 -173
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6114,7 +6114,7 @@ const SECTIONS = [
|
|
|
6114
6114
|
{ id: "type", title: "Type scale", eyebrow: "Typography" },
|
|
6115
6115
|
{ id: "space", title: "Spacing and size", eyebrow: "Space",
|
|
6116
6116
|
note: "There is no separate <code>padding</code> token — spacing <em>is</em> the padding scale, so it is shown both as a measure and as an applied inset." },
|
|
6117
|
-
{ id: "shape", title: "Borders, radius and elevation", eyebrow: "Shape &
|
|
6117
|
+
{ id: "shape", title: "Borders, radius and elevation", eyebrow: "Shape & depth" },
|
|
6118
6118
|
{ id: "motion", title: "Transitions", eyebrow: "Motion" },
|
|
6119
6119
|
{ id: "layout", title: "Breakpoints", eyebrow: "Layout",
|
|
6120
6120
|
note: "These drive the Width control at the top — pick one to reflow the whole specimen at that viewport." },
|
|
@@ -6155,6 +6155,64 @@ function lightnessOf(value) {
|
|
|
6155
6155
|
return undefined;
|
|
6156
6156
|
}
|
|
6157
6157
|
}
|
|
6158
|
+
/** WCAG relative luminance of a hex colour, or `undefined` when it isn't one. */
|
|
6159
|
+
function luminance(value) {
|
|
6160
|
+
const hex = value.trim();
|
|
6161
|
+
if (!/^#[0-9a-f]{6}$/i.test(hex))
|
|
6162
|
+
return undefined;
|
|
6163
|
+
const n = parseInt(hex.slice(1), 16);
|
|
6164
|
+
const ch = (c) => {
|
|
6165
|
+
const v = c / 255;
|
|
6166
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
6167
|
+
};
|
|
6168
|
+
return 0.2126 * ch((n >> 16) & 255) + 0.7152 * ch((n >> 8) & 255) + 0.0722 * ch(n & 255);
|
|
6169
|
+
}
|
|
6170
|
+
/** WCAG contrast ratio between two hex colours, or `undefined` if either isn't parseable. */
|
|
6171
|
+
function contrastRatio(a, b) {
|
|
6172
|
+
const la = luminance(a);
|
|
6173
|
+
const lb = luminance(b);
|
|
6174
|
+
if (la === undefined || lb === undefined)
|
|
6175
|
+
return undefined;
|
|
6176
|
+
return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
|
|
6177
|
+
}
|
|
6178
|
+
function colorProvenance(model) {
|
|
6179
|
+
var _a, _b, _c, _d;
|
|
6180
|
+
const out = new Map();
|
|
6181
|
+
const properties = (_b = (_a = model.subsystems.colors) === null || _a === void 0 ? void 0 : _a.properties) !== null && _b !== void 0 ? _b : {};
|
|
6182
|
+
const mark = (path, ref) => {
|
|
6183
|
+
var _a, _b;
|
|
6184
|
+
if (!ref)
|
|
6185
|
+
return;
|
|
6186
|
+
const derived = ref.ref !== undefined || ref.fn !== undefined || ((_b = (_a = ref.modifiers) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0;
|
|
6187
|
+
out.set(path, derived ? "gen" : "src");
|
|
6188
|
+
};
|
|
6189
|
+
for (const [family, property] of Object.entries(properties)) {
|
|
6190
|
+
mark(`colors.${family}`, property.base);
|
|
6191
|
+
for (const [extra, ref] of Object.entries((_c = property.extras) !== null && _c !== void 0 ? _c : {}))
|
|
6192
|
+
mark(`colors.${family}.${extra}`, ref);
|
|
6193
|
+
for (const [variant, model2] of Object.entries((_d = property.variants) !== null && _d !== void 0 ? _d : {})) {
|
|
6194
|
+
mark(`colors.${family}.${variant}`, model2.base);
|
|
6195
|
+
}
|
|
6196
|
+
}
|
|
6197
|
+
return out;
|
|
6198
|
+
}
|
|
6199
|
+
/**
|
|
6200
|
+
* The masthead wears the theme's own first palette — the one place the chrome takes a hue, and it
|
|
6201
|
+
* takes the theme's rather than asserting one. Falls back to ink when no colour token parses.
|
|
6202
|
+
*/
|
|
6203
|
+
function mastheadColor(leaves) {
|
|
6204
|
+
var _a;
|
|
6205
|
+
const usable = (l) => l.type === "color" && /^#[0-9a-f]{6}$/i.test(String(l.value).trim());
|
|
6206
|
+
// A family's `base` — NOT merely the first colour leaf, which is a ladder rung (`50`) and comes
|
|
6207
|
+
// out near-white. Fall back to any colour only when no family declares a base.
|
|
6208
|
+
const first = (_a = leaves.find(l => usable(l) && l.path[l.path.length - 1] === "base")) !== null && _a !== void 0 ? _a : leaves.find(usable);
|
|
6209
|
+
if (!first)
|
|
6210
|
+
return undefined;
|
|
6211
|
+
const bg = String(first.value).trim();
|
|
6212
|
+
const L = lightnessOf(bg);
|
|
6213
|
+
// A light brand needs dark type on it; anything else takes white.
|
|
6214
|
+
return { bg, fg: L !== undefined && L > 62 ? "#14171c" : "#ffffff" };
|
|
6215
|
+
}
|
|
6158
6216
|
/**
|
|
6159
6217
|
* Which rung the family's `base` LANDS on — never which rung it *is*.
|
|
6160
6218
|
*
|
|
@@ -6181,10 +6239,20 @@ function pxOf(value) {
|
|
|
6181
6239
|
return undefined;
|
|
6182
6240
|
return match[2] === "rem" || match[2] === "em" ? n * 16 : n;
|
|
6183
6241
|
}
|
|
6184
|
-
|
|
6185
|
-
|
|
6242
|
+
/**
|
|
6243
|
+
* Colour, as one CARD per family.
|
|
6244
|
+
*
|
|
6245
|
+
* The flat row-per-token list this replaces gave every family the same weight and let them run
|
|
6246
|
+
* together; a card gives each family an edge, a large base swatch to judge against, and room to
|
|
6247
|
+
* separate what the author WROTE from what refract derived.
|
|
6248
|
+
*/
|
|
6249
|
+
function renderPalette(leaves, model, tokenName) {
|
|
6186
6250
|
var _a, _b, _c;
|
|
6187
|
-
|
|
6251
|
+
const provenance = colorProvenance(model);
|
|
6252
|
+
const tagFor = (path) => {
|
|
6253
|
+
const kind = provenance.get(path);
|
|
6254
|
+
return kind ? `<span class="rfp-tag rfp-${kind}">${kind}</span>` : "";
|
|
6255
|
+
};
|
|
6188
6256
|
const families = new Map();
|
|
6189
6257
|
for (const leaf of leaves) {
|
|
6190
6258
|
const family = (_a = leaf.path[1]) !== null && _a !== void 0 ? _a : "color";
|
|
@@ -6195,63 +6263,80 @@ function renderPalette(leaves, tokenName) {
|
|
|
6195
6263
|
else
|
|
6196
6264
|
families.set(family, [[member, String(leaf.value)]]);
|
|
6197
6265
|
}
|
|
6198
|
-
const
|
|
6199
|
-
const
|
|
6266
|
+
const cards = [];
|
|
6267
|
+
const semantic = [];
|
|
6268
|
+
let total = 0;
|
|
6269
|
+
let passing = 0;
|
|
6200
6270
|
for (const [family, members] of families) {
|
|
6201
|
-
const rungs = members.filter(([name]) => isRung(name));
|
|
6271
|
+
const rungs = members.filter(([name]) => isRung(name)).sort((a, b) => Number(a[0]) - Number(b[0]));
|
|
6202
6272
|
const base = (_b = members.find(([name]) => name === "base")) === null || _b === void 0 ? void 0 : _b[1];
|
|
6273
|
+
const text = (_c = members.find(([name]) => name === "text")) === null || _c === void 0 ? void 0 : _c[1];
|
|
6274
|
+
const path = `colors.${family}`;
|
|
6275
|
+
// The one contrast pairing the author actually declared.
|
|
6276
|
+
if (base && text) {
|
|
6277
|
+
const ratio = contrastRatio(base, text);
|
|
6278
|
+
if (ratio !== undefined) {
|
|
6279
|
+
total += 1;
|
|
6280
|
+
if (ratio >= 4.5)
|
|
6281
|
+
passing += 1;
|
|
6282
|
+
}
|
|
6283
|
+
}
|
|
6203
6284
|
if (rungs.length >= 3) {
|
|
6204
|
-
// A ladder: contiguous rungs read as a ramp in a way a row-per-token list never does.
|
|
6205
|
-
rungs.sort((a, b) => Number(a[0]) - Number(b[0]));
|
|
6206
6285
|
const lands = baseLandsOn(base, rungs);
|
|
6207
6286
|
const strip = rungs
|
|
6208
6287
|
.map(([step, hex]) => {
|
|
6209
6288
|
const isLanding = lands !== undefined && step === lands;
|
|
6210
|
-
return (`<div class="rfp-rung"${isLanding ?
|
|
6289
|
+
return (`<div class="rfp-rung"${isLanding ? " data-lands" : ""}` +
|
|
6211
6290
|
` title="colors.${esc(family)}.${esc(step)} · ${esc(hex)}${isLanding ? " · base lands here" : ""}">` +
|
|
6212
|
-
`<div class="rfp-
|
|
6291
|
+
`<div class="rfp-sw" style="background:${cssValue(hex)}"></div>` +
|
|
6213
6292
|
`<div class="rfp-rung-foot">${esc(step)}</div></div>`);
|
|
6214
6293
|
})
|
|
6215
6294
|
.join("");
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6295
|
+
// Anything that isn't a rung is a declared member — show it with its provenance.
|
|
6296
|
+
const chips = members
|
|
6297
|
+
.filter(([name]) => !isRung(name) && name !== "base")
|
|
6298
|
+
.map(([member, hex]) => chipOf(`${path}.${member}`, member, hex, tagFor(`${path}.${member}`), tokenName))
|
|
6299
|
+
.join("");
|
|
6300
|
+
cards.push(`<section class="rfp-card"><div class="rfp-pal-top">` +
|
|
6301
|
+
`<div class="rfp-pal-base" style="background:${cssValue(base !== null && base !== void 0 ? base : rungs[Math.floor(rungs.length / 2)][1])}"></div>` +
|
|
6302
|
+
`<h3 class="rfp-pal-name">${esc(family)}` +
|
|
6303
|
+
`<small>${base ? `base ${esc(base)}` : ""}${lands ? ` · lands ≈ ${esc(lands)}` : ""} · ${rungs.length} rungs</small>` +
|
|
6304
|
+
idButton(path, tokenName === null || tokenName === void 0 ? void 0 : tokenName(path)) +
|
|
6305
|
+
`</h3></div>` +
|
|
6306
|
+
`<div class="rfp-row-label">Lightness ladder ${tagFor(`${path}.${rungs[0][0]}`) || '<span class="rfp-tag rfp-gen">gen</span>'}</div>` +
|
|
6307
|
+
`<div class="rfp-rungs">${strip}</div>` +
|
|
6308
|
+
(chips ? `<div class="rfp-row-label">Declared members</div><div class="rfp-chips">${chips}</div>` : "") +
|
|
6309
|
+
`</section>`);
|
|
6224
6310
|
continue;
|
|
6225
6311
|
}
|
|
6226
|
-
//
|
|
6227
|
-
//
|
|
6228
|
-
// The contrast readout goes ONLY on the member that genuinely declares the pairing: the family
|
|
6229
|
-
// base against its own `text`. Derived tints (`brand.dark`, `surface.lighter`, …) were never
|
|
6230
|
-
// meant to carry that text, so scoring them produces "fail" badges that read as a defect in the
|
|
6231
|
-
// user's theme when nothing is wrong. On a page whose whole job is to tell the truth about a
|
|
6232
|
-
// theme, inventing a pairing to score is the worst kind of noise.
|
|
6233
|
-
const text = (_c = members.find(([name]) => name === "text")) === null || _c === void 0 ? void 0 : _c[1];
|
|
6312
|
+
// No ladder — the family is a semantic colour (or a small set), so it joins the swatch grid.
|
|
6234
6313
|
for (const [member, hex] of members) {
|
|
6235
6314
|
if (member === "text")
|
|
6236
6315
|
continue;
|
|
6237
6316
|
const isBase = member === "base";
|
|
6238
|
-
const
|
|
6239
|
-
|
|
6240
|
-
pairs.push(`<div class="rfp-pair"><div class="rfp-pair-swatch" data-bg="${esc(hex)}"${paired ? ` data-fg="${esc(paired)}"` : ""}` +
|
|
6241
|
-
` style="background:${cssValue(hex)}${paired ? `;color:${cssValue(paired)}` : ""}">` +
|
|
6242
|
-
(paired ? `<span class="rfp-pair-sample">Aa</span><span class="rfp-pair-ratio"></span>` : "") +
|
|
6243
|
-
`</div><div class="rfp-pair-foot">${idButton(path, tokenName === null || tokenName === void 0 ? void 0 : tokenName(path))}` +
|
|
6244
|
-
`<span class="rfp-hex">${esc(hex)}${paired ? ` on ${esc(paired)}` : ""}</span></div></div>`);
|
|
6317
|
+
const memberPath = isBase ? path : `${path}.${member}`;
|
|
6318
|
+
semantic.push(chipOf(memberPath, isBase ? family : member, hex, tagFor(memberPath), tokenName, isBase ? text : undefined));
|
|
6245
6319
|
}
|
|
6246
6320
|
}
|
|
6247
|
-
let html = "";
|
|
6248
|
-
if (
|
|
6249
|
-
html +=
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6321
|
+
let html = cards.join("");
|
|
6322
|
+
if (semantic.length) {
|
|
6323
|
+
html +=
|
|
6324
|
+
`<section class="rfp-card"><div class="rfp-card-head"><span class="rfp-card-name">Semantic</span>` +
|
|
6325
|
+
`<span class="rfp-card-sub">contrast scored only where a <code>text</code> pairing is declared</span></div>` +
|
|
6326
|
+
`<div class="rfp-chips">${semantic.join("")}</div></section>`;
|
|
6253
6327
|
}
|
|
6254
|
-
return html;
|
|
6328
|
+
return { html, pairings: { total, passing } };
|
|
6329
|
+
}
|
|
6330
|
+
/** One colour chip: swatch (+ live contrast when a pairing is declared), label, tag, value. */
|
|
6331
|
+
function chipOf(path, label, hex, tag, tokenName, pairedText) {
|
|
6332
|
+
return (`<div class="rfp-chip"><div class="rfp-sw rfp-chip-sw"` +
|
|
6333
|
+
(pairedText ? ` data-bg="${esc(hex)}" data-fg="${esc(pairedText)}"` : "") +
|
|
6334
|
+
` style="background:${cssValue(hex)}${pairedText ? `;color:${cssValue(pairedText)}` : ""}">` +
|
|
6335
|
+
(pairedText ? `<span class="rfp-ratio"></span>` : "") +
|
|
6336
|
+
`</div><div class="rfp-cap"><div class="rfp-lbl">${esc(label)}${tag}</div>` +
|
|
6337
|
+
`<div class="rfp-val-sm">${esc(hex)}${pairedText ? ` on ${esc(pairedText)}` : ""}</div>` +
|
|
6338
|
+
idButton(path, tokenName === null || tokenName === void 0 ? void 0 : tokenName(path)) +
|
|
6339
|
+
`</div></div>`);
|
|
6255
6340
|
}
|
|
6256
6341
|
// ── Typography ─────────────────────────────────────────────────────────────
|
|
6257
6342
|
function renderTypography(leaves, tokenName) {
|
|
@@ -6647,6 +6732,33 @@ function renderComposition(recipes, descriptor) {
|
|
|
6647
6732
|
}
|
|
6648
6733
|
return "";
|
|
6649
6734
|
}
|
|
6735
|
+
/**
|
|
6736
|
+
* The contents cover. Built from the sections that actually rendered, so it shrinks with the theme
|
|
6737
|
+
* rather than advertising plates that aren't there. Accent bars borrow the theme's own colour.
|
|
6738
|
+
*/
|
|
6739
|
+
function renderIndex(bodies, counts, accent) {
|
|
6740
|
+
const present = SECTIONS.filter(s => bodies.has(s.id));
|
|
6741
|
+
if (present.length < 2)
|
|
6742
|
+
return "";
|
|
6743
|
+
const cards = present
|
|
6744
|
+
.map((section, i) => {
|
|
6745
|
+
var _a;
|
|
6746
|
+
const n = String(i + 1).padStart(2, "0");
|
|
6747
|
+
const count = (_a = counts.get(section.id)) !== null && _a !== void 0 ? _a : 0;
|
|
6748
|
+
return (`<a class="rfp-idx" href="#rfp-${section.id}" style="text-decoration:none;color:inherit">` +
|
|
6749
|
+
`<span class="rfp-accent" style="background:${accent ? cssValue(accent) : "var(--rfp-spec)"}"></span>` +
|
|
6750
|
+
`<div class="rfp-no">${n} · ${esc(section.eyebrow.toUpperCase())}</div>` +
|
|
6751
|
+
`<h3>${section.title} <span>${count} token(s)</span></h3>` +
|
|
6752
|
+
(section.note ? `<p>${section.note}</p>` : "") +
|
|
6753
|
+
`</a>`);
|
|
6754
|
+
})
|
|
6755
|
+
.join("");
|
|
6756
|
+
return (`<section class="rfp-section" id="rfp-index"><div class="rfp-section-head"><h2>Index</h2>` +
|
|
6757
|
+
`<span class="rfp-count">${present.length} sections</span></div>` +
|
|
6758
|
+
`<p class="rfp-note">A section appears only when the theme has tokens of that kind, so this list ` +
|
|
6759
|
+
`is the shape of the theme rather than a fixed table of contents.</p>` +
|
|
6760
|
+
`<div class="rfp-index">${cards}</div></section>`);
|
|
6761
|
+
}
|
|
6650
6762
|
// ---------------------------------------------------------------------------
|
|
6651
6763
|
// Page chrome
|
|
6652
6764
|
// ---------------------------------------------------------------------------
|
|
@@ -6661,164 +6773,183 @@ function renderComposition(recipes, descriptor) {
|
|
|
6661
6773
|
* dedicated mid-tone reads at the same weight on both grounds.
|
|
6662
6774
|
*/
|
|
6663
6775
|
const CHROME_CSS = `
|
|
6664
|
-
.rfp{--rfp-
|
|
6665
|
-
--rfp-ink-3:#79818f;--rfp-
|
|
6666
|
-
--rfp-spec:#97a1b0;--rfp-spec-2:#c2c9d4;--rfp-hatch:#
|
|
6667
|
-
--rfp-accent:#6b7a99;
|
|
6776
|
+
.rfp{--rfp-paper:#f5f6f8;--rfp-card:#fff;--rfp-sunk:#f0f2f5;--rfp-ink:#14171c;--rfp-ink-2:#4d5563;
|
|
6777
|
+
--rfp-ink-3:#79818f;--rfp-line:#e3e6ea;--rfp-line-2:#d0d5dd;--rfp-focus:#3b4ea8;
|
|
6778
|
+
--rfp-spec:#97a1b0;--rfp-spec-2:#c2c9d4;--rfp-hatch:#dfe3e9;
|
|
6668
6779
|
--rfp-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
|
|
6669
6780
|
--rfp-ui:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
|
|
6670
6781
|
font-family:var(--rfp-ui);font-size:14px;line-height:1.55;color:var(--rfp-ink);
|
|
6671
|
-
background:var(--rfp-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
:where(html){color-scheme:light dark}
|
|
6782
|
+
background:var(--rfp-paper);-webkit-font-smoothing:antialiased;
|
|
6783
|
+
width:100%;min-height:100vh;box-sizing:border-box}
|
|
6784
|
+
/* Full-bleed geometry. :where() gives these ZERO specificity, so a theme's own globals rules still
|
|
6785
|
+
win - the chrome resets the UA gutter without ever outranking the theme it is displaying.
|
|
6786
|
+
color-scheme is pinned to light: this sheet does NOT follow the OS (see below). */
|
|
6787
|
+
:where(html){color-scheme:light}
|
|
6678
6788
|
:where(body){margin:0}
|
|
6679
|
-
@media (prefers-color-scheme:dark){.rfp{--rfp-ground:#0f1114;--rfp-panel:#1a1e24;--rfp-panel-2:#232830;
|
|
6680
|
-
--rfp-ink:#e9ebef;--rfp-ink-2:#a8b0bd;--rfp-ink-3:#7b8492;--rfp-rule:#2b313a;--rfp-rule-2:#3b434f;
|
|
6681
|
-
--rfp-focus:#8ea2ff;--rfp-live:#4ec48d;--rfp-spec:#8791a0;--rfp-spec-2:#4a5361;--rfp-hatch:#333b46;
|
|
6682
|
-
--rfp-stage:#14181d;--rfp-raised:#232830;--rfp-accent:#8e9dbb}}
|
|
6683
6789
|
.rfp *{box-sizing:border-box}
|
|
6684
6790
|
.rfp *:focus-visible{outline:2px solid var(--rfp-focus);outline-offset:2px;border-radius:3px}
|
|
6685
|
-
|
|
6686
|
-
.rfp-
|
|
6687
|
-
|
|
6791
|
+
/* ── Masthead: the theme wearing its own first palette ── */
|
|
6792
|
+
.rfp-masthead{padding:52px 40px 36px}
|
|
6793
|
+
.rfp-kicker{font-family:var(--rfp-mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;opacity:.75;margin:0 0 12px}
|
|
6794
|
+
.rfp-masthead h1{margin:0;font-size:38px;font-weight:680;letter-spacing:-.028em;text-wrap:balance}
|
|
6795
|
+
.rfp-lede{margin:12px 0 0;max-width:66ch;opacity:.88;font-size:15px}
|
|
6796
|
+
.rfp-metrics{margin-top:28px;display:flex;gap:34px;flex-wrap:wrap}
|
|
6797
|
+
.rfp-metric b{display:block;font-size:26px;font-weight:700;line-height:1.1;font-variant-numeric:tabular-nums}
|
|
6798
|
+
.rfp-metric span{font-size:12px;opacity:.72;font-family:var(--rfp-mono)}
|
|
6799
|
+
/* ── Shell ── */
|
|
6800
|
+
.rfp-shell{display:grid;grid-template-columns:204px minmax(0,1fr);gap:44px;padding:0 40px 96px;align-items:start}
|
|
6801
|
+
.rfp-rail{position:sticky;top:0;padding:28px 0;max-height:100vh;overflow-y:auto}
|
|
6802
|
+
.rfp-brand{font-family:var(--rfp-mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
|
|
6803
|
+
color:var(--rfp-ink-3);padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid var(--rfp-line)}
|
|
6688
6804
|
.rfp-nav{display:flex;flex-direction:column;gap:1px}
|
|
6689
6805
|
.rfp-nav a{display:flex;justify-content:space-between;align-items:baseline;gap:10px;padding:5px 8px;
|
|
6690
|
-
border-radius:
|
|
6691
|
-
.rfp-nav a:hover{background:var(--rfp-
|
|
6692
|
-
.rfp-nav a[aria-current="true"]{background:var(--rfp-ink);color:var(--rfp-
|
|
6806
|
+
border-radius:5px;color:var(--rfp-ink-2);text-decoration:none;font-size:13px}
|
|
6807
|
+
.rfp-nav a:hover{background:var(--rfp-card);color:var(--rfp-ink)}
|
|
6808
|
+
.rfp-nav a[aria-current="true"]{background:var(--rfp-ink);color:var(--rfp-paper)}
|
|
6693
6809
|
.rfp-nav .rfp-n{font-family:var(--rfp-mono);font-size:11px;font-variant-numeric:tabular-nums;color:var(--rfp-ink-3)}
|
|
6694
|
-
.rfp-nav a[aria-current="true"] .rfp-n{color:var(--rfp-
|
|
6695
|
-
.rfp-main{padding-top:
|
|
6696
|
-
.rfp-
|
|
6697
|
-
.rfp-eyebrow{font-family:var(--rfp-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--rfp-ink-3)}
|
|
6698
|
-
.rfp-masthead h1{font-size:34px;line-height:1.1;letter-spacing:-.025em;font-weight:640;margin:10px 0 0;text-wrap:balance}
|
|
6699
|
-
.rfp-meta{display:flex;flex-wrap:wrap;gap:6px 10px;margin-top:16px;font-family:var(--rfp-mono);font-size:11.5px;color:var(--rfp-ink-2)}
|
|
6700
|
-
.rfp-meta span{display:inline-flex;align-items:center;gap:6px}
|
|
6701
|
-
.rfp-meta span+span::before{content:"";width:1px;height:11px;background:var(--rfp-rule-2)}
|
|
6702
|
-
.rfp-meta b{font-weight:600;color:var(--rfp-ink)}
|
|
6703
|
-
.rfp-dot{width:6px;height:6px;border-radius:50%;background:var(--rfp-live)}
|
|
6704
|
-
.rfp-controls{display:flex;flex-wrap:wrap;gap:24px;padding:18px 0;border-bottom:1px solid var(--rfp-rule);
|
|
6705
|
-
position:sticky;top:0;background:var(--rfp-ground);z-index:5}
|
|
6810
|
+
.rfp-nav a[aria-current="true"] .rfp-n{color:var(--rfp-paper);opacity:.6}
|
|
6811
|
+
.rfp-main{padding-top:28px;min-width:0}
|
|
6812
|
+
.rfp-controls{display:flex;flex-wrap:wrap;gap:22px;padding:14px 0 18px;position:sticky;top:0;background:var(--rfp-paper);z-index:5}
|
|
6706
6813
|
.rfp-ctl{display:flex;align-items:center;gap:8px}
|
|
6707
6814
|
.rfp-ctl-label{font-family:var(--rfp-mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--rfp-ink-3)}
|
|
6708
|
-
.rfp-seg{display:flex;border:1px solid var(--rfp-
|
|
6709
|
-
.rfp-seg button{font:inherit;font-family:var(--rfp-mono);font-size:11.5px;padding:4px
|
|
6710
|
-
border-left:1px solid var(--rfp-
|
|
6815
|
+
.rfp-seg{display:flex;border:1px solid var(--rfp-line-2);border-radius:7px;overflow:hidden;background:var(--rfp-card)}
|
|
6816
|
+
.rfp-seg button{font:inherit;font-family:var(--rfp-mono);font-size:11.5px;padding:4px 11px;border:0;
|
|
6817
|
+
border-left:1px solid var(--rfp-line-2);background:transparent;color:var(--rfp-ink-2);cursor:pointer}
|
|
6711
6818
|
.rfp-seg button:first-child{border-left:0}
|
|
6712
|
-
.rfp-seg button:hover{background:var(--rfp-
|
|
6713
|
-
.rfp-seg button[aria-pressed="true"]{background:var(--rfp-ink);color:var(--rfp-
|
|
6714
|
-
|
|
6715
|
-
.rfp-section
|
|
6716
|
-
.rfp-section-head
|
|
6717
|
-
.rfp-
|
|
6819
|
+
.rfp-seg button:hover{background:var(--rfp-sunk);color:var(--rfp-ink)}
|
|
6820
|
+
.rfp-seg button[aria-pressed="true"]{background:var(--rfp-ink);color:var(--rfp-card)}
|
|
6821
|
+
/* ── Sections + cards ── */
|
|
6822
|
+
.rfp-section{padding-top:44px;scroll-margin-top:64px}
|
|
6823
|
+
.rfp-section-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
|
|
6824
|
+
.rfp-section-head h2{margin:0;font-size:21px;letter-spacing:-.018em;font-weight:640}
|
|
6825
|
+
.rfp-count{font-family:var(--rfp-mono);font-size:11px;color:var(--rfp-ink-2);background:var(--rfp-card);
|
|
6826
|
+
border:1px solid var(--rfp-line);border-radius:999px;padding:2px 10px;white-space:nowrap}
|
|
6827
|
+
.rfp-note{margin:8px 0 20px;color:var(--rfp-ink-2);font-size:13.5px;max-width:72ch}
|
|
6718
6828
|
.rfp-note-sm{color:var(--rfp-ink-3);font-size:12.5px;margin:10px 0 0;max-width:64ch}
|
|
6719
|
-
.rfp-
|
|
6720
|
-
.rfp-
|
|
6721
|
-
.rfp-
|
|
6722
|
-
.rfp-
|
|
6723
|
-
.rfp-
|
|
6829
|
+
.rfp-card{background:var(--rfp-card);border:1px solid var(--rfp-line);border-radius:14px;padding:18px 20px;margin-top:14px}
|
|
6830
|
+
.rfp-card-head{display:flex;align-items:baseline;gap:10px;margin-bottom:14px;flex-wrap:wrap}
|
|
6831
|
+
.rfp-card-name{font-family:var(--rfp-mono);font-size:12.5px;font-weight:600}
|
|
6832
|
+
.rfp-card-sub{font-family:var(--rfp-mono);font-size:11px;color:var(--rfp-ink-3)}
|
|
6833
|
+
.rfp-row-label{font-family:var(--rfp-mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;
|
|
6834
|
+
color:var(--rfp-ink-3);margin:16px 0 9px;display:flex;align-items:center;gap:8px}
|
|
6835
|
+
.rfp-divider{display:flex;align-items:center;gap:14px;margin:52px 0 4px}
|
|
6836
|
+
.rfp-divider span{font-family:var(--rfp-mono);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;
|
|
6837
|
+
color:var(--rfp-ink-3);white-space:nowrap}
|
|
6838
|
+
.rfp-divider::before,.rfp-divider::after{content:"";height:1px;background:var(--rfp-line);flex:1}
|
|
6839
|
+
/* ── Index cover ── */
|
|
6840
|
+
.rfp-index{display:grid;grid-template-columns:repeat(auto-fill,minmax(272px,1fr));gap:14px}
|
|
6841
|
+
.rfp-idx{position:relative;background:var(--rfp-card);border:1px solid var(--rfp-line);border-radius:14px;
|
|
6842
|
+
padding:18px 18px 15px 22px;overflow:hidden}
|
|
6843
|
+
.rfp-idx .rfp-accent{position:absolute;inset:0 auto 0 0;width:5px}
|
|
6844
|
+
.rfp-idx .rfp-no{font-family:var(--rfp-mono);font-size:10.5px;font-weight:700;letter-spacing:.12em;color:var(--rfp-ink-3)}
|
|
6845
|
+
.rfp-idx h3{margin:6px 0 2px;font-size:18px;letter-spacing:-.015em;font-weight:620}
|
|
6846
|
+
.rfp-idx h3 span{font-family:var(--rfp-mono);font-size:11px;font-weight:500;color:var(--rfp-ink-3)}
|
|
6847
|
+
.rfp-idx p{margin:7px 0 0;font-size:12.5px;color:var(--rfp-ink-2)}
|
|
6848
|
+
/* ── Identifiers ── */
|
|
6724
6849
|
.rfp-id{font-family:var(--rfp-mono);font-size:11.5px;color:var(--rfp-ink-2);background:none;border:0;
|
|
6725
6850
|
padding:1px 4px;margin-left:-4px;border-radius:3px;cursor:copy;text-align:left;display:inline-block}
|
|
6726
|
-
.rfp-id:hover{background:var(--rfp-
|
|
6727
|
-
.rfp-id.rfp-copied{background:var(--rfp-ink);color:var(--rfp-
|
|
6851
|
+
.rfp-id:hover{background:var(--rfp-sunk);color:var(--rfp-ink)}
|
|
6852
|
+
.rfp-id.rfp-copied{background:var(--rfp-ink);color:var(--rfp-card)}
|
|
6728
6853
|
.rfp-var{font-family:var(--rfp-mono);font-size:10.5px;color:var(--rfp-ink-3);display:block;margin-top:1px}
|
|
6729
6854
|
.rfp-hex{font-family:var(--rfp-mono);font-size:11px;color:var(--rfp-ink-3);font-variant-numeric:tabular-nums;display:block;margin-top:1px}
|
|
6730
|
-
|
|
6731
|
-
.rfp-
|
|
6732
|
-
|
|
6733
|
-
.rfp-
|
|
6734
|
-
.rfp-
|
|
6855
|
+
/* ── Provenance tags ── */
|
|
6856
|
+
.rfp-tag{font-family:var(--rfp-mono);font-size:9px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
|
|
6857
|
+
padding:1px 5px;border-radius:4px}
|
|
6858
|
+
.rfp-src{background:color-mix(in srgb,var(--rfp-focus) 12%,transparent);color:var(--rfp-focus)}
|
|
6859
|
+
.rfp-gen{background:var(--rfp-sunk);color:var(--rfp-ink-3);border:1px solid var(--rfp-line)}
|
|
6860
|
+
/* ── Palette ── */
|
|
6861
|
+
.rfp-pal-top{display:flex;align-items:center;gap:16px}
|
|
6862
|
+
.rfp-pal-base{width:84px;height:84px;border-radius:12px;flex:none;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1)}
|
|
6863
|
+
.rfp-pal-name{margin:0;font-size:18px;font-weight:680;letter-spacing:-.015em}
|
|
6864
|
+
.rfp-pal-name small{display:block;font-family:var(--rfp-mono);font-weight:400;color:var(--rfp-ink-3);font-size:11.5px;margin-top:4px}
|
|
6865
|
+
.rfp-rungs{display:flex;border-radius:9px;overflow:hidden;border:1px solid var(--rfp-line)}
|
|
6735
6866
|
.rfp-rung{flex:1 1 0;min-width:0}
|
|
6736
|
-
.rfp-rung-
|
|
6737
|
-
.rfp-rung
|
|
6738
|
-
.rfp-rung[data-lands="true"] .rfp-rung-foot::before{content:"◆ "}
|
|
6739
|
-
.rfp-rung-foot{padding:5px 2px 6px;text-align:center;background:var(--rfp-panel);border-top:1px solid var(--rfp-rule);
|
|
6867
|
+
.rfp-rung .rfp-sw{height:54px}
|
|
6868
|
+
.rfp-rung-foot{padding:6px 2px 7px;text-align:center;background:var(--rfp-sunk);border-top:1px solid var(--rfp-line);
|
|
6740
6869
|
font-family:var(--rfp-mono);font-size:10px;font-variant-numeric:tabular-nums;color:var(--rfp-ink-2)}
|
|
6741
|
-
.rfp-
|
|
6742
|
-
.rfp-
|
|
6743
|
-
.rfp-
|
|
6744
|
-
.rfp-
|
|
6745
|
-
.rfp-
|
|
6746
|
-
|
|
6747
|
-
.rfp-
|
|
6870
|
+
.rfp-rung[data-lands] .rfp-rung-foot{color:var(--rfp-ink);font-weight:700}
|
|
6871
|
+
.rfp-rung[data-lands] .rfp-rung-foot::before{content:"◆ "}
|
|
6872
|
+
.rfp-chips{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:10px}
|
|
6873
|
+
.rfp-chip{border:1px solid var(--rfp-line);border-radius:10px;overflow:hidden;background:var(--rfp-card)}
|
|
6874
|
+
.rfp-chip-sw{height:50px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.05);display:flex;align-items:flex-end;padding:6px}
|
|
6875
|
+
.rfp-cap{padding:8px 9px 9px}
|
|
6876
|
+
.rfp-lbl{font-size:12px;font-weight:600;display:flex;align-items:center;gap:6px;justify-content:space-between}
|
|
6877
|
+
.rfp-val-sm{font-family:var(--rfp-mono);font-size:10.5px;color:var(--rfp-ink-3);margin-top:3px;font-variant-numeric:tabular-nums}
|
|
6878
|
+
.rfp-ratio{font-family:var(--rfp-mono);font-size:10px;padding:1px 6px;border-radius:4px;border:1px solid currentColor}
|
|
6879
|
+
/* ── Rows ── */
|
|
6748
6880
|
.rfp-rows{display:flex;flex-direction:column}
|
|
6749
|
-
.rfp-row{display:grid;grid-template-columns:
|
|
6750
|
-
padding:11px 0;border-top:1px solid var(--rfp-
|
|
6881
|
+
.rfp-row{display:grid;grid-template-columns:200px minmax(0,1fr) 104px;gap:20px;align-items:baseline;
|
|
6882
|
+
padding:11px 0;border-top:1px solid var(--rfp-line)}
|
|
6751
6883
|
.rfp-row:first-child{border-top:0}
|
|
6752
6884
|
.rfp-row.rfp-centred{align-items:center}
|
|
6753
6885
|
.rfp-rowval{font-family:var(--rfp-mono);font-size:11px;color:var(--rfp-ink-3);font-variant-numeric:tabular-nums;text-align:right;overflow-wrap:anywhere}
|
|
6754
6886
|
.rfp-specimen{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.015em}
|
|
6755
6887
|
.rfp-leading{font-size:13px;color:var(--rfp-ink-2);max-width:52ch}
|
|
6756
|
-
.rfp-bar{height:
|
|
6888
|
+
.rfp-bar{height:13px;background:var(--rfp-spec);border-radius:3px;max-width:100%}
|
|
6757
6889
|
.rfp-bar.rfp-ghost{background:var(--rfp-spec-2)}
|
|
6758
|
-
.rfp-gap{display:flex;
|
|
6890
|
+
.rfp-gap{display:flex;border:1px dashed var(--rfp-line-2);border-radius:8px;padding:10px;background:var(--rfp-sunk)}
|
|
6759
6891
|
.rfp-gap>i{flex:1 1 0;height:30px;background:var(--rfp-spec-2);border-radius:3px}
|
|
6760
|
-
.rfp-inset{border:1px solid var(--rfp-
|
|
6892
|
+
.rfp-inset{border:1px solid var(--rfp-line-2);border-radius:10px;
|
|
6761
6893
|
background:repeating-linear-gradient(-45deg,var(--rfp-hatch) 0 4px,transparent 4px 8px)}
|
|
6762
|
-
.rfp-inset-core{background:var(--rfp-spec);color:var(--rfp-
|
|
6763
|
-
font-size:10.5px;font-weight:
|
|
6764
|
-
|
|
6765
|
-
.rfp-
|
|
6766
|
-
.rfp-
|
|
6767
|
-
|
|
6768
|
-
|
|
6894
|
+
.rfp-inset-core{background:var(--rfp-spec);color:var(--rfp-card);border-radius:4px;font-family:var(--rfp-mono);
|
|
6895
|
+
font-size:10.5px;font-weight:700;text-align:center;padding:9px 4px}
|
|
6896
|
+
/* ── Tiles ── */
|
|
6897
|
+
.rfp-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(146px,1fr));gap:12px}
|
|
6898
|
+
.rfp-tile{border:1px solid var(--rfp-line);border-radius:12px;padding:14px;background:var(--rfp-card)}
|
|
6899
|
+
.rfp-stage{height:76px;display:grid;place-items:center;background:var(--rfp-sunk);border-radius:8px;
|
|
6900
|
+
margin-bottom:11px;color:var(--rfp-spec)}
|
|
6901
|
+
.rfp-obj{width:60px;height:60px;background:var(--rfp-spec)}
|
|
6769
6902
|
.rfp-obj.rfp-outlined{background:transparent}
|
|
6770
|
-
.rfp-obj.rfp-raised{background:var(--rfp-
|
|
6771
|
-
.rfp-obj.rfp-accent{background:var(--rfp-
|
|
6772
|
-
.rfp-numeral{font-family:var(--rfp-mono);font-size:
|
|
6773
|
-
.rfp-track{height:34px;border-radius:
|
|
6903
|
+
.rfp-obj.rfp-raised{background:var(--rfp-card)}
|
|
6904
|
+
.rfp-obj.rfp-accent{background:var(--rfp-spec)}
|
|
6905
|
+
.rfp-numeral{font-family:var(--rfp-mono);font-size:19px;font-variant-numeric:tabular-nums;color:var(--rfp-ink-2)}
|
|
6906
|
+
.rfp-track{height:34px;border-radius:8px;background:var(--rfp-sunk);border:1px solid var(--rfp-line);position:relative;overflow:hidden}
|
|
6774
6907
|
.rfp-dot{position:absolute;top:6px;left:6px;width:22px;height:22px;border-radius:5px;background:var(--rfp-spec)}
|
|
6775
|
-
.rfp-play{font:inherit;font-family:var(--rfp-mono);font-size:11.5px;padding:3px 10px;border-radius:
|
|
6776
|
-
border:1px solid var(--rfp-
|
|
6908
|
+
.rfp-play{font:inherit;font-family:var(--rfp-mono);font-size:11.5px;padding:3px 10px;border-radius:5px;
|
|
6909
|
+
border:1px solid var(--rfp-line-2);background:var(--rfp-sunk);color:var(--rfp-ink);cursor:pointer;margin-left:auto}
|
|
6910
|
+
/* ── Tables ── */
|
|
6777
6911
|
.rfp-scroll{overflow-x:auto}
|
|
6778
|
-
.rfp-diff{
|
|
6779
|
-
.rfp-diff th{text-align:left;font-family:var(--rfp-mono);font-size:10.5px;letter-spacing:.1em;
|
|
6780
|
-
color:var(--rfp-ink-3);font-weight:500;padding:0 12px
|
|
6781
|
-
.rfp-diff td{padding:
|
|
6912
|
+
.rfp-diff,.rfp-matrix{border-collapse:collapse;width:100%}
|
|
6913
|
+
.rfp-diff th,.rfp-matrix th{text-align:left;font-family:var(--rfp-mono);font-size:10.5px;letter-spacing:.1em;
|
|
6914
|
+
text-transform:uppercase;color:var(--rfp-ink-3);font-weight:500;padding:0 12px 9px 0;white-space:nowrap}
|
|
6915
|
+
.rfp-diff td{padding:9px 12px 9px 0;border-top:1px solid var(--rfp-line);vertical-align:middle}
|
|
6916
|
+
.rfp-matrix{min-width:560px}
|
|
6917
|
+
.rfp-matrix th{text-align:center;padding:0 8px 10px}
|
|
6918
|
+
.rfp-matrix th:first-child{text-align:left}
|
|
6919
|
+
.rfp-matrix td{padding:13px 8px;border-top:1px solid var(--rfp-line);text-align:center}
|
|
6920
|
+
.rfp-matrix td:first-child{text-align:left;width:208px}
|
|
6921
|
+
.rfp-none{font-family:var(--rfp-mono);font-size:11px;color:var(--rfp-ink-3);opacity:.55}
|
|
6782
6922
|
.rfp-swatch-cell{display:flex;align-items:center;gap:8px}
|
|
6783
|
-
.rfp-chip{width:18px;height:18px;border-radius:
|
|
6923
|
+
.rfp-chip-sm{width:18px;height:18px;border-radius:5px;border:1px solid var(--rfp-line-2);flex:none}
|
|
6784
6924
|
.rfp-arrow{color:var(--rfp-ink-3);font-family:var(--rfp-mono)}
|
|
6785
|
-
|
|
6786
|
-
.rfp-
|
|
6787
|
-
.rfp-
|
|
6788
|
-
|
|
6789
|
-
.rfp-
|
|
6790
|
-
.rfp-matrix td{padding:12px 8px;border-top:1px solid var(--rfp-rule);text-align:center}
|
|
6791
|
-
.rfp-matrix td:first-child{text-align:left;width:210px}
|
|
6792
|
-
.rfp-none{font-family:var(--rfp-mono);font-size:11px;color:var(--rfp-ink-3);opacity:.6}
|
|
6793
|
-
.rfp-recipes{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:14px}
|
|
6794
|
-
.rfp-recipe{border:1px solid var(--rfp-rule);border-radius:6px;overflow:hidden}
|
|
6795
|
-
.rfp-recipe-stage{min-height:96px;display:grid;place-items:center;padding:20px 16px;
|
|
6796
|
-
background:linear-gradient(45deg,var(--rfp-panel) 25%,transparent 25%,transparent 75%,var(--rfp-panel) 75%),
|
|
6797
|
-
linear-gradient(45deg,var(--rfp-panel) 25%,transparent 25%,transparent 75%,var(--rfp-panel) 75%);
|
|
6798
|
-
background-size:14px 14px;background-position:0 0,7px 7px}
|
|
6799
|
-
.rfp-recipe-foot{padding:9px 12px;border-top:1px solid var(--rfp-rule);background:var(--rfp-panel)}
|
|
6925
|
+
/* ── Recipes + prose ── */
|
|
6926
|
+
.rfp-recipes{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
|
|
6927
|
+
.rfp-recipe{border:1px solid var(--rfp-line);border-radius:12px;overflow:hidden;background:var(--rfp-card)}
|
|
6928
|
+
.rfp-recipe-stage{min-height:92px;display:grid;place-items:center;padding:18px;background:var(--rfp-sunk)}
|
|
6929
|
+
.rfp-recipe-foot{padding:9px 12px;border-top:1px solid var(--rfp-line)}
|
|
6800
6930
|
.rfp-addr{font-family:var(--rfp-mono);font-size:11px;color:var(--rfp-ink-3);display:block}
|
|
6801
6931
|
.rfp-compose{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
|
|
6802
|
-
.rfp-cls{font-family:var(--rfp-mono);font-size:11.5px;padding:3px
|
|
6803
|
-
border:1px solid var(--rfp-
|
|
6932
|
+
.rfp-cls{font-family:var(--rfp-mono);font-size:11.5px;padding:3px 9px;border-radius:6px;
|
|
6933
|
+
border:1px solid var(--rfp-line);background:var(--rfp-sunk)}
|
|
6804
6934
|
.rfp-cls b{font-weight:600;color:var(--rfp-ink)}
|
|
6805
6935
|
.rfp-cls span{color:var(--rfp-ink-3)}
|
|
6806
6936
|
.rfp-plus{color:var(--rfp-ink-3);font-family:var(--rfp-mono)}
|
|
6807
|
-
.rfp-
|
|
6808
|
-
|
|
6937
|
+
.rfp-prose{border:1px solid var(--rfp-line);border-radius:14px;padding:26px 28px;background:var(--rfp-card);overflow:hidden}
|
|
6938
|
+
.rfp-notice{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;padding:14px 16px;
|
|
6939
|
+
border:1px solid var(--rfp-line-2);border-radius:12px;background:var(--rfp-card);margin-top:16px}
|
|
6809
6940
|
.rfp-notice-mark{font-family:var(--rfp-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
|
|
6810
|
-
padding:2px
|
|
6941
|
+
padding:2px 7px;border-radius:5px;background:var(--rfp-ink);color:var(--rfp-card);white-space:nowrap;height:fit-content}
|
|
6811
6942
|
.rfp-notice p{margin:0;color:var(--rfp-ink-2);font-size:13px;max-width:68ch}
|
|
6812
6943
|
.rfp-notice p+p{margin-top:6px}
|
|
6813
|
-
.rfp-notice strong{color:var(--rfp-ink)
|
|
6944
|
+
.rfp-notice strong{color:var(--rfp-ink)}
|
|
6814
6945
|
.rfp-frame{margin:0 auto}
|
|
6815
6946
|
@media (prefers-reduced-motion:reduce){.rfp *{transition:none!important;animation:none!important}}
|
|
6816
6947
|
@media (max-width:900px){
|
|
6817
|
-
.rfp{grid-template-columns:minmax(0,1fr);gap:0;padding:0 20px 72px}
|
|
6818
|
-
.rfp-
|
|
6948
|
+
.rfp-shell{grid-template-columns:minmax(0,1fr);gap:0;padding:0 20px 72px}
|
|
6949
|
+
.rfp-masthead{padding:36px 20px 28px}
|
|
6950
|
+
.rfp-rail{position:static;max-height:none;padding:20px 0 0}
|
|
6819
6951
|
.rfp-nav{flex-direction:row;overflow-x:auto;gap:4px;padding-bottom:4px}
|
|
6820
6952
|
.rfp-nav a{white-space:nowrap}
|
|
6821
|
-
.rfp-ladder{grid-template-columns:minmax(0,1fr);gap:10px}
|
|
6822
6953
|
.rfp-row{grid-template-columns:130px minmax(0,1fr)}
|
|
6823
6954
|
.rfp-rowval{grid-column:1/-1;text-align:left}
|
|
6824
6955
|
}
|
|
@@ -6883,7 +7014,7 @@ function renderThemeLinks(stylesheets, contents, inline) {
|
|
|
6883
7014
|
// Entry point
|
|
6884
7015
|
// ---------------------------------------------------------------------------
|
|
6885
7016
|
function buildPreview(source, options) {
|
|
6886
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
7017
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
6887
7018
|
const { usage, preview, tokens, model } = source;
|
|
6888
7019
|
const fileName = (_a = options.file) !== null && _a !== void 0 ? _a : DEFAULT_FILE;
|
|
6889
7020
|
const inline = (_b = options.inline) !== null && _b !== void 0 ? _b : true;
|
|
@@ -6898,6 +7029,7 @@ function buildPreview(source, options) {
|
|
|
6898
7029
|
// entirely, so a theme without shadows shows no elevation plate rather than an empty box.
|
|
6899
7030
|
const bodies = new Map();
|
|
6900
7031
|
const counts = new Map();
|
|
7032
|
+
let pairings = { total: 0, passing: 0 };
|
|
6901
7033
|
for (const [group, items] of groups) {
|
|
6902
7034
|
const section = (_d = SECTION_OF[group]) !== null && _d !== void 0 ? _d : "other";
|
|
6903
7035
|
counts.set(section, ((_e = counts.get(section)) !== null && _e !== void 0 ? _e : 0) + items.length);
|
|
@@ -6907,8 +7039,11 @@ function buildPreview(source, options) {
|
|
|
6907
7039
|
if (!own.length)
|
|
6908
7040
|
continue;
|
|
6909
7041
|
let body = "";
|
|
6910
|
-
if (section.id === "palette")
|
|
6911
|
-
|
|
7042
|
+
if (section.id === "palette") {
|
|
7043
|
+
const palette = renderPalette(own.flatMap(([, l]) => l), model, tokenName);
|
|
7044
|
+
body = palette.html;
|
|
7045
|
+
pairings = palette.pairings;
|
|
7046
|
+
}
|
|
6912
7047
|
else if (section.id === "type")
|
|
6913
7048
|
body = renderTypography(own.flatMap(([, l]) => l), tokenName);
|
|
6914
7049
|
else if (section.id === "space")
|
|
@@ -6936,7 +7071,7 @@ function buildPreview(source, options) {
|
|
|
6936
7071
|
for (const section of SECTIONS) {
|
|
6937
7072
|
if (!bodies.has(section.id))
|
|
6938
7073
|
continue;
|
|
6939
|
-
navItems.push(`<a href="#rfp-${section.id}">${section.eyebrow}<span class="rfp-n">${(_h = counts.get(section.id)) !== null && _h !== void 0 ? _h : 0}</span></a>`);
|
|
7074
|
+
navItems.push(`<a href="#rfp-${section.id}">${esc(section.eyebrow)}<span class="rfp-n">${(_h = counts.get(section.id)) !== null && _h !== void 0 ? _h : 0}</span></a>`);
|
|
6940
7075
|
}
|
|
6941
7076
|
if (modesHtml)
|
|
6942
7077
|
navItems.push(`<a href="#rfp-modes">Appearance</a>`);
|
|
@@ -6946,16 +7081,18 @@ function buildPreview(source, options) {
|
|
|
6946
7081
|
// ── Masthead ────────────────────────────────────────────────────────────
|
|
6947
7082
|
const title = (_j = options.title) !== null && _j !== void 0 ? _j : `${usage.format} theme`;
|
|
6948
7083
|
const totalBytes = options.files.reduce((sum, f) => { var _a, _b, _c; return sum + ((_c = (_b = (_a = options.contents) === null || _a === void 0 ? void 0 : _a[f]) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0); }, 0);
|
|
6949
|
-
const
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
7084
|
+
const subsystems = Object.keys(model.subsystems).length;
|
|
7085
|
+
const elements = Object.keys((_m = (_l = (_k = model.subsystems.globals) === null || _k === void 0 ? void 0 : _k.ruleSets) === null || _l === void 0 ? void 0 : _l.elements) !== null && _m !== void 0 ? _m : {}).length;
|
|
7086
|
+
const metrics = [
|
|
7087
|
+
{ value: String(leaves.length), label: "tokens" },
|
|
7088
|
+
{ value: String(subsystems), label: "subsystems" },
|
|
7089
|
+
{ value: `${usage.recipes.length}${elements ? ` + ${elements}` : ""}`, label: elements ? "recipes + elements" : "recipes" },
|
|
7090
|
+
pairings.total ? { value: `${pairings.passing}/${pairings.total}`, label: "WCAG AA+ pairings" } : undefined,
|
|
7091
|
+
totalBytes ? { value: bytes(totalBytes), label: (_o = options.files[0]) !== null && _o !== void 0 ? _o : "output" } : undefined,
|
|
7092
|
+
].filter((m) => m !== undefined);
|
|
6956
7093
|
const modeAttribute = preview === null || preview === void 0 ? void 0 : preview.modeAttribute;
|
|
6957
7094
|
const modes = collectModes(model);
|
|
6958
|
-
const breakpoints = (
|
|
7095
|
+
const breakpoints = (_p = model.breakpoints) !== null && _p !== void 0 ? _p : {};
|
|
6959
7096
|
const controls = [];
|
|
6960
7097
|
if (modeAttribute && modes.length) {
|
|
6961
7098
|
const buttons = [`<button type="button" data-rfp-mode data-value="" aria-pressed="true">auto</button>`]
|
|
@@ -6972,11 +7109,14 @@ function buildPreview(source, options) {
|
|
|
6972
7109
|
}
|
|
6973
7110
|
// ── Sections ────────────────────────────────────────────────────────────
|
|
6974
7111
|
const sectionHtml = SECTIONS.filter(s => bodies.has(s.id))
|
|
6975
|
-
.map(s =>
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
7112
|
+
.map(s => {
|
|
7113
|
+
var _a;
|
|
7114
|
+
return `<section class="rfp-section" id="rfp-${s.id}"><div class="rfp-section-head">` +
|
|
7115
|
+
`<h2>${s.title}</h2><span class="rfp-count">${(_a = counts.get(s.id)) !== null && _a !== void 0 ? _a : 0} token(s)</span></div>` +
|
|
7116
|
+
(s.note ? `<p class="rfp-note">${s.note}</p>` : "") +
|
|
7117
|
+
bodies.get(s.id) +
|
|
7118
|
+
`</section>`;
|
|
7119
|
+
})
|
|
6980
7120
|
.join("");
|
|
6981
7121
|
const head = [
|
|
6982
7122
|
`<meta charset="utf-8">`,
|
|
@@ -6990,15 +7130,28 @@ function buildPreview(source, options) {
|
|
|
6990
7130
|
]
|
|
6991
7131
|
.filter(Boolean)
|
|
6992
7132
|
.join("\n");
|
|
7133
|
+
// The masthead is the ONE place the chrome takes a hue, and it takes the theme's own first
|
|
7134
|
+
// palette — the theme colouring itself rather than the tool asserting a brand.
|
|
7135
|
+
const brand = mastheadColor(leaves);
|
|
7136
|
+
const mastheadStyle = brand
|
|
7137
|
+
? ` style="background:${cssValue(brand.bg)};color:${cssValue(brand.fg)}"`
|
|
7138
|
+
: ` style="background:var(--rfp-ink);color:var(--rfp-card)"`;
|
|
7139
|
+
const indexHtml = renderIndex(bodies, counts, brand === null || brand === void 0 ? void 0 : brand.bg);
|
|
6993
7140
|
const body = `<div class="rfp">` +
|
|
7141
|
+
`<header class="rfp-masthead"${mastheadStyle}>` +
|
|
7142
|
+
`<p class="rfp-kicker">Theme specimen · ${esc(usage.format)} · ${esc(options.plan.type)}${live ? "" : " · tokens only"}</p>` +
|
|
7143
|
+
`<h1>${esc(title)}</h1>` +
|
|
7144
|
+
`<div class="rfp-metrics">` +
|
|
7145
|
+
metrics.map(m => `<div class="rfp-metric"><b>${esc(m.value)}</b><span>${esc(m.label)}</span></div>`).join("") +
|
|
7146
|
+
`</div></header>` +
|
|
7147
|
+
`<div class="rfp-shell">` +
|
|
6994
7148
|
`<aside class="rfp-rail"><div class="rfp-brand">refract preview</div>` +
|
|
6995
7149
|
`<nav class="rfp-nav">${navItems.join("")}</nav></aside>` +
|
|
6996
7150
|
`<main class="rfp-main">` +
|
|
6997
|
-
`<header class="rfp-masthead"><div class="rfp-eyebrow">Theme specimen</div>` +
|
|
6998
|
-
`<h1>${esc(title)}</h1><div class="rfp-meta">${metaBits.join("")}</div></header>` +
|
|
6999
7151
|
(controls.length ? `<div class="rfp-controls">${controls.join("")}</div>` : "") +
|
|
7000
7152
|
notes.map(n => `<p class="rfp-note">${esc(n)}</p>`).join("") +
|
|
7001
7153
|
`<div class="rfp-frame" id="rfp-frame">` +
|
|
7154
|
+
indexHtml +
|
|
7002
7155
|
sectionHtml +
|
|
7003
7156
|
modesHtml +
|
|
7004
7157
|
globalsHtml +
|
|
@@ -7007,7 +7160,7 @@ function buildPreview(source, options) {
|
|
|
7007
7160
|
`<span class="rfp-tag">${live ? "rendered live" : "names only"}</span></div>` +
|
|
7008
7161
|
renderRecipes(usage, preview, live) +
|
|
7009
7162
|
`</section>` +
|
|
7010
|
-
`</div></main></div>` +
|
|
7163
|
+
`</div></main></div></div>` +
|
|
7011
7164
|
`<script>\n${CHROME_JS}\n</script>`;
|
|
7012
7165
|
const html = `<!doctype html>\n<html lang="en"${modeAttribute ? ` data-rfp-mode-attr="${esc(modeAttribute)}"` : ""}>\n` +
|
|
7013
7166
|
`<head>\n${head}\n</head>\n<body>\n${body}\n</body>\n</html>\n`;
|