diff --git a/.config/forge/stylesheet/forge/stylesheet.css b/.config/forge/stylesheet/forge/stylesheet.css index 2fb259a..f8beac3 100644 --- a/.config/forge/stylesheet/forge/stylesheet.css +++ b/.config/forge/stylesheet/forge/stylesheet.css @@ -1,11 +1,11 @@ .window-unfocused-border { border-width: 3px; - border-color: rgb(174, 214, 222); + border-color: rgb(150, 208, 221); border-style: solid; border-radius: 12px; } .tiled { - color: rgb(222, 237, 241); + color: rgb(221, 236, 240); opacity: 1; border-width: 3px; } @@ -15,23 +15,23 @@ border-width: 3px; } .stacked { - color: rgb(2, 131, 151); + color: rgb(0, 110, 129); opacity: 1; border-width: 3px; } .tabbed { - color: rgb(2, 131, 151); + color: rgb(0, 110, 129); opacity: 1; border-width: 3px; } .floated { - color: rgb(2, 131, 151); + color: rgb(0, 110, 129); border-width: 3px; opacity: 1; } .window-tiled-border { border-width: 4px; - border-color: rgb(222, 237, 241); + border-color: rgb(221, 236, 240); border-style: solid; border-radius: 12px; } @@ -53,13 +53,13 @@ } .window-stacked-border { border-width: 3px; - border-color: rgb(2, 131, 151); + border-color: rgb(0, 110, 129); border-style: solid; border-radius: 12px; } .window-tabbed-border { border-width: 3px; - border-color: rgb(2, 131, 151); + border-color: rgb(0, 110, 129); border-style: solid; border-radius: 12px; } @@ -67,17 +67,17 @@ border-radius: 8px; } .window-tabbed-tab { - background-color: rgb(10, 98, 113); - border-color: rgba(10, 98, 113, 0.6); + background-color: rgb(0, 77, 92); + border-color: rgba(0, 77, 92, 0.6); border-width: 1px; border-radius: 8px; - color: rgb(174, 214, 222); + color: rgb(150, 208, 221); margin: 1px; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2); } .window-tabbed-tab-active { - background-color: rgb(2, 131, 151); - color: rgb(222, 237, 241); + background-color: rgb(0, 110, 129); + color: rgb(221, 236, 240); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2); } .window-tabbed-tab-close { @@ -85,14 +85,14 @@ margin: 4px; border-radius: 12px; width: 12px; - background-color: rgb(8, 110, 127); + background-color: rgb(0, 110, 129); } .window-tabbed-tab-icon { margin: 3px; } .window-floated-border { border-width: 4px; - border-color: rgb(2, 131, 151); + border-color: rgb(0, 110, 129); border-style: solid; border-radius: 12px; } @@ -105,21 +105,21 @@ } .window-tilepreview-stacked { border-width: 1px; - border-color: rgba(2, 131, 151, 0.4); + border-color: rgba(0, 110, 129, 0.4); border-style: solid; border-radius: 12px; - background-color: rgba(2, 131, 151, 0.3); + background-color: rgba(0, 110, 129, 0.3); } .window-tilepreview-swap { border-width: 1px; - border-color: rgba(124, 189, 203, 0.4); + border-color: rgba(89, 177, 196, 0.4); border-style: solid; border-radius: 12px; - background-color: rgba(124, 189, 203, 0.4); + background-color: rgba(89, 177, 196, 0.4); } .window-tilepreview-tabbed { border-width: 1px; - border-color: rgba(2, 131, 151, 0.4); + border-color: rgba(0, 110, 129, 0.4); border-style: solid; border-radius: 12px; } diff --git a/.config/gnome-settings/README.md b/.config/gnome-settings/README.md index 318ca12..65967b6 100644 --- a/.config/gnome-settings/README.md +++ b/.config/gnome-settings/README.md @@ -36,29 +36,55 @@ Process: ## Color Palette -A teal ramp from light to dark, - plus two neutral tones for the shell chrome. +A teal ramp of 7 stops from light to dark, + plus two neutral tones for the shell chrome, + plus 5 accent hues with 2 shades each for the terminal ANSI colors. + +All colors except the two neutrals can be verified + with [`derive-palette.py`](./derive-palette.py) + to be derived from GNOME's "teal" accent alone. + +The ramp is uniform in perceived lightness (i.e., OKLCH), + with the accent centered by arithmetic: + In dark mode it reads light-to-dark (e.g., text on dark surfaces), + in light mode dark-to-light. Translucent colors are always alpha-variants of a stop, - used for `forge`'s tile previews and tab decorations. + used for tile previews and tab decorations by `forge`. -| Stop | Hex | RGB | Role | -|------|-----------|--------------------|----------------------------------------------| -| 1 | `#DEEDF1` | rgb(222, 237, 241) | Foreground and text, focused borders | -| 2 | `#AED6DE` | rgb(174, 214, 222) | Quiet chrome: bar and unfocused windows | -| 3 | `#7CBDCB` | rgb(124, 189, 203) | Tile previews | -| 4 | `#4AA4B6` | rgb( 74, 164, 182) | Borders of active elements | -| 5 | `#2190A4` | rgb( 33, 144, 164) | Accent | -| 6 | `#028397` | rgb( 2, 131, 151) | Stacked and tabbed layout, floated windows | -| 7 | `#067A8D` | rgb( 6, 122, 141) | Openbar Highlights | -| 8 | `#086E7F` | rgb( 8, 110, 127) | Tab decorations | -| 9 | `#0A6271` | rgb( 10, 98, 113) | Dimmed backgrounds (e.g., inactive tabs) | -| 0 | `#054A55` | rgb( 5, 74, 85) | Dark base: terminal and sub-menu backgrounds | -| gray | `#2E2E32` | rgb( 46, 46, 50) | Surfaces: bar and menu backgrounds | -| base | `#000000` | rgb( 0, 0, 0) | Screensaver, shadows | +| Stop | Hex | RGB | Role | +|------|-----------|--------------------|-----------------------------------------------| +| 1 | `#DDECF0` | rgb(221, 236, 240) | Foreground and text, focused borders | +| 2 | `#96D0DD` | rgb(150, 208, 221) | Quiet chrome: bar and unfocused windows | +| 3 | `#59B1C4` | rgb( 89, 177, 196) | Tile previews, borders of active elements | +| 4 | `#2190A4` | rgb( 33, 144, 164) | Accent | +| 5 | `#006E81` | rgb( 0, 110, 129) | Stacked/tabbed layouts, tab decorations | +| 6 | `#004D5C` | rgb( 0, 77, 92) | Dimmed and sub-menu backgrounds | +| 7 | `#002E37` | rgb( 0, 46, 55) | Dark base: terminal background | +| gray | `#2E2E32` | rgb( 46, 46, 50) | Surfaces: bar and menu backgrounds | +| base | `#000000` | rgb( 0, 0, 0) | Screensaver, shadows | -Stop 5 is GNOME's default "teal" color, - which is one of nine built-in colors that cannot be changed. -"gray" is GNOME's dark surface gray. +Stop 4 is GNOME's "teal", + one of nine built-in accent colors that cannot be changed + (see `--accent-teal` in `libadwaita`). +"gray" is the dark header-bar and sidebar background in `libadwaita` + (see `--headerbar-bg-color` and `--sidebar-bg-color`). + + +### Terminal Accents + + +Derived at the anchor's chroma, + with lightness solved for WCAG 4.5:1 against stop 7; + "bright" is the same hue lifted by 0.10 in lightness. + + +| Hue | Normal | Bright | +|---------|-----------|-----------| +| red | `#C87B75` | `#EA9A93` | +| yellow | `#A38F45` | `#C2AF64` | +| green | `#669D68` | `#84BC85` | +| blue | `#6D91CC` | `#8BB0ED` | +| magenta | `#B57DB0` | `#D69CD0` | diff --git a/.config/gnome-settings/apps.ini b/.config/gnome-settings/apps.ini index 576f8e4..ff3303b 100644 --- a/.config/gnome-settings/apps.ini +++ b/.config/gnome-settings/apps.ini @@ -320,8 +320,8 @@ audible-bell=false use-theme-colors=false # Fallback values for when theme coloring is turned off -background-color='rgb(5,74,85)' -foreground-color='rgb(222,237,241)' +background-color='rgb(0,46,55)' +foreground-color='rgb(221,236,240)' bold-is-bright=true diff --git a/.config/gnome-settings/derive-palette.py b/.config/gnome-settings/derive-palette.py new file mode 100644 index 0000000..0fa2a29 --- /dev/null +++ b/.config/gnome-settings/derive-palette.py @@ -0,0 +1,119 @@ +"""Derive a full color palette from a GNOME accent. + +The palette is a single-hue ramp of 7 stops in OKLCH: + - All stops share the anchor's hue + - Lightness descends in uniform steps, with the anchor centered + => Choosing the light end also determines the dark end by mirroring + - Chroma follows a bell over lightness, peaking at the anchor + +In addition, 5 accent hues with 2 shades each are derived +for the terminals' ANSI colors. + +The resulting values are recorded in the palette table in ./README.md +and this script is the source of truth for all colors. + +Usage: `python3 derive-palette.py` + (requires `pip install coloraide` before) +""" + +import coloraide + +ANCHOR = "#2190A4" # GNOME's teal (i.e., libadwaita's "--accent-teal") + +L_LIGHT = 0.933 # The one chosen parameter + +# Tail values of the chroma bell at the ramp's two ends +# where the dark tail is held high enough to keep the darkest stop +# appear in the chosen accent's hue +C_LIGHT, C_DARK = 0.017, 0.055 + +# Canonical hue angles (in OKLCH) +# for the terminal's semantic colors +ACCENT_HUES = { + "red": 25, + "yellow": 95, + "green": 145, + "blue": 260, + "magenta": 330, +} + +# The anchor's lightness, chroma, and hue seed everything below +a = coloraide.Color(ANCHOR).convert("oklch") +AL, AC, H = a["lightness"], a["chroma"], a["hue"] +step = (L_LIGHT - AL) / 3 + + +def hexify(L, C, h=H): + """Convert an OKLCH color to an upper-case sRGB hex string. + + Colors outside the sRGB gamut are fitted by reducing chroma + while preserving lightness and hue; in this palette that only + affects the darkest stops, where sRGB cannot hold the full chroma. + """ + return ( + coloraide.Color("oklch", [L, C, h]) + .convert("srgb") + .fit(method="oklch-chroma") + .to_string(hex=True, upper=True) + ) + + +def bell(L): + """Return the ramp's chroma at lightness `L`. + + Chroma follows a parabola over lightness: it peaks at the anchor + (i.e., `AC`) and falls off to `C_LIGHT` at the light end and `C_DARK` + at the dark end of the ramp. So, both ends still appear in the chosen + accent's hue without ever exceeding the anchor's saturation. + """ + end = C_LIGHT if L >= AL else C_DARK + t = (L - AL) / (3 * step) + return AC - (AC - end) * t * t + + +def lift(h): + """Return the lightness at which hue `h` reads on the dark base. + + Starting from the anchor's lightness, raise it in steps of 0.01 + until the color reaches a WCAG 2.1 contrast of 4.5:1 against the + ramp's darkest stop (i.e., `dark_base`, defined below but before + the first call). The accents' lightness is thereby solved + from the contrast requirement rather than chosen by hand. + """ + L = AL + + while ( + coloraide.Color(hexify(L, AC, h)).contrast( + dark_base, + method="wcag21", + ) + < 4.5 + ): + L += 0.01 + + return L + + +ramp = [ + hexify(AL + k * step, AC if k == 0 else bell(AL + k * step)) + for k in range(3, -4, -1) +] + +dark_base = coloraide.Color(ramp[-1]) + + +accents = {} + +for n, h in ACCENT_HUES.items(): + L = lift(h) # Solve only once per hue + accents[n] = ( + hexify(L, AC, h), + hexify(L + 0.10, AC, h), + ) + + +print("ramp:", *ramp) + +for n, (norm, bright) in accents.items(): + + print(f"{n}: {norm} {bright}") diff --git a/.config/gnome-settings/misc.ini b/.config/gnome-settings/misc.ini index c68d2f4..71f30b5 100644 --- a/.config/gnome-settings/misc.ini +++ b/.config/gnome-settings/misc.ini @@ -92,8 +92,8 @@ picture-options='zoom' picture-uri-dark='file:///home/user/.local/share/backgrounds/dark.jpg' picture-uri='file:///home/user/.local/share/backgrounds/light.jpg' -primary-color='#054A55' -secondary-color='#054A55' +primary-color='#002E37' +secondary-color='#002E37' diff --git a/.config/gnome-settings/shell-extensions.ini b/.config/gnome-settings/shell-extensions.ini index 8859615..421da89 100644 --- a/.config/gnome-settings/shell-extensions.ini +++ b/.config/gnome-settings/shell-extensions.ini @@ -442,7 +442,7 @@ format='%A %B %-d, %Y %H:%M:%S %Z%z' # "padding" matches the border "inset" of 3 # in ~/.local/bin/patch-forge custom-rounded-corner-settings=@a{sv} {} -global-rounded-corner-settings={'padding': <{'left': uint32 0, 'right': 0, 'top': 0, 'bottom': 0}>, 'keepRoundedCorners': <{'maximized': true, 'fullscreen': true}>, 'borderRadius': , 'smoothing': <0.0>, 'borderColor': <(0.682, 0.839, 0.871, 1.0)>, 'enabled': } +global-rounded-corner-settings={'padding': <{'left': uint32 0, 'right': 0, 'top': 0, 'bottom': 0}>, 'keepRoundedCorners': <{'maximized': true, 'fullscreen': true}>, 'borderRadius': , 'smoothing': <0.0>, 'borderColor': <(0.588, 0.816, 0.867, 1.0)>, 'enabled': } focused-shadow={'horizontalOffset': 0, 'verticalOffset': 4, 'blurOffset': 28, 'spreadRadius': 4, 'opacity': 60} unfocused-shadow={'horizontalOffset': 0, 'verticalOffset': 2, 'blurOffset': 12, 'spreadRadius': -1, 'opacity': 65} @@ -475,9 +475,9 @@ workspaces-bar-padding=0 active-workspace-font-size=10 active-workspace-font-weight='700' -active-workspace-text-color='rgb(222,237,241)' +active-workspace-text-color='rgb(221,236,240)' active-workspace-background-color='rgb(33,144,164)' -active-workspace-border-color='rgb(74,164,182)' +active-workspace-border-color='rgb(89,177,196)' active-workspace-border-radius=8 active-workspace-border-width=2 active-workspace-padding-h=8 @@ -485,7 +485,7 @@ active-workspace-padding-v=2 inactive-workspace-font-size=10 inactive-workspace-font-weight='600' -inactive-workspace-text-color='rgb(174,214,222)' +inactive-workspace-text-color='rgb(150,208,221)' inactive-workspace-background-color='rgb(46,46,50)' inactive-workspace-border-color='rgb(46,46,50)' inactive-workspace-border-radius=8 @@ -495,7 +495,7 @@ inactive-workspace-padding-v=2 empty-workspace-font-size=10 empty-workspace-font-weight='600' -empty-workspace-text-color='rgb(6,122,141)' +empty-workspace-text-color='rgb(0,110,129)' empty-workspace-background-color='rgb(46,46,50)' empty-workspace-border-color='rgb(46,46,50)' empty-workspace-border-radius=8