diff --git a/gtk/meson.build b/gtk/meson.build
index bd59f38c72..38c32b8d63 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -721,6 +721,7 @@ if not fs.exists('theme/Default/Default-light.css')
sassc_opts = [ '-a', '-M', '-t', 'compact' ]
subdir('theme/Default')
+ subdir('theme/libadwaita')
theme_deps += [
default_theme_deps,
@@ -988,6 +989,7 @@ gtk_sources += [
gtkprivatetypebuiltins,
gtktypebuiltins,
font_script_language_sources,
+ libadwaita_stylesheet_resources,
]
gtk_deps = [
diff --git a/gtk/theme/libadwaita/README.md b/gtk/theme/libadwaita/README.md
new file mode 100644
index 0000000000..5616843987
--- /dev/null
+++ b/gtk/theme/libadwaita/README.md
@@ -0,0 +1,42 @@
+## Summary
+
+* To be able to use the latest/adequate version of sass, install sassc
+* meson will regenerate the CSS every time you modify the SCSS files.
+* Note that meson always builds out-of-tree, so the modified css files will
+ appear in your builddir.
+
+## Theme Variants
+
+The Adwaita theme comes in 4 variants: light, dark, hc (highcontrast) and
+hc-dark (highcontrast inverse). The generated CSS files for the variants
+are called Adwaita-$variant.css. For technical reasons, GTK adds one level
+of include wrappers around these, which are called gtk-$variant.css.
+
+## How to Tweak the Theme
+
+Adwaita is a complex theme, so to keep it maintainable it's written and
+processed in SASS. The generated CSS is then transformed into a gresource file
+during gtk build and used at runtime in a non-legible or editable form.
+
+It is very likely your change will happen in the _common.scss file. That's where
+all the widget selectors are defined. Here's a rundown of the "supporting"
+stylesheets, that are unlikely to be the right place for a drive by stylesheet
+fix:
+
+_colors.scss - global color definitions. We keep the number of defined
+ colors to a necessary minimum, most colors are derived
+ from a handful of basics. It covers both the light variant
+ and the dark variant.
+
+_colors-public.scss - SCSS colors exported through gtk to allow for 3rd party
+ apps color mixing.
+
+_drawing.scss - drawing helper mixings/functions to allow easier
+ definition of widget drawing under specific context. This
+ is why Adwaita isn't 15000 LOC.
+
+_common.scss - actual definitions of style for each widget. This is
+ where you are likely to add/remove your changes.
+
+You can read about SASS at http://sass-lang.com/documentation/. Once you make
+your changes to the _common.scss file, libadwaita will rebuild the CSS files.
diff --git a/gtk/theme/libadwaita/_colors.scss b/gtk/theme/libadwaita/_colors.scss
new file mode 100644
index 0000000000..614055c575
--- /dev/null
+++ b/gtk/theme/libadwaita/_colors.scss
@@ -0,0 +1,131 @@
+$border_opacity: if($contrast == 'high', .5, .15);
+$thin_border_opacity: if($contrast == 'high', .25, .05);
+$focus_border_opacity: if($contrast == 'high', 0.8, 0.5);
+
+// Colors from _defaults.scss
+
+$accent_bg_color: gtkcolor(accent_bg_color);
+$accent_fg_color: gtkcolor(accent_fg_color);
+$accent_color: gtkcolor(accent_color);
+
+$destructive_bg_color: gtkcolor(destructive_bg_color);
+$destructive_fg_color: gtkcolor(destructive_fg_color);
+$destructive_color: gtkcolor(destructive_color);
+
+$success_bg_color: gtkcolor(success_bg_color);
+$success_fg_color: gtkcolor(success_fg_color);
+$success_color: gtkcolor(success_color);
+
+$warning_bg_color: gtkcolor(warning_bg_color);
+$warning_fg_color: gtkcolor(warning_fg_color);
+$warning_color: gtkcolor(warning_color);
+
+$error_bg_color: gtkcolor(error_bg_color);
+$error_fg_color: gtkcolor(error_fg_color);
+$error_color: gtkcolor(error_color);
+
+$window_bg_color: gtkcolor(window_bg_color);
+$window_fg_color: gtkcolor(window_fg_color);
+
+$view_bg_color: gtkcolor(view_bg_color);
+$view_fg_color: gtkcolor(view_fg_color);
+
+$headerbar_bg_color: gtkcolor(headerbar_bg_color);
+$headerbar_fg_color: gtkcolor(headerbar_fg_color);
+$headerbar_border_color: gtkalpha(gtkcolor(headerbar_border_color), $border_opacity);
+$headerbar_backdrop_color: gtkcolor(headerbar_backdrop_color);
+$headerbar_shade_color: gtkcolor(headerbar_shade_color);
+$headerbar_darker_shade_color: gtkcolor(headerbar_darker_shade_color);
+
+$sidebar_bg_color: gtkcolor(sidebar_bg_color);
+$sidebar_fg_color: gtkcolor(sidebar_fg_color);
+$sidebar_backdrop_color: gtkcolor(sidebar_backdrop_color);
+$sidebar_border_color: gtkcolor(sidebar_border_color);
+$sidebar_shade_color: gtkcolor(sidebar_shade_color);
+
+$secondary_sidebar_bg_color: gtkcolor(secondary_sidebar_bg_color);
+$secondary_sidebar_fg_color: gtkcolor(secondary_sidebar_fg_color);
+$secondary_sidebar_backdrop_color: gtkcolor(secondary_sidebar_backdrop_color);
+$secondary_sidebar_border_color: gtkcolor(secondary_sidebar_border_color);
+$secondary_sidebar_shade_color: gtkcolor(secondary_sidebar_shade_color);
+
+$card_bg_color: gtkcolor(card_bg_color);
+$card_fg_color: gtkcolor(card_fg_color);
+$card_shade_color: gtkcolor(card_shade_color);
+
+$dialog_bg_color: gtkcolor(dialog_bg_color);
+$dialog_fg_color: gtkcolor(dialog_fg_color);
+
+$popover_bg_color: gtkcolor(popover_bg_color);
+$popover_fg_color: gtkcolor(popover_fg_color);
+$popover_shade_color: gtkcolor(popover_shade_color);
+
+$thumbnail_bg_color: gtkcolor(thumbnail_bg_color);
+$thumbnail_fg_color: gtkcolor(thumbnail_fg_color);
+
+$shade_color: gtkcolor(shade_color);
+$scrollbar_outline_color: gtkcolor(scrollbar_outline_color);
+
+// Other colors
+
+$border_color: gtkalpha(currentColor, $border_opacity);
+$thin_border_color: gtkalpha(currentColor, $thin_border_opacity);
+$link_color: $accent_color;
+$link_visited_color: gtkmix($accent_color, $view_fg_color, 80%);
+
+$hover_color: gtkalpha(currentColor, .07);
+$active_color: gtkalpha(currentColor, .16);
+$selected_color: gtkalpha(currentColor, .1);
+$selected_hover_color: gtkalpha(currentColor, .13);
+$selected_active_color: gtkalpha(currentColor, .19);
+
+$view_hover_color: gtkalpha(currentColor, .04);
+$view_active_color: gtkalpha(currentColor, .08);
+$view_selected_color: gtkalpha($accent_bg_color, .25);
+$view_selected_hover_color: gtkalpha($accent_bg_color, .32);
+$view_selected_active_color: gtkalpha($accent_bg_color, .39);
+
+$trough_color: gtkalpha(currentColor, .15);
+$trough_hover_color: gtkalpha(currentColor, .2);
+$trough_active_color: gtkalpha(currentColor, .25);
+
+$fill_color: $accent_bg_color;
+$fill_text_color: $accent_fg_color;
+
+$slider_color: gtkmix(white, $view_bg_color, 80%);
+$slider_hover_color: white;
+
+$osd_fg_color: transparentize(white, .1);
+$osd_text_color: white;
+$osd_bg_color: transparentize(black, 0.3);
+$osd_fill_bg_color: transparentize(white, .25);
+$osd_fill_fg_color: transparentize(black, .25);
+$osd_focus_color: transparentize(white, .5);
+$osd_link_color: gtkmix($accent_bg_color, $osd_text_color, 50%);
+$osd_link_visited_color: gtkmix($accent_bg_color, $osd_text_color, 75%);
+
+$tooltip_border_color: transparentize(white, 0.9);
+$shadow_color: transparentize(black, 0.9);
+
+$drop_target_color: $accent_bg_color;
+
+$window_outline_color: transparentize(white, .93);
+
+//special cased widget colors
+$focus_border_color: gtkalpha($accent_color, $focus_border_opacity);
+$dim_label_opacity: 0.55;
+$dimmer_opacity: 0.3;
+$disabled_opacity: 0.5;
+$strong_disabled_opacity: 0.3;
+
+// High Contrast color overrides
+@if $contrast == 'high' {
+ $dim_label_opacity: 0.9;
+ $dimmer_opacity: 0.8;
+ $disabled_opacity: 0.4;
+
+ $trough_color: gtkalpha(currentColor, .3);
+ $trough_hover_color: gtkalpha(currentColor, .4);
+ $trough_active_color: gtkalpha(currentColor, .5);
+ $window_outline_color: transparentize(white, .7);
+}
diff --git a/gtk/theme/libadwaita/_common.scss b/gtk/theme/libadwaita/_common.scss
new file mode 100644
index 0000000000..961be739d2
--- /dev/null
+++ b/gtk/theme/libadwaita/_common.scss
@@ -0,0 +1,107 @@
+$ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+$backdrop_transition: 200ms ease-out;
+$focus_transition: outline-color 200ms $ease-out-quad,
+ outline-width 200ms $ease-out-quad,
+ outline-offset 200ms $ease-out-quad;
+$button_transition: background 200ms $ease-out-quad,
+ box-shadow 200ms $ease-out-quad;
+$button_radius: 6px;
+$card_radius: $button_radius + 6;
+$menu_radius: 6px;
+$menu_margin: 6px; //margin around menuitems & sidebar items
+$menu_padding: 12px; //inner menuitem padding
+$window_radius: $button_radius + 6;
+$popover_radius: $window_radius;
+
+.background {
+ color: $window_fg_color;
+ background-color: $window_bg_color;
+}
+
+dnd {
+ color: $window_fg_color;
+}
+
+.normal-icons {
+ -gtk-icon-size: 16px;
+}
+
+.large-icons {
+ -gtk-icon-size: 32px;
+}
+
+%osd,
+.osd {
+ color: $osd_fg_color;
+ border: none;
+ background-color: $osd_bg_color;
+ background-clip: padding-box;
+}
+
+/* Text selection */
+
+selection {
+ background-color: gtkalpha($view_fg_color, 0.1);
+ color: transparent;
+
+ &:focus-within {
+ background-color: gtkalpha($accent_bg_color, 0.3);
+ }
+}
+
+:not(window):drop(active):focus,
+:not(window):drop(active) { // FIXME needs to be done widget by widget, this wildcard should really die
+ border-color: $drop_target_color;
+ box-shadow: inset 0 0 0 1px $drop_target_color;
+ caret-color: $drop_target_color;
+}
+
+.navigation-sidebar,
+placessidebar,
+stackswitcher,
+expander-widget {
+ :not(window):drop(active):focus,
+ :not(window):drop(active) {
+ box-shadow: none;
+ }
+}
+
+/* Outline for low res icons */
+.lowres-icon {
+ -gtk-icon-shadow: 0 -1px rgba(0,0,0,0.05),
+ 1px 0 rgba(0,0,0,0.1),
+ 0 1px rgba(0,0,0,0.3),
+ -1px 0 rgba(0,0,0,0.1);
+}
+
+/* Drop shadow for large icons */
+.icon-dropshadow {
+ -gtk-icon-shadow: 0 1px 12px rgba(0,0,0,0.05),
+ 0 -1px rgba(0,0,0,0.05),
+ 1px 0 rgba(0,0,0,0.1),
+ 0 1px rgba(0,0,0,0.3),
+ -1px 0 rgba(0,0,0,0.1);
+}
+
+@keyframes needs_attention {
+ from { background-image: radial-gradient(farthest-side, $accent_color 0%, transparent 0%); }
+ to { background-image: radial-gradient(farthest-side, $accent_color 95%, transparent); }
+}
+
+%needs_attention {
+ // the dot is drawn by using two radial gradient, the first one is the actual dot, the other
+ // simulates the shadow labels and icons normally have in buttons.
+ animation: needs_attention 150ms ease-in;
+
+ background-image: radial-gradient(farthest-side, $accent_color 96%, transparent);
+ background-size: 6px 6px;
+ background-repeat: no-repeat;
+
+ background-position: right 3px;
+
+ &:dir(rtl) {
+ background-position: left 3px;
+ }
+}
+
+@import 'widgets';
diff --git a/gtk/theme/libadwaita/_compat-colors.scss b/gtk/theme/libadwaita/_compat-colors.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/gtk/theme/libadwaita/_defaults.scss b/gtk/theme/libadwaita/_defaults.scss
new file mode 100644
index 0000000000..a262a9897a
--- /dev/null
+++ b/gtk/theme/libadwaita/_defaults.scss
@@ -0,0 +1,83 @@
+/* GTK NAMED COLORS
+ ----------------
+ use responsibly! */
+
+// Sass thinks we're using the colors in the variables as strings and may shoot
+// warning, it's innocuous and can be defeated by using #{$var}.
+
+// These are the colors apps are can override. We define the defaults here and
+// define variables for them in _colors.scss
+
+// The main accent color and the matching text value
+@define-color accent_bg_color @blue_3;
+@define-color accent_fg_color white;
+@define-color accent_color #{if($variant == 'dark', #78aeed, "@blue_4")};
+
+// destructive-action buttons
+@define-color destructive_bg_color #{if($variant == 'dark', "@red_4", "@red_3")};
+@define-color destructive_fg_color white;
+@define-color destructive_color #{if($variant == 'dark', #ff7b63, "@red_4")};
+
+// Levelbars, entries, labels and infobars. These don't need text colors
+@define-color success_bg_color #{if($variant == 'dark', "@green_5", "@green_4")};
+@define-color success_fg_color white;
+@define-color success_color #{if($variant == 'dark', "@green_1", "#1b8553")};
+
+@define-color warning_bg_color #{if($variant == 'dark', #cd9309, "@yellow_5")};
+@define-color warning_fg_color #{transparentize(black, .2)};
+@define-color warning_color #{if($variant == 'dark', "@yellow_2", #9c6e03)};
+
+@define-color error_bg_color #{if($variant == 'dark', "@red_4", "@red_3")};
+@define-color error_fg_color white;
+@define-color error_color #{if($variant == 'dark', #ff7b63, "@red_4")};
+
+// Window
+@define-color window_bg_color #{if($variant == 'light', #fafafa, #242424)};
+@define-color window_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+
+// Views - e.g. text view or tree view
+@define-color view_bg_color #{if($variant == 'light', #ffffff, #1e1e1e)};
+@define-color view_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+
+// Header bar, search bar, tab bar
+@define-color headerbar_bg_color #{if($variant == 'light', #ffffff, #303030)};
+@define-color headerbar_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+@define-color headerbar_border_color #{if($variant == 'light', transparentize(black, .2), white)};
+@define-color headerbar_backdrop_color @window_bg_color;
+@define-color headerbar_shade_color #{if($variant == 'light', transparentize(black, .88), transparentize(black, .64))};
+@define-color headerbar_darker_shade_color #{if($variant == 'light', transparentize(black, .88), transparentize(black, .1))};
+
+// Split pane views
+@define-color sidebar_bg_color #{if($variant == 'light', #ebebeb, #303030)};
+@define-color sidebar_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+@define-color sidebar_backdrop_color #{if($variant == 'light', #f2f2f2, #2a2a2a)};
+@define-color sidebar_shade_color #{if($variant == 'light', transparentize(black, .93), transparentize(black, .75))};
+@define-color sidebar_border_color #{if($variant == 'light', transparentize(black, .93), transparentize(black, .64))};
+
+@define-color secondary_sidebar_bg_color #{if($variant == 'light', #f3f3f3, #2a2a2a)};
+@define-color secondary_sidebar_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+@define-color secondary_sidebar_backdrop_color #{if($variant == 'light', #f6f6f6, #272727)};
+@define-color secondary_sidebar_shade_color #{if($variant == 'light', transparentize(black, .93), transparentize(black, .75))};
+@define-color secondary_sidebar_border_color #{if($variant == 'light', transparentize(black, .93), transparentize(black, .64))};
+
+// Cards, boxed lists
+@define-color card_bg_color #{if($variant == 'light', #ffffff, transparentize(white, .92))};
+@define-color card_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+@define-color card_shade_color #{if($variant == 'light', transparentize(black, .93), transparentize(black, .64))};
+
+// Dialogs
+@define-color dialog_bg_color #{if($variant == 'light', #fafafa, #383838)};
+@define-color dialog_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+
+// Popovers
+@define-color popover_bg_color #{if($variant == 'light', #ffffff, #383838)};
+@define-color popover_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+@define-color popover_shade_color #{if($variant == 'light', transparentize(black, .93), transparentize(black, .75))};
+
+// Thumbnails
+@define-color thumbnail_bg_color #{if($variant == 'light', #ffffff, #383838)};
+@define-color thumbnail_fg_color #{if($variant == 'light', transparentize(black, .2), white)};
+
+// Miscellaneous
+@define-color shade_color #{if($variant == 'light', transparentize(black, .93), transparentize(black, .75))};
+@define-color scrollbar_outline_color #{if($variant == 'light', white, transparentize(black, .5))};
diff --git a/gtk/theme/libadwaita/_drawing.scss b/gtk/theme/libadwaita/_drawing.scss
new file mode 100644
index 0000000000..ad64e5d909
--- /dev/null
+++ b/gtk/theme/libadwaita/_drawing.scss
@@ -0,0 +1,138 @@
+// Drawing mixins
+
+// generic drawing of more complex things
+
+//
+// Helper mixin for drawing visible focus rings
+//
+// If $target is specified, the focus ring is applied to the specified child element.
+// If $outer is true, the focus ring extends outward. Otherwise, it extends inward.
+// If $within is true, use focus-within instead of focus:focus-visible
+//
+@mixin focus-ring($target: null, $width: 2px, $offset: -$width, $outer: false, $focus-state: ':focus:focus-visible', $fc: $focus_border_color, $transition: null) {
+ & #{$target} {
+ outline: 0 solid transparent;
+ outline-offset: if($outer, $offset + 4px, $offset + $width + 4px);
+ transition: $focus_transition, $transition;
+ }
+
+ {$focus-state} #{$target} {
+ outline-color: $fc;
+ outline-width: $width;
+ outline-offset: $offset;
+ }
+}
+
+@mixin undershoot($p, $c: $shade_color, $neighbor: false) {
+//
+// undershoot
+//
+// $p: position
+// $c: shade color
+// $neighbor: use ~ instead of >
+//
+// possible $p values:
+// top, bottom, right, left
+//
+
+ $_border_pos: '';
+ $_direction: '';
+ $_selector: if($neighbor, '~', '>');
+
+ @if $p==top {
+ $_direction: bottom;
+ $_border_pos: 0 1px;
+ } @else if $p==bottom {
+ $_direction: top;
+ $_border_pos: 0 -1px;
+ } @else if $p==left {
+ $_direction: right;
+ $_border_pos: 1px 0;
+ } @else if $p==right {
+ $_direction: left;
+ $_border_pos: -1px 0;
+ } @else {
+ @error "Unknown position #{$p}"
+ }
+
+ #{$_selector} undershoot.#{$p} {
+ box-shadow: inset $_border_pos if($contrast == 'high', $border_color, gtkalpha($c, .75));
+ background: linear-gradient(to $_direction, gtkalpha($c, .75), transparent 4px);
+ }
+}
+
+@mixin overshoot($p) {
+//
+// overshoot
+//
+// $p: position
+//
+// possible $p values:
+// top, bottom, right, left
+//
+
+ $_small_gradient_length: 3%;
+ $_big_gradient_length: 50%;
+
+ $_small_gradient_size: 100% $_small_gradient_length;
+ $_big_gradient_size: 100% $_big_gradient_length;
+
+ @if $p==right or $p==left {
+ $_small_gradient_size: $_small_gradient_length 100%;
+ $_big_gradient_size: $_big_gradient_length 100%;
+ }
+
+ $_small_gradient: radial-gradient(farthest-side at $p,
+ gtkalpha(currentColor, 0.12) 85%,
+ gtkalpha(currentColor, 0));
+
+ $_big_gradient: radial-gradient(farthest-side at $p,
+ gtkalpha(currentColor, 0.05),
+ gtkalpha(currentColor, 0));
+
+ background-image: $_small_gradient, $_big_gradient;
+ background-size: $_small_gradient_size, $_big_gradient_size;
+
+ background-repeat: no-repeat;
+ background-position: $p;
+
+ background-color: transparent; // reset some properties to be sure to not inherit them somehow
+ border: none; //
+ box-shadow: none; //
+}
+
+@mixin background-shadow($direction, $color) {
+ background-image:
+ linear-gradient($direction,
+ gtkalpha($color, 0.7),
+ gtkalpha($color, 0.14) 40px,
+ gtkalpha($color, 0) 56px),
+ linear-gradient($direction,
+ gtkalpha($color, 0.4),
+ gtkalpha($color, 0.14) 7px,
+ gtkalpha($color, 0) 24px);
+}
+
+@mixin transition-shadows($color) {
+ > dimming {
+ background: $color;
+ }
+
+ @if $contrast == 'high' {
+ > border {
+ min-width: 1px;
+ min-height: 1px;
+ background: $border_color;
+ }
+ }
+
+ > shadow {
+ min-width: 56px;
+ min-height: 56px;
+
+ &.left { @include background-shadow(to right, $color); }
+ &.right { @include background-shadow(to left, $color); }
+ &.up { @include background-shadow(to bottom, $color); }
+ &.down { @include background-shadow(to top, $color); }
+ }
+}
diff --git a/gtk/theme/libadwaita/_functions.scss b/gtk/theme/libadwaita/_functions.scss
new file mode 100644
index 0000000000..c4af658b6c
--- /dev/null
+++ b/gtk/theme/libadwaita/_functions.scss
@@ -0,0 +1,16 @@
+@function gtkalpha($c,$a) {
+ @return unquote("alpha(#{$c},#{$a})");
+}
+
+@function gtkmix($c1,$c2,$r) {
+ $ratio: 1 - $r / 100%; // match SCSS mix()
+ @return unquote("mix(#{$c1},#{$c2},#{$ratio})");
+}
+
+@function gtkshade($c,$s) {
+ @return unquote("shade(#{$c},#{$s})");
+}
+
+@function gtkcolor($c) {
+ @return unquote("@#{$c}");
+}
diff --git a/gtk/theme/libadwaita/_palette.scss b/gtk/theme/libadwaita/_palette.scss
new file mode 100644
index 0000000000..dd59a7109e
--- /dev/null
+++ b/gtk/theme/libadwaita/_palette.scss
@@ -0,0 +1,94 @@
+$blue_1: #99c1f1;
+$blue_2: #62a0ea;
+$blue_3: #3584e4;
+$blue_4: #1c71d8;
+$blue_5: #1a5fb4;
+$green_1: #8ff0a4;
+$green_2: #57e389;
+$green_3: #33d17a;
+$green_4: #2ec27e;
+$green_5: #26a269;
+$yellow_1: #f9f06b;
+$yellow_2: #f8e45c;
+$yellow_3: #f6d32d;
+$yellow_4: #f5c211;
+$yellow_5: #e5a50a;
+$orange_1: #ffbe6f;
+$orange_2: #ffa348;
+$orange_3: #ff7800;
+$orange_4: #e66100;
+$orange_5: #c64600;
+$red_1: #f66151;
+$red_2: #ed333b;
+$red_3: #e01b24;
+$red_4: #c01c28;
+$red_5: #a51d2d;
+$purple_1: #dc8add;
+$purple_2: #c061cb;
+$purple_3: #9141ac;
+$purple_4: #813d9c;
+$purple_5: #613583;
+$brown_1: #cdab8f;
+$brown_2: #b5835a;
+$brown_3: #986a44;
+$brown_4: #865e3c;
+$brown_5: #63452c;
+$light_1: #ffffff;
+$light_2: #f6f5f4;
+$light_3: #deddda;
+$light_4: #c0bfbc;
+$light_5: #9a9996;
+$dark_1: #77767b;
+$dark_2: #5e5c64;
+$dark_3: #3d3846;
+$dark_4: #241f31;
+$dark_5: #000000;
+
+// Sass thinks we're using the colors in the variables as strings and may shoot
+// warning, it's innocuous and can be defeated by using #{$var}.
+
+@define-color blue_1 #{$blue_1};
+@define-color blue_2 #{$blue_2};
+@define-color blue_3 #{$blue_3};
+@define-color blue_4 #{$blue_4};
+@define-color blue_5 #{$blue_5};
+@define-color green_1 #{$green_1};
+@define-color green_2 #{$green_2};
+@define-color green_3 #{$green_3};
+@define-color green_4 #{$green_4};
+@define-color green_5 #{$green_5};
+@define-color yellow_1 #{$yellow_1};
+@define-color yellow_2 #{$yellow_2};
+@define-color yellow_3 #{$yellow_3};
+@define-color yellow_4 #{$yellow_4};
+@define-color yellow_5 #{$yellow_5};
+@define-color orange_1 #{$orange_1};
+@define-color orange_2 #{$orange_2};
+@define-color orange_3 #{$orange_3};
+@define-color orange_4 #{$orange_4};
+@define-color orange_5 #{$orange_5};
+@define-color red_1 #{$red_1};
+@define-color red_2 #{$red_2};
+@define-color red_3 #{$red_3};
+@define-color red_4 #{$red_4};
+@define-color red_5 #{$red_5};
+@define-color purple_1 #{$purple_1};
+@define-color purple_2 #{$purple_2};
+@define-color purple_3 #{$purple_3};
+@define-color purple_4 #{$purple_4};
+@define-color purple_5 #{$purple_5};
+@define-color brown_1 #{$brown_1};
+@define-color brown_2 #{$brown_2};
+@define-color brown_3 #{$brown_3};
+@define-color brown_4 #{$brown_4};
+@define-color brown_5 #{$brown_5};
+@define-color light_1 #{$light_1};
+@define-color light_2 #{$light_2};
+@define-color light_3 #{$light_3};
+@define-color light_4 #{$light_4};
+@define-color light_5 #{$light_5};
+@define-color dark_1 #{$dark_1};
+@define-color dark_2 #{$dark_2};
+@define-color dark_3 #{$dark_3};
+@define-color dark_4 #{$dark_4};
+@define-color dark_5 #{$dark_5};
diff --git a/gtk/theme/libadwaita/_widgets.scss b/gtk/theme/libadwaita/_widgets.scss
new file mode 100644
index 0000000000..471d0a9045
--- /dev/null
+++ b/gtk/theme/libadwaita/_widgets.scss
@@ -0,0 +1,42 @@
+@import 'widgets/avatar';
+@import 'widgets/bottom-sheet';
+@import 'widgets/buttons';
+@import 'widgets/calendar';
+@import 'widgets/checks';
+@import 'widgets/color-chooser';
+@import 'widgets/column-view';
+@import 'widgets/dialogs';
+@import 'widgets/deprecated';
+@import 'widgets/dropdowns';
+@import 'widgets/emoji-chooser';
+@import 'widgets/entries';
+@import 'widgets/expanders';
+@import 'widgets/file-chooser';
+@import 'widgets/header-bar';
+@import 'widgets/labels';
+@import 'widgets/level-bar';
+@import 'widgets/linked';
+@import 'widgets/links';
+@import 'widgets/lists';
+@import 'widgets/menus';
+@import 'widgets/message-dialog';
+@import 'widgets/misc';
+@import 'widgets/notebook';
+@import 'widgets/paned';
+@import 'widgets/popovers';
+@import 'widgets/preferences';
+@import 'widgets/progress-bar';
+@import 'widgets/scale';
+@import 'widgets/scrolling';
+@import 'widgets/shortcuts-window';
+@import 'widgets/sidebars';
+@import 'widgets/spinner';
+@import 'widgets/spin-button';
+@import 'widgets/switch';
+@import 'widgets/tab-view';
+@import 'widgets/text-selection';
+@import 'widgets/toolbars';
+@import 'widgets/tooltip';
+@import 'widgets/views';
+@import 'widgets/view-switcher';
+@import 'widgets/window';
diff --git a/gtk/theme/libadwaita/adwaita-stylesheet.gresources.xml b/gtk/theme/libadwaita/adwaita-stylesheet.gresources.xml
new file mode 100644
index 0000000000..c09dbe0db2
--- /dev/null
+++ b/gtk/theme/libadwaita/adwaita-stylesheet.gresources.xml
@@ -0,0 +1,32 @@
+
+
+
+ base.css
+ base-hc.css
+ defaults-light.css
+ defaults-dark.css
+
+ assets/bullet-symbolic.symbolic.png
+ assets/bullet@2-symbolic.symbolic.png
+ assets/check-symbolic.symbolic.png
+ assets/check@2-symbolic.symbolic.png
+ assets/dash-symbolic.symbolic.png
+ assets/dash@2-symbolic.symbolic.png
+
+ assets/bullet-symbolic.svg
+ assets/check-symbolic.svg
+ assets/dash-symbolic.svg
+
+ assets/devel-symbolic.svg
+
+
+
+ gtk.css
+ gtk-dark.css
+
+
+
+ gtk-hc.css
+ gtk-hc-dark.css
+
+
diff --git a/gtk/theme/libadwaita/assets/bullet-symbolic.svg b/gtk/theme/libadwaita/assets/bullet-symbolic.svg
new file mode 100644
index 0000000000..f359a7012e
--- /dev/null
+++ b/gtk/theme/libadwaita/assets/bullet-symbolic.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtk/theme/libadwaita/assets/bullet-symbolic.symbolic.png b/gtk/theme/libadwaita/assets/bullet-symbolic.symbolic.png
new file mode 100644
index 0000000000..8e6925a5f8
Binary files /dev/null and b/gtk/theme/libadwaita/assets/bullet-symbolic.symbolic.png differ
diff --git a/gtk/theme/libadwaita/assets/bullet@2-symbolic.symbolic.png b/gtk/theme/libadwaita/assets/bullet@2-symbolic.symbolic.png
new file mode 100644
index 0000000000..e9df4256c0
Binary files /dev/null and b/gtk/theme/libadwaita/assets/bullet@2-symbolic.symbolic.png differ
diff --git a/gtk/theme/libadwaita/assets/check-symbolic.svg b/gtk/theme/libadwaita/assets/check-symbolic.svg
new file mode 100644
index 0000000000..27c620d499
--- /dev/null
+++ b/gtk/theme/libadwaita/assets/check-symbolic.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtk/theme/libadwaita/assets/check-symbolic.symbolic.png b/gtk/theme/libadwaita/assets/check-symbolic.symbolic.png
new file mode 100644
index 0000000000..9144bcd1ba
Binary files /dev/null and b/gtk/theme/libadwaita/assets/check-symbolic.symbolic.png differ
diff --git a/gtk/theme/libadwaita/assets/check@2-symbolic.symbolic.png b/gtk/theme/libadwaita/assets/check@2-symbolic.symbolic.png
new file mode 100644
index 0000000000..c0baa3c10e
Binary files /dev/null and b/gtk/theme/libadwaita/assets/check@2-symbolic.symbolic.png differ
diff --git a/gtk/theme/libadwaita/assets/dash-symbolic.svg b/gtk/theme/libadwaita/assets/dash-symbolic.svg
new file mode 100644
index 0000000000..de3638dd2b
--- /dev/null
+++ b/gtk/theme/libadwaita/assets/dash-symbolic.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtk/theme/libadwaita/assets/dash-symbolic.symbolic.png b/gtk/theme/libadwaita/assets/dash-symbolic.symbolic.png
new file mode 100644
index 0000000000..3afcfd6fa2
Binary files /dev/null and b/gtk/theme/libadwaita/assets/dash-symbolic.symbolic.png differ
diff --git a/gtk/theme/libadwaita/assets/dash@2-symbolic.symbolic.png b/gtk/theme/libadwaita/assets/dash@2-symbolic.symbolic.png
new file mode 100644
index 0000000000..9cb5994595
Binary files /dev/null and b/gtk/theme/libadwaita/assets/dash@2-symbolic.symbolic.png differ
diff --git a/gtk/theme/libadwaita/assets/devel-symbolic.svg b/gtk/theme/libadwaita/assets/devel-symbolic.svg
new file mode 100644
index 0000000000..14843f0965
--- /dev/null
+++ b/gtk/theme/libadwaita/assets/devel-symbolic.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gtk/theme/libadwaita/base-hc.scss b/gtk/theme/libadwaita/base-hc.scss
new file mode 100644
index 0000000000..278e537909
--- /dev/null
+++ b/gtk/theme/libadwaita/base-hc.scss
@@ -0,0 +1,8 @@
+$contrast: 'high';
+
+@import 'palette';
+@import 'functions';
+@import 'colors';
+@import 'drawing';
+@import 'common';
+@import 'compat-colors';
diff --git a/gtk/theme/libadwaita/base.scss b/gtk/theme/libadwaita/base.scss
new file mode 100644
index 0000000000..ffba5eacdc
--- /dev/null
+++ b/gtk/theme/libadwaita/base.scss
@@ -0,0 +1,8 @@
+$contrast: 'normal';
+
+@import 'palette';
+@import 'functions';
+@import 'colors';
+@import 'drawing';
+@import 'common';
+@import 'compat-colors';
diff --git a/gtk/theme/libadwaita/defaults-dark.scss b/gtk/theme/libadwaita/defaults-dark.scss
new file mode 100644
index 0000000000..7c56516cf1
--- /dev/null
+++ b/gtk/theme/libadwaita/defaults-dark.scss
@@ -0,0 +1,3 @@
+$variant: 'dark';
+
+@import 'defaults';
diff --git a/gtk/theme/libadwaita/defaults-light.scss b/gtk/theme/libadwaita/defaults-light.scss
new file mode 100644
index 0000000000..97159a234f
--- /dev/null
+++ b/gtk/theme/libadwaita/defaults-light.scss
@@ -0,0 +1,3 @@
+$variant: 'light';
+
+@import 'defaults';
diff --git a/gtk/theme/libadwaita/empty.css b/gtk/theme/libadwaita/empty.css
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/gtk/theme/libadwaita/gtk-dark.css b/gtk/theme/libadwaita/gtk-dark.css
new file mode 100644
index 0000000000..18a6b5fc10
--- /dev/null
+++ b/gtk/theme/libadwaita/gtk-dark.css
@@ -0,0 +1,2 @@
+@import url("resource:///org/gnome/Adwaita/styles/base.css");
+@import url("resource:///org/gnome/Adwaita/styles/defaults-dark.css");
diff --git a/gtk/theme/libadwaita/gtk-hc-dark.css b/gtk/theme/libadwaita/gtk-hc-dark.css
new file mode 100644
index 0000000000..a0290659cc
--- /dev/null
+++ b/gtk/theme/libadwaita/gtk-hc-dark.css
@@ -0,0 +1,2 @@
+@import url("resource:///org/gnome/Adwaita/styles/base-hc.css");
+@import url("resource:///org/gnome/Adwaita/styles/defaults-dark.css");
diff --git a/gtk/theme/libadwaita/gtk-hc.css b/gtk/theme/libadwaita/gtk-hc.css
new file mode 100644
index 0000000000..793b67384d
--- /dev/null
+++ b/gtk/theme/libadwaita/gtk-hc.css
@@ -0,0 +1,2 @@
+@import url("resource:///org/gnome/Adwaita/styles/base-hc.css");
+@import url("resource:///org/gnome/Adwaita/styles/defaults-light.css");
diff --git a/gtk/theme/libadwaita/gtk.css b/gtk/theme/libadwaita/gtk.css
new file mode 100644
index 0000000000..d6216bb9cf
--- /dev/null
+++ b/gtk/theme/libadwaita/gtk.css
@@ -0,0 +1,2 @@
+@import url("resource:///org/gnome/Adwaita/styles/base.css");
+@import url("resource:///org/gnome/Adwaita/styles/defaults-light.css");
diff --git a/gtk/theme/libadwaita/meson.build b/gtk/theme/libadwaita/meson.build
new file mode 100644
index 0000000000..563cafcc4c
--- /dev/null
+++ b/gtk/theme/libadwaita/meson.build
@@ -0,0 +1,100 @@
+fs = import('fs')
+
+stylesheet_deps = []
+
+# For git checkouts, but not for tarballs...
+if not fs.exists('base.css')
+ sassc = find_program('sassc', required: false)
+ if not sassc.found()
+ subproject('sassc', default_options: ['warning_level=0', 'werror=false'])
+ sassc = find_program('sassc')
+ endif
+
+ if sassc.found()
+ sassc_opts = [ '-a', '-M', '-t', 'compact' ]
+
+ scss_deps = files([
+ '_colors.scss',
+ '_common.scss',
+ '_compat-colors.scss',
+ '_defaults.scss',
+ '_drawing.scss',
+ '_functions.scss',
+ '_widgets.scss',
+
+ 'widgets/_avatar.scss',
+ 'widgets/_bottom-sheet.scss',
+ 'widgets/_buttons.scss',
+ 'widgets/_calendar.scss',
+ 'widgets/_checks.scss',
+ 'widgets/_color-chooser.scss',
+ 'widgets/_column-view.scss',
+ 'widgets/_deprecated.scss',
+ 'widgets/_dialogs.scss',
+ 'widgets/_dropdowns.scss',
+ 'widgets/_emoji-chooser.scss',
+ 'widgets/_entries.scss',
+ 'widgets/_expanders.scss',
+ 'widgets/_file-chooser.scss',
+ 'widgets/_header-bar.scss',
+ 'widgets/_labels.scss',
+ 'widgets/_level-bar.scss',
+ 'widgets/_linked.scss',
+ 'widgets/_links.scss',
+ 'widgets/_lists.scss',
+ 'widgets/_menus.scss',
+ 'widgets/_message-dialog.scss',
+ 'widgets/_misc.scss',
+ 'widgets/_notebook.scss',
+ 'widgets/_paned.scss',
+ 'widgets/_popovers.scss',
+ 'widgets/_preferences.scss',
+ 'widgets/_progress-bar.scss',
+ 'widgets/_scale.scss',
+ 'widgets/_scrolling.scss',
+ 'widgets/_shortcuts-window.scss',
+ 'widgets/_sidebars.scss',
+ 'widgets/_spinner.scss',
+ 'widgets/_spin-button.scss',
+ 'widgets/_switch.scss',
+ 'widgets/_tab-view.scss',
+ 'widgets/_text-selection.scss',
+ 'widgets/_toolbars.scss',
+ 'widgets/_tooltip.scss',
+ 'widgets/_views.scss',
+ 'widgets/_view-switcher.scss',
+ 'widgets/_window.scss',
+ ])
+
+ scss_files = [
+ 'base',
+ 'base-hc',
+ 'defaults-light',
+ 'defaults-dark',
+ ]
+
+ foreach scss: scss_files
+ stylesheet_deps += custom_target('@0@.scss'.format(scss),
+ input: '@0@.scss'.format(scss),
+ output: '@0@.css'.format(scss),
+ command: [
+ sassc, sassc_opts, '@INPUT@', '@OUTPUT@',
+ ],
+ depend_files: scss_deps,
+ )
+ endforeach
+ endif
+endif
+
+libadwaita_stylesheet_resources = gnome.compile_resources(
+ 'adwaita-stylesheet-resources',
+ 'adwaita-stylesheet.gresources.xml',
+
+ source_dir: [
+ # List in order of preference
+ meson.current_build_dir(),
+ meson.current_source_dir(),
+ ],
+ dependencies: stylesheet_deps,
+ c_name: 'adw_stylesheet',
+)
diff --git a/gtk/theme/libadwaita/widgets/_avatar.scss b/gtk/theme/libadwaita/widgets/_avatar.scss
new file mode 100644
index 0000000000..9eaea476e1
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_avatar.scss
@@ -0,0 +1,38 @@
+avatar {
+ border-radius: 9999px;
+ font-weight: bold;
+
+ // The list of colors to generate avatars.
+ // Each avatar color is represented by a font color, a gradient start color and a gradient stop color.
+ // There are 8 different colors for avtars in the list if you change the number of them you
+ // need to update the NUMBER_OF_COLORS in src/adw-avatar.c.
+ // The 2D list has this form: ((font-color, gradient-top-color, gradient-bottom-color)).
+ $avatarcolorlist: (
+ (#cfe1f5, #83b6ec, #337fdc), // blue
+ (#caeaf2, #7ad9f1, #0f9ac8), // cyan
+ (#cef8d8, #8de6b1, #29ae74), // green
+ (#e6f9d7, #b5e98a, #6ab85b), // lime
+ (#f9f4e1, #f8e359, #d29d09), // yellow
+ (#ffead1, #ffcb62, #d68400), // gold
+ (#ffe5c5, #ffa95a, #ed5b00), // orange
+ (#f8d2ce, #f78773, #e62d42), // raspberry
+ (#fac7de, #e973ab, #e33b6a), // magenta
+ (#e7c2e8, #cb78d4, #9945b5), // purple
+ (#d5d2f5, #9e91e8, #7a59ca), // violet
+ (#f2eade, #e3cf9c, #b08952), // beige
+ (#e5d6ca, #be916d, #785336), // brown
+ (#d8d7d3, #c0bfbc, #6e6d71), // gray
+ );
+
+ @for $i from 1 through length($avatarcolorlist) {
+ &.color#{$i} {
+ $avatarcolor: nth($avatarcolorlist, $i);
+ background-image: linear-gradient(nth($avatarcolor, 2), nth($avatarcolor, 3));
+ color: nth($avatarcolor, 1);
+ }
+ }
+
+ &.contrasted { color: white; }
+
+ &.image { background: none; }
+}
diff --git a/gtk/theme/libadwaita/widgets/_bottom-sheet.scss b/gtk/theme/libadwaita/widgets/_bottom-sheet.scss
new file mode 100644
index 0000000000..8d280c12e8
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_bottom-sheet.scss
@@ -0,0 +1,45 @@
+
+bottom-sheet {
+ > dimming {
+ background-color: gtkalpha($shade_color, 2);
+ }
+
+ > sheet {
+ border-top-left-radius: $window_radius;
+ border-top-right-radius: $window_radius;
+ box-shadow: 0 2px 8px 2px transparentize(black, 0.93),
+ 0 3px 20px 10px transparentize(black, 0.95),
+ 0 6px 32px 16px transparentize(black, 0.98),
+ 0 0 0 1px transparentize(black, if($contrast == 'high', .2, .95));
+
+ > drag-handle {
+ background-color: gtkalpha(currentColor, .25);
+ min-width: 60px;
+ min-height: 4px;
+ margin: 6px;
+ border-radius: 99px;
+ }
+
+ > outline {
+ border-top-left-radius: $window_radius;
+ border-top-right-radius: $window_radius;
+ box-shadow: inset 1px 0 $window_outline_color,
+ inset -1px 0 $window_outline_color,
+ inset 0 1px $window_outline_color;
+
+ &.flush-left {
+ box-shadow: inset -1px 0 $window_outline_color,
+ inset 0 1px $window_outline_color;
+ }
+
+ &.flush-right {
+ box-shadow: inset 1px 0 $window_outline_color,
+ inset 0 1px $window_outline_color;
+ }
+
+ &.flush-left.flush-right {
+ box-shadow: inset 0 1px $window_outline_color;
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_buttons.scss b/gtk/theme/libadwaita/widgets/_buttons.scss
new file mode 100644
index 0000000000..d3f7bb4e6e
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_buttons.scss
@@ -0,0 +1,628 @@
+$button_color: gtkalpha(currentColor, .1);
+$button_hover_color: gtkalpha(currentColor, .15);
+$button_active_color: gtkalpha(currentColor, .3);
+$button_checked_color: gtkalpha(currentColor, .3);
+$button_checked_hover_color: gtkalpha(currentColor, .35);
+$button_checked_active_color: gtkalpha(currentColor, .4);
+
+$opaque_button_default_bg: gtkmix($window_bg_color, $window_fg_color, 85%);
+
+%button,
+button {
+ @at-root %button_basic, & {
+ min-height: 24px;
+ min-width: 16px;
+ padding: 5px 10px;
+ border-radius: $button_radius;
+ font-weight: bold;
+
+ @include focus-ring($transition: $button_transition);
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ @at-root %button_basic_raised, & {
+ background-color: $button_color;
+
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+
+ &:hover {
+ background-color: $button_hover_color;
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background-color: $button_active_color;
+ }
+
+ &:checked {
+ background-color: $button_checked_color;
+
+ &:hover {
+ background-color: $button_checked_hover_color;
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background-color: $button_checked_active_color;
+ }
+ }
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+
+ label {
+ filter: none;
+ }
+ }
+
+ &.image-button {
+ min-width: 24px;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ &.text-button {
+ padding-left: 17px;
+ padding-right: 17px;
+ }
+
+ &.text-button.image-button,
+ &.image-text-button {
+ padding-left: 9px;
+ padding-right: 9px;
+
+ > box,
+ > box > box {
+ border-spacing: 4px;
+
+ > label {
+ padding-left: 2px;
+ padding-right: 2px;
+ }
+ }
+ }
+
+ &.arrow-button {
+ padding-left: 9px;
+ padding-right: 9px;
+
+ > box { border-spacing: 4px; }
+
+ &.text-button {
+ > box { border-spacing: 4px; }
+ }
+ }
+
+ @at-root %button_basic_drop_active,
+ &:drop(active) {
+ color: $drop_target_color;
+ box-shadow: inset 0 0 0 2px $drop_target_color;
+ }
+ }
+
+ // big standalone buttons like in Documents pager
+ @at-root %osd_button,
+ &.osd {
+ min-width: 32px;
+ min-height: 32px;
+ @include focus-ring($outer: true, $offset: 1px, $transition: $button_transition);
+
+ color: $osd_fg_color;
+ background-color: transparentize(black, .35);
+
+ @if $contrast == 'high' {
+ box-shadow: 0 0 0 1px currentColor;
+ }
+
+ &:hover {
+ color: white;
+ background-color: gtkalpha(gtkmix(black, currentColor, 85%), .65);
+ }
+
+ &.keyboard-activating,
+ &:active {
+ color: white;
+ background-color: gtkalpha(gtkmix(black, currentColor, 75%), .65);
+ }
+
+ &:checked {
+ background-color: gtkalpha(gtkmix(black, currentColor, 80%), .65);
+
+ &:hover {
+ background-color: gtkalpha(gtkmix(black, currentColor, 75%), .65);
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background-color: gtkalpha(gtkmix(black, currentColor, 65%), .65);
+ }
+ }
+
+ // Specificity bump
+ &:drop(active) {
+ @extend %button_basic_drop_active;
+ }
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+ }
+
+ @at-root %opaque_button {
+ box-shadow: none;
+
+ @include focus-ring($outer: true, $offset: 1px, $transition: $button_transition);
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ &:hover {
+ background-image: image(gtkalpha(currentColor, .1));
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background-image: image(transparentize(black, .8));
+ }
+
+ &:checked {
+ background-image: image(transparentize(black, .85));
+
+ &:hover {
+ background-image: image(transparentize(black, .95));
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background-image: image(transparentize(black, .7));
+ }
+ }
+ }
+
+ &.opaque {
+ @extend %opaque_button;
+
+ background-color: $opaque_button_default_bg;
+ color: $window_fg_color;
+ }
+
+ &.destructive-action {
+ @extend %opaque_button;
+
+ color: $destructive_fg_color;
+
+ &, &:checked {
+ background-color: $destructive_bg_color;
+ }
+ }
+
+ &.suggested-action {
+ @extend %opaque_button;
+
+ color: $accent_fg_color;
+
+ &, &:checked {
+ background-color: $accent_bg_color;
+ }
+ }
+
+ @at-root %button_basic_flat,
+ &.flat {
+ background: transparent;
+ @include focus-ring($transition: $button_transition);
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ box-shadow: none;
+
+ @if $contrast == 'high' {
+ &:hover,
+ &.keyboard-activating,
+ &:active,
+ &:checked {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+
+ &:hover {
+ background: $hover_color;
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background: $active_color;
+ }
+
+ &:checked {
+ background: $selected_color;
+
+ &:hover {
+ background: $selected_hover_color;
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background: $selected_active_color;
+ }
+ }
+
+ &:disabled:not(:checked) {
+ filter: opacity($strong_disabled_opacity);
+ }
+
+ // Specificity bump
+ &:drop(active) {
+ @extend %button_basic_drop_active;
+ }
+ }
+
+ stackswitcher > & {
+ // to position the needs attention dot, padding is added to the button
+ // child, a label needs just lateral padding while an icon needs vertical
+ // padding added too.
+
+ > label {
+ padding: 0 6px;
+ margin: 0 -6px;
+ }
+
+ > image {
+ padding: 3px 6px;
+ margin: -3px -6px;
+ }
+
+ &.text-button { min-width: 100px; }
+
+ &.needs-attention {
+ > label,
+ > image { @extend %needs_attention; }
+ }
+ }
+
+ // hide separators
+ &.font {
+ separator { background-color: transparent; }
+ > box { border-spacing: 6px; }
+ > box > box > label { font-weight: bold; }
+ }
+
+ @at-root %circular_button,
+ &.circular { // force circular button shape
+ min-width: 34px;
+ min-height: 34px;
+ padding: 0;
+ border-radius: 9999px;
+
+ label { padding: 0; }
+ }
+
+ @at-root %pill_button,
+ &.pill {
+ padding: 10px 32px;
+ border-radius: 9999px;
+ }
+
+ &.card {
+ background-color: $card_bg_color;
+ background-clip: padding-box;
+ font-weight: inherit;
+ padding: 0;
+
+ @include focus-ring($offset: -1px, $transition: $button_transition);
+
+ &:hover {
+ background-image: image($view_hover_color);
+ }
+
+ &.keyboard-activating,
+ &:active {
+ background-image: image($view_active_color);
+ }
+
+ &:checked {
+ background-color: $card_bg_color;
+ background-image: image($view_selected_color);
+
+ &:hover { background-image: image($view_selected_hover_color); }
+
+ &.keyboard-activating,
+ &:active { background-image: image($view_selected_active_color); }
+
+ &.has-open-popup { background-image: image($view_selected_hover_color); }
+
+ .osd & {
+ background-color: gtkalpha(currentColor, .1);
+ }
+ }
+
+ &:drop(active) {
+ color: $drop_target_color;
+ box-shadow: inset 0 0 0 1px $drop_target_color;
+ }
+ }
+}
+
+%undecorated_button {
+ background-color: transparent;
+}
+
+button.color {
+ padding: 5px;
+
+ > colorswatch:only-child {
+ border-radius: 2.5px;
+
+ > overlay {
+ border-radius: 2px;
+ }
+
+ &:disabled {
+ filter: none;
+ }
+
+ &.light > overlay {
+ border-color: gtkalpha($view_fg_color, 0.1);
+ }
+ }
+}
+
+menubutton {
+ &.osd {
+ background: none;
+ color: inherit;
+
+ > button { @extend %osd_button; }
+ }
+
+ &.circular > button { @extend %circular_button; }
+ &.flat > button { @extend %button_basic_flat; }
+ &.pill > button { @extend %pill_button; }
+
+ &.suggested-action {
+ background-color: $accent_bg_color;
+ color: $accent_fg_color;
+ }
+
+ &.destructive-action {
+ background-color: $destructive_bg_color;
+ color: $destructive_fg_color;
+ }
+
+ &.opaque {
+ background-color: $opaque_button_default_bg;
+ color: $window_fg_color;
+ }
+
+ &.suggested-action,
+ &.destructive-action,
+ &.opaque {
+ border-radius: $button_radius;
+
+ &.circular, &.pill {
+ border-radius: 9999px;
+ }
+
+ > button {
+ @extend %opaque_button;
+
+ &, &:checked {
+ background-color: transparent;
+ color: inherit;
+ }
+ }
+ }
+
+ &.image-button > button {
+ min-width: 24px;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ &.card > button {
+ border-radius: $card_radius;
+ }
+
+ arrow {
+ min-height: 16px;
+ min-width: 16px;
+ &.none {
+ -gtk-icon-source: -gtk-icontheme('open-menu-symbolic');
+ }
+ &.down {
+ -gtk-icon-source: -gtk-icontheme('pan-down-symbolic');
+ }
+ &.up {
+ -gtk-icon-source: -gtk-icontheme('pan-up-symbolic');
+ }
+ &.left {
+ -gtk-icon-source: -gtk-icontheme('pan-start-symbolic');
+ }
+ &.right {
+ -gtk-icon-source: -gtk-icontheme('pan-end-symbolic');
+ }
+ }
+}
+
+splitbutton {
+ border-radius: $button_radius;
+
+ &, & > separator {
+ transition: $button_transition;
+ transition-property: background;
+ }
+
+ > separator {
+ margin-top: 6px;
+ margin-bottom: 6px;
+ background: none;
+ }
+
+ > menubutton > button {
+ padding-left: 4px;
+ padding-right: 4px;
+ }
+
+ // Since the inner button doesn't have any style classes on it,
+ // we have to add them manually
+ &.image-button > button {
+ min-width: 24px;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ &.text-button.image-button > button,
+ &.image-text-button > button {
+ padding-left: 9px;
+ padding-right: 9px;
+
+ > box {
+ border-spacing: 6px;
+ }
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+
+ > button, > menubutton > button {
+ filter: none;
+ }
+ }
+
+ // Reimplementing linked so we don't blow up css
+ > button:dir(ltr),
+ > menubutton > button:dir(rtl) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ margin-right: -1px;
+ }
+
+ > button:dir(rtl),
+ > menubutton > button:dir(ltr) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ margin-left: -1px;
+ }
+
+ @at-root %flat_split_button,
+ &.flat {
+ > separator {
+ background: gtkalpha(currentColor, $dimmer_opacity);
+ }
+
+ &:hover,
+ &:active,
+ &:checked {
+ background: $hover_color;
+
+ > separator {
+ background: none;
+ }
+
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 1px $thin_border_color;
+ }
+ }
+
+ &:disabled {
+ filter: opacity($strong_disabled_opacity);
+
+ > button:disabled, > menubutton > button:disabled {
+ filter: none;
+ }
+ }
+
+ &:focus-within:focus-visible > separator {
+ background: none;
+ }
+
+ > button,
+ > menubutton > button {
+ @extend %button_basic_flat;
+
+ border-radius: $button_radius;
+ }
+ }
+
+ &.suggested-action {
+ background-color: $accent_bg_color;
+ color: $accent_fg_color;
+ }
+
+ &.destructive-action {
+ background-color: $destructive_bg_color;
+ color: $destructive_fg_color;
+ }
+
+ &.opaque {
+ background-color: $opaque_button_default_bg;
+ color: $window_fg_color;
+ }
+
+ &.suggested-action,
+ &.destructive-action,
+ &.opaque {
+ > button, > menubutton > button {
+ @extend %opaque_button;
+
+ &, &:checked {
+ color: inherit;
+ background-color: transparent;
+ }
+ }
+
+ $_separator_color: gtkalpha(currentColor, $dimmer_opacity);
+ > menubutton > button {
+ &:dir(ltr) { box-shadow: inset 1px 0 $_separator_color; }
+ &:dir(rtl) { box-shadow: inset -1px 0 $_separator_color; }
+ }
+ }
+
+ > menubutton > button > arrow.none {
+ -gtk-icon-source: -gtk-icontheme('pan-down-symbolic');
+ }
+}
+
+buttoncontent {
+ > box {
+ border-spacing: 6px;
+
+ > label {
+ font-weight: bold;
+
+ &:dir(ltr) { padding-right: 2px; }
+ &:dir(rtl) { padding-left: 2px; }
+ }
+ }
+
+ .arrow-button > box > &,
+ splitbutton > button > & {
+ > box > label {
+ &:dir(ltr) { padding-right: 0; }
+ &:dir(rtl) { padding-left: 0; }
+ }
+ }
+}
+
+tabbutton {
+ label {
+ font-weight: 800;
+ font-size: 8pt;
+
+ &.small {
+ font-size: 6pt;
+ }
+ }
+
+ indicatorbin > indicator,
+ indicatorbin > mask {
+ transform: translate(-1px, 1px);
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_calendar.scss b/gtk/theme/libadwaita/widgets/_calendar.scss
new file mode 100644
index 0000000000..e2fdc04c71
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_calendar.scss
@@ -0,0 +1,54 @@
+calendar {
+ color: $view_fg_color;
+ background-clip: padding-box;
+ border: 1px solid $border_color;
+ font-feature-settings: "tnum";
+
+ > header {
+ border-bottom: 1px solid $border_color;
+
+ > button {
+ @extend %button_basic_flat;
+ border-radius: 0;
+ }
+ }
+
+ > grid {
+ padding-left: 3px;
+ padding-bottom: 3px;
+
+ > label.today {
+ box-shadow: inset 0px -2px $border_color;
+
+ &:selected {
+ box-shadow: none;
+ }
+ }
+
+ > label {
+ @include focus-ring($focus-state: ':focus');
+ margin-top: 3px;
+ margin-right: 3px;
+
+ &.day-number {
+ padding: 3px;
+
+ &:checked {
+ border-radius: $button_radius;
+ background-color: gtkalpha($accent_bg_color, 0.3);
+ }
+
+ &:selected {
+ border-radius: $button_radius;
+
+ background-color: $accent_bg_color;
+ color: $accent_fg_color;
+ }
+ }
+
+ &.day-number.other-month {
+ color: gtkalpha(currentColor, 0.3);
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_checks.scss b/gtk/theme/libadwaita/widgets/_checks.scss
new file mode 100644
index 0000000000..d87f675007
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_checks.scss
@@ -0,0 +1,104 @@
+checkbutton {
+ border-spacing: 4px;
+ border-radius: $button_radius + 3px;
+ padding: 3px;
+
+ @include focus-ring();
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ &.text-button {
+ // this is for a nice focus on check and radios text
+ padding: 4px;
+ }
+}
+
+check,
+radio {
+ min-height: 14px;
+ min-width: 14px;
+ -gtk-icon-size: 14px;
+ padding: 3px;
+
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 2px $border_color;
+ } @else {
+ box-shadow: inset 0 0 0 2px $trough_color;
+ }
+
+ &:not(:checked):not(:indeterminate) {
+ &:hover {
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 2px gtkalpha(currentColor, .6);
+ } @else {
+ box-shadow: inset 0 0 0 2px $trough_hover_color;
+ }
+ }
+
+ &:active {
+ @if $contrast == 'high' {
+ background-color: gtkalpha(currentColor, .6);
+ } @else {
+ background-color: $trough_active_color;
+ }
+ box-shadow: none;
+ }
+ }
+
+ &:checked,
+ &:indeterminate {
+ background-color: $fill_color;
+ color: $fill_text_color;
+ box-shadow: none;
+
+ &:hover { background-image: image(gtkalpha(currentColor, .1)); }
+ &:active { background-image: image(transparentize(black, .8)); }
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ .osd & {
+ &:checked,
+ &:indeterminate {
+ background-color: $osd_fill_bg_color;
+ color: $osd_fill_fg_color;
+ }
+ }
+}
+
+check {
+ border-radius: $button_radius;
+
+ &:checked { -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/check-symbolic.symbolic.png")),
+ -gtk-recolor(url("assets/check@2-symbolic.symbolic.png"))); }
+}
+
+radio {
+ border-radius: 100%;
+
+ &:checked { -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/bullet-symbolic.symbolic.png")),
+ -gtk-recolor(url("assets/bullet@2-symbolic.symbolic.png"))); }
+}
+
+check, radio {
+ &:indeterminate { -gtk-icon-source: -gtk-scaled(-gtk-recolor(url("assets/dash-symbolic.symbolic.png")),
+ -gtk-recolor(url("assets/dash@2-symbolic.symbolic.png"))); }
+}
+
+checkbutton.selection-mode {
+ border-radius: 100px;
+
+ check, radio {
+ padding: 7px;
+ border-radius: 100px;
+ }
+
+ label {
+ &:dir(ltr) { margin-right: 6px; }
+ &:dir(rtl) { margin-left: 6px; }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_color-chooser.scss b/gtk/theme/libadwaita/widgets/_color-chooser.scss
new file mode 100644
index 0000000000..514d33e851
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_color-chooser.scss
@@ -0,0 +1,109 @@
+colorswatch {
+ // This widget is made of two boxes one on top of the other, the lower box is colorswatch {} the other one
+ // is colorswatch overlay {}, colorswatch has the programmatically set background, so most of the style is
+ // applied to the overlay box.
+
+ @include focus-ring($width: 4px, $offset: -2px);
+
+ // base color corners rounding
+ // to avoid the artifacts caused by rounded corner anti-aliasing the base color
+ // sports a bigger radius.
+ // nth-child is needed by the custom color strip.
+
+ &.top {
+ border-top-left-radius: $button_radius + 0.5px;
+ border-top-right-radius: $button_radius + 0.5px;
+
+ > overlay {
+ border-top-left-radius: $button_radius;
+ border-top-right-radius: $button_radius;
+ }
+ }
+
+ &.bottom {
+ border-bottom-left-radius: $button_radius + 0.5px;
+ border-bottom-right-radius: $button_radius + 0.5px;
+
+ > overlay {
+ border-bottom-left-radius: $button_radius;
+ border-bottom-right-radius: $button_radius;
+ }
+ }
+
+ &.left,
+ &:first-child:not(.top) {
+ border-top-left-radius: $button_radius + 0.5px;
+ border-bottom-left-radius: $button_radius + 0.5px;
+
+ > overlay {
+ border-top-left-radius: $button_radius;
+ border-bottom-left-radius: $button_radius;
+ }
+ }
+
+ &.right,
+ &:last-child:not(.bottom) {
+ border-top-right-radius: $button_radius + 0.5px;
+ border-bottom-right-radius: $button_radius + 0.5px;
+
+ > overlay {
+ border-top-right-radius: $button_radius;
+ border-bottom-right-radius: $button_radius;
+ }
+ }
+
+ @if $contrast == 'high' {
+ > overlay {
+ box-shadow: inset 0 0 0 1px gtkalpha($view_fg_color, .5);
+ }
+ }
+
+ &.dark > overlay {
+ color: white;
+ }
+
+ &.light > overlay {
+ color: transparentize(black, .25);
+
+ @if $contrast != 'high' {
+ box-shadow: inset 0 0 0 1px gtkalpha($view_fg_color, 0.1);
+ }
+ }
+
+ &:drop(active) {
+ &.light > overlay {
+ box-shadow: inset 0 0 0 2px $drop_target_color;
+ }
+
+ &.dark > overlay {
+ box-shadow: inset 0 0 0 2px $drop_target_color;
+ }
+ }
+
+ add-color-button {
+ > overlay {
+ @extend %button_basic;
+
+ border-radius: $button_radius 0 0 $button_radius;
+ }
+
+ &:only-child > overlay { border-radius: $button_radius; }
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ editor-color-sample {
+ border-radius: $button_radius;
+
+ > overlay { border-radius: $button_radius + 0.5px; }
+ }
+}
+
+plane {
+ @include focus-ring($offset: 2px, $outer: true);
+}
+
+// colorscale popup
+colorchooser .popover.osd { border-radius: $popover_radius; }
diff --git a/gtk/theme/libadwaita/widgets/_column-view.scss b/gtk/theme/libadwaita/widgets/_column-view.scss
new file mode 100644
index 0000000000..422442e57c
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_column-view.scss
@@ -0,0 +1,115 @@
+columnview {
+ @include focus-ring();
+
+ &:drop(active) {
+ box-shadow: none;
+ }
+
+ > header > button {
+ @extend %undecorated_button;
+ padding-top: 3px;
+ padding-bottom: 3px;
+ padding-left: 6px;
+ padding-right: 6px;
+ border-radius: 0;
+ box-shadow: none;
+ line-height: 100%;
+ border-left: 1px solid transparent;
+
+ &:first-child {
+ border-left-width: 0;
+ }
+
+ > box {
+ color: gtkalpha(currentColor, if($contrast == 'high', .6, .4));
+ font-weight: 700;
+ font-size: 9pt;
+ border-spacing: 6px;
+ }
+
+ &:hover > box {
+ color: gtkalpha(currentColor, if($contrast == 'high', .9, .7));
+ box-shadow: none;
+ }
+
+ &:active > box {
+ color: currentColor;
+ }
+
+ sort-indicator {
+ &.ascending {
+ -gtk-icon-source: -gtk-icontheme('pan-up-symbolic');
+ }
+ &.descending {
+ -gtk-icon-source: -gtk-icontheme('pan-down-symbolic');
+ }
+
+ min-height: 16px;
+ min-width: 16px;
+ }
+ }
+
+ button.dnd,
+ header.button.dnd { // for treeview-like derive widgets
+ &:active, &:selected, &:hover, & {
+ color: $accent_fg_color;
+ background-color: $accent_bg_color;
+ transition: none;
+ }
+ }
+
+ // Remove the default background of the internal list view
+ // since we already apply a background to the column view
+ // with the .view class. Doing this will avoid overdraw.
+ &.view > listview.view {
+ background: none;
+ color: inherit;
+ }
+
+ // move padding to child cells
+ > listview > row {
+ padding: 0;
+
+ // align horizontal sizing with header buttons
+ > cell {
+ padding: 8px 6px;
+
+ &:not(:first-child) {
+ border-left: 1px solid transparent;
+ }
+ }
+ }
+
+ // make column separators visible when :show-column-separators is true
+ &.column-separators {
+ > listview > row > cell,
+ > header > button {
+ border-left-color: $border_color;
+ }
+ }
+
+ > listview:not(.horizontal).separators > row:not(.separator) {
+ border-top: 1px solid $border_color;
+ border-bottom: none;
+ }
+
+ // shrink vertically for .data-table
+ &.data-table > listview > row > cell {
+ padding-top: 2px;
+ padding-bottom: 2px;
+ }
+
+ @include undershoot(top, $shade_color, true);
+}
+
+columnview row:not(:selected) cell editablelabel:not(.editing):focus-within {
+ outline: 2px solid $focus_border_color;
+}
+
+columnview row:not(:selected) cell editablelabel.editing:focus-within {
+ outline: 2px solid $accent_color;
+}
+
+treeexpander {
+ border-spacing: 4px;
+}
diff --git a/gtk/theme/libadwaita/widgets/_deprecated.scss b/gtk/theme/libadwaita/widgets/_deprecated.scss
new file mode 100644
index 0000000000..faefe5765c
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_deprecated.scss
@@ -0,0 +1,343 @@
+// The following styles are deprecated in GTK and should be removed for GTK 5.x
+
+// .linked > element child
+$deprecated_linked_widgets: ("combobox", "> box > button.combo"),
+ ("appchooserbutton", "> combobox > box > button.combo");
+
+/***********************
+ * GtkAppChooserDialog *
+ ***********************/
+
+window.appchooser {
+ headerbar.titlebar {
+ @extend .flat;
+ @extend %headerbar-shrunk;
+
+ > windowhandle {
+ padding-top: 3px;
+ }
+
+ box.start + box {
+ margin-top: -6px;
+ margin-bottom: -6px;
+ min-height: 12px;
+ }
+ }
+
+ searchbar {
+ @extend %searchbar-flat;
+
+ background: none;
+ }
+
+ &.csd searchbar {
+ @extend %searchbar-shrunk;
+ }
+
+ .dialog-vbox > box > box:not(.dialog-action-area) {
+ margin: 6px;
+ }
+
+ .dialog-action-area {
+ margin-top: 0;
+ }
+}
+
+/****************
+ * GtkAssistant *
+ ****************/
+
+window.assistant {
+ .sidebar {
+ padding: $menu-margin;
+ background-color: $sidebar_bg_color;
+ color: $sidebar_fg_color;
+
+ &:not(separator) {
+ &:dir(ltr) {
+ border-right: none;
+ box-shadow: inset -1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+ }
+
+ &:dir(rtl) {
+ box-shadow: inset 1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+ }
+ }
+
+ &:backdrop {
+ background-color: $sidebar_backdrop_color;
+ transition: background-color $backdrop_transition;
+ }
+
+ > label {
+ padding: 6px 12px;
+ border-radius: $menu_radius;
+
+ &.highlight {
+ background-color: $selected_color;
+
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+ }
+ }
+}
+
+/***************
+ * GtkComboBox *
+ ***************/
+
+combobox {
+ @extend dropdown;
+
+ // Since cell view is taller than a plain label, make sure
+ // the button doesn't get stretched with a larger font
+ button {
+ padding-top: 2px;
+ padding-bottom: 2px;
+ min-height: 30px;
+ }
+}
+
+/***************
+ * GtkIconView *
+ ***************/
+
+iconview {
+ @extend %view;
+
+ @if $contrast == 'high' {
+ &:selected {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+
+ @include focus-ring();
+
+ &:drop(active) {
+ box-shadow: none;
+ }
+
+ > dndtarget:drop(active) {
+ border-style: solid;
+ border-width: 1px;
+ border-color: $drop_target_color;
+ }
+}
+
+/**************
+ * GtkInfoBar *
+ **************/
+
+infobar {
+ > revealer > box {
+ padding: 6px;
+ padding-bottom: 7px;
+ border-spacing: 6px;
+ box-shadow: inset 0 -1px if($contrast == 'high', $border_color, $shade_color);
+
+ > box {
+ border-spacing: 6px;
+ }
+ }
+
+ &.action:hover > revealer > box {
+ background-image: image(gtkalpha(currentColor, .05));
+ }
+
+ &.action:active > revealer > box {
+ background-image: image(gtkalpha(currentColor, .1));
+ }
+
+ @each $i_type, $i_color in (info, $accent_bg_color),
+ (question, $accent_bg_color),
+ (warning, $warning_bg_color),
+ (error, $error_bg_color) {
+ &.#{$i_type} > revealer > box {
+ background-color: gtkmix($i_color, $window_bg_color, 30%);
+ color: $window_fg_color;
+ }
+ }
+
+ .close {
+ min-width: 18px;
+ min-height: 18px;
+ padding: 4px;
+ border-radius: 50%;
+ @extend %button_basic_flat;
+ }
+}
+
+/****************
+ * GtkStatusBar *
+ ****************/
+
+statusbar {
+ padding: 6px 10px 6px 10px;
+}
+
+/***************
+ * GtkTreeView *
+ ***************/
+
+// To be used for opaque elements overlaid atop the selected row
+$treeview_selection_opaque: gtkmix(currentColor, $view_bg_color, 10%);
+$treeview_borders_opaque: gtkmix(currentColor, $view_bg_color, if($contrast == 'high', 40%, 20%));
+
+treeview.view {
+ @extend columnview;
+
+ border-left-color: $treeview_borders_opaque; // this is actually the tree lines color,
+ border-top-color: $treeview_borders_opaque; // while this is the grid lines color, better then nothing
+
+ &:selected {
+ &:focus, & {
+ border-radius: 0;
+ }
+ }
+
+ &.separator {
+ min-height: 2px;
+ color: $border_color;
+ }
+
+ &.expander {
+ // GtkTreeView uses the larger of the expander’s min-width and min-height
+ min-width: 16px;
+ min-height: 16px;
+ -gtk-icon-source: -gtk-icontheme('pan-end-symbolic');
+
+ &:dir(rtl) { -gtk-icon-source: -gtk-icontheme('pan-end-symbolic-rtl'); }
+
+ color: gtkalpha(currentColor, .7);
+
+ &:hover, &:active { color: currentColor; }
+
+ &:checked { -gtk-icon-source: -gtk-icontheme('pan-down-symbolic'); }
+
+ &:disabled { color: gtkalpha(currentColor, $disabled_opacity); }
+ }
+
+ > dndtarget:drop(active) {
+ border-style: solid none;
+ border-width: 1px;
+ border-color: $drop_target_color;
+
+ &.after { border-top-style: none; }
+
+ &.before { border-bottom-style: none; }
+ }
+
+ > header > button {
+ padding-left: 4px;
+ padding-right: 4px;
+ border-bottom: 1px solid $border_color;
+ }
+
+ &.progressbar { // progress bar in treeviews
+ &, &:selected {
+ background-color: $accent_bg_color;
+ color: $accent_fg_color;
+ }
+
+ box-shadow: none;
+ }
+
+ &.trough { // progress bar trough in treeviews
+ background-color: gtkalpha(currentColor, 0.1);
+ }
+
+ ~ undershoot.top {
+ box-shadow: none;
+ background: none;
+ }
+
+ acceleditor > label {
+ // see tests/testaccel in GTK to test
+ background-color: $treeview_selection_opaque;
+ }
+}
+
+treeview.navigation-sidebar {
+ padding: 0;
+
+ &:selected {
+ &:focus, & {
+ background-color: $selected_color;
+ }
+ }
+}
+
+treeview entry {
+ &:focus-within {
+ &:dir(rtl), &:dir(ltr) { // specificity bump hack
+ background-color: $view_bg_color;
+ transition-property: color, background;
+ }
+ }
+
+ &.flat, & {
+ border-radius: 0;
+ background-image: none;
+ background-color: $view_bg_color;
+
+ &:focus-within { border-color: $accent_color; }
+ }
+}
+
+treeview spinbutton:not(.vertical) {
+ min-height: 0;
+ border-style: none;
+ border-radius: 0;
+
+ > text {
+ min-height: 0;
+ padding: 1px 2px;
+ }
+}
+
+// The following styles are deprecated in libadwaita and should be removed in 2.x
+
+// Deprecated: use .boxed-list instead
+list.content {
+ @extend .boxed-list;
+}
+
+// Deprecated: use .navigation-sidebar instead
+.sidebar {
+ &:not(separator) {
+ &:dir(ltr),
+ &.left,
+ &.left:dir(rtl) {
+ border-right: 1px solid $border_color;
+ border-left-style: none;
+ }
+
+ &:dir(rtl),
+ &.right {
+ border-left: 1px solid $border_color;
+ border-right-style: none;
+ }
+ }
+
+ listview.view,
+ list {
+ background-color: transparent;
+ color: inherit;
+ }
+
+ paned & { &.left, &.right, &.left:dir(rtl), &:dir(rtl), &:dir(ltr), & { border-style: none; }}
+}
+
+// Deprecated: use .title-1
+.large-title {
+ font-weight: 300;
+ font-size: 24pt;
+}
+
+// Deprecated: use AdwToolbarView
+
+headerbar.flat {
+ @extend %headerbar-flat;
+}
diff --git a/gtk/theme/libadwaita/widgets/_dialogs.scss b/gtk/theme/libadwaita/widgets/_dialogs.scss
new file mode 100644
index 0000000000..3ff6b00040
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_dialogs.scss
@@ -0,0 +1,125 @@
+.dialog-action-area {
+ margin: 6px;
+ border-spacing: 6px;
+}
+
+/****************
+ * Print dialog *
+*****************/
+
+window.print {
+ drawing {
+ color: $window_fg_color;
+ background: none;
+ border: none;
+ padding: 0;
+
+ paper {
+ background-color: white;
+ color: transparentize(black, .2);
+ background-clip: padding-box;
+ border: 1px solid $border_color;
+ }
+ }
+
+ headerbar.titlebar {
+ @extend .flat;
+ }
+
+ .dialog-action-box {
+ @extend .view;
+ }
+}
+
+/********************
+ * Page setup dalog *
+ ********************/
+
+window.pagesetup {
+ headerbar.titlebar {
+ @extend .flat;
+ }
+}
+
+/******************
+ * GtkAboutDialog *
+ ******************/
+
+window.aboutdialog {
+ headerbar.titlebar {
+ @extend .flat;
+ }
+
+ image.large-icons {
+ -gtk-icon-size: 128px;
+ }
+}
+
+/*************************
+ * GtkColorChooserDialog *
+ *************************/
+window.colorchooser {
+ headerbar.titlebar {
+ @extend .flat;
+ }
+}
+
+/*************
+ * AdwDialog *
+ *************/
+
+floating-sheet {
+ > dimming {
+ background-color: gtkalpha($shade_color, 2);
+ }
+
+ > sheet {
+ border-radius: $window_radius;
+ box-shadow: 0 2px 8px 2px transparentize(black, 0.93),
+ 0 3px 20px 10px transparentize(black, 0.95),
+ 0 6px 32px 16px transparentize(black, 0.98),
+ 0 0 0 1px transparentize(black, if($contrast == 'high', .2, .95));
+ outline: 1px solid $window_outline_color;
+ outline-offset: -1px;
+ }
+}
+
+dialog.bottom-sheet {
+ &.landscape sheet {
+ margin-left: 30px;
+ margin-right: 30px;
+
+ > outline {
+ &.flush-left, &.flush-right, &.flush-left.flush-right {
+ box-shadow: inset 1px 0 $window_outline_color,
+ inset -1px 0 $window_outline_color,
+ inset 0 1px $window_outline_color;
+ }
+ }
+ }
+}
+
+dialog-host > dialog.background {
+ background: none;
+
+ sheet {
+ background-color: $window_bg_color;
+ color: $window_fg_color;
+ }
+}
+
+dialog-host > dialog.view {
+ background: none;
+
+ sheet {
+ @extend %view;
+ }
+}
+
+dialog-host > dialog.osd {
+ background: none;
+
+ sheet {
+ @extend %osd;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_dropdowns.scss b/gtk/theme/libadwaita/widgets/_dropdowns.scss
new file mode 100644
index 0000000000..efdb07b7de
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_dropdowns.scss
@@ -0,0 +1,38 @@
+dropdown {
+ > button > box {
+ border-spacing: 6px;
+
+ > stack > row.activatable {
+ &:hover, &:active { background: none; }
+ }
+ }
+
+ arrow {
+ -gtk-icon-source: -gtk-icontheme('pan-down-symbolic');
+ min-height: 16px;
+ min-width: 16px;
+ }
+
+ &:drop(active) { // FIXME: untested
+ box-shadow: none;
+
+ button.combo { @extend %button_basic_drop_active; }
+ }
+
+ popover.menu {
+ padding-top: 6px;
+
+ listview > row {
+ min-width: 0;
+ }
+
+ // dropdowns with searchboxes on top
+ .dropdown-searchbar {
+ padding: 6px;
+
+ + scrolledwindow {
+ @include undershoot(top, $popover_shade_color);
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_emoji-chooser.scss b/gtk/theme/libadwaita/widgets/_emoji-chooser.scss
new file mode 100644
index 0000000000..b52ffac717
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_emoji-chooser.scss
@@ -0,0 +1,91 @@
+popover.emoji-picker > contents {
+ padding: 0;
+}
+
+.emoji-searchbar {
+ padding: 6px;
+}
+
+.emoji-toolbar {
+ // flowbox children already have 3px padding, so we only need 3px more to
+ // get the regular 6px. We also don't need spacing, for the same reason.
+ padding: 3px;
+}
+
+button.emoji-section.image-button:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ @extend %circular_button;
+ @extend %button_basic_flat;
+
+ min-width: 32px;
+ min-height: 32px;
+}
+
+popover.emoji-picker emoji {
+ font-size: x-large;
+ padding: 6px;
+ border-radius: $button_radius;
+
+ &:focus,
+ &:hover {
+ background: $hover_color;
+ }
+
+ &:active {
+ background: $active_color;
+ }
+
+ @if $contrast == 'high' {
+ &:focus,
+ &:hover,
+ &:active {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+}
+
+popover.emoji-picker scrolledwindow.view {
+ background: none;
+ color: inherit;
+
+ @include undershoot(top, $popover_shade_color);
+ @include undershoot(bottom, $popover_shade_color);
+}
+
+// Emoji completion popover
+
+popover.emoji-completion > contents {
+ padding: $menu_margin;
+ padding-bottom: $menu_margin - 2px;
+}
+
+emoji-completion-row {
+ // emoji extends quite a bit into the padding, so we can't use the same padding on all sides
+ padding: $menu_padding - 6px;
+ margin-bottom: 2px;
+ border-radius: $menu_radius;
+
+ &:dir(ltr) { padding-right: $menu_padding; }
+ &:dir(rtl) { padding-left: $menu_padding; }
+
+ > box {
+ border-spacing: $menu_padding - 6px;
+ }
+
+ &:focus,
+ &:hover {
+ background-color: $selected_color;
+ color: $popover_fg_color;
+ }
+
+ &:active {
+ background-color: $active_color; // matching buttons
+ }
+
+ @if $contrast == 'high' {
+ &:focus,
+ &:hover,
+ &:active {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_entries.scss b/gtk/theme/libadwaita/widgets/_entries.scss
new file mode 100644
index 0000000000..271294edb7
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_entries.scss
@@ -0,0 +1,107 @@
+%entry,
+entry {
+ %entry_basic, & {
+ min-height: 34px;
+ padding-left: 9px;
+ padding-right: 9px;
+ border-radius: $button_radius;
+ border-spacing: 6px;
+ background-color: $button_color;
+ background-clip: padding-box;
+ caret-color: currentColor;
+
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+
+ @include focus-ring($focus-state: ':focus-within');
+
+ .osd &:focus-within {
+ outline-color: $osd_focus_color;
+ }
+
+ > text {
+ > placeholder {
+ @extend .dim-label;
+ }
+
+ > block-cursor {
+ color: $view_bg_color;
+ background-color: $view_fg_color;
+ }
+ }
+
+ &.flat {
+ &:focus-within, &:disabled, & {
+ min-height: 0;
+ padding: 2px;
+ background-color: transparent;
+ box-shadow: none;
+ border-radius: 0;
+ }
+ }
+
+ &:disabled { filter: opacity($disabled_opacity); }
+
+ // entry error and warning style
+ @each $e_type, $e_color in (error, $error_color),
+ (warning, $warning_color),
+ (success, $success_color) {
+ &.#{$e_type} {
+ @include focus-ring($focus-state: ':focus-within', $fc: gtkalpha(currentColor, $focus_border_opacity));
+
+ > text {
+ > selection:focus-within { background-color: gtkalpha($e_color, .2); }
+
+ > cursor-handle > contents { background-color: currentColor; }
+ }
+
+ > progress > trough > progress {
+ border-color: currentColor;
+ }
+ }
+ }
+
+ > image { // icons inside the entry
+ opacity: if($contrast == 'high', .85, .7);
+
+ &:hover { opacity: 1; }
+
+ &:active {
+ opacity: if($contrast == 'high', .9, .8);
+ }
+
+ &.left { margin-right: 6px; }
+ &.right { margin-left: 6px; }
+ }
+
+ &.password image.caps-lock-indicator {
+ opacity: $dimmer_opacity;
+ }
+
+ &:drop(active) {
+ &:focus-within, & {
+ border-color: $drop_target_color;
+ box-shadow: inset 0 0 0 1px $drop_target_color;
+ }
+ }
+ }
+
+ > progress {
+ margin-bottom: 3px;
+
+ > trough > progress {
+ background-color: transparent;
+ background-image: none;
+ border-radius: 0;
+ border-width: 0 0 2px;
+ border-color: $accent_bg_color;
+ border-style: solid;
+ box-shadow: none;
+ }
+ }
+
+ .osd & > progress > trough > progress {
+ border-color: $osd_fill_bg_color;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_expanders.scss b/gtk/theme/libadwaita/widgets/_expanders.scss
new file mode 100644
index 0000000000..77de60c74b
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_expanders.scss
@@ -0,0 +1,27 @@
+expander {
+ min-width: 16px;
+ min-height: 16px;
+ -gtk-icon-source: -gtk-icontheme('pan-end-symbolic');
+ &:dir(rtl) { -gtk-icon-source: -gtk-icontheme('pan-end-symbolic-rtl'); }
+
+ &:disabled { filter: opacity($disabled_opacity); }
+
+ &:checked { -gtk-icon-source: -gtk-icontheme('pan-down-symbolic'); }
+}
+
+expander-widget {
+ @include focus-ring("> box > title");
+
+ > box > title {
+ border-radius: $button_radius;
+
+ > expander {
+ opacity: .7;
+ }
+
+ &:hover > expander,
+ &:active > expander {
+ opacity: 1;
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_file-chooser.scss b/gtk/theme/libadwaita/widgets/_file-chooser.scss
new file mode 100644
index 0000000000..49455c646d
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_file-chooser.scss
@@ -0,0 +1,230 @@
+placessidebar {
+ .navigation-sidebar > row {
+ // Needs overriding of the `.navigation-sidebar > row` padding
+ padding: 0;
+
+ // Using margins/padding directly in the SidebarRow
+ // will make the animation of the new bookmark row jump
+ > revealer { padding: 0 14px; }
+
+ image.sidebar-icon {
+ &:dir(ltr) { padding-right: 8px; }
+ &:dir(rtl) { padding-left: 8px; }
+ }
+
+ label.sidebar-label {
+ &:dir(ltr) { padding-right: 2px; }
+ &:dir(rtl) { padding-left: 2px; }
+ }
+
+ @at-root button.sidebar-button {
+ @extend %button_basic_flat;
+
+ min-height: 26px;
+ min-width: 26px;
+ margin-top: 3px;
+ margin-bottom: 3px;
+ padding: 0;
+ border-radius: 100%;
+ }
+
+ // in the sidebar case it makes no sense to click the selected row
+ &:selected:active { box-shadow: none; }
+
+ &.sidebar-placeholder-row {
+ padding: 0 8px;
+ min-height: 2px;
+ background-image: image($drop_target_color);
+ background-clip: content-box;
+ }
+
+ &.sidebar-new-bookmark-row { color: $accent_color; }
+
+ &:drop(active):not(:disabled) {
+ color: $drop_target_color;
+ box-shadow: inset 0 0 0 1px $drop_target_color;
+ }
+ }
+}
+
+row {
+ image.sidebar-icon {
+ opacity: 0.7; // see bug #786613 for details on this oddity
+ }
+
+ .sidebar-button {
+ opacity: 0.7;
+
+ &:hover,
+ &:active,
+ &.keyboard-activating {
+ opacity: 1;
+ }
+ }
+}
+
+placesview {
+ .server-list-button > image {
+ transition: -gtk-icon-transform 200ms $ease-out-quad;
+ -gtk-icon-transform: rotate(0turn);
+ }
+
+ .server-list-button:checked > image {
+ -gtk-icon-transform: rotate(-0.5turn);
+ }
+
+ > actionbar > revealer > box > box {
+ border-spacing: 6px;
+ }
+}
+
+filechooser {
+ box-shadow: 0 1px $border_color;
+
+ // Make the toolbar buttons flat like on an actual toolbar
+ #pathbarbox > stack > box > {
+ button,
+ box > button,
+ menubutton > button {
+ @extend %button_basic_flat;
+ }
+ }
+
+ pathbar button {
+ &:not(.image-button) {
+ padding-left: 9px;
+ padding-right: 9px;
+ }
+
+ // Icon + label buttons
+ > box {
+ border-spacing: 4px;
+
+ > label {
+ padding-left: 2px;
+ padding-right: 2px;
+ }
+ }
+ }
+
+ columnview > listview > row > cell {
+ padding: 0;
+
+ > filelistcell {
+ padding: 8px 6px;
+ }
+ }
+
+ gridview {
+ @include undershoot(top, $shade_color, true);
+ padding: 15px;
+
+ > child {
+ border-radius: 12px;
+ padding: 0;
+ margin: 3px;
+
+ > filelistcell {
+ padding: 6px 12px;
+ }
+
+ & filethumbnail image {
+ filter: drop-shadow(0px 1px 1px rgba(0,0,0,0.3));
+ }
+
+ & box {
+ border-spacing: 6px;
+ }
+ }
+ }
+
+ // Style the outer action bar with a toolbar view-like shadow
+ > box > actionbar {
+ box-shadow: 0 -1px if($contrast == 'high', $border_color, gtkalpha($headerbar_shade_color, .5)),
+ 0 -2px 4px gtkalpha($headerbar_shade_color, .5);
+
+ > revealer > box {
+ box-shadow: none;
+ padding-top: 6px;
+ }
+ }
+
+ // Style the remote search action bar like a banner
+ scrolledwindow + actionbar > revealer > box {
+ background-color: gtkmix($accent_bg_color, $view_bg_color, 30%);
+ color: $window_fg_color;
+ box-shadow: none;
+ padding-top: 6px;
+ font-weight: bold;
+
+ &:backdrop {
+ background-color: gtkmix($accent_bg_color, $view_bg_color, 15%);
+ }
+ }
+
+ placesview {
+ // Only the bottom undershoot, since the action bar is guaranteed to be
+ // there, while the search bar can show and hide. That's a problem, since
+ // we only need top undershoot when it's visible, to avoid a double shadow.
+ > stack > scrolledwindow {
+ @include undershoot(bottom);
+ }
+
+ // Make the Connect to Server action bar flat
+ > actionbar > revealer > box {
+ background: $view_bg_color;
+ color: $view_fg_color;
+ box-shadow: none;
+ padding-top: 6px;
+
+ &:backdrop {
+ background: $view_bg_color;
+ transition: none;
+ }
+ }
+ }
+
+ placessidebar {
+ background-color: $sidebar_bg_color;
+ color: $sidebar_fg_color;
+
+ &:backdrop {
+ background-color: $sidebar_backdrop_color;
+ transition: background-color $backdrop_transition;
+ }
+ }
+
+ // The separator is a part of GtkPaned, so it needs to be styled separately
+ paned.horizontal > separator {
+ &:dir(ltr) {
+ box-shadow: inset 1px 0 $sidebar_bg_color,
+ inset 1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+
+ &:backdrop {
+ box-shadow: inset 1px 0 $sidebar_backdrop_color,
+ inset 1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+ }
+ }
+
+ &:dir(rtl) {
+ box-shadow: inset -1px 0 $sidebar_bg_color,
+ inset -1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+
+ &:backdrop {
+ box-shadow: inset -1px 0 $sidebar_backdrop_color,
+ inset -1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+ }
+ }
+
+ &:backdrop {
+ transition: box-shadow $backdrop_transition;
+ }
+ }
+}
+
+/* Fix header bar height in the file chooser */
+window.filechooser headerbar box.start + box.vertical {
+ margin-top: -6px;
+ margin-bottom: -6px;
+ min-height: 12px;
+}
diff --git a/gtk/theme/libadwaita/widgets/_header-bar.scss b/gtk/theme/libadwaita/widgets/_header-bar.scss
new file mode 100644
index 0000000000..29e22edd89
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_header-bar.scss
@@ -0,0 +1,230 @@
+headerbar {
+ min-height: 47px;
+ background-color: $headerbar_bg_color;
+ color: $headerbar_fg_color;
+ box-shadow: inset 0 -1px if($contrast == 'high', $headerbar_border_color, $headerbar_shade_color),
+ inset 1px 0 $headerbar_border_color,
+ inset -1px 0 $headerbar_border_color;
+
+ margin-left: -1px;
+ margin-right: -1px;
+
+ @extend %toolbar;
+
+ > windowhandle > box {
+ padding: 6px 7px 7px 7px;
+
+ > box.start,
+ > box.end {
+ border-spacing: 6px;
+ }
+
+ &, > widget {
+ > box.start:dir(ltr),
+ > box.end:dir(rtl) {
+ margin-right: 6px;
+ }
+
+ > box.start:dir(rtl),
+ > box.end:dir(ltr) {
+ margin-left: 6px;
+ }
+ }
+ }
+
+ &:backdrop {
+ background-color: $headerbar_backdrop_color;
+ transition: background-color $backdrop_transition;
+
+ > windowhandle {
+ // opacity looks weird with GtkSwitch, but filter works fine
+ filter: opacity(0.5);
+
+ transition: filter $backdrop_transition;
+ }
+ }
+
+ &.default-decoration {
+ min-height: 37px;
+
+ > windowhandle > box {
+ padding: 3px 4px 4px 4px;
+ }
+
+ windowcontrols {
+ > button {
+ min-height: 22px;
+ min-width: 22px;
+ padding: 4px;
+ }
+
+ > .icon {
+ margin: 7px;
+ }
+ }
+ }
+}
+
+window > {
+ .titlebar:not(.flat) {
+ box-shadow: 0 1px if($contrast == 'high', $border_color, gtkalpha($headerbar_shade_color, .5)),
+ 0 2px 4px gtkalpha($headerbar_shade_color, .5);
+ }
+
+ .titlebar headerbar:not(.flat) {
+ box-shadow: inset 1px 0 $headerbar_border_color,
+ inset -1px 0 $headerbar_border_color;
+ }
+
+ headerbar.titlebar,
+ .titlebar headerbar {
+ min-height: 46px;
+
+ > windowhandle > box {
+ padding-bottom: 6px;
+ }
+
+ &.default-decoration {
+ min-height: 36px;
+
+ > windowhandle > box {
+ padding-bottom: 3px;
+ }
+ }
+ }
+}
+
+%headerbar-flat {
+ background: none;
+ box-shadow: none;
+ color: inherit;
+
+ min-height: 46px;
+
+ > windowhandle > box {
+ padding-bottom: 6px;
+ }
+
+ &.default-decoration {
+ min-height: 36px;
+
+ > windowhandle > box {
+ padding-bottom: 3px;
+ }
+ }
+}
+
+%headerbar-inline {
+ @extend %headerbar-flat;
+
+ &:backdrop {
+ transition: none;
+
+ > windowhandle {
+ filter: none;
+ transition: none;
+ }
+ }
+
+ window.devel & > windowhandle {
+ background-image: none;
+ }
+}
+
+%headerbar-shrunk {
+ min-height: 40px;
+
+ > windowhandle > box {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ }
+
+ &.default-decoration {
+ min-height: 30px;
+
+ > windowhandle > box {
+ padding-top: 0px;
+ padding-bottom: 0px;
+ }
+ }
+}
+
+.titlebar:not(headerbar) {
+ separator { background-color: $headerbar_border_color; }
+}
+
+/*********************
+ * GtkWindowControls *
+ *********************/
+
+windowcontrols {
+ border-spacing: 3px;
+
+ > button {
+ min-width: 24px;
+ padding: 5px;
+ box-shadow: none;
+
+ > image {
+ background-color: $button_color;
+ border-radius: 100%;
+ padding: 2px;
+ transition: $button_transition;
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+
+ &, &:hover, &:active {
+ background: none;
+ }
+
+ &:hover > image { background-color: $button_hover_color; }
+ &:active > image { background-color: $button_active_color; }
+ }
+
+ > .icon {
+ margin: 9px;
+ }
+}
+
+/******************
+ * AdwWindowTitle *
+ ******************/
+
+headerbar,
+windowtitle {
+ .title {
+ padding-left: 12px;
+ padding-right: 12px;
+ font-weight: bold;
+ }
+
+ .subtitle {
+ font-size: smaller;
+ padding-left: 12px;
+ padding-right: 12px;
+ @extend .dim-label;
+ }
+}
+
+windowtitle {
+ margin-top: -6px;
+ margin-bottom: -6px;
+ min-height: 12px;
+}
+
+// Development versions of apps to use a differently styled headerbar
+
+window.devel {
+ headerbar > windowhandle {
+ background-image: cross-fade(5% -gtk-recolor(url("assets/devel-symbolic.svg")),
+ image(transparent));
+ background-repeat: repeat-x;
+ }
+
+ dialog headerbar > windowhandle {
+ background-image: unset;
+ background-repeat: unset;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_labels.scss b/gtk/theme/libadwaita/widgets/_labels.scss
new file mode 100644
index 0000000000..10f3a18709
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_labels.scss
@@ -0,0 +1,92 @@
+label {
+ caret-color: currentColor;
+
+ &.separator {
+ @extend .dim-label;
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+}
+
+.dim-label {
+ opacity: $dim_label_opacity;
+}
+
+.accent {
+ color: $accent_color;
+}
+
+.success {
+ color: $success_color;
+}
+
+.warning {
+ color: $warning_color;
+}
+
+.error {
+ color: $error_color;
+}
+
+/**********************
+ * General Typography *
+ **********************/
+
+.title-1 {
+ font-weight: 800;
+ font-size: 20pt;
+}
+
+.title-2 {
+ font-weight: 800;
+ font-size: 15pt;
+}
+
+.title-3 {
+ font-weight: 700;
+ font-size: 15pt;
+}
+
+.title-4 {
+ font-weight: 700;
+ font-size: 13pt;
+}
+
+.heading {
+ font-weight: 700;
+ font-size: 11pt;
+}
+
+.body {
+ font-weight: 400;
+ font-size: 11pt;
+}
+
+.caption-heading {
+ font-weight: 700;
+ font-size: 9pt;
+}
+
+.caption {
+ font-weight: 400;
+ font-size: 9pt;
+}
+
+.monospace {
+ font-family: monospace;
+}
+
+.numeric {
+ font-feature-settings: "tnum";
+}
+
+/*******************
+ * Editable Labels *
+ *******************/
+
+editablelabel > stack > text {
+ color: $view_fg_color;
+ background-color: $view_bg_color;
+}
diff --git a/gtk/theme/libadwaita/widgets/_level-bar.scss b/gtk/theme/libadwaita/widgets/_level-bar.scss
new file mode 100644
index 0000000000..bf75593df7
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_level-bar.scss
@@ -0,0 +1,100 @@
+$_levelbar_size: 8px;
+$_levelbar_border_radius: 99px;
+
+levelbar {
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ &.horizontal {
+ trough > block {
+ min-height: $_levelbar_size;
+ border-radius: $_levelbar_border_radius;
+
+ &.empty,
+ &.full {
+ border-radius: $_levelbar_border_radius;
+ }
+ }
+
+ // segmented level bar
+ &.discrete > trough > block {
+ min-height: $_levelbar_size;
+ margin-right: 2px;
+ min-width: 26px;
+ border-radius: 0;
+
+ &:first-child {
+ border-radius: $_levelbar_border_radius 0 0 $_levelbar_border_radius;
+ }
+
+ &:last-child {
+ border-radius: 0 $_levelbar_border_radius $_levelbar_border_radius 0;
+ margin-right: 0;
+ }
+ }
+ }
+
+ &.vertical {
+ trough > block {
+ min-width: $_levelbar_size;
+ border-radius: $_levelbar_border_radius;
+
+ &.empty,
+ &.full {
+ border-radius: $_levelbar_border_radius;
+ }
+ }
+
+ // segmented level bar
+ &.discrete > trough > block {
+ min-width: $_levelbar_size;
+ margin-bottom: 2px;
+ min-height: 26px;
+ border-radius: 0;
+
+ &:first-child {
+ border-radius: $_levelbar_border_radius $_levelbar_border_radius 0 0;
+ }
+
+ &:last-child {
+ border-radius: 0 0 $_levelbar_border_radius $_levelbar_border_radius;
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ > trough {
+ padding: 0;
+
+ // level bar colours
+ > block {
+ &.low {
+ background-color: $warning_bg_color;
+ }
+
+ &.high,
+ &:not(.empty) {
+ background-color: $fill_color;
+ }
+
+ &.full {
+ background-color: $success_bg_color;
+ }
+
+ &.empty {
+ background-color: $trough_color;
+
+ @if $contrast == "high" {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+ }
+ }
+
+ .osd & > trough > block {
+ &.high, &:not(.empty) {
+ background-color: $osd_fill_bg_color;
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_linked.scss b/gtk/theme/libadwaita/widgets/_linked.scss
new file mode 100644
index 0000000000..90e71884d2
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_linked.scss
@@ -0,0 +1,46 @@
+// .linked > element child
+$_linked_widgets: ("%button", ""),
+ ("button", ""),
+ ("menubutton", "> button"),
+ ("dropdown", "> button"),
+ ("colorbutton", "> button"),
+ ("fontbutton", "> button"),
+ ("tabbutton", "> button"),
+ ("%entry", ""),
+ ("entry", "");
+
+$_linked_widgets: join($_linked_widgets, $deprecated_linked_widgets);
+
+@each $widget, $child in $_linked_widgets {
+ .linked:not(.vertical) > {
+ #{$widget} {
+ &:dir(ltr):not(:first-child) #{$child},
+ &:dir(rtl):not(:last-child) #{$child} {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ margin-left: -1px;
+ }
+
+ &:dir(ltr):not(:last-child) #{$child},
+ &:dir(rtl):not(:first-child) #{$child} {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+ }
+ }
+
+ .linked.vertical {
+ #{$widget} {
+ &:not(:first-child) #{$child} {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ margin-top: -1px;
+ }
+
+ &:not(:last-child) #{$child} {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_links.scss b/gtk/theme/libadwaita/widgets/_links.scss
new file mode 100644
index 0000000000..3377f266e7
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_links.scss
@@ -0,0 +1,53 @@
+link,
+button.link {
+ color: $link_color;
+ text-decoration: underline;
+ font-weight: inherit;
+
+ &:visited {
+ color: $link_visited_color;
+ }
+
+ &:hover {
+ color: gtkshade($link_color, 1.1);
+ }
+
+ &:active {
+ color: $link_color;
+ }
+
+ &:disabled { color: gtkalpha(currentColor, $disabled_opacity); }
+
+ .osd & {
+ color: $osd_link_color;
+
+ &:visited {
+ color: $osd_link_visited_color;
+ }
+
+ &:active {
+ color: $osd_link_color;
+ }
+ }
+}
+
+link {
+ @include focus-ring();
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+}
+
+button.link {
+ &,
+ &:hover,
+ &:active,
+ &:checked {
+ @extend %undecorated_button;
+ }
+
+ > label {
+ text-decoration: underline;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_lists.scss b/gtk/theme/libadwaita/widgets/_lists.scss
new file mode 100644
index 0000000000..2693d514f8
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_lists.scss
@@ -0,0 +1,547 @@
+$row_transition: background-color 200ms $ease-out-quad,
+ background-image 200ms $ease-out-quad,
+ border-radius 200ms $ease-out-quad;
+
+listview,
+list {
+ color: $view_fg_color;
+ background-color: $view_bg_color;
+ background-clip: padding-box;
+ border-color: $border_color;
+
+ > row {
+ padding: 2px;
+ background-clip: padding-box;
+ }
+
+ > row.expander { padding: 0px; }
+ > row.expander .row-header { padding: 2px; }
+
+ &.horizontal row.separator,
+ &.separators.horizontal > row:not(.separator) {
+ border-left: 1px solid $border_color;
+ }
+
+ &:not(.horizontal) row.separator,
+ &.separators:not(.horizontal) > row:not(.separator) {
+ border-bottom: 1px solid $border_color;
+ }
+}
+
+listview > header {
+ @extend .heading;
+ padding: 2px;
+ padding-top: 18px;
+ padding-bottom: 6px;
+}
+
+row {
+ @include focus-ring();
+
+ .osd & {
+ &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ &.activatable {
+ &:hover { background-color: $hover_color; }
+
+ &:active { background-color: $active_color; }
+
+ // this is for indicathing which row generated a popover see https://bugzilla.gnome.org/show_bug.cgi?id=754411
+ &.has-open-popup { background-color: $hover_color; }
+
+ &:selected {
+ &:hover { background-color: $selected_hover_color; }
+
+ &:active { background-color: $selected_active_color; }
+
+ &.has-open-popup { background-color: $selected_hover_color; }
+ }
+ }
+
+ &:selected {
+ background-color: $selected_color;
+ }
+ }
+
+ background-clip: padding-box;
+
+ &.activatable {
+ &:hover { background-color: $view_hover_color; }
+
+ &:active { background-color: $view_active_color; }
+
+ // this is for indicathing which row generated a popover see https://bugzilla.gnome.org/show_bug.cgi?id=754411
+ &.has-open-popup { background-color: $view_hover_color; }
+
+ &:selected {
+ &:hover { background-color: $view_selected_hover_color; }
+
+ &:active { background-color: $view_selected_active_color; }
+
+ &.has-open-popup { background-color: $view_selected_hover_color; }
+ }
+ }
+
+ &:selected {
+ background-color: $view_selected_color;
+ }
+}
+
+/*******************************************************
+ * Rich Lists *
+ * Large list usually containing lots of widgets *
+ * https://gitlab.gnome.org/GNOME/gtk/-/issues/3073 *
+ *******************************************************/
+
+.rich-list { /* rich lists usually containing other widgets than just labels/text */
+ > row {
+ padding: 8px 12px;
+ min-height: 32px; /* should be tall even when only containing a label */
+
+ > box {
+ border-spacing: 12px;
+ }
+ }
+
+ > header {
+ padding-left: 12px;
+ padding-right: 12px;
+ }
+}
+
+/****************
+ * AdwActionRow *
+ ****************/
+
+row {
+ label.subtitle {
+ font-size: smaller;
+ @extend .dim-label;
+ }
+
+ > box.header {
+ margin-left: 12px;
+ margin-right: 12px;
+ border-spacing: 6px;
+ min-height: 50px;
+
+ > .icon:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ > box.title {
+ margin-top: 6px;
+ margin-bottom: 6px;
+ border-spacing: 3px;
+ padding: 0;
+
+ // Specificity bump for header bar
+ &,
+ > .title,
+ > .subtitle {
+ padding: 0;
+ font-weight: inherit;
+ }
+ }
+
+ > .prefixes,
+ > .suffixes {
+ border-spacing: 6px;
+ }
+
+ > .icon,
+ > .prefixes {
+ &:dir(ltr) { margin-right: 6px; }
+ &:dir(rtl) { margin-left: 6px; }
+ }
+ }
+
+ &.property > box.header > box.title > {
+ .title {
+ font-size: smaller;
+ @extend .dim-label;
+ }
+
+ .subtitle {
+ font-size: inherit;
+ opacity: 1;
+ }
+ }
+}
+
+/******************************
+ * AdwEntryRow and AdwSpinRow *
+ ******************************/
+
+row.entry {
+ &:disabled {
+ text {
+ opacity: $disabled_opacity;
+ }
+
+ .dim-label, .subtitle {
+ opacity: 1;
+ }
+ }
+
+ .edit-icon, .indicator {
+ min-width: 24px;
+ min-height: 24px;
+ padding: 5px;
+ }
+
+ .edit-icon:disabled {
+ opacity: $strong_disabled_opacity;
+ }
+
+ .indicator {
+ opacity: $dimmer_opacity;
+ }
+
+ &.monospace {
+ font-family: inherit;
+
+ text {
+ font-family: monospace;
+ }
+ }
+}
+
+row.spin {
+ spinbutton {
+ background: none;
+ border-spacing: 6px;
+ box-shadow: none;
+
+ &, &:focus {
+ outline: none;
+ }
+
+ > button.image-button.up:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque):last-child,
+ > button.image-button.down:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &, &:dir(ltr):last-child, &:dir(rtl):first-child {
+ @extend %button_basic;
+ @extend %circular_button;
+ min-width: 30px;
+ min-height: 30px;
+ margin: 10px 2px;
+ border: none;
+ }
+ }
+ }
+
+ &:disabled spinbutton {
+ > button.image-button.up:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque):last-child,
+ > button.image-button.down:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &, &:dir(ltr):last-child, &:dir(rtl):first-child {
+ &:disabled {
+ filter: none;
+ }
+ }
+ }
+ }
+}
+
+row.entry,
+row.spin {
+ @include focus-ring($focus-state: '.focused', $offset: -1px, $transition: $row_transition);
+
+ &:not(:selected).activatable.focused:hover,
+ &:not(:selected).activatable.focused:active {
+ background-color: transparent;
+ }
+
+ @each $e_type, $e_color, $e_bg_color, $e_fg_color in (error, $error_color, $error_bg_color, $error_fg_color),
+ (warning, $warning_color, $warning_bg_color, $warning_fg_color),
+ (success, $success_color, $success_bg_color, $success_fg_color) {
+ &.#{$e_type} {
+ @include focus-ring($focus-state: '.focused', $offset: -1px, $fc: gtkalpha(currentColor, $focus_border_opacity), $transition: $row_transition);
+
+ text {
+ > selection:focus-within { background-color: gtkalpha($e_color, .2); }
+
+ > cursor-handle > contents { background-color: currentColor; }
+ }
+
+ .dim-label, .subtitle {
+ opacity: 1;
+ }
+
+ .suggested-action {
+ background-color: $e_bg_color;
+ color: $e_fg_color;
+ }
+ }
+ }
+}
+
+/***************
+ * AdwComboRow *
+ ***************/
+
+row.combo {
+ image.dropdown-arrow:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ listview.inline {
+ background: none;
+ border: none;
+ box-shadow: none;
+ color: inherit;
+
+ &, &:disabled {
+ background: none;
+ color: inherit;
+ }
+ }
+
+ popover > contents {
+ min-width: 120px;
+
+ .combo-searchbar {
+ margin: 6px;
+
+ + scrolledwindow {
+ @include undershoot(top, $popover_shade_color);
+ }
+ }
+ }
+}
+
+/******************
+ * AdwExpanderRow *
+ ******************/
+
+@mixin margin-start($margin) {
+ &:dir(ltr) {
+ margin-left: $margin;
+ }
+
+ &:dir(rtl) {
+ margin-right: $margin;
+ }
+}
+
+%boxed_list_row {
+ @include focus-ring($offset: -1px, $transition: $row_transition);
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ border-bottom: 1px solid if($contrast == 'high', $border_color, $card_shade_color);
+
+ &:not(:selected).activatable {
+ &:hover {
+ background-color: gtkalpha(currentColor, .03);
+ }
+
+ &:active {
+ background-color: gtkalpha(currentColor, .08);
+ }
+
+ &.has-open-popup {
+ background-color: gtkalpha(currentColor, .03);
+ }
+ }
+}
+
+row.expander {
+ // Drop transparent background on expander rows to let nested rows handle it,
+ // avoiding double highlights.
+ background: none;
+ padding: 0px;
+
+ > box > list {
+ background: none;
+ color: inherit;
+ }
+
+ list.nested {
+ background-color: gtkalpha($card_shade_color, .5);
+ color: inherit;
+ }
+
+ list.nested > row {
+ @extend %boxed_list_row;
+ }
+
+ // AdwExpanderRow arrow rotation
+
+ image.expander-row-arrow {
+ @extend .dim-label;
+
+ transition: -gtk-icon-transform 200ms $ease-out-quad;
+ @include margin-start(3px);
+
+ &:dir(ltr) {
+ -gtk-icon-transform: rotate(0.5turn);
+ }
+
+ &:dir(rtl) {
+ -gtk-icon-transform: rotate(-0.5turn);
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+ }
+
+ &:checked image.expander-row-arrow {
+ -gtk-icon-transform: rotate(0turn);
+ opacity: 1;
+
+ &:not(:disabled) {
+ color: $accent_color;
+ }
+ }
+
+ .osd &:checked image.expander-row-arrow:not(:disabled) {
+ color: inherit;
+ }
+
+ &.property box > list > row {
+ @extend .property;
+ }
+}
+
+/***************
+ * AdwButtonRow *
+ ***************/
+
+row.button {
+ > box {
+ margin-left: 12px;
+ margin-right: 12px;
+ border-spacing: 6px;
+ min-height: 42px;
+ }
+
+ .title {
+ @extend .heading;
+ }
+
+ &.suggested-action {
+ color: $accent_color;
+ }
+
+ &.destructive-action {
+ color: $destructive_color;
+ }
+}
+
+/*****************
+ * Boxed Lists *
+ *****************/
+
+list.boxed-list {
+ @extend %card;
+
+ > row {
+ // Regular rows and expander header rows background
+ &, &.expander row.header {
+ @extend %boxed_list_row;
+ }
+
+ &.expander {
+ border: none;
+ }
+
+ // Rounded top
+ &:first-child {
+ &, &.expander row.header {
+ border-top-left-radius: $card_radius;
+ border-top-right-radius: $card_radius;
+ }
+ }
+
+ // Rounded bottom
+ &:last-child {
+ &,
+ &.expander:not(:checked),
+ &.expander:not(:checked) row.header,
+ &.expander:checked list.nested,
+ &.expander:checked list.nested > row:last-child {
+ border-bottom-left-radius: $card_radius;
+ border-bottom-right-radius: $card_radius;
+ border-bottom-width: 0;
+ }
+ }
+ }
+}
+
+list.boxed-list-separate {
+ background: none;
+ color: $card_fg_color;
+
+ > row {
+ @extend %card;
+
+ border: none;
+ margin-bottom: 12px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ @include focus-ring($offset: -1px, $transition: $row_transition);
+
+ .osd &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ &:not(.expander) {
+ &:not(:selected).activatable {
+ &:hover {
+ background-color: $card_bg_color;
+ background-image: image(gtkalpha(currentColor, .03));
+ }
+
+ &:active {
+ background-color: $card_bg_color;
+ background-image: image(gtkalpha(currentColor, .08));
+ }
+
+ &.has-open-popup {
+ background-color: $card_bg_color;
+ background-image: image(gtkalpha(currentColor, .03));
+ }
+ }
+ }
+
+ &.entry, &.spin {
+ &:not(:selected).activatable.focused:hover,
+ &:not(:selected).activatable.focused:active {
+ background-color: $card_bg_color;
+ background-image: none;
+ }
+
+ @each $e_type, $e_color in (error, $error_color),
+ (warning, $warning_color),
+ (success, $success_color) {
+ &.#{$e_type} {
+ color: $e_color;
+ }
+ }
+ }
+
+ &.expander {
+ row.header {
+ @extend %boxed_list_row;
+ border-top-left-radius: $card_radius;
+ border-top-right-radius: $card_radius;
+ }
+
+ &:not(:checked) row.header,
+ &.expander:checked list.nested,
+ &.expander:checked list.nested > row:last-child {
+ border-bottom-left-radius: $card_radius;
+ border-bottom-right-radius: $card_radius;
+ border-bottom: none;
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_menus.scss b/gtk/theme/libadwaita/widgets/_menus.scss
new file mode 100644
index 0000000000..4080f61ad4
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_menus.scss
@@ -0,0 +1,275 @@
+popover.menu {
+ > contents {
+ min-width: 120px;
+ }
+
+ scrollbar.vertical > range > trough > slider {
+ min-height: 30px;
+ }
+
+ box.inline-buttons {
+ padding: 0 $menu_padding;
+
+ button.image-button.model {
+ @extend %button_basic_flat;
+
+ min-height: 32px;
+ min-width: 32px;
+ padding: 0;
+ border: none;
+ outline: none;
+ transition: none;
+
+ &:selected {
+ background-color: $selected_color;
+
+ &:active {
+ background-color: $selected_active_color;
+ }
+ }
+ }
+ }
+
+ box.circular-buttons {
+ padding: $menu_padding $menu_padding 6px;
+
+ button.circular.image-button.model {
+ @extend %button_basic_flat;
+
+ outline: none;
+ padding: 11px;
+
+ box-shadow: inset 0 0 0 1px $border_color;
+
+ &:selected {
+ background-color: $selected_hover_color;
+
+ @if $contrast != 'high' {
+ box-shadow: none;
+ }
+
+ &:active {
+ background-color: $selected_active_color;
+ }
+ }
+ }
+ }
+
+ > contents {
+ padding: 0;
+
+ &, > scrolledwindow > viewport {
+ > stack > box {
+ padding: $menu_margin;
+ }
+ }
+ }
+
+ separator {
+ margin: 6px 0;
+ }
+
+ list separator {
+ margin: 0;
+ }
+
+ accelerator {
+ color: gtkalpha(currentColor, $dim_label_opacity);
+
+ &:dir(ltr) { margin-left: $menu_padding; }
+ &:dir(rtl) { margin-right: $menu_padding; }
+ }
+
+ check,
+ radio {
+ min-width: 14px;
+ min-height: 14px;
+ -gtk-icon-size: 14px;
+ padding: 2px;
+
+ &,
+ &:hover:checked,
+ &:hover:indeterminate,
+ &:hover:not(:checked):not(:indeterminate),
+ &:active:checked,
+ &:active:indeterminate,
+ &:active:not(:checked):not(:indeterminate), {
+ background: none;
+ box-shadow: none;
+ color: inherit;
+ }
+ }
+
+ .osd & {
+ check, radio {
+ background: none;
+ color: inherit;
+ }
+ }
+
+ //only menu radios have a border
+ radio {
+ padding: 1px;
+ border: 1px solid gtkalpha(currentColor, $dimmer_opacity);
+ }
+
+ check,
+ radio,
+ arrow {
+ &.left {
+ margin-left: -2px;
+ margin-right: 6px;
+ }
+
+ &.right {
+ margin-left: 6px;
+ margin-right: -2px;
+ }
+ }
+
+ modelbutton {
+ min-height: 32px;
+ min-width: 40px;
+ padding: 0 $menu_padding;
+ border-radius: $menu_radius;
+
+ @extend %undecorated_button;
+
+ &:hover,
+ &:selected {
+ background-color: $selected_color;
+ }
+
+ &:active {
+ background-color: $selected_active_color; // matching buttons
+ }
+
+ @if $contrast == 'high' {
+ &:hover,
+ &:selected,
+ &:active {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+
+ arrow {
+ background: none;
+ min-width: 16px;
+ min-height: 16px;
+ opacity: $dimmer_opacity;
+
+ &:hover { background: none; }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ &.left { -gtk-icon-source: -gtk-icontheme("go-previous-symbolic"); }
+
+ &.right { -gtk-icon-source: -gtk-icontheme("go-next-symbolic"); }
+ }
+ }
+
+ label.title {
+ font-weight: bold;
+ padding: 4px ($menu_padding + 20px); //this will fall apart with font sizing
+ }
+
+ list, listview {
+ background: none;
+ color: inherit;
+
+ > row {
+ border-radius: $menu_radius;
+ padding: 0 $menu_padding;
+ min-height: 32px;
+ min-width: 40px;
+
+ &:selected {
+ background: none;
+ }
+
+ &:hover {
+ &, &:selected.activatable {
+ background-color: $selected_color;
+ }
+ }
+
+ &:active {
+ &, &:selected.activatable {
+ background-color: $selected_active_color;
+ }
+ }
+
+ &.has-open-popup {
+ &, &:selected.activatable {
+ background-color: $selected_color;
+ }
+ }
+
+ @if $contrast == 'high' {
+ &:hover,
+ &:active,
+ &.has-open-popup {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+
+ > box {
+ border-spacing: 6px;
+ }
+ }
+ }
+
+ // Standalone lists should have same margins as menu sections,
+ // but we don't want that on lists inside sections themselves
+ contents > list,
+ contents > listview,
+ scrolledwindow > viewport > list,
+ scrolledwindow > listview {
+ padding: $menu_margin 0; //only vertical padding. horizontal row size would clip
+
+ > row {
+ margin: 0 $menu_margin;
+
+ padding: 9px $menu_padding;
+ min-height: 0;
+ }
+ }
+}
+
+menubar {
+ box-shadow: inset 0 -1px $border_color;
+ padding-bottom: 1px;
+
+ > item {
+ min-height: 16px;
+ padding: 4px 8px;
+ border-radius: $button_radius;
+
+ &:selected { //Seems like it :hover even with keyboard focus
+ background-color: $selected_color;
+
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+
+ //nested submenus
+ popover.menu popover.menu {
+ padding: 0 0 4px 0;
+ }
+
+ popover.menu popover.menu > contents {
+ margin: 0;
+ border-radius: $popover_radius; //including top
+ }
+ }
+}
+
+%menubar-inline {
+ box-shadow: none;
+ padding-bottom: 0;
+}
+
+%menubar-shrunk {}
diff --git a/gtk/theme/libadwaita/widgets/_message-dialog.scss b/gtk/theme/libadwaita/widgets/_message-dialog.scss
new file mode 100644
index 0000000000..eed5af6fab
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_message-dialog.scss
@@ -0,0 +1,170 @@
+/********************
+ * GtkMessageDialog *
+ ********************/
+
+window.dialog.message {
+ .titlebar {
+ min-height: 20px;
+ background: none;
+ box-shadow: none;
+ border-style: none;
+ border-top-left-radius: 7px;
+ border-top-right-radius: 7px;
+ }
+
+ box.dialog-vbox.vertical {
+ margin-top: 6px;
+ border-spacing: 24px;
+
+ > box > box > box > label.title {
+ font-weight: 800;
+ font-size: 15pt;
+ }
+ }
+
+ &.csd {
+ // bigger radius for better antialiasing
+ border-bottom-left-radius: $window_radius+1;
+ border-bottom-right-radius: $window_radius+1;
+
+ .dialog-action-area {
+ border-top: 1px solid $border_color;
+ margin: 0;
+ border-spacing: 0;
+
+ > button {
+ @extend %button_basic_flat;
+ padding: 10px 14px; // labels are not vertically centered on message dialog, this is a workaround
+ border-radius: 0;
+ border: none;
+ background-clip: padding-box;
+ border-left: 1px solid $border_color;
+
+ &:first-child {
+ border-bottom-left-radius: $window_radius+1;
+ border-left: none;
+ }
+
+ &:last-child {
+ border-bottom-right-radius: $window_radius+1;
+ }
+
+ &.suggested-action {
+ color: $accent_color;
+ }
+
+ &.destructive-action {
+ color: $destructive_color;
+ }
+ }
+ }
+ }
+}
+
+/********************
+ * AdwMessageDialog *
+ ********************/
+
+window.messagedialog,
+dialog-host > dialog.alert sheet,
+window.dialog-window.alert {
+ background-color: $dialog_bg_color;
+ color: $dialog_fg_color;
+}
+
+window.messagedialog {
+ @if $contrast != 'high' {
+ outline: none;
+ }
+}
+
+dialog-host > dialog.alert.floating sheet,
+window.dialog-window.alert {
+ border-radius: $window_radius+1;
+ outline: none;
+}
+
+window.messagedialog,
+dialog.alert {
+ .message-area {
+ padding: 24px 30px;
+ border-spacing: 24px;
+
+ &.has-heading.has-body {
+ border-spacing: 10px;
+ }
+ }
+
+ .response-area > button {
+ padding: 10px 14px;
+ border-radius: 0;
+
+ @if $contrast == 'high' {
+ &:hover,
+ &.keyboard-activating,
+ &:active,
+ &:checked {
+ box-shadow: none;
+ }
+ }
+
+ &.suggested {
+ color: $accent_color;
+ }
+
+ &.destructive {
+ color: $destructive_color;
+ }
+ }
+
+ .response-area {
+ &:not(.compact) > button {
+ margin-top: -1px;
+ margin-right: -1px;
+ margin-left: -1px;
+
+ &:first-child:dir(ltr),
+ &:last-child:dir(rtl) {
+ margin-left: 0;
+ }
+
+ &:last-child:dir(ltr),
+ &:first-child:dir(rtl) {
+ margin-right: 0;
+ }
+ }
+
+ &.compact > button {
+ margin-top: -1px;
+ margin-bottom: -1px;
+
+ &:first-child {
+ margin-bottom: 0;
+ }
+ }
+ }
+}
+
+window.messagedialog,
+dialog.alert.floating {
+ .response-area {
+ &:not(.compact) > button {
+ &:first-child:dir(ltr),
+ &:last-child:dir(rtl) {
+ border-bottom-left-radius: $window_radius+1;
+ }
+
+ &:last-child:dir(ltr),
+ &:first-child:dir(rtl) {
+ border-bottom-right-radius: $window_radius+1;
+ }
+ }
+
+ &.compact > button {
+ &:first-child {
+ border-bottom-left-radius: $window_radius+1;
+ border-bottom-right-radius: $window_radius+1;
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_misc.scss b/gtk/theme/libadwaita/widgets/_misc.scss
new file mode 100644
index 0000000000..140a8abd1d
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_misc.scss
@@ -0,0 +1,228 @@
+/**********
+ * Frames *
+ **********/
+frame,
+.frame {
+ border: 1px solid $border_color;
+}
+
+frame {
+ border-radius: $card_radius;
+
+ > label {
+ margin: 4px;
+ }
+}
+
+/**************
+ * Separators *
+ **************/
+
+separator {
+ background: $border_color;
+ min-width: 1px;
+ min-height: 1px;
+
+ &.spacer {
+ background: none;
+
+ &.horizontal { min-width: 12px; }
+ &.vertical { min-height: 12px; }
+ }
+}
+
+/*********************
+ * App Notifications *
+ *********************/
+
+.app-notification {
+ @extend %osd;
+
+ padding: 10px;
+ border-spacing: 10px;
+ border-radius: 0 0 $card_radius $card_radius;
+ background-color: $osd_bg_color;
+ background-image: linear-gradient(to bottom, transparentize(black, 0.8),
+ transparent 2px);
+ background-clip: padding-box;
+
+ border { border: none; }
+}
+
+/**********
+ * Toasts *
+ **********/
+
+toast {
+ @extend %osd;
+
+ margin: 12px;
+ margin-bottom: 24px;
+
+ border-radius: 150px;
+ border-spacing: 6px;
+ padding: 6px;
+
+ &:dir(ltr) { padding-left: 12px; }
+ &:dir(rtl) { padding-right: 12px; }
+
+ > widget {
+ margin: 0 6px;
+ }
+
+ @if $contrast == 'high' {
+ box-shadow: 0 0 0 1px $border_color;
+ }
+}
+
+/**************
+ * GtkVideo *
+ **************/
+
+video {
+ & image.osd {
+ min-width: 64px;
+ min-height: 64px;
+ border-radius: 32px;
+ }
+}
+
+/******************
+ * AdwAboutWindow *
+ ******************/
+
+window.about,
+dialog.about {
+ .main-page {
+ > viewport > clamp > box {
+ margin: 12px;
+ border-spacing: 6px;
+
+ > box {
+ margin-top: 18px;
+ border-spacing: 18px;
+ margin-bottom: 6px;
+ }
+ }
+
+ .app-version {
+ padding: 3px 18px;
+ color: $accent_color;
+ border-radius: 999px;
+ margin-top: 3px;
+ }
+ }
+
+ .subpage {
+ > viewport > clamp > box {
+ margin: 18px 12px;
+ border-spacing: 18px;
+ }
+
+ > clamp > textview {
+ background: none;
+ color: inherit;
+ }
+ }
+}
+
+/*****************
+ * AdwStatusPage *
+ *****************/
+
+statuspage {
+ > scrolledwindow > viewport > box {
+ margin: 36px 12px;
+ border-spacing: 36px;
+
+ > clamp > box {
+ border-spacing: 12px;
+
+ > .icon {
+ -gtk-icon-size: 128px;
+
+ color: gtkalpha(currentColor, $dim_label_opacity);
+
+ &:disabled {
+ opacity: $disabled_opacity;
+ }
+
+ &:not(:last-child) {
+ margin-bottom: 24px;
+ }
+ }
+ }
+ }
+
+ &.compact > scrolledwindow > viewport > box {
+ margin: 24px 12px;
+ border-spacing: 24px;
+
+ > clamp > box {
+ > .icon {
+ -gtk-icon-size: 96px;
+
+ &:not(:last-child) {
+ margin-bottom: 12px;
+ }
+ }
+
+ > .title {
+ font-size: 18pt;
+ }
+ }
+ }
+}
+
+/* Cards */
+
+.card {
+ @at-root %card, & {
+ background-color: $card_bg_color;
+ color: $card_fg_color;
+ border-radius: $card_radius;
+ box-shadow: 0 0 0 1px if($contrast == 'high', $border_color, transparentize(black, 0.97)),
+ 0 1px 3px 1px transparentize(black, .93),
+ 0 2px 6px 2px transparentize(black, .97);
+
+ .osd &, &.osd {
+ background-color: gtkalpha(currentColor, .1);
+ color: inherit;
+
+ @if $contrast == 'high' {
+ box-shadow: 0 0 0 1px $border_color;
+ } @else {
+ box-shadow: none;
+ }
+ }
+ }
+
+ @include focus-ring($offset: -1px);
+
+ .osd &, &.osd {
+ &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+ }
+
+ &.activatable {
+ transition: $focus_transition, $button_transition;
+
+ &:hover {
+ background-image: image(gtkalpha(currentColor, .03));
+ }
+
+ &:active {
+ background-image: image(gtkalpha(currentColor, .08));
+ }
+ }
+}
+
+/* Transition shadows */
+
+flap,
+leaflet,
+navigation-view,
+overlay-split-view {
+ @include transition-shadows($shade_color);
+}
diff --git a/gtk/theme/libadwaita/widgets/_notebook.scss b/gtk/theme/libadwaita/widgets/_notebook.scss
new file mode 100644
index 0000000000..3bade4722b
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_notebook.scss
@@ -0,0 +1,216 @@
+notebook {
+ @include focus-ring("> header > tabs > tab:checked", $offset: -2px, $focus-state: ':focus:focus-visible');
+
+ > header {
+ padding: 1px;
+ border-color: $border_color;
+ border-width: 1px;
+ background-clip: padding-box;
+
+ > tabs { margin: -1px; }
+
+ &.top {
+ border-bottom-style: solid;
+ > tabs {
+ margin-bottom: -2px;
+ > tab {
+ &:hover { box-shadow: inset 0 -4px $border_color; }
+
+ &:checked { box-shadow: inset 0 -4px $accent_bg_color; }
+ }
+ }
+ }
+
+ &.bottom {
+ border-top-style: solid;
+ > tabs {
+ margin-top: -2px;
+ > tab {
+ &:hover { box-shadow: inset 0 4px $border_color; }
+
+ &:checked { box-shadow: inset 0 4px $accent_bg_color; }
+ }
+ }
+ }
+
+ &.left {
+ border-right-style: solid;
+ > tabs {
+ margin-right: -2px;
+ > tab {
+ &:hover { box-shadow: inset -4px 0 $border_color; }
+
+ &:checked { box-shadow: inset -4px 0 $accent_bg_color; }
+ }
+ }
+ }
+
+ &.right {
+ border-left-style: solid;
+ > tabs {
+ margin-left: -2px;
+ > tab {
+ &:hover { box-shadow: inset 4px 0 $border_color; }
+
+ &:checked { box-shadow: inset 4px 0 $accent_bg_color; }
+ }
+ }
+ }
+
+ &.top > tabs > arrow {
+ @extend %notebook_vert_arrows;
+
+ border-top-style: none;
+ }
+
+ &.bottom > tabs > arrow {
+ @extend %notebook_vert_arrows;
+
+ border-bottom-style: none;
+ }
+
+ @at-root %notebook_vert_arrows {
+ margin-left: -5px;
+ margin-right: -5px;
+ padding-left: 4px;
+ padding-right: 4px;
+
+ &.down { -gtk-icon-source: -gtk-icontheme('pan-start-symbolic'); }
+
+ &.up { -gtk-icon-source: -gtk-icontheme('pan-end-symbolic'); }
+ }
+
+ &.left > tabs > arrow {
+ @extend %notebook_horz_arrows;
+
+ border-left-style: none;
+ }
+
+ &.right > tabs > arrow {
+ @extend %notebook_horz_arrows;
+
+ border-right-style: none;
+ }
+
+ @at-root %notebook_horz_arrows {
+ margin-top: -5px;
+ margin-bottom: -5px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+
+ &.down { -gtk-icon-source: -gtk-icontheme('pan-up-symbolic'); }
+
+ &.up { -gtk-icon-source: -gtk-icontheme('pan-down-symbolic'); }
+ }
+
+ > tabs > arrow {
+ @extend %button_basic;
+ @extend %button_basic_flat;
+
+ min-height: 16px;
+ min-width: 16px;
+ border-radius: 0;
+
+ &:hover:not(:active) {
+ box-shadow: none;
+ }
+ }
+
+ > tabs > tab {
+ transition: $focus_transition;
+ min-height: 30px;
+ min-width: 30px;
+ padding: 3px 12px;
+
+ font-weight: normal;
+
+ &:hover, &:active {
+ background-color: $hover_color;
+ }
+
+ &:not(:checked) {
+ outline-color: transparent;
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+
+ label, button {
+ filter: none;
+ }
+ }
+
+ // colors the button like the label, overridden otherwise
+ button.flat {
+ color: gtkalpha(currentColor, 0.3);
+ &:hover, &:active { color: currentColor; }
+
+ padding: 0;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ // FIXME: generalize .small-button?
+ min-width: 20px;
+ min-height: 20px;
+
+ &:last-child {
+ margin-left: 4px;
+ margin-right: -4px;
+ }
+
+ &:first-child {
+ margin-left: -4px;
+ margin-right: 4px;
+ }
+ }
+ }
+
+ &.top,
+ &.bottom {
+ > tabs {
+ padding-left: 4px;
+ padding-right: 4px;
+
+ &:not(:only-child) {
+ margin-left: 3px;
+ margin-right: 3px;
+
+ &:first-child { margin-left: -1px; }
+ &:last-child { margin-right: -1px; }
+ }
+
+ > tab {
+ margin-left: 4px;
+ margin-right: 4px;
+ }
+ }
+ }
+
+ &.left,
+ &.right {
+ > tabs {
+ padding-top: 4px;
+ padding-bottom: 4px;
+
+ &:not(:only-child) {
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ &:first-child { margin-top: -1px; }
+ &:last-child { margin-bottom: -1px; }
+ }
+
+ > tab {
+ margin-top: 4px;
+ margin-bottom: 4px;
+ }
+ }
+ }
+
+ &.top > tabs > tab { padding-bottom: 4px; }
+ &.bottom > tabs > tab { padding-top: 4px; }
+ }
+
+ > stack:not(:only-child) { // the :not(:only-child) is for "hidden" notebooks
+ background-color: $view_bg_color;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_paned.scss b/gtk/theme/libadwaita/widgets/_paned.scss
new file mode 100644
index 0000000000..baf320af5c
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_paned.scss
@@ -0,0 +1,46 @@
+paned {
+ > separator {
+ min-width: 1px;
+ min-height: 1px;
+ background: none;
+ background-size: 1px 1px;
+
+ &.wide {
+ min-width: 5px;
+ min-height: 5px;
+ }
+ }
+
+ &.horizontal > separator {
+ &:dir(ltr) {
+ margin: 0 -8px 0 0;
+ padding: 0 8px 0 0;
+ box-shadow: inset 1px 0 $border_color;
+ }
+ &:dir(rtl) {
+ margin: 0 0 0 -8px;
+ padding: 0 0 0 8px;
+ box-shadow: inset -1px 0 $border_color;
+ }
+
+ &.wide {
+ margin: 0;
+ padding: 0;
+ box-shadow: inset 1px 0 $border_color,
+ inset -1px 0 $border_color;
+ }
+ }
+
+ &.vertical > separator {
+ margin: 0 0 -8px 0;
+ padding: 0 0 8px 0;
+ box-shadow: inset 0 1px $border_color;
+
+ &.wide {
+ margin: 0;
+ padding: 0;
+ box-shadow: inset 0 1px $border_color,
+ inset 0 -1px $border_color;
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_popovers.scss b/gtk/theme/libadwaita/widgets/_popovers.scss
new file mode 100644
index 0000000000..03586c363a
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_popovers.scss
@@ -0,0 +1,83 @@
+toolbarview.undershoot-top popover scrolledwindow undershoot.top,
+toolbarview.undershoot-bottom popover scrolledwindow undershoot.bottom {
+ background: none;
+ box-shadow: none;
+}
+
+popover {
+ &.background {
+ background-color: transparent;
+ font: initial;
+ }
+
+ > arrow,
+ > contents {
+ background-color: $popover_bg_color;
+ color: $popover_fg_color;
+ background-clip: padding-box;
+ border: 1px solid if($contrast == 'high', $border_color, transparentize(black, .86));
+ box-shadow: 0 1px 5px 1px transparentize(black, .91),
+ 0 2px 14px 3px transparentize(black, .95);
+ }
+
+ > contents {
+ padding: 8px;
+ border-radius: $popover_radius;
+
+ > list,
+ > .view,
+ > toolbar {
+ border-style: none;
+ background-color: transparent;
+ }
+ }
+
+ .osd &,
+ &.touch-selection,
+ &.magnifier {
+ background-color: transparent;
+
+ > arrow,
+ > contents {
+ @extend %osd;
+
+ border: 1px solid transparentize(white, 0.9);
+ box-shadow: none;
+ }
+ }
+
+ toolbarview.undershoot-top scrolledwindow {
+ @include undershoot(top, $popover_shade_color);
+ }
+
+ toolbarview.undershoot-bottom scrolledwindow {
+ @include undershoot(bottom, $popover_shade_color);
+ }
+
+ scrolledwindow {
+ &.undershoot-top {
+ @include undershoot(top, $popover_shade_color);
+ }
+
+ &.undershoot-bottom {
+ @include undershoot(bottom, $popover_shade_color)
+ }
+
+ &.undershoot-start {
+ &:dir(ltr) { @include undershoot(left, $popover_shade_color); }
+ &:dir(rtl) { @include undershoot(right, $popover_shade_color); }
+ }
+
+ &.undershoot-end {
+ &:dir(ltr) { @include undershoot(right, $popover_shade_color); }
+ &:dir(rtl) { @include undershoot(left, $popover_shade_color); }
+ }
+ }
+
+ flap,
+ leaflet,
+ navigation-view,
+ overlay-split-view {
+ @include transition-shadows($popover_shade_color);
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_preferences.scss b/gtk/theme/libadwaita/widgets/_preferences.scss
new file mode 100644
index 0000000000..7996d584b8
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_preferences.scss
@@ -0,0 +1,18 @@
+preferencespage > scrolledwindow > viewport > clamp > box {
+ margin: 24px 12px;
+ border-spacing: 24px;
+}
+
+preferencesgroup > box {
+ &, .labels {
+ border-spacing: 6px;
+ }
+
+ > box.header:not(.single-line) {
+ margin-bottom: 6px;
+ }
+
+ > box.single-line {
+ min-height: 34px;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_progress-bar.scss b/gtk/theme/libadwaita/widgets/_progress-bar.scss
new file mode 100644
index 0000000000..8386f9522f
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_progress-bar.scss
@@ -0,0 +1,93 @@
+progressbar {
+ // sizing
+ &.horizontal {
+ > trough {
+ min-width: 150px;
+ &, > progress { min-height: 8px; }
+ }
+ }
+
+ &.vertical {
+ > trough {
+ min-height: 80px;
+ &, > progress { min-width: 8px; }
+ }
+ }
+
+ > text {
+ @extend .dim-label;
+ @extend .numeric;
+ font-size: smaller;
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ > trough {
+ @extend %scale_trough;
+
+ > progress {
+ @extend %scale_highlight; /* share most of scales' */
+
+ $_progress-radius: 99px;
+
+ border-radius: $_progress-radius;
+
+ &.left {
+ border-top-left-radius: $_progress-radius;
+ border-bottom-left-radius: $_progress-radius;
+ }
+
+ &.right {
+ border-top-right-radius: $_progress-radius;
+ border-bottom-right-radius: $_progress-radius;
+ }
+
+ &.top {
+ border-top-right-radius: $_progress-radius;
+ border-top-left-radius: $_progress-radius;
+ }
+
+ &.bottom {
+ border-bottom-right-radius: $_progress-radius;
+ border-bottom-left-radius: $_progress-radius;
+ }
+ }
+ }
+
+ &.osd {
+ // Thin progress bar with no trough, usually goes under the header bar
+ min-width: 2px;
+ min-height: 2px;
+ background-color: transparent;
+ color: inherit;
+
+ > trough {
+ border-style: none;
+ border-radius: 0;
+ background-color: transparent;
+ box-shadow: none;
+
+ > progress {
+ border-style: none;
+ border-radius: 0;
+ }
+
+ }
+
+ &.horizontal {
+ > trough, > trough > progress { min-height: 2px; }
+ }
+
+ &.vertical {
+ > trough, > trough > progress { min-width: 2px; }
+ }
+ }
+
+ > trough.empty > progress { all: unset; } // makes the progress indicator disappear, when the fraction is 0
+
+ .osd & > trough > progress {
+ background-color: $osd_fill_bg_color;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_scale.scss b/gtk/theme/libadwaita/widgets/_scale.scss
new file mode 100644
index 0000000000..bb3155e6d6
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_scale.scss
@@ -0,0 +1,232 @@
+$_slider_border_color: transparentize(black, if($contrast == 'high', .65, .9));
+
+%scale_trough {
+ border-radius: 99px;
+ background-color: $trough_color;
+
+ @if $contrast == "high" {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+}
+
+%scale_highlight {
+ border-radius: 99px;
+ background-color: $fill_color;
+ color: $fill_text_color;
+}
+
+scale {
+ // sizing
+ $_marks_length: 6px;
+ $_marks_distance: 6px;
+
+ min-height: 10px;
+ min-width: 10px;
+ padding: 12px;
+
+ @include focus-ring("> trough > slider", $offset: 0);
+
+ > trough {
+ @extend %scale_trough;
+
+ // the colored part of the backing bit
+ > highlight { @extend %scale_highlight; }
+
+ // this is another differently styled part of the backing bit, the most relevant use case is for example
+ // in media player to indicate how much video stream as been cached
+ > fill {
+ @extend %scale_trough;
+ }
+
+ > slider {
+ background-color: $slider_color;
+ box-shadow: 0 0 0 1px $_slider_border_color, 0 2px 4px transparentize(black, .8);
+
+ border-radius: 100%;
+
+ // the slider is inside the trough, so to have make it bigger there's a negative margin
+ min-width: 20px;
+ min-height: 20px;
+ margin: -8px;
+ }
+ }
+
+ &:hover, &:active {
+ > trough {
+ background-color: $trough_hover_color;
+
+ > highlight {
+ background-image: image(gtkalpha(currentColor, .1));
+ }
+
+ > slider {
+ background-color: $slider_hover_color;
+ }
+ }
+ }
+
+ .osd & {
+ &:focus:focus-visible > trough {
+ outline-color: $osd_focus_color;
+ }
+
+ > trough > highlight {
+ background-color: $osd_fill_bg_color;
+ color: $osd_fill_fg_color;
+ }
+ }
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+
+ > trough > slider {
+ box-shadow: 0 0 0 1px $_slider_border_color, 0 2px 4px transparent;
+ outline-color: transparentize(black, if($contrast == 'high', .5, .8));
+ }
+ }
+
+ // click-and-hold the slider to activate
+ &.fine-tune {
+ padding: 9px;
+
+ &.horizontal {
+ min-height: 16px;
+ }
+
+ &.vertical {
+ min-width: 16px;
+ }
+
+ > trough {
+ // to make the trough grow in fine-tune mode
+ > slider { margin: -5px; }
+ }
+ }
+
+ > value {
+ @extend .dim-label;
+ @extend .numeric;
+ }
+
+ &.marks-before:not(.marks-after),
+ &.marks-after:not(.marks-before) {
+ > trough > slider {
+ transform: rotate(45deg);
+
+ // Adjust box-shadow for the 45deg rotation, for 0px 2px we ideally want
+ // 1/√2px 1/√2px, round that to 1px 1px
+ box-shadow: 0 0 0 1px $_slider_border_color, 1px 1px 4px transparentize(black, .8);
+
+ &:disabled {
+ box-shadow: 0 0 0 1px $_slider_border_color, 1px 1px 4px transparent;
+ }
+ }
+ }
+
+ &.horizontal {
+ > marks {
+ color: gtkalpha(currentColor, $dim_label_opacity);
+ &.top { margin-bottom: $_marks_distance; }
+ &.bottom { margin-top: $_marks_distance; }
+
+ indicator {
+ background-color: currentColor;
+ min-height: $_marks_length;
+ min-width: 1px;
+ }
+ }
+
+ > value.left { margin-right: 9px; }
+ > value.right { margin-left: 9px; }
+
+ &.fine-tune > marks {
+ &.top { margin-top: 3px; }
+ &.bottom { margin-bottom: 3px; }
+
+ indicator { min-height: ($_marks_length - 3px); }
+ }
+
+ &.marks-before {
+ padding-top: 0;
+
+ > trough > slider {
+ border-top-left-radius: 0;
+ }
+ }
+
+ &.marks-after {
+ padding-bottom: 0;
+
+ > trough > slider {
+ border-bottom-right-radius: 0;
+ }
+ }
+
+ &.marks-before.marks-after > trough > slider {
+ border-radius: 100%;
+ }
+ }
+
+ &.vertical {
+ > marks {
+ color: gtkalpha(currentColor, $dim_label_opacity);
+ &.top { margin-right: $_marks_distance; }
+ &.bottom { margin-left: $_marks_distance; }
+
+ indicator {
+ background-color: currentColor;
+ min-height: 1px;
+ min-width: $_marks_length;
+ }
+ }
+
+ > value.top { margin-bottom: 9px; }
+ > value.bottom { margin-top: 9px; }
+
+ &.fine-tune > marks {
+ &.top { margin-left: 3px; }
+ &.bottom { margin-right: 3px; }
+
+ indicator { min-height: ($_marks_length - 3px); }
+ }
+
+ &.marks-before {
+ padding-left: 0;
+
+ > trough > slider {
+ border-bottom-left-radius: 0;
+ }
+ }
+
+ &.marks-after {
+ padding-right: 0;
+
+ > trough > slider {
+ border-top-right-radius: 0;
+ }
+ }
+ }
+
+ &.color {
+ padding: 0;
+
+ > trough {
+ border: none;
+ background: none;
+ border-radius: 10px;
+
+ > slider {
+ margin: 0;
+ background-color: transparentize(white, .2);
+ }
+ }
+
+ &.fine-tune {
+ padding: 2px;
+
+ > trough > slider {
+ margin: -2px;
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_scrolling.scss b/gtk/theme/libadwaita/widgets/_scrolling.scss
new file mode 100644
index 0000000000..cb78c88f6e
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_scrolling.scss
@@ -0,0 +1,184 @@
+$osd_scrollbar_outline_color: transparentize(black, .5);
+
+scrollbar {
+ $_slider_min_length: 40px;
+ $_slider_width: 8px;
+ $_scrollbar_transition: all 200ms linear;
+
+ > range > trough {
+ margin: 7px;
+ transition: $_scrollbar_transition;
+ border-radius: 10px;
+
+ > slider {
+ min-width: $_slider_width;
+ min-height: $_slider_width;
+ margin: -6px;
+ border: 6px solid transparent;
+ border-radius: 10px;
+ background-clip: padding-box;
+ transition: $_scrollbar_transition;
+
+ @if $contrast == 'high' {
+ background-color: gtkalpha(currentColor, .4);
+
+ &:hover { background-color: gtkalpha(currentColor, .6); }
+
+ &:active { background-color: currentColor; }
+ } @else {
+ background-color: gtkalpha(currentColor, .2);
+
+ &:hover { background-color: gtkalpha(currentColor, .4); }
+
+ &:active { background-color: gtkalpha(currentColor, .6); }
+ }
+
+ &:disabled { opacity: 0; }
+ }
+ }
+
+ &.horizontal > range > trough {
+ margin-top: 6px;
+ margin-bottom: 6px;
+ }
+
+ &.vertical > range > trough {
+ margin-left: 6px;
+ margin-right: 6px;
+ }
+
+ &.overlay-indicator {
+ background: none;
+ color: inherit;
+ box-shadow: none;
+ padding: 0;
+
+ > range > trough {
+ outline: 1px solid transparent;
+
+ > slider {
+ @if $contrast == 'high' {
+ outline: 1px solid $scrollbar_outline_color;
+ } @else {
+ outline: 1px solid gtkalpha($scrollbar_outline_color, .6);
+ }
+
+ .osd & {
+ @if $contrast == 'high' {
+ outline: 1px solid $osd_scrollbar_outline_color;
+ } @else {
+ outline: 1px solid gtkalpha($osd_scrollbar_outline_color, .6);
+ }
+ }
+
+ outline-offset: -6px;
+ }
+ }
+
+ &:not(.hovering) > range > trough > slider {
+ min-width: 3px;
+ min-height: 3px;
+
+ @if $contrast == 'high' {
+ outline-color: gtkalpha($scrollbar_outline_color, .6);
+ } @else {
+ outline-color: gtkalpha($scrollbar_outline_color, .35);
+ }
+
+ .osd & {
+ @if $contrast == 'high' {
+ outline-color: gtkalpha($osd_scrollbar_outline_color, .6);
+ } @else {
+ outline-color: gtkalpha($osd_scrollbar_outline_color, .35);
+ }
+ }
+ }
+
+ &.hovering > range > trough {
+ @if $contrast == 'high' {
+ background-color: gtkalpha(currentColor, .25);
+ } @else {
+ background-color: gtkalpha(currentColor, .1);
+ }
+ }
+
+ &.horizontal {
+ > range > trough > slider {
+ min-width: $_slider_min_length;
+ }
+
+ &.hovering > range > trough > slider {
+ min-height: $_slider_width;
+ }
+
+ &:not(.hovering) > range > trough {
+ margin-top: 3px;
+ margin-bottom: 3px;
+ }
+ }
+
+ &.vertical {
+ > range > trough > slider {
+ min-height: $_slider_min_length;
+ }
+
+ &.hovering > range > trough > slider {
+ min-width: $_slider_width;
+ }
+
+ &:not(.hovering) > range > trough {
+ margin-left: 3px;
+ margin-right: 3px;
+ }
+ }
+ }
+
+ &.horizontal > range > trough > slider { min-width: $_slider_min_length; }
+ &.vertical > range > trough > slider { min-height: $_slider_min_length; }
+
+ > range.fine-tune > trough > slider {
+ &, &:hover, &:active {
+ background-color: if($contrast == 'high', $accent_color, gtkalpha($accent_color, .6));
+ }
+ }
+}
+
+scrolledwindow {
+ // This is used when content is touch-dragged past boundaries.
+ // draws a box on top of the content, the size changes programmatically.
+ > overshoot {
+ &.top {
+ @include overshoot(top);
+ }
+
+ &.bottom {
+ @include overshoot(bottom);
+ }
+
+ &.left {
+ @include overshoot(left);
+ }
+
+ &.right {
+ @include overshoot(right);
+ }
+ }
+
+ &.undershoot-top {
+ @include undershoot(top);
+ }
+
+ &.undershoot-bottom {
+ @include undershoot(bottom);
+ }
+
+ &.undershoot-start {
+ &:dir(ltr) { @include undershoot(left); }
+ &:dir(rtl) { @include undershoot(right); }
+ }
+
+ &.undershoot-end {
+ &:dir(ltr) { @include undershoot(right); }
+ &:dir(rtl) { @include undershoot(left); }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_shortcuts-window.scss b/gtk/theme/libadwaita/widgets/_shortcuts-window.scss
new file mode 100644
index 0000000000..04f3b04f71
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_shortcuts-window.scss
@@ -0,0 +1,55 @@
+shortcuts-section {
+ margin: 20px;
+}
+
+.shortcuts-search-results {
+ margin: 20px;
+ border-spacing: 24px;
+}
+
+// shortcut window keys
+shortcut {
+ border-spacing: 6px;
+ border-radius: 6px;
+ @include focus-ring($outer: true, $offset: 4px);
+
+ > .keycap {
+ min-width: 20px;
+ min-height: 25px;
+ padding: 2px 6px;
+
+ @extend %card;
+
+ border-radius: $button_radius;
+ font-size: smaller;
+ }
+}
+
+shortcuts-section stackswitcher.circular {
+ border-spacing: 12px;
+
+ > button.circular,
+ > button.text-button.circular {
+ min-width: 32px;
+ min-height: 32px;
+ padding: 0;
+ }
+}
+
+window.shortcuts {
+ headerbar.titlebar {
+ @extend .flat;
+ @extend %headerbar-shrunk;
+
+ > windowhandle {
+ padding-top: 3px;
+ }
+ }
+
+ searchbar {
+ @extend %searchbar-flat;
+ @extend %searchbar-shrunk;
+
+ background: none;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_sidebars.scss b/gtk/theme/libadwaita/widgets/_sidebars.scss
new file mode 100644
index 0000000000..af024d28a8
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_sidebars.scss
@@ -0,0 +1,215 @@
+.sidebar-pane {
+ background-color: $sidebar_bg_color;
+ color: $sidebar_fg_color;
+
+ &:backdrop {
+ background-color: $sidebar_backdrop_color;
+ transition: background-color $backdrop_transition;
+ }
+
+ toolbarview.undershoot-top scrolledwindow {
+ @include undershoot(top, $sidebar_shade_color);
+ }
+
+ toolbarview.undershoot-bottom scrolledwindow {
+ @include undershoot(bottom, $sidebar_shade_color);
+ }
+
+ scrolledwindow {
+ &.undershoot-top {
+ @include undershoot(top, $sidebar_shade_color);
+ }
+
+ &.undershoot-bottom {
+ @include undershoot(bottom, $sidebar_shade_color)
+ }
+
+ &.undershoot-start {
+ &:dir(ltr) { @include undershoot(left, $sidebar_shade_color); }
+ &:dir(rtl) { @include undershoot(right, $sidebar_shade_color); }
+ }
+
+ &.undershoot-end {
+ &:dir(ltr) { @include undershoot(right, $sidebar_shade_color); }
+ &:dir(rtl) { @include undershoot(left, $sidebar_shade_color); }
+ }
+ }
+
+ flap,
+ leaflet,
+ navigation-view,
+ overlay-split-view {
+ @include transition-shadows($sidebar_shade_color);
+ }
+
+ banner > revealer > widget {
+ background-color: gtkmix($accent_bg_color, $sidebar_bg_color, 30%);
+ color: $sidebar_fg_color;
+
+ &:backdrop {
+ background-color: gtkmix($accent_bg_color, $sidebar_backdrop_color, 15%);
+ }
+ }
+
+ &:dir(ltr), &.end:dir(rtl) {
+ &, banner > revealer > widget {
+ box-shadow: inset -1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+ }
+ }
+
+ &:dir(rtl), &.end:dir(ltr) {
+ &, banner > revealer > widget {
+ box-shadow: inset 1px 0 if($contrast == 'high', $border_color, $sidebar_border_color);
+ }
+ }
+}
+
+/* Middle pane in three-pane setups */
+.content-pane .sidebar-pane,
+.sidebar-pane .content-pane {
+ background-color: $secondary_sidebar_bg_color;
+ color: $secondary_sidebar_fg_color;
+
+ &:backdrop {
+ background-color: $secondary_sidebar_backdrop_color;
+ transition: background-color $backdrop_transition;
+ }
+
+ toolbarview.undershoot-top scrolledwindow {
+ @include undershoot(top, $secondary_sidebar_shade_color);
+ }
+
+ toolbarview.undershoot-bottom scrolledwindow {
+ @include undershoot(bottom, $secondary_sidebar_shade_color);
+ }
+
+ scrolledwindow {
+ &.undershoot-top {
+ @include undershoot(top, $secondary_sidebar_shade_color);
+ }
+
+ &.undershoot-bottom {
+ @include undershoot(bottom, $secondary_sidebar_shade_color)
+ }
+
+ &.undershoot-start {
+ &:dir(ltr) { @include undershoot(left, $secondary_sidebar_shade_color); }
+ &:dir(rtl) { @include undershoot(right, $secondary_sidebar_shade_color); }
+ }
+
+ &.undershoot-end {
+ &:dir(ltr) { @include undershoot(right, $secondary_sidebar_shade_color); }
+ &:dir(rtl) { @include undershoot(left, $secondary_sidebar_shade_color); }
+ }
+ }
+
+ flap,
+ leaflet,
+ navigation-view,
+ overlay-split-view {
+ @include transition-shadows($secondary_sidebar_shade_color);
+ }
+
+ banner > revealer > widget {
+ background-color: gtkmix($accent_bg_color, $secondary_sidebar_bg_color, 30%);
+ color: $secondary_sidebar_fg_color;
+
+ &:backdrop {
+ background-color: gtkmix($accent_bg_color, $secondary_sidebar_backdrop_color, 15%);
+ }
+ }
+
+ &:dir(ltr), &.end:dir(rtl) {
+ &, banner > revealer > widget {
+ box-shadow: inset -1px 0 if($contrast == 'high', $border_color, $secondary_sidebar_border_color);
+ }
+ }
+
+ &:dir(rtl), &.end:dir(ltr) {
+ &, banner > revealer > widget {
+ box-shadow: inset 1px 0 if($contrast == 'high', $border_color, $secondary_sidebar_border_color);
+ }
+ }
+}
+
+.sidebar-pane .sidebar-pane {
+ background-color: transparent;
+ color: inherit;
+}
+
+stacksidebar row {
+ padding: 10px 4px;
+
+ > label {
+ padding-left: 6px;
+ padding-right: 6px;
+ }
+
+ &.needs-attention > label {
+ @extend %needs_attention;
+ background-size: 6px 6px, 0 0;
+ }
+}
+
+/**********************
+ * Navigation Sidebar *
+ **********************/
+
+.navigation-sidebar {
+ &, &.view, &.view:disabled {
+ background-color: transparent;
+ color: inherit;
+ }
+
+ &.background {
+ &, &:disabled {
+ background-color: $window_bg_color;
+ color: $window_fg_color;
+ }
+ }
+
+ row {
+ &.activatable {
+ &:hover { background-color: $hover_color; }
+
+ &:active { background-color: $active_color; }
+
+ // this is for indicathing which row generated a popover see https://bugzilla.gnome.org/show_bug.cgi?id=754411
+ &.has-open-popup { background-color: $hover_color; }
+
+ &:selected {
+ &:hover { background-color: $selected_hover_color; }
+
+ &:active { background-color: $selected_active_color; }
+
+ &.has-open-popup { background-color: $selected_hover_color; }
+ }
+ }
+
+ &:selected {
+ background-color: $selected_color;
+ }
+ }
+
+ padding: $menu-margin 0; //only vertical padding. horizontal row size would clip
+
+ > separator {
+ margin: $menu-margin;
+ }
+
+ > row {
+ min-height: 36px;
+ padding: 0 8px;
+ border-radius: $menu_radius;
+ margin: 0 $menu_margin 2px;
+
+ @if $contrast == 'high' {
+ &.activatable:hover,
+ &.activatable:active,
+ &.activatable.has-open-popup,
+ &:selected {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_spin-button.scss b/gtk/theme/libadwaita/widgets/_spin-button.scss
new file mode 100644
index 0000000000..4f806add96
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_spin-button.scss
@@ -0,0 +1,72 @@
+spinbutton {
+ @extend %entry;
+ @extend .numeric;
+
+ padding: 0;
+ border-spacing: 0;
+
+ /* :not here just to bump specificity above that of the list button styling */
+ > button.image-button.up:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque),
+ > button.image-button.down:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ @extend %button_basic_flat;
+
+ margin: 0;
+
+ border-radius: 0;
+ box-shadow: none;
+
+ border-style: solid;
+ border-color: gtkalpha(currentColor, if($contrast == 'high', .5, .1));
+ }
+
+ &:not(.vertical) {
+ > text {
+ min-width: 28px;
+ padding: 6px;
+ }
+
+ /* :not here just to bump specificity above that of the list button styling */
+ > button.image-button.up:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque),
+ > button.image-button.down:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ min-height: 16px;
+ min-width: 22px;
+ padding-bottom: 0;
+ padding-top: 0;
+ border-left-width: 1px;
+
+ &:dir(rtl) {
+ border-left-width: 0;
+ border-right-width: 1px;
+ }
+
+ &:dir(ltr):last-child {
+ border-radius: 0 $button_radius $button_radius 0;
+ }
+
+ &:dir(rtl):first-child {
+ border-radius: $button_radius 0 0 $button_radius;
+ }
+ }
+ }
+
+ &.vertical {
+ > text {
+ min-height: 30px;
+ min-width: 30px;
+ }
+
+ /* :not here just to bump specificity above that of the list button styling */
+ > button.image-button.up:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque),
+ > button.image-button.down:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &:last-child {
+ border-top-width: 1px;
+ border-radius: 0 0 $button_radius $button_radius;
+ }
+
+ &:first-child {
+ border-bottom-width: 1px;
+ border-radius: $button_radius $button_radius 0 0;
+ }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_spinner.scss b/gtk/theme/libadwaita/widgets/_spinner.scss
new file mode 100644
index 0000000000..ab1f020271
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_spinner.scss
@@ -0,0 +1,16 @@
+@keyframes spin {
+ to { transform: rotate(1turn); }
+}
+
+spinner {
+ background: none;
+ opacity: 0; // non spinning spinner makes no sense
+ -gtk-icon-source: -gtk-icontheme('process-working-symbolic');
+
+ &:checked {
+ opacity: 1;
+ animation: spin 1s linear infinite;
+
+ &:disabled { opacity: $disabled_opacity; }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_switch.scss b/gtk/theme/libadwaita/widgets/_switch.scss
new file mode 100644
index 0000000000..1cbb8835fd
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_switch.scss
@@ -0,0 +1,60 @@
+switch {
+ // similar to GtkScale
+ border-radius: 14px;
+ padding: 3px;
+
+ background-color: $trough_color;
+
+ &:hover { background-color: $trough_hover_color; }
+ &:active { background-color: $trough_active_color; }
+
+ @include focus-ring($offset: 1px, $outer: true);
+
+ &:disabled {
+ filter: opacity($disabled_opacity);
+ }
+
+ > slider {
+ min-width: 20px;
+ min-height: 20px;
+ border-radius: 50%;
+ background-color: $slider_color;
+ box-shadow: 0 2px 4px transparentize(black, .8);
+
+ &:disabled {
+ box-shadow: 0 2px 4px transparent;
+ }
+ }
+
+ &:hover > slider,
+ &:active > slider {
+ background: $slider_hover_color;
+ }
+
+ &:checked {
+ color: $fill_text_color;
+ background-color: $fill_color;
+
+ &:hover { background-image: image(gtkalpha(currentColor, .1)); }
+ &:active { background-image: image(transparentize(black, .8)); }
+
+ > slider {
+ background-color: $slider_hover_color;
+ }
+
+ @if $contrast == "high" {
+ > image { color: inherit; }
+ }
+ }
+
+ .osd & {
+ &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+
+ &:checked {
+ background-color: transparentize($osd_fill_bg_color, .15);
+ color: $osd_fill_fg_color;
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_tab-view.scss b/gtk/theme/libadwaita/widgets/_tab-view.scss
new file mode 100644
index 0000000000..8b69f08466
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_tab-view.scss
@@ -0,0 +1,268 @@
+tabbar {
+ .box {
+ background-color: $headerbar_bg_color;
+ color: $headerbar_fg_color;
+ box-shadow: inset 0 -1px if($contrast == 'high', $headerbar_border_color, $headerbar_shade_color);
+ padding: 1px;
+ padding-top: 0;
+
+ &:backdrop {
+ background-color: $headerbar_backdrop_color;
+ transition: background-color $backdrop_transition;
+
+ > scrolledwindow,
+ > .start-action,
+ > .end-action {
+ filter: opacity(0.5);
+ transition: filter $backdrop_transition;
+ }
+ }
+ }
+
+ tabbox {
+ padding-bottom: 6px;
+ padding-top: 6px;
+ min-height: 34px;
+
+ > tabboxchild {
+ @include focus-ring($focus-state: ':focus-within:focus-visible');
+ border-radius: $button_radius;
+ }
+
+ > separator {
+ margin-top: 3px;
+ margin-bottom: 3px;
+ transition: opacity 150ms ease-in-out;
+
+ &.hidden {
+ opacity: 0;
+ }
+ }
+
+ > revealer > indicator {
+ min-width: 2px;
+ border-radius: 2px;
+ margin: 3px 6px;
+ background: if($contrast == 'high', $accent_color, gtkalpha($accent_color, 0.5));
+ }
+ }
+
+ tab {
+ transition: background 150ms ease-in-out;
+
+ @if $contrast == 'high' {
+ &:hover,
+ &:active,
+ &:selected {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+
+ &:selected {
+ background-color: $selected_color;
+
+ &:hover { background-color: $selected_hover_color; }
+ &:active { background-color: $selected_active_color; }
+ }
+
+ &:hover { background-color: $hover_color; }
+ &:active { background-color: $active_color; }
+ }
+
+ tabbox.single-tab tab {
+ &, &:hover, &:active {
+ background: none;
+
+ @if $contrast == 'high' {
+ box-shadow: none;
+ }
+ }
+ }
+
+ .start-action,
+ .end-action {
+ padding: 6px 5px;
+ }
+
+ .start-action:dir(ltr),
+ .end-action:dir(rtl) {
+ padding-right: 0;
+ }
+
+ .start-action:dir(rtl),
+ .end-action:dir(ltr) {
+ padding-left: 0;
+ }
+
+ &.inline {
+ @extend %tabbar-inline;
+ }
+}
+
+%tabbar-inline .box {
+ background-color: transparent;
+ color: inherit;
+ box-shadow: none;
+ padding-bottom: 0;
+
+ &:backdrop {
+ background-color: transparent;
+ transition: none;
+
+ > scrolledwindow,
+ > .start-action,
+ > .end-action {
+ filter: none;
+ transition: none;
+ }
+ }
+}
+
+%tabbar-shrunk {
+ tabbox,
+ .start-action,
+ .end-action {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ }
+}
+
+dnd tab {
+ background-color: $headerbar_bg_color;
+ background-image: image($selected_active_color);
+ color: $headerbar_fg_color;
+
+ box-shadow: 0 0 0 1px transparentize(black, 0.97),
+ 0 1px 3px 1px transparentize(black, .93),
+ 0 2px 6px 2px transparentize(black, .97);
+
+ @if $contrast == 'high' {
+ outline: 1px solid $border_color;
+ outline-offset: -1px;
+ }
+
+ margin: 25px;
+}
+
+tabbar,
+dnd {
+ tab {
+ min-height: 26px;
+ padding: 4px;
+ border-radius: $button_radius;
+
+ button.image-button {
+ padding: 0;
+ margin: 0;
+ min-width: 24px;
+ min-height: 24px;
+ border-radius: 99px;
+ }
+
+ indicator {
+ min-height: 2px;
+ border-radius: 2px;
+ background: if($contrast == 'high', $accent_color, gtkalpha($accent_color, 0.5));
+ transform: translateY(4px);
+ }
+ }
+}
+
+tabgrid > tabgridchild {
+ @include focus-ring(".card", $offset: 0, $outer: true);
+}
+
+tabthumbnail {
+ border-radius: $card_radius + 4px;
+
+ > box {
+ margin: 6px;
+ }
+
+ &:drop(active) {
+ box-shadow: inset 0 0 0 2px gtkalpha($drop_target_color, .4);
+ background-color: gtkalpha($drop_target_color, .1);
+ }
+
+ transition: box-shadow 200ms $ease-out-quad, background-color $ease-out-quad;
+
+ .needs-attention {
+ &:dir(ltr) { transform: translate(8px, -8px); }
+ &:dir(rtl) { transform: translate(-8px, -8px); }
+
+ > widget {
+ background: $accent_color;
+ min-width: 12px;
+ min-height: 12px;
+ border-radius: 8px;
+ margin: 3px;
+ box-shadow: 0 1px 2px gtkalpha($accent_color, .4);
+ }
+ }
+
+ .card {
+ picture {
+ outline: 1px solid $window_outline_color;
+ outline-offset: -1px;
+ border-radius: $card_radius;
+ }
+
+ background: none;
+ color: inherit;
+
+ @if $contrast == 'high' {
+ box-shadow: 0 0 0 1px transparentize(black, 0.5),
+ 0 1px 3px 1px transparentize(black, .93),
+ 0 2px 6px 2px transparentize(black, .97);
+ }
+ }
+
+ &.pinned .card {
+ background-color: $thumbnail_bg_color;
+ color: $thumbnail_fg_color;
+
+ @if $contrast == 'high' {
+ outline: 1px solid $window_outline_color;
+ outline-offset: -1px;
+ }
+ }
+
+ .icon-title-box {
+ border-spacing: 6px;
+ }
+
+ .tab-unpin-icon {
+ margin: 6px;
+ min-width: 24px;
+ min-height: 24px;
+ }
+
+ button.circular {
+ margin: 6px;
+ background-color: gtkalpha($thumbnail_bg_color, .75);
+ min-width: 24px;
+ min-height: 24px;
+
+ @if $contrast == 'high' {
+ box-shadow: 0 0 0 1px currentColor;
+ }
+
+ &:hover {
+ background-color: gtkalpha(gtkmix($thumbnail_bg_color, currentColor, 90%), .75);
+ }
+
+ &:active {
+ background-color: gtkalpha(gtkmix($thumbnail_bg_color, currentColor, 80%), .75);
+ }
+ }
+}
+
+taboverview > .overview .new-tab-button {
+ margin: 18px;
+}
+
+tabview:drop(active),
+tabbox:drop(active),
+tabgrid:drop(active) {
+ box-shadow: none;
+}
diff --git a/gtk/theme/libadwaita/widgets/_text-selection.scss b/gtk/theme/libadwaita/widgets/_text-selection.scss
new file mode 100644
index 0000000000..2d596f5ba7
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_text-selection.scss
@@ -0,0 +1,30 @@
+cursor-handle {
+ all: unset;
+ padding: 24px 20px;
+
+ > contents {
+ min-width: 20px;
+ min-height: 20px;
+ border-radius: 50%;
+
+ background-color: $accent_bg_color;
+ }
+
+ &.top > contents {
+ border-top-right-radius: 0;
+ }
+
+ &.bottom > contents {
+ border-top-left-radius: 0;
+ transform: translateX(1px);
+ }
+
+ &.insertion-cursor > contents {
+ border-top-left-radius: 0;
+ transform: translateX(1px) translateY(4px) rotate(45deg);
+ }
+}
+
+magnifier {
+ background-color: $view_bg_color;
+}
diff --git a/gtk/theme/libadwaita/widgets/_toolbars.scss b/gtk/theme/libadwaita/widgets/_toolbars.scss
new file mode 100644
index 0000000000..62b3d67fbf
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_toolbars.scss
@@ -0,0 +1,310 @@
+%toolbar {
+ button:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &.arrow-button,
+ &.image-button,
+ &.image-text-button {
+ @extend %button_basic_flat;
+ }
+ }
+
+ &.osd button:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &:focus:focus-visible {
+ outline-color: $osd_focus_color;
+ }
+ }
+
+ menubutton:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &.image-button > button {
+ @extend %button_basic_flat;
+ }
+ }
+
+ .linked button:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &.arrow-button,
+ &.image-button,
+ &.image-text-button {
+ @extend %button_basic_raised;
+ }
+ }
+
+ menubutton.raised > button:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &.arrow-button,
+ &.image-button,
+ &.image-text-button {
+ @extend %button_basic_raised;
+ }
+ }
+
+ menubutton.suggested-action,
+ menubutton.destructive-action,
+ menubutton.opaque {
+ > button:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ @extend %opaque_button;
+
+ color: inherit;
+ background-color: transparent;
+ }
+ }
+
+ splitbutton:not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ @extend %flat_split_button;
+ }
+
+ switch {
+ margin-top: 4px;
+ margin-bottom: 4px;
+ }
+
+ // Reset styles for popovers
+ popover {
+ button:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &.arrow-button,
+ &.image-button,
+ &.image-text-button {
+ @extend %button_basic_raised;
+ }
+ }
+
+ menubutton:not(.flat):not(.raised):not(.suggested-action):not(.destructive-action):not(.opaque) {
+ &.image-button > button {
+ @extend %button_basic_raised;
+ }
+ }
+ }
+}
+
+.toolbar {
+ padding: 6px;
+ border-spacing: 6px;
+
+ @extend %toolbar;
+
+ // stand-alone OSD toolbars
+ &.osd {
+ padding: 12px;
+ border-radius: $card_radius;
+ }
+}
+
+%toolbar-shrunk {
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
+/****************
+ * GtkSearchBar *
+ ****************/
+
+searchbar {
+ > revealer > box {
+ padding: 6px 6px 7px 6px;
+
+ background-color: $headerbar_bg_color;
+ color: $headerbar_fg_color;
+ box-shadow: inset 0 -1px if($contrast == 'high', $headerbar_border_color, $headerbar_shade_color);
+
+ &:backdrop {
+ background-color: $headerbar_backdrop_color;
+ transition: background-color $backdrop_transition;
+
+ > * {
+ filter: opacity(.5);
+ transition: filter $backdrop_transition;
+ }
+ }
+
+ @extend %toolbar;
+
+ .close {
+ min-width: 18px;
+ min-height: 18px;
+ padding: 4px;
+ border-radius: 50%;
+ @extend %button_basic_flat;
+
+ &:dir(ltr) {
+ margin-left: 10px;
+ margin-right: 4px;
+ }
+
+ &:dir(rtl) {
+ margin-left: 4px;
+ margin-right: 10px;
+ }
+ }
+ }
+
+ &.inline {
+ @extend %searchbar-inline;
+ }
+}
+
+%searchbar-flat > revealer > box {
+ background-color: transparent;
+ color: inherit;
+ box-shadow: none;
+ padding-bottom: 6px;
+}
+
+%searchbar-inline {
+ @extend %searchbar-flat;
+
+ > revealer > box:backdrop {
+ background-color: transparent;
+ transition: none;
+
+ > * {
+ filter: none;
+ transition: none;
+ }
+ }
+}
+
+%searchbar-shrunk > revealer > box {
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
+/****************
+ * GtkActionBar *
+ ****************/
+
+actionbar > revealer > box {
+ background-color: $headerbar_bg_color;
+ color: $headerbar_fg_color;
+ box-shadow: inset 0 1px if($contrast == 'high', $headerbar_border_color, $headerbar_shade_color);
+ padding: 7px 6px 6px 6px;
+
+ @extend %toolbar;
+
+ &, > box.start, > box.end {
+ border-spacing: 6px;
+ }
+
+ &:backdrop {
+ background-color: $headerbar_backdrop_color;
+ transition: background-color $backdrop_transition;
+
+ > * {
+ filter: opacity(.5);
+ transition: filter $backdrop_transition;
+ }
+ }
+}
+
+%actionbar-inline > revealer > box {
+ background-color: transparent;
+ color: inherit;
+ box-shadow: none;
+ padding-top: 6px;
+
+ &:backdrop {
+ background-color: transparent;
+ transition: none;
+
+ > * {
+ filter: none;
+ transition: none;
+ }
+ }
+}
+
+%actionbar-shrunk > revealer > box {
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
+/*************
+ * AdwBanner *
+ *************/
+banner > revealer > widget {
+ /* There are 2 more instances in _sidebars.css, keep in sync with that */
+ background-color: gtkmix($accent_bg_color, $window_bg_color, 30%);
+ color: $window_fg_color;
+ padding: 6px;
+
+ &:backdrop {
+ background-color: gtkmix($accent_bg_color, $window_bg_color, 15%);
+ transition: background-color $backdrop_transition;
+
+ > label, > button {
+ filter: opacity(.5);
+ transition: filter $backdrop_transition;
+ }
+ }
+}
+
+/******************
+ * AdwToolbarView *
+ ******************/
+toolbarview {
+ > .top-bar,
+ > .bottom-bar {
+ headerbar { @extend %headerbar-inline; }
+ searchbar { @extend %searchbar-inline; }
+ actionbar { @extend %actionbar-inline; }
+ menubar { @extend %menubar-inline; }
+ tabbar { @extend %tabbar-inline; }
+
+ .collapse-spacing {
+ padding-top: 3px;
+ padding-bottom: 3px;
+
+ headerbar { @extend %headerbar-shrunk; }
+ searchbar { @extend %searchbar-shrunk; }
+ actionbar { @extend %actionbar-shrunk; }
+ menubar { @extend %menubar-shrunk; }
+ .toolbar { @extend %toolbar-shrunk; }
+ tabbar { @extend %tabbar-shrunk; }
+
+ viewswitcherbar { @extend %viewswitcherbar-shrunk; }
+ }
+
+ &.raised {
+ background-color: $headerbar_bg_color;
+ color: $headerbar_fg_color;
+
+ &:backdrop {
+ background-color: $headerbar_backdrop_color;
+ transition: background-color $backdrop_transition;
+ }
+ }
+
+ &:backdrop > windowhandle {
+ filter: opacity(.5);
+ transition: filter $backdrop_transition;
+ }
+ }
+
+ > .top-bar.raised {
+ box-shadow: 0 1px if($contrast == 'high', $border_color, gtkalpha($headerbar_shade_color, .5)),
+ 0 2px 4px gtkalpha($headerbar_shade_color, .5);
+
+ &.border {
+ box-shadow: 0 1px if($contrast == 'high', $border_color, $headerbar_darker_shade_color);
+ }
+ }
+
+ > .bottom-bar.raised {
+ box-shadow: 0 -1px if($contrast == 'high', $border_color, gtkalpha($headerbar_shade_color, .5)),
+ 0 -2px 4px gtkalpha($headerbar_shade_color, .5);
+
+ &.border {
+ box-shadow: 0 -1px if($contrast == 'high', $border_color, $headerbar_darker_shade_color);
+ }
+ }
+
+ &.undershoot-top scrolledwindow { @include undershoot(top); }
+ &.undershoot-bottom scrolledwindow { @include undershoot(bottom); }
+
+ window.devel & > .top-bar {
+ background-image: cross-fade(5% -gtk-recolor(url("assets/devel-symbolic.svg")),
+ image(transparent));
+ background-repeat: repeat-x;
+ }
+
+ window.devel dialog & > .top-bar {
+ background-image: unset;
+ background-repeat: unset;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_tooltip.scss b/gtk/theme/libadwaita/widgets/_tooltip.scss
new file mode 100644
index 0000000000..d9e6c92eac
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_tooltip.scss
@@ -0,0 +1,20 @@
+tooltip {
+ &.background {
+ // background-color needs to be set this way otherwise it gets drawn twice
+ // see https://bugzilla.gnome.org/show_bug.cgi?id=736155 for details.
+ background-color: transparentize(black, 0.2);
+ background-clip: padding-box;
+ border: 1px solid $tooltip_border_color; // this subtle border is meant to
+ // not make the tooltip melt with
+ // very dark backgrounds
+ color: white;
+ }
+
+ padding: 6px 10px;
+ border-radius: 9px;
+ box-shadow: none; // otherwise it gets inherited by windowframe.csd
+
+ > box {
+ border-spacing: 6px;
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_view-switcher.scss b/gtk/theme/libadwaita/widgets/_view-switcher.scss
new file mode 100644
index 0000000000..afc708fd55
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_view-switcher.scss
@@ -0,0 +1,123 @@
+viewswitcher {
+ border-spacing: 3px;
+
+ &.narrow {
+ margin-top: -3px;
+ margin-bottom: -3px;
+ min-height: 6px;
+ }
+
+ button.toggle {
+ padding: 0;
+
+ > stack > box {
+ &.narrow {
+ font-size: 0.75rem;
+ padding-top: 4px;
+
+ > label {
+ min-height: 18px;
+ padding-left: 3px;
+ padding-right: 3px;
+ padding-bottom: 2px;
+ }
+ }
+
+ &.wide {
+ padding: 2px 12px;
+ border-spacing: 6px;
+ }
+ }
+ }
+}
+
+/**********************
+ * AdwViewSwitcherBar *
+ **********************/
+
+viewswitcherbar actionbar > revealer > box {
+ padding-left: 0;
+ padding-right: 0;
+ padding-top: 7px;
+}
+
+%viewswitcherbar-shrunk actionbar > revealer > box {
+ // Not 0px because view switcher has negative margin
+ padding-top: 6px;
+}
+
+/************************
+ * AdwViewSwitcherTitle *
+ ************************/
+
+viewswitchertitle {
+ margin-top: -6px;
+ margin-bottom: -6px;
+
+ viewswitcher {
+ margin-left: 12px;
+ margin-right: 12px;
+
+ &.narrow {
+ margin-top: 3px;
+ margin-bottom: 3px;
+ }
+
+ &.wide {
+ margin-top: 6px;
+ margin-bottom: 6px;
+ }
+ }
+
+ windowtitle {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+}
+
+/*******************
+ * AdwIndicatorBin *
+ *******************/
+
+indicatorbin {
+ > indicator, > mask {
+ min-width: 6px;
+ min-height: 6px;
+ border-radius: 100px;
+ }
+
+ > indicator {
+ margin: 1px;
+ background: gtkalpha(currentColor, .4);
+ }
+
+ > mask {
+ padding: 1px;
+ background: black;
+ }
+
+ &.needs-attention > indicator {
+ background: $accent_color;
+ }
+
+ &.badge {
+ > indicator,
+ > mask {
+ min-height: 13px;
+ }
+
+ > indicator > label {
+ font-size: 0.6rem;
+ font-weight: bold;
+ padding-left: 4px;
+ padding-right: 4px;
+ color: white;
+ }
+
+ &.needs-attention > indicator {
+ background: $accent_bg_color;
+
+ > label { color: $accent_fg_color; }
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_views.scss b/gtk/theme/libadwaita/widgets/_views.scss
new file mode 100644
index 0000000000..f39ae5bf9d
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_views.scss
@@ -0,0 +1,75 @@
+.view,
+%view {
+ color: $view_fg_color;
+ background-color: $view_bg_color;
+
+ &:disabled {
+ color: gtkalpha(currentColor, .5);
+ background-color: gtkmix($window_bg_color, $view_bg_color, 60%);
+ }
+
+ &:selected {
+ &:focus, & {
+ background-color: $view_selected_color;
+
+ border-radius: $button_radius;
+ }
+ }
+}
+
+textview {
+ caret-color: currentColor;
+
+ > text {
+ @extend %view;
+
+ background-color: transparent;
+ }
+
+ > border {
+ background-color: gtkmix($window_bg_color, $view_bg_color, 50%);
+ }
+
+ &:drop(active) {
+ caret-color: $drop_target_color;
+ }
+}
+
+rubberband {
+ border: 1px solid $accent_color;
+ background-color: gtkalpha($accent_color, 0.2);
+}
+
+flowbox > flowboxchild,
+gridview > child {
+ padding: 3px;
+ border-radius: $button_radius;
+
+ @include focus-ring();
+
+ &:selected {
+ background-color: $view_selected_color;
+
+ @if $contrast == 'high' {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+}
+
+gridview > child.activatable {
+ &:hover { background-color: $view_hover_color; }
+
+ &:active { background-color: $view_active_color; }
+
+ &:selected {
+ &:hover { background-color: $view_selected_hover_color; }
+
+ &:active { background-color: $view_selected_active_color; }
+ }
+
+ @if $contrast == 'high' {
+ &:hover, &:active {
+ box-shadow: inset 0 0 0 1px $border_color;
+ }
+ }
+}
diff --git a/gtk/theme/libadwaita/widgets/_window.scss b/gtk/theme/libadwaita/widgets/_window.scss
new file mode 100644
index 0000000000..5f18de2d43
--- /dev/null
+++ b/gtk/theme/libadwaita/widgets/_window.scss
@@ -0,0 +1,81 @@
+window {
+ &.csd {
+ box-shadow: 0 1px 3px 3px transparent,
+ 0 2px 8px 2px transparentize(black, 0.87),
+ 0 3px 20px 10px transparentize(black, 0.91),
+ 0 6px 32px 16px transparentize(black, 0.96),
+ 0 0 0 1px transparentize(black, if($contrast == 'high', .2, .95));
+ margin: 0px;
+ border-radius: $window_radius;
+
+ outline: 1px solid $window_outline_color;
+ outline-offset: -1px;
+
+ &:backdrop {
+ // the transparent shadow here is to enforce that the shadow extents don't
+ // change when we go to backdrop, to prevent jumping windows.
+ // The biggest shadow should be in the same order then in the active state
+ // or the jumping will happen during the transition.
+ box-shadow: 0 1px 3px 3px transparentize(black, 0.91),
+ 0 2px 14px 5px transparentize(black, 0.95),
+ 0 4px 28px 12px transparentize(black, 0.97),
+ 0 6px 32px 16px transparent,
+ 0 0 0 1px transparentize(black, if($contrast == 'high', .2, .98));
+ transition: box-shadow $backdrop_transition;
+ }
+
+ &.dialog.message,
+ &.messagedialog {
+ box-shadow: 0 2px 8px 2px transparentize(black, 0.93),
+ 0 3px 20px 10px transparentize(black, 0.95),
+ 0 6px 32px 16px transparentize(black, 0.98),
+ 0 0 0 1px transparentize(black, if($contrast == 'high', .2, .95));
+ }
+
+ &.tiled,
+ &.tiled-top,
+ &.tiled-left,
+ &.tiled-right,
+ &.tiled-bottom {
+ border-radius: 0;
+ outline: none;
+
+ box-shadow: 0 0 0 1px $border_color,
+ 0 0 0 20px transparent; //transparent control workaround -- #3670
+
+ &:backdrop {
+ box-shadow: 0 0 0 1px $border_color,
+ 0 0 0 20px transparent;
+ }
+ }
+
+ &.maximized,
+ &.fullscreen {
+ border-radius: 0;
+ outline: none;
+ box-shadow: none;
+ transition: none;
+ }
+ }
+
+ &.solid-csd {
+ margin: 0;
+ padding: 5px;
+ border-radius: 0;
+ box-shadow: inset 0 0 0 5px $border_color,
+ inset 0 0 0 4px $headerbar_bg_color,
+ inset 0 0 0 1px $border_color;
+
+ &:backdrop {
+ box-shadow: inset 0 0 0 5px $border_color,
+ inset 0 0 0 4px $headerbar_backdrop_color,
+ inset 0 0 0 1px $border_color;
+ }
+ }
+
+ // server-side decorations as used by mutter
+ &.ssd {
+ // just doing borders, wm draws actual shadows
+ box-shadow: 0 0 0 1px transparentize(black, if($contrast == 'high', .2, .95));
+ }
+}