diff --git a/scripts/userstyles.yml b/scripts/userstyles.yml index 57c1872f88..1893ac0895 100644 --- a/scripts/userstyles.yml +++ b/scripts/userstyles.yml @@ -75,6 +75,7 @@ collaborators: - &koibtw koibtw - &TheAnonymousCrusher TheAnonymousCrusher - &42willow 42willow + - &ELHart05 ELHart05 userstyles: advent-of-code: @@ -282,7 +283,7 @@ userstyles: categories: [search_engine] icon: duckduckgo color: peach - current-maintainers: [*GenShibe] + current-maintainers: [*GenShibe, *ELHart05] ecosia: name: Ecosia link: https://www.ecosia.org diff --git a/styles/duckduckgo/catppuccin.user.less b/styles/duckduckgo/catppuccin.user.less index 6f3f492c96..00777753cc 100644 --- a/styles/duckduckgo/catppuccin.user.less +++ b/styles/duckduckgo/catppuccin.user.less @@ -18,11 +18,13 @@ @import "https://userstyles.catppuccin.com/lib/lib.less"; @-moz-document domain("duckduckgo.com"), domain("duck.ai") { - :root:not(.dark-bg, .no-theme) { + /* the homepage uses .theme-dark instead of .dark-bg, so count it as dark */ + :root:not(.dark-bg, .no-theme, .theme-dark) { #catppuccin(@lightFlavor); } - :root.dark-bg { + :root.dark-bg, + :root.theme-dark { #catppuccin(@darkFlavor); } @@ -163,6 +165,14 @@ --col-blue-30: @blue !important; --sds-color-palette-green-60: @green !important; --sds-color-background-utility: @surface0 !important; + --sds-color-background-03: @surface0 !important; + --sds-color-border-inner-divider: @surface1 !important; + --sds-color-focus: @accent !important; + --sds-color-text-primary: @text !important; + /* the header search box keys its bg off background-03 above; its input and + button text still ship near-white, so pin them to readable palette ink */ + --theme-col-txt-search-input: @text !important; + --theme-col-txt-search-button: @subtext0 !important; .address-detail { background-color: @mantle; @@ -1063,6 +1073,42 @@ border-color: @surface0; } + /* fill the rounded wrapper, not the square input, so it stops poking out */ + [data-testid="search-form-input-wrapper"] { + background-color: @surface0 !important; + } + #search_form_input { + background-color: transparent !important; + } + #search_form button[type="submit"], + #search_form button[type="reset"] { + color: @accent !important; + } + /* DDG fills this on focus too, so match the hover icon */ + #search_form button[type="submit"]:hover, + #search_form button[type="submit"]:active, + #search_form:focus-within button[type="submit"] { + color: @base !important; + background-color: @accent !important; + } + [data-testid="search-autocomplete-menu"] > div { + background-color: @surface0 !important; + } + [data-testid="search-autocomplete-menu"] [role="option"]:hover, + [data-testid="search-autocomplete-menu"] + [role="option"][aria-selected="true"] { + background-color: @surface1 !important; + } + /* Latte is low-contrast; keep the search box defined on the pale page */ + & when (@flavor = latte) { + [data-testid="search-form-input-wrapper"], + [data-testid="search-autocomplete-menu"] > div { + border-width: 1px !important; + border-style: solid !important; + border-color: @surface2 !important; + } + } + .acp--highlight, .bg-clr--platinum-light { background-color: @overlay0; @@ -1106,8 +1152,10 @@ background-image: url("data:image/svg+xml,@{svg}") !important; } - // ddg header logo - .header_logoImg__PFezv { + // ddg header logo — recolor it on every page that ships it (the home page + // gives the image a class, the compare page renders a bare ) + [class*="header_logoImg"], + [class*="header_logo"] img { @svg: escape( '' ); @@ -1116,8 +1164,10 @@ } } -@-moz-document domain("start.duckduckgo.com") { - :root:not(.theme-dark) { +/* the homepage app (also on start.duckduckgo.com) keys off theme-light/dark; + the results pages don't, so this block stays off the SERP */ +@-moz-document domain("duckduckgo.com") { + :root.theme-light { #catppuccin(@lightFlavor); } @@ -1145,59 +1195,349 @@ background-color: @surface0 !important; color: @text !important; } - li:hover { - background-color: @surface2 !important; - } - ul { - background-color: @surface0 !important; - } body { background-color: @base !important; - } - h1, - h2, - h3, - p, - a, - span { + /* inherited, so generic text follows the palette while accent-filled + callouts and buttons keep their own readable content color */ color: @text !important; } --color-yellow60: @yellow !important; --theme-button-primary-bg: @blue !important; + --theme-button-primary-text: @base !important; + --theme-button-secondary-text: @text !important; --theme-searchbox-caret-bg: @accent !important; - - .home_root__naJUp { - --theme-bg-home: @base !important; - --theme-button-secondary-text: @text !important; - --theme-text-bg: @text !important; - --theme-bg-home-searchbox: @surface0 !important; - --theme-border-color-home-searchbox: @surface0 !important; - } - .searchbox_suggestions__umkQH { - --theme-searchbox-bg: @surface0 !important; + --theme-searchbox-bg: @surface0 !important; + --theme-bg-home: @base !important; + --theme-bg-home-searchbox: @surface0 !important; + --theme-border-color-home-searchbox: @surface0 !important; + --theme-text-bg: @text !important; + --theme-sidemenu-bg: @surface0 !important; + --theme-searchbox-suggestion--hover: @surface1 !important; + + /* the redesign builds every --theme-* var on top of these design-system + tokens; recoloring the solid ones here themes the whole app at once and + leaves the translucent overlays (glow, tone, decoration) to blend on + their own */ + --ds-text-primary: @text !important; + --ds-text-secondary: @subtext1 !important; + --ds-text-tertiary: @subtext0 !important; + --ds-icons-primary: @text !important; + --ds-icons-secondary: @subtext1 !important; + --ds-icons-tertiary: @subtext0 !important; + --ds-surface-backdrop: @base !important; + --ds-surface-canvas: @base !important; + --ds-surface-primary: @surface0 !important; + --ds-surface-secondary: @surface0 !important; + --ds-surface-tertiary: @surface1 !important; + --ds-surface-primary-text: @text !important; + --ds-accent-primary: @accent !important; + --ds-accent-secondary: @accent !important; + --ds-accent-tertiary: @accent !important; + --ds-accent-quaternary: @accent !important; + --ds-accent-primary-content-color: @base !important; + --ds-accent-secondary-content-color: @base !important; + --ds-accent-tertiary-content-color: @base !important; + --ds-accent-primary-text-color: @accent !important; + --ds-accent-secondary-text-color: @accent !important; + --ds-accent-tertiary-text-color: @accent !important; + --ds-status-green: @green !important; + --ds-status-red: @red !important; + --ds-status-yellow: @yellow !important; + --ds-destructive-primary: @red !important; + --ds-destructive-secondary: @red !important; + --ds-destructive-tertiary: @red !important; + --ds-destructive-primary-content-color: @base !important; + --ds-destructive-primary-text-color: @red !important; + --ds-destructive-secondary-text-color: @red !important; + --ds-destructive-tertiary-text-color: @red !important; + + /* header nav links and the home/AI-chat button text fall back to plain + black or white; bring them onto the palette */ + --theme-header-text: @text !important; + --theme-header-text--hover: @subtext1 !important; + --theme-header-text--active: @subtext0 !important; + --theme-text-home: @text !important; + + /* the AI-search and Duck.ai glyphs ship in DuckDuckGo brand blue */ + --theme-ai-searchbox-ai-chat-icon--path: @blue !important; + --theme-ai-searchbox-ai-chat-icon--gradient-b1: @sapphire !important; + --theme-ai-searchbox-ai-chat-icon--gradient-b2: @sapphire !important; + --theme-ai-searchbox-ai-chat-icon--gradient-c1: @sapphire !important; + --theme-ai-searchbox-ai-chat-icon--gradient-c2: @sapphire !important; + --theme-ai-searchbox-ai-chat-icon--gradient-d1: @sapphire !important; + --theme-ai-searchbox-ai-chat-icon--gradient-d2: @sapphire !important; + --theme-ai-searchbox-search-find-icon--path: @text !important; + --theme-ai-searchbox-search-find-icon--gradient-a1: @sapphire !important; + --theme-ai-searchbox-search-find-icon--gradient-a2: @sapphire !important; + + [class*="minimal-homepage_layout"], + [class*="minimal-homepage_minimalHero"], + [class*="app_appRebrand"] { + background-color: @base !important; } - .minimal-homepage_minimalHeroLogo__QSVlf { + [class*="minimalHeroLogo"] { @svg: escape( '' ); content: url("data:image/svg+xml,@{svg}"); } - .header_headerButton__cLYU3 { + [class*="header_headerButton"] { color: @text !important; } - .sideMenu_sideMenuContent__OE7n9, - .searchbox_iconWrapper__suWUe { + [class*="sideMenu_sideMenuContent"], + [class*="ai-searchbox_combobox"], + [class*="search-input_searchbox"], + [class*="suggestions-list_suggestions"] { background-color: @surface0 !important; } - .button_primary__e2_Sy { - color: @mantle !important; + [class*="search-input_searchInput"] { + background-color: transparent !important; } - .searchbox_hasQuery__j8_VE:hover - .searchbox_searchButton__F5Bwq:not(:disabled), - .searchbox_hasQuery__j8_VE:focus-within { - color: @mantle !important; + [class*="ai-searchbox_combobox"] { + outline-color: @accent !important; + /* snap to a whole pixel; -0.5px renders lopsided at fractional + display scaling in Firefox */ + outline-offset: 0 !important; + } + [class*="suggestions-list_suggestions"] [role="option"]:hover { + background-color: @surface1 !important; + } + /* the "Ask Duck.ai" footer suffix and its shortcut ship DuckDuckGo greys + that wash out on the pale row; pin them to a readable palette tone */ + [class*="suggestions-list_duckAISuggestion"] { + color: @subtext0 !important; + } + /* only the accent-filled solid buttons want the content color; matching the + bare "button_primary" also hit surface cards and washed their text out */ + [class*="button_primary-solid"] { + color: var(--ds-accent-primary-content-color) !important; + } + /* search and Duck.ai modes use different button classes; target the + submit button so both get the same treatment */ + [class*="ai-searchbox_combobox"] button[type="submit"] { + color: @subtext0 !important; + background-color: transparent !important; + } + [class*="ai-searchbox_combobox"] button[type="submit"]:not(:disabled) { + color: @accent !important; + } + /* keep the icon on the button color (the generic span rule would + otherwise wash it out) */ + [class*="ai-searchbox_combobox"] button[type="submit"] span { + color: inherit !important; + } + /* fill on focus, bar-hover, and button hover/press, like the results page */ + [class*="ai-searchbox_combobox"] button[type="submit"]:not(:disabled):hover, + [class*="ai-searchbox_combobox"] + button[type="submit"]:not(:disabled):active, + [class*="ai-searchbox_combobox"]:hover button[type="submit"]:not(:disabled), + [class*="ai-searchbox_form"]:focus-within + button[type="submit"]:not(:disabled) { + color: @base !important; background-color: @accent !important; } + + /* below-the-fold: flatten brand-colored cards onto the palette */ + [class*="downloadsCard"], + [class*="card_card"], + [class*="card-button_root"] { + background-color: @surface0 !important; + border-color: @surface1 !important; + } + /* restore the hover lift the flat fill above wiped out */ + [class*="card-button_root"]:hover { + background-color: @surface1 !important; + } + /* a step darker than the hero, so the scroll-tab dome blends in and only + the bump shows (as in the original) */ + [class*="minimal-homepage_belowTheFold"], + [class*="app-quotes_root"], + [class*="_bottomRow"] { + background-color: @mantle !important; + } + [class*="pull-tab-scroll-button_keyContainer"] path { + fill: @mantle !important; + } + /* the down arrow ships light; keep it on the text color so it reads */ + [class*="pull-tab-scroll-button"] [class*="icon-button"] path { + fill: @text !important; + } + [class*="pull-tab-scroll-button_peekButtonKey"] { + color: @text !important; + } + [class*="plusMinusButton"] { + background-color: @surface1 !important; + } + [class*="heading_heading"], + [class*="_headingText"] { + color: @text !important; + } + + [class*="chip-select_root"] { + background-color: @crust !important; + } + [class*="chip-select_selectedIndicator"] { + background-color: @surface2 !important; + } + [class*="chip-select_option"] { + color: @text !important; + } + [class*="chip-select_optionIcon"] path { + fill: @text !important; + } + /* Duck.ai spark, mono (unselected) glyph */ + [clip-path*="ai-chat"]:not([clip-path*="color"]) path:nth-of-type(2) { + fill: @mauve !important; + } + /* selected option swaps in the filled color glyph: drop its solid bubble so + only the outline shows, leaving a spark that matches the mono one */ + [clip-path*="ai-chat"][clip-path*="color"] path:nth-of-type(1), + [clip-path*="ai-chat"][clip-path*="color"] path:nth-of-type(3) { + fill: transparent !important; + } + [clip-path*="ai-chat"][clip-path*="color"] path:nth-of-type(2) { + fill: @text !important; + } + [clip-path*="ai-chat"][clip-path*="color"] path:nth-of-type(4), + [clip-path*="ai-chat"][clip-path*="color"] path:nth-of-type(5) { + fill: @mauve !important; + /* this spark is bigger than the mono one; scale it down to match */ + transform: scale(0.72) !important; + transform-box: fill-box !important; + transform-origin: center !important; + } + [aria-label="Search"][class*="chip-select_optionIcon"] path { + fill: @blue !important; + } + /* the home comparison uses pill tabs; the /compare-privacy page uses an + underline indicator, so only fill the pills and recolor the underline */ + [class*="chipTabs"] [class*="tabs_tab__"] { + background-color: @surface0 !important; + } + [class*="chipTabs"] [class*="tabs_tab__"][aria-selected="true"], + [class*="chipTabs"] [class*="tabs_tab__"][data-selected] { + color: @base !important; + background-color: @accent !important; + } + /* the label is a child with its own color, so pin it on the filled pill */ + [class*="chipTabs"] + [class*="tabs_tab__"][aria-selected="true"] + [class*="tabs_tabLabel"], + [class*="chipTabs"] + [class*="tabs_tab__"][data-selected] + [class*="tabs_tabLabel"] { + color: @base !important; + } + [class*="tabs_tab__"][aria-selected="true"] { + border-bottom-color: @accent !important; + } + /* comparison table zebra rows: DuckDuckGo rounds the odd rows, so the + fill has to land on those for the pill shape to show */ + [class*="marketing-compare-privacy-table"] tbody tr:nth-child(odd) { + background-color: @surface0 !important; + } + + /* the primary CTA fill and label already ride the accent tokens; only its + icon ships a fixed color, so tie that to the button's content color */ + [class*="link-button_primary-solid"] path { + fill: var(--ds-accent-primary-content-color) !important; + } + + /* the compare-privacy hero ships a brand navy band; swap it for a crust band + so it stays clearly distinct from the page without the off-palette blue */ + [class*="compare-privacy-page_hero"] { + background-color: @crust !important; + } + /* outlined secondary buttons (e.g. the extension CTA) and the checkbox box + fall back to a faint black-alpha outline; give them a palette edge */ + [class*="link-button_secondary"], + [class*="checkbox_indicator"] { + border-color: @surface2 !important; + } + /* secondary/ghost link buttons (including the tagline pill) ship grey label + text that washes out; pin it to the palette ink */ + [class*="link-button_secondary"], + [class*="link-button_secondary"] [class*="buttonLabel"], + [class*="minimal-homepage_taglineText"] { + color: @text !important; + } + /* the side menu's close glyph ships a fixed light grey that vanishes on the + pale surface */ + [class*="sideMenu_closeButton"] { + color: @text !important; + } + [class*="sideMenu_closeButton"]:hover { + background-color: @surface1 !important; + } + + /* the +/- feature popups and hover tooltips paint the bubble, its text, + and its pointer with a motif color; flatten them onto a surface so they + read in every section */ + [class*="tooltip_tooltip"], + [class*="feature-card-detail-button_popover__"] { + background-color: @surface0 !important; + color: @text !important; + } + [class*="feature-card-detail-button_popoverText"] { + color: @text !important; + } + [class*="tooltip_arrow"] { + fill: @surface0 !important; + } + [class*="feature-card-detail-button_pointer"] { + color: @surface0 !important; + } + + /* the Customize Homepage dialog ships a flat #444/#fafafa surface and a + blue glow on the selected option; pull both onto the palette */ + [class*="customize-button_modal__"] { + background-color: @base !important; + } + [class*="customize-button_radio__"][data-selected] { + background-color: fade(@accent, 20%) !important; + } + /* the unselected option ships a near-invisible black-alpha tint and no edge; + give it a defined surface so both options read as choices */ + [class*="customize-button_radio__"]:not([data-selected]) { + background-color: @surface0 !important; + border-color: @surface2 !important; + } + /* the feedback thumbs ship mismatched colors (one brand blue, one grey); + give both glyphs one readable tone on their surface */ + [class*="customize-button_feedbackRadio__"] svg, + [class*="customize-button_feedbackRadio__"] path { + color: @subtext0 !important; + fill: @subtext0 !important; + } + + /* Latte is low-contrast, so give the surfaces a hairline border to keep + them defined against the pale page */ + & when (@flavor = latte) { + [class*="ai-searchbox_combobox"], + [class*="card_card"], + [class*="card-button_root"], + [class*="feature-card_root"], + [class*="downloadsCard"], + [class*="chip-select_root"] { + border-width: 1px !important; + border-style: solid !important; + border-color: @surface2 !important; + } + /* these controls fall back to a muddy black-on-white tint (or no fill at + all), which reads as dirty grey on the pale page; give them a clean + surface instead */ + [class*="customize-button_customizeButton"], + [class*="link-button_secondary-solid"] { + background-color: @surface0 !important; + border-color: @surface2 !important; + } + [class*="customize-button_feedbackRadio__"] { + background-color: @surface0 !important; + } + [class*="customize-button_feedbackRadio__"]:hover { + background-color: @surface1 !important; + } + } } }