aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/theme-studio')
-rw-r--r--scripts/theme-studio/README.md67
-rw-r--r--scripts/theme-studio/app-core.js225
-rw-r--r--scripts/theme-studio/app.js401
-rw-r--r--scripts/theme-studio/colormath.js29
-rw-r--r--scripts/theme-studio/generate.py91
-rwxr-xr-xscripts/theme-studio/run-tests.sh9
-rw-r--r--scripts/theme-studio/sterling.json5779
-rw-r--r--scripts/theme-studio/styles.css12
-rw-r--r--scripts/theme-studio/test-app-core.mjs2
-rw-r--r--scripts/theme-studio/test-colormath.mjs32
-rw-r--r--scripts/theme-studio/test-contrast.mjs111
-rw-r--r--scripts/theme-studio/test-families.mjs213
-rw-r--r--scripts/theme-studio/test-ramp.mjs105
-rw-r--r--scripts/theme-studio/theme-studio.html670
14 files changed, 7609 insertions, 137 deletions
diff --git a/scripts/theme-studio/README.md b/scripts/theme-studio/README.md
index 044ccc2e..caee7b24 100644
--- a/scripts/theme-studio/README.md
+++ b/scripts/theme-studio/README.md
@@ -42,7 +42,9 @@ The runner regenerates the page, runs the Python templating tests
(`test-colormath.mjs`, including the inline-integrity check), a syntax check of
the spliced page script, and the browser hash gates in headless Chrome
(`#selftest`, `#cursortest`, `#readouttest`, `#deltatest`, `#oklchtest`,
-`#planetest`). It exits non-zero on any failure. The browser gates need a
+`#planetest`, `#locktest`, `#sorttest`, `#mocktest`, `#contrasttest`,
+`#safetest`, `#healtest`, `#familytest`, `#counttest`, `#baseedittest`,
+`#roundtriptest`). It exits non-zero on any failure. The browser gates need a
Chromium-family browser; without one they report SKIPPED rather than passing
silently. The pure color math and the extracted picker logic (`planeCell`,
`paletteWarnings`) live in `colormath.js` so they are unit-tested directly in
@@ -65,10 +67,11 @@ Node; the DOM glue is covered by the browser hash gates.
Three tiers of faces, plus the palette:
-- **Palette** — named colors. Add by hex or with the in-page color picker
+- **Palette** — named colors, shown grouped into hue *families* (see Color
+ families below). Add by hex or with the in-page color picker
(saturation/value square, hue slider, palette reuse chips, live contrast
- readout, and an any / AA+ / AAA legibility mask). Remove, rename, reorder with
- arrows or drag. The colors serving as background and foreground are locked.
+ readout, and an any / AA+ / AAA legibility mask). Remove and rename per chip;
+ the colors serving as background and foreground are locked.
The picker also shows perceptual readouts beside the WCAG ratio: the OKLCH
coordinates (lightness, chroma, hue°) and the APCA Lc contrast against the
@@ -92,6 +95,62 @@ Three tiers of faces, plus the palette:
per face, shown in a live mock Emacs buffer.
- **Package faces** — per-package face tables with a live preview (below).
+## Color families
+
+The palette is displayed as **families**: colors grouped into vertical columns by
+their actual color, dark at the top and light at the bottom, columns arranged left
+to right. Grouping is derived from the hex on every render — never from the name —
+so renaming a color to anything never moves it between columns. The flat palette
+underneath is unchanged (export stays a flat `[hex, name]` list); families are a
+view over it, and the per-chip rename/remove still work.
+
+- **Grouping.** Chromatic colors bucket by their nearest perceptual hue (red,
+ orange, yellow, green, teal, blue, purple, pink). Near-neutrals — grays, the
+ background and foreground ramps — collapse into one neutral column ordered by
+ lightness, using a lightness-scaled chroma threshold so a faint pale tint keeps
+ its hue while a faint mid gray reads as neutral. Columns sort by hue; the ground
+ strip (the `bg` and `fg` assignments) pins first, neutrals next. (Hue-adjacent
+ warm colors like olive-greens and golds can still share a column — a known
+ limitation, since by hue they really are adjacent.)
+- **The count control** under each chromatic column sets how many steps sit on
+ each side of the family's base (its most-saturated color). Setting N regenerates
+ the family as a symmetric base ±N tonal ramp via `ramp()` — lighter and darker
+ steps on the base's hue with chroma easing toward the extremes — *replacing* the
+ column's current colors. N=0 collapses to the base alone.
+- **Editing a base** recolors the whole family: change a base color and the family
+ regenerates from it at the same count.
+- **References follow.** When a regenerate changes a step's hex, any face assigned
+ to that step is re-pointed to the new hex. A step *removed* by lowering the count
+ leaves its references showing "(gone)" — visible and recoverable, never a silent
+ jump to a different color.
+
+The standalone ramp generator is gone; fanning a color into a ramp is now "add the
+color, then raise its column's count."
+
+## Background-contrast safety
+
+Keep background tints readable. Works in OKLCH; the pure math is in `app-core.js`
+(`fgSetFor`, `floor`, `lMax`), the DOM in `app.js`.
+
+**Worst-case contrast.** A background overlay sits behind many foregrounds at
+once, so one fg/bg contrast pair is the wrong number. For the covered overlay
+faces — `region`, `hl-line`, `highlight`, `lazy-highlight`, `isearch` — the
+contrast cell shows the *worst-case floor*: the lowest contrast over the face's
+foreground set (the syntax-token colors plus the default foreground), naming the
+*limiting foreground* that sets it. A tint that clears the default text but fails
+the darkest token reads FAIL, with that token named. Package faces and the other
+UI rows keep their single-pair readout.
+
+The verdict is WCAG: AA (4.5) by default, AAA (7) selectable. APCA Lc stays a
+picker-only diagnostic and does not drive PASS/FAIL.
+
+**Safe lightness.** In the OKLCH picker, the "safe for" selector picks one
+covered face. The Chroma×Lightness plane then shades the lightness band too light
+to keep that face readable over its foreground set, with the L_max ceiling as the
+band's lower edge. If even pure black can't satisfy the target (a foreground is
+too dark), the whole plane shades; that is a true finding about the foreground,
+not a tool bug.
+
## Package faces
Pick an application from the dropdown to edit its faces. Each row has a
diff --git a/scripts/theme-studio/app-core.js b/scripts/theme-studio/app-core.js
index 0e3cfe49..60ee1410 100644
--- a/scripts/theme-studio/app-core.js
+++ b/scripts/theme-studio/app-core.js
@@ -4,6 +4,12 @@
// the browser runs the same code the tests import. The app.js wrappers (pname,
// seedPkgmap, ddList, pkgEffFg, pkgEffBg) are thin delegators that pass the
// live PALETTE / APPS / PKGMAP into these.
+//
+// The imports below are for the Node tests; generate.py strips them on inline,
+// where normHex (app-util.js) and the colormath helpers are already present from
+// the bodies inlined above this one.
+import { normHex } from './app-util.js';
+import { oklch2hex, srgb2oklab, oklab2oklch, contrast } from './colormath.js';
// Resolve a palette name (or a raw #hex) to a hex; null when the name is unknown.
function nameToHex(n,palette){if(!n)return null;if(/^#/.test(n))return n;const p=palette.find(p=>p[1]===n);return p?p[0]:null;}
@@ -29,4 +35,221 @@ function optList(cur,palette){const have=cur===''||palette.some(p=>p[0]===cur);r
// characters to a single dash, trim leading/trailing dashes, fall back to 'theme'.
function slugify(name){return name.replace(/[^A-Za-z0-9._-]+/g,'-').replace(/^-+|-+$/g,'')||'theme';}
-export { nameToHex, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList, slugify };
+// Generate a tonal ramp from one base color: 2n steps at offsets -n..-1 and
+// +1..+n (the base itself is excluded — it already lives in the palette),
+// ordered darkest -> lightest. Holds the OKLCH hue, steps lightness by stepL per
+// stop, and eases chroma toward the extremes (quadratic in |offset|/n, so only
+// the farthest step loses most of its color). Every step is gamut-clamped and
+// carries its own clamped flag. Returns {steps:[{hex,clamped,offset}], adjusted}
+// where adjusted names any knob clamped/rounded into range, or {steps:[],
+// error:'bad-hex'} for an unparseable base. Pure — opts are clamped, never thrown.
+function ramp(baseHex,opts){
+ const hex=typeof baseHex==='string'?normHex(baseHex):null;
+ if(!hex)return {steps:[],error:'bad-hex'};
+ const o=opts||{},adjusted=[];
+ const knob=(name,def,lo,hi,isInt)=>{
+ const v=o[name];
+ if(typeof v!=='number'||!isFinite(v))return def;
+ const r=isInt?Math.round(v):v,c=Math.min(hi,Math.max(lo,r));
+ if(c!==v)adjusted.push(name);
+ return c;
+ };
+ const n=knob('n',2,1,4,true),stepL=knob('stepL',0.08,0.04,0.12,false),chromaEase=knob('chromaEase',0.5,0,1,false);
+ const {L:L0,C:C0,H:H0}=oklab2oklch(srgb2oklab(hex));
+ const steps=[];
+ for(let off=-n;off<=n;off++){
+ if(off===0)continue;
+ const L=Math.min(1,Math.max(0,L0+off*stepL));
+ const t=Math.abs(off)/n,C=C0*(1-chromaEase*t*t);
+ const {hex:h,clamped}=oklch2hex(L,C,H0);
+ steps.push({hex:h,clamped,offset:off});
+ }
+ return {steps,adjusted};
+}
+
+// --- background-contrast safety (palette-ramps spec, Phase 3) ----------------
+// An overlay background sits behind many foregrounds at once, so its real
+// constraint is the worst-case contrast over the whole set, not one fg/bg pair.
+
+// The closed v1 set of code-overlay faces whose worst-case floor we compute.
+// Other overlay faces (secondary-selection, isearch-fail, ...) are vNext, added
+// explicitly rather than by a heuristic. Shared by app.js and the tests.
+const COVERED_FACES=['region','hl-line','highlight','lazy-highlight','isearch'];
+
+// A covered face's foreground set: the distinct syntax-token colors plus the
+// default foreground, each labeled (syntax role preferred, else 'default').
+// state = {covered:[face], syntaxAssignments:[{role,hex}], defaultFg}. Returns
+// {set:[{hex,label}]}, or {set:[],reason} where reason is 'out-of-scope' (the
+// face isn't in the covered set) or 'empty' (no syntax assignments constrain it).
+function fgSetFor(face,state){
+ const covered=(state&&state.covered)||COVERED_FACES;
+ if(!covered.includes(face))return {set:[],reason:'out-of-scope'};
+ const syn=((state&&state.syntaxAssignments)||[]).filter(a=>a&&a.hex);
+ if(!syn.length)return {set:[],reason:'empty'};
+ const byHex=new Map();
+ const add=(hex,label,isRole)=>{const k=hex.toLowerCase(),cur=byHex.get(k);if(!cur)byHex.set(k,{hex:k,label});else if(isRole&&cur.label==='default')cur.label=label;};
+ if(state&&state.defaultFg)add(state.defaultFg,'default',false);
+ for(const a of syn)add(a.hex,a.role||a.hex,true);
+ return {set:[...byHex.values()]};
+}
+
+// Worst-case (minimum) WCAG contrast of a background against a foreground set,
+// with the limiting foreground's hex and label. fgSet is fgSetFor's set. An empty
+// set returns nulls so the caller can show the no-set readout instead of a floor.
+function floor(bgHex,fgSet){
+ if(!fgSet||!fgSet.length)return {ratio:null,limitingHex:null,limitingLabel:null};
+ let best=Infinity,lh=null,ll=null;
+ for(const f of fgSet){const r=contrast(f.hex,bgHex);if(r<best){best=r;lh=f.hex;ll=f.label;}}
+ return {ratio:best,limitingHex:lh,limitingLabel:ll};
+}
+
+// The lightest background at (hue, chroma) whose worst-case floor over fgSet still
+// clears target (a WCAG ratio). Scans L up from black to bracket the first
+// dark-side crossing, then binary-searches it to tol 0.001. status:
+// 'ok' - a ceiling L was found
+// 'none' - even pure black fails (a foreground is too dark for the target)
+// 'all' - no foreground set to constrain (vacuously safe everywhere)
+// 'clamp' - the ceiling L can't hold the requested chroma (gamut-clamped there)
+function lMax(hue,chroma,fgSet,target){
+ if(!fgSet||!fgSet.length)return {L:1,status:'all'};
+ const at=(L)=>{const {hex,clamped}=oklch2hex(L,chroma,hue);return {r:floor(hex,fgSet).ratio,clamped};};
+ if(at(0).r<target)return {L:null,status:'none'};
+ let loL=0,hiL=null;
+ for(let L=0.01;L<=1+1e-9;L+=0.01){const c=Math.min(L,1);if(at(c).r<target){hiL=c;break;}loL=c;}
+ if(hiL===null)return {L:1,status:'all'};
+ for(let i=0;i<20;i++){const mid=(loL+hiL)/2;if(at(mid).r>=target)loL=mid;else hiL=mid;}
+ return {L:loL,status:at(loL).clamped?'clamp':'ok'};
+}
+
+// --- color families (color-families spec, Phase 1) ---------------------------
+// Families are a display grouping derived from the hex every render — never from
+// names — so renaming a color can't move it. The flat palette stays the editable
+// truth; these pure functions group it, regenerate a family's ramp, and plan the
+// assignment re-point across a regenerate.
+
+function oklchOf(hex){return oklab2oklch(srgb2oklab(hex));}
+function nameOfHex(palette,hex){const p=palette.find(p=>p[0].toLowerCase()===hex.toLowerCase());return p?p[1]:null;}
+function hueDist(a,b){const d=Math.abs(a-b);return Math.min(d,360-d);}
+
+// A color reads as neutral below this chroma. Lightness-scaled (the Munsell
+// insight): the mid-tones need more chroma to read as a hue. Floored at both ends
+// rather than tapering to zero, so pale warm grays stay neutral (and pure white,
+// C=0 at L=1, doesn't evade a zero threshold) while pale chromatic tints stay
+// colored. Tuned on real palettes (Codex + Fable color-sorting reviews).
+function neutralThreshold(L){
+ if(L<=0.2)return 0.020;
+ if(L<0.6)return 0.020+0.015*(L-0.2)/0.4;
+ if(L<0.85)return 0.035-0.017*(L-0.6)/0.25;
+ return 0.018;
+}
+// Lightness-conditioned compatibility of two chromatic colors (Fable's LCCL):
+// hue must match tightly at equal lightness and may drift across a lightness gap,
+// because a tonal ramp drifts in hue with lightness by design. The low-chroma noise
+// term widens the hue tolerance where hue is ill-defined (pale tints). A chroma
+// clause keeps a vivid accent out of a soft family at the same lightness. <=1 is
+// compatible. Source: ~/color-sorting-fable.org.
+function pairRatio(a,b){
+ const dL=Math.abs(a.L-b.L),dH=hueDist(a.H,b.H);
+ const noise=Math.min(45,Math.atan(0.015/Math.max(Math.min(a.C,b.C),1e-6))*180/Math.PI);
+ return Math.max(dH/(12+60*dL+noise),Math.abs(a.C-b.C)/(0.08+0.3*dL));
+}
+// Complete-linkage agglomerative clustering on pairRatio: greedily merge the two
+// clusters whose worst cross-pair is most compatible, stopping when no merge has
+// every cross-pair compatible. Complete linkage makes single-linkage chaining
+// structurally impossible — two ramps can't fuse through their converging pale
+// ends because their mid-lightness members stay far apart.
+function clusterChromatic(ms){
+ let cl=ms.map(m=>[m]);
+ const cd=(A,B)=>Math.max(...A.flatMap(a=>B.map(b=>pairRatio(a,b))));
+ for(;;){
+ let best=null;
+ for(let i=0;i<cl.length;i++)for(let j=i+1;j<cl.length;j++){const d=cd(cl[i],cl[j]);if(!best||d<best.d)best={d,i,j};}
+ if(!best||best.d>1)break;
+ cl[best.i]=cl[best.i].concat(cl[best.j]);cl.splice(best.j,1);
+ }
+ return cl;
+}
+// A family from its members: base is the most-saturated member (tie toward
+// mid-lightness), the anchor for a generated ramp.
+function makeFamily(ms,neutral){
+ let base=ms[0];
+ for(const m of ms)if(m.C>base.C||(m.C===base.C&&Math.abs(m.L-0.5)<Math.abs(base.L-0.5)))base=m;
+ return {base:base.hex,neutral:!!neutral,members:ms.map(m=>({hex:m.hex,name:m.name}))};
+}
+// Group a flat palette into the ground strip plus families. ground is {bg,fg}:
+// those two hexes form the pinned ground strip even when absent from the palette,
+// and a palette chip at a ground hex is not duplicated into a family. Near-neutrals
+// (chroma below the lightness-scaled threshold) form one neutral family; the rest
+// cluster by lightness-conditioned complete linkage (clusterChromatic).
+function familiesFromPalette(palette,ground){
+ const bg=ground&&ground.bg,fg=ground&&ground.fg;
+ const gset=new Set([bg,fg].filter(Boolean).map(h=>h.toLowerCase()));
+ const groundStrip=[];
+ if(bg)groundStrip.push({hex:bg,role:'bg',name:nameOfHex(palette,bg)});
+ if(fg)groundStrip.push({hex:fg,role:'fg',name:nameOfHex(palette,fg)});
+ const neutrals=[],chromatic=[];
+ for(const [hex,name] of palette){
+ if(gset.has(hex.toLowerCase()))continue;
+ const c=oklchOf(hex),m={hex,name,L:c.L,C:c.C,H:c.H};
+ (c.C<neutralThreshold(c.L)?neutrals:chromatic).push(m);
+ }
+ const families=[];
+ if(neutrals.length)families.push(makeFamily(neutrals,true));
+ for(const cl of clusterChromatic(chromatic))families.push(makeFamily(cl,false));
+ return {ground:groundStrip,families};
+}
+// Regenerate a family's members as a symmetric ramp around the base: n=0 is the
+// base alone (without ramp()'s 1-4 clamp), n>=1 is base plus ramp() steps, sorted
+// by offset. {members:[{hex,offset,clamped}]} or {members:[],error:'bad-hex'}.
+function regenFamily(baseHex,n,opts){
+ const hex=typeof baseHex==='string'?normHex(baseHex):null;
+ if(!hex)return {members:[],error:'bad-hex'};
+ const k=Math.min(4,Math.max(0,Math.round(n||0)));
+ if(k===0)return {members:[{hex,offset:0,clamped:false}]};
+ const r=ramp(hex,Object.assign({},opts,{n:k}));
+ if(r.error)return {members:[],error:r.error};
+ const members=[...r.steps,{hex,offset:0,clamped:false}].sort((a,b)=>a.offset-b.offset);
+ return {members};
+}
+// Rank a family's current member hexes by lightness and give each a signed offset
+// from the base (the matching hex, or the nearest by lightness if the base isn't
+// present). Lets a regenerate match old positions to new ramp offsets.
+function rankByLightness(memberHexes,baseHex){
+ const items=memberHexes.map(h=>({hex:h,L:oklchOf(h).L})).sort((a,b)=>a.L-b.L);
+ let bi=items.findIndex(m=>m.hex.toLowerCase()===(baseHex||'').toLowerCase());
+ if(bi<0){const bl=oklchOf(baseHex).L;let best=Infinity;items.forEach((m,i)=>{const d=Math.abs(m.L-bl);if(d<best){best=d;bi=i;}});}
+ return items.map((m,i)=>({hex:m.hex,offset:i-bi}));
+}
+// Plan the assignment re-point for a regenerate: for each old ranked member, the
+// new member at the same offset is the same position. {map:[[old,new]]} for
+// positions whose hex changed; {removed:[hex]} for positions with no new
+// counterpart (the caller leaves their references a visible "(gone)").
+function stepRepointPlan(oldRanked,newMembers){
+ const byOff=new Map(newMembers.map(m=>[m.offset,m.hex])),map=[],removed=[];
+ for(const o of oldRanked){
+ const nh=byOff.get(o.offset);
+ if(nh===undefined)removed.push(o.hex);
+ else if(nh.toLowerCase()!==o.hex.toLowerCase())map.push([o.hex,nh]);
+ }
+ return {map,removed};
+}
+
+// Order a family's members dark to light by OKLCH lightness.
+function sortFamilyMembers(fam){return Object.assign({},fam,{members:[...fam.members].sort((a,b)=>oklchOf(a.hex).L-oklchOf(b.hex).L)});}
+// Order families for display: neutrals first (by base lightness), then chromatic
+// by base hue, ties broken by base lightness then base hex. Each family's members
+// are lightness-sorted. Display-only — the stored palette order is untouched.
+function sortFamilies(families){
+ const keyed=families.map(f=>{const c=oklchOf(f.base);return {f,neutral:!!f.neutral,H:c.H,L:c.L,base:f.base};});
+ keyed.sort((a,b)=>{
+ if(a.neutral!==b.neutral)return a.neutral?-1:1;
+ if(a.neutral&&b.neutral)return a.L-b.L;
+ const ah=Math.round(a.H),bh=Math.round(b.H); // a hue hair shouldn't outrank lightness
+ if(ah!==bh)return ah-bh;
+ if(a.L!==b.L)return a.L-b.L;
+ return a.base.toLowerCase()<b.base.toLowerCase()?-1:a.base.toLowerCase()>b.base.toLowerCase()?1:0;
+ });
+ return keyed.map(k=>sortFamilyMembers(k.f));
+}
+
+export { nameToHex, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList, slugify, ramp, fgSetFor, floor, lMax, COVERED_FACES, familiesFromPalette, regenFamily, rankByLightness, stepRepointPlan, sortFamilies, sortFamilyMembers };
diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js
index d0fed81c..aadfd5b7 100644
--- a/scripts/theme-studio/app.js
+++ b/scripts/theme-studio/app.js
@@ -121,7 +121,7 @@ function buildTable(){
const crTd=document.createElement('td');crTd.style.whiteSpace='nowrap';crTd.style.fontSize='10pt';
function styleEx(){exTd.style.color=(kind==='bg'?MAP['p']:effFg(MAP[kind]));exTd.style.background=MAP['bg'];exTd.style.fontWeight=BOLD[kind]?'bold':'normal';exTd.style.fontStyle=ITALIC[kind]?'italic':'normal';}
function styleCr(){const r=contrast((kind==='bg'?MAP['p']:effFg(MAP[kind])),MAP['bg']);crTd.innerHTML=crHtml(r);}
- const dd=mkColorDropdown(list,cur,(hex)=>{MAP[kind]=hex;styleEx();styleCr();renderCode();if(kind==='bg'){applyGround();buildTable();}});
+ const dd=mkColorDropdown(list,cur,(hex)=>{MAP[kind]=hex;styleEx();styleCr();renderCode();if(kind==='bg'||kind==='p'){applyGround();buildTable();buildPkgTable();buildPkgPreview();}repaintCovered();});
styleEx();styleCr();
const lkTd=mkLockCell(kind,[dd]);
// style buttons
@@ -138,7 +138,23 @@ function buildTable(){
tr.appendChild(c2);tr.appendChild(lkTd);tr.appendChild(c0);tr.appendChild(stTd);tr.appendChild(crTd);tr.appendChild(exTd);
tb.appendChild(tr);}
}
-let dragFrom=null,selectedIdx=null;
+let selectedIdx=null;
+// When a named palette color is deleted, remember its hex keyed by name so that
+// recreating a color with the same name can re-bind the assignments still pointing
+// at the old (now "(gone)") hex. Consumed once per name; cleared on import.
+let lastGone={};
+// Re-point every assignment — syntax map, UI faces, package faces — from one hex
+// to another. Used when a palette color's value is edited and when a deleted name
+// is recreated.
+function repointHex(oldHex,newHex){
+ if(oldHex===newHex)return;
+ for(const k in MAP){if(MAP[k]===oldHex)MAP[k]=newHex;}
+ for(const f in UIMAP){if(UIMAP[f].fg===oldHex)UIMAP[f].fg=newHex;if(UIMAP[f].bg===oldHex)UIMAP[f].bg=newHex;}
+ for(const ap in PKGMAP)for(const fc in PKGMAP[ap]){const o=PKGMAP[ap][fc];if(o.fg===oldHex)o.fg=newHex;if(o.bg===oldHex)o.bg=newHex;}
+}
+// On adding a color, if its name matches a recently-deleted one, re-bind the
+// stranded assignments to the new hex. Returns true when a heal context existed.
+function healGone(name,newHex){const k=name.toLowerCase();if(!(k in lastGone))return false;const g=lastGone[k];delete lastGone[k];repointHex(g,newHex);return true;}
// Pairwise OKLab ΔE over the palette. Returns the sub-threshold pairs (sorted
// closest-first) and each color's nearest-neighbor distance for its chip title.
// Pure pairwise ΔE analysis lives in colormath.js (paletteWarnings); this renders it.
@@ -150,35 +166,90 @@ function renderPaletteWarnings(warnings,overflow){
if(overflow>0)html+=`<div class="pwl">and ${overflow} more</div>`;
w.innerHTML=html;w.style.display='block';
}
+// One palette chip for PALETTE[i], with its remove / rename / select handlers.
+// Families sort deterministically, so the old move-arrow / drag reordering is gone.
+function paletteChip(i,nearest){
+ const [hex,name]=PALETTE[i],tc=textOn(hex),nde=nearest[i];
+ const locked=(hex===MAP['bg']||hex===MAP['p']);
+ const d=document.createElement('div');d.className='pchip'+(i===selectedIdx?' sel':'');d.style.background=hex;
+ d.title=name+' '+hex+(nde===Infinity||nde===undefined?'':' — nearest ΔE '+nde.toFixed(3));
+ const rm=locked?`<span class="lock" title="${hex===MAP['bg']?'background':'foreground'} — can't remove" style="color:${tc}">&#128274;</span>`:`<button class="rm" title="remove" style="color:${tc}">×</button>`;
+ d.innerHTML=`${rm}<input class="nm" value="${name}" style="color:${tc}"><div class="hx" style="color:${tc}">${hex}</div>`;
+ if(!locked)d.querySelector('.rm').onclick=(e)=>{e.stopPropagation();if(name)lastGone[name.toLowerCase()]=hex;PALETTE.splice(i,1);if(selectedIdx===i)selectedIdx=null;renderPalette();buildTable();buildUITable();};
+ d.querySelector('.nm').onchange=(e)=>{PALETTE[i][1]=e.target.value;buildTable();buildUITable();};
+ d.onclick=(e)=>{if(e.target.closest('.rm')||e.target.closest('.nm'))return;selectColor(i);};
+ return d;
+}
+// Render the palette as hue families: the pinned ground strip, then hue-sorted
+// family strips, each dark to light. Grouping is derived from the hex by
+// familiesFromPalette every render, so renaming a color never moves it. The flat
+// PALETTE stays the editable truth; chips keep their per-chip controls.
function renderPalette(){
const p=document.getElementById('pals');p.innerHTML='';
const {warnings,overflow,nearest}=paletteWarnings(PALETTE,DELTAE_MIN,5);
- PALETTE.forEach((pc,i)=>{const [hex,name]=pc;const tc=textOn(hex);
- const nde=nearest[i];
- const locked=(hex===MAP['bg']||hex===MAP['p']);
- const d=document.createElement('div');d.className='pchip'+(i===selectedIdx?' sel':'');d.style.background=hex;d.draggable=true;
- d.title=name+' '+hex+(nde===Infinity?'':' — nearest \u0394E '+nde.toFixed(3));
- const lft=i>0?`<button class="mv l" title="move left" style="color:${tc}">&#8249;</button>`:'';
- const rgt=i<PALETTE.length-1?`<button class="mv r" title="move right" style="color:${tc}">&#8250;</button>`:'';
- const rm=locked?`<span class="lock" title="${hex===MAP['bg']?'background':'foreground'} — can't remove" style="color:${tc}">&#128274;</span>`:`<button class="rm" title="remove" style="color:${tc}">×</button>`;
- d.innerHTML=`${rm}${lft}${rgt}<input class="nm" value="${name}" style="color:${tc}"><div class="hx" style="color:${tc}">${hex}</div>`;
- if(!locked)d.querySelector('.rm').onclick=(e)=>{e.stopPropagation();PALETTE.splice(i,1);if(selectedIdx===i)selectedIdx=null;renderPalette();buildTable();buildUITable();};
- if(lft)d.querySelector('.mv.l').onclick=(e)=>{e.stopPropagation();moveColor(i,-1);};
- if(rgt)d.querySelector('.mv.r').onclick=(e)=>{e.stopPropagation();moveColor(i,1);};
- d.querySelector('.nm').onchange=(e)=>{PALETTE[i][1]=e.target.value;buildTable();buildUITable();};
- d.onclick=(e)=>{if(e.target.closest('.rm')||e.target.closest('.nm')||e.target.closest('.mv'))return;selectColor(i);};
- d.ondragstart=()=>{dragFrom=i;d.classList.add('drag');};
- d.ondragend=()=>{d.classList.remove('drag');document.querySelectorAll('.pchip.over').forEach(x=>x.classList.remove('over'));};
- d.ondragover=(e)=>{e.preventDefault();if(dragFrom!==null&&dragFrom!==i)d.classList.add('over');};
- d.ondragleave=()=>d.classList.remove('over');
- d.ondrop=(e)=>{e.preventDefault();d.classList.remove('over');if(dragFrom===null||dragFrom===i)return;const m=PALETTE.splice(dragFrom,1)[0];PALETTE.splice(i,0,m);dragFrom=null;selectedIdx=null;renderPalette();buildTable();buildUITable();};
- p.appendChild(d);});
+ const {ground,families}=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']});
+ const used=new Set();
+ const idxOf=(hex,name)=>{for(let i=0;i<PALETTE.length;i++)if(!used.has(i)&&PALETTE[i][0]===hex&&PALETTE[i][1]===name){used.add(i);return i;}return -1;};
+ const strip=(cls)=>{const s=document.createElement('div');s.className='fstrip'+(cls||'');p.appendChild(s);return s;};
+ const gs=strip(' ground');gs.dataset.family='ground';
+ ground.forEach(g=>{
+ const i=PALETTE.findIndex((pp,k)=>!used.has(k)&&pp[0]===g.hex);
+ if(i>=0){used.add(i);gs.appendChild(paletteChip(i,nearest));}
+ else{const tc=textOn(g.hex),sw=document.createElement('div');sw.className='pchip';sw.style.background=g.hex;sw.title=(g.role||'')+' '+g.hex;
+ sw.innerHTML=`<input class="nm" value="${g.role||''}" disabled style="color:${tc}"><div class="hx" style="color:${tc}">${g.hex}</div>`;gs.appendChild(sw);}
+ });
+ // The too-similar warning stays on the full flat palette: a generated ramp's
+ // steps are a stepL apart (well above the warning's ΔE threshold), so they never
+ // trigger it, and any pair that does is a genuine near-duplicate worth flagging.
+ sortFamilies(families).forEach(f=>{
+ const s=strip(f.neutral?' neutral':'');s.dataset.family=f.base;
+ f.members.forEach(m=>{const i=idxOf(m.hex,m.name);if(i>=0)s.appendChild(paletteChip(i,nearest));});
+ if(!f.neutral)s.appendChild(familyCountControl(f));
+ });
renderPaletteWarnings(warnings,overflow);
buildUITable();if(document.getElementById('pkgbody'))buildPkgTable();
}
+// The per-family count control under a chromatic strip. Its value is the family's
+// current per-side reach; setting N regenerates the family as base ±N.
+function familyCountControl(f){
+ const per=Math.max(0,...rankByLightness(f.members.map(m=>m.hex),f.base).map(m=>Math.abs(m.offset)));
+ const d=document.createElement('div');d.className='fcount';
+ d.innerHTML=`<span title="generate a symmetric ramp of N steps each side of this family's base — this replaces the family">&#177; <input type="number" min="0" max="4" value="${per}"></span>`;
+ d.querySelector('input').onchange=(e)=>setFamilyCount(f.base,Math.max(0,Math.min(4,parseInt(e.target.value,10)||0)));
+ return d;
+}
+// Regenerate a family as a symmetric base ±N ramp, replacing its current members.
+// References to a surviving position (matched by signed lightness rank) follow the
+// new hex; references to a position removed by lowering N leave their old hex,
+// which is no longer in the palette and so renders as "(gone)".
+// Replace oldHexes in the palette with a fresh base ±n ramp, repointing surviving
+// references and leaving removed ones on their now-gone hex. Returns the removed
+// count, or null on a bad base. Shared by the count control and the base edit.
+function regenFamilyInPlace(oldHexes,baseHex,baseName,n){
+ const r=regenFamily(baseHex,n,{});
+ if(r.error){notify('cannot regenerate from '+baseHex,true);return null;}
+ const plan=stepRepointPlan(rankByLightness(oldHexes,baseHex),r.members);
+ const oldSet=new Set(oldHexes.map(h=>h.toLowerCase()));
+ let at=PALETTE.length;
+ for(let i=0;i<PALETTE.length;i++)if(oldSet.has(PALETTE[i][0].toLowerCase())){at=i;break;}
+ for(let i=PALETTE.length-1;i>=0;i--)if(oldSet.has(PALETTE[i][0].toLowerCase()))PALETTE.splice(i,1);
+ const entries=r.members.map(m=>[m.hex,m.offset===0?baseName:baseName+(m.offset>0?'+'+m.offset:String(m.offset))]);
+ PALETTE.splice(Math.min(at,PALETTE.length),0,...entries);
+ for(const [o,nw] of plan.map)repointHex(o,nw);
+ return plan.removed.length;
+}
+function setFamilyCount(baseHex,n){
+ const {families}=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']});
+ const fam=families.find(f=>f.base.toLowerCase()===baseHex.toLowerCase());
+ if(!fam)return;
+ const baseName=(fam.members.find(m=>m.hex.toLowerCase()===baseHex.toLowerCase())||{}).name||'color';
+ const removed=regenFamilyInPlace(fam.members.map(m=>m.hex),baseHex,baseName,n);
+ if(removed===null)return;
+ selectedIdx=null;renderPalette();buildTable();buildUITable();renderCode();applyGround();
+ notify('regenerated "'+baseName+'" to ±'+n+(removed?(' — '+removed+' removed step(s) show "(gone)" where used'):''),false);
+}
function notify(msg,err){const m=document.getElementById('palmsg');if(!m)return;m.textContent=msg;m.style.color=err?'#cb6b4d':'#8a9496';m.style.opacity='1';clearTimeout(m._t);m._t=setTimeout(()=>{m.style.opacity='0';},err?4000:2800);}
function applyEdit(){if(selectedIdx!==null)updateColor();else addColor();}
-function moveColor(i,dir){const j=i+dir;if(j<0||j>=PALETTE.length)return;const t=PALETTE[i];PALETTE[i]=PALETTE[j];PALETTE[j]=t;if(selectedIdx===i)selectedIdx=j;else if(selectedIdx===j)selectedIdx=i;renderPalette();buildTable();buildUITable();}
function selectColor(i){selectedIdx=i;const [hex,name]=PALETTE[i];setHex(hex);document.getElementById('newname').value=name;renderPalette();notify('editing "'+name+'" — change the value, then Enter (or Update selected) to save',false);}
function updateColor(){
if(selectedIdx===null){notify('click a palette color to select it first',true);return;}
@@ -186,10 +257,17 @@ function updateColor(){
const newHex=curHex();
const newName=(document.getElementById('newname').value.trim())||PALETTE[i][1];
if(PALETTE.some((p,j)=>j!==i&&p[1].toLowerCase()===newName.toLowerCase())){notify('another color is already named "'+newName+'" — names must be unique',true);return;}
+ // If the edited color is a family base with a ramp, recolor the whole family: regenerate from the new base at the same count.
+ const fams=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']}).families;
+ const fam=fams.find(f=>!f.neutral&&f.base.toLowerCase()===oldHex.toLowerCase());
+ const count=fam?Math.max(0,...rankByLightness(fam.members.map(m=>m.hex),fam.base).map(m=>Math.abs(m.offset))):0;
PALETTE[i]=[newHex,newName];
- for(const k in MAP){if(MAP[k]===oldHex)MAP[k]=newHex;}
- for(const f in UIMAP){if(UIMAP[f].fg===oldHex)UIMAP[f].fg=newHex;if(UIMAP[f].bg===oldHex)UIMAP[f].bg=newHex;}
- for(const ap in PKGMAP)for(const fc in PKGMAP[ap]){const o=PKGMAP[ap][fc];if(o.fg===oldHex)o.fg=newHex;if(o.bg===oldHex)o.bg=newHex;}
+ repointHex(oldHex,newHex);
+ if(fam&&count>0){
+ const oldHexes=fam.members.map(m=>m.hex.toLowerCase()===oldHex.toLowerCase()?newHex:m.hex);
+ regenFamilyInPlace(oldHexes,newHex,newName,count);
+ closePicker();selectedIdx=null;renderPalette();buildTable();buildUITable();renderCode();applyGround();notify('recolored "'+newName+'" family from the new base',false);return;
+ }
closePicker();renderPalette();buildTable();buildUITable();renderCode();applyGround();notify('updated "'+newName+'"',false);
}
function curHex(){return normHex(document.getElementById('newhexstr').value)||'#888888';}
@@ -217,12 +295,30 @@ function paintOklchPlane(H){
if(T&&contrast(cell.hex,MAP['bg'])<T){ctx.fillStyle='rgba(8,7,6,0.66)';ctx.fillRect(x,y,step,step);}}}
_planeCache={key,data:ctx.getImageData(0,0,w,h)};
}
+// --- safe-lightness guidance (spec Phase 5) ----------------------------------
+let pkSafeFace=''; // covered overlay face the picker's lightness is checked against (or '')
+function setSafeFace(f){pkSafeFace=f;if(pickerOn)paintPicker();}
+// Shade the band of the C×L plane whose lightness is too light to keep pkSafeFace
+// readable over its foreground set, with the L_max ceiling as the band's lower
+// edge. One marker computed via lMax at the current chroma, not a per-pixel mask.
+function paintSafeBand(C,H){
+ const el=document.getElementById('svsafe');if(!el)return;
+ if(!pkSafeFace||pkModel!=='oklch'){el.style.display='none';return;}
+ const fs=fgSetForFace(pkSafeFace);
+ if(fs.reason||!fs.set.length){el.style.display='none';return;}
+ const sv=document.getElementById('sv'),h=sv.clientHeight,res=lMax(H,C,fs.set,WORST_TARGET);
+ if(res.status==='all'){el.style.display='none';return;}
+ el.style.display='block';el.style.top='0px';
+ el.style.height=(res.status==='none'?h:Math.max(0,(1-res.L)*h))+'px';
+ el.title='safe-lightness ceiling for '+pkSafeFace+' ('+(res.status==='none'?'no safe lightness — a foreground is too dark':'L_max '+res.L.toFixed(3)+(res.status==='clamp'?', chroma-clamped':''))+')';
+}
function paintPicker(){const sv=document.getElementById('sv');if(!sv)return;
const w=sv.clientWidth,h=sv.clientHeight,hh=document.getElementById('hue').clientHeight;
if(pkModel==='oklch'){const [L,C,H]=readOklch();sv.style.background='#15120f';paintOklchPlane(H);
document.getElementById('svcur').style.left=(Math.min(1,C/OKLCH_CMAX)*w)+'px';
document.getElementById('svcur').style.top=((1-L)*h)+'px';
- document.getElementById('huecur').style.top=((H/360)*hh)+'px';return;}
+ document.getElementById('huecur').style.top=((H/360)*hh)+'px';paintSafeBand(C,H);return;}
+ const sb=document.getElementById('svsafe');if(sb)sb.style.display='none';
sv.style.background=`linear-gradient(to top,#000,rgba(0,0,0,0)),linear-gradient(to right,#fff,rgba(255,255,255,0)),hsl(${pkH},100%,50%)`;
document.getElementById('svcur').style.left=(pkS*w)+'px';document.getElementById('svcur').style.top=((1-pkV)*h)+'px';document.getElementById('huecur').style.top=((pkH/360)*hh)+'px';drawMask();}
function pkReadout(h){const e=document.getElementById('pkhex');if(e)e.textContent=h;const c=document.getElementById('pkcon');if(c){const r=contrast(h,MAP['bg']);c.textContent=r.toFixed(1)+' '+rating(r);c.style.color=ratingColor(r);}
@@ -253,6 +349,7 @@ function closePicker(){if(!pickerOn)return;pickerOn=false;const p=document.getEl
function pkOutside(e){if(!e.target.closest('#picker')&&!e.target.closest('#swatch'))closePicker();}
function pkDrag(el,fn){el.addEventListener('pointerdown',e=>{e.preventDefault();fn(e);const mv=ev=>fn(ev),up=()=>{document.removeEventListener('pointermove',mv);document.removeEventListener('pointerup',up);};document.addEventListener('pointermove',mv);document.addEventListener('pointerup',up);});}
function initPicker(){const sw=document.getElementById('swatch');if(!sw)return;sw.style.background=curHex();sw.onclick=()=>pickerOn?closePicker():openPicker();
+ const sf=document.getElementById('safefor');if(sf&&sf.options.length<=1)COVERED_FACES.forEach(f=>{const o=document.createElement('option');o.value=f;o.textContent=f;sf.appendChild(o);});
pkDrag(document.getElementById('sv'),e=>{const r=document.getElementById('sv').getBoundingClientRect();const fx=Math.max(0,Math.min(1,(e.clientX-r.left)/r.width)),fy=Math.max(0,Math.min(1,(e.clientY-r.top)/r.height));
if(pkModel==='oklch'){setOklchInputs(1-fy,fx*OKLCH_CMAX,readOklch()[2]);pkOklchSet();}else{pkS=fx;pkV=1-fy;pkSet();}});
pkDrag(document.getElementById('hue'),e=>{const r=document.getElementById('hue').getBoundingClientRect();const fy=Math.max(0,Math.min(1,(e.clientY-r.top)/r.height));
@@ -266,7 +363,10 @@ function initPicker(){const sw=document.getElementById('swatch');if(!sw)return;s
function addColor(){const h=curHex();const name=document.getElementById('newname').value.trim();
if(!name){notify('name the color before adding it',true);return;}
if(PALETTE.some(p=>p[1].toLowerCase()===name.toLowerCase())){notify('a color named "'+name+'" already exists — select it and use Update selected to change its value',true);return;}
- PALETTE.push([h,name]);document.getElementById('newname').value='';selectedIdx=null;closePicker();renderPalette();buildTable();notify('added "'+name+'"',false);}
+ PALETTE.push([h,name]);const healed=healGone(name,h);document.getElementById('newname').value='';selectedIdx=null;closePicker();
+ renderPalette();buildTable();buildUITable();
+ if(healed){renderCode();applyGround();if(document.getElementById('pkgbody'))buildPkgTable();buildPkgPreview();}
+ notify(healed?('added "'+name+'" and reconnected its assignments'):('added "'+name+'"'),false);}
function themeName(){return (document.getElementById('themename').value||'theme').trim()||'theme';}
function fileSlug(){return slugify(themeName());}
function exportObj(){const a={};CATS.forEach(c=>a[c[0]]=MAP[c[0]]);const o={name:themeName(),palette:PALETTE,assignments:a,bold:Object.keys(BOLD).filter(k=>BOLD[k]),italic:Object.keys(ITALIC).filter(k=>ITALIC[k]),ui:UIMAP};if(LOCKED.size)o.locks=[...LOCKED];const pk=packagesForExport(PKGMAP);if(Object.keys(pk).length)o.packages=pk;return o;}
@@ -280,7 +380,7 @@ async function saveTheme(){const data=JSON.stringify(exportObj(),null,1);
try{if(!fileHandle)fileHandle=await window.showSaveFilePicker({suggestedName:fileSlug()+'.json',types:[{description:'theme JSON',accept:{'application/json':['.json']}}]});
const w=await fileHandle.createWritable();await w.write(data);await w.close();notify('saved "'+themeName()+'"',false);updateTitle();
}catch(e){if(e&&e.name!=='AbortError')notify('save failed: '+e.message,true);}}
-function applyImported(text){const d=JSON.parse(text);if(d.name)document.getElementById('themename').value=d.name;if(d.palette)PALETTE=d.palette;if(d.assignments)Object.assign(MAP,d.assignments);
+function applyImported(text){const d=JSON.parse(text);lastGone={};if(d.name)document.getElementById('themename').value=d.name;if(d.palette)PALETTE=d.palette;if(d.assignments)Object.assign(MAP,d.assignments);
BOLD={};(d.bold||[]).forEach(k=>BOLD[k]=true);ITALIC={};(d.italic||[]).forEach(k=>ITALIC[k]=true);
LOCKED=new Set(d.locks||[]);
if(d.ui)Object.assign(UIMAP,d.ui);
@@ -297,16 +397,25 @@ async function importTheme(){
const file=await h.getFile();applyImported(await file.text());fileHandle=h;updateTitle();
notify('imported "'+(themeName()||file.name)+'" — save now overwrites it',false);
}catch(e){if(e&&e.name!=='AbortError')notify('import failed: '+e.message,true);}}
-function applyGround(){document.querySelectorAll('pre').forEach(p=>p.style.background=MAP['bg']);document.querySelectorAll('.ex').forEach(e=>e.style.background=MAP['bg']);}
+// The blanket covers only the code panes and syntax example cells. UI-face
+// preview cells also carry .ex, but a face with its own bg must keep it, so
+// those rows repaint through paintUI (which also re-rates the contrast cell
+// against the new ground for faces without their own bg).
+function applyGround(){document.querySelectorAll('pre').forEach(p=>p.style.background=MAP['bg']);document.querySelectorAll('#legbody .ex').forEach(e=>e.style.background=MAP['bg']);UI_FACES.forEach(([f])=>{if(document.getElementById('uiprev-'+f))paintUI(f);});}
function uf(f){return UIMAP[f]||{};}
function udeco(o){return `font-weight:${o.bold?'bold':'normal'};font-style:${o.italic?'italic':'normal'};text-decoration:${(o.underline?'underline ':'')+(o.strike?'line-through':'')||'none'}`;}
// A face's :box, rendered as an inset box-shadow (no layout shift). Returns the
// box-shadow VALUE (or '' for no box). 'line' is a flat border in the box color
// (or the face's own color when unset); 'released'/'pressed' are the 3D button
// styles Emacs draws, derived from the background so they read on any color.
-function boxCss(b){if(!b||!b.style)return '';const w=b.width||1;
- if(b.style==='released')return `inset ${w}px ${w}px 0 #ffffff33,inset -${w}px -${w}px 0 #00000066`;
- if(b.style==='pressed')return `inset ${w}px ${w}px 0 #00000066,inset -${w}px -${w}px 0 #ffffff33`;
+function boxCss(b,bg){if(!b||!b.style)return '';const w=b.width||1;
+ if(b.style==='released'||b.style==='pressed'){
+ // Emacs derives the 3D edges from the face's background (reliefColors,
+ // ported from xterm.c); the translucent pair is only the no-bg fallback.
+ const r=bg?reliefColors(bg):{hl:null,sh:null};
+ const hl=r.hl||'#ffffff33',sh=r.sh||'#00000066';
+ const [a,z]=b.style==='released'?[hl,sh]:[sh,hl];
+ return `inset ${w}px ${w}px 0 ${a},inset -${w}px -${w}px 0 ${z}`;}
return `inset 0 0 0 ${w}px ${b.color||'currentColor'}`;}
// The per-row box control: none / line / raised / pressed. get()/set() read and
// write the face's box object (null = no box).
@@ -390,7 +499,7 @@ function buildMockFrame(){
buf+=`<div class="ln" style="background:${rowBg}"><span class="fr" data-face="fringe" style="background:${frng.bg||bg};color:${frng.fg||fg};text-align:center;font-size:10px;overflow:hidden" title="fringe">${L.cont?'&#8618;':''}</span><span class="num" data-face="${nFace}" style="color:${nFg};background:${nBg};${udeco(isc?lnc:ln)}">${i+1}</span><span class="cd">${cd||'&nbsp;'}</span></div>`;
});
let html=`<div class="mbuf" style="display:flex;background:${bg}"><div style="flex:1;min-width:0">${buf}</div><div data-face="vertical-border" title="vertical-border" style="width:3px;flex:0 0 auto;background:${vb.fg||vb.bg||'#2f343a'}"></div></div>`;
- const mlbx=boxCss(ml.box),mlibx=boxCss(mli.box);
+ const mlbx=boxCss(ml.box,ml.bg||bg),mlibx=boxCss(mli.box,mli.bg||bg);
html+=`<div class="bar" data-face="mode-line" style="background:${ml.bg||fg};color:${ml.fg||bg};${udeco(ml)}${mlbx?';box-shadow:'+mlbx:''}"> init.el (Emacs Lisp) L5 git:main </div>`;
html+=`<div class="bar" data-face="mode-line-inactive" style="background:${mli.bg||bg};color:${mli.fg||fg};${udeco(mli)}${mlibx?';box-shadow:'+mlibx:''}"> *Messages* (Fundamental) </div>`;
html+=`<div class="echo" style="color:${fg}"><span data-face="minibuffer-prompt" style="color:${mb.fg||fg};${udeco(mb)}">I-search:</span> count <span data-face="isearch-fail" style="color:${isf.fg||fg};background:${isf.bg||'transparent'};${udeco(isf)}">zzz [no match]</span></div>`;
@@ -435,7 +544,7 @@ function buildPkgTable(){
}
applyTableSort('pkgbody');
}
-function ofs(app,face){const f=PKGMAP[app][face]||{},fg=effFg(pkgEffFg(app,face)),bg=pkgEffBg(app,face);const dec=(f.underline?'underline ':'')+(f.strike?'line-through':'');const bx=boxCss(f.box);return `color:${fg};${bg?'background:'+bg+';':''}font-weight:${f.bold?'bold':'normal'};font-style:${f.italic?'italic':'normal'};text-decoration:${dec.trim()||'none'};font-size:${(f.height||1)}em${bx?';box-shadow:'+bx:''}`;}
+function ofs(app,face){const f=PKGMAP[app][face]||{},fg=effFg(pkgEffFg(app,face)),bg=pkgEffBg(app,face);const dec=(f.underline?'underline ':'')+(f.strike?'line-through':'');const bx=boxCss(f.box,bg||MAP['bg']);return `color:${fg};${bg?'background:'+bg+';':''}font-weight:${f.bold?'bold':'normal'};font-style:${f.italic?'italic':'normal'};text-decoration:${dec.trim()||'none'};font-size:${(f.height||1)}em${bx?';box-shadow:'+bx:''}`;}
function os(app,face,txt){return `<span data-face="${face}" style="${ofs(app,face)}">${txt}</span>`;}
function renderOrgPreview(){const a='org-mode',L=[];
L.push(os(a,'org-document-info-keyword','#+TITLE:')+' '+os(a,'org-document-title','Project Notes'));
@@ -736,8 +845,31 @@ function genericPreview(app){let h='<div style="padding:10px 14px;font:12pt/1.8
function buildPkgPreview(){const app=curApp(),p=document.getElementById('pkgpreview');if(!p)return;const pv=APPS[app].preview;const bespoke=['org','magit','elfeed','ghostel','dashboard','mu4e','lsp','gitgutter','flycheck','dired','dirvish','calibredb','erc','orgdrill','orgnoter','signel','pearl','slack','telega','shr'].includes(pv);p.innerHTML=pv==='org'?renderOrgPreview():pv==='magit'?renderMagitPreview():pv==='elfeed'?renderElfeedPreview():pv==='ghostel'?renderGhostelPreview():pv==='dashboard'?renderDashboardPreview():pv==='mu4e'?renderMu4ePreview():pv==='lsp'?renderLspPreview():pv==='gitgutter'?renderGitGutterPreview():pv==='flycheck'?renderFlycheckPreview():pv==='dired'?renderDiredPreview():pv==='dirvish'?renderDirvishPreview():pv==='calibredb'?renderCalibredbPreview():pv==='erc'?renderErcPreview():pv==='orgdrill'?renderOrgdrillPreview():pv==='orgnoter'?renderOrgnoterPreview():pv==='signel'?renderSignelPreview():pv==='pearl'?renderPearlPreview():pv==='slack'?renderSlackPreview():pv==='telega'?renderTelegaPreview():pv==='shr'?renderShrPreview():genericPreview(app);p.style.background=MAP['bg'];p.onclick=(e)=>{const u=e.target.closest('[data-face]');if(u)flashPkg(u.dataset.face);};const lbl=document.getElementById('pkgprevlabel');if(lbl)lbl.textContent=bespoke?(APPS[app].label+' preview'):'preview (generic — face names in their own colors)';}
function resetApp(){const app=curApp();PKGMAP[app]={};for(const [face,label,d] of APPS[app].faces)PKGMAP[app][face]=seedFace(d);pkgChanged();}
function syncPkgHeight(){const t=document.getElementById('pkgtable'),m=document.getElementById('pkgpreview');if(!t||!m)return;const lb=m.previousElementSibling,lbh=lb?lb.getBoundingClientRect().height+10:30;m.style.height=Math.max(t.getBoundingClientRect().height-lbh,220)+'px';}
-function paintUI(face){const pv=document.getElementById('uiprev-'+face);if(!pv)return;const o=UIMAP[face];pv.style.color=effFg(o.fg);pv.style.background=effBg(o.bg);pv.style.fontWeight=o.bold?'bold':'normal';pv.style.fontStyle=o.italic?'italic':'normal';pv.style.textDecoration=(o.underline?'underline ':'')+(o.strike?'line-through':'')||'none';pv.style.boxShadow=boxCss(o.box);
- const cr=document.getElementById('uicr-'+face);if(cr){const efg=effFg(o.fg),ebg=effBg(o.bg),r=contrast(efg,ebg);cr.innerHTML=crHtml(r);}}
+// --- worst-case readout for the covered overlay faces (spec Phase 4) ---------
+// Default WCAG target for the worst-case verdict (AA). AAA is selectable.
+let WORST_TARGET=4.5;
+// The live v1 foreground set for a covered overlay face: the syntax-token colors
+// (every assignable category except the ground) plus the default foreground.
+function fgSetForFace(face){
+ const syntaxAssignments=CATS.filter(c=>c[0]!=='bg'&&c[0]!=='p').map(c=>({role:c[0],hex:effFg(MAP[c[0]])}));
+ return fgSetFor(face,{covered:COVERED_FACES,syntaxAssignments,defaultFg:MAP['p']});
+}
+// The worst-case contrast cell for a covered face: the floor over its foreground
+// set against its effective background, naming the limiting foreground. Returns
+// null for an out-of-scope face so the caller keeps the single-pair readout.
+function worstCellHtml(face){
+ const r=fgSetForFace(face);
+ if(r.reason==='out-of-scope')return null;
+ if(r.reason==='empty'||!r.set.length)return '<span title="this overlay has no syntax foreground set yet">no fg set</span>';
+ const bg=effBg(uf(face).bg),fl=floor(bg,r.set),verdict=fl.ratio>=WORST_TARGET?'PASS':'FAIL';
+ const s='worst: '+fl.limitingLabel+' '+fl.limitingHex+' — '+fl.ratio.toFixed(1)+' '+verdict;
+ return `<span style="color:${ratingColor(fl.ratio)}" title="${esc(s)}">${esc(s)}</span>`;
+}
+// Repaint every covered overlay face (their floors depend on the syntax palette,
+// so a syntax-color edit has to refresh them even though it doesn't rebuild the table).
+function repaintCovered(){COVERED_FACES.forEach(f=>{if(UIMAP[f]&&document.getElementById('uicr-'+f))paintUI(f);});}
+function paintUI(face){const pv=document.getElementById('uiprev-'+face);if(!pv)return;const o=UIMAP[face];pv.style.color=effFg(o.fg);pv.style.background=effBg(o.bg);pv.style.fontWeight=o.bold?'bold':'normal';pv.style.fontStyle=o.italic?'italic':'normal';pv.style.textDecoration=(o.underline?'underline ':'')+(o.strike?'line-through':'')||'none';pv.style.boxShadow=boxCss(o.box,effBg(o.bg));
+ const cr=document.getElementById('uicr-'+face);if(cr){const w=worstCellHtml(face);if(w!==null){cr.innerHTML=w;}else{const efg=effFg(o.fg),ebg=effBg(o.bg),r=contrast(efg,ebg);cr.innerHTML=crHtml(r);}}}
function buildUITable(){
const tb=document.getElementById('uibody');tb.innerHTML='';
for(const [face,label,ex] of UI_FACES){
@@ -914,3 +1046,198 @@ if(location.hash==='#readouttest'){const hex='#67809c';document.getElementById('
const sane=Math.abs(lch.L-0.591)<0.01&&Math.abs(lch.C-0.052)<0.01&&Math.abs(lch.H-251.6)<2;
const ok=wired&&sane;document.title='READOUTTEST '+(ok?'PASS':'FAIL');
const d=document.createElement('div');d.id='readouttest';d.textContent='READOUTTEST '+(ok?'PASS':'FAIL')+' oklch='+o+' | apca='+a+' | wcag='+w;document.body.appendChild(d);}
+// Worst-case readout gate (open with #contrasttest): a covered overlay face shows
+// the floor over its foreground set and names the limiting foreground, an
+// out-of-scope face keeps the single-pair readout, and an empty set reads "no fg set".
+if(location.hash==='#contrasttest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveMAP=Object.assign({},MAP),saveUI=JSON.parse(JSON.stringify(UIMAP));
+ MAP['p']='#f0fef0';MAP['kw']='#67809c';MAP['str']='#a3b18a';MAP['bg']='#000000';
+ UIMAP['region']={fg:null,bg:'#202830',bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ const cell=document.getElementById('uicr-region');
+ A(cell&&/^worst:/.test(cell.textContent),'region shows the worst-case readout: '+(cell&&cell.textContent));
+ A(cell&&cell.textContent.includes('#67809c'),'limiting fg is keyword blue: '+(cell&&cell.textContent));
+ A(cell&&/\b(PASS|FAIL)\b/.test(cell.textContent),'readout carries a verdict');
+ const fl=floor('#202830',fgSetForFace('region').set);
+ A(fl.limitingHex==='#67809c','floor limiting is blue, got '+fl.limitingHex);
+ A(Math.abs(fl.ratio-contrast('#67809c','#202830'))<1e-9,'floor ratio matches blue-on-bg');
+ const ml=document.getElementById('uicr-mode-line');
+ A(worstCellHtml('mode-line')===null,'mode-line is out of scope (single-pair)');
+ A(ml&&/^\d/.test(ml.textContent.trim()),'mode-line cell is a numeric ratio: '+(ml&&ml.textContent));
+ MAP['p']='';CATS.forEach(c=>{if(c[0]!=='bg')MAP[c[0]]='';});buildUITable();
+ const empty=document.getElementById('uicr-region');
+ A(empty&&empty.textContent.trim()==='no fg set','empty set reads the no-set message: '+(empty&&empty.textContent));
+ // A two-color face (own fg AND own bg) rates its own pair, never the ground bg.
+ UIMAP['mode-line']={fg:'#112233',bg:'#aabbcc',bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ const two=document.getElementById('uicr-mode-line'),twoWant=contrast('#112233','#aabbcc');
+ A(two&&Math.abs(parseFloat(two.textContent)-twoWant)<0.06,'ui two-color face rates own fg-on-bg: got '+(two&&two.textContent.trim())+' want '+twoWant.toFixed(1));
+ const tApp=Object.keys(APPS)[0],tFace=APPS[tApp].faces[0][0],savePF=JSON.parse(JSON.stringify(PKGMAP[tApp][tFace]));
+ Object.assign(PKGMAP[tApp][tFace],{fg:'#112233',bg:'#aabbcc',inherit:null});buildPkgTable();
+ const prow=document.querySelector('#pkgbody tr[data-face="'+tFace+'"]'),pcell=prow&&prow.children[5];
+ A(pcell&&Math.abs(parseFloat(pcell.textContent)-twoWant)<0.06,'pkg two-color face rates own fg-on-bg: got '+(pcell&&pcell.textContent.trim())+' want '+twoWant.toFixed(1));
+ PKGMAP[tApp][tFace]=savePF;buildPkgTable();
+ // A ground-bg change must not clobber a face's own preview bg, must leave a
+ // two-color ratio alone, and must re-rate a ground-dependent face's cell.
+ UIMAP['fringe']={fg:'#ddeeff',bg:null,bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ MAP['bg']='#440000';applyGround();
+ const pv=document.getElementById('uiprev-mode-line');
+ A(pv&&pv.style.background==='rgb(170, 187, 204)','ground change keeps a face own preview bg: got '+(pv&&pv.style.background));
+ const twoAfter=document.getElementById('uicr-mode-line');
+ A(twoAfter&&Math.abs(parseFloat(twoAfter.textContent)-twoWant)<0.06,'ground change leaves a two-color ratio alone: got '+(twoAfter&&twoAfter.textContent.trim()));
+ const frc=document.getElementById('uicr-fringe'),frWant=contrast('#ddeeff','#440000');
+ A(frc&&Math.abs(parseFloat(frc.textContent)-frWant)<0.06,'ground change re-rates a ground-dependent face: got '+(frc&&frc.textContent.trim())+' want '+frWant.toFixed(1));
+ // A default-fg (p) change through the real syntax dropdown re-rates a face
+ // whose fg falls back to it. Drives the DOM so the handler wiring is pinned.
+ UIMAP['fringe']={fg:null,bg:'#aabbcc',bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ const pLocked=LOCKED.has('p');if(pLocked){LOCKED.delete('p');buildTable();}
+ const pdd=document.querySelector('#legbody tr[data-kind="p"] .cdd');
+ if(pdd){pdd.click();
+ const pHex=PALETTE.find(p=>p[0]!==MAP['p'])[0];
+ const prow=[...document.querySelectorAll('.cddpop .cddrow')].find(r=>r.querySelector('.cddhx').textContent===pHex);
+ if(prow)prow.click();
+ const pf=document.getElementById('uicr-fringe'),pfWant=contrast(pHex,'#aabbcc');
+ A(prow&&pf&&Math.abs(parseFloat(pf.textContent)-pfWant)<0.06,'default-fg change re-rates a p-fallback face: got '+(pf&&pf.textContent.trim())+' want '+pfWant.toFixed(1));
+ }else A(false,'syntax table has a p row with a dropdown');
+ if(pLocked){LOCKED.add('p');buildTable();}
+ for(const k in MAP)delete MAP[k];Object.assign(MAP,saveMAP);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveUI);buildUITable();applyGround();
+ document.title='CONTRASTTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='contrasttest';d.textContent='CONTRASTTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Bevel gate (open with #beveltest): released/pressed boxes derive their
+// highlight and shadow from the face's effective bg per Emacs's relief
+// algorithm, and pressed draws the shadow edge first.
+if(location.hash==='#beveltest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveUI=JSON.parse(JSON.stringify(UIMAP));
+ UIMAP['mode-line']={fg:'#d8dee9',bg:'#30343c',bold:false,italic:false,underline:false,strike:false,box:{style:'released',width:1,color:null}};
+ buildUITable();
+ const pv=document.getElementById('uiprev-mode-line');
+ const bs=pv&&pv.style.boxShadow;
+ A(bs&&bs.includes('rgb(113, 118, 127)'),'released highlight derives from the face bg (#71767f): '+bs);
+ A(bs&&bs.includes('rgb(15, 17, 22)'),'released shadow derives from the face bg (#0f1116): '+bs);
+ UIMAP['mode-line'].box={style:'pressed',width:1,color:null};paintUI('mode-line');
+ const bs2=pv&&pv.style.boxShadow;
+ A(bs2&&bs2.includes('rgb(15, 17, 22)')&&bs2.includes('rgb(113, 118, 127)')&&bs2.indexOf('rgb(15, 17, 22)')<bs2.indexOf('rgb(113, 118, 127)'),'pressed swaps the pair (shadow edge first): '+bs2);
+ UIMAP['mode-line'].box={style:'line',width:1,color:'#ff0000'};paintUI('mode-line');
+ A(pv&&pv.style.boxShadow.includes('rgb(255, 0, 0)'),'line style keeps its explicit color: '+(pv&&pv.style.boxShadow));
+ for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveUI);buildUITable();
+ document.title='BEVELTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='beveltest';d.textContent='BEVELTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Safe-lightness gate (open with #safetest): the OKLCH picker shades the unsafe
+// lightness band for a selected covered face and hides it when no face is selected.
+if(location.hash==='#safetest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveMAP=Object.assign({},MAP);
+ MAP['p']='#f0fef0';MAP['kw']='#67809c';MAP['bg']='#000000';
+ document.getElementById('newhexstr').value='#202830';openPicker();setPkModel('oklch');
+ setSafeFace('region');
+ const band=document.getElementById('svsafe');
+ A(band&&band.style.display==='block','safe band shows for an in-scope face');
+ A(band&&parseFloat(band.style.height)>0,'safe band has a positive height: '+(band&&band.style.height));
+ setSafeFace('');
+ A(band&&band.style.display==='none','safe band hidden when no face is selected');
+ for(const k in MAP)delete MAP[k];Object.assign(MAP,saveMAP);
+ setPkModel('hsv');closePicker();
+ document.title='SAFETEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='safetest';d.textContent='SAFETEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Gone-rebind gate (open with #healtest): deleting a named color then recreating
+// the name re-points the assignments stranded on the old hex to the new color.
+if(location.hash==='#healtest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveU=JSON.parse(JSON.stringify(UIMAP)),savePK=JSON.parse(JSON.stringify(PKGMAP)),saveG=Object.assign({},lastGone),saveSel=selectedIdx;
+ PALETTE=[['#0d0b0a','ground'],['#cdced1','fg'],['#67809c','blue']];MAP['kw']='#67809c';lastGone={};selectedIdx=null;renderPalette();buildTable();
+ const blue=[...document.querySelectorAll('#pals .pchip')].find(c=>c.querySelector('.nm')&&c.querySelector('.nm').value==='blue');
+ A(!!(blue&&blue.querySelector('.rm')),'blue chip has a remove button');
+ if(blue&&blue.querySelector('.rm'))blue.querySelector('.rm').click();
+ A(!PALETTE.some(p=>p[1]==='blue'),'blue was deleted');
+ A(lastGone['blue']==='#67809c','delete recorded the gone name->hex');
+ document.getElementById('newhexstr').value='#5a7a9a';document.getElementById('newname').value='blue';selectedIdx=null;addColor();
+ A(MAP['kw']==='#5a7a9a','assignment re-bound to the recreated name, got '+MAP['kw']);
+ A(!('blue' in lastGone),'heal consumed the gone entry');
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveU);PKGMAP=savePK;lastGone=saveG;selectedIdx=saveSel;
+ renderPalette();buildTable();buildUITable();if(document.getElementById('pkgbody'))buildPkgTable();
+ document.title='HEALTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='healtest';d.textContent='HEALTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Family-strip gate (open with #familytest): the palette renders as the pinned
+// ground strip plus hue families, chips keep their controls, and renaming a color
+// to anything leaves it in the same strip (grouping is by hex, not name).
+if(location.hash==='#familytest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveSel=selectedIdx;
+ MAP['bg']='#0d0b0a';MAP['p']='#f0fef0';
+ PALETTE=[['#0d0b0a','ground'],['#f0fef0','fg'],['#c0402a','red'],['#3a6ea5','blue'],['#808080','gray']];selectedIdx=null;renderPalette();
+ const strips=[...document.querySelectorAll('#pals .fstrip')];
+ A(strips.length&&strips[0].classList.contains('ground'),'ground strip is pinned first');
+ A(strips[0].querySelectorAll('.pchip').length===2,'ground strip carries bg + fg');
+ A(strips.length>=4,'ground + neutral + red + blue strips, got '+strips.length);
+ const redChip=[...document.querySelectorAll('#pals .pchip')].find(c=>c.querySelector('.nm')&&c.querySelector('.nm').value==='red');
+ A(!!redChip&&!!redChip.querySelector('.rm')&&!!redChip.querySelector('.nm'),'a family chip keeps remove + rename controls');
+ const redFamily=redChip&&redChip.closest('.fstrip').dataset.family;
+ const ri=PALETTE.findIndex(p=>p[1]==='red');PALETTE[ri][1]='zztop-absurd';renderPalette();
+ const renamed=[...document.querySelectorAll('#pals .pchip')].find(c=>c.querySelector('.nm')&&c.querySelector('.nm').value==='zztop-absurd');
+ A(!!renamed&&renamed.closest('.fstrip').dataset.family===redFamily,'a renamed color stays in the same strip');
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);selectedIdx=saveSel;renderPalette();
+ document.title='FAMILYTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='familytest';d.textContent='FAMILYTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Count-control gate (open with #counttest): the per-family count regenerates the
+// family — count up adds symmetric steps, count down drops the extremes, a
+// reference to a surviving step follows the new hex, a reference to a removed step
+// is left on its old (now-gone) hex.
+if(location.hash==='#counttest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveU=JSON.parse(JSON.stringify(UIMAP)),saveSel=selectedIdx;
+ MAP['bg']='#000000';MAP['p']='#f0fef0';
+ PALETTE=[['#0d0b0a','ground'],['#f0fef0','fg']];
+ regenFamily('#67809c',2).members.forEach(m=>PALETTE.push([m.hex,m.offset===0?'blue':'blue'+(m.offset>0?'+'+m.offset:m.offset)]));
+ const innerOld=regenFamily('#67809c',2).members.find(m=>m.offset===1).hex; // survives a count change
+ const outerOld=regenFamily('#67809c',2).members.find(m=>m.offset===2).hex; // dropped on count-down
+ UIMAP['region']={fg:null,bg:innerOld,bold:false,italic:false,underline:false,strike:false};
+ UIMAP['highlight']={fg:null,bg:outerOld,bold:false,italic:false,underline:false,strike:false};
+ selectedIdx=null;renderPalette();
+ setFamilyCount('#67809c',1);
+ const palHexes=new Set(PALETTE.map(p=>p[0].toLowerCase()));
+ A(!palHexes.has(outerOld.toLowerCase()),'outer step removed from palette on count down');
+ A(UIMAP['highlight'].bg.toLowerCase()===outerOld.toLowerCase(),'a removed-step reference stays on its old (gone) hex');
+ const newInner=regenFamily('#67809c',1).members.find(m=>m.offset===1).hex;
+ A(UIMAP['region'].bg.toLowerCase()===newInner.toLowerCase(),'a surviving-step reference followed the regenerate, got '+UIMAP['region'].bg);
+ setFamilyCount('#67809c',3);
+ const want3=regenFamily('#67809c',3).members.map(m=>m.hex.toLowerCase());
+ const have=new Set(PALETTE.map(p=>p[0].toLowerCase()));
+ A(want3.every(h=>have.has(h)),'count up to 3 adds all 7 ramp colors to the palette');
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveU);selectedIdx=saveSel;renderPalette();
+ document.title='COUNTTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='counttest';d.textContent='COUNTTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Base-edit + ground-edit gate (open with #baseedittest): editing a family base
+// recolors the whole family at the same count and references follow; editing a
+// ground swatch writes the bg/fg assignment.
+if(location.hash==='#baseedittest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveU=JSON.parse(JSON.stringify(UIMAP)),saveSel=selectedIdx;
+ MAP['bg']='#0d0b0a';MAP['p']='#f0fef0';
+ PALETTE=[['#0d0b0a','ground'],['#f0fef0','fg']];
+ regenFamily('#67809c',2).members.forEach(m=>PALETTE.push([m.hex,m.offset===0?'blue':'blue'+(m.offset>0?'+'+m.offset:m.offset)]));
+ UIMAP['region']={fg:null,bg:'#67809c',bold:false,italic:false,underline:false,strike:false};
+ renderPalette();buildUITable();
+ selectedIdx=PALETTE.findIndex(p=>p[0].toLowerCase()==='#67809c');
+ document.getElementById('newhexstr').value='#3a8a8a';document.getElementById('newname').value='teal';
+ updateColor();
+ const fam=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']}).families.find(f=>!f.neutral);
+ A(fam&&fam.members.some(m=>m.hex.toLowerCase()==='#3a8a8a'),'family base recolored to the new hex');
+ A(fam&&fam.members.length===5,'count preserved (±2 → 5 members), got '+(fam&&fam.members.length));
+ A(!new Set(PALETTE.map(p=>p[0].toLowerCase())).has('#67809c'),'old base removed from palette');
+ A(UIMAP['region'].bg.toLowerCase()==='#3a8a8a','a reference to the base followed to the new base hex');
+ // ground edit: select bg, change hex, MAP.bg follows
+ selectedIdx=PALETTE.findIndex(p=>p[0].toLowerCase()==='#0d0b0a');
+ document.getElementById('newhexstr').value='#101010';document.getElementById('newname').value='ground';
+ updateColor();
+ A(MAP['bg'].toLowerCase()==='#101010','editing the bg swatch wrote the bg assignment, got '+MAP['bg']);
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveU);selectedIdx=saveSel;renderPalette();
+ document.title='BASEEDITTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='baseedittest';d.textContent='BASEEDITTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Round-trip gate (open with #roundtriptest): export stays a flat palette and
+// import needs no family reconstruction, so export → import → export is identical.
+if(location.hash==='#roundtriptest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const before=JSON.stringify(exportObj());
+ applyImported(before);
+ const after=JSON.stringify(exportObj());
+ A(before===after,'export → import → export is byte-identical');
+ const obj=JSON.parse(after);
+ A(Array.isArray(obj.palette)&&obj.palette.every(e=>Array.isArray(e)&&e.length===2),'exported palette is still a flat [hex,name] list');
+ document.title='ROUNDTRIPTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='roundtriptest';d.textContent='ROUNDTRIPTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
diff --git a/scripts/theme-studio/colormath.js b/scripts/theme-studio/colormath.js
index 167a5ea1..2a7328e5 100644
--- a/scripts/theme-studio/colormath.js
+++ b/scripts/theme-studio/colormath.js
@@ -190,4 +190,31 @@ function paletteWarnings(palette, threshold = 0.02, cap = 5) {
return { warnings: pairs.slice(0, cap), overflow: Math.max(0, pairs.length - cap), nearest };
}
-export { srgb2oklab, oklab2oklch, oklch2oklab, oklch2hex, apca, deltaE, hex2rgb, lin, rl, contrast, rating, hsv2rgb, rgb2hsv, rgb2hex, oklab2lrgb, inGamut, lrgb2hex, planeCell, paletteWarnings };
+// --- 3D-box relief colors, matching Emacs's renderer ---------------------
+// Port of x_alloc_lighter_color (Emacs 30 xterm.c): highlight = bg x 1.2
+// (delta 0x8000), shadow = bg x 0.6 (delta 0x4000), both in 16-bit channel
+// space. Backgrounds dimmer than 48000/65535 (by Emacs's 2R+3G+B/6 weighting)
+// get an additive boost of delta*dimness*factor/2, because scaling alone
+// barely moves a dark color. When the result still equals the background
+// (pure black shadow, pure white highlight), Emacs retries with bg+delta.
+function reliefColors(bgHex) {
+ const rgb = hex2rgb(bgHex);
+ if (rgb.some((c) => Number.isNaN(c))) return { hl: null, sh: null };
+ const ch16 = rgb.map((c) => c * 257);
+ const one = (factor, delta) => {
+ let nw = ch16.map((c) => Math.min(0xffff, factor * c));
+ const bright = (2 * ch16[0] + 3 * ch16[1] + ch16[2]) / 6;
+ if (bright < 48000) {
+ const md = delta * (1 - bright / 48000) * factor / 2;
+ nw = factor < 1
+ ? nw.map((v) => Math.max(0, v - md))
+ : nw.map((v) => Math.min(0xffff, v + md));
+ }
+ if (nw.every((v, i) => Math.round(v) === ch16[i]))
+ nw = ch16.map((c) => Math.min(0xffff, c + delta));
+ return '#' + nw.map((v) => Math.round(v / 257).toString(16).padStart(2, '0')).join('');
+ };
+ return { hl: one(1.2, 0x8000), sh: one(0.6, 0x4000) };
+}
+
+export { srgb2oklab, oklab2oklch, oklch2oklab, oklch2hex, apca, deltaE, hex2rgb, lin, rl, contrast, rating, hsv2rgb, rgb2hsv, rgb2hex, oklab2lrgb, inGamut, lrgb2hex, planeCell, paletteWarnings, reliefColors };
diff --git a/scripts/theme-studio/generate.py b/scripts/theme-studio/generate.py
index ae525de7..b6e2fc73 100644
--- a/scripts/theme-studio/generate.py
+++ b/scripts/theme-studio/generate.py
@@ -78,7 +78,9 @@ UIMAP={"cursor":{"fg":None,"bg":"#a9b2bb"},"region":{"fg":None,"bg":"#264364"},
# Placed after every default it overrides (notably UIMAP) so the merge has targets.
# Mirrors what the in-page Import does, so reseed and import agree.
LOCKS=[]; ITALIC=[]
-_seed=os.environ.get('THEME_STUDIO_SEED')
+# sterling is the default theme; THEME_STUDIO_SEED=<file>.json overrides to view another.
+_seed=os.environ.get('THEME_STUDIO_SEED') or 'sterling.json'
+_d={}
if _seed:
_d=json.load(open(os.path.join(HERE,_seed)))
if _d.get('palette'): PALETTE=_d['palette']
@@ -153,12 +155,12 @@ ORG_SEED={
"org-level-5":{"fg":"terracotta"},"org-level-6":{"fg":"tan"},"org-level-7":{"fg":"sage"},"org-level-8":{"fg":"steel"},
"org-headline-done":{"fg":"pewter"},"org-todo":{"fg":"terracotta","bold":True},"org-done":{"fg":"sage","bold":True},
"org-priority":{"fg":"gold","bold":True},"org-tag":{"fg":"tan"},"org-tag-group":{"fg":"tan"},
- "org-special-keyword":{"fg":"pewter"},"org-drawer":{"fg":"pewter"},"org-property-value":{"fg":"steel"},
+ "org-special-keyword":{"fg":"pewter","bold":True},"org-drawer":{"fg":"pewter"},"org-property-value":{"fg":"steel"},
"org-checkbox":{"fg":"gold","inherit":"fixed-pitch"},"org-checkbox-statistics-todo":{"fg":"terracotta"},
"org-checkbox-statistics-done":{"fg":"sage"},"org-warning":{"fg":"terracotta","bold":True},
- "org-link":{"fg":"blue"},"org-footnote":{"fg":"blue"},"org-date":{"fg":"steel","inherit":"fixed-pitch"},
+ "org-link":{"fg":"blue","underline":True},"org-footnote":{"fg":"blue"},"org-date":{"fg":"steel","inherit":"fixed-pitch"},
"org-sexp-date":{"fg":"steel"},"org-date-selected":{"fg":"ground","bg":"gold"},"org-target":{"fg":"regal"},
- "org-macro":{"fg":"regal"},"org-cite":{"fg":"blue"},"org-cite-key":{"fg":"blue"},
+ "org-macro":{"fg":"regal"},"org-cite":{"fg":"blue","underline":True},"org-cite-key":{"fg":"blue","underline":True},
"org-block":{"fg":"white","bg":"bg-dim","inherit":"fixed-pitch"},
"org-block-begin-line":{"fg":"pewter","bg":"bg-dim","inherit":"fixed-pitch"},
"org-block-end-line":{"fg":"pewter","bg":"bg-dim","inherit":"fixed-pitch"},
@@ -195,8 +197,8 @@ MAGIT_SEED={
"magit-diff-file-heading-highlight":{"fg":"white","bold":True,"bg":"bg-dim"},
"magit-diff-hunk-heading":{"fg":"steel","bg":"gunmetal"},"magit-diff-hunk-heading-highlight":{"fg":"white","bg":"gunmetal"},
"magit-diffstat-added":{"fg":"sage"},"magit-diffstat-removed":{"fg":"terracotta"},
- "magit-branch-current":{"fg":"blue","bold":True},"magit-branch-local":{"fg":"blue"},
- "magit-branch-remote":{"fg":"sage"},"magit-branch-remote-head":{"fg":"sage","bold":True},
+ "magit-branch-current":{"fg":"blue","bold":True,"box":{"style":"line","width":1,"color":None}},"magit-branch-local":{"fg":"blue"},
+ "magit-branch-remote":{"fg":"sage"},"magit-branch-remote-head":{"fg":"sage","bold":True,"box":{"style":"line","width":1,"color":None}},
"magit-head":{"fg":"blue","bold":True},"magit-tag":{"fg":"gold"},"magit-hash":{"fg":"pewter"},
"magit-filename":{"fg":"steel"},"magit-dimmed":{"fg":"pewter"},"magit-keyword":{"fg":"regal"},
"magit-keyword-squash":{"fg":"terracotta"},"magit-refname":{"fg":"pewter"},"magit-log-author":{"fg":"tan"},
@@ -245,44 +247,43 @@ DASHBOARD_SEED={
# face list is curated from the set the dupre theme already themes.
MU4E_FACES=("mu4e-title-face mu4e-context-face mu4e-modeline-face mu4e-ok-face mu4e-warning-face "
"mu4e-header-title-face mu4e-header-key-face mu4e-header-value-face mu4e-header-face mu4e-header-highlight-face mu4e-header-marks-face "
- "mu4e-unread-face mu4e-flagged-face mu4e-replied-face mu4e-forwarded-face mu4e-draft-face mu4e-trashed-face mu4e-moved-face mu4e-related-face "
- "mu4e-contact-face mu4e-special-header-value-face mu4e-attach-number-face mu4e-url-number-face mu4e-link-face "
- "mu4e-cited-1-face mu4e-cited-2-face mu4e-cited-3-face mu4e-cited-4-face mu4e-cited-5-face mu4e-cited-6-face mu4e-cited-7-face "
- "mu4e-footer-face mu4e-region-code mu4e-system-face mu4e-highlight-face mu4e-compose-header-face mu4e-compose-separator-face").split()
+ "mu4e-unread-face mu4e-flagged-face mu4e-replied-face mu4e-forwarded-face mu4e-draft-face mu4e-trashed-face mu4e-related-face "
+ "mu4e-contact-face mu4e-special-header-value-face mu4e-url-number-face mu4e-link-face "
+ ""
+ "mu4e-footer-face mu4e-region-code mu4e-system-face mu4e-highlight-face mu4e-compose-separator-face").split()
MU4E_SEED={
"mu4e-title-face":{"fg":"blue","bold":True},"mu4e-context-face":{"fg":"blue","bold":True},"mu4e-modeline-face":{"fg":"silver"},"mu4e-ok-face":{"fg":"sage","bold":True},"mu4e-warning-face":{"fg":"gold","bold":True},
- "mu4e-header-title-face":{"fg":"blue","bold":True},"mu4e-header-key-face":{"fg":"blue","bold":True},"mu4e-header-value-face":{"fg":"silver"},"mu4e-header-face":{"fg":"#cdced1"},"mu4e-header-highlight-face":{"bg":"gunmetal"},"mu4e-header-marks-face":{"fg":"gold"},
- "mu4e-unread-face":{"fg":"white","bold":True},"mu4e-flagged-face":{"fg":"gold"},"mu4e-replied-face":{"fg":"silver"},"mu4e-forwarded-face":{"fg":"silver"},"mu4e-draft-face":{"fg":"steel","italic":True},"mu4e-trashed-face":{"fg":"pewter","strike":True},"mu4e-moved-face":{"fg":"steel","italic":True},"mu4e-related-face":{"fg":"steel","italic":True},
- "mu4e-contact-face":{"fg":"#cdced1"},"mu4e-special-header-value-face":{"fg":"silver"},"mu4e-attach-number-face":{"fg":"blue","bold":True},"mu4e-url-number-face":{"fg":"blue","bold":True},"mu4e-link-face":{"fg":"blue","underline":True},
- "mu4e-cited-1-face":{"fg":"silver"},"mu4e-cited-2-face":{"fg":"steel"},"mu4e-cited-3-face":{"fg":"sage"},"mu4e-cited-4-face":{"fg":"pewter"},"mu4e-cited-5-face":{"fg":"tan"},"mu4e-cited-6-face":{"fg":"terracotta"},"mu4e-cited-7-face":{"fg":"regal"},
- "mu4e-footer-face":{"fg":"pewter"},"mu4e-region-code":{"bg":"bg-dim"},"mu4e-system-face":{"fg":"pewter","italic":True},"mu4e-highlight-face":{"fg":"gold","bold":True},"mu4e-compose-header-face":{"fg":"blue","bold":True},"mu4e-compose-separator-face":{"fg":"pewter"}}
+ "mu4e-header-title-face":{"fg":"blue","bold":True},"mu4e-header-key-face":{"fg":"blue","bold":True},"mu4e-header-value-face":{"fg":"silver"},"mu4e-header-face":{"fg":"#cdced1"},"mu4e-header-highlight-face":{"bg":"gunmetal","underline":True},"mu4e-header-marks-face":{"fg":"gold"},
+ "mu4e-unread-face":{"fg":"white","bold":True},"mu4e-flagged-face":{"fg":"gold"},"mu4e-replied-face":{"fg":"silver"},"mu4e-forwarded-face":{"fg":"silver"},"mu4e-draft-face":{"fg":"steel","italic":True},"mu4e-trashed-face":{"fg":"pewter","strike":True},"mu4e-related-face":{"fg":"steel","italic":True},
+ "mu4e-contact-face":{"fg":"#cdced1"},"mu4e-special-header-value-face":{"fg":"silver"},"mu4e-url-number-face":{"fg":"blue","bold":True},"mu4e-link-face":{"fg":"blue","underline":True},
+ "mu4e-footer-face":{"fg":"pewter"},"mu4e-region-code":{"bg":"bg-dim"},"mu4e-system-face":{"fg":"pewter","italic":True},"mu4e-highlight-face":{"fg":"gold","bold":True},"mu4e-compose-separator-face":{"fg":"pewter"}}
LSP_FACES=("lsp-signature-face lsp-signature-highlight-function-argument lsp-signature-posframe "
"lsp-face-highlight-read lsp-face-highlight-write lsp-face-highlight-textual lsp-face-rename lsp-rename-placeholder-face "
"lsp-inlay-hint-face lsp-inlay-hint-parameter-face lsp-inlay-hint-type-face lsp-details-face "
"lsp-installation-buffer-face lsp-installation-finished-buffer-face").split()
LSP_SEED={
"lsp-signature-face":{"fg":"silver"},"lsp-signature-highlight-function-argument":{"fg":"gold","bold":True},"lsp-signature-posframe":{"bg":"bg-dim"},
- "lsp-face-highlight-read":{"bg":"navy"},"lsp-face-highlight-write":{"bg":"#3d2f4a"},"lsp-face-highlight-textual":{"bg":"gunmetal"},
- "lsp-face-rename":{"bg":"gunmetal","bold":True},"lsp-rename-placeholder-face":{"fg":"gold","bold":True},
+ "lsp-face-highlight-read":{"bg":"navy","underline":True},"lsp-face-highlight-write":{"bg":"#3d2f4a","bold":True},"lsp-face-highlight-textual":{"bg":"gunmetal"},
+ "lsp-face-rename":{"bg":"gunmetal","bold":True,"underline":True},"lsp-rename-placeholder-face":{"fg":"gold","bold":True},
"lsp-inlay-hint-face":{"fg":"pewter","italic":True},"lsp-inlay-hint-parameter-face":{"fg":"steel","italic":True},"lsp-inlay-hint-type-face":{"fg":"sage","italic":True},
- "lsp-details-face":{"fg":"pewter","italic":True},"lsp-installation-buffer-face":{"fg":"blue"},"lsp-installation-finished-buffer-face":{"fg":"sage"}}
+ "lsp-details-face":{"fg":"pewter","italic":True,"height":0.8},"lsp-installation-buffer-face":{"fg":"blue"},"lsp-installation-finished-buffer-face":{"fg":"sage"}}
GITGUTTER_FACES=("git-gutter:added git-gutter:modified git-gutter:deleted git-gutter:unchanged git-gutter:separator").split()
GITGUTTER_SEED={
- "git-gutter:added":{"fg":"emerald"},"git-gutter:modified":{"fg":"gold"},"git-gutter:deleted":{"fg":"terracotta"},
- "git-gutter:unchanged":{"fg":"pewter"},"git-gutter:separator":{"fg":"steel"}}
+ "git-gutter:added":{"fg":"emerald","bold":True},"git-gutter:modified":{"fg":"gold","bold":True},"git-gutter:deleted":{"fg":"terracotta","bold":True},
+ "git-gutter:unchanged":{"fg":"pewter"},"git-gutter:separator":{"fg":"steel","bold":True}}
FLYCHECK_FACES=("flycheck-error flycheck-warning flycheck-info flycheck-fringe-error flycheck-fringe-warning flycheck-fringe-info "
"flycheck-delimited-error flycheck-error-delimiter flycheck-error-list-error flycheck-error-list-warning flycheck-error-list-info "
"flycheck-error-list-error-message flycheck-error-list-checker-name flycheck-error-list-column-number flycheck-error-list-line-number "
"flycheck-error-list-filename flycheck-error-list-id flycheck-error-list-id-with-explainer flycheck-error-list-highlight flycheck-verify-select-checker").split()
FLYCHECK_SEED={
- "flycheck-error":{"fg":"terracotta"},"flycheck-warning":{"fg":"gold"},"flycheck-info":{"fg":"blue"},
+ "flycheck-error":{"fg":"terracotta","underline":True},"flycheck-warning":{"fg":"gold","underline":True},"flycheck-info":{"fg":"blue","underline":True},
"flycheck-fringe-error":{"fg":"terracotta"},"flycheck-fringe-warning":{"fg":"gold"},"flycheck-fringe-info":{"fg":"blue"},
"flycheck-delimited-error":{"fg":"terracotta"},"flycheck-error-delimiter":{"fg":"terracotta"},
"flycheck-error-list-error":{"fg":"terracotta"},"flycheck-error-list-warning":{"fg":"gold"},"flycheck-error-list-info":{"fg":"blue"},
"flycheck-error-list-error-message":{"fg":"#cdced1"},"flycheck-error-list-checker-name":{"fg":"steel"},
"flycheck-error-list-column-number":{"fg":"pewter"},"flycheck-error-list-line-number":{"fg":"pewter"},"flycheck-error-list-filename":{"fg":"blue"},
- "flycheck-error-list-id":{"fg":"steel"},"flycheck-error-list-id-with-explainer":{"fg":"steel","bold":True},
- "flycheck-error-list-highlight":{"bg":"gunmetal"},"flycheck-verify-select-checker":{"fg":"gold"}}
+ "flycheck-error-list-id":{"fg":"steel"},"flycheck-error-list-id-with-explainer":{"fg":"steel","bold":True,"box":{"style":"released","width":1,"color":None}},
+ "flycheck-error-list-highlight":{"bg":"gunmetal","bold":True},"flycheck-verify-select-checker":{"fg":"gold","box":{"style":"released","width":1,"color":None}}}
DIRED_FACES=("dired-header dired-directory dired-symlink dired-broken-symlink dired-special dired-set-id "
"dired-perm-write dired-mark dired-marked dired-flagged dired-ignored dired-warning").split()
DIRED_SEED={
@@ -305,7 +306,7 @@ DIRVISH_SEED={
"dirvish-file-size":{"fg":"sage"},"dirvish-file-time":{"fg":"pewter"},"dirvish-file-inode-number":{"fg":"pewter"},"dirvish-file-device-number":{"fg":"pewter"},
"dirvish-subtree-guide":{"fg":"pewter"},"dirvish-subtree-state":{"fg":"steel"},"dirvish-collapse-dir-face":{"fg":"blue"},
"dirvish-collapse-empty-dir-face":{"fg":"pewter"},"dirvish-collapse-file-face":{"fg":"silver"},"dirvish-emerge-group-title":{"fg":"gold","bold":True},
- "dirvish-media-info-heading":{"fg":"blue","bold":True},"dirvish-media-info-property-key":{"fg":"steel"},
+ "dirvish-media-info-heading":{"fg":"blue","bold":True},"dirvish-media-info-property-key":{"fg":"steel","italic":True},
"dirvish-narrow-match-face-0":{"fg":"gold","bold":True},"dirvish-narrow-match-face-1":{"fg":"blue","bold":True},
"dirvish-narrow-match-face-2":{"fg":"emerald","bold":True},"dirvish-narrow-match-face-3":{"fg":"regal","bold":True},"dirvish-narrow-split":{"fg":"pewter"},
"dirvish-proc-running":{"fg":"gold"},"dirvish-proc-finished":{"fg":"sage"},"dirvish-proc-failed":{"fg":"terracotta"},
@@ -316,7 +317,7 @@ DIRVISH_SEED={
ORGDRILL_FACES=("org-drill-hidden-cloze-face org-drill-visible-cloze-face org-drill-visible-cloze-hint-face").split()
ORGDRILL_SEED={"org-drill-hidden-cloze-face":{"fg":"#000000","bg":"steel"},"org-drill-visible-cloze-face":{"fg":"gold","bold":True},"org-drill-visible-cloze-hint-face":{"fg":"pewter","italic":True}}
ORGNOTER_FACES=("org-noter-notes-exist-face org-noter-no-notes-exist-face").split()
-ORGNOTER_SEED={"org-noter-notes-exist-face":{"fg":"sage"},"org-noter-no-notes-exist-face":{"fg":"pewter"}}
+ORGNOTER_SEED={"org-noter-notes-exist-face":{"fg":"sage","bold":True},"org-noter-no-notes-exist-face":{"fg":"pewter","bold":True}}
SIGNEL_FACES=("signel-timestamp-face signel-my-msg-face signel-other-msg-face signel-error-face").split()
SIGNEL_SEED={"signel-timestamp-face":{"fg":"pewter"},"signel-my-msg-face":{"fg":"blue"},"signel-other-msg-face":{"fg":"silver"},"signel-error-face":{"fg":"terracotta","bold":True}}
PEARL_FACES=("pearl-preamble-summary pearl-editable-comment pearl-readonly-comment pearl-modified-highlight pearl-modified-local pearl-modified-unknown").split()
@@ -326,17 +327,17 @@ CALIBREDB_FACES=("calibredb-search-header-library-name-face calibredb-search-hea
"calibredb-language-face calibredb-comment-face calibredb-archive-face calibredb-favorite-face calibredb-file-face calibredb-ids-face calibredb-highlight-face calibredb-current-page-button-face calibredb-mouse-face "
"calibredb-title-detailed-view-face calibredb-edit-annotation-header-title-face").split()
CALIBREDB_SEED={
- "calibredb-search-header-library-name-face":{"fg":"blue","bold":True},"calibredb-search-header-library-path-face":{"fg":"pewter"},"calibredb-search-header-total-face":{"fg":"sage"},"calibredb-search-header-filter-face":{"fg":"gold"},"calibredb-search-header-sort-face":{"fg":"steel"},"calibredb-search-header-highlight-face":{"fg":"gold","bold":True},
+ "calibredb-search-header-library-name-face":{"fg":"blue","bold":True},"calibredb-search-header-library-path-face":{"fg":"pewter"},"calibredb-search-header-total-face":{"fg":"sage"},"calibredb-search-header-filter-face":{"fg":"gold"},"calibredb-search-header-sort-face":{"fg":"steel"},"calibredb-search-header-highlight-face":{"fg":"gold","bold":True,"underline":True},
"calibredb-id-face":{"fg":"pewter"},"calibredb-title-face":{"fg":"blue","bold":True},"calibredb-author-face":{"fg":"sage"},"calibredb-format-face":{"fg":"steel"},"calibredb-size-face":{"fg":"pewter"},"calibredb-tag-face":{"fg":"tan"},"calibredb-date-face":{"fg":"pewter"},"calibredb-mark-face":{"fg":"gold","bold":True},"calibredb-series-face":{"fg":"regal"},"calibredb-publisher-face":{"fg":"steel"},"calibredb-pubdate-face":{"fg":"pewter"},
- "calibredb-language-face":{"fg":"steel"},"calibredb-comment-face":{"fg":"silver","italic":True},"calibredb-archive-face":{"fg":"pewter"},"calibredb-favorite-face":{"fg":"gold"},"calibredb-file-face":{"fg":"blue"},"calibredb-ids-face":{"fg":"pewter"},"calibredb-highlight-face":{"fg":"gold","bold":True},"calibredb-current-page-button-face":{"fg":"blue","bold":True},"calibredb-mouse-face":{"bg":"gunmetal"},
+ "calibredb-language-face":{"fg":"steel"},"calibredb-comment-face":{"fg":"silver","italic":True},"calibredb-archive-face":{"fg":"pewter"},"calibredb-favorite-face":{"fg":"gold"},"calibredb-file-face":{"fg":"blue"},"calibredb-ids-face":{"fg":"pewter"},"calibredb-highlight-face":{"fg":"gold","bold":True},"calibredb-current-page-button-face":{"fg":"blue","bold":True,"height":1.1},"calibredb-mouse-face":{"bg":"gunmetal"},
"calibredb-title-detailed-view-face":{"fg":"gold","bold":True},"calibredb-edit-annotation-header-title-face":{"fg":"blue","bold":True}}
ERC_FACES=("erc-header-line erc-timestamp-face erc-notice-face erc-default-face erc-current-nick-face erc-my-nick-face erc-my-nick-prefix-face erc-nick-default-face erc-nick-prefix-face erc-button-nick-default-face "
"erc-nick-msg-face erc-direct-msg-face erc-action-face erc-keyword-face erc-pal-face erc-fool-face erc-dangerous-host-face erc-error-face erc-input-face erc-prompt-face erc-command-indicator-face erc-information "
"erc-button erc-bold-face erc-italic-face erc-underline-face erc-inverse-face erc-spoiler-face erc-fill-wrap-merge-indicator-face erc-keep-place-indicator-arrow erc-keep-place-indicator-line").split()
ERC_SEED={
- "erc-header-line":{"fg":"white","bg":"gunmetal","bold":True},"erc-timestamp-face":{"fg":"pewter"},"erc-notice-face":{"fg":"steel"},"erc-default-face":{"fg":"#cdced1"},"erc-current-nick-face":{"fg":"gold","bold":True},"erc-my-nick-face":{"fg":"gold","bold":True},"erc-my-nick-prefix-face":{"fg":"gold"},"erc-nick-default-face":{"fg":"blue"},"erc-nick-prefix-face":{"fg":"sage"},"erc-button-nick-default-face":{"fg":"blue"},
- "erc-nick-msg-face":{"fg":"regal"},"erc-direct-msg-face":{"fg":"regal"},"erc-action-face":{"fg":"sage","italic":True},"erc-keyword-face":{"fg":"gold","bold":True},"erc-pal-face":{"fg":"emerald"},"erc-fool-face":{"fg":"pewter"},"erc-dangerous-host-face":{"fg":"terracotta","bold":True},"erc-error-face":{"fg":"terracotta","bold":True},"erc-input-face":{"fg":"silver"},"erc-prompt-face":{"fg":"blue","bold":True},"erc-command-indicator-face":{"fg":"steel","bold":True},"erc-information":{"fg":"steel"},
- "erc-button":{"fg":"blue"},"erc-bold-face":{"bold":True},"erc-italic-face":{"italic":True},"erc-underline-face":{"fg":"silver","underline":True},"erc-inverse-face":{"fg":"#000000","bg":"silver"},"erc-spoiler-face":{"fg":"#000000","bg":"gunmetal"},"erc-fill-wrap-merge-indicator-face":{"fg":"pewter"},"erc-keep-place-indicator-arrow":{"fg":"gold"},"erc-keep-place-indicator-line":{"bg":"bg-dim"}}
+ "erc-header-line":{"fg":"white","bg":"gunmetal","bold":True},"erc-timestamp-face":{"fg":"pewter"},"erc-notice-face":{"fg":"steel","bold":True},"erc-default-face":{"fg":"#cdced1"},"erc-current-nick-face":{"fg":"gold","bold":True},"erc-my-nick-face":{"fg":"gold","bold":True},"erc-my-nick-prefix-face":{"fg":"gold","bold":True},"erc-nick-default-face":{"fg":"blue","bold":True},"erc-nick-prefix-face":{"fg":"sage","bold":True},"erc-button-nick-default-face":{"fg":"blue","bold":True},
+ "erc-nick-msg-face":{"fg":"regal","bold":True},"erc-direct-msg-face":{"fg":"regal"},"erc-action-face":{"fg":"sage","italic":True},"erc-keyword-face":{"fg":"gold","bold":True},"erc-pal-face":{"fg":"emerald","bold":True},"erc-fool-face":{"fg":"pewter"},"erc-dangerous-host-face":{"fg":"terracotta","bold":True},"erc-error-face":{"fg":"terracotta","bold":True},"erc-input-face":{"fg":"silver"},"erc-prompt-face":{"fg":"blue","bold":True},"erc-command-indicator-face":{"fg":"steel","bold":True},"erc-information":{"fg":"steel"},
+ "erc-button":{"fg":"blue","bold":True},"erc-bold-face":{"bold":True},"erc-italic-face":{"italic":True},"erc-underline-face":{"fg":"silver","underline":True},"erc-inverse-face":{"fg":"#000000","bg":"silver"},"erc-spoiler-face":{"fg":"#000000","bg":"gunmetal"},"erc-fill-wrap-merge-indicator-face":{"fg":"pewter"},"erc-keep-place-indicator-arrow":{"fg":"gold"},"erc-keep-place-indicator-line":{"bg":"bg-dim"}}
SLACK_FACES=("slack-room-info-title-face slack-room-info-title-room-name-face slack-room-info-section-title-face slack-room-info-section-label-face slack-room-unread-face "
"slack-message-output-header slack-message-output-text slack-message-output-reaction slack-message-output-reaction-pressed slack-message-deleted-face slack-new-message-marker-face slack-all-thread-buffer-thread-header-face "
"slack-message-mention-face slack-message-mention-me-face slack-message-mention-keyword-face slack-channel-button-face "
@@ -349,14 +350,14 @@ SLACK_FACES=("slack-room-info-title-face slack-room-info-title-room-name-face sl
"slack-search-result-message-header-face slack-search-result-message-username-face "
"slack-modeline-has-unreads-face slack-modeline-channel-has-unreads-face slack-modeline-thread-has-unreads-face").split()
SLACK_SEED={
- "slack-room-info-title-face":{"fg":"blue","bold":True},"slack-room-info-title-room-name-face":{"fg":"gold","bold":True},"slack-room-info-section-title-face":{"fg":"blue","bold":True},"slack-room-info-section-label-face":{"fg":"steel"},"slack-room-unread-face":{"fg":"white","bold":True},
- "slack-message-output-header":{"fg":"blue","bold":True},"slack-message-output-text":{"fg":"#cdced1"},"slack-message-output-reaction":{"fg":"steel"},"slack-message-output-reaction-pressed":{"fg":"gold","bold":True},"slack-message-deleted-face":{"fg":"pewter","italic":True},"slack-new-message-marker-face":{"fg":"terracotta","bold":True},"slack-all-thread-buffer-thread-header-face":{"fg":"blue","bold":True},
- "slack-message-mention-face":{"fg":"blue"},"slack-message-mention-me-face":{"fg":"gold","bg":"navy","bold":True},"slack-message-mention-keyword-face":{"fg":"gold","bold":True},"slack-channel-button-face":{"fg":"blue"},
+ "slack-room-info-title-face":{"fg":"blue","bold":True},"slack-room-info-title-room-name-face":{"fg":"gold","bold":True},"slack-room-info-section-title-face":{"fg":"blue","bold":True},"slack-room-info-section-label-face":{"fg":"steel","bold":True},"slack-room-unread-face":{"fg":"white","bold":True},
+ "slack-message-output-header":{"fg":"blue","bold":True,"underline":True},"slack-message-output-text":{"fg":"#cdced1"},"slack-message-output-reaction":{"fg":"steel","box":{"style":"released","width":1,"color":None}},"slack-message-output-reaction-pressed":{"fg":"gold","bold":True,"box":{"style":"released","width":1,"color":None}},"slack-message-deleted-face":{"fg":"pewter","italic":True},"slack-new-message-marker-face":{"fg":"terracotta","bold":True},"slack-all-thread-buffer-thread-header-face":{"fg":"blue","bold":True},
+ "slack-message-mention-face":{"fg":"blue"},"slack-message-mention-me-face":{"fg":"gold","bg":"navy","bold":True},"slack-message-mention-keyword-face":{"fg":"gold","bold":True},"slack-channel-button-face":{"fg":"blue","underline":True},
"slack-mrkdwn-bold-face":{"bold":True},"slack-mrkdwn-italic-face":{"italic":True},"slack-mrkdwn-code-face":{"fg":"terracotta"},"slack-mrkdwn-code-block-face":{"fg":"terracotta","bg":"bg-dim"},"slack-mrkdwn-strike-face":{"fg":"pewter","strike":True},"slack-mrkdwn-blockquote-face":{"fg":"silver","italic":True},"slack-mrkdwn-list-face":{"fg":"silver"},
- "slack-attachment-header":{"fg":"blue","bold":True},"slack-attachment-footer":{"fg":"pewter"},"slack-attachment-pad":{"fg":"pewter"},"slack-attachment-field-title":{"fg":"steel","bold":True},"slack-message-attachment-preview-header-face":{"fg":"blue"},"slack-preview-face":{"fg":"silver"},"slack-block-highlight-source-overlay-face":{"bg":"bg-dim"},
- "slack-message-action-face":{"fg":"blue"},"slack-message-action-primary-face":{"fg":"sage"},"slack-message-action-danger-face":{"fg":"terracotta"},
- "slack-button-block-element-face":{"fg":"silver"},"slack-button-primary-block-element-face":{"fg":"sage","bold":True},"slack-button-danger-block-element-face":{"fg":"terracotta","bold":True},"slack-select-block-element-face":{"fg":"blue"},"slack-overflow-block-element-face":{"fg":"steel"},"slack-date-picker-block-element-face":{"fg":"blue"},
- "slack-dialog-title-face":{"fg":"blue","bold":True},"slack-dialog-element-label-face":{"fg":"steel"},"slack-dialog-element-hint-face":{"fg":"pewter","italic":True},"slack-dialog-element-placeholder-face":{"fg":"pewter"},"slack-dialog-element-error-face":{"fg":"terracotta"},"slack-dialog-submit-button-face":{"fg":"sage","bold":True},"slack-dialog-cancel-button-face":{"fg":"silver"},"slack-dialog-select-element-input-face":{"fg":"silver"},
+ "slack-attachment-header":{"fg":"blue","bold":True},"slack-attachment-footer":{"fg":"pewter"},"slack-attachment-pad":{"fg":"pewter"},"slack-attachment-field-title":{"fg":"steel","bold":True},"slack-message-attachment-preview-header-face":{"fg":"blue","bold":True},"slack-preview-face":{"fg":"silver"},"slack-block-highlight-source-overlay-face":{"bg":"bg-dim"},
+ "slack-message-action-face":{"fg":"blue","box":{"style":"released","width":1,"color":None}},"slack-message-action-primary-face":{"fg":"sage","box":{"style":"released","width":1,"color":None}},"slack-message-action-danger-face":{"fg":"terracotta","box":{"style":"released","width":1,"color":None}},
+ "slack-button-block-element-face":{"fg":"silver","box":{"style":"released","width":1,"color":None}},"slack-button-primary-block-element-face":{"fg":"sage","bold":True,"box":{"style":"released","width":1,"color":None}},"slack-button-danger-block-element-face":{"fg":"terracotta","bold":True,"box":{"style":"released","width":1,"color":None}},"slack-select-block-element-face":{"fg":"blue","box":{"style":"released","width":1,"color":None}},"slack-overflow-block-element-face":{"fg":"steel","box":{"style":"released","width":1,"color":None}},"slack-date-picker-block-element-face":{"fg":"blue","box":{"style":"released","width":1,"color":None}},
+ "slack-dialog-title-face":{"fg":"blue","bold":True},"slack-dialog-element-label-face":{"fg":"steel","bold":True},"slack-dialog-element-hint-face":{"fg":"pewter","italic":True},"slack-dialog-element-placeholder-face":{"fg":"pewter"},"slack-dialog-element-error-face":{"fg":"terracotta"},"slack-dialog-submit-button-face":{"fg":"sage","bold":True,"box":{"style":"released","width":1,"color":None}},"slack-dialog-cancel-button-face":{"fg":"silver","box":{"style":"released","width":1,"color":None}},"slack-dialog-select-element-input-face":{"fg":"silver","box":{"style":"released","width":1,"color":None}},
"slack-user-active-face":{"fg":"sage"},"slack-user-dnd-face":{"fg":"terracotta"},"slack-user-profile-header-face":{"fg":"blue","bold":True},"slack-user-profile-property-name-face":{"fg":"steel"},"slack-profile-image-face":{"fg":"pewter"},
"slack-search-result-message-header-face":{"fg":"blue"},"slack-search-result-message-username-face":{"fg":"gold","bold":True},
"slack-modeline-has-unreads-face":{"fg":"gold"},"slack-modeline-channel-has-unreads-face":{"fg":"gold","bold":True},"slack-modeline-thread-has-unreads-face":{"fg":"gold"}}
@@ -377,8 +378,8 @@ TELEGA_SEED={
"telega-entity-type-bold":{"bold":True},"telega-entity-type-italic":{"italic":True},"telega-entity-type-underline":{"fg":"silver","underline":True},"telega-entity-type-strikethrough":{"fg":"pewter","strike":True},"telega-entity-type-code":{"fg":"terracotta"},"telega-entity-type-pre":{"fg":"terracotta","bg":"bg-dim"},"telega-entity-type-blockquote":{"fg":"silver","italic":True},"telega-entity-type-mention":{"fg":"blue"},"telega-entity-type-hashtag":{"fg":"blue"},"telega-entity-type-cashtag":{"fg":"sage"},"telega-entity-type-botcommand":{"fg":"sage"},"telega-entity-type-texturl":{"fg":"blue"},"telega-entity-type-spoiler":{"fg":"gunmetal","bg":"gunmetal"},
"telega-reaction":{"fg":"steel"},"telega-reaction-chosen":{"fg":"gold","bold":True},"telega-reaction-paid":{"fg":"gold"},"telega-reaction-paid-chosen":{"fg":"gold","bold":True},"telega-highlight-text-face":{"fg":"#000000","bg":"gold"},"telega-button-highlight":{"fg":"gold","bold":True},
"telega-chat-prompt":{"fg":"blue","bold":True},"telega-chat-prompt-aux":{"fg":"steel"},"telega-chat-input-attachment":{"fg":"sage"},"telega-topic-button":{"fg":"blue"},"telega-filter-active":{"fg":"gold","bold":True},"telega-filter-button-active":{"fg":"#000000","bg":"gold"},"telega-filter-button-inactive":{"fg":"steel"},"telega-checklist-stats-done":{"fg":"sage"},"telega-checklist-stats-todo":{"fg":"steel"},
- "telega-box-button":{"fg":"blue"},"telega-box-button-active":{"fg":"#000000","bg":"blue"},"telega-box-button-default-active":{"fg":"#000000","bg":"silver"},"telega-box-button-default-passive":{"fg":"steel"},"telega-box-button-primary-active":{"fg":"#000000","bg":"blue"},"telega-box-button-primary-passive":{"fg":"blue"},"telega-box-button-success-active":{"fg":"#000000","bg":"emerald"},"telega-box-button-success-passive":{"fg":"sage"},"telega-box-button-danger-active":{"fg":"#000000","bg":"terracotta"},"telega-box-button-danger-passive":{"fg":"terracotta"},"telega-box-button-ui-active":{"fg":"#000000","bg":"gold"},"telega-box-button-ui-passive":{"fg":"gold"},"telega-box-button2-active":{"fg":"#000000","bg":"blue"},"telega-box-button2-passive":{"fg":"steel"},"telega-box-button2-white-foreground":{"fg":"white"},
- "telega-describe-item-title":{"fg":"steel","bold":True},"telega-describe-section-title":{"fg":"blue","bold":True},"telega-describe-subsection-title":{"fg":"blue"},"telega-enckey-00":{"fg":"pewter"},"telega-enckey-01":{"fg":"sage"},"telega-enckey-10":{"fg":"gold"},"telega-enckey-11":{"fg":"blue"},
+ "telega-box-button":{"fg":"blue","box":{"style":"released","width":1,"color":None}},"telega-box-button-active":{"fg":"#000000","bg":"blue","box":{"style":"released","width":1,"color":None}},"telega-box-button-default-active":{"fg":"#000000","bg":"silver","box":{"style":"released","width":1,"color":None}},"telega-box-button-default-passive":{"fg":"steel","box":{"style":"released","width":1,"color":None}},"telega-box-button-primary-active":{"fg":"#000000","bg":"blue","box":{"style":"released","width":1,"color":None}},"telega-box-button-primary-passive":{"fg":"blue","box":{"style":"released","width":1,"color":None}},"telega-box-button-success-active":{"fg":"#000000","bg":"emerald","box":{"style":"released","width":1,"color":None}},"telega-box-button-success-passive":{"fg":"sage","box":{"style":"released","width":1,"color":None}},"telega-box-button-danger-active":{"fg":"#000000","bg":"terracotta","box":{"style":"released","width":1,"color":None}},"telega-box-button-danger-passive":{"fg":"terracotta","box":{"style":"released","width":1,"color":None}},"telega-box-button-ui-active":{"fg":"#000000","bg":"gold","box":{"style":"released","width":1,"color":None}},"telega-box-button-ui-passive":{"fg":"gold","box":{"style":"released","width":1,"color":None}},"telega-box-button2-active":{"fg":"#000000","bg":"blue"},"telega-box-button2-passive":{"fg":"steel"},"telega-box-button2-white-foreground":{"fg":"white"},
+ "telega-describe-item-title":{"fg":"steel","bold":True},"telega-describe-section-title":{"fg":"blue","bold":True,"underline":True},"telega-describe-subsection-title":{"fg":"blue"},"telega-enckey-00":{"fg":"pewter"},"telega-enckey-01":{"fg":"sage"},"telega-enckey-10":{"fg":"gold"},"telega-enckey-11":{"fg":"blue"},
"telega-palette-builtin-blue":{"fg":"blue"},"telega-palette-builtin-green":{"fg":"emerald"},"telega-palette-builtin-orange":{"fg":"terracotta"},"telega-palette-builtin-purple":{"fg":"regal"},
"telega-webpage-title":{"fg":"blue","bold":True},"telega-webpage-subtitle":{"fg":"steel"},"telega-webpage-header":{"fg":"gold","bold":True},"telega-webpage-subheader":{"fg":"gold"},"telega-webpage-outline":{"fg":"pewter"},"telega-webpage-fixed":{"fg":"terracotta"},"telega-webpage-preformatted":{"fg":"terracotta","bg":"bg-dim"},"telega-webpage-marked":{"fg":"#000000","bg":"gold"},"telega-webpage-strike-through":{"fg":"pewter","strike":True},"telega-webpage-chat-link":{"fg":"blue"},"telega-link-preview-sitename":{"fg":"steel"},"telega-link-preview-title":{"fg":"blue","bold":True}}
# shr is built-in (not in the inventory). It is the HTML renderer behind nov
@@ -387,7 +388,7 @@ SHR_FACES=("shr-h1 shr-h2 shr-h3 shr-h4 shr-h5 shr-h6 shr-text shr-link shr-sele
"shr-code shr-mark shr-strike-through shr-sup shr-abbreviation shr-sliced-image").split()
SHR_SEED={
"shr-h1":{"fg":"gold","bold":True,"height":1.4},"shr-h2":{"fg":"blue","bold":True,"height":1.2},"shr-h3":{"fg":"blue","bold":True},"shr-h4":{"fg":"silver","bold":True},"shr-h5":{"fg":"steel","bold":True},"shr-h6":{"fg":"pewter","bold":True},
- "shr-text":{"fg":"#cdced1"},"shr-link":{"fg":"blue","underline":True},"shr-selected-link":{"fg":"gold","bold":True,"underline":True},"shr-code":{"fg":"terracotta","bg":"bg-dim"},"shr-mark":{"fg":"#000000","bg":"gold"},"shr-strike-through":{"fg":"pewter","strike":True},"shr-sup":{"fg":"steel"},"shr-abbreviation":{"fg":"steel","italic":True},"shr-sliced-image":{"fg":"pewter"}}
+ "shr-text":{"fg":"#cdced1"},"shr-link":{"fg":"blue","underline":True},"shr-selected-link":{"fg":"gold","bold":True,"underline":True},"shr-code":{"fg":"terracotta","bg":"bg-dim"},"shr-mark":{"fg":"#000000","bg":"gold"},"shr-strike-through":{"fg":"pewter","strike":True},"shr-sup":{"fg":"steel","height":0.8},"shr-abbreviation":{"fg":"steel","italic":True,"underline":True}}
def _faces(names,prefix,seed):
out=[]
for f in names:
@@ -425,6 +426,13 @@ if os.path.exists(_inv_path):
APPS[_pkg]={"label":_pkg,"preview":"generic","faces":[
[f,(f[len(_pkg)+1:] if f.startswith(_pkg+"-") else f).replace("-face","").replace("-"," "),{}]
for f in _INV[_pkg]]}
+# Apply the seed theme's package overrides (sterling by default): each full per-face
+# spec (color + structure) replaces the hardcoded face seed before the page renders.
+if _seed and _d.get('packages'):
+ for _app,_pkfaces in _d['packages'].items():
+ if _app in APPS:
+ for _row in APPS[_app]['faces']:
+ if _row[0] in _pkfaces: _row[2]=_pkfaces[_row[0]]
HTML = """<!doctype html><meta charset=utf-8><title>theme-studio</title>
<style>
STYLES_CSS</style>
@@ -443,10 +451,11 @@ STYLES_CSS</style>
<span id="palmsg"></span>
<div id="picker" class="picker">
<div class="prow">
- <div id="sv" class="sv"><canvas id="svmask" class="svmask"></canvas><div id="svcur" class="svcur"></div></div>
+ <div id="sv" class="sv"><canvas id="svmask" class="svmask"></canvas><div id="svsafe" class="svsafe" style="display:none"></div><div id="svcur" class="svcur"></div></div>
<div id="hue" class="hue"><div id="huecur" class="huecur"></div></div>
</div>
<div class="pmodel">edit <button data-pm="hsv" class="on">HSV</button><button data-pm="oklch">OKLCH</button></div>
+ <div class="pmodel" title="in OKLCH mode, shade the lightness too light to keep this overlay face readable over its foreground set">safe for <select id="safefor" onchange="setSafeFace(this.value)"><option value="">none</option></select></div>
<div class="oklchctl" id="oklchctl">
<div class="ocrow"><label title="perceptual lightness">L</label><input type="range" id="okL" min="0" max="1" step="0.001"><input type="number" id="okLn" min="0" max="1" step="0.001"></div>
<div class="ocrow"><label title="chroma (colorfulness)">C</label><input type="range" id="okC" min="0" max="0.4" step="0.001"><input type="number" id="okCn" min="0" max="0.4" step="0.001"></div>
diff --git a/scripts/theme-studio/run-tests.sh b/scripts/theme-studio/run-tests.sh
index e364d431..0db7faa0 100755
--- a/scripts/theme-studio/run-tests.sh
+++ b/scripts/theme-studio/run-tests.sh
@@ -53,17 +53,20 @@ CHROME=""
for c in google-chrome-stable google-chrome chromium chromium-browser; do
if command -v "$c" >/dev/null 2>&1; then CHROME="$c"; break; fi
done
-HASHES="selftest cursortest readouttest deltatest oklchtest planetest locktest sorttest mocktest"
+HASHES="selftest cursortest readouttest deltatest oklchtest planetest locktest sorttest mocktest contrasttest safetest healtest familytest counttest baseedittest roundtriptest beveltest"
if [ "$NO_BROWSER" = 1 ]; then
skip_msg "browser hash gates (--no-browser)"
elif [ -z "$CHROME" ]; then
for t in $HASHES; do skip_msg "#$t (no Chromium-family browser found)"; done
else
- PROF="$(mktemp -d)"
+ # An empty --user-data-dir makes Chrome fall back to the user's real default
+ # profile and take its SingletonLock; a hung headless render then blocks every
+ # interactive Chrome launch until killed. Never let an empty PROF reach Chrome.
+ PROF="$(mktemp -d)" && [ -n "$PROF" ] || { echo "mktemp -d failed — refusing to run browser gates" >&2; exit 1; }
trap 'rm -rf "$PROF"' EXIT
for t in $HASHES; do
upper="$(echo "$t" | tr '[:lower:]' '[:upper:]')"
- res="$("$CHROME" --headless --no-sandbox --disable-gpu --user-data-dir="$PROF" \
+ res="$(timeout --kill-after=5 30 "$CHROME" --headless --no-sandbox --disable-gpu --user-data-dir="$PROF" \
--virtual-time-budget=8000 --dump-dom "file://$HERE/theme-studio.html#$t" 2>/dev/null \
| grep -o "${upper}[^<]*" | head -1)"
case "$res" in
diff --git a/scripts/theme-studio/sterling.json b/scripts/theme-studio/sterling.json
new file mode 100644
index 00000000..bab5e641
--- /dev/null
+++ b/scripts/theme-studio/sterling.json
@@ -0,0 +1,5779 @@
+{
+ "name": "sterling",
+ "palette": [
+ [
+ "#f0fef0",
+ "fg"
+ ],
+ [
+ "#000000",
+ "bg"
+ ],
+ [
+ "#151311",
+ "bg+0"
+ ],
+ [
+ "#252321",
+ "bg+1"
+ ],
+ [
+ "#474544",
+ "bg+2"
+ ],
+ [
+ "#58574e",
+ "gray-2"
+ ],
+ [
+ "#6c6a60",
+ "gray-1"
+ ],
+ [
+ "#969385",
+ "gray"
+ ],
+ [
+ "#b4b1a2",
+ "gray+1"
+ ],
+ [
+ "#d0cbc0",
+ "gray+2"
+ ],
+ [
+ "#8a9496",
+ "steel"
+ ],
+ [
+ "#acb0b3",
+ "steel+1"
+ ],
+ [
+ "#c0c7ca",
+ "steel+2"
+ ],
+ [
+ "#67809c",
+ "blue"
+ ],
+ [
+ "#b2c3cc",
+ "blue+1"
+ ],
+ [
+ "#d9e2ff",
+ "blue+2"
+ ],
+ [
+ "#646d14",
+ "green-2"
+ ],
+ [
+ "#869038",
+ "green-1"
+ ],
+ [
+ "#a4ac64",
+ "green"
+ ],
+ [
+ "#ccc768",
+ "green+1"
+ ],
+ [
+ "#3f1c0f",
+ "red-3"
+ ],
+ [
+ "#7c2a09",
+ "red-2"
+ ],
+ [
+ "#a7502d",
+ "red-1"
+ ],
+ [
+ "#d47c59",
+ "red"
+ ],
+ [
+ "#edb08f",
+ "red+1"
+ ],
+ [
+ "#edbca2",
+ "red+2"
+ ],
+ [
+ "#875f00",
+ "yellow-2"
+ ],
+ [
+ "#8e784c",
+ "yellow-1"
+ ],
+ [
+ "#d7af5f",
+ "yellow"
+ ],
+ [
+ "#ffd75f",
+ "yellow+1"
+ ],
+ [
+ "#f9ee98",
+ "yellow+2"
+ ],
+ [
+ "#ff2a00",
+ "intense-red"
+ ]
+ ],
+ "assignments": {
+ "bg": "#000000",
+ "p": "#f0fef0",
+ "kw": "#67809c",
+ "bi": "#d7af5f",
+ "pp": "#acb0b3",
+ "fnd": "#d47c59",
+ "fnc": "",
+ "dec": "",
+ "ty": "#a4ac64",
+ "prop": "",
+ "con": "#d7af5f",
+ "num": "#d7af5f",
+ "str": "#a4ac64",
+ "esc": "",
+ "re": "",
+ "doc": "#969385",
+ "cm": "#969385",
+ "cmd": "#969385",
+ "var": "#b2c3cc",
+ "op": "",
+ "punc": ""
+ },
+ "bold": [
+ "kw",
+ "bi",
+ "pp",
+ "fnd",
+ "ty",
+ "con"
+ ],
+ "italic": [
+ "pp",
+ "cm",
+ "var",
+ "cmd"
+ ],
+ "ui": {
+ "cursor": {
+ "fg": null,
+ "bg": "#f0fef0"
+ },
+ "region": {
+ "fg": null,
+ "bg": "#474544"
+ },
+ "hl-line": {
+ "fg": null,
+ "bg": "#151311"
+ },
+ "highlight": {
+ "fg": null,
+ "bg": "#646d14"
+ },
+ "mode-line": {
+ "fg": "#000000",
+ "bg": "#67809c",
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ }
+ },
+ "mode-line-inactive": {
+ "fg": "#67809c",
+ "bg": "#000000",
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ }
+ },
+ "fringe": {
+ "fg": "#58574e",
+ "bg": "#151311"
+ },
+ "line-number": {
+ "fg": "#58574e",
+ "bg": null
+ },
+ "line-number-current-line": {
+ "fg": "#d7af5f",
+ "bg": null
+ },
+ "minibuffer-prompt": {
+ "fg": "#d7af5f",
+ "bg": null
+ },
+ "isearch": {
+ "fg": null,
+ "bg": null
+ },
+ "lazy-highlight": {
+ "fg": null,
+ "bg": "#8e784c",
+ "underline": true
+ },
+ "isearch-fail": {
+ "fg": "#f0fef0",
+ "bg": "#a7502d"
+ },
+ "show-paren-match": {
+ "fg": "#000000",
+ "bg": "#a4ac64",
+ "underline": true
+ },
+ "show-paren-mismatch": {
+ "fg": "#f0fef0",
+ "bg": "#a7502d"
+ },
+ "link": {
+ "fg": "#b2c3cc",
+ "bg": null,
+ "underline": true
+ },
+ "error": {
+ "fg": "#d47c59",
+ "bg": null,
+ "bold": true
+ },
+ "warning": {
+ "fg": "#ffd75f",
+ "bg": null,
+ "bold": true
+ },
+ "success": {
+ "fg": "#a4ac64",
+ "bg": null,
+ "bold": true
+ },
+ "vertical-border": {
+ "fg": "#58574e",
+ "bg": null
+ }
+ },
+ "locks": [
+ "kw",
+ "bg",
+ "p",
+ "bi",
+ "pp",
+ "fnd",
+ "ty",
+ "con",
+ "str",
+ "var",
+ "cm",
+ "doc",
+ "cmd",
+ "num",
+ "ui:mode-line",
+ "ui:mode-line-inactive",
+ "ui:link",
+ "ui:hl-line",
+ "ui:warning",
+ "ui:success",
+ "ui:error",
+ "ui:line-number-current-line",
+ "ui:minibuffer-prompt",
+ "ui:show-paren-mismatch",
+ "ui:show-paren-match",
+ "ui:vertical-border",
+ "ui:line-number",
+ "ui:fringe",
+ "ui:region"
+ ],
+ "packages": {
+ "org-mode": {
+ "org-document-title": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "height": 1.5,
+ "source": "default"
+ },
+ "org-document-info": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "org-document-info-keyword": {
+ "fg": "#8a9496",
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-level-1": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "height": 1.3,
+ "source": "default"
+ },
+ "org-level-2": {
+ "fg": null,
+ "bg": null,
+ "height": 1.2,
+ "source": "default"
+ },
+ "org-level-3": {
+ "fg": null,
+ "bg": null,
+ "height": 1.15,
+ "source": "default"
+ },
+ "org-level-4": {
+ "fg": null,
+ "bg": null,
+ "height": 1.1,
+ "source": "default"
+ },
+ "org-level-5": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-level-6": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-level-7": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-level-8": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "org-headline-todo": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-headline-done": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-todo": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-done": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-priority": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-tag": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-tag-group": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-special-keyword": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-drawer": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-property-value": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "org-checkbox": {
+ "fg": null,
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-checkbox-statistics-todo": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-checkbox-statistics-done": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-warning": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-link": {
+ "fg": "#67809c",
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "org-footnote": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "org-date": {
+ "fg": "#8a9496",
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-sexp-date": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "org-date-selected": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-target": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-macro": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-cite": {
+ "fg": "#67809c",
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "org-cite-key": {
+ "fg": "#67809c",
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "org-block": {
+ "fg": null,
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-block-begin-line": {
+ "fg": null,
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-block-end-line": {
+ "fg": null,
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-code": {
+ "fg": null,
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-verbatim": {
+ "fg": "#8a9496",
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-inline-src-block": {
+ "fg": null,
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-quote": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "org-verse": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "org-latex-and-related": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-table": {
+ "fg": "#8a9496",
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-table-header": {
+ "fg": null,
+ "bg": "#58574e",
+ "bold": true,
+ "source": "default"
+ },
+ "org-table-row": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-formula": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-column": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-column-title": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-list-dt": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-meta-line": {
+ "fg": null,
+ "bg": null,
+ "inherit": "fixed-pitch",
+ "source": "default"
+ },
+ "org-ellipsis": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-hide": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-indent": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-archived": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-default": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-dispatcher-highlight": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-agenda-structure": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "height": 1.1,
+ "source": "default"
+ },
+ "org-agenda-structure-secondary": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-structure-filter": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-agenda-date": {
+ "fg": "#8a9496",
+ "bg": null,
+ "height": 1.05,
+ "source": "default"
+ },
+ "org-agenda-date-today": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "height": 1.05,
+ "source": "default"
+ },
+ "org-agenda-date-weekend": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-agenda-date-weekend-today": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-agenda-current-time": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-done": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-dimmed-todo-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-calendar-event": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-calendar-sexp": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-calendar-daterange": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-diary": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-clocking": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-column-dateline": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-restriction-lock": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-agenda-filter-category": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-agenda-filter-effort": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-agenda-filter-regexp": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-agenda-filter-tags": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-scheduled": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-scheduled-today": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-scheduled-previously": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-upcoming-deadline": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-upcoming-distant-deadline": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-imminent-deadline": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-time-grid": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-clock-overlay": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-mode-line-clock": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "org-mode-line-clock-overrun": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ }
+ },
+ "magit": {
+ "magit-section-heading": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-section-secondary-heading": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-section-heading-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-section-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-section-child-count": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-added": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-added-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-removed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-removed-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-context": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-context-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-file-heading": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-diff-file-heading-highlight": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-diff-file-heading-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-hunk-heading": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-hunk-heading-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-hunk-heading-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-hunk-region": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-lines-heading": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-lines-boundary": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-base": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-base-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-our": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-our-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-their": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-their-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-conflict-heading": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-conflict-heading-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-revision-summary": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-revision-summary-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diff-whitespace-warning": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diffstat-added": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-diffstat-removed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-branch-current": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "box": {
+ "style": "line",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "magit-branch-local": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-branch-remote": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-branch-remote-head": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "box": {
+ "style": "line",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "magit-branch-upstream": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-branch-warning": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-head": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-tag": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-hash": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-filename": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-dimmed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-keyword": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-keyword-squash": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-refname": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-refname-stash": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-refname-wip": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-refname-pullreq": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-log-author": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-log-date": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-log-graph": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-header-line": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-header-line-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-header-line-log-select": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-process-ok": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-process-ng": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-mode-line-process": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-mode-line-process-error": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-bisect-good": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-bisect-bad": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-bisect-skip": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-heading": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-hash": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-name": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-date": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-summary": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-dimmed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-blame-margin": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-cherry-equivalent": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-cherry-unmatched": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-signature-good": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-signature-bad": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "magit-signature-untrusted": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-signature-expired": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-signature-expired-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-signature-revoked": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-signature-error": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-commit": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-amend": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-merge": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-checkout": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-reset": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-rebase": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-cherry-pick": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-remote": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-reflog-other": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-pick": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-stop": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-part": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-head": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-drop": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-done": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-onto": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-sequence-exec": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-left-margin": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "elfeed": {
+ "elfeed-search-date-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-search-title-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-search-unread-title-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "elfeed-search-feed-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-search-tag-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-search-unread-count-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-search-filter-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "elfeed-search-last-update-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-log-date-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-log-error-level-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "elfeed-log-warn-level-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-log-info-level-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "elfeed-log-debug-level-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "mu4e": {
+ "mu4e-title-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-context-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-modeline-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-ok-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-warning-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-header-title-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-header-key-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-header-value-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-header-face": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-header-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "mu4e-header-marks-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-unread-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-flagged-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-replied-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-forwarded-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-draft-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "mu4e-trashed-face": {
+ "fg": null,
+ "bg": null,
+ "strike": true,
+ "source": "default"
+ },
+ "mu4e-related-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "mu4e-contact-face": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-special-header-value-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-url-number-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-link-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "mu4e-footer-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-region-code": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "mu4e-system-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "mu4e-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "mu4e-compose-separator-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "ghostel": {
+ "ghostel-default": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-fake-cursor": {
+ "fg": "#000000",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-fake-cursor-box": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-black": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-red": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-green": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-yellow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-blue": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-magenta": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-cyan": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-white": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-black": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-red": {
+ "fg": "#de4949",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-green": {
+ "fg": "#84b068",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-yellow": {
+ "fg": "#eed376",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-blue": {
+ "fg": "#7a9abe",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-magenta": {
+ "fg": "#b07fd0",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-cyan": {
+ "fg": "#7fc0a8",
+ "bg": null,
+ "source": "default"
+ },
+ "ghostel-color-bright-white": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "dashboard": {
+ "dashboard-banner-logo-title": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dashboard-text-banner": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "dashboard-heading": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dashboard-items-face": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "dashboard-navigator": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "dashboard-no-items-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dashboard-footer-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dashboard-footer-icon-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "lsp-mode": {
+ "lsp-signature-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "lsp-signature-highlight-function-argument": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "lsp-signature-posframe": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "lsp-face-highlight-read": {
+ "fg": null,
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "lsp-face-highlight-write": {
+ "fg": null,
+ "bg": "#3d2f4a",
+ "bold": true,
+ "source": "default"
+ },
+ "lsp-face-highlight-textual": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "lsp-face-rename": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "underline": true,
+ "source": "default"
+ },
+ "lsp-rename-placeholder-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "lsp-inlay-hint-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "lsp-inlay-hint-parameter-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "lsp-inlay-hint-type-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "lsp-details-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "height": 0.8,
+ "source": "default"
+ },
+ "lsp-installation-buffer-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "lsp-installation-finished-buffer-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "git-gutter": {
+ "git-gutter:added": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "git-gutter:modified": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "git-gutter:deleted": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "git-gutter:unchanged": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "git-gutter:separator": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ }
+ },
+ "flycheck": {
+ "flycheck-error": {
+ "fg": null,
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "flycheck-warning": {
+ "fg": null,
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "flycheck-info": {
+ "fg": "#67809c",
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "flycheck-fringe-error": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-fringe-warning": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-fringe-info": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-delimited-error": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-delimiter": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-error": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-warning": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-info": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-error-message": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-checker-name": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-column-number": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-line-number": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-filename": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-id": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "flycheck-error-list-id-with-explainer": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "flycheck-error-list-highlight": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "flycheck-verify-select-checker": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ }
+ },
+ "dired": {
+ "dired-header": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dired-directory": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dired-symlink": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dired-broken-symlink": {
+ "fg": "#de4949",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dired-special": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dired-set-id": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dired-perm-write": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dired-mark": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dired-marked": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dired-flagged": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dired-ignored": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dired-warning": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ }
+ },
+ "dirvish": {
+ "dirvish-inactive": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-free-space": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-hl-line": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-hl-line-inactive": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-modes": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-link-number": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-user-id": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-group-id": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-size": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-time": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-inode-number": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-file-device-number": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-subtree-guide": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-subtree-state": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-collapse-dir-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-collapse-empty-dir-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-collapse-file-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-emerge-group-title": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dirvish-media-info-heading": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dirvish-media-info-property-key": {
+ "fg": "#8a9496",
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "dirvish-narrow-match-face-0": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dirvish-narrow-match-face-1": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dirvish-narrow-match-face-2": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dirvish-narrow-match-face-3": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dirvish-narrow-split": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-proc-running": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-proc-finished": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-proc-failed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-git-commit-message-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "dirvish-vc-added-state": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-vc-edited-state": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-vc-removed-state": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-vc-conflict-state": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "dirvish-vc-locked-state": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-vc-missing-state": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-vc-needs-merge-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-vc-needs-update-state": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "dirvish-vc-unregistered-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "calibredb": {
+ "calibredb-search-header-library-name-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "calibredb-search-header-library-path-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-search-header-total-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-search-header-filter-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-search-header-sort-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-search-header-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "underline": true,
+ "source": "default"
+ },
+ "calibredb-id-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-title-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "calibredb-author-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-format-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-size-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-tag-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-date-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-mark-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "calibredb-series-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-publisher-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-pubdate-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-language-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-comment-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "calibredb-archive-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-favorite-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-file-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-ids-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "calibredb-current-page-button-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "height": 1.1,
+ "source": "default"
+ },
+ "calibredb-mouse-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "calibredb-title-detailed-view-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "calibredb-edit-annotation-header-title-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ }
+ },
+ "erc": {
+ "erc-header-line": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-timestamp-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "erc-notice-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-default-face": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "erc-current-nick-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-my-nick-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-my-nick-prefix-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-nick-default-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-nick-prefix-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-button-nick-default-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-nick-msg-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-direct-msg-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "erc-action-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "erc-keyword-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-pal-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-fool-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "erc-dangerous-host-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-error-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-input-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "erc-prompt-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-command-indicator-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-information": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "erc-button": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-bold-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "erc-italic-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "erc-underline-face": {
+ "fg": null,
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "erc-inverse-face": {
+ "fg": "#000000",
+ "bg": null,
+ "source": "default"
+ },
+ "erc-spoiler-face": {
+ "fg": "#000000",
+ "bg": null,
+ "source": "default"
+ },
+ "erc-fill-wrap-merge-indicator-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "erc-keep-place-indicator-arrow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "erc-keep-place-indicator-line": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "org-drill": {
+ "org-drill-hidden-cloze-face": {
+ "fg": "#000000",
+ "bg": "#8a9496",
+ "source": "default"
+ },
+ "org-drill-visible-cloze-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-drill-visible-cloze-hint-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ }
+ },
+ "org-noter": {
+ "org-noter-notes-exist-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "org-noter-no-notes-exist-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ }
+ },
+ "signel": {
+ "signel-timestamp-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "signel-my-msg-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "signel-other-msg-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "signel-error-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ }
+ },
+ "pearl": {
+ "pearl-preamble-summary": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "pearl-editable-comment": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "pearl-readonly-comment": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "pearl-modified-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "pearl-modified-local": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "pearl-modified-unknown": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "slack": {
+ "slack-room-info-title-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-room-info-title-room-name-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-room-info-section-title-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-room-info-section-label-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-room-unread-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-message-output-header": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "underline": true,
+ "source": "default"
+ },
+ "slack-message-output-text": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "slack-message-output-reaction": {
+ "fg": "#8a9496",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-message-output-reaction-pressed": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-message-deleted-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "slack-new-message-marker-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-all-thread-buffer-thread-header-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-message-mention-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "slack-message-mention-me-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-message-mention-keyword-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-channel-button-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "slack-mrkdwn-bold-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-mrkdwn-italic-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "slack-mrkdwn-code-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-mrkdwn-code-block-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-mrkdwn-strike-face": {
+ "fg": null,
+ "bg": null,
+ "strike": true,
+ "source": "default"
+ },
+ "slack-mrkdwn-blockquote-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "slack-mrkdwn-list-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-attachment-header": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-attachment-footer": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-attachment-pad": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-attachment-field-title": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-message-attachment-preview-header-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-preview-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-block-highlight-source-overlay-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-message-action-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-message-action-primary-face": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-message-action-danger-face": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-button-block-element-face": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-button-primary-block-element-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-button-danger-block-element-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-select-block-element-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-overflow-block-element-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-date-picker-block-element-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-dialog-title-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-dialog-element-label-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-dialog-element-hint-face": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "slack-dialog-element-placeholder-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-dialog-element-error-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-dialog-submit-button-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-dialog-cancel-button-face": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-dialog-select-element-input-face": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "slack-user-active-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-user-dnd-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-user-profile-header-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-user-profile-property-name-face": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "slack-profile-image-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-search-result-message-header-face": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "slack-search-result-message-username-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-modeline-has-unreads-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "slack-modeline-channel-has-unreads-face": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "slack-modeline-thread-has-unreads-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "telega": {
+ "telega-root-heading": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-tracking": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-unread-unmuted-modeline": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-username": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-user-online-status": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-user-non-online-status": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-secret-title": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-contact-birthdays-today": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-muted-count": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-unmuted-count": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-mention-count": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-has-chatbuf-brackets": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-delim-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-shadow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-link": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-blue": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-red": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-msg-heading": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-msg-user-title": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-msg-self-title": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-msg-deleted": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "telega-msg-sponsored": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "telega-msg-inline-reply": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-msg-inline-forward": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-msg-inline-other": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-bold": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-entity-type-italic": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "telega-entity-type-underline": {
+ "fg": null,
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "telega-entity-type-strikethrough": {
+ "fg": null,
+ "bg": null,
+ "strike": true,
+ "source": "default"
+ },
+ "telega-entity-type-code": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-pre": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-blockquote": {
+ "fg": null,
+ "bg": null,
+ "italic": true,
+ "source": "default"
+ },
+ "telega-entity-type-mention": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-hashtag": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-cashtag": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-botcommand": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-texturl": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-entity-type-spoiler": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-reaction": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-reaction-chosen": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-reaction-paid": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-reaction-paid-chosen": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-highlight-text-face": {
+ "fg": "#000000",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-button-highlight": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-chat-prompt": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-chat-prompt-aux": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-chat-input-attachment": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-topic-button": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-filter-active": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-filter-button-active": {
+ "fg": "#000000",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-filter-button-inactive": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-checklist-stats-done": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-checklist-stats-todo": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-box-button": {
+ "fg": "#67809c",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-active": {
+ "fg": "#000000",
+ "bg": "#67809c",
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-default-active": {
+ "fg": "#000000",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-default-passive": {
+ "fg": "#8a9496",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-primary-active": {
+ "fg": "#000000",
+ "bg": "#67809c",
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-primary-passive": {
+ "fg": "#67809c",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-success-active": {
+ "fg": "#000000",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-success-passive": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-danger-active": {
+ "fg": "#000000",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-danger-passive": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-ui-active": {
+ "fg": "#000000",
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button-ui-passive": {
+ "fg": null,
+ "bg": null,
+ "box": {
+ "style": "released",
+ "width": 1,
+ "color": null
+ },
+ "source": "default"
+ },
+ "telega-box-button2-active": {
+ "fg": "#000000",
+ "bg": "#67809c",
+ "source": "default"
+ },
+ "telega-box-button2-passive": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-box-button2-white-foreground": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-describe-item-title": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-describe-section-title": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "underline": true,
+ "source": "default"
+ },
+ "telega-describe-subsection-title": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-enckey-00": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-enckey-01": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-enckey-10": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-enckey-11": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-palette-builtin-blue": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-palette-builtin-green": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-palette-builtin-orange": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-palette-builtin-purple": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-webpage-title": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-webpage-subtitle": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-webpage-header": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "telega-webpage-subheader": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-webpage-outline": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-webpage-fixed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-webpage-preformatted": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "telega-webpage-marked": {
+ "fg": "#000000",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-webpage-strike-through": {
+ "fg": null,
+ "bg": null,
+ "strike": true,
+ "source": "default"
+ },
+ "telega-webpage-chat-link": {
+ "fg": "#67809c",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-link-preview-sitename": {
+ "fg": "#8a9496",
+ "bg": null,
+ "source": "default"
+ },
+ "telega-link-preview-title": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ }
+ },
+ "shr": {
+ "shr-h1": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "height": 1.4,
+ "source": "default"
+ },
+ "shr-h2": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "height": 1.2,
+ "source": "default"
+ },
+ "shr-h3": {
+ "fg": "#67809c",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "shr-h4": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "shr-h5": {
+ "fg": "#8a9496",
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "shr-h6": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "source": "default"
+ },
+ "shr-text": {
+ "fg": "#cdced1",
+ "bg": null,
+ "source": "default"
+ },
+ "shr-link": {
+ "fg": "#67809c",
+ "bg": null,
+ "underline": true,
+ "source": "default"
+ },
+ "shr-selected-link": {
+ "fg": null,
+ "bg": null,
+ "bold": true,
+ "underline": true,
+ "source": "default"
+ },
+ "shr-code": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "shr-mark": {
+ "fg": "#000000",
+ "bg": null,
+ "source": "default"
+ },
+ "shr-strike-through": {
+ "fg": null,
+ "bg": null,
+ "strike": true,
+ "source": "default"
+ },
+ "shr-sup": {
+ "fg": "#8a9496",
+ "bg": null,
+ "height": 0.8,
+ "source": "default"
+ },
+ "shr-abbreviation": {
+ "fg": "#8a9496",
+ "bg": null,
+ "italic": true,
+ "underline": true,
+ "source": "default"
+ },
+ "shr-sliced-image": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "2048-game": {
+ "twentyfortyeight-face-1024": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-128": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-16": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-2": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-2048": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-256": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-32": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-4": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-512": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-64": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "twentyfortyeight-face-8": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "alert": {
+ "alert-high-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "alert-low-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "alert-moderate-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "alert-normal-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "alert-trivial-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "alert-urgent-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "all-the-icons": {
+ "all-the-icons-blue": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-blue-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-cyan": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-cyan-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dblue": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dcyan": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dgreen": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dmaroon": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dorange": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dpink": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dpurple": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dred": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dsilver": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-dyellow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-green": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lblue": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lcyan": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lgreen": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lmaroon": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lorange": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lpink": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lpurple": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lred": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lsilver": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-lyellow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-maroon": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-orange": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-pink": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-purple": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-purple-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-red": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-red-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-silver": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "all-the-icons-yellow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "company": {
+ "company-echo": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-echo-common": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-preview": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-preview-common": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-preview-search": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-annotation": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-annotation-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-common": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-common-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-deprecated": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-mouse": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-quick-access": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-quick-access-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-scrollbar-thumb": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-scrollbar-track": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-search": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-search-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-tooltip-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "company-box": {
+ "company-box-annotation": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-box-background": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-box-candidate": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-box-numbers": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-box-scrollbar": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "company-box-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "consult": {
+ "consult-async-failed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-async-finished": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-async-running": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-async-split": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-bookmark": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-buffer": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-file": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-grep-context": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-help": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-highlight-mark": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-highlight-match": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-line-number": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-line-number-prefix": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-line-number-wrapped": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-narrow-indicator": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-preview-insertion": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-preview-line": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-preview-match": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "consult-separator": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "embark": {
+ "embark-collect-annotation": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-collect-candidate": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-collect-group-separator": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-collect-group-title": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-keybinding": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-keybinding-repeat": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-keymap": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-selected": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-target": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-verbose-indicator-documentation": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-verbose-indicator-shadowed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "embark-verbose-indicator-title": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "emms": {
+ "emms-browser-album-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-browser-albumartist-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-browser-artist-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-browser-composer-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-browser-performer-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-browser-track-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-browser-year/genre-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-metaplaylist-mode-current-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-metaplaylist-mode-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-playlist-selected-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "emms-playlist-track-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "flyspell-correct": {
+ "flyspell-correct-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "highlight-indent-guides": {
+ "highlight-indent-guides-character-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-even-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-odd-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-stack-character-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-stack-even-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-stack-odd-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-top-character-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-top-even-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "highlight-indent-guides-top-odd-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "hl-todo": {
+ "hl-todo": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "hl-todo-flymake-type": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "json-mode": {
+ "json-mode-object-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "llama": {
+ "llama-##-macro": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "llama-deleted-argument": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "llama-llama-macro": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "llama-mandatory-argument": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "llama-optional-argument": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "lv": {
+ "lv-separator": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "magit-section": {
+ "magit-left-margin": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-section-child-count": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-section-heading": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-section-heading-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-section-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "magit-section-secondary-heading": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "malyon": {
+ "malyon-face-bold": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "malyon-face-error": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "malyon-face-italic": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "malyon-face-plain": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "malyon-face-reverse": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "marginalia": {
+ "marginalia-archive": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-char": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-date": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-documentation": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-name": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-owner": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-dir": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-exec": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-link": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-no": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-other": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-rare": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-read": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-file-priv-write": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-function": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-installed": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-lighter": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-list": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-mode": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-modified": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-null": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-number": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-off": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-on": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-size": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-string": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-symbol": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-true": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-type": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-value": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "marginalia-version": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "markdown-mode": {
+ "markdown-blockquote-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-bold-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-code-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-comment-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-footnote-marker-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-footnote-text-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-gfm-checkbox-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-delimiter-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-face-1": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-face-2": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-face-3": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-face-4": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-face-5": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-face-6": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-header-rule-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-highlighting-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-hr-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-html-attr-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-html-attr-value-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-html-entity-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-html-tag-delimiter-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-html-tag-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-inline-code-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-italic-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-language-info-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-language-keyword-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-line-break-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-link-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-link-title-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-list-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-markup-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-math-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-metadata-key-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-metadata-value-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-missing-link-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-plain-url-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-pre-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-reference-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-strike-through-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-table-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "markdown-url-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "nerd-icons": {
+ "nerd-icons-blue": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-blue-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-cyan": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-cyan-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dblue": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dcyan": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dgreen": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dmaroon": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dorange": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dpink": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dpurple": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dred": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dsilver": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-dyellow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-green": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lblue": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lcyan": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lgreen": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lmaroon": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lorange": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lpink": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lpurple": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lred": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lsilver": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-lyellow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-maroon": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-orange": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-pink": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-purple": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-purple-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-red": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-red-alt": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-silver": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "nerd-icons-yellow": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "nerd-icons-completion": {
+ "nerd-icons-completion-dir-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "orderless": {
+ "orderless-match-face-0": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "orderless-match-face-1": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "orderless-match-face-2": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "orderless-match-face-3": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "org-roam": {
+ "org-roam-dailies-calendar-note": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-dim": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-header-line": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-olp": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-preview-heading": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-preview-heading-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-preview-heading-selection": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-preview-region": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-roam-title": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "org-superstar": {
+ "org-superstar-first": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-superstar-header-bullet": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-superstar-item": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "org-superstar-leading": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "prescient": {
+ "prescient-primary-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "prescient-secondary-highlight": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "rainbow-delimiters": {
+ "rainbow-delimiters-base-error-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-base-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-1-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-2-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-3-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-4-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-5-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-6-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-7-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-8-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-depth-9-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-mismatched-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "rainbow-delimiters-unmatched-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "symbol-overlay": {
+ "symbol-overlay-default-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-1": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-2": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-3": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-4": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-5": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-6": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-7": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "symbol-overlay-face-8": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "tmr": {
+ "tmr-description": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-duration": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-end-time": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-finished": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-is-acknowledged": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-must-be-acknowledged": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-start-time": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-tabulated-acknowledgement": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-tabulated-description": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-tabulated-end-time": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-tabulated-remaining-time": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "tmr-tabulated-start-time": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "transient": {
+ "transient-active-infix": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-argument": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-delimiter": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-disabled-suffix": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-enabled-suffix": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-heading": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-higher-level": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-inactive-argument": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-inactive-value": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-inapt-argument": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-inapt-suffix": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-key-exit": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-key-noop": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-key-recurse": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-key-return": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-key-stack": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-key-stay": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-mismatched-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-nonstandard-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-unreachable": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-unreachable-key": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "transient-value": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "vertico": {
+ "vertico-current": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "vertico-group-separator": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "vertico-group-title": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "vertico-multiline": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "web-mode": {
+ "web-mode-annotation-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-annotation-html-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-annotation-tag-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-annotation-type-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-annotation-value-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-block-attr-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-block-attr-value-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-block-comment-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-block-control-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-block-delimiter-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-block-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-block-string-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-bold-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-builtin-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-comment-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-comment-keyword-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-constant-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-at-rule-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-color-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-comment-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-function-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-priority-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-property-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-pseudo-class-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-selector-class-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-selector-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-selector-tag-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-string-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-css-variable-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-current-column-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-current-element-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-doctype-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-error-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-filter-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-folded-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-function-call-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-function-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-attr-custom-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-attr-engine-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-attr-equal-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-attr-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-attr-value-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-entity-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-tag-bracket-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-tag-custom-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-tag-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-tag-namespaced-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-html-tag-unclosed-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-inlay-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-interpolate-color1-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-interpolate-color2-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-interpolate-color3-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-interpolate-color4-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-italic-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-javascript-comment-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-javascript-string-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-json-comment-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-json-context-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-json-key-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-json-string-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-jsx-depth-1-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-jsx-depth-2-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-jsx-depth-3-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-jsx-depth-4-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-jsx-depth-5-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-keyword-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-param-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-part-comment-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-part-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-part-string-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-preprocessor-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-script-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-sql-keyword-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-string-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-style-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-symbol-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-type-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-underline-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-variable-name-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-warning-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "web-mode-whitespace-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ },
+ "yasnippet": {
+ "yas--field-debug-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ },
+ "yas-field-highlight-face": {
+ "fg": null,
+ "bg": null,
+ "source": "default"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/scripts/theme-studio/styles.css b/scripts/theme-studio/styles.css
index 72541ca0..cc074dac 100644
--- a/scripts/theme-studio/styles.css
+++ b/scripts/theme-studio/styles.css
@@ -23,13 +23,16 @@
.cat{color:#b4b1a2} .ex{font-size:17px}
.sbtn{width:26px;height:24px;border:1px solid #3a3a3a;border-radius:3px;background:#eaeaea;color:#111;cursor:pointer;font-size:15px;margin-right:2px;padding:0}
.sbtn.on{background:#0d0b0a;color:#cdced1;border-color:#8a9496}
- .pals{display:flex;gap:8px;flex-wrap:wrap}
+ .pals{display:flex;flex-direction:row;flex-wrap:wrap;gap:10px;align-items:flex-start}
+ .fstrip{display:flex;flex-direction:column;gap:6px;padding:5px;border-radius:7px;border:1px solid transparent}
+ .fstrip.ground{border-color:#252321;background:#161412}
+ .fcount{margin-top:3px;font:9pt monospace;color:#8a9496;text-align:center}
+ .fcount input{width:40px;background:#0d0b0a;border:1px solid #252321;color:#cdced1;border-radius:4px;padding:2px 4px;font:9pt monospace;text-align:center}
.palwarn{display:none;margin-top:8px;font:10pt monospace;color:#cb6b4d}
.palwarn .pwh{font-weight:bold;margin-bottom:2px}
.palwarn .pwl{opacity:.92}
.pchip{width:128px;height:58px;border-radius:6px;border:1px solid #555;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:grab}
- .pchip.drag{opacity:.4} .pchip.sel{outline:3px solid #e8bd30;outline-offset:2px} .pchip.over{outline:2px dashed #e8bd30;outline-offset:1px} .pchip input.nm{background:transparent;border:none;text-align:center;font:bold 10pt monospace;width:108px;outline:none}
- .pchip .mv{position:absolute;bottom:-1px;background:none;border:none;cursor:pointer;font-size:22px;line-height:1;font-weight:bold;opacity:.5;padding:0 5px} .pchip .mv:hover{opacity:1} .pchip .mv.l{left:0} .pchip .mv.r{right:0}
+ .pchip.sel{outline:3px solid #e8bd30;outline-offset:2px} .pchip input.nm{background:transparent;border:none;text-align:center;font:bold 10pt monospace;width:108px;outline:none}
.pchip .hx{font-size:10pt;opacity:.8} .pchip .rm{position:absolute;top:2px;right:5px;background:none;border:none;cursor:pointer;font-size:14px;font-weight:bold;opacity:.7}
.pchip .lock{position:absolute;top:3px;right:5px;font-size:10px;opacity:.6}
.palctl{margin-top:12px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
@@ -55,13 +58,14 @@
.oklchctl .ocrow input[type=number]{width:62px;background:#252321;color:#cdced1;border:1px solid #3a3a3a;border-radius:3px;font:10pt monospace;padding:1px 3px}
.oklchctl .pclamp{display:none;color:#cb6b4d;margin-top:3px}
.oklchctl .pclamp.show{display:block}
- .svcur{position:absolute;width:16px;height:16px;border:2px solid #fff;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #0008;pointer-events:none}
+ .svcur{position:absolute;width:16px;height:16px;border:2px solid #fff;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #0008;pointer-events:none;z-index:3}
.hue{position:relative;width:34px;height:320px;border-radius:4px;cursor:ns-resize;background:linear-gradient(to bottom,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)}
.huecur{position:absolute;left:-2px;right:-2px;height:4px;background:#fff;border:1px solid #0008;transform:translateY(-50%);pointer-events:none}
.pinfo{display:flex;justify-content:space-between;margin:10px 2px 4px;font:12pt monospace;color:#cdced1}
.pinfo2{display:flex;justify-content:space-between;margin:0 2px 9px;font:10pt monospace;color:#9aa3ad}
.pinfo2 span{cursor:default}
.pkchips{display:flex;flex-wrap:wrap;gap:5px} .pkchips .pc{width:28px;height:28px;border-radius:3px;border:1px solid #555;cursor:pointer}
+ .svsafe{position:absolute;left:0;width:100%;background:rgba(203,107,77,0.30);border-bottom:2px solid #cb6b4d;pointer-events:none;z-index:2}
.palctl button,.filebar button,.fbtn{background:#252321;color:#e8bd30;border:1px solid #3a3a3a;border-radius:4px;padding:6px 12px;font:10pt monospace;cursor:pointer}
#palmsg{font:10pt monospace;opacity:0;transition:opacity .35s;margin-left:6px}
#export{width:100%;height:180px;margin-top:10px;background:#0d0b0a;color:#a4ac64;border:1px solid #252321;border-radius:6px;font:10pt monospace;padding:10px}
diff --git a/scripts/theme-studio/test-app-core.mjs b/scripts/theme-studio/test-app-core.mjs
index 16202525..39a44967 100644
--- a/scripts/theme-studio/test-app-core.mjs
+++ b/scripts/theme-studio/test-app-core.mjs
@@ -148,7 +148,7 @@ test('slugify: Error — an all-disallowed name falls back to "theme"', () => {
// the page must carry app-core.js's body (sans exports) verbatim. Requires
// `python3 generate.py` to have run first.
const stripExports = (s) =>
- s.split('\n').filter((l) => !l.startsWith('export')).join('\n').replace(/\s+$/, '');
+ s.split('\n').filter((l) => !(l.startsWith('export') || l.startsWith('import'))).join('\n').replace(/\s+$/, '');
test('inline-integrity: theme-studio.html contains the app-core.js body verbatim', () => {
const body = stripExports(readFileSync(here + 'app-core.js', 'utf8'));
diff --git a/scripts/theme-studio/test-colormath.mjs b/scripts/theme-studio/test-colormath.mjs
index 58ce7829..992d35bc 100644
--- a/scripts/theme-studio/test-colormath.mjs
+++ b/scripts/theme-studio/test-colormath.mjs
@@ -13,6 +13,7 @@ import {
srgb2oklab, oklab2oklch, oklch2oklab, oklch2hex, apca, deltaE,
hex2rgb, rl, contrast, rating, hsv2rgb, rgb2hsv, rgb2hex,
oklab2lrgb, inGamut, lrgb2hex, planeCell, paletteWarnings,
+ reliefColors,
} from './colormath.js';
const close = (a, b, eps = 0.005) => Math.abs(a - b) <= eps;
@@ -230,6 +231,37 @@ test('paletteWarnings: threshold is inclusive-exclusive at the boundary', () =>
assert.equal(paletteWarnings(pal, 0.007).warnings.length, 1, 'just above the pair distance');
});
+// Fixtures hand-computed from Emacs 30's xterm.c x_alloc_lighter_color
+// (factor 1.2 / delta 0x8000 highlight, 0.6 / 0x4000 shadow, dark boost
+// below brightness 48000/65535, same-color fallback adds delta).
+test('reliefColors: dark mode-line bg gets the dark boost (Normal)', () => {
+ const { hl, sh } = reliefColors('#30343c');
+ assert.equal(hl, '#71767f');
+ assert.equal(sh, '#0f1116');
+});
+
+test('reliefColors: grey75 brightness is above the boost limit (Normal)', () => {
+ const { hl, sh } = reliefColors('#bfbfbf');
+ assert.equal(hl, '#e5e5e5'); // 1.2x only, no additive boost
+ assert.equal(sh, '#737373'); // 0.6x only
+});
+
+test('reliefColors: pure black hits the same-color fallback for the shadow (Boundary)', () => {
+ const { hl, sh } = reliefColors('#000000');
+ assert.equal(hl, '#4d4d4d'); // boost lifts the highlight off black
+ assert.equal(sh, '#404040'); // 0.6x + boost still black -> fallback adds delta
+});
+
+test('reliefColors: pure white highlight saturates, shadow scales (Boundary)', () => {
+ const { hl, sh } = reliefColors('#ffffff');
+ assert.equal(hl, '#ffffff'); // clamped, fallback also clamps to white
+ assert.equal(sh, '#999999');
+});
+
+test('reliefColors: malformed hex returns null pair (Error)', () => {
+ assert.deepEqual(reliefColors('nonsense'), { hl: null, sh: null });
+});
+
// Guards the one-source-of-truth contract: the page must carry colormath.js's
// body (sans exports) verbatim, so the inlined copy and the tested module cannot
// drift. Requires `python3 generate.py` to have run first.
diff --git a/scripts/theme-studio/test-contrast.mjs b/scripts/theme-studio/test-contrast.mjs
new file mode 100644
index 00000000..9baf5bcc
--- /dev/null
+++ b/scripts/theme-studio/test-contrast.mjs
@@ -0,0 +1,111 @@
+// Unit tests for the background-contrast safety core (app-core.js): fgSetFor,
+// floor, and lMax. Phase 3 of the palette-ramps spec. A background overlay sits
+// behind many foregrounds at once, so its real constraint is the worst-case
+// (minimum) contrast over that foreground set, and the lightest background that
+// keeps the floor above the target. Pure, no DOM. Run: node --test scripts/theme-studio/
+
+import { test } from 'node:test';
+import assert from 'node:assert/strict';
+import { fgSetFor, floor, lMax, COVERED_FACES } from './app-core.js';
+import { contrast, oklch2hex } from './colormath.js';
+
+const DEFAULT_FG = '#f0fef0';
+const stateWith = (syntaxAssignments) => ({ covered: COVERED_FACES, syntaxAssignments, defaultFg: DEFAULT_FG });
+
+// --- fgSetFor ---------------------------------------------------------------
+
+test('fgSetFor: Normal — covered face gets default fg plus the distinct syntax colors', () => {
+ const r = fgSetFor('region', stateWith([
+ { role: 'keyword', hex: '#67809c' },
+ { role: 'string', hex: '#a3b18a' },
+ ]));
+ assert.equal(r.reason, undefined);
+ assert.equal(r.set.length, 3); // default + 2 syntax
+ const hexes = r.set.map(e => e.hex);
+ assert.ok(hexes.includes('#f0fef0') && hexes.includes('#67809c') && hexes.includes('#a3b18a'));
+ assert.equal(r.set.find(e => e.hex === '#67809c').label, 'keyword');
+ assert.equal(r.set.find(e => e.hex === '#f0fef0').label, 'default');
+});
+
+test('fgSetFor: Boundary — a syntax hex equal to the default collapses, role label wins', () => {
+ const r = fgSetFor('region', { covered: COVERED_FACES, syntaxAssignments: [{ role: 'keyword', hex: '#f0fef0' }], defaultFg: '#f0fef0' });
+ assert.equal(r.set.length, 1);
+ assert.equal(r.set[0].label, 'keyword'); // role preferred over 'default'
+});
+
+test('fgSetFor: Boundary — null/blank syntax hexes are dropped', () => {
+ const r = fgSetFor('isearch', stateWith([{ role: 'a', hex: null }, { role: 'b', hex: '#112233' }]));
+ assert.equal(r.set.length, 2); // default + the one real hex
+ assert.ok(r.set.some(e => e.hex === '#112233'));
+});
+
+test('fgSetFor: Error — a face outside the covered set is out-of-scope', () => {
+ const r = fgSetFor('mode-line', stateWith([{ role: 'keyword', hex: '#67809c' }]));
+ assert.deepEqual(r, { set: [], reason: 'out-of-scope' });
+});
+
+test('fgSetFor: Error — a covered face with no syntax assignments is empty', () => {
+ const r = fgSetFor('hl-line', stateWith([]));
+ assert.deepEqual(r, { set: [], reason: 'empty' });
+});
+
+test('fgSetFor: Normal — every covered face is in scope', () => {
+ for (const f of COVERED_FACES) {
+ const r = fgSetFor(f, stateWith([{ role: 'kw', hex: '#67809c' }]));
+ assert.equal(r.reason, undefined, `${f} should be covered`);
+ }
+});
+
+// --- floor ------------------------------------------------------------------
+
+test('floor: Normal — the keyword-blue worst case sets the floor and is named', () => {
+ // sterling's keyword blue is the darkest foreground; against a lifted highlight
+ // background it is the limiting color while the light default still clears.
+ const fgSet = [{ hex: '#f0fef0', label: 'default' }, { hex: '#67809c', label: 'keyword' }];
+ const bg = '#202830';
+ const r = floor(bg, fgSet);
+ assert.equal(r.limitingHex, '#67809c');
+ assert.equal(r.limitingLabel, 'keyword');
+ assert.ok(Math.abs(r.ratio - contrast('#67809c', bg)) < 1e-9);
+ assert.ok(r.ratio < contrast('#f0fef0', bg), 'the floor is below the default-fg contrast');
+});
+
+test('floor: Boundary — a single-entry set makes that entry the limit', () => {
+ const r = floor('#000000', [{ hex: '#67809c', label: 'keyword' }]);
+ assert.equal(r.limitingHex, '#67809c');
+ assert.ok(Math.abs(r.ratio - contrast('#67809c', '#000000')) < 1e-9);
+});
+
+test('floor: Error — an empty set returns nulls, not a bogus ratio', () => {
+ assert.deepEqual(floor('#000000', []), { ratio: null, limitingHex: null, limitingLabel: null });
+});
+
+// --- lMax -------------------------------------------------------------------
+
+const F = (L, chroma, hue, fgSet) => floor(oklch2hex(L, chroma, hue).hex, fgSet).ratio;
+
+test('lMax: Normal — finds the lightest safe background; the floor brackets the target', () => {
+ const fgSet = [{ hex: '#f0fef0', label: 'default' }, { hex: '#67809c', label: 'keyword' }];
+ const r = lMax(0, 0, fgSet, 4.5);
+ assert.equal(r.status, 'ok');
+ assert.ok(r.L > 0 && r.L < 1);
+ assert.ok(F(r.L, 0, 0, fgSet) >= 4.5 - 0.05, 'floor at L_max clears the target');
+ assert.ok(F(Math.min(1, r.L + 0.05), 0, 0, fgSet) < 4.5, 'just above L_max the floor fails');
+});
+
+test('lMax: Boundary — no L satisfies the target when a foreground is too dark', () => {
+ const r = lMax(0, 0, [{ hex: '#1a1a1a', label: 'dim' }], 4.5);
+ assert.equal(r.status, 'none'); // even pure-black background can't lift #1a1a1a to AA
+});
+
+test('lMax: Boundary — an empty foreground set is vacuously safe everywhere', () => {
+ const r = lMax(0, 0, [], 4.5);
+ assert.deepEqual(r, { L: 1, status: 'all' });
+});
+
+test('lMax: Boundary — requesting an unreachable chroma at the ceiling reports clamp', () => {
+ const fgSet = [{ hex: '#f0fef0', label: 'default' }, { hex: '#67809c', label: 'keyword' }];
+ const r = lMax(250, 0.3, fgSet, 4.5); // 0.3 chroma is out of gamut at the dark ceiling
+ assert.equal(r.status, 'clamp');
+ assert.ok(r.L > 0 && r.L < 1);
+});
diff --git a/scripts/theme-studio/test-families.mjs b/scripts/theme-studio/test-families.mjs
new file mode 100644
index 00000000..c6602aeb
--- /dev/null
+++ b/scripts/theme-studio/test-families.mjs
@@ -0,0 +1,213 @@
+// Unit tests for the color-families model (app-core.js): grouping a flat palette
+// into hue families, regenerating a family's ramp, ranking members by lightness,
+// and planning the assignment re-point across a regenerate. Phase 1 of the
+// color-families spec. Pure, no DOM. Run: node --test scripts/theme-studio/
+
+import { test } from 'node:test';
+import assert from 'node:assert/strict';
+import { familiesFromPalette, regenFamily, rankByLightness, stepRepointPlan, sortFamilies } from './app-core.js';
+import { oklch2hex, srgb2oklab, oklab2oklch } from './colormath.js';
+
+// Build a palette entry at a controlled OKLCH hue so clustering is deterministic.
+const at = (L, C, H, name) => [oklch2hex(L, C, H).hex, name || ('c' + H)];
+
+// --- familiesFromPalette ----------------------------------------------------
+
+test('familiesFromPalette: Normal — separated hues split into one family each', () => {
+ const pal = [at(0.6, 0.1, 30, 'red'), at(0.6, 0.1, 150, 'green'), at(0.6, 0.1, 270, 'blue')];
+ const { ground, families } = familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' });
+ assert.equal(families.length, 3, 'three separated hues -> three families');
+ assert.equal(ground.length, 2, 'ground strip carries bg and fg');
+ for (const f of families) assert.equal(f.members.length, 1);
+});
+
+test('familiesFromPalette: Boundary — near hues at the same lightness stay one family', () => {
+ const pal = [at(0.55, 0.1, 250, 'b1'), at(0.6, 0.1, 256, 'b2')];
+ const { families } = familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' });
+ assert.equal(families.length, 1, 'a near hue-pair is one family');
+ assert.equal(families[0].members.length, 2);
+});
+
+test('familiesFromPalette: Boundary — well-separated hues split', () => {
+ const pal = [at(0.6, 0.1, 255, 'b'), at(0.6, 0.1, 200, 'c')];
+ const { families } = familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' });
+ assert.equal(families.length, 2);
+});
+
+test('familiesFromPalette: Boundary — an intermediate chain does not merge gold into green', () => {
+ // complete linkage requires every cross-pair compatible, so the far endpoints (90° vs 150°) keep the chain from fusing
+ const pal = [at(0.7, 0.1, 90, 'gold'), at(0.65, 0.1, 110, 'olive'), at(0.6, 0.1, 130, 'yg'), at(0.55, 0.1, 150, 'green')];
+ const { families } = familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' });
+ assert.equal(families.length, 2, 'not one chained family');
+});
+
+test('familiesFromPalette: Boundary — a pale tint keeps its hue while a mid gray goes neutral', () => {
+ const paleBlue = oklch2hex(0.9, 0.03, 255).hex; // light, faint -> still blue
+ const midGray = oklch2hex(0.6, 0.025, 100).hex; // mid, faint -> reads neutral
+ const { families } = familiesFromPalette([[paleBlue, 'paleblue'], [midGray, 'graytone']], { bg: '#000000', fg: '#ffffff' });
+ const neutral = families.find(f => f.neutral);
+ assert.ok(neutral && neutral.members.some(m => m.name === 'graytone'), 'mid faint color is neutral');
+ assert.ok(families.some(f => !f.neutral && f.members.some(m => m.name === 'paleblue')), 'pale tint stays chromatic');
+});
+
+test('familiesFromPalette: Boundary — near-neutral colors form a separate family', () => {
+ const pal = [at(0.6, 0.1, 250, 'blue'), at(0.5, 0.004, 250, 'gray')]; // gray below the chroma threshold
+ const { families } = familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' });
+ const neutral = families.find(f => f.neutral);
+ assert.ok(neutral, 'a neutral family exists');
+ assert.ok(neutral.members.some(m => m.name === 'gray'));
+ assert.ok(families.some(f => !f.neutral && f.members.some(m => m.name === 'blue')));
+});
+
+// --- real-palette grouping (the hard cases the color-sorting reviews measured) ---
+
+// The contested region of the distinguished/sterling palette: the gold ramp and
+// the olive ramp whose hue ranges nearly touch but whose mid-tones are far apart.
+const GOLD = [['#875f00', 'yellow-2'], ['#8e784c', 'yellow-1'], ['#d7af5f', 'yellow'], ['#ffd75f', 'yellow+1']];
+const OLIVE = [['#646d14', 'green-2'], ['#869038', 'green-1'], ['#a4ac64', 'green'], ['#ccc768', 'green+1']];
+const famOf = (families, name) => families.find(f => f.members.some(m => m.name === name));
+
+test('familiesFromPalette: Normal — the gold and olive ramps separate', () => {
+ const { families } = familiesFromPalette([...GOLD, ...OLIVE], { bg: '#000000', fg: '#ffffff' });
+ const gold = famOf(families, 'yellow'), olive = famOf(families, 'green');
+ assert.notEqual(gold, olive, 'gold and olive are different families');
+ assert.ok(!gold.members.some(m => m.name.startsWith('green')), 'gold family has no greens');
+ assert.ok(!olive.members.some(m => m.name.startsWith('yellow')), 'olive family has no yellows');
+});
+
+test('familiesFromPalette: Normal — the blue ramp stays whole despite pale-tint hue drift', () => {
+ // blue (H 252), blue+1 (H 231), blue+2 (H 272): low-chroma pale tints swing in hue but belong together
+ const pal = [['#67809c', 'blue'], ['#b2c3cc', 'blue+1'], ['#d9e2ff', 'blue+2']];
+ const { families } = familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' });
+ const blue = famOf(families, 'blue');
+ assert.equal(blue.members.length, 3, 'all three blues in one family');
+});
+
+test('familiesFromPalette: Boundary — pale warm grays and pure white read as neutral', () => {
+ const pal = [['#b4b1a2', 'gray+1'], ['#d0cbc0', 'gray+2'], ['#ffffff', 'white'], ['#67809c', 'blue']];
+ const { families } = familiesFromPalette(pal, { bg: '#000000', fg: '#f0fef0' }); // fg distinct from the white swatch
+ const neutral = families.find(f => f.neutral);
+ for (const n of ['gray+1', 'gray+2', 'white']) assert.ok(neutral.members.some(m => m.name === n), n + ' is neutral');
+ assert.ok(famOf(families, 'blue') && !famOf(families, 'blue').neutral, 'blue stays chromatic');
+});
+
+test('familiesFromPalette: Boundary — a vivid accent stays out of a soft same-hue family', () => {
+ // intense-red (C 0.246) vs red (C 0.120) at similar lightness: the chroma clause keeps them apart
+ const pal = [['#ff2a00', 'intense-red'], ['#d47c59', 'red'], ['#a7502d', 'red-1']];
+ const { families } = familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' });
+ assert.notEqual(famOf(families, 'intense-red'), famOf(families, 'red'), 'intense-red is its own family');
+});
+
+test('familiesFromPalette: Boundary — grouping is independent of palette order', () => {
+ const base = [...GOLD, ...OLIVE, ['#67809c', 'blue'], ['#b2c3cc', 'blue+1'], ['#969385', 'gray']];
+ const key = pal => familiesFromPalette(pal, { bg: '#000000', fg: '#ffffff' }).families
+ .map(f => f.members.map(m => m.name).sort().join(',')).sort().join(' | ');
+ const ref = key(base);
+ for (const seed of [1, 2, 3]) { // a few deterministic shuffles
+ const shuffled = base.map((e, i) => [e, ((i + 1) * seed * 7) % base.length]).sort((a, b) => a[1] - b[1]).map(x => x[0]);
+ assert.equal(key(shuffled), ref, 'shuffle ' + seed + ' yields the same grouping');
+ }
+});
+
+test('familiesFromPalette: Boundary — ground hex absent from the palette still forms the strip', () => {
+ const pal = [at(0.6, 0.1, 250, 'blue')];
+ const { ground } = familiesFromPalette(pal, { bg: '#0d0b0a', fg: '#f0fef0' });
+ assert.equal(ground.length, 2);
+ assert.ok(ground.some(g => g.hex.toLowerCase() === '#0d0b0a' && g.role === 'bg'));
+ assert.ok(ground.some(g => g.role === 'fg'));
+});
+
+test('familiesFromPalette: Boundary — a chip at a ground hex is not duplicated into a family', () => {
+ const pal = [['#0d0b0a', 'ground'], at(0.6, 0.1, 250, 'blue')];
+ const { ground, families } = familiesFromPalette(pal, { bg: '#0d0b0a', fg: '#f0fef0' });
+ assert.ok(ground.some(g => g.hex.toLowerCase() === '#0d0b0a'));
+ assert.ok(!families.some(f => f.members.some(m => m.hex.toLowerCase() === '#0d0b0a')), 'ground chip stays out of families');
+});
+
+// --- regenFamily ------------------------------------------------------------
+
+test('regenFamily: Normal — n steps each side plus the base, ordered by offset', () => {
+ const r = regenFamily('#67809c', 2);
+ assert.equal(r.members.length, 5);
+ assert.deepEqual(r.members.map(m => m.offset), [-2, -1, 0, 1, 2]);
+ assert.equal(r.members.find(m => m.offset === 0).hex, '#67809c');
+});
+
+test('regenFamily: Boundary — n=0 is the base alone, no ramp() clamp to 1', () => {
+ const r = regenFamily('#67809c', 0);
+ assert.deepEqual(r.members, [{ hex: '#67809c', offset: 0, clamped: false }]);
+});
+
+test('regenFamily: Error — a malformed base returns a structured bad-hex', () => {
+ assert.deepEqual(regenFamily('nope', 2), { members: [], error: 'bad-hex' });
+});
+
+// --- rankByLightness --------------------------------------------------------
+
+test('rankByLightness: Normal — offsets are signed distance from the base by lightness', () => {
+ const members = regenFamily('#67809c', 2).members.map(m => m.hex);
+ const ranked = rankByLightness(members, '#67809c');
+ const base = ranked.find(m => m.hex === '#67809c');
+ assert.equal(base.offset, 0);
+ const sorted = [...ranked].sort((a, b) => a.offset - b.offset);
+ assert.deepEqual(sorted.map(m => m.offset), [-2, -1, 0, 1, 2]);
+});
+
+test('rankByLightness: Boundary — a base not among the members ranks by nearest lightness', () => {
+ const members = ['#222222', '#888888', '#dddddd'];
+ const ranked = rankByLightness(members, '#8a8a8a'); // near the mid member
+ const mid = ranked.find(m => m.hex === '#888888');
+ assert.equal(mid.offset, 0, 'nearest-lightness member is the base rank');
+});
+
+// --- stepRepointPlan --------------------------------------------------------
+
+test('stepRepointPlan: Normal — surviving offsets map old->new, changed hex only', () => {
+ const oldR = [{ hex: '#111111', offset: -1 }, { hex: '#222222', offset: 0 }, { hex: '#333333', offset: 1 }];
+ const neu = [{ hex: '#111111', offset: -1 }, { hex: '#aaaaaa', offset: 0 }, { hex: '#444444', offset: 1 }];
+ const { map, removed } = stepRepointPlan(oldR, neu);
+ assert.deepEqual(removed, []);
+ assert.deepEqual(map, [['#222222', '#aaaaaa'], ['#333333', '#444444']]); // -1 unchanged, skipped
+});
+
+test('stepRepointPlan: Boundary — an offset with no new counterpart is removed, not repointed', () => {
+ const oldR = [{ hex: '#000033', offset: -3 }, { hex: '#222222', offset: 0 }];
+ const neu = [{ hex: '#222222', offset: 0 }]; // count dropped, -3 gone
+ const { map, removed } = stepRepointPlan(oldR, neu);
+ assert.deepEqual(map, []);
+ assert.deepEqual(removed, ['#000033']);
+});
+
+// --- sortFamilies -----------------------------------------------------------
+
+const fam = (baseHex, neutral, members) => ({ base: baseHex, neutral: !!neutral, members: (members || [baseHex]).map(h => ({ hex: h, name: h })) });
+
+test('sortFamilies: Normal — chromatic families order by base hue', () => {
+ const fams = [fam(oklch2hex(0.6, 0.1, 270).hex), fam(oklch2hex(0.6, 0.1, 30).hex), fam(oklch2hex(0.6, 0.1, 150).hex)];
+ const sorted = sortFamilies(fams);
+ const hues = sorted.map(f => Math.round(oklab2oklch(srgb2oklab(f.base)).H));
+ for (let i = 1; i < hues.length; i++) assert.ok(hues[i] > hues[i - 1], 'ascending hue: ' + hues.join(','));
+});
+
+test('sortFamilies: Boundary — neutral families pin ahead of chromatic ones', () => {
+ const sorted = sortFamilies([fam(oklch2hex(0.6, 0.1, 200).hex, false), fam('#808080', true)]);
+ assert.equal(sorted[0].neutral, true, 'neutral first');
+ assert.equal(sorted[1].neutral, false);
+});
+
+test('sortFamilies: Normal — members within a family sort dark to light', () => {
+ const members = ['#dddddd', '#222222', '#888888'];
+ const sorted = sortFamilies([fam(oklch2hex(0.6, 0.1, 200).hex, false, members)]);
+ const ls = sorted[0].members.map(m => oklab2oklch(srgb2oklab(m.hex)).L);
+ for (let i = 1; i < ls.length; i++) assert.ok(ls[i] > ls[i - 1], 'ascending lightness');
+});
+
+test('sortFamilies: Boundary — order is (hue, then lightness); a hue tie falls to lightness', () => {
+ const bases = [oklch2hex(0.6, 0.1, 200).hex, oklch2hex(0.5, 0.1, 200).hex, oklch2hex(0.6, 0.1, 40).hex];
+ const sorted = sortFamilies(bases.map(b => fam(b, false)));
+ const key = h => { const c = oklab2oklch(srgb2oklab(h)); return [Math.round(c.H), c.L]; };
+ for (let i = 1; i < sorted.length; i++) {
+ const [h0, l0] = key(sorted[i - 1].base), [h1, l1] = key(sorted[i].base);
+ assert.ok(h0 < h1 || (h0 === h1 && l0 <= l1), `order at ${i}: hue ${h0}/${h1} L ${l0.toFixed(3)}/${l1.toFixed(3)}`);
+ }
+});
diff --git a/scripts/theme-studio/test-ramp.mjs b/scripts/theme-studio/test-ramp.mjs
new file mode 100644
index 00000000..0c447ff4
--- /dev/null
+++ b/scripts/theme-studio/test-ramp.mjs
@@ -0,0 +1,105 @@
+// Unit tests for the ramp generator (app-core.js `ramp`). Phase 1 of the
+// palette-ramps spec: one base color -> a harmonized tonal ramp by stepping
+// OKLCH lightness on a held hue, easing chroma toward the extremes, and
+// gamut-clamping each step. Pure, no DOM. Run: node --test scripts/theme-studio/
+
+import { test } from 'node:test';
+import assert from 'node:assert/strict';
+import { ramp } from './app-core.js';
+import { srgb2oklab, oklab2oklch, rl } from './colormath.js';
+
+const HEXRE = /^#[0-9a-f]{6}$/;
+const baseLCH = (hex) => oklab2oklch(srgb2oklab(hex));
+
+test('ramp: Normal — default opts give 2n steps, darkest-to-lightest, base excluded', () => {
+ const r = ramp('#67809c'); // mid blue
+ assert.deepEqual(r.adjusted, []);
+ assert.equal(r.steps.length, 4); // n=2 -> -2,-1,+1,+2
+ assert.deepEqual(r.steps.map(s => s.offset), [-2, -1, 1, 2]);
+ for (const s of r.steps) assert.match(s.hex, HEXRE, `${s.hex} is a 6-digit hex`);
+ // Lightness rises monotonically across the ordered steps.
+ const ls = r.steps.map(s => rl(s.hex));
+ for (let i = 1; i < ls.length; i++) assert.ok(ls[i] > ls[i - 1], 'each step lighter than the last');
+ // Base sits between -1 and +1 in lightness.
+ const baseL = rl('#67809c');
+ assert.ok(rl(r.steps[1].hex) < baseL && baseL < rl(r.steps[2].hex), 'base brackets the inner steps');
+});
+
+test('ramp: Normal — holds the hue across in-gamut steps', () => {
+ const base = '#67809c';
+ const H0 = baseLCH(base).H;
+ // chromaEase 0 keeps chroma up so the recovered hue is well-defined (near-gray
+ // steps have an ill-defined hue that 8-bit quantization can swing).
+ const r = ramp(base, { chromaEase: 0 });
+ for (const s of r.steps) {
+ if (s.clamped) continue; // a clamped step may drift hue; only assert on clean ones
+ const dH = Math.abs(baseLCH(s.hex).H - H0);
+ assert.ok(Math.min(dH, 360 - dH) < 3.0, `step ${s.offset} holds hue (${dH.toFixed(2)} deg off)`);
+ }
+});
+
+test('ramp: Normal — chroma eases toward the extremes (outer step less chromatic than inner)', () => {
+ const base = '#67809c';
+ const r = ramp(base, { n: 2, chromaEase: 0.8 });
+ const inner = baseLCH(r.steps[1].hex).C; // offset -1
+ const outer = baseLCH(r.steps[0].hex).C; // offset -2
+ assert.ok(outer < inner, 'the farther step carries less chroma');
+});
+
+test('ramp: Normal — chromaEase 0 holds chroma flat', () => {
+ const base = '#67809c';
+ const C0 = baseLCH(base).C;
+ const r = ramp(base, { n: 1, stepL: 0.06, chromaEase: 0 });
+ for (const s of r.steps) {
+ if (s.clamped) continue;
+ assert.ok(Math.abs(baseLCH(s.hex).C - C0) < 0.01, 'chroma held within tolerance');
+ }
+});
+
+test('ramp: Boundary — near-white base clamps the lighter steps at L=1', () => {
+ const r = ramp('#f6f6f6', { n: 2, stepL: 0.08 });
+ assert.equal(r.steps.length, 4);
+ const lightest = r.steps[r.steps.length - 1];
+ assert.match(lightest.hex, HEXRE);
+ assert.ok(rl(lightest.hex) > 0.9, 'lightest step is near white');
+});
+
+test('ramp: Boundary — near-black base clamps the darker steps at L=0', () => {
+ const r = ramp('#0b0b0b', { n: 2, stepL: 0.08 });
+ assert.equal(r.steps.length, 4);
+ const darkest = r.steps[0];
+ assert.match(darkest.hex, HEXRE);
+ assert.ok(rl(darkest.hex) < 0.05, 'darkest step is near black');
+});
+
+test('ramp: Boundary — n clamps to [1,4] and reports the adjustment', () => {
+ const lo = ramp('#67809c', { n: 0 });
+ assert.equal(lo.steps.length, 2); // clamped to n=1
+ assert.ok(lo.adjusted.includes('n'));
+ const hi = ramp('#67809c', { n: 9 });
+ assert.equal(hi.steps.length, 8); // clamped to n=4
+ assert.ok(hi.adjusted.includes('n'));
+ const frac = ramp('#67809c', { n: 2.7 });
+ assert.equal(frac.steps.length, 6); // rounded to 3, in range, still flagged as adjusted
+ assert.ok(frac.adjusted.includes('n'));
+});
+
+test('ramp: Boundary — stepL and chromaEase clamp to range and report', () => {
+ const r = ramp('#67809c', { stepL: 0.5, chromaEase: 2 });
+ assert.ok(r.adjusted.includes('stepL'));
+ assert.ok(r.adjusted.includes('chromaEase'));
+ assert.equal(r.steps.length, 4);
+});
+
+test('ramp: Error — malformed hex returns a structured bad-hex, not a throw', () => {
+ for (const bad of ['nope', '#xyz', '#12', '12345g', null, undefined, '']) {
+ const r = ramp(bad);
+ assert.deepEqual(r, { steps: [], error: 'bad-hex' }, `${String(bad)} -> bad-hex`);
+ }
+});
+
+test('ramp: Boundary — a six-digit hex without the leading # is accepted', () => {
+ const r = ramp('67809c');
+ assert.equal(r.steps.length, 4);
+ assert.ok(!r.error);
+});
diff --git a/scripts/theme-studio/theme-studio.html b/scripts/theme-studio/theme-studio.html
index 90ac00cc..b85eead8 100644
--- a/scripts/theme-studio/theme-studio.html
+++ b/scripts/theme-studio/theme-studio.html
@@ -25,13 +25,16 @@
.cat{color:#b4b1a2} .ex{font-size:17px}
.sbtn{width:26px;height:24px;border:1px solid #3a3a3a;border-radius:3px;background:#eaeaea;color:#111;cursor:pointer;font-size:15px;margin-right:2px;padding:0}
.sbtn.on{background:#0d0b0a;color:#cdced1;border-color:#8a9496}
- .pals{display:flex;gap:8px;flex-wrap:wrap}
+ .pals{display:flex;flex-direction:row;flex-wrap:wrap;gap:10px;align-items:flex-start}
+ .fstrip{display:flex;flex-direction:column;gap:6px;padding:5px;border-radius:7px;border:1px solid transparent}
+ .fstrip.ground{border-color:#252321;background:#161412}
+ .fcount{margin-top:3px;font:9pt monospace;color:#8a9496;text-align:center}
+ .fcount input{width:40px;background:#0d0b0a;border:1px solid #252321;color:#cdced1;border-radius:4px;padding:2px 4px;font:9pt monospace;text-align:center}
.palwarn{display:none;margin-top:8px;font:10pt monospace;color:#cb6b4d}
.palwarn .pwh{font-weight:bold;margin-bottom:2px}
.palwarn .pwl{opacity:.92}
.pchip{width:128px;height:58px;border-radius:6px;border:1px solid #555;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:grab}
- .pchip.drag{opacity:.4} .pchip.sel{outline:3px solid #e8bd30;outline-offset:2px} .pchip.over{outline:2px dashed #e8bd30;outline-offset:1px} .pchip input.nm{background:transparent;border:none;text-align:center;font:bold 10pt monospace;width:108px;outline:none}
- .pchip .mv{position:absolute;bottom:-1px;background:none;border:none;cursor:pointer;font-size:22px;line-height:1;font-weight:bold;opacity:.5;padding:0 5px} .pchip .mv:hover{opacity:1} .pchip .mv.l{left:0} .pchip .mv.r{right:0}
+ .pchip.sel{outline:3px solid #e8bd30;outline-offset:2px} .pchip input.nm{background:transparent;border:none;text-align:center;font:bold 10pt monospace;width:108px;outline:none}
.pchip .hx{font-size:10pt;opacity:.8} .pchip .rm{position:absolute;top:2px;right:5px;background:none;border:none;cursor:pointer;font-size:14px;font-weight:bold;opacity:.7}
.pchip .lock{position:absolute;top:3px;right:5px;font-size:10px;opacity:.6}
.palctl{margin-top:12px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
@@ -57,13 +60,14 @@
.oklchctl .ocrow input[type=number]{width:62px;background:#252321;color:#cdced1;border:1px solid #3a3a3a;border-radius:3px;font:10pt monospace;padding:1px 3px}
.oklchctl .pclamp{display:none;color:#cb6b4d;margin-top:3px}
.oklchctl .pclamp.show{display:block}
- .svcur{position:absolute;width:16px;height:16px;border:2px solid #fff;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #0008;pointer-events:none}
+ .svcur{position:absolute;width:16px;height:16px;border:2px solid #fff;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #0008;pointer-events:none;z-index:3}
.hue{position:relative;width:34px;height:320px;border-radius:4px;cursor:ns-resize;background:linear-gradient(to bottom,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)}
.huecur{position:absolute;left:-2px;right:-2px;height:4px;background:#fff;border:1px solid #0008;transform:translateY(-50%);pointer-events:none}
.pinfo{display:flex;justify-content:space-between;margin:10px 2px 4px;font:12pt monospace;color:#cdced1}
.pinfo2{display:flex;justify-content:space-between;margin:0 2px 9px;font:10pt monospace;color:#9aa3ad}
.pinfo2 span{cursor:default}
.pkchips{display:flex;flex-wrap:wrap;gap:5px} .pkchips .pc{width:28px;height:28px;border-radius:3px;border:1px solid #555;cursor:pointer}
+ .svsafe{position:absolute;left:0;width:100%;background:rgba(203,107,77,0.30);border-bottom:2px solid #cb6b4d;pointer-events:none;z-index:2}
.palctl button,.filebar button,.fbtn{background:#252321;color:#e8bd30;border:1px solid #3a3a3a;border-radius:4px;padding:6px 12px;font:10pt monospace;cursor:pointer}
#palmsg{font:10pt monospace;opacity:0;transition:opacity .35s;margin-left:6px}
#export{width:100%;height:180px;margin-top:10px;background:#0d0b0a;color:#a4ac64;border:1px solid #252321;border-radius:6px;font:10pt monospace;padding:10px}
@@ -103,10 +107,11 @@
<span id="palmsg"></span>
<div id="picker" class="picker">
<div class="prow">
- <div id="sv" class="sv"><canvas id="svmask" class="svmask"></canvas><div id="svcur" class="svcur"></div></div>
+ <div id="sv" class="sv"><canvas id="svmask" class="svmask"></canvas><div id="svsafe" class="svsafe" style="display:none"></div><div id="svcur" class="svcur"></div></div>
<div id="hue" class="hue"><div id="huecur" class="huecur"></div></div>
</div>
<div class="pmodel">edit <button data-pm="hsv" class="on">HSV</button><button data-pm="oklch">OKLCH</button></div>
+ <div class="pmodel" title="in OKLCH mode, shade the lightness too light to keep this overlay face readable over its foreground set">safe for <select id="safefor" onchange="setSafeFace(this.value)"><option value="">none</option></select></div>
<div class="oklchctl" id="oklchctl">
<div class="ocrow"><label title="perceptual lightness">L</label><input type="range" id="okL" min="0" max="1" step="0.001"><input type="number" id="okLn" min="0" max="1" step="0.001"></div>
<div class="ocrow"><label title="chroma (colorfulness)">C</label><input type="range" id="okC" min="0" max="0.4" step="0.001"><input type="number" id="okCn" min="0" max="0.4" step="0.001"></div>
@@ -173,9 +178,9 @@
</section>
</div>
<script>
-const SAMPLES={"Elisp": [[["cmd", ";;"], ["cm", " cache.el"]], [["punc", "("], ["kw", "require"], ["p", " "], ["con", "'cl-lib"], ["punc", ")"]], [], [["punc", "("], ["kw", "defvar"], ["p", " "], ["var", "cache--tbl"], ["p", " "], ["punc", "("], ["fnc", "make-hash-table"], ["p", " "], ["con", ":test"], ["p", " "], ["con", "'equal"], ["punc", "))"]], [["p", " "], ["doc", "\"Memo table.\")"]], [], [["punc", "("], ["kw", "defun"], ["p", " "], ["fnd", "cache-get"], ["p", " "], ["punc", "("], ["var", "key"], ["punc", ")"]], [["p", " "], ["doc", "\"Return cached value for KEY.\""]], [["p", " "], ["punc", "("], ["kw", "or"], ["p", " "], ["punc", "("], ["bi", "gethash"], ["p", " "], ["var", "key"], ["p", " "], ["var", "cache--tbl"], ["punc", ")"]], [["p", " "], ["punc", "("], ["kw", "let"], ["p", " "], ["punc", "(("], ["var", "v"], ["p", " "], ["punc", "("], ["fnc", "compute"], ["p", " "], ["var", "key"], ["p", " "], ["num", "42"], ["punc", "))) "]], [["p", " "], ["punc", "("], ["fnc", "puthash"], ["p", " "], ["var", "key"], ["p", " "], ["var", "v"], ["p", " "], ["var", "cache--tbl"], ["punc", ") "], ["var", "v"], ["punc", "))))"]], [], [["punc", "("], ["kw", "defun"], ["p", " "], ["fnd", "cache-clear"], ["p", " "], ["punc", "()"]], [["p", " "], ["doc", "\"Empty the memo table.\""]], [["p", " "], ["punc", "("], ["kw", "interactive"], ["punc", ")"]], [["p", " "], ["punc", "("], ["fnc", "clrhash"], ["p", " "], ["var", "cache--tbl"], ["punc", ")"]], [["p", " "], ["punc", "("], ["fnc", "message"], ["p", " "], ["str", "\"cleared"], ["esc", "\\n"], ["str", "\""], ["punc", "))"]], [], [["punc", "("], ["kw", "defun"], ["p", " "], ["fnd", "cache-keys"], ["p", " "], ["punc", "()"]], [["p", " "], ["doc", "\"Return all keys.\""]], [["p", " "], ["punc", "("], ["kw", "let"], ["p", " "], ["punc", "(("], ["var", "acc"], ["p", " "], ["con", "nil"], ["punc", "))"]], [["p", " "], ["punc", "("], ["fnc", "maphash"], ["p", " "], ["punc", "("], ["kw", "lambda"], ["p", " "], ["punc", "("], ["var", "k"], ["p", " "], ["var", "_v"], ["punc", ")"], ["p", " "], ["punc", "("], ["fnc", "push"], ["p", " "], ["var", "k"], ["p", " "], ["var", "acc"], ["punc", "))"]], [["p", " "], ["var", "cache--tbl"], ["punc", ")"], ["p", " "], ["var", "acc"], ["punc", "))"]], [], [["punc", "("], ["kw", "provide"], ["p", " "], ["con", "'cache"], ["punc", ")"]]], "Go": [[["cmd", "//"], ["cm", " queue.go"]], [["kw", "package"], ["p", " "], ["var", "main"]], [], [["kw", "import"], ["p", " "], ["str", "\"fmt\""]], [], [["kw", "const"], ["p", " "], ["con", "MaxItems"], ["p", " "], ["op", "="], ["p", " "], ["num", "100"]], [], [["kw", "type"], ["p", " "], ["ty", "Order"], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"]], [["p", " "], ["prop", "ID"], ["p", " "], ["ty", "int"]], [["p", " "], ["prop", "Name"], ["p", " "], ["ty", "string"]], [["punc", "}"]], [], [["kw", "func"], ["p", " "], ["punc", "("], ["var", "q"], ["p", " "], ["op", "*"], ["ty", "Queue"], ["punc", ")"], ["p", " "], ["fnd", "Push"], ["punc", "("], ["var", "o"], ["p", " "], ["op", "*"], ["ty", "Order"], ["punc", ")"], ["p", " "], ["ty", "error"], ["p", " "], ["punc", "{"]], [["p", " "], ["cmd", "//"], ["cm", " reject nil"]], [["p", " "], ["kw", "if"], ["p", " "], ["var", "o"], ["p", " "], ["op", "=="], ["p", " "], ["con", "nil"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "return"], ["p", " "], ["fnc", "fmt.Errorf"], ["punc", "("], ["str", "\"nil"], ["esc", "\\n"], ["str", "\""], ["punc", ")"]], [["p", " "], ["punc", "}"]], [["p", " "], ["var", "q"], ["op", "."], ["prop", "items"], ["p", " "], ["op", "="], ["p", " "], ["bi", "append"], ["punc", "("], ["var", "q"], ["op", "."], ["prop", "items"], ["punc", ","], ["p", " "], ["var", "o"], ["punc", ")"]], [["p", " "], ["kw", "return"], ["p", " "], ["con", "nil"]], [["punc", "}"]], [], [["kw", "func"], ["p", " "], ["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["fnc", "fmt.Println"], ["punc", "("], ["op", "&"], ["ty", "Queue"], ["punc", "{}"], ["punc", ")"]], [["punc", "}"]]], "Python": [[["cmd", "#"], ["cm", " theme.py"]], [["kw", "from"], ["p", " "], ["var", "dataclasses"], ["p", " "], ["kw", "import"], ["p", " "], ["var", "dataclass"], ["punc", ","], ["p", " "], ["var", "field"]], [], [["con", "DEFAULT_PORT"], ["op", ":"], ["p", " "], ["ty", "int"], ["p", " "], ["op", "="], ["p", " "], ["num", "8080"]], [["con", "HEX"], ["p", " "], ["op", "="], ["p", " "], ["var", "re"], ["op", "."], ["fnc", "compile"], ["punc", "("], ["re", "r\"#[0-9a-f]{6}\""], ["punc", ")"]], [], [["dec", "@dataclass"]], [["kw", "class"], ["p", " "], ["ty", "Theme"], ["op", ":"]], [["p", " "], ["doc", "\"\"\"A color theme.\"\"\""]], [["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["ty", "str"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""]], [["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["ty", "dict"], ["p", " "], ["op", "="], ["p", " "], ["fnc", "field"], ["punc", "("], ["prop", "default_factory"], ["op", "="], ["ty", "dict"], ["punc", ")"]], [], [["p", " "], ["kw", "def"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["var", "self"], ["punc", ","], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["ty", "str"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "str"], ["p", " "], ["op", "|"], ["p", " "], ["con", "None"], ["op", ":"]], [["p", " "], ["cmd", "#"], ["cm", " fallback to none"]], [["p", " "], ["var", "v"], ["p", " "], ["op", "="], ["p", " "], ["var", "self"], ["op", "."], ["prop", "colors"], ["op", "."], ["fnc", "get"], ["punc", "("], ["var", "key"], ["punc", ","], ["p", " "], ["str", "\""], ["esc", "\\t"], ["str", "none\""], ["punc", ")"]], [["p", " "], ["kw", "if"], ["p", " "], ["bi", "len"], ["punc", "("], ["var", "v"], ["punc", ")"], ["p", " "], ["op", "=="], ["p", " "], ["num", "0"], ["op", ":"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "None"]], [["p", " "], ["kw", "return"], ["p", " "], ["var", "v"]], [], [["p", " "], ["dec", "@property"]], [["p", " "], ["kw", "def"], ["p", " "], ["fnd", "size"], ["punc", "("], ["var", "self"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "int"], ["op", ":"]], [["p", " "], ["kw", "return"], ["p", " "], ["bi", "len"], ["punc", "("], ["var", "self"], ["op", "."], ["prop", "colors"], ["punc", ")"]], [], [["var", "theme"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Theme"], ["punc", "("], ["str", "\"dupre\""], ["punc", ")"]], [["fnc", "print"], ["punc", "("], ["var", "theme"], ["op", "."], ["fnc", "resolve"], ["punc", "("], ["str", "\"bg\""], ["punc", "))"]]], "TypeScript": [[["cmd", "//"], ["cm", " orders.ts"]], [["kw", "import"], ["p", " "], ["punc", "{"], ["p", " "], ["ty", "Order"], ["p", " "], ["punc", "}"], ["p", " "], ["kw", "from"], ["p", " "], ["str", "\"./types\""]], [], [["kw", "export"], ["p", " "], ["kw", "interface"], ["p", " "], ["ty", "Queue"], ["p", " "], ["punc", "{"]], [["p", " "], ["prop", "max"], ["op", ":"], ["p", " "], ["ty", "number"], ["punc", ";"]], [["p", " "], ["prop", "items"], ["op", ":"], ["p", " "], ["ty", "Order"], ["punc", "[];"]], [["punc", "}"]], [], [["dec", "@Injectable"], ["punc", "()"]], [["kw", "export"], ["p", " "], ["kw", "class"], ["p", " "], ["ty", "OrderQueue"], ["p", " "], ["kw", "implements"], ["p", " "], ["ty", "Queue"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "private"], ["p", " "], ["prop", "re"], ["p", " "], ["op", "="], ["p", " "], ["re", "/^#[0-9a-f]{6}$/i"], ["punc", ";"]], [], [["p", " "], ["fnd", "push"], ["punc", "("], ["var", "o"], ["op", ":"], ["p", " "], ["ty", "Order"], ["punc", ")"], ["op", ":"], ["p", " "], ["ty", "boolean"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "o"], ["p", " "], ["op", "==="], ["p", " "], ["con", "null"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "false"], ["punc", ";"]], [["p", " "], ["var", "console"], ["op", "."], ["fnc", "log"], ["punc", "("], ["str", "`id "], ["punc", "${"], ["var", "o"], ["op", "."], ["prop", "id"], ["punc", "}"], ["esc", "\\n"], ["str", "`"], ["punc", ");"]], [["p", " "], ["kw", "return"], ["p", " "], ["con", "true"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"]], [], [["kw", "const"], ["p", " "], ["con", "LIMIT"], ["op", ":"], ["p", " "], ["ty", "number"], ["p", " "], ["op", "="], ["p", " "], ["num", "50"], ["punc", ";"]], [["kw", "const"], ["p", " "], ["var", "q"], ["p", " "], ["op", "="], ["p", " "], ["kw", "new"], ["p", " "], ["ty", "OrderQueue"], ["punc", "()"], ["punc", ";"]], [["var", "q"], ["op", "."], ["fnd", "push"], ["punc", "("], ["punc", "{"], ["p", " "], ["prop", "id"], ["op", ":"], ["p", " "], ["num", "1"], ["p", " "], ["punc", "}"], ["p", " "], ["kw", "as"], ["p", " "], ["ty", "Order"], ["punc", ")"], ["punc", ";"]], [["var", "console"], ["op", "."], ["fnc", "log"], ["punc", "("], ["var", "q"], ["op", "."], ["prop", "max"], ["punc", ")"], ["punc", ";"]], [["kw", "const"], ["p", " "], ["var", "cap"], ["p", " "], ["op", "="], ["p", " "], ["var", "Math"], ["op", "."], ["bi", "max"], ["punc", "("], ["con", "LIMIT"], ["punc", ","], ["p", " "], ["num", "0"], ["punc", ")"], ["punc", ";"]]], "Java": [[["cmd", "/**"], ["doc", " A color theme. */"]], [["kw", "package"], ["p", " "], ["var", "com"], ["op", "."], ["var", "dupre"], ["punc", ";"]], [["kw", "import"], ["p", " "], ["var", "java"], ["op", "."], ["var", "util"], ["op", "."], ["var", "regex"], ["op", "."], ["ty", "Pattern"], ["punc", ";"]], [], [["dec", "@Deprecated"]], [["kw", "public"], ["p", " "], ["kw", "final"], ["p", " "], ["kw", "class"], ["p", " "], ["ty", "Theme"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "private"], ["p", " "], ["kw", "static"], ["p", " "], ["kw", "final"], ["p", " "], ["ty", "int"], ["p", " "], ["con", "MAX_PORT"], ["p", " "], ["op", "="], ["p", " "], ["num", "8080"], ["punc", ";"]], [["p", " "], ["kw", "private"], ["p", " "], ["kw", "final"], ["p", " "], ["ty", "String"], ["p", " "], ["prop", "name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ";"]], [["p", " "], ["kw", "private"], ["p", " "], ["kw", "static"], ["p", " "], ["kw", "final"], ["p", " "], ["ty", "Pattern"], ["p", " "], ["con", "HEX"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Pattern"], ["op", "."], ["fnc", "compile"], ["punc", "("], ["re", "\"#[0-9a-f]{6}\""], ["punc", ")"], ["punc", ";"]], [], [["p", " "], ["dec", "@Override"]], [["p", " "], ["kw", "public"], ["p", " "], ["ty", "String"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["ty", "String"], ["p", " "], ["var", "key"], ["punc", ")"], ["p", " "], ["punc", "{"]], [["p", " "], ["cmd", "//"], ["cm", " fall back to null"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "key"], ["op", "."], ["fnc", "isEmpty"], ["punc", "()"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "null"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["var", "key"], ["op", "."], ["fnc", "strip"], ["punc", "("], ["punc", ")"], ["op", "+"], ["str", "\""], ["esc", "\\t"], ["str", "\""], ["punc", ";"]], [["p", " "], ["punc", "}"]], [], [["p", " "], ["kw", "public"], ["p", " "], ["kw", "static"], ["p", " "], ["ty", "void"], ["p", " "], ["fnd", "main"], ["punc", "("], ["ty", "String"], ["punc", "[]"], ["p", " "], ["var", "args"], ["punc", ")"], ["p", " "], ["punc", "{"]], [["p", " "], ["ty", "var"], ["p", " "], ["var", "t"], ["p", " "], ["op", "="], ["p", " "], ["kw", "new"], ["p", " "], ["ty", "Theme"], ["punc", "()"], ["punc", ";"]], [["p", " "], ["ty", "System"], ["op", "."], ["prop", "out"], ["op", "."], ["fnc", "println"], ["punc", "("], ["var", "t"], ["op", "."], ["fnc", "resolve"], ["punc", "("], ["str", "\"bg\""], ["punc", "))"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"]]], "C": [[["cmd", "/**"], ["doc", " Order queue. */"]], [["pp", "#include"], ["p", " "], ["str", "<stdio.h>"]], [["pp", "#include"], ["p", " "], ["str", "<stdlib.h>"]], [["pp", "#define"], ["p", " "], ["con", "MAX_PORT"], ["p", " "], ["num", "8080"]], [], [["kw", "typedef"], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"]], [["p", " "], ["ty", "int"], ["p", " "], ["prop", "id"], ["punc", ";"]], [["p", " "], ["kw", "const"], ["p", " "], ["ty", "char"], ["p", " "], ["op", "*"], ["prop", "name"], ["punc", ";"]], [["punc", "}"], ["p", " "], ["ty", "Order"], ["punc", ";"]], [], [["cmd", "//"], ["cm", " returns -1 on null input"]], [["ty", "int"], ["p", " "], ["fnd", "push"], ["punc", "("], ["ty", "Order"], ["p", " "], ["op", "*"], ["var", "o"], ["punc", ")"], ["p", " "], ["dec", "__attribute__"], ["punc", "(("], ["dec", "nonnull"], ["punc", "))"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "o"], ["p", " "], ["op", "=="], ["p", " "], ["con", "NULL"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["num", "-1"], ["punc", ";"]], [["p", " "], ["fnc", "printf"], ["punc", "("], ["str", "\"id=%d"], ["esc", "\\n"], ["str", "\""], ["punc", ","], ["p", " "], ["var", "o"], ["op", "->"], ["prop", "id"], ["punc", ");"]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "0"], ["punc", ";"]], [["punc", "}"]], [], [["ty", "int"], ["p", " "], ["fnd", "main"], ["punc", "("], ["ty", "void"], ["punc", ")"], ["p", " "], ["punc", "{"]], [["p", " "], ["ty", "Order"], ["p", " "], ["var", "o"], ["p", " "], ["op", "="], ["p", " "], ["punc", "{"], ["p", " "], ["op", "."], ["prop", "id"], ["p", " "], ["op", "="], ["p", " "], ["num", "1"], ["punc", ","], ["p", " "], ["op", "."], ["prop", "name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["ty", "Order"], ["p", " "], ["op", "*"], ["var", "p2"], ["p", " "], ["op", "="], ["p", " "], ["bi", "malloc"], ["punc", "("], ["bi", "sizeof"], ["punc", "("], ["ty", "Order"], ["punc", "))"], ["punc", ";"]], [["p", " "], ["fnc", "push"], ["punc", "("], ["op", "&"], ["var", "o"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["bi", "free"], ["punc", "("], ["var", "p2"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "0"], ["punc", ";"]], [["punc", "}"]]], "C++": [[["cmd", "/**"], ["doc", " A color theme. */"]], [["pp", "#include"], ["p", " "], ["str", "<string>"]], [["pp", "#include"], ["p", " "], ["str", "<regex>"]], [["pp", "#pragma"], ["p", " "], ["pp", "once"]], [], [["kw", "namespace"], ["p", " "], ["var", "dupre"], ["p", " "], ["punc", "{"]], [], [["kw", "template"], ["op", "<"], ["kw", "typename"], ["p", " "], ["ty", "T"], ["op", ">"], ["p", " "], ["kw", "class"], ["p", " "], ["ty", "Theme"], ["p", " "], ["punc", "{"]], [["kw", "public"], ["op", ":"]], [["p", " "], ["kw", "static"], ["p", " "], ["kw", "constexpr"], ["p", " "], ["ty", "int"], ["p", " "], ["con", "MAX"], ["p", " "], ["op", "="], ["p", " "], ["num", "0x20"], ["punc", ";"]], [["p", " "], ["ty", "std"], ["op", "::"], ["ty", "string"], ["p", " "], ["prop", "name_"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ";"]], [], [["p", " "], ["dec", "[[nodiscard]]"], ["p", " "], ["ty", "T"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["kw", "const"], ["p", " "], ["ty", "std"], ["op", "::"], ["ty", "string"], ["op", "&"], ["p", " "], ["var", "key"], ["punc", ")"], ["p", " "], ["kw", "const"], ["p", " "], ["punc", "{"]], [["p", " "], ["cmd", "//"], ["cm", " validate against a hex pattern"]], [["p", " "], ["kw", "static"], ["p", " "], ["ty", "std"], ["op", "::"], ["ty", "regex"], ["p", " "], ["var", "re"], ["punc", "("], ["re", "R\"(#[0-9a-f]{6})\""], ["punc", ")"], ["punc", ";"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "key"], ["op", "."], ["fnc", "empty"], ["punc", "()"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "nullptr"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["ty", "T"], ["punc", "{"], ["var", "key"], ["punc", "}"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"], ["punc", ";"]], [], [["ty", "int"], ["p", " "], ["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "auto"], ["p", " "], ["var", "t"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Theme"], ["op", "<"], ["ty", "int"], ["op", ">"], ["punc", "{}"], ["punc", ";"]], [["p", " "], ["bi", "static_cast"], ["op", "<"], ["ty", "int"], ["op", ">"], ["punc", "("], ["var", "t"], ["op", "."], ["prop", "name_"], ["op", "."], ["fnc", "size"], ["punc", "())"], ["punc", ";"]], [["p", " "], ["ty", "std"], ["op", "::"], ["fnc", "printf"], ["punc", "("], ["str", "\"%s"], ["esc", "\\n"], ["str", "\""], ["punc", ","], ["p", " "], ["var", "t"], ["op", "."], ["prop", "name_"], ["op", "."], ["fnc", "c_str"], ["punc", "())"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "0"], ["punc", ";"]], [["punc", "}"]]], "Shell": [[["cmd", "#!"], ["cm", "/bin/bash"]], [["cmd", "#"], ["cm", " deploy.sh"]], [["bi", "set"], ["p", " "], ["op", "-"], ["var", "euo"], ["p", " "], ["var", "pipefail"]], [], [["var", "PORT"], ["op", "="], ["num", "8080"]], [["var", "NAME"], ["op", "="], ["str", "\"dupre\""]], [], [["fnd", "deploy"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "local"], ["p", " "], ["var", "target"], ["op", "="], ["str", "\"$1\""]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "[["], ["p", " "], ["op", "-z"], ["p", " "], ["str", "\"$target\""], ["p", " "], ["punc", "]]"], ["punc", ";"], ["p", " "], ["kw", "then"]], [["p", " "], ["bi", "echo"], ["p", " "], ["str", "\"no target\""]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "1"]], [["p", " "], ["kw", "fi"]], [["p", " "], ["fnc", "rsync"], ["p", " "], ["op", "-az"], ["p", " "], ["str", "\"$NAME\""], ["p", " "], ["str", "\"$target\""]], [["punc", "}"]], [], [["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "for"], ["p", " "], ["var", "host"], ["p", " "], ["kw", "in"], ["p", " "], ["str", "\"$@\""], ["punc", ";"], ["p", " "], ["kw", "do"]], [["p", " "], ["fnc", "deploy"], ["p", " "], ["str", "\"$host\""], ["p", " "], ["op", "||"], ["p", " "], ["bi", "exit"], ["p", " "], ["num", "1"]], [["p", " "], ["kw", "done"]], [["p", " "], ["bi", "echo"], ["p", " "], ["op", "-e"], ["p", " "], ["str", "\"all done"], ["esc", "\\n"], ["str", "\""]], [["punc", "}"]], [], [["fnc", "main"], ["p", " "], ["str", "\"$@\""]]]}, CATS=[["bg", "bg (ground)", "Aa Bb 123"], ["p", "fg", "other / whitespace"], ["kw", "keyword", "class def if return"], ["bi", "builtin", "len echo printf"], ["pp", "preprocessor", "#include #define"], ["fnd", "function \u00b7 def", "resolve push"], ["fnc", "function \u00b7 call", "printf rsync get"], ["dec", "decorator", "@dataclass"], ["ty", "type / class", "int str Order Queue"], ["prop", "property / field", "id name items"], ["con", "constant", "None nil NULL true"], ["num", "number", "8080 100 -1"], ["str", "string", "\"dupre\" \"fmt\""], ["esc", "escape", "\\n \\t"], ["re", "regexp", "/^#[0-9a-f]+/"], ["doc", "docstring", "\"\"\"...\"\"\""], ["cm", "comment", "# reject nil"], ["cmd", "comment delim", "# // ;;"], ["var", "variable / use", "value key self"], ["op", "operator", ": = -> =="], ["punc", "punctuation", "{ } ( ) ;"]], UI_FACES=[["cursor", "cursor", "Aa|"], ["region", "region (selection)", "selected text"], ["hl-line", "hl-line (current line)", "current line"], ["highlight", "highlight", "hover"], ["mode-line", "mode-line", "status active"], ["mode-line-inactive", "mode-line-inactive", "status idle"], ["fringe", "fringe", "| |"], ["line-number", "line-number", " 42"], ["line-number-current-line", "line-number-current-line", "> 42"], ["minibuffer-prompt", "minibuffer-prompt", "M-x "], ["isearch", "isearch (match)", "match"], ["lazy-highlight", "lazy-highlight", "other match"], ["isearch-fail", "isearch-fail", "no match"], ["show-paren-match", "show-paren-match", "( )"], ["show-paren-mismatch", "show-paren-mismatch", ") ("], ["link", "link", "https://"], ["error", "error", "error!"], ["warning", "warning", "warning"], ["success", "success", "ok"], ["vertical-border", "vertical-border", "|"]], APPS={"org-mode": {"label": "org-mode", "preview": "org", "faces": [["org-document-title", "document title", {"fg": "gold", "bold": true, "height": 1.5}], ["org-document-info", "document info", {"fg": "steel"}], ["org-document-info-keyword", "document info keyword", {"fg": "pewter", "inherit": "fixed-pitch"}], ["org-level-1", "level 1", {"fg": "blue", "bold": true, "height": 1.3}], ["org-level-2", "level 2", {"fg": "gold", "height": 1.2}], ["org-level-3", "level 3", {"fg": "regal", "height": 1.15}], ["org-level-4", "level 4", {"fg": "emerald", "height": 1.1}], ["org-level-5", "level 5", {"fg": "terracotta"}], ["org-level-6", "level 6", {"fg": "tan"}], ["org-level-7", "level 7", {"fg": "sage"}], ["org-level-8", "level 8", {"fg": "steel"}], ["org-headline-todo", "headline todo", {}], ["org-headline-done", "headline done", {"fg": "pewter"}], ["org-todo", "todo", {"fg": "terracotta", "bold": true}], ["org-done", "done", {"fg": "sage", "bold": true}], ["org-priority", "priority", {"fg": "gold", "bold": true}], ["org-tag", "tag", {"fg": "tan"}], ["org-tag-group", "tag group", {"fg": "tan"}], ["org-special-keyword", "special keyword", {"fg": "pewter"}], ["org-drawer", "drawer", {"fg": "pewter"}], ["org-property-value", "property value", {"fg": "steel"}], ["org-checkbox", "checkbox", {"fg": "gold", "inherit": "fixed-pitch"}], ["org-checkbox-statistics-todo", "checkbox statistics todo", {"fg": "terracotta"}], ["org-checkbox-statistics-done", "checkbox statistics done", {"fg": "sage"}], ["org-warning", "warning", {"fg": "terracotta", "bold": true}], ["org-link", "link", {"fg": "blue"}], ["org-footnote", "footnote", {"fg": "blue"}], ["org-date", "date", {"fg": "steel", "inherit": "fixed-pitch"}], ["org-sexp-date", "sexp date", {"fg": "steel"}], ["org-date-selected", "date selected", {"fg": "ground", "bg": "gold"}], ["org-target", "target", {"fg": "regal"}], ["org-macro", "macro", {"fg": "regal"}], ["org-cite", "cite", {"fg": "blue"}], ["org-cite-key", "cite key", {"fg": "blue"}], ["org-block", "block", {"fg": "white", "bg": "bg-dim", "inherit": "fixed-pitch"}], ["org-block-begin-line", "block begin line", {"fg": "pewter", "bg": "bg-dim", "inherit": "fixed-pitch"}], ["org-block-end-line", "block end line", {"fg": "pewter", "bg": "bg-dim", "inherit": "fixed-pitch"}], ["org-code", "code", {"fg": "terracotta", "inherit": "fixed-pitch"}], ["org-verbatim", "verbatim", {"fg": "steel", "inherit": "fixed-pitch"}], ["org-inline-src-block", "inline src block", {"fg": "terracotta", "inherit": "fixed-pitch"}], ["org-quote", "quote", {"fg": "silver", "italic": true}], ["org-verse", "verse", {"fg": "silver", "italic": true}], ["org-latex-and-related", "latex and related", {"fg": "gold"}], ["org-table", "table", {"fg": "steel", "inherit": "fixed-pitch"}], ["org-table-header", "table header", {"fg": "white", "bold": true, "bg": "gunmetal"}], ["org-table-row", "table row", {}], ["org-formula", "formula", {"fg": "terracotta"}], ["org-column", "column", {"bg": "gunmetal"}], ["org-column-title", "column title", {"fg": "white", "bold": true, "bg": "gunmetal"}], ["org-list-dt", "list dt", {"fg": "gold", "bold": true}], ["org-meta-line", "meta line", {"fg": "pewter", "inherit": "fixed-pitch"}], ["org-ellipsis", "ellipsis", {"fg": "pewter"}], ["org-hide", "hide", {"fg": "ground"}], ["org-indent", "indent", {"fg": "ground"}], ["org-archived", "archived", {"fg": "pewter"}], ["org-default", "default", {}], ["org-dispatcher-highlight", "dispatcher highlight", {"fg": "gold", "bold": true, "bg": "navy"}], ["org-agenda-structure", "agenda structure", {"fg": "blue", "bold": true, "height": 1.1}], ["org-agenda-structure-secondary", "agenda structure secondary", {"fg": "blue"}], ["org-agenda-structure-filter", "agenda structure filter", {"fg": "terracotta", "bold": true}], ["org-agenda-date", "agenda date", {"fg": "steel", "height": 1.05}], ["org-agenda-date-today", "agenda date today", {"fg": "gold", "bold": true, "height": 1.05}], ["org-agenda-date-weekend", "agenda date weekend", {"fg": "steel", "bold": true}], ["org-agenda-date-weekend-today", "agenda date weekend today", {"fg": "gold", "bold": true}], ["org-agenda-current-time", "agenda current time", {"fg": "gold"}], ["org-agenda-done", "agenda done", {"fg": "sage"}], ["org-agenda-dimmed-todo-face", "agenda dimmed todo", {"fg": "pewter"}], ["org-agenda-calendar-event", "agenda calendar event", {"fg": "white"}], ["org-agenda-calendar-sexp", "agenda calendar sexp", {"fg": "steel"}], ["org-agenda-calendar-daterange", "agenda calendar daterange", {"fg": "steel"}], ["org-agenda-diary", "agenda diary", {"fg": "sage"}], ["org-agenda-clocking", "agenda clocking", {"bg": "navy"}], ["org-agenda-column-dateline", "agenda column dateline", {"bg": "gunmetal"}], ["org-agenda-restriction-lock", "agenda restriction lock", {"bg": "terracotta"}], ["org-agenda-filter-category", "agenda filter category", {"fg": "gold", "bold": true}], ["org-agenda-filter-effort", "agenda filter effort", {"fg": "gold", "bold": true}], ["org-agenda-filter-regexp", "agenda filter regexp", {"fg": "gold", "bold": true}], ["org-agenda-filter-tags", "agenda filter tags", {"fg": "gold", "bold": true}], ["org-scheduled", "scheduled", {"fg": "sage"}], ["org-scheduled-today", "scheduled today", {"fg": "sage", "bold": true}], ["org-scheduled-previously", "scheduled previously", {"fg": "terracotta"}], ["org-upcoming-deadline", "upcoming deadline", {"fg": "gold"}], ["org-upcoming-distant-deadline", "upcoming distant deadline", {"fg": "tan"}], ["org-imminent-deadline", "imminent deadline", {"fg": "terracotta", "bold": true}], ["org-time-grid", "time grid", {"fg": "tan"}], ["org-clock-overlay", "clock overlay", {"bg": "navy"}], ["org-mode-line-clock", "mode line clock", {"fg": "steel"}], ["org-mode-line-clock-overrun", "mode line clock overrun", {"fg": "terracotta", "bold": true}]]}, "magit": {"label": "magit", "preview": "magit", "faces": [["magit-section-heading", "section heading", {"fg": "gold", "bold": true}], ["magit-section-secondary-heading", "section secondary heading", {"fg": "tan", "bold": true}], ["magit-section-heading-selection", "section heading selection", {"fg": "gold", "bg": "navy"}], ["magit-section-highlight", "section highlight", {"bg": "bg-dim"}], ["magit-section-child-count", "section child count", {"fg": "pewter"}], ["magit-diff-added", "diff added", {"fg": "sage"}], ["magit-diff-added-highlight", "diff added highlight", {"fg": "sage", "bg": "bg-dim"}], ["magit-diff-removed", "diff removed", {"fg": "terracotta"}], ["magit-diff-removed-highlight", "diff removed highlight", {"fg": "terracotta", "bg": "bg-dim"}], ["magit-diff-context", "diff context", {"fg": "pewter"}], ["magit-diff-context-highlight", "diff context highlight", {"fg": "silver", "bg": "bg-dim"}], ["magit-diff-file-heading", "diff file heading", {"fg": "white", "bold": true}], ["magit-diff-file-heading-highlight", "diff file heading highlight", {"fg": "white", "bold": true, "bg": "bg-dim"}], ["magit-diff-file-heading-selection", "diff file heading selection", {}], ["magit-diff-hunk-heading", "diff hunk heading", {"fg": "steel", "bg": "gunmetal"}], ["magit-diff-hunk-heading-highlight", "diff hunk heading highlight", {"fg": "white", "bg": "gunmetal"}], ["magit-diff-hunk-heading-selection", "diff hunk heading selection", {}], ["magit-diff-hunk-region", "diff hunk region", {}], ["magit-diff-lines-heading", "diff lines heading", {}], ["magit-diff-lines-boundary", "diff lines boundary", {}], ["magit-diff-base", "diff base", {}], ["magit-diff-base-highlight", "diff base highlight", {}], ["magit-diff-our", "diff our", {}], ["magit-diff-our-highlight", "diff our highlight", {}], ["magit-diff-their", "diff their", {}], ["magit-diff-their-highlight", "diff their highlight", {}], ["magit-diff-conflict-heading", "diff conflict heading", {}], ["magit-diff-conflict-heading-highlight", "diff conflict heading highlight", {}], ["magit-diff-revision-summary", "diff revision summary", {}], ["magit-diff-revision-summary-highlight", "diff revision summary highlight", {}], ["magit-diff-whitespace-warning", "diff whitespace warning", {"bg": "terracotta"}], ["magit-diffstat-added", "diffstat added", {"fg": "sage"}], ["magit-diffstat-removed", "diffstat removed", {"fg": "terracotta"}], ["magit-branch-current", "branch current", {"fg": "blue", "bold": true}], ["magit-branch-local", "branch local", {"fg": "blue"}], ["magit-branch-remote", "branch remote", {"fg": "sage"}], ["magit-branch-remote-head", "branch remote head", {"fg": "sage", "bold": true}], ["magit-branch-upstream", "branch upstream", {}], ["magit-branch-warning", "branch warning", {}], ["magit-head", "head", {"fg": "blue", "bold": true}], ["magit-tag", "tag", {"fg": "gold"}], ["magit-hash", "hash", {"fg": "pewter"}], ["magit-filename", "filename", {"fg": "steel"}], ["magit-dimmed", "dimmed", {"fg": "pewter"}], ["magit-keyword", "keyword", {"fg": "regal"}], ["magit-keyword-squash", "keyword squash", {"fg": "terracotta"}], ["magit-refname", "refname", {"fg": "pewter"}], ["magit-refname-stash", "refname stash", {}], ["magit-refname-wip", "refname wip", {}], ["magit-refname-pullreq", "refname pullreq", {}], ["magit-log-author", "log author", {"fg": "tan"}], ["magit-log-date", "log date", {"fg": "steel"}], ["magit-log-graph", "log graph", {"fg": "pewter"}], ["magit-header-line", "header line", {"fg": "white", "bold": true, "bg": "gunmetal"}], ["magit-header-line-key", "header line key", {}], ["magit-header-line-log-select", "header line log select", {}], ["magit-process-ok", "process ok", {"fg": "sage", "bold": true}], ["magit-process-ng", "process ng", {"fg": "terracotta", "bold": true}], ["magit-mode-line-process", "mode line process", {"fg": "sage"}], ["magit-mode-line-process-error", "mode line process error", {"fg": "terracotta"}], ["magit-bisect-good", "bisect good", {"fg": "sage"}], ["magit-bisect-bad", "bisect bad", {"fg": "terracotta"}], ["magit-bisect-skip", "bisect skip", {"fg": "gold"}], ["magit-blame-heading", "blame heading", {"fg": "steel", "bg": "gunmetal"}], ["magit-blame-highlight", "blame highlight", {}], ["magit-blame-hash", "blame hash", {"fg": "pewter"}], ["magit-blame-name", "blame name", {"fg": "tan"}], ["magit-blame-date", "blame date", {"fg": "steel"}], ["magit-blame-summary", "blame summary", {}], ["magit-blame-dimmed", "blame dimmed", {}], ["magit-blame-margin", "blame margin", {}], ["magit-cherry-equivalent", "cherry equivalent", {"fg": "regal"}], ["magit-cherry-unmatched", "cherry unmatched", {"fg": "sage"}], ["magit-signature-good", "signature good", {"fg": "sage"}], ["magit-signature-bad", "signature bad", {"fg": "terracotta", "bold": true}], ["magit-signature-untrusted", "signature untrusted", {"fg": "gold"}], ["magit-signature-expired", "signature expired", {"fg": "tan"}], ["magit-signature-expired-key", "signature expired key", {}], ["magit-signature-revoked", "signature revoked", {}], ["magit-signature-error", "signature error", {}], ["magit-reflog-commit", "reflog commit", {"fg": "sage"}], ["magit-reflog-amend", "reflog amend", {"fg": "regal"}], ["magit-reflog-merge", "reflog merge", {"fg": "sage"}], ["magit-reflog-checkout", "reflog checkout", {"fg": "blue"}], ["magit-reflog-reset", "reflog reset", {"fg": "terracotta"}], ["magit-reflog-rebase", "reflog rebase", {"fg": "regal"}], ["magit-reflog-cherry-pick", "reflog cherry pick", {"fg": "sage"}], ["magit-reflog-remote", "reflog remote", {"fg": "steel"}], ["magit-reflog-other", "reflog other", {"fg": "steel"}], ["magit-sequence-pick", "sequence pick", {"fg": "white"}], ["magit-sequence-stop", "sequence stop", {"fg": "terracotta"}], ["magit-sequence-part", "sequence part", {}], ["magit-sequence-head", "sequence head", {"fg": "blue"}], ["magit-sequence-drop", "sequence drop", {}], ["magit-sequence-done", "sequence done", {"fg": "pewter"}], ["magit-sequence-onto", "sequence onto", {}], ["magit-sequence-exec", "sequence exec", {}], ["magit-left-margin", "left margin", {}]]}, "elfeed": {"label": "elfeed", "preview": "elfeed", "faces": [["elfeed-search-date-face", "search date", {"fg": "steel"}], ["elfeed-search-title-face", "search title", {"fg": "silver"}], ["elfeed-search-unread-title-face", "search unread title", {"fg": "white", "bold": true}], ["elfeed-search-feed-face", "search feed", {"fg": "sage"}], ["elfeed-search-tag-face", "search tag", {"fg": "tan"}], ["elfeed-search-unread-count-face", "search unread count", {"fg": "gold"}], ["elfeed-search-filter-face", "search filter", {"fg": "blue", "bold": true}], ["elfeed-search-last-update-face", "search last update", {"fg": "pewter"}], ["elfeed-log-date-face", "log date", {"fg": "steel"}], ["elfeed-log-error-level-face", "log error level", {"fg": "terracotta", "bold": true}], ["elfeed-log-warn-level-face", "log warn level", {"fg": "gold"}], ["elfeed-log-info-level-face", "log info level", {"fg": "sage"}], ["elfeed-log-debug-level-face", "log debug level", {"fg": "pewter"}]]}, "mu4e": {"label": "mu4e", "preview": "mu4e", "faces": [["mu4e-title-face", "title", {"fg": "blue", "bold": true}], ["mu4e-context-face", "context", {"fg": "blue", "bold": true}], ["mu4e-modeline-face", "modeline", {"fg": "silver"}], ["mu4e-ok-face", "ok", {"fg": "sage", "bold": true}], ["mu4e-warning-face", "warning", {"fg": "gold", "bold": true}], ["mu4e-header-title-face", "header title", {"fg": "blue", "bold": true}], ["mu4e-header-key-face", "header key", {"fg": "blue", "bold": true}], ["mu4e-header-value-face", "header value", {"fg": "silver"}], ["mu4e-header-face", "header", {"fg": "#cdced1"}], ["mu4e-header-highlight-face", "header highlight", {"bg": "gunmetal"}], ["mu4e-header-marks-face", "header marks", {"fg": "gold"}], ["mu4e-unread-face", "unread", {"fg": "white", "bold": true}], ["mu4e-flagged-face", "flagged", {"fg": "gold"}], ["mu4e-replied-face", "replied", {"fg": "silver"}], ["mu4e-forwarded-face", "forwarded", {"fg": "silver"}], ["mu4e-draft-face", "draft", {"fg": "steel", "italic": true}], ["mu4e-trashed-face", "trashed", {"fg": "pewter", "strike": true}], ["mu4e-moved-face", "moved", {"fg": "steel", "italic": true}], ["mu4e-related-face", "related", {"fg": "steel", "italic": true}], ["mu4e-contact-face", "contact", {"fg": "#cdced1"}], ["mu4e-special-header-value-face", "special header value", {"fg": "silver"}], ["mu4e-attach-number-face", "attach number", {"fg": "blue", "bold": true}], ["mu4e-url-number-face", "url number", {"fg": "blue", "bold": true}], ["mu4e-link-face", "link", {"fg": "blue", "underline": true}], ["mu4e-cited-1-face", "cited 1", {"fg": "silver"}], ["mu4e-cited-2-face", "cited 2", {"fg": "steel"}], ["mu4e-cited-3-face", "cited 3", {"fg": "sage"}], ["mu4e-cited-4-face", "cited 4", {"fg": "pewter"}], ["mu4e-cited-5-face", "cited 5", {"fg": "tan"}], ["mu4e-cited-6-face", "cited 6", {"fg": "terracotta"}], ["mu4e-cited-7-face", "cited 7", {"fg": "regal"}], ["mu4e-footer-face", "footer", {"fg": "pewter"}], ["mu4e-region-code", "region code", {"bg": "bg-dim"}], ["mu4e-system-face", "system", {"fg": "pewter", "italic": true}], ["mu4e-highlight-face", "highlight", {"fg": "gold", "bold": true}], ["mu4e-compose-header-face", "compose header", {"fg": "blue", "bold": true}], ["mu4e-compose-separator-face", "compose separator", {"fg": "pewter"}]]}, "ghostel": {"label": "ghostel", "preview": "ghostel", "faces": [["ghostel-default", "default", {"fg": "#cdced1"}], ["ghostel-fake-cursor", "fake cursor", {"fg": "#000000", "bg": "silver"}], ["ghostel-fake-cursor-box", "fake cursor box", {"fg": "silver"}], ["ghostel-color-black", "color black", {"fg": "pewter"}], ["ghostel-color-red", "color red", {"fg": "terracotta"}], ["ghostel-color-green", "color green", {"fg": "emerald"}], ["ghostel-color-yellow", "color yellow", {"fg": "gold"}], ["ghostel-color-blue", "color blue", {"fg": "blue"}], ["ghostel-color-magenta", "color magenta", {"fg": "regal"}], ["ghostel-color-cyan", "color cyan", {"fg": "sage"}], ["ghostel-color-white", "color white", {"fg": "silver"}], ["ghostel-color-bright-black", "color bright black", {"fg": "steel"}], ["ghostel-color-bright-red", "color bright red", {"fg": "#de4949"}], ["ghostel-color-bright-green", "color bright green", {"fg": "#84b068"}], ["ghostel-color-bright-yellow", "color bright yellow", {"fg": "#eed376"}], ["ghostel-color-bright-blue", "color bright blue", {"fg": "#7a9abe"}], ["ghostel-color-bright-magenta", "color bright magenta", {"fg": "#b07fd0"}], ["ghostel-color-bright-cyan", "color bright cyan", {"fg": "#7fc0a8"}], ["ghostel-color-bright-white", "color bright white", {"fg": "white"}]]}, "dashboard": {"label": "dashboard", "preview": "dashboard", "faces": [["dashboard-banner-logo-title", "banner logo title", {"fg": "gold", "bold": true}], ["dashboard-text-banner", "text banner", {"fg": "steel"}], ["dashboard-heading", "heading", {"fg": "blue", "bold": true}], ["dashboard-items-face", "items", {"fg": "#cdced1"}], ["dashboard-navigator", "navigator", {"fg": "blue"}], ["dashboard-no-items-face", "no items", {"fg": "pewter"}], ["dashboard-footer-face", "footer", {"fg": "tan"}], ["dashboard-footer-icon-face", "footer icon", {"fg": "gold"}]]}, "lsp-mode": {"label": "lsp-mode", "preview": "lsp", "faces": [["lsp-signature-face", "signature", {"fg": "silver"}], ["lsp-signature-highlight-function-argument", "signature highlight function argument", {"fg": "gold", "bold": true}], ["lsp-signature-posframe", "signature posframe", {"bg": "bg-dim"}], ["lsp-face-highlight-read", "face highlight read", {"bg": "navy"}], ["lsp-face-highlight-write", "face highlight write", {"bg": "#3d2f4a"}], ["lsp-face-highlight-textual", "face highlight textual", {"bg": "gunmetal"}], ["lsp-face-rename", "face rename", {"bg": "gunmetal", "bold": true}], ["lsp-rename-placeholder-face", "rename placeholder", {"fg": "gold", "bold": true}], ["lsp-inlay-hint-face", "inlay hint", {"fg": "pewter", "italic": true}], ["lsp-inlay-hint-parameter-face", "inlay hint parameter", {"fg": "steel", "italic": true}], ["lsp-inlay-hint-type-face", "inlay hint type", {"fg": "sage", "italic": true}], ["lsp-details-face", "details", {"fg": "pewter", "italic": true}], ["lsp-installation-buffer-face", "installation buffer", {"fg": "blue"}], ["lsp-installation-finished-buffer-face", "installation finished buffer", {"fg": "sage"}]]}, "git-gutter": {"label": "git-gutter", "preview": "gitgutter", "faces": [["git-gutter:added", "added", {"fg": "emerald"}], ["git-gutter:modified", "modified", {"fg": "gold"}], ["git-gutter:deleted", "deleted", {"fg": "terracotta"}], ["git-gutter:unchanged", "unchanged", {"fg": "pewter"}], ["git-gutter:separator", "separator", {"fg": "steel"}]]}, "flycheck": {"label": "flycheck", "preview": "flycheck", "faces": [["flycheck-error", "error", {"fg": "terracotta"}], ["flycheck-warning", "warning", {"fg": "gold"}], ["flycheck-info", "info", {"fg": "blue"}], ["flycheck-fringe-error", "fringe error", {"fg": "terracotta"}], ["flycheck-fringe-warning", "fringe warning", {"fg": "gold"}], ["flycheck-fringe-info", "fringe info", {"fg": "blue"}], ["flycheck-delimited-error", "delimited error", {"fg": "terracotta"}], ["flycheck-error-delimiter", "error delimiter", {"fg": "terracotta"}], ["flycheck-error-list-error", "error list error", {"fg": "terracotta"}], ["flycheck-error-list-warning", "error list warning", {"fg": "gold"}], ["flycheck-error-list-info", "error list info", {"fg": "blue"}], ["flycheck-error-list-error-message", "error list error message", {"fg": "#cdced1"}], ["flycheck-error-list-checker-name", "error list checker name", {"fg": "steel"}], ["flycheck-error-list-column-number", "error list column number", {"fg": "pewter"}], ["flycheck-error-list-line-number", "error list line number", {"fg": "pewter"}], ["flycheck-error-list-filename", "error list filename", {"fg": "blue"}], ["flycheck-error-list-id", "error list id", {"fg": "steel"}], ["flycheck-error-list-id-with-explainer", "error list id with explainer", {"fg": "steel", "bold": true}], ["flycheck-error-list-highlight", "error list highlight", {"bg": "gunmetal"}], ["flycheck-verify-select-checker", "verify select checker", {"fg": "gold"}]]}, "dired": {"label": "dired", "preview": "dired", "faces": [["dired-header", "header", {"fg": "blue", "bold": true}], ["dired-directory", "directory", {"fg": "blue", "bold": true}], ["dired-symlink", "symlink", {"fg": "sage"}], ["dired-broken-symlink", "broken symlink", {"fg": "#de4949", "bold": true}], ["dired-special", "special", {"fg": "regal"}], ["dired-set-id", "set id", {"fg": "terracotta"}], ["dired-perm-write", "perm write", {"fg": "silver"}], ["dired-mark", "mark", {"fg": "gold"}], ["dired-marked", "marked", {"fg": "gold", "bold": true}], ["dired-flagged", "flagged", {"fg": "terracotta", "bold": true}], ["dired-ignored", "ignored", {"fg": "pewter"}], ["dired-warning", "warning", {"fg": "gold", "bold": true}]]}, "dirvish": {"label": "dirvish", "preview": "dirvish", "faces": [["dirvish-inactive", "inactive", {"fg": "pewter"}], ["dirvish-free-space", "free space", {"fg": "sage"}], ["dirvish-hl-line", "hl line", {"bg": "gunmetal"}], ["dirvish-hl-line-inactive", "hl line inactive", {"bg": "bg-dim"}], ["dirvish-file-modes", "file modes", {"fg": "steel"}], ["dirvish-file-link-number", "file link number", {"fg": "pewter"}], ["dirvish-file-user-id", "file user id", {"fg": "blue"}], ["dirvish-file-group-id", "file group id", {"fg": "steel"}], ["dirvish-file-size", "file size", {"fg": "sage"}], ["dirvish-file-time", "file time", {"fg": "pewter"}], ["dirvish-file-inode-number", "file inode number", {"fg": "pewter"}], ["dirvish-file-device-number", "file device number", {"fg": "pewter"}], ["dirvish-subtree-guide", "subtree guide", {"fg": "pewter"}], ["dirvish-subtree-state", "subtree state", {"fg": "steel"}], ["dirvish-collapse-dir-face", "collapse dir", {"fg": "blue"}], ["dirvish-collapse-empty-dir-face", "collapse empty dir", {"fg": "pewter"}], ["dirvish-collapse-file-face", "collapse file", {"fg": "silver"}], ["dirvish-emerge-group-title", "emerge group title", {"fg": "gold", "bold": true}], ["dirvish-media-info-heading", "media info heading", {"fg": "blue", "bold": true}], ["dirvish-media-info-property-key", "media info property key", {"fg": "steel"}], ["dirvish-narrow-match-face-0", "narrow match 0", {"fg": "gold", "bold": true}], ["dirvish-narrow-match-face-1", "narrow match 1", {"fg": "blue", "bold": true}], ["dirvish-narrow-match-face-2", "narrow match 2", {"fg": "emerald", "bold": true}], ["dirvish-narrow-match-face-3", "narrow match 3", {"fg": "regal", "bold": true}], ["dirvish-narrow-split", "narrow split", {"fg": "pewter"}], ["dirvish-proc-running", "proc running", {"fg": "gold"}], ["dirvish-proc-finished", "proc finished", {"fg": "sage"}], ["dirvish-proc-failed", "proc failed", {"fg": "terracotta"}], ["dirvish-git-commit-message-face", "git commit message", {"fg": "tan", "italic": true}], ["dirvish-vc-added-state", "vc added state", {"fg": "sage"}], ["dirvish-vc-edited-state", "vc edited state", {"fg": "gold"}], ["dirvish-vc-removed-state", "vc removed state", {"fg": "terracotta"}], ["dirvish-vc-conflict-state", "vc conflict state", {"fg": "terracotta", "bold": true}], ["dirvish-vc-locked-state", "vc locked state", {"fg": "blue"}], ["dirvish-vc-missing-state", "vc missing state", {"fg": "terracotta"}], ["dirvish-vc-needs-merge-face", "vc needs merge", {"fg": "gold"}], ["dirvish-vc-needs-update-state", "vc needs update state", {"fg": "gold"}], ["dirvish-vc-unregistered-face", "vc unregistered", {"fg": "pewter"}]]}, "calibredb": {"label": "calibredb", "preview": "calibredb", "faces": [["calibredb-search-header-library-name-face", "search header library name", {"fg": "blue", "bold": true}], ["calibredb-search-header-library-path-face", "search header library path", {"fg": "pewter"}], ["calibredb-search-header-total-face", "search header total", {"fg": "sage"}], ["calibredb-search-header-filter-face", "search header filter", {"fg": "gold"}], ["calibredb-search-header-sort-face", "search header sort", {"fg": "steel"}], ["calibredb-search-header-highlight-face", "search header highlight", {"fg": "gold", "bold": true}], ["calibredb-id-face", "id", {"fg": "pewter"}], ["calibredb-title-face", "title", {"fg": "blue", "bold": true}], ["calibredb-author-face", "author", {"fg": "sage"}], ["calibredb-format-face", "format", {"fg": "steel"}], ["calibredb-size-face", "size", {"fg": "pewter"}], ["calibredb-tag-face", "tag", {"fg": "tan"}], ["calibredb-date-face", "date", {"fg": "pewter"}], ["calibredb-mark-face", "mark", {"fg": "gold", "bold": true}], ["calibredb-series-face", "series", {"fg": "regal"}], ["calibredb-publisher-face", "publisher", {"fg": "steel"}], ["calibredb-pubdate-face", "pubdate", {"fg": "pewter"}], ["calibredb-language-face", "language", {"fg": "steel"}], ["calibredb-comment-face", "comment", {"fg": "silver", "italic": true}], ["calibredb-archive-face", "archive", {"fg": "pewter"}], ["calibredb-favorite-face", "favorite", {"fg": "gold"}], ["calibredb-file-face", "file", {"fg": "blue"}], ["calibredb-ids-face", "ids", {"fg": "pewter"}], ["calibredb-highlight-face", "highlight", {"fg": "gold", "bold": true}], ["calibredb-current-page-button-face", "current page button", {"fg": "blue", "bold": true}], ["calibredb-mouse-face", "mouse", {"bg": "gunmetal"}], ["calibredb-title-detailed-view-face", "title detailed view", {"fg": "gold", "bold": true}], ["calibredb-edit-annotation-header-title-face", "edit annotation header title", {"fg": "blue", "bold": true}]]}, "erc": {"label": "erc", "preview": "erc", "faces": [["erc-header-line", "header line", {"fg": "white", "bg": "gunmetal", "bold": true}], ["erc-timestamp-face", "timestamp", {"fg": "pewter"}], ["erc-notice-face", "notice", {"fg": "steel"}], ["erc-default-face", "default", {"fg": "#cdced1"}], ["erc-current-nick-face", "current nick", {"fg": "gold", "bold": true}], ["erc-my-nick-face", "my nick", {"fg": "gold", "bold": true}], ["erc-my-nick-prefix-face", "my nick prefix", {"fg": "gold"}], ["erc-nick-default-face", "nick default", {"fg": "blue"}], ["erc-nick-prefix-face", "nick prefix", {"fg": "sage"}], ["erc-button-nick-default-face", "button nick default", {"fg": "blue"}], ["erc-nick-msg-face", "nick msg", {"fg": "regal"}], ["erc-direct-msg-face", "direct msg", {"fg": "regal"}], ["erc-action-face", "action", {"fg": "sage", "italic": true}], ["erc-keyword-face", "keyword", {"fg": "gold", "bold": true}], ["erc-pal-face", "pal", {"fg": "emerald"}], ["erc-fool-face", "fool", {"fg": "pewter"}], ["erc-dangerous-host-face", "dangerous host", {"fg": "terracotta", "bold": true}], ["erc-error-face", "error", {"fg": "terracotta", "bold": true}], ["erc-input-face", "input", {"fg": "silver"}], ["erc-prompt-face", "prompt", {"fg": "blue", "bold": true}], ["erc-command-indicator-face", "command indicator", {"fg": "steel", "bold": true}], ["erc-information", "information", {"fg": "steel"}], ["erc-button", "button", {"fg": "blue"}], ["erc-bold-face", "bold", {"bold": true}], ["erc-italic-face", "italic", {"italic": true}], ["erc-underline-face", "underline", {"fg": "silver", "underline": true}], ["erc-inverse-face", "inverse", {"fg": "#000000", "bg": "silver"}], ["erc-spoiler-face", "spoiler", {"fg": "#000000", "bg": "gunmetal"}], ["erc-fill-wrap-merge-indicator-face", "fill wrap merge indicator", {"fg": "pewter"}], ["erc-keep-place-indicator-arrow", "keep place indicator arrow", {"fg": "gold"}], ["erc-keep-place-indicator-line", "keep place indicator line", {"bg": "bg-dim"}]]}, "org-drill": {"label": "org-drill", "preview": "orgdrill", "faces": [["org-drill-hidden-cloze-face", "hidden cloze", {"fg": "#000000", "bg": "steel"}], ["org-drill-visible-cloze-face", "visible cloze", {"fg": "gold", "bold": true}], ["org-drill-visible-cloze-hint-face", "visible cloze hint", {"fg": "pewter", "italic": true}]]}, "org-noter": {"label": "org-noter", "preview": "orgnoter", "faces": [["org-noter-notes-exist-face", "notes exist", {"fg": "sage"}], ["org-noter-no-notes-exist-face", "no notes exist", {"fg": "pewter"}]]}, "signel": {"label": "signel", "preview": "signel", "faces": [["signel-timestamp-face", "timestamp", {"fg": "pewter"}], ["signel-my-msg-face", "my msg", {"fg": "blue"}], ["signel-other-msg-face", "other msg", {"fg": "silver"}], ["signel-error-face", "error", {"fg": "terracotta", "bold": true}]]}, "pearl": {"label": "pearl", "preview": "pearl", "faces": [["pearl-preamble-summary", "preamble summary", {"fg": "blue", "bold": true}], ["pearl-editable-comment", "editable comment", {"fg": "silver"}], ["pearl-readonly-comment", "readonly comment", {"fg": "pewter", "italic": true}], ["pearl-modified-highlight", "modified highlight", {"bg": "navy"}], ["pearl-modified-local", "modified local", {"fg": "gold"}], ["pearl-modified-unknown", "modified unknown", {"fg": "pewter"}]]}, "slack": {"label": "slack", "preview": "slack", "faces": [["slack-room-info-title-face", "room info title", {"fg": "blue", "bold": true}], ["slack-room-info-title-room-name-face", "room info title room name", {"fg": "gold", "bold": true}], ["slack-room-info-section-title-face", "room info section title", {"fg": "blue", "bold": true}], ["slack-room-info-section-label-face", "room info section label", {"fg": "steel"}], ["slack-room-unread-face", "room unread", {"fg": "white", "bold": true}], ["slack-message-output-header", "message output header", {"fg": "blue", "bold": true}], ["slack-message-output-text", "message output text", {"fg": "#cdced1"}], ["slack-message-output-reaction", "message output reaction", {"fg": "steel"}], ["slack-message-output-reaction-pressed", "message output reaction pressed", {"fg": "gold", "bold": true}], ["slack-message-deleted-face", "message deleted", {"fg": "pewter", "italic": true}], ["slack-new-message-marker-face", "new message marker", {"fg": "terracotta", "bold": true}], ["slack-all-thread-buffer-thread-header-face", "all thread buffer thread header", {"fg": "blue", "bold": true}], ["slack-message-mention-face", "message mention", {"fg": "blue"}], ["slack-message-mention-me-face", "message mention me", {"fg": "gold", "bg": "navy", "bold": true}], ["slack-message-mention-keyword-face", "message mention keyword", {"fg": "gold", "bold": true}], ["slack-channel-button-face", "channel button", {"fg": "blue"}], ["slack-mrkdwn-bold-face", "mrkdwn bold", {"bold": true}], ["slack-mrkdwn-italic-face", "mrkdwn italic", {"italic": true}], ["slack-mrkdwn-code-face", "mrkdwn code", {"fg": "terracotta"}], ["slack-mrkdwn-code-block-face", "mrkdwn code block", {"fg": "terracotta", "bg": "bg-dim"}], ["slack-mrkdwn-strike-face", "mrkdwn strike", {"fg": "pewter", "strike": true}], ["slack-mrkdwn-blockquote-face", "mrkdwn blockquote", {"fg": "silver", "italic": true}], ["slack-mrkdwn-list-face", "mrkdwn list", {"fg": "silver"}], ["slack-attachment-header", "attachment header", {"fg": "blue", "bold": true}], ["slack-attachment-footer", "attachment footer", {"fg": "pewter"}], ["slack-attachment-pad", "attachment pad", {"fg": "pewter"}], ["slack-attachment-field-title", "attachment field title", {"fg": "steel", "bold": true}], ["slack-message-attachment-preview-header-face", "message attachment preview header", {"fg": "blue"}], ["slack-preview-face", "preview", {"fg": "silver"}], ["slack-block-highlight-source-overlay-face", "block highlight source overlay", {"bg": "bg-dim"}], ["slack-message-action-face", "message action", {"fg": "blue"}], ["slack-message-action-primary-face", "message action primary", {"fg": "sage"}], ["slack-message-action-danger-face", "message action danger", {"fg": "terracotta"}], ["slack-button-block-element-face", "button block element", {"fg": "silver"}], ["slack-button-primary-block-element-face", "button primary block element", {"fg": "sage", "bold": true}], ["slack-button-danger-block-element-face", "button danger block element", {"fg": "terracotta", "bold": true}], ["slack-select-block-element-face", "select block element", {"fg": "blue"}], ["slack-overflow-block-element-face", "overflow block element", {"fg": "steel"}], ["slack-date-picker-block-element-face", "date picker block element", {"fg": "blue"}], ["slack-dialog-title-face", "dialog title", {"fg": "blue", "bold": true}], ["slack-dialog-element-label-face", "dialog element label", {"fg": "steel"}], ["slack-dialog-element-hint-face", "dialog element hint", {"fg": "pewter", "italic": true}], ["slack-dialog-element-placeholder-face", "dialog element placeholder", {"fg": "pewter"}], ["slack-dialog-element-error-face", "dialog element error", {"fg": "terracotta"}], ["slack-dialog-submit-button-face", "dialog submit button", {"fg": "sage", "bold": true}], ["slack-dialog-cancel-button-face", "dialog cancel button", {"fg": "silver"}], ["slack-dialog-select-element-input-face", "dialog select element input", {"fg": "silver"}], ["slack-user-active-face", "user active", {"fg": "sage"}], ["slack-user-dnd-face", "user dnd", {"fg": "terracotta"}], ["slack-user-profile-header-face", "user profile header", {"fg": "blue", "bold": true}], ["slack-user-profile-property-name-face", "user profile property name", {"fg": "steel"}], ["slack-profile-image-face", "profile image", {"fg": "pewter"}], ["slack-search-result-message-header-face", "search result message header", {"fg": "blue"}], ["slack-search-result-message-username-face", "search result message username", {"fg": "gold", "bold": true}], ["slack-modeline-has-unreads-face", "modeline has unreads", {"fg": "gold"}], ["slack-modeline-channel-has-unreads-face", "modeline channel has unreads", {"fg": "gold", "bold": true}], ["slack-modeline-thread-has-unreads-face", "modeline thread has unreads", {"fg": "gold"}]]}, "telega": {"label": "telega", "preview": "telega", "faces": [["telega-root-heading", "root heading", {"fg": "blue", "bold": true}], ["telega-tracking", "tracking", {"fg": "gold"}], ["telega-unread-unmuted-modeline", "unread unmuted modeline", {"fg": "gold", "bold": true}], ["telega-username", "username", {"fg": "blue"}], ["telega-user-online-status", "user online status", {"fg": "sage"}], ["telega-user-non-online-status", "user non online status", {"fg": "pewter"}], ["telega-secret-title", "secret title", {"fg": "sage"}], ["telega-contact-birthdays-today", "contact birthdays today", {"fg": "gold"}], ["telega-muted-count", "muted count", {"fg": "pewter"}], ["telega-unmuted-count", "unmuted count", {"fg": "gold", "bold": true}], ["telega-mention-count", "mention count", {"fg": "gold", "bold": true}], ["telega-has-chatbuf-brackets", "has chatbuf brackets", {"fg": "steel"}], ["telega-delim-face", "delim", {"fg": "pewter"}], ["telega-shadow", "shadow", {"fg": "pewter"}], ["telega-link", "link", {"fg": "blue"}], ["telega-blue", "blue", {"fg": "blue"}], ["telega-red", "red", {"fg": "terracotta"}], ["telega-msg-heading", "msg heading", {"fg": "steel"}], ["telega-msg-user-title", "msg user title", {"fg": "blue", "bold": true}], ["telega-msg-self-title", "msg self title", {"fg": "gold", "bold": true}], ["telega-msg-deleted", "msg deleted", {"fg": "pewter", "italic": true}], ["telega-msg-sponsored", "msg sponsored", {"fg": "pewter", "italic": true}], ["telega-msg-inline-reply", "msg inline reply", {"fg": "steel"}], ["telega-msg-inline-forward", "msg inline forward", {"fg": "sage"}], ["telega-msg-inline-other", "msg inline other", {"fg": "pewter"}], ["telega-entity-type-bold", "entity type bold", {"bold": true}], ["telega-entity-type-italic", "entity type italic", {"italic": true}], ["telega-entity-type-underline", "entity type underline", {"fg": "silver", "underline": true}], ["telega-entity-type-strikethrough", "entity type strikethrough", {"fg": "pewter", "strike": true}], ["telega-entity-type-code", "entity type code", {"fg": "terracotta"}], ["telega-entity-type-pre", "entity type pre", {"fg": "terracotta", "bg": "bg-dim"}], ["telega-entity-type-blockquote", "entity type blockquote", {"fg": "silver", "italic": true}], ["telega-entity-type-mention", "entity type mention", {"fg": "blue"}], ["telega-entity-type-hashtag", "entity type hashtag", {"fg": "blue"}], ["telega-entity-type-cashtag", "entity type cashtag", {"fg": "sage"}], ["telega-entity-type-botcommand", "entity type botcommand", {"fg": "sage"}], ["telega-entity-type-texturl", "entity type texturl", {"fg": "blue"}], ["telega-entity-type-spoiler", "entity type spoiler", {"fg": "gunmetal", "bg": "gunmetal"}], ["telega-reaction", "reaction", {"fg": "steel"}], ["telega-reaction-chosen", "reaction chosen", {"fg": "gold", "bold": true}], ["telega-reaction-paid", "reaction paid", {"fg": "gold"}], ["telega-reaction-paid-chosen", "reaction paid chosen", {"fg": "gold", "bold": true}], ["telega-highlight-text-face", "highlight text", {"fg": "#000000", "bg": "gold"}], ["telega-button-highlight", "button highlight", {"fg": "gold", "bold": true}], ["telega-chat-prompt", "chat prompt", {"fg": "blue", "bold": true}], ["telega-chat-prompt-aux", "chat prompt aux", {"fg": "steel"}], ["telega-chat-input-attachment", "chat input attachment", {"fg": "sage"}], ["telega-topic-button", "topic button", {"fg": "blue"}], ["telega-filter-active", "filter active", {"fg": "gold", "bold": true}], ["telega-filter-button-active", "filter button active", {"fg": "#000000", "bg": "gold"}], ["telega-filter-button-inactive", "filter button inactive", {"fg": "steel"}], ["telega-checklist-stats-done", "checklist stats done", {"fg": "sage"}], ["telega-checklist-stats-todo", "checklist stats todo", {"fg": "steel"}], ["telega-box-button", "box button", {"fg": "blue"}], ["telega-box-button-active", "box button active", {"fg": "#000000", "bg": "blue"}], ["telega-box-button-default-active", "box button default active", {"fg": "#000000", "bg": "silver"}], ["telega-box-button-default-passive", "box button default passive", {"fg": "steel"}], ["telega-box-button-primary-active", "box button primary active", {"fg": "#000000", "bg": "blue"}], ["telega-box-button-primary-passive", "box button primary passive", {"fg": "blue"}], ["telega-box-button-success-active", "box button success active", {"fg": "#000000", "bg": "emerald"}], ["telega-box-button-success-passive", "box button success passive", {"fg": "sage"}], ["telega-box-button-danger-active", "box button danger active", {"fg": "#000000", "bg": "terracotta"}], ["telega-box-button-danger-passive", "box button danger passive", {"fg": "terracotta"}], ["telega-box-button-ui-active", "box button ui active", {"fg": "#000000", "bg": "gold"}], ["telega-box-button-ui-passive", "box button ui passive", {"fg": "gold"}], ["telega-box-button2-active", "box button2 active", {"fg": "#000000", "bg": "blue"}], ["telega-box-button2-passive", "box button2 passive", {"fg": "steel"}], ["telega-box-button2-white-foreground", "box button2 white foreground", {"fg": "white"}], ["telega-describe-item-title", "describe item title", {"fg": "steel", "bold": true}], ["telega-describe-section-title", "describe section title", {"fg": "blue", "bold": true}], ["telega-describe-subsection-title", "describe subsection title", {"fg": "blue"}], ["telega-enckey-00", "enckey 00", {"fg": "pewter"}], ["telega-enckey-01", "enckey 01", {"fg": "sage"}], ["telega-enckey-10", "enckey 10", {"fg": "gold"}], ["telega-enckey-11", "enckey 11", {"fg": "blue"}], ["telega-palette-builtin-blue", "palette builtin blue", {"fg": "blue"}], ["telega-palette-builtin-green", "palette builtin green", {"fg": "emerald"}], ["telega-palette-builtin-orange", "palette builtin orange", {"fg": "terracotta"}], ["telega-palette-builtin-purple", "palette builtin purple", {"fg": "regal"}], ["telega-webpage-title", "webpage title", {"fg": "blue", "bold": true}], ["telega-webpage-subtitle", "webpage subtitle", {"fg": "steel"}], ["telega-webpage-header", "webpage header", {"fg": "gold", "bold": true}], ["telega-webpage-subheader", "webpage subheader", {"fg": "gold"}], ["telega-webpage-outline", "webpage outline", {"fg": "pewter"}], ["telega-webpage-fixed", "webpage fixed", {"fg": "terracotta"}], ["telega-webpage-preformatted", "webpage preformatted", {"fg": "terracotta", "bg": "bg-dim"}], ["telega-webpage-marked", "webpage marked", {"fg": "#000000", "bg": "gold"}], ["telega-webpage-strike-through", "webpage strike through", {"fg": "pewter", "strike": true}], ["telega-webpage-chat-link", "webpage chat link", {"fg": "blue"}], ["telega-link-preview-sitename", "link preview sitename", {"fg": "steel"}], ["telega-link-preview-title", "link preview title", {"fg": "blue", "bold": true}]]}, "shr": {"label": "shr (HTML: nov/eww/mail)", "preview": "shr", "faces": [["shr-h1", "h1", {"fg": "gold", "bold": true, "height": 1.4}], ["shr-h2", "h2", {"fg": "blue", "bold": true, "height": 1.2}], ["shr-h3", "h3", {"fg": "blue", "bold": true}], ["shr-h4", "h4", {"fg": "silver", "bold": true}], ["shr-h5", "h5", {"fg": "steel", "bold": true}], ["shr-h6", "h6", {"fg": "pewter", "bold": true}], ["shr-text", "text", {"fg": "#cdced1"}], ["shr-link", "link", {"fg": "blue", "underline": true}], ["shr-selected-link", "selected link", {"fg": "gold", "bold": true, "underline": true}], ["shr-code", "code", {"fg": "terracotta", "bg": "bg-dim"}], ["shr-mark", "mark", {"fg": "#000000", "bg": "gold"}], ["shr-strike-through", "strike through", {"fg": "pewter", "strike": true}], ["shr-sup", "sup", {"fg": "steel"}], ["shr-abbreviation", "abbreviation", {"fg": "steel", "italic": true}], ["shr-sliced-image", "sliced image", {"fg": "pewter"}]]}, "2048-game": {"label": "2048-game", "preview": "generic", "faces": [["twentyfortyeight-face-1024", "twentyfortyeight 1024", {}], ["twentyfortyeight-face-128", "twentyfortyeight 128", {}], ["twentyfortyeight-face-16", "twentyfortyeight 16", {}], ["twentyfortyeight-face-2", "twentyfortyeight 2", {}], ["twentyfortyeight-face-2048", "twentyfortyeight 2048", {}], ["twentyfortyeight-face-256", "twentyfortyeight 256", {}], ["twentyfortyeight-face-32", "twentyfortyeight 32", {}], ["twentyfortyeight-face-4", "twentyfortyeight 4", {}], ["twentyfortyeight-face-512", "twentyfortyeight 512", {}], ["twentyfortyeight-face-64", "twentyfortyeight 64", {}], ["twentyfortyeight-face-8", "twentyfortyeight 8", {}]]}, "alert": {"label": "alert", "preview": "generic", "faces": [["alert-high-face", "high", {}], ["alert-low-face", "low", {}], ["alert-moderate-face", "moderate", {}], ["alert-normal-face", "normal", {}], ["alert-trivial-face", "trivial", {}], ["alert-urgent-face", "urgent", {}]]}, "all-the-icons": {"label": "all-the-icons", "preview": "generic", "faces": [["all-the-icons-blue", "blue", {}], ["all-the-icons-blue-alt", "blue alt", {}], ["all-the-icons-cyan", "cyan", {}], ["all-the-icons-cyan-alt", "cyan alt", {}], ["all-the-icons-dblue", "dblue", {}], ["all-the-icons-dcyan", "dcyan", {}], ["all-the-icons-dgreen", "dgreen", {}], ["all-the-icons-dmaroon", "dmaroon", {}], ["all-the-icons-dorange", "dorange", {}], ["all-the-icons-dpink", "dpink", {}], ["all-the-icons-dpurple", "dpurple", {}], ["all-the-icons-dred", "dred", {}], ["all-the-icons-dsilver", "dsilver", {}], ["all-the-icons-dyellow", "dyellow", {}], ["all-the-icons-green", "green", {}], ["all-the-icons-lblue", "lblue", {}], ["all-the-icons-lcyan", "lcyan", {}], ["all-the-icons-lgreen", "lgreen", {}], ["all-the-icons-lmaroon", "lmaroon", {}], ["all-the-icons-lorange", "lorange", {}], ["all-the-icons-lpink", "lpink", {}], ["all-the-icons-lpurple", "lpurple", {}], ["all-the-icons-lred", "lred", {}], ["all-the-icons-lsilver", "lsilver", {}], ["all-the-icons-lyellow", "lyellow", {}], ["all-the-icons-maroon", "maroon", {}], ["all-the-icons-orange", "orange", {}], ["all-the-icons-pink", "pink", {}], ["all-the-icons-purple", "purple", {}], ["all-the-icons-purple-alt", "purple alt", {}], ["all-the-icons-red", "red", {}], ["all-the-icons-red-alt", "red alt", {}], ["all-the-icons-silver", "silver", {}], ["all-the-icons-yellow", "yellow", {}]]}, "company": {"label": "company", "preview": "generic", "faces": [["company-echo", "echo", {}], ["company-echo-common", "echo common", {}], ["company-preview", "preview", {}], ["company-preview-common", "preview common", {}], ["company-preview-search", "preview search", {}], ["company-tooltip", "tooltip", {}], ["company-tooltip-annotation", "tooltip annotation", {}], ["company-tooltip-annotation-selection", "tooltip annotation selection", {}], ["company-tooltip-common", "tooltip common", {}], ["company-tooltip-common-selection", "tooltip common selection", {}], ["company-tooltip-deprecated", "tooltip deprecated", {}], ["company-tooltip-mouse", "tooltip mouse", {}], ["company-tooltip-quick-access", "tooltip quick access", {}], ["company-tooltip-quick-access-selection", "tooltip quick access selection", {}], ["company-tooltip-scrollbar-thumb", "tooltip scrollbar thumb", {}], ["company-tooltip-scrollbar-track", "tooltip scrollbar track", {}], ["company-tooltip-search", "tooltip search", {}], ["company-tooltip-search-selection", "tooltip search selection", {}], ["company-tooltip-selection", "tooltip selection", {}]]}, "company-box": {"label": "company-box", "preview": "generic", "faces": [["company-box-annotation", "annotation", {}], ["company-box-background", "background", {}], ["company-box-candidate", "candidate", {}], ["company-box-numbers", "numbers", {}], ["company-box-scrollbar", "scrollbar", {}], ["company-box-selection", "selection", {}]]}, "consult": {"label": "consult", "preview": "generic", "faces": [["consult-async-failed", "async failed", {}], ["consult-async-finished", "async finished", {}], ["consult-async-running", "async running", {}], ["consult-async-split", "async split", {}], ["consult-bookmark", "bookmark", {}], ["consult-buffer", "buffer", {}], ["consult-file", "file", {}], ["consult-grep-context", "grep context", {}], ["consult-help", "help", {}], ["consult-highlight-mark", "highlight mark", {}], ["consult-highlight-match", "highlight match", {}], ["consult-key", "key", {}], ["consult-line-number", "line number", {}], ["consult-line-number-prefix", "line number prefix", {}], ["consult-line-number-wrapped", "line number wrapped", {}], ["consult-narrow-indicator", "narrow indicator", {}], ["consult-preview-insertion", "preview insertion", {}], ["consult-preview-line", "preview line", {}], ["consult-preview-match", "preview match", {}], ["consult-separator", "separator", {}]]}, "embark": {"label": "embark", "preview": "generic", "faces": [["embark-collect-annotation", "collect annotation", {}], ["embark-collect-candidate", "collect candidate", {}], ["embark-collect-group-separator", "collect group separator", {}], ["embark-collect-group-title", "collect group title", {}], ["embark-keybinding", "keybinding", {}], ["embark-keybinding-repeat", "keybinding repeat", {}], ["embark-keymap", "keymap", {}], ["embark-selected", "selected", {}], ["embark-target", "target", {}], ["embark-verbose-indicator-documentation", "verbose indicator documentation", {}], ["embark-verbose-indicator-shadowed", "verbose indicator shadowed", {}], ["embark-verbose-indicator-title", "verbose indicator title", {}]]}, "emms": {"label": "emms", "preview": "generic", "faces": [["emms-browser-album-face", "browser album", {}], ["emms-browser-albumartist-face", "browser albumartist", {}], ["emms-browser-artist-face", "browser artist", {}], ["emms-browser-composer-face", "browser composer", {}], ["emms-browser-performer-face", "browser performer", {}], ["emms-browser-track-face", "browser track", {}], ["emms-browser-year/genre-face", "browser year/genre", {}], ["emms-metaplaylist-mode-current-face", "metaplaylist mode current", {}], ["emms-metaplaylist-mode-face", "metaplaylist mode", {}], ["emms-playlist-selected-face", "playlist selected", {}], ["emms-playlist-track-face", "playlist track", {}]]}, "flyspell-correct": {"label": "flyspell-correct", "preview": "generic", "faces": [["flyspell-correct-highlight-face", "highlight", {}]]}, "highlight-indent-guides": {"label": "highlight-indent-guides", "preview": "generic", "faces": [["highlight-indent-guides-character-face", "character", {}], ["highlight-indent-guides-even-face", "even", {}], ["highlight-indent-guides-odd-face", "odd", {}], ["highlight-indent-guides-stack-character-face", "stack character", {}], ["highlight-indent-guides-stack-even-face", "stack even", {}], ["highlight-indent-guides-stack-odd-face", "stack odd", {}], ["highlight-indent-guides-top-character-face", "top character", {}], ["highlight-indent-guides-top-even-face", "top even", {}], ["highlight-indent-guides-top-odd-face", "top odd", {}]]}, "hl-todo": {"label": "hl-todo", "preview": "generic", "faces": [["hl-todo", "hl todo", {}], ["hl-todo-flymake-type", "flymake type", {}]]}, "json-mode": {"label": "json-mode", "preview": "generic", "faces": [["json-mode-object-name-face", "object name", {}]]}, "llama": {"label": "llama", "preview": "generic", "faces": [["llama-##-macro", "## macro", {}], ["llama-deleted-argument", "deleted argument", {}], ["llama-llama-macro", "llama macro", {}], ["llama-mandatory-argument", "mandatory argument", {}], ["llama-optional-argument", "optional argument", {}]]}, "lv": {"label": "lv", "preview": "generic", "faces": [["lv-separator", "separator", {}]]}, "magit-section": {"label": "magit-section", "preview": "generic", "faces": [["magit-left-margin", "magit left margin", {}], ["magit-section-child-count", "child count", {}], ["magit-section-heading", "heading", {}], ["magit-section-heading-selection", "heading selection", {}], ["magit-section-highlight", "highlight", {}], ["magit-section-secondary-heading", "secondary heading", {}]]}, "malyon": {"label": "malyon", "preview": "generic", "faces": [["malyon-face-bold", "face bold", {}], ["malyon-face-error", "face error", {}], ["malyon-face-italic", "face italic", {}], ["malyon-face-plain", "face plain", {}], ["malyon-face-reverse", "face reverse", {}]]}, "marginalia": {"label": "marginalia", "preview": "generic", "faces": [["marginalia-archive", "archive", {}], ["marginalia-char", "char", {}], ["marginalia-date", "date", {}], ["marginalia-documentation", "documentation", {}], ["marginalia-file-name", "file name", {}], ["marginalia-file-owner", "file owner", {}], ["marginalia-file-priv-dir", "file priv dir", {}], ["marginalia-file-priv-exec", "file priv exec", {}], ["marginalia-file-priv-link", "file priv link", {}], ["marginalia-file-priv-no", "file priv no", {}], ["marginalia-file-priv-other", "file priv other", {}], ["marginalia-file-priv-rare", "file priv rare", {}], ["marginalia-file-priv-read", "file priv read", {}], ["marginalia-file-priv-write", "file priv write", {}], ["marginalia-function", "function", {}], ["marginalia-installed", "installed", {}], ["marginalia-key", "key", {}], ["marginalia-lighter", "lighter", {}], ["marginalia-list", "list", {}], ["marginalia-mode", "mode", {}], ["marginalia-modified", "modified", {}], ["marginalia-null", "null", {}], ["marginalia-number", "number", {}], ["marginalia-off", "off", {}], ["marginalia-on", "on", {}], ["marginalia-size", "size", {}], ["marginalia-string", "string", {}], ["marginalia-symbol", "symbol", {}], ["marginalia-true", "true", {}], ["marginalia-type", "type", {}], ["marginalia-value", "value", {}], ["marginalia-version", "version", {}]]}, "markdown-mode": {"label": "markdown-mode", "preview": "generic", "faces": [["markdown-blockquote-face", "markdown blockquote", {}], ["markdown-bold-face", "markdown bold", {}], ["markdown-code-face", "markdown code", {}], ["markdown-comment-face", "markdown comment", {}], ["markdown-footnote-marker-face", "markdown footnote marker", {}], ["markdown-footnote-text-face", "markdown footnote text", {}], ["markdown-gfm-checkbox-face", "markdown gfm checkbox", {}], ["markdown-header-delimiter-face", "markdown header delimiter", {}], ["markdown-header-face", "markdown header", {}], ["markdown-header-face-1", "markdown header 1", {}], ["markdown-header-face-2", "markdown header 2", {}], ["markdown-header-face-3", "markdown header 3", {}], ["markdown-header-face-4", "markdown header 4", {}], ["markdown-header-face-5", "markdown header 5", {}], ["markdown-header-face-6", "markdown header 6", {}], ["markdown-header-rule-face", "markdown header rule", {}], ["markdown-highlight-face", "markdown highlight", {}], ["markdown-highlighting-face", "markdown highlighting", {}], ["markdown-hr-face", "markdown hr", {}], ["markdown-html-attr-name-face", "markdown html attr name", {}], ["markdown-html-attr-value-face", "markdown html attr value", {}], ["markdown-html-entity-face", "markdown html entity", {}], ["markdown-html-tag-delimiter-face", "markdown html tag delimiter", {}], ["markdown-html-tag-name-face", "markdown html tag name", {}], ["markdown-inline-code-face", "markdown inline code", {}], ["markdown-italic-face", "markdown italic", {}], ["markdown-language-info-face", "markdown language info", {}], ["markdown-language-keyword-face", "markdown language keyword", {}], ["markdown-line-break-face", "markdown line break", {}], ["markdown-link-face", "markdown link", {}], ["markdown-link-title-face", "markdown link title", {}], ["markdown-list-face", "markdown list", {}], ["markdown-markup-face", "markdown markup", {}], ["markdown-math-face", "markdown math", {}], ["markdown-metadata-key-face", "markdown metadata key", {}], ["markdown-metadata-value-face", "markdown metadata value", {}], ["markdown-missing-link-face", "markdown missing link", {}], ["markdown-plain-url-face", "markdown plain url", {}], ["markdown-pre-face", "markdown pre", {}], ["markdown-reference-face", "markdown reference", {}], ["markdown-strike-through-face", "markdown strike through", {}], ["markdown-table-face", "markdown table", {}], ["markdown-url-face", "markdown url", {}]]}, "nerd-icons": {"label": "nerd-icons", "preview": "generic", "faces": [["nerd-icons-blue", "blue", {}], ["nerd-icons-blue-alt", "blue alt", {}], ["nerd-icons-cyan", "cyan", {}], ["nerd-icons-cyan-alt", "cyan alt", {}], ["nerd-icons-dblue", "dblue", {}], ["nerd-icons-dcyan", "dcyan", {}], ["nerd-icons-dgreen", "dgreen", {}], ["nerd-icons-dmaroon", "dmaroon", {}], ["nerd-icons-dorange", "dorange", {}], ["nerd-icons-dpink", "dpink", {}], ["nerd-icons-dpurple", "dpurple", {}], ["nerd-icons-dred", "dred", {}], ["nerd-icons-dsilver", "dsilver", {}], ["nerd-icons-dyellow", "dyellow", {}], ["nerd-icons-green", "green", {}], ["nerd-icons-lblue", "lblue", {}], ["nerd-icons-lcyan", "lcyan", {}], ["nerd-icons-lgreen", "lgreen", {}], ["nerd-icons-lmaroon", "lmaroon", {}], ["nerd-icons-lorange", "lorange", {}], ["nerd-icons-lpink", "lpink", {}], ["nerd-icons-lpurple", "lpurple", {}], ["nerd-icons-lred", "lred", {}], ["nerd-icons-lsilver", "lsilver", {}], ["nerd-icons-lyellow", "lyellow", {}], ["nerd-icons-maroon", "maroon", {}], ["nerd-icons-orange", "orange", {}], ["nerd-icons-pink", "pink", {}], ["nerd-icons-purple", "purple", {}], ["nerd-icons-purple-alt", "purple alt", {}], ["nerd-icons-red", "red", {}], ["nerd-icons-red-alt", "red alt", {}], ["nerd-icons-silver", "silver", {}], ["nerd-icons-yellow", "yellow", {}]]}, "nerd-icons-completion": {"label": "nerd-icons-completion", "preview": "generic", "faces": [["nerd-icons-completion-dir-face", "dir", {}]]}, "orderless": {"label": "orderless", "preview": "generic", "faces": [["orderless-match-face-0", "match 0", {}], ["orderless-match-face-1", "match 1", {}], ["orderless-match-face-2", "match 2", {}], ["orderless-match-face-3", "match 3", {}]]}, "org-roam": {"label": "org-roam", "preview": "generic", "faces": [["org-roam-dailies-calendar-note", "dailies calendar note", {}], ["org-roam-dim", "dim", {}], ["org-roam-header-line", "header line", {}], ["org-roam-olp", "olp", {}], ["org-roam-preview-heading", "preview heading", {}], ["org-roam-preview-heading-highlight", "preview heading highlight", {}], ["org-roam-preview-heading-selection", "preview heading selection", {}], ["org-roam-preview-region", "preview region", {}], ["org-roam-title", "title", {}]]}, "org-superstar": {"label": "org-superstar", "preview": "generic", "faces": [["org-superstar-first", "first", {}], ["org-superstar-header-bullet", "header bullet", {}], ["org-superstar-item", "item", {}], ["org-superstar-leading", "leading", {}]]}, "prescient": {"label": "prescient", "preview": "generic", "faces": [["prescient-primary-highlight", "primary highlight", {}], ["prescient-secondary-highlight", "secondary highlight", {}]]}, "rainbow-delimiters": {"label": "rainbow-delimiters", "preview": "generic", "faces": [["rainbow-delimiters-base-error-face", "base error", {}], ["rainbow-delimiters-base-face", "base", {}], ["rainbow-delimiters-depth-1-face", "depth 1", {}], ["rainbow-delimiters-depth-2-face", "depth 2", {}], ["rainbow-delimiters-depth-3-face", "depth 3", {}], ["rainbow-delimiters-depth-4-face", "depth 4", {}], ["rainbow-delimiters-depth-5-face", "depth 5", {}], ["rainbow-delimiters-depth-6-face", "depth 6", {}], ["rainbow-delimiters-depth-7-face", "depth 7", {}], ["rainbow-delimiters-depth-8-face", "depth 8", {}], ["rainbow-delimiters-depth-9-face", "depth 9", {}], ["rainbow-delimiters-mismatched-face", "mismatched", {}], ["rainbow-delimiters-unmatched-face", "unmatched", {}]]}, "symbol-overlay": {"label": "symbol-overlay", "preview": "generic", "faces": [["symbol-overlay-default-face", "default", {}], ["symbol-overlay-face-1", "face 1", {}], ["symbol-overlay-face-2", "face 2", {}], ["symbol-overlay-face-3", "face 3", {}], ["symbol-overlay-face-4", "face 4", {}], ["symbol-overlay-face-5", "face 5", {}], ["symbol-overlay-face-6", "face 6", {}], ["symbol-overlay-face-7", "face 7", {}], ["symbol-overlay-face-8", "face 8", {}]]}, "tmr": {"label": "tmr", "preview": "generic", "faces": [["tmr-description", "description", {}], ["tmr-duration", "duration", {}], ["tmr-end-time", "end time", {}], ["tmr-finished", "finished", {}], ["tmr-is-acknowledged", "is acknowledged", {}], ["tmr-must-be-acknowledged", "must be acknowledged", {}], ["tmr-start-time", "start time", {}], ["tmr-tabulated-acknowledgement", "tabulated acknowledgement", {}], ["tmr-tabulated-description", "tabulated description", {}], ["tmr-tabulated-end-time", "tabulated end time", {}], ["tmr-tabulated-remaining-time", "tabulated remaining time", {}], ["tmr-tabulated-start-time", "tabulated start time", {}]]}, "transient": {"label": "transient", "preview": "generic", "faces": [["transient-active-infix", "active infix", {}], ["transient-argument", "argument", {}], ["transient-delimiter", "delimiter", {}], ["transient-disabled-suffix", "disabled suffix", {}], ["transient-enabled-suffix", "enabled suffix", {}], ["transient-heading", "heading", {}], ["transient-higher-level", "higher level", {}], ["transient-inactive-argument", "inactive argument", {}], ["transient-inactive-value", "inactive value", {}], ["transient-inapt-argument", "inapt argument", {}], ["transient-inapt-suffix", "inapt suffix", {}], ["transient-key", "key", {}], ["transient-key-exit", "key exit", {}], ["transient-key-noop", "key noop", {}], ["transient-key-recurse", "key recurse", {}], ["transient-key-return", "key return", {}], ["transient-key-stack", "key stack", {}], ["transient-key-stay", "key stay", {}], ["transient-mismatched-key", "mismatched key", {}], ["transient-nonstandard-key", "nonstandard key", {}], ["transient-unreachable", "unreachable", {}], ["transient-unreachable-key", "unreachable key", {}], ["transient-value", "value", {}]]}, "vertico": {"label": "vertico", "preview": "generic", "faces": [["vertico-current", "current", {}], ["vertico-group-separator", "group separator", {}], ["vertico-group-title", "group title", {}], ["vertico-multiline", "multiline", {}]]}, "web-mode": {"label": "web-mode", "preview": "generic", "faces": [["web-mode-annotation-face", "annotation", {}], ["web-mode-annotation-html-face", "annotation html", {}], ["web-mode-annotation-tag-face", "annotation tag", {}], ["web-mode-annotation-type-face", "annotation type", {}], ["web-mode-annotation-value-face", "annotation value", {}], ["web-mode-block-attr-name-face", "block attr name", {}], ["web-mode-block-attr-value-face", "block attr value", {}], ["web-mode-block-comment-face", "block comment", {}], ["web-mode-block-control-face", "block control", {}], ["web-mode-block-delimiter-face", "block delimiter", {}], ["web-mode-block-face", "block", {}], ["web-mode-block-string-face", "block string", {}], ["web-mode-bold-face", "bold", {}], ["web-mode-builtin-face", "builtin", {}], ["web-mode-comment-face", "comment", {}], ["web-mode-comment-keyword-face", "comment keyword", {}], ["web-mode-constant-face", "constant", {}], ["web-mode-css-at-rule-face", "css at rule", {}], ["web-mode-css-color-face", "css color", {}], ["web-mode-css-comment-face", "css comment", {}], ["web-mode-css-function-face", "css function", {}], ["web-mode-css-priority-face", "css priority", {}], ["web-mode-css-property-name-face", "css property name", {}], ["web-mode-css-pseudo-class-face", "css pseudo class", {}], ["web-mode-css-selector-class-face", "css selector class", {}], ["web-mode-css-selector-face", "css selector", {}], ["web-mode-css-selector-tag-face", "css selector tag", {}], ["web-mode-css-string-face", "css string", {}], ["web-mode-css-variable-face", "css variable", {}], ["web-mode-current-column-highlight-face", "current column highlight", {}], ["web-mode-current-element-highlight-face", "current element highlight", {}], ["web-mode-doctype-face", "doctype", {}], ["web-mode-error-face", "error", {}], ["web-mode-filter-face", "filter", {}], ["web-mode-folded-face", "folded", {}], ["web-mode-function-call-face", "function call", {}], ["web-mode-function-name-face", "function name", {}], ["web-mode-html-attr-custom-face", "html attr custom", {}], ["web-mode-html-attr-engine-face", "html attr engine", {}], ["web-mode-html-attr-equal-face", "html attr equal", {}], ["web-mode-html-attr-name-face", "html attr name", {}], ["web-mode-html-attr-value-face", "html attr value", {}], ["web-mode-html-entity-face", "html entity", {}], ["web-mode-html-tag-bracket-face", "html tag bracket", {}], ["web-mode-html-tag-custom-face", "html tag custom", {}], ["web-mode-html-tag-face", "html tag", {}], ["web-mode-html-tag-namespaced-face", "html tag namespaced", {}], ["web-mode-html-tag-unclosed-face", "html tag unclosed", {}], ["web-mode-inlay-face", "inlay", {}], ["web-mode-interpolate-color1-face", "interpolate color1", {}], ["web-mode-interpolate-color2-face", "interpolate color2", {}], ["web-mode-interpolate-color3-face", "interpolate color3", {}], ["web-mode-interpolate-color4-face", "interpolate color4", {}], ["web-mode-italic-face", "italic", {}], ["web-mode-javascript-comment-face", "javascript comment", {}], ["web-mode-javascript-string-face", "javascript string", {}], ["web-mode-json-comment-face", "json comment", {}], ["web-mode-json-context-face", "json context", {}], ["web-mode-json-key-face", "json key", {}], ["web-mode-json-string-face", "json string", {}], ["web-mode-jsx-depth-1-face", "jsx depth 1", {}], ["web-mode-jsx-depth-2-face", "jsx depth 2", {}], ["web-mode-jsx-depth-3-face", "jsx depth 3", {}], ["web-mode-jsx-depth-4-face", "jsx depth 4", {}], ["web-mode-jsx-depth-5-face", "jsx depth 5", {}], ["web-mode-keyword-face", "keyword", {}], ["web-mode-param-name-face", "param name", {}], ["web-mode-part-comment-face", "part comment", {}], ["web-mode-part-face", "part", {}], ["web-mode-part-string-face", "part string", {}], ["web-mode-preprocessor-face", "preprocessor", {}], ["web-mode-script-face", "script", {}], ["web-mode-sql-keyword-face", "sql keyword", {}], ["web-mode-string-face", "string", {}], ["web-mode-style-face", "style", {}], ["web-mode-symbol-face", "symbol", {}], ["web-mode-type-face", "type", {}], ["web-mode-underline-face", "underline", {}], ["web-mode-variable-name-face", "variable name", {}], ["web-mode-warning-face", "warning", {}], ["web-mode-whitespace-face", "whitespace", {}]]}, "yasnippet": {"label": "yasnippet", "preview": "generic", "faces": [["yas--field-debug-face", "yas field debug", {}], ["yas-field-highlight-face", "yas field highlight", {}]]}};
-let MAP={"kw": "#67809c", "bi": "#67809c", "pp": "#67809c", "fnd": "#a9b2bb", "fnc": "#a9b2bb", "dec": "#e8bd30", "ty": "#9b5fd0", "prop": "#838d97", "con": "#cb6b4d", "num": "#cb6b4d", "esc": "#cb6b4d", "str": "#5d9b86", "re": "#5d9b86", "doc": "#5d9b86", "cm": "#be9e74", "cmd": "#a9b2bb", "var": "#e8bd30", "op": "#a9b2bb", "punc": "#a9b2bb", "p": "#ffffff", "bg": "#000000"}, PALETTE=[["#67809c", "blue"], ["#e8bd30", "gold"], ["#9b5fd0", "regal"], ["#2ba178", "emerald"], ["#5d9b86", "sage"], ["#cb6b4d", "terracotta"], ["#be9e74", "tan"], ["#ffffff", "white"], ["#a9b2bb", "silver"], ["#838d97", "steel"], ["#5e6770", "pewter"], ["#2f343a", "gunmetal"], ["#264364", "navy"], ["#000000", "ground"], ["#1a1714", "bg-dim"]], BOLD={"kw": true, "bi": false, "pp": false, "fnd": true, "fnc": false, "dec": false, "ty": false, "prop": false, "con": false, "num": false, "esc": false, "str": false, "re": false, "doc": false, "cm": false, "cmd": false, "var": false, "op": false, "punc": false, "p": false}, ITALIC={}, UIMAP={"cursor": {"fg": null, "bg": "#a9b2bb"}, "region": {"fg": null, "bg": "#264364"}, "hl-line": {"fg": null, "bg": "#1a1714"}, "highlight": {"fg": null, "bg": "#2f343a"}, "mode-line": {"fg": "#cdced1", "bg": "#2f343a", "box": {"style": "released", "width": 1, "color": null}}, "mode-line-inactive": {"fg": "#838d97", "bg": "#1a1714", "box": {"style": "released", "width": 1, "color": null}}, "fringe": {"fg": null, "bg": "#0d0b0a"}, "line-number": {"fg": "#5e6770", "bg": null}, "line-number-current-line": {"fg": "#e8bd30", "bg": "#1a1714"}, "minibuffer-prompt": {"fg": "#67809c", "bg": null}, "isearch": {"fg": "#0d0b0a", "bg": "#e8bd30"}, "lazy-highlight": {"fg": "#0d0b0a", "bg": "#838d97", "underline": true}, "isearch-fail": {"fg": "#cb6b4d", "bg": null}, "show-paren-match": {"fg": null, "bg": "#264364", "underline": true}, "show-paren-mismatch": {"fg": "#0d0b0a", "bg": "#cb6b4d"}, "link": {"fg": "#67809c", "bg": null, "underline": true}, "error": {"fg": "#cb6b4d", "bg": null, "bold": true}, "warning": {"fg": "#e8bd30", "bg": null, "bold": true}, "success": {"fg": "#5d9b86", "bg": null, "bold": true}, "vertical-border": {"fg": "#2f343a", "bg": null}};
-let LOCKED=new Set([]); // syntax categories whose element↔color is decided (dropdown disabled, skipped by clear-unlocked)
+const SAMPLES={"Elisp": [[["cmd", ";;"], ["cm", " cache.el"]], [["punc", "("], ["kw", "require"], ["p", " "], ["con", "'cl-lib"], ["punc", ")"]], [], [["punc", "("], ["kw", "defvar"], ["p", " "], ["var", "cache--tbl"], ["p", " "], ["punc", "("], ["fnc", "make-hash-table"], ["p", " "], ["con", ":test"], ["p", " "], ["con", "'equal"], ["punc", "))"]], [["p", " "], ["doc", "\"Memo table.\")"]], [], [["punc", "("], ["kw", "defun"], ["p", " "], ["fnd", "cache-get"], ["p", " "], ["punc", "("], ["var", "key"], ["punc", ")"]], [["p", " "], ["doc", "\"Return cached value for KEY.\""]], [["p", " "], ["punc", "("], ["kw", "or"], ["p", " "], ["punc", "("], ["bi", "gethash"], ["p", " "], ["var", "key"], ["p", " "], ["var", "cache--tbl"], ["punc", ")"]], [["p", " "], ["punc", "("], ["kw", "let"], ["p", " "], ["punc", "(("], ["var", "v"], ["p", " "], ["punc", "("], ["fnc", "compute"], ["p", " "], ["var", "key"], ["p", " "], ["num", "42"], ["punc", "))) "]], [["p", " "], ["punc", "("], ["fnc", "puthash"], ["p", " "], ["var", "key"], ["p", " "], ["var", "v"], ["p", " "], ["var", "cache--tbl"], ["punc", ") "], ["var", "v"], ["punc", "))))"]], [], [["punc", "("], ["kw", "defun"], ["p", " "], ["fnd", "cache-clear"], ["p", " "], ["punc", "()"]], [["p", " "], ["doc", "\"Empty the memo table.\""]], [["p", " "], ["punc", "("], ["kw", "interactive"], ["punc", ")"]], [["p", " "], ["punc", "("], ["fnc", "clrhash"], ["p", " "], ["var", "cache--tbl"], ["punc", ")"]], [["p", " "], ["punc", "("], ["fnc", "message"], ["p", " "], ["str", "\"cleared"], ["esc", "\\n"], ["str", "\""], ["punc", "))"]], [], [["punc", "("], ["kw", "defun"], ["p", " "], ["fnd", "cache-keys"], ["p", " "], ["punc", "()"]], [["p", " "], ["doc", "\"Return all keys.\""]], [["p", " "], ["punc", "("], ["kw", "let"], ["p", " "], ["punc", "(("], ["var", "acc"], ["p", " "], ["con", "nil"], ["punc", "))"]], [["p", " "], ["punc", "("], ["fnc", "maphash"], ["p", " "], ["punc", "("], ["kw", "lambda"], ["p", " "], ["punc", "("], ["var", "k"], ["p", " "], ["var", "_v"], ["punc", ")"], ["p", " "], ["punc", "("], ["fnc", "push"], ["p", " "], ["var", "k"], ["p", " "], ["var", "acc"], ["punc", "))"]], [["p", " "], ["var", "cache--tbl"], ["punc", ")"], ["p", " "], ["var", "acc"], ["punc", "))"]], [], [["punc", "("], ["kw", "provide"], ["p", " "], ["con", "'cache"], ["punc", ")"]]], "Go": [[["cmd", "//"], ["cm", " queue.go"]], [["kw", "package"], ["p", " "], ["var", "main"]], [], [["kw", "import"], ["p", " "], ["str", "\"fmt\""]], [], [["kw", "const"], ["p", " "], ["con", "MaxItems"], ["p", " "], ["op", "="], ["p", " "], ["num", "100"]], [], [["kw", "type"], ["p", " "], ["ty", "Order"], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"]], [["p", " "], ["prop", "ID"], ["p", " "], ["ty", "int"]], [["p", " "], ["prop", "Name"], ["p", " "], ["ty", "string"]], [["punc", "}"]], [], [["kw", "func"], ["p", " "], ["punc", "("], ["var", "q"], ["p", " "], ["op", "*"], ["ty", "Queue"], ["punc", ")"], ["p", " "], ["fnd", "Push"], ["punc", "("], ["var", "o"], ["p", " "], ["op", "*"], ["ty", "Order"], ["punc", ")"], ["p", " "], ["ty", "error"], ["p", " "], ["punc", "{"]], [["p", " "], ["cmd", "//"], ["cm", " reject nil"]], [["p", " "], ["kw", "if"], ["p", " "], ["var", "o"], ["p", " "], ["op", "=="], ["p", " "], ["con", "nil"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "return"], ["p", " "], ["fnc", "fmt.Errorf"], ["punc", "("], ["str", "\"nil"], ["esc", "\\n"], ["str", "\""], ["punc", ")"]], [["p", " "], ["punc", "}"]], [["p", " "], ["var", "q"], ["op", "."], ["prop", "items"], ["p", " "], ["op", "="], ["p", " "], ["bi", "append"], ["punc", "("], ["var", "q"], ["op", "."], ["prop", "items"], ["punc", ","], ["p", " "], ["var", "o"], ["punc", ")"]], [["p", " "], ["kw", "return"], ["p", " "], ["con", "nil"]], [["punc", "}"]], [], [["kw", "func"], ["p", " "], ["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["fnc", "fmt.Println"], ["punc", "("], ["op", "&"], ["ty", "Queue"], ["punc", "{}"], ["punc", ")"]], [["punc", "}"]]], "Python": [[["cmd", "#"], ["cm", " theme.py"]], [["kw", "from"], ["p", " "], ["var", "dataclasses"], ["p", " "], ["kw", "import"], ["p", " "], ["var", "dataclass"], ["punc", ","], ["p", " "], ["var", "field"]], [], [["con", "DEFAULT_PORT"], ["op", ":"], ["p", " "], ["ty", "int"], ["p", " "], ["op", "="], ["p", " "], ["num", "8080"]], [["con", "HEX"], ["p", " "], ["op", "="], ["p", " "], ["var", "re"], ["op", "."], ["fnc", "compile"], ["punc", "("], ["re", "r\"#[0-9a-f]{6}\""], ["punc", ")"]], [], [["dec", "@dataclass"]], [["kw", "class"], ["p", " "], ["ty", "Theme"], ["op", ":"]], [["p", " "], ["doc", "\"\"\"A color theme.\"\"\""]], [["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["ty", "str"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""]], [["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["ty", "dict"], ["p", " "], ["op", "="], ["p", " "], ["fnc", "field"], ["punc", "("], ["prop", "default_factory"], ["op", "="], ["ty", "dict"], ["punc", ")"]], [], [["p", " "], ["kw", "def"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["var", "self"], ["punc", ","], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["ty", "str"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "str"], ["p", " "], ["op", "|"], ["p", " "], ["con", "None"], ["op", ":"]], [["p", " "], ["cmd", "#"], ["cm", " fallback to none"]], [["p", " "], ["var", "v"], ["p", " "], ["op", "="], ["p", " "], ["var", "self"], ["op", "."], ["prop", "colors"], ["op", "."], ["fnc", "get"], ["punc", "("], ["var", "key"], ["punc", ","], ["p", " "], ["str", "\""], ["esc", "\\t"], ["str", "none\""], ["punc", ")"]], [["p", " "], ["kw", "if"], ["p", " "], ["bi", "len"], ["punc", "("], ["var", "v"], ["punc", ")"], ["p", " "], ["op", "=="], ["p", " "], ["num", "0"], ["op", ":"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "None"]], [["p", " "], ["kw", "return"], ["p", " "], ["var", "v"]], [], [["p", " "], ["dec", "@property"]], [["p", " "], ["kw", "def"], ["p", " "], ["fnd", "size"], ["punc", "("], ["var", "self"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "int"], ["op", ":"]], [["p", " "], ["kw", "return"], ["p", " "], ["bi", "len"], ["punc", "("], ["var", "self"], ["op", "."], ["prop", "colors"], ["punc", ")"]], [], [["var", "theme"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Theme"], ["punc", "("], ["str", "\"dupre\""], ["punc", ")"]], [["fnc", "print"], ["punc", "("], ["var", "theme"], ["op", "."], ["fnc", "resolve"], ["punc", "("], ["str", "\"bg\""], ["punc", "))"]]], "TypeScript": [[["cmd", "//"], ["cm", " orders.ts"]], [["kw", "import"], ["p", " "], ["punc", "{"], ["p", " "], ["ty", "Order"], ["p", " "], ["punc", "}"], ["p", " "], ["kw", "from"], ["p", " "], ["str", "\"./types\""]], [], [["kw", "export"], ["p", " "], ["kw", "interface"], ["p", " "], ["ty", "Queue"], ["p", " "], ["punc", "{"]], [["p", " "], ["prop", "max"], ["op", ":"], ["p", " "], ["ty", "number"], ["punc", ";"]], [["p", " "], ["prop", "items"], ["op", ":"], ["p", " "], ["ty", "Order"], ["punc", "[];"]], [["punc", "}"]], [], [["dec", "@Injectable"], ["punc", "()"]], [["kw", "export"], ["p", " "], ["kw", "class"], ["p", " "], ["ty", "OrderQueue"], ["p", " "], ["kw", "implements"], ["p", " "], ["ty", "Queue"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "private"], ["p", " "], ["prop", "re"], ["p", " "], ["op", "="], ["p", " "], ["re", "/^#[0-9a-f]{6}$/i"], ["punc", ";"]], [], [["p", " "], ["fnd", "push"], ["punc", "("], ["var", "o"], ["op", ":"], ["p", " "], ["ty", "Order"], ["punc", ")"], ["op", ":"], ["p", " "], ["ty", "boolean"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "o"], ["p", " "], ["op", "==="], ["p", " "], ["con", "null"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "false"], ["punc", ";"]], [["p", " "], ["var", "console"], ["op", "."], ["fnc", "log"], ["punc", "("], ["str", "`id "], ["punc", "${"], ["var", "o"], ["op", "."], ["prop", "id"], ["punc", "}"], ["esc", "\\n"], ["str", "`"], ["punc", ");"]], [["p", " "], ["kw", "return"], ["p", " "], ["con", "true"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"]], [], [["kw", "const"], ["p", " "], ["con", "LIMIT"], ["op", ":"], ["p", " "], ["ty", "number"], ["p", " "], ["op", "="], ["p", " "], ["num", "50"], ["punc", ";"]], [["kw", "const"], ["p", " "], ["var", "q"], ["p", " "], ["op", "="], ["p", " "], ["kw", "new"], ["p", " "], ["ty", "OrderQueue"], ["punc", "()"], ["punc", ";"]], [["var", "q"], ["op", "."], ["fnd", "push"], ["punc", "("], ["punc", "{"], ["p", " "], ["prop", "id"], ["op", ":"], ["p", " "], ["num", "1"], ["p", " "], ["punc", "}"], ["p", " "], ["kw", "as"], ["p", " "], ["ty", "Order"], ["punc", ")"], ["punc", ";"]], [["var", "console"], ["op", "."], ["fnc", "log"], ["punc", "("], ["var", "q"], ["op", "."], ["prop", "max"], ["punc", ")"], ["punc", ";"]], [["kw", "const"], ["p", " "], ["var", "cap"], ["p", " "], ["op", "="], ["p", " "], ["var", "Math"], ["op", "."], ["bi", "max"], ["punc", "("], ["con", "LIMIT"], ["punc", ","], ["p", " "], ["num", "0"], ["punc", ")"], ["punc", ";"]]], "Java": [[["cmd", "/**"], ["doc", " A color theme. */"]], [["kw", "package"], ["p", " "], ["var", "com"], ["op", "."], ["var", "dupre"], ["punc", ";"]], [["kw", "import"], ["p", " "], ["var", "java"], ["op", "."], ["var", "util"], ["op", "."], ["var", "regex"], ["op", "."], ["ty", "Pattern"], ["punc", ";"]], [], [["dec", "@Deprecated"]], [["kw", "public"], ["p", " "], ["kw", "final"], ["p", " "], ["kw", "class"], ["p", " "], ["ty", "Theme"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "private"], ["p", " "], ["kw", "static"], ["p", " "], ["kw", "final"], ["p", " "], ["ty", "int"], ["p", " "], ["con", "MAX_PORT"], ["p", " "], ["op", "="], ["p", " "], ["num", "8080"], ["punc", ";"]], [["p", " "], ["kw", "private"], ["p", " "], ["kw", "final"], ["p", " "], ["ty", "String"], ["p", " "], ["prop", "name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ";"]], [["p", " "], ["kw", "private"], ["p", " "], ["kw", "static"], ["p", " "], ["kw", "final"], ["p", " "], ["ty", "Pattern"], ["p", " "], ["con", "HEX"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Pattern"], ["op", "."], ["fnc", "compile"], ["punc", "("], ["re", "\"#[0-9a-f]{6}\""], ["punc", ")"], ["punc", ";"]], [], [["p", " "], ["dec", "@Override"]], [["p", " "], ["kw", "public"], ["p", " "], ["ty", "String"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["ty", "String"], ["p", " "], ["var", "key"], ["punc", ")"], ["p", " "], ["punc", "{"]], [["p", " "], ["cmd", "//"], ["cm", " fall back to null"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "key"], ["op", "."], ["fnc", "isEmpty"], ["punc", "()"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "null"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["var", "key"], ["op", "."], ["fnc", "strip"], ["punc", "("], ["punc", ")"], ["op", "+"], ["str", "\""], ["esc", "\\t"], ["str", "\""], ["punc", ";"]], [["p", " "], ["punc", "}"]], [], [["p", " "], ["kw", "public"], ["p", " "], ["kw", "static"], ["p", " "], ["ty", "void"], ["p", " "], ["fnd", "main"], ["punc", "("], ["ty", "String"], ["punc", "[]"], ["p", " "], ["var", "args"], ["punc", ")"], ["p", " "], ["punc", "{"]], [["p", " "], ["ty", "var"], ["p", " "], ["var", "t"], ["p", " "], ["op", "="], ["p", " "], ["kw", "new"], ["p", " "], ["ty", "Theme"], ["punc", "()"], ["punc", ";"]], [["p", " "], ["ty", "System"], ["op", "."], ["prop", "out"], ["op", "."], ["fnc", "println"], ["punc", "("], ["var", "t"], ["op", "."], ["fnc", "resolve"], ["punc", "("], ["str", "\"bg\""], ["punc", "))"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"]]], "C": [[["cmd", "/**"], ["doc", " Order queue. */"]], [["pp", "#include"], ["p", " "], ["str", "<stdio.h>"]], [["pp", "#include"], ["p", " "], ["str", "<stdlib.h>"]], [["pp", "#define"], ["p", " "], ["con", "MAX_PORT"], ["p", " "], ["num", "8080"]], [], [["kw", "typedef"], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"]], [["p", " "], ["ty", "int"], ["p", " "], ["prop", "id"], ["punc", ";"]], [["p", " "], ["kw", "const"], ["p", " "], ["ty", "char"], ["p", " "], ["op", "*"], ["prop", "name"], ["punc", ";"]], [["punc", "}"], ["p", " "], ["ty", "Order"], ["punc", ";"]], [], [["cmd", "//"], ["cm", " returns -1 on null input"]], [["ty", "int"], ["p", " "], ["fnd", "push"], ["punc", "("], ["ty", "Order"], ["p", " "], ["op", "*"], ["var", "o"], ["punc", ")"], ["p", " "], ["dec", "__attribute__"], ["punc", "(("], ["dec", "nonnull"], ["punc", "))"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "o"], ["p", " "], ["op", "=="], ["p", " "], ["con", "NULL"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["num", "-1"], ["punc", ";"]], [["p", " "], ["fnc", "printf"], ["punc", "("], ["str", "\"id=%d"], ["esc", "\\n"], ["str", "\""], ["punc", ","], ["p", " "], ["var", "o"], ["op", "->"], ["prop", "id"], ["punc", ");"]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "0"], ["punc", ";"]], [["punc", "}"]], [], [["ty", "int"], ["p", " "], ["fnd", "main"], ["punc", "("], ["ty", "void"], ["punc", ")"], ["p", " "], ["punc", "{"]], [["p", " "], ["ty", "Order"], ["p", " "], ["var", "o"], ["p", " "], ["op", "="], ["p", " "], ["punc", "{"], ["p", " "], ["op", "."], ["prop", "id"], ["p", " "], ["op", "="], ["p", " "], ["num", "1"], ["punc", ","], ["p", " "], ["op", "."], ["prop", "name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["ty", "Order"], ["p", " "], ["op", "*"], ["var", "p2"], ["p", " "], ["op", "="], ["p", " "], ["bi", "malloc"], ["punc", "("], ["bi", "sizeof"], ["punc", "("], ["ty", "Order"], ["punc", "))"], ["punc", ";"]], [["p", " "], ["fnc", "push"], ["punc", "("], ["op", "&"], ["var", "o"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["bi", "free"], ["punc", "("], ["var", "p2"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "0"], ["punc", ";"]], [["punc", "}"]]], "C++": [[["cmd", "/**"], ["doc", " A color theme. */"]], [["pp", "#include"], ["p", " "], ["str", "<string>"]], [["pp", "#include"], ["p", " "], ["str", "<regex>"]], [["pp", "#pragma"], ["p", " "], ["pp", "once"]], [], [["kw", "namespace"], ["p", " "], ["var", "dupre"], ["p", " "], ["punc", "{"]], [], [["kw", "template"], ["op", "<"], ["kw", "typename"], ["p", " "], ["ty", "T"], ["op", ">"], ["p", " "], ["kw", "class"], ["p", " "], ["ty", "Theme"], ["p", " "], ["punc", "{"]], [["kw", "public"], ["op", ":"]], [["p", " "], ["kw", "static"], ["p", " "], ["kw", "constexpr"], ["p", " "], ["ty", "int"], ["p", " "], ["con", "MAX"], ["p", " "], ["op", "="], ["p", " "], ["num", "0x20"], ["punc", ";"]], [["p", " "], ["ty", "std"], ["op", "::"], ["ty", "string"], ["p", " "], ["prop", "name_"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ";"]], [], [["p", " "], ["dec", "[[nodiscard]]"], ["p", " "], ["ty", "T"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["kw", "const"], ["p", " "], ["ty", "std"], ["op", "::"], ["ty", "string"], ["op", "&"], ["p", " "], ["var", "key"], ["punc", ")"], ["p", " "], ["kw", "const"], ["p", " "], ["punc", "{"]], [["p", " "], ["cmd", "//"], ["cm", " validate against a hex pattern"]], [["p", " "], ["kw", "static"], ["p", " "], ["ty", "std"], ["op", "::"], ["ty", "regex"], ["p", " "], ["var", "re"], ["punc", "("], ["re", "R\"(#[0-9a-f]{6})\""], ["punc", ")"], ["punc", ";"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "key"], ["op", "."], ["fnc", "empty"], ["punc", "()"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "nullptr"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["ty", "T"], ["punc", "{"], ["var", "key"], ["punc", "}"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"], ["punc", ";"]], [], [["ty", "int"], ["p", " "], ["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "auto"], ["p", " "], ["var", "t"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Theme"], ["op", "<"], ["ty", "int"], ["op", ">"], ["punc", "{}"], ["punc", ";"]], [["p", " "], ["bi", "static_cast"], ["op", "<"], ["ty", "int"], ["op", ">"], ["punc", "("], ["var", "t"], ["op", "."], ["prop", "name_"], ["op", "."], ["fnc", "size"], ["punc", "())"], ["punc", ";"]], [["p", " "], ["ty", "std"], ["op", "::"], ["fnc", "printf"], ["punc", "("], ["str", "\"%s"], ["esc", "\\n"], ["str", "\""], ["punc", ","], ["p", " "], ["var", "t"], ["op", "."], ["prop", "name_"], ["op", "."], ["fnc", "c_str"], ["punc", "())"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "0"], ["punc", ";"]], [["punc", "}"]]], "Shell": [[["cmd", "#!"], ["cm", "/bin/bash"]], [["cmd", "#"], ["cm", " deploy.sh"]], [["bi", "set"], ["p", " "], ["op", "-"], ["var", "euo"], ["p", " "], ["var", "pipefail"]], [], [["var", "PORT"], ["op", "="], ["num", "8080"]], [["var", "NAME"], ["op", "="], ["str", "\"dupre\""]], [], [["fnd", "deploy"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "local"], ["p", " "], ["var", "target"], ["op", "="], ["str", "\"$1\""]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "[["], ["p", " "], ["op", "-z"], ["p", " "], ["str", "\"$target\""], ["p", " "], ["punc", "]]"], ["punc", ";"], ["p", " "], ["kw", "then"]], [["p", " "], ["bi", "echo"], ["p", " "], ["str", "\"no target\""]], [["p", " "], ["kw", "return"], ["p", " "], ["num", "1"]], [["p", " "], ["kw", "fi"]], [["p", " "], ["fnc", "rsync"], ["p", " "], ["op", "-az"], ["p", " "], ["str", "\"$NAME\""], ["p", " "], ["str", "\"$target\""]], [["punc", "}"]], [], [["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "for"], ["p", " "], ["var", "host"], ["p", " "], ["kw", "in"], ["p", " "], ["str", "\"$@\""], ["punc", ";"], ["p", " "], ["kw", "do"]], [["p", " "], ["fnc", "deploy"], ["p", " "], ["str", "\"$host\""], ["p", " "], ["op", "||"], ["p", " "], ["bi", "exit"], ["p", " "], ["num", "1"]], [["p", " "], ["kw", "done"]], [["p", " "], ["bi", "echo"], ["p", " "], ["op", "-e"], ["p", " "], ["str", "\"all done"], ["esc", "\\n"], ["str", "\""]], [["punc", "}"]], [], [["fnc", "main"], ["p", " "], ["str", "\"$@\""]]]}, CATS=[["bg", "bg (ground)", "Aa Bb 123"], ["p", "fg", "other / whitespace"], ["kw", "keyword", "class def if return"], ["bi", "builtin", "len echo printf"], ["pp", "preprocessor", "#include #define"], ["fnd", "function \u00b7 def", "resolve push"], ["fnc", "function \u00b7 call", "printf rsync get"], ["dec", "decorator", "@dataclass"], ["ty", "type / class", "int str Order Queue"], ["prop", "property / field", "id name items"], ["con", "constant", "None nil NULL true"], ["num", "number", "8080 100 -1"], ["str", "string", "\"dupre\" \"fmt\""], ["esc", "escape", "\\n \\t"], ["re", "regexp", "/^#[0-9a-f]+/"], ["doc", "docstring", "\"\"\"...\"\"\""], ["cm", "comment", "# reject nil"], ["cmd", "comment delim", "# // ;;"], ["var", "variable / use", "value key self"], ["op", "operator", ": = -> =="], ["punc", "punctuation", "{ } ( ) ;"]], UI_FACES=[["cursor", "cursor", "Aa|"], ["region", "region (selection)", "selected text"], ["hl-line", "hl-line (current line)", "current line"], ["highlight", "highlight", "hover"], ["mode-line", "mode-line", "status active"], ["mode-line-inactive", "mode-line-inactive", "status idle"], ["fringe", "fringe", "| |"], ["line-number", "line-number", " 42"], ["line-number-current-line", "line-number-current-line", "> 42"], ["minibuffer-prompt", "minibuffer-prompt", "M-x "], ["isearch", "isearch (match)", "match"], ["lazy-highlight", "lazy-highlight", "other match"], ["isearch-fail", "isearch-fail", "no match"], ["show-paren-match", "show-paren-match", "( )"], ["show-paren-mismatch", "show-paren-mismatch", ") ("], ["link", "link", "https://"], ["error", "error", "error!"], ["warning", "warning", "warning"], ["success", "success", "ok"], ["vertical-border", "vertical-border", "|"]], APPS={"org-mode": {"label": "org-mode", "preview": "org", "faces": [["org-document-title", "document title", {"fg": null, "bg": null, "bold": true, "height": 1.5, "source": "default"}], ["org-document-info", "document info", {"fg": "#8a9496", "bg": null, "source": "default"}], ["org-document-info-keyword", "document info keyword", {"fg": "#8a9496", "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-level-1", "level 1", {"fg": "#67809c", "bg": null, "bold": true, "height": 1.3, "source": "default"}], ["org-level-2", "level 2", {"fg": null, "bg": null, "height": 1.2, "source": "default"}], ["org-level-3", "level 3", {"fg": null, "bg": null, "height": 1.15, "source": "default"}], ["org-level-4", "level 4", {"fg": null, "bg": null, "height": 1.1, "source": "default"}], ["org-level-5", "level 5", {"fg": null, "bg": null, "source": "default"}], ["org-level-6", "level 6", {"fg": null, "bg": null, "source": "default"}], ["org-level-7", "level 7", {"fg": null, "bg": null, "source": "default"}], ["org-level-8", "level 8", {"fg": "#8a9496", "bg": null, "source": "default"}], ["org-headline-todo", "headline todo", {"fg": null, "bg": null, "source": "default"}], ["org-headline-done", "headline done", {"fg": null, "bg": null, "source": "default"}], ["org-todo", "todo", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-done", "done", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-priority", "priority", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-tag", "tag", {"fg": null, "bg": null, "source": "default"}], ["org-tag-group", "tag group", {"fg": null, "bg": null, "source": "default"}], ["org-special-keyword", "special keyword", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-drawer", "drawer", {"fg": null, "bg": null, "source": "default"}], ["org-property-value", "property value", {"fg": "#8a9496", "bg": null, "source": "default"}], ["org-checkbox", "checkbox", {"fg": null, "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-checkbox-statistics-todo", "checkbox statistics todo", {"fg": null, "bg": null, "source": "default"}], ["org-checkbox-statistics-done", "checkbox statistics done", {"fg": null, "bg": null, "source": "default"}], ["org-warning", "warning", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-link", "link", {"fg": "#67809c", "bg": null, "underline": true, "source": "default"}], ["org-footnote", "footnote", {"fg": "#67809c", "bg": null, "source": "default"}], ["org-date", "date", {"fg": "#8a9496", "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-sexp-date", "sexp date", {"fg": "#8a9496", "bg": null, "source": "default"}], ["org-date-selected", "date selected", {"fg": null, "bg": null, "source": "default"}], ["org-target", "target", {"fg": null, "bg": null, "source": "default"}], ["org-macro", "macro", {"fg": null, "bg": null, "source": "default"}], ["org-cite", "cite", {"fg": "#67809c", "bg": null, "underline": true, "source": "default"}], ["org-cite-key", "cite key", {"fg": "#67809c", "bg": null, "underline": true, "source": "default"}], ["org-block", "block", {"fg": null, "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-block-begin-line", "block begin line", {"fg": null, "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-block-end-line", "block end line", {"fg": null, "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-code", "code", {"fg": null, "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-verbatim", "verbatim", {"fg": "#8a9496", "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-inline-src-block", "inline src block", {"fg": null, "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-quote", "quote", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["org-verse", "verse", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["org-latex-and-related", "latex and related", {"fg": null, "bg": null, "source": "default"}], ["org-table", "table", {"fg": "#8a9496", "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-table-header", "table header", {"fg": null, "bg": "#58574e", "bold": true, "source": "default"}], ["org-table-row", "table row", {"fg": null, "bg": null, "source": "default"}], ["org-formula", "formula", {"fg": null, "bg": null, "source": "default"}], ["org-column", "column", {"fg": null, "bg": null, "source": "default"}], ["org-column-title", "column title", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-list-dt", "list dt", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-meta-line", "meta line", {"fg": null, "bg": null, "inherit": "fixed-pitch", "source": "default"}], ["org-ellipsis", "ellipsis", {"fg": null, "bg": null, "source": "default"}], ["org-hide", "hide", {"fg": null, "bg": null, "source": "default"}], ["org-indent", "indent", {"fg": null, "bg": null, "source": "default"}], ["org-archived", "archived", {"fg": null, "bg": null, "source": "default"}], ["org-default", "default", {"fg": null, "bg": null, "source": "default"}], ["org-dispatcher-highlight", "dispatcher highlight", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-agenda-structure", "agenda structure", {"fg": "#67809c", "bg": null, "bold": true, "height": 1.1, "source": "default"}], ["org-agenda-structure-secondary", "agenda structure secondary", {"fg": "#67809c", "bg": null, "source": "default"}], ["org-agenda-structure-filter", "agenda structure filter", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-agenda-date", "agenda date", {"fg": "#8a9496", "bg": null, "height": 1.05, "source": "default"}], ["org-agenda-date-today", "agenda date today", {"fg": null, "bg": null, "bold": true, "height": 1.05, "source": "default"}], ["org-agenda-date-weekend", "agenda date weekend", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["org-agenda-date-weekend-today", "agenda date weekend today", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-agenda-current-time", "agenda current time", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-done", "agenda done", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-dimmed-todo-face", "agenda dimmed todo", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-calendar-event", "agenda calendar event", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-calendar-sexp", "agenda calendar sexp", {"fg": "#8a9496", "bg": null, "source": "default"}], ["org-agenda-calendar-daterange", "agenda calendar daterange", {"fg": "#8a9496", "bg": null, "source": "default"}], ["org-agenda-diary", "agenda diary", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-clocking", "agenda clocking", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-column-dateline", "agenda column dateline", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-restriction-lock", "agenda restriction lock", {"fg": null, "bg": null, "source": "default"}], ["org-agenda-filter-category", "agenda filter category", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-agenda-filter-effort", "agenda filter effort", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-agenda-filter-regexp", "agenda filter regexp", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-agenda-filter-tags", "agenda filter tags", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-scheduled", "scheduled", {"fg": null, "bg": null, "source": "default"}], ["org-scheduled-today", "scheduled today", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-scheduled-previously", "scheduled previously", {"fg": null, "bg": null, "source": "default"}], ["org-upcoming-deadline", "upcoming deadline", {"fg": null, "bg": null, "source": "default"}], ["org-upcoming-distant-deadline", "upcoming distant deadline", {"fg": null, "bg": null, "source": "default"}], ["org-imminent-deadline", "imminent deadline", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-time-grid", "time grid", {"fg": null, "bg": null, "source": "default"}], ["org-clock-overlay", "clock overlay", {"fg": null, "bg": null, "source": "default"}], ["org-mode-line-clock", "mode line clock", {"fg": "#8a9496", "bg": null, "source": "default"}], ["org-mode-line-clock-overrun", "mode line clock overrun", {"fg": null, "bg": null, "bold": true, "source": "default"}]]}, "magit": {"label": "magit", "preview": "magit", "faces": [["magit-section-heading", "section heading", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-section-secondary-heading", "section secondary heading", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-section-heading-selection", "section heading selection", {"fg": null, "bg": null, "source": "default"}], ["magit-section-highlight", "section highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-section-child-count", "section child count", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-added", "diff added", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-added-highlight", "diff added highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-removed", "diff removed", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-removed-highlight", "diff removed highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-context", "diff context", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-context-highlight", "diff context highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-file-heading", "diff file heading", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-diff-file-heading-highlight", "diff file heading highlight", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-diff-file-heading-selection", "diff file heading selection", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-hunk-heading", "diff hunk heading", {"fg": "#8a9496", "bg": null, "source": "default"}], ["magit-diff-hunk-heading-highlight", "diff hunk heading highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-hunk-heading-selection", "diff hunk heading selection", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-hunk-region", "diff hunk region", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-lines-heading", "diff lines heading", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-lines-boundary", "diff lines boundary", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-base", "diff base", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-base-highlight", "diff base highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-our", "diff our", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-our-highlight", "diff our highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-their", "diff their", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-their-highlight", "diff their highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-conflict-heading", "diff conflict heading", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-conflict-heading-highlight", "diff conflict heading highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-revision-summary", "diff revision summary", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-revision-summary-highlight", "diff revision summary highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-diff-whitespace-warning", "diff whitespace warning", {"fg": null, "bg": null, "source": "default"}], ["magit-diffstat-added", "diffstat added", {"fg": null, "bg": null, "source": "default"}], ["magit-diffstat-removed", "diffstat removed", {"fg": null, "bg": null, "source": "default"}], ["magit-branch-current", "branch current", {"fg": "#67809c", "bg": null, "bold": true, "box": {"style": "line", "width": 1, "color": null}, "source": "default"}], ["magit-branch-local", "branch local", {"fg": "#67809c", "bg": null, "source": "default"}], ["magit-branch-remote", "branch remote", {"fg": null, "bg": null, "source": "default"}], ["magit-branch-remote-head", "branch remote head", {"fg": null, "bg": null, "bold": true, "box": {"style": "line", "width": 1, "color": null}, "source": "default"}], ["magit-branch-upstream", "branch upstream", {"fg": null, "bg": null, "source": "default"}], ["magit-branch-warning", "branch warning", {"fg": null, "bg": null, "source": "default"}], ["magit-head", "head", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["magit-tag", "tag", {"fg": null, "bg": null, "source": "default"}], ["magit-hash", "hash", {"fg": null, "bg": null, "source": "default"}], ["magit-filename", "filename", {"fg": "#8a9496", "bg": null, "source": "default"}], ["magit-dimmed", "dimmed", {"fg": null, "bg": null, "source": "default"}], ["magit-keyword", "keyword", {"fg": null, "bg": null, "source": "default"}], ["magit-keyword-squash", "keyword squash", {"fg": null, "bg": null, "source": "default"}], ["magit-refname", "refname", {"fg": null, "bg": null, "source": "default"}], ["magit-refname-stash", "refname stash", {"fg": null, "bg": null, "source": "default"}], ["magit-refname-wip", "refname wip", {"fg": null, "bg": null, "source": "default"}], ["magit-refname-pullreq", "refname pullreq", {"fg": null, "bg": null, "source": "default"}], ["magit-log-author", "log author", {"fg": null, "bg": null, "source": "default"}], ["magit-log-date", "log date", {"fg": "#8a9496", "bg": null, "source": "default"}], ["magit-log-graph", "log graph", {"fg": null, "bg": null, "source": "default"}], ["magit-header-line", "header line", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-header-line-key", "header line key", {"fg": null, "bg": null, "source": "default"}], ["magit-header-line-log-select", "header line log select", {"fg": null, "bg": null, "source": "default"}], ["magit-process-ok", "process ok", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-process-ng", "process ng", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-mode-line-process", "mode line process", {"fg": null, "bg": null, "source": "default"}], ["magit-mode-line-process-error", "mode line process error", {"fg": null, "bg": null, "source": "default"}], ["magit-bisect-good", "bisect good", {"fg": null, "bg": null, "source": "default"}], ["magit-bisect-bad", "bisect bad", {"fg": null, "bg": null, "source": "default"}], ["magit-bisect-skip", "bisect skip", {"fg": null, "bg": null, "source": "default"}], ["magit-blame-heading", "blame heading", {"fg": "#8a9496", "bg": null, "source": "default"}], ["magit-blame-highlight", "blame highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-blame-hash", "blame hash", {"fg": null, "bg": null, "source": "default"}], ["magit-blame-name", "blame name", {"fg": null, "bg": null, "source": "default"}], ["magit-blame-date", "blame date", {"fg": "#8a9496", "bg": null, "source": "default"}], ["magit-blame-summary", "blame summary", {"fg": null, "bg": null, "source": "default"}], ["magit-blame-dimmed", "blame dimmed", {"fg": null, "bg": null, "source": "default"}], ["magit-blame-margin", "blame margin", {"fg": null, "bg": null, "source": "default"}], ["magit-cherry-equivalent", "cherry equivalent", {"fg": null, "bg": null, "source": "default"}], ["magit-cherry-unmatched", "cherry unmatched", {"fg": null, "bg": null, "source": "default"}], ["magit-signature-good", "signature good", {"fg": null, "bg": null, "source": "default"}], ["magit-signature-bad", "signature bad", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["magit-signature-untrusted", "signature untrusted", {"fg": null, "bg": null, "source": "default"}], ["magit-signature-expired", "signature expired", {"fg": null, "bg": null, "source": "default"}], ["magit-signature-expired-key", "signature expired key", {"fg": null, "bg": null, "source": "default"}], ["magit-signature-revoked", "signature revoked", {"fg": null, "bg": null, "source": "default"}], ["magit-signature-error", "signature error", {"fg": null, "bg": null, "source": "default"}], ["magit-reflog-commit", "reflog commit", {"fg": null, "bg": null, "source": "default"}], ["magit-reflog-amend", "reflog amend", {"fg": null, "bg": null, "source": "default"}], ["magit-reflog-merge", "reflog merge", {"fg": null, "bg": null, "source": "default"}], ["magit-reflog-checkout", "reflog checkout", {"fg": "#67809c", "bg": null, "source": "default"}], ["magit-reflog-reset", "reflog reset", {"fg": null, "bg": null, "source": "default"}], ["magit-reflog-rebase", "reflog rebase", {"fg": null, "bg": null, "source": "default"}], ["magit-reflog-cherry-pick", "reflog cherry pick", {"fg": null, "bg": null, "source": "default"}], ["magit-reflog-remote", "reflog remote", {"fg": "#8a9496", "bg": null, "source": "default"}], ["magit-reflog-other", "reflog other", {"fg": "#8a9496", "bg": null, "source": "default"}], ["magit-sequence-pick", "sequence pick", {"fg": null, "bg": null, "source": "default"}], ["magit-sequence-stop", "sequence stop", {"fg": null, "bg": null, "source": "default"}], ["magit-sequence-part", "sequence part", {"fg": null, "bg": null, "source": "default"}], ["magit-sequence-head", "sequence head", {"fg": "#67809c", "bg": null, "source": "default"}], ["magit-sequence-drop", "sequence drop", {"fg": null, "bg": null, "source": "default"}], ["magit-sequence-done", "sequence done", {"fg": null, "bg": null, "source": "default"}], ["magit-sequence-onto", "sequence onto", {"fg": null, "bg": null, "source": "default"}], ["magit-sequence-exec", "sequence exec", {"fg": null, "bg": null, "source": "default"}], ["magit-left-margin", "left margin", {"fg": null, "bg": null, "source": "default"}]]}, "elfeed": {"label": "elfeed", "preview": "elfeed", "faces": [["elfeed-search-date-face", "search date", {"fg": "#8a9496", "bg": null, "source": "default"}], ["elfeed-search-title-face", "search title", {"fg": null, "bg": null, "source": "default"}], ["elfeed-search-unread-title-face", "search unread title", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["elfeed-search-feed-face", "search feed", {"fg": null, "bg": null, "source": "default"}], ["elfeed-search-tag-face", "search tag", {"fg": null, "bg": null, "source": "default"}], ["elfeed-search-unread-count-face", "search unread count", {"fg": null, "bg": null, "source": "default"}], ["elfeed-search-filter-face", "search filter", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["elfeed-search-last-update-face", "search last update", {"fg": null, "bg": null, "source": "default"}], ["elfeed-log-date-face", "log date", {"fg": "#8a9496", "bg": null, "source": "default"}], ["elfeed-log-error-level-face", "log error level", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["elfeed-log-warn-level-face", "log warn level", {"fg": null, "bg": null, "source": "default"}], ["elfeed-log-info-level-face", "log info level", {"fg": null, "bg": null, "source": "default"}], ["elfeed-log-debug-level-face", "log debug level", {"fg": null, "bg": null, "source": "default"}]]}, "mu4e": {"label": "mu4e", "preview": "mu4e", "faces": [["mu4e-title-face", "title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["mu4e-context-face", "context", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["mu4e-modeline-face", "modeline", {"fg": null, "bg": null, "source": "default"}], ["mu4e-ok-face", "ok", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["mu4e-warning-face", "warning", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["mu4e-header-title-face", "header title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["mu4e-header-key-face", "header key", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["mu4e-header-value-face", "header value", {"fg": null, "bg": null, "source": "default"}], ["mu4e-header-face", "header", {"fg": "#cdced1", "bg": null, "source": "default"}], ["mu4e-header-highlight-face", "header highlight", {"fg": null, "bg": null, "underline": true, "source": "default"}], ["mu4e-header-marks-face", "header marks", {"fg": null, "bg": null, "source": "default"}], ["mu4e-unread-face", "unread", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["mu4e-flagged-face", "flagged", {"fg": null, "bg": null, "source": "default"}], ["mu4e-replied-face", "replied", {"fg": null, "bg": null, "source": "default"}], ["mu4e-forwarded-face", "forwarded", {"fg": null, "bg": null, "source": "default"}], ["mu4e-draft-face", "draft", {"fg": "#8a9496", "bg": null, "italic": true, "source": "default"}], ["mu4e-trashed-face", "trashed", {"fg": null, "bg": null, "strike": true, "source": "default"}], ["mu4e-related-face", "related", {"fg": "#8a9496", "bg": null, "italic": true, "source": "default"}], ["mu4e-contact-face", "contact", {"fg": "#cdced1", "bg": null, "source": "default"}], ["mu4e-special-header-value-face", "special header value", {"fg": null, "bg": null, "source": "default"}], ["mu4e-url-number-face", "url number", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["mu4e-link-face", "link", {"fg": "#67809c", "bg": null, "underline": true, "source": "default"}], ["mu4e-footer-face", "footer", {"fg": null, "bg": null, "source": "default"}], ["mu4e-region-code", "region code", {"fg": null, "bg": null, "source": "default"}], ["mu4e-system-face", "system", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["mu4e-highlight-face", "highlight", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["mu4e-compose-separator-face", "compose separator", {"fg": null, "bg": null, "source": "default"}]]}, "ghostel": {"label": "ghostel", "preview": "ghostel", "faces": [["ghostel-default", "default", {"fg": "#cdced1", "bg": null, "source": "default"}], ["ghostel-fake-cursor", "fake cursor", {"fg": "#000000", "bg": null, "source": "default"}], ["ghostel-fake-cursor-box", "fake cursor box", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-black", "color black", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-red", "color red", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-green", "color green", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-yellow", "color yellow", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-blue", "color blue", {"fg": "#67809c", "bg": null, "source": "default"}], ["ghostel-color-magenta", "color magenta", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-cyan", "color cyan", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-white", "color white", {"fg": null, "bg": null, "source": "default"}], ["ghostel-color-bright-black", "color bright black", {"fg": "#8a9496", "bg": null, "source": "default"}], ["ghostel-color-bright-red", "color bright red", {"fg": "#de4949", "bg": null, "source": "default"}], ["ghostel-color-bright-green", "color bright green", {"fg": "#84b068", "bg": null, "source": "default"}], ["ghostel-color-bright-yellow", "color bright yellow", {"fg": "#eed376", "bg": null, "source": "default"}], ["ghostel-color-bright-blue", "color bright blue", {"fg": "#7a9abe", "bg": null, "source": "default"}], ["ghostel-color-bright-magenta", "color bright magenta", {"fg": "#b07fd0", "bg": null, "source": "default"}], ["ghostel-color-bright-cyan", "color bright cyan", {"fg": "#7fc0a8", "bg": null, "source": "default"}], ["ghostel-color-bright-white", "color bright white", {"fg": null, "bg": null, "source": "default"}]]}, "dashboard": {"label": "dashboard", "preview": "dashboard", "faces": [["dashboard-banner-logo-title", "banner logo title", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dashboard-text-banner", "text banner", {"fg": "#8a9496", "bg": null, "source": "default"}], ["dashboard-heading", "heading", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["dashboard-items-face", "items", {"fg": "#cdced1", "bg": null, "source": "default"}], ["dashboard-navigator", "navigator", {"fg": "#67809c", "bg": null, "source": "default"}], ["dashboard-no-items-face", "no items", {"fg": null, "bg": null, "source": "default"}], ["dashboard-footer-face", "footer", {"fg": null, "bg": null, "source": "default"}], ["dashboard-footer-icon-face", "footer icon", {"fg": null, "bg": null, "source": "default"}]]}, "lsp-mode": {"label": "lsp-mode", "preview": "lsp", "faces": [["lsp-signature-face", "signature", {"fg": null, "bg": null, "source": "default"}], ["lsp-signature-highlight-function-argument", "signature highlight function argument", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["lsp-signature-posframe", "signature posframe", {"fg": null, "bg": null, "source": "default"}], ["lsp-face-highlight-read", "face highlight read", {"fg": null, "bg": null, "underline": true, "source": "default"}], ["lsp-face-highlight-write", "face highlight write", {"fg": null, "bg": "#3d2f4a", "bold": true, "source": "default"}], ["lsp-face-highlight-textual", "face highlight textual", {"fg": null, "bg": null, "source": "default"}], ["lsp-face-rename", "face rename", {"fg": null, "bg": null, "bold": true, "underline": true, "source": "default"}], ["lsp-rename-placeholder-face", "rename placeholder", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["lsp-inlay-hint-face", "inlay hint", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["lsp-inlay-hint-parameter-face", "inlay hint parameter", {"fg": "#8a9496", "bg": null, "italic": true, "source": "default"}], ["lsp-inlay-hint-type-face", "inlay hint type", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["lsp-details-face", "details", {"fg": null, "bg": null, "italic": true, "height": 0.8, "source": "default"}], ["lsp-installation-buffer-face", "installation buffer", {"fg": "#67809c", "bg": null, "source": "default"}], ["lsp-installation-finished-buffer-face", "installation finished buffer", {"fg": null, "bg": null, "source": "default"}]]}, "git-gutter": {"label": "git-gutter", "preview": "gitgutter", "faces": [["git-gutter:added", "added", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["git-gutter:modified", "modified", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["git-gutter:deleted", "deleted", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["git-gutter:unchanged", "unchanged", {"fg": null, "bg": null, "source": "default"}], ["git-gutter:separator", "separator", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}]]}, "flycheck": {"label": "flycheck", "preview": "flycheck", "faces": [["flycheck-error", "error", {"fg": null, "bg": null, "underline": true, "source": "default"}], ["flycheck-warning", "warning", {"fg": null, "bg": null, "underline": true, "source": "default"}], ["flycheck-info", "info", {"fg": "#67809c", "bg": null, "underline": true, "source": "default"}], ["flycheck-fringe-error", "fringe error", {"fg": null, "bg": null, "source": "default"}], ["flycheck-fringe-warning", "fringe warning", {"fg": null, "bg": null, "source": "default"}], ["flycheck-fringe-info", "fringe info", {"fg": "#67809c", "bg": null, "source": "default"}], ["flycheck-delimited-error", "delimited error", {"fg": null, "bg": null, "source": "default"}], ["flycheck-error-delimiter", "error delimiter", {"fg": null, "bg": null, "source": "default"}], ["flycheck-error-list-error", "error list error", {"fg": null, "bg": null, "source": "default"}], ["flycheck-error-list-warning", "error list warning", {"fg": null, "bg": null, "source": "default"}], ["flycheck-error-list-info", "error list info", {"fg": "#67809c", "bg": null, "source": "default"}], ["flycheck-error-list-error-message", "error list error message", {"fg": "#cdced1", "bg": null, "source": "default"}], ["flycheck-error-list-checker-name", "error list checker name", {"fg": "#8a9496", "bg": null, "source": "default"}], ["flycheck-error-list-column-number", "error list column number", {"fg": null, "bg": null, "source": "default"}], ["flycheck-error-list-line-number", "error list line number", {"fg": null, "bg": null, "source": "default"}], ["flycheck-error-list-filename", "error list filename", {"fg": "#67809c", "bg": null, "source": "default"}], ["flycheck-error-list-id", "error list id", {"fg": "#8a9496", "bg": null, "source": "default"}], ["flycheck-error-list-id-with-explainer", "error list id with explainer", {"fg": "#8a9496", "bg": null, "bold": true, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["flycheck-error-list-highlight", "error list highlight", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["flycheck-verify-select-checker", "verify select checker", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}]]}, "dired": {"label": "dired", "preview": "dired", "faces": [["dired-header", "header", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["dired-directory", "directory", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["dired-symlink", "symlink", {"fg": null, "bg": null, "source": "default"}], ["dired-broken-symlink", "broken symlink", {"fg": "#de4949", "bg": null, "bold": true, "source": "default"}], ["dired-special", "special", {"fg": null, "bg": null, "source": "default"}], ["dired-set-id", "set id", {"fg": null, "bg": null, "source": "default"}], ["dired-perm-write", "perm write", {"fg": null, "bg": null, "source": "default"}], ["dired-mark", "mark", {"fg": null, "bg": null, "source": "default"}], ["dired-marked", "marked", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dired-flagged", "flagged", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dired-ignored", "ignored", {"fg": null, "bg": null, "source": "default"}], ["dired-warning", "warning", {"fg": null, "bg": null, "bold": true, "source": "default"}]]}, "dirvish": {"label": "dirvish", "preview": "dirvish", "faces": [["dirvish-inactive", "inactive", {"fg": null, "bg": null, "source": "default"}], ["dirvish-free-space", "free space", {"fg": null, "bg": null, "source": "default"}], ["dirvish-hl-line", "hl line", {"fg": null, "bg": null, "source": "default"}], ["dirvish-hl-line-inactive", "hl line inactive", {"fg": null, "bg": null, "source": "default"}], ["dirvish-file-modes", "file modes", {"fg": "#8a9496", "bg": null, "source": "default"}], ["dirvish-file-link-number", "file link number", {"fg": null, "bg": null, "source": "default"}], ["dirvish-file-user-id", "file user id", {"fg": "#67809c", "bg": null, "source": "default"}], ["dirvish-file-group-id", "file group id", {"fg": "#8a9496", "bg": null, "source": "default"}], ["dirvish-file-size", "file size", {"fg": null, "bg": null, "source": "default"}], ["dirvish-file-time", "file time", {"fg": null, "bg": null, "source": "default"}], ["dirvish-file-inode-number", "file inode number", {"fg": null, "bg": null, "source": "default"}], ["dirvish-file-device-number", "file device number", {"fg": null, "bg": null, "source": "default"}], ["dirvish-subtree-guide", "subtree guide", {"fg": null, "bg": null, "source": "default"}], ["dirvish-subtree-state", "subtree state", {"fg": "#8a9496", "bg": null, "source": "default"}], ["dirvish-collapse-dir-face", "collapse dir", {"fg": "#67809c", "bg": null, "source": "default"}], ["dirvish-collapse-empty-dir-face", "collapse empty dir", {"fg": null, "bg": null, "source": "default"}], ["dirvish-collapse-file-face", "collapse file", {"fg": null, "bg": null, "source": "default"}], ["dirvish-emerge-group-title", "emerge group title", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dirvish-media-info-heading", "media info heading", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["dirvish-media-info-property-key", "media info property key", {"fg": "#8a9496", "bg": null, "italic": true, "source": "default"}], ["dirvish-narrow-match-face-0", "narrow match 0", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dirvish-narrow-match-face-1", "narrow match 1", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["dirvish-narrow-match-face-2", "narrow match 2", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dirvish-narrow-match-face-3", "narrow match 3", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dirvish-narrow-split", "narrow split", {"fg": null, "bg": null, "source": "default"}], ["dirvish-proc-running", "proc running", {"fg": null, "bg": null, "source": "default"}], ["dirvish-proc-finished", "proc finished", {"fg": null, "bg": null, "source": "default"}], ["dirvish-proc-failed", "proc failed", {"fg": null, "bg": null, "source": "default"}], ["dirvish-git-commit-message-face", "git commit message", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["dirvish-vc-added-state", "vc added state", {"fg": null, "bg": null, "source": "default"}], ["dirvish-vc-edited-state", "vc edited state", {"fg": null, "bg": null, "source": "default"}], ["dirvish-vc-removed-state", "vc removed state", {"fg": null, "bg": null, "source": "default"}], ["dirvish-vc-conflict-state", "vc conflict state", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["dirvish-vc-locked-state", "vc locked state", {"fg": "#67809c", "bg": null, "source": "default"}], ["dirvish-vc-missing-state", "vc missing state", {"fg": null, "bg": null, "source": "default"}], ["dirvish-vc-needs-merge-face", "vc needs merge", {"fg": null, "bg": null, "source": "default"}], ["dirvish-vc-needs-update-state", "vc needs update state", {"fg": null, "bg": null, "source": "default"}], ["dirvish-vc-unregistered-face", "vc unregistered", {"fg": null, "bg": null, "source": "default"}]]}, "calibredb": {"label": "calibredb", "preview": "calibredb", "faces": [["calibredb-search-header-library-name-face", "search header library name", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["calibredb-search-header-library-path-face", "search header library path", {"fg": null, "bg": null, "source": "default"}], ["calibredb-search-header-total-face", "search header total", {"fg": null, "bg": null, "source": "default"}], ["calibredb-search-header-filter-face", "search header filter", {"fg": null, "bg": null, "source": "default"}], ["calibredb-search-header-sort-face", "search header sort", {"fg": "#8a9496", "bg": null, "source": "default"}], ["calibredb-search-header-highlight-face", "search header highlight", {"fg": null, "bg": null, "bold": true, "underline": true, "source": "default"}], ["calibredb-id-face", "id", {"fg": null, "bg": null, "source": "default"}], ["calibredb-title-face", "title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["calibredb-author-face", "author", {"fg": null, "bg": null, "source": "default"}], ["calibredb-format-face", "format", {"fg": "#8a9496", "bg": null, "source": "default"}], ["calibredb-size-face", "size", {"fg": null, "bg": null, "source": "default"}], ["calibredb-tag-face", "tag", {"fg": null, "bg": null, "source": "default"}], ["calibredb-date-face", "date", {"fg": null, "bg": null, "source": "default"}], ["calibredb-mark-face", "mark", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["calibredb-series-face", "series", {"fg": null, "bg": null, "source": "default"}], ["calibredb-publisher-face", "publisher", {"fg": "#8a9496", "bg": null, "source": "default"}], ["calibredb-pubdate-face", "pubdate", {"fg": null, "bg": null, "source": "default"}], ["calibredb-language-face", "language", {"fg": "#8a9496", "bg": null, "source": "default"}], ["calibredb-comment-face", "comment", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["calibredb-archive-face", "archive", {"fg": null, "bg": null, "source": "default"}], ["calibredb-favorite-face", "favorite", {"fg": null, "bg": null, "source": "default"}], ["calibredb-file-face", "file", {"fg": "#67809c", "bg": null, "source": "default"}], ["calibredb-ids-face", "ids", {"fg": null, "bg": null, "source": "default"}], ["calibredb-highlight-face", "highlight", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["calibredb-current-page-button-face", "current page button", {"fg": "#67809c", "bg": null, "bold": true, "height": 1.1, "source": "default"}], ["calibredb-mouse-face", "mouse", {"fg": null, "bg": null, "source": "default"}], ["calibredb-title-detailed-view-face", "title detailed view", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["calibredb-edit-annotation-header-title-face", "edit annotation header title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}]]}, "erc": {"label": "erc", "preview": "erc", "faces": [["erc-header-line", "header line", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-timestamp-face", "timestamp", {"fg": null, "bg": null, "source": "default"}], ["erc-notice-face", "notice", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["erc-default-face", "default", {"fg": "#cdced1", "bg": null, "source": "default"}], ["erc-current-nick-face", "current nick", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-my-nick-face", "my nick", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-my-nick-prefix-face", "my nick prefix", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-nick-default-face", "nick default", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["erc-nick-prefix-face", "nick prefix", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-button-nick-default-face", "button nick default", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["erc-nick-msg-face", "nick msg", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-direct-msg-face", "direct msg", {"fg": null, "bg": null, "source": "default"}], ["erc-action-face", "action", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["erc-keyword-face", "keyword", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-pal-face", "pal", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-fool-face", "fool", {"fg": null, "bg": null, "source": "default"}], ["erc-dangerous-host-face", "dangerous host", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-error-face", "error", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-input-face", "input", {"fg": null, "bg": null, "source": "default"}], ["erc-prompt-face", "prompt", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["erc-command-indicator-face", "command indicator", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["erc-information", "information", {"fg": "#8a9496", "bg": null, "source": "default"}], ["erc-button", "button", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["erc-bold-face", "bold", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["erc-italic-face", "italic", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["erc-underline-face", "underline", {"fg": null, "bg": null, "underline": true, "source": "default"}], ["erc-inverse-face", "inverse", {"fg": "#000000", "bg": null, "source": "default"}], ["erc-spoiler-face", "spoiler", {"fg": "#000000", "bg": null, "source": "default"}], ["erc-fill-wrap-merge-indicator-face", "fill wrap merge indicator", {"fg": null, "bg": null, "source": "default"}], ["erc-keep-place-indicator-arrow", "keep place indicator arrow", {"fg": null, "bg": null, "source": "default"}], ["erc-keep-place-indicator-line", "keep place indicator line", {"fg": null, "bg": null, "source": "default"}]]}, "org-drill": {"label": "org-drill", "preview": "orgdrill", "faces": [["org-drill-hidden-cloze-face", "hidden cloze", {"fg": "#000000", "bg": "#8a9496", "source": "default"}], ["org-drill-visible-cloze-face", "visible cloze", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-drill-visible-cloze-hint-face", "visible cloze hint", {"fg": null, "bg": null, "italic": true, "source": "default"}]]}, "org-noter": {"label": "org-noter", "preview": "orgnoter", "faces": [["org-noter-notes-exist-face", "notes exist", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["org-noter-no-notes-exist-face", "no notes exist", {"fg": null, "bg": null, "bold": true, "source": "default"}]]}, "signel": {"label": "signel", "preview": "signel", "faces": [["signel-timestamp-face", "timestamp", {"fg": null, "bg": null, "source": "default"}], ["signel-my-msg-face", "my msg", {"fg": "#67809c", "bg": null, "source": "default"}], ["signel-other-msg-face", "other msg", {"fg": null, "bg": null, "source": "default"}], ["signel-error-face", "error", {"fg": null, "bg": null, "bold": true, "source": "default"}]]}, "pearl": {"label": "pearl", "preview": "pearl", "faces": [["pearl-preamble-summary", "preamble summary", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["pearl-editable-comment", "editable comment", {"fg": null, "bg": null, "source": "default"}], ["pearl-readonly-comment", "readonly comment", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["pearl-modified-highlight", "modified highlight", {"fg": null, "bg": null, "source": "default"}], ["pearl-modified-local", "modified local", {"fg": null, "bg": null, "source": "default"}], ["pearl-modified-unknown", "modified unknown", {"fg": null, "bg": null, "source": "default"}]]}, "slack": {"label": "slack", "preview": "slack", "faces": [["slack-room-info-title-face", "room info title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["slack-room-info-title-room-name-face", "room info title room name", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-room-info-section-title-face", "room info section title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["slack-room-info-section-label-face", "room info section label", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["slack-room-unread-face", "room unread", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-message-output-header", "message output header", {"fg": "#67809c", "bg": null, "bold": true, "underline": true, "source": "default"}], ["slack-message-output-text", "message output text", {"fg": "#cdced1", "bg": null, "source": "default"}], ["slack-message-output-reaction", "message output reaction", {"fg": "#8a9496", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-message-output-reaction-pressed", "message output reaction pressed", {"fg": null, "bg": null, "bold": true, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-message-deleted-face", "message deleted", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["slack-new-message-marker-face", "new message marker", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-all-thread-buffer-thread-header-face", "all thread buffer thread header", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["slack-message-mention-face", "message mention", {"fg": "#67809c", "bg": null, "source": "default"}], ["slack-message-mention-me-face", "message mention me", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-message-mention-keyword-face", "message mention keyword", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-channel-button-face", "channel button", {"fg": "#67809c", "bg": null, "underline": true, "source": "default"}], ["slack-mrkdwn-bold-face", "mrkdwn bold", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-mrkdwn-italic-face", "mrkdwn italic", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["slack-mrkdwn-code-face", "mrkdwn code", {"fg": null, "bg": null, "source": "default"}], ["slack-mrkdwn-code-block-face", "mrkdwn code block", {"fg": null, "bg": null, "source": "default"}], ["slack-mrkdwn-strike-face", "mrkdwn strike", {"fg": null, "bg": null, "strike": true, "source": "default"}], ["slack-mrkdwn-blockquote-face", "mrkdwn blockquote", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["slack-mrkdwn-list-face", "mrkdwn list", {"fg": null, "bg": null, "source": "default"}], ["slack-attachment-header", "attachment header", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["slack-attachment-footer", "attachment footer", {"fg": null, "bg": null, "source": "default"}], ["slack-attachment-pad", "attachment pad", {"fg": null, "bg": null, "source": "default"}], ["slack-attachment-field-title", "attachment field title", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["slack-message-attachment-preview-header-face", "message attachment preview header", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["slack-preview-face", "preview", {"fg": null, "bg": null, "source": "default"}], ["slack-block-highlight-source-overlay-face", "block highlight source overlay", {"fg": null, "bg": null, "source": "default"}], ["slack-message-action-face", "message action", {"fg": "#67809c", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-message-action-primary-face", "message action primary", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-message-action-danger-face", "message action danger", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-button-block-element-face", "button block element", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-button-primary-block-element-face", "button primary block element", {"fg": null, "bg": null, "bold": true, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-button-danger-block-element-face", "button danger block element", {"fg": null, "bg": null, "bold": true, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-select-block-element-face", "select block element", {"fg": "#67809c", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-overflow-block-element-face", "overflow block element", {"fg": "#8a9496", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-date-picker-block-element-face", "date picker block element", {"fg": "#67809c", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-dialog-title-face", "dialog title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["slack-dialog-element-label-face", "dialog element label", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["slack-dialog-element-hint-face", "dialog element hint", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["slack-dialog-element-placeholder-face", "dialog element placeholder", {"fg": null, "bg": null, "source": "default"}], ["slack-dialog-element-error-face", "dialog element error", {"fg": null, "bg": null, "source": "default"}], ["slack-dialog-submit-button-face", "dialog submit button", {"fg": null, "bg": null, "bold": true, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-dialog-cancel-button-face", "dialog cancel button", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-dialog-select-element-input-face", "dialog select element input", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["slack-user-active-face", "user active", {"fg": null, "bg": null, "source": "default"}], ["slack-user-dnd-face", "user dnd", {"fg": null, "bg": null, "source": "default"}], ["slack-user-profile-header-face", "user profile header", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["slack-user-profile-property-name-face", "user profile property name", {"fg": "#8a9496", "bg": null, "source": "default"}], ["slack-profile-image-face", "profile image", {"fg": null, "bg": null, "source": "default"}], ["slack-search-result-message-header-face", "search result message header", {"fg": "#67809c", "bg": null, "source": "default"}], ["slack-search-result-message-username-face", "search result message username", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-modeline-has-unreads-face", "modeline has unreads", {"fg": null, "bg": null, "source": "default"}], ["slack-modeline-channel-has-unreads-face", "modeline channel has unreads", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["slack-modeline-thread-has-unreads-face", "modeline thread has unreads", {"fg": null, "bg": null, "source": "default"}]]}, "telega": {"label": "telega", "preview": "telega", "faces": [["telega-root-heading", "root heading", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["telega-tracking", "tracking", {"fg": null, "bg": null, "source": "default"}], ["telega-unread-unmuted-modeline", "unread unmuted modeline", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-username", "username", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-user-online-status", "user online status", {"fg": null, "bg": null, "source": "default"}], ["telega-user-non-online-status", "user non online status", {"fg": null, "bg": null, "source": "default"}], ["telega-secret-title", "secret title", {"fg": null, "bg": null, "source": "default"}], ["telega-contact-birthdays-today", "contact birthdays today", {"fg": null, "bg": null, "source": "default"}], ["telega-muted-count", "muted count", {"fg": null, "bg": null, "source": "default"}], ["telega-unmuted-count", "unmuted count", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-mention-count", "mention count", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-has-chatbuf-brackets", "has chatbuf brackets", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-delim-face", "delim", {"fg": null, "bg": null, "source": "default"}], ["telega-shadow", "shadow", {"fg": null, "bg": null, "source": "default"}], ["telega-link", "link", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-blue", "blue", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-red", "red", {"fg": null, "bg": null, "source": "default"}], ["telega-msg-heading", "msg heading", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-msg-user-title", "msg user title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["telega-msg-self-title", "msg self title", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-msg-deleted", "msg deleted", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["telega-msg-sponsored", "msg sponsored", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["telega-msg-inline-reply", "msg inline reply", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-msg-inline-forward", "msg inline forward", {"fg": null, "bg": null, "source": "default"}], ["telega-msg-inline-other", "msg inline other", {"fg": null, "bg": null, "source": "default"}], ["telega-entity-type-bold", "entity type bold", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-entity-type-italic", "entity type italic", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["telega-entity-type-underline", "entity type underline", {"fg": null, "bg": null, "underline": true, "source": "default"}], ["telega-entity-type-strikethrough", "entity type strikethrough", {"fg": null, "bg": null, "strike": true, "source": "default"}], ["telega-entity-type-code", "entity type code", {"fg": null, "bg": null, "source": "default"}], ["telega-entity-type-pre", "entity type pre", {"fg": null, "bg": null, "source": "default"}], ["telega-entity-type-blockquote", "entity type blockquote", {"fg": null, "bg": null, "italic": true, "source": "default"}], ["telega-entity-type-mention", "entity type mention", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-entity-type-hashtag", "entity type hashtag", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-entity-type-cashtag", "entity type cashtag", {"fg": null, "bg": null, "source": "default"}], ["telega-entity-type-botcommand", "entity type botcommand", {"fg": null, "bg": null, "source": "default"}], ["telega-entity-type-texturl", "entity type texturl", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-entity-type-spoiler", "entity type spoiler", {"fg": null, "bg": null, "source": "default"}], ["telega-reaction", "reaction", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-reaction-chosen", "reaction chosen", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-reaction-paid", "reaction paid", {"fg": null, "bg": null, "source": "default"}], ["telega-reaction-paid-chosen", "reaction paid chosen", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-highlight-text-face", "highlight text", {"fg": "#000000", "bg": null, "source": "default"}], ["telega-button-highlight", "button highlight", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-chat-prompt", "chat prompt", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["telega-chat-prompt-aux", "chat prompt aux", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-chat-input-attachment", "chat input attachment", {"fg": null, "bg": null, "source": "default"}], ["telega-topic-button", "topic button", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-filter-active", "filter active", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-filter-button-active", "filter button active", {"fg": "#000000", "bg": null, "source": "default"}], ["telega-filter-button-inactive", "filter button inactive", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-checklist-stats-done", "checklist stats done", {"fg": null, "bg": null, "source": "default"}], ["telega-checklist-stats-todo", "checklist stats todo", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-box-button", "box button", {"fg": "#67809c", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-active", "box button active", {"fg": "#000000", "bg": "#67809c", "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-default-active", "box button default active", {"fg": "#000000", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-default-passive", "box button default passive", {"fg": "#8a9496", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-primary-active", "box button primary active", {"fg": "#000000", "bg": "#67809c", "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-primary-passive", "box button primary passive", {"fg": "#67809c", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-success-active", "box button success active", {"fg": "#000000", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-success-passive", "box button success passive", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-danger-active", "box button danger active", {"fg": "#000000", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-danger-passive", "box button danger passive", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-ui-active", "box button ui active", {"fg": "#000000", "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button-ui-passive", "box button ui passive", {"fg": null, "bg": null, "box": {"style": "released", "width": 1, "color": null}, "source": "default"}], ["telega-box-button2-active", "box button2 active", {"fg": "#000000", "bg": "#67809c", "source": "default"}], ["telega-box-button2-passive", "box button2 passive", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-box-button2-white-foreground", "box button2 white foreground", {"fg": null, "bg": null, "source": "default"}], ["telega-describe-item-title", "describe item title", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["telega-describe-section-title", "describe section title", {"fg": "#67809c", "bg": null, "bold": true, "underline": true, "source": "default"}], ["telega-describe-subsection-title", "describe subsection title", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-enckey-00", "enckey 00", {"fg": null, "bg": null, "source": "default"}], ["telega-enckey-01", "enckey 01", {"fg": null, "bg": null, "source": "default"}], ["telega-enckey-10", "enckey 10", {"fg": null, "bg": null, "source": "default"}], ["telega-enckey-11", "enckey 11", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-palette-builtin-blue", "palette builtin blue", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-palette-builtin-green", "palette builtin green", {"fg": null, "bg": null, "source": "default"}], ["telega-palette-builtin-orange", "palette builtin orange", {"fg": null, "bg": null, "source": "default"}], ["telega-palette-builtin-purple", "palette builtin purple", {"fg": null, "bg": null, "source": "default"}], ["telega-webpage-title", "webpage title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["telega-webpage-subtitle", "webpage subtitle", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-webpage-header", "webpage header", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["telega-webpage-subheader", "webpage subheader", {"fg": null, "bg": null, "source": "default"}], ["telega-webpage-outline", "webpage outline", {"fg": null, "bg": null, "source": "default"}], ["telega-webpage-fixed", "webpage fixed", {"fg": null, "bg": null, "source": "default"}], ["telega-webpage-preformatted", "webpage preformatted", {"fg": null, "bg": null, "source": "default"}], ["telega-webpage-marked", "webpage marked", {"fg": "#000000", "bg": null, "source": "default"}], ["telega-webpage-strike-through", "webpage strike through", {"fg": null, "bg": null, "strike": true, "source": "default"}], ["telega-webpage-chat-link", "webpage chat link", {"fg": "#67809c", "bg": null, "source": "default"}], ["telega-link-preview-sitename", "link preview sitename", {"fg": "#8a9496", "bg": null, "source": "default"}], ["telega-link-preview-title", "link preview title", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}]]}, "shr": {"label": "shr (HTML: nov/eww/mail)", "preview": "shr", "faces": [["shr-h1", "h1", {"fg": null, "bg": null, "bold": true, "height": 1.4, "source": "default"}], ["shr-h2", "h2", {"fg": "#67809c", "bg": null, "bold": true, "height": 1.2, "source": "default"}], ["shr-h3", "h3", {"fg": "#67809c", "bg": null, "bold": true, "source": "default"}], ["shr-h4", "h4", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["shr-h5", "h5", {"fg": "#8a9496", "bg": null, "bold": true, "source": "default"}], ["shr-h6", "h6", {"fg": null, "bg": null, "bold": true, "source": "default"}], ["shr-text", "text", {"fg": "#cdced1", "bg": null, "source": "default"}], ["shr-link", "link", {"fg": "#67809c", "bg": null, "underline": true, "source": "default"}], ["shr-selected-link", "selected link", {"fg": null, "bg": null, "bold": true, "underline": true, "source": "default"}], ["shr-code", "code", {"fg": null, "bg": null, "source": "default"}], ["shr-mark", "mark", {"fg": "#000000", "bg": null, "source": "default"}], ["shr-strike-through", "strike through", {"fg": null, "bg": null, "strike": true, "source": "default"}], ["shr-sup", "sup", {"fg": "#8a9496", "bg": null, "height": 0.8, "source": "default"}], ["shr-abbreviation", "abbreviation", {"fg": "#8a9496", "bg": null, "italic": true, "underline": true, "source": "default"}], ["shr-sliced-image", "sliced image", {"fg": null, "bg": null, "source": "default"}]]}, "2048-game": {"label": "2048-game", "preview": "generic", "faces": [["twentyfortyeight-face-1024", "twentyfortyeight 1024", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-128", "twentyfortyeight 128", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-16", "twentyfortyeight 16", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-2", "twentyfortyeight 2", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-2048", "twentyfortyeight 2048", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-256", "twentyfortyeight 256", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-32", "twentyfortyeight 32", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-4", "twentyfortyeight 4", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-512", "twentyfortyeight 512", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-64", "twentyfortyeight 64", {"fg": null, "bg": null, "source": "default"}], ["twentyfortyeight-face-8", "twentyfortyeight 8", {"fg": null, "bg": null, "source": "default"}]]}, "alert": {"label": "alert", "preview": "generic", "faces": [["alert-high-face", "high", {"fg": null, "bg": null, "source": "default"}], ["alert-low-face", "low", {"fg": null, "bg": null, "source": "default"}], ["alert-moderate-face", "moderate", {"fg": null, "bg": null, "source": "default"}], ["alert-normal-face", "normal", {"fg": null, "bg": null, "source": "default"}], ["alert-trivial-face", "trivial", {"fg": null, "bg": null, "source": "default"}], ["alert-urgent-face", "urgent", {"fg": null, "bg": null, "source": "default"}]]}, "all-the-icons": {"label": "all-the-icons", "preview": "generic", "faces": [["all-the-icons-blue", "blue", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-blue-alt", "blue alt", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-cyan", "cyan", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-cyan-alt", "cyan alt", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dblue", "dblue", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dcyan", "dcyan", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dgreen", "dgreen", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dmaroon", "dmaroon", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dorange", "dorange", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dpink", "dpink", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dpurple", "dpurple", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dred", "dred", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dsilver", "dsilver", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-dyellow", "dyellow", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-green", "green", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lblue", "lblue", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lcyan", "lcyan", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lgreen", "lgreen", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lmaroon", "lmaroon", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lorange", "lorange", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lpink", "lpink", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lpurple", "lpurple", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lred", "lred", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lsilver", "lsilver", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-lyellow", "lyellow", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-maroon", "maroon", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-orange", "orange", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-pink", "pink", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-purple", "purple", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-purple-alt", "purple alt", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-red", "red", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-red-alt", "red alt", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-silver", "silver", {"fg": null, "bg": null, "source": "default"}], ["all-the-icons-yellow", "yellow", {"fg": null, "bg": null, "source": "default"}]]}, "company": {"label": "company", "preview": "generic", "faces": [["company-echo", "echo", {"fg": null, "bg": null, "source": "default"}], ["company-echo-common", "echo common", {"fg": null, "bg": null, "source": "default"}], ["company-preview", "preview", {"fg": null, "bg": null, "source": "default"}], ["company-preview-common", "preview common", {"fg": null, "bg": null, "source": "default"}], ["company-preview-search", "preview search", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip", "tooltip", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-annotation", "tooltip annotation", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-annotation-selection", "tooltip annotation selection", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-common", "tooltip common", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-common-selection", "tooltip common selection", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-deprecated", "tooltip deprecated", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-mouse", "tooltip mouse", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-quick-access", "tooltip quick access", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-quick-access-selection", "tooltip quick access selection", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-scrollbar-thumb", "tooltip scrollbar thumb", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-scrollbar-track", "tooltip scrollbar track", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-search", "tooltip search", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-search-selection", "tooltip search selection", {"fg": null, "bg": null, "source": "default"}], ["company-tooltip-selection", "tooltip selection", {"fg": null, "bg": null, "source": "default"}]]}, "company-box": {"label": "company-box", "preview": "generic", "faces": [["company-box-annotation", "annotation", {"fg": null, "bg": null, "source": "default"}], ["company-box-background", "background", {"fg": null, "bg": null, "source": "default"}], ["company-box-candidate", "candidate", {"fg": null, "bg": null, "source": "default"}], ["company-box-numbers", "numbers", {"fg": null, "bg": null, "source": "default"}], ["company-box-scrollbar", "scrollbar", {"fg": null, "bg": null, "source": "default"}], ["company-box-selection", "selection", {"fg": null, "bg": null, "source": "default"}]]}, "consult": {"label": "consult", "preview": "generic", "faces": [["consult-async-failed", "async failed", {"fg": null, "bg": null, "source": "default"}], ["consult-async-finished", "async finished", {"fg": null, "bg": null, "source": "default"}], ["consult-async-running", "async running", {"fg": null, "bg": null, "source": "default"}], ["consult-async-split", "async split", {"fg": null, "bg": null, "source": "default"}], ["consult-bookmark", "bookmark", {"fg": null, "bg": null, "source": "default"}], ["consult-buffer", "buffer", {"fg": null, "bg": null, "source": "default"}], ["consult-file", "file", {"fg": null, "bg": null, "source": "default"}], ["consult-grep-context", "grep context", {"fg": null, "bg": null, "source": "default"}], ["consult-help", "help", {"fg": null, "bg": null, "source": "default"}], ["consult-highlight-mark", "highlight mark", {"fg": null, "bg": null, "source": "default"}], ["consult-highlight-match", "highlight match", {"fg": null, "bg": null, "source": "default"}], ["consult-key", "key", {"fg": null, "bg": null, "source": "default"}], ["consult-line-number", "line number", {"fg": null, "bg": null, "source": "default"}], ["consult-line-number-prefix", "line number prefix", {"fg": null, "bg": null, "source": "default"}], ["consult-line-number-wrapped", "line number wrapped", {"fg": null, "bg": null, "source": "default"}], ["consult-narrow-indicator", "narrow indicator", {"fg": null, "bg": null, "source": "default"}], ["consult-preview-insertion", "preview insertion", {"fg": null, "bg": null, "source": "default"}], ["consult-preview-line", "preview line", {"fg": null, "bg": null, "source": "default"}], ["consult-preview-match", "preview match", {"fg": null, "bg": null, "source": "default"}], ["consult-separator", "separator", {"fg": null, "bg": null, "source": "default"}]]}, "embark": {"label": "embark", "preview": "generic", "faces": [["embark-collect-annotation", "collect annotation", {"fg": null, "bg": null, "source": "default"}], ["embark-collect-candidate", "collect candidate", {"fg": null, "bg": null, "source": "default"}], ["embark-collect-group-separator", "collect group separator", {"fg": null, "bg": null, "source": "default"}], ["embark-collect-group-title", "collect group title", {"fg": null, "bg": null, "source": "default"}], ["embark-keybinding", "keybinding", {"fg": null, "bg": null, "source": "default"}], ["embark-keybinding-repeat", "keybinding repeat", {"fg": null, "bg": null, "source": "default"}], ["embark-keymap", "keymap", {"fg": null, "bg": null, "source": "default"}], ["embark-selected", "selected", {"fg": null, "bg": null, "source": "default"}], ["embark-target", "target", {"fg": null, "bg": null, "source": "default"}], ["embark-verbose-indicator-documentation", "verbose indicator documentation", {"fg": null, "bg": null, "source": "default"}], ["embark-verbose-indicator-shadowed", "verbose indicator shadowed", {"fg": null, "bg": null, "source": "default"}], ["embark-verbose-indicator-title", "verbose indicator title", {"fg": null, "bg": null, "source": "default"}]]}, "emms": {"label": "emms", "preview": "generic", "faces": [["emms-browser-album-face", "browser album", {"fg": null, "bg": null, "source": "default"}], ["emms-browser-albumartist-face", "browser albumartist", {"fg": null, "bg": null, "source": "default"}], ["emms-browser-artist-face", "browser artist", {"fg": null, "bg": null, "source": "default"}], ["emms-browser-composer-face", "browser composer", {"fg": null, "bg": null, "source": "default"}], ["emms-browser-performer-face", "browser performer", {"fg": null, "bg": null, "source": "default"}], ["emms-browser-track-face", "browser track", {"fg": null, "bg": null, "source": "default"}], ["emms-browser-year/genre-face", "browser year/genre", {"fg": null, "bg": null, "source": "default"}], ["emms-metaplaylist-mode-current-face", "metaplaylist mode current", {"fg": null, "bg": null, "source": "default"}], ["emms-metaplaylist-mode-face", "metaplaylist mode", {"fg": null, "bg": null, "source": "default"}], ["emms-playlist-selected-face", "playlist selected", {"fg": null, "bg": null, "source": "default"}], ["emms-playlist-track-face", "playlist track", {"fg": null, "bg": null, "source": "default"}]]}, "flyspell-correct": {"label": "flyspell-correct", "preview": "generic", "faces": [["flyspell-correct-highlight-face", "highlight", {"fg": null, "bg": null, "source": "default"}]]}, "highlight-indent-guides": {"label": "highlight-indent-guides", "preview": "generic", "faces": [["highlight-indent-guides-character-face", "character", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-even-face", "even", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-odd-face", "odd", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-stack-character-face", "stack character", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-stack-even-face", "stack even", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-stack-odd-face", "stack odd", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-top-character-face", "top character", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-top-even-face", "top even", {"fg": null, "bg": null, "source": "default"}], ["highlight-indent-guides-top-odd-face", "top odd", {"fg": null, "bg": null, "source": "default"}]]}, "hl-todo": {"label": "hl-todo", "preview": "generic", "faces": [["hl-todo", "hl todo", {"fg": null, "bg": null, "source": "default"}], ["hl-todo-flymake-type", "flymake type", {"fg": null, "bg": null, "source": "default"}]]}, "json-mode": {"label": "json-mode", "preview": "generic", "faces": [["json-mode-object-name-face", "object name", {"fg": null, "bg": null, "source": "default"}]]}, "llama": {"label": "llama", "preview": "generic", "faces": [["llama-##-macro", "## macro", {"fg": null, "bg": null, "source": "default"}], ["llama-deleted-argument", "deleted argument", {"fg": null, "bg": null, "source": "default"}], ["llama-llama-macro", "llama macro", {"fg": null, "bg": null, "source": "default"}], ["llama-mandatory-argument", "mandatory argument", {"fg": null, "bg": null, "source": "default"}], ["llama-optional-argument", "optional argument", {"fg": null, "bg": null, "source": "default"}]]}, "lv": {"label": "lv", "preview": "generic", "faces": [["lv-separator", "separator", {"fg": null, "bg": null, "source": "default"}]]}, "magit-section": {"label": "magit-section", "preview": "generic", "faces": [["magit-left-margin", "magit left margin", {"fg": null, "bg": null, "source": "default"}], ["magit-section-child-count", "child count", {"fg": null, "bg": null, "source": "default"}], ["magit-section-heading", "heading", {"fg": null, "bg": null, "source": "default"}], ["magit-section-heading-selection", "heading selection", {"fg": null, "bg": null, "source": "default"}], ["magit-section-highlight", "highlight", {"fg": null, "bg": null, "source": "default"}], ["magit-section-secondary-heading", "secondary heading", {"fg": null, "bg": null, "source": "default"}]]}, "malyon": {"label": "malyon", "preview": "generic", "faces": [["malyon-face-bold", "face bold", {"fg": null, "bg": null, "source": "default"}], ["malyon-face-error", "face error", {"fg": null, "bg": null, "source": "default"}], ["malyon-face-italic", "face italic", {"fg": null, "bg": null, "source": "default"}], ["malyon-face-plain", "face plain", {"fg": null, "bg": null, "source": "default"}], ["malyon-face-reverse", "face reverse", {"fg": null, "bg": null, "source": "default"}]]}, "marginalia": {"label": "marginalia", "preview": "generic", "faces": [["marginalia-archive", "archive", {"fg": null, "bg": null, "source": "default"}], ["marginalia-char", "char", {"fg": null, "bg": null, "source": "default"}], ["marginalia-date", "date", {"fg": null, "bg": null, "source": "default"}], ["marginalia-documentation", "documentation", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-name", "file name", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-owner", "file owner", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-dir", "file priv dir", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-exec", "file priv exec", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-link", "file priv link", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-no", "file priv no", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-other", "file priv other", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-rare", "file priv rare", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-read", "file priv read", {"fg": null, "bg": null, "source": "default"}], ["marginalia-file-priv-write", "file priv write", {"fg": null, "bg": null, "source": "default"}], ["marginalia-function", "function", {"fg": null, "bg": null, "source": "default"}], ["marginalia-installed", "installed", {"fg": null, "bg": null, "source": "default"}], ["marginalia-key", "key", {"fg": null, "bg": null, "source": "default"}], ["marginalia-lighter", "lighter", {"fg": null, "bg": null, "source": "default"}], ["marginalia-list", "list", {"fg": null, "bg": null, "source": "default"}], ["marginalia-mode", "mode", {"fg": null, "bg": null, "source": "default"}], ["marginalia-modified", "modified", {"fg": null, "bg": null, "source": "default"}], ["marginalia-null", "null", {"fg": null, "bg": null, "source": "default"}], ["marginalia-number", "number", {"fg": null, "bg": null, "source": "default"}], ["marginalia-off", "off", {"fg": null, "bg": null, "source": "default"}], ["marginalia-on", "on", {"fg": null, "bg": null, "source": "default"}], ["marginalia-size", "size", {"fg": null, "bg": null, "source": "default"}], ["marginalia-string", "string", {"fg": null, "bg": null, "source": "default"}], ["marginalia-symbol", "symbol", {"fg": null, "bg": null, "source": "default"}], ["marginalia-true", "true", {"fg": null, "bg": null, "source": "default"}], ["marginalia-type", "type", {"fg": null, "bg": null, "source": "default"}], ["marginalia-value", "value", {"fg": null, "bg": null, "source": "default"}], ["marginalia-version", "version", {"fg": null, "bg": null, "source": "default"}]]}, "markdown-mode": {"label": "markdown-mode", "preview": "generic", "faces": [["markdown-blockquote-face", "markdown blockquote", {"fg": null, "bg": null, "source": "default"}], ["markdown-bold-face", "markdown bold", {"fg": null, "bg": null, "source": "default"}], ["markdown-code-face", "markdown code", {"fg": null, "bg": null, "source": "default"}], ["markdown-comment-face", "markdown comment", {"fg": null, "bg": null, "source": "default"}], ["markdown-footnote-marker-face", "markdown footnote marker", {"fg": null, "bg": null, "source": "default"}], ["markdown-footnote-text-face", "markdown footnote text", {"fg": null, "bg": null, "source": "default"}], ["markdown-gfm-checkbox-face", "markdown gfm checkbox", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-delimiter-face", "markdown header delimiter", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-face", "markdown header", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-face-1", "markdown header 1", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-face-2", "markdown header 2", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-face-3", "markdown header 3", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-face-4", "markdown header 4", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-face-5", "markdown header 5", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-face-6", "markdown header 6", {"fg": null, "bg": null, "source": "default"}], ["markdown-header-rule-face", "markdown header rule", {"fg": null, "bg": null, "source": "default"}], ["markdown-highlight-face", "markdown highlight", {"fg": null, "bg": null, "source": "default"}], ["markdown-highlighting-face", "markdown highlighting", {"fg": null, "bg": null, "source": "default"}], ["markdown-hr-face", "markdown hr", {"fg": null, "bg": null, "source": "default"}], ["markdown-html-attr-name-face", "markdown html attr name", {"fg": null, "bg": null, "source": "default"}], ["markdown-html-attr-value-face", "markdown html attr value", {"fg": null, "bg": null, "source": "default"}], ["markdown-html-entity-face", "markdown html entity", {"fg": null, "bg": null, "source": "default"}], ["markdown-html-tag-delimiter-face", "markdown html tag delimiter", {"fg": null, "bg": null, "source": "default"}], ["markdown-html-tag-name-face", "markdown html tag name", {"fg": null, "bg": null, "source": "default"}], ["markdown-inline-code-face", "markdown inline code", {"fg": null, "bg": null, "source": "default"}], ["markdown-italic-face", "markdown italic", {"fg": null, "bg": null, "source": "default"}], ["markdown-language-info-face", "markdown language info", {"fg": null, "bg": null, "source": "default"}], ["markdown-language-keyword-face", "markdown language keyword", {"fg": null, "bg": null, "source": "default"}], ["markdown-line-break-face", "markdown line break", {"fg": null, "bg": null, "source": "default"}], ["markdown-link-face", "markdown link", {"fg": null, "bg": null, "source": "default"}], ["markdown-link-title-face", "markdown link title", {"fg": null, "bg": null, "source": "default"}], ["markdown-list-face", "markdown list", {"fg": null, "bg": null, "source": "default"}], ["markdown-markup-face", "markdown markup", {"fg": null, "bg": null, "source": "default"}], ["markdown-math-face", "markdown math", {"fg": null, "bg": null, "source": "default"}], ["markdown-metadata-key-face", "markdown metadata key", {"fg": null, "bg": null, "source": "default"}], ["markdown-metadata-value-face", "markdown metadata value", {"fg": null, "bg": null, "source": "default"}], ["markdown-missing-link-face", "markdown missing link", {"fg": null, "bg": null, "source": "default"}], ["markdown-plain-url-face", "markdown plain url", {"fg": null, "bg": null, "source": "default"}], ["markdown-pre-face", "markdown pre", {"fg": null, "bg": null, "source": "default"}], ["markdown-reference-face", "markdown reference", {"fg": null, "bg": null, "source": "default"}], ["markdown-strike-through-face", "markdown strike through", {"fg": null, "bg": null, "source": "default"}], ["markdown-table-face", "markdown table", {"fg": null, "bg": null, "source": "default"}], ["markdown-url-face", "markdown url", {"fg": null, "bg": null, "source": "default"}]]}, "nerd-icons": {"label": "nerd-icons", "preview": "generic", "faces": [["nerd-icons-blue", "blue", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-blue-alt", "blue alt", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-cyan", "cyan", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-cyan-alt", "cyan alt", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dblue", "dblue", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dcyan", "dcyan", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dgreen", "dgreen", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dmaroon", "dmaroon", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dorange", "dorange", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dpink", "dpink", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dpurple", "dpurple", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dred", "dred", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dsilver", "dsilver", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-dyellow", "dyellow", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-green", "green", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lblue", "lblue", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lcyan", "lcyan", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lgreen", "lgreen", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lmaroon", "lmaroon", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lorange", "lorange", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lpink", "lpink", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lpurple", "lpurple", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lred", "lred", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lsilver", "lsilver", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-lyellow", "lyellow", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-maroon", "maroon", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-orange", "orange", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-pink", "pink", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-purple", "purple", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-purple-alt", "purple alt", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-red", "red", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-red-alt", "red alt", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-silver", "silver", {"fg": null, "bg": null, "source": "default"}], ["nerd-icons-yellow", "yellow", {"fg": null, "bg": null, "source": "default"}]]}, "nerd-icons-completion": {"label": "nerd-icons-completion", "preview": "generic", "faces": [["nerd-icons-completion-dir-face", "dir", {"fg": null, "bg": null, "source": "default"}]]}, "orderless": {"label": "orderless", "preview": "generic", "faces": [["orderless-match-face-0", "match 0", {"fg": null, "bg": null, "source": "default"}], ["orderless-match-face-1", "match 1", {"fg": null, "bg": null, "source": "default"}], ["orderless-match-face-2", "match 2", {"fg": null, "bg": null, "source": "default"}], ["orderless-match-face-3", "match 3", {"fg": null, "bg": null, "source": "default"}]]}, "org-roam": {"label": "org-roam", "preview": "generic", "faces": [["org-roam-dailies-calendar-note", "dailies calendar note", {"fg": null, "bg": null, "source": "default"}], ["org-roam-dim", "dim", {"fg": null, "bg": null, "source": "default"}], ["org-roam-header-line", "header line", {"fg": null, "bg": null, "source": "default"}], ["org-roam-olp", "olp", {"fg": null, "bg": null, "source": "default"}], ["org-roam-preview-heading", "preview heading", {"fg": null, "bg": null, "source": "default"}], ["org-roam-preview-heading-highlight", "preview heading highlight", {"fg": null, "bg": null, "source": "default"}], ["org-roam-preview-heading-selection", "preview heading selection", {"fg": null, "bg": null, "source": "default"}], ["org-roam-preview-region", "preview region", {"fg": null, "bg": null, "source": "default"}], ["org-roam-title", "title", {"fg": null, "bg": null, "source": "default"}]]}, "org-superstar": {"label": "org-superstar", "preview": "generic", "faces": [["org-superstar-first", "first", {"fg": null, "bg": null, "source": "default"}], ["org-superstar-header-bullet", "header bullet", {"fg": null, "bg": null, "source": "default"}], ["org-superstar-item", "item", {"fg": null, "bg": null, "source": "default"}], ["org-superstar-leading", "leading", {"fg": null, "bg": null, "source": "default"}]]}, "prescient": {"label": "prescient", "preview": "generic", "faces": [["prescient-primary-highlight", "primary highlight", {"fg": null, "bg": null, "source": "default"}], ["prescient-secondary-highlight", "secondary highlight", {"fg": null, "bg": null, "source": "default"}]]}, "rainbow-delimiters": {"label": "rainbow-delimiters", "preview": "generic", "faces": [["rainbow-delimiters-base-error-face", "base error", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-base-face", "base", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-1-face", "depth 1", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-2-face", "depth 2", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-3-face", "depth 3", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-4-face", "depth 4", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-5-face", "depth 5", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-6-face", "depth 6", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-7-face", "depth 7", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-8-face", "depth 8", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-depth-9-face", "depth 9", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-mismatched-face", "mismatched", {"fg": null, "bg": null, "source": "default"}], ["rainbow-delimiters-unmatched-face", "unmatched", {"fg": null, "bg": null, "source": "default"}]]}, "symbol-overlay": {"label": "symbol-overlay", "preview": "generic", "faces": [["symbol-overlay-default-face", "default", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-1", "face 1", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-2", "face 2", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-3", "face 3", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-4", "face 4", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-5", "face 5", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-6", "face 6", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-7", "face 7", {"fg": null, "bg": null, "source": "default"}], ["symbol-overlay-face-8", "face 8", {"fg": null, "bg": null, "source": "default"}]]}, "tmr": {"label": "tmr", "preview": "generic", "faces": [["tmr-description", "description", {"fg": null, "bg": null, "source": "default"}], ["tmr-duration", "duration", {"fg": null, "bg": null, "source": "default"}], ["tmr-end-time", "end time", {"fg": null, "bg": null, "source": "default"}], ["tmr-finished", "finished", {"fg": null, "bg": null, "source": "default"}], ["tmr-is-acknowledged", "is acknowledged", {"fg": null, "bg": null, "source": "default"}], ["tmr-must-be-acknowledged", "must be acknowledged", {"fg": null, "bg": null, "source": "default"}], ["tmr-start-time", "start time", {"fg": null, "bg": null, "source": "default"}], ["tmr-tabulated-acknowledgement", "tabulated acknowledgement", {"fg": null, "bg": null, "source": "default"}], ["tmr-tabulated-description", "tabulated description", {"fg": null, "bg": null, "source": "default"}], ["tmr-tabulated-end-time", "tabulated end time", {"fg": null, "bg": null, "source": "default"}], ["tmr-tabulated-remaining-time", "tabulated remaining time", {"fg": null, "bg": null, "source": "default"}], ["tmr-tabulated-start-time", "tabulated start time", {"fg": null, "bg": null, "source": "default"}]]}, "transient": {"label": "transient", "preview": "generic", "faces": [["transient-active-infix", "active infix", {"fg": null, "bg": null, "source": "default"}], ["transient-argument", "argument", {"fg": null, "bg": null, "source": "default"}], ["transient-delimiter", "delimiter", {"fg": null, "bg": null, "source": "default"}], ["transient-disabled-suffix", "disabled suffix", {"fg": null, "bg": null, "source": "default"}], ["transient-enabled-suffix", "enabled suffix", {"fg": null, "bg": null, "source": "default"}], ["transient-heading", "heading", {"fg": null, "bg": null, "source": "default"}], ["transient-higher-level", "higher level", {"fg": null, "bg": null, "source": "default"}], ["transient-inactive-argument", "inactive argument", {"fg": null, "bg": null, "source": "default"}], ["transient-inactive-value", "inactive value", {"fg": null, "bg": null, "source": "default"}], ["transient-inapt-argument", "inapt argument", {"fg": null, "bg": null, "source": "default"}], ["transient-inapt-suffix", "inapt suffix", {"fg": null, "bg": null, "source": "default"}], ["transient-key", "key", {"fg": null, "bg": null, "source": "default"}], ["transient-key-exit", "key exit", {"fg": null, "bg": null, "source": "default"}], ["transient-key-noop", "key noop", {"fg": null, "bg": null, "source": "default"}], ["transient-key-recurse", "key recurse", {"fg": null, "bg": null, "source": "default"}], ["transient-key-return", "key return", {"fg": null, "bg": null, "source": "default"}], ["transient-key-stack", "key stack", {"fg": null, "bg": null, "source": "default"}], ["transient-key-stay", "key stay", {"fg": null, "bg": null, "source": "default"}], ["transient-mismatched-key", "mismatched key", {"fg": null, "bg": null, "source": "default"}], ["transient-nonstandard-key", "nonstandard key", {"fg": null, "bg": null, "source": "default"}], ["transient-unreachable", "unreachable", {"fg": null, "bg": null, "source": "default"}], ["transient-unreachable-key", "unreachable key", {"fg": null, "bg": null, "source": "default"}], ["transient-value", "value", {"fg": null, "bg": null, "source": "default"}]]}, "vertico": {"label": "vertico", "preview": "generic", "faces": [["vertico-current", "current", {"fg": null, "bg": null, "source": "default"}], ["vertico-group-separator", "group separator", {"fg": null, "bg": null, "source": "default"}], ["vertico-group-title", "group title", {"fg": null, "bg": null, "source": "default"}], ["vertico-multiline", "multiline", {"fg": null, "bg": null, "source": "default"}]]}, "web-mode": {"label": "web-mode", "preview": "generic", "faces": [["web-mode-annotation-face", "annotation", {"fg": null, "bg": null, "source": "default"}], ["web-mode-annotation-html-face", "annotation html", {"fg": null, "bg": null, "source": "default"}], ["web-mode-annotation-tag-face", "annotation tag", {"fg": null, "bg": null, "source": "default"}], ["web-mode-annotation-type-face", "annotation type", {"fg": null, "bg": null, "source": "default"}], ["web-mode-annotation-value-face", "annotation value", {"fg": null, "bg": null, "source": "default"}], ["web-mode-block-attr-name-face", "block attr name", {"fg": null, "bg": null, "source": "default"}], ["web-mode-block-attr-value-face", "block attr value", {"fg": null, "bg": null, "source": "default"}], ["web-mode-block-comment-face", "block comment", {"fg": null, "bg": null, "source": "default"}], ["web-mode-block-control-face", "block control", {"fg": null, "bg": null, "source": "default"}], ["web-mode-block-delimiter-face", "block delimiter", {"fg": null, "bg": null, "source": "default"}], ["web-mode-block-face", "block", {"fg": null, "bg": null, "source": "default"}], ["web-mode-block-string-face", "block string", {"fg": null, "bg": null, "source": "default"}], ["web-mode-bold-face", "bold", {"fg": null, "bg": null, "source": "default"}], ["web-mode-builtin-face", "builtin", {"fg": null, "bg": null, "source": "default"}], ["web-mode-comment-face", "comment", {"fg": null, "bg": null, "source": "default"}], ["web-mode-comment-keyword-face", "comment keyword", {"fg": null, "bg": null, "source": "default"}], ["web-mode-constant-face", "constant", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-at-rule-face", "css at rule", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-color-face", "css color", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-comment-face", "css comment", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-function-face", "css function", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-priority-face", "css priority", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-property-name-face", "css property name", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-pseudo-class-face", "css pseudo class", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-selector-class-face", "css selector class", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-selector-face", "css selector", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-selector-tag-face", "css selector tag", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-string-face", "css string", {"fg": null, "bg": null, "source": "default"}], ["web-mode-css-variable-face", "css variable", {"fg": null, "bg": null, "source": "default"}], ["web-mode-current-column-highlight-face", "current column highlight", {"fg": null, "bg": null, "source": "default"}], ["web-mode-current-element-highlight-face", "current element highlight", {"fg": null, "bg": null, "source": "default"}], ["web-mode-doctype-face", "doctype", {"fg": null, "bg": null, "source": "default"}], ["web-mode-error-face", "error", {"fg": null, "bg": null, "source": "default"}], ["web-mode-filter-face", "filter", {"fg": null, "bg": null, "source": "default"}], ["web-mode-folded-face", "folded", {"fg": null, "bg": null, "source": "default"}], ["web-mode-function-call-face", "function call", {"fg": null, "bg": null, "source": "default"}], ["web-mode-function-name-face", "function name", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-attr-custom-face", "html attr custom", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-attr-engine-face", "html attr engine", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-attr-equal-face", "html attr equal", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-attr-name-face", "html attr name", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-attr-value-face", "html attr value", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-entity-face", "html entity", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-tag-bracket-face", "html tag bracket", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-tag-custom-face", "html tag custom", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-tag-face", "html tag", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-tag-namespaced-face", "html tag namespaced", {"fg": null, "bg": null, "source": "default"}], ["web-mode-html-tag-unclosed-face", "html tag unclosed", {"fg": null, "bg": null, "source": "default"}], ["web-mode-inlay-face", "inlay", {"fg": null, "bg": null, "source": "default"}], ["web-mode-interpolate-color1-face", "interpolate color1", {"fg": null, "bg": null, "source": "default"}], ["web-mode-interpolate-color2-face", "interpolate color2", {"fg": null, "bg": null, "source": "default"}], ["web-mode-interpolate-color3-face", "interpolate color3", {"fg": null, "bg": null, "source": "default"}], ["web-mode-interpolate-color4-face", "interpolate color4", {"fg": null, "bg": null, "source": "default"}], ["web-mode-italic-face", "italic", {"fg": null, "bg": null, "source": "default"}], ["web-mode-javascript-comment-face", "javascript comment", {"fg": null, "bg": null, "source": "default"}], ["web-mode-javascript-string-face", "javascript string", {"fg": null, "bg": null, "source": "default"}], ["web-mode-json-comment-face", "json comment", {"fg": null, "bg": null, "source": "default"}], ["web-mode-json-context-face", "json context", {"fg": null, "bg": null, "source": "default"}], ["web-mode-json-key-face", "json key", {"fg": null, "bg": null, "source": "default"}], ["web-mode-json-string-face", "json string", {"fg": null, "bg": null, "source": "default"}], ["web-mode-jsx-depth-1-face", "jsx depth 1", {"fg": null, "bg": null, "source": "default"}], ["web-mode-jsx-depth-2-face", "jsx depth 2", {"fg": null, "bg": null, "source": "default"}], ["web-mode-jsx-depth-3-face", "jsx depth 3", {"fg": null, "bg": null, "source": "default"}], ["web-mode-jsx-depth-4-face", "jsx depth 4", {"fg": null, "bg": null, "source": "default"}], ["web-mode-jsx-depth-5-face", "jsx depth 5", {"fg": null, "bg": null, "source": "default"}], ["web-mode-keyword-face", "keyword", {"fg": null, "bg": null, "source": "default"}], ["web-mode-param-name-face", "param name", {"fg": null, "bg": null, "source": "default"}], ["web-mode-part-comment-face", "part comment", {"fg": null, "bg": null, "source": "default"}], ["web-mode-part-face", "part", {"fg": null, "bg": null, "source": "default"}], ["web-mode-part-string-face", "part string", {"fg": null, "bg": null, "source": "default"}], ["web-mode-preprocessor-face", "preprocessor", {"fg": null, "bg": null, "source": "default"}], ["web-mode-script-face", "script", {"fg": null, "bg": null, "source": "default"}], ["web-mode-sql-keyword-face", "sql keyword", {"fg": null, "bg": null, "source": "default"}], ["web-mode-string-face", "string", {"fg": null, "bg": null, "source": "default"}], ["web-mode-style-face", "style", {"fg": null, "bg": null, "source": "default"}], ["web-mode-symbol-face", "symbol", {"fg": null, "bg": null, "source": "default"}], ["web-mode-type-face", "type", {"fg": null, "bg": null, "source": "default"}], ["web-mode-underline-face", "underline", {"fg": null, "bg": null, "source": "default"}], ["web-mode-variable-name-face", "variable name", {"fg": null, "bg": null, "source": "default"}], ["web-mode-warning-face", "warning", {"fg": null, "bg": null, "source": "default"}], ["web-mode-whitespace-face", "whitespace", {"fg": null, "bg": null, "source": "default"}]]}, "yasnippet": {"label": "yasnippet", "preview": "generic", "faces": [["yas--field-debug-face", "yas field debug", {"fg": null, "bg": null, "source": "default"}], ["yas-field-highlight-face", "yas field highlight", {"fg": null, "bg": null, "source": "default"}]]}};
+let MAP={"kw": "#67809c", "bi": "#d7af5f", "pp": "#acb0b3", "fnd": "#d47c59", "fnc": "", "dec": "", "ty": "#a4ac64", "prop": "", "con": "#d7af5f", "num": "#d7af5f", "esc": "", "str": "#a4ac64", "re": "", "doc": "#969385", "cm": "#969385", "cmd": "#969385", "var": "#b2c3cc", "op": "", "punc": "", "p": "#f0fef0", "bg": "#000000"}, PALETTE=[["#f0fef0", "fg"], ["#000000", "bg"], ["#151311", "bg+0"], ["#252321", "bg+1"], ["#474544", "bg+2"], ["#58574e", "gray-2"], ["#6c6a60", "gray-1"], ["#969385", "gray"], ["#b4b1a2", "gray+1"], ["#d0cbc0", "gray+2"], ["#8a9496", "steel"], ["#acb0b3", "steel+1"], ["#c0c7ca", "steel+2"], ["#67809c", "blue"], ["#b2c3cc", "blue+1"], ["#d9e2ff", "blue+2"], ["#646d14", "green-2"], ["#869038", "green-1"], ["#a4ac64", "green"], ["#ccc768", "green+1"], ["#3f1c0f", "red-3"], ["#7c2a09", "red-2"], ["#a7502d", "red-1"], ["#d47c59", "red"], ["#edb08f", "red+1"], ["#edbca2", "red+2"], ["#875f00", "yellow-2"], ["#8e784c", "yellow-1"], ["#d7af5f", "yellow"], ["#ffd75f", "yellow+1"], ["#f9ee98", "yellow+2"], ["#ff2a00", "intense-red"]], BOLD={"kw": true, "bi": true, "pp": true, "fnd": true, "fnc": false, "dec": false, "ty": true, "prop": false, "con": true, "num": false, "esc": false, "str": false, "re": false, "doc": false, "cm": false, "cmd": false, "var": false, "op": false, "punc": false, "p": false}, ITALIC={"pp": true, "cm": true, "var": true, "cmd": true}, UIMAP={"cursor": {"fg": null, "bg": "#f0fef0"}, "region": {"fg": null, "bg": "#474544"}, "hl-line": {"fg": null, "bg": "#151311"}, "highlight": {"fg": null, "bg": "#646d14"}, "mode-line": {"fg": "#000000", "bg": "#67809c", "box": {"style": "released", "width": 1, "color": null}}, "mode-line-inactive": {"fg": "#67809c", "bg": "#000000", "box": {"style": "released", "width": 1, "color": null}}, "fringe": {"fg": "#58574e", "bg": "#151311"}, "line-number": {"fg": "#58574e", "bg": null}, "line-number-current-line": {"fg": "#d7af5f", "bg": null}, "minibuffer-prompt": {"fg": "#d7af5f", "bg": null}, "isearch": {"fg": null, "bg": null}, "lazy-highlight": {"fg": null, "bg": "#8e784c", "underline": true}, "isearch-fail": {"fg": "#f0fef0", "bg": "#a7502d"}, "show-paren-match": {"fg": "#000000", "bg": "#a4ac64", "underline": true}, "show-paren-mismatch": {"fg": "#f0fef0", "bg": "#a7502d"}, "link": {"fg": "#b2c3cc", "bg": null, "underline": true}, "error": {"fg": "#d47c59", "bg": null, "bold": true}, "warning": {"fg": "#ffd75f", "bg": null, "bold": true}, "success": {"fg": "#a4ac64", "bg": null, "bold": true}, "vertical-border": {"fg": "#58574e", "bg": null}};
+let LOCKED=new Set(["kw", "bg", "p", "bi", "pp", "fnd", "ty", "con", "str", "var", "cm", "doc", "cmd", "num", "ui:mode-line", "ui:mode-line-inactive", "ui:link", "ui:hl-line", "ui:warning", "ui:success", "ui:error", "ui:line-number-current-line", "ui:minibuffer-prompt", "ui:show-paren-mismatch", "ui:show-paren-match", "ui:vertical-border", "ui:line-number", "ui:fringe", "ui:region"]); // syntax categories whose element↔color is decided (dropdown disabled, skipped by clear-unlocked)
const DELTAE_MIN=0.02; // OKLab ΔE below this = colors too close to tell apart (perceptual-metrics spec)
// --- tier-3 package faces: pure state helpers (Phase 1) ---
// Thin wrappers over the pure logic in app-core.js (inlined further down),
@@ -378,6 +383,33 @@ function paletteWarnings(palette, threshold = 0.02, cap = 5) {
pairs.sort((a, b) => a.dE - b.dE);
return { warnings: pairs.slice(0, cap), overflow: Math.max(0, pairs.length - cap), nearest };
}
+
+// --- 3D-box relief colors, matching Emacs's renderer ---------------------
+// Port of x_alloc_lighter_color (Emacs 30 xterm.c): highlight = bg x 1.2
+// (delta 0x8000), shadow = bg x 0.6 (delta 0x4000), both in 16-bit channel
+// space. Backgrounds dimmer than 48000/65535 (by Emacs's 2R+3G+B/6 weighting)
+// get an additive boost of delta*dimness*factor/2, because scaling alone
+// barely moves a dark color. When the result still equals the background
+// (pure black shadow, pure white highlight), Emacs retries with bg+delta.
+function reliefColors(bgHex) {
+ const rgb = hex2rgb(bgHex);
+ if (rgb.some((c) => Number.isNaN(c))) return { hl: null, sh: null };
+ const ch16 = rgb.map((c) => c * 257);
+ const one = (factor, delta) => {
+ let nw = ch16.map((c) => Math.min(0xffff, factor * c));
+ const bright = (2 * ch16[0] + 3 * ch16[1] + ch16[2]) / 6;
+ if (bright < 48000) {
+ const md = delta * (1 - bright / 48000) * factor / 2;
+ nw = factor < 1
+ ? nw.map((v) => Math.max(0, v - md))
+ : nw.map((v) => Math.min(0xffff, v + md));
+ }
+ if (nw.every((v, i) => Math.round(v) === ch16[i]))
+ nw = ch16.map((c) => Math.min(0xffff, c + delta));
+ return '#' + nw.map((v) => Math.round(v / 257).toString(16).padStart(2, '0')).join('');
+ };
+ return { hl: one(1.2, 0x8000), sh: one(0.6, 0x4000) };
+}
// Pure package-model + dropdown logic, inlined verbatim from app-core.js. The
// wrappers above (pname/seedPkgmap/ddList/pkgEffFg/pkgEffBg) delegate here.
// Pure app logic — the package-face model and the dropdown option list — with no
@@ -386,6 +418,10 @@ function paletteWarnings(palette, threshold = 0.02, cap = 5) {
// the browser runs the same code the tests import. The app.js wrappers (pname,
// seedPkgmap, ddList, pkgEffFg, pkgEffBg) are thin delegators that pass the
// live PALETTE / APPS / PKGMAP into these.
+//
+// The imports below are for the Node tests; generate.py strips them on inline,
+// where normHex (app-util.js) and the colormath helpers are already present from
+// the bodies inlined above this one.
// Resolve a palette name (or a raw #hex) to a hex; null when the name is unknown.
function nameToHex(n,palette){if(!n)return null;if(/^#/.test(n))return n;const p=palette.find(p=>p[1]===n);return p?p[0]:null;}
@@ -410,6 +446,223 @@ function optList(cur,palette){const have=cur===''||palette.some(p=>p[0]===cur);r
// Turn a theme name into a safe filename slug: collapse runs of disallowed
// characters to a single dash, trim leading/trailing dashes, fall back to 'theme'.
function slugify(name){return name.replace(/[^A-Za-z0-9._-]+/g,'-').replace(/^-+|-+$/g,'')||'theme';}
+
+// Generate a tonal ramp from one base color: 2n steps at offsets -n..-1 and
+// +1..+n (the base itself is excluded — it already lives in the palette),
+// ordered darkest -> lightest. Holds the OKLCH hue, steps lightness by stepL per
+// stop, and eases chroma toward the extremes (quadratic in |offset|/n, so only
+// the farthest step loses most of its color). Every step is gamut-clamped and
+// carries its own clamped flag. Returns {steps:[{hex,clamped,offset}], adjusted}
+// where adjusted names any knob clamped/rounded into range, or {steps:[],
+// error:'bad-hex'} for an unparseable base. Pure — opts are clamped, never thrown.
+function ramp(baseHex,opts){
+ const hex=typeof baseHex==='string'?normHex(baseHex):null;
+ if(!hex)return {steps:[],error:'bad-hex'};
+ const o=opts||{},adjusted=[];
+ const knob=(name,def,lo,hi,isInt)=>{
+ const v=o[name];
+ if(typeof v!=='number'||!isFinite(v))return def;
+ const r=isInt?Math.round(v):v,c=Math.min(hi,Math.max(lo,r));
+ if(c!==v)adjusted.push(name);
+ return c;
+ };
+ const n=knob('n',2,1,4,true),stepL=knob('stepL',0.08,0.04,0.12,false),chromaEase=knob('chromaEase',0.5,0,1,false);
+ const {L:L0,C:C0,H:H0}=oklab2oklch(srgb2oklab(hex));
+ const steps=[];
+ for(let off=-n;off<=n;off++){
+ if(off===0)continue;
+ const L=Math.min(1,Math.max(0,L0+off*stepL));
+ const t=Math.abs(off)/n,C=C0*(1-chromaEase*t*t);
+ const {hex:h,clamped}=oklch2hex(L,C,H0);
+ steps.push({hex:h,clamped,offset:off});
+ }
+ return {steps,adjusted};
+}
+
+// --- background-contrast safety (palette-ramps spec, Phase 3) ----------------
+// An overlay background sits behind many foregrounds at once, so its real
+// constraint is the worst-case contrast over the whole set, not one fg/bg pair.
+
+// The closed v1 set of code-overlay faces whose worst-case floor we compute.
+// Other overlay faces (secondary-selection, isearch-fail, ...) are vNext, added
+// explicitly rather than by a heuristic. Shared by app.js and the tests.
+const COVERED_FACES=['region','hl-line','highlight','lazy-highlight','isearch'];
+
+// A covered face's foreground set: the distinct syntax-token colors plus the
+// default foreground, each labeled (syntax role preferred, else 'default').
+// state = {covered:[face], syntaxAssignments:[{role,hex}], defaultFg}. Returns
+// {set:[{hex,label}]}, or {set:[],reason} where reason is 'out-of-scope' (the
+// face isn't in the covered set) or 'empty' (no syntax assignments constrain it).
+function fgSetFor(face,state){
+ const covered=(state&&state.covered)||COVERED_FACES;
+ if(!covered.includes(face))return {set:[],reason:'out-of-scope'};
+ const syn=((state&&state.syntaxAssignments)||[]).filter(a=>a&&a.hex);
+ if(!syn.length)return {set:[],reason:'empty'};
+ const byHex=new Map();
+ const add=(hex,label,isRole)=>{const k=hex.toLowerCase(),cur=byHex.get(k);if(!cur)byHex.set(k,{hex:k,label});else if(isRole&&cur.label==='default')cur.label=label;};
+ if(state&&state.defaultFg)add(state.defaultFg,'default',false);
+ for(const a of syn)add(a.hex,a.role||a.hex,true);
+ return {set:[...byHex.values()]};
+}
+
+// Worst-case (minimum) WCAG contrast of a background against a foreground set,
+// with the limiting foreground's hex and label. fgSet is fgSetFor's set. An empty
+// set returns nulls so the caller can show the no-set readout instead of a floor.
+function floor(bgHex,fgSet){
+ if(!fgSet||!fgSet.length)return {ratio:null,limitingHex:null,limitingLabel:null};
+ let best=Infinity,lh=null,ll=null;
+ for(const f of fgSet){const r=contrast(f.hex,bgHex);if(r<best){best=r;lh=f.hex;ll=f.label;}}
+ return {ratio:best,limitingHex:lh,limitingLabel:ll};
+}
+
+// The lightest background at (hue, chroma) whose worst-case floor over fgSet still
+// clears target (a WCAG ratio). Scans L up from black to bracket the first
+// dark-side crossing, then binary-searches it to tol 0.001. status:
+// 'ok' - a ceiling L was found
+// 'none' - even pure black fails (a foreground is too dark for the target)
+// 'all' - no foreground set to constrain (vacuously safe everywhere)
+// 'clamp' - the ceiling L can't hold the requested chroma (gamut-clamped there)
+function lMax(hue,chroma,fgSet,target){
+ if(!fgSet||!fgSet.length)return {L:1,status:'all'};
+ const at=(L)=>{const {hex,clamped}=oklch2hex(L,chroma,hue);return {r:floor(hex,fgSet).ratio,clamped};};
+ if(at(0).r<target)return {L:null,status:'none'};
+ let loL=0,hiL=null;
+ for(let L=0.01;L<=1+1e-9;L+=0.01){const c=Math.min(L,1);if(at(c).r<target){hiL=c;break;}loL=c;}
+ if(hiL===null)return {L:1,status:'all'};
+ for(let i=0;i<20;i++){const mid=(loL+hiL)/2;if(at(mid).r>=target)loL=mid;else hiL=mid;}
+ return {L:loL,status:at(loL).clamped?'clamp':'ok'};
+}
+
+// --- color families (color-families spec, Phase 1) ---------------------------
+// Families are a display grouping derived from the hex every render — never from
+// names — so renaming a color can't move it. The flat palette stays the editable
+// truth; these pure functions group it, regenerate a family's ramp, and plan the
+// assignment re-point across a regenerate.
+
+function oklchOf(hex){return oklab2oklch(srgb2oklab(hex));}
+function nameOfHex(palette,hex){const p=palette.find(p=>p[0].toLowerCase()===hex.toLowerCase());return p?p[1]:null;}
+function hueDist(a,b){const d=Math.abs(a-b);return Math.min(d,360-d);}
+
+// A color reads as neutral below this chroma. Lightness-scaled (the Munsell
+// insight): the mid-tones need more chroma to read as a hue. Floored at both ends
+// rather than tapering to zero, so pale warm grays stay neutral (and pure white,
+// C=0 at L=1, doesn't evade a zero threshold) while pale chromatic tints stay
+// colored. Tuned on real palettes (Codex + Fable color-sorting reviews).
+function neutralThreshold(L){
+ if(L<=0.2)return 0.020;
+ if(L<0.6)return 0.020+0.015*(L-0.2)/0.4;
+ if(L<0.85)return 0.035-0.017*(L-0.6)/0.25;
+ return 0.018;
+}
+// Lightness-conditioned compatibility of two chromatic colors (Fable's LCCL):
+// hue must match tightly at equal lightness and may drift across a lightness gap,
+// because a tonal ramp drifts in hue with lightness by design. The low-chroma noise
+// term widens the hue tolerance where hue is ill-defined (pale tints). A chroma
+// clause keeps a vivid accent out of a soft family at the same lightness. <=1 is
+// compatible. Source: ~/color-sorting-fable.org.
+function pairRatio(a,b){
+ const dL=Math.abs(a.L-b.L),dH=hueDist(a.H,b.H);
+ const noise=Math.min(45,Math.atan(0.015/Math.max(Math.min(a.C,b.C),1e-6))*180/Math.PI);
+ return Math.max(dH/(12+60*dL+noise),Math.abs(a.C-b.C)/(0.08+0.3*dL));
+}
+// Complete-linkage agglomerative clustering on pairRatio: greedily merge the two
+// clusters whose worst cross-pair is most compatible, stopping when no merge has
+// every cross-pair compatible. Complete linkage makes single-linkage chaining
+// structurally impossible — two ramps can't fuse through their converging pale
+// ends because their mid-lightness members stay far apart.
+function clusterChromatic(ms){
+ let cl=ms.map(m=>[m]);
+ const cd=(A,B)=>Math.max(...A.flatMap(a=>B.map(b=>pairRatio(a,b))));
+ for(;;){
+ let best=null;
+ for(let i=0;i<cl.length;i++)for(let j=i+1;j<cl.length;j++){const d=cd(cl[i],cl[j]);if(!best||d<best.d)best={d,i,j};}
+ if(!best||best.d>1)break;
+ cl[best.i]=cl[best.i].concat(cl[best.j]);cl.splice(best.j,1);
+ }
+ return cl;
+}
+// A family from its members: base is the most-saturated member (tie toward
+// mid-lightness), the anchor for a generated ramp.
+function makeFamily(ms,neutral){
+ let base=ms[0];
+ for(const m of ms)if(m.C>base.C||(m.C===base.C&&Math.abs(m.L-0.5)<Math.abs(base.L-0.5)))base=m;
+ return {base:base.hex,neutral:!!neutral,members:ms.map(m=>({hex:m.hex,name:m.name}))};
+}
+// Group a flat palette into the ground strip plus families. ground is {bg,fg}:
+// those two hexes form the pinned ground strip even when absent from the palette,
+// and a palette chip at a ground hex is not duplicated into a family. Near-neutrals
+// (chroma below the lightness-scaled threshold) form one neutral family; the rest
+// cluster by lightness-conditioned complete linkage (clusterChromatic).
+function familiesFromPalette(palette,ground){
+ const bg=ground&&ground.bg,fg=ground&&ground.fg;
+ const gset=new Set([bg,fg].filter(Boolean).map(h=>h.toLowerCase()));
+ const groundStrip=[];
+ if(bg)groundStrip.push({hex:bg,role:'bg',name:nameOfHex(palette,bg)});
+ if(fg)groundStrip.push({hex:fg,role:'fg',name:nameOfHex(palette,fg)});
+ const neutrals=[],chromatic=[];
+ for(const [hex,name] of palette){
+ if(gset.has(hex.toLowerCase()))continue;
+ const c=oklchOf(hex),m={hex,name,L:c.L,C:c.C,H:c.H};
+ (c.C<neutralThreshold(c.L)?neutrals:chromatic).push(m);
+ }
+ const families=[];
+ if(neutrals.length)families.push(makeFamily(neutrals,true));
+ for(const cl of clusterChromatic(chromatic))families.push(makeFamily(cl,false));
+ return {ground:groundStrip,families};
+}
+// Regenerate a family's members as a symmetric ramp around the base: n=0 is the
+// base alone (without ramp()'s 1-4 clamp), n>=1 is base plus ramp() steps, sorted
+// by offset. {members:[{hex,offset,clamped}]} or {members:[],error:'bad-hex'}.
+function regenFamily(baseHex,n,opts){
+ const hex=typeof baseHex==='string'?normHex(baseHex):null;
+ if(!hex)return {members:[],error:'bad-hex'};
+ const k=Math.min(4,Math.max(0,Math.round(n||0)));
+ if(k===0)return {members:[{hex,offset:0,clamped:false}]};
+ const r=ramp(hex,Object.assign({},opts,{n:k}));
+ if(r.error)return {members:[],error:r.error};
+ const members=[...r.steps,{hex,offset:0,clamped:false}].sort((a,b)=>a.offset-b.offset);
+ return {members};
+}
+// Rank a family's current member hexes by lightness and give each a signed offset
+// from the base (the matching hex, or the nearest by lightness if the base isn't
+// present). Lets a regenerate match old positions to new ramp offsets.
+function rankByLightness(memberHexes,baseHex){
+ const items=memberHexes.map(h=>({hex:h,L:oklchOf(h).L})).sort((a,b)=>a.L-b.L);
+ let bi=items.findIndex(m=>m.hex.toLowerCase()===(baseHex||'').toLowerCase());
+ if(bi<0){const bl=oklchOf(baseHex).L;let best=Infinity;items.forEach((m,i)=>{const d=Math.abs(m.L-bl);if(d<best){best=d;bi=i;}});}
+ return items.map((m,i)=>({hex:m.hex,offset:i-bi}));
+}
+// Plan the assignment re-point for a regenerate: for each old ranked member, the
+// new member at the same offset is the same position. {map:[[old,new]]} for
+// positions whose hex changed; {removed:[hex]} for positions with no new
+// counterpart (the caller leaves their references a visible "(gone)").
+function stepRepointPlan(oldRanked,newMembers){
+ const byOff=new Map(newMembers.map(m=>[m.offset,m.hex])),map=[],removed=[];
+ for(const o of oldRanked){
+ const nh=byOff.get(o.offset);
+ if(nh===undefined)removed.push(o.hex);
+ else if(nh.toLowerCase()!==o.hex.toLowerCase())map.push([o.hex,nh]);
+ }
+ return {map,removed};
+}
+
+// Order a family's members dark to light by OKLCH lightness.
+function sortFamilyMembers(fam){return Object.assign({},fam,{members:[...fam.members].sort((a,b)=>oklchOf(a.hex).L-oklchOf(b.hex).L)});}
+// Order families for display: neutrals first (by base lightness), then chromatic
+// by base hue, ties broken by base lightness then base hex. Each family's members
+// are lightness-sorted. Display-only — the stored palette order is untouched.
+function sortFamilies(families){
+ const keyed=families.map(f=>{const c=oklchOf(f.base);return {f,neutral:!!f.neutral,H:c.H,L:c.L,base:f.base};});
+ keyed.sort((a,b)=>{
+ if(a.neutral!==b.neutral)return a.neutral?-1:1;
+ if(a.neutral&&b.neutral)return a.L-b.L;
+ const ah=Math.round(a.H),bh=Math.round(b.H); // a hue hair shouldn't outrank lightness
+ if(ah!==bh)return ah-bh;
+ if(a.L!==b.L)return a.L-b.L;
+ return a.base.toLowerCase()<b.base.toLowerCase()?-1:a.base.toLowerCase()>b.base.toLowerCase()?1:0;
+ });
+ return keyed.map(k=>sortFamilyMembers(k.f));
+}
// Pure color/UI-boundary helpers (normHex, ratingColor, textOn), inlined from
// app-util.js. textOn uses rl from the colormath core above.
// Pure color/UI-boundary helpers: hex-input parsing, the contrast-rating status
@@ -531,7 +784,7 @@ function buildTable(){
const crTd=document.createElement('td');crTd.style.whiteSpace='nowrap';crTd.style.fontSize='10pt';
function styleEx(){exTd.style.color=(kind==='bg'?MAP['p']:effFg(MAP[kind]));exTd.style.background=MAP['bg'];exTd.style.fontWeight=BOLD[kind]?'bold':'normal';exTd.style.fontStyle=ITALIC[kind]?'italic':'normal';}
function styleCr(){const r=contrast((kind==='bg'?MAP['p']:effFg(MAP[kind])),MAP['bg']);crTd.innerHTML=crHtml(r);}
- const dd=mkColorDropdown(list,cur,(hex)=>{MAP[kind]=hex;styleEx();styleCr();renderCode();if(kind==='bg'){applyGround();buildTable();}});
+ const dd=mkColorDropdown(list,cur,(hex)=>{MAP[kind]=hex;styleEx();styleCr();renderCode();if(kind==='bg'||kind==='p'){applyGround();buildTable();buildPkgTable();buildPkgPreview();}repaintCovered();});
styleEx();styleCr();
const lkTd=mkLockCell(kind,[dd]);
// style buttons
@@ -548,7 +801,23 @@ function buildTable(){
tr.appendChild(c2);tr.appendChild(lkTd);tr.appendChild(c0);tr.appendChild(stTd);tr.appendChild(crTd);tr.appendChild(exTd);
tb.appendChild(tr);}
}
-let dragFrom=null,selectedIdx=null;
+let selectedIdx=null;
+// When a named palette color is deleted, remember its hex keyed by name so that
+// recreating a color with the same name can re-bind the assignments still pointing
+// at the old (now "(gone)") hex. Consumed once per name; cleared on import.
+let lastGone={};
+// Re-point every assignment — syntax map, UI faces, package faces — from one hex
+// to another. Used when a palette color's value is edited and when a deleted name
+// is recreated.
+function repointHex(oldHex,newHex){
+ if(oldHex===newHex)return;
+ for(const k in MAP){if(MAP[k]===oldHex)MAP[k]=newHex;}
+ for(const f in UIMAP){if(UIMAP[f].fg===oldHex)UIMAP[f].fg=newHex;if(UIMAP[f].bg===oldHex)UIMAP[f].bg=newHex;}
+ for(const ap in PKGMAP)for(const fc in PKGMAP[ap]){const o=PKGMAP[ap][fc];if(o.fg===oldHex)o.fg=newHex;if(o.bg===oldHex)o.bg=newHex;}
+}
+// On adding a color, if its name matches a recently-deleted one, re-bind the
+// stranded assignments to the new hex. Returns true when a heal context existed.
+function healGone(name,newHex){const k=name.toLowerCase();if(!(k in lastGone))return false;const g=lastGone[k];delete lastGone[k];repointHex(g,newHex);return true;}
// Pairwise OKLab ΔE over the palette. Returns the sub-threshold pairs (sorted
// closest-first) and each color's nearest-neighbor distance for its chip title.
// Pure pairwise ΔE analysis lives in colormath.js (paletteWarnings); this renders it.
@@ -560,35 +829,90 @@ function renderPaletteWarnings(warnings,overflow){
if(overflow>0)html+=`<div class="pwl">and ${overflow} more</div>`;
w.innerHTML=html;w.style.display='block';
}
+// One palette chip for PALETTE[i], with its remove / rename / select handlers.
+// Families sort deterministically, so the old move-arrow / drag reordering is gone.
+function paletteChip(i,nearest){
+ const [hex,name]=PALETTE[i],tc=textOn(hex),nde=nearest[i];
+ const locked=(hex===MAP['bg']||hex===MAP['p']);
+ const d=document.createElement('div');d.className='pchip'+(i===selectedIdx?' sel':'');d.style.background=hex;
+ d.title=name+' '+hex+(nde===Infinity||nde===undefined?'':' — nearest ΔE '+nde.toFixed(3));
+ const rm=locked?`<span class="lock" title="${hex===MAP['bg']?'background':'foreground'} — can't remove" style="color:${tc}">&#128274;</span>`:`<button class="rm" title="remove" style="color:${tc}">×</button>`;
+ d.innerHTML=`${rm}<input class="nm" value="${name}" style="color:${tc}"><div class="hx" style="color:${tc}">${hex}</div>`;
+ if(!locked)d.querySelector('.rm').onclick=(e)=>{e.stopPropagation();if(name)lastGone[name.toLowerCase()]=hex;PALETTE.splice(i,1);if(selectedIdx===i)selectedIdx=null;renderPalette();buildTable();buildUITable();};
+ d.querySelector('.nm').onchange=(e)=>{PALETTE[i][1]=e.target.value;buildTable();buildUITable();};
+ d.onclick=(e)=>{if(e.target.closest('.rm')||e.target.closest('.nm'))return;selectColor(i);};
+ return d;
+}
+// Render the palette as hue families: the pinned ground strip, then hue-sorted
+// family strips, each dark to light. Grouping is derived from the hex by
+// familiesFromPalette every render, so renaming a color never moves it. The flat
+// PALETTE stays the editable truth; chips keep their per-chip controls.
function renderPalette(){
const p=document.getElementById('pals');p.innerHTML='';
const {warnings,overflow,nearest}=paletteWarnings(PALETTE,DELTAE_MIN,5);
- PALETTE.forEach((pc,i)=>{const [hex,name]=pc;const tc=textOn(hex);
- const nde=nearest[i];
- const locked=(hex===MAP['bg']||hex===MAP['p']);
- const d=document.createElement('div');d.className='pchip'+(i===selectedIdx?' sel':'');d.style.background=hex;d.draggable=true;
- d.title=name+' '+hex+(nde===Infinity?'':' — nearest \u0394E '+nde.toFixed(3));
- const lft=i>0?`<button class="mv l" title="move left" style="color:${tc}">&#8249;</button>`:'';
- const rgt=i<PALETTE.length-1?`<button class="mv r" title="move right" style="color:${tc}">&#8250;</button>`:'';
- const rm=locked?`<span class="lock" title="${hex===MAP['bg']?'background':'foreground'} — can't remove" style="color:${tc}">&#128274;</span>`:`<button class="rm" title="remove" style="color:${tc}">×</button>`;
- d.innerHTML=`${rm}${lft}${rgt}<input class="nm" value="${name}" style="color:${tc}"><div class="hx" style="color:${tc}">${hex}</div>`;
- if(!locked)d.querySelector('.rm').onclick=(e)=>{e.stopPropagation();PALETTE.splice(i,1);if(selectedIdx===i)selectedIdx=null;renderPalette();buildTable();buildUITable();};
- if(lft)d.querySelector('.mv.l').onclick=(e)=>{e.stopPropagation();moveColor(i,-1);};
- if(rgt)d.querySelector('.mv.r').onclick=(e)=>{e.stopPropagation();moveColor(i,1);};
- d.querySelector('.nm').onchange=(e)=>{PALETTE[i][1]=e.target.value;buildTable();buildUITable();};
- d.onclick=(e)=>{if(e.target.closest('.rm')||e.target.closest('.nm')||e.target.closest('.mv'))return;selectColor(i);};
- d.ondragstart=()=>{dragFrom=i;d.classList.add('drag');};
- d.ondragend=()=>{d.classList.remove('drag');document.querySelectorAll('.pchip.over').forEach(x=>x.classList.remove('over'));};
- d.ondragover=(e)=>{e.preventDefault();if(dragFrom!==null&&dragFrom!==i)d.classList.add('over');};
- d.ondragleave=()=>d.classList.remove('over');
- d.ondrop=(e)=>{e.preventDefault();d.classList.remove('over');if(dragFrom===null||dragFrom===i)return;const m=PALETTE.splice(dragFrom,1)[0];PALETTE.splice(i,0,m);dragFrom=null;selectedIdx=null;renderPalette();buildTable();buildUITable();};
- p.appendChild(d);});
+ const {ground,families}=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']});
+ const used=new Set();
+ const idxOf=(hex,name)=>{for(let i=0;i<PALETTE.length;i++)if(!used.has(i)&&PALETTE[i][0]===hex&&PALETTE[i][1]===name){used.add(i);return i;}return -1;};
+ const strip=(cls)=>{const s=document.createElement('div');s.className='fstrip'+(cls||'');p.appendChild(s);return s;};
+ const gs=strip(' ground');gs.dataset.family='ground';
+ ground.forEach(g=>{
+ const i=PALETTE.findIndex((pp,k)=>!used.has(k)&&pp[0]===g.hex);
+ if(i>=0){used.add(i);gs.appendChild(paletteChip(i,nearest));}
+ else{const tc=textOn(g.hex),sw=document.createElement('div');sw.className='pchip';sw.style.background=g.hex;sw.title=(g.role||'')+' '+g.hex;
+ sw.innerHTML=`<input class="nm" value="${g.role||''}" disabled style="color:${tc}"><div class="hx" style="color:${tc}">${g.hex}</div>`;gs.appendChild(sw);}
+ });
+ // The too-similar warning stays on the full flat palette: a generated ramp's
+ // steps are a stepL apart (well above the warning's ΔE threshold), so they never
+ // trigger it, and any pair that does is a genuine near-duplicate worth flagging.
+ sortFamilies(families).forEach(f=>{
+ const s=strip(f.neutral?' neutral':'');s.dataset.family=f.base;
+ f.members.forEach(m=>{const i=idxOf(m.hex,m.name);if(i>=0)s.appendChild(paletteChip(i,nearest));});
+ if(!f.neutral)s.appendChild(familyCountControl(f));
+ });
renderPaletteWarnings(warnings,overflow);
buildUITable();if(document.getElementById('pkgbody'))buildPkgTable();
}
+// The per-family count control under a chromatic strip. Its value is the family's
+// current per-side reach; setting N regenerates the family as base ±N.
+function familyCountControl(f){
+ const per=Math.max(0,...rankByLightness(f.members.map(m=>m.hex),f.base).map(m=>Math.abs(m.offset)));
+ const d=document.createElement('div');d.className='fcount';
+ d.innerHTML=`<span title="generate a symmetric ramp of N steps each side of this family's base — this replaces the family">&#177; <input type="number" min="0" max="4" value="${per}"></span>`;
+ d.querySelector('input').onchange=(e)=>setFamilyCount(f.base,Math.max(0,Math.min(4,parseInt(e.target.value,10)||0)));
+ return d;
+}
+// Regenerate a family as a symmetric base ±N ramp, replacing its current members.
+// References to a surviving position (matched by signed lightness rank) follow the
+// new hex; references to a position removed by lowering N leave their old hex,
+// which is no longer in the palette and so renders as "(gone)".
+// Replace oldHexes in the palette with a fresh base ±n ramp, repointing surviving
+// references and leaving removed ones on their now-gone hex. Returns the removed
+// count, or null on a bad base. Shared by the count control and the base edit.
+function regenFamilyInPlace(oldHexes,baseHex,baseName,n){
+ const r=regenFamily(baseHex,n,{});
+ if(r.error){notify('cannot regenerate from '+baseHex,true);return null;}
+ const plan=stepRepointPlan(rankByLightness(oldHexes,baseHex),r.members);
+ const oldSet=new Set(oldHexes.map(h=>h.toLowerCase()));
+ let at=PALETTE.length;
+ for(let i=0;i<PALETTE.length;i++)if(oldSet.has(PALETTE[i][0].toLowerCase())){at=i;break;}
+ for(let i=PALETTE.length-1;i>=0;i--)if(oldSet.has(PALETTE[i][0].toLowerCase()))PALETTE.splice(i,1);
+ const entries=r.members.map(m=>[m.hex,m.offset===0?baseName:baseName+(m.offset>0?'+'+m.offset:String(m.offset))]);
+ PALETTE.splice(Math.min(at,PALETTE.length),0,...entries);
+ for(const [o,nw] of plan.map)repointHex(o,nw);
+ return plan.removed.length;
+}
+function setFamilyCount(baseHex,n){
+ const {families}=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']});
+ const fam=families.find(f=>f.base.toLowerCase()===baseHex.toLowerCase());
+ if(!fam)return;
+ const baseName=(fam.members.find(m=>m.hex.toLowerCase()===baseHex.toLowerCase())||{}).name||'color';
+ const removed=regenFamilyInPlace(fam.members.map(m=>m.hex),baseHex,baseName,n);
+ if(removed===null)return;
+ selectedIdx=null;renderPalette();buildTable();buildUITable();renderCode();applyGround();
+ notify('regenerated "'+baseName+'" to ±'+n+(removed?(' — '+removed+' removed step(s) show "(gone)" where used'):''),false);
+}
function notify(msg,err){const m=document.getElementById('palmsg');if(!m)return;m.textContent=msg;m.style.color=err?'#cb6b4d':'#8a9496';m.style.opacity='1';clearTimeout(m._t);m._t=setTimeout(()=>{m.style.opacity='0';},err?4000:2800);}
function applyEdit(){if(selectedIdx!==null)updateColor();else addColor();}
-function moveColor(i,dir){const j=i+dir;if(j<0||j>=PALETTE.length)return;const t=PALETTE[i];PALETTE[i]=PALETTE[j];PALETTE[j]=t;if(selectedIdx===i)selectedIdx=j;else if(selectedIdx===j)selectedIdx=i;renderPalette();buildTable();buildUITable();}
function selectColor(i){selectedIdx=i;const [hex,name]=PALETTE[i];setHex(hex);document.getElementById('newname').value=name;renderPalette();notify('editing "'+name+'" — change the value, then Enter (or Update selected) to save',false);}
function updateColor(){
if(selectedIdx===null){notify('click a palette color to select it first',true);return;}
@@ -596,10 +920,17 @@ function updateColor(){
const newHex=curHex();
const newName=(document.getElementById('newname').value.trim())||PALETTE[i][1];
if(PALETTE.some((p,j)=>j!==i&&p[1].toLowerCase()===newName.toLowerCase())){notify('another color is already named "'+newName+'" — names must be unique',true);return;}
+ // If the edited color is a family base with a ramp, recolor the whole family: regenerate from the new base at the same count.
+ const fams=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']}).families;
+ const fam=fams.find(f=>!f.neutral&&f.base.toLowerCase()===oldHex.toLowerCase());
+ const count=fam?Math.max(0,...rankByLightness(fam.members.map(m=>m.hex),fam.base).map(m=>Math.abs(m.offset))):0;
PALETTE[i]=[newHex,newName];
- for(const k in MAP){if(MAP[k]===oldHex)MAP[k]=newHex;}
- for(const f in UIMAP){if(UIMAP[f].fg===oldHex)UIMAP[f].fg=newHex;if(UIMAP[f].bg===oldHex)UIMAP[f].bg=newHex;}
- for(const ap in PKGMAP)for(const fc in PKGMAP[ap]){const o=PKGMAP[ap][fc];if(o.fg===oldHex)o.fg=newHex;if(o.bg===oldHex)o.bg=newHex;}
+ repointHex(oldHex,newHex);
+ if(fam&&count>0){
+ const oldHexes=fam.members.map(m=>m.hex.toLowerCase()===oldHex.toLowerCase()?newHex:m.hex);
+ regenFamilyInPlace(oldHexes,newHex,newName,count);
+ closePicker();selectedIdx=null;renderPalette();buildTable();buildUITable();renderCode();applyGround();notify('recolored "'+newName+'" family from the new base',false);return;
+ }
closePicker();renderPalette();buildTable();buildUITable();renderCode();applyGround();notify('updated "'+newName+'"',false);
}
function curHex(){return normHex(document.getElementById('newhexstr').value)||'#888888';}
@@ -627,12 +958,30 @@ function paintOklchPlane(H){
if(T&&contrast(cell.hex,MAP['bg'])<T){ctx.fillStyle='rgba(8,7,6,0.66)';ctx.fillRect(x,y,step,step);}}}
_planeCache={key,data:ctx.getImageData(0,0,w,h)};
}
+// --- safe-lightness guidance (spec Phase 5) ----------------------------------
+let pkSafeFace=''; // covered overlay face the picker's lightness is checked against (or '')
+function setSafeFace(f){pkSafeFace=f;if(pickerOn)paintPicker();}
+// Shade the band of the C×L plane whose lightness is too light to keep pkSafeFace
+// readable over its foreground set, with the L_max ceiling as the band's lower
+// edge. One marker computed via lMax at the current chroma, not a per-pixel mask.
+function paintSafeBand(C,H){
+ const el=document.getElementById('svsafe');if(!el)return;
+ if(!pkSafeFace||pkModel!=='oklch'){el.style.display='none';return;}
+ const fs=fgSetForFace(pkSafeFace);
+ if(fs.reason||!fs.set.length){el.style.display='none';return;}
+ const sv=document.getElementById('sv'),h=sv.clientHeight,res=lMax(H,C,fs.set,WORST_TARGET);
+ if(res.status==='all'){el.style.display='none';return;}
+ el.style.display='block';el.style.top='0px';
+ el.style.height=(res.status==='none'?h:Math.max(0,(1-res.L)*h))+'px';
+ el.title='safe-lightness ceiling for '+pkSafeFace+' ('+(res.status==='none'?'no safe lightness — a foreground is too dark':'L_max '+res.L.toFixed(3)+(res.status==='clamp'?', chroma-clamped':''))+')';
+}
function paintPicker(){const sv=document.getElementById('sv');if(!sv)return;
const w=sv.clientWidth,h=sv.clientHeight,hh=document.getElementById('hue').clientHeight;
if(pkModel==='oklch'){const [L,C,H]=readOklch();sv.style.background='#15120f';paintOklchPlane(H);
document.getElementById('svcur').style.left=(Math.min(1,C/OKLCH_CMAX)*w)+'px';
document.getElementById('svcur').style.top=((1-L)*h)+'px';
- document.getElementById('huecur').style.top=((H/360)*hh)+'px';return;}
+ document.getElementById('huecur').style.top=((H/360)*hh)+'px';paintSafeBand(C,H);return;}
+ const sb=document.getElementById('svsafe');if(sb)sb.style.display='none';
sv.style.background=`linear-gradient(to top,#000,rgba(0,0,0,0)),linear-gradient(to right,#fff,rgba(255,255,255,0)),hsl(${pkH},100%,50%)`;
document.getElementById('svcur').style.left=(pkS*w)+'px';document.getElementById('svcur').style.top=((1-pkV)*h)+'px';document.getElementById('huecur').style.top=((pkH/360)*hh)+'px';drawMask();}
function pkReadout(h){const e=document.getElementById('pkhex');if(e)e.textContent=h;const c=document.getElementById('pkcon');if(c){const r=contrast(h,MAP['bg']);c.textContent=r.toFixed(1)+' '+rating(r);c.style.color=ratingColor(r);}
@@ -663,6 +1012,7 @@ function closePicker(){if(!pickerOn)return;pickerOn=false;const p=document.getEl
function pkOutside(e){if(!e.target.closest('#picker')&&!e.target.closest('#swatch'))closePicker();}
function pkDrag(el,fn){el.addEventListener('pointerdown',e=>{e.preventDefault();fn(e);const mv=ev=>fn(ev),up=()=>{document.removeEventListener('pointermove',mv);document.removeEventListener('pointerup',up);};document.addEventListener('pointermove',mv);document.addEventListener('pointerup',up);});}
function initPicker(){const sw=document.getElementById('swatch');if(!sw)return;sw.style.background=curHex();sw.onclick=()=>pickerOn?closePicker():openPicker();
+ const sf=document.getElementById('safefor');if(sf&&sf.options.length<=1)COVERED_FACES.forEach(f=>{const o=document.createElement('option');o.value=f;o.textContent=f;sf.appendChild(o);});
pkDrag(document.getElementById('sv'),e=>{const r=document.getElementById('sv').getBoundingClientRect();const fx=Math.max(0,Math.min(1,(e.clientX-r.left)/r.width)),fy=Math.max(0,Math.min(1,(e.clientY-r.top)/r.height));
if(pkModel==='oklch'){setOklchInputs(1-fy,fx*OKLCH_CMAX,readOklch()[2]);pkOklchSet();}else{pkS=fx;pkV=1-fy;pkSet();}});
pkDrag(document.getElementById('hue'),e=>{const r=document.getElementById('hue').getBoundingClientRect();const fy=Math.max(0,Math.min(1,(e.clientY-r.top)/r.height));
@@ -676,7 +1026,10 @@ function initPicker(){const sw=document.getElementById('swatch');if(!sw)return;s
function addColor(){const h=curHex();const name=document.getElementById('newname').value.trim();
if(!name){notify('name the color before adding it',true);return;}
if(PALETTE.some(p=>p[1].toLowerCase()===name.toLowerCase())){notify('a color named "'+name+'" already exists — select it and use Update selected to change its value',true);return;}
- PALETTE.push([h,name]);document.getElementById('newname').value='';selectedIdx=null;closePicker();renderPalette();buildTable();notify('added "'+name+'"',false);}
+ PALETTE.push([h,name]);const healed=healGone(name,h);document.getElementById('newname').value='';selectedIdx=null;closePicker();
+ renderPalette();buildTable();buildUITable();
+ if(healed){renderCode();applyGround();if(document.getElementById('pkgbody'))buildPkgTable();buildPkgPreview();}
+ notify(healed?('added "'+name+'" and reconnected its assignments'):('added "'+name+'"'),false);}
function themeName(){return (document.getElementById('themename').value||'theme').trim()||'theme';}
function fileSlug(){return slugify(themeName());}
function exportObj(){const a={};CATS.forEach(c=>a[c[0]]=MAP[c[0]]);const o={name:themeName(),palette:PALETTE,assignments:a,bold:Object.keys(BOLD).filter(k=>BOLD[k]),italic:Object.keys(ITALIC).filter(k=>ITALIC[k]),ui:UIMAP};if(LOCKED.size)o.locks=[...LOCKED];const pk=packagesForExport(PKGMAP);if(Object.keys(pk).length)o.packages=pk;return o;}
@@ -690,7 +1043,7 @@ async function saveTheme(){const data=JSON.stringify(exportObj(),null,1);
try{if(!fileHandle)fileHandle=await window.showSaveFilePicker({suggestedName:fileSlug()+'.json',types:[{description:'theme JSON',accept:{'application/json':['.json']}}]});
const w=await fileHandle.createWritable();await w.write(data);await w.close();notify('saved "'+themeName()+'"',false);updateTitle();
}catch(e){if(e&&e.name!=='AbortError')notify('save failed: '+e.message,true);}}
-function applyImported(text){const d=JSON.parse(text);if(d.name)document.getElementById('themename').value=d.name;if(d.palette)PALETTE=d.palette;if(d.assignments)Object.assign(MAP,d.assignments);
+function applyImported(text){const d=JSON.parse(text);lastGone={};if(d.name)document.getElementById('themename').value=d.name;if(d.palette)PALETTE=d.palette;if(d.assignments)Object.assign(MAP,d.assignments);
BOLD={};(d.bold||[]).forEach(k=>BOLD[k]=true);ITALIC={};(d.italic||[]).forEach(k=>ITALIC[k]=true);
LOCKED=new Set(d.locks||[]);
if(d.ui)Object.assign(UIMAP,d.ui);
@@ -707,16 +1060,25 @@ async function importTheme(){
const file=await h.getFile();applyImported(await file.text());fileHandle=h;updateTitle();
notify('imported "'+(themeName()||file.name)+'" — save now overwrites it',false);
}catch(e){if(e&&e.name!=='AbortError')notify('import failed: '+e.message,true);}}
-function applyGround(){document.querySelectorAll('pre').forEach(p=>p.style.background=MAP['bg']);document.querySelectorAll('.ex').forEach(e=>e.style.background=MAP['bg']);}
+// The blanket covers only the code panes and syntax example cells. UI-face
+// preview cells also carry .ex, but a face with its own bg must keep it, so
+// those rows repaint through paintUI (which also re-rates the contrast cell
+// against the new ground for faces without their own bg).
+function applyGround(){document.querySelectorAll('pre').forEach(p=>p.style.background=MAP['bg']);document.querySelectorAll('#legbody .ex').forEach(e=>e.style.background=MAP['bg']);UI_FACES.forEach(([f])=>{if(document.getElementById('uiprev-'+f))paintUI(f);});}
function uf(f){return UIMAP[f]||{};}
function udeco(o){return `font-weight:${o.bold?'bold':'normal'};font-style:${o.italic?'italic':'normal'};text-decoration:${(o.underline?'underline ':'')+(o.strike?'line-through':'')||'none'}`;}
// A face's :box, rendered as an inset box-shadow (no layout shift). Returns the
// box-shadow VALUE (or '' for no box). 'line' is a flat border in the box color
// (or the face's own color when unset); 'released'/'pressed' are the 3D button
// styles Emacs draws, derived from the background so they read on any color.
-function boxCss(b){if(!b||!b.style)return '';const w=b.width||1;
- if(b.style==='released')return `inset ${w}px ${w}px 0 #ffffff33,inset -${w}px -${w}px 0 #00000066`;
- if(b.style==='pressed')return `inset ${w}px ${w}px 0 #00000066,inset -${w}px -${w}px 0 #ffffff33`;
+function boxCss(b,bg){if(!b||!b.style)return '';const w=b.width||1;
+ if(b.style==='released'||b.style==='pressed'){
+ // Emacs derives the 3D edges from the face's background (reliefColors,
+ // ported from xterm.c); the translucent pair is only the no-bg fallback.
+ const r=bg?reliefColors(bg):{hl:null,sh:null};
+ const hl=r.hl||'#ffffff33',sh=r.sh||'#00000066';
+ const [a,z]=b.style==='released'?[hl,sh]:[sh,hl];
+ return `inset ${w}px ${w}px 0 ${a},inset -${w}px -${w}px 0 ${z}`;}
return `inset 0 0 0 ${w}px ${b.color||'currentColor'}`;}
// The per-row box control: none / line / raised / pressed. get()/set() read and
// write the face's box object (null = no box).
@@ -800,7 +1162,7 @@ function buildMockFrame(){
buf+=`<div class="ln" style="background:${rowBg}"><span class="fr" data-face="fringe" style="background:${frng.bg||bg};color:${frng.fg||fg};text-align:center;font-size:10px;overflow:hidden" title="fringe">${L.cont?'&#8618;':''}</span><span class="num" data-face="${nFace}" style="color:${nFg};background:${nBg};${udeco(isc?lnc:ln)}">${i+1}</span><span class="cd">${cd||'&nbsp;'}</span></div>`;
});
let html=`<div class="mbuf" style="display:flex;background:${bg}"><div style="flex:1;min-width:0">${buf}</div><div data-face="vertical-border" title="vertical-border" style="width:3px;flex:0 0 auto;background:${vb.fg||vb.bg||'#2f343a'}"></div></div>`;
- const mlbx=boxCss(ml.box),mlibx=boxCss(mli.box);
+ const mlbx=boxCss(ml.box,ml.bg||bg),mlibx=boxCss(mli.box,mli.bg||bg);
html+=`<div class="bar" data-face="mode-line" style="background:${ml.bg||fg};color:${ml.fg||bg};${udeco(ml)}${mlbx?';box-shadow:'+mlbx:''}"> init.el (Emacs Lisp) L5 git:main </div>`;
html+=`<div class="bar" data-face="mode-line-inactive" style="background:${mli.bg||bg};color:${mli.fg||fg};${udeco(mli)}${mlibx?';box-shadow:'+mlibx:''}"> *Messages* (Fundamental) </div>`;
html+=`<div class="echo" style="color:${fg}"><span data-face="minibuffer-prompt" style="color:${mb.fg||fg};${udeco(mb)}">I-search:</span> count <span data-face="isearch-fail" style="color:${isf.fg||fg};background:${isf.bg||'transparent'};${udeco(isf)}">zzz [no match]</span></div>`;
@@ -845,7 +1207,7 @@ function buildPkgTable(){
}
applyTableSort('pkgbody');
}
-function ofs(app,face){const f=PKGMAP[app][face]||{},fg=effFg(pkgEffFg(app,face)),bg=pkgEffBg(app,face);const dec=(f.underline?'underline ':'')+(f.strike?'line-through':'');const bx=boxCss(f.box);return `color:${fg};${bg?'background:'+bg+';':''}font-weight:${f.bold?'bold':'normal'};font-style:${f.italic?'italic':'normal'};text-decoration:${dec.trim()||'none'};font-size:${(f.height||1)}em${bx?';box-shadow:'+bx:''}`;}
+function ofs(app,face){const f=PKGMAP[app][face]||{},fg=effFg(pkgEffFg(app,face)),bg=pkgEffBg(app,face);const dec=(f.underline?'underline ':'')+(f.strike?'line-through':'');const bx=boxCss(f.box,bg||MAP['bg']);return `color:${fg};${bg?'background:'+bg+';':''}font-weight:${f.bold?'bold':'normal'};font-style:${f.italic?'italic':'normal'};text-decoration:${dec.trim()||'none'};font-size:${(f.height||1)}em${bx?';box-shadow:'+bx:''}`;}
function os(app,face,txt){return `<span data-face="${face}" style="${ofs(app,face)}">${txt}</span>`;}
function renderOrgPreview(){const a='org-mode',L=[];
L.push(os(a,'org-document-info-keyword','#+TITLE:')+' '+os(a,'org-document-title','Project Notes'));
@@ -1146,8 +1508,31 @@ function genericPreview(app){let h='<div style="padding:10px 14px;font:12pt/1.8
function buildPkgPreview(){const app=curApp(),p=document.getElementById('pkgpreview');if(!p)return;const pv=APPS[app].preview;const bespoke=['org','magit','elfeed','ghostel','dashboard','mu4e','lsp','gitgutter','flycheck','dired','dirvish','calibredb','erc','orgdrill','orgnoter','signel','pearl','slack','telega','shr'].includes(pv);p.innerHTML=pv==='org'?renderOrgPreview():pv==='magit'?renderMagitPreview():pv==='elfeed'?renderElfeedPreview():pv==='ghostel'?renderGhostelPreview():pv==='dashboard'?renderDashboardPreview():pv==='mu4e'?renderMu4ePreview():pv==='lsp'?renderLspPreview():pv==='gitgutter'?renderGitGutterPreview():pv==='flycheck'?renderFlycheckPreview():pv==='dired'?renderDiredPreview():pv==='dirvish'?renderDirvishPreview():pv==='calibredb'?renderCalibredbPreview():pv==='erc'?renderErcPreview():pv==='orgdrill'?renderOrgdrillPreview():pv==='orgnoter'?renderOrgnoterPreview():pv==='signel'?renderSignelPreview():pv==='pearl'?renderPearlPreview():pv==='slack'?renderSlackPreview():pv==='telega'?renderTelegaPreview():pv==='shr'?renderShrPreview():genericPreview(app);p.style.background=MAP['bg'];p.onclick=(e)=>{const u=e.target.closest('[data-face]');if(u)flashPkg(u.dataset.face);};const lbl=document.getElementById('pkgprevlabel');if(lbl)lbl.textContent=bespoke?(APPS[app].label+' preview'):'preview (generic — face names in their own colors)';}
function resetApp(){const app=curApp();PKGMAP[app]={};for(const [face,label,d] of APPS[app].faces)PKGMAP[app][face]=seedFace(d);pkgChanged();}
function syncPkgHeight(){const t=document.getElementById('pkgtable'),m=document.getElementById('pkgpreview');if(!t||!m)return;const lb=m.previousElementSibling,lbh=lb?lb.getBoundingClientRect().height+10:30;m.style.height=Math.max(t.getBoundingClientRect().height-lbh,220)+'px';}
-function paintUI(face){const pv=document.getElementById('uiprev-'+face);if(!pv)return;const o=UIMAP[face];pv.style.color=effFg(o.fg);pv.style.background=effBg(o.bg);pv.style.fontWeight=o.bold?'bold':'normal';pv.style.fontStyle=o.italic?'italic':'normal';pv.style.textDecoration=(o.underline?'underline ':'')+(o.strike?'line-through':'')||'none';pv.style.boxShadow=boxCss(o.box);
- const cr=document.getElementById('uicr-'+face);if(cr){const efg=effFg(o.fg),ebg=effBg(o.bg),r=contrast(efg,ebg);cr.innerHTML=crHtml(r);}}
+// --- worst-case readout for the covered overlay faces (spec Phase 4) ---------
+// Default WCAG target for the worst-case verdict (AA). AAA is selectable.
+let WORST_TARGET=4.5;
+// The live v1 foreground set for a covered overlay face: the syntax-token colors
+// (every assignable category except the ground) plus the default foreground.
+function fgSetForFace(face){
+ const syntaxAssignments=CATS.filter(c=>c[0]!=='bg'&&c[0]!=='p').map(c=>({role:c[0],hex:effFg(MAP[c[0]])}));
+ return fgSetFor(face,{covered:COVERED_FACES,syntaxAssignments,defaultFg:MAP['p']});
+}
+// The worst-case contrast cell for a covered face: the floor over its foreground
+// set against its effective background, naming the limiting foreground. Returns
+// null for an out-of-scope face so the caller keeps the single-pair readout.
+function worstCellHtml(face){
+ const r=fgSetForFace(face);
+ if(r.reason==='out-of-scope')return null;
+ if(r.reason==='empty'||!r.set.length)return '<span title="this overlay has no syntax foreground set yet">no fg set</span>';
+ const bg=effBg(uf(face).bg),fl=floor(bg,r.set),verdict=fl.ratio>=WORST_TARGET?'PASS':'FAIL';
+ const s='worst: '+fl.limitingLabel+' '+fl.limitingHex+' — '+fl.ratio.toFixed(1)+' '+verdict;
+ return `<span style="color:${ratingColor(fl.ratio)}" title="${esc(s)}">${esc(s)}</span>`;
+}
+// Repaint every covered overlay face (their floors depend on the syntax palette,
+// so a syntax-color edit has to refresh them even though it doesn't rebuild the table).
+function repaintCovered(){COVERED_FACES.forEach(f=>{if(UIMAP[f]&&document.getElementById('uicr-'+f))paintUI(f);});}
+function paintUI(face){const pv=document.getElementById('uiprev-'+face);if(!pv)return;const o=UIMAP[face];pv.style.color=effFg(o.fg);pv.style.background=effBg(o.bg);pv.style.fontWeight=o.bold?'bold':'normal';pv.style.fontStyle=o.italic?'italic':'normal';pv.style.textDecoration=(o.underline?'underline ':'')+(o.strike?'line-through':'')||'none';pv.style.boxShadow=boxCss(o.box,effBg(o.bg));
+ const cr=document.getElementById('uicr-'+face);if(cr){const w=worstCellHtml(face);if(w!==null){cr.innerHTML=w;}else{const efg=effFg(o.fg),ebg=effBg(o.bg),r=contrast(efg,ebg);cr.innerHTML=crHtml(r);}}}
function buildUITable(){
const tb=document.getElementById('uibody');tb.innerHTML='';
for(const [face,label,ex] of UI_FACES){
@@ -1324,4 +1709,199 @@ if(location.hash==='#readouttest'){const hex='#67809c';document.getElementById('
const sane=Math.abs(lch.L-0.591)<0.01&&Math.abs(lch.C-0.052)<0.01&&Math.abs(lch.H-251.6)<2;
const ok=wired&&sane;document.title='READOUTTEST '+(ok?'PASS':'FAIL');
const d=document.createElement('div');d.id='readouttest';d.textContent='READOUTTEST '+(ok?'PASS':'FAIL')+' oklch='+o+' | apca='+a+' | wcag='+w;document.body.appendChild(d);}
+// Worst-case readout gate (open with #contrasttest): a covered overlay face shows
+// the floor over its foreground set and names the limiting foreground, an
+// out-of-scope face keeps the single-pair readout, and an empty set reads "no fg set".
+if(location.hash==='#contrasttest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveMAP=Object.assign({},MAP),saveUI=JSON.parse(JSON.stringify(UIMAP));
+ MAP['p']='#f0fef0';MAP['kw']='#67809c';MAP['str']='#a3b18a';MAP['bg']='#000000';
+ UIMAP['region']={fg:null,bg:'#202830',bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ const cell=document.getElementById('uicr-region');
+ A(cell&&/^worst:/.test(cell.textContent),'region shows the worst-case readout: '+(cell&&cell.textContent));
+ A(cell&&cell.textContent.includes('#67809c'),'limiting fg is keyword blue: '+(cell&&cell.textContent));
+ A(cell&&/\b(PASS|FAIL)\b/.test(cell.textContent),'readout carries a verdict');
+ const fl=floor('#202830',fgSetForFace('region').set);
+ A(fl.limitingHex==='#67809c','floor limiting is blue, got '+fl.limitingHex);
+ A(Math.abs(fl.ratio-contrast('#67809c','#202830'))<1e-9,'floor ratio matches blue-on-bg');
+ const ml=document.getElementById('uicr-mode-line');
+ A(worstCellHtml('mode-line')===null,'mode-line is out of scope (single-pair)');
+ A(ml&&/^\d/.test(ml.textContent.trim()),'mode-line cell is a numeric ratio: '+(ml&&ml.textContent));
+ MAP['p']='';CATS.forEach(c=>{if(c[0]!=='bg')MAP[c[0]]='';});buildUITable();
+ const empty=document.getElementById('uicr-region');
+ A(empty&&empty.textContent.trim()==='no fg set','empty set reads the no-set message: '+(empty&&empty.textContent));
+ // A two-color face (own fg AND own bg) rates its own pair, never the ground bg.
+ UIMAP['mode-line']={fg:'#112233',bg:'#aabbcc',bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ const two=document.getElementById('uicr-mode-line'),twoWant=contrast('#112233','#aabbcc');
+ A(two&&Math.abs(parseFloat(two.textContent)-twoWant)<0.06,'ui two-color face rates own fg-on-bg: got '+(two&&two.textContent.trim())+' want '+twoWant.toFixed(1));
+ const tApp=Object.keys(APPS)[0],tFace=APPS[tApp].faces[0][0],savePF=JSON.parse(JSON.stringify(PKGMAP[tApp][tFace]));
+ Object.assign(PKGMAP[tApp][tFace],{fg:'#112233',bg:'#aabbcc',inherit:null});buildPkgTable();
+ const prow=document.querySelector('#pkgbody tr[data-face="'+tFace+'"]'),pcell=prow&&prow.children[5];
+ A(pcell&&Math.abs(parseFloat(pcell.textContent)-twoWant)<0.06,'pkg two-color face rates own fg-on-bg: got '+(pcell&&pcell.textContent.trim())+' want '+twoWant.toFixed(1));
+ PKGMAP[tApp][tFace]=savePF;buildPkgTable();
+ // A ground-bg change must not clobber a face's own preview bg, must leave a
+ // two-color ratio alone, and must re-rate a ground-dependent face's cell.
+ UIMAP['fringe']={fg:'#ddeeff',bg:null,bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ MAP['bg']='#440000';applyGround();
+ const pv=document.getElementById('uiprev-mode-line');
+ A(pv&&pv.style.background==='rgb(170, 187, 204)','ground change keeps a face own preview bg: got '+(pv&&pv.style.background));
+ const twoAfter=document.getElementById('uicr-mode-line');
+ A(twoAfter&&Math.abs(parseFloat(twoAfter.textContent)-twoWant)<0.06,'ground change leaves a two-color ratio alone: got '+(twoAfter&&twoAfter.textContent.trim()));
+ const frc=document.getElementById('uicr-fringe'),frWant=contrast('#ddeeff','#440000');
+ A(frc&&Math.abs(parseFloat(frc.textContent)-frWant)<0.06,'ground change re-rates a ground-dependent face: got '+(frc&&frc.textContent.trim())+' want '+frWant.toFixed(1));
+ // A default-fg (p) change through the real syntax dropdown re-rates a face
+ // whose fg falls back to it. Drives the DOM so the handler wiring is pinned.
+ UIMAP['fringe']={fg:null,bg:'#aabbcc',bold:false,italic:false,underline:false,strike:false};
+ buildUITable();
+ const pLocked=LOCKED.has('p');if(pLocked){LOCKED.delete('p');buildTable();}
+ const pdd=document.querySelector('#legbody tr[data-kind="p"] .cdd');
+ if(pdd){pdd.click();
+ const pHex=PALETTE.find(p=>p[0]!==MAP['p'])[0];
+ const prow=[...document.querySelectorAll('.cddpop .cddrow')].find(r=>r.querySelector('.cddhx').textContent===pHex);
+ if(prow)prow.click();
+ const pf=document.getElementById('uicr-fringe'),pfWant=contrast(pHex,'#aabbcc');
+ A(prow&&pf&&Math.abs(parseFloat(pf.textContent)-pfWant)<0.06,'default-fg change re-rates a p-fallback face: got '+(pf&&pf.textContent.trim())+' want '+pfWant.toFixed(1));
+ }else A(false,'syntax table has a p row with a dropdown');
+ if(pLocked){LOCKED.add('p');buildTable();}
+ for(const k in MAP)delete MAP[k];Object.assign(MAP,saveMAP);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveUI);buildUITable();applyGround();
+ document.title='CONTRASTTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='contrasttest';d.textContent='CONTRASTTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Bevel gate (open with #beveltest): released/pressed boxes derive their
+// highlight and shadow from the face's effective bg per Emacs's relief
+// algorithm, and pressed draws the shadow edge first.
+if(location.hash==='#beveltest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveUI=JSON.parse(JSON.stringify(UIMAP));
+ UIMAP['mode-line']={fg:'#d8dee9',bg:'#30343c',bold:false,italic:false,underline:false,strike:false,box:{style:'released',width:1,color:null}};
+ buildUITable();
+ const pv=document.getElementById('uiprev-mode-line');
+ const bs=pv&&pv.style.boxShadow;
+ A(bs&&bs.includes('rgb(113, 118, 127)'),'released highlight derives from the face bg (#71767f): '+bs);
+ A(bs&&bs.includes('rgb(15, 17, 22)'),'released shadow derives from the face bg (#0f1116): '+bs);
+ UIMAP['mode-line'].box={style:'pressed',width:1,color:null};paintUI('mode-line');
+ const bs2=pv&&pv.style.boxShadow;
+ A(bs2&&bs2.includes('rgb(15, 17, 22)')&&bs2.includes('rgb(113, 118, 127)')&&bs2.indexOf('rgb(15, 17, 22)')<bs2.indexOf('rgb(113, 118, 127)'),'pressed swaps the pair (shadow edge first): '+bs2);
+ UIMAP['mode-line'].box={style:'line',width:1,color:'#ff0000'};paintUI('mode-line');
+ A(pv&&pv.style.boxShadow.includes('rgb(255, 0, 0)'),'line style keeps its explicit color: '+(pv&&pv.style.boxShadow));
+ for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveUI);buildUITable();
+ document.title='BEVELTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='beveltest';d.textContent='BEVELTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Safe-lightness gate (open with #safetest): the OKLCH picker shades the unsafe
+// lightness band for a selected covered face and hides it when no face is selected.
+if(location.hash==='#safetest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveMAP=Object.assign({},MAP);
+ MAP['p']='#f0fef0';MAP['kw']='#67809c';MAP['bg']='#000000';
+ document.getElementById('newhexstr').value='#202830';openPicker();setPkModel('oklch');
+ setSafeFace('region');
+ const band=document.getElementById('svsafe');
+ A(band&&band.style.display==='block','safe band shows for an in-scope face');
+ A(band&&parseFloat(band.style.height)>0,'safe band has a positive height: '+(band&&band.style.height));
+ setSafeFace('');
+ A(band&&band.style.display==='none','safe band hidden when no face is selected');
+ for(const k in MAP)delete MAP[k];Object.assign(MAP,saveMAP);
+ setPkModel('hsv');closePicker();
+ document.title='SAFETEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='safetest';d.textContent='SAFETEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Gone-rebind gate (open with #healtest): deleting a named color then recreating
+// the name re-points the assignments stranded on the old hex to the new color.
+if(location.hash==='#healtest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveU=JSON.parse(JSON.stringify(UIMAP)),savePK=JSON.parse(JSON.stringify(PKGMAP)),saveG=Object.assign({},lastGone),saveSel=selectedIdx;
+ PALETTE=[['#0d0b0a','ground'],['#cdced1','fg'],['#67809c','blue']];MAP['kw']='#67809c';lastGone={};selectedIdx=null;renderPalette();buildTable();
+ const blue=[...document.querySelectorAll('#pals .pchip')].find(c=>c.querySelector('.nm')&&c.querySelector('.nm').value==='blue');
+ A(!!(blue&&blue.querySelector('.rm')),'blue chip has a remove button');
+ if(blue&&blue.querySelector('.rm'))blue.querySelector('.rm').click();
+ A(!PALETTE.some(p=>p[1]==='blue'),'blue was deleted');
+ A(lastGone['blue']==='#67809c','delete recorded the gone name->hex');
+ document.getElementById('newhexstr').value='#5a7a9a';document.getElementById('newname').value='blue';selectedIdx=null;addColor();
+ A(MAP['kw']==='#5a7a9a','assignment re-bound to the recreated name, got '+MAP['kw']);
+ A(!('blue' in lastGone),'heal consumed the gone entry');
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveU);PKGMAP=savePK;lastGone=saveG;selectedIdx=saveSel;
+ renderPalette();buildTable();buildUITable();if(document.getElementById('pkgbody'))buildPkgTable();
+ document.title='HEALTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='healtest';d.textContent='HEALTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Family-strip gate (open with #familytest): the palette renders as the pinned
+// ground strip plus hue families, chips keep their controls, and renaming a color
+// to anything leaves it in the same strip (grouping is by hex, not name).
+if(location.hash==='#familytest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveSel=selectedIdx;
+ MAP['bg']='#0d0b0a';MAP['p']='#f0fef0';
+ PALETTE=[['#0d0b0a','ground'],['#f0fef0','fg'],['#c0402a','red'],['#3a6ea5','blue'],['#808080','gray']];selectedIdx=null;renderPalette();
+ const strips=[...document.querySelectorAll('#pals .fstrip')];
+ A(strips.length&&strips[0].classList.contains('ground'),'ground strip is pinned first');
+ A(strips[0].querySelectorAll('.pchip').length===2,'ground strip carries bg + fg');
+ A(strips.length>=4,'ground + neutral + red + blue strips, got '+strips.length);
+ const redChip=[...document.querySelectorAll('#pals .pchip')].find(c=>c.querySelector('.nm')&&c.querySelector('.nm').value==='red');
+ A(!!redChip&&!!redChip.querySelector('.rm')&&!!redChip.querySelector('.nm'),'a family chip keeps remove + rename controls');
+ const redFamily=redChip&&redChip.closest('.fstrip').dataset.family;
+ const ri=PALETTE.findIndex(p=>p[1]==='red');PALETTE[ri][1]='zztop-absurd';renderPalette();
+ const renamed=[...document.querySelectorAll('#pals .pchip')].find(c=>c.querySelector('.nm')&&c.querySelector('.nm').value==='zztop-absurd');
+ A(!!renamed&&renamed.closest('.fstrip').dataset.family===redFamily,'a renamed color stays in the same strip');
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);selectedIdx=saveSel;renderPalette();
+ document.title='FAMILYTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='familytest';d.textContent='FAMILYTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Count-control gate (open with #counttest): the per-family count regenerates the
+// family — count up adds symmetric steps, count down drops the extremes, a
+// reference to a surviving step follows the new hex, a reference to a removed step
+// is left on its old (now-gone) hex.
+if(location.hash==='#counttest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveU=JSON.parse(JSON.stringify(UIMAP)),saveSel=selectedIdx;
+ MAP['bg']='#000000';MAP['p']='#f0fef0';
+ PALETTE=[['#0d0b0a','ground'],['#f0fef0','fg']];
+ regenFamily('#67809c',2).members.forEach(m=>PALETTE.push([m.hex,m.offset===0?'blue':'blue'+(m.offset>0?'+'+m.offset:m.offset)]));
+ const innerOld=regenFamily('#67809c',2).members.find(m=>m.offset===1).hex; // survives a count change
+ const outerOld=regenFamily('#67809c',2).members.find(m=>m.offset===2).hex; // dropped on count-down
+ UIMAP['region']={fg:null,bg:innerOld,bold:false,italic:false,underline:false,strike:false};
+ UIMAP['highlight']={fg:null,bg:outerOld,bold:false,italic:false,underline:false,strike:false};
+ selectedIdx=null;renderPalette();
+ setFamilyCount('#67809c',1);
+ const palHexes=new Set(PALETTE.map(p=>p[0].toLowerCase()));
+ A(!palHexes.has(outerOld.toLowerCase()),'outer step removed from palette on count down');
+ A(UIMAP['highlight'].bg.toLowerCase()===outerOld.toLowerCase(),'a removed-step reference stays on its old (gone) hex');
+ const newInner=regenFamily('#67809c',1).members.find(m=>m.offset===1).hex;
+ A(UIMAP['region'].bg.toLowerCase()===newInner.toLowerCase(),'a surviving-step reference followed the regenerate, got '+UIMAP['region'].bg);
+ setFamilyCount('#67809c',3);
+ const want3=regenFamily('#67809c',3).members.map(m=>m.hex.toLowerCase());
+ const have=new Set(PALETTE.map(p=>p[0].toLowerCase()));
+ A(want3.every(h=>have.has(h)),'count up to 3 adds all 7 ramp colors to the palette');
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveU);selectedIdx=saveSel;renderPalette();
+ document.title='COUNTTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='counttest';d.textContent='COUNTTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Base-edit + ground-edit gate (open with #baseedittest): editing a family base
+// recolors the whole family at the same count and references follow; editing a
+// ground swatch writes the bg/fg assignment.
+if(location.hash==='#baseedittest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const saveP=PALETTE.slice(),saveM=Object.assign({},MAP),saveU=JSON.parse(JSON.stringify(UIMAP)),saveSel=selectedIdx;
+ MAP['bg']='#0d0b0a';MAP['p']='#f0fef0';
+ PALETTE=[['#0d0b0a','ground'],['#f0fef0','fg']];
+ regenFamily('#67809c',2).members.forEach(m=>PALETTE.push([m.hex,m.offset===0?'blue':'blue'+(m.offset>0?'+'+m.offset:m.offset)]));
+ UIMAP['region']={fg:null,bg:'#67809c',bold:false,italic:false,underline:false,strike:false};
+ renderPalette();buildUITable();
+ selectedIdx=PALETTE.findIndex(p=>p[0].toLowerCase()==='#67809c');
+ document.getElementById('newhexstr').value='#3a8a8a';document.getElementById('newname').value='teal';
+ updateColor();
+ const fam=familiesFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']}).families.find(f=>!f.neutral);
+ A(fam&&fam.members.some(m=>m.hex.toLowerCase()==='#3a8a8a'),'family base recolored to the new hex');
+ A(fam&&fam.members.length===5,'count preserved (±2 → 5 members), got '+(fam&&fam.members.length));
+ A(!new Set(PALETTE.map(p=>p[0].toLowerCase())).has('#67809c'),'old base removed from palette');
+ A(UIMAP['region'].bg.toLowerCase()==='#3a8a8a','a reference to the base followed to the new base hex');
+ // ground edit: select bg, change hex, MAP.bg follows
+ selectedIdx=PALETTE.findIndex(p=>p[0].toLowerCase()==='#0d0b0a');
+ document.getElementById('newhexstr').value='#101010';document.getElementById('newname').value='ground';
+ updateColor();
+ A(MAP['bg'].toLowerCase()==='#101010','editing the bg swatch wrote the bg assignment, got '+MAP['bg']);
+ PALETTE=saveP;for(const k in MAP)delete MAP[k];Object.assign(MAP,saveM);for(const f in UIMAP)delete UIMAP[f];Object.assign(UIMAP,saveU);selectedIdx=saveSel;renderPalette();
+ document.title='BASEEDITTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='baseedittest';d.textContent='BASEEDITTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
+// Round-trip gate (open with #roundtriptest): export stays a flat palette and
+// import needs no family reconstruction, so export → import → export is identical.
+if(location.hash==='#roundtriptest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}};
+ const before=JSON.stringify(exportObj());
+ applyImported(before);
+ const after=JSON.stringify(exportObj());
+ A(before===after,'export → import → export is byte-identical');
+ const obj=JSON.parse(after);
+ A(Array.isArray(obj.palette)&&obj.palette.every(e=>Array.isArray(e)&&e.length===2),'exported palette is still a flat [hex,name] list');
+ document.title='ROUNDTRIPTEST '+(ok?'PASS':'FAIL');
+ const d=document.createElement('div');d.id='roundtriptest';d.textContent='ROUNDTRIPTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);}
</script> \ No newline at end of file