From 523e1f0bb4ab16b5826f3a10a3c5a533ecd8bbbb Mon Sep 17 00:00:00 2001
From: dragonwocky <thedragonring.bod@gmail.com>
Date: Mon, 9 Jan 2023 13:35:35 +1100
Subject: [PATCH] refactor(theme): pass style overrides and css variables
 through generator

---
 scripts/generate-theme-css.mjs | 1150 +++++++++++---------------------
 1 file changed, 391 insertions(+), 759 deletions(-)

diff --git a/scripts/generate-theme-css.mjs b/scripts/generate-theme-css.mjs
index 844e75d..776029b 100644
--- a/scripts/generate-theme-css.mjs
+++ b/scripts/generate-theme-css.mjs
@@ -1,791 +1,423 @@
 /**
  * notion-enhancer
- * (c) 2022 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
+ * (c) 2023 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
  * (https://notion-enhancer.github.io/) under the MIT license
  */
 
 // paste this in the devtools console at to generate theme css
-// at https://www.notion.so/9390e51f458940a5a339dc4b8fdea2fb
+// at https://www.notion.so/9390e51f458940a5a339dc4b8fdea2fb.
+// to detect fonts, open the ... menu before running.
 
-// the variables at the top of the file should be placed in core/variables.css
-// as a reference for theme developers, but not loaded into notion.
+// repeat for both light and dark modes, pass the css through
+// https://css-minifier.com/ and https://css.github.io/csso/csso.html
+// and then save it to core/variables.css and core/theme.css
 
-// the css body below should be passed through https://css-minifier.com/ and
-// https://css.github.io/csso/csso.html, then saved to core/theme.css.
-// repeat this process for both light and dark modes.
-
-// not yet themed: notion's new svg icons
-
-// future application once cleaned up and improved:
-// generate theme at runtime rather than manually building styles
+// todo: svg page & property icons
 
 const darkMode = document.body.classList.contains("dark"),
