0&&(p+=y,le)))for(r=0;r=a)continue;(o>0||e.hskipBeforeAndAfter)&&(i=l.deflt(c.pregap,u),0!==i&&(z=Ve.makeSpan(["arraycolsep"],[]),z.style.width=F(i),M.push(z)));let d=[];for(r=0;r0){const e=Ve.makeLineSpan("hline",t,m),r=Ve.makeLineSpan("hdashline",t,m),n=[{type:"elem",elem:h,shift:0}];for(;c.length>0;){const t=c.pop(),o=t.pos-k;t.isDashed?n.push({type:"elem",elem:r,shift:o}):n.push({type:"elem",elem:e,shift:o})}h=Ve.makeVList({positionType:"individualShift",children:n},t)}if(0===T.length)return Ve.makeSpan(["mord"],[h],t);{let e=Ve.makeVList({positionType:"individualShift",children:T},t);return e=Ve.makeSpan(["tag"],[e],t),Ve.makeFragment([h,e])}},Lr={c:"center ",l:"left ",r:"right "},Dr=function(e,t){const r=[],n=new gt.MathNode("mtd",[],["mtr-glue"]),o=new gt.MathNode("mtd",[],["mml-eqn-num"]);for(let s=0;s0){const t=e.cols;let r="",n=!1,o=0,i=t.length;"separator"===t[0].type&&(a+="top ",o=1),"separator"===t[t.length-1].type&&(a+="bottom ",i-=1);for(let e=o;e0?"left ":"",a+=c[c.length-1].length>0?"right ":"";for(let e=1;e-1?"alignat":"align",s="split"===e.envName,i=Hr(e.parser,{cols:r,addJot:!0,autoTag:s?void 0:Rr(e.envName),emptySingleRow:!0,colSeparationType:o,maxNumCols:s?2:void 0,leqno:e.parser.settings.leqno},"display");let a,l=0;const h={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){let e="";for(let r=0;r0&&c&&(n=1),r[e]={type:"align",align:t,pregap:n,postgap:0}}return i.colSeparationType=c?"align":"alignat",i};Ar({type:"array",names:["array","darray"],props:{numArgs:1},handler(e,t){const r=(Rt(t[0])?[t[0]]:qt(t[0],"ordgroup").body).map((function(e){const t=It(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),o={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Hr(e.parser,o,Or(e.envName))},htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler(e){const t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")];let r="c";const o={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){const t=e.parser;if(t.consumeSpaces(),"["===t.fetch().text){if(t.consume(),t.consumeSpaces(),r=t.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",t.nextToken);t.consume(),t.consumeSpaces(),t.expect("]"),t.consume(),o.cols=[{type:"align",align:r}]}}const s=Hr(e.parser,o,Or(e.envName)),i=Math.max(0,...s.body.map((e=>e.length)));return s.cols=new Array(i).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[s],left:t[0],right:t[1],rightColor:void 0}:s},htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["smallmatrix"],props:{numArgs:0},handler(e){const t=Hr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["subarray"],props:{numArgs:1},handler(e,t){const r=(Rt(t[0])?[t[0]]:qt(t[0],"ordgroup").body).map((function(e){const t=It(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");let o={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if(o=Hr(e.parser,o,"script"),o.body.length>0&&o.body[0].length>1)throw new n("{subarray} can contain only one column");return o},htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler(e){const t=Hr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},Or(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Vr,htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler(e){l.contains(["gather","gather*"],e.envName)&&Ir(e);const t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",autoTag:Rr(e.envName),emptySingleRow:!0,leqno:e.parser.settings.leqno};return Hr(e.parser,t,"display")},htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Vr,htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["equation","equation*"],props:{numArgs:0},handler(e){Ir(e);const t={autoTag:Rr(e.envName),emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Hr(e.parser,t,"display")},htmlBuilder:Er,mathmlBuilder:Dr}),Ar({type:"array",names:["CD"],props:{numArgs:0},handler(e){return Ir(e),function(e){const t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();const r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}let r=[];const o=[r];for(let a=0;a-1);else{if(!("<>AV".indexOf(o)>-1))throw new n('Expected one of "<>AV=|." after @',l[t]);for(let e=0;e<2;e++){let r=!0;for(let h=t+1;h{const r=e.font,n=t.withFont(r);return ht(e.body,n)},Gr=(e,t)=>{const r=e.font,n=t.withFont(r);return vt(e.body,n)},Ur={"\\Bbb":"\\mathbb","\\bold":"\\mathbf","\\frak":"\\mathfrak","\\bm":"\\boldsymbol"};je({type:"font",names:["\\mathrm","\\mathit","\\mathbf","\\mathnormal","\\mathbb","\\mathcal","\\mathfrak","\\mathscr","\\mathsf","\\mathtt","\\Bbb","\\bold","\\frak"],props:{numArgs:1,allowedInArgument:!0},handler:(e,t)=>{let{parser:r,funcName:n}=e;const o=Ze(t[0]);let s=n;return s in Ur&&(s=Ur[s]),{type:"font",mode:r.mode,font:s.slice(1),body:o}},htmlBuilder:Fr,mathmlBuilder:Gr}),je({type:"mclass",names:["\\boldsymbol","\\bm"],props:{numArgs:1},handler:(e,t)=>{let{parser:r}=e;const n=t[0],o=l.isCharacterBox(n);return{type:"mclass",mode:r.mode,mclass:Ft(n),body:[{type:"font",mode:r.mode,font:"boldsymbol",body:n}],isCharacterBox:o}}}),je({type:"font",names:["\\rm","\\sf","\\tt","\\bf","\\it","\\cal"],props:{numArgs:0,allowedInText:!0},handler:(e,t)=>{let{parser:r,funcName:n,breakOnTokenText:o}=e;const{mode:s}=r,i=r.parseExpression(!0,o);return{type:"font",mode:s,font:"math"+n.slice(1),body:{type:"ordgroup",mode:r.mode,body:i}}},htmlBuilder:Fr,mathmlBuilder:Gr});const Yr=(e,t)=>{let r=t;return"display"===e?r=r.id>=w.SCRIPT.id?r.text():w.DISPLAY:"text"===e&&r.size===w.DISPLAY.size?r=w.TEXT:"script"===e?r=w.SCRIPT:"scriptscript"===e&&(r=w.SCRIPTSCRIPT),r},Xr=(e,t)=>{const r=Yr(e.size,t.style),n=r.fracNum(),o=r.fracDen();let s;s=t.havingStyle(n);const i=ht(e.numer,s,t);if(e.continued){const e=8.5/t.fontMetrics().ptPerEm,r=3.5/t.fontMetrics().ptPerEm;i.height=i.height0?3*c:7*c,u=t.fontMetrics().denom1):(h>0?(m=t.fontMetrics().num2,p=c):(m=t.fontMetrics().num3,p=3*c),u=t.fontMetrics().denom2),l){const e=t.fontMetrics().axisHeight;m-i.depth-(e+.5*h){let r=new gt.MathNode("mfrac",[vt(e.numer,t),vt(e.denom,t)]);if(e.hasBarLine){if(e.barSize){const n=P(e.barSize,t);r.setAttribute("linethickness",F(n))}}else r.setAttribute("linethickness","0px");const n=Yr(e.size,t.style);if(n.size!==t.style.size){r=new gt.MathNode("mstyle",[r]);const e=n.size===w.DISPLAY.size?"true":"false";r.setAttribute("displaystyle",e),r.setAttribute("scriptlevel","0")}if(null!=e.leftDelim||null!=e.rightDelim){const t=[];if(null!=e.leftDelim){const r=new gt.MathNode("mo",[new gt.TextNode(e.leftDelim.replace("\\",""))]);r.setAttribute("fence","true"),t.push(r)}if(t.push(r),null!=e.rightDelim){const r=new gt.MathNode("mo",[new gt.TextNode(e.rightDelim.replace("\\",""))]);r.setAttribute("fence","true"),t.push(r)}return bt(t)}return r};je({type:"genfrac",names:["\\dfrac","\\frac","\\tfrac","\\dbinom","\\binom","\\tbinom","\\\\atopfrac","\\\\bracefrac","\\\\brackfrac"],props:{numArgs:2,allowedInArgument:!0},handler:(e,t)=>{let{parser:r,funcName:n}=e;const o=t[0],s=t[1];let i,a=null,l=null,h="auto";switch(n){case"\\dfrac":case"\\frac":case"\\tfrac":i=!0;break;case"\\\\atopfrac":i=!1;break;case"\\dbinom":case"\\binom":case"\\tbinom":i=!1,a="(",l=")";break;case"\\\\bracefrac":i=!1,a="\\{",l="\\}";break;case"\\\\brackfrac":i=!1,a="[",l="]";break;default:throw new Error("Unrecognized genfrac command")}switch(n){case"\\dfrac":case"\\dbinom":h="display";break;case"\\tfrac":case"\\tbinom":h="text"}return{type:"genfrac",mode:r.mode,continued:!1,numer:o,denom:s,hasBarLine:i,leftDelim:a,rightDelim:l,size:h,barSize:null}},htmlBuilder:Xr,mathmlBuilder:Wr}),je({type:"genfrac",names:["\\cfrac"],props:{numArgs:2},handler:(e,t)=>{let{parser:r,funcName:n}=e;const o=t[0],s=t[1];return{type:"genfrac",mode:r.mode,continued:!0,numer:o,denom:s,hasBarLine:!0,leftDelim:null,rightDelim:null,size:"display",barSize:null}}}),je({type:"infix",names:["\\over","\\choose","\\atop","\\brace","\\brack"],props:{numArgs:0,infix:!0},handler(e){let t,{parser:r,funcName:n,token:o}=e;switch(n){case"\\over":t="\\frac";break;case"\\choose":t="\\binom";break;case"\\atop":t="\\\\atopfrac";break;case"\\brace":t="\\\\bracefrac";break;case"\\brack":t="\\\\brackfrac";break;default:throw new Error("Unrecognized infix genfrac command")}return{type:"infix",mode:r.mode,replaceWith:t,token:o}}});const _r=["display","text","script","scriptscript"],jr=function(e){let t=null;return e.length>0&&(t=e,t="."===t?null:t),t};je({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler(e,t){let{parser:r}=e;const n=t[4],o=t[5],s=Ze(t[0]),i="atom"===s.type&&"open"===s.family?jr(s.text):null,a=Ze(t[1]),l="atom"===a.type&&"close"===a.family?jr(a.text):null,h=qt(t[2],"size");let c,m=null;h.isBlank?c=!0:(m=h.value,c=m.number>0);let p="auto",u=t[3];if("ordgroup"===u.type){if(u.body.length>0){const e=qt(u.body[0],"textord");p=_r[Number(e.text)]}}else u=qt(u,"textord"),p=_r[Number(u.text)];return{type:"genfrac",mode:r.mode,numer:n,denom:o,continued:!1,hasBarLine:c,barSize:m,leftDelim:i,rightDelim:l,size:p}},htmlBuilder:Xr,mathmlBuilder:Wr}),je({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler(e,t){let{parser:r,funcName:n,token:o}=e;return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:qt(t[0],"size").value,token:o}}}),je({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:(e,t)=>{let{parser:r,funcName:n}=e;const o=t[0],s=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(qt(t[1],"infix").size),i=t[2],a=s.number>0;return{type:"genfrac",mode:r.mode,numer:o,denom:i,continued:!1,hasBarLine:a,barSize:s,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:Xr,mathmlBuilder:Wr});const $r=(e,t)=>{const r=t.style;let n,o;"supsub"===e.type?(n=e.sup?ht(e.sup,t.havingStyle(r.sup()),t):ht(e.sub,t.havingStyle(r.sub()),t),o=qt(e.base,"horizBrace")):o=qt(e,"horizBrace");const s=ht(o.base,t.havingBaseStyle(w.DISPLAY)),i=Nt(o,t);let a;if(o.isOver?(a=Ve.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:i}]},t),a.children[0].children[0].children[1].classes.push("svg-align")):(a=Ve.makeVList({positionType:"bottom",positionData:s.depth+.1+i.height,children:[{type:"elem",elem:i},{type:"kern",size:.1},{type:"elem",elem:s}]},t),a.children[0].children[0].children[0].classes.push("svg-align")),n){const e=Ve.makeSpan(["mord",o.isOver?"mover":"munder"],[a],t);a=o.isOver?Ve.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:e},{type:"kern",size:.2},{type:"elem",elem:n}]},t):Ve.makeVList({positionType:"bottom",positionData:e.depth+.2+n.height+n.depth,children:[{type:"elem",elem:n},{type:"kern",size:.2},{type:"elem",elem:e}]},t)}return Ve.makeSpan(["mord",o.isOver?"mover":"munder"],[a],t)};je({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler(e,t){let{parser:r,funcName:n}=e;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:$r,mathmlBuilder:(e,t)=>{const r=Ct(e.label);return new gt.MathNode(e.isOver?"mover":"munder",[vt(e.base,t),r])}}),je({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:(e,t)=>{let{parser:r}=e;const n=t[1],o=qt(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:o})?{type:"href",mode:r.mode,href:o,body:Ke(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:(e,t)=>{const r=nt(e.body,t,!1);return Ve.makeAnchor(e.href,[],r,t)},mathmlBuilder:(e,t)=>{let r=wt(e.body,t);return r instanceof ut||(r=new ut("mrow",[r])),r.setAttribute("href",e.href),r}}),je({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:(e,t)=>{let{parser:r}=e;const n=qt(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");const o=[];for(let e=0;e{let{parser:r,funcName:o,token:s}=e;const i=qt(t[0],"raw").string,a=t[1];let l;r.settings.strict&&r.settings.reportNonstrict("htmlExtension","HTML extension is disabled on strict mode");const h={};switch(o){case"\\htmlClass":h.class=i,l={command:"\\htmlClass",class:i};break;case"\\htmlId":h.id=i,l={command:"\\htmlId",id:i};break;case"\\htmlStyle":h.style=i,l={command:"\\htmlStyle",style:i};break;case"\\htmlData":{const e=i.split(",");for(let t=0;t{const r=nt(e.body,t,!1),n=["enclosing"];e.attributes.class&&n.push(...e.attributes.class.trim().split(/\s+/));const o=Ve.makeSpan(n,r,t);for(const t in e.attributes)"class"!==t&&e.attributes.hasOwnProperty(t)&&o.setAttribute(t,e.attributes[t]);return o},mathmlBuilder:(e,t)=>wt(e.body,t)}),je({type:"htmlmathml",names:["\\html@mathml"],props:{numArgs:2,allowedInText:!0},handler:(e,t)=>{let{parser:r}=e;return{type:"htmlmathml",mode:r.mode,html:Ke(t[0]),mathml:Ke(t[1])}},htmlBuilder:(e,t)=>{const r=nt(e.html,t,!1);return Ve.makeFragment(r)},mathmlBuilder:(e,t)=>wt(e.mathml,t)});const Zr=function(e){if(/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(e))return{number:+e,unit:"bp"};{const t=/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(e);if(!t)throw new n("Invalid size: '"+e+"' in \\includegraphics");const r={number:+(t[1]+t[2]),unit:t[3]};if(!V(r))throw new n("Invalid unit: '"+r.unit+"' in \\includegraphics.");return r}};je({type:"includegraphics",names:["\\includegraphics"],props:{numArgs:1,numOptionalArgs:1,argTypes:["raw","url"],allowedInText:!1},handler:(e,t,r)=>{let{parser:o}=e,s={number:0,unit:"em"},i={number:.9,unit:"em"},a={number:0,unit:"em"},l="";if(r[0]){const e=qt(r[0],"raw").string.split(",");for(let t=0;t{const r=P(e.height,t);let n=0;e.totalheight.number>0&&(n=P(e.totalheight,t)-r);let o=0;e.width.number>0&&(o=P(e.width,t));const s={height:F(r+n)};o>0&&(s.width=F(o)),n>0&&(s.verticalAlign=F(-n));const i=new j(e.src,e.alt,s);return i.height=r,i.depth=n,i},mathmlBuilder:(e,t)=>{const r=new gt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);const n=P(e.height,t);let o=0;if(e.totalheight.number>0&&(o=P(e.totalheight,t)-n,r.setAttribute("valign",F(-o))),r.setAttribute("height",F(n+o)),e.width.number>0){const n=P(e.width,t);r.setAttribute("width",F(n))}return r.setAttribute("src",e.src),r}}),je({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler(e,t){let{parser:r,funcName:n}=e;const o=qt(t[0],"size");if(r.settings.strict){const e="m"===n[1],t="mu"===o.value.unit;e?(t||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+o.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):t&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:o.value}},htmlBuilder(e,t){return Ve.makeGlue(e.dimension,t)},mathmlBuilder(e,t){const r=P(e.dimension,t);return new gt.SpaceNode(r)}}),je({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:(e,t)=>{let{parser:r,funcName:n}=e;const o=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:o}},htmlBuilder:(e,t)=>{let r;"clap"===e.alignment?(r=Ve.makeSpan([],[ht(e.body,t)]),r=Ve.makeSpan(["inner"],[r],t)):r=Ve.makeSpan(["inner"],[ht(e.body,t)]);const n=Ve.makeSpan(["fix"],[]);let o=Ve.makeSpan([e.alignment],[r,n],t);const s=Ve.makeSpan(["strut"]);return s.style.height=F(o.height+o.depth),o.depth&&(s.style.verticalAlign=F(-o.depth)),o.children.unshift(s),o=Ve.makeSpan(["thinbox"],[o],t),Ve.makeSpan(["mord","vbox"],[o],t)},mathmlBuilder:(e,t)=>{const r=new gt.MathNode("mpadded",[vt(e.body,t)]);if("rlap"!==e.alignment){const t="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",t+"width")}return r.setAttribute("width","0px"),r}}),je({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler(e,t){let{funcName:r,parser:n}=e;const o=n.mode;n.switchMode("math");const s="\\("===r?"\\)":"$",i=n.parseExpression(!1,s);return n.expect(s),n.switchMode(o),{type:"styling",mode:n.mode,style:"text",body:i}}}),je({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler(e,t){throw new n("Mismatched "+e.funcName)}});const Kr=(e,t)=>{switch(t.style.size){case w.DISPLAY.size:return e.display;case w.TEXT.size:return e.text;case w.SCRIPT.size:return e.script;case w.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};je({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:(e,t)=>{let{parser:r}=e;return{type:"mathchoice",mode:r.mode,display:Ke(t[0]),text:Ke(t[1]),script:Ke(t[2]),scriptscript:Ke(t[3])}},htmlBuilder:(e,t)=>{const r=Kr(e,t),n=nt(r,t,!1);return Ve.makeFragment(n)},mathmlBuilder:(e,t)=>{const r=Kr(e,t);return wt(r,t)}});const Jr=(e,t,r,n,o,s,i)=>{e=Ve.makeSpan([],[e]);const a=r&&l.isCharacterBox(r);let h,c,m;if(t){const e=ht(t,n.havingStyle(o.sup()),n);c={elem:e,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-e.depth)}}if(r){const e=ht(r,n.havingStyle(o.sub()),n);h={elem:e,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-e.height)}}if(c&&h){const t=n.fontMetrics().bigOpSpacing5+h.elem.height+h.elem.depth+h.kern+e.depth+i;m=Ve.makeVList({positionType:"bottom",positionData:t,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:h.elem,marginLeft:F(-s)},{type:"kern",size:h.kern},{type:"elem",elem:e},{type:"kern",size:c.kern},{type:"elem",elem:c.elem,marginLeft:F(s)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(h){const t=e.height-i;m=Ve.makeVList({positionType:"top",positionData:t,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:h.elem,marginLeft:F(-s)},{type:"kern",size:h.kern},{type:"elem",elem:e}]},n)}else{if(!c)return e;{const t=e.depth+i;m=Ve.makeVList({positionType:"bottom",positionData:t,children:[{type:"elem",elem:e},{type:"kern",size:c.kern},{type:"elem",elem:c.elem,marginLeft:F(s)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}}const p=[m];if(h&&0!==s&&!a){const e=Ve.makeSpan(["mspace"],[],n);e.style.marginRight=F(s),p.unshift(e)}return Ve.makeSpan(["mop","op-limits"],p,n)},Qr=["\\smallint"],en=(e,t)=>{let r,n,o,s=!1;"supsub"===e.type?(r=e.sup,n=e.sub,o=qt(e.base,"op"),s=!0):o=qt(e,"op");const i=t.style;let a,h=!1;if(i.size===w.DISPLAY.size&&o.symbol&&!l.contains(Qr,o.name)&&(h=!0),o.symbol){const e=h?"Size2-Regular":"Size1-Regular";let r="";if("\\oiint"!==o.name&&"\\oiiint"!==o.name||(r=o.name.slice(1),o.name="oiint"===r?"\\iint":"\\iiint"),a=Ve.makeSymbol(o.name,e,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),r.length>0){const e=a.italic,n=Ve.staticSvg(r+"Size"+(h?"2":"1"),t);a=Ve.makeVList({positionType:"individualShift",children:[{type:"elem",elem:a,shift:0},{type:"elem",elem:n,shift:h?.08:0}]},t),o.name="\\"+r,a.classes.unshift("mop"),a.italic=e}}else if(o.body){const e=nt(o.body,t,!0);1===e.length&&e[0]instanceof Z?(a=e[0],a.classes[0]="mop"):a=Ve.makeSpan(["mop"],e,t)}else{const e=[];for(let r=1;r{let r;if(e.symbol)r=new ut("mo",[ft(e.name,e.mode)]),l.contains(Qr,e.name)&&r.setAttribute("largeop","false");else if(e.body)r=new ut("mo",xt(e.body,t));else{r=new ut("mi",[new dt(e.name.slice(1))]);const t=new ut("mo",[ft("\u2061","text")]);r=e.parentIsSupSub?new ut("mrow",[r,t]):pt([r,t])}return r},rn={"\u220f":"\\prod","\u2210":"\\coprod","\u2211":"\\sum","\u22c0":"\\bigwedge","\u22c1":"\\bigvee","\u22c2":"\\bigcap","\u22c3":"\\bigcup","\u2a00":"\\bigodot","\u2a01":"\\bigoplus","\u2a02":"\\bigotimes","\u2a04":"\\biguplus","\u2a06":"\\bigsqcup"};je({type:"op",names:["\\coprod","\\bigvee","\\bigwedge","\\biguplus","\\bigcap","\\bigcup","\\intop","\\prod","\\sum","\\bigotimes","\\bigoplus","\\bigodot","\\bigsqcup","\\smallint","\u220f","\u2210","\u2211","\u22c0","\u22c1","\u22c2","\u22c3","\u2a00","\u2a01","\u2a02","\u2a04","\u2a06"],props:{numArgs:0},handler:(e,t)=>{let{parser:r,funcName:n}=e,o=n;return 1===o.length&&(o=rn[o]),{type:"op",mode:r.mode,limits:!0,parentIsSupSub:!1,symbol:!0,name:o}},htmlBuilder:en,mathmlBuilder:tn}),je({type:"op",names:["\\mathop"],props:{numArgs:1,primitive:!0},handler:(e,t)=>{let{parser:r}=e;const n=t[0];return{type:"op",mode:r.mode,limits:!1,parentIsSupSub:!1,symbol:!1,body:Ke(n)}},htmlBuilder:en,mathmlBuilder:tn});const nn={"\u222b":"\\int","\u222c":"\\iint","\u222d":"\\iiint","\u222e":"\\oint","\u222f":"\\oiint","\u2230":"\\oiiint"};je({type:"op",names:["\\arcsin","\\arccos","\\arctan","\\arctg","\\arcctg","\\arg","\\ch","\\cos","\\cosec","\\cosh","\\cot","\\cotg","\\coth","\\csc","\\ctg","\\cth","\\deg","\\dim","\\exp","\\hom","\\ker","\\lg","\\ln","\\log","\\sec","\\sin","\\sinh","\\sh","\\tan","\\tanh","\\tg","\\th"],props:{numArgs:0},handler(e){let{parser:t,funcName:r}=e;return{type:"op",mode:t.mode,limits:!1,parentIsSupSub:!1,symbol:!1,name:r}},htmlBuilder:en,mathmlBuilder:tn}),je({type:"op",names:["\\det","\\gcd","\\inf","\\lim","\\max","\\min","\\Pr","\\sup"],props:{numArgs:0},handler(e){let{parser:t,funcName:r}=e;return{type:"op",mode:t.mode,limits:!0,parentIsSupSub:!1,symbol:!1,name:r}},htmlBuilder:en,mathmlBuilder:tn}),je({type:"op",names:["\\int","\\iint","\\iiint","\\oint","\\oiint","\\oiiint","\u222b","\u222c","\u222d","\u222e","\u222f","\u2230"],props:{numArgs:0},handler(e){let{parser:t,funcName:r}=e,n=r;return 1===n.length&&(n=nn[n]),{type:"op",mode:t.mode,limits:!1,parentIsSupSub:!1,symbol:!0,name:n}},htmlBuilder:en,mathmlBuilder:tn});const on=(e,t)=>{let r,n,o,s,i=!1;if("supsub"===e.type?(r=e.sup,n=e.sub,o=qt(e.base,"operatorname"),i=!0):o=qt(e,"operatorname"),o.body.length>0){const e=o.body.map((e=>{const t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),r=nt(e,t.withFont("mathrm"),!0);for(let e=0;e{let{parser:r,funcName:n}=e;const o=t[0];return{type:"operatorname",mode:r.mode,body:Ke(o),alwaysHandleSupSub:"\\operatornamewithlimits"===n,limits:!1,parentIsSupSub:!1}},htmlBuilder:on,mathmlBuilder:(e,t)=>{let r=xt(e.body,t.withFont("mathrm")),n=!0;for(let e=0;ee.toText())).join("");r=[new gt.TextNode(e)]}const o=new gt.MathNode("mi",r);o.setAttribute("mathvariant","normal");const s=new gt.MathNode("mo",[ft("\u2061","text")]);return e.parentIsSupSub?new gt.MathNode("mrow",[o,s]):gt.newDocumentFragment([o,s])}}),Br("\\operatorname","\\@ifstar\\operatornamewithlimits\\operatorname@"),$e({type:"ordgroup",htmlBuilder(e,t){return e.semisimple?Ve.makeFragment(nt(e.body,t,!1)):Ve.makeSpan(["mord"],nt(e.body,t,!0),t)},mathmlBuilder(e,t){return wt(e.body,t,!0)}}),je({type:"overline",names:["\\overline"],props:{numArgs:1},handler(e,t){let{parser:r}=e;const n=t[0];return{type:"overline",mode:r.mode,body:n}},htmlBuilder(e,t){const r=ht(e.body,t.havingCrampedStyle()),n=Ve.makeLineSpan("overline-line",t),o=t.fontMetrics().defaultRuleThickness,s=Ve.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r},{type:"kern",size:3*o},{type:"elem",elem:n},{type:"kern",size:o}]},t);return Ve.makeSpan(["mord","overline"],[s],t)},mathmlBuilder(e,t){const r=new gt.MathNode("mo",[new gt.TextNode("\u203e")]);r.setAttribute("stretchy","true");const n=new gt.MathNode("mover",[vt(e.body,t),r]);return n.setAttribute("accent","true"),n}}),je({type:"phantom",names:["\\phantom"],props:{numArgs:1,allowedInText:!0},handler:(e,t)=>{let{parser:r}=e;const n=t[0];return{type:"phantom",mode:r.mode,body:Ke(n)}},htmlBuilder:(e,t)=>{const r=nt(e.body,t.withPhantom(),!1);return Ve.makeFragment(r)},mathmlBuilder:(e,t)=>{const r=xt(e.body,t);return new gt.MathNode("mphantom",r)}}),je({type:"hphantom",names:["\\hphantom"],props:{numArgs:1,allowedInText:!0},handler:(e,t)=>{let{parser:r}=e;const n=t[0];return{type:"hphantom",mode:r.mode,body:n}},htmlBuilder:(e,t)=>{let r=Ve.makeSpan([],[ht(e.body,t.withPhantom())]);if(r.height=0,r.depth=0,r.children)for(let e=0;e{const r=xt(Ke(e.body),t),n=new gt.MathNode("mphantom",r),o=new gt.MathNode("mpadded",[n]);return o.setAttribute("height","0px"),o.setAttribute("depth","0px"),o}}),je({type:"vphantom",names:["\\vphantom"],props:{numArgs:1,allowedInText:!0},handler:(e,t)=>{let{parser:r}=e;const n=t[0];return{type:"vphantom",mode:r.mode,body:n}},htmlBuilder:(e,t)=>{const r=Ve.makeSpan(["inner"],[ht(e.body,t.withPhantom())]),n=Ve.makeSpan(["fix"],[]);return Ve.makeSpan(["mord","rlap"],[r,n],t)},mathmlBuilder:(e,t)=>{const r=xt(Ke(e.body),t),n=new gt.MathNode("mphantom",r),o=new gt.MathNode("mpadded",[n]);return o.setAttribute("width","0px"),o}}),je({type:"raisebox",names:["\\raisebox"],props:{numArgs:2,argTypes:["size","hbox"],allowedInText:!0},handler(e,t){let{parser:r}=e;const n=qt(t[0],"size").value,o=t[1];return{type:"raisebox",mode:r.mode,dy:n,body:o}},htmlBuilder(e,t){const r=ht(e.body,t),n=P(e.dy,t);return Ve.makeVList({positionType:"shift",positionData:-n,children:[{type:"elem",elem:r}]},t)},mathmlBuilder(e,t){const r=new gt.MathNode("mpadded",[vt(e.body,t)]),n=e.dy.number+e.dy.unit;return r.setAttribute("voffset",n),r}}),je({type:"internal",names:["\\relax"],props:{numArgs:0,allowedInText:!0},handler(e){let{parser:t}=e;return{type:"internal",mode:t.mode}}}),je({type:"rule",names:["\\rule"],props:{numArgs:2,numOptionalArgs:1,argTypes:["size","size","size"]},handler(e,t,r){let{parser:n}=e;const o=r[0],s=qt(t[0],"size"),i=qt(t[1],"size");return{type:"rule",mode:n.mode,shift:o&&qt(o,"size").value,width:s.value,height:i.value}},htmlBuilder(e,t){const r=Ve.makeSpan(["mord","rule"],[],t),n=P(e.width,t),o=P(e.height,t),s=e.shift?P(e.shift,t):0;return r.style.borderRightWidth=F(n),r.style.borderTopWidth=F(o),r.style.bottom=F(s),r.width=n,r.height=o+s,r.depth=-s,r.maxFontSize=1.125*o*t.sizeMultiplier,r},mathmlBuilder(e,t){const r=P(e.width,t),n=P(e.height,t),o=e.shift?P(e.shift,t):0,s=t.color&&t.getColor()||"black",i=new gt.MathNode("mspace");i.setAttribute("mathbackground",s),i.setAttribute("width",F(r)),i.setAttribute("height",F(n));const a=new gt.MathNode("mpadded",[i]);return o>=0?a.setAttribute("height",F(o)):(a.setAttribute("height",F(o)),a.setAttribute("depth",F(-o))),a.setAttribute("voffset",F(o)),a}});const an=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];je({type:"sizing",names:an,props:{numArgs:0,allowedInText:!0},handler:(e,t)=>{let{breakOnTokenText:r,funcName:n,parser:o}=e;const s=o.parseExpression(!1,r);return{type:"sizing",mode:o.mode,size:an.indexOf(n)+1,body:s}},htmlBuilder:(e,t)=>{const r=t.havingSize(e.size);return sn(e.body,r,t)},mathmlBuilder:(e,t)=>{const r=t.havingSize(e.size),n=xt(e.body,r),o=new gt.MathNode("mstyle",n);return o.setAttribute("mathsize",F(r.sizeMultiplier)),o}}),je({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:(e,t,r)=>{let{parser:n}=e,o=!1,s=!1;const i=r[0]&&qt(r[0],"ordgroup");if(i){let e="";for(let t=0;t{const r=Ve.makeSpan([],[ht(e.body,t)]);if(!e.smashHeight&&!e.smashDepth)return r;if(e.smashHeight&&(r.height=0,r.children))for(let e=0;e{const r=new gt.MathNode("mpadded",[vt(e.body,t)]);return e.smashHeight&&r.setAttribute("height","0px"),e.smashDepth&&r.setAttribute("depth","0px"),r}}),je({type:"sqrt",names:["\\sqrt"],props:{numArgs:1,numOptionalArgs:1},handler(e,t,r){let{parser:n}=e;const o=r[0],s=t[0];return{type:"sqrt",mode:n.mode,body:s,index:o}},htmlBuilder(e,t){let r=ht(e.body,t.havingCrampedStyle());0===r.height&&(r.height=t.fontMetrics().xHeight),r=Ve.wrapFragment(r,t);const n=t.fontMetrics().defaultRuleThickness;let o=n;t.style.idr.height+r.depth+s&&(s=(s+c-r.height-r.depth)/2);const m=a.height-r.height-s-l;r.style.paddingLeft=F(h);const p=Ve.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+m)},{type:"elem",elem:a},{type:"kern",size:l}]},t);if(e.index){const r=t.havingStyle(w.SCRIPTSCRIPT),n=ht(e.index,r,t),o=.6*(p.height-p.depth),s=Ve.makeVList({positionType:"shift",positionData:-o,children:[{type:"elem",elem:n}]},t),i=Ve.makeSpan(["root"],[s]);return Ve.makeSpan(["mord","sqrt"],[i,p],t)}return Ve.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder(e,t){const{body:r,index:n}=e;return n?new gt.MathNode("mroot",[vt(r,t),vt(n,t)]):new gt.MathNode("msqrt",[vt(r,t)])}});const ln={display:w.DISPLAY,text:w.TEXT,script:w.SCRIPT,scriptscript:w.SCRIPTSCRIPT};je({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler(e,t){let{breakOnTokenText:r,funcName:n,parser:o}=e;const s=o.parseExpression(!0,r),i=n.slice(1,n.length-5);return{type:"styling",mode:o.mode,style:i,body:s}},htmlBuilder(e,t){const r=ln[e.style],n=t.havingStyle(r).withFont("");return sn(e.body,n,t)},mathmlBuilder(e,t){const r=ln[e.style],n=t.havingStyle(r),o=xt(e.body,n),s=new gt.MathNode("mstyle",o),i={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return s.setAttribute("scriptlevel",i[0]),s.setAttribute("displaystyle",i[1]),s}});$e({type:"supsub",htmlBuilder(e,t){const r=function(e,t){const r=e.base;if(r)return"op"===r.type?r.limits&&(t.style.size===w.DISPLAY.size||r.alwaysHandleSupSub)?en:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===w.DISPLAY.size||r.limits)?on:null:"accent"===r.type?l.isCharacterBox(r.base)?Ht:null:"horizBrace"===r.type&&!e.sub===r.isOver?$r:null;return null}(e,t);if(r)return r(e,t);const{base:n,sup:o,sub:s}=e,i=ht(n,t);let a,h;const c=t.fontMetrics();let m=0,p=0;const u=n&&l.isCharacterBox(n);if(o){const e=t.havingStyle(t.style.sup());a=ht(o,e,t),u||(m=i.height-e.fontMetrics().supDrop*e.sizeMultiplier/t.sizeMultiplier)}if(s){const e=t.havingStyle(t.style.sub());h=ht(s,e,t),u||(p=i.depth+e.fontMetrics().subDrop*e.sizeMultiplier/t.sizeMultiplier)}let d;d=t.style===w.DISPLAY?c.sup1:t.style.cramped?c.sup3:c.sup2;const g=t.sizeMultiplier,f=F(.5/c.ptPerEm/g);let b,y=null;if(h){const t=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(i instanceof Z||t)&&(y=F(-i.italic))}if(a&&h){m=Math.max(m,d,a.depth+.25*c.xHeight),p=Math.max(p,c.sub2);const e=4*c.defaultRuleThickness;if(m-a.depth-(h.height-p)0&&(m+=t,p-=t)}const r=[{type:"elem",elem:h,shift:p,marginRight:f,marginLeft:y},{type:"elem",elem:a,shift:-m,marginRight:f}];b=Ve.makeVList({positionType:"individualShift",children:r},t)}else if(h){p=Math.max(p,c.sub1,h.height-.8*c.xHeight);const e=[{type:"elem",elem:h,marginLeft:y,marginRight:f}];b=Ve.makeVList({positionType:"shift",positionData:p,children:e},t)}else{if(!a)throw new Error("supsub must have either sup or sub.");m=Math.max(m,d,a.depth+.25*c.xHeight),b=Ve.makeVList({positionType:"shift",positionData:-m,children:[{type:"elem",elem:a,marginRight:f}]},t)}const x=at(i,"right")||"mord";return Ve.makeSpan([x],[i,Ve.makeSpan(["msupsub"],[b])],t)},mathmlBuilder(e,t){let r,n,o=!1;e.base&&"horizBrace"===e.base.type&&(n=!!e.sup,n===e.base.isOver&&(o=!0,r=e.base.isOver)),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);const s=[vt(e.base,t)];let i;if(e.sub&&s.push(vt(e.sub,t)),e.sup&&s.push(vt(e.sup,t)),o)i=r?"mover":"munder";else if(e.sub)if(e.sup){const r=e.base;i=r&&"op"===r.type&&r.limits&&t.style===w.DISPLAY||r&&"operatorname"===r.type&&r.alwaysHandleSupSub&&(t.style===w.DISPLAY||r.limits)?"munderover":"msubsup"}else{const r=e.base;i=r&&"op"===r.type&&r.limits&&(t.style===w.DISPLAY||r.alwaysHandleSupSub)||r&&"operatorname"===r.type&&r.alwaysHandleSupSub&&(r.limits||t.style===w.DISPLAY)?"munder":"msub"}else{const r=e.base;i=r&&"op"===r.type&&r.limits&&(t.style===w.DISPLAY||r.alwaysHandleSupSub)||r&&"operatorname"===r.type&&r.alwaysHandleSupSub&&(r.limits||t.style===w.DISPLAY)?"mover":"msup"}return new gt.MathNode(i,s)}}),$e({type:"atom",htmlBuilder(e,t){return Ve.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder(e,t){const r=new gt.MathNode("mo",[ft(e.text,e.mode)]);if("bin"===e.family){const n=yt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});const hn={mi:"italic",mn:"normal",mtext:"normal"};$e({type:"mathord",htmlBuilder(e,t){return Ve.makeOrd(e,t,"mathord")},mathmlBuilder(e,t){const r=new gt.MathNode("mi",[ft(e.text,e.mode,t)]),n=yt(e,t)||"italic";return n!==hn[r.type]&&r.setAttribute("mathvariant",n),r}}),$e({type:"textord",htmlBuilder(e,t){return Ve.makeOrd(e,t,"textord")},mathmlBuilder(e,t){const r=ft(e.text,e.mode,t),n=yt(e,t)||"normal";let o;return o="text"===e.mode?new gt.MathNode("mtext",[r]):/[0-9]/.test(e.text)?new gt.MathNode("mn",[r]):"\\prime"===e.text?new gt.MathNode("mo",[r]):new gt.MathNode("mi",[r]),n!==hn[o.type]&&o.setAttribute("mathvariant",n),o}});const cn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},mn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};$e({type:"spacing",htmlBuilder(e,t){if(mn.hasOwnProperty(e.text)){const r=mn[e.text].className||"";if("text"===e.mode){const n=Ve.makeOrd(e,t,"textord");return n.classes.push(r),n}return Ve.makeSpan(["mspace",r],[Ve.mathsym(e.text,e.mode,t)],t)}if(cn.hasOwnProperty(e.text))return Ve.makeSpan(["mspace",cn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder(e,t){let r;if(!mn.hasOwnProperty(e.text)){if(cn.hasOwnProperty(e.text))return new gt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return r=new gt.MathNode("mtext",[new gt.TextNode("\xa0")]),r}});const pn=()=>{const e=new gt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};$e({type:"tag",mathmlBuilder(e,t){const r=new gt.MathNode("mtable",[new gt.MathNode("mtr",[pn(),new gt.MathNode("mtd",[wt(e.body,t)]),pn(),new gt.MathNode("mtd",[wt(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});const un={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},dn={"\\textbf":"textbf","\\textmd":"textmd"},gn={"\\textit":"textit","\\textup":"textup"},fn=(e,t)=>{const r=e.font;return r?un[r]?t.withTextFontFamily(un[r]):dn[r]?t.withTextFontWeight(dn[r]):"\\emph"===r?"textit"===t.fontShape?t.withTextFontShape("textup"):t.withTextFontShape("textit"):t.withTextFontShape(gn[r]):t};je({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup","\\emph"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler(e,t){let{parser:r,funcName:n}=e;const o=t[0];return{type:"text",mode:r.mode,body:Ke(o),font:n}},htmlBuilder(e,t){const r=fn(e,t),n=nt(e.body,r,!0);return Ve.makeSpan(["mord","text"],n,r)},mathmlBuilder(e,t){const r=fn(e,t);return wt(e.body,r)}}),je({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler(e,t){let{parser:r}=e;return{type:"underline",mode:r.mode,body:t[0]}},htmlBuilder(e,t){const r=ht(e.body,t),n=Ve.makeLineSpan("underline-line",t),o=t.fontMetrics().defaultRuleThickness,s=Ve.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:o},{type:"elem",elem:n},{type:"kern",size:3*o},{type:"elem",elem:r}]},t);return Ve.makeSpan(["mord","underline"],[s],t)},mathmlBuilder(e,t){const r=new gt.MathNode("mo",[new gt.TextNode("\u203e")]);r.setAttribute("stretchy","true");const n=new gt.MathNode("munder",[vt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),je({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler(e,t){let{parser:r}=e;return{type:"vcenter",mode:r.mode,body:t[0]}},htmlBuilder(e,t){const r=ht(e.body,t),n=t.fontMetrics().axisHeight,o=.5*(r.height-n-(r.depth+n));return Ve.makeVList({positionType:"shift",positionData:o,children:[{type:"elem",elem:r}]},t)},mathmlBuilder(e,t){return new gt.MathNode("mpadded",[vt(e.body,t)],["vcenter"])}}),je({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder(e,t){const r=bn(e),n=[],o=t.havingStyle(t.style.text());for(let t=0;te.body.replace(/ /g,e.star?"\u2423":"\xa0");var yn=Xe;const xn="[ \r\n\t]",wn="(\\\\[a-zA-Z@]+)"+xn+"*",vn="[\u0300-\u036f]",kn=new RegExp(vn+"+$"),Sn="("+xn+"+)|\\\\(\n|[ \r\t]+\n?)[ \r\t]*|([!-\\[\\]-\u2027\u202a-\ud7ff\uf900-\uffff]"+vn+"*|[\ud800-\udbff][\udc00-\udfff]"+vn+"*|\\\\verb\\*([^]).*?\\4|\\\\verb([^*a-zA-Z]).*?\\5|"+wn+"|\\\\[^\ud800-\udfff])";class Mn{constructor(e,t){this.input=void 0,this.settings=void 0,this.tokenRegex=void 0,this.catcodes=void 0,this.input=e,this.settings=t,this.tokenRegex=new RegExp(Sn,"g"),this.catcodes={"%":14,"~":13}}setCatcode(e,t){this.catcodes[e]=t}lex(){const e=this.input,t=this.tokenRegex.lastIndex;if(t===e.length)return new Nr("EOF",new Cr(this,t,t));const r=this.tokenRegex.exec(e);if(null===r||r.index!==t)throw new n("Unexpected character: '"+e[t]+"'",new Nr(e[t],new Cr(this,t,t+1)));const o=r[6]||r[3]||(r[2]?"\\ ":" ");if(14===this.catcodes[o]){const t=e.indexOf("\n",this.tokenRegex.lastIndex);return-1===t?(this.tokenRegex.lastIndex=e.length,this.settings.reportNonstrict("commentAtEnd","% comment has no terminating newline; LaTeX would fail because of commenting the end of math mode (e.g. $)")):this.tokenRegex.lastIndex=t+1,this.lex()}return new Nr(o,new Cr(this,t,this.tokenRegex.lastIndex))}}class zn{constructor(e,t){void 0===e&&(e={}),void 0===t&&(t={}),this.current=void 0,this.builtins=void 0,this.undefStack=void 0,this.current=t,this.builtins=e,this.undefStack=[]}beginGroup(){this.undefStack.push({})}endGroup(){if(0===this.undefStack.length)throw new n("Unbalanced namespace destruction: attempt to pop global namespace; please report this as a bug");const e=this.undefStack.pop();for(const t in e)e.hasOwnProperty(t)&&(null==e[t]?delete this.current[t]:this.current[t]=e[t])}endGroups(){for(;this.undefStack.length>0;)this.endGroup()}has(e){return this.current.hasOwnProperty(e)||this.builtins.hasOwnProperty(e)}get(e){return this.current.hasOwnProperty(e)?this.current[e]:this.builtins[e]}set(e,t,r){if(void 0===r&&(r=!1),r){for(let t=0;t0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{const t=this.undefStack[this.undefStack.length-1];t&&!t.hasOwnProperty(e)&&(t[e]=this.current[e])}null==t?delete this.current[e]:this.current[e]=t}}var An=Tr;Br("\\noexpand",(function(e){const t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),Br("\\expandafter",(function(e){const t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),Br("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),Br("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),Br("\\@ifnextchar",(function(e){const t=e.consumeArgs(3);e.consumeSpaces();const r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),Br("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),Br("\\TextOrMath",(function(e){const t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));const Tn={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};Br("\\char",(function(e){let t,r=e.popToken(),o="";if("'"===r.text)t=8,r=e.popToken();else if('"'===r.text)t=16,r=e.popToken();else if("`"===r.text)if(r=e.popToken(),"\\"===r.text[0])o=r.text.charCodeAt(1);else{if("EOF"===r.text)throw new n("\\char` missing argument");o=r.text.charCodeAt(0)}else t=10;if(t){if(o=Tn[r.text],null==o||o>=t)throw new n("Invalid base-"+t+" digit "+r.text);let s;for(;null!=(s=Tn[e.future().text])&&s{let o=e.consumeArg().tokens;if(1!==o.length)throw new n("\\newcommand's first argument must be a macro name");const s=o[0].text,i=e.isDefined(s);if(i&&!t)throw new n("\\newcommand{"+s+"} attempting to redefine "+s+"; use \\renewcommand");if(!i&&!r)throw new n("\\renewcommand{"+s+"} when command "+s+" does not yet exist; use \\newcommand");let a=0;if(o=e.consumeArg().tokens,1===o.length&&"["===o[0].text){let t="",r=e.expandNextToken();for(;"]"!==r.text&&"EOF"!==r.text;)t+=r.text,r=e.expandNextToken();if(!t.match(/^\s*[0-9]+\s*$/))throw new n("Invalid number of arguments: "+t);a=parseInt(t),o=e.consumeArg().tokens}return e.macros.set(s,{tokens:o,numArgs:a}),""};Br("\\newcommand",(e=>Bn(e,!1,!0))),Br("\\renewcommand",(e=>Bn(e,!0,!1))),Br("\\providecommand",(e=>Bn(e,!0,!0))),Br("\\message",(e=>{const t=e.consumeArgs(1)[0];return console.log(t.reverse().map((e=>e.text)).join("")),""})),Br("\\errmessage",(e=>{const t=e.consumeArgs(1)[0];return console.error(t.reverse().map((e=>e.text)).join("")),""})),Br("\\show",(e=>{const t=e.popToken(),r=t.text;return console.log(t,e.macros.get(r),yn[r],oe.math[r],oe.text[r]),""})),Br("\\bgroup","{"),Br("\\egroup","}"),Br("~","\\nobreakspace"),Br("\\lq","`"),Br("\\rq","'"),Br("\\aa","\\r a"),Br("\\AA","\\r A"),Br("\\textcopyright","\\html@mathml{\\textcircled{c}}{\\char`\xa9}"),Br("\\copyright","\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}"),Br("\\textregistered","\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`\xae}"),Br("\u212c","\\mathscr{B}"),Br("\u2130","\\mathscr{E}"),Br("\u2131","\\mathscr{F}"),Br("\u210b","\\mathscr{H}"),Br("\u2110","\\mathscr{I}"),Br("\u2112","\\mathscr{L}"),Br("\u2133","\\mathscr{M}"),Br("\u211b","\\mathscr{R}"),Br("\u212d","\\mathfrak{C}"),Br("\u210c","\\mathfrak{H}"),Br("\u2128","\\mathfrak{Z}"),Br("\\Bbbk","\\Bbb{k}"),Br("\xb7","\\cdotp"),Br("\\llap","\\mathllap{\\textrm{#1}}"),Br("\\rlap","\\mathrlap{\\textrm{#1}}"),Br("\\clap","\\mathclap{\\textrm{#1}}"),Br("\\mathstrut","\\vphantom{(}"),Br("\\underbar","\\underline{\\text{#1}}"),Br("\\not",'\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'),Br("\\neq","\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`\u2260}}"),Br("\\ne","\\neq"),Br("\u2260","\\neq"),Br("\\notin","\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}{\\mathrel{\\char`\u2209}}"),Br("\u2209","\\notin"),Br("\u2258","\\html@mathml{\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}}{\\mathrel{\\char`\u2258}}"),Br("\u2259","\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}"),Br("\u225a","\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225a}}"),Br("\u225b","\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}{\\mathrel{\\char`\u225b}}"),Br("\u225d","\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}{\\mathrel{\\char`\u225d}}"),Br("\u225e","\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}{\\mathrel{\\char`\u225e}}"),Br("\u225f","\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225f}}"),Br("\u27c2","\\perp"),Br("\u203c","\\mathclose{!\\mkern-0.8mu!}"),Br("\u220c","\\notni"),Br("\u231c","\\ulcorner"),Br("\u231d","\\urcorner"),Br("\u231e","\\llcorner"),Br("\u231f","\\lrcorner"),Br("\xa9","\\copyright"),Br("\xae","\\textregistered"),Br("\ufe0f","\\textregistered"),Br("\\ulcorner",'\\html@mathml{\\@ulcorner}{\\mathop{\\char"231c}}'),Br("\\urcorner",'\\html@mathml{\\@urcorner}{\\mathop{\\char"231d}}'),Br("\\llcorner",'\\html@mathml{\\@llcorner}{\\mathop{\\char"231e}}'),Br("\\lrcorner",'\\html@mathml{\\@lrcorner}{\\mathop{\\char"231f}}'),Br("\\vdots","\\mathord{\\varvdots\\rule{0pt}{15pt}}"),Br("\u22ee","\\vdots"),Br("\\varGamma","\\mathit{\\Gamma}"),Br("\\varDelta","\\mathit{\\Delta}"),Br("\\varTheta","\\mathit{\\Theta}"),Br("\\varLambda","\\mathit{\\Lambda}"),Br("\\varXi","\\mathit{\\Xi}"),Br("\\varPi","\\mathit{\\Pi}"),Br("\\varSigma","\\mathit{\\Sigma}"),Br("\\varUpsilon","\\mathit{\\Upsilon}"),Br("\\varPhi","\\mathit{\\Phi}"),Br("\\varPsi","\\mathit{\\Psi}"),Br("\\varOmega","\\mathit{\\Omega}"),Br("\\substack","\\begin{subarray}{c}#1\\end{subarray}"),Br("\\colon","\\nobreak\\mskip2mu\\mathpunct{}\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"),Br("\\boxed","\\fbox{$\\displaystyle{#1}$}"),Br("\\iff","\\DOTSB\\;\\Longleftrightarrow\\;"),Br("\\implies","\\DOTSB\\;\\Longrightarrow\\;"),Br("\\impliedby","\\DOTSB\\;\\Longleftarrow\\;");const Cn={",":"\\dotsc","\\not":"\\dotsb","+":"\\dotsb","=":"\\dotsb","<":"\\dotsb",">":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};Br("\\dots",(function(e){let t="\\dotso";const r=e.expandAfterFuture().text;return r in Cn?t=Cn[r]:("\\not"===r.slice(0,4)||r in oe.math&&l.contains(["bin","rel"],oe.math[r].group))&&(t="\\dotsb"),t}));const Nn={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};Br("\\dotso",(function(e){return e.future().text in Nn?"\\ldots\\,":"\\ldots"})),Br("\\dotsc",(function(e){const t=e.future().text;return t in Nn&&","!==t?"\\ldots\\,":"\\ldots"})),Br("\\cdots",(function(e){return e.future().text in Nn?"\\@cdots\\,":"\\@cdots"})),Br("\\dotsb","\\cdots"),Br("\\dotsm","\\cdots"),Br("\\dotsi","\\!\\cdots"),Br("\\dotsx","\\ldots\\,"),Br("\\DOTSI","\\relax"),Br("\\DOTSB","\\relax"),Br("\\DOTSX","\\relax"),Br("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),Br("\\,","\\tmspace+{3mu}{.1667em}"),Br("\\thinspace","\\,"),Br("\\>","\\mskip{4mu}"),Br("\\:","\\tmspace+{4mu}{.2222em}"),Br("\\medspace","\\:"),Br("\\;","\\tmspace+{5mu}{.2777em}"),Br("\\thickspace","\\;"),Br("\\!","\\tmspace-{3mu}{.1667em}"),Br("\\negthinspace","\\!"),Br("\\negmedspace","\\tmspace-{4mu}{.2222em}"),Br("\\negthickspace","\\tmspace-{5mu}{.277em}"),Br("\\enspace","\\kern.5em "),Br("\\enskip","\\hskip.5em\\relax"),Br("\\quad","\\hskip1em\\relax"),Br("\\qquad","\\hskip2em\\relax"),Br("\\tag","\\@ifstar\\tag@literal\\tag@paren"),Br("\\tag@paren","\\tag@literal{({#1})}"),Br("\\tag@literal",(e=>{if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),Br("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),Br("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),Br("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),Br("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),Br("\\newline","\\\\\\relax"),Br("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");const qn=F(T["Main-Regular"]["T".charCodeAt(0)][1]-.7*T["Main-Regular"]["A".charCodeAt(0)][1]);Br("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+qn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),Br("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+qn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),Br("\\hspace","\\@ifstar\\@hspacer\\@hspace"),Br("\\@hspace","\\hskip #1\\relax"),Br("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),Br("\\ordinarycolon",":"),Br("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),Br("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),Br("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),Br("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),Br("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),Br("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),Br("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),Br("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),Br("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),Br("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),Br("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),Br("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),Br("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),Br("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),Br("\u2237","\\dblcolon"),Br("\u2239","\\eqcolon"),Br("\u2254","\\coloneqq"),Br("\u2255","\\eqqcolon"),Br("\u2a74","\\Coloneqq"),Br("\\ratio","\\vcentcolon"),Br("\\coloncolon","\\dblcolon"),Br("\\colonequals","\\coloneqq"),Br("\\coloncolonequals","\\Coloneqq"),Br("\\equalscolon","\\eqqcolon"),Br("\\equalscoloncolon","\\Eqqcolon"),Br("\\colonminus","\\coloneq"),Br("\\coloncolonminus","\\Coloneq"),Br("\\minuscolon","\\eqcolon"),Br("\\minuscoloncolon","\\Eqcolon"),Br("\\coloncolonapprox","\\Colonapprox"),Br("\\coloncolonsim","\\Colonsim"),Br("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Br("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Br("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Br("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Br("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),Br("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),Br("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),Br("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),Br("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),Br("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),Br("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),Br("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),Br("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),Br("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),Br("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),Br("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),Br("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),Br("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),Br("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),Br("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),Br("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),Br("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),Br("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),Br("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),Br("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),Br("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),Br("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),Br("\\imath","\\html@mathml{\\@imath}{\u0131}"),Br("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),Br("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),Br("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),Br("\u27e6","\\llbracket"),Br("\u27e7","\\rrbracket"),Br("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),Br("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),Br("\u2983","\\lBrace"),Br("\u2984","\\rBrace"),Br("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),Br("\u29b5","\\minuso"),Br("\\darr","\\downarrow"),Br("\\dArr","\\Downarrow"),Br("\\Darr","\\Downarrow"),Br("\\lang","\\langle"),Br("\\rang","\\rangle"),Br("\\uarr","\\uparrow"),Br("\\uArr","\\Uparrow"),Br("\\Uarr","\\Uparrow"),Br("\\N","\\mathbb{N}"),Br("\\R","\\mathbb{R}"),Br("\\Z","\\mathbb{Z}"),Br("\\alef","\\aleph"),Br("\\alefsym","\\aleph"),Br("\\Alpha","\\mathrm{A}"),Br("\\Beta","\\mathrm{B}"),Br("\\bull","\\bullet"),Br("\\Chi","\\mathrm{X}"),Br("\\clubs","\\clubsuit"),Br("\\cnums","\\mathbb{C}"),Br("\\Complex","\\mathbb{C}"),Br("\\Dagger","\\ddagger"),Br("\\diamonds","\\diamondsuit"),Br("\\empty","\\emptyset"),Br("\\Epsilon","\\mathrm{E}"),Br("\\Eta","\\mathrm{H}"),Br("\\exist","\\exists"),Br("\\harr","\\leftrightarrow"),Br("\\hArr","\\Leftrightarrow"),Br("\\Harr","\\Leftrightarrow"),Br("\\hearts","\\heartsuit"),Br("\\image","\\Im"),Br("\\infin","\\infty"),Br("\\Iota","\\mathrm{I}"),Br("\\isin","\\in"),Br("\\Kappa","\\mathrm{K}"),Br("\\larr","\\leftarrow"),Br("\\lArr","\\Leftarrow"),Br("\\Larr","\\Leftarrow"),Br("\\lrarr","\\leftrightarrow"),Br("\\lrArr","\\Leftrightarrow"),Br("\\Lrarr","\\Leftrightarrow"),Br("\\Mu","\\mathrm{M}"),Br("\\natnums","\\mathbb{N}"),Br("\\Nu","\\mathrm{N}"),Br("\\Omicron","\\mathrm{O}"),Br("\\plusmn","\\pm"),Br("\\rarr","\\rightarrow"),Br("\\rArr","\\Rightarrow"),Br("\\Rarr","\\Rightarrow"),Br("\\real","\\Re"),Br("\\reals","\\mathbb{R}"),Br("\\Reals","\\mathbb{R}"),Br("\\Rho","\\mathrm{P}"),Br("\\sdot","\\cdot"),Br("\\sect","\\S"),Br("\\spades","\\spadesuit"),Br("\\sub","\\subset"),Br("\\sube","\\subseteq"),Br("\\supe","\\supseteq"),Br("\\Tau","\\mathrm{T}"),Br("\\thetasym","\\vartheta"),Br("\\weierp","\\wp"),Br("\\Zeta","\\mathrm{Z}"),Br("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),Br("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),Br("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),Br("\\bra","\\mathinner{\\langle{#1}|}"),Br("\\ket","\\mathinner{|{#1}\\rangle}"),Br("\\braket","\\mathinner{\\langle{#1}\\rangle}"),Br("\\Bra","\\left\\langle#1\\right|"),Br("\\Ket","\\left|#1\\right\\rangle");const In=e=>t=>{const r=t.consumeArg().tokens,n=t.consumeArg().tokens,o=t.consumeArg().tokens,s=t.consumeArg().tokens,i=t.macros.get("|"),a=t.macros.get("\\|");t.macros.beginGroup();const l=t=>r=>{e&&(r.macros.set("|",i),o.length&&r.macros.set("\\|",a));let s=t;if(!t&&o.length){"|"===r.future().text&&(r.popToken(),s=!0)}return{tokens:s?o:n,numArgs:0}};t.macros.set("|",l(!1)),o.length&&t.macros.set("\\|",l(!0));const h=t.consumeArg().tokens,c=t.expandTokens([...s,...h,...r]);return t.macros.endGroup(),{tokens:c.reverse(),numArgs:0}};Br("\\bra@ket",In(!1)),Br("\\bra@set",In(!0)),Br("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"),Br("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),Br("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),Br("\\angln","{\\angl n}"),Br("\\blue","\\textcolor{##6495ed}{#1}"),Br("\\orange","\\textcolor{##ffa500}{#1}"),Br("\\pink","\\textcolor{##ff00af}{#1}"),Br("\\red","\\textcolor{##df0030}{#1}"),Br("\\green","\\textcolor{##28ae7b}{#1}"),Br("\\gray","\\textcolor{gray}{#1}"),Br("\\purple","\\textcolor{##9d38bd}{#1}"),Br("\\blueA","\\textcolor{##ccfaff}{#1}"),Br("\\blueB","\\textcolor{##80f6ff}{#1}"),Br("\\blueC","\\textcolor{##63d9ea}{#1}"),Br("\\blueD","\\textcolor{##11accd}{#1}"),Br("\\blueE","\\textcolor{##0c7f99}{#1}"),Br("\\tealA","\\textcolor{##94fff5}{#1}"),Br("\\tealB","\\textcolor{##26edd5}{#1}"),Br("\\tealC","\\textcolor{##01d1c1}{#1}"),Br("\\tealD","\\textcolor{##01a995}{#1}"),Br("\\tealE","\\textcolor{##208170}{#1}"),Br("\\greenA","\\textcolor{##b6ffb0}{#1}"),Br("\\greenB","\\textcolor{##8af281}{#1}"),Br("\\greenC","\\textcolor{##74cf70}{#1}"),Br("\\greenD","\\textcolor{##1fab54}{#1}"),Br("\\greenE","\\textcolor{##0d923f}{#1}"),Br("\\goldA","\\textcolor{##ffd0a9}{#1}"),Br("\\goldB","\\textcolor{##ffbb71}{#1}"),Br("\\goldC","\\textcolor{##ff9c39}{#1}"),Br("\\goldD","\\textcolor{##e07d10}{#1}"),Br("\\goldE","\\textcolor{##a75a05}{#1}"),Br("\\redA","\\textcolor{##fca9a9}{#1}"),Br("\\redB","\\textcolor{##ff8482}{#1}"),Br("\\redC","\\textcolor{##f9685d}{#1}"),Br("\\redD","\\textcolor{##e84d39}{#1}"),Br("\\redE","\\textcolor{##bc2612}{#1}"),Br("\\maroonA","\\textcolor{##ffbde0}{#1}"),Br("\\maroonB","\\textcolor{##ff92c6}{#1}"),Br("\\maroonC","\\textcolor{##ed5fa6}{#1}"),Br("\\maroonD","\\textcolor{##ca337c}{#1}"),Br("\\maroonE","\\textcolor{##9e034e}{#1}"),Br("\\purpleA","\\textcolor{##ddd7ff}{#1}"),Br("\\purpleB","\\textcolor{##c6b9fc}{#1}"),Br("\\purpleC","\\textcolor{##aa87ff}{#1}"),Br("\\purpleD","\\textcolor{##7854ab}{#1}"),Br("\\purpleE","\\textcolor{##543b78}{#1}"),Br("\\mintA","\\textcolor{##f5f9e8}{#1}"),Br("\\mintB","\\textcolor{##edf2df}{#1}"),Br("\\mintC","\\textcolor{##e0e5cc}{#1}"),Br("\\grayA","\\textcolor{##f6f7f7}{#1}"),Br("\\grayB","\\textcolor{##f0f1f2}{#1}"),Br("\\grayC","\\textcolor{##e3e5e6}{#1}"),Br("\\grayD","\\textcolor{##d6d8da}{#1}"),Br("\\grayE","\\textcolor{##babec2}{#1}"),Br("\\grayF","\\textcolor{##888d93}{#1}"),Br("\\grayG","\\textcolor{##626569}{#1}"),Br("\\grayH","\\textcolor{##3b3e40}{#1}"),Br("\\grayI","\\textcolor{##21242c}{#1}"),Br("\\kaBlue","\\textcolor{##314453}{#1}"),Br("\\kaGreen","\\textcolor{##71B307}{#1}");const Rn={"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0};class Hn{constructor(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new zn(An,t.macros),this.mode=r,this.stack=[]}feed(e){this.lexer=new Mn(e,this.settings)}switchMode(e){this.mode=e}beginGroup(){this.macros.beginGroup()}endGroup(){this.macros.endGroup()}endGroups(){this.macros.endGroups()}future(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]}popToken(){return this.future(),this.stack.pop()}pushToken(e){this.stack.push(e)}pushTokens(e){this.stack.push(...e)}scanArgument(e){let t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken(),({tokens:n,end:r}=this.consumeArg(["]"]))}else({tokens:n,start:t,end:r}=this.consumeArg());return this.pushToken(new Nr("EOF",r.loc)),this.pushTokens(n),t.range(r,"")}consumeSpaces(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}}consumeArg(e){const t=[],r=e&&e.length>0;r||this.consumeSpaces();const o=this.future();let s,i=0,a=0;do{if(s=this.popToken(),t.push(s),"{"===s.text)++i;else if("}"===s.text){if(--i,-1===i)throw new n("Extra }",s)}else if("EOF"===s.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[a]:"}")+"'",s);if(e&&r)if((0===i||1===i&&"{"===e[a])&&s.text===e[a]){if(++a,a===e.length){t.splice(-a,a);break}}else a=0}while(0!==i||r);return"{"===o.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:o,end:s}}consumeArgs(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");const r=t[0];for(let e=0;ethis.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting")}expandOnce(e){const t=this.popToken(),r=t.text,o=t.noexpand?null:this._getExpansion(r);if(null==o||e&&o.unexpandable){if(e&&null==o&&"\\"===r[0]&&!this.isDefined(r))throw new n("Undefined control sequence: "+r);return this.pushToken(t),!1}this.countExpansion(1);let s=o.tokens;const i=this.consumeArgs(o.numArgs,o.delimiters);if(o.numArgs){s=s.slice();for(let e=s.length-1;e>=0;--e){let t=s[e];if("#"===t.text){if(0===e)throw new n("Incomplete placeholder at end of macro body",t);if(t=s[--e],"#"===t.text)s.splice(e+1,1);else{if(!/^[1-9]$/.test(t.text))throw new n("Not a valid argument number",t);s.splice(e,2,...i[+t.text-1])}}}}return this.pushTokens(s),s.length}expandAfterFuture(){return this.expandOnce(),this.future()}expandNextToken(){for(;;)if(!1===this.expandOnce()){const e=this.stack.pop();return e.treatAsRelax&&(e.text="\\relax"),e}throw new Error}expandMacro(e){return this.macros.has(e)?this.expandTokens([new Nr(e)]):void 0}expandTokens(e){const t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;)if(!1===this.expandOnce(!0)){const e=this.stack.pop();e.treatAsRelax&&(e.noexpand=!1,e.treatAsRelax=!1),t.push(e)}return this.countExpansion(t.length),t}expandMacroAsText(e){const t=this.expandMacro(e);return t?t.map((e=>e.text)).join(""):t}_getExpansion(e){const t=this.macros.get(e);if(null==t)return t;if(1===e.length){const t=this.lexer.catcodes[e];if(null!=t&&13!==t)return}const r="function"==typeof t?t(this):t;if("string"==typeof r){let e=0;if(-1!==r.indexOf("#")){const t=r.replace(/##/g,"");for(;-1!==t.indexOf("#"+(e+1));)++e}const t=new Mn(r,this.settings),n=[];let o=t.lex();for(;"EOF"!==o.text;)n.push(o),o=t.lex();n.reverse();return{tokens:n,numArgs:e}}return r}isDefined(e){return this.macros.has(e)||yn.hasOwnProperty(e)||oe.math.hasOwnProperty(e)||oe.text.hasOwnProperty(e)||Rn.hasOwnProperty(e)}isExpandable(e){const t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:yn.hasOwnProperty(e)&&!yn[e].primitive}}const On=/^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/,En=Object.freeze({"\u208a":"+","\u208b":"-","\u208c":"=","\u208d":"(","\u208e":")","\u2080":"0","\u2081":"1","\u2082":"2","\u2083":"3","\u2084":"4","\u2085":"5","\u2086":"6","\u2087":"7","\u2088":"8","\u2089":"9","\u2090":"a","\u2091":"e","\u2095":"h","\u1d62":"i","\u2c7c":"j","\u2096":"k","\u2097":"l","\u2098":"m","\u2099":"n","\u2092":"o","\u209a":"p","\u1d63":"r","\u209b":"s","\u209c":"t","\u1d64":"u","\u1d65":"v","\u2093":"x","\u1d66":"\u03b2","\u1d67":"\u03b3","\u1d68":"\u03c1","\u1d69":"\u03d5","\u1d6a":"\u03c7","\u207a":"+","\u207b":"-","\u207c":"=","\u207d":"(","\u207e":")","\u2070":"0","\xb9":"1","\xb2":"2","\xb3":"3","\u2074":"4","\u2075":"5","\u2076":"6","\u2077":"7","\u2078":"8","\u2079":"9","\u1d2c":"A","\u1d2e":"B","\u1d30":"D","\u1d31":"E","\u1d33":"G","\u1d34":"H","\u1d35":"I","\u1d36":"J","\u1d37":"K","\u1d38":"L","\u1d39":"M","\u1d3a":"N","\u1d3c":"O","\u1d3e":"P","\u1d3f":"R","\u1d40":"T","\u1d41":"U","\u2c7d":"V","\u1d42":"W","\u1d43":"a","\u1d47":"b","\u1d9c":"c","\u1d48":"d","\u1d49":"e","\u1da0":"f","\u1d4d":"g","\u02b0":"h","\u2071":"i","\u02b2":"j","\u1d4f":"k","\u02e1":"l","\u1d50":"m","\u207f":"n","\u1d52":"o","\u1d56":"p","\u02b3":"r","\u02e2":"s","\u1d57":"t","\u1d58":"u","\u1d5b":"v","\u02b7":"w","\u02e3":"x","\u02b8":"y","\u1dbb":"z","\u1d5d":"\u03b2","\u1d5e":"\u03b3","\u1d5f":"\u03b4","\u1d60":"\u03d5","\u1d61":"\u03c7","\u1dbf":"\u03b8"}),Ln={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"},"\u0327":{text:"\\c"}},Dn={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u1e09":"c\u0327\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\xe7":"c\u0327","\u010f":"d\u030c","\u1e0b":"d\u0307","\u1e11":"d\u0327","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u1e1d":"e\u0327\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u0229":"e\u0327","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u0123":"g\u0327","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\u1e29":"h\u0327","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u0137":"k\u0327","\u013a":"l\u0301","\u013e":"l\u030c","\u013c":"l\u0327","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\u0146":"n\u0327","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u0157":"r\u0327","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u015f":"s\u0327","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\u0163":"t\u0327","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u1e08":"C\u0327\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\xc7":"C\u0327","\u010e":"D\u030c","\u1e0a":"D\u0307","\u1e10":"D\u0327","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u1e1c":"E\u0327\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u0228":"E\u0327","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u0122":"G\u0327","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\u1e28":"H\u0327","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0136":"K\u0327","\u0139":"L\u0301","\u013d":"L\u030c","\u013b":"L\u0327","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\u0145":"N\u0327","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u0156":"R\u0327","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u015e":"S\u0327","\u0164":"T\u030c","\u1e6a":"T\u0307","\u0162":"T\u0327","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"};class Vn{constructor(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new Hn(e,t,this.mode),this.settings=t,this.leftrightDepth=0}expect(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()}consume(){this.nextToken=null}fetch(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken}switchMode(e){this.mode=e,this.gullet.switchMode(e)}parse(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{const e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}}subparse(e){const t=this.nextToken;this.consume(),this.gullet.pushToken(new Nr("}")),this.gullet.pushTokens(e);const r=this.parseExpression(!1);return this.expect("}"),this.nextToken=t,r}parseExpression(e,t){const r=[];for(;;){"math"===this.mode&&this.consumeSpaces();const n=this.fetch();if(-1!==Vn.endOfExpression.indexOf(n.text))break;if(t&&n.text===t)break;if(e&&yn[n.text]&&yn[n.text].infix)break;const o=this.parseAtom(t);if(!o)break;"internal"!==o.type&&r.push(o)}return"text"===this.mode&&this.formLigatures(r),this.handleInfixNodes(r)}handleInfixNodes(e){let t,r=-1;for(let o=0;o=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);const r=oe[this.mode][t].group,n=Cr.range(e);let s;if(te.hasOwnProperty(r)){const e=r;s={type:"atom",mode:this.mode,family:e,loc:n,text:t}}else s={type:r,mode:this.mode,loc:n,text:t};o=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(S(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),o={type:"textord",mode:"text",loc:Cr.range(e),text:t}}if(this.consume(),r)for(let t=0;t.
+function makeTeaser(body, terms) {
+ var TERM_WEIGHT = 40;
+ var NORMAL_WORD_WEIGHT = 2;
+ var FIRST_WORD_WEIGHT = 8;
+ var TEASER_MAX_WORDS = 30;
+
+ var stemmedTerms = terms.map(function (w) {
+ return elasticlunr.stemmer(w.toLowerCase());
+ });
+ var termFound = false;
+ var index = 0;
+ var weighted = []; // contains elements of ["word", weight, index_in_document]
+
+ // split in sentences, then words
+ var sentences = body.toLowerCase().split(". ");
+
+ for (var i in sentences) {
+ var words = sentences[i].split(" ");
+ var value = FIRST_WORD_WEIGHT;
+
+ for (var j in words) {
+ var word = words[j];
+
+ if (word.length > 0) {
+ for (var k in stemmedTerms) {
+ if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
+ value = TERM_WEIGHT;
+ termFound = true;
+ }
+ }
+ weighted.push([word, value, index]);
+ value = NORMAL_WORD_WEIGHT;
+ }
+
+ index += word.length;
+ index += 1; // ' ' or '.' if last word in sentence
+ }
+
+ index += 1; // because we split at a two-char boundary '. '
+ }
+
+ if (weighted.length === 0) {
+ return body;
+ }
+
+ var windowWeights = [];
+ var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
+ // We add a window with all the weights first
+ var curSum = 0;
+ for (var i = 0; i < windowSize; i++) {
+ curSum += weighted[i][1];
+ }
+ windowWeights.push(curSum);
+
+ for (var i = 0; i < weighted.length - windowSize; i++) {
+ curSum -= weighted[i][1];
+ curSum += weighted[i + windowSize][1];
+ windowWeights.push(curSum);
+ }
+
+ // If we didn't find the term, just pick the first window
+ var maxSumIndex = 0;
+ if (termFound) {
+ var maxFound = 0;
+ // backwards
+ for (var i = windowWeights.length - 1; i >= 0; i--) {
+ if (windowWeights[i] > maxFound) {
+ maxFound = windowWeights[i];
+ maxSumIndex = i;
+ }
+ }
+ }
+
+ var teaser = [];
+ var startIndex = weighted[maxSumIndex][2];
+ for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
+ var word = weighted[i];
+ if (startIndex < word[2]) {
+ // missing text from index to start of `word`
+ teaser.push(body.substring(startIndex, word[2]));
+ startIndex = word[2];
+ }
+
+ // add around search terms
+ if (word[1] === TERM_WEIGHT) {
+ teaser.push("");
+ }
+ startIndex = word[2] + word[0].length;
+ teaser.push(body.substring(word[2], startIndex));
+
+ if (word[1] === TERM_WEIGHT) {
+ teaser.push("");
+ }
+ }
+ teaser.push("…");
+ return teaser.join("");
+}
+
+function formatSearchResultItem(item, terms) {
+ return '';
+}
+
+function initSearch() {
+ var searchBar = document.getElementById("search-bar");
+ var searchContainer = document.getElementById("search-container");
+ var searchResults = document.getElementById("search-results");
+ var MAX_ITEMS = 10;
+
+ var options = {
+ bool: "AND",
+ fields: {
+ title: { boost: 2 },
+ body: { boost: 1 },
+ }
+ };
+ var currentTerm = "";
+ var index;
+
+ var initIndex = async function () {
+ if (index === undefined) {
+ let searchIndex = document.getElementById("search-index").textContent;
+ index = fetch(searchIndex)
+ .then(
+ async function (response) {
+ return await elasticlunr.Index.load(await response.json());
+ }
+ );
+ }
+ let res = await index;
+ return res;
+ }
+
+ searchBar.addEventListener("keyup", debounce(async function () {
+ var term = searchBar.value.trim();
+ if (term === currentTerm) {
+ return;
+ }
+ searchResults.style.display = term === "" ? "none" : "flex";
+ searchResults.innerHTML = "";
+ currentTerm = term;
+ if (term === "") {
+ return;
+ }
+
+ var results = (await initIndex()).search(term, options);
+ if (results.length === 0) {
+ searchResults.style.display = "none";
+ return;
+ }
+
+ for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) {
+ searchResults.innerHTML += formatSearchResultItem(results[i], term.split(" "));
+ }
+ }, 150));
+
+ document.addEventListener("keydown", function (event) {
+ if (event.key === "/") {
+ event.preventDefault();
+ toggleSearch();
+ }
+ });
+
+ document.getElementById("search-toggle").addEventListener("click", toggleSearch);
+}
+
+function toggleSearch() {
+ var searchContainer = document.getElementById("search-container");
+ var searchBar = document.getElementById("search-bar");
+ searchContainer.classList.toggle("active");
+ searchBar.toggleAttribute("disabled");
+ searchBar.focus();
+}
+
+if (document.readyState === "complete" ||
+ (document.readyState !== "loading" && !document.documentElement.doScroll)
+) {
+ initSearch();
+} else {
+ document.addEventListener("DOMContentLoaded", initSearch);
+}
diff --git a/public/search-fuse.js b/public/search-fuse.js
new file mode 100644
index 00000000..adecf08f
--- /dev/null
+++ b/public/search-fuse.js
@@ -0,0 +1,127 @@
+ // Based on https://codeberg.org/daudix/duckquill/issues/101#issuecomment-2377169
+ let searchSetup = false;
+ let fuse;
+
+ async function initIndex() {
+ if (searchSetup) return;
+
+ const url = document.getElementById("search-index").textContent;
+ const response = await fetch(url);
+
+ if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
+
+ const options = {
+ includeScore: false,
+ includeMatches: true,
+ ignoreLocation: true,
+ threshold: 0.15,
+ keys: [
+ { name: "title", weight: 3 },
+ { name: "description", weight: 2 },
+ { name: "body", weight: 1 }
+ ]
+ };
+
+ fuse = new Fuse(await response.json(), options);
+ searchSetup = true;
+
+ console.log("Search index initialized successfully");
+ }
+
+ function toggleSearch() {
+ initIndex();
+ const searchBar = document.getElementById("search-bar");
+ const searchContainer = document.getElementById("search-container");
+ const searchResults = document.getElementById("search-results");
+ searchContainer.classList.toggle("active");
+ searchBar.toggleAttribute("disabled");
+ searchBar.focus();
+ }
+
+ function debounce(actual_fn, wait) {
+ let timeoutId;
+
+ return (...args) => {
+ clearTimeout(timeoutId);
+
+ timeoutId = setTimeout(() => {
+ actual_fn(...args);
+ }, wait);
+ };
+ };
+
+ function initSearch() {
+ const searchBar = document.getElementById("search-bar");
+ const searchResults = document.getElementById("search-results");
+ const searchContainer = document.getElementById("search-container");
+ const MAX_ITEMS = 10;
+ const MAX_RESULTS = 4;
+
+ let currentTerm = "";
+
+ searchBar.addEventListener("keyup", (e) => {
+ const searchVal = searchBar.value.trim();
+ const results = fuse.search(searchVal, { limit: MAX_ITEMS });
+
+ let html = "";
+ for (const result of results) {
+ html += makeTeaser(result, searchVal);
+ }
+ searchResults.innerHTML = html;
+
+ if (html) {
+ searchResults.style.display = "flex";
+ } else {
+ searchResults.style.display = "none";
+ }
+ });
+
+ function makeTeaser(result, searchVal) {
+ const TEASER_SIZE = 20;
+ let output = `${result.item.title}`;
+
+ for (const match of result.matches) {
+ if (match.key === "title") continue;
+
+ const indices = match.indices.sort((a, b) => Math.abs(a[1] - a[0] - searchVal.length) - Math.abs(b[1] - b[0] - searchVal.length)).slice(0, MAX_RESULTS);
+ const value = match.value;
+
+ for (const ind of indices) {
+ const start = Math.max(0, ind[0] - TEASER_SIZE);
+ const end = Math.min(value.length - 1, ind[1] + TEASER_SIZE);
+ output += "
"
+ + value.substring(start, ind[0])
+ + `${value.substring(ind[0], ind[1] + 1)}`
+ + value.substring(ind[1] + 1, end)
+ + "";
+ }
+
+ if (match.indices.length > 4) {
+ const moreMatchesText = document.getElementById("more-matches-text").textContent;
+ output += `
${moreMatchesText}`.replace("$MATCHES", `+${match.indices.length - MAX_RESULTS}`);
+ }
+ }
+ return output + "
";
+ }
+
+ /*window.addEventListener("click", function (event) {
+ if (searchSetup && searchBar.getAttribute("disabled") === null && !searchContainer.contains(event.target)) {
+ toggleSearch();
+ }
+ }, { passive: true });*/
+
+ document.addEventListener("keydown", function(event) {
+ if (event.key === "/") {
+ event.preventDefault();
+ toggleSearch();
+ }
+ });
+
+ document.getElementById("search-toggle").addEventListener("click", toggleSearch);
+ }
+
+ if (document.readyState === "complete" ||
+ (document.readyState !== "loading" && !document.documentElement.doScroll))
+ initSearch();
+ else
+ document.addEventListener("DOMContentLoaded", initSearch);
diff --git a/public/search_index.en.json b/public/search_index.en.json
new file mode 100644
index 00000000..0784098f
--- /dev/null
+++ b/public/search_index.en.json
@@ -0,0 +1 @@
+[{"url":"http://127.0.0.1:1111/blog/","title":"Aron's Blog","description":null,"body":"Find all my projects here.\nThey are sorted by date, you can also filter by tags.\n","path":null},{"url":"http://127.0.0.1:1111/blog/master-thesis/","title":"Master's Thesis","description":null,"body":"Master's Thesis: Human - Waste\nPlastics offer significant material benefits, such as durability and versatility, yet their\nwidespread use has led to severe environmental pollution and waste management\nchallenges. This thesis develops alternative concepts for collaborative participation in\nrecycling processes by examining existing waste management systems. Exploring the\nhistorical and material context of plastics, it investigates the role of making and hacking as\ntransformative practices in waste revaluation. Drawing on theories from Discard Studies,\nMaterial Ecocriticism, and Valuation Studies, it applies methods to examine human-waste\nrelationships and the shifting perception of objects between value and non-value. Practical\ninvestigations, including workshop-based experiments with polymer identification and\nmachine-based interventions, provide hands-on insights into the material properties of\ndiscarded plastics. These experiments reveal their epistemic potential, leading to the\nintroduction of novel archiving practices and knowledge structures that form an integrated\nmethodology for artistic research and practice. Inspired by the Materialstudien of the\nBauhaus Vorkurs, the workshop not only explores material engagement but also offers new\ninsights for educational science, advocating for peer-learning scenarios. Through these\napproaches, this research fosters a socially transformative relationship with waste,\nemphasizing participation, design, and speculative material reuse. Findings are evaluated\nthrough participant feedback and workshop outcomes, contributing to a broader discussion\non waste as both a challenge and an opportunity for sustainable futures and a material\nreality of the human experience.\n\n\n See the image archive yourself\n\n\n See the archive graph yourself\n\n\n Find the complete Repo on Forgejo\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/käsewerkstatt/","title":"Käsewerkstatt","description":null,"body":"Enter the Käsewerkstatt\nOne day earlier this year I woke up and realized I had a space problem.\nI was trying to build out a workshop and tackle ever more advanced and dusty plastic and woodworking projects and after another small run in with my girlfriend after I had repeatedly crossed the \"No-Sanding-and-Linseed-Oiling-Policy\" in our Living Room, it was time to do something about it.\nI am based in Berlin right now and the housing market is going completely haywire over here ( quick shoutout in solidarity with Deutsche Wohnen und Co enteignen).\nEnd of the song: I won't be able to afford to rent a small workshop anywhere near berlin anytime soon. As you will notice in some other projects, I am quite opposed to the Idea that it should be considered normal to park ones car in the middle of the city on public spaces, for example Autoimmunitaet, Commoning Cars or Dreams of Cars.\nSo, the idea was born, to regain that space as habitable zone, taking back usable space from parked cars.\nI was gonna install a mobile workshop within a trailer.\nIdeally, the trailer should be lockable and have enough standing and working space.\nAs it turns out, Food Trailers fulfill these criteria quite nicely. So I got out on a quest, finding the cheapest food trailer available in germany.\n6 weeks later, I found it near munich, got it and started immediately renovating it.\nDue to developments in parallel, I was already invited to sell food and have the ofgficial premiere at the Bergfest, a Weekend Format in Brandenburg an der Havel, initiated and organized by Zirkus Creativo. Many thanks for the invitation here again!\nSo on it went, I spent some afternoons renovating and outfitting the trailer, and did my first ever shopping at Metro, a local B2B Foodstuffs Market.\nMeanwhile, I got into all the paperwork and did all the necessary instructional courses and certificates.\nThe first food I wanted to sell was Raclette on fresh bread, a swiss dish that is quite popular in germany.\nFor the future, the trailer is supposed to tend more towards vegan dishes, as a first tryout I also sold a bruschetta combo. This turned out great, since the weather was quite hot and the bruschetta was a nice and light snack, while I could use the same type of bread for the raclette.\n\nThe event itself was great, and, in part at least, started paying off the trailer.\nSome photos of the opeing event @ Bergfest in Brandenburg an der Havel\n\n\n\nWe encountered lots of positive feedback and I am looking forward to the next event. So, in case you want to have a foodtruck at your event, hit me up!\nContact me at: käsewerkstatt@petau.net\n","path":null},{"url":"http://127.0.0.1:1111/blog/sferics/","title":"Sferics","description":null,"body":"What the hell are Sferics?\n\nA radio atmospheric signal or sferic (sometimes also spelled \"spheric\") is a broadband electromagnetic impulse that occurs as a result of natural atmospheric lightning discharges. Sferics may propagate from their lightning source without major attenuation in the Earth–ionosphere waveguide, and can be received thousands of kilometres from their source.\n\n\nWikipedia\n\nWhy catch them?\nMicrosferics is a nice reference Project, which is a network of Sferics antennas, which are used to detect lightning strikes. Through triangulation not unlike the Maths happening in GPS, the (more or less) exact location of the strike can be determined. This is useful for weather prediction, but also for the detection of forest fires, which are often caused by lightning strikes.\nBecause the Frequency of the Sferics is, when converted to audio, still in the audible range, it is possible to listen to the strikes. This usually sounds a bit like a crackling noise, but can also be quite melodic. I was a bit reminded by a Geiger Counter.\nSferics are in the VLF (Very Low Frequency) range, sitting roughly at 10kHz, which is a bit of a problem for most radios, as they are not designed to pick up such low frequencies. This is why we built our own antenna.\nAt 10kHz, we are talking about insanely large waves. a single wavelength there is roughly 30 Kilometers. This is why the antenna needs to be quite large. A special property of waves this large is, that they get easily reflected by the Ionosphere and the Earth's surface. Effectively, a wave like this can bounce around the globe several times before it is absorbed by the ground. This is why we can pick up Sferics from all over the world and even listen to Australian Lightning strikes. Of course, without the maths, we cannot attribute directions, but the so called \"Tweeks\" we picked up, usually come from at least 2000km distance.\nThe Build\nWe built several so-called \"Long-Loop\" antennas, which are essentially a coil of wire with a capacitor at the end. Further, a specific balun is needed, depending on the length of the wire. this can then directly output an electric signal on an XLR cable.\nLoosely based on instructions from Calvin R. Graf, We built a 26m long antenna, looped several times around a wooden frame.\nThe Result\nWe have several hour-long recordings of the Sferics, which we are currently investigating for further potential.\nHave a listen to a recording of the Sferics here:\n\n\nAs you can hear, there is quite a bit of 60 hz ground buzz in the recording.\nThis is either due to the fact that the antenna was not properly grounded or we simply were still too close to the bustling city.\nI think it is already surprising that we got such a clear impression so close to Berlin. Let's see what we can get in the countryside!\n\n\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/local-diffusion/","title":"Local Diffusion","description":null,"body":"Local Diffusion\nThe official call for the Workshop\nIs it possible to create a graphic novel with generative A.I.?\nWhat does it mean to use these emerging media in collaboration with others?\nAnd why does their local and offline application matter?\nWith AI becoming more and more democratised and GPT-like Structures increasingly integrated into everyday life, the black-box notion of the mysterious all-powerful Intelligence hinders insightful and effective usage of emerging tools. One particularly hands-on example is AI generated images. Within the proposed Workshop, we will dive into Explainable AI, explore Stable Diffusion, and most importantly, understand the most important parameters within it. We want to steer outcomes in a deliberate manner. Emphasis here is on open and accessible technology, to increase user agency and make techno-social dependencies and power relations visible.\nEmpower yourself against readymade technology!\nDo not let others decide on what your best practices are. Get involved in the modification of the algorithm and get surprised by endless creative possibilities. Through creating a short graphic novel with 4-8 panels, participants will be able to utilise multiple flavours of the Stable Diffusion algorithm, and will have a non-mathematical understanding of the parameters and their effects on the output within some common GUIs. They will be able to apply several post-processing techniques to their generated images, such as upscaling, masking, inpainting and pose redrawing. Further, participants will be able to understand the structure of a good text prompt, be able to utilise online reference databases and manipulate parameters and directives of the Image to optimise desired qualities. Participants will also be introduced to ControlNet, enabling them to direct Pose and Image composition in detail.\nWorkshop Evaluation\nOver the course of 3 hours, I gave an introductory workshop in local stable diffusion processing and introduced participants to the server available to UdK Students for fast remote computation that circumvents the unethicality of continuously using a proprietary cloud service for similar outputs. There is not much we can do on the data production side and many ethical dilemmas surrounding digital colonialism remain, but local computation takes one step towards a critical and transparent use of AI tools by Artists.\nThe Workshop format was rathert open and experimental, which was welcomed by the participants and they tried the collages enthusiastically. We also had a refreshing discussion on different positions regarding the ethicalities and whether a complete block of these tools is called for and feasible.\nI am looking forward to round 2 with the next iteration, where we are definitely diving deeper into the depths of comfyui, an interface that i absolutely adore, while its power also terrifies me sometimes.\n","path":null},{"url":"http://127.0.0.1:1111/blog/airaspi-build-log/","title":"AIRASPI Build Log","description":null,"body":"AI-Raspi Build Log\nThis should document the rough steps to recreate airaspi as I go along.\nRough Idea: Build an edge device with image recognition and object detection capabilites.\nIt should be realtime, aiming for 30fps at 720p.\nPortability and usage at installations is a priority, so it has to function without active internet connection and be as small as possible.\nIt would be a real Edge Device, with no computation happening in the cloud.\nInspo from: pose2art\nHardware\n\nRaspberry Pi 5\nRaspberry Pi Camera Module v1.3\nRaspberry Pi GlobalShutter Camera\n2x CSI FPC Cable (needs one compact side to fit pi 5)\nPineberry AI Hat (m.2 E key)\nCoral Dual Edge TPU (m.2 E key)\nRaspi Official 5A Power Supply\nRaspi active cooler\n\nSetup\nMost important sources used\ncoral.ai\nJeff Geerling\nFrigate NVR\nRaspberry Pi OS\nI used the Raspberry Pi Imager to flash the latest Raspberry Pi OS Lite to a SD Card.\nNeeds to be Debian Bookworm.\nNeeds to be the full arm64 image (with desktop), otherwise you will get into camera driver hell.\n{: .notice}\nSettings applied:\n\nused the default arm64 image (with desktop)\nenable custom settings:\nenable ssh\nset wifi country\nset wifi ssid and password\nset locale\nset hostname: airaspi\n\nupdate\nThis is always good practice on a fresh install. It takes quite long with the full os image.\n\nprep system for coral\nThanks again @Jeff Geerling, this is completely out of my comfort zone, I rely on people writing solid tutorials like this one.\n\n\nWhile in the file, add the following lines:\n\nSave and reboot:\n\n\n\nshould be different now, with a -v8 at the end\n\nedit /boot/firmware/cmdline.txt\n\n\nadd pcie_aspm=off before rootwait\n\n\nchange device tree\nwrong device tree\nThe script simply did not work for me.\nmaybe this script is the issue?\ni will try again without it\n{: .notice}\n\n\nYes it was the issue, wrote a comment about it on the gist\ncomment\n\nWhat to do instead?\nHere, I followed Jeff Geerling down to the T. Please refer to his tutorial for more information.\nIn the meantime the Script got updated and it is now recommended again.\n{: .notice}\n\nNote: msi- parent sems to carry the value <0x2c> nowadays, cost me a few hours.\n{: .notice}\ninstall apex driver\nfollowing instructions from coral.ai\n\nVerify with\n\n\nshould display the connected tpu\n\n\nconfirm with, if the output is not /dev/apex_0, something went wrong\n\nDocker\nInstall docker, use the official instructions for debian.\n\n\nProbably a source with source .bashrc would be enough, but I rebooted anyways\n{: .notice}\n\n\nset docker to start on boot\n\nTest the edge tpu\n\nInto the new file, paste:\n\n\n\n\nHere, you should see the inference results from the edge tpu with some confidence values.\nIf it ain't so, safest bet is a clean restart\nPortainer\nThis is optional, gives you a browser gui for your various docker containers\n{: .notice}\nInstall portainer\n\nopen portainer in browser and set admin password\n\nshould be available under https://airaspi.local:9443\n\nvnc in raspi-config\noptional, useful to test your cameras on your headless device.\nYou could of course also attach a monitor, but i find this more convenient.\n{: .notice}\n\n-- interface otions, enable vnc\nconnect through vnc viewer\nInstall vnc viewer on mac.\nUse airaspi.local:5900 as address.\nworking docker-compose for frigate\nStart this as a custom template in portainer.\nImportant: you need to change the paths to your own paths\n{: .notice}\n\nWorking frigate config file\nFrigate wants this file wherever you specified earlier that it will be.\nThis is necessary just once. Afterwards, you will be able to change the config in the gui.\n{: .notice}\n\nmediamtx\ninstall mediamtx, do not use the docker version, it will be painful\ndouble check the chip architecture here, caused me some headache\n{: .notice}\n\nedit the mediamtx.yml file\nworking paths section in mediamtx.yml\n\nalso change rtspAddress: :8554\nto rtspAddress: :8900\nOtherwise there is a conflict with frigate.\nWith this, you should be able to start mediamtx.\n\nIf there is no error, you can verify your stream through vlc under rtsp://airaspi.local:8900/cam1 (default would be 8554, but we changed it in the config file)\nCurrent Status\nI get working streams from both cameras, sending them out at 30fps at 720p.\nfrigate, however limits the display fps to 5, which is depressing to watch, especially since the tpu doesnt even break a little sweat.\nFrigate claime that the TPU is good for up to 10 cameras, so there is headroom.\nThe stram is completely errant and drops frames left and right. I have sometimes seen detect fps of 0.2, but the TPU speed should definitely not be the bottleneck here. Maybe attach the cameras to a separate device and stream from there?\nThe biggest issue here is that the google folx seems to have abandoned the coral, even though they just released a new piece of hardware for it.\nTheir most RECENT python build is 3.9.\nSpecifically, pycoral seems to be the problem there. without a decent update, I will be confined to debian 10, with python 3.7.3.\nThat sucks.\nThere are custom wheels, but nothing that seems plug and play.\nAbout the rest of this setup:\nThe decision to go for m.2 E key to save money, instead of spending more on the usb version was a huge mistake.\nPlease do yourself a favor and spend the extra 40 bucks.\nTechnically, its probably faster and better with continuous operation, but i have yet to feel the benefit of that.\nTODOs\n\nadd images and screenshots to the build log\nCheck whether vdo.ninja is a viable way to add mobile streams. then Smartphone stream evaluation would be on the horizon.\nBother the mediamtx makers about the libcamera bump, so we can get rid of the rpicam-vid hack.\nI suspect there is quirte a lot of performance lost there.\ntweak the frigate config to get snapshots and maybe build an image / video database to later train a custom model.\nworry about attaching an external ssd and saving the video files on it.\nfind a way to export the landmark points from frigate. maybe send them via osc like in pose2art?\nfind a different hat that lets me access the other TPU? I have the dual version, but can currently only acces 1 of the 2 TPUs due to hardware restrictions.\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/lusatia/","title":"Lusatia - an immersion in (De)Fences","description":null,"body":"\n\nOn an Excursion to Lusatia, a project with the Working Title (De)Fences was born.\nHere are the current materials.\n\nTODO: upload unity project\n","path":null},{"url":"http://127.0.0.1:1111/blog/autoimmunitaet/","title":"Autoimmunitaet","description":null,"body":"How do we design our Commute?\nIn the context of the Design and Computation Studio Course Milli Keil, Marla Gaiser and me developed a concept for a playful critique of the traffic decisions we take and the idols we embrace.\nIt should open up questions of whether the generations to come should still grow up playing on traffic carpets that are mostly grey and whether the Letzte Generation, a political climate activist group in Germany receives enough recognition for their acts.\nA call for solidarity.\n\n{: .center}\nThe scan results\n \nThe Action Figure, ready for printing\n \nAutoimmunitaet\nAutoimmunity is a term for defects, that are produced by a dysfunctional self-tolerance of a system.\nThis dysfunction causes the immune system to stop accepting certain parts of itself and build antibodies instead.\nAn invitation for a speculative playful interaction.\n\n\n\n\n\n\nThe Process\nThe figurines are 3D Scans of ourselves, in various typical poses of the Letzte Generation.\nWe used photogrammetry to create the scans, which is a technique that uses a lot of photos of an object to create a 3D model of it.\nWe used the app Polycam to create the scans using IPads and their inbuilt Lidar scanners.\n","path":null},{"url":"http://127.0.0.1:1111/blog/dreams-of-cars/","title":"Dreams of Cars","description":null,"body":"Photography\nIn the context of the course \"Fotografie Elementar\" with Sebastian Herold I developed a small concept of urban intervention.\nThe results were exhibited at the UdK Rundgang 2023 and are also visible here.\n\nDreams of Cars\nThese are not just cars.\nThey are Sport Utility Vehicles.\nWhat might they have had as hopes and dreams on the production line?\nDo they dream of drifting in dusty deserts?\nClimbing steep rocky canyon roads?\nSliding down sun-drenched dunes?\nDiscovering remote pathways in natural grasslands?\nNevertheless, they did end up in the parking spots here in Berlin.\nWhat drove them here?\n\n\n\n\n\n\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/stable-dreamfusion/","title":"Stable Dreamfusion","description":null,"body":"Stable Dreamfusion\n \nSources\nI forked a really popular implementation that reverse engineered the Google Dreamfusion algorithm. This algorithm is closed-source and not publicly available.\nThe implementation I forked is here\nThis one is running on stable-diffusion as a bas process, which means we are are expected to have worse results than google.\nThe original implementation is here\n\n\nGradio\nThe reason i forked the code is so that i could implement my own gradio interface for the algorithm. Gradio is a great tool for quickly building interfaces for machine learning models. No code involves, any user can state their wish, and the mechanism will spit out a ready-to-be-rigged model (obj file)\nMixamo\nI used Mixamo to rig the model. It is a great tool for rigging and animating models. But before everything, it is simple. as long as you have a model with a decent humanoid shape in something of a t-pose, you can rig it in seconds. Thats exactly what i did here.\nUnity\nI used Unity to render the model to the magic leap 1.\nThrough this, i could create an interactive and immersive environment with the generated models.\nThe dream was, to build a AI- Chamber of wishes.\nYou pick up the glasses, state your desires and then the algorithm will present to you an almost-real object in AR.\nDue to not having access to the proprietary sources from google and the beefy, but still not quite machine-learning ready computers we have at the studio, the results are not quite as good as i hoped.\nBut still, the results are quite interesting and i am happy with the outcome.\nA single generated object in the Box takes roughly 20 minutes to generate.\nEven then, the algorithm is quite particular and oftentimes will not generate anything coherent at all.\n","path":null},{"url":"http://127.0.0.1:1111/blog/auraglow/","title":"Auraglow","description":null,"body":"\nWhat makes a room?\nHow do moods and atmospheres emerge?\nCan we visualize them to make the experiences visible?\nThe project \"The Nature of Objects\" aims to expand (augment) perception by making the moods of places tangible through the respective auras of the objects in the space.\nWhat makes objects subjects?\nHow can we make the implicit explicit?\nAnd how can we make the character of a place visible?\\\nHere, we question the conservative, purely physical concept of space and address in the project a temporal, historical component of space, its objects, and their past.\nSpace will have transformed: from a simple \"object on which interest, thought, action is directed\" (definition object Duden), to a \"creature that is endowed with consciousness, thinking, sensing, acting\" (definition subject Duden).\nThis metamorphosis of subject formation on objects enables the space to undergo changes influenced, or, more precisely a shaping, reshaping, deformation -such that the space can finally be perceived differently and multiangular.\nSee the Project on GitHub{: .btn .btn--large}\n","path":null},{"url":"http://127.0.0.1:1111/blog/ruminations/","title":"Ruminations","description":null,"body":"Ruminations\nwas a contemplation on data privacy at Amazon.\nIt asks how to subvert browser fingerprinting and evading the omnipresent tracking of the consumer.\nThe initial idea was to somehow, by interacting with the perpetrator and letting data accumulate that would degrade their knowledge and thereby destroy predictablity, making this particular dataset worth less.\nWe could have just added a random clickbot, to confuse things a bit and make the data less valuable.\nBut looking at todays state of datacleanup algorithms and the sheer amount of data that is collected, this would have been a futile attempt. Amazon just detects and removes any noise we add and continues to use the data.\nSo, then, how can we create coherent, non-random data that is still not predictable?\nOne answer that this concept should demonstrate, is by inserting patterns that amazon cannot foresee with their current algorithms. As if they were trying to predict the actions of a person with shizophrenia.\nThe Concept\nIt consists of a browser extension (currently Chrome only) that overlays all web pages of Amazon with a moving entity that tracks your behavior. While tracking, an image classifier algorithm is used to formulate a product query off of the Storefront. After computation, a perfectly fitting product is displayed for your consumer's pleasure.\nThe analogue watchdog\nA second part of the project is a low-tech installation consisting of a camera (we used a smartphone) running a computer-vision algorithm tracking tiny movements. This was then pointed towards the browser console in the laptop running the extension. The camera was then connected to a screen that displayed the captured image. The watchdog was trained to make robot noises depending on the type and amount of movement detected. Effectively, whenever data traffic beween amazon and the browser was detected, the watchdog would start making noises.\nThe Browser extension\ngallery:\n\n\n\nFind the code on GitHub\nSubvert a bit yourself, or just have a look at the code.\nThe code of the Project on GitHub\nTODO: create video with live demo\n","path":null},{"url":"http://127.0.0.1:1111/blog/ballpark/","title":"Ballpark","description":null,"body":"Ballpark: 3D Environments in Unity\nImplemented in Unity, Ballpark is a Concept work for a collaborative 2-Player Game, where one player is a navigator with a third-person perspective and another player is a copilot, responsible for interaction with the environment – featuring mostly working physics, intelligent enemies, a gun, a grappling hook system for traversing the map, a 2D Interface for navigation and a health bar system. On top of the meanest cyberpunk vibes my past self was able to conjure.\nEnjoy!\n\n\nAs you can see, the design faces some questionable choices, but all mechanics are homemade from the ground up and I learned a lot. I often struggle to enjoy competitive games and think there is potential in a co-dependent game interface. During early testing, we often found that it enforces player communication since already the tutorial is quite hard to beat.\nDue to me being a leftie, perhaps not entirely smart, I gave player one the keyboard arrows to work with and player two the WASD keys and left and right mouse buttons for grappling and shooting. For the game, it has an interesting side effect, in that players are forced not only to interact through the differing information on each player's screen but also have to physically interact and coordinate the controls.\nAs you can perhaps see, the ball-rolling navigation is quite hard to use.\nIt is a purely physics-based system, where, depending on the materiality of the ball, its weight, and therefore its inertia will drastically change.\nOn small screens, the prototype version of the game is virtually impossible to control and several visual bugs within the viewport still obfuscate items when they are too close. Considering that virtually all the mechanics are written from scratch, with a follow-me camera, collision detection, smart moving agents, and a still very wonky-looking grappling gun, I still think it deserves a spot in this portfolio.\nFor this project I focused completely on the mechanics of the game, resulting in lots of used prefabs and readymade 3D Objects. Next time, I want to do that myself too.\nI enjoyed my stint into Unity a lot and am looking forward to creating my first VR application and would love to try out some form of mechanics where the user vision is completely obfuscated by VR and they have to carry their eyes as a handheld connected camera so that the players can move around the camera itself with their hands.\n","path":null},{"url":"http://127.0.0.1:1111/blog/homebrew/","title":"Homebrew","description":null,"body":"Brewing\nMaking my own beer\nI love hosting, I love experimenting in the Kitchen. Starting with homebrews was a natural fit for me and during the first wave of Covid-19, I went the whole homebrewer’s route of bottle fermentation and small batches later elevating my game with larger batches of 50 liters and a pressure tank system.\nStarting out, I found it fascinating, how just 4 rather simple ingredients, malt, hops, water and yeast, can form such an incredible range of taste experiences. It was and still is, a tremendous learning experience, where one slowly has to accept not being able to control the process fully and find room for creativity.\nWhy do I present such an unrelated non-academic hobby here? I simply do not regard it as unrelated, experimenting and optimizing a process and a workflow, creating optimal conditions for the yeast to do its job feels very similar to approaching a coding project.\nYeast and what it does fascinates me. Every time I open the latch to release some pressure on the Tank I think of the awesome symbiotic relationships yeast has with humans and how many different strains live there together to create a unique, yet tailored flavor. Several ideas are floating around of changing the brewing process by capturing the created carbon dioxide and using it productively. I could see a car tire being filled with my beer gas, or an algae farm munching away on my CO2 byproducts. Within a closed-loop pressurized system, such ideas actually become realizable and I would love to explore them further.\nI am not yet an expert on algae, but I can manage with yeast and I believe they can coexist and create a more sustainable cycle of production.\nYoung Henrys, a brewery in Australia is already incorporating algae into its industrial process:\nThe Algae project\nSuch ideas do not come into the industry by themselves: I believe that art and the exploratory discovery of novel techniques are the same things. Good and inventive design can improve society and make steps towards sustainability. I want to be part of that and would love to find new ways of using yeast in other design contexts: See whether I can make them work in a closed circular system, make them calculate things for me, or simply making my next beer taste awesome with just the right amount of fizz.\n\n\n\n \n \n \n \n \n \n \n The latest iteration of my homebrew setup, using pressure tanks and a pressurized fermentation chamber\n \n \n \n \n \n \n \n \n An electric kettle I use for the Brew\n \n \n \n \n \n \n \n \n I made my own kegging system featuring a tap from an old table leg.\n \n \n \n \n \n \n \n \n An active fermentation\n \n \n \n \n \n \n \n \n Hops growing in our garden, so I can experiment with fresh specialty hops\n \n \n \n \n \n \n \n \n The leftover mass of spent grain. Animals love it, it's great for composting, but most importantly, it's great for baking bread!\n \n \n \n \n\n","path":null},{"url":"http://127.0.0.1:1111/blog/thesis/","title":"Bachelor Thesis","description":null,"body":"An online psycholinguistic study using reaction time\nLast year, I wrote my thesis during the pandemic. With the struggles our university had transitioning to online teaching, I selected a guided topic, although my initial dream was to start writing about my proposed plan for automated plastic recycling. You can read more about that here:\n\nI chose a project that wanted to examine the possibilities of a novel smart hearing protection device specifically designed for auditory hypersensitivity, which is often, but not always, and not exclusively a phenomenon visible in people with an autism spectrum disorder.\nA common reaction to this elevated sensitivity is stress and avoidance behavior, often leading to very awkward social situations and impairing the ability to take part in social situations.\nSchools are one such social situation and we all know the stress a noisy classroom can produce. Concentration is gone, and education, as well as essential skills like language reproduction, suffer.\nThere is lots of prior research on these fields, and there is some evidence that sensory information in people on the Autism spectrum is processed differently than in a neurotypical brain. It seems that a certain adaptability, needed to overcome noise issues and bridge asynchrony between auditory and visual sensory input, is reduced in some people on the Autism Spectrum.\nIn essence, my experiment was responsible for looking at neurotypical people and measuring any effect on language perception produced by varying the delay between auditory and visual input, as well as the loudness.\nHere, I had the possibility to conduct an entire reaction-time-based experiment with over 70 participants and went through all the struggles that come with proper science.\nI did extensive literature research, coded the experiment, and learned a lot about the reasons nobody really ever does reaction time-based studies like this via a common internet browser.\nIt was an almost 9 months long learning experience full of doing things I had never done before.\nI learned and got to love writing in Latex, had to learn JavaScript for the efficient serving of the stimuli, and R for the statistical analysis. I also got to brush up on my data visualization skills in Python and made some pretty graphs of the results.\nThe experiment is still working and online if you want to have a look at it. Be mindful though that measuring reaction speed every millisecond is important, which is why it makes heavy use of your browser cache and has been known to crash and defeat some not-so-tough computers.\n\n Try out the experiment yourself\n\nEven with writing alone I had extensive helpful feedback from my supervisors and learned a lot about scientific processes and associated considerations.\nThere was always the next unsolvable problem. Just one example was scientificity and ethical considerations clashing, data privacy against the accuracy of results. Since the machines participants participated on, were private devices, I was unable to know important data like their internet speed and provider, their type of GPU, and their type of external hardware. Turns out, for an auditory experiment, the type and setup of the speakers do play an important role and influence response speed.\nThe final version of my thesis has something around 80 pages, much of it utterly boring, but nevertheless important statistical analyses.\nIf you really want to, you can have a look at the whole thing here:\n\n Read the original Thesis\n\nI am a fan and proponent of open source and open science practices.\nSo here you can also find the rest of the project with the original source code.\nI am not yet where I want to be with my documentation practices, and it scares me a bit that anyone can now have a full grasp of all the mistakes I did, but I am throwing this out there as a practice step. I learned and gained a lot from looking at other people's projects and I strive to be open about my processes too.\nThe original video stimuli are not mine and I have no right releasing them, so they are omitted here.\n\n Find the complete Repo on Github\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/coding/","title":"Coding Examples","description":null,"body":"Neural Networks and Computer Vision\nA selection of coding projects\nAlthough pure coding and debugging are often not a passion of mine, I recognize the importance of neural networks and other recent developments in Computer Vision. From several projects regarding AI and Machine Learning that I co-authored during my Bachelor Program, I picked this one since I think it is well documented and explains on a step-by-step basis what we do there.\nImage Super-Resolution using Convolutional Neural Networks (Recreation of a 2016 Paper)\nImage Super-Resolution is a hugely important topic in Computer Vision. If it works sufficiently advanced, we could take all our screenshots and selfies and cat pictures from the 2006 facebook-era and even from before and scale them up to suit modern 4K needs.\nJust to give an example of what is possible in 2020, just 4 years after the paper here, have a look at this video from 1902:\n\n\nThe 2016 paper we had a look at is much more modest: it tries to upscale only a single Image, but historically, it was one of the first to achieve computing times sufficiently small to make such realtime-video-upscaling as visible in the Video (from 2020) or of the likes that Nvidia uses nowadays to upscale Videogames.\nExample of a Super-Resolution Image.\nThe Neural network is artificially adding Pixels so that we can finally put our measly selfie on a billboard poster and not be appalled by our deformed-and-pixelated-through-technology face.\n\n\n\n \n \n \n \n \n \n \n A low-resolution sample\n \n \n \n \n \n \n \n \n A high-resolution sample. This is also called 'ground truth'\n \n \n \n \n \n \n \n \n The artificially enlarged image patch resulting from the algorithm\n \n \n \n \n \n \n \n \n A graph showing an exemplary loss function applied during training\n \n \n \n \n \n \n \n \n One qualitative measurement we used was pixel-wise cosine similarity. It is used to measure how similar the output and the ground truth images are\n \n \n \n \n\nThe Python notebook for Image super-resolution in Colab\nMTCNN (Application and Comparison of a 2016 Paper)\nHere, you can also have a look at another, much smaller project, where we rebuilt a rather classical Machine learning approach for face detection. Here, we use preexisting libraries to demonstrate the difference in efficacy of approaches, showing that Multi-task Cascaded Convolutional Networks (MTCNN) was one of the best-performing approaches in 2016. Since I invested much more love and work into the above project, I would prefer for you to check that one out, in case two projects are too much.\nFace detection using a classical AI Approach (Recreation of a 2016 Paper)\n","path":null},{"url":"http://127.0.0.1:1111/blog/critical-philosophy-subjectivity/","title":"Critical Philosophy of Subjectivity","description":null,"body":"Forum entries from the Seminar: Critical Philosophy of Subjectivity 1: Michel Foucault\nOn Butler: Constituting norms =/= carrying normative responsibilities for their existence\n\n\t\n\t\tNote\n\tSource Text: Butler, J. (2004). Undoing Gender (1st ed.). Routledge. https://doi.org/10.4324/9780203499627\nPublication\n\n\nCitation from Butler, Page 51, citing Ewald, which is, in turn, interpreting Foucault:\n\nThe norm integrates anything which might attempt to go beyond it—nothing, nobody, whatever difference it might display, can ever claim to be exterior, or claim to possess an otherness which would actually make it other”\n(Norms, Discipline, and the Law, P.173)\n\nSuch a view suggests that any opposition to the norm is already\ncontained within the norm, and is crucial to its functioning.\nHere, for me, the entire futility of the approach later identified and described is condensed into a few sentences.\n\nHence, regulations that seek merely to curb certain specified activities (sexual harassment, welfare fraud, sexual speech) perform another activity that, for the most part, remains unmarked: the production of the parameters of personhood, that is, making persons according to abstract norms that at once condition and exceed the lives they make—and break.\nPage 56, final sentence\n\nThe idea that it is impossible to legislatively regulate norms without propelling, propagating, and carving them out deeper resonates with me, but at the same time, it has left me undecided on how to proceed.\nI understand the first citation to clearly be Ewald's interpretation of things and am not sure whether Foucault's careful circumvention of the term \"Norms\" is related to anticipation of this argument.\nFurther, I am not sure I share Ewald's interpretation; I see that the object \"othered\" by a norm is a constituent and necessary object for the norm, simply due to its \"comparative\" nature (p. 51, citation from Ewald).\nThe oppressed may well be as constituting of norms as the privileged, but this does not translate to a normative responsibility nor a pang of guilt in my opinion. The dangerous argument that the oppressed bear responsibility for their situation is too close for my taste. I would like to emphasize a clear cut between constituting and reinforcing a norm and thriving on it.\nYes, maybe that is a good location to make the cut: The normative and ethical pressure, or better, the guilt of complicity lies with the ones thriving BECAUSE of a norm and clearly not with those thriving DESPITE OF a norm.\nI would think that Butler makes a similar argument elsewhere, but as such, I was missing it here, resulting in a very bleak and hopeless situation where any struggle to change the status quo through legislation is doomed and inevitably propagates and reinvents stable unfair relations of power.\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 23. January 2022, 14:23\n\n\nOn Ewald: What, then, is a norm?\n\n\t\n\t\tNote\n\tSource Text: François Ewald; Norms, Discipline, and the Law. Representations 1 April 1990; 30 138–161. doi: https://doi.org/10.2307/2928449\nPublication\n\n\nSome tiny details about norms that stuck out to me about the norm were that: 1: they are fictional and thus, an object conforming to a norm is not more meaningful than an object not conforming to a norm. 2: the entire given set comprises the norm, the deviations play a defining role in the formation of the norm itself (or an average).\np. 152: Under norm, 3 phenomena are subsumed: Discipline,\nless as a constraint, but more as a regulatory mechanism insurance,\nReducing objects to their relative occurrence, distributing risk. and standardization.\nThe norm has three defining features:\n\npositivism,\nas reliant on facts, which have an aura of objectivity around them.\nrelativity,\nthey are neither absolute nor universal, they have a scope, both in definition as a certain temporal extension.\npolarity\ninvolving a classification between the normal and the abnormal, where the abnormal is to be some handicap, not attaining something that the normal does attain.\n\nWhat, then, is a norm?\n\nIt is a way for a group to provide itself with a common denominator in accordance with a rigorous principle of self-referentiality, with no recourse to any kind of external reference point, either in the form of an idea or an object. The normative process can obey a variety of different logics: the panoptical logic of discipline, the probabilistic schema of insurance, or the communicative logic of the technical norm. These three logics have the same form: in each case, the rule which serves as a norm, by virtue of which everyone can measure, evaluate, and identify himself or herself, will be derived from those for whom it will serve as a standard. A strange logic, this, which forces the group to turn back in upon itself and which, from the moment it establishes itself, will let no one escape its purview.\np. 154\n\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 16. January 2022, 18:48\n\n\nOn Foucault: The effects without effector\n\n\t\n\t\tNote\n\tSource Text: Michael Foucault. Power/knowledge: Selected interviews and other writings 1972–1977. Pantheon, New York, 1980.\nPublication\n\n\n\none finds all sorts of support mechanisms [...] which invent, modify and re-adjust, according to the circumstances of the moment and the place- so that you get a coherent, rational strategy, but one for which it is no longer possible to identify a person who conceived it.\np. 203\n\nIn this passage, and the one following it, I think Foucault pinpoints as one of the central attributes of the apparatus (or dispositif) the arbitrariness of the order of power relations. There is no identity having to undergo some sort of inventive process to start off a collective change, a \"strategy\" just happens to meet the criteria for deployment.\n\nBut between the strategy which fixes, reproduces, multiplies and accentuates existing relations of forces, and the class which thereby finds itself in a ruling position, there is a reciprocal relation of production. Thus one can say that the strategy of moralising the working class is that of the bourgeoisie. One can even say that it's the strategy which allows the bourgeois class to be the bourgeois class and to exercise its domination. But what I don't think one can say is that it's the bourgeois class on the level of its ideology or its economic project which, as a sort of at once real and fictive subject, invented and forcibly imposed this strategy on the working class.\n\nThis was for me the most powerful grasp of what an apparatus is. A complicated removal of the effector from the effect.\nI struggle to continue to find any substance to the relations of the classes. Does reciprocal mean anything more than both are constitutive of each other? One produces the means of reproduction of the other, but where exactly can I apply moral judgements?\nThis whole ordeal and now I lack subjects to blame.\nHow can this theory possibly bring about change in society? Is that even its goal? Do we undergo this analysis in order to make society better in the end?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 12. December 2021, 22:01\n\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/philosophy/","title":"Philosophy","description":null,"body":"Critical considerations during my studies\nI have attended a fair share of philosophical seminars in my studies and consider it a core topic connected both to science and to digital environments.\nNormative and feminist social theory, as well as the theory of science and phenomenology, are all brought to me through seminar formats at university and made up a good part of my education there.\nI find it hard to properly demonstrate what interests me without presenting often long-winded and dull term papers.\nThe courses I loved most also often had a format with a weekly hand-in, where students are asked to comment on the paper they just read to identify points to carry into next week's discussion. I am incredibly thankful for this methodology of approaching complex philosophical works, often complete books with supplicant essays surrounding the course topic. In my opinion, nearly all of the value created during these seminars is contained within the live discussions fed by reading materials and little opinion pieces in the form of forum comments. That's why I decided to share here a selection of these weekly commentaries and the sources they are based upon. They are often unrefined and informal, but they indicate the centerpiece of the seminars and demonstrate many thought processes that happened within me during these sessions. Although I took only a small selection, in sum they are a substantial read. Feel free to just skip through and read what catches your interest.\nForum entries from the Seminar: Critical Epistemologies\nOn Anderson: Institutions\n\n\t\n\t\tNote\n\tSource Text: Epistemic Justice as a Virtue of Social Institutions\nElizabeth Anderson (2012) Epistemic Justice as a Virtue of Social Institutions, Social Epistemology, 26:2, 163-173,\nDOI: 10.1080/02691728.2011.652211 Publication\n\n\nThe text by Anderson helped shed light on a few issues I stumbled over with Frickers Account. On top of the various issues I and seemingly others have with her virtue-based approach, I think a utilitarian angle is worth considering. That would be: okay, I accept that people can help fight injustice by realising their privilege, showing restraint, silencing themselves, and adopting the benevolent listening approach. I think that is a practical, virtuous, and realistic endeavour.\nBut is it the effective path to alleviating structural injustice? I think not, and initially, that is a major reason I discarded Fricker’s approach, although I saw merit. I have similar concerns to Anderson in the scalability of virtues. Virtuous behavior might help my personal well-being, it gives me normative elevation and might even further the quality of relationships I have. But is it applicable to society, is it enough to counteract structural injustice?\nWell, maybe, assuming that:\n\nEveryone realizes their privilege,\nEveryone concludes that justice is the right goal,\nUpon deciding to adopt a virtuous stance, everyone at least moderately succeeds in practicing what they preach.\n\nI think, for society, the same society that came up with patriarchy in the first place, external pressure, some measure independent of the convictedness of the subjects is needed.\nAnderson made the powerful point of: “Anything that works, goes”, which took me some time to appreciate. I am always angry when I get told to keep my shower to a minimum or stop using plastic straws when I know exactly that my using less water is nothing compared to the institutionalized practice of Coca-Cola putting water into bottles. I feel like it is unjustified to ask me to save water while others triple their output, for performance.\nThe same thing applies to Epistemic injustices. It strikes me how much energy it costs to keep up virtuous behavior individually and how little effect there is to show for it. I do not believe in “trickling up” where institutions will eventually adopt individual practices.\nIs Fricker thereby less right in her point? No, it adds up, as an entire population showering shorter adds up to lots of water saved.\nAnderson also points out how locally innocent biases can create injustice on a “macro” scale. Another indicator for me is that local virtue is not the sole solution, as it can still feed and sustain a system enforcing epistemic injustice.\nI still have doubts about what to do now with my ideas, on how the world looks that I want. I lack the imagination of seeing a world that is epistemically just, and it is hard to strive for something one cannot even imagine. The system is inherently leaning toward inequality, if I try to balance something on a needle, it will only go well so long, before small imbalances create chain reactions and the object should be called unstable. Should we even succeed in “resetting” society, creating equal participation for each subject, how will it remain just? Is Justice always a conjunct of Equality? Are there ways to achieve real Justice without needing equality?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Tuesday 14. July 2020, 17:45\n\n\nOn Medina, the informant and the inquirer\n\n\t\n\t\tNote\n\tSource Text: Dr. José Medina (2012) Hermeneutical Injustice and Polyphonic Contextualism: Social Silences and Shared Hermeneutical Responsibilities, Social Epistemology, 26:2, 201-220, DOI: 10.1080/02691728.2011.652214\nPublication\n\n\nMy biggest takeaway here was that, as I tried to hint at in an earlier comment,\nWhenever we talk about justice, this necessarily refers to a relational concept, where everybody has a double role to ensure successful communication. Medina calls these the inquirer and the informant. So, every individual has to make sure to act to her capacity as an epistemologically sound knowledge-acquiring agent (the inquirer). This would involve knowing when and how to falsify/qualify statements, making inferences about the theory of mind, and generally comparing different statements. The other role is the informant, where the individual should have the capacity to function as an object in an inquiry by another.\nVery roughly this can, I think, be compared to any good communication model, where there are a listener and a speaker, and both have to function. What was new here, or at least came out more clear is that it not only depends on the capacity of both of these roles on the subject, but it is also directly dependent on the “other”, the agent opposite of the subject. We may call this other society later but it helps me to visualize the other as an individual nonetheless. Where the analogy to communication now fails, in my opinion, is this cross-dependence, where an agent does not fully determine her capacity to act both as an inquirer and as an informant, it is co-determined by the “other”. So, if I, as an “other”, listen to someone's statements, and I fail or refuse to understand the epistemic content of the message, I am not only impairing my epistemic agency, but I also hurt the epistemic agency of the subject. Maybe obvious to most, but this thought struck me as being exactly the point of leverage for dysfunctionalities in power relations.\nAlso argued convincingly in the paper was that these are distinct and independent agencies, which can be impairing an individual separately.\nOverall, the Medina text was incredibly helpful after the somewhat confusing Fricker text that felt incomplete and left a lot of questions for me. The medina text picked up all my initial doubts, that I couldn't properly formulate, and many more, while still holding to the general framework of Fricker.\nAlthough I was not convinced by the Fricker Text, I tend to think the strategy:\n\"When in doubt, give the subject full epistemic credibility\"\nIs a good strategy that might alleviate a lot of issues regarding functions of power, and hierarchy, but also further, it might be a good counter for things as our confirmation bias, expectation bias and many individual errors that we could minimize by constantly exposing ourselves to falsifiability through others (voluntarily). Sounds like science applied to agency to me.\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Thursday 09. July 2020, 11:25\n\n\nOn Jaggar: Norms, Outlaw Emotions, and the Ideal Society\n\n\t\n\t\tNote\n\tSource Text: Alison M. Jaggar (1989) Love and knowledge: Emotion in feminist epistemology, Inquiry, 32:2, 151-176, DOI: 10.1080/00201748908602185\nPublication\n\n\nI found Jaggar to be a very wholesome read, it was the perfect amount of grounded argumentative structure and felt very connected as a whole. This was, together with the ideas from Lugones the best and most fruitful paper for me.\nOn outlaw emotions:\nFirst, I hate the term, I think it’s placative and fails to frame the (actually nice) idea behind it.\nOutlaw Emotions are all those emotions incompatible with the dominant norms. That’s a huge field to cover, among feminist emotions they would also encompass emotions that are irrational or “faulty”. So, Jaggar does the term Justice by saying, some, but not all Outlaw Emotions are Feminist emotions. To make this evident, just think of a murderer's joy for killing, it is of no feminist interest to dissect, yet it is against dominant values. So, experiencing Outlaw emotions is a (probably) necessary, but not sufficient condition for feminism. The incompatible emotion serves to create discourse and change.\nJaggar convincingly shows how emotions have a direct influence on beliefs and can validly constitute evidence, while simultaneously validly influencing values in a similar manner.\nWhen we talk about dominant/alternative norms, we already endorse hierarchy in society. We acknowledge its existence, simply by identifying the dominant norm. I am not quite sure what exactly Jaggar proposes we should do with the hierarchy structures in society. Explicitly I can read: Subcultures rejecting dominant norms should be formed, to create counterbalances and a somewhat fair discourse over the topic.\n“How can we determine which outlaw emotions are to be endorsed or encouraged and which rejected? In what sense can we say that some emotional responses are more appropriate than others? What reason is there for supposing that certain alternative perceptions of the world, perceptions informed by outlaw emotions, are to be preferred to perceptions informed by conventional emotions? Here I can indicate only the general direction of an answer, whose full elaboration must await another occasion. I suggest that emotions are appropriate if they are characteristic of a society in which all Human Life (and perhaps some nonhuman life, too) thrive, or if they are conducive to establishing such a society.”\nTo me this passage sounds sketchy at best, there is no indication of how to successfully separate appropriate from inappropriate emotions. Roughly, I read this part as: emotions are warranted iff they increase the balance of power. (equivalent to minimizing the height of the hierarchy) I would love to get to read this “other occasion” because it seems indefensible to me to formulate a norm that states: Accept only emotions which eliminate/diminish norms.\nThe idea roughly resembles Rawls's Minimax Principle, where a policy should be implemented iff the benefit for the most disadvantaged is highest.\nAnother thing I found helpful is her reformulation of what norms do:\n“Dominant Norms tend to serve dominant interests”\ntil here nothing new, this is a tautology for me, I understand norms as identical to dominant interests, that’s literally what norms are.\nIs an alternative, suppressed norm even thinkable? Isn't it inherent in a norm that it be the dominant one?\nBut then, after that: \"Whatever our color / gender / class / sexual orientation, we are likely to adopt the dominant value of racist, classist, homophobe, misogynistic white men.\"\nThis was rather helpful to me, as it reframes the “act” of oppression as the “likelihood of value distribution” being skewed in your favor, making everybody’s values more likely to be similar to yours. This nicely illustrates how a system can be hierarchical and oppressive, without anybody actively, intentionally “acting oppressive”, while still perpetuating oppression. I'm\nnot saying everybody is acting unintentionally oppressive, but it is always hard to imagine for me to picture \"White Men\" forming a group and collectively deciding on who to hate this coming season, Conceptually separating \"being oppressed\" and \"oppressing\" into phenomena\nwithout necessary inherent causal relation makes sense to me here.\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Tuesday 23. June 2020, 18:52\n\n\nForum entries from the Seminar: Critical Philosophy of Subjectivity 1: Michel Foucault\nOn Butler: Constituting norms =/= carrying normative responsibilities for their existence\n\n\t\n\t\tNote\n\tSource Text: Butler, J. (2004). Undoing Gender (1st ed.). Routledge. https://doi.org/10.4324/9780203499627\nPublication\n\n\nCitation from Butler, Page 51, citing Ewald, which is, in turn, interpreting Foucault:\n\nThe norm integrates anything which might attempt to go beyond it—nothing, nobody, whatever difference it might display, can ever claim to be exterior, or claim to possess an otherness which would actually make it other”\n(Norms, Discipline, and the Law, P.173)\n\nSuch a view suggests that any opposition to the norm is already\ncontained within the norm, and is crucial to its functioning.\nHere, for me, the entire futility of the approach later identified and described is condensed into a few sentences.\n\nHence, regulations that seek merely to curb certain specified activities (sexual harassment, welfare fraud, sexual speech) perform another activity that, for the most part, remains unmarked: the production of the parameters of personhood, that is, making persons according to abstract norms that at once condition and exceed the lives they make—and break.\nPage 56, final sentence\n\nThe idea that it is impossible to legislatively regulate norms without propelling, propagating, and carving them out deeper resonates with me, but at the same time, it has left me undecided on how to proceed.\nI understand the first citation to clearly be Ewald's interpretation of things and am not sure whether Foucault's careful circumvention of the term \"Norms\" is related to anticipation of this argument.\nFurther, I am not sure I share Ewald's interpretation; I see that the object \"othered\" by a norm is a constituent and necessary object for the norm, simply due to its \"comparative\" nature (p. 51, citation from Ewald).\nThe oppressed may well be as constituting of norms as the privileged, but this does not translate to a normative responsibility nor a pang of guilt in my opinion. The dangerous argument that the oppressed bear responsibility for their situation is too close for my taste. I would like to emphasize a clear cut between constituting and reinforcing a norm and thriving on it.\nYes, maybe that is a good location to make the cut: The normative and ethical pressure, or better, the guilt of complicity lies with the ones thriving BECAUSE of a norm and clearly not with those thriving DESPITE OF a norm.\nI would think that Butler makes a similar argument elsewhere, but as such, I was missing it here, resulting in a very bleak and hopeless situation where any struggle to change the status quo through legislation is doomed and inevitably propagates and reinvents stable unfair relations of power.\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 23. January 2022, 14:23\n\n\nOn Ewald: What, then, is a norm?\n\n\t\n\t\tNote\n\tSource Text: François Ewald; Norms, Discipline, and the Law. Representations 1 April 1990; 30 138–161. doi: https://doi.org/10.2307/2928449\nPublication\n\n\nSome tiny details about norms that stuck out to me about the norm were that: 1: they are fictional and thus, an object conforming to a norm is not more meaningful than an object not conforming to a norm. 2: the entire given set comprises the norm, the deviations play a defining role in the formation of the norm itself (or an average).\np. 152: Under norm, 3 phenomena are subsumed: Discipline,\nless as a constraint, but more as a regulatory mechanism insurance,\nReducing objects to their relative occurrence, distributing risk. and standardization.\nThe norm has three defining features:\n\npositivism,\nas reliant on facts, which have an aura of objectivity around them.\nrelativity,\nthey are neither absolute nor universal, they have a scope, both in definition as a certain temporal extension.\npolarity\ninvolving a classification between the normal and the abnormal, where the abnormal is to be some handicap, not attaining something that the normal does attain.\n\nWhat, then, is a norm?\n\nIt is a way for a group to provide itself with a common denominator in accordance with a rigorous principle of self-referentiality, with no recourse to any kind of external reference point, either in the form of an idea or an object. The normative process can obey a variety of different logics: the panoptical logic of discipline, the probabilistic schema of insurance, or the communicative logic of the technical norm. These three logics have the same form: in each case, the rule which serves as a norm, by virtue of which everyone can measure, evaluate, and identify himself or herself, will be derived from those for whom it will serve as a standard. A strange logic, this, which forces the group to turn back in upon itself and which, from the moment it establishes itself, will let no one escape its purview.\np. 154\n\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 16. January 2022, 18:48\n\n\nOn Foucault: The effects without effector\n\n\t\n\t\tNote\n\tSource Text: Michael Foucault. Power/knowledge: Selected interviews and other writings 1972–1977. Pantheon, New York, 1980.\nPublication\n\n\n\none finds all sorts of support mechanisms [...] which invent, modify and re-adjust, according to the circumstances of the moment and the place- so that you get a coherent, rational strategy, but one for which it is no longer possible to identify a person who conceived it.\np. 203\n\nIn this passage, and the one following it, I think Foucault pinpoints as one of the central attributes of the apparatus (or dispositif) the arbitrariness of the order of power relations. There is no identity having to undergo some sort of inventive process to start off a collective change, a \"strategy\" just happens to meet the criteria for deployment.\n\nBut between the strategy which fixes, reproduces, multiplies and accentuates existing relations of forces, and the class which thereby finds itself in a ruling position, there is a reciprocal relation of production. Thus one can say that the strategy of moralising the working class is that of the bourgeoisie. One can even say that it's the strategy which allows the bourgeois class to be the bourgeois class and to exercise its domination. But what I don't think one can say is that it's the bourgeois class on the level of its ideology or its economic project which, as a sort of at once real and fictive subject, invented and forcibly imposed this strategy on the working class.\n\nThis was for me the most powerful grasp of what an apparatus is. A complicated removal of the effector from the effect.\nI struggle to continue to find any substance to the relations of the classes. Does reciprocal mean anything more than both are constitutive of each other? One produces the means of reproduction of the other, but where exactly can I apply moral judgements?\nThis whole ordeal and now I lack subjects to blame.\nHow can this theory possibly bring about change in society? Is that even its goal? Do we undergo this analysis in order to make society better in the end?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 12. December 2021, 22:01\n\n\nForum entries from the Seminar: Is political violence justifiable? Reading Judith Butler and Elsa Dorlin\nOn Dorlin\n\n\t\n\t\tNote\n\tSource Text: Dorlin, Elsa. Se défendre: une philosophie de la violence. Zones, 2017.\nPublication (Not yet translated to English)\n\n\nFrom the seventh chapter in Dorlins \"Self-Defense\", I found the idea that safe spaces are actually prone to be counterproductive very strong.\nI think the discussion around whether safe spaces are an effective tool that is appropriate on top is a rather current and ongoing one.\nIn so many other words, Dorlin here opens up the idea that the creation of a safe space always implies a hostile \"outside\" or other space.\nFurther, Dorling sees as problematic that safe spaces will often experience problematic situations when trying to self-govern. The line of thought here is that safe spaces often explicitly reject the authority of traditional state bodies, since those exactly are identified as the oppressive force. This is problematic because then the community inside the safe space has to recreate social norms from scratch and qua definition of a safe space end up being much more restrictive and monitoring, tapping also into potentially extreme measurements for \"enforcing\" safety.\nDorlin notes that by doing this, societal oppressive norms can end up becoming reproduced through the very instance created to shelter from it.\nI think this opens up 2 points worth discussing:\nAre there limits to the self-governance of leftist groups? How can self-governance be made possible without recreating some hierarchy or other?\nDoes this ignore that safe spaces can sometimes be essential for survival? According to Dorlin, the alternative seems to be to instead of building sheltered, isolated safe spaces, the fight has to occur in the public, transforming the entire space without the necessity for exclusive logic. How can we argue this? Could there be an oppressed position from whence any aggressive stance towards the public forbids itself? (I think there is!) For me this seems like putting the entire burden of transformational potential on the oppressed individual, enabling a position like: \"Well, the person did not object or introduce change, so the person implied consent.\"\nWill a public fight cause more harm being fought than it will save after introducing change? And who are we to calculate this beforehand?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 05. December 2021, 15:52\n\n\nWeekly hand in from the Seminar: Soziale Erkenntnistheorie\nOn Fricker: Epistemic Injustice\n\n\t\n\t\tNote\n\tSource Text: Fricker, Miranda. Epistemic injustice: Power and the ethics of knowing. Oxford University Press, 2007.\nPublication\n\n\n\nWorin unterscheiden sich inferentialistische von nicht-inferentialistischen Theorien der testimonialen Erkenntnis (d.h. des Wissens durch das Zeugniss andere)?\n\nInferentialistische Theorien gehen davon aus, dass die eigentliche Inferenz, also die Generierung eines neuen Epistems im Subjekt stattfindet. Konkret heisst dass, dass Ich die Aussage P einer dritten Person erst in irgendeiner Weise vor mir selbst rechtfertigen muss, bevor ich sie selbst verwenden kann. Ist die Aussage nun 2 + 2 = 4, muss ich also mit allen mir zur Verfügung stehenden Mitteln selbst überprüfen, ob diese Aussage Wahrheits- und Kohärenzkriterien erfüllt. Ich muss also beispielsweise über darunterliegende Axiome, die mir bekannt sind, die Aussage extern (ausserhalb von Person X hat das gesagt, also kann Ich das glauben) überprüfen. Im simplen Beispiel also konkret das Ergebnis berechnen. Wenn man so will, liegt also immer die “Beweislast” für meine eigenen Episteme bei mir und ich kann diesen Beweisaufwand nur begrenzt auslagern. Eine sehr direkte Folge davon wäre, dass jeglicher Erkenntnisgewinn mit erheblicher, bewusster oder unbewusster Arbeit verbunden ist.\nDies wäre die wahrscheinlich logisch stringentere Theorie, gegen sie spricht aber die Phänomenologie eines Erkenntisgewinns. Eine Erkenntnis kommt uns oft vor wie ein “Heureka” Moment, wir “finden” sie, plötzlich ist sie da und wir können mit ihr arbeiten.\nEine nicht-inferentialistische Theorie legt ebendiese Beweislast nicht im Subjekt an, ich habe eine Erlaubnis, oder besser, ein Recht auf a-priori Annahme der Richtigkeit der Aussage. “Person X hat mir P gesagt, also kann ich P verwenden” ist nun valide und bedarf erstmal keiner weiteren Überprüfung auf Richtigkeit. Diese Argumentationslinie ist deutlich kompatibler mit der phänomenologischen Erfahrung einer Erkenntnis vim Alltag. Wir stoßen aber auf deutlich größere Probleme, wenn wir uns fragen, woher eigentlich unser Recht auf Wahrheitsannahme von Drittaussagen kommt. Klar, 2+2=4, weil der Prof das an die Tafel geschrieben hat, ist die “schlechtere” Begründung als zu sagen, dass das Ergebnis aus gewissen mathematischen Axiomen deduziert wurde.\n\nFormulieren Sie jeweils einen Einwand gegen beide Theorien.\n\nWir befinden uns also nun in der Spannung der phänomenalistischen “Heureka” Erfahrung des Findens von Epistemen (in nicht-inferentiellen Systemen) und dem Problem der schwachen Justifizierung von Aussagen gegenüber der erhöhten Stringenz eines epistemischen Systems, dass externe (logische, probabilistische, normative etc.) Gründe für Aussagen zur Verfügung stellt, aber einen schier unüberwindbaren rechnerischen Aufwand darstellt. Auch das Problem der ersten Begründung bleibt bestehen. Angenommen, ich weiß noch nichts, habe bisher null Episteme gesammelt, wie wird das erste Epistem, das ich finde, begründbar sein?\n\nWorin besteht doxastische Verantwortung (doxastic responsibility) nach F und Ihrer eigenen Meinung nach.\n\nDoxastische Verantwortung ist die Verantwortung für die Begründbarkeit des eigenen Nezwerkes aus Epistemen. Wenn mich also jemand fragt: Warum glaubst du das?, ist es sozial im Allgemeinen erwartbar, dass ich darauf eine Antwort liefern kann. Und wie wir eben schon am Beispiel der Begründung für 2+2=4 gesehen haben, scheint es hier “bessere” und weniger gute Gründe zu geben, das heisst, eine Person kann zur Verantwortung gezogen werden, unzureichend begründete Episteme fallen zu lassen und eine gewisse Grenze zu ziehen, eine mindest erwartbare Begründung. Diese kann sehr wahrscheinlich nicht universell formuliert werden. Eine Regel wie: Alle Bürger dürfen nur noch Aussagen weiterverwenden, denen sie eine mindestens 90-prozentige Wahrheitswarscheinlichkeit attestieren, ist aus diversen Gründen problematisch.\nFrickers Auffassung Doxastischer Verantwortung ist insofern speziell, als dass sie eine deutliche Verbindung moralischer Verantwortung (die wir offensichtlich alle in irgendeiner Form tragen) und Doxastischer Verantwortung sieht. Sogar die Gründe sind oft überlappend. Eine Gute Moralische Begründung, die zum Beispiel der Wahrhaftigkeit, scheint ganz offensichtlich auch eine gute doxastische begründung zu sein. Diese Parallelität zieht Fricker heran, um neo-aristotelianische Moralbegründuungen auch auf epistemischer Ebene wirksam zu machen.\nIch lasse mich da gern Überzeugen von Ihr und erache es als sinnvoll Doxastische Verantwortung in gewisser Weise moralisch bindend zu machen. Intuitiv wissen wir ja auch, dass unsere Erwartung, dass dritte wahrhaftig mit uns interagieren, auf Gegenseitigkeit beruht und das leben nicht nur normativ, sondern auch auf epistemischer Ebene “verbessert”. Dies liefert auch eine recht simplistesche Rechtfertigung, annehmen zu können, dass Dritte mir die Wahreit sagen. Ich tue ja auch immer mein Bestes, warum also die anderen nicht?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on 05.01.2021\n\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/political-violence/","title":"Political Violence","description":null,"body":"Forum entries from the Seminar: Is political violence justifiable? Reading Judith Butler and Elsa Dorlin\nOn Dorlin\n\n\t\n\t\tNote\n\tSource Text: Dorlin, Elsa. Se défendre: une philosophie de la violence. Zones, 2017.\nPublication (Not yet translated to English)\n\n\nFrom the seventh chapter in Dorlins \"Self-Defense\", I found the idea that safe spaces are actually prone to be counterproductive very strong.\nI think the discussion around whether safe spaces are an effective tool that is appropriate on top is a rather current and ongoing one.\nIn so many other words, Dorlin here opens up the idea that the creation of a safe space always implies a hostile \"outside\" or other space.\nFurther, Dorling sees as problematic that safe spaces will often experience problematic situations when trying to self-govern. The line of thought here is that safe spaces often explicitly reject the authority of traditional state bodies, since those exactly are identified as the oppressive force. This is problematic because then the community inside the safe space has to recreate social norms from scratch and qua definition of a safe space end up being much more restrictive and monitoring, tapping also into potentially extreme measurements for \"enforcing\" safety.\nDorlin notes that by doing this, societal oppressive norms can end up becoming reproduced through the very instance created to shelter from it.\nI think this opens up 2 points worth discussing:\nAre there limits to the self-governance of leftist groups? How can self-governance be made possible without recreating some hierarchy or other?\nDoes this ignore that safe spaces can sometimes be essential for survival? According to Dorlin, the alternative seems to be to instead of building sheltered, isolated safe spaces, the fight has to occur in the public, transforming the entire space without the necessity for exclusive logic. How can we argue this? Could there be an oppressed position from whence any aggressive stance towards the public forbids itself? (I think there is!) For me this seems like putting the entire burden of transformational potential on the oppressed individual, enabling a position like: \"Well, the person did not object or introduce change, so the person implied consent.\"\nWill a public fight cause more harm being fought than it will save after introducing change? And who are we to calculate this beforehand?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Sunday 05. December 2021, 15:52\n\n\nWeekly hand in from the Seminar: Soziale Erkenntnistheorie\nOn Fricker: Epistemic Injustice\n\n\t\n\t\tNote\n\tSource Text: Fricker, Miranda. Epistemic injustice: Power and the ethics of knowing. Oxford University Press, 2007.\nPublication\n\n\n\nWorin unterscheiden sich inferentialistische von nicht-inferentialistischen Theorien der testimonialen Erkenntnis (d.h. des Wissens durch das Zeugniss andere)?\n\nInferentialistische Theorien gehen davon aus, dass die eigentliche Inferenz, also die Generierung eines neuen Epistems im Subjekt stattfindet. Konkret heisst dass, dass Ich die Aussage P einer dritten Person erst in irgendeiner Weise vor mir selbst rechtfertigen muss, bevor ich sie selbst verwenden kann. Ist die Aussage nun 2 + 2 = 4, muss ich also mit allen mir zur Verfügung stehenden Mitteln selbst überprüfen, ob diese Aussage Wahrheits- und Kohärenzkriterien erfüllt. Ich muss also beispielsweise über darunterliegende Axiome, die mir bekannt sind, die Aussage extern (ausserhalb von Person X hat das gesagt, also kann Ich das glauben) überprüfen. Im simplen Beispiel also konkret das Ergebnis berechnen. Wenn man so will, liegt also immer die “Beweislast” für meine eigenen Episteme bei mir und ich kann diesen Beweisaufwand nur begrenzt auslagern. Eine sehr direkte Folge davon wäre, dass jeglicher Erkenntnisgewinn mit erheblicher, bewusster oder unbewusster Arbeit verbunden ist.\nDies wäre die wahrscheinlich logisch stringentere Theorie, gegen sie spricht aber die Phänomenologie eines Erkenntisgewinns. Eine Erkenntnis kommt uns oft vor wie ein “Heureka” Moment, wir “finden” sie, plötzlich ist sie da und wir können mit ihr arbeiten.\nEine nicht-inferentialistische Theorie legt ebendiese Beweislast nicht im Subjekt an, ich habe eine Erlaubnis, oder besser, ein Recht auf a-priori Annahme der Richtigkeit der Aussage. “Person X hat mir P gesagt, also kann ich P verwenden” ist nun valide und bedarf erstmal keiner weiteren Überprüfung auf Richtigkeit. Diese Argumentationslinie ist deutlich kompatibler mit der phänomenologischen Erfahrung einer Erkenntnis vim Alltag. Wir stoßen aber auf deutlich größere Probleme, wenn wir uns fragen, woher eigentlich unser Recht auf Wahrheitsannahme von Drittaussagen kommt. Klar, 2+2=4, weil der Prof das an die Tafel geschrieben hat, ist die “schlechtere” Begründung als zu sagen, dass das Ergebnis aus gewissen mathematischen Axiomen deduziert wurde.\n\nFormulieren Sie jeweils einen Einwand gegen beide Theorien.\n\nWir befinden uns also nun in der Spannung der phänomenalistischen “Heureka” Erfahrung des Findens von Epistemen (in nicht-inferentiellen Systemen) und dem Problem der schwachen Justifizierung von Aussagen gegenüber der erhöhten Stringenz eines epistemischen Systems, dass externe (logische, probabilistische, normative etc.) Gründe für Aussagen zur Verfügung stellt, aber einen schier unüberwindbaren rechnerischen Aufwand darstellt. Auch das Problem der ersten Begründung bleibt bestehen. Angenommen, ich weiß noch nichts, habe bisher null Episteme gesammelt, wie wird das erste Epistem, das ich finde, begründbar sein?\n\nWorin besteht doxastische Verantwortung (doxastic responsibility) nach F und Ihrer eigenen Meinung nach.\n\nDoxastische Verantwortung ist die Verantwortung für die Begründbarkeit des eigenen Nezwerkes aus Epistemen. Wenn mich also jemand fragt: Warum glaubst du das?, ist es sozial im Allgemeinen erwartbar, dass ich darauf eine Antwort liefern kann. Und wie wir eben schon am Beispiel der Begründung für 2+2=4 gesehen haben, scheint es hier “bessere” und weniger gute Gründe zu geben, das heisst, eine Person kann zur Verantwortung gezogen werden, unzureichend begründete Episteme fallen zu lassen und eine gewisse Grenze zu ziehen, eine mindest erwartbare Begründung. Diese kann sehr wahrscheinlich nicht universell formuliert werden. Eine Regel wie: Alle Bürger dürfen nur noch Aussagen weiterverwenden, denen sie eine mindestens 90-prozentige Wahrheitswarscheinlichkeit attestieren, ist aus diversen Gründen problematisch.\nFrickers Auffassung Doxastischer Verantwortung ist insofern speziell, als dass sie eine deutliche Verbindung moralischer Verantwortung (die wir offensichtlich alle in irgendeiner Form tragen) und Doxastischer Verantwortung sieht. Sogar die Gründe sind oft überlappend. Eine Gute Moralische Begründung, die zum Beispiel der Wahrhaftigkeit, scheint ganz offensichtlich auch eine gute doxastische begründung zu sein. Diese Parallelität zieht Fricker heran, um neo-aristotelianische Moralbegründuungen auch auf epistemischer Ebene wirksam zu machen.\nIch lasse mich da gern Überzeugen von Ihr und erache es als sinnvoll Doxastische Verantwortung in gewisser Weise moralisch bindend zu machen. Intuitiv wissen wir ja auch, dass unsere Erwartung, dass dritte wahrhaftig mit uns interagieren, auf Gegenseitigkeit beruht und das leben nicht nur normativ, sondern auch auf epistemischer Ebene “verbessert”. Dies liefert auch eine recht simplistesche Rechtfertigung, annehmen zu können, dass Dritte mir die Wahreit sagen. Ich tue ja auch immer mein Bestes, warum also die anderen nicht?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on 05.01.2021\n\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/chatbot/","title":"Chatbot","description":null,"body":"Guru to Go: a speech-controlled meditation assistant and sentiment tracker\n\n\nHere, you see a Demo video of a voice-controlled meditation assistant that we worked on in the course \"Conversational Agents and speech interfaces\"\n\n Course Description\n\nThe central goal of the entire project was to make the Assistant be entirely speech controlled, such that the phone needn't be touched while immersing yourself in meditation.\nThe Chatbot was built in Google Dialogflow, a natural language understanding engine that can interpret free text input and identify entities and intents within it,\nWe wrote a custom python backend to then use these evaluated intents and compute individualized responses.\nThe resulting application runs in Google Assistant and can adaptively deliver meditations, visualize sentiment history and comprehensively inform about meditation practices. Sadly, we used beta functionality from the older \"Google Assistant\" Framework, which got rebranded months after by Google into \"Actions on Google\" and changed core functionality requiring extensive migration that neither Chris, my partner in this project, nor I found time to do.\nNevertheless, the whole Chatbot functioned as a meditation player and was able to graph and store recorded sentiments over time for each user.\nAttached below you can also find our final report with details on the programming and thought process.\n\n Read the full report\n\n\n Look at the Project on GitHub\n\n\n\t\n\t\tNote\n\tAfter this being my first dip into using the Google Framework for the creation of a speech assistant and encountering many problems along the way that partly found their way also into the final report, now I managed to utilize these explorations and am currently working to create Ällei, another chatbot with a different focus, which is not realized within Actions on google, but will rather be getting its own react app on a website.\n\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/critical-epistemologies/","title":"Critical Epistemology","description":null,"body":"Forum entries from the Seminar: Critical Epistemologies\nOn Anderson: Institutions\n\n\t\n\t\tNote\n\tSource Text: Epistemic Justice as a Virtue of Social Institutions\nElizabeth Anderson (2012) Epistemic Justice as a Virtue of Social Institutions, Social Epistemology, 26:2, 163-173,\nDOI: 10.1080/02691728.2011.652211 Publication\n\n\nThe text by Anderson helped shed light on a few issues I stumbled over with Frickers Account. On top of the various issues I and seemingly others have with her virtue-based approach, I think a utilitarian angle is worth considering. That would be: okay, I accept that people can help fight injustice by realising their privilege, showing restraint, silencing themselves, and adopting the benevolent listening approach. I think that is a practical, virtuous, and realistic endeavour.\nBut is it the effective path to alleviating structural injustice? I think not, and initially, that is a major reason I discarded Fricker’s approach, although I saw merit. I have similar concerns to Anderson in the scalability of virtues. Virtuous behavior might help my personal well-being, it gives me normative elevation and might even further the quality of relationships I have. But is it applicable to society, is it enough to counteract structural injustice?\nWell, maybe, assuming that:\n\nEveryone realizes their privilege,\nEveryone concludes that justice is the right goal,\nUpon deciding to adopt a virtuous stance, everyone at least moderately succeeds in practicing what they preach.\n\nI think, for society, the same society that came up with patriarchy in the first place, external pressure, some measure independent of the convictedness of the subjects is needed.\nAnderson made the powerful point of: “Anything that works, goes”, which took me some time to appreciate. I am always angry when I get told to keep my shower to a minimum or stop using plastic straws when I know exactly that my using less water is nothing compared to the institutionalized practice of Coca-Cola putting water into bottles. I feel like it is unjustified to ask me to save water while others triple their output, for performance.\nThe same thing applies to Epistemic injustices. It strikes me how much energy it costs to keep up virtuous behavior individually and how little effect there is to show for it. I do not believe in “trickling up” where institutions will eventually adopt individual practices.\nIs Fricker thereby less right in her point? No, it adds up, as an entire population showering shorter adds up to lots of water saved.\nAnderson also points out how locally innocent biases can create injustice on a “macro” scale. Another indicator for me is that local virtue is not the sole solution, as it can still feed and sustain a system enforcing epistemic injustice.\nI still have doubts about what to do now with my ideas, on how the world looks that I want. I lack the imagination of seeing a world that is epistemically just, and it is hard to strive for something one cannot even imagine. The system is inherently leaning toward inequality, if I try to balance something on a needle, it will only go well so long, before small imbalances create chain reactions and the object should be called unstable. Should we even succeed in “resetting” society, creating equal participation for each subject, how will it remain just? Is Justice always a conjunct of Equality? Are there ways to achieve real Justice without needing equality?\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Tuesday 14. July 2020, 17:45\n\n\nOn Medina, the informant and the inquirer\n\n\t\n\t\tNote\n\tSource Text: Dr. José Medina (2012) Hermeneutical Injustice and Polyphonic Contextualism: Social Silences and Shared Hermeneutical Responsibilities, Social Epistemology, 26:2, 201-220, DOI: 10.1080/02691728.2011.652214\nPublication\n\n\nMy biggest takeaway here was that, as I tried to hint at in an earlier comment,\nWhenever we talk about justice, this necessarily refers to a relational concept, where everybody has a double role to ensure successful communication. Medina calls these the inquirer and the informant. So, every individual has to make sure to act to her capacity as an epistemologically sound knowledge-acquiring agent (the inquirer). This would involve knowing when and how to falsify/qualify statements, making inferences about the theory of mind, and generally comparing different statements. The other role is the informant, where the individual should have the capacity to function as an object in an inquiry by another.\nVery roughly this can, I think, be compared to any good communication model, where there are a listener and a speaker, and both have to function. What was new here, or at least came out more clear is that it not only depends on the capacity of both of these roles on the subject, but it is also directly dependent on the “other”, the agent opposite of the subject. We may call this other society later but it helps me to visualize the other as an individual nonetheless. Where the analogy to communication now fails, in my opinion, is this cross-dependence, where an agent does not fully determine her capacity to act both as an inquirer and as an informant, it is co-determined by the “other”. So, if I, as an “other”, listen to someone's statements, and I fail or refuse to understand the epistemic content of the message, I am not only impairing my epistemic agency, but I also hurt the epistemic agency of the subject. Maybe obvious to most, but this thought struck me as being exactly the point of leverage for dysfunctionalities in power relations.\nAlso argued convincingly in the paper was that these are distinct and independent agencies, which can be impairing an individual separately.\nOverall, the Medina text was incredibly helpful after the somewhat confusing Fricker text that felt incomplete and left a lot of questions for me. The medina text picked up all my initial doubts, that I couldn't properly formulate, and many more, while still holding to the general framework of Fricker.\nAlthough I was not convinced by the Fricker Text, I tend to think the strategy:\n\"When in doubt, give the subject full epistemic credibility\"\nIs a good strategy that might alleviate a lot of issues regarding functions of power, and hierarchy, but also further, it might be a good counter for things as our confirmation bias, expectation bias and many individual errors that we could minimize by constantly exposing ourselves to falsifiability through others (voluntarily). Sounds like science applied to agency to me.\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Thursday 09. July 2020, 11:25\n\n\nOn Jaggar: Norms, Outlaw Emotions, and the Ideal Society\n\n\t\n\t\tNote\n\tSource Text: Alison M. Jaggar (1989) Love and knowledge: Emotion in feminist epistemology, Inquiry, 32:2, 151-176, DOI: 10.1080/00201748908602185\nPublication\n\n\nI found Jaggar to be a very wholesome read, it was the perfect amount of grounded argumentative structure and felt very connected as a whole. This was, together with the ideas from Lugones the best and most fruitful paper for me.\nOn outlaw emotions:\nFirst, I hate the term, I think it’s placative and fails to frame the (actually nice) idea behind it.\nOutlaw Emotions are all those emotions incompatible with the dominant norms. That’s a huge field to cover, among feminist emotions they would also encompass emotions that are irrational or “faulty”. So, Jaggar does the term Justice by saying, some, but not all Outlaw Emotions are Feminist emotions. To make this evident, just think of a murderer's joy for killing, it is of no feminist interest to dissect, yet it is against dominant values. So, experiencing Outlaw emotions is a (probably) necessary, but not sufficient condition for feminism. The incompatible emotion serves to create discourse and change.\nJaggar convincingly shows how emotions have a direct influence on beliefs and can validly constitute evidence, while simultaneously validly influencing values in a similar manner.\nWhen we talk about dominant/alternative norms, we already endorse hierarchy in society. We acknowledge its existence, simply by identifying the dominant norm. I am not quite sure what exactly Jaggar proposes we should do with the hierarchy structures in society. Explicitly I can read: Subcultures rejecting dominant norms should be formed, to create counterbalances and a somewhat fair discourse over the topic.\n“How can we determine which outlaw emotions are to be endorsed or encouraged and which rejected? In what sense can we say that some emotional responses are more appropriate than others? What reason is there for supposing that certain alternative perceptions of the world, perceptions informed by outlaw emotions, are to be preferred to perceptions informed by conventional emotions? Here I can indicate only the general direction of an answer, whose full elaboration must await another occasion. I suggest that emotions are appropriate if they are characteristic of a society in which all Human Life (and perhaps some nonhuman life, too) thrive, or if they are conducive to establishing such a society.”\nTo me this passage sounds sketchy at best, there is no indication of how to successfully separate appropriate from inappropriate emotions. Roughly, I read this part as: emotions are warranted iff they increase the balance of power. (equivalent to minimizing the height of the hierarchy) I would love to get to read this “other occasion” because it seems indefensible to me to formulate a norm that states: Accept only emotions which eliminate/diminish norms.\nThe idea roughly resembles Rawls's Minimax Principle, where a policy should be implemented iff the benefit for the most disadvantaged is highest.\nAnother thing I found helpful is her reformulation of what norms do:\n“Dominant Norms tend to serve dominant interests”\ntil here nothing new, this is a tautology for me, I understand norms as identical to dominant interests, that’s literally what norms are.\nIs an alternative, suppressed norm even thinkable? Isn't it inherent in a norm that it be the dominant one?\nBut then, after that: \"Whatever our color / gender / class / sexual orientation, we are likely to adopt the dominant value of racist, classist, homophobe, misogynistic white men.\"\nThis was rather helpful to me, as it reframes the “act” of oppression as the “likelihood of value distribution” being skewed in your favor, making everybody’s values more likely to be similar to yours. This nicely illustrates how a system can be hierarchical and oppressive, without anybody actively, intentionally “acting oppressive”, while still perpetuating oppression. I'm\nnot saying everybody is acting unintentionally oppressive, but it is always hard to imagine for me to picture \"White Men\" forming a group and collectively deciding on who to hate this coming season, Conceptually separating \"being oppressed\" and \"oppressing\" into phenomena\nwithout necessary inherent causal relation makes sense to me here.\n\n\t\n\t\tNote\n\tcreated by Aron Petau on Tuesday 23. June 2020, 18:52\n\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/plastic-recycling/","title":"Plastic Recycling","description":null,"body":"Being involved with 3D Printers, there is the issue of sustainability that I am confronted with regularly.\nMost 3D printed parts never get recycled and add to the global waste problem, rather than reducing it.\nThe printer most certainly doesn’t care what it is printing, the main problem is the dimensional accuracy and the purity of the material. All of this leads to a huge industry, Germany being especially involved, using loads of virgin plastic.\nWhat can be done about it?\nWe can design our products to last longer, we can also print recycling labels on them so they do not have to get burned after their first life. We can take care to only print functional objects, not just fun toys nobody uses.\nYet, none of that prevents the use of virgin plastics. If you buy a spool of filament, there are some recycled options, but usually at twice the price at worse quality. No wonder recycled filament fails to convince the masses. It is mostly a fun thing YouTubers can pursue, not a valid commercial process.\n\n\nIn my opinion, the core problem is the nonexistent economic feasibility of a proper recycling process. Identifying the exact material of a piece of trash is a very hard problem, definitely not solved yet. So why do we mix the plastic up in the first place? There is a general willingness of people to recycle, but the system for it is missing.\nThe Master Plan\nI want to get people to wash and separate their trash for me, which are the most expensive steps in the recycling process. There is a willingness to take the extra step, and even if just my mom collects bottle caps for me, that is more than I can realistically use up.\nThis only really works when I am thinking in a local and decentral environment.\nThe existing recycling facilities clearly will not be able to provide 200 different containers for 200 different types of plastic.\nStarting the process with clean and sorted materials, like bottle caps (HDPE) or failed prints (PET-G), I start off with an advantage.\nNow I have to take apart the trash into evenly sized particles.\nMeet:\nThe Shredder\nWe built the Precious Plastic Shredder!\n\nWith these awesome open-source drawings, I was able to cobble together my very own very dangerous plastic shredder.\nAfter finding some way to drive this massive axis, I feed the beast and hopefully get tiny pretty uniform plastic bits that are ready to begin the cycle of life anew.\nThe solution for the motorization was an old and used garden shredder that still had an intact motor and wiring.\nWe cut it in half and attached it to the shredder box.\n\n\nAfter replacing the weak force transmission screw for an industrial coupler, we were ready to try it out. Obviously, there are still security concerns in this prototype, a proper hopper is already being made.\nNevertheless, we are confident that this shredder will be able to deal with the light sorts of plastic we are thinking of.\nAs you can see, I am now able to produce awesome confetti but to do more with the plastic flakes I have to extrude them.\nMeet the Filastruder\nThis is the Filastruder, designed and made by Tim Elmore, in an attempt to create the cheapest viable way to extrude plastic. The biggest cost issue is the tight industrial tolerances in thickness that have to be adhered to. This is in essence what separates good from the bad filament. The industry standard nowadays is at +-0.03mm. Hard to achieve on a DIY setup, but not unheard of. The setup, like any bigger industry equivalent, consists of a motor pressing plastic pellets through a heated screw, extruding molten plastic at the end through a nozzle, and setting the diameter. The leftmost machine is responsible for winding the filament properly onto a spool.\nHere you can see the extrusion process in action.\n\n\nThe Filastruder is controlled by an Arduino and is highly configurable. The laser sensor visible in the video is already working, but I am missing more direct control over the diameter of the filament.\nWhen it all really comes down to the single variable of the filament diameter responsible for the quality of my recycled project, a simple Machine Learning optimization directly jumps at me: I have a few variables like winder speed, extrusion speed, heat, and cooling intensity. These variables can be optimized on the fly for an exact diameter. This is actually roughly how virgin filament is produced, commercial facilities just manage much faster.\n\nSo far, I am aware of a few companies and academic projects attempting this process, but none of them manage to get either the quality or the price of other products available. Automatization does not just take out jobs away, I think it can also be a helpful tool, for example tackling environmental issues such as this one.\nThis project is very dear to my heart and I plan to investigate it further in the form of a master thesis.\nThe realization will require many skills I am already picking up or still need to work on within the Design and Computation program.\n{: .notice--info}\n\n Reflow Filament\n\n\n Perpetual Plastic Project\n\n\n Precious Plastic Community\n\n\n Filamentive Statement on why recycling is not feasible in their opinion\n\n\n Open source filament diameter sensor by Tomas Sanladerer\n\n\n Re-Pet Shop\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/beacon/","title":"BEACON","description":null,"body":"BEACON: Decentralizing the Energy Grid in inaccessible and remote regions\nAccess to Electricity is a basic human right. At first, that may seem over the top, but if one stops to think what all the little tasks that electricity can indirectly handle for us (lightning, laundry, cooking, freezing, heating, entertaining…) would consume in time and effort if we had to perform them manually, this idea becomes very clear. There are globally around 1 billion people without tier 2 access to electricity.\nSDGS Goal 7\n\nPeople only know the intensity of labor that goes into everything when there is no electricity. And it is not even only about convenience, electricity is an enormous lifesaver in any number of scenarios, think just of hospitals or mobile phone networks that would be rendered completely useless without it. So we can easily agree on a need, a demand for electricity globally, for every person. But what about the supply? Why is there 1 billion undersupplied?\nThe Answer: missing profitability. It would be a charity project to supply every last person on earth, not a profitable one. And while charitable projects are noble and should be pursued, the reality within capitalism shows that this is not the way it is going to happen.\nBut what if we could come up with technology, or rather, a communal structure, that enables us to supply profitably, and still adapt to both, the difficult external factors (weather issues, remoteness, altitude, etc.) and the smaller purses of the undersupplied?\nLocation\nTowards the end of 2018, I spent 4 months in northern India, on a research project with the IIT Kharagpur.\nThe goal was to work on one of the 17 UN-defined sustainable development goals – electricity.\nWorldwide, an estimated 1 billion people have no or insubstantial access to the grid.\nSome of them live here, in the Key Monastery in the Spiti Valley at around 3500 meters altitude.\n\n\n\nThis is Tashi Gang, a village close to the Monastery. It houses around 50 people and only has road access during 3-4 months in the summer. For the rest of the time, the people rely on first aid services by helicopter, which can only be called with a working cell phone tower.\n\nThe Project\nIn an environment reliant on hydro-energy and solar (diesel transport is unreliable due to snowed-in mountain roads), over 6 months of snowy winter, frequent snowstorms, and temperatures of up to -35°C, securing the grid is hard.\nOur way to tackle the issue was to reject the in the western society very established notion of electricity as a homogenous product with centralized production and instead researched the possibilities of a predictive, self-correcting, and decentral grid.\nBy prioritizing energy usage cases, instead of a full blackout during a storm, essential functions like radio towers and hospitals could be partially powered and maybe stay functioning. The binarity of either having electricity or not would be replaced by assigned quantities and timeslots, in a collective effort to be mindful and distribute the electricity necessity-based.\nThe ultimate vision was a live predictive electricity market, where people could even earn money by selling their allotted, but not needed electricity.\nTo gauge feasibility, I conducted several psychological acceptance studies and collected data on local electricity demands.\nI simulated a typical day of electricity demand in the Key monastery and the surrounding villages and mapped out the potential to install cost-efficient smart microgrid controllers enabling such an accurate and predictive behavior.\nThe smart grid operator boxes available here in Germany cost several hundred, with installation several thousand Euros, not a feasible solution for the Indian population. Instead, we wanted to use Raspberry Pi's, which are interconnected through ethernet cables or local mesh networking.\nResearch\n\nData Collection\nBuilding a questionnaire and visiting public schools during their English Classes, I had the chance to speak to a range of teenagers, answering questions about the state of electricity in their homes, generating more data than I could have accomplished running from door to door without any skills speaking local dialects. The questionnaire was as scientific as I could make it in such a situation and geared towards finding the type and number of electric devices in the homes and estimating typical usage scenarios.\nWith a total of 145 participants from more than 6 different schools and roughly 4 different districts, all located in the Indian part of the Himalayas, the findings are as follows:\nThe participants range from 11 to 53 years, with an average of 17 years.\nThe average household has 6 members with an average of 5 smart devices. Only 2 percent of the Households had not a single smart device, but at the same time, only 42 percent had direct or indirect access to a laptop or computer. So the main body of smart devices consists of smartphones with a negligible portion of tablets.\nThe average total amount of electrical devices is around 11 electrical appliances per house.\nSubjective Quality Rating on a scale of 1 to 10:\n\nAverage quality in summer: 7.1\nAverage quality in monsoon: 5.6\nAverage quality in autumn: 7.1\nAverage quality in winter: 4.0\n\nSo, as you would expect, during winter, but also when it rains, the felt quality drops by more than 30 percent on average.\nAs for the daily supply time, the average sits at 15.1 hours out of 24, meaning the people have electricity only for 62.9 percent of the time, some, as for example the people in Diskit only have a sad 4 hours of daily access. On top of that, this estimation does not account for the snowfalls in Spiti for example, where it is not uncommon to experience 3 consecutive days of powercut or more.\nAs the Power Meter is supplied by the government, a solid 82 percent of the houses have a working power meter, if one assumes that the 13 percent who did not know whether they have a power meter, do have one, we can say that around 95% of the houses have a power meter.\nAnother goal of the studies was to find out what would incline people to be caring and sharing with the available electricity, something rather unimaginable here in Germany.\nIn general, the uninformed openness to delaying usage of electricity on a scale of 1-10 was around 5.5, with the additional information that a smart delay would cause an overall price reduction, the acceptance went up to 6.9, a good 14%. This implies that people would be a lot more inclined to give up conveniences if the benefits have a direct impact on them.\nSimulation\nAfter collecting all the estimated electric appliances of the local population, I simulated the use of 200 Solar Panels with 300Wp each, once for simultaneous electricity use, and once for mitigated electricity peaks through smart optimization and electricity usage delay.\n\n\nAlthough solar is definitely not the optimal choice here and generates lots of issues with energy storage and battery charging at negative degrees, we figured that this was the way to go for the project.\nAnd as you can see, optimizing peak usage can improve solar from generating only one-fifth of the demand in winter to about half the demand in winter. Keeping in mind here, that the added solar farm was only intended to supply additional energy and not replace existing solutions, such a \"small\" farm would be a real lifesaver there and optimize the limited space in extremely mountainous terrain.\nClosing words\nThere are to sides which the problems can be tackled: we can bring the total energy production up, by adding more panels or electricity by other means, but we can also try and bring the total demand down. This is to be achieved by investing strictly in the most energy-efficient appliances. Even replacing older, not-so-efficient appliances might sometimes be of use.\nBut ensuring efficient use is not the only way to bring down the overall demand.\nAs introduced as core ideas for the whole project, sharing and delaying will prove immensely useful. How so?\nBy sharing, we mean a concept that is already widely applied in the relevant areas. What to do in a Village that has no access to water? Will we send each household out to the faraway river to catch water for their family? Or would we join hands in a community effort to dig a central well used by everyone?\nSo, when we look at sharing electricity, how would we apply the concept? We take the appliances that consume the most energy individually and scale them up in order to increase efficiency. For example, in our case, that is most applicable to electric heating. If we manage to heat central community spaces available for everyone, naturally, fewer individual rooms will have to be heated. Similarly, one could declare a room as a public cinema, where people come together and watch Tv on a big Projector. Twice as fun, and conserving a great deal of energy again. Such ideas and others have to be realized in order to be able to match the total demand with the available supply.\nSadly, the project was never taken up further, and the situation for the people in the Spiti Valley has not improved. Two years ago, a road directly through the mountains was finished, making the population hopeful for an increase in tourism, increasing the chances of the economic viability of improved solutions.\nI spent my time there in the function of a research intern, having no real say in the realization of the project. The problem remains, and I still think that decentral solutions look to be the most promising for this specific location. Of course, the Himalayas present a bit of an extreme location, but that doesn't change the fact that people live there and have a basic human right to electricity.\n","path":null},{"url":"http://127.0.0.1:1111/blog/cad/","title":"3D Modeling and CAD","description":null,"body":"3D Modeling and CAD\nDesigning 3D Objects\nWhile learning about 3D Printing, I was most intrigued by the possibility to modify and repair existing products. While there is an amazing community with lots of good and free models around, naturally I came to a point where I did not find what I was looking for readily designed. I realized this is an essential skill for effectively operating not just 3D Printers, but any productive machine really.\nSince youtube was the place I was learning all about 3D Printing, and all the people that I looked up to there were using Fusion 360 as their CAD Program that’s what I got into.\nIn hindsight, that was a pretty good choice and I am in love with the abilities parametric design gives me.\nBelow you will find some of my designs.\nThe process is something that I enjoy a lot and wish to dive into deeper.\nBy trial and error, I already learned a lot about designing specifically for 3D Printing, but I often feel that there are many aesthetic considerations in design that I am not familiar with.\nI want to broaden my general ability to design physical objects, which is something I hope to gain during my master’s.\n\n\n\n\n\n\n\nCheck out more of my finished designs in the Prusaprinters (now Printables) Community\n\n My Printables Profile\n\n3D Scanning and Photogrammetry\nBesides coming up with new objects, incorporating the real world is also an interest of mine.\nInteraction with real objects and environments\nIn the last few years I have played around with a few smartphone cameras and was always quite sad, that my scans were never quite accurate enough to do cool stuff with them. I could not really afford real 3D scanner and had already started cobbling together a raspberry Pi camera with a cheap TOF sensor, which is a simple, but not quite as good replacement for a laser or a lidar sensor, but then Apple came out with the first phones with accessible Lidar sensor.\nRecently, through work at the university I got access to a device with a lidar sensor and started having fun with it.\nSee some examples here:\n \n \nThis last one was scanned with just my smartphone camera. You can see that the quality is notably worse, but considering is was created with just a single, run-of-the-mill smartphone sensor, I think it is still pretty impressive and will certainly do something towards democratizing such technologies and abilities.\n \nPerspective\nWhat this section is supposed to deliver is the message that I am currently not where I want to be navigating the vast possibilities of CAD. I feel confident enough to approach small repairs around the flat with a new perspective, but I still lack technical expertise when approaching a collection composite parts, having to function together. I still have lots of projects halfdone or half-thought and one major reason is that there is no real critical exchange within my field of study.\nI want more than designing figurines or wearables.\nI want to incorporate 3D printing as a method to extend the abilities of other tools, have mechanical and electrical purposes, be foodsafe and engaging.\nI fell in love with the idea of designing a toy system, inspired by Makeways on Kickstarter, I have already started adding my own parts to their set.\nI dream of my very own 3D printed coffeecup, one that is both foodsafe and dishwasher-surviving. For that, I would have to do quite a bit of material research, but that just makes the idea so much more appealing.\nI would love finding a material composition incorporating waste to stop relying on plastics, or at least on fossile plastics.\nOnce in Berlin, I would want to talk to the people at Kaffeform producing largely compostable Coffee Cups incorporating a significant amount of old ground espresso, albeit using injection molding for their process.\nThe industry selling composite filaments is much more conservative with the percentage of non-plastic additives, because with a nozzle extrusion process there is much more to go wrong.\nStill, I would love to explore that avenue further and think there is a lot to be gained from looking at pellet printers.\nI also credit huge parts of my exploration process into local recycling to the awesome people at Precious Plastic, who I will join over the summer to learn more about their system.\nI find it hard to write anything about CAD without connecting it directly to a manufacturing process.\nAnd I believe that's a good thing. Always tying a design process to its realization, grounds the process and attaches to it some immediacy.\nFor me to become more confident in this process, I am still missing more expertise in organic shapes, so I would be happy to dig more into Blender, an awesome tool that in my mind is far too powerful to dive into it with just youtube lessons.\nSoftware that I have used and like\n\n AliceVision Meshroom\n Scaniverse\n My Sketchfab Profile\n 3D Live Scanner for Android\n\n","path":null},{"url":"http://127.0.0.1:1111/blog/printing/","title":"3D printing","description":null,"body":"\n\n\n \n \n \n \n \n \n \n A plant propagation station now preparing our tomatoes for summer\n \n \n \n \n \n \n \n \n We use this to determine the flatmate of the month\n \n \n \n \n \n \n \n \n A dragon's head that was later treated to glow in the dark.\n \n \n \n \n \n \n \n \n This was my entry into a new world, the now 10 years old Ender 2\n \n \n \n \n \n \n \n \n I made some lithophanes, a process where the composition and thickness of the material are used for creating an image.\n \n \n \n \n \n \n \n \n This is my second printer, a Prusa i3 MK3s.\n \n \n \n \n \n \n \n \n This candle is the result of a 3D printed plastic mold that I then poured wax into.\n \n \n \n \n \n \n \n \n An enclosure for my portable soldering iron\n \n \n \n \n \n \n \n \n A lamp screen design that particularly fascinated me, it effortlessly comes from a simple 2D spiral shape.\n \n \n \n \n \n \n \n \n A custom-built printer enclosure made up of 3 Ikea Lack tables and around 3 kgs of plastic.\n \n \n \n \n\n3D Printing\n\n\n3D Printing is more than just a hobby for me\nIn it, I see societal changes, the democratization of production, and creative possibilities. Plastic does not have to be one of our greatest environmental problems if we just choose to change our perspective and behavior toward it.\nPlastic Injection molding was one major driving force for the capitalist setting we are in now.\n3D Printing can be utilized to counteract the production of scale.\nToday, the buzzword 3D Printing is already associated with problematic societal practices, it is related to \"automatization\" and \"on-demand economy\". The technology has many aspects to be considered and evaluated and as a technology, many awesome things happen through it and on the same page it fuels developments I would consider problematic. Due to a history of patents influencing the development of the technology, and avid adoption of companies hoping to optimize production processes and margins, but also a very active hobbyist community, all sorts of projects are realized. While certainly societally explosive, there is still a lot going for 3D Printing.\n3D Printing means local and custom production. While I do not buy the whole “every household is going to have a machine that prints what they need right now at the press of a button”, I do see vast potential in 3D Printing.\nThat’s why I want to build my future on it.\nI want to design things and make them become reality.\nA 3D Printer lets me control that process from start to finish. Being able to design a thing in CAD is not enough here, I also need to be able to fully understand and control the machine that makes my thing.\nI started using a 3D Printer in early 2018, and by now I have two of them and they mostly do what I tell them to do.\nI built both of them from kits and heavily modified them. I control them via octoprint, a software that, with its open and helpful community, makes me proud to use it and taught me a lot about open-source principles. 3D Printing in the hobbyist space is a positive example where a method informs my design and I love all the areas it introduced me to.\nThrough it, I felt more at home using Linux, programming, soldering, incorporating electronics, and iteratively designing.\nI love the abilities a 3D Printer gives me and plan on using it for the recycling project.\nDuring the last half year, I also worked in a university context with 3D printers.\nWe conceptualized and established a \"Digitallabor\", an open space to enable all people to get into contact with innovative technologies. The idea was to create some form of Makerspace while emphasizing digital media.\nThe project is young, it started in August last year and so most of my tasks were in Workgroups, deciding on the type of machines and types of content such a project can provide value with.\nRead more about it on the Website:\nDigiLab Osnabrück\nLooking forward, I am also incredibly interested in going beyond polymers for printing. I would love to be able to be more experimental concerning the material choices, something rather hard to achieve while staying in a shared student flat. There have been great projects with ceramics and printing, which I certainly want to have a deeper look into. One project I want to highlight is the evolving cups which impressed me a lot.\nEvolving Objects\nThis group from the Netherlands is algorithmically generating shapes of cups and then printing them on a paste extruder with clay.\nThe process used is described more here:\nThe artist Tom Dijkstra is developing a paste extruder that can be attached to modify a conventional Printer and I would very much love to develop my version and experiment with printing new and old materials in such a concept printer.\nPrinting with Ceramics\nThe Paste Extruder\nAlso with regards to the recycling project, it might make sense for me to incorporate multiple machines into one and let the printer itself directly handle pellet- or paste-form. I am looking forward to expanding my horizon there and seeing what is possible.\nCups and Tableware are of course just one sample area where a backtrack toward traditional materials within modern manufacturing could make sense. There is also more and more talk of 3D Printed Clay- or Earth homes, an area where WASP is a company I look up to.\nThey built several concept buildings and structures from locally mixed earth, creating some awesome environmentally conscious structures.\nAdhering to principles of local building with locally available materials and taking into account the infamous emission problem within the building industry has several great advantages.\nAnd since such alternative solutions are unlikely to come from the industry itself, one major avenue to explore and pursue these solutions are art projects and public demonstrations.\nI want to explore all these areas and look at how manufacturing and sustainability can converge and create lasting solutions for society.\nAlso, 3D Printing is directly tied to the plans for my master's thesis, since everything I manage to reclaim, will somehow have to end up being something again. Why not print away our waste?\nNow, after a few years of tinkering, modifying and upgrading, I find that I did not change my current setup for over a year. It simply works and I am happy with it. Since my first beginner's printer, the failure rates are negligible and I have had to print really complex parts in order to generate enough waste for the recycling project.\nGradually, the mechanical system of the printer shifted from an object of care to simply a tool that I use. In the last years, hardware, but especially software has matured to a point where, at least to me, it tends to be a set-and-forget situation. On to actually making my parts and designs. Read more about that in the post about CAD\n","path":null},{"url":"http://127.0.0.1:1111/","title":"Home","description":null,"body":"\nWelcome\nto the online presence of Aron Petau.\nThis site is a collection of my thoughts and experiences.\nI hope you find something interesting here.\n\n\t\n\t\tNote\n\tThis Page is currently under active construction.\nBroken links are to be expected.\n\n\n\n","path":null}]
\ No newline at end of file
diff --git a/public/style.css b/public/style.css
new file mode 100644
index 00000000..b628a6fe
--- /dev/null
+++ b/public/style.css
@@ -0,0 +1,5 @@
+/*!
+ * Duckquill v6.3.0 (https://duckquill.daudix.one)
+ * Copyright 2024-2025 David "Daudix" Lapshin
+ * Licensed under MIT (https://codeberg.org/daudix/duckquill/src/branch/main/LICENSE)
+ */:where(html){-webkit-text-size-adjust:100%;text-size-adjust:100%;line-height:1.15}:where(h1){margin-block-start:.67em;margin-block-end:.67em;font-size:2em}:where(dl,ol,ul) :where(dl,ol,ul){margin-block-start:0;margin-block-end:0}:where(hr){box-sizing:content-box;height:0;color:inherit}:where(abbr[title]){text-decoration:underline;text-decoration:underline dotted}:where(b,strong){font-weight:bolder}:where(code,kbd,pre,samp){font-size:1em;font-family:monospace,monospace}:where(small){font-size:80%}:where(table){border-color:currentColor;text-indent:0}:where(button,input,select){margin:0}:where(button){text-transform:none}:where(button,input:is([type=button i],[type=reset i],[type=submit i])){-webkit-appearance:button}:where(progress){vertical-align:baseline}:where(select){text-transform:none}:where(textarea){margin:0}:where(input[type=search i]){-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-input-placeholder{opacity:.54;color:inherit}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focus-inner{border-style:none;padding:0}:where(button,input:is([type=button i],[type=color i],[type=reset i],[type=submit i]))::-moz-focusring{outline:1px dotted ButtonText}:where(:-moz-ui-invalid){box-shadow:none}:where(dialog){position:absolute;right:0;left:0;margin:auto;border:solid;background-color:#fff;padding:1em;width:-moz-fit-content;width:fit-content;height:-moz-fit-content;height:fit-content;color:#000}:where(dialog:not([open])){display:none}:where(summary){display:list-item}:root{--bg-color: color-mix(in srgb, var(--accent-color) 20%, white);--bg-overlay: linear-gradient(rgb(255 255 255 / 0.8), rgb(255 255 255 / 0.8));--fg-color: rgb(0 0 0 / 0.8);--fg-contrast: rgb(255 255 255);--fg-muted-1: rgb(0 0 0 / 0.05);--fg-muted-2: rgb(0 0 0 / 0.1);--fg-muted-3: rgb(0 0 0 / 0.2);--fg-muted-4: rgb(0 0 0 / 0.5);--fg-muted-5: rgb(0 0 0 / 0.6);--glass-bg: rgb(242 242 242 / 0.7);--accent-color-alpha: rgb(from var(--accent-color) r g b / var(--color-opacity));--blue-bg: rgb(from var(--blue-fg) r g b / var(--color-opacity));--blue-fg: rgb(53 132 228);--brown-bg: rgb(from var(--brown-fg) r g b / var(--color-opacity));--brown-fg: rgb(99 69 44);--green-bg: rgb(from var(--green-fg) r g b / var(--color-opacity));--green-fg: rgb(38 162 105);--purple-bg: rgb(from var(--purple-fg) r g b / var(--color-opacity));--purple-fg: rgb(145 65 172);--red-bg: rgb(from var(--red-fg) r g b / var(--color-opacity));--red-fg: rgb(224 27 36);--yellow-bg: rgb(from var(--yellow-fg) r g b / var(--color-opacity));--yellow-fg: rgb(156 110 3);--l: clamp(0, (l / 0.623 - 1) * -infinity, 1);--a: calc(var(--l) + (var(--dim-opacity) * (1 - var(--l))));--contrast-color: oklch(from var(--accent-color) var(--l) 0 h / var(--a));--container-width: 720px;--rounded-corner: 0.75rem;--rounded-corner-small: 0.5rem;--blur: saturate(1.8) blur(0.75rem);--font-size-xx-small: 0.625rem;--font-size-x-small: 0.75rem;--font-size-small: 0.875rem;--font-size-medium: 1rem;--font-size-large: 1.25rem;--font-size-x-large: 1.5rem;--font-size-xx-large: 2rem;--font-size-xxx-large: 3rem;--font-size-xx-small-em: 0.625em;--font-size-x-small-em: 0.75em;--font-size-small-em: 0.875em;--font-size-medium-em: 1em;--font-size-large-em: 1.25em;--font-size-x-large-em: 1.5em;--font-size-xx-large-em: 2em;--font-size-xxx-large-em: 3em;--font-system-ui: system-ui, sans-serif;--font-transitional: Charter, "Bitstream Charter", "Sitka Text", Cambria, serif;--font-old-style: "Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif;--font-humanist: Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, sans-serif;--font-geometric-humanist: Avenir, Montserrat, Corbel, "URW Gothic", source-sans-pro, sans-serif;--font-classical-humanist: Optima, Candara, "Noto Sans", source-sans-pro, sans-serif;--font-neo-grotesque: Inter, Roboto, "Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif;--font-monospace-slab-serif: "Nimbus Mono PS", "Courier New", monospace;--font-monospace-code: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;--font-industrial: Bahnschrift, "DIN Alternate", "Franklin Gothic Medium", "Nimbus Sans Narrow", sans-serif-condensed, sans-serif;--font-rounded-sans: ui-rounded, "Hiragino Maru Gothic ProN", Quicksand, Comfortaa, Manjari, "Arial Rounded MT", "Arial Rounded MT Bold", Calibri, source-sans-pro, sans-serif;--font-slab-serif: Rockwell, "Rockwell Nova", "Roboto Slab", "DejaVu Serif", "Sitka Small", serif;--font-antique: Superclarendon, "Bookman Old Style", "URW Bookman", "URW Bookman L", "Georgia Pro", Georgia, serif;--font-didone: Didot, "Bodoni MT", "Noto Serif Display", "URW Palladio L", P052, Sylfaen, serif;--font-handwritten: "Segoe Print", "Bradley Hand", Chilanka, TSCu_Comic, casual, cursive;--font-emoji: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--color-opacity: 0.1;--dim-opacity: 0.8;--disabled-opacity: 0.6;--edge-highlight: inset 0 0.0625rem 0 rgb(255 255 255 / 0.1);--shadow: 0 0 0 0.0625rem rgb(0 0 0 / 0.03), 0 0.0625rem 0.1875rem 0.0625rem rgb(0 0 0 / 0.07), 0 0.125rem 0.375rem 0.125rem rgb(0 0 0 / 0.03);--shadow-raised: 0 0 0 0.0625rem rgb(0 0 0 / 0.06), 0 0.125rem 0.375rem 0.125rem rgb(0 0 0 / 0.14), 0 0.25rem 0.75rem 0.25rem rgb(0 0 0 / 0.06);--shadow-glass: 0 0.75rem 1.5rem -1rem rgb(0 0 0 / 0.5);--shadow-glow: 0 0 0 0.0625rem var(--accent-color-alpha), 0 0.125rem 0.375rem 0.125rem var(--accent-color-alpha), 0 0.25rem 1.5rem 0.25rem var(--accent-color-alpha);--text-shadow-glow: var(--accent-color-alpha) 0 0 0.25rem, var(--accent-color) 0 0 0.75rem;--hover: scale(1.1);--active: scale(0.9);--transition: 0.2s;--transition-longer: 0.4s;--transition-long: 0.8s;--icon-archive: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M2 1C.89 1 0 1.89 0 3v2c0 .751.41 1.402 1.018 1.744A2 2 0 0 0 1 7v7c0 1.11.89 2 2 2h10c1.11 0 2-.89 2-2V7a2 2 0 0 0-.018-.256A2 2 0 0 0 16 5V3c0-1.11-.89-2-2-2zm0 2h12v2H2zm1 4h10v7H3zm3 1v1h4V8z'/%3E%3C/svg%3E");--icon-backlink: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M5 14a1 1 0 0 1-.707-.293l-4-4a1 1 0 0 1 0-1.414l4-4a1 1 0 1 1 1.414 1.414L3.414 8H12c1.117 0 2-.883 2-2s-.883-2-2-2c-.55 0-1-.45-1-1s.45-1 1-1c2.2 0 4 1.8 4 4s-1.8 4-4 4H3.414l2.293 2.293A1 1 0 0 1 5 14m0 0'/%3E%3C/svg%3E");--icon-boosts: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 1v2H4C1.8 3 0 4.8 0 7v2a4 4 0 0 0 1.02 2.672 1 1 0 1 0 1.488-1.336A1.97 1.97 0 0 1 2 9V7c0-1.125.875-2 2-2h4v2h1v-.008a1 1 0 0 0 .707-.285l2-2a1 1 0 0 0 0-1.414l-2-2A1 1 0 0 0 9 1.008V1zm6.29 3a1 1 0 0 0-.72.258.993.993 0 0 0-.078 1.41c.317.355.508.816.508 1.34v2c0 1.125-.875 2-2 2H8V9H7v.008a1 1 0 0 0-.707.285l-2 2a1 1 0 0 0 0 1.414l2 2c.187.184.441.29.707.285V15h1v-1.992h4c2.2 0 4-1.805 4-4v-2a4 4 0 0 0-1.02-2.676A1 1 0 0 0 14.29 4m0 0'/%3E%3C/svg%3E");--icon-bug: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M5 0c-.55 0-1 .45-1 1 0 .691.39 1.285.8 1.605C4.298 3.277 4 4.105 4 5H3V4H1v1c0 .832.563 1.523 1.05 1.77.493.246.95.23.95.23h1v1H1v2h3v1H3s-.457-.016-.95.23C1.563 11.477 1 12.168 1 13v3h2v-3h1.129c.45 1.719 2.016 3 3.871 3s3.422-1.281 3.871-3H13v3h2v-3c0-.832-.562-1.523-1.05-1.77-.493-.246-.95-.23-.95-.23h-1v-1h3V8h-3V7h1s.457.016.95-.23C14.437 6.523 15 5.832 15 5V4h-2v1h-1c0-.895-.297-1.723-.8-2.395.41-.32.8-.914.8-1.605 0-.55-.45-1-1-1s-1 .45-1 1a1 1 0 0 0-.645.238C8.93 1.086 8.473 1 8 1s-.93.086-1.355.238A1 1 0 0 0 6 1c0-.55-.45-1-1-1m2.969 5.031h.062A.97.97 0 0 1 9 6v3.063a.97.97 0 0 1-.969.968H7.97A.97.97 0 0 1 7 9.062V6a.97.97 0 0 1 .969-.969m0 6h.062A.97.97 0 0 1 9 12v.063a.97.97 0 0 1-.969.968H7.97a.97.97 0 0 1-.97-.969V12a.97.97 0 0 1 .969-.969m0 0'/%3E%3C/svg%3E");--icon-caution: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M5 0a1 1 0 0 0-.707.293l-4 4A1 1 0 0 0 0 5v6a1 1 0 0 0 .293.707l4 4A1 1 0 0 0 5 16h6a1 1 0 0 0 .707-.293l4-4A1 1 0 0 0 16 11V5a1 1 0 0 0-.293-.707l-4-4A1 1 0 0 0 11 0zm.414 2h5.172L14 5.414v5.172L10.586 14H5.414L2 10.586V5.414zM8 4c-.554 0-1 .446-1 1v3c0 .554.446 1 1 1s1-.446 1-1V5c0-.554-.446-1-1-1m0 6a1 1 0 0 0-1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1'/%3E%3C/svg%3E");--icon-checkmark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M13.754 4.668c.176-.2.262-.461.246-.723a1 1 0 0 0-.34-.687 1 1 0 0 0-.726-.246 1 1 0 0 0-.688.34L5.95 10.547 3.707 8.3A1 1 0 0 0 2 9.01a1 1 0 0 0 .293.708l3 3c.195.195.465.3.742.293.278-.012.535-.133.719-.344zm0 0'/%3E%3C/svg%3E");--icon-copy: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' height='16' width='16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 3c0-1.645 1.355-3 3-3h5c1.645 0 3 1.355 3 3 0 .55-.45 1-1 1s-1-.45-1-1c0-.57-.43-1-1-1H3c-.57 0-1 .43-1 1v5c0 .57.43 1 1 1 .55 0 1 .45 1 1s-.45 1-1 1c-1.645 0-3-1.355-3-3zm5 5c0-1.645 1.355-3 3-3h5c1.645 0 3 1.355 3 3v5c0 1.645-1.355 3-3 3H8c-1.645 0-3-1.355-3-3zm2 0v5c0 .57.43 1 1 1h5c.57 0 1-.43 1-1V8c0-.57-.43-1-1-1H8c-.57 0-1 .43-1 1m0 0'/%3E%3C/svg%3E");--icon-done: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M7.883 0q-.486.008-.965.074a7.98 7.98 0 0 0-4.602 2.293 8.01 8.01 0 0 0-1.23 9.664 8.015 8.015 0 0 0 9.02 3.684 8 8 0 0 0 5.89-7.75 1 1 0 1 0-2 .008 5.986 5.986 0 0 1-4.418 5.816 5.996 5.996 0 0 1-6.762-2.766 5.99 5.99 0 0 1 .922-7.25 5.99 5.99 0 0 1 7.239-.984 1 1 0 0 0 1.363-.371c.273-.48.11-1.09-.371-1.367A8 8 0 0 0 9.492.14 8 8 0 0 0 7.882 0m7.15 1.998-.1.002a1 1 0 0 0-.687.34L7.95 9.535 5.707 7.29A1 1 0 0 0 4 8a1 1 0 0 0 .293.707l3 3c.195.195.465.3.742.293.277-.012.535-.133.719-.344l7-8A1 1 0 0 0 16 2.934a1 1 0 0 0-.34-.688 1 1 0 0 0-.627-.248'/%3E%3C/svg%3E");--icon-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='m2.293 6.707 5 5a1 1 0 0 0 1.414 0l5-5a1 1 0 1 0-1.414-1.414L8 9.586 3.707 5.293a1 1 0 1 0-1.414 1.414m0 0'/%3E%3C/svg%3E");--icon-feed: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M1.988 1.988V3c.008.547.453.984 1 .988.004-.004.008-.004.012-.004v.028A8.977 8.977 0 0 1 11.988 13a.991.991 0 0 0 1 .984h1V13h-.004c0-.004 0-.004.004-.008C13.984 7.02 9.184 2.148 3.242 2.02A1.004 1.004 0 0 0 3 1.988v-.004zm0 4V7c.008.547.453.984 1 .988.004-.004.008-.004.012-.004V8a4.985 4.985 0 0 1 4.996 4.844 1.002 1.002 0 0 0 .988 1.145c.008-.005.012-.005.016-.005v.004h.984V13H10c0-3.793-3.047-6.898-6.82-6.992 0-.004-.004-.004-.004-.004A.892.892 0 0 0 3 5.988v-.004zm2 4a1.999 1.999 0 1 0-.002 3.998 1.999 1.999 0 0 0 .002-3.998m0 0'%3E%3C/path%3E%3C/svg%3E");--icon-fire: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M9.184.973C4.957 3.113 5.586 6.273 7 9 5.762 7.36 5.016 5.48 5 4 3.375 5 2 7 2 9a6.005 6.005 0 0 0 3.969 5.648c-.492-.84-.367-1.96.703-3.015 2.14-2.11 1.558-2.735 1.558-2.735 2.266 1.149-.32 3.137.418 3.88.563.558 1.758-1.391 1.77-2.184.848.96 1.246 1.676 1.246 2.75q0 .273-.035.52c2.512-1.805 3.273-5.41.46-8.184C8.095 1.742 9.185.973 9.185.973m0 0'/%3E%3C/svg%3E");--icon-first: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M3 2v12h2V8.414l5.293 5.293a1 1 0 1 0 1.414-1.414L7.414 8l4.293-4.293a1 1 0 1 0-1.414-1.414L5 7.586V2zm0 0'/%3E%3C/svg%3E");--icon-git: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 0a1 1 0 0 0-.707.293L5.707 1.875l5.238 5.234c.176-.07.364-.109.555-.109A1.5 1.5 0 1 1 10 8.5q0-.276.102-.535L8.05 5.915v4.19a1.5 1.5 0 1 1-1-.035V4.914L4.859 2.727.293 7.293a1 1 0 0 0 0 1.414l7 7a1 1 0 0 0 1.414 0l7-7a1.007 1.007 0 0 0 0-1.414l-7-7A1 1 0 0 0 8 0m0 0'/%3E%3C/svg%3E");--icon-home: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 .361a2.2 2.2 0 0 0-1.41.51L2.129 4.59A3.14 3.14 0 0 0 1 7v6c0 1.66 1.34 3 3 3h8c1.66 0 3-1.34 3-3V7c0-.93-.414-1.813-1.129-2.41L9.411.87A2.2 2.2 0 0 0 8 .361m0 2.002a.2.2 0 0 1 .129.047l4.46 3.719c.263.215.411.535.411.871v6c0 .547-.453 1-1 1h-2V9c0-.55-.45-1-1-1H7c-.55 0-1 .45-1 1v5H4c-.547 0-1-.453-1-1V7c0-.336.148-.656.41-.871L7.871 2.41A.2.2 0 0 1 8 2.363'/%3E%3C/svg%3E");--icon-important: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M3 0C1.355 0 0 1.355 0 3v7c0 1.256.893 2.14 2 2.584V15a1 1 0 0 0 1.707.707L6.414 13H13c1.645 0 3-1.355 3-3V3c0-1.645-1.355-3-3-3zm0 2h10c.571 0 1 .429 1 1v7c0 .571-.429 1-1 1H6a1 1 0 0 0-.707.293L4 12.586V12a1 1 0 0 0-1-1c-.571 0-1-.429-1-1V3c0-.571.429-1 1-1m5 1c-.554 0-1 .446-1 1v2c0 .554.446 1 1 1s1-.446 1-1V4c0-.554-.446-1-1-1m0 5a1 1 0 0 0-1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1'/%3E%3C/svg%3E");--icon-info: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 0C3.59 0 0 3.59 0 8s3.59 8 8 8 8-3.59 8-8-3.59-8-8-8m0 2c3.332 0 6 2.668 6 6s-2.668 6-6 6-6-2.668-6-6 2.668-6 6-6m0 1.875a1.125 1.125 0 1 0 0 2.25 1.125 1.125 0 0 0 0-2.25M6.477 7A.5.5 0 0 0 6.5 8H7v3h-.5a.499.499 0 1 0 0 1h3a.499.499 0 1 0 0-1H9V7zm0 0'/%3E%3C/svg%3E");--icon-languages: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M3.98 1v3H1v2h2.947a4.8 4.8 0 0 1-.592 1.871c-.425.758-1.101 1.488-2.062 2.45l1.414 1.413c.92-.92 1.703-1.728 2.283-2.697.38.632.844 1.196 1.377 1.768l.668-2.309a6 6 0 0 1-.41-.625A4.75 4.75 0 0 1 6.033 6h1.53l.511-2H6V1zm5.24 1L6 15h2l.781-3h4.438L14 15h2L12.781 2zm1.562 2h.438l1.5 6H9.28z'/%3E%3C/svg%3E");--icon-last: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M11 2v5.586L5.707 2.293a1 1 0 1 0-1.414 1.414L8.586 8l-4.293 4.293a1 1 0 1 0 1.414 1.414L11 8.414V14h2V2zm0 0'/%3E%3C/svg%3E");--icon-lightbulb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M7.996 0C5.16 0 2.703 2 2.125 4.777c-.527 2.535.688 5.036 2.871 6.325L5 12a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-.898c2.184-1.293 3.402-3.797 2.871-6.332A6.01 6.01 0 0 0 7.996 0m0 2a3.994 3.994 0 0 1 3.918 3.18 3.99 3.99 0 0 1-2.312 4.484 1.01 1.01 0 0 0-.602.914V11H6.996v-.418a1 1 0 0 0-.598-.914 3.994 3.994 0 0 1-2.316-4.484A3.99 3.99 0 0 1 7.996 2m-.998 4a.5.5 0 0 0-.354.852l1 1a.5.5 0 0 0 .708 0l1-1a.5.5 0 0 0 0-.707.507.507 0 0 0-.707 0l-.649.648-.644-.648A.5.5 0 0 0 6.998 6M6 14v1c0 .555.445 1 1 1h2c.555 0 1-.445 1-1v-1z'/%3E%3C/svg%3E");--icon-link: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M4 4C1.8 4 0 5.8 0 8s1.8 4 4 4v-2c-1.125 0-2-.875-2-2s.875-2 2-2h3c1.125 0 2 .875 2 2 0 .84-.496 1.535-1.207 1.84l.785 1.84A4 4 0 0 0 11 8c0-2.2-1.8-4-4-4zm8 2v2c1.125 0 2 .875 2 2s-.875 2-2 2H9c-1.125 0-2-.875-2-2 0-.828.484-1.516 1.184-1.828l-.817-1.828A4.01 4.01 0 0 0 5 10c0 2.2 1.8 4 4 4h3c2.2 0 4-1.8 4-4s-1.8-4-4-4'/%3E%3C/svg%3E");--icon-next: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='m6.707 13.707 5-5a1 1 0 0 0 0-1.414l-5-5a1 1 0 1 0-1.414 1.414L9.586 8l-4.293 4.293a1 1 0 1 0 1.414 1.414m0 0'/%3E%3C/svg%3E");--icon-pencil: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M12.277.832c-.578.008-1.168.23-1.691.754l-9 9A2 2 0 0 0 1 12v3h3c.531 0 1.04-.21 1.414-.586l9-9c1.79-1.789.082-4.39-1.89-4.57-.083-.012-.165-.012-.247-.012M10.5 4.437 11.563 5.5 4.5 12.563 3.438 11.5zm0 0'/%3E%3C/svg%3E");--icon-poop: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8.963 1.514A4 4 0 0 1 5 5H4c-1.108 0-2 .892-2 2s.892 2 2 2H3c-1.662 0-3 1.338-3 3s1.338 3 3 3h10c1.662 0 3-1.338 3-3s-1.338-3-3-3h-1c1.108 0 2-.892 2-2s-.892-2-2-2h-1a4 4 0 0 0-2.037-3.486'/%3E%3C/svg%3E");--icon-previous: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='m9.293 13.707-5-5a1 1 0 0 1 0-1.414l5-5a1 1 0 1 1 1.414 1.414L6.414 8l4.293 4.293a1 1 0 1 1-1.414 1.414m0 0'/%3E%3C/svg%3E");--icon-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='m5.707 1.293 6 6a1 1 0 0 1 0 1.414l-6 6a1 1 0 1 1-1.414-1.414L9.586 8 4.293 2.707a1 1 0 1 1 1.414-1.414m0 0'/%3E%3C/svg%3E");--icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M6.57.063c-3.578 0-6.5 2.921-6.5 6.5 0 3.578 2.922 6.5 6.5 6.5a6.46 6.46 0 0 0 3.83-1.256l2.975 2.974c.957.938 2.363-.5 1.406-1.437l-2.96-2.961a6.46 6.46 0 0 0 1.25-3.82c0-3.579-2.923-6.5-6.5-6.5m0 2c2.5 0 4.5 2.003 4.5 4.5 0 2.5-2 4.5-4.5 4.5-2.496 0-4.5-2-4.5-4.5 0-2.497 2.004-4.5 4.5-4.5'/%3E%3C/svg%3E");--icon-share: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 1a1 1 0 0 0-.5.135 1 1 0 0 0-.207.158l-3 3a1 1 0 0 0 0 1.414 1 1 0 0 0 1.414 0L7 4.414V10a1 1 0 0 0 1 1 1 1 0 0 0 1-1V4.414l1.293 1.293a1 1 0 0 0 1.414 0 1 1 0 0 0 0-1.414L8.738 1.326 8.7 1.287a1 1 0 0 0-.195-.15l-.008-.004a1 1 0 0 0-.236-.098h-.004A1 1 0 0 0 8 1M4 7c-1.645 0-3 1.355-3 3v2c0 1.645 1.355 3 3 3h8c1.645 0 3-1.355 3-3v-2c0-1.645-1.355-3-3-3a1 1 0 0 0 0 2c.564 0 1 .436 1 1v2c0 .564-.436 1-1 1H4c-.564 0-1-.436-1-1v-2c0-.564.436-1 1-1a1 1 0 0 0 0-2'/%3E%3C/svg%3E");--icon-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 0a1 1 0 0 0-.95.684l-1.448 4.34-4.59-.016C.032 5.004-.371 6.266.43 6.828l3.625 2.555-1.5 4.285c-.317.902.687 1.691 1.492 1.172l4.004-2.594 3.894 2.586c.801.531 1.817-.258 1.5-1.16l-1.504-4.29 3.645-2.577c.789-.563.394-1.809-.574-1.813l-4.66-.015L8.949.69A1 1 0 0 0 8 0m0 0'/%3E%3C/svg%3E");--icon-theme-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M.918 8.004a7.072 7.072 0 0 0 14.102.793 1.01 1.01 0 0 0-.457-.957 1 1 0 0 0-1.063-.004 3.9 3.9 0 0 1-2.031.578 3.89 3.89 0 0 1-3.883-3.883c0-.715.203-1.422.578-2.031a1 1 0 0 0-.004-1.062c-.207-.32-.578-.5-.957-.458A7.07 7.07 0 0 0 .918 8.004M5.586 4.53a5.877 5.877 0 0 0 8.965 5.004l-1.52-.96a5.09 5.09 0 0 1-5.035 4.507 5.09 5.09 0 0 1-5.078-5.078 5.09 5.09 0 0 1 4.508-5.035l-.961-1.52a5.9 5.9 0 0 0-.88 3.082m0 0'/%3E%3C/svg%3E");--icon-theme-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8.004-.008a1 1 0 0 0-1 1v1a1 1 0 1 0 2 0v-1c0-.554-.445-1-1-1M3.053 2.035a1 1 0 0 0-.26.035.994.994 0 0 0-.45 1.672l.708.707a1 1 0 1 0 1.414-1.414l-.707-.707a1 1 0 0 0-.705-.293m9.9.012a1 1 0 0 0-.707.293l-.707.707a1 1 0 1 0 1.414 1.414l.707-.707a1 1 0 0 0-.707-1.707M8 4C5.785 4 4 5.785 4 8s1.785 4 4 4 4-1.785 4-4-1.785-4-4-4m0 2c1.098 0 2 .902 2 2s-.902 2-2 2-2-.902-2-2 .902-2 2-2m-7.004.984a1 1 0 1 0 0 2h1a1 1 0 1 0 0-2zM14 7c-.55 0-1 .45-1 1s.45 1 1 1h1c.55 0 1-.45 1-1s-.45-1-1-1zM3.748 11.234a1 1 0 0 0-.705.293l-.711.707a1.007 1.007 0 0 0 0 1.414c.39.391 1.027.391 1.418 0l.707-.707a1 1 0 0 0-.709-1.707m8.49.006q-.131 0-.261.033a1.01 1.01 0 0 0-.707.711 1 1 0 0 0 .261.965l.707.707a.995.995 0 0 0 1.672-.445 1 1 0 0 0-.258-.969l-.707-.707a1 1 0 0 0-.707-.295m-4.246 1.756c-.554 0-1 .445-1 1v1a1 1 0 1 0 2 0v-1a1 1 0 0 0-1-1'/%3E%3C/svg%3E");--icon-theme-system: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 0C3.594 0 0 3.594 0 8s3.594 8 8 8 8-3.594 8-8-3.594-8-8-8m0 1.941c3.36 0 6.059 2.7 6.059 6.059s-2.7 6.059-6.059 6.059zm0 0'/%3E%3C/svg%3E");--icon-toc: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M2 3a1 1 0 1 0 0 2 1 1 0 0 0 0-2m4 0c-.554 0-1 .446-1 1s.446 1 1 1h8c.554 0 1-.446 1-1s-.446-1-1-1ZM2 7a1 1 0 1 0 0 2 1 1 0 0 0 0-2m4 0c-.554 0-1 .446-1 1s.446 1 1 1h8c.554 0 1-.446 1-1s-.446-1-1-1Zm-4 4a1 1 0 1 0 0 2 1 1 0 0 0 0-2m4 0c-.554 0-1 .446-1 1s.446 1 1 1h8c.554 0 1-.446 1-1s-.446-1-1-1z'/%3E%3C/svg%3E");--icon-top: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M1 11a1 1 0 0 1 .293-.707l6-6a1 1 0 0 1 1.414 0l6 6a1 1 0 1 1-1.414 1.414L8 6.414l-5.293 5.293A1 1 0 0 1 1 11m0 0'/%3E%3C/svg%3E");--icon-verified: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M5.21 1.27A3.7 3.7 0 0 1 8 0c1.113 0 2.11.492 2.79 1.27a3.68 3.68 0 0 1 2.866 1.074A3.68 3.68 0 0 1 14.73 5.21C15.54 5.914 16 6.93 16 8s-.46 2.086-1.27 2.79a3.68 3.68 0 0 1-1.074 2.866 3.68 3.68 0 0 1-2.867 1.074C10.086 15.54 9.07 16 8 16s-2.086-.46-2.79-1.27a3.68 3.68 0 0 1-2.866-1.074A3.68 3.68 0 0 1 1.27 10.79 3.7 3.7 0 0 1 0 8c0-1.113.492-2.11 1.27-2.79a3.68 3.68 0 0 1 1.074-2.866A3.68 3.68 0 0 1 5.21 1.27m5.75 5.242a.613.613 0 0 0-.437-.98.61.61 0 0 0-.562.265L7.305 9.512 5.973 8.18a.616.616 0 0 0-.868.87l1.844 1.845a.61.61 0 0 0 .485.18.63.63 0 0 0 .453-.255zm0 0'/%3E%3C/svg%3E");--icon-warning: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8 .844c-.907 0-1.814.444-2.291 1.334l-.002.002-5.178 9.697C-.45 13.704.928 16.002 3 16h10c2.072.002 3.45-2.296 2.47-4.123L10.294 2.18l-.002-.002C9.814 1.288 8.907.844 8 .844M8 2.77c.201 0 .403.118.53.353l5.177 9.697.002.002c.307.573-.057 1.18-.707 1.178H2.998c-.65.001-1.014-.605-.707-1.178l.002-.002 5.18-9.699c.126-.233.327-.351.527-.351M8 5c-.554 0-1 .446-1 1v3c0 .554.446 1 1 1s1-.446 1-1V6c0-.554-.446-1-1-1m0 6a1 1 0 0 0-1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1'/%3E%3C/svg%3E");--icon-external: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' %3E%3Cpath d='m6 6 5-5M7 1h4v4M4 2H3a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h5a2 2 0 0 0 2-2V8' style='fill:none;stroke:black;stroke-linejoin:round;stroke-linecap:round;stroke-width:2'/%3E%3C/svg%3E")}[data-theme=dark]{--bg-color: color-mix(in srgb, var(--accent-color) 10%, black);--bg-overlay: linear-gradient(rgb(0 0 0 / 0.9), rgb(0 0 0 / 0.9));--fg-color: rgb(255 255 255);--fg-contrast: rgb(0 0 0 / 0.8);--fg-muted-1: rgb(255 255 255 / 0.05);--fg-muted-2: rgb(255 255 255 / 0.1);--fg-muted-3: rgb(255 255 255 / 0.2);--fg-muted-4: rgb(255 255 255 / 0.5);--fg-muted-5: rgb(255 255 255 / 0.6);--glass-bg: rgb(25 25 25 / 0.7);--blue-fg: rgb(153 193 241);--brown-fg: rgb(205 171 143);--green-fg: rgb(143 240 164);--purple-fg: rgb(220 138 221);--red-fg: rgb(246 97 81);--yellow-fg: rgb(248 228 92);color-scheme:dark}@media (prefers-color-scheme: dark){:root:not([data-theme=light]){--bg-color: color-mix(in srgb, var(--accent-color) 10%, black);--bg-overlay: linear-gradient(rgb(0 0 0 / 0.9), rgb(0 0 0 / 0.9));--fg-color: rgb(255 255 255);--fg-contrast: rgb(0 0 0 / 0.8);--fg-muted-1: rgb(255 255 255 / 0.05);--fg-muted-2: rgb(255 255 255 / 0.1);--fg-muted-3: rgb(255 255 255 / 0.2);--fg-muted-4: rgb(255 255 255 / 0.5);--fg-muted-5: rgb(255 255 255 / 0.6);--glass-bg: rgb(25 25 25 / 0.7);--blue-fg: rgb(153 193 241);--brown-fg: rgb(205 171 143);--green-fg: rgb(143 240 164);--purple-fg: rgb(220 138 221);--red-fg: rgb(246 97 81);--yellow-fg: rgb(248 228 92);color-scheme:dark}}blockquote.note{border-inline-start:.25rem solid var(--blue-fg)}blockquote.note .alert-title,blockquote.note li::marker{color:var(--blue-fg)}blockquote.note .alert-title .icon{-webkit-mask-image:var(--icon-info);mask-image:var(--icon-info)}blockquote.tip{border-inline-start:.25rem solid var(--green-fg)}blockquote.tip .alert-title,blockquote.tip li::marker{color:var(--green-fg)}blockquote.tip .alert-title .icon{-webkit-mask-image:var(--icon-lightbulb);mask-image:var(--icon-lightbulb)}blockquote.important{border-inline-start:.25rem solid var(--purple-fg)}blockquote.important .alert-title,blockquote.important li::marker{color:var(--purple-fg)}blockquote.important .alert-title .icon{-webkit-mask-image:var(--icon-important);mask-image:var(--icon-important)}blockquote.warning{border-inline-start:.25rem solid var(--yellow-fg)}blockquote.warning .alert-title,blockquote.warning li::marker{color:var(--yellow-fg)}blockquote.warning .alert-title .icon{-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}blockquote.caution{border-inline-start:.25rem solid var(--red-fg)}blockquote.caution .alert-title,blockquote.caution li::marker{color:var(--red-fg)}blockquote.caution .alert-title .icon{-webkit-mask-image:var(--icon-caution);mask-image:var(--icon-caution)}blockquote .alert-title{margin-block-end:-.75rem;font-weight:bold}blockquote .alert-title .icon{vertical-align:-.125em;margin-inline-end:.25rem}#article-list{display:flex;flex-direction:column;gap:1rem;margin-block-start:2rem}#article-list article{--bg-overlay: var(--accent-color-alpha);position:relative;transition:var(--transition);box-shadow:var(--edge-highlight),var(--shadow-glass);border-radius:var(--rounded-corner);border-start-end-radius:2.125rem;border-end-end-radius:1.8125rem;background-image:linear-gradient(var(--bg-overlay), var(--bg-overlay)),linear-gradient(var(--glass-bg), var(--glass-bg)),var(--blurnail);background-position:center;background-size:cover;background-color:var(--bg-overlay);padding:1rem;overflow:hidden}#article-list article:hover h3::after{transform:none;opacity:1}:root[dir*=rtl] #article-list article:hover h3::after{transform:scaleX(-1)}#article-list article:active:not(:has(.tag:active)){transform:var(--active)}#article-list article:has(>a:focus-visible){animation:focus-in var(--transition);outline:.125rem solid var(--accent-color);outline-offset:.125rem}@supports not selector(:focus-visible){#article-list article:has(>a:focus){animation:focus-in var(--transition);outline:.125rem solid var(--accent-color);outline-offset:.125rem}}#article-list article>a{position:absolute;inset:0;border-radius:var(--rounded-corner);border-start-end-radius:2.125rem;border-end-end-radius:1.8125rem}#article-list article h3{margin:0;color:var(--accent-color);font-weight:bold;line-height:1;font-family:var(--font-system-ui)}#article-list article h3::after{-webkit-mask-image:var(--icon-right);display:inline-block;position:relative;transform:translateX(-.25rem);opacity:0;mask-image:var(--icon-right);transition:var(--transition);margin-inline-start:.25rem;background-color:currentColor;width:1rem;height:1rem;pointer-events:none;content:""}:root[dir*=rtl] #article-list article h3::after{transform:scaleX(-1) translateX(-.25rem)}#article-list article .tags{position:relative;justify-content:flex-end;z-index:1;margin:0}#article-list article .tags a{background-color:var(--accent-color-alpha);color:var(--accent-color)}#article-list article .tags a:hover{background-color:var(--accent-color);color:var(--contrast-color)}#article-list article.draft::before,#article-list article.archive::before,#article-list article.featured::before,#article-list article.hot::before,#article-list article.poor::before{position:absolute;transform:translateY(-50%);opacity:var(--disabled-opacity);mask-size:cover;transition:var(--transition-longer);inset-block-start:50%;inset-inline-end:-3rem;width:12rem;height:12rem;content:""}#article-list article.draft:hover::before,#article-list article.archive:hover::before,#article-list article.featured:hover::before,#article-list article.hot:hover::before,#article-list article.poor:hover::before{transform:translateY(-50%) rotate(-10deg) scale(1.5)}:root[dir*=rtl] #article-list article.draft:hover::before,:root[dir*=rtl] #article-list article.archive:hover::before,:root[dir*=rtl] #article-list article.featured:hover::before,:root[dir*=rtl] #article-list article.hot:hover::before,:root[dir*=rtl] #article-list article.poor:hover::before{transform:translateY(-50%) rotate(10deg) scale(1.5)}#article-list article.draft{--bg-overlay: var(--fg-muted-1)}#article-list article.draft::before{-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil);background-color:var(--fg-muted-1)}#article-list article.draft h3{color:var(--fg-muted-4)}#article-list article.draft .badge{background-color:var(--fg-muted-1);color:var(--fg-muted-5)}#article-list article.draft .badge .icon{-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil)}#article-list article.draft .tags a{background-color:var(--fg-muted-1);color:var(--fg-muted-5)}#article-list article.draft .tags a:hover{background-color:var(--fg-muted-5);color:var(--fg-contrast)}#article-list article.archive{--bg-overlay: var(--purple-bg)}#article-list article.archive::before{-webkit-mask-image:var(--icon-archive);mask-image:var(--icon-archive);background-color:var(--purple-bg)}#article-list article.archive h3{color:var(--purple-fg)}#article-list article.archive .badge{background-color:var(--purple-bg);color:var(--purple-fg)}#article-list article.archive .badge .icon{-webkit-mask-image:var(--icon-archive);mask-image:var(--icon-archive)}#article-list article.archive .tags a{background-color:var(--purple-bg);color:var(--purple-fg)}#article-list article.archive .tags a:hover{background-color:var(--purple-fg);color:var(--fg-contrast)}#article-list article.featured{--bg-overlay: var(--yellow-bg)}#article-list article.featured::before{-webkit-mask-image:var(--icon-star);mask-image:var(--icon-star);background-color:var(--yellow-bg)}#article-list article.featured:hover::before{transform:translateY(-50%) rotate(62deg) scale(1.5)}:root[dir*=rtl] #article-list article.featured:hover::before{transform:translateY(-50%) rotate(-62deg) scale(1.5)}#article-list article.featured h3{color:var(--yellow-fg)}#article-list article.featured .badge{background-color:var(--yellow-bg);color:var(--yellow-fg)}#article-list article.featured .badge .icon{-webkit-mask-image:var(--icon-star);mask-image:var(--icon-star)}#article-list article.featured .tags a{background-color:var(--yellow-bg);color:var(--yellow-fg)}#article-list article.featured .tags a:hover{background-color:var(--yellow-fg);color:var(--fg-contrast)}#article-list article.hot{--bg-overlay: var(--red-bg)}#article-list article.hot::before{-webkit-mask-image:var(--icon-fire);mask-image:var(--icon-fire);background-color:var(--red-bg)}#article-list article.hot h3{color:var(--red-fg)}#article-list article.hot .badge{background-color:var(--red-bg);color:var(--red-fg)}#article-list article.hot .badge .icon{-webkit-mask-image:var(--icon-fire);mask-image:var(--icon-fire)}#article-list article.hot .tags a{background-color:var(--red-bg);color:var(--red-fg)}#article-list article.hot .tags a:hover{background-color:var(--red-fg);color:var(--fg-contrast)}#article-list article.poor{--bg-overlay: var(--brown-bg)}#article-list article.poor::before{-webkit-mask-image:var(--icon-poop);mask-image:var(--icon-poop);background-color:var(--brown-bg)}#article-list article.poor h3{color:var(--brown-fg)}#article-list article.poor .badge{background-color:var(--brown-bg);color:var(--brown-fg)}#article-list article.poor .badge .icon{-webkit-mask-image:var(--icon-poop);mask-image:var(--icon-poop)}#article-list article.poor .tags a{background-color:var(--brown-bg);color:var(--brown-fg)}#article-list article.poor .tags a:hover{background-color:var(--brown-fg);color:var(--fg-contrast)}#article-list article .badge{float:inline-end;box-shadow:var(--edge-highlight);border-radius:999px;padding:.375rem .75rem;height:fit-content;font-weight:bold;white-space:nowrap}#article-list article .badge .icon{vertical-align:-.125em;margin-inline-end:.25rem}#article-list article .details{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;gap:.25rem;margin-block-start:1rem;border-block-start:max(1px,.0625rem) solid var(--fg-muted-2);padding-block-start:.5rem}#paginator{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:.25rem;margin-block-start:4rem}#paginator #paginator-first,#paginator #paginator-previous,#paginator #paginator-next,#paginator #paginator-last{display:inline-block;transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:1rem;background-color:var(--fg-muted-1);padding:.5rem;color:var(--fg-muted-4);line-height:0}#paginator #paginator-first .icon,#paginator #paginator-previous .icon,#paginator #paginator-next .icon,#paginator #paginator-last .icon{transition:var(--transition)}:root[dir*=rtl] #paginator #paginator-first .icon,:root[dir*=rtl] #paginator #paginator-previous .icon,:root[dir*=rtl] #paginator #paginator-next .icon,:root[dir*=rtl] #paginator #paginator-last .icon{transform:scaleX(-1)}#paginator a#paginator-first:hover,#paginator a#paginator-previous:hover,#paginator a#paginator-next:hover,#paginator a#paginator-last:hover{background-color:var(--fg-muted-2);color:var(--fg-muted-5)}#paginator a#paginator-first:active,#paginator a#paginator-previous:active,#paginator a#paginator-next:active,#paginator a#paginator-last:active{transform:var(--active);border-radius:1rem}#paginator span#paginator-first,#paginator span#paginator-previous,#paginator span#paginator-next,#paginator span#paginator-last{opacity:var(--disabled-opacity);cursor:not-allowed}#paginator #paginator-previous{border-start-end-radius:var(--rounded-corner-small);border-end-end-radius:var(--rounded-corner-small)}#paginator #paginator-next{border-start-start-radius:var(--rounded-corner-small);border-end-start-radius:var(--rounded-corner-small)}#paginator #paginator-first .icon{-webkit-mask-image:var(--icon-first);mask-image:var(--icon-first)}#paginator #paginator-previous .icon{-webkit-mask-image:var(--icon-previous);mask-image:var(--icon-previous)}#paginator #paginator-next .icon{-webkit-mask-image:var(--icon-next);mask-image:var(--icon-next)}#paginator #paginator-last .icon{-webkit-mask-image:var(--icon-last);mask-image:var(--icon-last)}#paginator #paginator-counter{display:inline-block;transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner-small);background-color:var(--accent-color-alpha);padding:.5rem .625rem;color:var(--accent-color);font-weight:bold;line-height:1;font-variant-numeric:tabular-nums}#paginator:has(a#paginator-previous:active) #paginator-counter{border-start-start-radius:1rem;border-end-start-radius:1rem}#paginator:has(a#paginator-next:active) #paginator-counter{border-start-end-radius:1rem;border-end-end-radius:1rem}#banner-container{--mask: linear-gradient(black, transparent);-webkit-user-select:none;-webkit-mask-image:var(--mask);position:absolute;z-index:-1;mask-image:var(--mask);inset-block-start:0;inset-inline-start:0;aspect-ratio:2/1;width:100%;user-select:none}#banner-container #banner{position:fixed;transition:none;margin:0;inset-block-start:0;inset-inline-start:0}#banner-container+#heading{margin-block-start:calc(50vw - 7rem)}@media only screen and (max-width: 480px){body:has(#banner-container) #site-nav:not(#handle+#site-nav){margin-block-start:calc(50vw + 1rem)}}#heading{margin:2rem 0 1rem;text-align:center}#heading h1{-webkit-background-clip:text;margin:0;background-image:linear-gradient(to right, var(--fg-muted-4), var(--fg-color), var(--fg-muted-4));background-clip:text;color:rgba(0,0,0,0)}#heading h1+p{display:inline}#heading .tags{display:inline-flex;justify-content:center;margin-block-start:1rem}#buttons-container{display:flex;position:fixed;flex-direction:column;gap:.5rem;inset-block-end:1rem;inset-inline-end:1rem}@media only screen and (max-width: 720px){#buttons-container{position:static;flex-direction:row-reverse;margin-block-start:2rem}}#buttons-container summary,#buttons-container #go-to-top,#buttons-container #share,#buttons-container #issue{display:inline-block;transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:999px;background-color:var(--fg-muted-1);padding:.5rem;color:var(--fg-muted-4);line-height:0}#buttons-container summary:hover,#buttons-container #go-to-top:hover,#buttons-container #share:hover,#buttons-container #issue:hover{background-color:var(--fg-muted-2);color:var(--fg-muted-5)}#buttons-container summary:active,#buttons-container #go-to-top:active,#buttons-container #share:active,#buttons-container #issue:active{transform:var(--active)}#buttons-container summary .icon,#buttons-container #go-to-top .icon,#buttons-container #share .icon,#buttons-container #issue .icon{transition:var(--transition)}#buttons-container details{position:relative;box-shadow:none;border-radius:0;background-color:rgba(0,0,0,0);padding:0}#buttons-container details[open] summary~*{transform-origin:bottom right;animation:button-dropdown-open var(--transition)}:root[dir*=rtl] #buttons-container details[open] summary~*{transform-origin:bottom left;animation:button-dropdown-open-rtl var(--transition)}@keyframes button-dropdown-open{from{transform:scale(.5) translate(1rem, 1rem);opacity:0}}@keyframes button-dropdown-open-rtl{from{transform:scale(.5) translate(-1rem, 1rem);opacity:0}}#buttons-container details summary::before{display:none}#buttons-container summary+div{-webkit-backdrop-filter:var(--blur);display:flex;position:absolute;flex-direction:column;z-index:1;backdrop-filter:var(--blur);inset-block-end:0;inset-inline-end:3rem;box-shadow:var(--edge-highlight),var(--shadow-glass);border-radius:var(--rounded-corner);background-color:var(--glass-bg);padding:1rem;width:min(var(--container-width)/3,90vw - 3rem);max-height:50vh}@media only screen and (max-width: 720px){#buttons-container summary+div{inset-inline-end:2.5rem;width:min(var(--container-width)/3,90vw - 2.5rem)}}#buttons-container summary+div strong.title{color:var(--fg-muted-4)}#buttons-container summary+div div{--mask: linear-gradient( to bottom, transparent, black 1rem, black calc(100% - 1rem), transparent );-webkit-mask-image:var(--mask);flex:1;mask-image:var(--mask);margin:0 -1rem -1rem;padding:1rem;padding-block-start:0;overflow:auto}#buttons-container summary+div ol,#buttons-container summary+div ul{margin:0;padding-inline-start:.75rem;font-size:var(--font-size-small)}#buttons-container summary+div ol:first-child,#buttons-container summary+div ul:first-child{margin-block-start:.75rem}#buttons-container summary+div ol li::marker,#buttons-container summary+div ul li::marker{color:var(--fg-muted-5)}#buttons-container summary+div ol a,#buttons-container summary+div ul a{color:var(--fg-muted-5)}#buttons-container #toc .icon{-webkit-mask-image:var(--icon-toc);mask-image:var(--icon-toc)}:root[dir*=rtl] #buttons-container #toc .icon{transform:scaleX(-1)}#buttons-container #backlinks .icon{-webkit-mask-image:var(--icon-backlink);mask-image:var(--icon-backlink)}:root[dir*=rtl] #buttons-container #backlinks .icon{transform:scaleX(-1)}#buttons-container #backlinks summary+div{width:min(var(--container-width)/3,90vw - 5rem)}@media only screen and (max-width: 720px){#buttons-container #go-to-top{display:none}}#buttons-container #go-to-top .icon{-webkit-mask-image:var(--icon-top);mask-image:var(--icon-top)}#buttons-container #share .icon{-webkit-mask-image:var(--icon-share);mask-image:var(--icon-share)}#buttons-container #issue .icon{-webkit-mask-image:var(--icon-bug);mask-image:var(--icon-bug)}.buttons{display:flex;flex-direction:row;justify-content:space-between;margin-block-start:4rem}.buttons.centered{justify-content:space-around}.buttons a{text-decoration:none}.buttons button{appearance:none;cursor:pointer;border:none;font-family:inherit}.buttons button:disabled{cursor:not-allowed}.buttons button:disabled:hover{background-color:var(--fg-muted-1);color:var(--fg-muted-5)}.buttons button:disabled:active{transform:none}.buttons a,.buttons button{transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);padding:.75rem 1rem;color:var(--fg-muted-5);font-weight:bold;font-size:var(--font-size-small);line-height:1}.buttons a:hover,.buttons button:hover{background-color:var(--fg-muted-2);color:var(--fg-color)}.buttons a:active,.buttons button:active{transform:var(--active)}.buttons a.colored,.buttons button.colored{box-shadow:none;background-color:rgba(0,0,0,0);color:var(--accent-color)}.buttons a.colored:hover,.buttons button.colored:hover{box-shadow:var(--edge-highlight);background-color:var(--accent-color-alpha)}.buttons a.big,.buttons button.big{border-radius:999px;padding:1rem 1.5rem}pre,code,kbd,samp{font-family:var(--font-monospace-code)}code:not(pre code){box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner-small);background-color:var(--fg-muted-1);padding:.125rem .375rem;color:var(--red-fg);font-size:var(--font-size-small-em)}pre{margin:1rem 0 1rem;box-shadow:var(--edge-highlight),var(--shadow);border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);padding:1rem;max-width:100vw;overflow:auto;line-height:normal}pre table{box-shadow:none;border-radius:0;background-color:rgba(0,0,0,0);table-layout:auto;overflow:hidden}pre table tr:nth-child(even){background-color:rgba(0,0,0,0)}pre table tr th,pre table tr td{padding:0}pre table tr th{background-color:rgba(0,0,0,0);font-weight:normal}pre table td:nth-of-type(1){-webkit-user-select:none;user-select:none;text-align:center}pre mark{display:block;box-shadow:none;border-radius:0;background-color:var(--fg-muted-1);padding:0;color:var(--fg-color)}pre[data-linenos]{padding:1rem 0}#comments #qrcode{float:inline-end;transform-origin:right;box-sizing:content-box;margin-inline-start:1rem;margin-block-start:3rem;margin-block-end:0;background-color:#fff;padding:.75rem;width:7.8125rem;height:7.8125rem}:root[dir*=rtl] #comments #qrcode{transform-origin:left}@media only screen and (max-width: 720px){#comments #qrcode{display:none}}#comments .buttons{justify-content:start;gap:.25rem;margin-block-start:2rem}#comments .buttons #load-comments:disabled{--shimmer: rgb( from var(--accent-color) r g b / calc(var(--color-opacity) * 2) );animation:loading-shimmer var(--transition-long) ease-in-out alternate infinite;transition:none;background-image:linear-gradient(to right, var(--fg-muted-1) 50%, var(--shimmer) 75%, var(--fg-muted-1) 100%);background-size:200%;background-color:rgba(0,0,0,0)}#comments .buttons #load-comments:disabled:hover{background-color:rgba(0,0,0,0)}@keyframes loading-shimmer{to{background-position-x:-200%}}#comments #comments-wrapper{display:flex;flex-direction:column;gap:2rem;margin-block-start:2rem}#comments #comments-wrapper #comments-status{color:var(--fg-muted-4);font-weight:bold;font-size:var(--font-size-x-large);text-align:center}#comments #comments-wrapper .comment{display:grid;grid-template-columns:min-content;grid-template-areas:"avatar name " "avatar time " "avatar post " "...... media " "...... card " "...... interactions";column-gap:1rem;justify-items:start}#comments #comments-wrapper .comment.comment-reply{position:relative;border-radius:.25rem;border-inline-start:.25rem solid var(--fg-muted-2);padding-inline-start:1rem}#comments #comments-wrapper .comment.comment-reply:has(+.comment-reply){border-end-start-radius:0}#comments #comments-wrapper .comment.comment-reply+.comment-reply{margin-block-start:-2rem;border-start-start-radius:0;padding-block-start:2rem}#comments #comments-wrapper .comment .avatar-link{position:relative;grid-area:avatar;width:4rem;height:4rem}#comments #comments-wrapper .comment .avatar-link .avatar{transition:var(--transition);margin:0;background-size:cover;width:100%;height:100%}#comments #comments-wrapper .comment .avatar-link .avatar:hover{transform:rotate(10deg) var(--hover);border-radius:var(--rounded-corner)}#comments #comments-wrapper .comment .avatar-link .avatar:active{transform:var(--active)}#comments #comments-wrapper .comment .author{display:flex;grid-area:name;align-items:center;gap:.25rem;font-weight:bold}#comments #comments-wrapper .comment .author .instance{transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:999px;background-color:var(--fg-muted-1);padding:.375rem .75rem;color:var(--fg-muted-5);font-size:var(--font-size-small);line-height:1;text-decoration:none}#comments #comments-wrapper .comment .author .instance:hover{background-color:var(--fg-muted-5);color:var(--fg-contrast);text-decoration:none}#comments #comments-wrapper .comment .author .instance:active{transform:var(--active)}#comments #comments-wrapper .comment .author .instance.op{background-color:var(--accent-color-alpha);padding-inline-start:.4375rem;color:var(--accent-color)}#comments #comments-wrapper .comment .author .instance.op:hover{background-color:var(--accent-color);color:var(--contrast-color)}#comments #comments-wrapper .comment .author .instance.op:hover::before{background-color:var(--contrast-color)}#comments #comments-wrapper .comment .author .instance.op::before{-webkit-mask-image:var(--icon-verified);display:inline-block;vertical-align:-.1875rem;mask-image:var(--icon-verified);mask-size:cover;transition:var(--transition);margin-inline-end:.25rem;background-color:var(--accent-color);width:1rem;height:1rem;content:""}:root[dir*=rtl] #comments #comments-wrapper .comment .author .instance.op{padding:.375rem .5rem .375rem .75rem}#comments #comments-wrapper .comment .mention{display:inline-block;transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner-small);background-color:var(--accent-color-alpha);padding:.25rem .375rem;line-height:1;text-decoration:none}#comments #comments-wrapper .comment .mention:hover{background-color:var(--accent-color);color:var(--contrast-color)}#comments #comments-wrapper .comment .mention:active{transform:var(--active)}#comments #comments-wrapper .comment .mention.hashtag{background-color:var(--fg-muted-1);color:var(--fg-muted-5)}#comments #comments-wrapper .comment .mention.hashtag:hover{background-color:var(--fg-muted-5);color:var(--fg-contrast)}#comments #comments-wrapper .comment time{grid-area:time;margin-block-start:.5rem;font-size:var(--font-size-small)}#comments #comments-wrapper .comment time a{color:var(--fg-muted-5)}#comments #comments-wrapper .comment time a:after{background-color:var(--fg-muted-5)}#comments #comments-wrapper .comment details[open]{border-radius:var(--rounded-corner-small);background-image:linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0) .5rem, var(--fg-muted-1) .5rem, var(--fg-muted-1) calc(100% - .5rem), rgba(0,0,0,0) calc(100% - .5rem), rgba(0,0,0,0)),linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0) .5rem, var(--bg-color) .5rem, var(--bg-color) calc(100% - .5rem), rgba(0,0,0,0) calc(100% - .5rem), rgba(0,0,0,0)),repeating-linear-gradient(45deg, var(--contrast-color), var(--contrast-color) .25rem, var(--accent-color) .25rem, var(--accent-color) .5rem)}#comments #comments-wrapper .comment details[open] summary{border-radius:0;background-image:none}#comments #comments-wrapper .comment details summary{border-radius:var(--rounded-corner-small);background-image:linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0) .5rem, var(--fg-muted-1) .5rem, var(--fg-muted-1) calc(100% - .5rem), rgba(0,0,0,0) calc(100% - .5rem), rgba(0,0,0,0)),linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0) .5rem, var(--bg-color) .5rem, var(--bg-color) calc(100% - .5rem), rgba(0,0,0,0) calc(100% - .5rem), rgba(0,0,0,0)),repeating-linear-gradient(45deg, var(--contrast-color), var(--contrast-color) .25rem, var(--accent-color) .25rem, var(--accent-color) .5rem)}#comments #comments-wrapper .comment main{grid-area:post;margin:1rem 0 0;width:100%}#comments #comments-wrapper .comment main :first-child{margin-block-start:0}#comments #comments-wrapper .comment main :last-child{margin-block-end:0}#comments #comments-wrapper .comment .attachments{display:grid;grid-template-columns:repeat(auto-fit, minmax(16rem, 1fr));grid-area:media;gap:.5rem;margin-block-start:1rem}#comments #comments-wrapper .comment .attachments img,#comments #comments-wrapper .comment .attachments video{margin:0}#comments #comments-wrapper .comment .card{grid-area:card;transition:var(--transition);margin-block-start:1rem;width:min(var(--container-width)/2,100%);font-weight:normal;text-decoration:none}#comments #comments-wrapper .comment .card:hover:not(:active) img{transform:var(--hover);box-shadow:var(--edge-highlight),var(--shadow-raised);border-radius:var(--rounded-corner-small)}#comments #comments-wrapper .comment .card:hover:not(:active) figcaption{border-radius:var(--rounded-corner);background-color:var(--fg-muted-2)}#comments #comments-wrapper .comment .card:active{transform:var(--active)}#comments #comments-wrapper .comment .card figure{display:flex;flex-direction:column;gap:.25rem;margin:0}#comments #comments-wrapper .comment .card figure img{margin:0;border-radius:var(--rounded-corner) var(--rounded-corner) var(--rounded-corner-small) var(--rounded-corner-small);aspect-ratio:16/9;object-fit:cover}#comments #comments-wrapper .comment .card figure img+figcaption{border-radius:var(--rounded-corner-small) var(--rounded-corner-small) var(--rounded-corner) var(--rounded-corner)}#comments #comments-wrapper .comment .card figure figcaption{display:flex;flex-direction:column;gap:.25rem;transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);padding:1rem;color:var(--fg-color);font-size:var(--font-size-medium);text-align:start}#comments #comments-wrapper .comment .card figure figcaption p{margin:0;color:var(--fg-muted-5);font-size:var(--font-size-small)}#comments #comments-wrapper .comment footer{display:flex;grid-area:interactions;gap:.25rem;margin-block-start:1rem}#comments #comments-wrapper .comment footer .boosts,#comments #comments-wrapper .comment footer .faves{transition:var(--transition);border-radius:999px;background-color:rgba(0,0,0,0);padding:.5rem .75rem;padding-inline-start:.625rem;line-height:1;font-variant-numeric:tabular-nums;text-decoration:none}#comments #comments-wrapper .comment footer .boosts .icon,#comments #comments-wrapper .comment footer .faves .icon{vertical-align:-.125em;transition:var(--transition-longer);margin-inline-end:.25rem}#comments #comments-wrapper .comment footer .boosts:hover,#comments #comments-wrapper .comment footer .faves:hover{box-shadow:var(--edge-highlight);text-decoration:none}#comments #comments-wrapper .comment footer .boosts:active,#comments #comments-wrapper .comment footer .faves:active{transform:var(--active)}#comments #comments-wrapper .comment footer .boosts{color:var(--purple-fg)}#comments #comments-wrapper .comment footer .boosts:hover{background-color:var(--purple-bg)}#comments #comments-wrapper .comment footer .boosts:hover .icon{transform:rotate(180deg)}:root[dir*=rtl] #comments #comments-wrapper .comment footer .boosts:hover .icon{transform:scaleX(-1) rotate(180deg)}#comments #comments-wrapper .comment footer .boosts .icon{-webkit-mask-image:var(--icon-boosts);mask-image:var(--icon-boosts)}:root[dir*=rtl] #comments #comments-wrapper .comment footer .boosts .icon{transform:scaleX(-1)}#comments #comments-wrapper .comment footer .faves{color:var(--yellow-fg)}#comments #comments-wrapper .comment footer .faves:hover{background-color:var(--yellow-bg)}#comments #comments-wrapper .comment footer .faves:hover .icon{transform:rotate(72deg)}:root[dir*=rtl] #comments #comments-wrapper .comment footer .faves:hover .icon{transform:rotate(-72deg)}#comments #comments-wrapper .comment footer .faves .icon{-webkit-mask-image:var(--icon-star);mask-image:var(--icon-star)}.crt{margin:1rem 0 1rem;box-shadow:var(--edge-highlight),var(--shadow-glow);border-radius:var(--rounded-corner);background-image:radial-gradient(color-mix(in srgb, var(--accent-color) 30%, #000), color-mix(in srgb, var(--accent-color) 10%, #000) 80%, color-mix(in srgb, var(--accent-color) 5%, #000))}.crt pre{--text-shadow-1: hsl(from var(--accent-color) h s l / 0.5);--text-shadow-2: hsl(from var(--accent-color) h calc(s * 2) l);animation:flicker .25s alternate infinite;margin:0;box-shadow:none;background-color:rgba(0,0,0,0) !important;padding:1rem 1rem;color:var(--accent-color) !important;text-shadow:var(--text-shadow-1) 0 0 .25rem,var(--text-shadow-2) 0 0 .75rem}@keyframes flicker{25%{opacity:.95}50%{opacity:.85}75%{opacity:1}to{opacity:.9}}.scanlines{position:relative;overflow:hidden}.scanlines::before{display:block;position:absolute;z-index:1;animation:scanlines .1s linear infinite;inset:0;background-image:repeating-linear-gradient(to bottom, rgba(0,0,0,.25), rgba(0,0,0,.25) .125rem, rgba(0,0,0,0) .125rem, rgba(0,0,0,0) .25rem);pointer-events:none;content:""}@keyframes scanlines{to{background-position-y:.25rem}}.scanlines::after{--scanline-color: rgb(from var(--accent-color) r g b / 0.05);display:block;position:absolute;animation:scanline 5s linear infinite;inset:0;background-image:linear-gradient(to bottom, rgba(0,0,0,0), var(--scanline-color) 16rem);background-size:auto 16rem;background-repeat:no-repeat;background-position-y:-16rem;pointer-events:none;content:""}@keyframes scanline{to{background-position-y:calc(100% + 16rem)}}.cursor{animation:cursor-blink 1s infinite}@keyframes cursor-blink{50%{opacity:0}}.emoji{display:inline-block;vertical-align:bottom;transition:var(--transition);cursor:zoom-in;margin:0;box-shadow:none;border-radius:0;background-color:rgba(0,0,0,0);width:1.5em;height:1.5em}.emoji:hover{transform:scale(2)}a.external::after{-webkit-mask-image:var(--icon-external);display:inline-block;opacity:var(--dim-opacity);mask-image:var(--icon-external);mask-size:cover;margin-inline-start:.25rem;background-color:currentColor;width:max(.75rem,.75em);height:max(.75rem,.75em);content:""}:root[dir*=rtl] a.external::after{transform:scaleX(-1)}h1 a:has(.icon.feed){color:currentColor}h1 .icon.feed{-webkit-mask-image:var(--icon-feed);vertical-align:-.375rem;mask-image:var(--icon-feed);margin-inline-start:.5rem;width:1em;height:1em}#site-footer{grid-area:footer;margin-block-end:2rem;text-align:center}#site-footer nav{display:inline-block;margin:0 auto 1rem;box-shadow:var(--edge-highlight);border-radius:1.375rem;background-color:var(--fg-muted-1);padding:.25rem;max-width:90%}#site-footer nav ul{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:.25rem;margin:0;padding:0}#site-footer nav li{display:flex;margin:0;padding:0;list-style:none}@media only screen and (max-width: 480px){#site-footer nav li{flex:0 0 100%}}#site-footer nav a{flex:1;transition:var(--transition);border-radius:999px;padding:.375rem .75rem;color:var(--fg-muted-4);text-align:center;text-decoration:none}#site-footer nav a.active{box-shadow:var(--edge-highlight);background-color:var(--accent-color-alpha);color:var(--accent-color)}#site-footer nav a.active:hover{background-color:var(--accent-color);color:var(--contrast-color)}#site-footer nav a:hover{box-shadow:var(--edge-highlight);background-color:var(--fg-muted-1);color:var(--fg-muted-5)}#site-footer nav a:active{transform:var(--active)}#site-footer #socials{display:flex;flex-wrap:wrap;justify-content:center;gap:.5rem;margin:1rem auto 0;padding:0}#site-footer #socials li{margin:0;padding:0;list-style:none}#site-footer #socials a{display:block;transition:var(--transition);border-radius:999px;padding:.5rem;color:var(--fg-muted-4);line-height:0}#site-footer #socials a:hover{box-shadow:var(--edge-highlight);background-color:var(--fg-muted-1);color:var(--fg-muted-5)}#site-footer #socials a:active{transform:var(--active)}#site-footer #socials a .icon{-webkit-mask-image:var(--icon);mask-image:var(--icon);transition:var(--transition);width:1.5rem;height:1.5rem}#site-footer #socials a span{display:none}#site-footer p{margin:1rem auto}#site-footer .link{display:inline-block;transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner-small);background-color:var(--accent-color-alpha);padding:.25rem .375rem;line-height:1;text-decoration:none}#site-footer .link:hover{background-color:var(--accent-color);color:var(--contrast-color)}#site-footer .link:active{transform:var(--active)}.footnotes-list p{margin-block-start:0;margin-block-end:0}*{box-sizing:border-box}:root{scroll-behavior:smooth;scrollbar-color:var(--accent-color) rgba(0,0,0,0);accent-color:var(--accent-color);font-size:16px}body{text-wrap:pretty;display:grid;grid-template-rows:auto minmax(auto, 1fr) auto;grid-template-areas:"nav" "main" "footer";margin:0;background-color:var(--bg-color);min-height:100vh;color:var(--fg-color);line-height:1.5;font-family:var(--font-system-ui),var(--font-emoji);overflow-wrap:break-word}body:has(#sidebar){grid-template-columns:1fr min(var(--container-width),90%) 1fr;grid-template-areas:"nav nav nav" "sidebar main ." "footer footer footer"}@media only screen and (max-width: 1200px){body:has(#sidebar){grid-template-areas:"nav nav nav" ". sidebar ." ". main ." "footer footer footer"}}::selection{background-color:var(--accent-color);color:var(--contrast-color)}:target:not(#main-content){transition:all var(--transition),scroll-margin-block-start 0s;scroll-margin-block-start:15vh;color:var(--accent-color);text-shadow:var(--text-shadow-glow)}:focus-visible{animation:focus-in var(--transition);outline:.125rem solid var(--accent-color);outline-offset:.125rem}@supports not selector(:focus-visible){:focus{animation:focus-in var(--transition);outline:.125rem solid var(--accent-color);outline-offset:.125rem}}@keyframes focus-in{from{outline:.5rem solid rgba(0,0,0,0);outline-offset:.25rem}}main{margin:4.25rem auto 4rem;width:min(var(--container-width),90%)}#sidebar{display:flex;position:sticky;top:0;grid-area:sidebar;opacity:.2;transition:var(--transition);height:100vh}#sidebar:hover{opacity:1}@media only screen and (max-width: 1200px){#sidebar{position:static;opacity:1;margin-block-start:4.25rem;margin-block-end:-4.25rem;padding:0;height:auto}}#sidebar>div{--mask: linear-gradient(to bottom, transparent, black 1rem, black calc(100% - 1rem), transparent);-webkit-mask-image:var(--mask);mask-image:var(--mask);padding:1rem;overflow:auto}#sidebar+main{grid-area:main;margin:0;margin-block-start:4.25rem;margin-block-end:4rem;width:auto}@media (prefers-reduced-motion){*,*::before,*::after{animation-duration:0s !important;transition-duration:0s !important}}.hidden{display:none;visibility:hidden}i.icon{display:inline-block;mask-size:cover;background-color:currentColor;width:1rem;height:1rem;font-style:normal;font-variant:normal;line-height:0;text-rendering:auto}iframe{display:block;margin:1rem auto;box-shadow:var(--edge-highlight),var(--shadow);border:none;border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);width:100%;max-width:100%}iframe.mastodon-embed{aspect-ratio:3/4;width:min(var(--container-width)/2,100%)}iframe.vimeo-embed,iframe.youtube-embed{aspect-ratio:16/9}iframe:fullscreen{box-shadow:none;border-radius:0}iframe:-webkit-full-screen{box-shadow:none;border-radius:0}input[type=radio],input[type=checkbox],input[type=color]{position:relative;appearance:none;transition:var(--transition);cursor:pointer;border:.15rem solid var(--fg-muted-2);background-color:var(--fg-muted-1);width:1rem;height:1rem}input[type=radio]:hover,input[type=checkbox]:hover,input[type=color]:hover{background-color:var(--fg-muted-2)}input[type=radio]:disabled,input[type=checkbox]:disabled,input[type=color]:disabled{opacity:var(--disabled-opacity);cursor:not-allowed}input[type=radio]:disabled:hover,input[type=checkbox]:disabled:hover,input[type=color]:disabled:hover{background-color:var(--fg-muted-1)}input[type=radio]:disabled:hover:checked,input[type=checkbox]:disabled:hover:checked,input[type=color]:disabled:hover:checked{background-color:var(--accent-color)}input[type=radio]::before,input[type=checkbox]::before{display:block;position:absolute;transform:scale(.5);opacity:0;transition:var(--transition);background-color:var(--contrast-color);content:""}input[type=radio]:checked,input[type=checkbox]:checked{border:.15rem solid rgba(0,0,0,0);background-color:var(--accent-color)}input[type=radio]:checked::before,input[type=checkbox]:checked::before{transform:scale(1);opacity:1}input[type=radio]{vertical-align:-.1875em;border-radius:50%}input[type=radio]::before{inset-block-start:.125rem;inset-inline-start:.125rem;border-radius:50%;width:.5rem;height:.5rem}input[type=checkbox]{vertical-align:-.1875em;border-radius:calc(var(--rounded-corner-small)/2)}input[type=checkbox]::before{-webkit-mask-image:var(--icon-checkmark);transform-origin:bottom left;mask-image:var(--icon-checkmark);mask-size:cover;inset-block-start:-.125rem;inset-inline-start:-.125rem;width:1rem;height:1rem}input[type=checkbox].switch{vertical-align:-.375rem;box-shadow:var(--edge-highlight);border:none;border-radius:999px;width:2.5rem;height:1.5rem}input[type=checkbox].switch.big{vertical-align:-.625rem;width:3rem;height:2rem}input[type=checkbox].switch.big::before{width:1.5rem;height:1.5rem}input[type=checkbox].switch::before{transform:none;transform-origin:center;opacity:1;mask-image:none;transition:var(--transition);inset-block-start:.25rem;inset-inline-start:.25rem;box-shadow:var(--shadow);border-radius:50%;background-color:#fff;width:1rem;height:1rem}input[type=checkbox].switch:checked{background-color:var(--accent-color)}input[type=checkbox].switch:checked::before{transform:translateX(1rem);background-color:var(--contrast-color)}:root[dir*=rtl] input[type=checkbox].switch:checked::before{transform:translateX(-1rem)}input[type=checkbox].switch:disabled::before{box-shadow:none}input[type=color]{vertical-align:-.375em;box-shadow:var(--edge-highlight);border:none;border-radius:var(--rounded-corner-small);padding:.25rem;width:3rem;height:2rem}input[type=color]::-moz-color-swatch{border:none;border-radius:calc(var(--rounded-corner-small) - .25rem)}input[type=color]::-webkit-color-swatch-wrapper{padding:0}input[type=color]::-webkit-color-swatch{border-radius:calc(var(--rounded-corner-small) - .25rem)}input[type=range]{appearance:none;transition:var(--transition);cursor:pointer;box-shadow:var(--edge-highlight);border-radius:999px;background:var(--accent-color);width:100%;height:.5rem}input[type=range]::-webkit-slider-thumb{appearance:none;filter:brightness(.9);transition:var(--transition);cursor:grab;box-shadow:var(--shadow);border-radius:999px;background-color:#fff;width:1.5rem;height:1.5rem}input[type=range]::-webkit-slider-thumb:active{transform:var(--active);cursor:grabbing}input[type=range]::-moz-range-thumb{appearance:none;transition:var(--transition);cursor:grab;box-shadow:var(--shadow);border:none;border-radius:999px;background-color:#fff;width:1.5rem;height:1.5rem}input[type=range]::-moz-range-thumb:active{transform:var(--active);cursor:grabbing}img,video{display:block;margin:1rem auto;box-shadow:var(--edge-highlight),var(--shadow);border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);max-width:100%}img.full,img[src*="#full"],video.full,video[src*="#full"]{width:100%}img.full-bleed,img[src*="#full-bleed"],video.full-bleed,video[src*="#full-bleed"]{margin-inline-start:calc((-100vw + 100%)/2);margin-inline-end:calc((-100vw + 100%)/2);width:100vw;max-width:100vw}img.start,img.end,img[src*="#start"],img[src*="#end"],video.start,video.end,video[src*="#start"],video[src*="#end"]{margin:0;width:30%}@media only screen and (max-width: 720px){img.start,img.end,img[src*="#start"],img[src*="#end"],video.start,video.end,video[src*="#start"],video[src*="#end"]{float:none;margin-inline-start:0;margin-inline-end:0;margin-block-start:1rem;margin-block-end:1rem;width:100%}}img.start,img[src*="#start"],video.start,video[src*="#start"]{float:inline-start;transform-origin:left;margin-inline-end:1rem}:root[dir*=rtl] img.start,:root[dir*=rtl] img[src*="#start"],:root[dir*=rtl] video.start,:root[dir*=rtl] video[src*="#start"]{transform-origin:right}img.end,img[src*="#end"],video.end,video[src*="#end"]{float:inline-end;transform-origin:right;margin-inline-start:1rem}:root[dir*=rtl] img.end,:root[dir*=rtl] img[src*="#end"],:root[dir*=rtl] video.end,:root[dir*=rtl] video[src*="#end"]{transform-origin:left}img.pixels,img[src*="#pixels"],video.pixels,video[src*="#pixels"]{image-rendering:pixelated}img.transparent,img.full-bleed,img[src*="#transparent"],img[src*="#full-bleed"],video.transparent,video.full-bleed,video[src*="#transparent"],video[src*="#full-bleed"]{box-shadow:none;border-radius:0;background-color:rgba(0,0,0,0)}img.spoiler,img[src*="#spoiler"],video.spoiler,video[src*="#spoiler"]{opacity:var(--dim-opacity);clip-path:inset(0 0 0 0 round var(--rounded-corner));filter:blur(1rem)}img.spoiler:hover,img.spoiler:active,img[src*="#spoiler"]:hover,img[src*="#spoiler"]:active,video.spoiler:hover,video.spoiler:active,video[src*="#spoiler"]:hover,video[src*="#spoiler"]:active{opacity:1;clip-path:inset(-.75rem -.75rem -.75rem -.75rem round var(--rounded-corner-small));filter:none}img.spoiler.solid,img.spoiler[src*="#solid"],img[src*="#spoiler"].solid,img[src*="#spoiler"][src*="#solid"],video.spoiler.solid,video.spoiler[src*="#solid"],video[src*="#spoiler"].solid,video[src*="#spoiler"][src*="#solid"]{clip-path:none;filter:brightness(0) contrast(.5);box-shadow:none}img.spoiler.solid:hover,img.spoiler.solid:active,img.spoiler[src*="#solid"]:hover,img.spoiler[src*="#solid"]:active,img[src*="#spoiler"].solid:hover,img[src*="#spoiler"].solid:active,img[src*="#spoiler"][src*="#solid"]:hover,img[src*="#spoiler"][src*="#solid"]:active,video.spoiler.solid:hover,video.spoiler.solid:active,video.spoiler[src*="#solid"]:hover,video.spoiler[src*="#solid"]:active,video[src*="#spoiler"].solid:hover,video[src*="#spoiler"].solid:active,video[src*="#spoiler"][src*="#solid"]:hover,video[src*="#spoiler"][src*="#solid"]:active{filter:none}img{transition:var(--transition-longer)}img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji){cursor:zoom-in}img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji):hover{position:relative;transform:var(--hover);z-index:1;box-shadow:var(--edge-highlight),var(--shadow-raised);border-radius:var(--rounded-corner-small)}img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji).start:hover,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji).end:hover,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji)[src*="#start"]:hover,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji)[src*="#end"]:hover{transform:scale(2)}@media only screen and (max-width: 720px){img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji).start,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji).end,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji)[src*="#start"],img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji)[src*="#end"]{transform-origin:center}img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji).start:hover,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji).end:hover,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji)[src*="#start"]:hover,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji)[src*="#end"]:hover{transform:var(--hover)}}img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji).transparent:hover,img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"],.emoji)[src*="#transparent"]:hover{box-shadow:none}a img:not(.no-hover,.full-bleed,[src*="#no-hover"],[src*="#full-bleed"]){cursor:pointer}video:fullscreen{box-shadow:none;border-radius:0}video:-webkit-full-screen{box-shadow:none;border-radius:0}#handle{position:fixed;z-index:999;transition:var(--transition);margin:0 auto;inset-block-start:0;inset-inline-end:0;inset-inline-start:0;width:min(var(--container-width),90%);height:4.25rem}#handle::before{position:absolute;transition:var(--transition);margin:0 auto;inset-block-start:.5rem;inset-inline-end:0;inset-inline-start:0;box-shadow:var(--edge-highlight);border-radius:999px;background-color:var(--accent-color);width:min(var(--container-width)/4,100%);height:.5rem;content:""}#handle:hover::before,#handle:has(+#site-nav:hover)::before,#handle:has(+#site-nav *:focus-visible,+#site-nav *:focus)::before{transform:translateY(-1rem) scale(.5);opacity:0}#handle:hover+#site-nav,#handle+#site-nav:hover,#handle+#site-nav:has(*:focus-visible,*:focus){transform:none;opacity:1;pointer-events:auto}#handle:hover+#site-nav::before,#handle+#site-nav:hover::before,#handle+#site-nav:has(*:focus-visible,*:focus)::before{-webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur)}#handle+#site-nav{position:fixed;transform:translateY(-1rem) scale(.5);transform-origin:top;opacity:0;transition:var(--transition);margin:0 auto;width:max-content;pointer-events:none}#handle+#site-nav::before{-webkit-backdrop-filter:saturate(1) blur(0);backdrop-filter:saturate(1) blur(0);transition:var(--transition)}#site-nav{position:sticky;grid-area:nav;z-index:999;margin:1rem auto 0;inset-block-start:1rem;inset-inline-end:0;inset-inline-start:0;border-radius:1.625rem;max-width:min(var(--container-width),90%)}@media only screen and (max-width: 480px){#site-nav{position:relative;margin:0 auto}}#site-nav::before{-webkit-backdrop-filter:var(--blur);position:absolute;z-index:-1;backdrop-filter:var(--blur);inset:0;box-shadow:var(--edge-highlight),var(--shadow-glass);border-radius:1.625rem;background-color:var(--glass-bg);content:""}#site-nav nav{padding:.5rem}#site-nav nav>a{-webkit-backdrop-filter:var(--blur);position:absolute;left:50%;transform:translateX(-50%);opacity:0;z-index:999;backdrop-filter:var(--blur);transition:var(--transition);inset-block-start:0;box-shadow:var(--edge-highlight),var(--shadow-glass);border-radius:999px;background-color:var(--glass-bg);padding:.625rem .75rem;pointer-events:none;line-height:1;text-decoration:none}#site-nav nav>a:focus{opacity:1;inset-block-start:calc(100% + .5rem)}#site-nav nav ul{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:.25rem;margin:0;padding:0}#site-nav nav li{display:flex;margin:0;padding:0;list-style:none}@media only screen and (max-width: 480px){#site-nav nav li:not(:has(.circle)){flex:0 0 100%}}#site-nav nav a,#site-nav nav summary{flex:1;transition:var(--transition);box-shadow:none;border-radius:999px;background-color:rgba(0,0,0,0);padding:.625rem .75rem;font-weight:bold;line-height:1;list-style:none;text-align:center;text-decoration:none}#site-nav nav a.active{box-shadow:var(--edge-highlight);background-color:var(--accent-color-alpha);color:var(--accent-color)}#site-nav nav a.active:hover{background-color:var(--accent-color);color:var(--contrast-color)}#site-nav nav #home a{color:var(--fg-muted-5);font-weight:800}#site-nav nav #home a:hover{color:var(--fg-color)}#site-nav nav #home a.active{color:var(--accent-color)}#site-nav nav #home a.active:hover{color:var(--contrast-color)}#site-nav nav #home a .icon{-webkit-mask-image:var(--icon-home);vertical-align:-.125em;mask-image:var(--icon-home);transition:var(--transition);margin-inline-end:.25rem}#site-nav nav .divider{align-self:stretch;margin:0 .25rem;background-color:var(--fg-muted-2);width:max(1px,.0625em)}@media only screen and (max-width: 480px){#site-nav nav .divider{display:none}}#site-nav nav a,#site-nav nav #search button,#site-nav nav #language-switcher summary,#site-nav nav #theme-switcher summary,#site-nav nav #theme-switcher button,#site-nav nav summary{color:var(--fg-muted-4)}#site-nav nav a:hover,#site-nav nav #search button:hover,#site-nav nav #language-switcher summary:hover,#site-nav nav #theme-switcher summary:hover,#site-nav nav #theme-switcher button:hover,#site-nav nav summary:hover{box-shadow:var(--edge-highlight);background-color:var(--fg-muted-1);color:var(--fg-muted-5)}#site-nav nav a:active,#site-nav nav #search button:active,#site-nav nav #language-switcher summary:active,#site-nav nav #theme-switcher summary:active,#site-nav nav #theme-switcher button:active,#site-nav nav summary:active{transform:var(--active)}#site-nav nav .circle{padding:.625rem .625rem;line-height:0}#site-nav nav .circle::before{display:none}#site-nav nav .circle .icon{vertical-align:-.125em;transition:var(--transition)}#site-nav nav button{appearance:none;transition:var(--transition);cursor:pointer;border:none;border-radius:999px;background-color:rgba(0,0,0,0);font-size:var(--font-size-medium)}#site-nav nav details{display:flex;position:relative;flex:1;box-shadow:none;border-radius:0;background-color:rgba(0,0,0,0);padding:0}#site-nav nav details[open] ul{animation:dropdown-open var(--transition)}@keyframes dropdown-open{from{transform:scale(.5) translate(-50%, -1rem);opacity:0}}#site-nav nav details ul{-webkit-backdrop-filter:var(--blur);position:absolute;left:50%;flex-direction:column;transform:translateX(-50%);transform-origin:top left;z-index:1;backdrop-filter:var(--blur);inset-block-start:3.25rem;box-shadow:var(--edge-highlight),var(--shadow-glass);border-radius:calc(var(--rounded-corner) + .25rem);background-color:var(--glass-bg);padding:.25rem}#site-nav nav details ul li{width:100%;white-space:nowrap}#site-nav nav details ul li a{border-radius:var(--rounded-corner);text-align:start}@media only screen and (max-width: 480px){#site-nav nav details:has(summary:not(.circle)) ul{inset-block-start:2.75rem}}#site-nav nav #search .icon{-webkit-mask-image:var(--icon-search);mask-image:var(--icon-search)}:root[dir*=rtl] #site-nav nav #search .icon{transform:scaleX(-1)}#site-nav nav #feed .icon{-webkit-mask-image:var(--icon-feed);mask-image:var(--icon-feed)}:root[dir*=rtl] #site-nav nav #feed .icon{transform:scaleX(-1)}#site-nav nav #repo .icon{-webkit-mask-image:var(--icon-git);mask-image:var(--icon-git)}#site-nav nav #language-switcher .icon{-webkit-mask-image:var(--icon-languages);mask-image:var(--icon-languages)}#site-nav nav #theme-switcher ul{flex-direction:row;flex-wrap:nowrap;border-radius:999px}#site-nav nav #theme-switcher .active{box-shadow:var(--edge-highlight);background-color:var(--accent-color-alpha);color:var(--accent-color)}#site-nav nav #theme-switcher .active:hover{background-color:var(--accent-color);color:var(--contrast-color)}#site-nav nav #theme-switcher #theme-system .icon,#site-nav nav #theme-switcher .icon{-webkit-mask-image:var(--icon-theme-system);mask-image:var(--icon-theme-system)}:root[dir*=rtl] #site-nav nav #theme-switcher #theme-system .icon,:root[dir*=rtl] #site-nav nav #theme-switcher .icon{transform:scaleX(-1)}#site-nav nav #theme-switcher #theme-light .icon,#site-nav nav #theme-switcher .icon.light{-webkit-mask-image:var(--icon-theme-light);mask-image:var(--icon-theme-light)}#site-nav nav #theme-switcher #theme-dark .icon,#site-nav nav #theme-switcher .icon.dark{-webkit-mask-image:var(--icon-theme-dark);mask-image:var(--icon-theme-dark)}:root[dir*=rtl] #site-nav nav #theme-switcher #theme-dark .icon,:root[dir*=rtl] #site-nav nav #theme-switcher .icon.dark{transform:scaleX(-1)}#site-nav #search-container{transform:scale(.5) translateY(-2.75rem);opacity:0;transition:var(--transition);padding:0 .5rem 0;height:0;pointer-events:none}#site-nav #search-container.active{transform:none;opacity:1;padding:0 .5rem .5rem;height:2.75rem;pointer-events:all}#site-nav #search-bar{box-shadow:var(--edge-highlight);border:none;border-radius:999px;background:var(--fg-muted-1);padding:0 .75rem;width:100%;height:2.25rem;color:inherit;font-size:var(--font-size-medium)}#site-nav #search-bar::placeholder{opacity:1;color:var(--fg-muted-4)}#site-nav #search-results-container{-webkit-backdrop-filter:var(--blur);display:flex;position:absolute;backdrop-filter:var(--blur);inset-block-start:calc(100% + .5rem);inset-inline-start:0;box-shadow:var(--edge-highlight),var(--shadow-glass);border-radius:calc(var(--rounded-corner) + .5rem);background-color:var(--glass-bg);width:100%;max-height:50vh}#site-nav #search-results{--mask: linear-gradient(to bottom, transparent, black 1rem, black calc(100% - 1rem), transparent);-webkit-mask-image:var(--mask);display:none;flex:1;flex-direction:column;gap:.5rem;mask-image:var(--mask);padding:.5rem;overflow:auto}#site-nav #search-results .item{display:inline-flex;flex-direction:column;box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);padding:.5rem}#site-nav #search-results .item a{width:fit-content}#site-nav #search-results .item a::after{content:" →"}:root[dir*=rtl] #site-nav #search-results .item a::after{content:" ←"}#site-nav #search-results .item span{color:var(--fg-muted-5)}#site-nav #search-results .item span:first-of-type,#site-nav #search-results .item span.more-matches{margin-block-start:.5rem;border-block-start:max(1px,.0625rem) solid var(--fg-muted-2);padding-block-start:.25rem}#site-nav #search-results .item span.more-matches{font-size:var(--font-size-small)}#site-nav #search-results .item span strong{color:var(--fg-color)}#not-found{width:min(var(--container-width)/5,100%)}#post-nav{display:flex;flex-direction:row;gap:.25rem}@media only screen and (max-width: 720px){#post-nav{flex-direction:column}}#post-nav .post-nav-item{flex:1;transition:var(--transition);border-radius:var(--rounded-corner);padding:1rem;padding-block-end:.75rem;min-width:0;text-decoration:none}#post-nav .post-nav-item:hover{box-shadow:var(--edge-highlight);background-color:var(--accent-color-alpha)}#post-nav .post-nav-item:hover .post-title{color:var(--accent-color)}#post-nav .post-nav-item:active{transform:var(--active)}#post-nav .post-nav-item.post-nav-prev .nav-arrow::before{content:"← "}:root[dir*=rtl] #post-nav .post-nav-item.post-nav-prev .nav-arrow::before{content:"→ "}#post-nav .post-nav-item.post-nav-next{text-align:end}#post-nav .post-nav-item.post-nav-next .nav-arrow::after{content:" →"}:root[dir*=rtl] #post-nav .post-nav-item.post-nav-next .nav-arrow::after{content:" ←"}#post-nav .post-nav-item .nav-arrow{margin-block-end:.75rem;color:var(--fg-muted-5);font-weight:normal;line-height:1}#post-nav .post-nav-item .post-title{display:block;transition:var(--transition);max-width:90vw;overflow:hidden;color:var(--fg-color);text-overflow:ellipsis;white-space:nowrap}.pre-container{margin:1rem 0 1rem;box-shadow:var(--edge-highlight),var(--shadow);border-radius:var(--rounded-corner)}.pre-container .header{--shimmer: rgb( from var(--accent-color) r g b / calc(var(--color-opacity) * 2) );display:flex;justify-content:space-between;align-items:center;border-radius:var(--rounded-corner) var(--rounded-corner) 0 0;background-image:linear-gradient(to right, var(--fg-muted-1) 50%, var(--shimmer) 75%, var(--fg-muted-1) 100%);background-size:200%;padding:.25rem;height:2.5rem}.pre-container .header span{margin-inline-start:.75rem;color:var(--fg-muted-5);font-weight:bold;line-height:1}.pre-container .header button{appearance:none;transition:var(--transition);cursor:pointer;border:none;border-radius:var(--rounded-corner-small);background-color:rgba(0,0,0,0);padding:.5rem;color:var(--fg-muted-4);line-height:0}.pre-container .header button:hover{box-shadow:var(--edge-highlight);background-color:var(--fg-muted-1);color:var(--fg-muted-5)}.pre-container .header button:active{transform:var(--active)}.pre-container .header button:disabled{cursor:not-allowed}.pre-container .header button:disabled:active{transform:none}.pre-container .header button .icon{-webkit-mask-image:var(--icon-copy);mask-image:var(--icon-copy);transition:var(--transition)}:root[dir*=rtl] .pre-container .header button .icon{transform:scaleX(-1)}.pre-container .header.active{animation:active-shimmer var(--transition-long)}.pre-container .header.active button{box-shadow:var(--edge-highlight);background-color:var(--accent-color-alpha);color:var(--accent-color)}.pre-container .header.active button .icon{-webkit-mask-image:var(--icon-done);mask-image:var(--icon-done)}@keyframes active-shimmer{to{background-position-x:-200%}}.pre-container pre{margin:0;box-shadow:none;border-radius:0 0 var(--rounded-corner) var(--rounded-corner)}.sparkline{display:flex;flex-direction:row;align-items:flex-end;float:inline-end;gap:.25rem;margin:1rem 0;width:6rem;height:2rem}.sparkline div{flex:1;transform-origin:bottom;transition:var(--transition);background-image:linear-gradient(to top, var(--accent-color) var(--bar-height), rgba(0,0,0,0) var(--bar-height));height:100%}.sparkline div:hover{height:200%}span.spoiler{filter:blur(.25rem);transition:var(--transition)}span.spoiler:hover,span.spoiler:active{filter:none}span.spoiler.solid{filter:none;border-radius:var(--rounded-corner-small);background-color:var(--fg-muted-4);color:rgba(0,0,0,0)}span.spoiler.solid:hover,span.spoiler.solid:active{background-color:rgba(0,0,0,0);color:inherit}.statement-container{margin:1rem 0;box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);padding:1rem}.statement-container :last-child{margin-block-end:0}.statement-container>:nth-child(2){margin-block-start:.5rem}.statement-container li::marker{color:inherit}.statement-container a{color:inherit}.statement-container .title{color:inherit}.statement-container .title .icon{margin-inline-end:.375rem}.statement-container.archive{background-color:var(--purple-bg);color:var(--purple-fg)}.statement-container.archive .icon{-webkit-mask-image:var(--icon-archive);mask-image:var(--icon-archive)}.statement-container.disclaimer{background-color:var(--red-bg);color:var(--red-fg)}.statement-container.disclaimer .icon{-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}.statement-container.trigger{background-color:var(--yellow-bg);color:var(--yellow-fg)}.statement-container.trigger .icon{-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}table{box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);border-collapse:collapse;background-color:var(--fg-muted-1);width:100%;overflow:hidden}table tr:nth-child(even){background-color:var(--fg-muted-1)}table tr th,table tr td{padding:.5rem 1rem}table tr th{background-color:var(--fg-muted-2);font-weight:bold}.tags{display:flex;flex-wrap:wrap;gap:.25rem;margin:0;margin-block-start:2rem;padding:0;list-style:none}.tags li{display:flex;transition:var(--transition);margin:0;padding:0}.tags li:active{transform:var(--active)}.tags a{transition:var(--transition);box-shadow:var(--edge-highlight);border-radius:999px;background-color:var(--fg-muted-1);padding:.375rem .75rem;color:var(--fg-muted-5);font-size:var(--font-size-small);line-height:1;text-decoration:none;white-space:nowrap}.tags a:hover{background-color:var(--accent-color-alpha);color:var(--accent-color);text-decoration:none}.tags a:hover .count{background-color:var(--accent-color-alpha);color:var(--accent-color)}.tags a:has(.tag){padding:0}.tags a .tag{display:inline-block;padding-inline-start:.75rem;padding-inline-end:.5rem;padding-block-start:.375rem;padding-block-end:.375rem}.tags a .count{display:inline-block;transition:var(--transition);border-start-end-radius:999px;border-end-end-radius:999px;background-color:var(--fg-muted-1);padding-inline-start:.5rem;padding-inline-end:.625rem;padding-block-start:.375rem;padding-block-end:.375rem;font-variant-numeric:tabular-nums}strong.title{color:var(--accent-color);font-size:var(--font-size-x-large);line-height:1}h1,h2,h3,h4,h5,h6{text-wrap:balance;margin:2rem 0 1rem;font-weight:lighter;line-height:normal;font-family:var(--font-antique);letter-spacing:-.05em}h1{font-size:var(--font-size-xxx-large)}h2{font-size:var(--font-size-xx-large)}h3{font-size:var(--font-size-x-large)}h4{font-size:var(--font-size-large)}h5{font-size:var(--font-size-medium)}h6{font-size:var(--font-size-small)}small{color:var(--fg-muted-5);font-size:var(--font-size-small-em)}abbr[title]{cursor:help;text-decoration:underline;text-decoration-style:dotted;text-decoration-thickness:max(1px,.0625em)}figcaption{color:var(--fg-muted-4);font-size:var(--font-size-small-em);text-align:center}blockquote{margin:0;border-radius:.25rem;border-inline-start:.25rem solid var(--accent-color);padding-inline-start:.75rem;color:var(--fg-muted-5)}mark,del,ins,samp,q{box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner-small);padding:.125rem .375rem}mark{background-color:var(--accent-color-alpha);color:var(--accent-color)}del{background-color:var(--red-bg);color:var(--red-fg);text-decoration:line-through;text-decoration-thickness:max(1px,.0625em)}ins{background-color:var(--green-bg);color:var(--green-fg);text-decoration:underline;text-decoration-thickness:max(1px,.0625em)}samp{background-color:var(--fg-muted-1);color:var(--fg-muted-5);font-size:var(--font-size-small-em)}q{background-color:var(--fg-muted-1);color:var(--fg-muted-5);font-style:italic}u{text-decoration:underline;text-decoration-style:wavy;text-decoration-color:var(--red-fg);text-decoration-thickness:max(1px,.0625em)}progress{appearance:none;box-shadow:var(--edge-highlight);border:none;border-radius:999px;background-color:var(--fg-muted-1);width:100%;height:.5rem;color:var(--accent-color)}progress:indeterminate{background-color:var(--fg-muted-1)}progress:indeterminate::-moz-progress-bar{background-color:rgba(0,0,0,0)}progress::-webkit-progress-bar{background-color:rgba(0,0,0,0)}progress::-moz-progress-bar{border-radius:999px;background-color:var(--accent-color)}progress::-webkit-progress-value{border-radius:999px;background-color:var(--accent-color)}kbd{display:inline-block;transition:var(--transition);cursor:pointer;box-shadow:var(--edge-highlight),inset 0 -.125rem 0 var(--fg-muted-2);border-radius:var(--rounded-corner-small);background-color:var(--fg-muted-1);padding:.125rem .375rem;font-size:var(--font-size-small-em)}kbd:active{transform:translateY(.125rem);box-shadow:inset 0 .0625rem 0 var(--fg-muted-2);background-color:var(--fg-muted-2)}a{color:var(--accent-color);font-weight:bold;text-decoration-thickness:max(1px,.0625em)}a:hover{text-decoration-style:wavy}hr{margin:2rem auto;border:none;border-block-start:.1875rem double var(--fg-muted-2);overflow:visible;text-align:center}hr::after{position:relative;inset-block-start:-1.25rem;content:"❦";color:var(--fg-muted-4);font-size:var(--font-size-x-large)}dt{font-weight:bold}dd{margin-inline-start:1.5rem;margin-block-end:1rem}aside{float:right;margin-inline-start:1rem;box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);background-color:var(--accent-color-alpha);padding:1rem;width:30%}:root[dir*=rtl] aside{float:left}@media only screen and (max-width: 720px){aside{float:none;margin-inline-start:0;width:100%}}aside :first-child{margin-block-start:0}aside :last-child{margin-block-end:0}details summary{cursor:pointer;box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);padding:1rem;color:var(--fg-muted-5);font-weight:bold;line-height:1;list-style:none}details summary::marker,details summary::-webkit-details-marker{display:none}details summary::before{-webkit-mask-image:var(--icon-down);display:inline-block;vertical-align:-.125em;mask-image:var(--icon-down);transition:var(--transition);margin-inline-end:.25rem;background-color:currentColor;width:1rem;height:1rem;content:""}details :last-child{margin-block-end:0}details[open]{box-shadow:var(--edge-highlight);border-radius:var(--rounded-corner);background-color:var(--fg-muted-1);padding:1rem}details[open] summary{box-shadow:none;border-radius:0;background-color:rgba(0,0,0,0);padding:0}details[open] summary::before{transform:scaleY(-1)}details[open] summary~*{animation:details-open var(--transition)}@keyframes details-open{from{transform:translateY(-1rem);opacity:0}}figure{margin-inline:0}ol,ul{padding-inline-start:1.5rem}li{margin:.125rem 0;padding-inline-start:.25rem}li::marker{color:var(--accent-color);font-weight:bold}.visually-hidden{clip:rect(0 0 0 0);position:absolute !important;clip-path:inset(100%);width:1px !important;height:1px !important;overflow:hidden;white-space:nowrap}h1:hover .zola-anchor,h2:hover .zola-anchor,h3:hover .zola-anchor,h4:hover .zola-anchor,h5:hover .zola-anchor,h6:hover .zola-anchor{transform:translateY(-.125em);opacity:1}:root[dir*=rtl] h1:hover .zola-anchor,:root[dir*=rtl] h2:hover .zola-anchor,:root[dir*=rtl] h3:hover .zola-anchor,:root[dir*=rtl] h4:hover .zola-anchor,:root[dir*=rtl] h5:hover .zola-anchor,:root[dir*=rtl] h6:hover .zola-anchor{transform:translateY(-.125em)}.zola-anchor{position:absolute;transform:translateX(.5rem) translateY(-.125em);opacity:0;transition:var(--transition);margin-inline-start:calc(-1em - .5rem);color:var(--fg-muted-4);line-height:1}@media only screen and (max-width: 832px){.zola-anchor{display:none}}:root[dir*=rtl] .zola-anchor{transform:translateX(-.5rem) translateY(-.125em)}.zola-anchor:hover{color:var(--accent-color)}.zola-anchor:active{transform:var(--active)}.zola-anchor:focus-visible{opacity:1}.zola-anchor .icon{-webkit-mask-image:var(--icon-link);mask-image:var(--icon-link);mask-size:cover;transition:var(--transition);width:1em;height:1em}:root[dir*=rtl] .zola-anchor .icon{transform:scaleX(-1)}:target .zola-anchor{color:var(--accent-color-alpha)}
\ No newline at end of file
diff --git a/public/syntax-theme-dark.css b/public/syntax-theme-dark.css
new file mode 100644
index 00000000..a18f9ba7
--- /dev/null
+++ b/public/syntax-theme-dark.css
@@ -0,0 +1,283 @@
+/*
+ * theme "Solarized (dark)" generated by syntect
+ */
+
+.z-code {
+ color: #839496;
+ background-color: #002b36;
+}
+
+.z-comment, .z-meta.z-documentation {
+ color: #586e75;
+}
+.z-string {
+ color: #2aa198;
+}
+.z-string.z-regexp {
+ color: #2aa198;
+}
+.z-constant.z-character.z-escape {
+ color: #dc322f;
+}
+.z-constant.z-numeric {
+ color: #6c71c4;
+}
+.z-variable {
+ color: #268bd2;
+}
+.z-variable.z-function {
+ color: #b58900;
+}
+.z-variable.z-language {
+ color: #d33682;
+}
+.z-keyword {
+ color: #859900;
+}
+.z-meta.z-import .z-keyword, .z-keyword.z-control.z-import, .z-keyword.z-control.z-import.z-from, .z-keyword.z-other.z-import, .z-keyword.z-control.z-at-rule.z-include, .z-keyword.z-control.z-at-rule.z-import {
+ color: #cb4b16;
+}
+.z-keyword.z-operator.z-comparison, .z-keyword.z-operator.z-assignment, .z-keyword.z-operator.z-arithmetic {
+ color: #657b83;
+}
+.z-storage {
+ color: #859900;
+}
+.z-storage.z-modifier {
+ color: #93a1a1;
+}
+.z-keyword.z-control.z-class, .z-entity.z-name, .z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class {
+ color: #b58900;
+}
+.z-entity.z-other.z-inherited-class {
+ color: #268bd2;
+}
+.z-entity.z-other.z-attribute-name {
+ color: #b58900;
+}
+.z-support, .z-support.z-type, .z-support.z-class {
+ color: #859900;
+}
+.z-entity.z-name.z-function {
+ color: #b58900;
+}
+.z-punctuation.z-definition.z-variable {
+ color: #859900;
+}
+.z-constant, .z-constant.z-language, .z-meta.z-preprocessor {
+ color: #b58900;
+}
+.z-entity.z-name.z-section {
+ color: #cb4b16;
+}
+.z-support.z-function.z-construct, .z-keyword.z-other.z-new {
+ color: #dc322f;
+}
+.z-constant.z-character, .z-constant.z-other {
+ color: #cb4b16;
+}
+.z-entity.z-name.z-tag {
+ color: #268bd2;
+}
+.z-punctuation.z-definition.z-tag.z-html, .z-punctuation.z-definition.z-tag.z-begin, .z-punctuation.z-definition.z-tag.z-end {
+ color: #586e75;
+}
+.z-support.z-function {
+ color: #859900;
+}
+.z-punctuation.z-separator.z-continuation {
+ color: #dc322f;
+}
+.z-storage.z-type {
+ color: #268bd2;
+}
+.z-support.z-type.z-exception {
+ color: #cb4b16;
+}
+.z-keyword.z-other.z-special-method {
+ color: #cb4b16;
+}
+.z-invalid {
+ background-color: #6e2e32;
+}
+.z-string.z-quoted.z-double, .z-string.z-quoted.z-single {
+ color: #2aa198;
+}
+.z-punctuation.z-definition.z-string {
+ color: #839496;
+}
+.z-meta.z-brace.z-square, .z-punctuation.z-section.z-brackets {
+ color: #268bd2;
+}
+.z-meta.z-brace.z-round, .z-meta.z-brace.z-curly, .z-punctuation.z-section, .z-punctuation.z-section.z-block, .z-punctuation.z-definition.z-parameters, .z-punctuation.z-section.z-group {
+ color: #657b83;
+}
+.z-support.z-constant.z-color, .z-invalid.z-deprecated.z-color.z-w3c-non-standard-color-name.z-scss {
+ color: #b58900;
+}
+.z-meta.z-selector.z-css {
+ color: #657b83;
+}
+.z-entity.z-name.z-tag.z-css, .z-entity.z-name.z-tag.z-scss, .z-source.z-less .z-keyword.z-control.z-html.z-elements, .z-source.z-sass .z-keyword.z-control.z-untitled {
+ color: #b58900;
+}
+.z-entity.z-other.z-attribute-name.z-class {
+ color: #b58900;
+}
+.z-entity.z-other.z-attribute-name.z-id {
+ color: #b58900;
+}
+.z-entity.z-other.z-attribute-name.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-pseudo-class, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-class {
+ color: #268bd2;
+}
+.z-text.z-html.z-basic .z-meta.z-tag.z-other.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-any.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-block.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-inline.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-structure.z-any.z-html, .z-text.z-html.z-basic .z-source.z-js.z-embedded.z-html, .z-punctuation.z-separator.z-key-value.z-html {
+ color: #657b83;
+}
+.z-text.z-html.z-basic .z-entity.z-other.z-attribute-name.z-html, .z-meta.z-tag.z-xml .z-entity.z-other.z-attribute-name {
+ color: #b58900;
+}
+.z-keyword.z-other.z-special-method.z-ruby {
+ color: #859900;
+}
+.z-variable.z-other.z-constant.z-ruby {
+ color: #b58900;
+}
+.z-constant.z-other.z-symbol.z-ruby {
+ color: #2aa198;
+}
+.z-keyword.z-other.z-special-method.z-ruby {
+ color: #cb4b16;
+}
+.z-meta.z-array .z-support.z-function.z-construct.z-php {
+ color: #b58900;
+}
+.z-entity.z-name.z-function.z-preprocessor.z-c, .z-meta.z-preprocessor.z-c.z-include, .z-meta.z-preprocessor.z-macro.z-c {
+ color: #cb4b16;
+}
+.z-meta.z-preprocessor.z-c.z-include .z-string.z-quoted.z-other.z-lt-gt.z-include.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-begin.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-end.z-c {
+ color: #2aa198;
+}
+.z-other.z-package.z-exclude, .z-other.z-remove {
+ color: #dc322f;
+}
+.z-other.z-add {
+ color: #2aa198;
+}
+.z-punctuation.z-section.z-group.z-tex, .z-punctuation.z-definition.z-arguments.z-begin.z-latex, .z-punctuation.z-definition.z-arguments.z-end.z-latex, .z-punctuation.z-definition.z-arguments.z-latex {
+ color: #dc322f;
+}
+.z-meta.z-group.z-braces.z-tex {
+ color: #b58900;
+}
+.z-string.z-other.z-math.z-tex {
+ color: #b58900;
+}
+.z-variable.z-parameter.z-function.z-latex {
+ color: #cb4b16;
+}
+.z-punctuation.z-definition.z-constant.z-math.z-tex {
+ color: #dc322f;
+}
+.z-text.z-tex.z-latex .z-constant.z-other.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-character.z-math.z-tex {
+ color: #2aa198;
+}
+.z-string.z-other.z-math.z-tex {
+ color: #b58900;
+}
+.z-punctuation.z-definition.z-string.z-begin.z-tex, .z-punctuation.z-definition.z-string.z-end.z-tex {
+ color: #dc322f;
+}
+.z-keyword.z-control.z-label.z-latex, .z-text.z-tex.z-latex .z-constant.z-other.z-general.z-math.z-tex {
+ color: #2aa198;
+}
+.z-variable.z-parameter.z-definition.z-label.z-latex {
+ color: #dc322f;
+}
+.z-support.z-function.z-be.z-latex {
+ color: #859900;
+}
+.z-support.z-function.z-section.z-latex {
+ color: #cb4b16;
+}
+.z-support.z-function.z-general.z-tex {
+ color: #2aa198;
+}
+.z-keyword.z-control.z-ref.z-latex {
+ color: #2aa198;
+}
+.z-storage.z-type.z-class.z-python, .z-storage.z-type.z-function.z-python, .z-storage.z-modifier.z-global.z-python {
+ color: #859900;
+}
+.z-support.z-type.z-exception.z-python {
+ color: #b58900;
+}
+.z-meta.z-scope.z-for-in-loop.z-shell, .z-variable.z-other.z-loop.z-shell {
+ color: #93a1a1;
+}
+.z-meta.z-scope.z-case-block.z-shell, .z-meta.z-scope.z-case-body.z-shell {
+ color: #93a1a1;
+}
+.z-punctuation.z-definition.z-logical-expression.z-shell {
+ color: #dc322f;
+}
+.z-storage.z-modifier.z-c++ {
+ color: #859900;
+}
+.z-support.z-function.z-perl {
+ color: #268bd2;
+}
+.z-meta.z-diff, .z-meta.z-diff.z-header {
+ color: #586e75;
+}
+.z-meta.z-diff.z-range {
+ color: #268bd2;
+}
+.z-markup.z-deleted {
+ color: #dc322f;
+}
+.z-markup.z-changed {
+ color: #b58900;
+}
+.z-markup.z-inserted {
+ color: #859900;
+}
+.z-markup.z-warning {
+ color: #b58900;
+}
+.z-markup.z-error {
+ color: #dc322f;
+}
+.z-markup.z-heading, .z-punctuation.z-definition.z-heading.z-markdown {
+ color: #b58900;
+font-weight: bold;
+}
+.z-markup.z-quote {
+ color: #859900;
+}
+.z-markup.z-italic {
+font-style: italic;
+}
+.z-markup.z-bold {
+font-weight: bold;
+}
+.z-markup.z-underline.z-link.z-markdown, .z-meta.z-link.z-reference .z-constant.z-other.z-reference.z-link.z-markdown {
+ color: #2aa198;
+}
+.z-constant.z-other.z-reference.z-link.z-markdown {
+ color: #6c71c4;
+}
+.z-meta.z-paragraph.z-markdown .z-meta.z-dummy.z-line-break {
+ background-color: #586e75;
+}
+.z-brackethighlighter.z-all {
+ color: #586e75;
+}
+.z-entity.z-name.z-filename.z-find-in-files {
+ color: #2aa198;
+}
+.z-constant.z-numeric.z-line-number.z-find-in-files {
+ color: #586e75;
+}
+.z-variable.z-other.z-readwrite.z-js, .z-variable.z-other.z-object.z-js, .z-variable.z-other.z-constant.z-js {
+ color: #839496;
+}
diff --git a/public/syntax-theme-light.css b/public/syntax-theme-light.css
new file mode 100644
index 00000000..40ea69e2
--- /dev/null
+++ b/public/syntax-theme-light.css
@@ -0,0 +1,283 @@
+/*
+ * theme "Solarized (light)" generated by syntect
+ */
+
+.z-code {
+ color: #657b83;
+ background-color: #fdf6e3;
+}
+
+.z-comment, .z-meta.z-documentation {
+ color: #93a1a1;
+}
+.z-string {
+ color: #2aa198;
+}
+.z-string.z-regexp {
+ color: #2aa198;
+}
+.z-constant.z-character.z-escape {
+ color: #dc322f;
+}
+.z-constant.z-numeric {
+ color: #6c71c4;
+}
+.z-variable {
+ color: #268bd2;
+}
+.z-variable.z-function {
+ color: #b58900;
+}
+.z-variable.z-language {
+ color: #d33682;
+}
+.z-keyword {
+ color: #859900;
+}
+.z-meta.z-import .z-keyword, .z-keyword.z-control.z-import, .z-keyword.z-control.z-import.z-from, .z-keyword.z-other.z-import, .z-keyword.z-control.z-at-rule.z-include, .z-keyword.z-control.z-at-rule.z-import {
+ color: #cb4b16;
+}
+.z-keyword.z-operator.z-comparison, .z-keyword.z-operator.z-assignment, .z-keyword.z-operator.z-arithmetic {
+ color: #657b83;
+}
+.z-storage {
+ color: #859900;
+}
+.z-storage.z-modifier {
+ color: #586e75;
+}
+.z-keyword.z-control.z-class, .z-entity.z-name, .z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class {
+ color: #b58900;
+}
+.z-entity.z-other.z-inherited-class {
+ color: #268bd2;
+}
+.z-entity.z-other.z-attribute-name {
+ color: #b58900;
+}
+.z-support, .z-support.z-type, .z-support.z-class {
+ color: #859900;
+}
+.z-entity.z-name.z-function {
+ color: #b58900;
+}
+.z-punctuation.z-definition.z-variable {
+ color: #859900;
+}
+.z-constant, .z-constant.z-language, .z-meta.z-preprocessor {
+ color: #b58900;
+}
+.z-entity.z-name.z-section {
+ color: #cb4b16;
+}
+.z-support.z-function.z-construct, .z-keyword.z-other.z-new {
+ color: #dc322f;
+}
+.z-constant.z-character, .z-constant.z-other {
+ color: #cb4b16;
+}
+.z-entity.z-name.z-tag {
+ color: #268bd2;
+}
+.z-punctuation.z-definition.z-tag.z-html, .z-punctuation.z-definition.z-tag.z-begin, .z-punctuation.z-definition.z-tag.z-end {
+ color: #93a1a1;
+}
+.z-support.z-function {
+ color: #859900;
+}
+.z-punctuation.z-separator.z-continuation {
+ color: #dc322f;
+}
+.z-storage.z-type {
+ color: #268bd2;
+}
+.z-support.z-type.z-exception {
+ color: #cb4b16;
+}
+.z-keyword.z-other.z-special-method {
+ color: #cb4b16;
+}
+.z-invalid {
+ background-color: #ec9489;
+}
+.z-string.z-quoted.z-double, .z-string.z-quoted.z-single {
+ color: #2aa198;
+}
+.z-punctuation.z-definition.z-string {
+ color: #839496;
+}
+.z-meta.z-brace.z-square, .z-punctuation.z-section.z-brackets {
+ color: #268bd2;
+}
+.z-meta.z-brace.z-round, .z-meta.z-brace.z-curly, .z-punctuation.z-section, .z-punctuation.z-section.z-block, .z-punctuation.z-definition.z-parameters, .z-punctuation.z-section.z-group {
+ color: #657b83;
+}
+.z-support.z-constant.z-color, .z-invalid.z-deprecated.z-color.z-w3c-non-standard-color-name.z-scss {
+ color: #b58900;
+}
+.z-meta.z-selector.z-css {
+ color: #657b83;
+}
+.z-entity.z-name.z-tag.z-css, .z-entity.z-name.z-tag.z-scss, .z-source.z-less .z-keyword.z-control.z-html.z-elements, .z-source.z-sass .z-keyword.z-control.z-untitled {
+ color: #b58900;
+}
+.z-entity.z-other.z-attribute-name.z-class {
+ color: #b58900;
+}
+.z-entity.z-other.z-attribute-name.z-id {
+ color: #b58900;
+}
+.z-entity.z-other.z-attribute-name.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-pseudo-class, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-class {
+ color: #268bd2;
+}
+.z-text.z-html.z-basic .z-meta.z-tag.z-other.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-any.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-block.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-inline.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-structure.z-any.z-html, .z-text.z-html.z-basic .z-source.z-js.z-embedded.z-html, .z-punctuation.z-separator.z-key-value.z-html {
+ color: #657b83;
+}
+.z-text.z-html.z-basic .z-entity.z-other.z-attribute-name.z-html, .z-meta.z-tag.z-xml .z-entity.z-other.z-attribute-name {
+ color: #b58900;
+}
+.z-keyword.z-other.z-special-method.z-ruby {
+ color: #859900;
+}
+.z-variable.z-other.z-constant.z-ruby {
+ color: #b58900;
+}
+.z-constant.z-other.z-symbol.z-ruby {
+ color: #2aa198;
+}
+.z-keyword.z-other.z-special-method.z-ruby {
+ color: #cb4b16;
+}
+.z-meta.z-array .z-support.z-function.z-construct.z-php {
+ color: #b58900;
+}
+.z-entity.z-name.z-function.z-preprocessor.z-c, .z-meta.z-preprocessor.z-c.z-include, .z-meta.z-preprocessor.z-macro.z-c {
+ color: #cb4b16;
+}
+.z-meta.z-preprocessor.z-c.z-include .z-string.z-quoted.z-other.z-lt-gt.z-include.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-begin.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-end.z-c {
+ color: #2aa198;
+}
+.z-other.z-package.z-exclude, .z-other.z-remove {
+ color: #dc322f;
+}
+.z-other.z-add {
+ color: #2aa198;
+}
+.z-punctuation.z-section.z-group.z-tex, .z-punctuation.z-definition.z-arguments.z-begin.z-latex, .z-punctuation.z-definition.z-arguments.z-end.z-latex, .z-punctuation.z-definition.z-arguments.z-latex {
+ color: #dc322f;
+}
+.z-meta.z-group.z-braces.z-tex {
+ color: #b58900;
+}
+.z-string.z-other.z-math.z-tex {
+ color: #b58900;
+}
+.z-variable.z-parameter.z-function.z-latex {
+ color: #cb4b16;
+}
+.z-punctuation.z-definition.z-constant.z-math.z-tex {
+ color: #dc322f;
+}
+.z-text.z-tex.z-latex .z-constant.z-other.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-character.z-math.z-tex {
+ color: #2aa198;
+}
+.z-string.z-other.z-math.z-tex {
+ color: #b58900;
+}
+.z-punctuation.z-definition.z-string.z-begin.z-tex, .z-punctuation.z-definition.z-string.z-end.z-tex {
+ color: #dc322f;
+}
+.z-keyword.z-control.z-label.z-latex, .z-text.z-tex.z-latex .z-constant.z-other.z-general.z-math.z-tex {
+ color: #2aa198;
+}
+.z-variable.z-parameter.z-definition.z-label.z-latex {
+ color: #dc322f;
+}
+.z-support.z-function.z-be.z-latex {
+ color: #859900;
+}
+.z-support.z-function.z-section.z-latex {
+ color: #cb4b16;
+}
+.z-support.z-function.z-general.z-tex {
+ color: #2aa198;
+}
+.z-keyword.z-control.z-ref.z-latex {
+ color: #2aa198;
+}
+.z-storage.z-type.z-class.z-python, .z-storage.z-type.z-function.z-python, .z-storage.z-modifier.z-global.z-python {
+ color: #859900;
+}
+.z-support.z-type.z-exception.z-python {
+ color: #b58900;
+}
+.z-meta.z-scope.z-for-in-loop.z-shell, .z-variable.z-other.z-loop.z-shell {
+ color: #586e75;
+}
+.z-meta.z-scope.z-case-block.z-shell, .z-meta.z-scope.z-case-body.z-shell {
+ color: #586e75;
+}
+.z-punctuation.z-definition.z-logical-expression.z-shell {
+ color: #dc322f;
+}
+.z-storage.z-modifier.z-c++ {
+ color: #859900;
+}
+.z-support.z-function.z-perl {
+ color: #268bd2;
+}
+.z-meta.z-diff, .z-meta.z-diff.z-header {
+ color: #93a1a1;
+}
+.z-meta.z-diff.z-range {
+ color: #268bd2;
+}
+.z-markup.z-deleted {
+ color: #dc322f;
+}
+.z-markup.z-changed {
+ color: #b58900;
+}
+.z-markup.z-inserted {
+ color: #859900;
+}
+.z-markup.z-warning {
+ color: #b58900;
+}
+.z-markup.z-error {
+ color: #dc322f;
+}
+.z-markup.z-heading, .z-punctuation.z-definition.z-heading.z-markdown {
+ color: #b58900;
+font-weight: bold;
+}
+.z-markup.z-quote {
+ color: #859900;
+}
+.z-markup.z-italic {
+font-style: italic;
+}
+.z-markup.z-bold {
+font-weight: bold;
+}
+.z-markup.z-underline.z-link.z-markdown, .z-meta.z-link.z-reference .z-constant.z-other.z-reference.z-link.z-markdown {
+ color: #2aa198;
+}
+.z-constant.z-other.z-reference.z-link.z-markdown {
+ color: #6c71c4;
+}
+.z-meta.z-paragraph.z-markdown .z-meta.z-dummy.z-line-break {
+ background-color: #eee8d5;
+}
+.z-brackethighlighter.z-all {
+ color: #93a1a1;
+}
+.z-entity.z-name.z-filename.z-find-in-files {
+ color: #2aa198;
+}
+.z-constant.z-numeric.z-line-number.z-find-in-files {
+ color: #93a1a1;
+}
+.z-variable.z-other.z-readwrite.z-js, .z-variable.z-other.z-object.z-js, .z-variable.z-other.z-constant.z-js {
+ color: #657b83;
+}
diff --git a/public/theme-switcher.js b/public/theme-switcher.js
new file mode 100644
index 00000000..5632d6f1
--- /dev/null
+++ b/public/theme-switcher.js
@@ -0,0 +1,104 @@
+// Theme Initialization
+(function () {
+ // Get the default theme from the HTML data-theme attribute.
+ const defaultTheme = document.documentElement.getAttribute("data-theme");
+
+ // Set the data-default-theme attribute only if defaultTheme is not null.
+ if (defaultTheme) {
+ document.documentElement.setAttribute("data-default-theme", defaultTheme);
+ }
+
+ // Attempt to retrieve the current theme from the browser's local storage.
+ const storedTheme = localStorage.getItem("theme");
+
+ if (storedTheme && storedTheme !== "system") {
+ document.documentElement.setAttribute("data-theme", storedTheme);
+ } else if (defaultTheme && storedTheme !== "system") {
+ document.documentElement.setAttribute("data-theme", defaultTheme);
+ } else {
+ // If no theme is found in local storage and no default theme is set, hand over control to the CSS.
+ document.documentElement.removeAttribute("data-theme");
+ }
+
+ // Expose defaultTheme to the outer scope.
+ window.defaultTheme = defaultTheme;
+})();
+
+// Icon Update and Theme Switching
+function setTheme(theme, saveToLocalStorage = false) {
+ if (theme === "system") {
+ document.documentElement.removeAttribute("data-theme");
+ } else {
+ document.documentElement.setAttribute("data-theme", theme);
+ }
+
+ if (saveToLocalStorage) {
+ localStorage.setItem("theme", theme);
+ } else {
+ localStorage.removeItem("theme");
+ }
+
+ // Update icon class based on the selected theme.
+ updateIconClass(theme);
+
+ // Update the active button based on the selected theme.
+ updateActiveButton(theme);
+}
+
+function resetTheme() {
+ // Reset the theme to the default or system preference if no default is set.
+ setTheme(window.defaultTheme || "system");
+}
+
+function switchTheme(theme) {
+ if (theme === "system") {
+ resetTheme();
+ } else {
+ setTheme(theme, true);
+ }
+}
+
+function updateIconClass(theme) {
+ const iconElement = document.querySelector("#theme-switcher summary .icon");
+
+ // Remove any existing theme classes
+ iconElement.classList.remove("light", "dark");
+
+ // Add the appropriate class based on the selected theme
+ if (theme === "light") {
+ iconElement.classList.add("light");
+ } else if (theme === "dark") {
+ iconElement.classList.add("dark");
+ }
+}
+
+function updateActiveButton(theme) {
+ // Remove .active class from all buttons
+ document.querySelectorAll('#theme-switcher button').forEach(button => {
+ button.classList.remove('active');
+ });
+
+ // Add .active class to the button corresponding to the current theme
+ const activeButton = document.querySelector(`#theme-${theme}`);
+ if (activeButton) {
+ activeButton.classList.add('active');
+ }
+}
+
+document.getElementById("theme-light").addEventListener("click", function () {
+ switchTheme("light");
+});
+document.getElementById("theme-dark").addEventListener("click", function () {
+ switchTheme("dark");
+});
+document.getElementById("theme-system").addEventListener("click", function () {
+ switchTheme("system");
+});
+
+// Update icon class on page load based on current theme
+const currentTheme = localStorage.getItem("theme") || window.defaultTheme || "system";
+updateIconClass(currentTheme);
+updateActiveButton(currentTheme);
+
+// Make the switchTheme function accessible globally
+window.switchTheme = switchTheme;
diff --git a/static/css/gallery.css b/static/css/gallery.css
index 12ceeabd..b581b5b0 100644
--- a/static/css/gallery.css
+++ b/static/css/gallery.css
@@ -1,22 +1,48 @@
+#image-gallery {
+ margin: 2rem 0;
+}
+
.gallery {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
- gap: 1rem;
+ column-count: 3;
+ column-gap: 1rem;
}
-.gallery a {
- display: block;
+.gallery-item {
+ break-inside: avoid;
+ margin-bottom: 1rem;
+ text-align: center;
+ list-style: none; /* ← important! */
}
-.gallery img {
+
+.gallery-item img {
width: 100%;
height: auto;
- border-radius: 8px;
+ border-radius: 12px;
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
+ transition: transform 0.2s ease;
+}
+
+.gallery-item img:hover {
+ transform: scale(1.6);
}
.caption {
- text-align: center;
font-size: 0.9rem;
- color: #666;
- margin-top: 0.25rem;
+ margin-top: 0.5rem;
+ margin-bottom: 0; /* ← just in case */
+ color: var(--fg-color);
+ list-style: none; /* ← extra-safe */
+}
+
+@media (max-width: 768px) {
+ .gallery {
+ column-count: 2;
+ }
+}
+
+@media (max-width: 480px) {
+ .gallery {
+ column-count: 1;
+ }
}
diff --git a/static/css/skills.css b/static/css/skills.css
index 030cb0c3..97eee96f 100644
--- a/static/css/skills.css
+++ b/static/css/skills.css
@@ -1,39 +1,72 @@
-.skills {
+/* Basic Layout for Skills List */
+#skills-content {
+ margin: 2rem 0;
+}
+
+#skills-content .category {
margin-bottom: 3rem;
}
-.skills-title {
- font-size: 2rem;
- font-weight: 700;
- margin-bottom: 1.5rem;
+#skills-content .category h3 {
+ font-size: 1.5rem;
+ font-weight: regular;
+ margin-bottom: 1rem;
}
-.skills-subtitle {
- font-size: 1.25rem;
- font-weight: 600;
- color: #444;
- margin-top: 2rem;
- margin-bottom: 0.5rem;
-}
-
-.skills-list {
+/* Skills container for single-line display */
+#skills-content .skills-list {
list-style: none;
padding: 0;
margin: 0;
- display: flex;
- flex-wrap: wrap;
- gap: 0.75rem 1.5rem;
+ display: flex; /* Use flexbox for single-line display */
+ flex-wrap: wrap; /* Allow skills to wrap if needed */
+ gap: 1rem; /* Spacing between skills */
}
-.skills-item {
- display: inline-flex;
+/* Skill List Item */
+#skills-content .skills-list .skill {
+ display: inline-flex; /* Ensures each skill is aligned inline */
align-items: center;
- font-size: 1rem;
- color: #666;
+ position: relative;
+ cursor: pointer; /* Show pointer cursor on hover */
+ text-decoration: none; /* Remove underline from links */
+ color: inherit; /* Inherit color from parent */
+ transition: background-color 0.3s, color 0.3s;
}
-.skills-item i {
- margin-right: 0.3rem;
- font-size: 1rem;
- opacity: 0.7;
+
+/* Skill Name */
+#skills-content .skills-list .skill span {
+ display: inline-block;
+ font-size: 1.2rem;
+ margin-left: 0.5rem;
+ line-height: 1.4;
+}
+
+/* Skill Icon */
+#skills-content .skills-list .skill .skill-icon {
+ margin-right: 0.5rem;
+ color: var(--accent-color);
+ font-size: 1.4rem;
+ vertical-align: middle;
+}
+
+/* Hover Effects for Skills */
+#skills-content .skills-list .skill:hover::before {
+ background: var(--accent-color-dark);
+}
+
+#skills-content .skills-list .skill:hover {
+ background-color: var(--accent-color-alpha);
+ color: var(--fg-color); /* Change text color on hover */
+}
+
+/* Skill Category Hover Effect */
+#skills-content .skills-list .skill:hover span {
+ color: var(--fg-color);
+}
+
+/* Optional: Customize Icon Color on Hover */
+#skills-content .skills-list .skill:hover .skill-icon {
+ color: var(--fg-color);
}
diff --git a/static/processed_images/beer_tap.b5ed59baacade122.jpg b/static/processed_images/beer_tap.b5ed59baacade122.jpg
new file mode 100644
index 00000000..8545d8c8
Binary files /dev/null and b/static/processed_images/beer_tap.b5ed59baacade122.jpg differ
diff --git a/static/processed_images/beer_tap.d2530d5b25b32124.webp b/static/processed_images/beer_tap.d2530d5b25b32124.webp
new file mode 100644
index 00000000..6027c6a6
Binary files /dev/null and b/static/processed_images/beer_tap.d2530d5b25b32124.webp differ
diff --git a/static/processed_images/sample_lr.2b064f7d7f2f54b3.png b/static/processed_images/sample_lr.2b064f7d7f2f54b3.png
new file mode 100644
index 00000000..02289afc
Binary files /dev/null and b/static/processed_images/sample_lr.2b064f7d7f2f54b3.png differ
diff --git a/static/processed_images/sample_lr.dbe53f15081c455a.webp b/static/processed_images/sample_lr.dbe53f15081c455a.webp
new file mode 100644
index 00000000..f87ddef1
Binary files /dev/null and b/static/processed_images/sample_lr.dbe53f15081c455a.webp differ
diff --git a/templates/partials/footer.html b/templates/partials/footer.html
new file mode 100644
index 00000000..2a603442
--- /dev/null
+++ b/templates/partials/footer.html
@@ -0,0 +1,70 @@
+{%- set rel_attributes = macros_rel_attributes::rel_attributes() | trim -%}
+
+
diff --git a/templates/shortcodes/gallery.html b/templates/shortcodes/gallery.html
index 888bc9b5..b0fc7bb5 100644
--- a/templates/shortcodes/gallery.html
+++ b/templates/shortcodes/gallery.html
@@ -4,7 +4,9 @@
{% for item in gallery_data %}
-
-
+
+
+
{% if item.title %}
{{ item.title }}
{% endif %}
diff --git a/templates/shortcodes/skills.html b/templates/shortcodes/skills.html
index 46ded3e1..b3174fdf 100644
--- a/templates/shortcodes/skills.html
+++ b/templates/shortcodes/skills.html
@@ -1,24 +1,22 @@
-{% macro display() %}
-{% set data = load_data(path="data/skills.json") %}
-
-
- Skills
-
- {% for group in data %}
-
-
{{ group.grouping }}
+{% set skills = load_data(literal = body, format="json") %}
+
+ {% for category in skills %}
+
+
{{ category.name | markdown | safe }}
- {% for skill in group.skills %}
- -
- {% if "icon" in skill %}
-
- {% endif %}
- {{ skill.name }}
-
+ {% for skill in category.skills %}
+ -
+ {% if skill.icon %}
+
+ {% endif %}
+ {% if skill.link %}
+ {{ skill.name }}
+ {% else %}
+ {{ skill.name }}
+ {% endif %}
+
{% endfor %}
{% endfor %}
-
-
-{% endmacro %}
+