diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-14 18:14:29 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-14 18:14:29 -0500 |
| commit | 214c16fe127e007965b21d38d0c9c24f8c995b4c (patch) | |
| tree | b4a54af6a928122c3f8af374618b07da5fc798c8 /scripts/theme-studio | |
| parent | 814f7dbf74af01e7932be7a994ecc8297e843f37 (diff) | |
| download | dotemacs-214c16fe127e007965b21d38d0c9c24f8c995b4c.tar.gz dotemacs-214c16fe127e007965b21d38d0c9c24f8c995b4c.zip | |
feat(theme-studio): palette generator and preview fidelity
Two strands land together because the generated theme-studio.html bundles every source file into one page and can't be split cleanly.
The palette generator is a preview-first panel: palette-generator-core.js plans the palette and palette-generator-ui.js draws it. Generated colors stay inspectable and tunable through the existing selector, and committing one creates a normal base column. It adds source-mode and scheme controls, a configurable accent count, and color names from color-names.json.
For preview fidelity, syntax and UI colors now resolve through the real Emacs inherit chains, so the preview matches how Emacs renders the theme. resolveSyntaxFg pins dec to ty (Emacs has no decorator face) and otherwise follows comment-delimiter to comment, doc to string, property to variable, function-call to function-name. resolveUiAttr walks mode-line-inactive to mode-line and line-number-current-line to line-number. The decorator label now reads "decorator to type" to match the type face Emacs uses for it.
Design recorded in the two theme-studio specs under docs/.
Diffstat (limited to 'scripts/theme-studio')
| -rw-r--r-- | scripts/theme-studio/README.md | 28 | ||||
| -rw-r--r-- | scripts/theme-studio/app-core.js | 53 | ||||
| -rw-r--r-- | scripts/theme-studio/app.js | 117 | ||||
| -rw-r--r-- | scripts/theme-studio/browser-gates.js | 90 | ||||
| -rw-r--r-- | scripts/theme-studio/color-names.json | 542 | ||||
| -rw-r--r-- | scripts/theme-studio/generate.py | 10 | ||||
| -rw-r--r-- | scripts/theme-studio/palette-generator-core.js | 267 | ||||
| -rw-r--r-- | scripts/theme-studio/palette-generator-ui.js | 152 | ||||
| -rwxr-xr-x | scripts/theme-studio/run-tests.sh | 2 | ||||
| -rw-r--r-- | scripts/theme-studio/styles.css | 24 | ||||
| -rw-r--r-- | scripts/theme-studio/test-app-core.mjs | 441 | ||||
| -rw-r--r-- | scripts/theme-studio/test_generate.py | 8 | ||||
| -rw-r--r-- | scripts/theme-studio/theme-studio.html | 709 | ||||
| -rw-r--r-- | scripts/theme-studio/theme-studio.template.html | 13 | ||||
| -rw-r--r-- | scripts/theme-studio/theme.json | 1000 |
15 files changed, 2953 insertions, 503 deletions
diff --git a/scripts/theme-studio/README.md b/scripts/theme-studio/README.md index 6ca3285ec..df3d92607 100644 --- a/scripts/theme-studio/README.md +++ b/scripts/theme-studio/README.md @@ -30,6 +30,34 @@ During color work, disable Hyprland inactive-window dimming so colors read true: hyprctl keyword decoration:dim_inactive false ``` +## Build A Theme + +Convert a Theme Studio JSON export into a loadable Emacs theme: + +```bash +make theme-studio-theme JSON=/path/to/theme.json +``` + +That writes `themes/<name>-theme.el`, where `<name>` comes from the JSON +`name` field. To write somewhere else: + +```bash +make theme-studio-theme JSON=/path/to/theme.json OUT=/tmp/themes +``` + +To apply a generated theme in the current Emacs session after disabling every +enabled custom theme: + +```bash +make theme-studio-theme-load THEME=theme +``` + +To rebuild a JSON export and cleanly reload the theme named by that JSON: + +```bash +make theme-studio-theme-reload JSON=/path/to/theme.json +``` + ## Tests ```bash diff --git a/scripts/theme-studio/app-core.js b/scripts/theme-studio/app-core.js index 5da521773..2761031b9 100644 --- a/scripts/theme-studio/app-core.js +++ b/scripts/theme-studio/app-core.js @@ -33,6 +33,51 @@ function mergePackagesInto(map,pkgs){if(!pkgs)return;for(const app in pkgs){if(! // against an inherit cycle (returns null rather than recursing forever). function effResolve(map,app,face,attr,seen){seen=seen||{};const f=map[app]&&map[app][face];if(!f||seen[face])return null;seen[face]=1;if(f[attr])return f[attr];if(f.inherit&&map[app][f.inherit])return effResolve(map,app,f.inherit,attr,seen);return null;} +// Emacs built-in inherit chains for the syntax categories theme studio exposes. +// An unset category foreground resolves the way the generated theme renders in +// Emacs: build-theme.el writes no override for an unset face, so Emacs falls back +// to the face's own :inherit -- comment-delimiter->comment, doc->string, +// property-name->variable-name, function-call->function-name -- not to the +// default foreground. +const SYNTAX_INHERIT={cmd:'cm',doc:'str',prop:'var',fnc:'fnd'}; + +// Effective foreground for a syntax category, following the Emacs inherit chain. +// SYNTAX maps category -> face object with an optional `fg`; DEFAULTFG is the +// theme's default foreground (the chain's floor). `dec` (decorator) is pinned to +// `ty`: Emacs has no decorator face and renders decorators with +// font-lock-type-face, so a dec color set in the studio would never reach Emacs. +function resolveSyntaxFg(cat,syntax,defaultFg){ + let k=(cat==='dec')?'ty':cat; + const seen={}; + while(k&&!seen[k]){ + seen[k]=1; + const fg=syntax[k]&&syntax[k].fg; + if(fg)return fg; + k=SYNTAX_INHERIT[k]; + } + return defaultFg; +} + +// Emacs built-in inherit chains for the ui faces whose parent is also a studio ui +// face, so an unset attribute previews the way Emacs renders it: mode-line-inactive +// inherits mode-line, line-number-current-line inherits line-number. +const UI_INHERIT={'mode-line-inactive':'mode-line','line-number-current-line':'line-number'}; + +// First set value of ATTR ('fg'/'bg') for ui FACE, walking UI_INHERIT; null when +// nothing up the chain is set. The caller applies its own floor (default fg, +// ground, or transparent), since that floor differs per attribute and face. +function resolveUiAttr(face,attr,uimap){ + let f=face; + const seen={}; + while(f&&!seen[f]){ + seen[f]=1; + const v=uimap[f]&&uimap[f][attr]; + if(v)return v; + f=UI_INHERIT[f]; + } + return null; +} + // Standard swatch-dropdown option list: a default entry, then the palette. When // cur is set but no longer in the palette, surface it as a "(gone)" entry first. function optList(cur,palette){const have=cur===''||palette.some(p=>p[0]===cur);return [['','— default —'],...(have?palette:[[cur,'(gone)'],...palette])];} @@ -93,9 +138,9 @@ function fgSetFor(face,state){ 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); + const add=(hex,label,name,isRole)=>{const k=hex.toLowerCase(),cur=byHex.get(k);if(!cur)byHex.set(k,{hex:k,label,name:name||label});else if(isRole&&cur.label==='default'){cur.label=label;cur.name=name||label;}}; + if(state&&state.defaultFg)add(state.defaultFg,'default','default',false); + for(const a of syn)add(a.hex,a.role||a.hex,a.name||a.role||a.hex,true); return {set:[...byHex.values()]}; } @@ -322,4 +367,4 @@ function spanNeighborHex(cur,palette,ground,dir){ return null; } -export { nameToHex, normalizePkgFace, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList, paletteOptionList, spanNeighborHex, slugify, ramp, fgSetFor, floor, lMax, COVERED_FACES, columnsFromPalette, regenColumn, rankByLightness, stepRepointPlan, sortColumns, sortColumnMembers, groundRoleOfEntry, groundColumnMembersFromPalette, clearPalettePlan, deletePaletteColumnPlan, areAllLocked, lockToggleLabel, toggleLockSet }; +export { nameToHex, normalizePkgFace, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, resolveSyntaxFg, resolveUiAttr, optList, paletteOptionList, spanNeighborHex, slugify, ramp, fgSetFor, floor, lMax, COVERED_FACES, columnsFromPalette, regenColumn, rankByLightness, stepRepointPlan, sortColumns, sortColumnMembers, groundRoleOfEntry, groundColumnMembersFromPalette, clearPalettePlan, deletePaletteColumnPlan, areAllLocked, lockToggleLabel, toggleLockSet }; diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js index 45b1f4864..4b331c555 100644 --- a/scripts/theme-studio/app.js +++ b/scripts/theme-studio/app.js @@ -1,4 +1,5 @@ const SAMPLES=SAMPLES_J, CATS=CATS_J, UI_FACES=UIFACES_J, APPS=APPS_J; +const COLOR_NAMES=COLOR_NAMES_J; let MAP=MAP_J, PALETTE=PALETTE_J, SYNTAX=SYNTAX_J, UIMAP=UIMAP_J; let LOCKED=new Set(LOCKS_J); // rows whose choice is decided (controls disabled, skipped by erase/reset batch actions) const DELTAE_MIN=0.02; // OKLab ΔE below this = colors too close to tell apart (perceptual-metrics spec) @@ -28,9 +29,13 @@ APP_CORE_J // Pure color/UI-boundary helpers (normHex, ratingColor, textOn), inlined from // app-util.js. textOn uses rl from the colormath core above. APP_UTIL_J +// Pure palette-generator planner and browser-side generator panel. +PALETTE_GENERATOR_CORE_J +PALETTE_GENERATOR_UI_J // The contrast-cell readout shared by every table: a WCAG ratio colored by its -// AA/AAA rating, with the rating word. Callers compute r for their own fg/bg. -function crHtml(r){return `<span style="color:${ratingColor(r)}">${r.toFixed(1)} ${rating(r)}</span>`;} +// table verdict. Callers compute r for their own fg/bg. +function verdictFor(r,target=4.5){return r>=target?'PASS':'FAIL';} +function crHtml(r,target=4.5){const v=verdictFor(r,target);return `<span style="color:${ratingColor(r)}">${r.toFixed(1)} ${v}</span>`;} // Effective fg/bg with the standard fallback: an unset foreground reads as the // default fg (MAP['p']), an unset background as the ground (MAP['bg']). All three // tiers resolve their raw value through these before measuring or rendering. @@ -61,21 +66,25 @@ function mkColorDropdown(options,cur,onPick,opts={}){ left.textContent='‹';right.textContent='›';left.title='move to next darker color in this column';right.title='move to next lighter color in this column'; const t=document.createElement('div');t.className='cdd'+(opts.compact?' compact':'');t.tabIndex=0; const nameOf=h=>{const o=options.find(p=>p[0]===h);return o?o[1]:(h||'none');}; + const displayHex=h=>h||(opts.defaultHex||''); + const displayName=h=>h?nameOf(h):(opts.defaultName||nameOf(h)); function step(dir){if(wrap.dataset.locked==='1')return;const next=spanNeighborHex(cur,PALETTE,{bg:MAP['bg'],fg:MAP['p']},dir);if(!next)return;cur=next;paint();onPick(next);} function paintStepButtons(){ const locked=wrap.dataset.locked==='1'; left.disabled=locked||!spanNeighborHex(cur,PALETTE,{bg:MAP['bg'],fg:MAP['p']},-1); right.disabled=locked||!spanNeighborHex(cur,PALETTE,{bg:MAP['bg'],fg:MAP['p']},1); } - function paint(){const nm=nameOf(cur),ttl=cur?(nm+' '+cur):nm;t.style.background=cur||'#161412';t.style.color=cur?textOn(cur):'#b4b1a2';t.dataset.val=cur||'';t.title=ttl;t.classList.toggle('is-default',!cur); - t.innerHTML=opts.compact?`<span class="cddsw" style="background:${cur||'transparent'}"></span>`:`<span class="cddsw" style="background:${cur||'transparent'}"></span>${esc(nm)}`;paintStepButtons();} + function paint(){const shown=displayHex(cur),nm=displayName(cur),ttl=cur?(nm+' '+cur):(nm+(shown?' -> '+shown:''));t.style.background=shown||'#161412';t.style.color=shown?textOn(shown):'#b4b1a2';t.dataset.val=cur||'';t.title=ttl;t.classList.toggle('is-default',!cur); + t.innerHTML=opts.compact?`<span class="cddsw" style="background:${shown||'transparent'}"></span>`:`<span class="cddsw" style="background:${shown||'transparent'}"></span>${esc(nm)}`;paintStepButtons();} paint(); left.onclick=e=>{e.stopPropagation();step(-1);}; right.onclick=e=>{e.stopPropagation();step(1);}; t.onclick=(e)=>{e.stopPropagation();if(wrap.dataset.locked==='1')return;if(_ddPop){closeColorDropdown();return;} const pop=document.createElement('div');pop.className='cddpop'; for(const [hex,name] of options){const row=document.createElement('div');row.className='cddrow'+(hex===cur?' sel':''); - row.innerHTML=`<span class="cddsw" style="background:${hex||'transparent'}"></span><span class="cddnm">${esc(name)}</span><span class="cddhx">${hex||''}</span>`; + const shown=displayHex(hex),nm=hex?name:(opts.defaultName||name); + row.style.background=hex?'':shown;row.style.color=shown?textOn(shown):''; + row.innerHTML=`<span class="cddsw" style="background:${shown||'transparent'}"></span><span class="cddnm">${esc(nm)}</span><span class="cddhx">${hex||shown||''}</span>`; row.onclick=(ev)=>{ev.stopPropagation();cur=hex;paint();closeColorDropdown();onPick(hex);}; pop.appendChild(row);} document.body.appendChild(pop);const r=t.getBoundingClientRect(); @@ -182,8 +191,8 @@ function buildTable(){ function rowBg(){return syntaxFace(kind).bg||MAP['bg'];} function styleEx(){const s=syntaxFace(kind);exTd.style.color=rowFg();exTd.style.background=rowBg();exTd.style.fontWeight=s.bold?'bold':'normal';exTd.style.fontStyle=s.italic?'italic':'normal';exTd.style.textDecoration=(s.underline?'underline ':'')+(s.strike?'line-through':'')||'none';exTd.style.boxShadow=boxCss(s.box,rowBg());} function styleCr(){const r=contrast(rowFg(),rowBg());crTd.innerHTML=crHtml(r);} - const dd=mkColorDropdown(list,cur,(hex)=>{const s=syntaxFace(kind);s.fg=hex||null;syncSyntaxCache(kind);styleEx();styleCr();renderCode();if(kind==='bg'||kind==='p'){applyGround();buildTable();buildPkgTable();buildPkgPreview();}repaintCovered();},{compact:true}); - const bgd=mkColorDropdown(ddList(sf.bg||''),sf.bg||'',hex=>{const s=syntaxFace(kind);s.bg=hex||null;styleEx();styleCr();renderCode();repaintCovered();},{compact:true}); + const dd=mkColorDropdown(list,cur,(hex)=>{const s=syntaxFace(kind);s.fg=hex||null;syncSyntaxCache(kind);styleEx();styleCr();renderCode();if(kind==='bg'||kind==='p'){applyGround();buildTable();buildPkgTable();buildPkgPreview();}repaintCovered();},{compact:true,defaultHex:rowFg()}); + const bgd=mkColorDropdown(ddList(sf.bg||''),sf.bg||'',hex=>{const s=syntaxFace(kind);s.bg=hex||null;styleEx();styleCr();renderCode();repaintCovered();},{compact:true,defaultHex:rowBg()}); styleEx();styleCr(); const stTd=document.createElement('td'); const stBtns=mkStyleButtons(at=>syntaxFace(kind)[at],at=>{const s=syntaxFace(kind);s[at]=!s[at];styleEx();renderCode();}); @@ -200,7 +209,7 @@ function buildTable(){ PALETTE_ACTIONS_J 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 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 selectColor(i){selectedIdx=i;GEN_SELECTION=null;const [hex,name]=PALETTE[i];setHex(hex);document.getElementById('newname').value=name;renderPalette();renderGeneratorPreview();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;} const i=selectedIdx,oldHex=PALETTE[i][0],oldRole=groundRoleOfEntry(PALETTE[i],{bg:MAP['bg'],fg:MAP['p']}); @@ -319,8 +328,9 @@ 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,columnIdOf([h,name])]);const healed=healGone(name,h);document.getElementById('newname').value='';selectedIdx=null;closePicker(); + PALETTE.push([h,name,columnIdOf([h,name])]);const healed=healGone(name,h);document.getElementById('newname').value='';selectedIdx=null;GEN_SELECTION=null;closePicker(); refreshPaletteState({code:healed,ground:healed,pkgPreview:healed}); + renderGeneratorPreview(); notify(healed?('added "'+name+'" and reconnected its face references'):('added "'+name+'"'),false);} function themeName(){return (document.getElementById('themename').value||'theme').trim()||'theme';} function fileSlug(){return slugify(themeName());} @@ -366,7 +376,7 @@ function boxCss(b,bg){if(!b||!b.style)return '';const w=b.width||1; 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'}`;} -function syntaxStyle(k){const s=syntaxFace(k),fg=(k==='bg'?MAP['p']:effFg(s.fg)),bg=s.bg||null,dec=(s.underline?'underline ':'')+(s.strike?'line-through':''), +function syntaxStyle(k){const s=syntaxFace(k),fg=(k==='bg'?MAP['p']:resolveSyntaxFg(k,SYNTAX,MAP['p'])),bg=s.bg||null,dec=(s.underline?'underline ':'')+(s.strike?'line-through':''), bx=boxCss(s.box,bg||MAP['bg']); return `color:${fg};${bg?'background:'+bg+';':''}font-weight:${s.bold?'bold':'normal'};font-style:${s.italic?'italic':'normal'};text-decoration:${dec.trim()||'none'}${bx?';box-shadow:'+bx:''}`;} // The per-row box control: none / line / raised / pressed plus optional line @@ -374,7 +384,7 @@ function syntaxStyle(k){const s=syntaxFace(k),fg=(k==='bg'?MAP['p']:effFg(s.fg)) function mkBoxControl(get,set,opts={}){const wrap=document.createElement('div');wrap.className='boxctl'; const s=document.createElement('select');s.className='chip';s.style.cssText='width:84px;font:10pt monospace'; [['','no box'],['line','line'],['released','raised'],['pressed','pressed']].forEach(([v,l])=>{const o=document.createElement('option');o.value=v;o.textContent=l;s.appendChild(o);}); - const dd=mkColorDropdown(ddList((get()&&get().color)||''),(get()&&get().color)||'',h=>{const cur=get();if(!cur)return;set(Object.assign({},cur,{color:h||null}));},{compact:!!opts.compact}); + const dd=mkColorDropdown(ddList((get()&&get().color)||''),(get()&&get().color)||'',h=>{const cur=get();if(!cur)return;set(Object.assign({},cur,{color:h||null}));},{compact:!!opts.compact,defaultHex:opts.defaultHex}); function paint(){const cur=get();s.value=cur&&cur.style?cur.style:'';dd.setValue(cur&&cur.color?cur.color:''); const off=!cur||!cur.style||wrap.dataset.locked==='1';dd.dataset.locked=off?'1':'';dd.classList.toggle('locked',off);if(dd.syncLocked)dd.syncLocked();} s.onchange=()=>{const cur=get();set(s.value?{style:s.value,width:cur&&cur.width||1,color:cur&&cur.color||null}:null);paint();}; @@ -444,7 +454,7 @@ function buildMockFrame(){ let buf=''; lines.forEach((L,i)=>{ const isc=L.cur; - const nFg=isc?(lnc.fg||fg):(ln.fg||fg), nBg=isc?(lnc.bg||'transparent'):(ln.bg||'transparent'); + const nFg=isc?(resolveUiAttr('line-number-current-line','fg',UIMAP)||fg):(ln.fg||fg), nBg=isc?(resolveUiAttr('line-number-current-line','bg',UIMAP)||'transparent'):(ln.bg||'transparent'); const rowFace=isc?hl:null,rowStyle=rowFace?uiCss(rowFace,rowFace.fg||'inherit',rowFace.bg||'transparent'):'background:transparent'; let cd; if(isc)cd=withCursor(L.t); @@ -459,9 +469,9 @@ function buildMockFrame(){ const nFace=isc?'line-number-current-line':'line-number'; buf+=`<div class="ln" ${rowFace?'data-face="hl-line" ':''}style="${rowStyle}"><span class="fr" data-face="fringe" style="${uiCss(frng,frng.fg||fg,frng.bg||bg)};text-align:center;font-size:10px;overflow:hidden" title="fringe">${L.cont?'↪':''}</span><span class="num" data-face="${nFace}" style="${uiCss(isc?lnc:ln,nFg,nBg)}">${i+1}</span><span class="cd">${cd||' '}</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>`; + let html=`<div class="mbuf" style="background:${bg}"><div class="mbuftext">${buf}</div><div class="vborder" data-face="vertical-border" title="vertical-border" style="background:${vb.fg||vb.bg||'#2f343a'}"></div></div>`; html+=`<div class="bar" data-face="mode-line" style="${uiCss(ml,ml.fg||bg,ml.bg||fg)}"> init.el (Emacs Lisp) L5 git:main </div>`; - html+=`<div class="bar" data-face="mode-line-inactive" style="${uiCss(mli,mli.fg||fg,mli.bg||bg)}"> *Messages* (Fundamental) </div>`; + html+=`<div class="bar" data-face="mode-line-inactive" style="${uiCss(mli,resolveUiAttr('mode-line-inactive','fg',UIMAP)||fg,resolveUiAttr('mode-line-inactive','bg',UIMAP)||bg)}"> *Messages* (Fundamental)</div>`; html+=`<div class="echo" style="color:${fg}"><span data-face="minibuffer-prompt" style="${uiCss(mb,mb.fg||fg,mb.bg||null)}">I-search:</span> count <span data-face="isearch-fail" style="${uiCss(isf,isf.fg||fg,isf.bg||'transparent')}">zzz [no match]</span></div>`; html+=`<div class="echo"><span data-face="link" style="${uiCss(lnk,lnk.fg||fg,lnk.bg||null)}">https://gnu.org</span> <span data-face="error" style="${uiCss(err,err.fg||fg,err.bg||null)}">error</span> <span data-face="warning" style="${uiCss(wrn,wrn.fg||fg,wrn.bg||null)}">warning</span> <span data-face="success" style="${uiCss(suc,suc.fg||fg,suc.bg||null)}">ok</span></div>`; fr.innerHTML=html;fr.style.background=bg;fr.style.color=fg; @@ -471,7 +481,7 @@ function buildMockFrame(){ // native <select> rendered swatch colors unreliably on Linux Chrome, so it is // gone. '' (the default entry) maps back to null in the stored model. function uiSelect(face,attr){const cur=UIMAP[face][attr]||''; - return mkColorDropdown(ddList(cur),cur,h=>{UIMAP[face][attr]=h||null;paintUI(face);buildMockFrame();},{compact:true});} + return mkColorDropdown(ddList(cur),cur,h=>{UIMAP[face][attr]=h||null;paintUI(face);buildMockFrame();},{compact:true,defaultHex:attr==='fg'?effFg(null):effBg(null)});} const BASE_INHERITS=['fixed-pitch','variable-pitch','default','link','bold','italic','shadow']; function uiFaceBlank(){return {fg:null,bg:null,bold:false,italic:false,underline:false,strike:false};} function seedFace(d){return normalizePkgFace({fg:pname(d.fg),bg:pname(d.bg),bold:d.bold,italic:d.italic,underline:d.underline,strike:d.strike,inherit:d.inherit,height:d.height,box:d.box},'default');} @@ -488,8 +498,8 @@ function buildPkgTable(){ if(flt&&!(face.toLowerCase().includes(flt)||label.toLowerCase().includes(flt)))continue; const f=PKGMAP[app][face],tr=document.createElement('tr');tr.dataset.face=face; const c0=document.createElement('td');c0.className='cat';c0.textContent=label;c0.title=face;c0.style.cursor='pointer';c0.onclick=()=>flashPkgPreview(face); - const fgd=mkColorDropdown(ddList(f.fg||''),f.fg||'',h=>{f.fg=h||null;f.source='user';pkgChanged();},{compact:true}), - bgd=mkColorDropdown(ddList(f.bg||''),f.bg||'',h=>{f.bg=h||null;f.source='user';pkgChanged();},{compact:true}); + const fgd=mkColorDropdown(ddList(f.fg||''),f.fg||'',h=>{f.fg=h||null;f.source='user';pkgChanged();},{compact:true,defaultHex:effFg(pkgEffFg(app,face))}), + bgd=mkColorDropdown(ddList(f.bg||''),f.bg||'',h=>{f.bg=h||null;f.source='user';pkgChanged();},{compact:true,defaultHex:effBg(pkgEffBg(app,face))}); const cf=document.createElement('td');cf.appendChild(fgd); const cb=document.createElement('td');cb.appendChild(bgd); const cw=document.createElement('td'); @@ -624,17 +634,31 @@ function renderGhostelPreview(){const a='ghostel',L=[]; L.push(os(a,'ghostel-default','default terminal output, 256-color text and a blinking ')+os(a,'ghostel-fake-cursor','cursor')+'.'); return `<div style="padding:12px 16px;font:12pt/1.7 monospace;white-space:pre">${L.join('\n')}</div>`;} function renderDashboardPreview(){const a='dashboard',L=[]; - L.push(os(a,'dashboard-text-banner',' ___ _ __ ___ __ _ ___ ___')); - L.push(os(a,'dashboard-banner-logo-title',' Welcome back, Craig')); + L.push(os(a,'dashboard-text-banner',' [ dashboard banner image ]')); + L.push(os(a,'dashboard-banner-logo-title','Emacs: The Editor That Saves Your Soul')); + L.push(''); + L.push(os(a,'dashboard-navigator',' Code Files Terminal Agenda')); + L.push(os(a,'dashboard-navigator',' Feeds Books Flashcards Music')); + L.push(os(a,'dashboard-navigator',' Email IRC Telegram')); + L.push(os(a,'dashboard-navigator',' Slack Linear')); + L.push(''); + L.push(''); + L.push(os(a,'dashboard-heading','Projects:')); + L.push(' ~/'); + L.push(' ~/.emacs.d/'); + L.push(' ~/projects/work/'); + L.push(' ~/org/roam/'); + L.push(' ~/projects/home/'); L.push(''); - L.push(os(a,'dashboard-heading','Recent Files')); - L.push(' '+os(a,'dashboard-items-face','init.el')); - L.push(' '+os(a,'dashboard-items-face','notes.org')); L.push(os(a,'dashboard-heading','Bookmarks')); - L.push(' '+os(a,'dashboard-no-items-face','-- no items --')); + L.push(' Cesar Aira, The Little Buddhist Monk & the Proof'); + L.push(' Edward Abbey, The Fool’s Progress: An Honest Novel'); + L.push(' Agatha Christie, The A.B.C. Murders'); L.push(''); - L.push(os(a,'dashboard-navigator','[ Projects ] [ Recent ] [ Agenda ]')); - L.push(os(a,'dashboard-footer-icon-face','*')+' '+os(a,'dashboard-footer-face','Happy hacking, Craig!')); + L.push(os(a,'dashboard-heading','Recent Files:')); + L.push(' theme-theme.el'); + L.push(' todo.org'); + L.push(' theme-studio-palette-generator-spec.org'); return `<div style="padding:12px 16px;font:12pt/1.7 monospace;white-space:pre">${L.join('\n')}</div>`;} function renderMu4ePreview(){const a='mu4e',L=[]; L.push(os(a,'mu4e-title-face','mu4e')+' '+os(a,'mu4e-context-face','[Personal]')+' '+os(a,'mu4e-ok-face','online')+' '+os(a,'mu4e-warning-face','2 retry')+' '+os(a,'mu4e-modeline-face','12/340')); @@ -827,25 +851,47 @@ 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(syntaxFace(c[0]).fg)})); + const syntaxAssignments=CATS.filter(c=>c[0]!=='bg'&&c[0]!=='p').map(c=>({role:c[0],name:c[1],hex:effFg(syntaxFace(c[0]).fg)})); 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){ +function coveredContrastReport(face){ + if(uf(face).fg)return null; 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>`; + if(r.reason==='empty'||!r.set.length)return {empty:true}; + const bg=effBg(uf(face).bg); + const rows=r.set.map(f=>{ + const ratio=contrast(f.hex,bg); + return {label:f.label,name:f.name||f.label,hex:f.hex,ratio,verdict:verdictFor(ratio,WORST_TARGET)}; + }).sort((a,b)=>a.ratio-b.ratio); + return {bg,rows,worst:rows[0],failures:rows.filter(x=>x.ratio<WORST_TARGET)}; +} +function failureTitle(report){ + if(!report||!report.failures||!report.failures.length)return ''; + const lines=['failing covered-text contrasts against '+report.bg+':']; + report.failures.forEach(f=>lines.push(`${f.ratio.toFixed(1)} FAIL ${f.label} (${f.name}) ${f.hex}`)); + return lines.join('\n'); +} +// The worst-case contrast cell for a covered face: the floor over its foreground +// set against its effective background. Returns null for an out-of-scope face so +// the caller keeps the single-pair readout. +function worstCellHtml(face){ + const report=coveredContrastReport(face); + if(report===null)return null; + if(report.empty)return '<span title="this overlay has no syntax foreground set yet">no fg set</span>'; + return `<span style="color:${ratingColor(report.worst.ratio)}" title="${esc(failureTitle(report)||'all covered text clears '+WORST_TARGET.toFixed(1))}">${report.worst.ratio.toFixed(1)} ${report.worst.verdict}</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);}}} + const report=coveredContrastReport(face); + pv.querySelectorAll('.crerr').forEach(e=>e.remove()); + pv.title=''; + if(report&&report.failures&&report.failures.length){ + const badge=document.createElement('span');badge.className='crerr';badge.textContent=report.worst.ratio.toFixed(1)+' FAIL';badge.title=failureTitle(report);pv.title=badge.title;pv.appendChild(badge); + } + const cr=document.getElementById('uicr-'+face);if(cr){cr.title='';if(report!==null){if(report.empty){cr.title='this overlay has no syntax foreground set yet';cr.innerHTML='<span title="this overlay has no syntax foreground set yet">no fg set</span>';}else{const title=failureTitle(report)||'all covered text clears '+WORST_TARGET.toFixed(1);cr.title=title;cr.innerHTML=`<span style="color:${ratingColor(report.worst.ratio)}" title="${esc(title)}">${report.worst.ratio.toFixed(1)} ${report.worst.verdict}</span>`;}}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){ @@ -877,6 +923,7 @@ function srtTable(tbId,col){tableSort[tbId]={col,asc:!(tableSort[tbId]&&tableSor function applyTableSort(tbId){const s=tableSort[tbId];if(!s)return;const tb=document.getElementById(tbId);if(!tb)return;const dir=s.asc?1:-1;const r=[...tb.rows];r.sort((a,b)=>{const x=cellVal(a.cells[s.col]),y=cellVal(b.cells[s.col]);return ((typeof x==='number'&&typeof y==='number')?x-y:(x<y?-1:x>y?1:0))*dir;});r.forEach(x=>tb.appendChild(x));} function initApp(){ buildLangSel();buildAppSel();renderPalette();rebuildColorTables();renderCode();applyGround(); + initGeneratorControls(); updateTitle();initPicker();buildPkgPreview();syncMockHeight();syncPkgHeight(); } initApp(); diff --git a/scripts/theme-studio/browser-gates.js b/scripts/theme-studio/browser-gates.js index 372937f18..3e5e12628 100644 --- a/scripts/theme-studio/browser-gates.js +++ b/scripts/theme-studio/browser-gates.js @@ -25,6 +25,7 @@ if(location.hash==='#selftest')pkgSelftest(); // the shared mkLockCell. (2) reset/erase batch actions update editable rows but // leave locked rows (syntax bare-kind, ui:, pkg: keys) untouched. if(location.hash==='#locktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}}; + const cssRgb=h=>{const [r,g,b]=hex2rgb(h);return 'rgb('+r+', '+g+', '+b+')';}; LOCKED.clear();buildTable(); {const k=CATS.map(c=>c[0]).filter(k=>k!=='bg'&&k!=='p')[0]; const tr=document.querySelector('#legbody tr[data-kind="'+k+'"]'),step=tr.querySelector('.cstep'),dd=tr.querySelector('.cdd'),lb=tr.querySelector('.lockbtn'); @@ -41,6 +42,15 @@ if(location.hash==='#locktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c const tr=document.querySelector('#uibody tr[data-face="region"]'),fg=tr.cells[2].querySelector('.cdd'),bg=tr.cells[3].querySelector('.cdd'); A(fg.classList.contains('is-default'),'compact default color button has default outline class'); A(!bg.classList.contains('is-default'),'compact assigned color button does not have default outline class');} + {setSyntaxFg('kw','');buildTable(); + const dd=document.querySelector('#legbody tr[data-kind="kw"] .cdd'); + A(dd&&dd.style.backgroundColor===cssRgb(MAP['p']),'syntax default fg swatch shows inherited fg color');} + {UIMAP['fringe'].bg=null;buildUITable(); + const dd=document.querySelector('#uibody tr[data-face="fringe"]').cells[3].querySelector('.cdd'); + A(dd&&dd.style.backgroundColor===cssRgb(MAP['bg']),'ui default bg swatch shows inherited ground color');} + {const app=curApp(),face=APPS[app].faces[0][0];PKGMAP[app][face].fg=null;PKGMAP[app][face].inherit=null;buildPkgTable(); + const dd=document.querySelector('#pkgbody tr[data-face="'+face+'"]').cells[2].querySelector('.cdd'); + A(dd&&dd.style.backgroundColor===cssRgb(MAP['p']),'package default fg swatch shows inherited/default fg color');} {PALETTE=[['#000000','bg','ground'],['#ffffff','fg','ground'],['#222222','gray-dark','gray'],['#888888','gray-mid','gray'],['#dddddd','gray-light','gray']];setSyntaxFg('bg','#000000');setSyntaxFg('p','#ffffff');setSyntaxFg('kw','#888888');LOCKED.clear();buildTable(); const tr=document.querySelector('#legbody tr[data-kind="kw"]'),btns=tr.querySelectorAll('.cstepbtn');btns[1].click(); A(MAP['kw']==='#dddddd'&&tr.querySelector('.cdd').dataset.val==='#dddddd','syntax right arrow steps to lighter color');btns[0].click(); @@ -134,6 +144,12 @@ if(location.hash==='#mocktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c A([...document.querySelectorAll('#mockframe .fr')].some(e=>e.textContent.trim()),'fringe-indicator-present'); const mlbar=Q('[data-face="mode-line"]'); A(mlbar&&/box-shadow/.test(mlbar.getAttribute('style')||''),'mode-line-box'); + const textBox=Q('.mbuftext'),border=Q('[data-face="vertical-border"]'),mock=document.getElementById('mockframe'); + if(textBox&&border&&mock){ + const tr=textBox.getBoundingClientRect(),br=border.getBoundingClientRect(); + const ch=parseFloat(getComputedStyle(textBox).fontSize)*0.65; + A(br.left-tr.right<=ch*4.8,'vertical-border-near-text'); + }else A(false,'vertical-border-layout-elements-present'); UIMAP['line-number-current-line'].bold=true;buildMockFrame(); const curNum=Q('[data-face="line-number-current-line"]'); A(curNum&&/font-weight:\s*bold/.test(curNum.getAttribute('style')||''),'line-number-honors-weight'); @@ -151,6 +167,62 @@ if(location.hash==='#mocktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c A(pkgBtn()&&pkgBtn().classList.contains('on')&&PKGMAP[app][face].bold===true,'pkg style button visual state turns on after rebuild'); document.title='MOCKTEST '+(ok?'PASS':'FAIL'); const d=document.createElement('div');d.id='mocktest';d.textContent='MOCKTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);} +// Palette-generator gate (open with #generatortest): previewing is non-mutating, +// clicking a generated tile loads the existing selector, adding creates a normal +// singleton base column, and appending a preview column commits all span members +// under one stable column id. +if(location.hash==='#generatortest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}}; + const before=JSON.stringify(PALETTE); + A(document.getElementById('genaccents').value==='5','default accent count is 5'); + A(document.getElementById('gensource').value==='palette','default generator source is palette'); + A(document.querySelector('label:has(#genintent)').title==='what kind of candidate colors to look for','intent label hover explains the control'); + A(document.getElementById('genintent').title.includes('Pure exploration'),'intent select hover explains random'); + A([...document.getElementById('genintent').options].some(o=>o.value==='fill-hue-gaps'),'fill hue gaps intent is available'); + document.getElementById('genintent').value='fill-hue-gaps';syncGeneratorControls(); + A(document.getElementById('genintent').title.includes('underrepresented hue regions'),'fill hue gaps hover explains hue bonus'); + document.getElementById('genintent').value='near-palette';syncGeneratorControls(); + A(document.getElementById('genintent').title.includes('current palette base colors'),'intent select hover updates for selected intent'); + A(!document.getElementById('genscheme'),'legacy scheme control is removed from the generator UI'); + A(!document.getElementById('genhue'),'legacy base hue control is removed from the generator UI'); + document.getElementById('genaccents').value='3'; + document.getElementById('genintent').value='fill-gaps'; + document.getElementById('genvibe').value='warm'; + document.getElementById('gensource').value='palette'; + previewGenerator(); + A(GEN_PROPOSAL&&GEN_PROPOSAL.intent==='fill-gaps'&&GEN_PROPOSAL.vibe==='warm'&&GEN_PROPOSAL.sourceMode==='palette','intent/vibe/source feed the generator proposal'); + A(JSON.stringify(PALETTE)===before,'preview does not mutate palette'); + A(document.querySelectorAll('#genpreview .gencol').length===3,'renders requested preview columns'); + A(parseInt(getComputedStyle(document.querySelector('#genpreview .genchip')).width,10)===128,'generated candidate tile width matches palette tiles'); + A(parseInt(getComputedStyle(document.querySelector('#genpreview .genchip')).height,10)===58,'generated candidate tile height matches palette tiles'); + A([...document.querySelectorAll('#genpreview .gencol')].every(c=>c.querySelectorAll('.genchip').length===1),'preview columns show only one base tile each'); + const tile=document.querySelector('#genpreview .genchip[data-col="0"][data-member="0"]'); + A(!!tile,'base generated tile exists'); + const tileHex=tile&&tile.dataset.hex,tileName=tile&&tile.dataset.name; + if(tile)tile.click(); + A(document.getElementById('newhexstr').value===tileHex,'generated tile loads selector hex'); + A(document.getElementById('newname').value===tileName,'generated tile loads selector name'); + document.getElementById('genaccents').value='2'; + previewGenerator(); + A(document.querySelectorAll('#genpreview .gencol').length===2,'preview again replaces old preview columns'); + A(!document.querySelector('#genpreview .genchip.sel'),'preview again clears generated tile selection'); + document.getElementById('genaccents').value='3'; + previewGenerator(); + addColor(); + A(PALETTE.some(p=>p[0]===tileHex&&p[1]===tileName),'add color commits selected generated tile'); + const afterSingle=PALETTE.length; + previewGenerator(); + const append=document.querySelector('#genpreview .genappend[data-col="0"]'); + A(!!append,'append generated column button exists'); + if(append)append.click(); + A(PALETTE.length===afterSingle+1,'append commits one generated base color'); + const added=PALETTE.slice(-1); + A(new Set(added.map(p=>p[2])).size===1,'appended generated span has one stable column id'); + A(!/[+-]\d+$/.test(added[0][1]),'appended generated color is a base name, not a signed span neighbor'); + GEN_PROPOSAL={summary:{generated:1,rejected:0,minContrast:null},columns:[{name:'medium-aquamarine',members:[{name:'medium-aquamarine',hex:'#66cdaa',offset:0,columnId:'medium-aquamarine'}]}]}; + renderGeneratorPreview(); + A(document.querySelector('#genpreview .genchip .gn').textContent==='medium aquamarine','generated tile names display spaces instead of hyphens'); + document.title='GENERATORTEST '+(ok?'PASS':'FAIL'); + const d=document.createElement('div');d.id='generatortest';d.textContent='GENERATORTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);} if(location.hash.startsWith('#pick')){openPicker();const m=location.hash.slice(5);if(m){const b=document.querySelector('.pmode button[data-m="'+m+'"]');if(b)b.click();}} if(location.hash==='#cursortest'){document.getElementById('newhexstr').value='#67809c';openPicker();const sc=document.getElementById('svcur'),hc=document.getElementById('huecur');const L=parseFloat(sc.style.left||'0'),T=parseFloat(sc.style.top||'0'),H=parseFloat(hc.style.top||'0');const ok=L>1&&T>1&&H>1;document.title='CURSORTEST '+(ok?'PASS':'FAIL');const d=document.createElement('div');d.id='cursortest';d.textContent='CURSORTEST '+(ok?'PASS':'FAIL')+' left='+sc.style.left+' top='+sc.style.top+' hue='+hc.style.top;document.body.appendChild(d);} if(location.hash.startsWith('#app')){const ap=location.hash.slice(4),s=document.getElementById('appsel');if(s&&ap){s.value=ap;pkgChanged();}} @@ -219,15 +291,27 @@ if(location.hash==='#contrasttest'){let ok=true;const notes=[];const A=(c,n)=>{i 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'); + A(cell&&/^\d+\.\d (PASS|FAIL)$/.test(cell.textContent.trim()),'region shows compact worst-case readout: '+(cell&&cell.textContent)); + A(cell&&!cell.textContent.includes('#67809c'),'compact readout omits limiting fg details: '+(cell&&cell.textContent)); + A(cell&&cell.title.includes('kw (keyword) #67809c'),'hover names failing keyword blue: '+(cell&&cell.title)); + const badge=document.querySelector('#uiprev-region .crerr'); + A(badge&&badge.textContent.trim()===cell.textContent.trim(),'region preview shows failing contrast badge: '+(badge&&badge.textContent)); + A(badge&&badge.title.includes('kw (keyword) #67809c'),'preview badge hover carries failures: '+(badge&&badge.title)); + const firstFail=badge&&badge.title.split('\n')[1]; + A(firstFail&&firstFail.includes('kw (keyword) #67809c'),'failures are sorted from worst first: '+firstFail); 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'); + UIMAP['region']={fg:'#f0fef0',bg:'#202830',bold:false,italic:false,underline:false,strike:false}; + buildUITable(); + const pairCell=document.getElementById('uicr-region'),pairWant=contrast('#f0fef0','#202830'); + A(pairCell&&Math.abs(parseFloat(pairCell.textContent)-pairWant)<0.06,'region with explicit fg rates its own fg/bg pair: got '+(pairCell&&pairCell.textContent.trim())+' want '+pairWant.toFixed(1)); + A(!document.querySelector('#uiprev-region .crerr'),'region with explicit fg does not show covered-text error badge'); + A(pairCell&&!pairCell.title.includes('#67809c'),'region explicit fg hover omits underlying syntax failures: '+(pairCell&&pairCell.title)); 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)); + UIMAP['region']={fg:null,bg:'#202830',bold:false,italic:false,underline:false,strike:false}; setSyntaxFg('p','');CATS.forEach(c=>{if(c[0]!=='bg')setSyntaxFg(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)); diff --git a/scripts/theme-studio/color-names.json b/scripts/theme-studio/color-names.json new file mode 100644 index 000000000..d28f4f449 --- /dev/null +++ b/scripts/theme-studio/color-names.json @@ -0,0 +1,542 @@ +[ + [ + "alice-blue", + "#f0f8ff" + ], + [ + "antique-white", + "#faebd7" + ], + [ + "aquamarine", + "#7fffd4" + ], + [ + "azure", + "#f0ffff" + ], + [ + "beige", + "#f5f5dc" + ], + [ + "bisque", + "#ffe4c4" + ], + [ + "black", + "#000000" + ], + [ + "blanched-almond", + "#ffebcd" + ], + [ + "blue", + "#0000ff" + ], + [ + "blue-violet", + "#8a2be2" + ], + [ + "brown", + "#a52a2a" + ], + [ + "burlywood", + "#deb887" + ], + [ + "cadet-blue", + "#5f9ea0" + ], + [ + "chartreuse", + "#7fff00" + ], + [ + "chocolate", + "#d2691e" + ], + [ + "coral", + "#ff7f50" + ], + [ + "cornflower-blue", + "#6495ed" + ], + [ + "cornsilk", + "#fff8dc" + ], + [ + "cyan", + "#00ffff" + ], + [ + "dark-blue", + "#00008b" + ], + [ + "dark-cyan", + "#008b8b" + ], + [ + "dark-goldenrod", + "#b8860b" + ], + [ + "dark-green", + "#006400" + ], + [ + "dark-grey", + "#a9a9a9" + ], + [ + "dark-khaki", + "#bdb76b" + ], + [ + "dark-magenta", + "#8b008b" + ], + [ + "dark-olive", + "#556b2f" + ], + [ + "dark-orange", + "#ff8c00" + ], + [ + "dark-orchid", + "#9932cc" + ], + [ + "dark-red", + "#8b0000" + ], + [ + "dark-salmon", + "#e9967a" + ], + [ + "dark-sea", + "#8fbc8f" + ], + [ + "dark-slate", + "#2f4f4f" + ], + [ + "dark-slate", + "#483d8b" + ], + [ + "dark-turquoise", + "#00ced1" + ], + [ + "dark-violet", + "#9400d3" + ], + [ + "deep-pink", + "#ff1493" + ], + [ + "deep-sky", + "#00bfff" + ], + [ + "dim-gray", + "#696969" + ], + [ + "dodger-blue", + "#1e90ff" + ], + [ + "firebrick", + "#b22222" + ], + [ + "floral-white", + "#fffaf0" + ], + [ + "forest-green", + "#228b22" + ], + [ + "gainsboro", + "#dcdcdc" + ], + [ + "ghost-white", + "#f8f8ff" + ], + [ + "gold", + "#ffd700" + ], + [ + "goldenrod", + "#daa520" + ], + [ + "gray", + "#bebebe" + ], + [ + "green", + "#00ff00" + ], + [ + "green-yellow", + "#adff2f" + ], + [ + "honeydew", + "#f0fff0" + ], + [ + "hot-pink", + "#ff69b4" + ], + [ + "indian-red", + "#cd5c5c" + ], + [ + "ivory", + "#fffff0" + ], + [ + "khaki", + "#f0e68c" + ], + [ + "lavender", + "#e6e6fa" + ], + [ + "lavender-blush", + "#fff0f5" + ], + [ + "lawn-green", + "#7cfc00" + ], + [ + "lemon-chiffon", + "#fffacd" + ], + [ + "light-blue", + "#add8e6" + ], + [ + "light-coral", + "#f08080" + ], + [ + "light-cyan", + "#e0ffff" + ], + [ + "light-goldenrod", + "#eedd82" + ], + [ + "light-goldenrod", + "#fafad2" + ], + [ + "light-green", + "#90ee90" + ], + [ + "light-grey", + "#d3d3d3" + ], + [ + "light-pink", + "#ffb6c1" + ], + [ + "light-salmon", + "#ffa07a" + ], + [ + "light-sea", + "#20b2aa" + ], + [ + "light-sky", + "#87cefa" + ], + [ + "light-slate", + "#778899" + ], + [ + "light-slate", + "#8470ff" + ], + [ + "light-steel", + "#b0c4de" + ], + [ + "light-yellow", + "#ffffe0" + ], + [ + "lime-green", + "#32cd32" + ], + [ + "linen", + "#faf0e6" + ], + [ + "magenta", + "#ff00ff" + ], + [ + "maroon", + "#b03060" + ], + [ + "medium-aquamarine", + "#66cdaa" + ], + [ + "medium-blue", + "#0000cd" + ], + [ + "medium-orchid", + "#ba55d3" + ], + [ + "medium-purple", + "#9370db" + ], + [ + "medium-sea", + "#3cb371" + ], + [ + "medium-slate", + "#7b68ee" + ], + [ + "medium-spring", + "#00fa9a" + ], + [ + "medium-turquoise", + "#48d1cc" + ], + [ + "medium-violet", + "#c71585" + ], + [ + "midnight-blue", + "#191970" + ], + [ + "mint-cream", + "#f5fffa" + ], + [ + "misty-rose", + "#ffe4e1" + ], + [ + "moccasin", + "#ffe4b5" + ], + [ + "navajo-white", + "#ffdead" + ], + [ + "navy", + "#000080" + ], + [ + "old-lace", + "#fdf5e6" + ], + [ + "olive-drab", + "#6b8e23" + ], + [ + "orange", + "#ffa500" + ], + [ + "orange-red", + "#ff4500" + ], + [ + "orchid", + "#da70d6" + ], + [ + "pale-goldenrod", + "#eee8aa" + ], + [ + "pale-green", + "#98fb98" + ], + [ + "pale-turquoise", + "#afeeee" + ], + [ + "pale-violet", + "#db7093" + ], + [ + "papaya-whip", + "#ffefd5" + ], + [ + "peach-puff", + "#ffdab9" + ], + [ + "peru", + "#cd853f" + ], + [ + "pink", + "#ffc0cb" + ], + [ + "plum", + "#dda0dd" + ], + [ + "powder-blue", + "#b0e0e6" + ], + [ + "purple", + "#a020f0" + ], + [ + "red", + "#ff0000" + ], + [ + "rosy-brown", + "#bc8f8f" + ], + [ + "royal-blue", + "#4169e1" + ], + [ + "saddle-brown", + "#8b4513" + ], + [ + "salmon", + "#fa8072" + ], + [ + "sandy-brown", + "#f4a460" + ], + [ + "sea-green", + "#2e8b57" + ], + [ + "seashell", + "#fff5ee" + ], + [ + "sienna", + "#a0522d" + ], + [ + "sky-blue", + "#87ceeb" + ], + [ + "slate-blue", + "#6a5acd" + ], + [ + "slate-gray", + "#708090" + ], + [ + "snow", + "#fffafa" + ], + [ + "spring-green", + "#00ff7f" + ], + [ + "steel-blue", + "#4682b4" + ], + [ + "tan", + "#d2b48c" + ], + [ + "thistle", + "#d8bfd8" + ], + [ + "tomato", + "#ff6347" + ], + [ + "turquoise", + "#40e0d0" + ], + [ + "violet", + "#ee82ee" + ], + [ + "violet-red", + "#d02090" + ], + [ + "wheat", + "#f5deb3" + ], + [ + "white", + "#ffffff" + ], + [ + "white-smoke", + "#f5f5f5" + ], + [ + "yellow", + "#ffff00" + ], + [ + "yellow-green", + "#9acd32" + ] +] diff --git a/scripts/theme-studio/generate.py b/scripts/theme-studio/generate.py index fbaf7dd80..aa0e829fb 100644 --- a/scripts/theme-studio/generate.py +++ b/scripts/theme-studio/generate.py @@ -44,12 +44,17 @@ APP_CORE_BODY=strip_exports(read_text('app-core.js')) # test-app-util.mjs. Its `import rl` line is stripped on inline (rl is already in # the page from the colormath core). APP_UTIL_BODY=strip_exports(read_text('app-util.js')) +# Pure palette-generator planner and its browser UI panel, split from the shared +# app core so generation behavior and panel wiring can evolve locally. +PALETTE_GENERATOR_CORE_BODY=strip_exports(read_text('palette-generator-core.js')) +PALETTE_GENERATOR_UI_BODY=strip_exports(read_text('palette-generator-ui.js')) # Palette panel actions and rendering. This is stateful browser code, split from # app.js because color-column behavior changes often and benefits from locality. PALETTE_ACTIONS_BODY=strip_exports(read_text('palette-actions.js')) # Browser hash gates, split from app.js so the application code is not buried # under the test harness while still shipping one self-contained HTML file. BROWSER_GATES_BODY=strip_exports(read_text('browser-gates.js')) +COLOR_NAMES=read_json('color-names.json') ns={} src=read_text('samples.py') exec(src[:src.index('cols=')], ns) @@ -183,7 +188,7 @@ MAP,BOLD,ITALIC_MAP=initial_maps(COLS,DEFAULTS) PALETTE=[[MAP['bg'],"bg","ground"],[MAP['p'],"fg","ground"]] 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 · def","resolve push"], - ["fnc","function · call","printf rsync get"],["dec","decorator","@dataclass"], + ["fnc","function · call","printf rsync get"],["dec","decorator → type","@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]+/"], @@ -261,8 +266,11 @@ def fill_data(s): return (s.replace("COLORMATH_J",COLORMATH_BODY) .replace("APP_CORE_J",APP_CORE_BODY) .replace("APP_UTIL_J",APP_UTIL_BODY) + .replace("PALETTE_GENERATOR_CORE_J",PALETTE_GENERATOR_CORE_BODY) + .replace("PALETTE_GENERATOR_UI_J",PALETTE_GENERATOR_UI_BODY) .replace("PALETTE_ACTIONS_J",PALETTE_ACTIONS_BODY) .replace("BROWSER_GATES_J",BROWSER_GATES_BODY) + .replace("COLOR_NAMES_J",json.dumps(COLOR_NAMES)) .replace("SAMPLES_J",json.dumps(SAMPLES)) .replace("PALETTE_J",json.dumps(PALETTE)).replace("CATS_J",json.dumps(CATS)) .replace("UIFACES_J",json.dumps(UI_FACES)).replace("UIMAP_J",json.dumps(UIMAP)).replace("APPS_J",json.dumps(APPS)) diff --git a/scripts/theme-studio/palette-generator-core.js b/scripts/theme-studio/palette-generator-core.js new file mode 100644 index 000000000..6bce0d59a --- /dev/null +++ b/scripts/theme-studio/palette-generator-core.js @@ -0,0 +1,267 @@ +// Pure palette-generator planner. It depends on the shared palette-column model +// from app-core.js, but owns candidate hue selection, naming, contrast filtering, +// and conversion from preview columns to palette entries. +import { normHex } from './app-util.js'; +import { oklch2hex, srgb2oklab, oklab2oklch, contrast, deltaE } from './colormath.js'; +import { columnsFromPalette } from './app-core.js'; + +function oklchOf(hex){return oklab2oklch(srgb2oklab(hex));} +function isPureEndpointHex(hex){const h=(hex||'').toLowerCase();return h==='#ffffff'||h==='#000000';} +function generatedExistingNames(palette){ + return new Set((palette||[]).map(p=>(p&&p[1]||'').toLowerCase()).filter(Boolean)); +} +const DEFAULT_COLOR_NAMES=[['black','#000000'],['white','#ffffff'],['red','#ff0000'],['green','#008000'],['blue','#0000ff'],['yellow','#ffff00'],['cyan','#00ffff'],['magenta','#ff00ff'],['gray','#808080']]; +function nearestColorName(hex,colorNames){ + const h=typeof hex==='string'?normHex(hex):null; + if(!h)return 'generated'; + let best=(colorNames&&colorNames[0]&&colorNames[0][0])||DEFAULT_COLOR_NAMES[0][0],bd=Infinity; + for(const [name,nhex] of (colorNames&&colorNames.length?colorNames:DEFAULT_COLOR_NAMES)){const d=deltaE(h,nhex);if(d<bd){bd=d;best=name;}} + return best; +} +function uniqueGeneratedName(base,used){ + let name=base||'generated',i=2; + if(!used.has(name.toLowerCase())){used.add(name.toLowerCase());return name;} + while(used.has((name+'-alt'+i).toLowerCase()))i++; + const out=name+'-alt'+i;used.add(out.toLowerCase());return out; +} +function hueOfHex(hex,fallback){ + const h=typeof hex==='string'?normHex(hex):null; + if(!h)return fallback; + const lch=oklab2oklch(srgb2oklab(h)); + return Number.isFinite(lch.H)?lch.H:fallback; +} +function generatorSourceHue(palette,ground,cfg){ + const fallback=((cfg&&typeof cfg.baseHue==='number'&&isFinite(cfg.baseHue))?cfg.baseHue:250)%360; + if(cfg&&cfg.sourceMode==='palette'){const hs=paletteBaseHues(palette,ground);return hs.length?hs[0]:(fallback+360)%360;} + if(cfg&&cfg.sourceMode==='selected'&&typeof cfg.selectedHex==='string'&&normHex(cfg.selectedHex))return hueOfHex(cfg.selectedHex,fallback); + const bg=hueOfHex(ground&&ground.bg,fallback),fg=hueOfHex(ground&&ground.fg,fallback); + if(Math.abs(bg-fallback)>0.001||Math.abs(fg-fallback)>0.001)return ((bg+fg)/2+360)%360; + return (fallback+360)%360; +} +function generatorHues(baseHue,scheme,count,rng){ + const n=Math.max(1,Math.min(12,Math.round(count||8))), b=((baseHue%360)+360)%360; + if(scheme==='random'){ + const rnd=typeof rng==='function'?rng:Math.random; + return Array.from({length:n},()=>Math.floor(rnd()*360)); + } + if(scheme==='analogous'){ + const spread=Math.min(120,Math.max(30,n*14)), start=b-spread/2; + return Array.from({length:n},(_,i)=>(start+(n===1?0:(spread*i)/(n-1))+360)%360); + } + if(scheme==='triadic'){ + const offsets=[0,120,240,30,150,270,60,180,300,90,210,330]; + return offsets.slice(0,n).map(o=>(b+o)%360); + } + if(scheme==='manual')return Array.from({length:n},(_,i)=>(b+(i*360)/n)%360); + return Array.from({length:n},(_,i)=>(b+(i*360)/n)%360); +} +function generatorChroma(mode){ + return mode==='subdued'?0.055:mode==='vivid'?0.13:0.085; +} +function generatorTarget(mode){return mode==='aaa'?7:mode==='none'?0:4.5;} +function jitterHue(h,rng,spread){ + const rnd=typeof rng==='function'?rng:Math.random; + return (h+(rnd()*2-1)*spread+360)%360; +} +function paletteBaseHues(palette,ground){ + const cols=columnsFromPalette(palette||[],ground||{}).columns; + return cols.map(c=>hueOfHex(c.base,0)).filter(Number.isFinite); +} +function paletteBaseHexes(palette,ground){ + return columnsFromPalette(palette||[],ground||{}).columns.map(c=>normHex(c.base)).filter(Boolean); +} +function sourceAnchorHues(palette,ground,cfg,baseHue){ + const mode=cfg&&cfg.sourceMode||'bg-fg'; + if(mode==='none')return []; + if(mode==='palette')return paletteBaseHues(palette,ground); + if(mode==='selected'&&typeof (cfg&&cfg.selectedHex)==='string'&&normHex(cfg.selectedHex))return [hueOfHex(cfg.selectedHex,baseHue)]; + const anchors=[]; + if(ground&&ground.bg)anchors.push(hueOfHex(ground.bg,baseHue)); + if(ground&&ground.fg)anchors.push(hueOfHex(ground.fg,baseHue)); + return anchors.filter(Number.isFinite); +} +function sourceAnchorHexes(palette,ground,cfg){ + const mode=cfg&&cfg.sourceMode||'bg-fg'; + if(mode==='none')return []; + if(mode==='palette')return paletteBaseHexes(palette,ground); + if(mode==='selected'&&typeof (cfg&&cfg.selectedHex)==='string'&&normHex(cfg.selectedHex))return [normHex(cfg.selectedHex)]; + return [ground&&ground.bg,ground&&ground.fg].map(h=>typeof h==='string'?normHex(h):null).filter(Boolean); +} +function bridgeHues(anchors,count,rng){ + if(anchors.length<2)return generatorHues(anchors[0]||250,'random',count,rng); + const sorted=[...anchors].sort((a,b)=>a-b),pairs=[]; + for(let i=0;i<sorted.length;i++){ + const a=sorted[i],b=sorted[(i+1)%sorted.length]+(i===sorted.length-1?360:0); + pairs.push(((a+b)/2)%360); + } + return Array.from({length:count},(_,i)=>jitterHue(pairs[i%pairs.length],rng,10)); +} +function repeatOffsets(base,offsets,count){ + return Array.from({length:count},(_,i)=>(base+offsets[i%offsets.length]+360)%360); +} +function harmonyHues(intent,src,baseHue,count,rng){ + const b=src&&src.length?src[0]:baseHue, n=Math.max(1,Math.min(12,Math.round(count||8))); + if(intent==='complementary')return repeatOffsets(b,[180],n); + if(intent==='analogous')return repeatOffsets(b,[-30,30,-60,60,0],n); + if(intent==='split-complementary')return repeatOffsets(b,[150,210,0],n); + if(intent==='triadic')return repeatOffsets(b,[0,120,240],n); + if(intent==='tetradic')return repeatOffsets(b,[0,60,180,240],n); + if(intent==='square')return repeatOffsets(b,[0,90,180,270],n); + if(intent==='monochromatic')return Array.from({length:n},()=>jitterHue(b,rng,3)); + if(intent==='rainbow')return Array.from({length:n},(_,i)=>(b+(i*360)/n)%360); + return null; +} +function intentHues(intent,anchors,baseHue,count,rng){ + const n=Math.max(1,Math.min(12,Math.round(count||8))), src=anchors&&anchors.length?anchors:[baseHue]; + const harmony=harmonyHues(intent,src,baseHue,n,rng); + if(harmony)return harmony; + if(intent==='near-palette'||intent==='near-selected')return Array.from({length:n},(_,i)=>jitterHue(src[i%src.length],rng,18)); + if(intent==='fill-gaps')return generatorHues(src[0]||baseHue,'random',n,rng); + if(intent==='complements')return Array.from({length:n},(_,i)=>jitterHue((src[i%src.length]+180)%360,rng,18)); + if(intent==='bridges')return bridgeHues(src,n,rng); + return generatorHues(baseHue,'random',n,rng); +} +function vibeHueBias(hues,vibe,rng){ + const rnd=typeof rng==='function'?rng:Math.random; + const pick=bands=>bands[Math.floor(rnd()*bands.length)]; + if(vibe==='warm')return hues.map(()=>jitterHue(pick([12,28,44,58]),rng,14)); + if(vibe==='cool')return hues.map(()=>jitterHue(pick([170,195,220,250,278]),rng,16)); + if(vibe==='earthy')return hues.map(h=>jitterHue([28,42,58,82,112].reduce((a,b)=>Math.abs(b-h)<Math.abs(a-h)?b:a,42),rng,12)); + return hues; +} +function candidateLightnesses(bgHex,vibe){ + const bgL=typeof bgHex==='string'&&normHex(bgHex)?oklchOf(bgHex).L:0; + if(vibe==='pastel')return bgL>0.55?[0.74,0.68,0.80,0.62,0.86,0.56,0.50]:[0.82,0.88,0.76,0.92,0.70,0.64]; + if(vibe==='deep'||vibe==='jewel')return bgL>0.55?[0.30,0.24,0.36,0.18,0.42,0.48]:[0.56,0.62,0.50,0.68,0.44,0.74]; + return bgL>0.55 + ? [0.34,0.28,0.40,0.22,0.46,0.16,0.52,0.10,0.58] + : [0.70,0.76,0.64,0.82,0.58,0.88,0.52,0.94,0.46]; +} +function randomChroma(rng){ + const rnd=typeof rng==='function'?rng:Math.random; + return 0.10+rnd()*0.09; +} +function vibeChroma(vibe,rng){ + const rnd=typeof rng==='function'?rng:Math.random; + if(vibe==='muted')return 0.045+rnd()*0.035; + if(vibe==='pastel')return 0.035+rnd()*0.045; + if(vibe==='deep')return 0.085+rnd()*0.055; + if(vibe==='jewel')return 0.12+rnd()*0.075; + if(vibe==='earthy')return 0.055+rnd()*0.04; + if(vibe==='warm'||vibe==='cool')return 0.08+rnd()*0.06; + if(vibe==='neon')return 0.18+rnd()*0.09; + if(vibe==='strange')return 0.145+rnd()*0.095; + if(vibe==='balanced')return 0.075+rnd()*0.045; + return 0.12+rnd()*0.07; +} +function accentCandidateForHue(hue,ground,cfg){ + const C=cfg&&cfg.vibe?vibeChroma(cfg.vibe,cfg.rng):(cfg&&cfg.scheme==='random'?randomChroma(cfg.rng):generatorChroma(cfg&&cfg.chromaMode)), target=generatorTarget(cfg&&cfg.contrastMode), bg=ground&&ground.bg; + let best=null; + for(const L of candidateLightnesses(bg,cfg&&cfg.vibe)){ + const c=oklch2hex(L,C,hue), r=bg?contrast(c.hex,bg):Infinity; + const item={hex:c.hex,L,C,hue,contrast:r,clamped:c.clamped}; + if(!best||r>best.contrast)best=item; + if(r>=target&&!isPureEndpointHex(c.hex))return item; + } + return best&&best.contrast>=target&&!isPureEndpointHex(best.hex)?best:null; +} +function candidateForHueLightness(hue,L,C,ground,cfg){ + const target=generatorTarget(cfg&&cfg.contrastMode),bg=ground&&ground.bg,c=oklch2hex(L,C,hue),r=bg?contrast(c.hex,bg):Infinity; + return r>=target&&!isPureEndpointHex(c.hex)?{hex:c.hex,L,C,hue,contrast:r,clamped:c.clamped}:null; +} +function minDistanceToSet(hex,set){ + return set.length?Math.min(...set.map(h=>deltaE(hex,h))):Infinity; +} +function hueDistance(a,b){return Math.abs((((a-b+540)%360)-180));} +function anchorHueSet(hexes){ + return hexes.map(hex=>oklchOf(hex)).filter(lch=>lch.C>0.025&&Number.isFinite(lch.H)).map(lch=>lch.H); +} +function minHueDistance(hue,hues){ + return hues.length?Math.min(...hues.map(h=>hueDistance(hue,h))):180; +} +function perceptualGapCandidates(palette,ground,cfg,sourceMode,baseHue,count,scheme,intent,hueAware){ + const anchors=sourceAnchorHexes(palette,ground,Object.assign({},cfg,{sourceMode})); + if(anchors.length<2){ + return intentHues('fill-gaps',sourceAnchorHues(palette,ground,Object.assign({},cfg,{sourceMode}),baseHue),baseHue,count,cfg.rng) + .map(hue=>accentCandidateForHue(hue,ground,Object.assign({},cfg,{scheme,intent}))).filter(Boolean); + } + const C=cfg&&cfg.vibe?vibeChroma(cfg.vibe,cfg.rng):(scheme==='random'?randomChroma(cfg.rng):generatorChroma(cfg&&cfg.chromaMode)); + const hueStep=10,hueOffset=(typeof cfg.rng==='function'?cfg.rng():Math.random())*hueStep; + const pool=[],seen=new Set(); + for(let hue=hueOffset;hue<360;hue+=hueStep){ + for(const L of candidateLightnesses(ground&&ground.bg,cfg&&cfg.vibe)){ + const cand=candidateForHueLightness(hue,L,C,ground,cfg); + if(!cand)continue; + const key=cand.hex.toLowerCase(); + if(seen.has(key))continue; + seen.add(key);pool.push(cand); + } + } + const picked=[],occupied=[...anchors]; + const occupiedHues=anchorHueSet(anchors); + while(picked.length<count&&pool.length){ + let bestI=-1,bestScore=-1,bestContrast=-1; + for(let i=0;i<pool.length;i++){ + const cand=pool[i],perceptual=minDistanceToSet(cand.hex,occupied); + const hueBonus=hueAware?0.10*(minHueDistance(cand.hue,occupiedHues)/180):0; + const score=perceptual+hueBonus; + if(score>bestScore+1e-9||(Math.abs(score-bestScore)<1e-9&&cand.contrast>bestContrast)){ + bestI=i;bestScore=score;bestContrast=cand.contrast; + } + } + const cand=pool.splice(bestI,1)[0]; + picked.push(cand);occupied.push(cand.hex);occupiedHues.push(cand.hue); + } + return picked; +} +function generatedMembers(baseHex,baseName,spanCount,columnId){ + const hex=typeof baseHex==='string'?normHex(baseHex):null; + return hex?[{hex,name:baseName,offset:0,clamped:false,columnId}]:[]; +} +function planPaletteGenerator(palette,ground,config){ + const cfg=config||{}; + const requestedSource=cfg.sourceMode||'bg-fg', resolvedSource=requestedSource==='selected' + ? (typeof cfg.selectedHex==='string'&&normHex(cfg.selectedHex)?'selected':'bg-fg') + : requestedSource; + const sourceMode=['selected','palette','none','bg-fg'].includes(resolvedSource)?resolvedSource:'bg-fg'; + const scheme=cfg.scheme||'random', intent=cfg.intent||(cfg.scheme&&cfg.scheme!=='random'?'scheme':'random'), count=Math.max(1,Math.min(12,Math.round(cfg.accentCount??5))); + const spanCount=Math.max(0,Math.min(8,Math.round(cfg.spanCount??2))); + const used=generatedExistingNames(palette), baseHue=generatorSourceHue(palette,ground,Object.assign({},cfg,{sourceMode})); + const anchors=sourceAnchorHues(palette,ground,Object.assign({},cfg,{sourceMode}),baseHue); + const columns=[], rejected=[]; + const candidates=(intent==='fill-gaps'||intent==='fill-hue-gaps') + ? perceptualGapCandidates(palette,ground,cfg,sourceMode,baseHue,count,scheme,intent,intent==='fill-hue-gaps').map(cand=>({cand,hue:cand&&cand.hue})) + : vibeHueBias(intent&&intent!=='manual'&&intent!=='scheme'?intentHues(intent,anchors,baseHue,count,cfg.rng):generatorHues(baseHue,scheme,count,cfg.rng),cfg.vibe,cfg.rng) + .map(hue=>({hue,cand:accentCandidateForHue(hue,ground,Object.assign({},cfg,{scheme,intent}))})); + for(const {cand,hue} of candidates){ + if(!cand){rejected.push({hue,reason:'contrast'});continue;} + const name=uniqueGeneratedName(nearestColorName(cand.hex,cfg.colorNames),used), columnId=name; + const members=generatedMembers(cand.hex,name,spanCount,columnId); + columns.push({name,columnId,baseHex:cand.hex,L:cand.L,C:cand.C,hue:cand.hue,contrast:cand.contrast,clamped:cand.clamped,members}); + } + const contrasts=columns.map(c=>c.contrast).filter(Number.isFinite); + return { + sourceMode, + scheme, + intent, + vibe: cfg.vibe||null, + baseHue, + accentCount:count, + spanCount, + columns, + rejected, + summary:{ + generated:columns.length, + rejected:rejected.length, + clamped:columns.reduce((n,c)=>n+(c.clamped?1:0)+c.members.filter(m=>m.clamped).length,0), + minContrast:contrasts.length?Math.min(...contrasts):null, + }, + }; +} +function entriesForGeneratedColumn(column){ + if(!column||!Array.isArray(column.members))return []; + const columnId=column.columnId||column.name||'generated'; + return column.members.map(m=>[m.hex,m.name,columnId]); +} + +export { planPaletteGenerator, entriesForGeneratedColumn }; diff --git a/scripts/theme-studio/palette-generator-ui.js b/scripts/theme-studio/palette-generator-ui.js new file mode 100644 index 000000000..6cab65508 --- /dev/null +++ b/scripts/theme-studio/palette-generator-ui.js @@ -0,0 +1,152 @@ +// Browser-side palette-generator panel. The pure planner lives in +// palette-generator-core.js; this file only gathers controls, renders previews, +// and commits selected generated colors into normal palette entries. +let GEN_PROPOSAL=null, GEN_SELECTION=null; +const GENERATOR_CONTROLS={ + genintent:{ + labelTitle:'what kind of candidate colors to look for', + options:[ + ['random','random','Pure exploration: reroll unrelated candidate base colors.'], + ['near-palette','near palette','Generate candidates near the current palette base colors.'], + ['fill-gaps','fill gaps','Find missing perceptual colors using OKLab distance.'], + ['fill-hue-gaps','fill hue gaps','Find missing perceptual colors while rewarding underrepresented hue regions.'], + ['complements','complements','Generate colors opposite palette or selected anchors.'], + ['bridges','bridges','Generate colors between existing palette anchors.'], + ['near-selected','near selected','Generate candidates near the current selector color.'], + ['complementary','complementary','Use the hue opposite the anchor.'], + ['analogous','analogous','Use neighboring hues around the anchor.'], + ['split-complementary','split complementary','Use hues on both sides of the anchor complement.'], + ['triadic','triadic','Use three hues spaced 120 degrees apart.'], + ['tetradic','tetradic','Use two complementary hue pairs.'], + ['square','square','Use four hues spaced 90 degrees apart.'], + ['monochromatic','monochromatic','Stay near one hue and vary color character.'], + ['rainbow','rainbow','Spread candidates evenly around the full hue wheel.'], + ], + }, + genvibe:{ + labelTitle:'the character of generated candidate colors', + options:[ + ['bold','bold','Higher chroma, assertive candidate colors.'], + ['balanced','balanced','Moderate chroma candidate colors.'], + ['muted','muted','Lower chroma, quieter candidate colors.'], + ['pastel','pastel','Light, low-chroma candidate colors.'], + ['deep','deep','Lower-lightness, richer candidate colors.'], + ['jewel','jewel','Saturated, rich candidate colors.'], + ['earthy','earthy','Warmer, reduced-chroma earth-tone candidates.'], + ['neon','neon','Very high-chroma candidate colors.'], + ['strange','strange','More unusual, high-variance candidate colors.'], + ['warm','warm','Bias candidates toward red, orange, and yellow.'], + ['cool','cool','Bias candidates toward green, cyan, blue, and violet.'], + ], + }, + gensource:{ + labelTitle:'where starting hues come from', + options:[ + ['palette','palette','Use current base color columns as anchors; span tiles are ignored.'], + ['none','none','Use no anchors; useful for pure random exploration.'], + ['bg-fg','bg/fg','Use the current background and foreground as anchors.'], + ['selected','selected','Use the current selector tile as the anchor.'], + ], + }, + gencontrast:{ + labelTitle:'minimum contrast against the current bg', + options:[ + ['aa','AA','Require WCAG AA contrast against the current background.'], + ['aaa','AAA','Require WCAG AAA contrast against the current background.'], + ['none','none','Do not reject candidates by WCAG contrast.'], + ], + }, +}; +function generatorOptionTitle(id,value){ + const ctl=GENERATOR_CONTROLS[id]; + const row=ctl&&ctl.options.find(o=>o[0]===value); + return row?row[2]:''; +} +function populateGeneratorSelects(){ + Object.entries(GENERATOR_CONTROLS).forEach(([id,ctl])=>{ + const el=document.getElementById(id);if(!el)return; + const cur=el.value||el.dataset.default||ctl.options[0][0]; + el.innerHTML=''; + ctl.options.forEach(([value,label])=>{const o=document.createElement('option');o.value=value;o.textContent=label;el.appendChild(o);}); + el.value=ctl.options.some(o=>o[0]===cur)?cur:ctl.options[0][0]; + const label=el.closest('label');if(label)label.title=ctl.labelTitle; + }); +} +function genConfig(){ + const intent=document.getElementById('genintent'),vibe=document.getElementById('genvibe'), + source=document.getElementById('gensource'), + accents=document.getElementById('genaccents'),contrastSel=document.getElementById('gencontrast'); + return { + intent:intent?intent.value:'random', + vibe:vibe?vibe.value:'bold', + sourceMode:source?source.value:'palette', + scheme:'random', + baseHue:250, + accentCount:accents?parseInt(accents.value,10):5, + spanCount:0, + contrastMode:contrastSel?contrastSel.value:'aa', + selectedHex:curHex(), + colorNames:COLOR_NAMES, + }; +} +function syncGeneratorControls(){syncGeneratorSelectTitles();} +function syncGeneratorSelectTitles(){ + Object.keys(GENERATOR_CONTROLS).forEach(id=>{const el=document.getElementById(id);if(el)el.title=generatorOptionTitle(id,el.value);}); +} +function setGenMessage(msg,err){const m=document.getElementById('genmsg');if(!m)return;m.textContent=msg||'';m.style.color=err?'#cb6b4d':'#8a9496';} +function renderGeneratorPreview(){ + const host=document.getElementById('genpreview');if(!host)return;host.innerHTML=''; + if(!GEN_PROPOSAL){setGenMessage('',false);return;} + GEN_PROPOSAL.columns.forEach((col,ci)=>{ + const strip=document.createElement('div');strip.className='gencol'; + const head=document.createElement('div');head.className='genhead'; + head.innerHTML=`<span title="${esc(col.name)}">${esc(col.name)}</span><button class="genappend" data-col="${ci}" title="append this generated column to the palette">+</button>`; + head.querySelector('.genappend').onclick=()=>appendGeneratedColumn(ci); + strip.appendChild(head); + col.members.forEach((m,mi)=>{ + const chip=document.createElement('div'),tc=textOn(m.hex); + chip.className='genchip'+(GEN_SELECTION&&GEN_SELECTION.hex===m.hex&&GEN_SELECTION.name===m.name?' sel':''); + chip.dataset.col=String(ci);chip.dataset.member=String(mi);chip.dataset.hex=m.hex;chip.dataset.name=m.name; + chip.style.background=m.hex;chip.style.color=tc;chip.title=m.name+' '+m.hex+(m.clamped?' (sRGB clamped)':''); + chip.innerHTML=`<div class="gn">${esc(m.name.replace(/-/g,' '))}</div><div class="gh">${m.hex}</div>`; + chip.onclick=()=>selectGeneratedTile(ci,mi); + strip.appendChild(chip); + }); + host.appendChild(strip); + }); + const s=GEN_PROPOSAL.summary; + setGenMessage(s.generated+' column(s) previewed'+(s.rejected?(', '+s.rejected+' rejected'):'')+(s.minContrast?(', min '+s.minContrast.toFixed(1)+':1'):''),false); +} +function resetGeneratorPreviewState(){ + GEN_PROPOSAL=null;GEN_SELECTION=null; + renderGeneratorPreview(); +} +function previewGenerator(){ + const cfg=genConfig(); + resetGeneratorPreviewState(); + GEN_PROPOSAL=planPaletteGenerator(PALETTE,{bg:MAP['bg'],fg:MAP['p']},cfg); + renderGeneratorPreview(); +} +function clearGeneratorPreview(){resetGeneratorPreviewState();} +function selectGeneratedTile(ci,mi){ + if(!GEN_PROPOSAL||!GEN_PROPOSAL.columns[ci])return; + const m=GEN_PROPOSAL.columns[ci].members[mi];if(!m)return; + selectedIdx=null;GEN_SELECTION={column:ci,member:mi,hex:m.hex,name:m.name}; + setHex(m.hex);document.getElementById('newname').value=m.name; + renderPalette();renderGeneratorPreview(); + notify('loaded generated "'+m.name+'" into the selector - add it to commit',false); +} +function appendGeneratedColumn(ci){ + if(!GEN_PROPOSAL||!GEN_PROPOSAL.columns[ci])return; + const colName=GEN_PROPOSAL.columns[ci].name, entries=entriesForGeneratedColumn(GEN_PROPOSAL.columns[ci]); + const existing=new Set(PALETTE.map(p=>(p[1]||'').toLowerCase())); + if(entries.some(e=>existing.has(e[1].toLowerCase()))){notify('generated names already exist - preview again for fresh names',true);return;} + PALETTE.push(...entries);GEN_SELECTION=null;selectedIdx=null; + refreshPaletteState();previewGenerator(); + notify('added generated column "'+colName+'"',false); +} +function initGeneratorControls(){ + populateGeneratorSelects(); + Object.keys(GENERATOR_CONTROLS).forEach(id=>{const el=document.getElementById(id);if(el)el.onchange=syncGeneratorControls;}); + syncGeneratorControls(); +} diff --git a/scripts/theme-studio/run-tests.sh b/scripts/theme-studio/run-tests.sh index 95a3dde68..f6a68c41b 100755 --- a/scripts/theme-studio/run-tests.sh +++ b/scripts/theme-studio/run-tests.sh @@ -55,7 +55,7 @@ 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 contrasttest safetest healtest columntest counttest baseedittest roundtriptest beveltest previewlinktest" +HASHES="selftest cursortest readouttest deltatest oklchtest planetest locktest sorttest mocktest contrasttest safetest healtest columntest counttest baseedittest roundtriptest beveltest previewlinktest generatortest" if [ "$NO_BROWSER" = 1 ]; then skip_msg "browser hash gates (--no-browser)" elif [ -z "$CHROME" ]; then diff --git a/scripts/theme-studio/styles.css b/scripts/theme-studio/styles.css index 5de838b68..a2242728b 100644 --- a/scripts/theme-studio/styles.css +++ b/scripts/theme-studio/styles.css @@ -40,6 +40,7 @@ .boxctl .cstepbtn{width:18px} .legctl{margin:0 0 8px;display:flex;gap:8px;align-items:center} .cat{color:#b4b1a2} .ex{font-size:17px} + .crerr{display:inline-block;margin-left:8px;padding:0 4px;border-radius:3px;background:#2b130e;color:#cb6b4d;border:1px solid #7b3324;font:9pt monospace;vertical-align:middle} .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;flex-direction:row;flex-wrap:wrap;gap:10px;align-items:flex-start} @@ -96,6 +97,24 @@ .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} + .genctl{margin:0 0 14px;padding:8px 10px;border:1px solid #252321;border-radius:7px;background:#11100e} + .genrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap;color:#b4b1a2;font:10pt monospace} + .genrow label{display:flex;gap:5px;align-items:center} + .genrow label.disabled{opacity:.45} + .genrow select,.genrow input{background:#161412;border:1px solid #252321;color:#cdced1;border-radius:4px;padding:4px 6px;font:10pt monospace} + .genrow input:disabled{opacity:.55;cursor:default} + .genrow input{width:48px} + .genrow button{background:#252321;color:#e8bd30;border:1px solid #3a3a3a;border-radius:4px;padding:5px 10px;font:10pt monospace;cursor:pointer} + #genmsg{color:#8a9496} + .genpreview{display:flex;gap:10px;align-items:flex-start;flex-wrap:wrap;margin-top:8px} + .gencol{display:flex;flex-direction:column;gap:6px;padding:5px;border:1px dashed #3a3a3a;border-radius:7px} + .genhead{width:128px;display:flex;gap:4px;align-items:center;justify-content:center;color:#b4b1a2;font:9pt monospace} + .genhead span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;text-align:center;white-space:nowrap} + .genappend{width:22px;height:22px;padding:0;border:1px solid #3a3a3a;border-radius:4px;background:#252321;color:#e8bd30;font:bold 12px monospace;cursor:pointer} + .genchip{width:128px;height:58px;border-radius:6px;border:1px solid #555;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer;font:10pt monospace;line-height:1.15;text-align:center;box-sizing:border-box;padding:3px 5px;overflow:hidden} + .genchip.sel{outline:2px solid #e8bd30;outline-offset:2px} + .genchip .gn{font-weight:bold;white-space:normal;overflow-wrap:normal;max-width:116px} + .genchip .gh{opacity:.8;white-space:nowrap} #export{width:100%;height:180px;margin-top:10px;background:#0d0b0a;color:#a4ac64;border:1px solid #252321;border-radius:6px;font:10pt monospace;padding:10px} .filebar{margin:6px 0 0;display:flex;gap:8px;align-items:center} #pagetitle{font-size:30px;color:#cdced1;font-weight:normal;border:none;margin:0;padding:0} @@ -110,7 +129,10 @@ #pkgbody td{padding:3px 8px} #codepre{width:100%;box-sizing:border-box} .mock{border:1px solid #252321;border-radius:8px;overflow:hidden;font:12pt/1.7 monospace;display:flex;flex-direction:column} - .mock .mbuf{flex:1} .mock .ln{display:flex;align-items:stretch;white-space:pre} + .mock .mbuf{flex:1;display:flex;align-items:stretch;overflow:auto} + .mock .mbuftext{flex:0 1 auto;width:max-content;max-width:calc(100% - 4ch - 3px);padding-right:4ch;box-sizing:border-box;overflow:hidden} + .mock .vborder{width:3px;flex:0 0 auto} + .mock .ln{display:flex;align-items:stretch;white-space:pre} .mock .fr{width:14px;flex:0 0 auto;border-right:1px solid #ffffff14} .mock .num{width:36px;flex:0 0 auto;text-align:right;padding-right:10px} .mock .cd{flex:1;padding-left:8px} .mock .bar,.mock .echo{padding:4px 10px;white-space:pre} #codepre [data-k],.mock [data-k],.mock [data-face]{cursor:pointer} diff --git a/scripts/theme-studio/test-app-core.mjs b/scripts/theme-studio/test-app-core.mjs index 95763cdaf..63e79a95c 100644 --- a/scripts/theme-studio/test-app-core.mjs +++ b/scripts/theme-studio/test-app-core.mjs @@ -7,12 +7,15 @@ import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { - nameToHex, normalizePkgFace, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList, paletteOptionList, spanNeighborHex, slugify, + nameToHex, normalizePkgFace, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, resolveSyntaxFg, resolveUiAttr, optList, paletteOptionList, spanNeighborHex, slugify, clearPalettePlan, deletePaletteColumnPlan, groundColumnMembersFromPalette, areAllLocked, lockToggleLabel, toggleLockSet, } from './app-core.js'; +import { planPaletteGenerator, entriesForGeneratedColumn } from './palette-generator-core.js'; +import { oklch2hex, deltaE } from './colormath.js'; const here = fileURLToPath(new URL('.', import.meta.url)); const PAL = [['#67809c', 'blue'], ['#e8bd30', 'gold']]; +const COLOR_NAMES = JSON.parse(readFileSync(new URL('./color-names.json', import.meta.url), 'utf8')); test('nameToHex: Normal — resolves a palette name to its hex', () => { assert.equal(nameToHex('blue', PAL), '#67809c'); @@ -180,6 +183,381 @@ test('deletePaletteColumnPlan: Boundary — never deletes ground entries', () => assert.deepEqual(plan.removed, []); }); +test('planPaletteGenerator: Normal — builds deterministic preview columns without mutating palette', () => { + const pal = [['#0d0b0a', 'bg', 'ground'], ['#f0fef0', 'fg', 'ground'], ['#67809c', 'blue', 'blue']]; + const before = JSON.stringify(pal); + const plan = planPaletteGenerator(pal, { bg: '#0d0b0a', fg: '#f0fef0' }, { + sourceMode: 'bg-fg', + scheme: 'syntax-balanced', + baseHue: 250, + accentCount: 5, + spanCount: 2, + chromaMode: 'balanced', + contrastMode: 'aa', + }); + assert.equal(JSON.stringify(pal), before, 'planner is pure'); + assert.equal(plan.sourceMode, 'bg-fg'); + assert.equal(plan.scheme, 'syntax-balanced'); + assert.equal(plan.columns.length, 5); + assert.equal(plan.summary.generated, 5); + assert.equal(plan.summary.rejected, 0); + assert.ok(plan.summary.minContrast >= 4.5); + assert.ok(!/^generated-/.test(plan.columns[0].name), 'generated bases get nearest color names'); + assert.equal(plan.columns[0].members.length, 1); + assert.ok(plan.columns.every(c => c.columnId && c.members.some(m => m.offset === 0 && m.hex === c.baseHex))); +}); + +test('planPaletteGenerator: Normal — random scheme varies candidate bases for inspiration', () => { + const pal = [['#0d0b0a', 'bg', 'ground'], ['#f0fef0', 'fg', 'ground']]; + const seq = [0.10, 0.80, 0.35, 0.65, 0.90, 0.20, 0.48, 0.72, 0.04, 0.55, 0.30, 0.88]; + let at = 0; + const rng = () => seq[at++ % seq.length]; + const a = planPaletteGenerator(pal, { bg: '#0d0b0a', fg: '#f0fef0' }, { scheme: 'random', accentCount: 4, spanCount: 0, rng }); + const b = planPaletteGenerator(pal, { bg: '#0d0b0a', fg: '#f0fef0' }, { scheme: 'random', accentCount: 4, spanCount: 0, rng }); + assert.equal(a.scheme, 'random'); + assert.equal(a.columns.length, 4); + assert.notDeepEqual(a.columns.map(c => c.baseHex), b.columns.map(c => c.baseHex)); + assert.ok(a.columns.every(c => c.contrast >= 4.5)); + assert.ok(a.columns.some(c => c.C >= 0.11), 'random candidates include more saturated colors than the quiet default'); +}); + +test('planPaletteGenerator: Boundary — omitted scheme defaults to random', () => { + const plan = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { accentCount: 1, spanCount: 0, rng: () => 0.25 }); + assert.equal(plan.scheme, 'random'); +}); + +test('planPaletteGenerator: Boundary — omitted accent count defaults to five', () => { + const plan = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { spanCount: 0, rng: () => 0.25 }); + assert.equal(plan.accentCount, 5); + assert.equal(plan.columns.length, 5); +}); + +test('planPaletteGenerator: Boundary — accent count is clamped to the supported range', () => { + const low = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { accentCount: -4, spanCount: 0, rng: () => 0.25 }); + const high = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { accentCount: 99, spanCount: 0, rng: () => 0.25 }); + assert.equal(low.accentCount, 1); + assert.equal(low.columns.length, 1); + assert.equal(high.accentCount, 12); + assert.equal(high.columns.length, 12); +}); + +test('planPaletteGenerator: Boundary — unknown source mode falls back to bg/fg', () => { + const plan = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { + sourceMode: 'mystery', + baseHue: 17, + accentCount: 1, + spanCount: 0, + }); + assert.equal(plan.sourceMode, 'bg-fg'); + assert.notEqual(Math.round(plan.baseHue), 17); +}); + +test('planPaletteGenerator: Normal — intent near palette uses base columns as anchors', () => { + const pal = [ + ['#0d0b0a', 'bg', 'ground'], + ['#f0fef0', 'fg', 'ground'], + ['#67809c', 'blue', 'blue'], + ['#e8bd30', 'gold', 'gold'], + ['#ffffff', 'blue+1', 'blue'], + ]; + const plan = planPaletteGenerator(pal, { bg: '#0d0b0a', fg: '#f0fef0' }, { + intent: 'near-palette', + sourceMode: 'palette', + vibe: 'balanced', + accentCount: 4, + spanCount: 0, + rng: () => 0.5, + }); + const anchorHues = ['#67809c', '#e8bd30'].map(hex => Math.round(planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { sourceMode: 'selected', selectedHex: hex, accentCount: 1, spanCount: 0, rng: () => 0.1 }).baseHue)); + assert.equal(plan.intent, 'near-palette'); + assert.equal(plan.sourceMode, 'palette'); + assert.equal(plan.columns.length, 4); + assert.ok(plan.columns.every(c => anchorHues.some(h => Math.abs((((c.hue - h + 540) % 360) - 180)) <= 20))); + assert.ok(plan.columns.every(c => c.C >= 0.075 && c.C <= 0.13)); +}); + +test('planPaletteGenerator: Normal — intent fill gaps targets underused hue regions', () => { + const pal = [['#67809c', 'blue', 'blue'], ['#e8bd30', 'gold', 'gold'], ['#cb6b4d', 'terra', 'terra']]; + const plan = planPaletteGenerator(pal, { bg: '#000000', fg: '#ffffff' }, { + intent: 'fill-gaps', + sourceMode: 'palette', + vibe: 'muted', + accentCount: 3, + spanCount: 0, + rng: () => 0.5, + }); + assert.equal(plan.intent, 'fill-gaps'); + assert.equal(plan.columns.length, 3); + assert.ok(plan.columns.every(c => c.C <= 0.09), 'muted vibe keeps chroma lower'); + assert.ok(new Set(plan.columns.map(c => Math.round(c.hue))).size > 1, 'gap fill proposes multiple hue regions'); +}); + +test('planPaletteGenerator: Normal — fill gaps chooses missing perceptual colors', () => { + const anchor = (L,C,H) => oklch2hex(L, C, H).hex; + const pal = [ + [anchor(0.25, 0.08, 40), 'dark-warm', 'dark-warm'], + [anchor(0.75, 0.08, 40), 'light-warm', 'light-warm'], + [anchor(0.50, 0.08, 220), 'mid-cool', 'mid-cool'], + ]; + const plan = planPaletteGenerator(pal, { bg: '#000000', fg: '#ffffff' }, { + intent: 'fill-gaps', + sourceMode: 'palette', + vibe: 'balanced', + contrastMode: 'none', + accentCount: 5, + spanCount: 0, + rng: () => 0.5, + }); + const Ls = plan.columns.map(c => c.L), nearestAnchor = plan.columns.map(c => Math.min(...pal.map(p => deltaE(c.baseHex, p[0])))); + assert.equal(plan.columns.length, 5); + assert.ok(Math.max(...Ls) - Math.min(...Ls) > 0.35, 'candidate spread includes lightness, not hue alone'); + assert.ok(nearestAnchor.every(d => d > 0.14), 'candidates stay perceptually away from existing anchors: '+nearestAnchor.join(',')); +}); + +test('planPaletteGenerator: Boundary — fill gaps with no anchors falls back to random-style candidates', () => { + const seq = [0.10, 0.20, 0.30, 0.40, 0.50, 0.60]; + let at = 0; + const plan = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { + intent: 'fill-gaps', + sourceMode: 'none', + vibe: 'balanced', + accentCount: 3, + spanCount: 0, + rng: () => seq[at++ % seq.length], + }); + assert.equal(plan.columns.length, 3); + assert.ok(new Set(plan.columns.map(c => Math.round(c.hue))).size > 1); +}); + +test('planPaletteGenerator: Normal — fill hue gaps rewards underrepresented hue regions', () => { + const ground = { bg: '#000000', fg: '#ffffff' }; + const baseCfg = { sourceMode: 'bg-fg', vibe: 'balanced', contrastMode: 'aa', accentCount: 5, spanCount: 0, rng: () => 0.5 }; + const plain = planPaletteGenerator([], ground, { ...baseCfg, intent: 'fill-gaps' }); + const hueAware = planPaletteGenerator([], ground, { ...baseCfg, intent: 'fill-hue-gaps' }); + const yellowish = c => c.hue >= 45 && c.hue <= 105; + assert.equal(hueAware.intent, 'fill-hue-gaps'); + assert.notDeepEqual(hueAware.columns.map(c => Math.round(c.hue)), plain.columns.map(c => Math.round(c.hue))); + assert.ok(hueAware.columns.some(yellowish), 'hue-aware fill should surface a yellow/gold region early'); + assert.ok(!plain.columns.some(yellowish), 'plain perceptual fill stays available as a separate behavior'); +}); + +test('planPaletteGenerator: Normal — intent complements generates opposite anchor colors', () => { + const plan = planPaletteGenerator([['#67809c', 'blue', 'blue']], { bg: '#000000', fg: '#ffffff' }, { + intent: 'complements', + sourceMode: 'palette', + vibe: 'bold', + accentCount: 2, + spanCount: 0, + rng: () => 0.5, + }); + assert.equal(plan.intent, 'complements'); + assert.ok(plan.columns.every(c => c.C >= 0.12)); + assert.ok(plan.columns.every(c => Math.abs((((c.hue - (plan.baseHue + 180) + 540) % 360) - 180)) <= 20)); +}); + +test('planPaletteGenerator: Normal — intent bridges generates colors between anchors', () => { + const pal = [['#67809c', 'blue', 'blue'], ['#e8bd30', 'gold', 'gold'], ['#cb6b4d', 'terra', 'terra']]; + const plan = planPaletteGenerator(pal, { bg: '#000000', fg: '#ffffff' }, { + intent: 'bridges', + sourceMode: 'palette', + vibe: 'balanced', + accentCount: 3, + spanCount: 0, + rng: () => 0.5, + }); + assert.equal(plan.intent, 'bridges'); + assert.equal(plan.columns.length, 3); + assert.ok(new Set(plan.columns.map(c => Math.round(c.hue))).size > 1); + assert.ok(plan.columns.every(c => c.C >= 0.075 && c.C <= 0.13)); +}); + +test('planPaletteGenerator: Normal — harmony intents generate expected hue families', () => { + const planFor = intent => planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { + intent, + sourceMode: 'selected', + selectedHex: '#67809c', + baseHue: 250, + vibe: 'balanced', + accentCount: 4, + spanCount: 0, + rng: () => 0.5, + }); + const cfg = intent => planFor(intent).columns.map(c => Math.round(c.hue)); + const base = Math.round(planFor('triadic').baseHue); + const dist = (a, b) => Math.abs((((a - b + 540) % 360) - 180)); + assert.ok(cfg('complementary').every(h => dist(h, (base + 180) % 360) <= 1)); + assert.deepEqual(cfg('triadic').slice(0, 3).map(h => Math.round((h - base + 360) % 360)), [0, 120, 240]); + assert.deepEqual(cfg('square').map(h => Math.round((h - base + 360) % 360)), [0, 90, 180, 270]); + assert.deepEqual(cfg('tetradic').map(h => Math.round((h - base + 360) % 360)), [0, 60, 180, 240]); + assert.ok(new Set(cfg('rainbow')).size === 4); + assert.ok(cfg('monochromatic').every(h => dist(h, base) <= 3)); + assert.ok(cfg('split-complementary').slice(0, 2).every(h => dist(h, (base + 150) % 360) <= 1 || dist(h, (base + 210) % 360) <= 1)); + assert.ok(cfg('analogous').slice(0, 2).every(h => dist(h, (base + 330) % 360) <= 1 || dist(h, (base + 30) % 360) <= 1)); +}); + +test('planPaletteGenerator: Normal — harmony intents work with palette anchors', () => { + const pal = [['#67809c', 'blue', 'blue'], ['#e8bd30', 'gold', 'gold']]; + const intents = ['complementary', 'analogous', 'split-complementary', 'triadic', 'tetradic', 'square', 'monochromatic', 'rainbow']; + for (const intent of intents) { + const plan = planPaletteGenerator(pal, { bg: '#000000', fg: '#ffffff' }, { + intent, + sourceMode: 'palette', + vibe: 'balanced', + accentCount: 4, + spanCount: 0, + rng: () => 0.5, + }); + assert.equal(plan.sourceMode, 'palette', intent); + assert.equal(plan.intent, intent); + assert.equal(plan.columns.length, 4, intent); + assert.ok(plan.columns.every(c => c.contrast >= 4.5), intent); + } +}); + +test('planPaletteGenerator: Boundary — empty palette source falls back to configured hue', () => { + const plan = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { + intent: 'near-palette', + sourceMode: 'palette', + baseHue: 123, + vibe: 'balanced', + accentCount: 2, + spanCount: 0, + rng: () => 0.5, + }); + assert.equal(plan.sourceMode, 'palette'); + assert.equal(plan.columns.length, 2); + assert.ok(Math.abs(plan.baseHue - 123) < 0.001); + assert.ok(plan.columns.every(c => Math.abs((((c.hue - 123 + 540) % 360) - 180)) <= 20)); +}); + +test('planPaletteGenerator: Boundary — invalid selected source falls back to bg/fg', () => { + const plan = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { + intent: 'near-selected', + sourceMode: 'selected', + selectedHex: 'not-a-color', + baseHue: 22, + accentCount: 1, + spanCount: 0, + }); + assert.equal(plan.sourceMode, 'bg-fg'); + assert.notEqual(Math.round(plan.baseHue), 22); +}); + +test('planPaletteGenerator: Boundary — high contrast can reject every candidate', () => { + const plan = planPaletteGenerator([], { bg: '#777777', fg: '#ffffff' }, { + intent: 'random', + sourceMode: 'none', + vibe: 'pastel', + contrastMode: 'aaa', + accentCount: 4, + spanCount: 0, + rng: () => 0.5, + }); + assert.equal(plan.columns.length, 0); + assert.equal(plan.rejected.length, 4); + assert.equal(plan.summary.rejected, 4); + assert.equal(plan.summary.minContrast, null); +}); + +test('planPaletteGenerator: Boundary — contrast none keeps otherwise rejected candidates', () => { + const plan = planPaletteGenerator([], { bg: '#777777', fg: '#ffffff' }, { + intent: 'random', + sourceMode: 'none', + vibe: 'pastel', + contrastMode: 'none', + accentCount: 4, + spanCount: 0, + rng: () => 0.5, + }); + assert.equal(plan.columns.length, 4); + assert.equal(plan.rejected.length, 0); + assert.ok(plan.summary.minContrast < 7); +}); + +test('planPaletteGenerator: Normal — warm and cool vibes bias candidate hue families', () => { + const warm = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { intent: 'random', vibe: 'warm', accentCount: 4, spanCount: 0, rng: () => 0.25 }); + const cool = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { intent: 'random', vibe: 'cool', accentCount: 4, spanCount: 0, rng: () => 0.25 }); + assert.ok(warm.columns.every(c => c.hue < 90 || c.hue > 340), 'warm stays in red/orange/yellow hue families'); + assert.ok(cool.columns.every(c => c.hue > 140 && c.hue < 310), 'cool stays in green/cyan/blue/violet hue families'); +}); + +test('planPaletteGenerator: Normal — added vibes produce distinct chroma ranges', () => { + const mk = vibe => planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { intent: 'random', vibe, accentCount: 1, spanCount: 0, rng: () => 0.5 }).columns[0].C; + assert.ok(mk('pastel') < mk('deep')); + assert.ok(mk('jewel') > mk('balanced')); + assert.ok(mk('neon') > mk('jewel')); + assert.ok(mk('strange') > mk('bold')); +}); + +test('planPaletteGenerator: Boundary — selected source uses the selected color hue', () => { + const plan = planPaletteGenerator([['#67809c', 'blue', 'blue']], { bg: '#101010', fg: '#f0f0f0' }, { + sourceMode: 'selected', + selectedHex: '#e8bd30', + accentCount: 3, + spanCount: 0, + }); + assert.equal(plan.sourceMode, 'selected'); + assert.equal(plan.columns.length, 3); + assert.equal(plan.columns[0].members.length, 1); + assert.ok(Math.abs(plan.baseHue - 91) < 8, 'gold-ish selected color drives the hue base'); +}); + +test('planPaletteGenerator: Boundary — generated names avoid palette collisions', () => { + const plan = planPaletteGenerator([['#111111', 'steel-blue', 'steel-blue']], { bg: '#000000', fg: '#ffffff' }, { + sourceMode: 'selected', + selectedHex: '#67809c', + accentCount: 2, + spanCount: 0, + rng: () => 0.5, + colorNames: COLOR_NAMES, + }); + assert.ok(plan.columns.every(c => !/^generated/.test(c.name)), 'generated candidates use nearest color names'); + assert.equal(new Set(plan.columns.map(c => c.name)).size, 2, 'nearest names are uniqued'); + assert.ok(plan.columns.every(c => !/[+-]\d+$/.test(c.name)), 'unique generated base names do not look like span offsets'); +}); + +test('color name table: Normal — uses filtered X11/CSS-style names', () => { + assert.ok(COLOR_NAMES.length > 100); + assert.ok(COLOR_NAMES.some(([name]) => name === 'steel-blue')); + assert.ok(COLOR_NAMES.some(([name]) => name === 'dark-olive')); + assert.ok(!COLOR_NAMES.some(([name]) => name === 'dark-olive-green')); + assert.ok(COLOR_NAMES.some(([name]) => name === 'medium-aquamarine')); + assert.ok(COLOR_NAMES.some(([name]) => name === 'medium-turquoise')); + assert.ok(COLOR_NAMES.every(([name]) => !/\d+$/.test(name)), 'numbered variants are excluded'); + assert.ok(COLOR_NAMES.every(([, hex]) => /^#[0-9a-f]{6}$/.test(hex)), 'colors are normalized hex'); +}); + +test('planPaletteGenerator: Boundary — missing neutral source falls back to configured hue', () => { + const plan = planPaletteGenerator([], {}, { baseHue: 42, accentCount: 1, spanCount: 0 }); + assert.ok(Math.abs(plan.baseHue - 42) < 0.001); + assert.equal(plan.columns.length, 1); +}); + +test('planPaletteGenerator: Normal — analogous and triadic schemes choose distinct hue layouts', () => { + const base = { baseHue: 30, accentCount: 3, spanCount: 0 }; + const analogous = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { ...base, scheme: 'analogous' }); + const triadic = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { ...base, scheme: 'triadic' }); + assert.notDeepEqual( + analogous.columns.map(c => Math.round(c.hue)), + triadic.columns.map(c => Math.round(c.hue)), + ); + assert.ok(Math.abs(triadic.columns[1].hue - ((triadic.columns[0].hue + 120) % 360)) < 1); +}); + +test('entriesForGeneratedColumn: Normal — converts one preview column to stable palette entries', () => { + const plan = planPaletteGenerator([], { bg: '#000000', fg: '#ffffff' }, { accentCount: 1, spanCount: 1 }); + const entries = entriesForGeneratedColumn(plan.columns[0]); + assert.equal(entries.length, 1); + assert.ok(entries.every(e => e[2] === plan.columns[0].columnId)); + assert.deepEqual(entries.map(e => e[1]), [plan.columns[0].name]); +}); + +test('entriesForGeneratedColumn: Boundary — empty and partial columns are safe', () => { + assert.deepEqual(entriesForGeneratedColumn(null), []); + assert.deepEqual(entriesForGeneratedColumn({ name: 'candidate', members: [{ hex: '#123456', name: 'candidate' }] }), [['#123456', 'candidate', 'candidate']]); + assert.deepEqual(entriesForGeneratedColumn({ members: [{ hex: '#abcdef', name: 'unnamed' }] }), [['#abcdef', 'unnamed', 'generated']]); +}); + test('groundColumnMembersFromPalette: Normal — sorts bg, ground+N steps, then fg', () => { const members = groundColumnMembersFromPalette([ ['#ffffff', 'bg', 'ground'], @@ -319,6 +697,18 @@ test('inline-integrity: theme-studio.html contains the app-core.js body verbatim assert.ok(html.includes(body), 'generated page is missing the app-core.js body verbatim'); }); +test('inline-integrity: theme-studio.html contains palette-generator-core.js verbatim', () => { + const body = stripExports(readFileSync(here + 'palette-generator-core.js', 'utf8')); + const html = readFileSync(here + 'theme-studio.html', 'utf8'); + assert.ok(html.includes(body), 'generated page is missing palette-generator-core.js verbatim'); +}); + +test('inline-integrity: theme-studio.html contains palette-generator-ui.js verbatim', () => { + const body = stripExports(readFileSync(here + 'palette-generator-ui.js', 'utf8')); + const html = readFileSync(here + 'theme-studio.html', 'utf8'); + assert.ok(html.includes(body), 'generated page is missing palette-generator-ui.js verbatim'); +}); + test('inline-integrity: theme-studio.html contains palette-actions.js verbatim', () => { const body = stripExports(readFileSync(here + 'palette-actions.js', 'utf8')); const html = readFileSync(here + 'theme-studio.html', 'utf8'); @@ -330,3 +720,52 @@ test('inline-integrity: theme-studio.html contains browser-gates.js verbatim', ( const html = readFileSync(here + 'theme-studio.html', 'utf8'); assert.ok(html.includes(body), 'generated page is missing browser-gates.js verbatim'); }); + +// resolveSyntaxFg: an unset syntax category resolves through the Emacs inherit +// chain (the way the generated theme renders), not to the flat default fg. +test('resolveSyntaxFg: a set category uses its own foreground', () => { + assert.equal(resolveSyntaxFg('kw', { kw: { fg: '#aaaaaa' } }, '#ffffff'), '#aaaaaa'); +}); +test('resolveSyntaxFg: unset cmd inherits cm (comment-delimiter -> comment)', () => { + assert.equal(resolveSyntaxFg('cmd', { cm: { fg: '#888888' }, cmd: { fg: null } }, '#ffffff'), '#888888'); +}); +test('resolveSyntaxFg: unset doc inherits str (doc -> string)', () => { + assert.equal(resolveSyntaxFg('doc', { str: { fg: '#00aa00' }, doc: { fg: null } }, '#ffffff'), '#00aa00'); +}); +test('resolveSyntaxFg: unset prop inherits var (property-name -> variable-name)', () => { + assert.equal(resolveSyntaxFg('prop', { var: { fg: '#0000aa' }, prop: { fg: null } }, '#ffffff'), '#0000aa'); +}); +test('resolveSyntaxFg: unset fnc inherits fnd (function-call -> function-name)', () => { + assert.equal(resolveSyntaxFg('fnc', { fnd: { fg: '#aa00aa' }, fnc: { fg: null } }, '#ffffff'), '#aa00aa'); +}); +test('resolveSyntaxFg: dec is pinned to ty even when dec has its own fg', () => { + assert.equal(resolveSyntaxFg('dec', { ty: { fg: '#9b5fd0' }, dec: { fg: '#e8bd30' } }, '#ffffff'), '#9b5fd0'); +}); +test('resolveSyntaxFg: an unset chain bottoms out at the default fg', () => { + assert.equal(resolveSyntaxFg('cmd', { cm: { fg: null }, cmd: { fg: null } }, '#ffffff'), '#ffffff'); +}); +test('resolveSyntaxFg: a category with no inherit and no fg uses the default fg', () => { + assert.equal(resolveSyntaxFg('kw', { kw: { fg: null } }, '#ffffff'), '#ffffff'); +}); + +// resolveUiAttr: an unset ui face attribute resolves through the Emacs built-in +// ui inherit chain (mode-line-inactive -> mode-line, line-number-current-line -> +// line-number), returning null when nothing up the chain is set (caller floors it). +test('resolveUiAttr: a set ui face uses its own attribute', () => { + assert.equal(resolveUiAttr('mode-line', 'fg', { 'mode-line': { fg: '#111111' } }), '#111111'); +}); +test('resolveUiAttr: unset mode-line-inactive inherits mode-line', () => { + assert.equal(resolveUiAttr('mode-line-inactive', 'bg', + { 'mode-line': { bg: '#222222' }, 'mode-line-inactive': { bg: null } }), '#222222'); +}); +test('resolveUiAttr: unset line-number-current-line inherits line-number', () => { + assert.equal(resolveUiAttr('line-number-current-line', 'fg', + { 'line-number': { fg: '#333333' }, 'line-number-current-line': { fg: null } }), '#333333'); +}); +test('resolveUiAttr: returns null when nothing up the chain is set', () => { + assert.equal(resolveUiAttr('mode-line-inactive', 'fg', + { 'mode-line': { fg: null }, 'mode-line-inactive': { fg: null } }), null); +}); +test('resolveUiAttr: a face with no inherit and an unset attribute returns null', () => { + assert.equal(resolveUiAttr('region', 'bg', { 'region': { bg: null } }), null); +}); diff --git a/scripts/theme-studio/test_generate.py b/scripts/theme-studio/test_generate.py index 4e9afb1e5..ed2ce74ba 100644 --- a/scripts/theme-studio/test_generate.py +++ b/scripts/theme-studio/test_generate.py @@ -78,9 +78,11 @@ class ColormathInlining(unittest.TestCase): class AssembledPage(unittest.TestCase): PLACEHOLDERS = [ "STYLES_CSS", "APP_JS", "APP_CORE_J", "APP_UTIL_J", + "PALETTE_GENERATOR_CORE_J", "PALETTE_GENERATOR_UI_J", "PALETTE_ACTIONS_J", "BROWSER_GATES_J", "COLORMATH_J", "SAMPLES_J", "PALETTE_J", "CATS_J", "UIFACES_J", "UIMAP_J", "APPS_J", "SYNTAX_J", "MAP_J", + "COLOR_NAMES_J", ] def test_every_placeholder_is_substituted(self): @@ -101,6 +103,12 @@ class AssembledPage(unittest.TestCase): # app-util.js inlines verbatim after its import line is stripped. self.assertIn(generate.APP_UTIL_BODY, generate.HTML) + def test_page_carries_palette_generator_core_verbatim(self): + self.assertIn(generate.PALETTE_GENERATOR_CORE_BODY, generate.HTML) + + def test_page_carries_palette_generator_ui_verbatim(self): + self.assertIn(generate.PALETTE_GENERATOR_UI_BODY, generate.HTML) + def test_page_carries_palette_actions_verbatim(self): self.assertIn(generate.PALETTE_ACTIONS_BODY, generate.HTML) diff --git a/scripts/theme-studio/theme-studio.html b/scripts/theme-studio/theme-studio.html index b815e5bfa..d05ac912f 100644 --- a/scripts/theme-studio/theme-studio.html +++ b/scripts/theme-studio/theme-studio.html @@ -42,6 +42,7 @@ .boxctl .cstepbtn{width:18px} .legctl{margin:0 0 8px;display:flex;gap:8px;align-items:center} .cat{color:#b4b1a2} .ex{font-size:17px} + .crerr{display:inline-block;margin-left:8px;padding:0 4px;border-radius:3px;background:#2b130e;color:#cb6b4d;border:1px solid #7b3324;font:9pt monospace;vertical-align:middle} .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;flex-direction:row;flex-wrap:wrap;gap:10px;align-items:flex-start} @@ -98,6 +99,24 @@ .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} + .genctl{margin:0 0 14px;padding:8px 10px;border:1px solid #252321;border-radius:7px;background:#11100e} + .genrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap;color:#b4b1a2;font:10pt monospace} + .genrow label{display:flex;gap:5px;align-items:center} + .genrow label.disabled{opacity:.45} + .genrow select,.genrow input{background:#161412;border:1px solid #252321;color:#cdced1;border-radius:4px;padding:4px 6px;font:10pt monospace} + .genrow input:disabled{opacity:.55;cursor:default} + .genrow input{width:48px} + .genrow button{background:#252321;color:#e8bd30;border:1px solid #3a3a3a;border-radius:4px;padding:5px 10px;font:10pt monospace;cursor:pointer} + #genmsg{color:#8a9496} + .genpreview{display:flex;gap:10px;align-items:flex-start;flex-wrap:wrap;margin-top:8px} + .gencol{display:flex;flex-direction:column;gap:6px;padding:5px;border:1px dashed #3a3a3a;border-radius:7px} + .genhead{width:128px;display:flex;gap:4px;align-items:center;justify-content:center;color:#b4b1a2;font:9pt monospace} + .genhead span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;text-align:center;white-space:nowrap} + .genappend{width:22px;height:22px;padding:0;border:1px solid #3a3a3a;border-radius:4px;background:#252321;color:#e8bd30;font:bold 12px monospace;cursor:pointer} + .genchip{width:128px;height:58px;border-radius:6px;border:1px solid #555;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer;font:10pt monospace;line-height:1.15;text-align:center;box-sizing:border-box;padding:3px 5px;overflow:hidden} + .genchip.sel{outline:2px solid #e8bd30;outline-offset:2px} + .genchip .gn{font-weight:bold;white-space:normal;overflow-wrap:normal;max-width:116px} + .genchip .gh{opacity:.8;white-space:nowrap} #export{width:100%;height:180px;margin-top:10px;background:#0d0b0a;color:#a4ac64;border:1px solid #252321;border-radius:6px;font:10pt monospace;padding:10px} .filebar{margin:6px 0 0;display:flex;gap:8px;align-items:center} #pagetitle{font-size:30px;color:#cdced1;font-weight:normal;border:none;margin:0;padding:0} @@ -112,7 +131,10 @@ #pkgbody td{padding:3px 8px} #codepre{width:100%;box-sizing:border-box} .mock{border:1px solid #252321;border-radius:8px;overflow:hidden;font:12pt/1.7 monospace;display:flex;flex-direction:column} - .mock .mbuf{flex:1} .mock .ln{display:flex;align-items:stretch;white-space:pre} + .mock .mbuf{flex:1;display:flex;align-items:stretch;overflow:auto} + .mock .mbuftext{flex:0 1 auto;width:max-content;max-width:calc(100% - 4ch - 3px);padding-right:4ch;box-sizing:border-box;overflow:hidden} + .mock .vborder{width:3px;flex:0 0 auto} + .mock .ln{display:flex;align-items:stretch;white-space:pre} .mock .fr{width:14px;flex:0 0 auto;border-right:1px solid #ffffff14} .mock .num{width:36px;flex:0 0 auto;text-align:right;padding-right:10px} .mock .cd{flex:1;padding-left:8px} .mock .bar,.mock .echo{padding:4px 10px;white-space:pre} #codepre [data-k],.mock [data-k],.mock [data-face]{cursor:pointer} @@ -162,6 +184,19 @@ <div id="pkchips" class="pkchips"></div> </div> </div> + <div class="genctl" id="genctl"> + <div class="genrow"> + <label>intent <select id="genintent"></select></label> + <label>vibe <select id="genvibe"></select></label> + <label>source <select id="gensource"></select></label> + <label title="how many base columns to propose">accent count <input id="genaccents" type="number" min="1" max="12" step="1" value="5"></label> + <label>contrast <select id="gencontrast"></select></label> + <button onclick="previewGenerator()">preview</button> + <button onclick="clearGeneratorPreview()">clear preview</button> + <span id="genmsg"></span> + </div> + <div id="genpreview" class="genpreview"></div> + </div> <div class="pals" id="pals"></div> <div class="palwarn" id="palwarn"></div> </section> @@ -205,7 +240,8 @@ </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", "}"]]], "Rust": [[["cmd", "//"], ["cm", " theme.rs"]], [["dec", "#![allow(dead_code)]"]], [["kw", "use"], ["p", " "], ["var", "std"], ["op", "::"], ["var", "fmt"], ["punc", ";"]], [], [["dec", "#[derive"], ["punc", "("], ["dec", "Debug"], ["punc", ","], ["p", " "], ["dec", "Clone"], ["punc", ")]"]], [["kw", "pub"], ["p", " "], ["kw", "trait"], ["p", " "], ["ty", "Theme"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "const"], ["p", " "], ["con", "NAME"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'static"], ["p", " "], ["ty", "str"], ["punc", ";"]], [["p", " "], ["kw", "fn"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["op", "&"], ["var", "'a"], ["p", " "], ["var", "self"], ["punc", ","], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "Option"], ["op", "<"], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["op", ">"], ["punc", ";"]], [["punc", "}"]], [], [["kw", "pub"], ["p", " "], ["kw", "struct"], ["p", " "], ["ty", "Palette"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "pub"], ["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ","]], [["p", " "], ["kw", "pub"], ["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["ty", "Vec"], ["op", "<"], ["punc", "("], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ","], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ")"], ["op", ">"], ["punc", ","]], [["punc", "}"]], [], [["kw", "impl"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["ty", "Theme"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["kw", "for"], ["p", " "], ["ty", "Palette"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "const"], ["p", " "], ["con", "NAME"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'static"], ["p", " "], ["ty", "str"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ";"]], [["p", " "], ["kw", "fn"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["op", "&"], ["var", "'a"], ["p", " "], ["var", "self"], ["punc", ","], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "Option"], ["op", "<"], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["var", "key"], ["op", "."], ["fnc", "is_empty"], ["punc", "()"], ["p", " "], ["punc", "{"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "None"], ["punc", ";"], ["p", " "], ["punc", "}"]], [["p", " "], ["var", "self"], ["op", "."], ["prop", "colors"], ["op", "."], ["fnc", "iter"], ["punc", "()"], ["op", "."], ["fnc", "find"], ["punc", "("], ["op", "|"], ["punc", "("], ["var", "k"], ["punc", ","], ["p", " "], ["var", "_"], ["punc", ")"], ["op", "|"], ["p", " "], ["op", "*"], ["var", "k"], ["p", " "], ["op", "=="], ["p", " "], ["var", "key"], ["punc", ")"], ["op", "."], ["fnc", "map"], ["punc", "("], ["op", "|"], ["punc", "("], ["var", "_"], ["punc", ","], ["p", " "], ["var", "v"], ["punc", ")"], ["op", "|"], ["p", " "], ["op", "*"], ["var", "v"], ["punc", ")"]], [["p", " "], ["punc", "}"]], [["punc", "}"]], [], [["kw", "fn"], ["p", " "], ["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "let"], ["p", " "], ["var", "palette"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Palette"], ["p", " "], ["punc", "{"], ["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["str", "\"dupre\""], ["punc", ","], ["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["bi", "vec!"], ["punc", "["], ["punc", "("], ["str", "\"bg\""], ["punc", ","], ["p", " "], ["str", "\"#0d0b0a\""], ["punc", ")"], ["punc", "]"], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["bi", "println!"], ["punc", "("], ["str", "\"{:?}\""], ["punc", ","], ["p", " "], ["var", "palette"], ["op", "."], ["fnc", "resolve"], ["punc", "("], ["str", "\"bg\""], ["punc", "))"], ["punc", ";"]], [["punc", "}"]]], "Zig": [[["cmd", "//"], ["cm", " theme.zig"]], [["kw", "const"], ["p", " "], ["var", "std"], ["p", " "], ["op", "="], ["p", " "], ["bi", "@import"], ["punc", "("], ["str", "\"std\""], ["punc", ")"], ["punc", ";"]], [["kw", "const"], ["p", " "], ["ty", "Allocator"], ["p", " "], ["op", "="], ["p", " "], ["var", "std"], ["op", "."], ["var", "mem"], ["op", "."], ["ty", "Allocator"], ["punc", ";"]], [], [["kw", "pub"], ["p", " "], ["kw", "const"], ["p", " "], ["ty", "Theme"], ["p", " "], ["op", "="], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"]], [["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["punc", ","]], [["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "Color"], ["punc", ","]], [], [["p", " "], ["kw", "pub"], ["p", " "], ["kw", "fn"], ["p", " "], ["fnd", "init"], ["punc", "("], ["var", "alloc"], ["op", ":"], ["p", " "], ["op", "*"], ["ty", "Allocator"], ["punc", ")"], ["p", " "], ["op", "!"], ["bi", "@This"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "const"], ["p", " "], ["var", "colors"], ["p", " "], ["op", "="], ["p", " "], ["kw", "try"], ["p", " "], ["var", "alloc"], ["op", "."], ["fnc", "alloc"], ["punc", "("], ["ty", "Color"], ["punc", ","], ["p", " "], ["num", "2"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["var", "colors"], ["punc", "["], ["num", "0"], ["punc", "]"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Color"], ["punc", "{"], ["p", " "], ["prop", ".name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"bg\""], ["punc", ","], ["p", " "], ["prop", ".hex"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"#0d0b0a\""], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["bi", "@This"], ["punc", "()"], ["punc", "{"], ["p", " "], ["prop", ".name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ","], ["p", " "], ["prop", ".colors"], ["p", " "], ["op", "="], ["p", " "], ["var", "colors"], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"], ["punc", ";"]], [], [["kw", "const"], ["p", " "], ["ty", "Color"], ["p", " "], ["op", "="], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"], ["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["punc", ","], ["p", " "], ["prop", "hex"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["p", " "], ["punc", "}"], ["punc", ";"]], [], [["kw", "fn"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["var", "theme"], ["op", ":"], ["p", " "], ["ty", "Theme"], ["punc", ","], ["p", " "], ["kw", "comptime"], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", ":"], ["num", "0"], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["punc", ")"], ["p", " "], ["op", "!"], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "inline"], ["p", " "], ["kw", "for"], ["p", " "], ["punc", "("], ["var", "theme"], ["op", "."], ["prop", "colors"], ["punc", ")"], ["p", " "], ["op", "|"], ["var", "color"], ["op", "|"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "std"], ["op", "."], ["var", "mem"], ["op", "."], ["fnc", "eql"], ["punc", "("], ["ty", "u8"], ["punc", ","], ["p", " "], ["var", "color"], ["op", "."], ["prop", "name"], ["punc", ","], ["p", " "], ["var", "key"], ["punc", ")"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["var", "color"], ["op", "."], ["prop", "hex"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["p", " "], ["kw", "return"], ["p", " "], ["con", "error.MissingColor"], ["punc", ";"]], [["punc", "}"]], [], [["kw", "test"], ["p", " "], ["str", "\"resolve bg\""], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "var"], ["p", " "], ["var", "arena"], ["p", " "], ["op", "="], ["p", " "], ["var", "std"], ["op", "."], ["var", "heap"], ["op", "."], ["ty", "ArenaAllocator"], ["op", "."], ["fnc", "init"], ["punc", "("], ["var", "std"], ["op", "."], ["var", "testing"], ["op", "."], ["prop", "allocator"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["kw", "defer"], ["p", " "], ["var", "arena"], ["op", "."], ["fnc", "deinit"], ["punc", "()"], ["punc", ";"]], [["p", " "], ["kw", "try"], ["p", " "], ["var", "std"], ["op", "."], ["var", "testing"], ["op", "."], ["fnc", "expectEqualStrings"], ["punc", "("], ["str", "\"#0d0b0a\""], ["punc", ","], ["p", " "], ["kw", "try"], ["p", " "], ["fnc", "resolve"], ["punc", "("], ["kw", "try"], ["p", " "], ["ty", "Theme"], ["op", "."], ["fnc", "init"], ["punc", "("], ["op", "&"], ["var", "arena"], ["op", "."], ["prop", "allocator"], ["punc", ")"], ["punc", ","], ["p", " "], ["str", "\"bg\""], ["punc", "))"], ["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", {}], ["org-document-info", "document info", {}], ["org-document-info-keyword", "document info keyword", {}], ["org-level-1", "level 1", {}], ["org-level-2", "level 2", {}], ["org-level-3", "level 3", {}], ["org-level-4", "level 4", {}], ["org-level-5", "level 5", {}], ["org-level-6", "level 6", {}], ["org-level-7", "level 7", {}], ["org-level-8", "level 8", {}], ["org-headline-todo", "headline todo", {}], ["org-headline-done", "headline done", {}], ["org-todo", "todo", {}], ["org-done", "done", {}], ["org-priority", "priority", {}], ["org-tag", "tag", {}], ["org-tag-group", "tag group", {}], ["org-special-keyword", "special keyword", {}], ["org-drawer", "drawer", {}], ["org-property-value", "property value", {}], ["org-checkbox", "checkbox", {}], ["org-checkbox-statistics-todo", "checkbox statistics todo", {}], ["org-checkbox-statistics-done", "checkbox statistics done", {}], ["org-warning", "warning", {}], ["org-link", "link", {}], ["org-footnote", "footnote", {}], ["org-date", "date", {}], ["org-sexp-date", "sexp date", {}], ["org-date-selected", "date selected", {}], ["org-target", "target", {}], ["org-macro", "macro", {}], ["org-cite", "cite", {}], ["org-cite-key", "cite key", {}], ["org-block", "block", {}], ["org-block-begin-line", "block begin line", {}], ["org-block-end-line", "block end line", {}], ["org-code", "code", {}], ["org-verbatim", "verbatim", {}], ["org-inline-src-block", "inline src block", {}], ["org-quote", "quote", {}], ["org-verse", "verse", {}], ["org-latex-and-related", "latex and related", {}], ["org-table", "table", {}], ["org-table-header", "table header", {}], ["org-table-row", "table row", {}], ["org-formula", "formula", {}], ["org-column", "column", {}], ["org-column-title", "column title", {}], ["org-list-dt", "list dt", {}], ["org-meta-line", "meta line", {}], ["org-ellipsis", "ellipsis", {}], ["org-hide", "hide", {}], ["org-indent", "indent", {}], ["org-archived", "archived", {}], ["org-default", "default", {}], ["org-dispatcher-highlight", "dispatcher highlight", {}], ["org-agenda-structure", "agenda structure", {}], ["org-agenda-structure-secondary", "agenda structure secondary", {}], ["org-agenda-structure-filter", "agenda structure filter", {}], ["org-agenda-date", "agenda date", {}], ["org-agenda-date-today", "agenda date today", {}], ["org-agenda-date-weekend", "agenda date weekend", {}], ["org-agenda-date-weekend-today", "agenda date weekend today", {}], ["org-agenda-current-time", "agenda current time", {}], ["org-agenda-done", "agenda done", {}], ["org-agenda-dimmed-todo-face", "agenda dimmed todo", {}], ["org-agenda-calendar-event", "agenda calendar event", {}], ["org-agenda-calendar-sexp", "agenda calendar sexp", {}], ["org-agenda-calendar-daterange", "agenda calendar daterange", {}], ["org-agenda-diary", "agenda diary", {}], ["org-agenda-clocking", "agenda clocking", {}], ["org-agenda-column-dateline", "agenda column dateline", {}], ["org-agenda-restriction-lock", "agenda restriction lock", {}], ["org-agenda-filter-category", "agenda filter category", {}], ["org-agenda-filter-effort", "agenda filter effort", {}], ["org-agenda-filter-regexp", "agenda filter regexp", {}], ["org-agenda-filter-tags", "agenda filter tags", {}], ["org-scheduled", "scheduled", {}], ["org-scheduled-today", "scheduled today", {}], ["org-scheduled-previously", "scheduled previously", {}], ["org-upcoming-deadline", "upcoming deadline", {}], ["org-upcoming-distant-deadline", "upcoming distant deadline", {}], ["org-imminent-deadline", "imminent deadline", {}], ["org-time-grid", "time grid", {}], ["org-clock-overlay", "clock overlay", {}], ["org-mode-line-clock", "mode line clock", {}], ["org-mode-line-clock-overrun", "mode line clock overrun", {}]]}, "magit": {"label": "magit", "preview": "magit", "faces": [["magit-section-heading", "section heading", {}], ["magit-section-secondary-heading", "section secondary heading", {}], ["magit-section-heading-selection", "section heading selection", {}], ["magit-section-highlight", "section highlight", {}], ["magit-section-child-count", "section child count", {}], ["magit-diff-added", "diff added", {}], ["magit-diff-added-highlight", "diff added highlight", {}], ["magit-diff-removed", "diff removed", {}], ["magit-diff-removed-highlight", "diff removed highlight", {}], ["magit-diff-context", "diff context", {}], ["magit-diff-context-highlight", "diff context highlight", {}], ["magit-diff-file-heading", "diff file heading", {}], ["magit-diff-file-heading-highlight", "diff file heading highlight", {}], ["magit-diff-file-heading-selection", "diff file heading selection", {}], ["magit-diff-hunk-heading", "diff hunk heading", {}], ["magit-diff-hunk-heading-highlight", "diff hunk heading highlight", {}], ["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", {}], ["magit-diffstat-added", "diffstat added", {}], ["magit-diffstat-removed", "diffstat removed", {}], ["magit-branch-current", "branch current", {}], ["magit-branch-local", "branch local", {}], ["magit-branch-remote", "branch remote", {}], ["magit-branch-remote-head", "branch remote head", {}], ["magit-branch-upstream", "branch upstream", {}], ["magit-branch-warning", "branch warning", {}], ["magit-head", "head", {}], ["magit-tag", "tag", {}], ["magit-hash", "hash", {}], ["magit-filename", "filename", {}], ["magit-dimmed", "dimmed", {}], ["magit-keyword", "keyword", {}], ["magit-keyword-squash", "keyword squash", {}], ["magit-refname", "refname", {}], ["magit-refname-stash", "refname stash", {}], ["magit-refname-wip", "refname wip", {}], ["magit-refname-pullreq", "refname pullreq", {}], ["magit-log-author", "log author", {}], ["magit-log-date", "log date", {}], ["magit-log-graph", "log graph", {}], ["magit-header-line", "header line", {}], ["magit-header-line-key", "header line key", {}], ["magit-header-line-log-select", "header line log select", {}], ["magit-process-ok", "process ok", {}], ["magit-process-ng", "process ng", {}], ["magit-mode-line-process", "mode line process", {}], ["magit-mode-line-process-error", "mode line process error", {}], ["magit-bisect-good", "bisect good", {}], ["magit-bisect-bad", "bisect bad", {}], ["magit-bisect-skip", "bisect skip", {}], ["magit-blame-heading", "blame heading", {}], ["magit-blame-highlight", "blame highlight", {}], ["magit-blame-hash", "blame hash", {}], ["magit-blame-name", "blame name", {}], ["magit-blame-date", "blame date", {}], ["magit-blame-summary", "blame summary", {}], ["magit-blame-dimmed", "blame dimmed", {}], ["magit-blame-margin", "blame margin", {}], ["magit-cherry-equivalent", "cherry equivalent", {}], ["magit-cherry-unmatched", "cherry unmatched", {}], ["magit-signature-good", "signature good", {}], ["magit-signature-bad", "signature bad", {}], ["magit-signature-untrusted", "signature untrusted", {}], ["magit-signature-expired", "signature expired", {}], ["magit-signature-expired-key", "signature expired key", {}], ["magit-signature-revoked", "signature revoked", {}], ["magit-signature-error", "signature error", {}], ["magit-reflog-commit", "reflog commit", {}], ["magit-reflog-amend", "reflog amend", {}], ["magit-reflog-merge", "reflog merge", {}], ["magit-reflog-checkout", "reflog checkout", {}], ["magit-reflog-reset", "reflog reset", {}], ["magit-reflog-rebase", "reflog rebase", {}], ["magit-reflog-cherry-pick", "reflog cherry pick", {}], ["magit-reflog-remote", "reflog remote", {}], ["magit-reflog-other", "reflog other", {}], ["magit-sequence-pick", "sequence pick", {}], ["magit-sequence-stop", "sequence stop", {}], ["magit-sequence-part", "sequence part", {}], ["magit-sequence-head", "sequence head", {}], ["magit-sequence-drop", "sequence drop", {}], ["magit-sequence-done", "sequence done", {}], ["magit-sequence-onto", "sequence onto", {}], ["magit-sequence-exec", "sequence exec", {}], ["magit-left-margin", "left margin", {}], ["git-commit-comment-action", "git commit comment action", {}], ["git-commit-comment-branch-local", "git commit comment branch local", {}], ["git-commit-comment-branch-remote", "git commit comment branch remote", {}], ["git-commit-comment-detached", "git commit comment detached", {}], ["git-commit-comment-file", "git commit comment file", {}], ["git-commit-comment-heading", "git commit comment heading", {}], ["git-commit-keyword", "git commit keyword", {}], ["git-commit-nonempty-second-line", "git commit nonempty second line", {}], ["git-commit-overlong-summary", "git commit overlong summary", {}], ["git-commit-summary", "git commit summary", {}], ["git-commit-trailer-token", "git commit trailer token", {}], ["git-commit-trailer-value", "git commit trailer value", {}]]}, "elfeed": {"label": "elfeed", "preview": "elfeed", "faces": [["elfeed-search-date-face", "search date", {"fg": "#aaa"}], ["elfeed-search-title-face", "search title", {"fg": "#000"}], ["elfeed-search-unread-title-face", "search unread title", {"bold": true}], ["elfeed-search-feed-face", "search feed", {"fg": "#aa0"}], ["elfeed-search-tag-face", "search tag", {"fg": "#070"}], ["elfeed-search-unread-count-face", "search unread count", {"fg": "#000"}], ["elfeed-search-filter-face", "search filter", {"inherit": "mode-line-buffer-id"}], ["elfeed-search-last-update-face", "search last update", {}], ["elfeed-log-date-face", "log date", {"inherit": "font-lock-type-face"}], ["elfeed-log-error-level-face", "log error level", {"fg": "#ff0000"}], ["elfeed-log-warn-level-face", "log warn level", {"fg": "#daa520"}], ["elfeed-log-info-level-face", "log info level", {"fg": "#00bfff"}], ["elfeed-log-debug-level-face", "log debug level", {"fg": "#ee00ee"}]]}, "mu4e": {"label": "mu4e", "preview": "mu4e", "faces": [["mu4e-title-face", "title", {}], ["mu4e-context-face", "context", {}], ["mu4e-modeline-face", "modeline", {}], ["mu4e-ok-face", "ok", {}], ["mu4e-warning-face", "warning", {}], ["mu4e-header-title-face", "header title", {}], ["mu4e-header-key-face", "header key", {}], ["mu4e-header-value-face", "header value", {}], ["mu4e-header-face", "header", {}], ["mu4e-header-highlight-face", "header highlight", {}], ["mu4e-header-marks-face", "header marks", {}], ["mu4e-unread-face", "unread", {}], ["mu4e-flagged-face", "flagged", {}], ["mu4e-replied-face", "replied", {}], ["mu4e-forwarded-face", "forwarded", {}], ["mu4e-draft-face", "draft", {}], ["mu4e-trashed-face", "trashed", {}], ["mu4e-related-face", "related", {}], ["mu4e-contact-face", "contact", {}], ["mu4e-special-header-value-face", "special header value", {}], ["mu4e-url-number-face", "url number", {}], ["mu4e-link-face", "link", {}], ["mu4e-footer-face", "footer", {}], ["mu4e-region-code", "region code", {}], ["mu4e-system-face", "system", {}], ["mu4e-highlight-face", "highlight", {}], ["mu4e-compose-separator-face", "compose separator", {}]]}, "ghostel": {"label": "ghostel", "preview": "ghostel", "faces": [["ghostel-default", "default", {"inherit": "default"}], ["ghostel-fake-cursor", "fake cursor", {"box": {"style": "line", "width": 1, "color": null}}], ["ghostel-fake-cursor-box", "fake cursor box", {"inherit": "cursor"}], ["ghostel-color-black", "color black", {"inherit": "ansi-color-black"}], ["ghostel-color-red", "color red", {"inherit": "ansi-color-red"}], ["ghostel-color-green", "color green", {"inherit": "ansi-color-green"}], ["ghostel-color-yellow", "color yellow", {"inherit": "ansi-color-yellow"}], ["ghostel-color-blue", "color blue", {"inherit": "ansi-color-blue"}], ["ghostel-color-magenta", "color magenta", {"inherit": "ansi-color-magenta"}], ["ghostel-color-cyan", "color cyan", {"inherit": "ansi-color-cyan"}], ["ghostel-color-white", "color white", {"inherit": "ansi-color-white"}], ["ghostel-color-bright-black", "color bright black", {"inherit": "ansi-color-bright-black"}], ["ghostel-color-bright-red", "color bright red", {"inherit": "ansi-color-bright-red"}], ["ghostel-color-bright-green", "color bright green", {"inherit": "ansi-color-bright-green"}], ["ghostel-color-bright-yellow", "color bright yellow", {"inherit": "ansi-color-bright-yellow"}], ["ghostel-color-bright-blue", "color bright blue", {"inherit": "ansi-color-bright-blue"}], ["ghostel-color-bright-magenta", "color bright magenta", {"inherit": "ansi-color-bright-magenta"}], ["ghostel-color-bright-cyan", "color bright cyan", {"inherit": "ansi-color-bright-cyan"}], ["ghostel-color-bright-white", "color bright white", {"inherit": "ansi-color-bright-white"}]]}, "dashboard": {"label": "dashboard", "preview": "dashboard", "faces": [["dashboard-banner-logo-title", "banner logo title", {"inherit": "default"}], ["dashboard-text-banner", "text banner", {"inherit": "font-lock-keyword-face"}], ["dashboard-heading", "heading", {"inherit": "font-lock-keyword-face"}], ["dashboard-items-face", "items", {"inherit": "widget-button"}], ["dashboard-navigator", "navigator", {"inherit": "font-lock-keyword-face"}], ["dashboard-no-items-face", "no items", {"inherit": "widget-button"}], ["dashboard-footer-face", "footer", {"inherit": "font-lock-doc-face"}], ["dashboard-footer-icon-face", "footer icon", {"inherit": "dashboard-footer-face"}]]}, "lsp-mode": {"label": "lsp-mode", "preview": "lsp", "faces": [["lsp-signature-face", "signature", {}], ["lsp-signature-highlight-function-argument", "signature highlight function argument", {}], ["lsp-signature-posframe", "signature posframe", {}], ["lsp-face-highlight-read", "face highlight read", {}], ["lsp-face-highlight-write", "face highlight write", {}], ["lsp-face-highlight-textual", "face highlight textual", {}], ["lsp-face-rename", "face rename", {}], ["lsp-rename-placeholder-face", "rename placeholder", {}], ["lsp-inlay-hint-face", "inlay hint", {}], ["lsp-inlay-hint-parameter-face", "inlay hint parameter", {}], ["lsp-inlay-hint-type-face", "inlay hint type", {}], ["lsp-details-face", "details", {}], ["lsp-installation-buffer-face", "installation buffer", {}], ["lsp-installation-finished-buffer-face", "installation finished buffer", {}]]}, "git-gutter": {"label": "git-gutter", "preview": "gitgutter", "faces": [["git-gutter:added", "added", {"fg": "#00ff00", "bold": true, "inherit": "default"}], ["git-gutter:modified", "modified", {"fg": "#ff00ff", "bold": true, "inherit": "default"}], ["git-gutter:deleted", "deleted", {"fg": "#ff0000", "bold": true, "inherit": "default"}], ["git-gutter:unchanged", "unchanged", {"bg": "#ffff00", "inherit": "default"}], ["git-gutter:separator", "separator", {"fg": "#00ffff", "bold": true, "inherit": "default"}]]}, "flycheck": {"label": "flycheck", "preview": "flycheck", "faces": [["flycheck-error", "error", {"underline": true}], ["flycheck-warning", "warning", {"underline": true}], ["flycheck-info", "info", {"underline": true}], ["flycheck-fringe-error", "fringe error", {"inherit": "error"}], ["flycheck-fringe-warning", "fringe warning", {"inherit": "warning"}], ["flycheck-fringe-info", "fringe info", {"inherit": "success"}], ["flycheck-delimited-error", "delimited error", {}], ["flycheck-error-delimiter", "error delimiter", {}], ["flycheck-error-list-error", "error list error", {"inherit": "error"}], ["flycheck-error-list-warning", "error list warning", {"inherit": "warning"}], ["flycheck-error-list-info", "error list info", {"inherit": "success"}], ["flycheck-error-list-error-message", "error list error message", {}], ["flycheck-error-list-checker-name", "error list checker name", {"inherit": "font-lock-function-name-face"}], ["flycheck-error-list-column-number", "error list column number", {}], ["flycheck-error-list-line-number", "error list line number", {}], ["flycheck-error-list-filename", "error list filename", {"inherit": "mode-line-buffer-id"}], ["flycheck-error-list-id", "error list id", {"inherit": "font-lock-type-face"}], ["flycheck-error-list-id-with-explainer", "error list id with explainer", {"inherit": "flycheck-error-list-id", "box": {"style": "released", "width": 1, "color": null}}], ["flycheck-error-list-highlight", "error list highlight", {"bold": true}], ["flycheck-verify-select-checker", "verify select checker", {"box": {"style": "released", "width": 1, "color": null}}]]}, "dired": {"label": "dired", "preview": "dired", "faces": [["dired-header", "header", {}], ["dired-directory", "directory", {}], ["dired-symlink", "symlink", {}], ["dired-broken-symlink", "broken symlink", {}], ["dired-special", "special", {}], ["dired-set-id", "set id", {}], ["dired-perm-write", "perm write", {}], ["dired-mark", "mark", {}], ["dired-marked", "marked", {}], ["dired-flagged", "flagged", {}], ["dired-ignored", "ignored", {}], ["dired-warning", "warning", {}]]}, "dirvish": {"label": "dirvish", "preview": "dirvish", "faces": [["dirvish-inactive", "inactive", {"inherit": "shadow"}], ["dirvish-free-space", "free space", {"inherit": "font-lock-constant-face"}], ["dirvish-hl-line", "hl line", {"inherit": "highlight"}], ["dirvish-hl-line-inactive", "hl line inactive", {"inherit": "region"}], ["dirvish-file-modes", "file modes", {"fg": "#6b6b6b"}], ["dirvish-file-link-number", "file link number", {"inherit": "font-lock-constant-face"}], ["dirvish-file-user-id", "file user id", {"inherit": "font-lock-preprocessor-face"}], ["dirvish-file-group-id", "file group id", {"inherit": "dirvish-file-user-id"}], ["dirvish-file-size", "file size", {"underline": true, "inherit": "completions-annotations"}], ["dirvish-file-time", "file time", {"fg": "#979797"}], ["dirvish-file-inode-number", "file inode number", {"inherit": "dirvish-file-link-number"}], ["dirvish-file-device-number", "file device number", {"inherit": "dirvish-file-link-number"}], ["dirvish-subtree-guide", "subtree guide", {"bg": "unspecified", "underline": true, "inherit": "dired-ignored"}], ["dirvish-subtree-state", "subtree state", {"bg": "unspecified", "underline": true, "inherit": "dired-ignored"}], ["dirvish-collapse-dir-face", "collapse dir", {"inherit": "dired-directory"}], ["dirvish-collapse-empty-dir-face", "collapse empty dir", {"inherit": "shadow"}], ["dirvish-collapse-file-face", "collapse file", {"inherit": "default"}], ["dirvish-emerge-group-title", "emerge group title", {"inherit": "dired-ignored"}], ["dirvish-media-info-heading", "media info heading", {"inherit": ["dired-header", "bold"]}], ["dirvish-media-info-property-key", "media info property key", {"inherit": ["italic"]}], ["dirvish-narrow-match-face-0", "narrow match 0", {"fg": "#223fbf", "bold": true}], ["dirvish-narrow-match-face-1", "narrow match 1", {"fg": "#8f0075", "bold": true}], ["dirvish-narrow-match-face-2", "narrow match 2", {"fg": "#145a00", "bold": true}], ["dirvish-narrow-match-face-3", "narrow match 3", {"fg": "#804000", "bold": true}], ["dirvish-narrow-split", "narrow split", {"inherit": "font-lock-negation-char-face"}], ["dirvish-proc-running", "proc running", {"inherit": "warning"}], ["dirvish-proc-finished", "proc finished", {"inherit": "success"}], ["dirvish-proc-failed", "proc failed", {"inherit": "error"}], ["dirvish-git-commit-message-face", "git commit message", {"bg": "unspecified", "underline": true, "inherit": "dired-ignored"}], ["dirvish-vc-added-state", "vc added state", {"inherit": "vc-locally-added-state"}], ["dirvish-vc-edited-state", "vc edited state", {"inherit": "vc-edited-state"}], ["dirvish-vc-removed-state", "vc removed state", {"inherit": "vc-removed-state"}], ["dirvish-vc-conflict-state", "vc conflict state", {"inherit": "vc-conflict-state"}], ["dirvish-vc-locked-state", "vc locked state", {"inherit": "vc-locked-state"}], ["dirvish-vc-missing-state", "vc missing state", {"inherit": "vc-missing-state"}], ["dirvish-vc-needs-merge-face", "vc needs merge", {"bg": "#efcbcf"}], ["dirvish-vc-needs-update-state", "vc needs update state", {"inherit": "vc-needs-update-state"}], ["dirvish-vc-unregistered-face", "vc unregistered", {"inherit": "font-lock-constant-face"}]]}, "calibredb": {"label": "calibredb", "preview": "calibredb", "faces": [["calibredb-search-header-library-name-face", "search header library name", {}], ["calibredb-search-header-library-path-face", "search header library path", {}], ["calibredb-search-header-total-face", "search header total", {}], ["calibredb-search-header-filter-face", "search header filter", {}], ["calibredb-search-header-sort-face", "search header sort", {}], ["calibredb-search-header-highlight-face", "search header highlight", {}], ["calibredb-id-face", "id", {}], ["calibredb-title-face", "title", {}], ["calibredb-author-face", "author", {}], ["calibredb-format-face", "format", {}], ["calibredb-size-face", "size", {}], ["calibredb-tag-face", "tag", {}], ["calibredb-date-face", "date", {}], ["calibredb-mark-face", "mark", {}], ["calibredb-series-face", "series", {}], ["calibredb-publisher-face", "publisher", {}], ["calibredb-pubdate-face", "pubdate", {}], ["calibredb-language-face", "language", {}], ["calibredb-comment-face", "comment", {}], ["calibredb-archive-face", "archive", {}], ["calibredb-favorite-face", "favorite", {}], ["calibredb-file-face", "file", {}], ["calibredb-ids-face", "ids", {}], ["calibredb-highlight-face", "highlight", {}], ["calibredb-current-page-button-face", "current page button", {}], ["calibredb-mouse-face", "mouse", {}], ["calibredb-title-detailed-view-face", "title detailed view", {}], ["calibredb-edit-annotation-header-title-face", "edit annotation header title", {}]]}, "erc": {"label": "erc", "preview": "erc", "faces": [["erc-header-line", "header line", {}], ["erc-timestamp-face", "timestamp", {}], ["erc-notice-face", "notice", {}], ["erc-default-face", "default", {}], ["erc-current-nick-face", "current nick", {}], ["erc-my-nick-face", "my nick", {}], ["erc-my-nick-prefix-face", "my nick prefix", {}], ["erc-nick-default-face", "nick default", {}], ["erc-nick-prefix-face", "nick prefix", {}], ["erc-button-nick-default-face", "button nick default", {}], ["erc-nick-msg-face", "nick msg", {}], ["erc-direct-msg-face", "direct msg", {}], ["erc-action-face", "action", {}], ["erc-keyword-face", "keyword", {}], ["erc-pal-face", "pal", {}], ["erc-fool-face", "fool", {}], ["erc-dangerous-host-face", "dangerous host", {}], ["erc-error-face", "error", {}], ["erc-input-face", "input", {}], ["erc-prompt-face", "prompt", {}], ["erc-command-indicator-face", "command indicator", {}], ["erc-information", "information", {}], ["erc-button", "button", {}], ["erc-bold-face", "bold", {}], ["erc-italic-face", "italic", {}], ["erc-underline-face", "underline", {}], ["erc-inverse-face", "inverse", {}], ["erc-spoiler-face", "spoiler", {}], ["erc-fill-wrap-merge-indicator-face", "fill wrap merge indicator", {}], ["erc-keep-place-indicator-arrow", "keep place indicator arrow", {}], ["erc-keep-place-indicator-line", "keep place indicator line", {}]]}, "org-drill": {"label": "org-drill", "preview": "orgdrill", "faces": [["org-drill-hidden-cloze-face", "hidden cloze", {}], ["org-drill-visible-cloze-face", "visible cloze", {}], ["org-drill-visible-cloze-hint-face", "visible cloze hint", {}]]}, "org-noter": {"label": "org-noter", "preview": "orgnoter", "faces": [["org-noter-notes-exist-face", "notes exist", {}], ["org-noter-no-notes-exist-face", "no notes exist", {}]]}, "signel": {"label": "signel", "preview": "signel", "faces": [["signel-timestamp-face", "timestamp", {}], ["signel-my-msg-face", "my msg", {}], ["signel-other-msg-face", "other msg", {}], ["signel-error-face", "error", {}]]}, "pearl": {"label": "pearl", "preview": "pearl", "faces": [["pearl-preamble-summary", "preamble summary", {}], ["pearl-editable-comment", "editable comment", {}], ["pearl-readonly-comment", "readonly comment", {}], ["pearl-modified-highlight", "modified highlight", {}], ["pearl-modified-local", "modified local", {}], ["pearl-modified-unknown", "modified unknown", {}]]}, "slack": {"label": "slack", "preview": "slack", "faces": [["slack-room-info-title-face", "room info title", {}], ["slack-room-info-title-room-name-face", "room info title room name", {}], ["slack-room-info-section-title-face", "room info section title", {}], ["slack-room-info-section-label-face", "room info section label", {}], ["slack-room-unread-face", "room unread", {}], ["slack-message-output-header", "message output header", {}], ["slack-message-output-text", "message output text", {}], ["slack-message-output-reaction", "message output reaction", {}], ["slack-message-output-reaction-pressed", "message output reaction pressed", {}], ["slack-message-deleted-face", "message deleted", {}], ["slack-new-message-marker-face", "new message marker", {}], ["slack-all-thread-buffer-thread-header-face", "all thread buffer thread header", {}], ["slack-message-mention-face", "message mention", {}], ["slack-message-mention-me-face", "message mention me", {}], ["slack-message-mention-keyword-face", "message mention keyword", {}], ["slack-channel-button-face", "channel button", {}], ["slack-mrkdwn-bold-face", "mrkdwn bold", {}], ["slack-mrkdwn-italic-face", "mrkdwn italic", {}], ["slack-mrkdwn-code-face", "mrkdwn code", {}], ["slack-mrkdwn-code-block-face", "mrkdwn code block", {}], ["slack-mrkdwn-strike-face", "mrkdwn strike", {}], ["slack-mrkdwn-blockquote-face", "mrkdwn blockquote", {}], ["slack-mrkdwn-list-face", "mrkdwn list", {}], ["slack-attachment-header", "attachment header", {}], ["slack-attachment-footer", "attachment footer", {}], ["slack-attachment-pad", "attachment pad", {}], ["slack-attachment-field-title", "attachment field title", {}], ["slack-message-attachment-preview-header-face", "message attachment preview header", {}], ["slack-preview-face", "preview", {}], ["slack-block-highlight-source-overlay-face", "block highlight source overlay", {}], ["slack-message-action-face", "message action", {}], ["slack-message-action-primary-face", "message action primary", {}], ["slack-message-action-danger-face", "message action danger", {}], ["slack-button-block-element-face", "button block element", {}], ["slack-button-primary-block-element-face", "button primary block element", {}], ["slack-button-danger-block-element-face", "button danger block element", {}], ["slack-select-block-element-face", "select block element", {}], ["slack-overflow-block-element-face", "overflow block element", {}], ["slack-date-picker-block-element-face", "date picker block element", {}], ["slack-dialog-title-face", "dialog title", {}], ["slack-dialog-element-label-face", "dialog element label", {}], ["slack-dialog-element-hint-face", "dialog element hint", {}], ["slack-dialog-element-placeholder-face", "dialog element placeholder", {}], ["slack-dialog-element-error-face", "dialog element error", {}], ["slack-dialog-submit-button-face", "dialog submit button", {}], ["slack-dialog-cancel-button-face", "dialog cancel button", {}], ["slack-dialog-select-element-input-face", "dialog select element input", {}], ["slack-user-active-face", "user active", {}], ["slack-user-dnd-face", "user dnd", {}], ["slack-user-profile-header-face", "user profile header", {}], ["slack-user-profile-property-name-face", "user profile property name", {}], ["slack-profile-image-face", "profile image", {}], ["slack-search-result-message-header-face", "search result message header", {}], ["slack-search-result-message-username-face", "search result message username", {}], ["slack-modeline-has-unreads-face", "modeline has unreads", {}], ["slack-modeline-channel-has-unreads-face", "modeline channel has unreads", {}], ["slack-modeline-thread-has-unreads-face", "modeline thread has unreads", {}]]}, "telega": {"label": "telega", "preview": "telega", "faces": [["telega-root-heading", "root heading", {}], ["telega-tracking", "tracking", {}], ["telega-unread-unmuted-modeline", "unread unmuted modeline", {}], ["telega-username", "username", {}], ["telega-user-online-status", "user online status", {}], ["telega-user-non-online-status", "user non online status", {}], ["telega-secret-title", "secret title", {}], ["telega-contact-birthdays-today", "contact birthdays today", {}], ["telega-muted-count", "muted count", {}], ["telega-unmuted-count", "unmuted count", {}], ["telega-mention-count", "mention count", {}], ["telega-has-chatbuf-brackets", "has chatbuf brackets", {}], ["telega-delim-face", "delim", {}], ["telega-shadow", "shadow", {}], ["telega-link", "link", {}], ["telega-blue", "blue", {}], ["telega-red", "red", {}], ["telega-msg-heading", "msg heading", {}], ["telega-msg-user-title", "msg user title", {}], ["telega-msg-self-title", "msg self title", {}], ["telega-msg-deleted", "msg deleted", {}], ["telega-msg-sponsored", "msg sponsored", {}], ["telega-msg-inline-reply", "msg inline reply", {}], ["telega-msg-inline-forward", "msg inline forward", {}], ["telega-msg-inline-other", "msg inline other", {}], ["telega-entity-type-bold", "entity type bold", {}], ["telega-entity-type-italic", "entity type italic", {}], ["telega-entity-type-underline", "entity type underline", {}], ["telega-entity-type-strikethrough", "entity type strikethrough", {}], ["telega-entity-type-code", "entity type code", {}], ["telega-entity-type-pre", "entity type pre", {}], ["telega-entity-type-blockquote", "entity type blockquote", {}], ["telega-entity-type-mention", "entity type mention", {}], ["telega-entity-type-hashtag", "entity type hashtag", {}], ["telega-entity-type-cashtag", "entity type cashtag", {}], ["telega-entity-type-botcommand", "entity type botcommand", {}], ["telega-entity-type-texturl", "entity type texturl", {}], ["telega-entity-type-spoiler", "entity type spoiler", {}], ["telega-reaction", "reaction", {}], ["telega-reaction-chosen", "reaction chosen", {}], ["telega-reaction-paid", "reaction paid", {}], ["telega-reaction-paid-chosen", "reaction paid chosen", {}], ["telega-highlight-text-face", "highlight text", {}], ["telega-button-highlight", "button highlight", {}], ["telega-chat-prompt", "chat prompt", {}], ["telega-chat-prompt-aux", "chat prompt aux", {}], ["telega-chat-input-attachment", "chat input attachment", {}], ["telega-topic-button", "topic button", {}], ["telega-filter-active", "filter active", {}], ["telega-filter-button-active", "filter button active", {}], ["telega-filter-button-inactive", "filter button inactive", {}], ["telega-checklist-stats-done", "checklist stats done", {}], ["telega-checklist-stats-todo", "checklist stats todo", {}], ["telega-box-button", "box button", {}], ["telega-box-button-active", "box button active", {}], ["telega-box-button-default-active", "box button default active", {}], ["telega-box-button-default-passive", "box button default passive", {}], ["telega-box-button-primary-active", "box button primary active", {}], ["telega-box-button-primary-passive", "box button primary passive", {}], ["telega-box-button-success-active", "box button success active", {}], ["telega-box-button-success-passive", "box button success passive", {}], ["telega-box-button-danger-active", "box button danger active", {}], ["telega-box-button-danger-passive", "box button danger passive", {}], ["telega-box-button-ui-active", "box button ui active", {}], ["telega-box-button-ui-passive", "box button ui passive", {}], ["telega-box-button2-active", "box button2 active", {}], ["telega-box-button2-passive", "box button2 passive", {}], ["telega-box-button2-white-foreground", "box button2 white foreground", {}], ["telega-describe-item-title", "describe item title", {}], ["telega-describe-section-title", "describe section title", {}], ["telega-describe-subsection-title", "describe subsection title", {}], ["telega-enckey-00", "enckey 00", {}], ["telega-enckey-01", "enckey 01", {}], ["telega-enckey-10", "enckey 10", {}], ["telega-enckey-11", "enckey 11", {}], ["telega-palette-builtin-blue", "palette builtin blue", {}], ["telega-palette-builtin-green", "palette builtin green", {}], ["telega-palette-builtin-orange", "palette builtin orange", {}], ["telega-palette-builtin-purple", "palette builtin purple", {}], ["telega-webpage-title", "webpage title", {}], ["telega-webpage-subtitle", "webpage subtitle", {}], ["telega-webpage-header", "webpage header", {}], ["telega-webpage-subheader", "webpage subheader", {}], ["telega-webpage-outline", "webpage outline", {}], ["telega-webpage-fixed", "webpage fixed", {}], ["telega-webpage-preformatted", "webpage preformatted", {}], ["telega-webpage-marked", "webpage marked", {}], ["telega-webpage-strike-through", "webpage strike through", {}], ["telega-webpage-chat-link", "webpage chat link", {}], ["telega-link-preview-sitename", "link preview sitename", {}], ["telega-link-preview-title", "link preview title", {}]]}, "shr": {"label": "shr (HTML: nov/eww/mail)", "preview": "shr", "faces": [["shr-h1", "h1", {}], ["shr-h2", "h2", {}], ["shr-h3", "h3", {}], ["shr-h4", "h4", {}], ["shr-h5", "h5", {}], ["shr-h6", "h6", {}], ["shr-text", "text", {}], ["shr-link", "link", {}], ["shr-selected-link", "selected link", {}], ["shr-code", "code", {}], ["shr-mark", "mark", {}], ["shr-strike-through", "strike through", {}], ["shr-sup", "sup", {}], ["shr-abbreviation", "abbreviation", {}], ["shr-sliced-image", "sliced image", {}]]}, "2048-game": {"label": "2048-game", "preview": "generic", "faces": [["twentyfortyeight-face-1024", "twentyfortyeight 1024", {"fg": "#000000", "bg": "#ffd700"}], ["twentyfortyeight-face-128", "twentyfortyeight 128", {"fg": "#ffffff", "bg": "#8b0000"}], ["twentyfortyeight-face-16", "twentyfortyeight 16", {"fg": "#000000", "bg": "#ffa500"}], ["twentyfortyeight-face-2", "twentyfortyeight 2", {"fg": "#000000", "bg": "#f0e68c"}], ["twentyfortyeight-face-2048", "twentyfortyeight 2048", {"fg": "#000000", "bg": "#ffff00"}], ["twentyfortyeight-face-256", "twentyfortyeight 256", {"fg": "#ffffff", "bg": "#8b008b"}], ["twentyfortyeight-face-32", "twentyfortyeight 32", {"fg": "#000000", "bg": "#ff4500"}], ["twentyfortyeight-face-4", "twentyfortyeight 4", {"fg": "#000000", "bg": "#deb887"}], ["twentyfortyeight-face-512", "twentyfortyeight 512", {"fg": "#000000", "bg": "#ff00ff"}], ["twentyfortyeight-face-64", "twentyfortyeight 64", {"fg": "#ffffff", "bg": "#b22222"}], ["twentyfortyeight-face-8", "twentyfortyeight 8", {"fg": "#000000", "bg": "#cd8500"}]]}, "alert": {"label": "alert", "preview": "generic", "faces": [["alert-high-face", "high", {"fg": "#ff8c00", "bold": true}], ["alert-low-face", "low", {"fg": "#00008b"}], ["alert-moderate-face", "moderate", {"fg": "#ffd700", "bold": true}], ["alert-normal-face", "normal", {}], ["alert-trivial-face", "trivial", {"fg": "#9400d3"}], ["alert-urgent-face", "urgent", {"fg": "#ff0000", "bold": true}]]}, "all-the-icons": {"label": "all-the-icons", "preview": "generic", "faces": [["all-the-icons-blue", "blue", {"fg": "#6a9fb5"}], ["all-the-icons-blue-alt", "blue alt", {"fg": "#2188b6"}], ["all-the-icons-cyan", "cyan", {"fg": "#75b5aa"}], ["all-the-icons-cyan-alt", "cyan alt", {"fg": "#0595bd"}], ["all-the-icons-dblue", "dblue", {"fg": "#446674"}], ["all-the-icons-dcyan", "dcyan", {"fg": "#48746d"}], ["all-the-icons-dgreen", "dgreen", {"fg": "#6d8143"}], ["all-the-icons-dmaroon", "dmaroon", {"fg": "#72584b"}], ["all-the-icons-dorange", "dorange", {"fg": "#915b2d"}], ["all-the-icons-dpink", "dpink", {"fg": "#7e5d5f"}], ["all-the-icons-dpurple", "dpurple", {"fg": "#694863"}], ["all-the-icons-dred", "dred", {"fg": "#843031"}], ["all-the-icons-dsilver", "dsilver", {"fg": "#838484"}], ["all-the-icons-dyellow", "dyellow", {"fg": "#b48d56"}], ["all-the-icons-green", "green", {"fg": "#90a959"}], ["all-the-icons-lblue", "lblue", {"fg": "#677174"}], ["all-the-icons-lcyan", "lcyan", {"fg": "#2c7d6e"}], ["all-the-icons-lgreen", "lgreen", {"fg": "#3d6837"}], ["all-the-icons-lmaroon", "lmaroon", {"fg": "#ce7a4e"}], ["all-the-icons-lorange", "lorange", {"fg": "#ffa500"}], ["all-the-icons-lpink", "lpink", {"fg": "#ff505b"}], ["all-the-icons-lpurple", "lpurple", {"fg": "#e69dd6"}], ["all-the-icons-lred", "lred", {"fg": "#eb595a"}], ["all-the-icons-lsilver", "lsilver", {"fg": "#7f7869"}], ["all-the-icons-lyellow", "lyellow", {"fg": "#ff9300"}], ["all-the-icons-maroon", "maroon", {"fg": "#8f5536"}], ["all-the-icons-orange", "orange", {"fg": "#d4843e"}], ["all-the-icons-pink", "pink", {"fg": "#fc505b"}], ["all-the-icons-purple", "purple", {"fg": "#68295b"}], ["all-the-icons-purple-alt", "purple alt", {"fg": "#5d54e1"}], ["all-the-icons-red", "red", {"fg": "#ac4142"}], ["all-the-icons-red-alt", "red alt", {"fg": "#843031"}], ["all-the-icons-silver", "silver", {"fg": "#716e68"}], ["all-the-icons-yellow", "yellow", {"fg": "#ffcc0e"}]]}, "company": {"label": "company", "preview": "generic", "faces": [["company-echo", "echo", {}], ["company-echo-common", "echo common", {"fg": "#8b1a1a"}], ["company-preview", "preview", {"inherit": ["company-tooltip-selection", "company-tooltip"]}], ["company-preview-common", "preview common", {"inherit": "company-tooltip-common-selection"}], ["company-preview-search", "preview search", {"inherit": "company-tooltip-common-selection"}], ["company-tooltip", "tooltip", {"fg": "#000000", "bg": "#fff8dc"}], ["company-tooltip-annotation", "tooltip annotation", {"fg": "#8b1a1a"}], ["company-tooltip-annotation-selection", "tooltip annotation selection", {"inherit": "company-tooltip-annotation"}], ["company-tooltip-common", "tooltip common", {"fg": "#8b0000"}], ["company-tooltip-common-selection", "tooltip common selection", {"inherit": "company-tooltip-common"}], ["company-tooltip-deprecated", "tooltip deprecated", {"strike": true}], ["company-tooltip-mouse", "tooltip mouse", {"inherit": "highlight"}], ["company-tooltip-quick-access", "tooltip quick access", {"inherit": "company-tooltip-annotation"}], ["company-tooltip-quick-access-selection", "tooltip quick access selection", {"inherit": "company-tooltip-annotation-selection"}], ["company-tooltip-scrollbar-thumb", "tooltip scrollbar thumb", {"bg": "#cd5c5c"}], ["company-tooltip-scrollbar-track", "tooltip scrollbar track", {"bg": "#f5deb3"}], ["company-tooltip-search", "tooltip search", {"inherit": "highlight"}], ["company-tooltip-search-selection", "tooltip search selection", {"inherit": "highlight"}], ["company-tooltip-selection", "tooltip selection", {"bg": "#add8e6"}]]}, "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", {"inherit": "error"}], ["consult-async-finished", "async finished", {"inherit": "success"}], ["consult-async-running", "async running", {"inherit": "consult-narrow-indicator"}], ["consult-async-split", "async split", {"inherit": "font-lock-negation-char-face"}], ["consult-bookmark", "bookmark", {"inherit": "font-lock-constant-face"}], ["consult-buffer", "buffer", {}], ["consult-file", "file", {"inherit": "font-lock-function-name-face"}], ["consult-grep-context", "grep context", {"inherit": "shadow"}], ["consult-help", "help", {"inherit": "shadow"}], ["consult-highlight-mark", "highlight mark", {"inherit": "consult-highlight-match"}], ["consult-highlight-match", "highlight match", {"inherit": "match"}], ["consult-key", "key", {"inherit": "font-lock-keyword-face"}], ["consult-line-number", "line number", {"inherit": "consult-key"}], ["consult-line-number-prefix", "line number prefix", {"inherit": "line-number"}], ["consult-line-number-wrapped", "line number wrapped", {"inherit": "font-lock-warning-face"}], ["consult-narrow-indicator", "narrow indicator", {"inherit": "warning"}], ["consult-preview-insertion", "preview insertion", {"inherit": "region"}], ["consult-preview-line", "preview line", {"inherit": "consult-preview-insertion"}], ["consult-preview-match", "preview match", {"inherit": "isearch"}], ["consult-separator", "separator", {"fg": "#ccc"}]]}, "embark": {"label": "embark", "preview": "generic", "faces": [["embark-collect-annotation", "collect annotation", {"inherit": "completions-annotations"}], ["embark-collect-candidate", "collect candidate", {"inherit": "default"}], ["embark-collect-group-separator", "collect group separator", {"strike": true, "inherit": "shadow"}], ["embark-collect-group-title", "collect group title", {"italic": true, "inherit": "shadow"}], ["embark-keybinding", "keybinding", {"inherit": "success"}], ["embark-keybinding-repeat", "keybinding repeat", {"inherit": "font-lock-builtin-face"}], ["embark-keymap", "keymap", {"italic": true}], ["embark-selected", "selected", {"inherit": "match"}], ["embark-target", "target", {"inherit": "highlight"}], ["embark-verbose-indicator-documentation", "verbose indicator documentation", {"inherit": "completions-annotations"}], ["embark-verbose-indicator-shadowed", "verbose indicator shadowed", {"inherit": "shadow"}], ["embark-verbose-indicator-title", "verbose indicator title", {"bold": true, "height": 1.1}]]}, "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", {"fg": "#ffffff", "bg": "#cd0000"}], ["emms-metaplaylist-mode-face", "metaplaylist mode", {"fg": "#cd0000"}], ["emms-playlist-selected-face", "playlist selected", {"fg": "#ffffff", "bg": "#0000cd"}], ["emms-playlist-track-face", "playlist track", {"fg": "#0000ff"}]]}, "flyspell-correct": {"label": "flyspell-correct", "preview": "generic", "faces": [["flyspell-correct-highlight-face", "highlight", {"inherit": "isearch"}]]}, "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", {"fg": "#cc9393", "bold": true}], ["hl-todo-flymake-type", "flymake type", {"inherit": "font-lock-keyword-face"}]]}, "json-mode": {"label": "json-mode", "preview": "generic", "faces": [["json-mode-object-name-face", "object name", {"inherit": "font-lock-variable-name-face"}]]}, "llama": {"label": "llama", "preview": "generic", "faces": [["llama-##-macro", "## macro", {"inherit": "font-lock-function-call-face"}], ["llama-deleted-argument", "deleted argument", {"box": {"style": "line", "width": 1, "color": "#ff0000"}}], ["llama-llama-macro", "llama macro", {"inherit": "font-lock-keyword-face"}], ["llama-mandatory-argument", "mandatory argument", {"inherit": "font-lock-variable-use-face"}], ["llama-optional-argument", "optional argument", {"inherit": "font-lock-type-face"}]]}, "lv": {"label": "lv", "preview": "generic", "faces": [["lv-separator", "separator", {"bg": "#cccccc"}]]}, "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", {"inherit": "bold"}], ["malyon-face-error", "face error", {"inherit": "error"}], ["malyon-face-italic", "face italic", {"inherit": "italic"}], ["malyon-face-plain", "face plain", {"inherit": "default"}], ["malyon-face-reverse", "face reverse", {"inherit": "default"}]]}, "marginalia": {"label": "marginalia", "preview": "generic", "faces": [["marginalia-archive", "archive", {"inherit": "warning"}], ["marginalia-char", "char", {"inherit": "marginalia-key"}], ["marginalia-date", "date", {"inherit": "marginalia-key"}], ["marginalia-documentation", "documentation", {"inherit": "completions-annotations"}], ["marginalia-file-name", "file name", {"inherit": "marginalia-documentation"}], ["marginalia-file-owner", "file owner", {"inherit": "font-lock-preprocessor-face"}], ["marginalia-file-priv-dir", "file priv dir", {"inherit": "font-lock-keyword-face"}], ["marginalia-file-priv-exec", "file priv exec", {"inherit": "font-lock-function-name-face"}], ["marginalia-file-priv-link", "file priv link", {"inherit": "font-lock-keyword-face"}], ["marginalia-file-priv-no", "file priv no", {"inherit": "shadow"}], ["marginalia-file-priv-other", "file priv other", {"inherit": "font-lock-constant-face"}], ["marginalia-file-priv-rare", "file priv rare", {"inherit": "font-lock-variable-name-face"}], ["marginalia-file-priv-read", "file priv read", {"inherit": "font-lock-type-face"}], ["marginalia-file-priv-write", "file priv write", {"inherit": "font-lock-builtin-face"}], ["marginalia-function", "function", {"inherit": "font-lock-function-name-face"}], ["marginalia-installed", "installed", {"inherit": "success"}], ["marginalia-key", "key", {"inherit": "font-lock-keyword-face"}], ["marginalia-lighter", "lighter", {"inherit": "marginalia-size"}], ["marginalia-list", "list", {"inherit": "font-lock-constant-face"}], ["marginalia-mode", "mode", {"inherit": "marginalia-key"}], ["marginalia-modified", "modified", {"inherit": "font-lock-negation-char-face"}], ["marginalia-null", "null", {"inherit": "font-lock-comment-face"}], ["marginalia-number", "number", {"inherit": "font-lock-constant-face"}], ["marginalia-off", "off", {"inherit": "error"}], ["marginalia-on", "on", {"inherit": "success"}], ["marginalia-size", "size", {"inherit": "marginalia-number"}], ["marginalia-string", "string", {"inherit": "font-lock-string-face"}], ["marginalia-symbol", "symbol", {"inherit": "font-lock-type-face"}], ["marginalia-true", "true", {"inherit": "font-lock-builtin-face"}], ["marginalia-type", "type", {"inherit": "marginalia-key"}], ["marginalia-value", "value", {"inherit": "marginalia-key"}], ["marginalia-version", "version", {"inherit": "marginalia-number"}]]}, "markdown-mode": {"label": "markdown-mode", "preview": "generic", "faces": [["markdown-blockquote-face", "markdown blockquote", {"inherit": "font-lock-doc-face"}], ["markdown-bold-face", "markdown bold", {"inherit": "bold"}], ["markdown-code-face", "markdown code", {"inherit": "fixed-pitch"}], ["markdown-comment-face", "markdown comment", {"inherit": "font-lock-comment-face"}], ["markdown-footnote-marker-face", "markdown footnote marker", {"inherit": "markdown-markup-face"}], ["markdown-footnote-text-face", "markdown footnote text", {"inherit": "font-lock-comment-face"}], ["markdown-gfm-checkbox-face", "markdown gfm checkbox", {"inherit": "font-lock-builtin-face"}], ["markdown-header-delimiter-face", "markdown header delimiter", {"inherit": "markdown-markup-face"}], ["markdown-header-face", "markdown header", {"bold": true, "inherit": ["font-lock-function-name-face"]}], ["markdown-header-face-1", "markdown header 1", {"inherit": "markdown-header-face"}], ["markdown-header-face-2", "markdown header 2", {"inherit": "markdown-header-face"}], ["markdown-header-face-3", "markdown header 3", {"inherit": "markdown-header-face"}], ["markdown-header-face-4", "markdown header 4", {"inherit": "markdown-header-face"}], ["markdown-header-face-5", "markdown header 5", {"inherit": "markdown-header-face"}], ["markdown-header-face-6", "markdown header 6", {"inherit": "markdown-header-face"}], ["markdown-header-rule-face", "markdown header rule", {"inherit": "markdown-markup-face"}], ["markdown-highlight-face", "markdown highlight", {"inherit": "highlight"}], ["markdown-highlighting-face", "markdown highlighting", {"fg": "#000000", "bg": "#ffff00"}], ["markdown-hr-face", "markdown hr", {"inherit": "markdown-markup-face"}], ["markdown-html-attr-name-face", "markdown html attr name", {"inherit": "font-lock-variable-name-face"}], ["markdown-html-attr-value-face", "markdown html attr value", {"inherit": "font-lock-string-face"}], ["markdown-html-entity-face", "markdown html entity", {"inherit": "font-lock-variable-name-face"}], ["markdown-html-tag-delimiter-face", "markdown html tag delimiter", {"inherit": "markdown-markup-face"}], ["markdown-html-tag-name-face", "markdown html tag name", {"inherit": "font-lock-type-face"}], ["markdown-inline-code-face", "markdown inline code", {"inherit": ["markdown-code-face", "font-lock-constant-face"]}], ["markdown-italic-face", "markdown italic", {"inherit": "italic"}], ["markdown-language-info-face", "markdown language info", {"inherit": "font-lock-string-face"}], ["markdown-language-keyword-face", "markdown language keyword", {"inherit": "font-lock-type-face"}], ["markdown-line-break-face", "markdown line break", {"underline": true, "inherit": "font-lock-constant-face"}], ["markdown-link-face", "markdown link", {"inherit": "link"}], ["markdown-link-title-face", "markdown link title", {"inherit": "font-lock-comment-face"}], ["markdown-list-face", "markdown list", {"inherit": "markdown-markup-face"}], ["markdown-markup-face", "markdown markup", {"inherit": "shadow"}], ["markdown-math-face", "markdown math", {"inherit": "font-lock-string-face"}], ["markdown-metadata-key-face", "markdown metadata key", {"inherit": "font-lock-variable-name-face"}], ["markdown-metadata-value-face", "markdown metadata value", {"inherit": "font-lock-string-face"}], ["markdown-missing-link-face", "markdown missing link", {"inherit": "font-lock-warning-face"}], ["markdown-plain-url-face", "markdown plain url", {"inherit": "markdown-link-face"}], ["markdown-pre-face", "markdown pre", {"inherit": ["markdown-code-face", "font-lock-constant-face"]}], ["markdown-reference-face", "markdown reference", {"inherit": "markdown-markup-face"}], ["markdown-strike-through-face", "markdown strike through", {"strike": true}], ["markdown-table-face", "markdown table", {"inherit": ["markdown-code-face"]}], ["markdown-url-face", "markdown url", {"inherit": "font-lock-string-face"}]]}, "nerd-icons": {"label": "nerd-icons", "preview": "generic", "faces": [["nerd-icons-blue", "blue", {"fg": "#6a9fb5"}], ["nerd-icons-blue-alt", "blue alt", {"fg": "#2188b6"}], ["nerd-icons-cyan", "cyan", {"fg": "#75b5aa"}], ["nerd-icons-cyan-alt", "cyan alt", {"fg": "#0595bd"}], ["nerd-icons-dblue", "dblue", {"fg": "#446674"}], ["nerd-icons-dcyan", "dcyan", {"fg": "#48746d"}], ["nerd-icons-dgreen", "dgreen", {"fg": "#6d8143"}], ["nerd-icons-dmaroon", "dmaroon", {"fg": "#72584b"}], ["nerd-icons-dorange", "dorange", {"fg": "#915b2d"}], ["nerd-icons-dpink", "dpink", {"fg": "#7e5d5f"}], ["nerd-icons-dpurple", "dpurple", {"fg": "#694863"}], ["nerd-icons-dred", "dred", {"fg": "#843031"}], ["nerd-icons-dsilver", "dsilver", {"fg": "#838484"}], ["nerd-icons-dyellow", "dyellow", {"fg": "#b48d56"}], ["nerd-icons-green", "green", {"fg": "#90a959"}], ["nerd-icons-lblue", "lblue", {"fg": "#677174"}], ["nerd-icons-lcyan", "lcyan", {"fg": "#2c7d6e"}], ["nerd-icons-lgreen", "lgreen", {"fg": "#3d6837"}], ["nerd-icons-lmaroon", "lmaroon", {"fg": "#ce7a4e"}], ["nerd-icons-lorange", "lorange", {"fg": "#ffa500"}], ["nerd-icons-lpink", "lpink", {"fg": "#ff505b"}], ["nerd-icons-lpurple", "lpurple", {"fg": "#e69dd6"}], ["nerd-icons-lred", "lred", {"fg": "#eb595a"}], ["nerd-icons-lsilver", "lsilver", {"fg": "#7f7869"}], ["nerd-icons-lyellow", "lyellow", {"fg": "#ff9300"}], ["nerd-icons-maroon", "maroon", {"fg": "#8f5536"}], ["nerd-icons-orange", "orange", {"fg": "#d4843e"}], ["nerd-icons-pink", "pink", {"fg": "#fc505b"}], ["nerd-icons-purple", "purple", {"fg": "#68295b"}], ["nerd-icons-purple-alt", "purple alt", {"fg": "#5d54e1"}], ["nerd-icons-red", "red", {"fg": "#ac4142"}], ["nerd-icons-red-alt", "red alt", {"fg": "#843031"}], ["nerd-icons-silver", "silver", {"fg": "#716e68"}], ["nerd-icons-yellow", "yellow", {"fg": "#ffcc0e"}]]}, "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", {"fg": "#223fbf", "bold": true}], ["orderless-match-face-1", "match 1", {"fg": "#8f0075", "bold": true}], ["orderless-match-face-2", "match 2", {"fg": "#145a00", "bold": true}], ["orderless-match-face-3", "match 3", {"fg": "#804000", "bold": true}]]}, "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", {"inherit": "org-warning"}], ["org-superstar-header-bullet", "header bullet", {}], ["org-superstar-item", "item", {"inherit": "default"}], ["org-superstar-leading", "leading", {"fg": "#bebebe", "inherit": "default"}]]}, "prescient": {"label": "prescient", "preview": "generic", "faces": [["prescient-primary-highlight", "primary highlight", {"bold": true}], ["prescient-secondary-highlight", "secondary highlight", {"underline": true, "inherit": "prescient-primary-highlight"}]]}, "rainbow-delimiters": {"label": "rainbow-delimiters", "preview": "generic", "faces": [["rainbow-delimiters-base-error-face", "base error", {"fg": "#88090b", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-base-face", "base", {"inherit": "unspecified"}], ["rainbow-delimiters-depth-1-face", "depth 1", {"fg": "#707183", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-2-face", "depth 2", {"fg": "#7388d6", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-3-face", "depth 3", {"fg": "#909183", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-4-face", "depth 4", {"fg": "#709870", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-5-face", "depth 5", {"fg": "#907373", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-6-face", "depth 6", {"fg": "#6276ba", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-7-face", "depth 7", {"fg": "#858580", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-8-face", "depth 8", {"fg": "#80a880", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-9-face", "depth 9", {"fg": "#887070", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-mismatched-face", "mismatched", {"inherit": "rainbow-delimiters-unmatched-face"}], ["rainbow-delimiters-unmatched-face", "unmatched", {"inherit": "rainbow-delimiters-base-error-face"}]]}, "symbol-overlay": {"label": "symbol-overlay", "preview": "generic", "faces": [["symbol-overlay-default-face", "default", {"inherit": "highlight"}], ["symbol-overlay-face-1", "face 1", {"fg": "#000000", "bg": "#1e90ff"}], ["symbol-overlay-face-2", "face 2", {"fg": "#000000", "bg": "#ff69b4"}], ["symbol-overlay-face-3", "face 3", {"fg": "#000000", "bg": "#ffff00"}], ["symbol-overlay-face-4", "face 4", {"fg": "#000000", "bg": "#da70d6"}], ["symbol-overlay-face-5", "face 5", {"fg": "#000000", "bg": "#ff0000"}], ["symbol-overlay-face-6", "face 6", {"fg": "#000000", "bg": "#fa8072"}], ["symbol-overlay-face-7", "face 7", {"fg": "#000000", "bg": "#00ff7f"}], ["symbol-overlay-face-8", "face 8", {"fg": "#000000", "bg": "#40e0d0"}]]}, "tmr": {"label": "tmr", "preview": "generic", "faces": [["tmr-description", "description", {"inherit": "bold"}], ["tmr-duration", "duration", {}], ["tmr-end-time", "end time", {"inherit": "error"}], ["tmr-finished", "finished", {"inherit": "error"}], ["tmr-is-acknowledged", "is acknowledged", {"inherit": "success"}], ["tmr-must-be-acknowledged", "must be acknowledged", {"inherit": "warning"}], ["tmr-start-time", "start time", {"inherit": "success"}], ["tmr-tabulated-acknowledgement", "tabulated acknowledgement", {"inherit": "bold"}], ["tmr-tabulated-description", "tabulated description", {"inherit": "font-lock-doc-face"}], ["tmr-tabulated-end-time", "tabulated end time", {"fg": "#800040"}], ["tmr-tabulated-remaining-time", "tabulated remaining time", {"fg": "#603f00"}], ["tmr-tabulated-start-time", "tabulated start time", {"fg": "#004476"}]]}, "transient": {"label": "transient", "preview": "generic", "faces": [["transient-active-infix", "active infix", {"inherit": "highlight"}], ["transient-argument", "argument", {"bold": true, "inherit": "font-lock-string-face"}], ["transient-delimiter", "delimiter", {"inherit": "shadow"}], ["transient-disabled-suffix", "disabled suffix", {"fg": "#000000", "bg": "#ff0000", "bold": true}], ["transient-enabled-suffix", "enabled suffix", {"fg": "#000000", "bg": "#00ff00", "bold": true}], ["transient-heading", "heading", {"inherit": "font-lock-keyword-face"}], ["transient-higher-level", "higher level", {"box": {"style": "line", "width": 1, "color": "grey60"}}], ["transient-inactive-argument", "inactive argument", {"inherit": "shadow"}], ["transient-inactive-value", "inactive value", {"inherit": "shadow"}], ["transient-inapt-argument", "inapt argument", {"bold": true, "inherit": "shadow"}], ["transient-inapt-suffix", "inapt suffix", {"italic": true, "inherit": "shadow"}], ["transient-key", "key", {"inherit": "font-lock-builtin-face"}], ["transient-key-exit", "key exit", {"fg": "#aa2222", "inherit": "transient-key"}], ["transient-key-noop", "key noop", {"fg": "#cccccc", "inherit": "transient-key"}], ["transient-key-recurse", "key recurse", {"fg": "#2266ff", "inherit": "transient-key"}], ["transient-key-return", "key return", {"fg": "#aaaa11", "inherit": "transient-key"}], ["transient-key-stack", "key stack", {"fg": "#dd4488", "inherit": "transient-key"}], ["transient-key-stay", "key stay", {"fg": "#22aa22", "inherit": "transient-key"}], ["transient-mismatched-key", "mismatched key", {"box": {"style": "line", "width": 1, "color": "#ff00ff"}}], ["transient-nonstandard-key", "nonstandard key", {"box": {"style": "line", "width": 1, "color": "#00ffff"}}], ["transient-unreachable", "unreachable", {"inherit": "shadow"}], ["transient-unreachable-key", "unreachable key", {"inherit": ["shadow", "transient-key"]}], ["transient-value", "value", {"bold": true, "inherit": "font-lock-string-face"}]]}, "vertico": {"label": "vertico", "preview": "generic", "faces": [["vertico-current", "current", {"inherit": "highlight"}], ["vertico-group-separator", "group separator", {"strike": true, "inherit": "vertico-group-title"}], ["vertico-group-title", "group title", {"italic": true, "inherit": "shadow"}], ["vertico-multiline", "multiline", {"inherit": "shadow"}]]}, "web-mode": {"label": "web-mode", "preview": "generic", "faces": [["web-mode-annotation-face", "annotation", {"inherit": "web-mode-comment-face"}], ["web-mode-annotation-html-face", "annotation html", {"italic": true, "inherit": "web-mode-annotation-face"}], ["web-mode-annotation-tag-face", "annotation tag", {"underline": true, "inherit": "web-mode-annotation-face"}], ["web-mode-annotation-type-face", "annotation type", {"bold": true, "inherit": "web-mode-annotation-face"}], ["web-mode-annotation-value-face", "annotation value", {"italic": true, "inherit": "web-mode-annotation-face"}], ["web-mode-block-attr-name-face", "block attr name", {"fg": "#8fbc8f"}], ["web-mode-block-attr-value-face", "block attr value", {"fg": "#5f9ea0"}], ["web-mode-block-comment-face", "block comment", {"inherit": "web-mode-comment-face"}], ["web-mode-block-control-face", "block control", {"inherit": "font-lock-preprocessor-face"}], ["web-mode-block-delimiter-face", "block delimiter", {"inherit": "font-lock-preprocessor-face"}], ["web-mode-block-face", "block", {"bg": "#ffffe0"}], ["web-mode-block-string-face", "block string", {"inherit": "web-mode-string-face"}], ["web-mode-bold-face", "bold", {"bold": true}], ["web-mode-builtin-face", "builtin", {"inherit": "font-lock-builtin-face"}], ["web-mode-comment-face", "comment", {"inherit": "font-lock-comment-face"}], ["web-mode-comment-keyword-face", "comment keyword", {"bold": true}], ["web-mode-constant-face", "constant", {"inherit": "font-lock-constant-face"}], ["web-mode-css-at-rule-face", "css at rule", {"inherit": "font-lock-constant-face"}], ["web-mode-css-color-face", "css color", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-comment-face", "css comment", {"inherit": "web-mode-comment-face"}], ["web-mode-css-function-face", "css function", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-priority-face", "css priority", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-property-name-face", "css property name", {"inherit": "font-lock-variable-name-face"}], ["web-mode-css-pseudo-class-face", "css pseudo class", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-selector-class-face", "css selector class", {"inherit": "font-lock-keyword-face"}], ["web-mode-css-selector-face", "css selector", {"inherit": "font-lock-keyword-face"}], ["web-mode-css-selector-tag-face", "css selector tag", {"inherit": "font-lock-keyword-face"}], ["web-mode-css-string-face", "css string", {"inherit": "web-mode-string-face"}], ["web-mode-css-variable-face", "css variable", {"italic": true, "inherit": "web-mode-variable-name-face"}], ["web-mode-current-column-highlight-face", "current column highlight", {"bg": "#3e3c36"}], ["web-mode-current-element-highlight-face", "current element highlight", {"fg": "#ffffff", "bg": "#000000"}], ["web-mode-doctype-face", "doctype", {"fg": "#bebebe"}], ["web-mode-error-face", "error", {"bg": "#ff0000"}], ["web-mode-filter-face", "filter", {"inherit": "font-lock-function-name-face"}], ["web-mode-folded-face", "folded", {"underline": true}], ["web-mode-function-call-face", "function call", {"inherit": "font-lock-function-name-face"}], ["web-mode-function-name-face", "function name", {"inherit": "font-lock-function-name-face"}], ["web-mode-html-attr-custom-face", "html attr custom", {"inherit": "web-mode-html-attr-name-face"}], ["web-mode-html-attr-engine-face", "html attr engine", {"inherit": "web-mode-block-delimiter-face"}], ["web-mode-html-attr-equal-face", "html attr equal", {"inherit": "web-mode-html-attr-name-face"}], ["web-mode-html-attr-name-face", "html attr name", {"fg": "#8b8989"}], ["web-mode-html-attr-value-face", "html attr value", {"inherit": "font-lock-string-face"}], ["web-mode-html-entity-face", "html entity", {"italic": true}], ["web-mode-html-tag-bracket-face", "html tag bracket", {"fg": "#242424"}], ["web-mode-html-tag-custom-face", "html tag custom", {"inherit": "web-mode-html-tag-face"}], ["web-mode-html-tag-face", "html tag", {"fg": "#8b8989"}], ["web-mode-html-tag-namespaced-face", "html tag namespaced", {"inherit": "web-mode-block-control-face"}], ["web-mode-html-tag-unclosed-face", "html tag unclosed", {"underline": true, "inherit": "web-mode-html-tag-face"}], ["web-mode-inlay-face", "inlay", {"bg": "#ffffe0"}], ["web-mode-interpolate-color1-face", "interpolate color1", {"inherit": "web-mode-string-face"}], ["web-mode-interpolate-color2-face", "interpolate color2", {"inherit": "web-mode-string-face"}], ["web-mode-interpolate-color3-face", "interpolate color3", {"inherit": "web-mode-string-face"}], ["web-mode-interpolate-color4-face", "interpolate color4", {"inherit": "web-mode-string-face"}], ["web-mode-italic-face", "italic", {"italic": true}], ["web-mode-javascript-comment-face", "javascript comment", {"inherit": "web-mode-comment-face"}], ["web-mode-javascript-string-face", "javascript string", {"inherit": "web-mode-string-face"}], ["web-mode-json-comment-face", "json comment", {"inherit": "web-mode-comment-face"}], ["web-mode-json-context-face", "json context", {"fg": "#cd69c9"}], ["web-mode-json-key-face", "json key", {"fg": "#dda0dd"}], ["web-mode-json-string-face", "json string", {"inherit": "web-mode-string-face"}], ["web-mode-jsx-depth-1-face", "jsx depth 1", {"bg": "#000053"}], ["web-mode-jsx-depth-2-face", "jsx depth 2", {"bg": "#001970"}], ["web-mode-jsx-depth-3-face", "jsx depth 3", {"bg": "#002984"}], ["web-mode-jsx-depth-4-face", "jsx depth 4", {"bg": "#49599a"}], ["web-mode-jsx-depth-5-face", "jsx depth 5", {"bg": "#9499b7"}], ["web-mode-keyword-face", "keyword", {"inherit": "font-lock-keyword-face"}], ["web-mode-param-name-face", "param name", {"fg": "#cdc9c9"}], ["web-mode-part-comment-face", "part comment", {"inherit": "web-mode-comment-face"}], ["web-mode-part-face", "part", {"inherit": "web-mode-block-face"}], ["web-mode-part-string-face", "part string", {"inherit": "web-mode-string-face"}], ["web-mode-preprocessor-face", "preprocessor", {"inherit": "font-lock-preprocessor-face"}], ["web-mode-script-face", "script", {"inherit": "web-mode-part-face"}], ["web-mode-sql-keyword-face", "sql keyword", {"bold": true, "italic": true}], ["web-mode-string-face", "string", {"inherit": "font-lock-string-face"}], ["web-mode-style-face", "style", {"inherit": "web-mode-part-face"}], ["web-mode-symbol-face", "symbol", {"fg": "#eeb422"}], ["web-mode-type-face", "type", {"inherit": "font-lock-type-face"}], ["web-mode-underline-face", "underline", {"underline": true}], ["web-mode-variable-name-face", "variable name", {"inherit": "font-lock-variable-name-face"}], ["web-mode-warning-face", "warning", {"inherit": "font-lock-warning-face"}], ["web-mode-whitespace-face", "whitespace", {"bg": "#68228b"}]]}, "yasnippet": {"label": "yasnippet", "preview": "generic", "faces": [["yas--field-debug-face", "yas field debug", {}], ["yas-field-highlight-face", "yas field highlight", {"inherit": "region"}]]}}; +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", "}"]]], "Rust": [[["cmd", "//"], ["cm", " theme.rs"]], [["dec", "#![allow(dead_code)]"]], [["kw", "use"], ["p", " "], ["var", "std"], ["op", "::"], ["var", "fmt"], ["punc", ";"]], [], [["dec", "#[derive"], ["punc", "("], ["dec", "Debug"], ["punc", ","], ["p", " "], ["dec", "Clone"], ["punc", ")]"]], [["kw", "pub"], ["p", " "], ["kw", "trait"], ["p", " "], ["ty", "Theme"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "const"], ["p", " "], ["con", "NAME"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'static"], ["p", " "], ["ty", "str"], ["punc", ";"]], [["p", " "], ["kw", "fn"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["op", "&"], ["var", "'a"], ["p", " "], ["var", "self"], ["punc", ","], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "Option"], ["op", "<"], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["op", ">"], ["punc", ";"]], [["punc", "}"]], [], [["kw", "pub"], ["p", " "], ["kw", "struct"], ["p", " "], ["ty", "Palette"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "pub"], ["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ","]], [["p", " "], ["kw", "pub"], ["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["ty", "Vec"], ["op", "<"], ["punc", "("], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ","], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ")"], ["op", ">"], ["punc", ","]], [["punc", "}"]], [], [["kw", "impl"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["ty", "Theme"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["kw", "for"], ["p", " "], ["ty", "Palette"], ["op", "<"], ["var", "'a"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "const"], ["p", " "], ["con", "NAME"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'static"], ["p", " "], ["ty", "str"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ";"]], [["p", " "], ["kw", "fn"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["op", "&"], ["var", "'a"], ["p", " "], ["var", "self"], ["punc", ","], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["punc", ")"], ["p", " "], ["op", "->"], ["p", " "], ["ty", "Option"], ["op", "<"], ["op", "&"], ["var", "'a"], ["p", " "], ["ty", "str"], ["op", ">"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["var", "key"], ["op", "."], ["fnc", "is_empty"], ["punc", "()"], ["p", " "], ["punc", "{"], ["p", " "], ["kw", "return"], ["p", " "], ["con", "None"], ["punc", ";"], ["p", " "], ["punc", "}"]], [["p", " "], ["var", "self"], ["op", "."], ["prop", "colors"], ["op", "."], ["fnc", "iter"], ["punc", "()"], ["op", "."], ["fnc", "find"], ["punc", "("], ["op", "|"], ["punc", "("], ["var", "k"], ["punc", ","], ["p", " "], ["var", "_"], ["punc", ")"], ["op", "|"], ["p", " "], ["op", "*"], ["var", "k"], ["p", " "], ["op", "=="], ["p", " "], ["var", "key"], ["punc", ")"], ["op", "."], ["fnc", "map"], ["punc", "("], ["op", "|"], ["punc", "("], ["var", "_"], ["punc", ","], ["p", " "], ["var", "v"], ["punc", ")"], ["op", "|"], ["p", " "], ["op", "*"], ["var", "v"], ["punc", ")"]], [["p", " "], ["punc", "}"]], [["punc", "}"]], [], [["kw", "fn"], ["p", " "], ["fnd", "main"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "let"], ["p", " "], ["var", "palette"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Palette"], ["p", " "], ["punc", "{"], ["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["str", "\"dupre\""], ["punc", ","], ["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["bi", "vec!"], ["punc", "["], ["punc", "("], ["str", "\"bg\""], ["punc", ","], ["p", " "], ["str", "\"#0d0b0a\""], ["punc", ")"], ["punc", "]"], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["bi", "println!"], ["punc", "("], ["str", "\"{:?}\""], ["punc", ","], ["p", " "], ["var", "palette"], ["op", "."], ["fnc", "resolve"], ["punc", "("], ["str", "\"bg\""], ["punc", "))"], ["punc", ";"]], [["punc", "}"]]], "Zig": [[["cmd", "//"], ["cm", " theme.zig"]], [["kw", "const"], ["p", " "], ["var", "std"], ["p", " "], ["op", "="], ["p", " "], ["bi", "@import"], ["punc", "("], ["str", "\"std\""], ["punc", ")"], ["punc", ";"]], [["kw", "const"], ["p", " "], ["ty", "Allocator"], ["p", " "], ["op", "="], ["p", " "], ["var", "std"], ["op", "."], ["var", "mem"], ["op", "."], ["ty", "Allocator"], ["punc", ";"]], [], [["kw", "pub"], ["p", " "], ["kw", "const"], ["p", " "], ["ty", "Theme"], ["p", " "], ["op", "="], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"]], [["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["punc", ","]], [["p", " "], ["prop", "colors"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "Color"], ["punc", ","]], [], [["p", " "], ["kw", "pub"], ["p", " "], ["kw", "fn"], ["p", " "], ["fnd", "init"], ["punc", "("], ["var", "alloc"], ["op", ":"], ["p", " "], ["op", "*"], ["ty", "Allocator"], ["punc", ")"], ["p", " "], ["op", "!"], ["bi", "@This"], ["punc", "()"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "const"], ["p", " "], ["var", "colors"], ["p", " "], ["op", "="], ["p", " "], ["kw", "try"], ["p", " "], ["var", "alloc"], ["op", "."], ["fnc", "alloc"], ["punc", "("], ["ty", "Color"], ["punc", ","], ["p", " "], ["num", "2"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["var", "colors"], ["punc", "["], ["num", "0"], ["punc", "]"], ["p", " "], ["op", "="], ["p", " "], ["ty", "Color"], ["punc", "{"], ["p", " "], ["prop", ".name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"bg\""], ["punc", ","], ["p", " "], ["prop", ".hex"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"#0d0b0a\""], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["kw", "return"], ["p", " "], ["bi", "@This"], ["punc", "()"], ["punc", "{"], ["p", " "], ["prop", ".name"], ["p", " "], ["op", "="], ["p", " "], ["str", "\"dupre\""], ["punc", ","], ["p", " "], ["prop", ".colors"], ["p", " "], ["op", "="], ["p", " "], ["var", "colors"], ["p", " "], ["punc", "}"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["punc", "}"], ["punc", ";"]], [], [["kw", "const"], ["p", " "], ["ty", "Color"], ["p", " "], ["op", "="], ["p", " "], ["kw", "struct"], ["p", " "], ["punc", "{"], ["p", " "], ["prop", "name"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["punc", ","], ["p", " "], ["prop", "hex"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["p", " "], ["punc", "}"], ["punc", ";"]], [], [["kw", "fn"], ["p", " "], ["fnd", "resolve"], ["punc", "("], ["var", "theme"], ["op", ":"], ["p", " "], ["ty", "Theme"], ["punc", ","], ["p", " "], ["kw", "comptime"], ["p", " "], ["var", "key"], ["op", ":"], ["p", " "], ["punc", "["], ["punc", ":"], ["num", "0"], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["punc", ")"], ["p", " "], ["op", "!"], ["punc", "["], ["punc", "]"], ["kw", "const"], ["p", " "], ["ty", "u8"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "inline"], ["p", " "], ["kw", "for"], ["p", " "], ["punc", "("], ["var", "theme"], ["op", "."], ["prop", "colors"], ["punc", ")"], ["p", " "], ["op", "|"], ["var", "color"], ["op", "|"], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "if"], ["p", " "], ["punc", "("], ["var", "std"], ["op", "."], ["var", "mem"], ["op", "."], ["fnc", "eql"], ["punc", "("], ["ty", "u8"], ["punc", ","], ["p", " "], ["var", "color"], ["op", "."], ["prop", "name"], ["punc", ","], ["p", " "], ["var", "key"], ["punc", ")"], ["punc", ")"], ["p", " "], ["kw", "return"], ["p", " "], ["var", "color"], ["op", "."], ["prop", "hex"], ["punc", ";"]], [["p", " "], ["punc", "}"]], [["p", " "], ["kw", "return"], ["p", " "], ["con", "error.MissingColor"], ["punc", ";"]], [["punc", "}"]], [], [["kw", "test"], ["p", " "], ["str", "\"resolve bg\""], ["p", " "], ["punc", "{"]], [["p", " "], ["kw", "var"], ["p", " "], ["var", "arena"], ["p", " "], ["op", "="], ["p", " "], ["var", "std"], ["op", "."], ["var", "heap"], ["op", "."], ["ty", "ArenaAllocator"], ["op", "."], ["fnc", "init"], ["punc", "("], ["var", "std"], ["op", "."], ["var", "testing"], ["op", "."], ["prop", "allocator"], ["punc", ")"], ["punc", ";"]], [["p", " "], ["kw", "defer"], ["p", " "], ["var", "arena"], ["op", "."], ["fnc", "deinit"], ["punc", "()"], ["punc", ";"]], [["p", " "], ["kw", "try"], ["p", " "], ["var", "std"], ["op", "."], ["var", "testing"], ["op", "."], ["fnc", "expectEqualStrings"], ["punc", "("], ["str", "\"#0d0b0a\""], ["punc", ","], ["p", " "], ["kw", "try"], ["p", " "], ["fnc", "resolve"], ["punc", "("], ["kw", "try"], ["p", " "], ["ty", "Theme"], ["op", "."], ["fnc", "init"], ["punc", "("], ["op", "&"], ["var", "arena"], ["op", "."], ["prop", "allocator"], ["punc", ")"], ["punc", ","], ["p", " "], ["str", "\"bg\""], ["punc", "))"], ["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 \u2192 type", "@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", {}], ["org-document-info", "document info", {}], ["org-document-info-keyword", "document info keyword", {}], ["org-level-1", "level 1", {}], ["org-level-2", "level 2", {}], ["org-level-3", "level 3", {}], ["org-level-4", "level 4", {}], ["org-level-5", "level 5", {}], ["org-level-6", "level 6", {}], ["org-level-7", "level 7", {}], ["org-level-8", "level 8", {}], ["org-headline-todo", "headline todo", {}], ["org-headline-done", "headline done", {}], ["org-todo", "todo", {}], ["org-done", "done", {}], ["org-priority", "priority", {}], ["org-tag", "tag", {}], ["org-tag-group", "tag group", {}], ["org-special-keyword", "special keyword", {}], ["org-drawer", "drawer", {}], ["org-property-value", "property value", {}], ["org-checkbox", "checkbox", {}], ["org-checkbox-statistics-todo", "checkbox statistics todo", {}], ["org-checkbox-statistics-done", "checkbox statistics done", {}], ["org-warning", "warning", {}], ["org-link", "link", {}], ["org-footnote", "footnote", {}], ["org-date", "date", {}], ["org-sexp-date", "sexp date", {}], ["org-date-selected", "date selected", {}], ["org-target", "target", {}], ["org-macro", "macro", {}], ["org-cite", "cite", {}], ["org-cite-key", "cite key", {}], ["org-block", "block", {}], ["org-block-begin-line", "block begin line", {}], ["org-block-end-line", "block end line", {}], ["org-code", "code", {}], ["org-verbatim", "verbatim", {}], ["org-inline-src-block", "inline src block", {}], ["org-quote", "quote", {}], ["org-verse", "verse", {}], ["org-latex-and-related", "latex and related", {}], ["org-table", "table", {}], ["org-table-header", "table header", {}], ["org-table-row", "table row", {}], ["org-formula", "formula", {}], ["org-column", "column", {}], ["org-column-title", "column title", {}], ["org-list-dt", "list dt", {}], ["org-meta-line", "meta line", {}], ["org-ellipsis", "ellipsis", {}], ["org-hide", "hide", {}], ["org-indent", "indent", {}], ["org-archived", "archived", {}], ["org-default", "default", {}], ["org-dispatcher-highlight", "dispatcher highlight", {}], ["org-agenda-structure", "agenda structure", {}], ["org-agenda-structure-secondary", "agenda structure secondary", {}], ["org-agenda-structure-filter", "agenda structure filter", {}], ["org-agenda-date", "agenda date", {}], ["org-agenda-date-today", "agenda date today", {}], ["org-agenda-date-weekend", "agenda date weekend", {}], ["org-agenda-date-weekend-today", "agenda date weekend today", {}], ["org-agenda-current-time", "agenda current time", {}], ["org-agenda-done", "agenda done", {}], ["org-agenda-dimmed-todo-face", "agenda dimmed todo", {}], ["org-agenda-calendar-event", "agenda calendar event", {}], ["org-agenda-calendar-sexp", "agenda calendar sexp", {}], ["org-agenda-calendar-daterange", "agenda calendar daterange", {}], ["org-agenda-diary", "agenda diary", {}], ["org-agenda-clocking", "agenda clocking", {}], ["org-agenda-column-dateline", "agenda column dateline", {}], ["org-agenda-restriction-lock", "agenda restriction lock", {}], ["org-agenda-filter-category", "agenda filter category", {}], ["org-agenda-filter-effort", "agenda filter effort", {}], ["org-agenda-filter-regexp", "agenda filter regexp", {}], ["org-agenda-filter-tags", "agenda filter tags", {}], ["org-scheduled", "scheduled", {}], ["org-scheduled-today", "scheduled today", {}], ["org-scheduled-previously", "scheduled previously", {}], ["org-upcoming-deadline", "upcoming deadline", {}], ["org-upcoming-distant-deadline", "upcoming distant deadline", {}], ["org-imminent-deadline", "imminent deadline", {}], ["org-time-grid", "time grid", {}], ["org-clock-overlay", "clock overlay", {}], ["org-mode-line-clock", "mode line clock", {}], ["org-mode-line-clock-overrun", "mode line clock overrun", {}]]}, "magit": {"label": "magit", "preview": "magit", "faces": [["magit-section-heading", "section heading", {}], ["magit-section-secondary-heading", "section secondary heading", {}], ["magit-section-heading-selection", "section heading selection", {}], ["magit-section-highlight", "section highlight", {}], ["magit-section-child-count", "section child count", {}], ["magit-diff-added", "diff added", {}], ["magit-diff-added-highlight", "diff added highlight", {}], ["magit-diff-removed", "diff removed", {}], ["magit-diff-removed-highlight", "diff removed highlight", {}], ["magit-diff-context", "diff context", {}], ["magit-diff-context-highlight", "diff context highlight", {}], ["magit-diff-file-heading", "diff file heading", {}], ["magit-diff-file-heading-highlight", "diff file heading highlight", {}], ["magit-diff-file-heading-selection", "diff file heading selection", {}], ["magit-diff-hunk-heading", "diff hunk heading", {}], ["magit-diff-hunk-heading-highlight", "diff hunk heading highlight", {}], ["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", {}], ["magit-diffstat-added", "diffstat added", {}], ["magit-diffstat-removed", "diffstat removed", {}], ["magit-branch-current", "branch current", {}], ["magit-branch-local", "branch local", {}], ["magit-branch-remote", "branch remote", {}], ["magit-branch-remote-head", "branch remote head", {}], ["magit-branch-upstream", "branch upstream", {}], ["magit-branch-warning", "branch warning", {}], ["magit-head", "head", {}], ["magit-tag", "tag", {}], ["magit-hash", "hash", {}], ["magit-filename", "filename", {}], ["magit-dimmed", "dimmed", {}], ["magit-keyword", "keyword", {}], ["magit-keyword-squash", "keyword squash", {}], ["magit-refname", "refname", {}], ["magit-refname-stash", "refname stash", {}], ["magit-refname-wip", "refname wip", {}], ["magit-refname-pullreq", "refname pullreq", {}], ["magit-log-author", "log author", {}], ["magit-log-date", "log date", {}], ["magit-log-graph", "log graph", {}], ["magit-header-line", "header line", {}], ["magit-header-line-key", "header line key", {}], ["magit-header-line-log-select", "header line log select", {}], ["magit-process-ok", "process ok", {}], ["magit-process-ng", "process ng", {}], ["magit-mode-line-process", "mode line process", {}], ["magit-mode-line-process-error", "mode line process error", {}], ["magit-bisect-good", "bisect good", {}], ["magit-bisect-bad", "bisect bad", {}], ["magit-bisect-skip", "bisect skip", {}], ["magit-blame-heading", "blame heading", {}], ["magit-blame-highlight", "blame highlight", {}], ["magit-blame-hash", "blame hash", {}], ["magit-blame-name", "blame name", {}], ["magit-blame-date", "blame date", {}], ["magit-blame-summary", "blame summary", {}], ["magit-blame-dimmed", "blame dimmed", {}], ["magit-blame-margin", "blame margin", {}], ["magit-cherry-equivalent", "cherry equivalent", {}], ["magit-cherry-unmatched", "cherry unmatched", {}], ["magit-signature-good", "signature good", {}], ["magit-signature-bad", "signature bad", {}], ["magit-signature-untrusted", "signature untrusted", {}], ["magit-signature-expired", "signature expired", {}], ["magit-signature-expired-key", "signature expired key", {}], ["magit-signature-revoked", "signature revoked", {}], ["magit-signature-error", "signature error", {}], ["magit-reflog-commit", "reflog commit", {}], ["magit-reflog-amend", "reflog amend", {}], ["magit-reflog-merge", "reflog merge", {}], ["magit-reflog-checkout", "reflog checkout", {}], ["magit-reflog-reset", "reflog reset", {}], ["magit-reflog-rebase", "reflog rebase", {}], ["magit-reflog-cherry-pick", "reflog cherry pick", {}], ["magit-reflog-remote", "reflog remote", {}], ["magit-reflog-other", "reflog other", {}], ["magit-sequence-pick", "sequence pick", {}], ["magit-sequence-stop", "sequence stop", {}], ["magit-sequence-part", "sequence part", {}], ["magit-sequence-head", "sequence head", {}], ["magit-sequence-drop", "sequence drop", {}], ["magit-sequence-done", "sequence done", {}], ["magit-sequence-onto", "sequence onto", {}], ["magit-sequence-exec", "sequence exec", {}], ["magit-left-margin", "left margin", {}], ["git-commit-comment-action", "git commit comment action", {}], ["git-commit-comment-branch-local", "git commit comment branch local", {}], ["git-commit-comment-branch-remote", "git commit comment branch remote", {}], ["git-commit-comment-detached", "git commit comment detached", {}], ["git-commit-comment-file", "git commit comment file", {}], ["git-commit-comment-heading", "git commit comment heading", {}], ["git-commit-keyword", "git commit keyword", {}], ["git-commit-nonempty-second-line", "git commit nonempty second line", {}], ["git-commit-overlong-summary", "git commit overlong summary", {}], ["git-commit-summary", "git commit summary", {}], ["git-commit-trailer-token", "git commit trailer token", {}], ["git-commit-trailer-value", "git commit trailer value", {}]]}, "elfeed": {"label": "elfeed", "preview": "elfeed", "faces": [["elfeed-search-date-face", "search date", {"fg": "#aaa"}], ["elfeed-search-title-face", "search title", {"fg": "#000"}], ["elfeed-search-unread-title-face", "search unread title", {"bold": true}], ["elfeed-search-feed-face", "search feed", {"fg": "#aa0"}], ["elfeed-search-tag-face", "search tag", {"fg": "#070"}], ["elfeed-search-unread-count-face", "search unread count", {"fg": "#000"}], ["elfeed-search-filter-face", "search filter", {"inherit": "mode-line-buffer-id"}], ["elfeed-search-last-update-face", "search last update", {}], ["elfeed-log-date-face", "log date", {"inherit": "font-lock-type-face"}], ["elfeed-log-error-level-face", "log error level", {"fg": "#ff0000"}], ["elfeed-log-warn-level-face", "log warn level", {"fg": "#daa520"}], ["elfeed-log-info-level-face", "log info level", {"fg": "#00bfff"}], ["elfeed-log-debug-level-face", "log debug level", {"fg": "#ee00ee"}]]}, "mu4e": {"label": "mu4e", "preview": "mu4e", "faces": [["mu4e-title-face", "title", {}], ["mu4e-context-face", "context", {}], ["mu4e-modeline-face", "modeline", {}], ["mu4e-ok-face", "ok", {}], ["mu4e-warning-face", "warning", {}], ["mu4e-header-title-face", "header title", {}], ["mu4e-header-key-face", "header key", {}], ["mu4e-header-value-face", "header value", {}], ["mu4e-header-face", "header", {}], ["mu4e-header-highlight-face", "header highlight", {}], ["mu4e-header-marks-face", "header marks", {}], ["mu4e-unread-face", "unread", {}], ["mu4e-flagged-face", "flagged", {}], ["mu4e-replied-face", "replied", {}], ["mu4e-forwarded-face", "forwarded", {}], ["mu4e-draft-face", "draft", {}], ["mu4e-trashed-face", "trashed", {}], ["mu4e-related-face", "related", {}], ["mu4e-contact-face", "contact", {}], ["mu4e-special-header-value-face", "special header value", {}], ["mu4e-url-number-face", "url number", {}], ["mu4e-link-face", "link", {}], ["mu4e-footer-face", "footer", {}], ["mu4e-region-code", "region code", {}], ["mu4e-system-face", "system", {}], ["mu4e-highlight-face", "highlight", {}], ["mu4e-compose-separator-face", "compose separator", {}]]}, "ghostel": {"label": "ghostel", "preview": "ghostel", "faces": [["ghostel-default", "default", {"inherit": "default"}], ["ghostel-fake-cursor", "fake cursor", {"box": {"style": "line", "width": 1, "color": null}}], ["ghostel-fake-cursor-box", "fake cursor box", {"inherit": "cursor"}], ["ghostel-color-black", "color black", {"inherit": "ansi-color-black"}], ["ghostel-color-red", "color red", {"inherit": "ansi-color-red"}], ["ghostel-color-green", "color green", {"inherit": "ansi-color-green"}], ["ghostel-color-yellow", "color yellow", {"inherit": "ansi-color-yellow"}], ["ghostel-color-blue", "color blue", {"inherit": "ansi-color-blue"}], ["ghostel-color-magenta", "color magenta", {"inherit": "ansi-color-magenta"}], ["ghostel-color-cyan", "color cyan", {"inherit": "ansi-color-cyan"}], ["ghostel-color-white", "color white", {"inherit": "ansi-color-white"}], ["ghostel-color-bright-black", "color bright black", {"inherit": "ansi-color-bright-black"}], ["ghostel-color-bright-red", "color bright red", {"inherit": "ansi-color-bright-red"}], ["ghostel-color-bright-green", "color bright green", {"inherit": "ansi-color-bright-green"}], ["ghostel-color-bright-yellow", "color bright yellow", {"inherit": "ansi-color-bright-yellow"}], ["ghostel-color-bright-blue", "color bright blue", {"inherit": "ansi-color-bright-blue"}], ["ghostel-color-bright-magenta", "color bright magenta", {"inherit": "ansi-color-bright-magenta"}], ["ghostel-color-bright-cyan", "color bright cyan", {"inherit": "ansi-color-bright-cyan"}], ["ghostel-color-bright-white", "color bright white", {"inherit": "ansi-color-bright-white"}]]}, "dashboard": {"label": "dashboard", "preview": "dashboard", "faces": [["dashboard-banner-logo-title", "banner logo title", {"inherit": "default"}], ["dashboard-text-banner", "text banner", {"inherit": "font-lock-keyword-face"}], ["dashboard-heading", "heading", {"inherit": "font-lock-keyword-face"}], ["dashboard-items-face", "items", {"inherit": "widget-button"}], ["dashboard-navigator", "navigator", {"inherit": "font-lock-keyword-face"}], ["dashboard-no-items-face", "no items", {"inherit": "widget-button"}], ["dashboard-footer-face", "footer", {"inherit": "font-lock-doc-face"}], ["dashboard-footer-icon-face", "footer icon", {"inherit": "dashboard-footer-face"}]]}, "lsp-mode": {"label": "lsp-mode", "preview": "lsp", "faces": [["lsp-signature-face", "signature", {}], ["lsp-signature-highlight-function-argument", "signature highlight function argument", {}], ["lsp-signature-posframe", "signature posframe", {}], ["lsp-face-highlight-read", "face highlight read", {}], ["lsp-face-highlight-write", "face highlight write", {}], ["lsp-face-highlight-textual", "face highlight textual", {}], ["lsp-face-rename", "face rename", {}], ["lsp-rename-placeholder-face", "rename placeholder", {}], ["lsp-inlay-hint-face", "inlay hint", {}], ["lsp-inlay-hint-parameter-face", "inlay hint parameter", {}], ["lsp-inlay-hint-type-face", "inlay hint type", {}], ["lsp-details-face", "details", {}], ["lsp-installation-buffer-face", "installation buffer", {}], ["lsp-installation-finished-buffer-face", "installation finished buffer", {}]]}, "git-gutter": {"label": "git-gutter", "preview": "gitgutter", "faces": [["git-gutter:added", "added", {"fg": "#00ff00", "bold": true, "inherit": "default"}], ["git-gutter:modified", "modified", {"fg": "#ff00ff", "bold": true, "inherit": "default"}], ["git-gutter:deleted", "deleted", {"fg": "#ff0000", "bold": true, "inherit": "default"}], ["git-gutter:unchanged", "unchanged", {"bg": "#ffff00", "inherit": "default"}], ["git-gutter:separator", "separator", {"fg": "#00ffff", "bold": true, "inherit": "default"}]]}, "flycheck": {"label": "flycheck", "preview": "flycheck", "faces": [["flycheck-error", "error", {"underline": true}], ["flycheck-warning", "warning", {"underline": true}], ["flycheck-info", "info", {"underline": true}], ["flycheck-fringe-error", "fringe error", {"inherit": "error"}], ["flycheck-fringe-warning", "fringe warning", {"inherit": "warning"}], ["flycheck-fringe-info", "fringe info", {"inherit": "success"}], ["flycheck-delimited-error", "delimited error", {}], ["flycheck-error-delimiter", "error delimiter", {}], ["flycheck-error-list-error", "error list error", {"inherit": "error"}], ["flycheck-error-list-warning", "error list warning", {"inherit": "warning"}], ["flycheck-error-list-info", "error list info", {"inherit": "success"}], ["flycheck-error-list-error-message", "error list error message", {}], ["flycheck-error-list-checker-name", "error list checker name", {"inherit": "font-lock-function-name-face"}], ["flycheck-error-list-column-number", "error list column number", {}], ["flycheck-error-list-line-number", "error list line number", {}], ["flycheck-error-list-filename", "error list filename", {"inherit": "mode-line-buffer-id"}], ["flycheck-error-list-id", "error list id", {"inherit": "font-lock-type-face"}], ["flycheck-error-list-id-with-explainer", "error list id with explainer", {"inherit": "flycheck-error-list-id", "box": {"style": "released", "width": 1, "color": null}}], ["flycheck-error-list-highlight", "error list highlight", {"bold": true}], ["flycheck-verify-select-checker", "verify select checker", {"box": {"style": "released", "width": 1, "color": null}}]]}, "dired": {"label": "dired", "preview": "dired", "faces": [["dired-header", "header", {}], ["dired-directory", "directory", {}], ["dired-symlink", "symlink", {}], ["dired-broken-symlink", "broken symlink", {}], ["dired-special", "special", {}], ["dired-set-id", "set id", {}], ["dired-perm-write", "perm write", {}], ["dired-mark", "mark", {}], ["dired-marked", "marked", {}], ["dired-flagged", "flagged", {}], ["dired-ignored", "ignored", {}], ["dired-warning", "warning", {}]]}, "dirvish": {"label": "dirvish", "preview": "dirvish", "faces": [["dirvish-inactive", "inactive", {"inherit": "shadow"}], ["dirvish-free-space", "free space", {"inherit": "font-lock-constant-face"}], ["dirvish-hl-line", "hl line", {"inherit": "highlight"}], ["dirvish-hl-line-inactive", "hl line inactive", {"inherit": "region"}], ["dirvish-file-modes", "file modes", {"fg": "#6b6b6b"}], ["dirvish-file-link-number", "file link number", {"inherit": "font-lock-constant-face"}], ["dirvish-file-user-id", "file user id", {"inherit": "font-lock-preprocessor-face"}], ["dirvish-file-group-id", "file group id", {"inherit": "dirvish-file-user-id"}], ["dirvish-file-size", "file size", {"underline": true, "inherit": "completions-annotations"}], ["dirvish-file-time", "file time", {"fg": "#979797"}], ["dirvish-file-inode-number", "file inode number", {"inherit": "dirvish-file-link-number"}], ["dirvish-file-device-number", "file device number", {"inherit": "dirvish-file-link-number"}], ["dirvish-subtree-guide", "subtree guide", {"bg": "unspecified", "underline": true, "inherit": "dired-ignored"}], ["dirvish-subtree-state", "subtree state", {"bg": "unspecified", "underline": true, "inherit": "dired-ignored"}], ["dirvish-collapse-dir-face", "collapse dir", {"inherit": "dired-directory"}], ["dirvish-collapse-empty-dir-face", "collapse empty dir", {"inherit": "shadow"}], ["dirvish-collapse-file-face", "collapse file", {"inherit": "default"}], ["dirvish-emerge-group-title", "emerge group title", {"inherit": "dired-ignored"}], ["dirvish-media-info-heading", "media info heading", {"inherit": ["dired-header", "bold"]}], ["dirvish-media-info-property-key", "media info property key", {"inherit": ["italic"]}], ["dirvish-narrow-match-face-0", "narrow match 0", {"fg": "#223fbf", "bold": true}], ["dirvish-narrow-match-face-1", "narrow match 1", {"fg": "#8f0075", "bold": true}], ["dirvish-narrow-match-face-2", "narrow match 2", {"fg": "#145a00", "bold": true}], ["dirvish-narrow-match-face-3", "narrow match 3", {"fg": "#804000", "bold": true}], ["dirvish-narrow-split", "narrow split", {"inherit": "font-lock-negation-char-face"}], ["dirvish-proc-running", "proc running", {"inherit": "warning"}], ["dirvish-proc-finished", "proc finished", {"inherit": "success"}], ["dirvish-proc-failed", "proc failed", {"inherit": "error"}], ["dirvish-git-commit-message-face", "git commit message", {"bg": "unspecified", "underline": true, "inherit": "dired-ignored"}], ["dirvish-vc-added-state", "vc added state", {"inherit": "vc-locally-added-state"}], ["dirvish-vc-edited-state", "vc edited state", {"inherit": "vc-edited-state"}], ["dirvish-vc-removed-state", "vc removed state", {"inherit": "vc-removed-state"}], ["dirvish-vc-conflict-state", "vc conflict state", {"inherit": "vc-conflict-state"}], ["dirvish-vc-locked-state", "vc locked state", {"inherit": "vc-locked-state"}], ["dirvish-vc-missing-state", "vc missing state", {"inherit": "vc-missing-state"}], ["dirvish-vc-needs-merge-face", "vc needs merge", {"bg": "#efcbcf"}], ["dirvish-vc-needs-update-state", "vc needs update state", {"inherit": "vc-needs-update-state"}], ["dirvish-vc-unregistered-face", "vc unregistered", {"inherit": "font-lock-constant-face"}]]}, "calibredb": {"label": "calibredb", "preview": "calibredb", "faces": [["calibredb-search-header-library-name-face", "search header library name", {}], ["calibredb-search-header-library-path-face", "search header library path", {}], ["calibredb-search-header-total-face", "search header total", {}], ["calibredb-search-header-filter-face", "search header filter", {}], ["calibredb-search-header-sort-face", "search header sort", {}], ["calibredb-search-header-highlight-face", "search header highlight", {}], ["calibredb-id-face", "id", {}], ["calibredb-title-face", "title", {}], ["calibredb-author-face", "author", {}], ["calibredb-format-face", "format", {}], ["calibredb-size-face", "size", {}], ["calibredb-tag-face", "tag", {}], ["calibredb-date-face", "date", {}], ["calibredb-mark-face", "mark", {}], ["calibredb-series-face", "series", {}], ["calibredb-publisher-face", "publisher", {}], ["calibredb-pubdate-face", "pubdate", {}], ["calibredb-language-face", "language", {}], ["calibredb-comment-face", "comment", {}], ["calibredb-archive-face", "archive", {}], ["calibredb-favorite-face", "favorite", {}], ["calibredb-file-face", "file", {}], ["calibredb-ids-face", "ids", {}], ["calibredb-highlight-face", "highlight", {}], ["calibredb-current-page-button-face", "current page button", {}], ["calibredb-mouse-face", "mouse", {}], ["calibredb-title-detailed-view-face", "title detailed view", {}], ["calibredb-edit-annotation-header-title-face", "edit annotation header title", {}]]}, "erc": {"label": "erc", "preview": "erc", "faces": [["erc-header-line", "header line", {}], ["erc-timestamp-face", "timestamp", {}], ["erc-notice-face", "notice", {}], ["erc-default-face", "default", {}], ["erc-current-nick-face", "current nick", {}], ["erc-my-nick-face", "my nick", {}], ["erc-my-nick-prefix-face", "my nick prefix", {}], ["erc-nick-default-face", "nick default", {}], ["erc-nick-prefix-face", "nick prefix", {}], ["erc-button-nick-default-face", "button nick default", {}], ["erc-nick-msg-face", "nick msg", {}], ["erc-direct-msg-face", "direct msg", {}], ["erc-action-face", "action", {}], ["erc-keyword-face", "keyword", {}], ["erc-pal-face", "pal", {}], ["erc-fool-face", "fool", {}], ["erc-dangerous-host-face", "dangerous host", {}], ["erc-error-face", "error", {}], ["erc-input-face", "input", {}], ["erc-prompt-face", "prompt", {}], ["erc-command-indicator-face", "command indicator", {}], ["erc-information", "information", {}], ["erc-button", "button", {}], ["erc-bold-face", "bold", {}], ["erc-italic-face", "italic", {}], ["erc-underline-face", "underline", {}], ["erc-inverse-face", "inverse", {}], ["erc-spoiler-face", "spoiler", {}], ["erc-fill-wrap-merge-indicator-face", "fill wrap merge indicator", {}], ["erc-keep-place-indicator-arrow", "keep place indicator arrow", {}], ["erc-keep-place-indicator-line", "keep place indicator line", {}]]}, "org-drill": {"label": "org-drill", "preview": "orgdrill", "faces": [["org-drill-hidden-cloze-face", "hidden cloze", {}], ["org-drill-visible-cloze-face", "visible cloze", {}], ["org-drill-visible-cloze-hint-face", "visible cloze hint", {}]]}, "org-noter": {"label": "org-noter", "preview": "orgnoter", "faces": [["org-noter-notes-exist-face", "notes exist", {}], ["org-noter-no-notes-exist-face", "no notes exist", {}]]}, "signel": {"label": "signel", "preview": "signel", "faces": [["signel-timestamp-face", "timestamp", {}], ["signel-my-msg-face", "my msg", {}], ["signel-other-msg-face", "other msg", {}], ["signel-error-face", "error", {}]]}, "pearl": {"label": "pearl", "preview": "pearl", "faces": [["pearl-preamble-summary", "preamble summary", {}], ["pearl-editable-comment", "editable comment", {}], ["pearl-readonly-comment", "readonly comment", {}], ["pearl-modified-highlight", "modified highlight", {}], ["pearl-modified-local", "modified local", {}], ["pearl-modified-unknown", "modified unknown", {}]]}, "slack": {"label": "slack", "preview": "slack", "faces": [["slack-room-info-title-face", "room info title", {}], ["slack-room-info-title-room-name-face", "room info title room name", {}], ["slack-room-info-section-title-face", "room info section title", {}], ["slack-room-info-section-label-face", "room info section label", {}], ["slack-room-unread-face", "room unread", {}], ["slack-message-output-header", "message output header", {}], ["slack-message-output-text", "message output text", {}], ["slack-message-output-reaction", "message output reaction", {}], ["slack-message-output-reaction-pressed", "message output reaction pressed", {}], ["slack-message-deleted-face", "message deleted", {}], ["slack-new-message-marker-face", "new message marker", {}], ["slack-all-thread-buffer-thread-header-face", "all thread buffer thread header", {}], ["slack-message-mention-face", "message mention", {}], ["slack-message-mention-me-face", "message mention me", {}], ["slack-message-mention-keyword-face", "message mention keyword", {}], ["slack-channel-button-face", "channel button", {}], ["slack-mrkdwn-bold-face", "mrkdwn bold", {}], ["slack-mrkdwn-italic-face", "mrkdwn italic", {}], ["slack-mrkdwn-code-face", "mrkdwn code", {}], ["slack-mrkdwn-code-block-face", "mrkdwn code block", {}], ["slack-mrkdwn-strike-face", "mrkdwn strike", {}], ["slack-mrkdwn-blockquote-face", "mrkdwn blockquote", {}], ["slack-mrkdwn-list-face", "mrkdwn list", {}], ["slack-attachment-header", "attachment header", {}], ["slack-attachment-footer", "attachment footer", {}], ["slack-attachment-pad", "attachment pad", {}], ["slack-attachment-field-title", "attachment field title", {}], ["slack-message-attachment-preview-header-face", "message attachment preview header", {}], ["slack-preview-face", "preview", {}], ["slack-block-highlight-source-overlay-face", "block highlight source overlay", {}], ["slack-message-action-face", "message action", {}], ["slack-message-action-primary-face", "message action primary", {}], ["slack-message-action-danger-face", "message action danger", {}], ["slack-button-block-element-face", "button block element", {}], ["slack-button-primary-block-element-face", "button primary block element", {}], ["slack-button-danger-block-element-face", "button danger block element", {}], ["slack-select-block-element-face", "select block element", {}], ["slack-overflow-block-element-face", "overflow block element", {}], ["slack-date-picker-block-element-face", "date picker block element", {}], ["slack-dialog-title-face", "dialog title", {}], ["slack-dialog-element-label-face", "dialog element label", {}], ["slack-dialog-element-hint-face", "dialog element hint", {}], ["slack-dialog-element-placeholder-face", "dialog element placeholder", {}], ["slack-dialog-element-error-face", "dialog element error", {}], ["slack-dialog-submit-button-face", "dialog submit button", {}], ["slack-dialog-cancel-button-face", "dialog cancel button", {}], ["slack-dialog-select-element-input-face", "dialog select element input", {}], ["slack-user-active-face", "user active", {}], ["slack-user-dnd-face", "user dnd", {}], ["slack-user-profile-header-face", "user profile header", {}], ["slack-user-profile-property-name-face", "user profile property name", {}], ["slack-profile-image-face", "profile image", {}], ["slack-search-result-message-header-face", "search result message header", {}], ["slack-search-result-message-username-face", "search result message username", {}], ["slack-modeline-has-unreads-face", "modeline has unreads", {}], ["slack-modeline-channel-has-unreads-face", "modeline channel has unreads", {}], ["slack-modeline-thread-has-unreads-face", "modeline thread has unreads", {}]]}, "telega": {"label": "telega", "preview": "telega", "faces": [["telega-root-heading", "root heading", {}], ["telega-tracking", "tracking", {}], ["telega-unread-unmuted-modeline", "unread unmuted modeline", {}], ["telega-username", "username", {}], ["telega-user-online-status", "user online status", {}], ["telega-user-non-online-status", "user non online status", {}], ["telega-secret-title", "secret title", {}], ["telega-contact-birthdays-today", "contact birthdays today", {}], ["telega-muted-count", "muted count", {}], ["telega-unmuted-count", "unmuted count", {}], ["telega-mention-count", "mention count", {}], ["telega-has-chatbuf-brackets", "has chatbuf brackets", {}], ["telega-delim-face", "delim", {}], ["telega-shadow", "shadow", {}], ["telega-link", "link", {}], ["telega-blue", "blue", {}], ["telega-red", "red", {}], ["telega-msg-heading", "msg heading", {}], ["telega-msg-user-title", "msg user title", {}], ["telega-msg-self-title", "msg self title", {}], ["telega-msg-deleted", "msg deleted", {}], ["telega-msg-sponsored", "msg sponsored", {}], ["telega-msg-inline-reply", "msg inline reply", {}], ["telega-msg-inline-forward", "msg inline forward", {}], ["telega-msg-inline-other", "msg inline other", {}], ["telega-entity-type-bold", "entity type bold", {}], ["telega-entity-type-italic", "entity type italic", {}], ["telega-entity-type-underline", "entity type underline", {}], ["telega-entity-type-strikethrough", "entity type strikethrough", {}], ["telega-entity-type-code", "entity type code", {}], ["telega-entity-type-pre", "entity type pre", {}], ["telega-entity-type-blockquote", "entity type blockquote", {}], ["telega-entity-type-mention", "entity type mention", {}], ["telega-entity-type-hashtag", "entity type hashtag", {}], ["telega-entity-type-cashtag", "entity type cashtag", {}], ["telega-entity-type-botcommand", "entity type botcommand", {}], ["telega-entity-type-texturl", "entity type texturl", {}], ["telega-entity-type-spoiler", "entity type spoiler", {}], ["telega-reaction", "reaction", {}], ["telega-reaction-chosen", "reaction chosen", {}], ["telega-reaction-paid", "reaction paid", {}], ["telega-reaction-paid-chosen", "reaction paid chosen", {}], ["telega-highlight-text-face", "highlight text", {}], ["telega-button-highlight", "button highlight", {}], ["telega-chat-prompt", "chat prompt", {}], ["telega-chat-prompt-aux", "chat prompt aux", {}], ["telega-chat-input-attachment", "chat input attachment", {}], ["telega-topic-button", "topic button", {}], ["telega-filter-active", "filter active", {}], ["telega-filter-button-active", "filter button active", {}], ["telega-filter-button-inactive", "filter button inactive", {}], ["telega-checklist-stats-done", "checklist stats done", {}], ["telega-checklist-stats-todo", "checklist stats todo", {}], ["telega-box-button", "box button", {}], ["telega-box-button-active", "box button active", {}], ["telega-box-button-default-active", "box button default active", {}], ["telega-box-button-default-passive", "box button default passive", {}], ["telega-box-button-primary-active", "box button primary active", {}], ["telega-box-button-primary-passive", "box button primary passive", {}], ["telega-box-button-success-active", "box button success active", {}], ["telega-box-button-success-passive", "box button success passive", {}], ["telega-box-button-danger-active", "box button danger active", {}], ["telega-box-button-danger-passive", "box button danger passive", {}], ["telega-box-button-ui-active", "box button ui active", {}], ["telega-box-button-ui-passive", "box button ui passive", {}], ["telega-box-button2-active", "box button2 active", {}], ["telega-box-button2-passive", "box button2 passive", {}], ["telega-box-button2-white-foreground", "box button2 white foreground", {}], ["telega-describe-item-title", "describe item title", {}], ["telega-describe-section-title", "describe section title", {}], ["telega-describe-subsection-title", "describe subsection title", {}], ["telega-enckey-00", "enckey 00", {}], ["telega-enckey-01", "enckey 01", {}], ["telega-enckey-10", "enckey 10", {}], ["telega-enckey-11", "enckey 11", {}], ["telega-palette-builtin-blue", "palette builtin blue", {}], ["telega-palette-builtin-green", "palette builtin green", {}], ["telega-palette-builtin-orange", "palette builtin orange", {}], ["telega-palette-builtin-purple", "palette builtin purple", {}], ["telega-webpage-title", "webpage title", {}], ["telega-webpage-subtitle", "webpage subtitle", {}], ["telega-webpage-header", "webpage header", {}], ["telega-webpage-subheader", "webpage subheader", {}], ["telega-webpage-outline", "webpage outline", {}], ["telega-webpage-fixed", "webpage fixed", {}], ["telega-webpage-preformatted", "webpage preformatted", {}], ["telega-webpage-marked", "webpage marked", {}], ["telega-webpage-strike-through", "webpage strike through", {}], ["telega-webpage-chat-link", "webpage chat link", {}], ["telega-link-preview-sitename", "link preview sitename", {}], ["telega-link-preview-title", "link preview title", {}]]}, "shr": {"label": "shr (HTML: nov/eww/mail)", "preview": "shr", "faces": [["shr-h1", "h1", {}], ["shr-h2", "h2", {}], ["shr-h3", "h3", {}], ["shr-h4", "h4", {}], ["shr-h5", "h5", {}], ["shr-h6", "h6", {}], ["shr-text", "text", {}], ["shr-link", "link", {}], ["shr-selected-link", "selected link", {}], ["shr-code", "code", {}], ["shr-mark", "mark", {}], ["shr-strike-through", "strike through", {}], ["shr-sup", "sup", {}], ["shr-abbreviation", "abbreviation", {}], ["shr-sliced-image", "sliced image", {}]]}, "2048-game": {"label": "2048-game", "preview": "generic", "faces": [["twentyfortyeight-face-1024", "twentyfortyeight 1024", {"fg": "#000000", "bg": "#ffd700"}], ["twentyfortyeight-face-128", "twentyfortyeight 128", {"fg": "#ffffff", "bg": "#8b0000"}], ["twentyfortyeight-face-16", "twentyfortyeight 16", {"fg": "#000000", "bg": "#ffa500"}], ["twentyfortyeight-face-2", "twentyfortyeight 2", {"fg": "#000000", "bg": "#f0e68c"}], ["twentyfortyeight-face-2048", "twentyfortyeight 2048", {"fg": "#000000", "bg": "#ffff00"}], ["twentyfortyeight-face-256", "twentyfortyeight 256", {"fg": "#ffffff", "bg": "#8b008b"}], ["twentyfortyeight-face-32", "twentyfortyeight 32", {"fg": "#000000", "bg": "#ff4500"}], ["twentyfortyeight-face-4", "twentyfortyeight 4", {"fg": "#000000", "bg": "#deb887"}], ["twentyfortyeight-face-512", "twentyfortyeight 512", {"fg": "#000000", "bg": "#ff00ff"}], ["twentyfortyeight-face-64", "twentyfortyeight 64", {"fg": "#ffffff", "bg": "#b22222"}], ["twentyfortyeight-face-8", "twentyfortyeight 8", {"fg": "#000000", "bg": "#cd8500"}]]}, "alert": {"label": "alert", "preview": "generic", "faces": [["alert-high-face", "high", {"fg": "#ff8c00", "bold": true}], ["alert-low-face", "low", {"fg": "#00008b"}], ["alert-moderate-face", "moderate", {"fg": "#ffd700", "bold": true}], ["alert-normal-face", "normal", {}], ["alert-trivial-face", "trivial", {"fg": "#9400d3"}], ["alert-urgent-face", "urgent", {"fg": "#ff0000", "bold": true}]]}, "all-the-icons": {"label": "all-the-icons", "preview": "generic", "faces": [["all-the-icons-blue", "blue", {"fg": "#6a9fb5"}], ["all-the-icons-blue-alt", "blue alt", {"fg": "#2188b6"}], ["all-the-icons-cyan", "cyan", {"fg": "#75b5aa"}], ["all-the-icons-cyan-alt", "cyan alt", {"fg": "#0595bd"}], ["all-the-icons-dblue", "dblue", {"fg": "#446674"}], ["all-the-icons-dcyan", "dcyan", {"fg": "#48746d"}], ["all-the-icons-dgreen", "dgreen", {"fg": "#6d8143"}], ["all-the-icons-dmaroon", "dmaroon", {"fg": "#72584b"}], ["all-the-icons-dorange", "dorange", {"fg": "#915b2d"}], ["all-the-icons-dpink", "dpink", {"fg": "#7e5d5f"}], ["all-the-icons-dpurple", "dpurple", {"fg": "#694863"}], ["all-the-icons-dred", "dred", {"fg": "#843031"}], ["all-the-icons-dsilver", "dsilver", {"fg": "#838484"}], ["all-the-icons-dyellow", "dyellow", {"fg": "#b48d56"}], ["all-the-icons-green", "green", {"fg": "#90a959"}], ["all-the-icons-lblue", "lblue", {"fg": "#677174"}], ["all-the-icons-lcyan", "lcyan", {"fg": "#2c7d6e"}], ["all-the-icons-lgreen", "lgreen", {"fg": "#3d6837"}], ["all-the-icons-lmaroon", "lmaroon", {"fg": "#ce7a4e"}], ["all-the-icons-lorange", "lorange", {"fg": "#ffa500"}], ["all-the-icons-lpink", "lpink", {"fg": "#ff505b"}], ["all-the-icons-lpurple", "lpurple", {"fg": "#e69dd6"}], ["all-the-icons-lred", "lred", {"fg": "#eb595a"}], ["all-the-icons-lsilver", "lsilver", {"fg": "#7f7869"}], ["all-the-icons-lyellow", "lyellow", {"fg": "#ff9300"}], ["all-the-icons-maroon", "maroon", {"fg": "#8f5536"}], ["all-the-icons-orange", "orange", {"fg": "#d4843e"}], ["all-the-icons-pink", "pink", {"fg": "#fc505b"}], ["all-the-icons-purple", "purple", {"fg": "#68295b"}], ["all-the-icons-purple-alt", "purple alt", {"fg": "#5d54e1"}], ["all-the-icons-red", "red", {"fg": "#ac4142"}], ["all-the-icons-red-alt", "red alt", {"fg": "#843031"}], ["all-the-icons-silver", "silver", {"fg": "#716e68"}], ["all-the-icons-yellow", "yellow", {"fg": "#ffcc0e"}]]}, "company": {"label": "company", "preview": "generic", "faces": [["company-echo", "echo", {}], ["company-echo-common", "echo common", {"fg": "#8b1a1a"}], ["company-preview", "preview", {"inherit": ["company-tooltip-selection", "company-tooltip"]}], ["company-preview-common", "preview common", {"inherit": "company-tooltip-common-selection"}], ["company-preview-search", "preview search", {"inherit": "company-tooltip-common-selection"}], ["company-tooltip", "tooltip", {"fg": "#000000", "bg": "#fff8dc"}], ["company-tooltip-annotation", "tooltip annotation", {"fg": "#8b1a1a"}], ["company-tooltip-annotation-selection", "tooltip annotation selection", {"inherit": "company-tooltip-annotation"}], ["company-tooltip-common", "tooltip common", {"fg": "#8b0000"}], ["company-tooltip-common-selection", "tooltip common selection", {"inherit": "company-tooltip-common"}], ["company-tooltip-deprecated", "tooltip deprecated", {"strike": true}], ["company-tooltip-mouse", "tooltip mouse", {"inherit": "highlight"}], ["company-tooltip-quick-access", "tooltip quick access", {"inherit": "company-tooltip-annotation"}], ["company-tooltip-quick-access-selection", "tooltip quick access selection", {"inherit": "company-tooltip-annotation-selection"}], ["company-tooltip-scrollbar-thumb", "tooltip scrollbar thumb", {"bg": "#cd5c5c"}], ["company-tooltip-scrollbar-track", "tooltip scrollbar track", {"bg": "#f5deb3"}], ["company-tooltip-search", "tooltip search", {"inherit": "highlight"}], ["company-tooltip-search-selection", "tooltip search selection", {"inherit": "highlight"}], ["company-tooltip-selection", "tooltip selection", {"bg": "#add8e6"}]]}, "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", {"inherit": "error"}], ["consult-async-finished", "async finished", {"inherit": "success"}], ["consult-async-running", "async running", {"inherit": "consult-narrow-indicator"}], ["consult-async-split", "async split", {"inherit": "font-lock-negation-char-face"}], ["consult-bookmark", "bookmark", {"inherit": "font-lock-constant-face"}], ["consult-buffer", "buffer", {}], ["consult-file", "file", {"inherit": "font-lock-function-name-face"}], ["consult-grep-context", "grep context", {"inherit": "shadow"}], ["consult-help", "help", {"inherit": "shadow"}], ["consult-highlight-mark", "highlight mark", {"inherit": "consult-highlight-match"}], ["consult-highlight-match", "highlight match", {"inherit": "match"}], ["consult-key", "key", {"inherit": "font-lock-keyword-face"}], ["consult-line-number", "line number", {"inherit": "consult-key"}], ["consult-line-number-prefix", "line number prefix", {"inherit": "line-number"}], ["consult-line-number-wrapped", "line number wrapped", {"inherit": "font-lock-warning-face"}], ["consult-narrow-indicator", "narrow indicator", {"inherit": "warning"}], ["consult-preview-insertion", "preview insertion", {"inherit": "region"}], ["consult-preview-line", "preview line", {"inherit": "consult-preview-insertion"}], ["consult-preview-match", "preview match", {"inherit": "isearch"}], ["consult-separator", "separator", {"fg": "#ccc"}]]}, "embark": {"label": "embark", "preview": "generic", "faces": [["embark-collect-annotation", "collect annotation", {"inherit": "completions-annotations"}], ["embark-collect-candidate", "collect candidate", {"inherit": "default"}], ["embark-collect-group-separator", "collect group separator", {"strike": true, "inherit": "shadow"}], ["embark-collect-group-title", "collect group title", {"italic": true, "inherit": "shadow"}], ["embark-keybinding", "keybinding", {"inherit": "success"}], ["embark-keybinding-repeat", "keybinding repeat", {"inherit": "font-lock-builtin-face"}], ["embark-keymap", "keymap", {"italic": true}], ["embark-selected", "selected", {"inherit": "match"}], ["embark-target", "target", {"inherit": "highlight"}], ["embark-verbose-indicator-documentation", "verbose indicator documentation", {"inherit": "completions-annotations"}], ["embark-verbose-indicator-shadowed", "verbose indicator shadowed", {"inherit": "shadow"}], ["embark-verbose-indicator-title", "verbose indicator title", {"bold": true, "height": 1.1}]]}, "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", {"fg": "#ffffff", "bg": "#cd0000"}], ["emms-metaplaylist-mode-face", "metaplaylist mode", {"fg": "#cd0000"}], ["emms-playlist-selected-face", "playlist selected", {"fg": "#ffffff", "bg": "#0000cd"}], ["emms-playlist-track-face", "playlist track", {"fg": "#0000ff"}]]}, "flyspell-correct": {"label": "flyspell-correct", "preview": "generic", "faces": [["flyspell-correct-highlight-face", "highlight", {"inherit": "isearch"}]]}, "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", {"fg": "#cc9393", "bold": true}], ["hl-todo-flymake-type", "flymake type", {"inherit": "font-lock-keyword-face"}]]}, "json-mode": {"label": "json-mode", "preview": "generic", "faces": [["json-mode-object-name-face", "object name", {"inherit": "font-lock-variable-name-face"}]]}, "llama": {"label": "llama", "preview": "generic", "faces": [["llama-##-macro", "## macro", {"inherit": "font-lock-function-call-face"}], ["llama-deleted-argument", "deleted argument", {"box": {"style": "line", "width": 1, "color": "#ff0000"}}], ["llama-llama-macro", "llama macro", {"inherit": "font-lock-keyword-face"}], ["llama-mandatory-argument", "mandatory argument", {"inherit": "font-lock-variable-use-face"}], ["llama-optional-argument", "optional argument", {"inherit": "font-lock-type-face"}]]}, "lv": {"label": "lv", "preview": "generic", "faces": [["lv-separator", "separator", {"bg": "#cccccc"}]]}, "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", {"inherit": "bold"}], ["malyon-face-error", "face error", {"inherit": "error"}], ["malyon-face-italic", "face italic", {"inherit": "italic"}], ["malyon-face-plain", "face plain", {"inherit": "default"}], ["malyon-face-reverse", "face reverse", {"inherit": "default"}]]}, "marginalia": {"label": "marginalia", "preview": "generic", "faces": [["marginalia-archive", "archive", {"inherit": "warning"}], ["marginalia-char", "char", {"inherit": "marginalia-key"}], ["marginalia-date", "date", {"inherit": "marginalia-key"}], ["marginalia-documentation", "documentation", {"inherit": "completions-annotations"}], ["marginalia-file-name", "file name", {"inherit": "marginalia-documentation"}], ["marginalia-file-owner", "file owner", {"inherit": "font-lock-preprocessor-face"}], ["marginalia-file-priv-dir", "file priv dir", {"inherit": "font-lock-keyword-face"}], ["marginalia-file-priv-exec", "file priv exec", {"inherit": "font-lock-function-name-face"}], ["marginalia-file-priv-link", "file priv link", {"inherit": "font-lock-keyword-face"}], ["marginalia-file-priv-no", "file priv no", {"inherit": "shadow"}], ["marginalia-file-priv-other", "file priv other", {"inherit": "font-lock-constant-face"}], ["marginalia-file-priv-rare", "file priv rare", {"inherit": "font-lock-variable-name-face"}], ["marginalia-file-priv-read", "file priv read", {"inherit": "font-lock-type-face"}], ["marginalia-file-priv-write", "file priv write", {"inherit": "font-lock-builtin-face"}], ["marginalia-function", "function", {"inherit": "font-lock-function-name-face"}], ["marginalia-installed", "installed", {"inherit": "success"}], ["marginalia-key", "key", {"inherit": "font-lock-keyword-face"}], ["marginalia-lighter", "lighter", {"inherit": "marginalia-size"}], ["marginalia-list", "list", {"inherit": "font-lock-constant-face"}], ["marginalia-mode", "mode", {"inherit": "marginalia-key"}], ["marginalia-modified", "modified", {"inherit": "font-lock-negation-char-face"}], ["marginalia-null", "null", {"inherit": "font-lock-comment-face"}], ["marginalia-number", "number", {"inherit": "font-lock-constant-face"}], ["marginalia-off", "off", {"inherit": "error"}], ["marginalia-on", "on", {"inherit": "success"}], ["marginalia-size", "size", {"inherit": "marginalia-number"}], ["marginalia-string", "string", {"inherit": "font-lock-string-face"}], ["marginalia-symbol", "symbol", {"inherit": "font-lock-type-face"}], ["marginalia-true", "true", {"inherit": "font-lock-builtin-face"}], ["marginalia-type", "type", {"inherit": "marginalia-key"}], ["marginalia-value", "value", {"inherit": "marginalia-key"}], ["marginalia-version", "version", {"inherit": "marginalia-number"}]]}, "markdown-mode": {"label": "markdown-mode", "preview": "generic", "faces": [["markdown-blockquote-face", "markdown blockquote", {"inherit": "font-lock-doc-face"}], ["markdown-bold-face", "markdown bold", {"inherit": "bold"}], ["markdown-code-face", "markdown code", {"inherit": "fixed-pitch"}], ["markdown-comment-face", "markdown comment", {"inherit": "font-lock-comment-face"}], ["markdown-footnote-marker-face", "markdown footnote marker", {"inherit": "markdown-markup-face"}], ["markdown-footnote-text-face", "markdown footnote text", {"inherit": "font-lock-comment-face"}], ["markdown-gfm-checkbox-face", "markdown gfm checkbox", {"inherit": "font-lock-builtin-face"}], ["markdown-header-delimiter-face", "markdown header delimiter", {"inherit": "markdown-markup-face"}], ["markdown-header-face", "markdown header", {"bold": true, "inherit": ["font-lock-function-name-face"]}], ["markdown-header-face-1", "markdown header 1", {"inherit": "markdown-header-face"}], ["markdown-header-face-2", "markdown header 2", {"inherit": "markdown-header-face"}], ["markdown-header-face-3", "markdown header 3", {"inherit": "markdown-header-face"}], ["markdown-header-face-4", "markdown header 4", {"inherit": "markdown-header-face"}], ["markdown-header-face-5", "markdown header 5", {"inherit": "markdown-header-face"}], ["markdown-header-face-6", "markdown header 6", {"inherit": "markdown-header-face"}], ["markdown-header-rule-face", "markdown header rule", {"inherit": "markdown-markup-face"}], ["markdown-highlight-face", "markdown highlight", {"inherit": "highlight"}], ["markdown-highlighting-face", "markdown highlighting", {"fg": "#000000", "bg": "#ffff00"}], ["markdown-hr-face", "markdown hr", {"inherit": "markdown-markup-face"}], ["markdown-html-attr-name-face", "markdown html attr name", {"inherit": "font-lock-variable-name-face"}], ["markdown-html-attr-value-face", "markdown html attr value", {"inherit": "font-lock-string-face"}], ["markdown-html-entity-face", "markdown html entity", {"inherit": "font-lock-variable-name-face"}], ["markdown-html-tag-delimiter-face", "markdown html tag delimiter", {"inherit": "markdown-markup-face"}], ["markdown-html-tag-name-face", "markdown html tag name", {"inherit": "font-lock-type-face"}], ["markdown-inline-code-face", "markdown inline code", {"inherit": ["markdown-code-face", "font-lock-constant-face"]}], ["markdown-italic-face", "markdown italic", {"inherit": "italic"}], ["markdown-language-info-face", "markdown language info", {"inherit": "font-lock-string-face"}], ["markdown-language-keyword-face", "markdown language keyword", {"inherit": "font-lock-type-face"}], ["markdown-line-break-face", "markdown line break", {"underline": true, "inherit": "font-lock-constant-face"}], ["markdown-link-face", "markdown link", {"inherit": "link"}], ["markdown-link-title-face", "markdown link title", {"inherit": "font-lock-comment-face"}], ["markdown-list-face", "markdown list", {"inherit": "markdown-markup-face"}], ["markdown-markup-face", "markdown markup", {"inherit": "shadow"}], ["markdown-math-face", "markdown math", {"inherit": "font-lock-string-face"}], ["markdown-metadata-key-face", "markdown metadata key", {"inherit": "font-lock-variable-name-face"}], ["markdown-metadata-value-face", "markdown metadata value", {"inherit": "font-lock-string-face"}], ["markdown-missing-link-face", "markdown missing link", {"inherit": "font-lock-warning-face"}], ["markdown-plain-url-face", "markdown plain url", {"inherit": "markdown-link-face"}], ["markdown-pre-face", "markdown pre", {"inherit": ["markdown-code-face", "font-lock-constant-face"]}], ["markdown-reference-face", "markdown reference", {"inherit": "markdown-markup-face"}], ["markdown-strike-through-face", "markdown strike through", {"strike": true}], ["markdown-table-face", "markdown table", {"inherit": ["markdown-code-face"]}], ["markdown-url-face", "markdown url", {"inherit": "font-lock-string-face"}]]}, "nerd-icons": {"label": "nerd-icons", "preview": "generic", "faces": [["nerd-icons-blue", "blue", {"fg": "#6a9fb5"}], ["nerd-icons-blue-alt", "blue alt", {"fg": "#2188b6"}], ["nerd-icons-cyan", "cyan", {"fg": "#75b5aa"}], ["nerd-icons-cyan-alt", "cyan alt", {"fg": "#0595bd"}], ["nerd-icons-dblue", "dblue", {"fg": "#446674"}], ["nerd-icons-dcyan", "dcyan", {"fg": "#48746d"}], ["nerd-icons-dgreen", "dgreen", {"fg": "#6d8143"}], ["nerd-icons-dmaroon", "dmaroon", {"fg": "#72584b"}], ["nerd-icons-dorange", "dorange", {"fg": "#915b2d"}], ["nerd-icons-dpink", "dpink", {"fg": "#7e5d5f"}], ["nerd-icons-dpurple", "dpurple", {"fg": "#694863"}], ["nerd-icons-dred", "dred", {"fg": "#843031"}], ["nerd-icons-dsilver", "dsilver", {"fg": "#838484"}], ["nerd-icons-dyellow", "dyellow", {"fg": "#b48d56"}], ["nerd-icons-green", "green", {"fg": "#90a959"}], ["nerd-icons-lblue", "lblue", {"fg": "#677174"}], ["nerd-icons-lcyan", "lcyan", {"fg": "#2c7d6e"}], ["nerd-icons-lgreen", "lgreen", {"fg": "#3d6837"}], ["nerd-icons-lmaroon", "lmaroon", {"fg": "#ce7a4e"}], ["nerd-icons-lorange", "lorange", {"fg": "#ffa500"}], ["nerd-icons-lpink", "lpink", {"fg": "#ff505b"}], ["nerd-icons-lpurple", "lpurple", {"fg": "#e69dd6"}], ["nerd-icons-lred", "lred", {"fg": "#eb595a"}], ["nerd-icons-lsilver", "lsilver", {"fg": "#7f7869"}], ["nerd-icons-lyellow", "lyellow", {"fg": "#ff9300"}], ["nerd-icons-maroon", "maroon", {"fg": "#8f5536"}], ["nerd-icons-orange", "orange", {"fg": "#d4843e"}], ["nerd-icons-pink", "pink", {"fg": "#fc505b"}], ["nerd-icons-purple", "purple", {"fg": "#68295b"}], ["nerd-icons-purple-alt", "purple alt", {"fg": "#5d54e1"}], ["nerd-icons-red", "red", {"fg": "#ac4142"}], ["nerd-icons-red-alt", "red alt", {"fg": "#843031"}], ["nerd-icons-silver", "silver", {"fg": "#716e68"}], ["nerd-icons-yellow", "yellow", {"fg": "#ffcc0e"}]]}, "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", {"fg": "#223fbf", "bold": true}], ["orderless-match-face-1", "match 1", {"fg": "#8f0075", "bold": true}], ["orderless-match-face-2", "match 2", {"fg": "#145a00", "bold": true}], ["orderless-match-face-3", "match 3", {"fg": "#804000", "bold": true}]]}, "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", {"inherit": "org-warning"}], ["org-superstar-header-bullet", "header bullet", {}], ["org-superstar-item", "item", {"inherit": "default"}], ["org-superstar-leading", "leading", {"fg": "#bebebe", "inherit": "default"}]]}, "prescient": {"label": "prescient", "preview": "generic", "faces": [["prescient-primary-highlight", "primary highlight", {"bold": true}], ["prescient-secondary-highlight", "secondary highlight", {"underline": true, "inherit": "prescient-primary-highlight"}]]}, "rainbow-delimiters": {"label": "rainbow-delimiters", "preview": "generic", "faces": [["rainbow-delimiters-base-error-face", "base error", {"fg": "#88090b", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-base-face", "base", {"inherit": "unspecified"}], ["rainbow-delimiters-depth-1-face", "depth 1", {"fg": "#707183", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-2-face", "depth 2", {"fg": "#7388d6", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-3-face", "depth 3", {"fg": "#909183", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-4-face", "depth 4", {"fg": "#709870", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-5-face", "depth 5", {"fg": "#907373", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-6-face", "depth 6", {"fg": "#6276ba", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-7-face", "depth 7", {"fg": "#858580", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-8-face", "depth 8", {"fg": "#80a880", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-depth-9-face", "depth 9", {"fg": "#887070", "inherit": "rainbow-delimiters-base-face"}], ["rainbow-delimiters-mismatched-face", "mismatched", {"inherit": "rainbow-delimiters-unmatched-face"}], ["rainbow-delimiters-unmatched-face", "unmatched", {"inherit": "rainbow-delimiters-base-error-face"}]]}, "symbol-overlay": {"label": "symbol-overlay", "preview": "generic", "faces": [["symbol-overlay-default-face", "default", {"inherit": "highlight"}], ["symbol-overlay-face-1", "face 1", {"fg": "#000000", "bg": "#1e90ff"}], ["symbol-overlay-face-2", "face 2", {"fg": "#000000", "bg": "#ff69b4"}], ["symbol-overlay-face-3", "face 3", {"fg": "#000000", "bg": "#ffff00"}], ["symbol-overlay-face-4", "face 4", {"fg": "#000000", "bg": "#da70d6"}], ["symbol-overlay-face-5", "face 5", {"fg": "#000000", "bg": "#ff0000"}], ["symbol-overlay-face-6", "face 6", {"fg": "#000000", "bg": "#fa8072"}], ["symbol-overlay-face-7", "face 7", {"fg": "#000000", "bg": "#00ff7f"}], ["symbol-overlay-face-8", "face 8", {"fg": "#000000", "bg": "#40e0d0"}]]}, "tmr": {"label": "tmr", "preview": "generic", "faces": [["tmr-description", "description", {"inherit": "bold"}], ["tmr-duration", "duration", {}], ["tmr-end-time", "end time", {"inherit": "error"}], ["tmr-finished", "finished", {"inherit": "error"}], ["tmr-is-acknowledged", "is acknowledged", {"inherit": "success"}], ["tmr-must-be-acknowledged", "must be acknowledged", {"inherit": "warning"}], ["tmr-start-time", "start time", {"inherit": "success"}], ["tmr-tabulated-acknowledgement", "tabulated acknowledgement", {"inherit": "bold"}], ["tmr-tabulated-description", "tabulated description", {"inherit": "font-lock-doc-face"}], ["tmr-tabulated-end-time", "tabulated end time", {"fg": "#800040"}], ["tmr-tabulated-remaining-time", "tabulated remaining time", {"fg": "#603f00"}], ["tmr-tabulated-start-time", "tabulated start time", {"fg": "#004476"}]]}, "transient": {"label": "transient", "preview": "generic", "faces": [["transient-active-infix", "active infix", {"inherit": "highlight"}], ["transient-argument", "argument", {"bold": true, "inherit": "font-lock-string-face"}], ["transient-delimiter", "delimiter", {"inherit": "shadow"}], ["transient-disabled-suffix", "disabled suffix", {"fg": "#000000", "bg": "#ff0000", "bold": true}], ["transient-enabled-suffix", "enabled suffix", {"fg": "#000000", "bg": "#00ff00", "bold": true}], ["transient-heading", "heading", {"inherit": "font-lock-keyword-face"}], ["transient-higher-level", "higher level", {"box": {"style": "line", "width": 1, "color": "grey60"}}], ["transient-inactive-argument", "inactive argument", {"inherit": "shadow"}], ["transient-inactive-value", "inactive value", {"inherit": "shadow"}], ["transient-inapt-argument", "inapt argument", {"bold": true, "inherit": "shadow"}], ["transient-inapt-suffix", "inapt suffix", {"italic": true, "inherit": "shadow"}], ["transient-key", "key", {"inherit": "font-lock-builtin-face"}], ["transient-key-exit", "key exit", {"fg": "#aa2222", "inherit": "transient-key"}], ["transient-key-noop", "key noop", {"fg": "#cccccc", "inherit": "transient-key"}], ["transient-key-recurse", "key recurse", {"fg": "#2266ff", "inherit": "transient-key"}], ["transient-key-return", "key return", {"fg": "#aaaa11", "inherit": "transient-key"}], ["transient-key-stack", "key stack", {"fg": "#dd4488", "inherit": "transient-key"}], ["transient-key-stay", "key stay", {"fg": "#22aa22", "inherit": "transient-key"}], ["transient-mismatched-key", "mismatched key", {"box": {"style": "line", "width": 1, "color": "#ff00ff"}}], ["transient-nonstandard-key", "nonstandard key", {"box": {"style": "line", "width": 1, "color": "#00ffff"}}], ["transient-unreachable", "unreachable", {"inherit": "shadow"}], ["transient-unreachable-key", "unreachable key", {"inherit": ["shadow", "transient-key"]}], ["transient-value", "value", {"bold": true, "inherit": "font-lock-string-face"}]]}, "vertico": {"label": "vertico", "preview": "generic", "faces": [["vertico-current", "current", {"inherit": "highlight"}], ["vertico-group-separator", "group separator", {"strike": true, "inherit": "vertico-group-title"}], ["vertico-group-title", "group title", {"italic": true, "inherit": "shadow"}], ["vertico-multiline", "multiline", {"inherit": "shadow"}]]}, "web-mode": {"label": "web-mode", "preview": "generic", "faces": [["web-mode-annotation-face", "annotation", {"inherit": "web-mode-comment-face"}], ["web-mode-annotation-html-face", "annotation html", {"italic": true, "inherit": "web-mode-annotation-face"}], ["web-mode-annotation-tag-face", "annotation tag", {"underline": true, "inherit": "web-mode-annotation-face"}], ["web-mode-annotation-type-face", "annotation type", {"bold": true, "inherit": "web-mode-annotation-face"}], ["web-mode-annotation-value-face", "annotation value", {"italic": true, "inherit": "web-mode-annotation-face"}], ["web-mode-block-attr-name-face", "block attr name", {"fg": "#8fbc8f"}], ["web-mode-block-attr-value-face", "block attr value", {"fg": "#5f9ea0"}], ["web-mode-block-comment-face", "block comment", {"inherit": "web-mode-comment-face"}], ["web-mode-block-control-face", "block control", {"inherit": "font-lock-preprocessor-face"}], ["web-mode-block-delimiter-face", "block delimiter", {"inherit": "font-lock-preprocessor-face"}], ["web-mode-block-face", "block", {"bg": "#ffffe0"}], ["web-mode-block-string-face", "block string", {"inherit": "web-mode-string-face"}], ["web-mode-bold-face", "bold", {"bold": true}], ["web-mode-builtin-face", "builtin", {"inherit": "font-lock-builtin-face"}], ["web-mode-comment-face", "comment", {"inherit": "font-lock-comment-face"}], ["web-mode-comment-keyword-face", "comment keyword", {"bold": true}], ["web-mode-constant-face", "constant", {"inherit": "font-lock-constant-face"}], ["web-mode-css-at-rule-face", "css at rule", {"inherit": "font-lock-constant-face"}], ["web-mode-css-color-face", "css color", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-comment-face", "css comment", {"inherit": "web-mode-comment-face"}], ["web-mode-css-function-face", "css function", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-priority-face", "css priority", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-property-name-face", "css property name", {"inherit": "font-lock-variable-name-face"}], ["web-mode-css-pseudo-class-face", "css pseudo class", {"inherit": "font-lock-builtin-face"}], ["web-mode-css-selector-class-face", "css selector class", {"inherit": "font-lock-keyword-face"}], ["web-mode-css-selector-face", "css selector", {"inherit": "font-lock-keyword-face"}], ["web-mode-css-selector-tag-face", "css selector tag", {"inherit": "font-lock-keyword-face"}], ["web-mode-css-string-face", "css string", {"inherit": "web-mode-string-face"}], ["web-mode-css-variable-face", "css variable", {"italic": true, "inherit": "web-mode-variable-name-face"}], ["web-mode-current-column-highlight-face", "current column highlight", {"bg": "#3e3c36"}], ["web-mode-current-element-highlight-face", "current element highlight", {"fg": "#ffffff", "bg": "#000000"}], ["web-mode-doctype-face", "doctype", {"fg": "#bebebe"}], ["web-mode-error-face", "error", {"bg": "#ff0000"}], ["web-mode-filter-face", "filter", {"inherit": "font-lock-function-name-face"}], ["web-mode-folded-face", "folded", {"underline": true}], ["web-mode-function-call-face", "function call", {"inherit": "font-lock-function-name-face"}], ["web-mode-function-name-face", "function name", {"inherit": "font-lock-function-name-face"}], ["web-mode-html-attr-custom-face", "html attr custom", {"inherit": "web-mode-html-attr-name-face"}], ["web-mode-html-attr-engine-face", "html attr engine", {"inherit": "web-mode-block-delimiter-face"}], ["web-mode-html-attr-equal-face", "html attr equal", {"inherit": "web-mode-html-attr-name-face"}], ["web-mode-html-attr-name-face", "html attr name", {"fg": "#8b8989"}], ["web-mode-html-attr-value-face", "html attr value", {"inherit": "font-lock-string-face"}], ["web-mode-html-entity-face", "html entity", {"italic": true}], ["web-mode-html-tag-bracket-face", "html tag bracket", {"fg": "#242424"}], ["web-mode-html-tag-custom-face", "html tag custom", {"inherit": "web-mode-html-tag-face"}], ["web-mode-html-tag-face", "html tag", {"fg": "#8b8989"}], ["web-mode-html-tag-namespaced-face", "html tag namespaced", {"inherit": "web-mode-block-control-face"}], ["web-mode-html-tag-unclosed-face", "html tag unclosed", {"underline": true, "inherit": "web-mode-html-tag-face"}], ["web-mode-inlay-face", "inlay", {"bg": "#ffffe0"}], ["web-mode-interpolate-color1-face", "interpolate color1", {"inherit": "web-mode-string-face"}], ["web-mode-interpolate-color2-face", "interpolate color2", {"inherit": "web-mode-string-face"}], ["web-mode-interpolate-color3-face", "interpolate color3", {"inherit": "web-mode-string-face"}], ["web-mode-interpolate-color4-face", "interpolate color4", {"inherit": "web-mode-string-face"}], ["web-mode-italic-face", "italic", {"italic": true}], ["web-mode-javascript-comment-face", "javascript comment", {"inherit": "web-mode-comment-face"}], ["web-mode-javascript-string-face", "javascript string", {"inherit": "web-mode-string-face"}], ["web-mode-json-comment-face", "json comment", {"inherit": "web-mode-comment-face"}], ["web-mode-json-context-face", "json context", {"fg": "#cd69c9"}], ["web-mode-json-key-face", "json key", {"fg": "#dda0dd"}], ["web-mode-json-string-face", "json string", {"inherit": "web-mode-string-face"}], ["web-mode-jsx-depth-1-face", "jsx depth 1", {"bg": "#000053"}], ["web-mode-jsx-depth-2-face", "jsx depth 2", {"bg": "#001970"}], ["web-mode-jsx-depth-3-face", "jsx depth 3", {"bg": "#002984"}], ["web-mode-jsx-depth-4-face", "jsx depth 4", {"bg": "#49599a"}], ["web-mode-jsx-depth-5-face", "jsx depth 5", {"bg": "#9499b7"}], ["web-mode-keyword-face", "keyword", {"inherit": "font-lock-keyword-face"}], ["web-mode-param-name-face", "param name", {"fg": "#cdc9c9"}], ["web-mode-part-comment-face", "part comment", {"inherit": "web-mode-comment-face"}], ["web-mode-part-face", "part", {"inherit": "web-mode-block-face"}], ["web-mode-part-string-face", "part string", {"inherit": "web-mode-string-face"}], ["web-mode-preprocessor-face", "preprocessor", {"inherit": "font-lock-preprocessor-face"}], ["web-mode-script-face", "script", {"inherit": "web-mode-part-face"}], ["web-mode-sql-keyword-face", "sql keyword", {"bold": true, "italic": true}], ["web-mode-string-face", "string", {"inherit": "font-lock-string-face"}], ["web-mode-style-face", "style", {"inherit": "web-mode-part-face"}], ["web-mode-symbol-face", "symbol", {"fg": "#eeb422"}], ["web-mode-type-face", "type", {"inherit": "font-lock-type-face"}], ["web-mode-underline-face", "underline", {"underline": true}], ["web-mode-variable-name-face", "variable name", {"inherit": "font-lock-variable-name-face"}], ["web-mode-warning-face", "warning", {"inherit": "font-lock-warning-face"}], ["web-mode-whitespace-face", "whitespace", {"bg": "#68228b"}]]}, "yasnippet": {"label": "yasnippet", "preview": "generic", "faces": [["yas--field-debug-face", "yas field debug", {}], ["yas-field-highlight-face", "yas field highlight", {"inherit": "region"}]]}}; +const COLOR_NAMES=[["alice-blue", "#f0f8ff"], ["antique-white", "#faebd7"], ["aquamarine", "#7fffd4"], ["azure", "#f0ffff"], ["beige", "#f5f5dc"], ["bisque", "#ffe4c4"], ["black", "#000000"], ["blanched-almond", "#ffebcd"], ["blue", "#0000ff"], ["blue-violet", "#8a2be2"], ["brown", "#a52a2a"], ["burlywood", "#deb887"], ["cadet-blue", "#5f9ea0"], ["chartreuse", "#7fff00"], ["chocolate", "#d2691e"], ["coral", "#ff7f50"], ["cornflower-blue", "#6495ed"], ["cornsilk", "#fff8dc"], ["cyan", "#00ffff"], ["dark-blue", "#00008b"], ["dark-cyan", "#008b8b"], ["dark-goldenrod", "#b8860b"], ["dark-green", "#006400"], ["dark-grey", "#a9a9a9"], ["dark-khaki", "#bdb76b"], ["dark-magenta", "#8b008b"], ["dark-olive", "#556b2f"], ["dark-orange", "#ff8c00"], ["dark-orchid", "#9932cc"], ["dark-red", "#8b0000"], ["dark-salmon", "#e9967a"], ["dark-sea", "#8fbc8f"], ["dark-slate", "#2f4f4f"], ["dark-slate", "#483d8b"], ["dark-turquoise", "#00ced1"], ["dark-violet", "#9400d3"], ["deep-pink", "#ff1493"], ["deep-sky", "#00bfff"], ["dim-gray", "#696969"], ["dodger-blue", "#1e90ff"], ["firebrick", "#b22222"], ["floral-white", "#fffaf0"], ["forest-green", "#228b22"], ["gainsboro", "#dcdcdc"], ["ghost-white", "#f8f8ff"], ["gold", "#ffd700"], ["goldenrod", "#daa520"], ["gray", "#bebebe"], ["green", "#00ff00"], ["green-yellow", "#adff2f"], ["honeydew", "#f0fff0"], ["hot-pink", "#ff69b4"], ["indian-red", "#cd5c5c"], ["ivory", "#fffff0"], ["khaki", "#f0e68c"], ["lavender", "#e6e6fa"], ["lavender-blush", "#fff0f5"], ["lawn-green", "#7cfc00"], ["lemon-chiffon", "#fffacd"], ["light-blue", "#add8e6"], ["light-coral", "#f08080"], ["light-cyan", "#e0ffff"], ["light-goldenrod", "#eedd82"], ["light-goldenrod", "#fafad2"], ["light-green", "#90ee90"], ["light-grey", "#d3d3d3"], ["light-pink", "#ffb6c1"], ["light-salmon", "#ffa07a"], ["light-sea", "#20b2aa"], ["light-sky", "#87cefa"], ["light-slate", "#778899"], ["light-slate", "#8470ff"], ["light-steel", "#b0c4de"], ["light-yellow", "#ffffe0"], ["lime-green", "#32cd32"], ["linen", "#faf0e6"], ["magenta", "#ff00ff"], ["maroon", "#b03060"], ["medium-aquamarine", "#66cdaa"], ["medium-blue", "#0000cd"], ["medium-orchid", "#ba55d3"], ["medium-purple", "#9370db"], ["medium-sea", "#3cb371"], ["medium-slate", "#7b68ee"], ["medium-spring", "#00fa9a"], ["medium-turquoise", "#48d1cc"], ["medium-violet", "#c71585"], ["midnight-blue", "#191970"], ["mint-cream", "#f5fffa"], ["misty-rose", "#ffe4e1"], ["moccasin", "#ffe4b5"], ["navajo-white", "#ffdead"], ["navy", "#000080"], ["old-lace", "#fdf5e6"], ["olive-drab", "#6b8e23"], ["orange", "#ffa500"], ["orange-red", "#ff4500"], ["orchid", "#da70d6"], ["pale-goldenrod", "#eee8aa"], ["pale-green", "#98fb98"], ["pale-turquoise", "#afeeee"], ["pale-violet", "#db7093"], ["papaya-whip", "#ffefd5"], ["peach-puff", "#ffdab9"], ["peru", "#cd853f"], ["pink", "#ffc0cb"], ["plum", "#dda0dd"], ["powder-blue", "#b0e0e6"], ["purple", "#a020f0"], ["red", "#ff0000"], ["rosy-brown", "#bc8f8f"], ["royal-blue", "#4169e1"], ["saddle-brown", "#8b4513"], ["salmon", "#fa8072"], ["sandy-brown", "#f4a460"], ["sea-green", "#2e8b57"], ["seashell", "#fff5ee"], ["sienna", "#a0522d"], ["sky-blue", "#87ceeb"], ["slate-blue", "#6a5acd"], ["slate-gray", "#708090"], ["snow", "#fffafa"], ["spring-green", "#00ff7f"], ["steel-blue", "#4682b4"], ["tan", "#d2b48c"], ["thistle", "#d8bfd8"], ["tomato", "#ff6347"], ["turquoise", "#40e0d0"], ["violet", "#ee82ee"], ["violet-red", "#d02090"], ["wheat", "#f5deb3"], ["white", "#ffffff"], ["white-smoke", "#f5f5f5"], ["yellow", "#ffff00"], ["yellow-green", "#9acd32"]]; let MAP={"kw": "#d3d3d3", "bi": "#d3d3d3", "pp": "#d3d3d3", "fnd": "#0000ff", "fnc": "#0000ff", "dec": "", "ty": "#e5e5e5", "prop": "#e5e5e5", "con": "#d3d3d3", "num": "#000000", "esc": "#000000", "str": "#696969", "re": "#696969", "doc": "#696969", "cm": "#696969", "cmd": "#696969", "var": "#e5e5e5", "op": "#000000", "punc": "#000000", "p": "#000000", "bg": "#ffffff"}, PALETTE=[["#ffffff", "bg", "ground"], ["#000000", "fg", "ground"], ["#d3d3d3", "lightgray", "lightgray"], ["#0000ff", "blue1", "blue"], ["#e5e5e5", "gray90", "gray"], ["#696969", "dimgray", "dimgray"], ["#eedc82", "lightgoldenrod2", "lightgoldenrod"], ["#b4eeb4", "darkseagreen2", "darkseagreen"], ["#bfbfbf", "grey75", "grey"], ["#333333", "grey20", "grey"], ["#f2f2f2", "grey95", "grey"], ["#ff00ff", "magenta", "magenta"], ["#b0e2ff", "lightskyblue1", "lightskyblue"], ["#cd00cd", "magenta3", "magenta"], ["#afeeee", "paleturquoise", "paleturquoise"], ["#ffc1c1", "rosybrown1", "rosybrown"], ["#40e0d0", "turquoise", "turquoise"], ["#a020f0", "purple", "purple"], ["#3a5fcd", "royalblue3", "royalblue"], ["#ff0000", "red", "red"], ["#ff8c00", "dark-orange", "dark-orange"], ["#228b22", "forestgreen", "forestgreen"], ["#aaa", "color-22", "color-22"], ["#000", "color-23", "color-23"], ["#aa0", "color-24", "color-24"], ["#070", "color-25", "color-25"], ["#daa520", "goldenrod", "goldenrod"], ["#00bfff", "deep-sky-blue", "deep-sky-blue"], ["#ee00ee", "magenta2", "magenta"], ["#00ff00", "green", "green"], ["#ffff00", "yellow", "yellow"], ["#00ffff", "cyan", "cyan"], ["#6b6b6b", "color-32", "color-32"], ["#979797", "color-33", "color-33"], ["unspecified", "color-34", "color-34"], ["#223fbf", "color-35", "color-35"], ["#8f0075", "color-36", "color-36"], ["#145a00", "color-37", "color-37"], ["#804000", "color-38", "color-38"], ["#efcbcf", "color-39", "color-39"], ["#ffd700", "gold", "gold"], ["#8b0000", "darkred", "darkred"], ["#ffa500", "orange", "orange"], ["#f0e68c", "khaki", "khaki"], ["#8b008b", "dark-magenta", "dark-magenta"], ["#ff4500", "orange-red", "orange-red"], ["#deb887", "burlywood", "burlywood"], ["#b22222", "firebrick", "firebrick"], ["#cd8500", "orange3", "orange"], ["#00008b", "dark-blue", "dark-blue"], ["#9400d3", "dark-violet", "dark-violet"], ["#6a9fb5", "color-51", "color-51"], ["#2188b6", "color-52", "color-52"], ["#75b5aa", "color-53", "color-53"], ["#0595bd", "color-54", "color-54"], ["#446674", "color-55", "color-55"], ["#48746d", "color-56", "color-56"], ["#6d8143", "color-57", "color-57"], ["#72584b", "color-58", "color-58"], ["#915b2d", "color-59", "color-59"], ["#7e5d5f", "color-60", "color-60"], ["#694863", "color-61", "color-61"], ["#843031", "color-62", "color-62"], ["#838484", "color-63", "color-63"], ["#b48d56", "color-64", "color-64"], ["#90a959", "color-65", "color-65"], ["#677174", "color-66", "color-66"], ["#2c7d6e", "color-67", "color-67"], ["#3d6837", "color-68", "color-68"], ["#ce7a4e", "color-69", "color-69"], ["#ff505b", "color-70", "color-70"], ["#e69dd6", "color-71", "color-71"], ["#eb595a", "color-72", "color-72"], ["#7f7869", "color-73", "color-73"], ["#ff9300", "color-74", "color-74"], ["#8f5536", "color-75", "color-75"], ["#d4843e", "color-76", "color-76"], ["#fc505b", "color-77", "color-77"], ["#68295b", "color-78", "color-78"], ["#5d54e1", "color-79", "color-79"], ["#ac4142", "color-80", "color-80"], ["#716e68", "color-81", "color-81"], ["#ffcc0e", "color-82", "color-82"], ["#8b1a1a", "firebrick4", "firebrick"], ["#fff8dc", "cornsilk", "cornsilk"], ["#cd5c5c", "indian-red", "indian-red"], ["#f5deb3", "wheat", "wheat"], ["#add8e6", "light-blue", "light-blue"], ["#ccc", "color-88", "color-88"], ["#cd0000", "red3", "red"], ["#0000cd", "blue3", "blue"], ["#cc9393", "color-91", "color-91"], ["#cccccc", "grey80", "grey"], ["#bebebe", "gray", "gray"], ["#88090b", "color-94", "color-94"], ["#707183", "color-95", "color-95"], ["#7388d6", "color-96", "color-96"], ["#909183", "color-97", "color-97"], ["#709870", "color-98", "color-98"], ["#907373", "color-99", "color-99"], ["#6276ba", "color-100", "color-100"], ["#858580", "color-101", "color-101"], ["#80a880", "color-102", "color-102"], ["#887070", "color-103", "color-103"], ["#1e90ff", "dodger-blue", "dodger-blue"], ["#ff69b4", "hot-pink", "hot-pink"], ["#da70d6", "orchid", "orchid"], ["#fa8072", "salmon", "salmon"], ["#00ff7f", "spring-green", "spring-green"], ["#800040", "color-109", "color-109"], ["#603f00", "color-110", "color-110"], ["#004476", "color-111", "color-111"], ["grey60", "color-112", "color-112"], ["#aa2222", "color-113", "color-113"], ["#2266ff", "color-114", "color-114"], ["#aaaa11", "color-115", "color-115"], ["#dd4488", "color-116", "color-116"], ["#22aa22", "color-117", "color-117"], ["#8fbc8f", "color-118", "color-118"], ["#5f9ea0", "color-119", "color-119"], ["#ffffe0", "lightyellow1", "lightyellow"], ["#3e3c36", "color-121", "color-121"], ["#8b8989", "snow4", "snow"], ["#242424", "grey14", "grey"], ["#cd69c9", "orchid3", "orchid"], ["#dda0dd", "plum", "plum"], ["#000053", "color-126", "color-126"], ["#001970", "color-127", "color-127"], ["#002984", "color-128", "color-128"], ["#49599a", "color-129", "color-129"], ["#9499b7", "color-130", "color-130"], ["#cdc9c9", "snow3", "snow"], ["#eeb422", "goldenrod2", "goldenrod"], ["#68228b", "darkorchid4", "darkorchid"]], SYNTAX={"kw": {"fg": "#d3d3d3", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "box": null}, "bi": {"fg": "#d3d3d3", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "box": null}, "pp": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "font-lock-builtin-face"}, "fnd": {"fg": "#0000ff", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "fnc": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "font-lock-function-name-face"}, "dec": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "ty": {"fg": "#e5e5e5", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "box": null}, "prop": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "font-lock-variable-name-face"}, "con": {"fg": "#d3d3d3", "bg": null, "bold": true, "italic": false, "underline": true, "strike": false, "box": null}, "num": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "esc": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "font-lock-regexp-grouping-backslash"}, "str": {"fg": "#696969", "bg": null, "bold": false, "italic": true, "underline": false, "strike": false, "box": null}, "re": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "font-lock-string-face"}, "doc": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "font-lock-string-face"}, "cm": {"fg": "#696969", "bg": null, "bold": true, "italic": true, "underline": false, "strike": false, "box": null}, "cmd": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "font-lock-comment-face"}, "var": {"fg": "#e5e5e5", "bg": null, "bold": true, "italic": true, "underline": false, "strike": false, "box": null}, "op": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "punc": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "p": {"fg": "#000000", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "bg": {"fg": "#ffffff", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}}, UIMAP={"cursor": {"fg": null, "bg": "#000000", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "region": {"fg": null, "bg": "#eedc82", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "hl-line": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "highlight"}, "highlight": {"fg": null, "bg": "#b4eeb4", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "mode-line": {"fg": "#000000", "bg": "#bfbfbf", "bold": false, "italic": false, "underline": false, "strike": false, "box": {"style": "released", "width": 1, "color": null}}, "mode-line-inactive": {"fg": "#333333", "bg": "#e5e5e5", "bold": false, "italic": false, "underline": false, "strike": false, "box": {"style": "line", "width": 1, "color": "#bfbfbf"}, "inherit": "mode-line"}, "fringe": {"fg": null, "bg": "#f2f2f2", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "line-number": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": ["shadow", "default"]}, "line-number-current-line": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null, "inherit": "line-number"}, "minibuffer-prompt": {"fg": "#ff00ff", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "isearch": {"fg": "#b0e2ff", "bg": "#cd00cd", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "lazy-highlight": {"fg": null, "bg": "#afeeee", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "isearch-fail": {"fg": null, "bg": "#ffc1c1", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "show-paren-match": {"fg": null, "bg": "#40e0d0", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "show-paren-mismatch": {"fg": "#ffffff", "bg": "#a020f0", "bold": false, "italic": false, "underline": false, "strike": false, "box": null}, "link": {"fg": "#3a5fcd", "bg": null, "bold": false, "italic": false, "underline": true, "strike": false, "box": null}, "error": {"fg": "#ff0000", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "box": null}, "warning": {"fg": "#ff8c00", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "box": null}, "success": {"fg": "#228b22", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "box": null}, "vertical-border": {"fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "box": null}}; let LOCKED=new Set([]); // rows whose choice is decided (controls disabled, skipped by erase/reset batch actions) const DELTAE_MIN=0.02; // OKLab ΔE below this = colors too close to tell apart (perceptual-metrics spec) @@ -481,6 +517,51 @@ function mergePackagesInto(map,pkgs){if(!pkgs)return;for(const app in pkgs){if(! // against an inherit cycle (returns null rather than recursing forever). function effResolve(map,app,face,attr,seen){seen=seen||{};const f=map[app]&&map[app][face];if(!f||seen[face])return null;seen[face]=1;if(f[attr])return f[attr];if(f.inherit&&map[app][f.inherit])return effResolve(map,app,f.inherit,attr,seen);return null;} +// Emacs built-in inherit chains for the syntax categories theme studio exposes. +// An unset category foreground resolves the way the generated theme renders in +// Emacs: build-theme.el writes no override for an unset face, so Emacs falls back +// to the face's own :inherit -- comment-delimiter->comment, doc->string, +// property-name->variable-name, function-call->function-name -- not to the +// default foreground. +const SYNTAX_INHERIT={cmd:'cm',doc:'str',prop:'var',fnc:'fnd'}; + +// Effective foreground for a syntax category, following the Emacs inherit chain. +// SYNTAX maps category -> face object with an optional `fg`; DEFAULTFG is the +// theme's default foreground (the chain's floor). `dec` (decorator) is pinned to +// `ty`: Emacs has no decorator face and renders decorators with +// font-lock-type-face, so a dec color set in the studio would never reach Emacs. +function resolveSyntaxFg(cat,syntax,defaultFg){ + let k=(cat==='dec')?'ty':cat; + const seen={}; + while(k&&!seen[k]){ + seen[k]=1; + const fg=syntax[k]&&syntax[k].fg; + if(fg)return fg; + k=SYNTAX_INHERIT[k]; + } + return defaultFg; +} + +// Emacs built-in inherit chains for the ui faces whose parent is also a studio ui +// face, so an unset attribute previews the way Emacs renders it: mode-line-inactive +// inherits mode-line, line-number-current-line inherits line-number. +const UI_INHERIT={'mode-line-inactive':'mode-line','line-number-current-line':'line-number'}; + +// First set value of ATTR ('fg'/'bg') for ui FACE, walking UI_INHERIT; null when +// nothing up the chain is set. The caller applies its own floor (default fg, +// ground, or transparent), since that floor differs per attribute and face. +function resolveUiAttr(face,attr,uimap){ + let f=face; + const seen={}; + while(f&&!seen[f]){ + seen[f]=1; + const v=uimap[f]&&uimap[f][attr]; + if(v)return v; + f=UI_INHERIT[f]; + } + return null; +} + // Standard swatch-dropdown option list: a default entry, then the palette. When // cur is set but no longer in the palette, surface it as a "(gone)" entry first. function optList(cur,palette){const have=cur===''||palette.some(p=>p[0]===cur);return [['','— default —'],...(have?palette:[[cur,'(gone)'],...palette])];} @@ -541,9 +622,9 @@ function fgSetFor(face,state){ 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); + const add=(hex,label,name,isRole)=>{const k=hex.toLowerCase(),cur=byHex.get(k);if(!cur)byHex.set(k,{hex:k,label,name:name||label});else if(isRole&&cur.label==='default'){cur.label=label;cur.name=name||label;}}; + if(state&&state.defaultFg)add(state.defaultFg,'default','default',false); + for(const a of syn)add(a.hex,a.role||a.hex,a.name||a.role||a.hex,true); return {set:[...byHex.values()]}; } @@ -788,9 +869,425 @@ function ratingColor(r){return r>=7?'#5d9b86':r>=4.5?'#a9b2bb':'#cb6b4d';} // Pick black or white text for a background hex, by WCAG relative luminance. function textOn(h){const L=rl(h);return ((L+0.05)/0.05)>(1.05/(L+0.05))?'#000':'#fff';} +// Pure palette-generator planner and browser-side generator panel. +// Pure palette-generator planner. It depends on the shared palette-column model +// from app-core.js, but owns candidate hue selection, naming, contrast filtering, +// and conversion from preview columns to palette entries. + +function oklchOf(hex){return oklab2oklch(srgb2oklab(hex));} +function isPureEndpointHex(hex){const h=(hex||'').toLowerCase();return h==='#ffffff'||h==='#000000';} +function generatedExistingNames(palette){ + return new Set((palette||[]).map(p=>(p&&p[1]||'').toLowerCase()).filter(Boolean)); +} +const DEFAULT_COLOR_NAMES=[['black','#000000'],['white','#ffffff'],['red','#ff0000'],['green','#008000'],['blue','#0000ff'],['yellow','#ffff00'],['cyan','#00ffff'],['magenta','#ff00ff'],['gray','#808080']]; +function nearestColorName(hex,colorNames){ + const h=typeof hex==='string'?normHex(hex):null; + if(!h)return 'generated'; + let best=(colorNames&&colorNames[0]&&colorNames[0][0])||DEFAULT_COLOR_NAMES[0][0],bd=Infinity; + for(const [name,nhex] of (colorNames&&colorNames.length?colorNames:DEFAULT_COLOR_NAMES)){const d=deltaE(h,nhex);if(d<bd){bd=d;best=name;}} + return best; +} +function uniqueGeneratedName(base,used){ + let name=base||'generated',i=2; + if(!used.has(name.toLowerCase())){used.add(name.toLowerCase());return name;} + while(used.has((name+'-alt'+i).toLowerCase()))i++; + const out=name+'-alt'+i;used.add(out.toLowerCase());return out; +} +function hueOfHex(hex,fallback){ + const h=typeof hex==='string'?normHex(hex):null; + if(!h)return fallback; + const lch=oklab2oklch(srgb2oklab(h)); + return Number.isFinite(lch.H)?lch.H:fallback; +} +function generatorSourceHue(palette,ground,cfg){ + const fallback=((cfg&&typeof cfg.baseHue==='number'&&isFinite(cfg.baseHue))?cfg.baseHue:250)%360; + if(cfg&&cfg.sourceMode==='palette'){const hs=paletteBaseHues(palette,ground);return hs.length?hs[0]:(fallback+360)%360;} + if(cfg&&cfg.sourceMode==='selected'&&typeof cfg.selectedHex==='string'&&normHex(cfg.selectedHex))return hueOfHex(cfg.selectedHex,fallback); + const bg=hueOfHex(ground&&ground.bg,fallback),fg=hueOfHex(ground&&ground.fg,fallback); + if(Math.abs(bg-fallback)>0.001||Math.abs(fg-fallback)>0.001)return ((bg+fg)/2+360)%360; + return (fallback+360)%360; +} +function generatorHues(baseHue,scheme,count,rng){ + const n=Math.max(1,Math.min(12,Math.round(count||8))), b=((baseHue%360)+360)%360; + if(scheme==='random'){ + const rnd=typeof rng==='function'?rng:Math.random; + return Array.from({length:n},()=>Math.floor(rnd()*360)); + } + if(scheme==='analogous'){ + const spread=Math.min(120,Math.max(30,n*14)), start=b-spread/2; + return Array.from({length:n},(_,i)=>(start+(n===1?0:(spread*i)/(n-1))+360)%360); + } + if(scheme==='triadic'){ + const offsets=[0,120,240,30,150,270,60,180,300,90,210,330]; + return offsets.slice(0,n).map(o=>(b+o)%360); + } + if(scheme==='manual')return Array.from({length:n},(_,i)=>(b+(i*360)/n)%360); + return Array.from({length:n},(_,i)=>(b+(i*360)/n)%360); +} +function generatorChroma(mode){ + return mode==='subdued'?0.055:mode==='vivid'?0.13:0.085; +} +function generatorTarget(mode){return mode==='aaa'?7:mode==='none'?0:4.5;} +function jitterHue(h,rng,spread){ + const rnd=typeof rng==='function'?rng:Math.random; + return (h+(rnd()*2-1)*spread+360)%360; +} +function paletteBaseHues(palette,ground){ + const cols=columnsFromPalette(palette||[],ground||{}).columns; + return cols.map(c=>hueOfHex(c.base,0)).filter(Number.isFinite); +} +function paletteBaseHexes(palette,ground){ + return columnsFromPalette(palette||[],ground||{}).columns.map(c=>normHex(c.base)).filter(Boolean); +} +function sourceAnchorHues(palette,ground,cfg,baseHue){ + const mode=cfg&&cfg.sourceMode||'bg-fg'; + if(mode==='none')return []; + if(mode==='palette')return paletteBaseHues(palette,ground); + if(mode==='selected'&&typeof (cfg&&cfg.selectedHex)==='string'&&normHex(cfg.selectedHex))return [hueOfHex(cfg.selectedHex,baseHue)]; + const anchors=[]; + if(ground&&ground.bg)anchors.push(hueOfHex(ground.bg,baseHue)); + if(ground&&ground.fg)anchors.push(hueOfHex(ground.fg,baseHue)); + return anchors.filter(Number.isFinite); +} +function sourceAnchorHexes(palette,ground,cfg){ + const mode=cfg&&cfg.sourceMode||'bg-fg'; + if(mode==='none')return []; + if(mode==='palette')return paletteBaseHexes(palette,ground); + if(mode==='selected'&&typeof (cfg&&cfg.selectedHex)==='string'&&normHex(cfg.selectedHex))return [normHex(cfg.selectedHex)]; + return [ground&&ground.bg,ground&&ground.fg].map(h=>typeof h==='string'?normHex(h):null).filter(Boolean); +} +function bridgeHues(anchors,count,rng){ + if(anchors.length<2)return generatorHues(anchors[0]||250,'random',count,rng); + const sorted=[...anchors].sort((a,b)=>a-b),pairs=[]; + for(let i=0;i<sorted.length;i++){ + const a=sorted[i],b=sorted[(i+1)%sorted.length]+(i===sorted.length-1?360:0); + pairs.push(((a+b)/2)%360); + } + return Array.from({length:count},(_,i)=>jitterHue(pairs[i%pairs.length],rng,10)); +} +function repeatOffsets(base,offsets,count){ + return Array.from({length:count},(_,i)=>(base+offsets[i%offsets.length]+360)%360); +} +function harmonyHues(intent,src,baseHue,count,rng){ + const b=src&&src.length?src[0]:baseHue, n=Math.max(1,Math.min(12,Math.round(count||8))); + if(intent==='complementary')return repeatOffsets(b,[180],n); + if(intent==='analogous')return repeatOffsets(b,[-30,30,-60,60,0],n); + if(intent==='split-complementary')return repeatOffsets(b,[150,210,0],n); + if(intent==='triadic')return repeatOffsets(b,[0,120,240],n); + if(intent==='tetradic')return repeatOffsets(b,[0,60,180,240],n); + if(intent==='square')return repeatOffsets(b,[0,90,180,270],n); + if(intent==='monochromatic')return Array.from({length:n},()=>jitterHue(b,rng,3)); + if(intent==='rainbow')return Array.from({length:n},(_,i)=>(b+(i*360)/n)%360); + return null; +} +function intentHues(intent,anchors,baseHue,count,rng){ + const n=Math.max(1,Math.min(12,Math.round(count||8))), src=anchors&&anchors.length?anchors:[baseHue]; + const harmony=harmonyHues(intent,src,baseHue,n,rng); + if(harmony)return harmony; + if(intent==='near-palette'||intent==='near-selected')return Array.from({length:n},(_,i)=>jitterHue(src[i%src.length],rng,18)); + if(intent==='fill-gaps')return generatorHues(src[0]||baseHue,'random',n,rng); + if(intent==='complements')return Array.from({length:n},(_,i)=>jitterHue((src[i%src.length]+180)%360,rng,18)); + if(intent==='bridges')return bridgeHues(src,n,rng); + return generatorHues(baseHue,'random',n,rng); +} +function vibeHueBias(hues,vibe,rng){ + const rnd=typeof rng==='function'?rng:Math.random; + const pick=bands=>bands[Math.floor(rnd()*bands.length)]; + if(vibe==='warm')return hues.map(()=>jitterHue(pick([12,28,44,58]),rng,14)); + if(vibe==='cool')return hues.map(()=>jitterHue(pick([170,195,220,250,278]),rng,16)); + if(vibe==='earthy')return hues.map(h=>jitterHue([28,42,58,82,112].reduce((a,b)=>Math.abs(b-h)<Math.abs(a-h)?b:a,42),rng,12)); + return hues; +} +function candidateLightnesses(bgHex,vibe){ + const bgL=typeof bgHex==='string'&&normHex(bgHex)?oklchOf(bgHex).L:0; + if(vibe==='pastel')return bgL>0.55?[0.74,0.68,0.80,0.62,0.86,0.56,0.50]:[0.82,0.88,0.76,0.92,0.70,0.64]; + if(vibe==='deep'||vibe==='jewel')return bgL>0.55?[0.30,0.24,0.36,0.18,0.42,0.48]:[0.56,0.62,0.50,0.68,0.44,0.74]; + return bgL>0.55 + ? [0.34,0.28,0.40,0.22,0.46,0.16,0.52,0.10,0.58] + : [0.70,0.76,0.64,0.82,0.58,0.88,0.52,0.94,0.46]; +} +function randomChroma(rng){ + const rnd=typeof rng==='function'?rng:Math.random; + return 0.10+rnd()*0.09; +} +function vibeChroma(vibe,rng){ + const rnd=typeof rng==='function'?rng:Math.random; + if(vibe==='muted')return 0.045+rnd()*0.035; + if(vibe==='pastel')return 0.035+rnd()*0.045; + if(vibe==='deep')return 0.085+rnd()*0.055; + if(vibe==='jewel')return 0.12+rnd()*0.075; + if(vibe==='earthy')return 0.055+rnd()*0.04; + if(vibe==='warm'||vibe==='cool')return 0.08+rnd()*0.06; + if(vibe==='neon')return 0.18+rnd()*0.09; + if(vibe==='strange')return 0.145+rnd()*0.095; + if(vibe==='balanced')return 0.075+rnd()*0.045; + return 0.12+rnd()*0.07; +} +function accentCandidateForHue(hue,ground,cfg){ + const C=cfg&&cfg.vibe?vibeChroma(cfg.vibe,cfg.rng):(cfg&&cfg.scheme==='random'?randomChroma(cfg.rng):generatorChroma(cfg&&cfg.chromaMode)), target=generatorTarget(cfg&&cfg.contrastMode), bg=ground&&ground.bg; + let best=null; + for(const L of candidateLightnesses(bg,cfg&&cfg.vibe)){ + const c=oklch2hex(L,C,hue), r=bg?contrast(c.hex,bg):Infinity; + const item={hex:c.hex,L,C,hue,contrast:r,clamped:c.clamped}; + if(!best||r>best.contrast)best=item; + if(r>=target&&!isPureEndpointHex(c.hex))return item; + } + return best&&best.contrast>=target&&!isPureEndpointHex(best.hex)?best:null; +} +function candidateForHueLightness(hue,L,C,ground,cfg){ + const target=generatorTarget(cfg&&cfg.contrastMode),bg=ground&&ground.bg,c=oklch2hex(L,C,hue),r=bg?contrast(c.hex,bg):Infinity; + return r>=target&&!isPureEndpointHex(c.hex)?{hex:c.hex,L,C,hue,contrast:r,clamped:c.clamped}:null; +} +function minDistanceToSet(hex,set){ + return set.length?Math.min(...set.map(h=>deltaE(hex,h))):Infinity; +} +function hueDistance(a,b){return Math.abs((((a-b+540)%360)-180));} +function anchorHueSet(hexes){ + return hexes.map(hex=>oklchOf(hex)).filter(lch=>lch.C>0.025&&Number.isFinite(lch.H)).map(lch=>lch.H); +} +function minHueDistance(hue,hues){ + return hues.length?Math.min(...hues.map(h=>hueDistance(hue,h))):180; +} +function perceptualGapCandidates(palette,ground,cfg,sourceMode,baseHue,count,scheme,intent,hueAware){ + const anchors=sourceAnchorHexes(palette,ground,Object.assign({},cfg,{sourceMode})); + if(anchors.length<2){ + return intentHues('fill-gaps',sourceAnchorHues(palette,ground,Object.assign({},cfg,{sourceMode}),baseHue),baseHue,count,cfg.rng) + .map(hue=>accentCandidateForHue(hue,ground,Object.assign({},cfg,{scheme,intent}))).filter(Boolean); + } + const C=cfg&&cfg.vibe?vibeChroma(cfg.vibe,cfg.rng):(scheme==='random'?randomChroma(cfg.rng):generatorChroma(cfg&&cfg.chromaMode)); + const hueStep=10,hueOffset=(typeof cfg.rng==='function'?cfg.rng():Math.random())*hueStep; + const pool=[],seen=new Set(); + for(let hue=hueOffset;hue<360;hue+=hueStep){ + for(const L of candidateLightnesses(ground&&ground.bg,cfg&&cfg.vibe)){ + const cand=candidateForHueLightness(hue,L,C,ground,cfg); + if(!cand)continue; + const key=cand.hex.toLowerCase(); + if(seen.has(key))continue; + seen.add(key);pool.push(cand); + } + } + const picked=[],occupied=[...anchors]; + const occupiedHues=anchorHueSet(anchors); + while(picked.length<count&&pool.length){ + let bestI=-1,bestScore=-1,bestContrast=-1; + for(let i=0;i<pool.length;i++){ + const cand=pool[i],perceptual=minDistanceToSet(cand.hex,occupied); + const hueBonus=hueAware?0.10*(minHueDistance(cand.hue,occupiedHues)/180):0; + const score=perceptual+hueBonus; + if(score>bestScore+1e-9||(Math.abs(score-bestScore)<1e-9&&cand.contrast>bestContrast)){ + bestI=i;bestScore=score;bestContrast=cand.contrast; + } + } + const cand=pool.splice(bestI,1)[0]; + picked.push(cand);occupied.push(cand.hex);occupiedHues.push(cand.hue); + } + return picked; +} +function generatedMembers(baseHex,baseName,spanCount,columnId){ + const hex=typeof baseHex==='string'?normHex(baseHex):null; + return hex?[{hex,name:baseName,offset:0,clamped:false,columnId}]:[]; +} +function planPaletteGenerator(palette,ground,config){ + const cfg=config||{}; + const requestedSource=cfg.sourceMode||'bg-fg', resolvedSource=requestedSource==='selected' + ? (typeof cfg.selectedHex==='string'&&normHex(cfg.selectedHex)?'selected':'bg-fg') + : requestedSource; + const sourceMode=['selected','palette','none','bg-fg'].includes(resolvedSource)?resolvedSource:'bg-fg'; + const scheme=cfg.scheme||'random', intent=cfg.intent||(cfg.scheme&&cfg.scheme!=='random'?'scheme':'random'), count=Math.max(1,Math.min(12,Math.round(cfg.accentCount??5))); + const spanCount=Math.max(0,Math.min(8,Math.round(cfg.spanCount??2))); + const used=generatedExistingNames(palette), baseHue=generatorSourceHue(palette,ground,Object.assign({},cfg,{sourceMode})); + const anchors=sourceAnchorHues(palette,ground,Object.assign({},cfg,{sourceMode}),baseHue); + const columns=[], rejected=[]; + const candidates=(intent==='fill-gaps'||intent==='fill-hue-gaps') + ? perceptualGapCandidates(palette,ground,cfg,sourceMode,baseHue,count,scheme,intent,intent==='fill-hue-gaps').map(cand=>({cand,hue:cand&&cand.hue})) + : vibeHueBias(intent&&intent!=='manual'&&intent!=='scheme'?intentHues(intent,anchors,baseHue,count,cfg.rng):generatorHues(baseHue,scheme,count,cfg.rng),cfg.vibe,cfg.rng) + .map(hue=>({hue,cand:accentCandidateForHue(hue,ground,Object.assign({},cfg,{scheme,intent}))})); + for(const {cand,hue} of candidates){ + if(!cand){rejected.push({hue,reason:'contrast'});continue;} + const name=uniqueGeneratedName(nearestColorName(cand.hex,cfg.colorNames),used), columnId=name; + const members=generatedMembers(cand.hex,name,spanCount,columnId); + columns.push({name,columnId,baseHex:cand.hex,L:cand.L,C:cand.C,hue:cand.hue,contrast:cand.contrast,clamped:cand.clamped,members}); + } + const contrasts=columns.map(c=>c.contrast).filter(Number.isFinite); + return { + sourceMode, + scheme, + intent, + vibe: cfg.vibe||null, + baseHue, + accentCount:count, + spanCount, + columns, + rejected, + summary:{ + generated:columns.length, + rejected:rejected.length, + clamped:columns.reduce((n,c)=>n+(c.clamped?1:0)+c.members.filter(m=>m.clamped).length,0), + minContrast:contrasts.length?Math.min(...contrasts):null, + }, + }; +} +function entriesForGeneratedColumn(column){ + if(!column||!Array.isArray(column.members))return []; + const columnId=column.columnId||column.name||'generated'; + return column.members.map(m=>[m.hex,m.name,columnId]); +} +// Browser-side palette-generator panel. The pure planner lives in +// palette-generator-core.js; this file only gathers controls, renders previews, +// and commits selected generated colors into normal palette entries. +let GEN_PROPOSAL=null, GEN_SELECTION=null; +const GENERATOR_CONTROLS={ + genintent:{ + labelTitle:'what kind of candidate colors to look for', + options:[ + ['random','random','Pure exploration: reroll unrelated candidate base colors.'], + ['near-palette','near palette','Generate candidates near the current palette base colors.'], + ['fill-gaps','fill gaps','Find missing perceptual colors using OKLab distance.'], + ['fill-hue-gaps','fill hue gaps','Find missing perceptual colors while rewarding underrepresented hue regions.'], + ['complements','complements','Generate colors opposite palette or selected anchors.'], + ['bridges','bridges','Generate colors between existing palette anchors.'], + ['near-selected','near selected','Generate candidates near the current selector color.'], + ['complementary','complementary','Use the hue opposite the anchor.'], + ['analogous','analogous','Use neighboring hues around the anchor.'], + ['split-complementary','split complementary','Use hues on both sides of the anchor complement.'], + ['triadic','triadic','Use three hues spaced 120 degrees apart.'], + ['tetradic','tetradic','Use two complementary hue pairs.'], + ['square','square','Use four hues spaced 90 degrees apart.'], + ['monochromatic','monochromatic','Stay near one hue and vary color character.'], + ['rainbow','rainbow','Spread candidates evenly around the full hue wheel.'], + ], + }, + genvibe:{ + labelTitle:'the character of generated candidate colors', + options:[ + ['bold','bold','Higher chroma, assertive candidate colors.'], + ['balanced','balanced','Moderate chroma candidate colors.'], + ['muted','muted','Lower chroma, quieter candidate colors.'], + ['pastel','pastel','Light, low-chroma candidate colors.'], + ['deep','deep','Lower-lightness, richer candidate colors.'], + ['jewel','jewel','Saturated, rich candidate colors.'], + ['earthy','earthy','Warmer, reduced-chroma earth-tone candidates.'], + ['neon','neon','Very high-chroma candidate colors.'], + ['strange','strange','More unusual, high-variance candidate colors.'], + ['warm','warm','Bias candidates toward red, orange, and yellow.'], + ['cool','cool','Bias candidates toward green, cyan, blue, and violet.'], + ], + }, + gensource:{ + labelTitle:'where starting hues come from', + options:[ + ['palette','palette','Use current base color columns as anchors; span tiles are ignored.'], + ['none','none','Use no anchors; useful for pure random exploration.'], + ['bg-fg','bg/fg','Use the current background and foreground as anchors.'], + ['selected','selected','Use the current selector tile as the anchor.'], + ], + }, + gencontrast:{ + labelTitle:'minimum contrast against the current bg', + options:[ + ['aa','AA','Require WCAG AA contrast against the current background.'], + ['aaa','AAA','Require WCAG AAA contrast against the current background.'], + ['none','none','Do not reject candidates by WCAG contrast.'], + ], + }, +}; +function generatorOptionTitle(id,value){ + const ctl=GENERATOR_CONTROLS[id]; + const row=ctl&&ctl.options.find(o=>o[0]===value); + return row?row[2]:''; +} +function populateGeneratorSelects(){ + Object.entries(GENERATOR_CONTROLS).forEach(([id,ctl])=>{ + const el=document.getElementById(id);if(!el)return; + const cur=el.value||el.dataset.default||ctl.options[0][0]; + el.innerHTML=''; + ctl.options.forEach(([value,label])=>{const o=document.createElement('option');o.value=value;o.textContent=label;el.appendChild(o);}); + el.value=ctl.options.some(o=>o[0]===cur)?cur:ctl.options[0][0]; + const label=el.closest('label');if(label)label.title=ctl.labelTitle; + }); +} +function genConfig(){ + const intent=document.getElementById('genintent'),vibe=document.getElementById('genvibe'), + source=document.getElementById('gensource'), + accents=document.getElementById('genaccents'),contrastSel=document.getElementById('gencontrast'); + return { + intent:intent?intent.value:'random', + vibe:vibe?vibe.value:'bold', + sourceMode:source?source.value:'palette', + scheme:'random', + baseHue:250, + accentCount:accents?parseInt(accents.value,10):5, + spanCount:0, + contrastMode:contrastSel?contrastSel.value:'aa', + selectedHex:curHex(), + colorNames:COLOR_NAMES, + }; +} +function syncGeneratorControls(){syncGeneratorSelectTitles();} +function syncGeneratorSelectTitles(){ + Object.keys(GENERATOR_CONTROLS).forEach(id=>{const el=document.getElementById(id);if(el)el.title=generatorOptionTitle(id,el.value);}); +} +function setGenMessage(msg,err){const m=document.getElementById('genmsg');if(!m)return;m.textContent=msg||'';m.style.color=err?'#cb6b4d':'#8a9496';} +function renderGeneratorPreview(){ + const host=document.getElementById('genpreview');if(!host)return;host.innerHTML=''; + if(!GEN_PROPOSAL){setGenMessage('',false);return;} + GEN_PROPOSAL.columns.forEach((col,ci)=>{ + const strip=document.createElement('div');strip.className='gencol'; + const head=document.createElement('div');head.className='genhead'; + head.innerHTML=`<span title="${esc(col.name)}">${esc(col.name)}</span><button class="genappend" data-col="${ci}" title="append this generated column to the palette">+</button>`; + head.querySelector('.genappend').onclick=()=>appendGeneratedColumn(ci); + strip.appendChild(head); + col.members.forEach((m,mi)=>{ + const chip=document.createElement('div'),tc=textOn(m.hex); + chip.className='genchip'+(GEN_SELECTION&&GEN_SELECTION.hex===m.hex&&GEN_SELECTION.name===m.name?' sel':''); + chip.dataset.col=String(ci);chip.dataset.member=String(mi);chip.dataset.hex=m.hex;chip.dataset.name=m.name; + chip.style.background=m.hex;chip.style.color=tc;chip.title=m.name+' '+m.hex+(m.clamped?' (sRGB clamped)':''); + chip.innerHTML=`<div class="gn">${esc(m.name.replace(/-/g,' '))}</div><div class="gh">${m.hex}</div>`; + chip.onclick=()=>selectGeneratedTile(ci,mi); + strip.appendChild(chip); + }); + host.appendChild(strip); + }); + const s=GEN_PROPOSAL.summary; + setGenMessage(s.generated+' column(s) previewed'+(s.rejected?(', '+s.rejected+' rejected'):'')+(s.minContrast?(', min '+s.minContrast.toFixed(1)+':1'):''),false); +} +function resetGeneratorPreviewState(){ + GEN_PROPOSAL=null;GEN_SELECTION=null; + renderGeneratorPreview(); +} +function previewGenerator(){ + const cfg=genConfig(); + resetGeneratorPreviewState(); + GEN_PROPOSAL=planPaletteGenerator(PALETTE,{bg:MAP['bg'],fg:MAP['p']},cfg); + renderGeneratorPreview(); +} +function clearGeneratorPreview(){resetGeneratorPreviewState();} +function selectGeneratedTile(ci,mi){ + if(!GEN_PROPOSAL||!GEN_PROPOSAL.columns[ci])return; + const m=GEN_PROPOSAL.columns[ci].members[mi];if(!m)return; + selectedIdx=null;GEN_SELECTION={column:ci,member:mi,hex:m.hex,name:m.name}; + setHex(m.hex);document.getElementById('newname').value=m.name; + renderPalette();renderGeneratorPreview(); + notify('loaded generated "'+m.name+'" into the selector - add it to commit',false); +} +function appendGeneratedColumn(ci){ + if(!GEN_PROPOSAL||!GEN_PROPOSAL.columns[ci])return; + const colName=GEN_PROPOSAL.columns[ci].name, entries=entriesForGeneratedColumn(GEN_PROPOSAL.columns[ci]); + const existing=new Set(PALETTE.map(p=>(p[1]||'').toLowerCase())); + if(entries.some(e=>existing.has(e[1].toLowerCase()))){notify('generated names already exist - preview again for fresh names',true);return;} + PALETTE.push(...entries);GEN_SELECTION=null;selectedIdx=null; + refreshPaletteState();previewGenerator(); + notify('added generated column "'+colName+'"',false); +} +function initGeneratorControls(){ + populateGeneratorSelects(); + Object.keys(GENERATOR_CONTROLS).forEach(id=>{const el=document.getElementById(id);if(el)el.onchange=syncGeneratorControls;}); + syncGeneratorControls(); +} // The contrast-cell readout shared by every table: a WCAG ratio colored by its -// AA/AAA rating, with the rating word. Callers compute r for their own fg/bg. -function crHtml(r){return `<span style="color:${ratingColor(r)}">${r.toFixed(1)} ${rating(r)}</span>`;} +// table verdict. Callers compute r for their own fg/bg. +function verdictFor(r,target=4.5){return r>=target?'PASS':'FAIL';} +function crHtml(r,target=4.5){const v=verdictFor(r,target);return `<span style="color:${ratingColor(r)}">${r.toFixed(1)} ${v}</span>`;} // Effective fg/bg with the standard fallback: an unset foreground reads as the // default fg (MAP['p']), an unset background as the ground (MAP['bg']). All three // tiers resolve their raw value through these before measuring or rendering. @@ -821,21 +1318,25 @@ function mkColorDropdown(options,cur,onPick,opts={}){ left.textContent='‹';right.textContent='›';left.title='move to next darker color in this column';right.title='move to next lighter color in this column'; const t=document.createElement('div');t.className='cdd'+(opts.compact?' compact':'');t.tabIndex=0; const nameOf=h=>{const o=options.find(p=>p[0]===h);return o?o[1]:(h||'none');}; + const displayHex=h=>h||(opts.defaultHex||''); + const displayName=h=>h?nameOf(h):(opts.defaultName||nameOf(h)); function step(dir){if(wrap.dataset.locked==='1')return;const next=spanNeighborHex(cur,PALETTE,{bg:MAP['bg'],fg:MAP['p']},dir);if(!next)return;cur=next;paint();onPick(next);} function paintStepButtons(){ const locked=wrap.dataset.locked==='1'; left.disabled=locked||!spanNeighborHex(cur,PALETTE,{bg:MAP['bg'],fg:MAP['p']},-1); right.disabled=locked||!spanNeighborHex(cur,PALETTE,{bg:MAP['bg'],fg:MAP['p']},1); } - function paint(){const nm=nameOf(cur),ttl=cur?(nm+' '+cur):nm;t.style.background=cur||'#161412';t.style.color=cur?textOn(cur):'#b4b1a2';t.dataset.val=cur||'';t.title=ttl;t.classList.toggle('is-default',!cur); - t.innerHTML=opts.compact?`<span class="cddsw" style="background:${cur||'transparent'}"></span>`:`<span class="cddsw" style="background:${cur||'transparent'}"></span>${esc(nm)}`;paintStepButtons();} + function paint(){const shown=displayHex(cur),nm=displayName(cur),ttl=cur?(nm+' '+cur):(nm+(shown?' -> '+shown:''));t.style.background=shown||'#161412';t.style.color=shown?textOn(shown):'#b4b1a2';t.dataset.val=cur||'';t.title=ttl;t.classList.toggle('is-default',!cur); + t.innerHTML=opts.compact?`<span class="cddsw" style="background:${shown||'transparent'}"></span>`:`<span class="cddsw" style="background:${shown||'transparent'}"></span>${esc(nm)}`;paintStepButtons();} paint(); left.onclick=e=>{e.stopPropagation();step(-1);}; right.onclick=e=>{e.stopPropagation();step(1);}; t.onclick=(e)=>{e.stopPropagation();if(wrap.dataset.locked==='1')return;if(_ddPop){closeColorDropdown();return;} const pop=document.createElement('div');pop.className='cddpop'; for(const [hex,name] of options){const row=document.createElement('div');row.className='cddrow'+(hex===cur?' sel':''); - row.innerHTML=`<span class="cddsw" style="background:${hex||'transparent'}"></span><span class="cddnm">${esc(name)}</span><span class="cddhx">${hex||''}</span>`; + const shown=displayHex(hex),nm=hex?name:(opts.defaultName||name); + row.style.background=hex?'':shown;row.style.color=shown?textOn(shown):''; + row.innerHTML=`<span class="cddsw" style="background:${shown||'transparent'}"></span><span class="cddnm">${esc(nm)}</span><span class="cddhx">${hex||shown||''}</span>`; row.onclick=(ev)=>{ev.stopPropagation();cur=hex;paint();closeColorDropdown();onPick(hex);}; pop.appendChild(row);} document.body.appendChild(pop);const r=t.getBoundingClientRect(); @@ -942,8 +1443,8 @@ function buildTable(){ function rowBg(){return syntaxFace(kind).bg||MAP['bg'];} function styleEx(){const s=syntaxFace(kind);exTd.style.color=rowFg();exTd.style.background=rowBg();exTd.style.fontWeight=s.bold?'bold':'normal';exTd.style.fontStyle=s.italic?'italic':'normal';exTd.style.textDecoration=(s.underline?'underline ':'')+(s.strike?'line-through':'')||'none';exTd.style.boxShadow=boxCss(s.box,rowBg());} function styleCr(){const r=contrast(rowFg(),rowBg());crTd.innerHTML=crHtml(r);} - const dd=mkColorDropdown(list,cur,(hex)=>{const s=syntaxFace(kind);s.fg=hex||null;syncSyntaxCache(kind);styleEx();styleCr();renderCode();if(kind==='bg'||kind==='p'){applyGround();buildTable();buildPkgTable();buildPkgPreview();}repaintCovered();},{compact:true}); - const bgd=mkColorDropdown(ddList(sf.bg||''),sf.bg||'',hex=>{const s=syntaxFace(kind);s.bg=hex||null;styleEx();styleCr();renderCode();repaintCovered();},{compact:true}); + const dd=mkColorDropdown(list,cur,(hex)=>{const s=syntaxFace(kind);s.fg=hex||null;syncSyntaxCache(kind);styleEx();styleCr();renderCode();if(kind==='bg'||kind==='p'){applyGround();buildTable();buildPkgTable();buildPkgPreview();}repaintCovered();},{compact:true,defaultHex:rowFg()}); + const bgd=mkColorDropdown(ddList(sf.bg||''),sf.bg||'',hex=>{const s=syntaxFace(kind);s.bg=hex||null;styleEx();styleCr();renderCode();repaintCovered();},{compact:true,defaultHex:rowBg()}); styleEx();styleCr(); const stTd=document.createElement('td'); const stBtns=mkStyleButtons(at=>syntaxFace(kind)[at],at=>{const s=syntaxFace(kind);s[at]=!s[at];styleEx();renderCode();}); @@ -1202,7 +1703,7 @@ function setColumnCount(baseHex,n){ } 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 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 selectColor(i){selectedIdx=i;GEN_SELECTION=null;const [hex,name]=PALETTE[i];setHex(hex);document.getElementById('newname').value=name;renderPalette();renderGeneratorPreview();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;} const i=selectedIdx,oldHex=PALETTE[i][0],oldRole=groundRoleOfEntry(PALETTE[i],{bg:MAP['bg'],fg:MAP['p']}); @@ -1321,8 +1822,9 @@ 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,columnIdOf([h,name])]);const healed=healGone(name,h);document.getElementById('newname').value='';selectedIdx=null;closePicker(); + PALETTE.push([h,name,columnIdOf([h,name])]);const healed=healGone(name,h);document.getElementById('newname').value='';selectedIdx=null;GEN_SELECTION=null;closePicker(); refreshPaletteState({code:healed,ground:healed,pkgPreview:healed}); + renderGeneratorPreview(); notify(healed?('added "'+name+'" and reconnected its face references'):('added "'+name+'"'),false);} function themeName(){return (document.getElementById('themename').value||'theme').trim()||'theme';} function fileSlug(){return slugify(themeName());} @@ -1368,7 +1870,7 @@ function boxCss(b,bg){if(!b||!b.style)return '';const w=b.width||1; 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'}`;} -function syntaxStyle(k){const s=syntaxFace(k),fg=(k==='bg'?MAP['p']:effFg(s.fg)),bg=s.bg||null,dec=(s.underline?'underline ':'')+(s.strike?'line-through':''), +function syntaxStyle(k){const s=syntaxFace(k),fg=(k==='bg'?MAP['p']:resolveSyntaxFg(k,SYNTAX,MAP['p'])),bg=s.bg||null,dec=(s.underline?'underline ':'')+(s.strike?'line-through':''), bx=boxCss(s.box,bg||MAP['bg']); return `color:${fg};${bg?'background:'+bg+';':''}font-weight:${s.bold?'bold':'normal'};font-style:${s.italic?'italic':'normal'};text-decoration:${dec.trim()||'none'}${bx?';box-shadow:'+bx:''}`;} // The per-row box control: none / line / raised / pressed plus optional line @@ -1376,7 +1878,7 @@ function syntaxStyle(k){const s=syntaxFace(k),fg=(k==='bg'?MAP['p']:effFg(s.fg)) function mkBoxControl(get,set,opts={}){const wrap=document.createElement('div');wrap.className='boxctl'; const s=document.createElement('select');s.className='chip';s.style.cssText='width:84px;font:10pt monospace'; [['','no box'],['line','line'],['released','raised'],['pressed','pressed']].forEach(([v,l])=>{const o=document.createElement('option');o.value=v;o.textContent=l;s.appendChild(o);}); - const dd=mkColorDropdown(ddList((get()&&get().color)||''),(get()&&get().color)||'',h=>{const cur=get();if(!cur)return;set(Object.assign({},cur,{color:h||null}));},{compact:!!opts.compact}); + const dd=mkColorDropdown(ddList((get()&&get().color)||''),(get()&&get().color)||'',h=>{const cur=get();if(!cur)return;set(Object.assign({},cur,{color:h||null}));},{compact:!!opts.compact,defaultHex:opts.defaultHex}); function paint(){const cur=get();s.value=cur&&cur.style?cur.style:'';dd.setValue(cur&&cur.color?cur.color:''); const off=!cur||!cur.style||wrap.dataset.locked==='1';dd.dataset.locked=off?'1':'';dd.classList.toggle('locked',off);if(dd.syncLocked)dd.syncLocked();} s.onchange=()=>{const cur=get();set(s.value?{style:s.value,width:cur&&cur.width||1,color:cur&&cur.color||null}:null);paint();}; @@ -1446,7 +1948,7 @@ function buildMockFrame(){ let buf=''; lines.forEach((L,i)=>{ const isc=L.cur; - const nFg=isc?(lnc.fg||fg):(ln.fg||fg), nBg=isc?(lnc.bg||'transparent'):(ln.bg||'transparent'); + const nFg=isc?(resolveUiAttr('line-number-current-line','fg',UIMAP)||fg):(ln.fg||fg), nBg=isc?(resolveUiAttr('line-number-current-line','bg',UIMAP)||'transparent'):(ln.bg||'transparent'); const rowFace=isc?hl:null,rowStyle=rowFace?uiCss(rowFace,rowFace.fg||'inherit',rowFace.bg||'transparent'):'background:transparent'; let cd; if(isc)cd=withCursor(L.t); @@ -1461,9 +1963,9 @@ function buildMockFrame(){ const nFace=isc?'line-number-current-line':'line-number'; buf+=`<div class="ln" ${rowFace?'data-face="hl-line" ':''}style="${rowStyle}"><span class="fr" data-face="fringe" style="${uiCss(frng,frng.fg||fg,frng.bg||bg)};text-align:center;font-size:10px;overflow:hidden" title="fringe">${L.cont?'↪':''}</span><span class="num" data-face="${nFace}" style="${uiCss(isc?lnc:ln,nFg,nBg)}">${i+1}</span><span class="cd">${cd||' '}</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>`; + let html=`<div class="mbuf" style="background:${bg}"><div class="mbuftext">${buf}</div><div class="vborder" data-face="vertical-border" title="vertical-border" style="background:${vb.fg||vb.bg||'#2f343a'}"></div></div>`; html+=`<div class="bar" data-face="mode-line" style="${uiCss(ml,ml.fg||bg,ml.bg||fg)}"> init.el (Emacs Lisp) L5 git:main </div>`; - html+=`<div class="bar" data-face="mode-line-inactive" style="${uiCss(mli,mli.fg||fg,mli.bg||bg)}"> *Messages* (Fundamental) </div>`; + html+=`<div class="bar" data-face="mode-line-inactive" style="${uiCss(mli,resolveUiAttr('mode-line-inactive','fg',UIMAP)||fg,resolveUiAttr('mode-line-inactive','bg',UIMAP)||bg)}"> *Messages* (Fundamental)</div>`; html+=`<div class="echo" style="color:${fg}"><span data-face="minibuffer-prompt" style="${uiCss(mb,mb.fg||fg,mb.bg||null)}">I-search:</span> count <span data-face="isearch-fail" style="${uiCss(isf,isf.fg||fg,isf.bg||'transparent')}">zzz [no match]</span></div>`; html+=`<div class="echo"><span data-face="link" style="${uiCss(lnk,lnk.fg||fg,lnk.bg||null)}">https://gnu.org</span> <span data-face="error" style="${uiCss(err,err.fg||fg,err.bg||null)}">error</span> <span data-face="warning" style="${uiCss(wrn,wrn.fg||fg,wrn.bg||null)}">warning</span> <span data-face="success" style="${uiCss(suc,suc.fg||fg,suc.bg||null)}">ok</span></div>`; fr.innerHTML=html;fr.style.background=bg;fr.style.color=fg; @@ -1473,7 +1975,7 @@ function buildMockFrame(){ // native <select> rendered swatch colors unreliably on Linux Chrome, so it is // gone. '' (the default entry) maps back to null in the stored model. function uiSelect(face,attr){const cur=UIMAP[face][attr]||''; - return mkColorDropdown(ddList(cur),cur,h=>{UIMAP[face][attr]=h||null;paintUI(face);buildMockFrame();},{compact:true});} + return mkColorDropdown(ddList(cur),cur,h=>{UIMAP[face][attr]=h||null;paintUI(face);buildMockFrame();},{compact:true,defaultHex:attr==='fg'?effFg(null):effBg(null)});} const BASE_INHERITS=['fixed-pitch','variable-pitch','default','link','bold','italic','shadow']; function uiFaceBlank(){return {fg:null,bg:null,bold:false,italic:false,underline:false,strike:false};} function seedFace(d){return normalizePkgFace({fg:pname(d.fg),bg:pname(d.bg),bold:d.bold,italic:d.italic,underline:d.underline,strike:d.strike,inherit:d.inherit,height:d.height,box:d.box},'default');} @@ -1490,8 +1992,8 @@ function buildPkgTable(){ if(flt&&!(face.toLowerCase().includes(flt)||label.toLowerCase().includes(flt)))continue; const f=PKGMAP[app][face],tr=document.createElement('tr');tr.dataset.face=face; const c0=document.createElement('td');c0.className='cat';c0.textContent=label;c0.title=face;c0.style.cursor='pointer';c0.onclick=()=>flashPkgPreview(face); - const fgd=mkColorDropdown(ddList(f.fg||''),f.fg||'',h=>{f.fg=h||null;f.source='user';pkgChanged();},{compact:true}), - bgd=mkColorDropdown(ddList(f.bg||''),f.bg||'',h=>{f.bg=h||null;f.source='user';pkgChanged();},{compact:true}); + const fgd=mkColorDropdown(ddList(f.fg||''),f.fg||'',h=>{f.fg=h||null;f.source='user';pkgChanged();},{compact:true,defaultHex:effFg(pkgEffFg(app,face))}), + bgd=mkColorDropdown(ddList(f.bg||''),f.bg||'',h=>{f.bg=h||null;f.source='user';pkgChanged();},{compact:true,defaultHex:effBg(pkgEffBg(app,face))}); const cf=document.createElement('td');cf.appendChild(fgd); const cb=document.createElement('td');cb.appendChild(bgd); const cw=document.createElement('td'); @@ -1626,17 +2128,31 @@ function renderGhostelPreview(){const a='ghostel',L=[]; L.push(os(a,'ghostel-default','default terminal output, 256-color text and a blinking ')+os(a,'ghostel-fake-cursor','cursor')+'.'); return `<div style="padding:12px 16px;font:12pt/1.7 monospace;white-space:pre">${L.join('\n')}</div>`;} function renderDashboardPreview(){const a='dashboard',L=[]; - L.push(os(a,'dashboard-text-banner',' ___ _ __ ___ __ _ ___ ___')); - L.push(os(a,'dashboard-banner-logo-title',' Welcome back, Craig')); + L.push(os(a,'dashboard-text-banner',' [ dashboard banner image ]')); + L.push(os(a,'dashboard-banner-logo-title','Emacs: The Editor That Saves Your Soul')); + L.push(''); + L.push(os(a,'dashboard-navigator',' Code Files Terminal Agenda')); + L.push(os(a,'dashboard-navigator',' Feeds Books Flashcards Music')); + L.push(os(a,'dashboard-navigator',' Email IRC Telegram')); + L.push(os(a,'dashboard-navigator',' Slack Linear')); + L.push(''); + L.push(''); + L.push(os(a,'dashboard-heading','Projects:')); + L.push(' ~/'); + L.push(' ~/.emacs.d/'); + L.push(' ~/projects/work/'); + L.push(' ~/org/roam/'); + L.push(' ~/projects/home/'); L.push(''); - L.push(os(a,'dashboard-heading','Recent Files')); - L.push(' '+os(a,'dashboard-items-face','init.el')); - L.push(' '+os(a,'dashboard-items-face','notes.org')); L.push(os(a,'dashboard-heading','Bookmarks')); - L.push(' '+os(a,'dashboard-no-items-face','-- no items --')); + L.push(' Cesar Aira, The Little Buddhist Monk & the Proof'); + L.push(' Edward Abbey, The Fool’s Progress: An Honest Novel'); + L.push(' Agatha Christie, The A.B.C. Murders'); L.push(''); - L.push(os(a,'dashboard-navigator','[ Projects ] [ Recent ] [ Agenda ]')); - L.push(os(a,'dashboard-footer-icon-face','*')+' '+os(a,'dashboard-footer-face','Happy hacking, Craig!')); + L.push(os(a,'dashboard-heading','Recent Files:')); + L.push(' theme-theme.el'); + L.push(' todo.org'); + L.push(' theme-studio-palette-generator-spec.org'); return `<div style="padding:12px 16px;font:12pt/1.7 monospace;white-space:pre">${L.join('\n')}</div>`;} function renderMu4ePreview(){const a='mu4e',L=[]; L.push(os(a,'mu4e-title-face','mu4e')+' '+os(a,'mu4e-context-face','[Personal]')+' '+os(a,'mu4e-ok-face','online')+' '+os(a,'mu4e-warning-face','2 retry')+' '+os(a,'mu4e-modeline-face','12/340')); @@ -1829,25 +2345,47 @@ 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(syntaxFace(c[0]).fg)})); + const syntaxAssignments=CATS.filter(c=>c[0]!=='bg'&&c[0]!=='p').map(c=>({role:c[0],name:c[1],hex:effFg(syntaxFace(c[0]).fg)})); 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){ +function coveredContrastReport(face){ + if(uf(face).fg)return null; 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>`; + if(r.reason==='empty'||!r.set.length)return {empty:true}; + const bg=effBg(uf(face).bg); + const rows=r.set.map(f=>{ + const ratio=contrast(f.hex,bg); + return {label:f.label,name:f.name||f.label,hex:f.hex,ratio,verdict:verdictFor(ratio,WORST_TARGET)}; + }).sort((a,b)=>a.ratio-b.ratio); + return {bg,rows,worst:rows[0],failures:rows.filter(x=>x.ratio<WORST_TARGET)}; +} +function failureTitle(report){ + if(!report||!report.failures||!report.failures.length)return ''; + const lines=['failing covered-text contrasts against '+report.bg+':']; + report.failures.forEach(f=>lines.push(`${f.ratio.toFixed(1)} FAIL ${f.label} (${f.name}) ${f.hex}`)); + return lines.join('\n'); +} +// The worst-case contrast cell for a covered face: the floor over its foreground +// set against its effective background. Returns null for an out-of-scope face so +// the caller keeps the single-pair readout. +function worstCellHtml(face){ + const report=coveredContrastReport(face); + if(report===null)return null; + if(report.empty)return '<span title="this overlay has no syntax foreground set yet">no fg set</span>'; + return `<span style="color:${ratingColor(report.worst.ratio)}" title="${esc(failureTitle(report)||'all covered text clears '+WORST_TARGET.toFixed(1))}">${report.worst.ratio.toFixed(1)} ${report.worst.verdict}</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);}}} + const report=coveredContrastReport(face); + pv.querySelectorAll('.crerr').forEach(e=>e.remove()); + pv.title=''; + if(report&&report.failures&&report.failures.length){ + const badge=document.createElement('span');badge.className='crerr';badge.textContent=report.worst.ratio.toFixed(1)+' FAIL';badge.title=failureTitle(report);pv.title=badge.title;pv.appendChild(badge); + } + const cr=document.getElementById('uicr-'+face);if(cr){cr.title='';if(report!==null){if(report.empty){cr.title='this overlay has no syntax foreground set yet';cr.innerHTML='<span title="this overlay has no syntax foreground set yet">no fg set</span>';}else{const title=failureTitle(report)||'all covered text clears '+WORST_TARGET.toFixed(1);cr.title=title;cr.innerHTML=`<span style="color:${ratingColor(report.worst.ratio)}" title="${esc(title)}">${report.worst.ratio.toFixed(1)} ${report.worst.verdict}</span>`;}}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){ @@ -1879,6 +2417,7 @@ function srtTable(tbId,col){tableSort[tbId]={col,asc:!(tableSort[tbId]&&tableSor function applyTableSort(tbId){const s=tableSort[tbId];if(!s)return;const tb=document.getElementById(tbId);if(!tb)return;const dir=s.asc?1:-1;const r=[...tb.rows];r.sort((a,b)=>{const x=cellVal(a.cells[s.col]),y=cellVal(b.cells[s.col]);return ((typeof x==='number'&&typeof y==='number')?x-y:(x<y?-1:x>y?1:0))*dir;});r.forEach(x=>tb.appendChild(x));} function initApp(){ buildLangSel();buildAppSel();renderPalette();rebuildColorTables();renderCode();applyGround(); + initGeneratorControls(); updateTitle();initPicker();buildPkgPreview();syncMockHeight();syncPkgHeight(); } initApp(); @@ -1910,6 +2449,7 @@ if(location.hash==='#selftest')pkgSelftest(); // the shared mkLockCell. (2) reset/erase batch actions update editable rows but // leave locked rows (syntax bare-kind, ui:, pkg: keys) untouched. if(location.hash==='#locktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}}; + const cssRgb=h=>{const [r,g,b]=hex2rgb(h);return 'rgb('+r+', '+g+', '+b+')';}; LOCKED.clear();buildTable(); {const k=CATS.map(c=>c[0]).filter(k=>k!=='bg'&&k!=='p')[0]; const tr=document.querySelector('#legbody tr[data-kind="'+k+'"]'),step=tr.querySelector('.cstep'),dd=tr.querySelector('.cdd'),lb=tr.querySelector('.lockbtn'); @@ -1926,6 +2466,15 @@ if(location.hash==='#locktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c const tr=document.querySelector('#uibody tr[data-face="region"]'),fg=tr.cells[2].querySelector('.cdd'),bg=tr.cells[3].querySelector('.cdd'); A(fg.classList.contains('is-default'),'compact default color button has default outline class'); A(!bg.classList.contains('is-default'),'compact assigned color button does not have default outline class');} + {setSyntaxFg('kw','');buildTable(); + const dd=document.querySelector('#legbody tr[data-kind="kw"] .cdd'); + A(dd&&dd.style.backgroundColor===cssRgb(MAP['p']),'syntax default fg swatch shows inherited fg color');} + {UIMAP['fringe'].bg=null;buildUITable(); + const dd=document.querySelector('#uibody tr[data-face="fringe"]').cells[3].querySelector('.cdd'); + A(dd&&dd.style.backgroundColor===cssRgb(MAP['bg']),'ui default bg swatch shows inherited ground color');} + {const app=curApp(),face=APPS[app].faces[0][0];PKGMAP[app][face].fg=null;PKGMAP[app][face].inherit=null;buildPkgTable(); + const dd=document.querySelector('#pkgbody tr[data-face="'+face+'"]').cells[2].querySelector('.cdd'); + A(dd&&dd.style.backgroundColor===cssRgb(MAP['p']),'package default fg swatch shows inherited/default fg color');} {PALETTE=[['#000000','bg','ground'],['#ffffff','fg','ground'],['#222222','gray-dark','gray'],['#888888','gray-mid','gray'],['#dddddd','gray-light','gray']];setSyntaxFg('bg','#000000');setSyntaxFg('p','#ffffff');setSyntaxFg('kw','#888888');LOCKED.clear();buildTable(); const tr=document.querySelector('#legbody tr[data-kind="kw"]'),btns=tr.querySelectorAll('.cstepbtn');btns[1].click(); A(MAP['kw']==='#dddddd'&&tr.querySelector('.cdd').dataset.val==='#dddddd','syntax right arrow steps to lighter color');btns[0].click(); @@ -2019,6 +2568,12 @@ if(location.hash==='#mocktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c A([...document.querySelectorAll('#mockframe .fr')].some(e=>e.textContent.trim()),'fringe-indicator-present'); const mlbar=Q('[data-face="mode-line"]'); A(mlbar&&/box-shadow/.test(mlbar.getAttribute('style')||''),'mode-line-box'); + const textBox=Q('.mbuftext'),border=Q('[data-face="vertical-border"]'),mock=document.getElementById('mockframe'); + if(textBox&&border&&mock){ + const tr=textBox.getBoundingClientRect(),br=border.getBoundingClientRect(); + const ch=parseFloat(getComputedStyle(textBox).fontSize)*0.65; + A(br.left-tr.right<=ch*4.8,'vertical-border-near-text'); + }else A(false,'vertical-border-layout-elements-present'); UIMAP['line-number-current-line'].bold=true;buildMockFrame(); const curNum=Q('[data-face="line-number-current-line"]'); A(curNum&&/font-weight:\s*bold/.test(curNum.getAttribute('style')||''),'line-number-honors-weight'); @@ -2036,6 +2591,62 @@ if(location.hash==='#mocktest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c A(pkgBtn()&&pkgBtn().classList.contains('on')&&PKGMAP[app][face].bold===true,'pkg style button visual state turns on after rebuild'); document.title='MOCKTEST '+(ok?'PASS':'FAIL'); const d=document.createElement('div');d.id='mocktest';d.textContent='MOCKTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);} +// Palette-generator gate (open with #generatortest): previewing is non-mutating, +// clicking a generated tile loads the existing selector, adding creates a normal +// singleton base column, and appending a preview column commits all span members +// under one stable column id. +if(location.hash==='#generatortest'){let ok=true;const notes=[];const A=(c,n)=>{if(!c){ok=false;notes.push(n);}}; + const before=JSON.stringify(PALETTE); + A(document.getElementById('genaccents').value==='5','default accent count is 5'); + A(document.getElementById('gensource').value==='palette','default generator source is palette'); + A(document.querySelector('label:has(#genintent)').title==='what kind of candidate colors to look for','intent label hover explains the control'); + A(document.getElementById('genintent').title.includes('Pure exploration'),'intent select hover explains random'); + A([...document.getElementById('genintent').options].some(o=>o.value==='fill-hue-gaps'),'fill hue gaps intent is available'); + document.getElementById('genintent').value='fill-hue-gaps';syncGeneratorControls(); + A(document.getElementById('genintent').title.includes('underrepresented hue regions'),'fill hue gaps hover explains hue bonus'); + document.getElementById('genintent').value='near-palette';syncGeneratorControls(); + A(document.getElementById('genintent').title.includes('current palette base colors'),'intent select hover updates for selected intent'); + A(!document.getElementById('genscheme'),'legacy scheme control is removed from the generator UI'); + A(!document.getElementById('genhue'),'legacy base hue control is removed from the generator UI'); + document.getElementById('genaccents').value='3'; + document.getElementById('genintent').value='fill-gaps'; + document.getElementById('genvibe').value='warm'; + document.getElementById('gensource').value='palette'; + previewGenerator(); + A(GEN_PROPOSAL&&GEN_PROPOSAL.intent==='fill-gaps'&&GEN_PROPOSAL.vibe==='warm'&&GEN_PROPOSAL.sourceMode==='palette','intent/vibe/source feed the generator proposal'); + A(JSON.stringify(PALETTE)===before,'preview does not mutate palette'); + A(document.querySelectorAll('#genpreview .gencol').length===3,'renders requested preview columns'); + A(parseInt(getComputedStyle(document.querySelector('#genpreview .genchip')).width,10)===128,'generated candidate tile width matches palette tiles'); + A(parseInt(getComputedStyle(document.querySelector('#genpreview .genchip')).height,10)===58,'generated candidate tile height matches palette tiles'); + A([...document.querySelectorAll('#genpreview .gencol')].every(c=>c.querySelectorAll('.genchip').length===1),'preview columns show only one base tile each'); + const tile=document.querySelector('#genpreview .genchip[data-col="0"][data-member="0"]'); + A(!!tile,'base generated tile exists'); + const tileHex=tile&&tile.dataset.hex,tileName=tile&&tile.dataset.name; + if(tile)tile.click(); + A(document.getElementById('newhexstr').value===tileHex,'generated tile loads selector hex'); + A(document.getElementById('newname').value===tileName,'generated tile loads selector name'); + document.getElementById('genaccents').value='2'; + previewGenerator(); + A(document.querySelectorAll('#genpreview .gencol').length===2,'preview again replaces old preview columns'); + A(!document.querySelector('#genpreview .genchip.sel'),'preview again clears generated tile selection'); + document.getElementById('genaccents').value='3'; + previewGenerator(); + addColor(); + A(PALETTE.some(p=>p[0]===tileHex&&p[1]===tileName),'add color commits selected generated tile'); + const afterSingle=PALETTE.length; + previewGenerator(); + const append=document.querySelector('#genpreview .genappend[data-col="0"]'); + A(!!append,'append generated column button exists'); + if(append)append.click(); + A(PALETTE.length===afterSingle+1,'append commits one generated base color'); + const added=PALETTE.slice(-1); + A(new Set(added.map(p=>p[2])).size===1,'appended generated span has one stable column id'); + A(!/[+-]\d+$/.test(added[0][1]),'appended generated color is a base name, not a signed span neighbor'); + GEN_PROPOSAL={summary:{generated:1,rejected:0,minContrast:null},columns:[{name:'medium-aquamarine',members:[{name:'medium-aquamarine',hex:'#66cdaa',offset:0,columnId:'medium-aquamarine'}]}]}; + renderGeneratorPreview(); + A(document.querySelector('#genpreview .genchip .gn').textContent==='medium aquamarine','generated tile names display spaces instead of hyphens'); + document.title='GENERATORTEST '+(ok?'PASS':'FAIL'); + const d=document.createElement('div');d.id='generatortest';d.textContent='GENERATORTEST '+(ok?'PASS':'FAIL')+(notes.length?' | '+notes.join(' ; '):'');document.body.appendChild(d);} if(location.hash.startsWith('#pick')){openPicker();const m=location.hash.slice(5);if(m){const b=document.querySelector('.pmode button[data-m="'+m+'"]');if(b)b.click();}} if(location.hash==='#cursortest'){document.getElementById('newhexstr').value='#67809c';openPicker();const sc=document.getElementById('svcur'),hc=document.getElementById('huecur');const L=parseFloat(sc.style.left||'0'),T=parseFloat(sc.style.top||'0'),H=parseFloat(hc.style.top||'0');const ok=L>1&&T>1&&H>1;document.title='CURSORTEST '+(ok?'PASS':'FAIL');const d=document.createElement('div');d.id='cursortest';d.textContent='CURSORTEST '+(ok?'PASS':'FAIL')+' left='+sc.style.left+' top='+sc.style.top+' hue='+hc.style.top;document.body.appendChild(d);} if(location.hash.startsWith('#app')){const ap=location.hash.slice(4),s=document.getElementById('appsel');if(s&&ap){s.value=ap;pkgChanged();}} @@ -2104,15 +2715,27 @@ if(location.hash==='#contrasttest'){let ok=true;const notes=[];const A=(c,n)=>{i 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'); + A(cell&&/^\d+\.\d (PASS|FAIL)$/.test(cell.textContent.trim()),'region shows compact worst-case readout: '+(cell&&cell.textContent)); + A(cell&&!cell.textContent.includes('#67809c'),'compact readout omits limiting fg details: '+(cell&&cell.textContent)); + A(cell&&cell.title.includes('kw (keyword) #67809c'),'hover names failing keyword blue: '+(cell&&cell.title)); + const badge=document.querySelector('#uiprev-region .crerr'); + A(badge&&badge.textContent.trim()===cell.textContent.trim(),'region preview shows failing contrast badge: '+(badge&&badge.textContent)); + A(badge&&badge.title.includes('kw (keyword) #67809c'),'preview badge hover carries failures: '+(badge&&badge.title)); + const firstFail=badge&&badge.title.split('\n')[1]; + A(firstFail&&firstFail.includes('kw (keyword) #67809c'),'failures are sorted from worst first: '+firstFail); 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'); + UIMAP['region']={fg:'#f0fef0',bg:'#202830',bold:false,italic:false,underline:false,strike:false}; + buildUITable(); + const pairCell=document.getElementById('uicr-region'),pairWant=contrast('#f0fef0','#202830'); + A(pairCell&&Math.abs(parseFloat(pairCell.textContent)-pairWant)<0.06,'region with explicit fg rates its own fg/bg pair: got '+(pairCell&&pairCell.textContent.trim())+' want '+pairWant.toFixed(1)); + A(!document.querySelector('#uiprev-region .crerr'),'region with explicit fg does not show covered-text error badge'); + A(pairCell&&!pairCell.title.includes('#67809c'),'region explicit fg hover omits underlying syntax failures: '+(pairCell&&pairCell.title)); 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)); + UIMAP['region']={fg:null,bg:'#202830',bold:false,italic:false,underline:false,strike:false}; setSyntaxFg('p','');CATS.forEach(c=>{if(c[0]!=='bg')setSyntaxFg(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)); diff --git a/scripts/theme-studio/theme-studio.template.html b/scripts/theme-studio/theme-studio.template.html index 0fe8ed5de..bc96f12d1 100644 --- a/scripts/theme-studio/theme-studio.template.html +++ b/scripts/theme-studio/theme-studio.template.html @@ -42,6 +42,19 @@ STYLES_CSS</style> <div id="pkchips" class="pkchips"></div> </div> </div> + <div class="genctl" id="genctl"> + <div class="genrow"> + <label>intent <select id="genintent"></select></label> + <label>vibe <select id="genvibe"></select></label> + <label>source <select id="gensource"></select></label> + <label title="how many base columns to propose">accent count <input id="genaccents" type="number" min="1" max="12" step="1" value="5"></label> + <label>contrast <select id="gencontrast"></select></label> + <button onclick="previewGenerator()">preview</button> + <button onclick="clearGeneratorPreview()">clear preview</button> + <span id="genmsg"></span> + </div> + <div id="genpreview" class="genpreview"></div> + </div> <div class="pals" id="pals"></div> <div class="palwarn" id="palwarn"></div> </section> diff --git a/scripts/theme-studio/theme.json b/scripts/theme-studio/theme.json index e4af0fc2d..2254e56d6 100644 --- a/scripts/theme-studio/theme.json +++ b/scripts/theme-studio/theme.json @@ -2,17 +2,67 @@ "name": "theme", "palette": [ [ - "#070b10", + "#0a0c0d", + "silver-4", + "silver" + ], + [ + "#2c2f32", + "silver-3", + "silver" + ], + [ + "#53575c", + "silver-2", + "silver" + ], + [ + "#7c838a", + "silver-1", + "silver" + ], + [ + "#a9b2bb", + "silver", + "silver" + ], + [ + "#bac1c8", + "silver+1", + "silver" + ], + [ + "#cbd0d6", + "silver+2", + "silver" + ], + [ + "#dce0e3", + "silver+3", + "silver" + ], + [ + "#edeff1", + "silver+4", + "silver" + ], + [ + "#040609", + "blue-4", + "blue" + ], + [ + "#171f28", "blue-3", "blue" ], [ - "#232e39", + "#303d4c", "blue-2", "blue" ], [ - "#445569", + "#4b5d73", "blue-1", "blue" ], @@ -22,87 +72,142 @@ "blue" ], [ - "#8b9eb4", + "#8498af", "blue+1", "blue" ], [ - "#b1becd", + "#a1b1c3", "blue+2", "blue" ], [ - "#d7dee6", + "#c0cbd7", "blue+3", "blue" ], [ + "#dfe5eb", + "blue+4", + "blue" + ], + [ "#e4eaf8", "fg", "blue" ], [ - "#0a0c0d", - "silver-4", - "silver" + "#00040d", + "sapphire-4", + "sapphire" ], [ - "#2c2f32", - "silver-3", - "silver" + "#011933", + "sapphire-3", + "sapphire" ], [ - "#53575c", - "silver-2", - "silver" + "#02325e", + "sapphire-2", + "sapphire" ], [ - "#7c838a", - "silver-1", - "silver" + "#044e8c", + "sapphire-1", + "sapphire" ], [ - "#a9b2bb", - "silver", - "silver" + "#086cbe", + "sapphire", + "sapphire" ], [ - "#bac1c8", - "silver+1", - "silver" + "#4a8acd", + "sapphire+1", + "sapphire" ], [ - "#cbd0d6", - "silver+2", - "silver" + "#78a7db", + "sapphire+2", + "sapphire" ], [ - "#dce0e3", - "silver+3", - "silver" + "#a5c4e8", + "sapphire+3", + "sapphire" ], [ - "#edeff1", - "silver+4", - "silver" + "#d2e2f4", + "sapphire+4", + "sapphire" + ], + [ + "#020e13", + "blue zircon-4", + "blue zircon" + ], + [ + "#113640", + "blue zircon-3", + "blue zircon" + ], + [ + "#266273", + "blue zircon-2", + "blue zircon" + ], + [ + "#3d93ab", + "blue zircon-1", + "blue zircon" + ], + [ + "#55c7e6", + "blue zircon", + "blue zircon" + ], + [ + "#7ed3eb", + "blue zircon+1", + "blue zircon" + ], + [ + "#a1def1", + "blue zircon+2", + "blue zircon" + ], + [ + "#c2e9f6", + "blue zircon+3", + "blue zircon" ], [ - "#140f02", + "#e1f4fa", + "blue zircon+4", + "blue zircon" + ], + [ + "#0d0901", + "gold-5", + "gold" + ], + [ + "#332908", "gold-4", "gold" ], [ - "#43370e", + "#5e4d17", "gold-3", "gold" ], [ - "#796420", + "#8c7426", "gold-2", "gold" ], [ - "#b49534", + "#be9e37", "gold-1", "gold" ], @@ -112,26 +217,31 @@ "gold" ], [ - "#f5d577", + "#f4d370", "gold+1", "gold" ], [ - "#f7e09d", + "#f6dd91", "gold+2", "gold" ], [ - "#faebbf", + "#f9e6ae", "gold+3", "gold" ], [ - "#fcf5df", + "#fbeeca", "gold+4", "gold" ], [ + "#fdf7e5", + "gold+5", + "gold" + ], + [ "#0f0402", "terracotta-4", "terracotta" @@ -177,27 +287,32 @@ "terracotta" ], [ - "#0f0000", + "#0a0000", + "ruby-6", + "fire" + ], + [ + "#2a0000", "ruby-5", "fire" ], [ - "#360000", + "#4f0000", "ruby-4", "fire" ], [ - "#630000", + "#780000", "ruby-3", "fire" ], [ - "#940000", + "#a30000", "ruby-2", "fire" ], [ - "#c80000", + "#d00000", "ruby-1", "fire" ], @@ -207,52 +322,52 @@ "fire" ], [ - "#ff5544", + "#ff4e3e", "ruby+1", "fire" ], [ - "#ff7e6c", + "#ff7361", "ruby+2", "fire" ], [ - "#ffa191", + "#ff9281", "ruby+3", "fire" ], [ - "#ffc1b6", + "#ffafa1", "ruby+4", "fire" ], [ - "#ffe1da", + "#ffcac0", "ruby+5", "fire" ], [ - "#020005", - "regal-5", - "regal" + "#ffe5df", + "ruby+6", + "fire" ], [ - "#0f021e", + "#040009", "regal-4", "regal" ], [ - "#23073b", + "#170429", "regal-3", "regal" ], [ - "#38105b", + "#2f0c4e", "regal-2", "regal" ], [ - "#4e1a7d", + "#4a1876", "regal-1", "regal" ], @@ -262,119 +377,109 @@ "regal" ], [ - "#7d4eb2", + "#8255b5", "regal+1", "regal" ], [ - "#9572c3", + "#9f80c9", "regal+2", "regal" ], [ - "#af94d3", + "#bea9dc", "regal+3", "regal" ], [ - "#c9b7e2", + "#ded4ee", "regal+4", "regal" ], [ - "#e4dbf1", - "regal+5", - "regal" - ], - [ - "#030906", - "jade-4", - "sage" - ], - [ - "#142821", - "jade-3", - "sage" - ], - [ - "#2a4b40", - "jade-2", - "sage" - ], - [ - "#437262", - "jade-1", - "sage" - ], - [ - "#5d9b86", - "jade", - "sage" - ], - [ - "#7eaf9d", - "jade+1", - "sage" - ], - [ - "#9ec2b5", - "jade+2", - "sage" - ], - [ - "#bed6cd", - "jade+3", - "sage" - ], - [ - "#deebe6", - "jade+4", - "sage" - ], - [ "#000000", "ground", "ground" ], [ - "#040404", + "#050506", "ground+1", "ground" ], [ - "#17181a", + "#1d1e20", "ground+2", "ground" ], [ - "#2f3134", + "#393b3f", "ground+3", "ground" ], [ - "#4a4c51", + "#585a60", "ground+4", "ground" ], [ - "#666970", + "#787c84", "ground+5", "ground" ], [ - "#848790", + "#9b9fa9", "ground+6", "ground" ], [ - "#a3a7b1", + "#bfc4d0", "ground+7", "ground" ], [ - "#c3c8d4", - "ground+8", - "ground" + "#000300", + "emerald-4", + "emerald" + ], + [ + "#001600", + "emerald-3", + "emerald" + ], + [ + "#012e02", + "emerald-2", + "emerald" + ], + [ + "#024704", + "emerald-1", + "emerald" + ], + [ + "#046307", + "emerald", + "emerald" + ], + [ + "#448141", + "emerald+1", + "emerald" + ], + [ + "#73a06f", + "emerald+2", + "emerald" + ], + [ + "#a1bf9e", + "emerald+3", + "emerald" + ], + [ + "#cfdfce", + "emerald+4", + "emerald" ] ], "syntax": { @@ -442,7 +547,7 @@ "box": null }, "dec": { - "fg": "#b49534", + "fg": "#a9b2bb", "bg": null, "bold": false, "italic": false, @@ -451,7 +556,7 @@ "box": null }, "ty": { - "fg": "#f2ca49", + "fg": "#be9e37", "bg": null, "bold": false, "italic": false, @@ -487,7 +592,7 @@ "box": null }, "str": { - "fg": "#7eaf9d", + "fg": "#73a06f", "bg": null, "bold": false, "italic": false, @@ -496,8 +601,8 @@ "box": null }, "esc": { - "fg": "#9572c3", - "bg": null, + "fg": "#c3c8d4", + "bg": "#050506", "bold": false, "italic": false, "underline": false, @@ -505,7 +610,7 @@ "box": null }, "re": { - "fg": "#7eaf9d", + "fg": "#73a06f", "bg": null, "bold": false, "italic": false, @@ -514,7 +619,7 @@ "box": null }, "doc": { - "fg": "#a9b2bb", + "fg": "#d9e7f6", "bg": null, "bold": false, "italic": false, @@ -523,7 +628,7 @@ "box": null }, "cm": { - "fg": "#9572c3", + "fg": "#73a06f", "bg": null, "bold": false, "italic": true, @@ -532,7 +637,7 @@ "box": null }, "cmd": { - "fg": "#9572c3", + "fg": "#73a06f", "bg": null, "bold": false, "italic": true, @@ -570,24 +675,29 @@ }, "ui": { "cursor": { - "fg": null, - "bg": "#000000", + "fg": "#000000", + "bg": "#bac1c8", "bold": false, "italic": false, "underline": false, "strike": false }, "region": { - "fg": null, - "bg": "#eedc82", + "fg": "#f4d370", + "bg": "#332908", "bold": false, "italic": false, "underline": false, - "strike": false + "strike": false, + "box": { + "style": "line", + "width": 1, + "color": "#be9e37" + } }, "hl-line": { "fg": null, - "bg": "#17181a", + "bg": "#1d1e20", "bold": false, "italic": false, "underline": false, @@ -596,23 +706,24 @@ }, "highlight": { "fg": null, - "bg": "#43370e", + "bg": "#332908", "bold": false, "italic": false, "underline": false, - "strike": false + "strike": false, + "box": null }, "mode-line": { - "fg": "#000000", - "bg": "#67809c", - "bold": false, + "fg": "#cbd0d6", + "bg": "#303d4c", + "bold": true, "italic": false, "underline": false, "strike": false, "box": { "style": "released", "width": 1, - "color": "#53575c" + "color": "#0a0c0d" } }, "mode-line-inactive": { @@ -626,45 +737,40 @@ "box": null }, "fringe": { - "fg": null, - "bg": "#f2f2f2", - "bold": false, + "fg": "#fbeeca", + "bg": null, + "bold": true, "italic": false, "underline": false, "strike": false }, "line-number": { - "fg": null, + "fg": "#4b5d73", "bg": null, "bold": false, "italic": false, "underline": false, - "strike": false, - "inherit": [ - "shadow", - "default" - ] + "strike": false }, "line-number-current-line": { - "fg": null, + "fg": "#f6dd91", "bg": null, "bold": false, "italic": false, "underline": false, - "strike": false, - "inherit": "line-number" + "strike": false }, "minibuffer-prompt": { - "fg": "#ff00ff", + "fg": "#a1b1c3", "bg": null, - "bold": false, + "bold": true, "italic": false, "underline": false, "strike": false }, "isearch": { - "fg": "#b0e2ff", - "bg": "#cd00cd", + "fg": null, + "bg": "#332908", "bold": false, "italic": false, "underline": false, @@ -672,23 +778,24 @@ }, "lazy-highlight": { "fg": null, - "bg": "#afeeee", + "bg": "#332908", "bold": false, "italic": false, "underline": false, "strike": false }, "isearch-fail": { - "fg": null, - "bg": "#ffc1c1", - "bold": false, + "fg": "#cb6b4d", + "bg": "#000000", + "bold": true, "italic": false, "underline": false, - "strike": false + "strike": false, + "box": null }, "show-paren-match": { - "fg": null, - "bg": "#40e0d0", + "fg": "#000000", + "bg": "#448141", "bold": false, "italic": false, "underline": false, @@ -696,14 +803,14 @@ }, "show-paren-mismatch": { "fg": "#ffffff", - "bg": "#a020f0", + "bg": "#a30000", "bold": false, "italic": false, "underline": false, "strike": false }, "link": { - "fg": "#b1becd", + "fg": "#a1b1c3", "bg": "#000000", "bold": false, "italic": false, @@ -711,15 +818,20 @@ "strike": false }, "error": { - "fg": "#940000", - "bg": "#000000", + "fg": "#ff4e3e", + "bg": "#4f0000", "bold": true, "italic": false, "underline": false, - "strike": false + "strike": false, + "box": { + "style": "line", + "width": 1, + "color": "#a30000" + } }, "warning": { - "fg": "#b49534", + "fg": "#be9e37", "bg": "#000000", "bold": true, "italic": false, @@ -735,12 +847,13 @@ "strike": false }, "vertical-border": { - "fg": null, + "fg": "#303d4c", "bg": null, "bold": false, "italic": false, "underline": false, - "strike": false + "strike": false, + "box": null } }, "locks": [ @@ -750,38 +863,81 @@ "bi", "pp", "fnc", - "dec", - "ty", "prop", - "con", - "num", - "esc", - "re", - "doc", - "cm", - "cmd", "var", "op", "punc", - "str", - "ui:mode-line-inactive", - "ui:mode-line", - "ui:highlight", "fnd", - "pkg:org-mode:org-document-title", - "pkg:org-mode:org-document-info", "ui:success", "ui:warning", - "ui:error", "ui:link", + "ui:minibuffer-prompt", + "pkg:org-mode:org-document-title", + "pkg:org-mode:org-document-info", + "re", + "esc", + "doc", + "ui:line-number-current-line", + "dec", + "ui:cursor", + "ui:line-number", + "ui:vertical-border", + "ui:hl-line", + "con", + "num", + "ui:show-paren-mismatch", + "ui:show-paren-match", + "ui:fringe", + "pkg:org-mode:org-document-info-keyword", + "pkg:org-mode:org-ellipsis", + "pkg:org-mode:org-table", + "pkg:org-mode:org-table-row", + "pkg:org-mode:org-meta-line", + "pkg:org-mode:org-headline-done", "pkg:org-mode:org-headline-todo", + "ui:isearch-fail", + "pkg:org-mode:org-table-header", + "ui:highlight", + "ui:isearch", + "ui:lazy-highlight", + "ui:mode-line-inactive", + "ui:mode-line", + "cm", + "cmd", + "ui:error", + "ui:region", + "pkg:ghostel:ghostel-color-bright-red", + "pkg:ghostel:ghostel-color-bright-yellow", + "pkg:ghostel:ghostel-color-magenta", + "pkg:ghostel:ghostel-color-bright-magenta", + "pkg:ghostel:ghostel-color-bright-cyan", + "pkg:ghostel:ghostel-color-cyan", + "pkg:ghostel:ghostel-color-bright-white", + "pkg:ghostel:ghostel-color-white", + "pkg:ghostel:ghostel-default", + "pkg:ghostel:ghostel-color-black", + "pkg:ghostel:ghostel-color-bright-black", + "pkg:ghostel:ghostel-color-blue", + "pkg:ghostel:ghostel-color-bright-blue", + "pkg:ghostel:ghostel-fake-cursor-box", + "pkg:ghostel:ghostel-color-red", + "pkg:ghostel:ghostel-color-green", + "pkg:ghostel:ghostel-color-bright-green", + "pkg:ghostel:ghostel-fake-cursor", + "str", + "ty", + "pkg:ghostel:ghostel-color-yellow", + "pkg:org-mode:org-level-1", + "pkg:org-mode:org-level-3", + "pkg:org-mode:org-level-2", "pkg:org-mode:org-done", - "ui:hl-line" + "pkg:org-mode:org-priority", + "pkg:org-mode:org-todo" ], "packages": { "org-mode": { "org-document-title": { - "fg": "#b1becd", + "fg": "#f4d370", "bg": null, "bold": true, "italic": false, @@ -792,7 +948,7 @@ "height": 1.2 }, "org-document-info": { - "fg": "#bac1c8", + "fg": "#f2ca49", "bg": null, "bold": true, "italic": false, @@ -800,31 +956,30 @@ "strike": false, "inherit": null, "source": "user", - "height": 1.1 + "height": 1.15 }, "org-document-info-keyword": { - "fg": "#666970", + "fg": "#7c838a", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", + "inherit": null, "source": "user" }, "org-level-1": { - "fg": "#dce0e3", + "fg": "#f4d370", "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "user", - "height": 1.1 + "source": "user" }, "org-level-2": { - "fg": "#faebbf", + "fg": "#a5c4e8", "bg": null, "bold": false, "italic": false, @@ -834,7 +989,7 @@ "source": "user" }, "org-level-3": { - "fg": "#c9b7e2", + "fg": "#73a06f", "bg": null, "bold": false, "italic": false, @@ -844,17 +999,17 @@ "source": "user" }, "org-level-4": { - "fg": "#2ba178", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "user" + "source": "default" }, "org-level-5": { - "fg": "#cb6b4d", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -864,7 +1019,7 @@ "source": "default" }, "org-level-6": { - "fg": "#998162", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -874,7 +1029,7 @@ "source": "default" }, "org-level-7": { - "fg": "#5d9b86", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -884,7 +1039,7 @@ "source": "default" }, "org-level-8": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -894,7 +1049,7 @@ "source": "default" }, "org-headline-todo": { - "fg": null, + "fg": "#cbd0d6", "bg": null, "bold": false, "italic": false, @@ -904,7 +1059,7 @@ "source": "user" }, "org-headline-done": { - "fg": "#848790", + "fg": "#a9b2bb", "bg": null, "bold": false, "italic": true, @@ -914,37 +1069,47 @@ "source": "user" }, "org-todo": { - "fg": "#cb6b4d", - "bg": null, + "fg": "#cfdfce", + "bg": "#046307", "bold": true, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user", + "box": { + "style": "line", + "width": 1, + "color": "#448141" + } }, "org-done": { - "fg": "#666970", - "bg": null, + "fg": "#9b9fa9", + "bg": "#2c2f32", "bold": true, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "user" + "source": "user", + "box": { + "style": "line", + "width": 1, + "color": "#53575c" + } }, "org-priority": { "fg": "#f2ca49", - "bg": null, - "bold": true, + "bg": "#000000", + "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "org-tag": { - "fg": "#998162", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -954,7 +1119,7 @@ "source": "default" }, "org-tag-group": { - "fg": "#998162", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -964,7 +1129,7 @@ "source": "default" }, "org-special-keyword": { - "fg": "#5e6770", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -974,7 +1139,7 @@ "source": "default" }, "org-drawer": { - "fg": "#5e6770", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -984,7 +1149,7 @@ "source": "default" }, "org-property-value": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -994,17 +1159,17 @@ "source": "default" }, "org-checkbox": { - "fg": "#f2ca49", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", + "inherit": null, "source": "default" }, "org-checkbox-statistics-todo": { - "fg": "#cb6b4d", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1014,7 +1179,7 @@ "source": "default" }, "org-checkbox-statistics-done": { - "fg": "#5d9b86", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1024,9 +1189,9 @@ "source": "default" }, "org-warning": { - "fg": "#cb6b4d", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1034,7 +1199,7 @@ "source": "default" }, "org-link": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1044,7 +1209,7 @@ "source": "default" }, "org-footnote": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1054,17 +1219,17 @@ "source": "default" }, "org-date": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", + "inherit": null, "source": "default" }, "org-sexp-date": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1074,8 +1239,8 @@ "source": "default" }, "org-date-selected": { - "fg": "#000000", - "bg": "#f2ca49", + "fg": null, + "bg": null, "bold": false, "italic": false, "underline": false, @@ -1084,7 +1249,7 @@ "source": "default" }, "org-target": { - "fg": "#6624a0", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1094,7 +1259,7 @@ "source": "default" }, "org-macro": { - "fg": "#6624a0", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1104,7 +1269,7 @@ "source": "default" }, "org-cite": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1114,7 +1279,7 @@ "source": "default" }, "org-cite-key": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1124,87 +1289,87 @@ "source": "default" }, "org-block": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", - "source": "user" + "inherit": null, + "source": "default" }, "org-block-begin-line": { - "fg": "#5e6770", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", - "source": "user" + "inherit": null, + "source": "default" }, "org-block-end-line": { - "fg": "#5e6770", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", - "source": "user" + "inherit": null, + "source": "default" }, "org-code": { - "fg": "#cb6b4d", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", + "inherit": null, "source": "default" }, "org-verbatim": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", + "inherit": null, "source": "default" }, "org-inline-src-block": { - "fg": "#cb6b4d", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", + "inherit": null, "source": "default" }, "org-quote": { - "fg": "#a9b2bb", + "fg": null, "bg": null, "bold": false, - "italic": true, + "italic": false, "underline": false, "strike": false, "inherit": null, "source": "default" }, "org-verse": { - "fg": "#a9b2bb", + "fg": null, "bg": null, "bold": false, - "italic": true, + "italic": false, "underline": false, "strike": false, "inherit": null, "source": "default" }, "org-latex-and-related": { - "fg": "#f2ca49", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1214,37 +1379,42 @@ "source": "default" }, "org-table": { - "fg": "#838d97", + "fg": "#bac1c8", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", - "source": "default" + "inherit": null, + "source": "user" }, "org-table-header": { - "fg": "#e4eaf8", - "bg": "#2f343a", - "bold": true, + "fg": "#cbd0d6", + "bg": "#4b5d73", + "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user", + "box": { + "style": "line", + "width": 1, + "color": "#53575c" + } }, "org-table-row": { - "fg": null, + "fg": "#bac1c8", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "org-formula": { - "fg": "#cb6b4d", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1255,7 +1425,7 @@ }, "org-column": { "fg": null, - "bg": "#2f343a", + "bg": null, "bold": false, "italic": false, "underline": false, @@ -1264,9 +1434,9 @@ "source": "default" }, "org-column-title": { - "fg": "#e4eaf8", - "bg": "#2f343a", - "bold": true, + "fg": null, + "bg": null, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1274,9 +1444,9 @@ "source": "default" }, "org-list-dt": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1284,27 +1454,27 @@ "source": "default" }, "org-meta-line": { - "fg": "#5e6770", + "fg": "#7c838a", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": "fixed-pitch", - "source": "default" + "inherit": null, + "source": "user" }, "org-ellipsis": { - "fg": "#5e6770", + "fg": "#8498af", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "org-hide": { - "fg": "#000000", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1314,7 +1484,7 @@ "source": "default" }, "org-indent": { - "fg": "#000000", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1324,7 +1494,7 @@ "source": "default" }, "org-archived": { - "fg": "#5e6770", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1344,9 +1514,9 @@ "source": "default" }, "org-dispatcher-highlight": { - "fg": "#f2ca49", - "bg": "#264364", - "bold": true, + "fg": null, + "bg": null, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1354,18 +1524,17 @@ "source": "default" }, "org-agenda-structure": { - "fg": "#e4eaf8", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default", - "height": 1.1 + "source": "default" }, "org-agenda-structure-secondary": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1375,9 +1544,9 @@ "source": "default" }, "org-agenda-structure-filter": { - "fg": "#cb6b4d", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1385,31 +1554,29 @@ "source": "default" }, "org-agenda-date": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default", - "height": 1.05 + "source": "default" }, "org-agenda-date-today": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default", - "height": 1.05 + "source": "default" }, "org-agenda-date-weekend": { - "fg": "#838d97", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1417,9 +1584,9 @@ "source": "default" }, "org-agenda-date-weekend-today": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1427,7 +1594,7 @@ "source": "default" }, "org-agenda-current-time": { - "fg": "#f2ca49", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1437,7 +1604,7 @@ "source": "default" }, "org-agenda-done": { - "fg": "#5d9b86", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1447,7 +1614,7 @@ "source": "default" }, "org-agenda-dimmed-todo-face": { - "fg": "#5e6770", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1457,7 +1624,7 @@ "source": "default" }, "org-agenda-calendar-event": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1467,7 +1634,7 @@ "source": "default" }, "org-agenda-calendar-sexp": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1477,7 +1644,7 @@ "source": "default" }, "org-agenda-calendar-daterange": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1487,7 +1654,7 @@ "source": "default" }, "org-agenda-diary": { - "fg": "#5d9b86", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1498,7 +1665,7 @@ }, "org-agenda-clocking": { "fg": null, - "bg": "#264364", + "bg": null, "bold": false, "italic": false, "underline": false, @@ -1508,7 +1675,7 @@ }, "org-agenda-column-dateline": { "fg": null, - "bg": "#2f343a", + "bg": null, "bold": false, "italic": false, "underline": false, @@ -1518,7 +1685,7 @@ }, "org-agenda-restriction-lock": { "fg": null, - "bg": "#cb6b4d", + "bg": null, "bold": false, "italic": false, "underline": false, @@ -1527,9 +1694,9 @@ "source": "default" }, "org-agenda-filter-category": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1537,9 +1704,9 @@ "source": "default" }, "org-agenda-filter-effort": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1547,9 +1714,9 @@ "source": "default" }, "org-agenda-filter-regexp": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1557,9 +1724,9 @@ "source": "default" }, "org-agenda-filter-tags": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1567,7 +1734,7 @@ "source": "default" }, "org-scheduled": { - "fg": "#5d9b86", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1577,9 +1744,9 @@ "source": "default" }, "org-scheduled-today": { - "fg": "#5d9b86", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1587,7 +1754,7 @@ "source": "default" }, "org-scheduled-previously": { - "fg": "#cb6b4d", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1597,7 +1764,7 @@ "source": "default" }, "org-upcoming-deadline": { - "fg": "#f2ca49", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1607,7 +1774,7 @@ "source": "default" }, "org-upcoming-distant-deadline": { - "fg": "#998162", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1617,9 +1784,9 @@ "source": "default" }, "org-imminent-deadline": { - "fg": "#cb6b4d", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -1627,7 +1794,7 @@ "source": "default" }, "org-time-grid": { - "fg": "#998162", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1638,7 +1805,7 @@ }, "org-clock-overlay": { "fg": null, - "bg": "#264364", + "bg": null, "bold": false, "italic": false, "underline": false, @@ -1647,7 +1814,7 @@ "source": "default" }, "org-mode-line-clock": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, @@ -1657,9 +1824,9 @@ "source": "default" }, "org-mode-line-clock-overrun": { - "fg": "#cb6b4d", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, @@ -2771,84 +2938,84 @@ }, "elfeed": { "elfeed-search-date-face": { - "fg": "#838d97", + "fg": "#7c838a", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-search-title-face": { - "fg": "#a9b2bb", + "fg": "#7c838a", "bg": null, "bold": false, - "italic": false, + "italic": true, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-search-unread-title-face": { - "fg": "#e4eaf8", + "fg": "#f2ca49", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-search-feed-face": { - "fg": "#5d9b86", + "fg": "#73a06f", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-search-tag-face": { - "fg": "#998162", + "fg": "#bea9dc", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-search-unread-count-face": { - "fg": "#f2ca49", + "fg": "#a1b1c3", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-search-filter-face": { - "fg": "#e4eaf8", + "fg": "#8498af", "bg": null, "bold": true, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-search-last-update-face": { - "fg": "#5e6770", + "fg": "#8498af", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-log-date-face": { "fg": "#838d97", @@ -2881,24 +3048,24 @@ "source": "default" }, "elfeed-log-info-level-face": { - "fg": "#5d9b86", + "fg": "#73a06f", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "elfeed-log-debug-level-face": { - "fg": "#5e6770", + "fg": "#c3c8d4", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" } }, "mu4e": { @@ -3275,14 +3442,14 @@ }, "ghostel": { "ghostel-default": { - "fg": "#cdced1", + "fg": "#edeff1", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-fake-cursor": { "fg": "#000000", @@ -3292,258 +3459,263 @@ "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user", + "box": { + "style": "line", + "width": 1, + "color": "#bfc4d0" + } }, "ghostel-fake-cursor-box": { - "fg": "#a9b2bb", + "fg": "#bac1c8", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-black": { - "fg": "#5e6770", + "fg": "#9b9fa9", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-red": { - "fg": "#cb6b4d", + "fg": "#ff0000", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-green": { - "fg": "#2ba178", + "fg": "#73a06f", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-yellow": { - "fg": "#f2ca49", + "fg": "#be9e37", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-blue": { - "fg": "#e4eaf8", + "fg": "#4a8acd", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-magenta": { - "fg": "#6624a0", + "fg": "#9f80c9", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-cyan": { - "fg": "#5d9b86", + "fg": "#3d93ab", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-white": { - "fg": "#a9b2bb", + "fg": "#bac1c8", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-black": { - "fg": "#838d97", + "fg": "#bfc4d0", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-red": { - "fg": "#de4949", + "fg": "#ff4e3e", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-green": { - "fg": "#84b068", + "fg": "#a1bf9e", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-yellow": { - "fg": "#eed376", + "fg": "#f6dd91", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-blue": { - "fg": "#7a9abe", + "fg": "#a5c4e8", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-magenta": { - "fg": "#b07fd0", + "fg": "#bea9dc", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-cyan": { - "fg": "#7fc0a8", + "fg": "#7ed3eb", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" }, "ghostel-color-bright-white": { - "fg": "#e4eaf8", + "fg": "#edeff1", "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, "inherit": null, - "source": "default" + "source": "user" } }, "dashboard": { "dashboard-banner-logo-title": { - "fg": "#f2ca49", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, + "inherit": "default", "source": "default" }, "dashboard-text-banner": { - "fg": "#838d97", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, - "source": "default" + "inherit": "default", + "source": "user" }, "dashboard-heading": { - "fg": "#e4eaf8", + "fg": null, "bg": null, - "bold": true, + "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, + "inherit": "font-lock-keyword-face", "source": "default" }, "dashboard-items-face": { - "fg": "#cdced1", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, + "inherit": "widget-button", "source": "default" }, "dashboard-navigator": { - "fg": "#e4eaf8", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, + "inherit": "font-lock-keyword-face", "source": "default" }, "dashboard-no-items-face": { - "fg": "#5e6770", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, + "inherit": "widget-button", "source": "default" }, "dashboard-footer-face": { - "fg": "#998162", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, + "inherit": "font-lock-doc-face", "source": "default" }, "dashboard-footer-icon-face": { - "fg": "#f2ca49", + "fg": null, "bg": null, "bold": false, "italic": false, "underline": false, "strike": false, - "inherit": null, + "inherit": "dashboard-footer-face", "source": "default" } }, |