-  modeSelector = darkMode ? ".dark" : ":not(.dark)";
+  modeSelector = darkMode ? ".dark" : ":not(.dark)",
+  bodySelector = `.notion-body${modeSelector}`;
 let cssRoot = "",
   cssBody = "";
 
 const getComputedPropertyValue = (el, prop) => {
-  const styles = window.getComputedStyle(el),
-    value = styles.getPropertyValue(prop);
-  return value;
-};
+    const styles = window.getComputedStyle(el),
+      value = styles.getPropertyValue(prop);
+    return value;
+  },
+  cssVariable = ({ name, value, alias, splitValues = false }) => {
+    const values = splitValues ? value.split(", ") : [value];
+    if (!cssRoot.includes(`--theme--${name}:`)) {
+      cssRoot += `--theme--${name}:${
+        alias ? `var(--theme--${alias})` : value
+      };`;
+    }
+    return {
+      name,
+      value,
+      ref: `var(--theme--${name},${values[0]})${
+        values.length > 1 ? ", " : ""
+      }${values.slice(1).join(", ")} !important`,
+    };
+  },
+  overrideStyle = ({
+    element,
+    selector = "",
+    property,
+    variable,
+    variableAliases = {},
+    valueAliases = [],
+    specificity = ["mode", "value"],
+    cssProps = {},
+    postProcessor = (selector, cssProps) => [selector, cssProps],
+  }) => {
+    if (selector) element ??= document.querySelector(selector);
+    const style = element?.getAttribute("style") ?? "",
+      pattern = String.raw`(?:^|(?:;\s*))${property}:\s*([^;]+);?`,
+      match = style.match(new RegExp(pattern));
+    if (typeof variable === "string") {
+      const value =
+        match?.[1] ??
+        (element ? getComputedPropertyValue(element, property) : "");
+      if (!value) throw new Error(`${property} not found for ${selector}`);
+      variable = cssVariable({
+        name: variable,
+        value: value,
+        alias: variableAliases[value],
+        splitValues: property === "font-family",
+      });
+    }
+    if (specificity.includes("mode")) selector = `${bodySelector} ${selector}`;
+    if (specificity.includes("value")) {
+      if (selector.includes(",")) selector = `:is(${selector})`;
+      if (match?.[0]) selector += `[style*="${match[0].replace(/"/g, `\\"`)}"]`;
+      else {
+        const propSelector = [variable.value, ...valueAliases]
+          .map((value) =>
+            property === "color"
+              ? `[style^="color: ${value}"],
+                 [style^="color:${value}"],
+                 [style*=";color: ${value}"],
+                 [style*=";color:${value}"],
+                 [style*=" color: ${value}"],
+                 [style*=" color:${value}"]`
+              : property === "background"
+              ? `[style*="background: ${value}"],
+                 [style*="background:${value}"]
+                 [style*="background-color: ${value}"],
+                 [style*="background-color:${value}"]`
+              : `[style*="${property}: ${value}"],
+                 [style*="${property}:${value}"]`
+          )
+          .join(",");
+        selector += selector ? `:is(${propSelector})` : propSelector;
+      }
+    }
+    cssProps[property] = variable;
+    [selector, cssProps] = postProcessor(selector, cssProps);
+    cssBody += `${selector}{${Object.entries(cssProps)
+      .map(([prop, val]) => `${prop}:${val?.ref ?? val}`)
+      .join(";")}}`;
+    variableAliases[variable.value] ??= variable.name;
+  };
 
-const generateFontStyles = () => {
-  const fontSans = `ui-sans-serif, -apple-system, BlinkMacSystemFont,
-      "Segoe UI", Helvetica, "Apple Color Emoji", Arial,
-      sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"`,
-    fontSerif = `Lyon-Text, Georgia, YuMincho, "Yu Mincho",
-      "Hiragino Mincho ProN", "Hiragino Mincho Pro", "Songti TC",
-      "Songti SC", SimSun, "Nanum Myeongjo", NanumMyeongjo, Batang, serif`,
-    fontMono = `iawriter-mono, Nitti, Menlo, Courier, monospace`,
-    fontCode = `SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace`;
-  cssRoot += `
-    --theme--font-sans: ${fontSans};
-    --theme--font-serif: ${fontSerif};
-    --theme--font-mono: ${fontMono};
-    --theme--font-code: ${fontCode};`;
-  cssBody += `
-    [style*='Segoe UI'] {
-      font-family: var(--theme--font-sans, ${
-        fontSans.split(",")[0]
-      }), ${fontSans} !important;
-    }
-    [style*='Georgia'] {
-      font-family: var(--theme--font-serif, ${
-        fontSerif.split(",")[0]
-      }), ${fontSerif} !important;
-    }
-    [style*='iawriter-mono'] {
-      font-family: var(--theme--font-mono, ${
-        fontMono.split(",")[0]
-      }), ${fontMono} !important;
-    }
-    [style*='SFMono-Regular'] {
-      font-family: var(--theme--font-code, ${
-        fontCode.split(",")[0]
-      }), ${fontCode} !important;
-    }
-  `;
-};
-generateFontStyles();
+const styleFonts = () => {
+    overrideStyle({
+      selector: "[style*='Segoe UI']",
+      property: "font-family",
+      variable: "font-sans",
+      specificity: [],
+    });
+    overrideStyle({
+      selector: "[style*='Georgia']",
+      property: "font-family",
+      variable: "font-serif",
+      specificity: [],
+    });
+    overrideStyle({
+      selector: "[style*='iawriter-mono']",
+      property: "font-family",
+      variable: "font-mono",
+      specificity: [],
+    });
+    overrideStyle({
+      selector: "[style*='SFMono-Regular']",
+      property: "font-family",
+      variable: "font-code",
+      specificity: [],
+    });
+  },
+  styleAccents = () => {
+    const primary = cssVariable({
+        name: "accent-primary",
+        value: "rgb(35, 131, 226)",
+      }),
+      primaryHover = cssVariable({
+        name: "accent-primary_hover",
+        value: "rgb(0, 117, 211)",
+      }),
+      primaryContrast = cssVariable({
+        name: "accent-primary_contrast",
+        value: "rgb(255, 255, 255)",
+      }),
+      primaryTransparent = cssVariable({
+        name: "accent-primary_transparent",
+        value: "rgba(35, 131, 226, 0.14)",
+      });
+    overrideStyle({
+      property: "color",
+      variable: primary,
+      specificity: ["value"],
+    });
+    overrideStyle({
+      property: "fill",
+      variable: primary,
+      specificity: ["value"],
+    });
+    overrideStyle({
+      property: "background",
+      variable: primary,
+      specificity: ["value"],
+      cssProps: {
+        fill: primaryContrast,
+        color: primaryContrast,
+      },
+    });
+    overrideStyle({
+      property: "background",
+      variable: primaryHover,
+      specificity: ["value"],
+      cssProps: {
+        fill: primaryContrast,
+        color: primaryContrast,
+      },
+    });
+    overrideStyle({
+      selector: `.notion-table-selection-overlay [style*="border: 2px solid"]`,
+      property: "border-color",
+      variable: primary,
+      specificity: [],
+    });
+    overrideStyle({
+      selector: `
+        [style*="background: ${primary.value}"] svg[style*="fill"],
+        [style*="background-color: ${primary.value}"]  svg[style*="fill"]
+      `,
+      property: "fill",
+      variable: primaryContrast,
+      specificity: [],
+    });
+    overrideStyle({
+      selector: `[style*="border-radius: 44px;"] > [style*="border-radius: 44px; background: white;"]`,
+      property: "background",
+      variable: primaryContrast,
+      specificity: [],
+    });
+    overrideStyle({
+      selector: `
+        *::selection,
+        .notion-selectable-halo,
+        #notion-app .rdp-day:not(.rdp-day_disabled):not(.rdp-day_selected
+        ):not(.rdp-day_value):not(.rdp-day_start):not(.rdp-day_end):hover,
+        [style*="background: ${primaryTransparent.value.split(".")[0]}."],
+        [style*="background:${primaryTransparent.value.split(".")[0]}."],
+        [style*="background-color: ${primaryTransparent.value.split(".")[0]}."],
+        [style*="background-color:${primaryTransparent.value.split(".")[0]}."]
+      `,
+      property: "background",
+      variable: primaryTransparent,
+      specificity: [],
+    });
 
-const generateForegroundStyles = () => {
-  const rgbPrimary = darkMode ? "rgb(255, 255, 255)" : "rgb(55, 53, 47)",
-    defaultPrimary = darkMode ? "rgba(255, 255, 255, 0.81)" : "rgb(55, 53, 47)",
-    defaultSecondary = darkMode
-      ? "rgb(155, 155, 155)"
-      : "rgba(25, 23, 17, 0.6)",
-    fgPrimary = new Set([
-      rgbPrimary,
-      darkMode ? "rgb(211, 211, 211)" : "rgba(255, 255, 255, 0.9)",
-    ]),
-    fgSecondary = new Set([
-      defaultSecondary,
-      darkMode ? "rgb(127, 127, 127)" : "rgba(206, 205, 202, 0.6)",
-    ]);
-  for (const el of document.querySelectorAll(
-    '[style^="color"], [style*=" color"], [style*=";color"], [style*="fill"]'
-  )) {
-    const colorVal =
-        el
-          .getAttribute("style")
-          .match(/(?:^|(?:;\s*))color:\s*([^;]+);?/)?.[1] ??
-        getComputedPropertyValue(el, "color"),
-      fillVal =
-        el
-          .getAttribute("style")
-          .match(/(?:^|(?:;\s*))fill:\s*([^;]+);?/)?.[1] ??
-        getComputedPropertyValue(el, "fill");
-    if (colorVal.startsWith(`rgba(${rgbPrimary.slice(4, -1)}`)) {
-      const alpha = +colorVal.slice(5, -1).split(", ")[3];
-      if (alpha > 0.8) {
-        fgPrimary.add(colorVal);
-      } else fgSecondary.add(colorVal);
-    }
-    if (fillVal.startsWith(`rgba(${rgbPrimary.slice(4, -1)}`)) {
-      const alpha = +fillVal.slice(5, -1).split(", ")[3];
-      if (alpha > 0.8) {
-        fgPrimary.add(fillVal);
-      } else fgSecondary.add(fillVal);
-    }
-    if (
-      // light mode tags have coloured text,
-      // replace with primary text for consistency
-      !darkMode &&
-      el.matches(
-        `[style*="height: 20px; border-radius: 3px; padding-left: 6px;"][style*="background:"],
-        .notion-collection_view-block [style*="height: 14px; border-radius: 3px; padding-left: 6px;"],
-        .notion-timeline-item-properties [style*="height: 18px; border-radius: 3px; padding-left: 8px;"]`
-      )
-    ) {
-      fgPrimary.add(colorVal);
-    }
-  }
-  cssRoot += `
-    --theme--fg-primary: ${defaultPrimary};
-    --theme--fg-secondary: ${defaultSecondary};
-  `;
-  const mapFgToSelectors = (colorVal) =>
-    `.notion-body${modeSelector} [style^="color:${colorVal}"],
-    .notion-body${modeSelector} [style^="color: ${colorVal}"],
-    .notion-body${modeSelector} [style*=" color:${colorVal}"],
-    .notion-body${modeSelector} [style*=" color: ${colorVal}"],
-    .notion-body${modeSelector} [style*=";color:${colorVal}"],
-    .notion-body${modeSelector} [style*=";color: ${colorVal}"],
-    .notion-body${modeSelector} [style*="fill:${colorVal}"],
-    .notion-body${modeSelector} [style*="fill: ${colorVal}"]`;
-  cssBody += `
-    ${[...fgPrimary].map(mapFgToSelectors).join(", ")} {
-      color: var(--theme--fg-primary, ${defaultPrimary}) !important;
-      caret-color: var(--theme--fg-primary, ${defaultPrimary}) !important;
-      text-decoration-color: currentColor !important;
-      fill: var(--theme--fg-primary, ${defaultPrimary}) !important;
-    }
-    .notion-body${modeSelector} .rdp-nav_icon,
-    .notion-body${modeSelector} .rdp-head_cell,
-    .notion-body${modeSelector} .rdp-day.rdp-day_outside,
-    .notion-body${modeSelector} ::placeholder,
-    ${[...fgSecondary].map(mapFgToSelectors).join(", ")} {
-      color: var(--theme--fg-secondary, ${defaultSecondary}) !important; 
-      caret-color: var(--theme--fg-secondary, ${defaultSecondary}) !important;
-      text-decoration-color: currentColor !important;
-      fill: var(--theme--fg-secondary, ${defaultSecondary}) !important; 
-    }
-    ${[...fgPrimary]
-      .map(
-        (colorVal) =>
-          `.notion-body${modeSelector} :is(
-          [style*="caret-color:${colorVal}"], [style*="caret-color: ${colorVal}"])`
-      )
-      .join(", ")} {
-      caret-color: var(--theme--fg-primary, ${defaultPrimary}) !important;
-    }
-    .notion-body${modeSelector} ::placeholder,
-    ${[...fgSecondary]
-      .map(
-        (colorVal) =>
-          `.notion-body${modeSelector} :is(
-          [style*="caret-color:${colorVal}"], [style*="caret-color: ${colorVal}"])`
-      )
-      .join(", ")} {
-      caret-color: var(--theme--fg-secondary, ${defaultSecondary}) !important;
-    }
-    .notion-body${modeSelector} [style*="-webkit-text-fill-color:"] {
-      -webkit-text-fill-color: var(--theme--fg-secondary, ${defaultSecondary}) !important;
-    }
-  `;
+    const secondary = cssVariable({
+        name: "accent-secondary",
+        value: "rgb(235, 87, 87)",
+      }),
+      secondaryAliases = [
+        "rgb(180, 65, 60)",
+        "rgb(211, 79, 67)",
+        "rgb(205, 73, 69)",
+      ],
+      secondaryContrast = cssVariable({
+        name: "accent-secondary_contrast",
+        value: "white",
+      }),
+      secondaryTransparent = cssVariable({
+        name: "accent-secondary_transparent",
+        value: "rgba(235, 87, 87, 0.1)",
+      });
+    overrideStyle({
+      property: "color",
+      variable: secondary,
+      valueAliases: secondaryAliases,
+      specificity: ["value"],
+    });
+    overrideStyle({
+      property: "fill",
+      variable: secondary,
+      valueAliases: secondaryAliases,
+      specificity: ["value"],
+    });
+    overrideStyle({
+      property: "background",
+      variable: secondary,
+      valueAliases: secondaryAliases,
+      specificity: ["value"],
+      cssProps: {
+        fill: secondaryContrast,
+        color: secondaryContrast,
+      },
+      postProcessor: (selector, cssProps) => [
+        `#notion-app .rdp-day_today:not(.rdp-day_selected):not(.rdp-day_value
+         ):not(.rdp-day_start):not(.rdp-day_end)::after, ${selector}`,
+        cssProps,
+      ],
+    });
+    overrideStyle({
+      property: "background",
+      variable: secondary,
+      valueAliases: secondaryAliases,
+      specificity: ["value"],
+      cssProps: {
+        fill: secondaryContrast,
+        color: secondaryContrast,
+      },
+      postProcessor: (selector, cssProps) => {
+        delete cssProps["background"];
+        return [
+          `#notion-app .rdp-day_today:not(.rdp-day_selected):not(.rdp-day_value):not(.rdp-day_start
+          ):not(.rdp-day_end), :is(${selector}) + :is([style*="fill: ${secondaryContrast.value};"],
+          [style*="color: ${secondaryContrast.value};"]), :is(${selector})
+          :is([style*="fill: ${secondaryContrast.value};"], [style*="color: ${secondaryContrast.value};"])`,
+          cssProps,
+        ];
+      },
+    });
+    overrideStyle({
+      property: "background",
+      variable: secondaryTransparent,
+      specificity: ["value"],
+    });
 
-  // borders
-  const defaultBorder = darkMode ? "rgb(47, 47, 47)" : "rgb(233, 233, 231)",
-    possibleBorders = darkMode
-      ? [defaultBorder.slice(4, -1), "255, 255, 255"]
-      : [defaultBorder.slice(4, -1), "55, 53, 47"],
-    borderColors = new Set([
-      darkMode ? "rgb(37, 37, 37)" : "rgb(238, 238, 237)",
-    ]),
-    boxShadows = new Set(
-      darkMode
-        ? [
-            "; box-shadow: rgba(255, 255, 255, 0.094) 0px -1px 0px;",
-            "; box-shadow: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px inset;",
-            "; box-shadow: rgb(25, 25, 25) -3px 0px 0px, rgb(47, 47, 47) 0px 1px 0px;",
-          ]
-        : [
-            "; box-shadow: rgba(55, 53, 47, 0.09) 0px -1px 0px;",
-            "; box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px inset;",
-            "; box-shadow: white -3px 0px 0px, rgb(233, 233, 231) 0px 1px 0px;",
-          ]
-    );
-  for (const el of document.querySelectorAll(
-    `[style*="border:"], [style*="border-right:"], [style*="border-left:"],
-    [style*="border-top:"], [style*="border-bottom:"], [style*="box-shadow:"]`
-  )) {
-    const borderColor = el
-      .getAttribute("style")
-      .match(/(?:^|(?:;\s*))border(?:-\w+)?:\s*([^;]+);?/)?.[1];
-    if (
-      borderColor &&
-      possibleBorders.some((border) => borderColor.includes(border))
-    ) {
-      borderColors.add(borderColor);
+    // box-shadows are complicated, style manually
+    cssBody += `.notion-focusable-within:focus-within {
+      box-shadow:
+        var(--theme--accent-primary, ${primary.value}) 0px 0px 0px 1px inset,
+        var(--theme--accent-primary, ${primary.value}) 0px 0px 0px 2px
+      !important;
     }
-    const boxShadowStyle = el
-      .getAttribute("style")
-      .match(/(?:^|(?:;\s*))box-shadow:\s*([^;]+);?/)?.[0];
-    if (
-      boxShadowStyle &&
-      possibleBorders.some((border) => boxShadowStyle.includes(border))
-    ) {
-      boxShadows.add(boxShadowStyle);
+    .notion-focusable:focus-visible {
+      box-shadow:
+        var(--theme--accent-primary, ${primary.value}) 0px 0px 0px 1px inset,
+        var(--theme--accent-primary, ${primary.value}) 0px 0px 0px 2px
+      !important;
     }
-  }
-  cssRoot += `--theme--fg-border: ${defaultBorder};`;
-  cssBody += `
-    .notion-body${modeSelector} ${[...borderColors]
-    .map(
-      (border) =>
-        `[style*="${border}"]:is([style*="border:"],
-        [style*="border-top:"], [style*="border-left:"],
-        [style*="border-bottom:"], [style*="border-right:"])`
-    )
-    .join(", ")} {
-      border-color: var(--theme--fg-border, ${defaultBorder}) !important;
-    }
-    ${[...boxShadows]
-      .map(
-        (shadow, i) =>
-          `.notion-body${modeSelector} [style*="${shadow}"] {
-            ${shadow
-              .replace(
-                /rgba?\([^\)]+\)/g,
-                i === 2
-                  ? "transparent"
-                  : `var(--theme--fg-border, ${defaultBorder})`
-              )
-              .slice(0, -1)} !important;
-      }`
-      )
+    ${["box-shadow: rgb(35, 131, 226) 0px 0px 0px 2px inset"]
+      .map((shadow) => {
+        return `[style*="${shadow}"] { ${shadow.replace(
+          /rgba?\([^\)]+\)/g,
+          `var(--theme--accent-primary, ${primary})`
+        )} !important; }`;
+      })
       .join("")}
-    .notion-body${modeSelector} [style*="height: 1px;"][style*="background"] {
-      background: var(--theme--fg-border, ${defaultBorder}) !important;
-    }
-  `;
-
-  const refs = {};
-  // inline text color
-  for (const el of document.querySelectorAll(
-    '.notion-selectable .notion-enable-hover[style*="color:"][style*="fill:"]'
-  )) {
-    if (!el.innerText || el.innerText.includes(" ")) continue;
-    if (el.getAttribute("style").includes("mono")) continue;
-    const cssVar = `--theme--fg-${el.innerText}`,
-      colorVal = getComputedPropertyValue(el, "color"),
-      styleAttr = el
-        .getAttribute("style")
-        .match(/(?:^|(?:;\s*))color:\s*([^;]+);?/)[1];
-    cssRoot += `${cssVar}: ${colorVal};`;
-    refs[`${cssVar}, ${colorVal}`] ??= [];
-    refs[`${cssVar}, ${colorVal}`].push(
-      `.notion-body${modeSelector} .notion-enable-hover[style*="${styleAttr}"],
-      .notion-body${modeSelector} .notion-code-block span.token[style*="${styleAttr}"]`
-    );
-  }
-  // block text color
-  const targetSelector =
-    '.notion-text-block > [style*="color:"][style*="fill:"]';
-  for (const el of document.querySelectorAll(targetSelector)) {
-    if (!el.innerText || el.innerText.includes(" ")) continue;
-    const cssVar = `--theme--fg-${el.innerText}`,
-      colorVal = getComputedPropertyValue(el, "color"),
-      styleAttr = el
-        .getAttribute("style")
-        .match(/(?:^|(?:;\s*))color:\s*([^;]+);?/)[1];
-    refs[`${cssVar}, ${colorVal}`] ??= [];
-    refs[`${cssVar}, ${colorVal}`].push(
-      `.notion-body${modeSelector} ${targetSelector}[style*="${styleAttr}"]`
-    );
-  }
-  // board text
-  for (const group of document.querySelectorAll(
-    ".notion-board-view .notion-board-group"
-  )) {
-    // get color name from card
-    const card = group.querySelector('a[style*="background"]'),
-      innerText = card.innerText.replace("Drag image to reposition\n", "");
-    if (!innerText || innerText.includes(" ")) continue;
-    const el = group.querySelector('[style*="height: 32px"]'),
-      colorVal = getComputedPropertyValue(el, "color"),
-      cssVar = `--theme--fg-${
-        // --fg-light_gray doesn't exist
-        innerText === "light_gray" ? "secondary" : innerText
-      }`,
-      styleAttr = group
-        .getAttribute("style")
-        .match(/background(?:-color)?:\s*([^;]+);?/)[1];
-    refs[`${cssVar}, ${colorVal}`] ??= [];
-    refs[`${cssVar}, ${colorVal}`].push(
-      `.notion-body${modeSelector} .notion-board-view :is(
-          .notion-board-group[style*="${styleAttr}"] [style*="height: 32px"],
-          [style*="${styleAttr}"] > [style*="color"]:nth-child(2),
-          [style*="${styleAttr}"] > div > svg
-        )`
-    );
-  }
-  for (const varRef in refs) {
-    cssBody += `${refs[varRef].join(",")} {
-        color: var(${varRef}) !important;
-        fill: var(${varRef}) !important;
-      }`;
-  }
-};
-generateForegroundStyles();
-
-const generateBackgroundStyles = () => {
-  const defaultPrimary = darkMode ? "rgb(25, 25, 25)" : "rgb(255, 255, 255)",
-    defaultSecondary = darkMode ? "rgb(32, 32, 32)" : "rgb(251, 251, 250)",
-    bgPrimary = new Set([
-      defaultPrimary,
-      ...(darkMode
-        ? ["rgb(37, 37, 37)", "rgba(255, 255, 255, 0.13)"]
-        : ["white", "rgb(247, 247, 247)"]),
-    ]),
-    bgSecondary = new Set([
-      defaultSecondary,
-      ...(darkMode
-        ? ["rgba(255, 255, 255, 0.0", "rgb(47, 47, 47)"]
-        : ["rgb(253, 253, 253)", "rgb(15, 15, 15)"]),
-    ]),
-    bgOverlay = darkMode ? "rgba(15, 15, 15, 0.8)" : "rgba(15, 15, 15, 0.6)";
-  for (const el of document.querySelectorAll(
-    '[style*="background:"], [style*="background-color:"]'
-  )) {
-    const colorVal = el
-      .getAttribute("style")
-      .match(/background(?:-color)?:\s*([^;]+);?/)?.[1];
-    if (colorVal.startsWith(`rgba(${defaultPrimary.slice(4, -1)}`)) {
-      const alpha = +colorVal.slice(5, -1).split(", ")[3];
-      if (alpha > 0.8) {
-        bgPrimary.add(colorVal);
-      } else bgSecondary.add(colorVal);
-    }
-  }
-  cssRoot += `
-    --theme--bg-primary: ${defaultPrimary};
-    --theme--bg-secondary: ${defaultSecondary};
-    --theme--overlay-shadow: ${bgOverlay};
-  `;
-  const mapBgToSelectors = (colorVal) =>
-    `.notion-body${modeSelector} [style*="background:${colorVal}"],
-    .notion-body${modeSelector} [style*="background: ${colorVal}"],
-    .notion-body${modeSelector} [style*="background-color:${colorVal}"],
-    .notion-body${modeSelector} [style*="background-color: ${colorVal}"]`;
-  cssBody += `
-    ${[...bgPrimary].map(mapBgToSelectors).join(", ")} {
-      background: var(--theme--bg-primary, ${defaultPrimary}) !important;
-    }
-     .notion-body${modeSelector} .notion-focusable-within
-     [style*="background"]:not([style*="background: none"]),
-    ${[...bgSecondary].map(mapBgToSelectors).join(", ")} {
-      background: var(--theme--bg-secondary, ${defaultSecondary}) !important;
-    }
-    [style*="linear-gradient(to left, ${
-      defaultPrimary === "rgb(255, 255, 255)" ? "white" : defaultPrimary
-    } 20%, rgba(${defaultPrimary.slice(4, -1)}, 0) 100%)"] {
-      background-image: linear-gradient(to left,
-        var(--theme--bg-primary, ${defaultPrimary}) 20%, transparent 100%) !important;
-    }
-    [style*="linear-gradient(to right, ${
-      defaultPrimary === "rgb(255, 255, 255)" ? "white" : defaultPrimary
-    } 20%, rgba(${defaultPrimary.slice(4, -1)}, 0) 100%)"] {
-      background-image: linear-gradient(to right,
-        var(--theme--bg-primary, ${defaultPrimary}) 20%, transparent 100%) !important;
-    }
-    .notion-body${modeSelector} .notion-overlay-container
-    [data-overlay] > div > [style*="position: absolute"]:first-child {
-      background: var(--theme--overlay-shadow, ${bgOverlay}) !important;
-    }
-  `;
-
-  // hovered elements, inputs and unchecked toggle backgrounds
-  const bgHover = darkMode
-    ? ["rgba(255, 255, 255, 0.055)", "rgb(47, 47, 47)"]
-    : [
-        "rgba(55, 53, 47, 0.08)",
-        "rgba(242, 241, 238, 0.6)",
-        "rgb(225, 225, 225)",
-        "rgb(239, 239, 238)",
-      ];
-  cssRoot += `--theme--bg-hover: ${bgHover[0]};`;
-  cssBody += `${bgHover
-    .map(
-      (hover) => `.notion-body${modeSelector} :is(
-        [style*="background: ${hover}"], [style*="background-color: ${hover}"]
-      )${
-        hover === "rgb(47, 47, 47)"
-          ? '[style*="transition: background"]:hover'
-          : ""
-      }`
-    )
-    .join(", ")},
-    .notion-body${modeSelector} [style*="height: 14px; width: 26px; border-radius: 44px;"][style*="rgba"] {
-    background: var(--theme--bg-hover, ${bgHover[0]}) !important;
-  }`;
-
-  // get bg variable values from tags
-  for (const el of document.querySelectorAll(
-    '.notion-collection_view-block [style*="height: 20px; border-radius: 3px; padding-left: 6px;"]'
-  )) {
-    if (!el.innerText || el.innerText.includes(" ")) continue;
-    const cssVar = `--theme--bg-${el.innerText}`,
-      colorVal = getComputedPropertyValue(el, "background-color");
-    cssRoot += `${cssVar}: ${colorVal};`;
-  }
-  const refs = {};
-  for (const targetSelector of [
-    // inline highlight
-    '.notion-selectable .notion-enable-hover[style*="background:"]',
-    // block highlight
-    '.notion-text-block > [style*="background:"]',
-    // database tag
-    '[style*="height: 20px; border-radius: 3px; padding-left: 6px;"][style*="background:"]',
-    '.notion-collection_view-block [style*="height: 14px; border-radius: 3px; padding-left: 6px;"]',
-    '.notion-timeline-item-properties [style*="height: 18px; border-radius: 3px; padding-left: 8px;"]',
-  ]) {
-    for (const el of document.querySelectorAll(targetSelector)) {
-      if (!el.innerText || el.innerText.includes(" ")) continue;
-      const cssVar = `--theme--bg-${el.innerText}`,
-        colorVal = getComputedPropertyValue(el, "background-color"),
-        styleAttr = el
-          .getAttribute("style")
-          .match(/background(?:-color)?:\s*([^;]+);?/)[1];
-      refs[`${cssVar}, ${colorVal}`] ??= [];
-      refs[`${cssVar}, ${colorVal}`].push(
-        `.notion-body${modeSelector} ${targetSelector}[style*="${styleAttr}"]`
-      );
-    }
-  }
-  // board cards
-  for (const group of document.querySelectorAll(
-    ".notion-board-view .notion-board-group"
-  )) {
-    const page = group.querySelector('a[style*="background"]'),
-      innerText = page.innerText.replace("Drag image to reposition\n", "");
-    if (!innerText || innerText.includes(" ")) continue;
-    const pageVar = `--theme--bg-${innerText}`,
-      pageColor = getComputedPropertyValue(page, "background-color"),
-      groupVar = `--theme--dim-${innerText}`,
-      groupColor = group
-        .getAttribute("style")
-        .match(/background(?:-color)?:\s*([^;]+);?/)[1];
-    // get dim variable values
-    cssRoot += `${groupVar}: ${groupColor};`;
-    // in light mode pages in board views all have bg "white"
-    // by default, must be styled based on parent
-    refs[`${pageVar}, ${pageColor}`] ??= [];
-    refs[`${pageVar}, ${pageColor}`].push(
-      `.notion-body${modeSelector} .notion-board-view
-      .notion-board-group[style*="${groupColor}"] a[style*="background"]`
-    );
-    refs[`${groupVar}, ${groupColor}`] ??= [];
-    refs[`${groupVar}, ${groupColor}`].push(
-      `.notion-body${modeSelector} .notion-board-view
-      [style*="${groupColor}"]:is(.notion-board-group, [style*="border-top-left-radius: 5px;"])`
-    );
-  }
-  // use bg-yellow for notification highlights
-  refs[`--theme--bg-yellow, rgba(255, 212, 0, 0.14)`] ??= [];
-  refs[`--theme--bg-yellow, rgba(255, 212, 0, 0.14)`].push(
-    `.notion-body${modeSelector} [style*="background: rgba(255, 212, 0, 0.14)"]`
-  );
-  // use dim for callout blocks
-  for (const el of document.querySelectorAll(
-    '.notion-callout-block > div > [style*="background:"]'
-  )) {
-    if (!el.innerText || el.innerText.includes(" ")) continue;
-    const cssVar = `--theme--dim-${el.innerText}`,
-      colorVal = getComputedPropertyValue(el, "background-color"),
-      styleAttr = el
-        .getAttribute("style")
-        .match(/background(?:-color)?:\s*([^;]+);?/)[1];
-    refs[`${cssVar}, ${colorVal}`] ??= [];
-    refs[`${cssVar}, ${colorVal}`].push(
-      `.notion-body${modeSelector} .notion-callout-block > div
-        > [style*="background:"][style*="${styleAttr}"]`
-    );
-  }
-  // use light_gray for taglike elements e.g. file property values
-  const taglikeEl = document.querySelector(
-      '[style*="height: 18px; border-radius: 3px; background"]'
-    ),
-    taglikeBg = taglikeEl
-      .getAttribute("style")
-      .match(/background(?:-color)?:\s*([^;]+);?/)[1];
-  refs[`--theme--bg-light_gray, ${taglikeBg}`] ??= [];
-  refs[`--theme--bg-light_gray, ${taglikeBg}`].push(
-    `[style*="height: 18px; border-radius: 3px; background"][style*="${taglikeBg}"]`
-  );
-  // group selectors with same bg together
-  for (const varRef in refs) {
-    cssBody += `${refs[varRef].join(",")} {
-      background: var(${varRef}) !important;
-    }`;
-  }
-};
-generateBackgroundStyles();
-
-const generateAccentStyles = () => {
-  // accents are the same in both light and dark modes
-  // duplicate styles should be removed by csso
-  const accentPrimary = "rgb(35, 131, 226)",
-    accentPrimaryHover = "rgb(0, 117, 211)",
-    accentPrimaryContrast = "rgb(255, 255, 255)",
-    accentPrimaryTransparent = [
-      "rgba(35, 131, 226, 0.14)",
-      "rgba(35, 131, 226, 0.",
-    ],
-    accentPrimaryBoxShadows = [
-      "box-shadow: rgb(35, 131, 226) 0px 0px 0px 2px inset",
-    ],
-    accentSecondary = [
-      "rgb(235, 87, 87)",
-      "rgb(180, 65, 60)",
-      "rgb(211, 79, 67)",
-      "rgb(205, 73, 69)",
-    ],
-    accentSecondaryContrast = "rgb(255, 255, 255)",
-    accentSecondaryTransparent = "rgba(235, 87, 87, 0.1)",
-    accentSecondaryBorder = [
+    ${[
       "border: 1px solid rgb(110, 54, 48)",
       "border: 1px solid rgba(235, 87, 87, 0.5)",
       "border: 2px solid rgb(110, 54, 48)",
       "border: 2px solid rgb(227, 134, 118)",
       "border-right: 1px solid rgb(180, 65, 60)",
       "border-right: 1px solid rgb(211, 79, 67)",
-    ];
-  cssRoot += `--theme--accent-primary: ${accentPrimary};
-    --theme--accent-primary_hover: ${accentPrimaryHover};
-    --theme--accent-primary_contrast: ${accentPrimaryContrast};
-    --theme--accent-primary_transparent: ${accentPrimaryTransparent[0]};
-    --theme--accent-secondary: ${accentSecondary[0]};
-    --theme--accent-secondary_contrast: ${accentSecondaryContrast};
-    --theme--accent-secondary_transparent: ${accentSecondaryTransparent};`;
-  cssBody += `
-    [style*="color: ${accentPrimary}"],
-    [style*="fill: ${accentPrimary}"] {
-      color: var(--theme--accent-primary, ${accentPrimary}) !important;
-    }
-    [style*="background: ${accentPrimary}"],
-    [style*="background-color: ${accentPrimary}"] {
-      background: var(--theme--accent-primary, ${accentPrimary}) !important;
-      color: var(--theme--accent-primary_contrast, ${accentPrimaryContrast}) !important;
-      fill: var(--theme--accent-primary_contrast, ${accentPrimaryContrast}) !important;
-    }
-    [style*="background: ${accentPrimary}"] svg[style*="fill"],
-    [style*="background-color: ${accentPrimary}"]  svg[style*="fill"] {
-      fill: var(--theme--accent-primary_contrast, ${accentPrimaryContrast}) !important;
-    }
-    [style*="border-radius: 44px;"] > [style*="border-radius: 44px; background: white;"] {
-      background: var(--theme--accent-primary_contrast, ${accentPrimaryContrast}) !important;
-    }
-    [style*="background: ${accentPrimaryHover}"],
-    [style*="background-color: ${accentPrimaryHover}"] {
-      background: var(--theme--accent-primary_hover, ${accentPrimaryHover}) !important;
-      color: var(--theme--accent-primary_contrast, ${accentPrimaryContrast}) !important;
-      fill: var(--theme--accent-primary_contrast, ${accentPrimaryContrast}) !important;
-    }
-    .notion-table-selection-overlay [style*='border: 2px solid'] {
-      border-color: var(--theme--accent-primary, ${accentPrimary}) !important;
-    }
-    .notion-focusable-within:focus-within {
-      box-shadow: var(--theme--accent-primary, ${accentPrimary}) 0px 0px 0px 1px inset,
-        var(--theme--accent-primary, ${accentPrimary}) 0px 0px 0px 2px !important;
-    }
-    .notion-focusable:focus-visible {
-      box-shadow: var(--theme--accent-primary, ${accentPrimary}) 0px 0px 0px 1px inset,
-        var(--theme--accent-primary, ${accentPrimary}) 0px 0px 0px 2px !important;
-    }
-    ${[...accentPrimaryBoxShadows]
-      .map(
-        (shadow) =>
-          `[style*="${shadow}"] {
-            ${shadow.replace(
-              /rgba?\([^\)]+\)/g,
-              `var(--theme--accent-primary, ${accentPrimary})`
-            )} !important;
-      }`
-      )
-      .join("")}
-    *::selection,
-    .notion-selectable-halo,
-    #notion-app .rdp-day:not(.rdp-day_disabled):not(.rdp-day_selected):not(.rdp-day_value):not(.rdp-day_start):not(.rdp-day_end):hover,
-    [style*="background: ${accentPrimaryTransparent[1]}"],
-    [style*="background-color: ${accentPrimaryTransparent[1]}"] {
-      background: var(--theme--accent-primary_transparent, ${
-        accentPrimaryTransparent[0]
-      }) !important;
-    }
-    ${accentSecondary
-      .map(
-        (accent) =>
-          `[style*="color: ${accent}"],
-          [style*="fill: ${accent}"]`
-      )
-      .join(", ")} {
-      color: var(--theme--accent-secondary, ${accentSecondary[0]}) !important;
-      fill: var(--theme--accent-secondary, ${accentSecondary[0]}) !important;
-    }
-    #notion-app .rdp-day_today:not(.rdp-day_selected):not(.rdp-day_value):not(.rdp-day_start):not(.rdp-day_end)::after,
-    ${accentSecondary
-      .map(
-        (accent) =>
-          `[style*="background: ${accent}"],
-          [style*="background-color: ${accent}"]`
-      )
-      .join(", ")} {
-      background: var(--theme--accent-secondary, ${
-        accentSecondary[0]
-      }) !important;
-      color: var(--theme--accent-secondary_contrast, ${accentSecondaryContrast}) !important;
-      fill: var(--theme--accent-secondary_contrast, ${accentSecondaryContrast}) !important;
-    }
-    #notion-app .rdp-day_today:not(.rdp-day_selected):not(.rdp-day_value):not(.rdp-day_start):not(.rdp-day_end),
-    :is(${accentSecondary
-      .map(
-        (accent) =>
-          `[style*="background: ${accent}"],
-          [style*="background-color: ${accent}"]`
-      )
-      .join(", ")})
-    + :is([style*="fill: white;"], [style*="color: white;"]),
-    :is(${accentSecondary
-      .map(
-        (accent) =>
-          `[style*="background: ${accent}"],
-          [style*="background-color: ${accent}"]`
-      )
-      .join(", ")})
-    :is([style*="fill: white;"], [style*="color: white;"]) {
-      color: var(--theme--accent-secondary_contrast, ${accentSecondaryContrast}) !important;
-      fill: var(--theme--accent-secondary_contrast, ${accentSecondaryContrast}) !important;
-    }
-    [style*="background: ${accentSecondaryTransparent}"],
-    [style*="background-color: ${accentSecondaryTransparent}"] {
-      background: var(--theme--accent-secondary_transparent, ${accentSecondaryTransparent}) !important;
-    }
-    ${accentSecondaryBorder
+    ]
       .map((border) => `[style*="${border}"]`)
-      .join(", ")} {
-      border-color: var(--theme--accent-secondary, ${
-        accentSecondary[0]
-      }) !important;
-    }`;
-};
-generateAccentStyles();
+      .join(", ")} { border-color: var(--theme--accent-secondary,
+      ${secondary.value}) !important; }`;
+  },
+  styleScrollbars = () => {
+    overrideStyle({
+      selector: "::-webkit-scrollbar-track, ::-webkit-scrollbar-corner",
+      property: "background",
+      variable: cssVariable({
+        name: "scrollbar-track",
+        value: darkMode ? "rgba(202, 204, 206, 0.04)" : "#EDECE9",
+      }),
+    });
+    overrideStyle({
+      selector: "::-webkit-scrollbar-thumb",
+      property: "background",
+      variable: cssVariable({
+        name: "scrollbar-thumb",
+        value: darkMode ? "#474c50" : "#D3D1CB",
+      }),
+    });
+    overrideStyle({
+      selector: "::-webkit-scrollbar-thumb:hover",
+      property: "background",
+      variable: cssVariable({
+        name: "scrollbar-thumb_hover",
+        value: darkMode ? "rgba(202, 204, 206, 0.3)" : "#AEACA6",
+      }),
+    });
+  },
+  styleCode = () => {
+    overrideStyle({
+      selector: '.notion-text-block .notion-enable-hover[style*="mono"]',
+      property: "color",
+      variable: "code-inline_fg",
+    });
+    overrideStyle({
+      selector: '.notion-text-block .notion-enable-hover[style*="mono"]',
+      property: "background",
+      variable: "code-inline_bg",
+    });
 
-const generateScrollbarStyles = () => {
-  const scrollbarTrack = darkMode ? "rgba(202, 204, 206, 0.04)" : "#EDECE9",
-    scrollbarThumb = darkMode ? "#474c50" : "#D3D1CB",
-    scrollbarThumbHover = darkMode ? "rgba(202, 204, 206, 0.3)" : "#AEACA6";
-  cssRoot += `--theme--scrollbar-track: ${scrollbarTrack};
-    --theme--scrollbar-thumb: ${scrollbarThumb};
-    --theme--scrollbar-thumb_hover: ${scrollbarThumbHover};`;
-  cssBody += `
-    .notion-body${modeSelector} ::-webkit-scrollbar-track,
-    .notion-body${modeSelector} ::-webkit-scrollbar-corner {
-      background: var(--theme--scrollbar-track, ${scrollbarTrack}) !important;
-    }
-    .notion-body${modeSelector} ::-webkit-scrollbar-thumb {
-      background: var(--theme--scrollbar-thumb, ${scrollbarThumb}) !important;
-    }
-    .notion-body${modeSelector} ::-webkit-scrollbar-thumb:hover {
-      background: var(--theme--scrollbar-thumb_hover, ${scrollbarThumbHover}) !important;
-    }
-  `;
-};
-generateScrollbarStyles();
+    overrideStyle({
+      selector: '.notion-code-block > [style*="mono"]',
+      property: "color",
+      variable: "code-block_fg",
+    });
+    overrideStyle({
+      selector: '.notion-code-block > div > [style*="background"]',
+      property: "background",
+      variable: "code-block_bg",
+    });
 
-const prismTokens = [
-    // all standard tokens from https://prismjs.com/tokens.html
-    "keyword",
-    "builtin",
-    "class-name",
-    "function",
-    "boolean",
-    "number",
-    "string",
-    "char",
-    "symbol",
-    "regex",
-    "url",
-    "operator",
-    "variable",
-    "constant",
-    "property",
-    "punctuation",
-    "important",
-    "comment",
-    "tag",
-    "attr-name",
-    "attr-value",
-    "namespace",
-    "prolog",
-    "doctype",
-    "cdata",
-    "entity",
-    "atrule",
-    "selector",
-    "inserted",
-    "deleted",
-  ],
-  generateCodeStyles = () => {
-    const inlineCode = document.querySelector(
-        '.notion-text-block .notion-enable-hover[style*="mono"]'
-      ),
-      inlineFg = inlineCode
-        .getAttribute("style")
-        .match(/(?:^|(?:;\s*))color:\s*([^;]+);?/)?.[1],
-      inlineBg = inlineCode
-        .getAttribute("style")
-        .match(/(?:^|(?:;\s*))background:\s*([^;]+);?/)?.[1];
-    cssRoot += `
-      --theme--code-inline_fg: ${inlineFg};
-      --theme--code-inline_bg: ${inlineBg};`;
-    cssBody += `
-      .notion-body${modeSelector} .notion-text-block
-      .notion-enable-hover[style*="mono"][style*="color:${inlineFg}"] {
-        color: var(--theme--code-inline_fg, ${inlineFg}) !important;
-      }
-      .notion-body${modeSelector} .notion-text-block
-      .notion-enable-hover[style*="mono"][style*="background:${inlineBg}"] {
-        background: var(--theme--code-inline_bg, ${inlineBg}) !important;
-      }
-    `;
-    const blockFg = document
-        .querySelector('.notion-code-block > [style*="mono"]')
-        .getAttribute("style")
-        .match(/(?:^|(?:;\s*))color:\s*([^;]+);?/)?.[1],
-      blockBg = document
-        .querySelector('.notion-code-block > div > [style*="background"]')
-        .getAttribute("style")
-        .match(/(?:^|(?:;\s*))background:\s*([^;]+);?/)?.[1];
-    cssRoot += `--theme--code-block_fg: ${blockFg};
-      --theme--code-block_bg: ${blockBg};`;
-    cssBody += `
-      .notion-body${modeSelector} .notion-code-block > [style*="mono"] {
-        color: var(--theme--code-block_fg, ${blockFg}) !important;
-      }
-      .notion-body${modeSelector} .notion-code-block > div > [style*="background"] {
-        background: var(--theme--code-block_bg, ${blockBg}) !important;
-      }
-    `;
-    const refs = {},
-      el = document.querySelector(".notion-code-block .token");
-    for (const token of prismTokens) {
-      el.className = `token ${token}`;
-      const cssVar = `--theme--code-${token.replace(/-/g, "_")}`,
-        colorVal = getComputedPropertyValue(el, "color");
-      refs[colorVal] ??= cssVar;
-      cssRoot += `${cssVar}: ${
-        refs[colorVal] === cssVar ? colorVal : `var(${refs[colorVal]})`
-      };`;
-      cssBody += `.notion-body${modeSelector} .notion-code-block .token.${token} {
-        color: var(${cssVar}, ${colorVal}) !important;
-      }`;
-    }
-    // patch: remove backgrounds from prism tokens
-    if (!darkMode) {
-      cssBody += `
-        .notion-body${modeSelector} .token.operator,
-        .notion-body${modeSelector} .token.entity,
-        .notion-body${modeSelector} .token.url,
-        .notion-body${modeSelector} .language-css .token.string,
-        .notion-body${modeSelector} .style .token.string {
-          background: transparent !important;
-        }
-      `;
+    const aliases = {},
+      code = document.querySelector(".notion-code-block .token");
+    for (const token of [
+      // standard tokens from https://prismjs.com/tokens.html
+      "keyword",
+      "builtin",
+      "class-name",
+      "function",
+      "boolean",
+      "number",
+      "string",
+      "char",
+      "symbol",
+      "regex",
+      "url",
+      "operator",
+      "variable",
+      "constant",
+      "property",
+      "punctuation",
+      "important",
+      "comment",
+      "tag",
+      "attr-name",
+      "attr-value",
+      "namespace",
+      "prolog",
+      "doctype",
+      "cdata",
+      "entity",
+      "atrule",
+      "selector",
+      "inserted",
+      "deleted",
+    ]) {
+      code.className = `token ${token}`;
+      overrideStyle({
+        target: code,
+        selector: `.notion-code-block .token.${token}`,
+        property: "color",
+        variable: `code-${token.replace(/-/g, "_")}`,
+        variableAliases: aliases,
+        specificity: ["mode"],
+      });
     }
+
+    // patch: remove individual backgrounds from prism tokens
+    cssBody += `.token:is(
+      .operator, .entity, .url,
+      :is(.language-css, .style) .string
+    ) { background: transparent !important; }`;
   };
-generateCodeStyles();
 
-const cssDoc = `body${modeSelector} { ${cssRoot} } ${cssBody}`;
-console.log(cssDoc);
+styleFonts();
+styleAccents();
+styleScrollbars();
+styleCode();
+
+cssBody = cssBody.replace(/\s+/g, " ");
+console.log(`body${modeSelector} { ${cssRoot} } ${cssBody}`);