// ==UserScript== // @name WaniKani Catppuccin Mocha // @namespace wk-catppuccin-mocha // @version 0.6.3 // @author Federico G. Schwindt // @description Applies the Catppuccin Mocha palette to WaniKani with system and manual modes. // @license MIT // @homepageURL https://github.com/fgsch/wanikani // @updateURL https://raw.githubusercontent.com/fgsch/wanikani/main/wk-catppuccin-mocha.js // @downloadURL https://raw.githubusercontent.com/fgsch/wanikani/main/wk-catppuccin-mocha.js // @match https://www.wanikani.com/* // @grant none // @run-at document-start // ==/UserScript== (function () { "use strict"; const STYLE_ID = "wk-catppuccin-mocha-styles"; const TOGGLE_ID = "wk-catppuccin-mocha-toggle"; const STORAGE_KEY = "wk-catppuccin-mocha-mode"; const modes = ["system", "dark", "light"]; const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); const NAME = GM_info.script.name; const VERSION = GM_info.script.version; const pendingLevelUpImages = new WeakMap(); let mode = "system"; try { const storedMode = localStorage.getItem(STORAGE_KEY); if (modes.includes(storedMode)) { mode = storedMode; } } catch (error) { void error; } const styles = ` :root { --ctp-mocha-rosewater: #f5e0dc; --ctp-mocha-blue: #89b4fa; --ctp-mocha-blue-bold: oklch(72.04% 0.1913 261.88); --ctp-mocha-sky: #89dceb; --ctp-mocha-teal: #94e2d5; --ctp-mocha-green: #a6e3a1; --ctp-mocha-red: #f38ba8; --ctp-mocha-peach: #fab387; --ctp-mocha-pink: #f5c2e7; --ctp-mocha-pink-bold: oklch(81.78% 0.1552 338.3); --ctp-mocha-mauve: #cba6f7; --ctp-mocha-mauve-bold: oklch(73.99% 0.1987 306.77); --ctp-mocha-lavender: #b4befe; --ctp-mocha-text: #cdd6f4; --ctp-mocha-subtext-0: #a6adc8; --ctp-mocha-overlay-2: #9399b2; --ctp-mocha-overlay-1: #7f849c; --ctp-mocha-overlay-0: #6c7086; --ctp-mocha-surface-2: #585b70; --ctp-mocha-surface-1: #45475a; --ctp-mocha-surface-0: #313244; --ctp-mocha-base: #1e1e2e; --ctp-mocha-mantle: #181825; --ctp-mocha-crust: #11111b; } html[data-wk-mocha-active] { color-scheme: dark; --wk-dark-background: var(--ctp-mocha-base); --wk-dark-surface: var(--ctp-mocha-mantle); --wk-dark-surface-raised: var(--ctp-mocha-surface-0); --wk-dark-surface-hover: var(--ctp-mocha-surface-1); --wk-dark-border: var(--ctp-mocha-surface-2); --wk-dark-text: var(--ctp-mocha-text); --wk-dark-text-muted: var(--ctp-mocha-subtext-0); --wk-dark-progress: color-mix(in srgb, var(--ctp-mocha-green) 80%, var(--wk-dark-surface-raised)); --color-radical: var(--ctp-mocha-blue-bold); --color-radical-dark: color-mix(in srgb, var(--ctp-mocha-blue) 35%, var(--ctp-mocha-crust)); --color-kanji: var(--ctp-mocha-pink-bold); --color-kanji-dark: color-mix(in srgb, var(--ctp-mocha-pink) 35%, var(--ctp-mocha-crust)); --color-vocabulary: var(--ctp-mocha-mauve-bold); --color-vocabulary-dark: color-mix(in srgb, var(--ctp-mocha-mauve) 35%, var(--ctp-mocha-crust)); --color-blue: var(--color-radical); --color-blue-dark: var(--color-radical-dark); --color-blue-light: color-mix(in srgb, var(--ctp-mocha-blue) 30%, var(--wk-dark-surface-raised)); --color-pink: var(--color-kanji); --color-pink-dark: var(--color-kanji-dark); --color-pink-light: color-mix(in srgb, var(--ctp-mocha-pink) 30%, var(--wk-dark-surface-raised)); --color-purple: var(--color-vocabulary); --color-purple-dark: var(--color-vocabulary-dark); --color-purple-light: color-mix(in srgb, var(--ctp-mocha-mauve) 30%, var(--wk-dark-surface-raised)); --color-text-highlight-radical-text: var(--ctp-mocha-blue); --color-text-highlight-radical-background: color-mix(in srgb, var(--ctp-mocha-blue) 12%, var(--wk-dark-surface-raised)); --color-text-highlight-kanji-text: var(--ctp-mocha-pink); --color-text-highlight-kanji-background: color-mix(in srgb, var(--ctp-mocha-pink) 12%, var(--wk-dark-surface-raised)); --color-text-highlight-vocabulary-text: var(--ctp-mocha-mauve); --color-text-highlight-vocabulary-background: color-mix(in srgb, var(--ctp-mocha-mauve) 12%, var(--wk-dark-surface-raised)); --color-text-highlight-meaning-text: var(--wk-dark-text); --color-text-highlight-meaning-background: var(--wk-dark-surface-raised); --color-text-highlight-reading-text: var(--wk-dark-text); --color-text-highlight-reading-background: var(--wk-dark-surface-raised); --color-app-background: var(--wk-dark-background); --color-text: var(--wk-dark-text); --color-focus: var(--ctp-mocha-lavender); --color-title-underline: var(--wk-dark-border); --color-link: var(--ctp-mocha-blue); --color-input-text: var(--wk-dark-text); --color-input-background: var(--wk-dark-surface); --color-input-border: var(--wk-dark-border); --color-quiz-input-background: var(--wk-dark-surface); --color-quiz-input-focus: var(--ctp-mocha-lavender); --color-quiz-correct-background: color-mix(in srgb, var(--ctp-mocha-green) 18%, var(--wk-dark-surface)); --color-quiz-correct-text-color: var(--wk-dark-text); --color-quiz-srs-correct-background: var(--wk-dark-progress); --color-quiz-srs-correct-text-color: var(--ctp-mocha-base); --color-quiz-incorrect-background: color-mix(in srgb, var(--ctp-mocha-red) 18%, var(--wk-dark-surface)); --color-quiz-incorrect-text-color: var(--wk-dark-text); --colorQuizExceptionBackground: var(--wk-dark-surface-raised); --colorQuizExceptionText: var(--wk-dark-text); --color-hint-background: var(--wk-dark-surface-raised); --color-code-background: var(--wk-dark-surface-raised); --color-code-border: var(--wk-dark-border); --color-alert-system-background: var(--ctp-mocha-pink); --color-alert-system-button-edge: var(--ctp-mocha-crust); --color-alert-system-text: var(--ctp-mocha-crust); --color-page-header-title: var(--wk-dark-text); --color-page-header-subtitle: var(--wk-dark-text-muted); --color-page-header-description: var(--wk-dark-text-muted); --color-page-nav-header-icon: var(--wk-dark-text-muted); --color-section-header-border: var(--wk-dark-border); --color-section-subtitle: var(--wk-dark-text-muted); --color-setting-divider: var(--wk-dark-border); --color-authentication-footer-divider: var(--wk-dark-border); --color-subject-slide-navigation-background: var(--ctp-mocha-crust); --color-subject-slide-navigation-text: var(--wk-dark-text); --color-subject-slide-navigation-button-hover: var(--wk-dark-surface-hover); --colorSlideBackground: var(--wk-dark-surface); --colorSlideBorder: var(--wk-dark-border); --colorSlideShadow: color-mix(in srgb, var(--ctp-mocha-crust) 50%, transparent); --color-global-header-background: var(--wk-dark-surface); --color-global-header-border: var(--wk-dark-border); --color-lesson-and-review-border: var(--wk-dark-border); --color-lesson-and-review-border-hover: var(--ctp-mocha-overlay-0); --color-lesson-and-review-count-background: var(--ctp-mocha-surface-2); --color-lesson-and-review-count-zero-background: var(--wk-dark-surface-hover); --color-lesson-and-review-count-text: var(--wk-dark-text); --color-grouped-navigation-background: var(--ctp-mocha-crust); --color-grouped-navigation-link-background: var(--wk-dark-surface-raised); --color-grouped-navigation-link-active-background: var(--wk-dark-background); --color-grouped-navigation-link-active-border: var(--wk-dark-border); --color-grouped-navigation-link-hover-background: var(--wk-dark-surface-hover); --color-grouped-navigation-link-hover-text: var(--wk-dark-text); --color-widget-background: var(--wk-dark-surface); --color-widget-border: var(--wk-dark-border); --color-widget-divider: var(--wk-dark-border); --color-widget-primary-text: var(--wk-dark-text); --color-widget-secondary-text: var(--wk-dark-text-muted); --color-empty-widget-background: var(--wk-dark-surface); --color-extra-study-flashcard-seperator: var(--wk-dark-border); --color-extra-study-flashcard-subject: var(--ctp-mocha-base); --color-extra-study-button-background: var(--wk-dark-surface-raised); --color-extra-study-button-hover-background: var(--wk-dark-surface-hover); --color-extra-study-button-active-background: var(--ctp-mocha-surface-2); --color-extra-study-button-disabled-background: var(--wk-dark-surface); --color-extra-study-button-border: var(--wk-dark-border); --color-extra-study-button-text: var(--wk-dark-text); --color-extra-study-button-icon: var(--wk-dark-text-muted); --color-extra-study-button-remaining-text: var(--wk-dark-text-muted); --color-wk-panel-background: var(--wk-dark-surface); --color-wk-panel-content-background: var(--wk-dark-surface); --color-wk-panel-content-title-underline: var(--wk-dark-border); --color-modal-background: var(--wk-dark-surface-raised); --color-modal-mask: color-mix(in srgb, var(--ctp-mocha-crust) 75%, transparent); --color-modal-button-edge: var(--ctp-mocha-overlay-0); --color-lesson-modal-text: var(--wk-dark-text); --color-new-user-modal-background: var(--wk-dark-surface-raised); --color-new-user-modal-text: var(--wk-dark-text); --color-button-primary-background: var(--wk-dark-surface-raised); --color-button-primary-hover-background: var(--wk-dark-surface-hover); --color-button-primary-active-background: var(--ctp-mocha-surface-2); --color-button-primary-border: var(--ctp-mocha-overlay-0); --color-button-primary-text: var(--wk-dark-text); --color-button-primary-icon: var(--wk-dark-text-muted); --color-button-secondary-background: var(--wk-dark-surface-raised); --color-button-secondary-hover-background: var(--wk-dark-surface-hover); --color-button-secondary-active-background: var(--ctp-mocha-surface-2); --color-button-secondary-border: var(--wk-dark-border); --color-button-secondary-text: var(--wk-dark-text); --color-button-secondary-icon: var(--wk-dark-text-muted); --color-button-frameless-text: var(--wk-dark-text); --color-button-frameless-icon: var(--wk-dark-text-muted); --color-button-frameless-hover-background: var(--wk-dark-surface-hover); --color-button-icon-only-text: var(--wk-dark-text); --color-button-icon-only-hover-background: var(--wk-dark-surface-hover); --color-chip-background: var(--wk-dark-surface-raised); --color-chip-border: var(--wk-dark-border); --color-chip-text: var(--wk-dark-text); --color-chip-hover-background: var(--wk-dark-surface-hover); --color-chip-hover-border: var(--ctp-mocha-overlay-0); --color-chip-hover-text: var(--wk-dark-text); --color-chip-active-background: var(--ctp-mocha-overlay-0); --color-chip-active-border: var(--ctp-mocha-overlay-1); --color-count-bubble-background: var(--wk-dark-surface-raised); --color-count-bubble-border: var(--wk-dark-border); --color-count-bubble-divider: var(--wk-dark-border); --color-count-bubble-text: var(--wk-dark-text); --color-progress-chart-bar-background: var(--wk-dark-border); --color-progress-chart-bar: var(--wk-dark-progress); --color-progress-chart-metric-text: var(--wk-dark-text-muted); --color-progress-chart-metric-count: var(--wk-dark-text); --color-progress-chart-metric-count-background: var(--wk-dark-surface-hover); --color-subject-srs-progress-stage-background: var(--wk-dark-border); --color-subject-srs-progress-stage-complete-background: var(--wk-dark-progress); --color-subject-srs-progress-text: var(--wk-dark-text-muted); --color-item-spread-row-background: var(--wk-dark-surface); --color-item-spread-row-hover-background: var(--wk-dark-surface-hover); --color-item-spread-row-active-background: var(--wk-dark-surface-raised); --color-item-spread-row-border: var(--wk-dark-border); --color-item-spread-row-count: var(--wk-dark-text); --color-item-spread-total-background: var(--wk-dark-surface-raised); --color-item-spread-total-border: var(--wk-dark-border); --color-review-forecast-header-background: var(--wk-dark-surface-raised); --color-review-forecast-day-header-label: var(--wk-dark-text); --color-review-forecast-day-hover: var(--wk-dark-surface-hover); --color-review-forecast-day-active: var(--ctp-mocha-surface-2); --color-review-forecast-bar-positive: var(--wk-dark-progress); --color-review-forecast-bar-positive-border: var(--wk-dark-progress); --color-review-forecast-increase-positive: var(--ctp-mocha-green); --color-review-forecast-priority-count-inside: var(--ctp-mocha-crust); --color-review-forecast-bar-zero: var(--wk-dark-surface-hover); --color-review-forecast-bar-zero-border: var(--wk-dark-border); --color-level-progress-subjects-background: var(--wk-dark-surface); --color-level-progress-subjects-border: var(--wk-dark-border); --color-level-progress-item-stat-border: var(--wk-dark-border); --color-level-progress-item-stat-hover-background: var(--wk-dark-surface-hover); --color-level-progress-item-stat-active-background: var(--wk-dark-surface-raised); --color-level-progress-completed-bar: var(--wk-dark-progress); --color-level-progress-bar: var(--wk-dark-border); --color-subject-character-grid-header-background: var(--wk-dark-surface-raised); --color-subject-character-grid-header-title: var(--wk-dark-text); --color-subject-character-grid-header-subtitle: var(--wk-dark-text-muted); --color-subject-character-grid-item-background: var(--wk-dark-surface); --color-subject-character-grid-item-border: var(--wk-dark-border); --color-subject-page-header-border: var(--wk-dark-border); --color-dashboard-customization-menu-background: var(--wk-dark-surface-raised); --color-dashboard-customization-menu-border: var(--wk-dark-border); --color-dashboard-customization-menu-divider: var(--wk-dark-border); --color-dashboard-customization-menu-text: var(--wk-dark-text); --color-dashboard-customization-row-background: var(--wk-dark-surface); --color-dashboard-customization-template-background: var(--wk-dark-surface); --color-dashboard-customization-template-border: var(--wk-dark-border); --color-dashboard-customization-template-hover-background: var(--wk-dark-surface-hover); --color-dashboard-customization-template-selected-background: var(--wk-dark-surface-raised); --color-dashboard-customization-widget-container-background: var(--wk-dark-surface); --color-billing-plan-background: var(--wk-dark-surface); --color-billing-plan-border: var(--wk-dark-border); --color-subscription-plan-background: var(--wk-dark-surface); --color-subscription-plan-border: var(--wk-dark-border); --color-subscription-plan-divider: var(--wk-dark-border); --color-lesson-picker-footer-background: color-mix(in srgb, var(--ctp-mocha-mantle) 92%, transparent); --color-lesson-picker-footer-border: 1px solid var(--wk-dark-border); } html[data-wk-mocha-active], html[data-wk-mocha-active] body, html[data-wk-mocha-active] .site-content, html[data-wk-mocha-active] .site-container { background-color: var(--wk-dark-background); color: var(--wk-dark-text); } html[data-wk-mocha-active] .wk-alert--system { --color-button-icon-only-hover-background: color-mix(in srgb, var(--color-alert-system-background) 85%, var(--color-alert-system-text)); } html[data-wk-mocha-active] .wk-pitch-accent-variant-1 { --wk-pitch-accent-color: var(--ctp-mocha-green); } html[data-wk-mocha-active] .wk-pitch-accent-variant-2 { --wk-pitch-accent-color: var(--ctp-mocha-pink); } html[data-wk-mocha-active] .wk-pitch-accent-variant-3 { --wk-pitch-accent-color: var(--ctp-mocha-blue); } html[data-wk-mocha-active] .wk-pitch-accent-variant-4 { --wk-pitch-accent-color: var(--ctp-mocha-peach); } html[data-wk-mocha-active] .wk-kanjivg-stroke-1 { --wk-kanjivg-stroke-color: var(--ctp-mocha-blue); } html[data-wk-mocha-active] .wk-kanjivg-stroke-2 { --wk-kanjivg-stroke-color: var(--ctp-mocha-green); } html[data-wk-mocha-active] .wk-kanjivg-stroke-3 { --wk-kanjivg-stroke-color: var(--ctp-mocha-teal); } html[data-wk-mocha-active] .wk-kanjivg-stroke-4 { --wk-kanjivg-stroke-color: var(--ctp-mocha-mauve); } html[data-wk-mocha-active] .wk-kanjivg-stroke-5 { --wk-kanjivg-stroke-color: var(--ctp-mocha-peach); } html[data-wk-mocha-active] .wk-kanjivg-stroke-6 { --wk-kanjivg-stroke-color: var(--ctp-mocha-sky); } html[data-wk-mocha-active] .wk-kanjivg-stroke-7 { --wk-kanjivg-stroke-color: var(--ctp-mocha-pink); } html[data-wk-mocha-active] .wk-kanjivg-stroke-8 { --wk-kanjivg-stroke-color: var(--ctp-mocha-lavender); } html[data-wk-mocha-active] .wk-kanjivg-radical { --wk-kanjivg-stroke-color: var(--ctp-mocha-pink); } html[data-wk-mocha-active] .wk-kanjivg-group { --wk-kanjivg-stroke-color: var(--ctp-mocha-teal); } html[data-wk-mocha-active] .wk-kanjivg-faint { --wk-kanjivg-stroke-color: var(--ctp-mocha-overlay-1); } html[data-wk-mocha-active] .sitemap__section-header { color: var(--wk-dark-text); } html[data-wk-mocha-active] .sitemap__section-header:not(.sitemap__section-header--radicals):not(.sitemap__section-header--kanji):not(.sitemap__section-header--vocabulary):not(.sitemap__section-header--account):hover { border-color: var(--ctp-mocha-overlay-1); } html[data-wk-mocha-active] .sitemap__section-header:not(.sitemap__section-header--radicals):not(.sitemap__section-header--kanji):not(.sitemap__section-header--vocabulary):not(.sitemap__section-header--account):focus { border-color: var(--ctp-mocha-lavender); } html[data-wk-mocha-active] .sitemap__expandable-chunk--levels { background-color: var(--wk-dark-surface-raised); box-shadow: 0 4px 12px color-mix(in srgb, var(--ctp-mocha-crust) 55%, transparent); color: var(--wk-dark-text); } html[data-wk-mocha-active] .sitemap__expandable-chunk--levels::before { background-color: var(--wk-dark-surface-raised); } html[data-wk-mocha-active] .sitemap__expandable-chunk--levels .sitemap__group-header { color: var(--wk-dark-text-muted); } html[data-wk-mocha-active] .sitemap__pages--levels .sitemap__page a { background-color: var(--wk-dark-surface-hover); color: var(--wk-dark-text); } html[data-wk-mocha-active] .sitemap__pages--levels .sitemap__page a:hover, html[data-wk-mocha-active] .sitemap__pages--levels .sitemap__page a:focus { background-color: var(--ctp-mocha-surface-2); } html[data-wk-mocha-active] .sitemap__page--current-level a, html[data-wk-mocha-active] .sitemap__pages--levels .sitemap__page a:focus { border-color: var(--ctp-mocha-lavender); } html[data-wk-mocha-active] .sitemap__expandable-chunk--help { background-color: var(--wk-dark-surface-raised); box-shadow: 0 4px 12px color-mix(in srgb, var(--ctp-mocha-crust) 55%, transparent); color: var(--wk-dark-text); } html[data-wk-mocha-active] .sitemap__expandable-chunk--help::before { background-color: var(--wk-dark-surface-raised); } html[data-wk-mocha-active] .sitemap__expandable-chunk--help .sitemap__page--subject { border-bottom-color: #585b70; } html[data-wk-mocha-active] .sitemap__expandable-chunk--help .sitemap__page--subject a, html[data-wk-mocha-active] .sitemap__expandable-chunk--help .button--chat { color: var(--wk-dark-text); } html[data-wk-mocha-active] .sitemap__expandable-chunk--help .sitemap__page--subject a:hover, html[data-wk-mocha-active] .sitemap__expandable-chunk--help .sitemap__page--subject a:focus, html[data-wk-mocha-active] .sitemap__expandable-chunk--help .button--chat:hover, html[data-wk-mocha-active] .sitemap__expandable-chunk--help .button--chat:focus { background-color: var(--wk-dark-surface-hover); } html[data-wk-mocha-active] .sitemap__expandable-chunk--help .sitemap__page--subject a:focus, html[data-wk-mocha-active] .sitemap__expandable-chunk--help .button--chat:focus { border-color: #b4befe; } html[data-wk-mocha-active] .sitemap__expandable-chunk--help .button--chat::before { border-color: var(--ctp-mocha-lavender); } html[data-wk-mocha-active] .sitemap__expandable-chunk--account { background-color: var(--wk-dark-surface-raised); box-shadow: 0 4px 12px color-mix(in srgb, var(--ctp-mocha-crust) 55%, transparent); color: var(--wk-dark-text); } html[data-wk-mocha-active] .sitemap__expandable-chunk--account::before { background-color: var(--wk-dark-surface-raised); } html[data-wk-mocha-active] .sitemap__expandable-chunk--account .user-summary, html[data-wk-mocha-active] .sitemap__expandable-chunk--account .sitemap__page--community { border-color: var(--wk-dark-border); } html[data-wk-mocha-active] .sitemap__expandable-chunk--account .user-summary__username, html[data-wk-mocha-active] .sitemap__expandable-chunk--account .user-summary__attribute a, html[data-wk-mocha-active] .sitemap__expandable-chunk--account .sitemap__page a { color: var(--wk-dark-text); } html[data-wk-mocha-active] .sitemap__expandable-chunk--account .sitemap__section-header--subsection { color: var(--wk-dark-text-muted); } html[data-wk-mocha-active] .sitemap__expandable-chunk--account .sitemap__page a:hover, html[data-wk-mocha-active] .sitemap__expandable-chunk--account .sitemap__page a:focus { background-color: var(--wk-dark-surface-hover); } html[data-wk-mocha-active] .sitemap__expandable-chunk--account .sitemap__page a:focus { border-color: var(--ctp-mocha-lavender); } html[data-wk-mocha-active] .sitemap__section-header--radicals:hover, html[data-wk-mocha-active] .sitemap__section-header--radicals:focus, html[data-wk-mocha-active] .sitemap__section--open .sitemap__section-header--radicals { border-color: var(--color-radical); color: var(--color-radical); } html[data-wk-mocha-active] .sitemap__section-header--kanji:hover, html[data-wk-mocha-active] .sitemap__section-header--kanji:focus, html[data-wk-mocha-active] .sitemap__section--open .sitemap__section-header--kanji { border-color: var(--color-kanji); color: var(--color-kanji); } html[data-wk-mocha-active] .sitemap__section-header--vocabulary:hover, html[data-wk-mocha-active] .sitemap__section-header--vocabulary:focus, html[data-wk-mocha-active] .sitemap__section--open .sitemap__section-header--vocabulary { border-color: var(--color-vocabulary); color: var(--color-vocabulary); } html[data-wk-mocha-active] .sitemap__expandable-chunk--radicals, html[data-wk-mocha-active] .sitemap__expandable-chunk--radicals:before { background: var(--color-radical); } html[data-wk-mocha-active] .sitemap__expandable-chunk--kanji, html[data-wk-mocha-active] .sitemap__expandable-chunk--kanji:before { background: var(--color-kanji); } html[data-wk-mocha-active] .sitemap__expandable-chunk--vocabulary, html[data-wk-mocha-active] .sitemap__expandable-chunk--vocabulary:before { background: var(--color-vocabulary); } html[data-wk-mocha-active] .sitemap__expandable-chunk--radicals .sitemap__page--subject a, html[data-wk-mocha-active] .sitemap__expandable-chunk--kanji .sitemap__page--subject a, html[data-wk-mocha-active] .sitemap__expandable-chunk--vocabulary .sitemap__page--subject a, html[data-wk-mocha-active] .sitemap__expandable-chunk--radicals .sitemap__page-subtitle, html[data-wk-mocha-active] .sitemap__expandable-chunk--kanji .sitemap__page-subtitle, html[data-wk-mocha-active] .sitemap__expandable-chunk--vocabulary .sitemap__page-subtitle { color: var(--ctp-mocha-base); } html[data-wk-mocha-active] .subject-collocations__pattern-name { background-color: var(--wk-dark-surface-raised); border: 1px solid #585b70; color: var(--wk-dark-text); } html[data-wk-mocha-active] .subject-collocations__pattern-name[aria-selected="true"] { background-color: var(--wk-dark-surface-hover); border-color: #b4befe; } html[data-wk-mocha-active] .subject-collocations__pattern-name[aria-selected="false"]:hover, html[data-wk-mocha-active] .subject-collocations__pattern-name[aria-selected="false"]:focus-visible { background-color: var(--wk-dark-surface-hover); border-color: #6c7086; } html[data-wk-mocha-active] .subject-collocations__pattern-name[aria-selected="true"]::after, html[data-wk-mocha-active] .subject-info .subject-collocations__pattern-name[aria-selected="true"]::after { background-color: var(--wk-dark-background); background-image: none; } html[data-wk-mocha-active] .wk-button--quiz { --color-button-background: var(--ctp-mocha-teal); --color-button-hover-background: var(--ctp-mocha-teal); --color-button-active-background: color-mix(in srgb, var(--ctp-mocha-teal) 80%, var(--ctp-mocha-crust)); --color-button-border: color-mix(in srgb, var(--ctp-mocha-teal) 65%, var(--ctp-mocha-crust)); --color-button-hover-border: var(--color-button-border); --color-button-active-border: color-mix(in srgb, var(--ctp-mocha-teal) 55%, var(--ctp-mocha-crust)); --color-button-edge: var(--color-button-border); --color-button-hover-edge: var(--color-button-hover-border); --color-button-active-edge: var(--color-button-active-border); --color-button-text: var(--ctp-mocha-crust); --color-button-hover-text: var(--ctp-mocha-crust); --color-button-active-text: var(--ctp-mocha-crust); --color-button-icon: var(--color-button-text); --color-button-hover-icon: var(--color-button-hover-text); --color-button-active-icon: var(--color-button-active-text); --button-outline: var(--ctp-mocha-teal); } html[data-wk-mocha-active] .subject-character__characters-text { color: var(--ctp-mocha-text) !important; } html[data-wk-mocha-active] .subject-character:not(.subject-character--locked):not(.subject-character--burned) .subject-character__characters-text, html[data-wk-mocha-active] .character-header__content, html[data-wk-mocha-active] .character-header__menu, html[data-wk-mocha-active] .character-header .summary-button, html[data-wk-mocha-active] .character-header__characters, html[data-wk-mocha-active] .character-header__meaning { color: var(--ctp-mocha-base) !important; } html[data-wk-mocha-active] .subject-character--locked.subject-character--radical .subject-character__characters-text { color: var(--color-radical) !important; } html[data-wk-mocha-active] .subject-character--locked.subject-character--kanji .subject-character__characters-text { color: var(--color-kanji) !important; } html[data-wk-mocha-active] .subject-character--locked.subject-character--vocabulary .subject-character__characters-text { color: var(--color-vocabulary) !important; } html[data-wk-mocha-active] .subject-legend-character { color: var(--ctp-mocha-text) !important; } html[data-wk-mocha-active] .subject-legend-character--lesson, html[data-wk-mocha-active] .subject-legend-character--review { color: var(--ctp-mocha-base) !important; } html[data-wk-mocha-active] .subject-legend-character--locked.subject-legend-character--radical { color: var(--color-radical) !important; } html[data-wk-mocha-active] .subject-legend-character--locked.subject-legend-character--kanji { color: var(--color-kanji) !important; } html[data-wk-mocha-active] .subject-legend-character--locked.subject-legend-character--vocabulary { color: var(--color-vocabulary) !important; } html[data-wk-mocha-active] .level-progress-widget .subject-legend-character:not(.subject-legend-character--locked), html[data-wk-mocha-active] .item-spread-table-widget .subject-legend-character:not(.subject-legend-character--locked), html[data-wk-mocha-active] .item-spread-table-widget .item-spread-table-row__count { color: var(--ctp-mocha-base) !important; } html[data-wk-mocha-active] [data-reveal="true"] .extra-study-flash-card-widget__subject-label { opacity: 1; } /* Image radicals read --color-text inside their shadow root. */ html[data-wk-mocha-active] .subject-character:not(.subject-character--locked):not(.subject-character--burned) .subject-character__character-image, html[data-wk-mocha-active] .character-header__character-image { --color-text: var(--ctp-mocha-base); } html[data-wk-mocha-active] .subject-character--locked.subject-character--radical .subject-character__character-image { --color-text: var(--color-radical); } html[data-wk-mocha-active] .subject-legend-character--lesson.subject-legend-character--radical, html[data-wk-mocha-active] .subject-character--recent.subject-character--radical .subject-character__characters-text { background-color: var(--ctp-mocha-blue); } html[data-wk-mocha-active] .subject-legend-character--lesson.subject-legend-character--kanji, html[data-wk-mocha-active] .subject-character--recent.subject-character--kanji .subject-character__characters-text { background-color: var(--ctp-mocha-pink); } html[data-wk-mocha-active] .subject-legend-character--lesson.subject-legend-character--vocabulary, html[data-wk-mocha-active] .subject-character--recent.subject-character--vocabulary .subject-character__characters-text { background-color: var(--ctp-mocha-mauve); } html[data-wk-mocha-active] .lesson-container__queue .subject-character--burned .subject-character__characters-text { background-color: var(--ctp-mocha-surface-2); border-color: var(--ctp-mocha-overlay-1); } html[data-wk-mocha-active] .subject-character--expandable .subject-character__characters:hover::before { background-color: var(--wk-dark-surface-raised); border: 1px solid #585b70; box-shadow: 0 0 8px color-mix(in srgb, var(--ctp-mocha-crust) 65%, transparent); } html[data-wk-mocha-active] .character-header--radical, html[data-wk-mocha-active] .quiz-header--radical { background-color: var(--color-radical); background-image: none; } html[data-wk-mocha-active] .character-header--kanji, html[data-wk-mocha-active] .quiz-header--kanji { background-color: var(--color-kanji); background-image: none; } html[data-wk-mocha-active] .character-header--vocabulary, html[data-wk-mocha-active] .quiz-header--vocabulary { background-color: var(--color-vocabulary); background-image: none; } html[data-wk-mocha-active] .subject-info { background-color: var(--wk-dark-surface); } html[data-wk-mocha-active] .todays-lessons-widget.theme--neon:not(.todays-lessons-widget--complete), html[data-wk-mocha-active] .reviews-widget.theme--neon:not(.reviews-widget--complete) { --color-widget-primary-text: var(--ctp-mocha-base); --color-widget-secondary-text: var(--ctp-mocha-base); } html[data-wk-mocha-active] .todays-lessons-widget.theme--neon:not(.todays-lessons-widget--complete) .count-bubble, html[data-wk-mocha-active] .reviews-widget.theme--neon:not(.reviews-widget--complete) .count-bubble { color: var(--ctp-mocha-base); } html[data-wk-mocha-active] .todays-lessons-widget--complete, html[data-wk-mocha-active] .reviews-widget--complete { --color-widget-background: var(--wk-dark-surface); } html[data-wk-mocha-active] .review-forecast-widget:not(.review-forecast-widget--loading) { --color-review-forecast-header-background: var(--wk-dark-surface-raised); } html[data-wk-mocha-mode] .level-up-alert__image img { color-scheme: light; } html[data-wk-mocha-active] .level-up-alert__image img { color-scheme: dark; } html[data-wk-mocha-active] .level-progress-widget__info-bubble { --color-notification-info-background: var(--wk-dark-surface-raised); --color-notification-info-border: var(--ctp-mocha-blue); --color-notification-info-icon: var(--ctp-mocha-blue); --color-notification-success-background: var(--wk-dark-surface-raised); --color-notification-success-border: var(--ctp-mocha-green); --color-notification-success-icon: var(--ctp-mocha-green); } html[data-wk-mocha-active] input, html[data-wk-mocha-active] textarea, html[data-wk-mocha-active] select { background-color: var(--wk-dark-surface); border-color: var(--wk-dark-border); box-shadow: none; caret-color: var(--ctp-mocha-rosewater); color: var(--wk-dark-text); } html[data-wk-mocha-active] ::placeholder { color: var(--wk-dark-text-muted); opacity: 1; } html[data-wk-mocha-active] .quiz-input__question-type-container[data-question-type="meaning"] { background-color: var(--wk-dark-surface-raised); background-image: none; border-color: var(--wk-dark-border); color: var(--wk-dark-text); } html[data-wk-mocha-active] .quiz-input__question-type-container[data-question-type="reading"] { background-color: var(--wk-dark-surface); background-image: none; border-color: var(--wk-dark-border); color: var(--wk-dark-text); } html[data-wk-mocha-active] .quiz-input__input-container[correct]:not([correct="false"]) .quiz-input__input { border-color: #a6e3a1; } html[data-wk-mocha-active] .quiz-input__input-container[correct="false"] .quiz-input__input { border-color: #f38ba8; } html[data-wk-mocha-active] .answer-exception { box-shadow: none; } html[data-wk-mocha-active] .additional-content__item { background-color: var(--wk-dark-surface-raised); border-color: var(--wk-dark-border); box-shadow: 2px 2px 4px color-mix(in srgb, var(--ctp-mocha-crust) 35%, transparent); color: var(--wk-dark-text-muted); } html[data-wk-mocha-active] .additional-content__item--disabled { background-color: var(--wk-dark-surface); box-shadow: none; color: var(--ctp-mocha-overlay-0); } html[data-wk-mocha-active] .additional-content__item--active { background-color: var(--ctp-mocha-overlay-0); box-shadow: none; color: var(--wk-dark-text); } html[data-wk-mocha-active] .additional-content__item--open::after { border-color: transparent transparent var(--wk-dark-border); } html[data-wk-mocha-active] .additional-content__content { background-color: var(--wk-dark-surface); border-color: #585b70; box-shadow: none; color: var(--wk-dark-text); } html[data-wk-mocha-active] .kana-chart__tab { color: var(--wk-dark-text); } html[data-wk-mocha-active] .kana-chart__tab:not(.kana-chart__tab--selected) { border-bottom-color: #585b70; color: var(--wk-dark-text-muted); } html[data-wk-mocha-active] .kana-chart__tab--selected { background-color: var(--wk-dark-surface-raised); border-color: #585b70 #585b70 transparent; } html[data-wk-mocha-active] .kana-chart__backspace, html[data-wk-mocha-active] .kana-chart__character { background-color: var(--wk-dark-surface-raised); color: var(--wk-dark-text); } html[data-wk-mocha-active] .kana-chart__character-romaji { color: var(--wk-dark-text-muted); } html[data-wk-mocha-active] .kana-chart__backspace:hover, html[data-wk-mocha-active] .kana-chart__character:hover { background-color: var(--wk-dark-surface-hover); } html[data-wk-mocha-active] .kana-chart__tab:not(.kana-chart__tab--selected):hover { color: var(--wk-dark-text); } html[data-wk-mocha-active] .kana-chart__tab:focus-visible, html[data-wk-mocha-active] .kana-chart__backspace:focus-visible, html[data-wk-mocha-active] .kana-chart__character:focus-visible { outline: 2px solid var(--ctp-mocha-lavender); outline-offset: 2px; } html[data-wk-mocha-active] .kana-chart__backspace:disabled, html[data-wk-mocha-active] .kana-chart__character:disabled { background-color: var(--wk-dark-surface); color: var(--ctp-mocha-overlay-0); } html[data-wk-mocha-active] ::selection { background-color: color-mix(in srgb, var(--ctp-mocha-overlay-2) 25%, transparent); color: var(--wk-dark-text); } html[data-wk-mocha-active] :focus-visible { outline-color: var(--ctp-mocha-lavender); } html[data-wk-mocha-active] body * { text-shadow: none !important; } html[data-wk-mocha-active] body *::before, html[data-wk-mocha-active] body *::after { text-shadow: none !important; } #${TOGGLE_ID} { all: initial; align-items: center; background: var(--ctp-mocha-surface-0); border: 1px solid var(--ctp-mocha-overlay-0); border-radius: 999px; bottom: 16px; box-shadow: 0 4px 16px color-mix(in srgb, var(--ctp-mocha-crust) 35%, transparent); color: var(--ctp-mocha-text); cursor: pointer; display: flex; font: 600 12px/1 system-ui, sans-serif; justify-content: center; min-height: 34px; min-width: 66px; padding: 0 12px; position: fixed; left: 16px; z-index: 2147483647; } #${TOGGLE_ID}:hover { background: var(--ctp-mocha-surface-1); } #${TOGGLE_ID}:focus-visible { outline: 3px solid var(--ctp-mocha-lavender); outline-offset: 2px; } `; function installStyles() { if (document.getElementById(STYLE_ID)) { return; } const style = document.createElement("style"); style.id = STYLE_ID; style.textContent = styles; (document.head || document.documentElement).append(style); } function applyTheme() { document.documentElement.dataset.wkMochaMode = mode; document.documentElement.toggleAttribute( "data-wk-mocha-active", mode === "dark" || (mode === "system" && mediaQuery.matches), ); } function updateToggle(toggle) { const nextMode = modes[(modes.indexOf(mode) + 1) % modes.length]; const label = `${mode[0].toUpperCase()}${mode.slice(1)}`; const nextLabel = `${nextMode[0].toUpperCase()}${nextMode.slice(1)}`; toggle.textContent = label; toggle.setAttribute( "aria-label", `Theme: ${label}. Click for ${nextLabel}.`, ); toggle.title = `Theme: ${label} (click for ${nextLabel})`; } function selectNextMode(toggle) { mode = modes[(modes.indexOf(mode) + 1) % modes.length]; try { localStorage.setItem(STORAGE_KEY, mode); } catch (error) { void error; } applyTheme(); updateToggle(toggle); } function installToggle() { if (!document.body) { return; } const existingToggle = document.getElementById(TOGGLE_ID); if (existingToggle) { updateToggle(existingToggle); return; } const toggle = document.createElement("button"); toggle.id = TOGGLE_ID; toggle.type = "button"; toggle.addEventListener("click", () => selectNextMode(toggle)); updateToggle(toggle); document.body.append(toggle); } async function themeLevelUpImage(element) { const attribute = element.localName === "source" ? "srcset" : "src"; const original = element.getAttribute(attribute); if (!original || pendingLevelUpImages.get(element) === original) { return; } const url = new URL(original, document.baseURI); if ( url.origin !== location.origin || url.pathname !== "/level_up_image.svg" ) { return; } pendingLevelUpImages.set(element, original); try { const response = await fetch(url); if (!response.ok) { throw new Error(`Level-up image request failed: ${response.status}`); } const svg = new DOMParser().parseFromString( await response.text(), "image/svg+xml", ); if ( svg.querySelector("parsererror") || svg.documentElement.localName !== "svg" || !svg.querySelector(".lu-title") ) { return; } // Embedded SVG media queries follow the image's color-scheme, including // manual theme overrides. Keep the artwork isolated in an image document. const style = svg.createElementNS("http://www.w3.org/2000/svg", "style"); const textColor = getComputedStyle(document.documentElement) .getPropertyValue("--ctp-mocha-text") .trim(); style.textContent = `@media (prefers-color-scheme: dark) { .lu-title { fill: ${textColor}; text-shadow: none; } }`; svg.documentElement.append(style); if (element.getAttribute(attribute) === original) { element.setAttribute( attribute, `data:image/svg+xml;charset=utf-8,${encodeURIComponent( new XMLSerializer().serializeToString(svg), )}`, ); } } catch (error) { console.warn(`[${NAME}] Could not theme level-up image:`, error); } finally { if (pendingLevelUpImages.get(element) === original) { pendingLevelUpImages.delete(element); } } } function installPageContent() { installToggle(); document .querySelectorAll( ".level-up-alert__image img[src], .level-up-alert__image source[srcset]", ) .forEach(themeLevelUpImage); } function run() { installStyles(); applyTheme(); installPageContent(); if (document.readyState === "loading" || !document.body) { document.addEventListener("DOMContentLoaded", installPageContent, { once: true, }); } } // Banner images can load after the document and Turbo page scans. document.addEventListener( "load", ({ target }) => { if (!target.matches?.(".level-up-alert__image img")) { return; } themeLevelUpImage(target); target .closest("picture") ?.querySelectorAll("source[srcset]") .forEach(themeLevelUpImage); }, true, ); mediaQuery.addEventListener?.("change", () => { if (mode === "system") { applyTheme(); } }); document.addEventListener("turbo:load", run); console.debug(`[${NAME}] Script loaded, version ${VERSION}`); run(); })();