[debian-edu-commits] debian-edu/ 03/09: add art-softwaves.

Wolfgang Schweer schweer-guest at moszumanska.debian.org
Fri Oct 28 15:48:01 UTC 2016


This is an automated email from the git hooks/post-receive script.

schweer-guest pushed a commit to branch schweer/softwaves
in repository debian-edu-artwork.

commit 11cee336c941a7b40cc8779260f1e61afa973576
Author: Wolfgang Schweer <wschweer at arcor.de>
Date:   Fri Oct 28 14:00:17 2016 +0200

    add art-softwaves.
---
 art-softwaves/Makefile.am                          |    5 +
 art-softwaves/desktop-base/20-desktop-base-edu.js  |   13 +
 art-softwaves/desktop-base/Makefile.am             |   91 +
 .../desktop-base/debian-edu-softwaves-grub.svg     |    1 +
 .../debian-edu-softwaves-grub_1920x1080.svg        |    1 +
 .../desktop-base/debian-edu-softwaves-login.svg    |    1 +
 .../debian-edu-softwaves-wallpaper.svg.desktop     |    7 +
 .../debian-edu-softwaves-wallpaper_1024x768.svg    |    1 +
 .../debian-edu-softwaves-wallpaper_1280x1024.svg   |    1 +
 .../debian-edu-softwaves-wallpaper_1600x1200.svg   |    1 +
 .../debian-edu-softwaves-wallpaper_1920x1080.svg   |    1 +
 .../debian-edu-softwaves-wallpaper_1920x1200.svg   |    1 +
 .../debian-edu-softwaves-wallpaper_2560x1080.svg   |    1 +
 .../desktop-base/debian-edu-softwaves.xml          |   13 +
 art-softwaves/desktop-base/metadata.desktop        |    7 +
 art-softwaves/g-i/Makefile.am                      |   17 +
 art-softwaves/g-i/README                           |   12 +
 .../g-i/debian-edu-softwaves-installer-logo.info   |    6 +
 .../g-i/debian-edu-softwaves-installer-logo.svg    |    1 +
 art-softwaves/gnome-shell/Makefile.am              |    8 +
 .../gnome-shell/debian-edu-softwaves-gdm.svg       |    1 +
 .../debian-edu-softwaves-gnome-shell.css           | 2711 ++++++++++++++++++++
 art-softwaves/ldm/Makefile.am                      |   15 +
 art-softwaves/ldm/bg.png                           |  Bin 0 -> 130472 bytes
 art-softwaves/ldm/bg.svg                           |    1 +
 art-softwaves/ldm/greeter-gtkrc                    |   91 +
 art-softwaves/ldm/logo.png                         |  Bin 0 -> 1846 bytes
 art-softwaves/ldm/preview.png                      |  Bin 0 -> 145615 bytes
 art-softwaves/plymouth/Makefile.am                 |   28 +
 art-softwaves/plymouth/README                      |    1 +
 .../plymouth/debian-edu-softwaves-logo.svg         |    1 +
 .../plymouth/debian-edu-softwaves-plymouth.svg     |    1 +
 .../plymouth/debian-edu-softwaves.plymouth         |    8 +
 art-softwaves/plymouth/debian-edu-softwaves.script | 1031 ++++++++
 art-softwaves/plymouth/password_dot.png            |  Bin 0 -> 324 bytes
 art-softwaves/plymouth/password_dot16.png          |  Bin 0 -> 285 bytes
 art-softwaves/plymouth/password_field.png          |  Bin 0 -> 1214 bytes
 art-softwaves/plymouth/password_field16.png        |  Bin 0 -> 230 bytes
 38 files changed, 4078 insertions(+)

diff --git a/art-softwaves/Makefile.am b/art-softwaves/Makefile.am
new file mode 100644
index 0000000..3baaeb1
--- /dev/null
+++ b/art-softwaves/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = desktop-base \
+          g-i \
+          gnome-shell \
+          ldm \
+          plymouth
diff --git a/art-softwaves/desktop-base/20-desktop-base-edu.js b/art-softwaves/desktop-base/20-desktop-base-edu.js
new file mode 100644
index 0000000..b621ae0
--- /dev/null
+++ b/art-softwaves/desktop-base/20-desktop-base-edu.js
@@ -0,0 +1,13 @@
+// Placed in /usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/
+//
+// This script is run once for each user and it sets the default wallpaper
+// for all activities
+
+d = desktops()
+
+for (i in d) {
+    d[i].wallpaperPlugin = 'org.kde.image'
+    d[i].currentConfigGroup = Array('Wallpaper', 'org.kde.image', 'General')
+    d[i].writeConfig('Image', 'Debian-Edu-SoftWaves')
+    d[i].writeConfig('FillMode', '2')          //enables croping
+}
diff --git a/art-softwaves/desktop-base/Makefile.am b/art-softwaves/desktop-base/Makefile.am
new file mode 100644
index 0000000..ef7e27e
--- /dev/null
+++ b/art-softwaves/desktop-base/Makefile.am
@@ -0,0 +1,91 @@
+THEME = softwaves
+THEMECONTENT = SoftWaves
+DESKTOPBASEIMG = \
+	debian-edu-$(THEME)-wallpaper_1024x768.svg \
+	debian-edu-$(THEME)-wallpaper_1280x1024.svg \
+	debian-edu-$(THEME)-wallpaper_1600x1200.svg \
+	debian-edu-$(THEME)-wallpaper_1920x1080.svg \
+	debian-edu-$(THEME)-wallpaper_1920x1200.svg \
+	debian-edu-$(THEME)-wallpaper_2560x1080.svg \
+	debian-edu-$(THEME)-login.svg \
+	debian-edu-$(THEME)-grub.png \
+	debian-edu-$(THEME)-grub_1920x1080.png
+
+EDUIMG = \
+	1024x768.png \
+	1280x1024.png \
+	1600x1200.png \
+	1920x1080.png \
+	1920x1200.png \
+	2560x1080.png
+
+desktopbaseimgdir = $(datadir)/images/desktop-base
+desktopbaseimg_DATA = $(DESKTOPBASEIMG) debian-edu-$(THEME).xml
+
+kdeplasmadir = $(datadir)/debian-edu-artwork-$(THEME)/kde4/apps/plasma-desktop/init/
+kdeplasma_DATA = 20-desktop-base-edu.js
+
+edudir = $(datadir)/wallpapers/Debian-Edu-$(THEMECONTENT)/
+edu_DATA = metadata.desktop
+
+educontentsdir = $(datadir)/wallpapers/Debian-Edu-$(THEMECONTENT)/contents/
+educontents_DATA = screenshot.png
+
+eduimgdir = $(datadir)/wallpapers/Debian-Edu-$(THEMECONTENT)/contents/images/
+eduimg_DATA = $(EDUIMG)
+
+# Build rules for PNG files using the SVG files in playground/stretch as source.
+1024x768.png: debian-edu-$(THEME)-wallpaper_1024x768.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+1280x1024.png: debian-edu-$(THEME)-wallpaper_1280x1024.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+1600x1200.png: debian-edu-$(THEME)-wallpaper_1600x1200.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+1920x1080.png: debian-edu-$(THEME)-wallpaper_1920x1080.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+1920x1200.png: debian-edu-$(THEME)-wallpaper_1920x1200.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+2560x1080.png: debian-edu-$(THEME)-wallpaper_2560x1080.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+debian-edu-$(THEME)-grub.png: debian-edu-$(THEME)-grub.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+debian-edu-$(THEME)-grub_1920x1080.png: debian-edu-$(THEME)-grub_1920x1080.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+screenshot.png: debian-edu-$(THEME)-wallpaper_1920x1200.svg
+	inkscape -z -e $@ $^
+	convert $@ -resize 400x +set date:create +set date:modify $@
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+install-data-local:
+	$(mkinstalldirs) $(DESTDIR)$(desktopbaseimgdir)
+	$(mkinstalldirs) $(DESTDIR)$(edudir)
+	$(mkinstalldirs) $(DESTDIR)$(educontentsdir)
+	$(mkinstalldirs) $(DESTDIR)$(eduimgdir)
+	$(mkinstalldirs) $(DESTDIR)$(Xsessiondir)
+
+EXTRA_DIST = $(desktopbaseimg_DATA) $(edu_DATA) $(educontents_DATA) $(eduimg_DATA) $(kdeplasma_DATA)
+
+CLEANFILES = 1024x768.png 1280x1024.png 1600x1200.png 1920x1080.png 1920x1200.png 2560x1080.png \
+             debian-edu-$(THEME)-grub.png debian-edu-$(THEME)-grub_1920x1080.png screenshot.png
+
+
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-grub.svg b/art-softwaves/desktop-base/debian-edu-softwaves-grub.svg
new file mode 120000
index 0000000..1247fc9
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-grub.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-grub.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-grub_1920x1080.svg b/art-softwaves/desktop-base/debian-edu-softwaves-grub_1920x1080.svg
new file mode 120000
index 0000000..270122f
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-grub_1920x1080.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-grub_1920x1080.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-login.svg b/art-softwaves/desktop-base/debian-edu-softwaves-login.svg
new file mode 120000
index 0000000..53bd5a0
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-login.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-login.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper.svg.desktop b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper.svg.desktop
new file mode 100644
index 0000000..c74f1af
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper.svg.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Debian-Edu-SoftWaves
+
+X-KDE-PluginInfo-Name=Debian Edu SoftWaves
+X-KDE-PluginInfo-Author=Wolfgang Schweer <wschweer at arcor.de>
+X-KDE-PluginInfo-Email=debian-edu at lists.debian.org
+X-KDE-PluginInfo-License=GPLv2+
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1024x768.svg b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1024x768.svg
new file mode 120000
index 0000000..76974eb
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1024x768.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-wallpaper_1024x768.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1280x1024.svg b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1280x1024.svg
new file mode 120000
index 0000000..c130772
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1280x1024.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-wallpaper_1280x1024.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1600x1200.svg b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1600x1200.svg
new file mode 120000
index 0000000..cb746c1
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1600x1200.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-wallpaper_1600x1200.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1920x1080.svg b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1920x1080.svg
new file mode 120000
index 0000000..681b30f
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1920x1080.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-wallpaper_1920x1080.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1920x1200.svg b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1920x1200.svg
new file mode 120000
index 0000000..186a551
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_1920x1200.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-wallpaper_1920x1200.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_2560x1080.svg b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_2560x1080.svg
new file mode 120000
index 0000000..cc3be70
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves-wallpaper_2560x1080.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-wallpaper_2560x1080.svg
\ No newline at end of file
diff --git a/art-softwaves/desktop-base/debian-edu-softwaves.xml b/art-softwaves/desktop-base/debian-edu-softwaves.xml
new file mode 100644
index 0000000..3ae26a0
--- /dev/null
+++ b/art-softwaves/desktop-base/debian-edu-softwaves.xml
@@ -0,0 +1,13 @@
+<background>
+  <static>
+    <duration>8640000.0</duration>
+    <file>
+      <size width="1024" height="768">/usr/share/images/desktop-base/debian-edu-softwaves-wallpaper_1024x768.svg</size>
+      <size width="1280" height="1024">/usr/share/images/desktop-base/debian-edu-softwaves-wallpaper_1280x1024.svg</size>
+      <size width="1600" height="1200">/usr/share/images/desktop-base/debian-edu-softwaves-wallpaper_1600x1200.svg</size>
+      <size width="1920" height="1080">/usr/share/images/desktop-base/debian-edu-softwaves-wallpaper_1920x1080.svg</size>
+      <size width="1920" height="1200">/usr/share/images/desktop-base/debian-edu-softwaves-wallpaper_1920x1200.svg</size>
+      <size width="2560" height="1080">/usr/share/images/desktop-base/debian-edu-softwaves-wallpaper_2560x1080.svg</size>
+    </file>
+  </static>
+</background>
diff --git a/art-softwaves/desktop-base/metadata.desktop b/art-softwaves/desktop-base/metadata.desktop
new file mode 100644
index 0000000..c74f1af
--- /dev/null
+++ b/art-softwaves/desktop-base/metadata.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Debian-Edu-SoftWaves
+
+X-KDE-PluginInfo-Name=Debian Edu SoftWaves
+X-KDE-PluginInfo-Author=Wolfgang Schweer <wschweer at arcor.de>
+X-KDE-PluginInfo-Email=debian-edu at lists.debian.org
+X-KDE-PluginInfo-License=GPLv2+
diff --git a/art-softwaves/g-i/Makefile.am b/art-softwaves/g-i/Makefile.am
new file mode 100644
index 0000000..02479bc
--- /dev/null
+++ b/art-softwaves/g-i/Makefile.am
@@ -0,0 +1,17 @@
+THEME = softwaves
+logodir = $(datadir)/pixmaps
+
+logo_DATA = debian-edu-$(THEME)-installer-logo.png
+
+install-data-local:
+	$(mkinstalldirs) $(DESTDIR)$(logodir)
+
+# Build rule for the PNG using the SVG as the source
+debian-edu-$(THEME)-installer-logo.png: debian-edu-$(THEME)-installer-logo.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+EXTRA_DIST = README $(logo_DATA)
+
+CLEANFILES = debian-edu-$(THEME)-installer-logo.png
diff --git a/art-softwaves/g-i/README b/art-softwaves/g-i/README
new file mode 100644
index 0000000..4a8007e
--- /dev/null
+++ b/art-softwaves/g-i/README
@@ -0,0 +1,12 @@
+We should find a way to replace the banner image used in the graphical
+version of the debian installer.  The image used by g-i is
+/usr/share/graphics/logo_debian.png from the rootskel-gtk package.
+It  is a PNG image data, 800 x 75, 8-bit/color RGBA, non-interlaced.
+
+It is unknown how to properly replace it in a custom debian distribution.
+Perhaps we need to make our own g-i boot images to make it happen.
+
+An idea is to modify debian-cd to append a compressed cpio archive with
+this replacement file to the initrd.gz file used when booting g-i.  It
+will then replace the original file when the initrd is unpackaged into
+memory.
diff --git a/art-softwaves/g-i/debian-edu-softwaves-installer-logo.info b/art-softwaves/g-i/debian-edu-softwaves-installer-logo.info
new file mode 100644
index 0000000..f9b5e4d
--- /dev/null
+++ b/art-softwaves/g-i/debian-edu-softwaves-installer-logo.info
@@ -0,0 +1,6 @@
+The debian-edu-softwaves-installer-logo.svg was created by 
+Wolfgang Schweer <wschweer at arcor.de> based upon the Stretch 'softWaves' 
+theme by Juliette Taka Belin <juliette.belin at free.fr> and the
+Debian Edu logo by Christoph Muetze <gizmo at pixelz.de>.
+
+It has been released under version 2 of the GPL or any later version.
diff --git a/art-softwaves/g-i/debian-edu-softwaves-installer-logo.svg b/art-softwaves/g-i/debian-edu-softwaves-installer-logo.svg
new file mode 120000
index 0000000..f3bc3ff
--- /dev/null
+++ b/art-softwaves/g-i/debian-edu-softwaves-installer-logo.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-installer-logo.svg
\ No newline at end of file
diff --git a/art-softwaves/gnome-shell/Makefile.am b/art-softwaves/gnome-shell/Makefile.am
new file mode 100644
index 0000000..a9a5e1e
--- /dev/null
+++ b/art-softwaves/gnome-shell/Makefile.am
@@ -0,0 +1,8 @@
+THEME = softwaves
+gnomedir    = $(datadir)/gnome-shell/theme
+gnome_DATA  = debian-edu-$(THEME)-gdm.svg debian-edu-$(THEME)-gnome-shell.css
+
+install-data-local:
+	$(mkinstalldirs) $(DESTDIR)$(gnomedir)
+
+EXTRA_DIST = $(gnomedir_DATA)
diff --git a/art-softwaves/gnome-shell/debian-edu-softwaves-gdm.svg b/art-softwaves/gnome-shell/debian-edu-softwaves-gdm.svg
new file mode 120000
index 0000000..4afdcb9
--- /dev/null
+++ b/art-softwaves/gnome-shell/debian-edu-softwaves-gdm.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-gdm.svg
\ No newline at end of file
diff --git a/art-softwaves/gnome-shell/debian-edu-softwaves-gnome-shell.css b/art-softwaves/gnome-shell/debian-edu-softwaves-gnome-shell.css
new file mode 100644
index 0000000..e4672f1
--- /dev/null
+++ b/art-softwaves/gnome-shell/debian-edu-softwaves-gnome-shell.css
@@ -0,0 +1,2711 @@
+/* Copyright 2009, Red Hat, Inc.
+ *
+ * Portions adapted from Mx's data/style/default.css
+ *   Copyright 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Text Styles */
+
+/* default text style */
+stage {
+    font-family: cantarell, sans-serif;
+    font-size: 11pt;
+    color: white;
+}
+
+/* links */
+.shell-link {
+    color: #0000ff;
+    text-decoration: underline;
+}
+
+.shell-link:hover {
+    color: #0000e0;
+}
+
+/* small */
+.app-well-menu,
+.run-dialog-error-label {
+    font-size: 9pt;
+}
+
+/* small bold */
+.dash-label,
+.window-caption,
+.switcher-list,
+.app-well-app > .overview-icon,
+.show-apps > .overview-icon,
+.grid-search-result .overview-icon {
+    font-size: 9pt;
+    font-weight: bold;
+}
+
+/* Scroll Bars */
+
+StScrollBar {
+    padding: 0px;
+}
+
+StScrollView.vfade {
+    -st-vfade-offset: 68px;
+}
+
+StScrollView.hfade {
+    -st-hfade-offset: 68px;
+}
+
+StScrollView StScrollBar {
+    min-width: 14px;
+    min-height: 14px;
+}
+
+StScrollBar StBin#trough {
+    background-color: rgba(0,0,0,0.3);
+    border-radius: 8px;
+}
+
+StScrollBar StButton#vhandle {
+    background-color: #5d6464;
+    border: 2px solid #242424;
+    border-radius: 8px;
+}
+
+StScrollBar StButton#hhandle {
+    background-color: #5d6464;
+    border: 2px solid #242424;
+    border-radius: 8px;
+}
+
+StScrollBar StButton#hhandle:hover,
+StScrollBar StButton#vhandle:hover {
+    background-color: #777d7c;
+}
+
+StScrollBar StButton#hhandle:active,
+StScrollBar StButton#vhandle:active {
+    background-color: #3465a4;
+}
+
+/* Check Boxes */
+
+.check-box StBoxLayout {
+    spacing: .8em;
+}
+
+.check-box StBin {
+    width: 24px;
+    height: 22px;
+    background-image: url("checkbox-off.svg");
+}
+
+.check-box:focus StBin {
+    background-image: url("checkbox-off-focused.svg");
+}
+
+.check-box:checked StBin {
+    background-image: url("checkbox.svg");
+}
+
+.check-box:focus:checked StBin {
+    background-image: url("checkbox-focused.svg");
+}
+
+/* Slider */
+
+.slider {
+    height: 1em;
+    -slider-height: 0.3em;
+    -slider-background-color: #333333;
+    -slider-border-color: #5f5f5f;
+    -slider-active-background-color: #76b0ec;
+    -slider-active-border-color: #1f6dbc;
+    -slider-border-width: 1px;
+    -slider-handle-radius: 6px;
+}
+
+/* PopupMenu */
+
+.popup-menu-ornament {
+    text-align: right;
+    width: 1em;
+}
+
+.popup-menu-boxpointer,
+.candidate-popup-boxpointer {
+    -arrow-border-radius: 8px;
+    -arrow-background-color: rgba(0,0,0,0.9);
+    -arrow-border-width: 2px;
+    -arrow-border-color: #a5a5a5;
+    -arrow-base: 24px;
+    -arrow-rise: 11px;
+}
+
+.popup-menu-boxpointer.fallback-app-menu {
+    -arrow-border-radius: 4px;
+    -arrow-background-color: #ededed;
+    -arrow-border-width: 1px;
+    -arrow-border-color: #a6a6a6;
+    -arrow-base: 24px;
+    -arrow-rise: 11px;
+}
+
+.popup-menu-boxpointer.fallback-app-menu.dark {
+    -arrow-background-color: #3f4747;
+    -arrow-border-color: #282b2b;
+}
+
+
+.popup-menu {
+    min-width: 200px;
+}
+
+.popup-menu-arrow {
+    width: 16px;
+    height: 16px;
+}
+
+.popup-submenu-menu-item:open {
+    background-color: #333333;
+}
+
+.fallback-app-menu .popup-submenu-menu-item:open {
+    background-color: #888888;
+    color: white;
+}
+
+.fallback-app-menu.dark .popup-submenu-menu-item:open {
+    background-color: #333333;
+}
+
+.popup-sub-menu {
+    background-gradient-start: rgba(80,80,80,0.3);
+    background-gradient-end: rgba(80,80,80,0.4);
+    background-gradient-direction: vertical;
+    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
+}
+
+.fallback-app-menu .popup-sub-menu {
+    background-gradient-start: #dddddd;
+    background-gradient-end: #dfdfdf;
+    background-gradient-direction: vertical;
+    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.4);
+}
+
+.fallback-app-menu.dark .popup-sub-menu {
+    background-gradient-start: #474747;
+    background-gradient-end: #4b4b4b;
+    background-gradient-direction: vertical;
+    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
+}
+
+.popup-sub-menu:scrolled .popup-menu-item:ltr {
+    padding-right: 0em;
+}
+
+.popup-sub-menu:scrolled .popup-menu-item:rtl {
+    padding-left: 0em;
+}
+
+.popup-sub-menu StScrollBar {
+    padding: 4px;
+}
+
+.popup-sub-menu StScrollBar StBin#trough {
+    border-width: 0px;
+}
+
+.popup-sub-menu StScrollBar StBin#vhandle {
+    background-color: #4c4c4c;
+    border-width: 0px;
+}
+
+/* The remaining popup-menu sizing is all done in ems, so that if you
+ * override .popup-menu.font-size, everything else will scale with it.
+ */
+.popup-menu-content {
+    padding: 1em 0em;
+}
+
+.popup-menu-item {
+    spacing: 12px;
+}
+
+.popup-menu-item:ltr {
+    padding: .4em 1.75em .4em 0em;
+}
+
+.popup-menu-item:rtl {
+    padding: .4em 0em .4em 1.75em;
+}
+
+.popup-menu-item:active {
+    background-color: #4c4c4c;
+}
+
+.popup-menu-item:insensitive {
+    color: #9f9f9f;
+}
+
+.fallback-app-menu .popup-menu-item {
+    color: #43484a;
+}
+
+.fallback-app-menu .popup-menu-item:active {
+    color: white;
+    background-color: #4689cd;
+}
+
+.fallback-app-menu .popup-menu-item:insensitive {
+    color: gray;
+}
+
+.fallback-app-menu.dark .popup-menu-item {
+    color: white;
+}
+
+.fallback-app-menu.dark .popup-menu-item:active {
+    background-color: #445f7d;
+}
+
+.fallback-app-menu.dark .popup-menu-item:insensitive {
+    color: #9f9f9f;
+}
+
+.popup-separator-menu-item {
+    -gradient-height: 1px;
+    -gradient-start: rgba(255,255,255,0.0);
+    -gradient-end: rgba(255,255,255,0.3);
+    -margin-horizontal: 24px;
+    height: 1px;
+    padding: 8px 0px;
+}
+
+.fallback-app-menu .popup-separator-menu-item {
+    -gradient-start: #a0a2a3;
+    -gradient-end: #a0a2a3;
+    -margin-horizontal: 0;
+}
+
+.fallback-app-menu.dark .popup-separator-menu-item {
+    -gradient-start: #818584;
+    -gradient-end: #818584;
+}
+
+.popup-status-menu-item {
+    font-weight: normal;
+    color: #999;
+}
+
+.popup-inactive-menu-item, .popup-inactive-menu-item:insensitive {
+    color: white;
+}
+
+.popup-menu-icon {
+    icon-size: 1.09em;
+}
+
+/* Switches */
+.toggle-switch {
+    width: 65px;
+    height: 22px;
+}
+
+.toggle-switch-us {
+    background-image: url("toggle-off-us.svg");
+    background-size: contain;
+}
+.toggle-switch-us:checked {
+    background-image: url("toggle-on-us.svg");
+    background-size: contain;
+}
+
+.toggle-switch-intl {
+    background-image: url("toggle-off-intl.svg");
+    background-size: contain;
+}
+.toggle-switch-intl:checked {
+    background-image: url("toggle-on-intl.svg");
+    background-size: contain;
+}
+
+/* Network */
+
+.nm-dialog {
+    max-height: 500px;
+    min-height: 450px;
+    min-width: 470px;
+}
+
+.nm-dialog-content {
+    spacing: 20px;
+}
+
+.nm-dialog-header-hbox {
+    spacing: 10px;
+}
+
+.nm-dialog-airplane-box {
+    spacing: 12px;
+}
+
+.nm-dialog-airplane-headline {
+    font-size: 1.1em;
+    font-weight: bold;
+    text-align: center;
+}
+
+.nm-dialog-airplane-text {
+    color: #999999;
+}
+
+.nm-dialog-header-icon {
+    icon-size: 32px;
+}
+
+.nm-dialog-scroll-view {
+    border: 2px solid #666;
+    border-radius: 6px;
+}
+
+.nm-dialog-header {
+    font-weight: bold;
+}
+
+.nm-dialog-item {
+    font-size: 12pt;
+    border-bottom: 1px solid #666;
+    padding: 12px;
+    spacing: 20px;
+}
+
+.nm-dialog-item:selected {
+    background-color: #333;
+}
+
+.nm-dialog-icons {
+    spacing: .5em;
+}
+
+.nm-dialog-icon {
+    icon-size: 16px;
+}
+
+.no-networks-label {
+    color: #999999;
+}
+
+.no-networks-box {
+    spacing: 12px;
+}
+
+/* Buttons */
+
+.candidate-page-button,
+.notification-button,
+.notification-icon-button,
+.hotplug-notification-item,
+.hotplug-resident-eject-button,
+.modal-dialog-button,
+.app-view-control {
+    border: 1px solid #8b8b8b;
+    background-gradient-direction: vertical;
+    background-gradient-start: rgba(255, 255, 255, 0.2);
+    background-gradient-end: rgba(255, 255, 255, 0);
+}
+
+.modal-dialog-button {
+    font-weight: bold;
+}
+
+.candidate-page-button:hover,
+.notification-button:hover,
+.notification-icon-button:hover,
+.hotplug-notification-item:hover,
+.hotplug-resident-eject-button:hover,
+.modal-dialog-button:hover {
+    background-gradient-start: rgba(255, 255, 255, 0.3);
+    background-gradient-end: rgba(255, 255, 255, 0.1);
+}
+
+.notification-button:focus,
+.notification-icon-button:focus,
+.hotplug-notification-item:focus,
+.modal-dialog-button:focus,
+.app-view-control:focus {
+    border-width: 2px;
+}
+
+.app-view-control:first-child:ltr:focus,
+.app-view-control:last-child:rtl:focus {
+    border-right-width: 1px;
+}
+
+.candidate-page-button:active,
+.candidate-page-button:pressed,
+.notification-button:active,
+.notification-icon-button:active,
+.hotplug-notification-item:active,
+.hotplug-resident-eject-button:active,
+.modal-dialog-button:active,
+.modal-dialog-button:pressed,
+.app-view-control:checked {
+    background-gradient-start: rgba(255, 255, 255, 0);
+    background-gradient-end: rgba(255, 255, 255, 0.2);
+}
+
+.candidate-page-button:insensitive,
+.notification-button:insensitive,
+.notification-icon-button:insensitive,
+.modal-dialog-button:insensitive {
+    border-color: #666666;
+    color: #9f9f9f;
+    background-gradient-direction: none;
+    background-color: rgba(102, 102, 102, 0.15);
+}
+
+/* Common radii */
+
+.search-entry,
+.modal-dialog-button,
+.notification-button,
+.hotplug-notification-item,
+.app-view-controls,
+#screenShieldNotifications {
+    border-radius: 18px;
+}
+
+.app-view-control:first-child:ltr,
+.app-view-control:last-child:rtl {
+    border-radius: 18px 0px 0px 18px;
+    border-right-width: 0px;
+}
+
+.app-view-control:last-child:ltr,
+.app-view-control:first-child:rtl {
+    border-radius: 0px 18px 18px 0px;
+}
+
+/* Entries */
+
+.search-entry,
+.login-dialog StEntry,
+.notification StEntry,
+.modal-dialog StEntry {
+    color: rgb(64, 64, 64);
+    caret-color: rgb(64, 64, 64);
+    font-size: 12pt;
+    caret-size: 1px;
+    selected-color: white;
+    padding: 4px 12px;
+}
+
+.search-entry,
+.login-dialog StEntry,
+.run-dialog-entry,
+.notification StEntry {
+    border: 2px solid rgba(245,245,245,0.2);
+    background-gradient-start: rgba(5,5,6,0.1);
+    background-gradient-end: rgba(254,254,254,0.1);
+    background-gradient-direction: vertical;
+    transition-duration: 300ms;
+    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6);
+}
+
+.search-entry:focus,
+.search-entry:hover,
+.login-dialog StEntry:focus,
+.notification StEntry:focus,
+.modal-dialog StEntry {
+    border: 2px solid rgb(136,138,133);
+    background-gradient-start: rgb(200,200,200);
+    background-gradient-end: white;
+    background-gradient-direction: vertical;
+    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6);
+}
+
+.login-dialog StEntry:focus,
+.notification StEntry:focus,
+.modal-dialog StEntry:focus {
+    border: 2px solid #3465a4;
+}
+
+.search-entry {
+    border-color: rgba(245,245,245,0.3);
+    color: rgb(192, 192, 192);
+    caret-color: rgb(192, 192, 192);
+}
+
+.search-entry:hover {
+    color: rgb(128, 128, 128);
+    caret-color: rgb(128, 128, 128);
+}
+
+.search-entry:focus {
+    color: rgb(64, 64, 64);
+    caret-color: rgb(64, 64, 64);
+    font-weight: bold;
+    transition-duration: 0ms;
+}
+
+.login-dialog StEntry,
+.notification StEntry,
+.modal-dialog StEntry {
+    border-radius: 5px;
+    padding: 4px 4px;
+}
+
+.prompt-dialog-password-entry .capslock-warning,
+.login-dialog-prompt-entry .capslock-warning {
+    icon-size: 16px;
+    warning-color: #999;
+    padding: 0 4px;
+}
+
+.login-dialog StEntry:insensitive,
+.modal-dialog StEntry:insensitive {
+    border-color: #666666;
+    color: #9f9f9f;
+    border: 2px solid #9f9f9f;
+    background-gradient-direction: none;
+    background-color: rgba(102, 102, 102, 0.15);
+    box-shadow: inset 0 0 rgba(0,0,0,1.0);
+}
+
+/* Panel */
+
+#panel {
+    background-color: black;
+    font-weight: bold;
+    height: 1.86em;
+}
+
+#panel.unlock-screen,
+#panel.login-screen {
+    background-color: transparent;
+}
+
+#panelLeft, #panelCenter {
+    spacing: 4px;
+}
+
+#panelLeft:ltr {
+    padding-right: 4px;
+}
+
+#panelLeft:rtl {
+    padding-left: 4px;
+}
+
+#panelRight:ltr {
+    padding-left: 4px;
+}
+
+#panelRight:rtl {
+    padding-right: 4px;
+}
+
+.panel-corner {
+    -panel-corner-radius: 6px;
+    -panel-corner-background-color: black;
+    -panel-corner-border-width: 2px;
+    -panel-corner-border-color: transparent;
+}
+
+.panel-corner:active,
+.panel-corner:overview,
+.panel-corner:focus {
+    -panel-corner-border-color: rgba(255,255,255,0.8);
+}
+
+.panel-corner.lock-screen,
+.panel-corner.unlock-screen,
+.panel-corner.login-screen {
+    -panel-corner-background-color: transparent;
+    -panel-corner-border-color: transparent;
+}
+
+#appMenu {
+    spinner-image: url("process-working.svg");
+    spacing: 4px;
+}
+
+/* used for the app menu header only */
+.label-shadow {
+    color: rgba(0,0,0,0.5);
+}
+
+.panel-button #appMenuIcon {
+    app-icon-bottom-clip: 1px;
+}
+
+.panel-button:active #appMenuIcon,
+.panel-button:checked #appMenuIcon,
+.panel-button:focus #appMenuIcon {
+    app-icon-bottom-clip: 2px;
+}
+
+.panel-button {
+    -natural-hpadding: 12px;
+    -minimum-hpadding: 6px;
+    font-weight: bold;
+    color: #ccc;
+    transition-duration: 100ms;
+}
+
+#panel.unlock-screen .panel-button,
+#panel.lock-screen .panel-button,
+#panel.login-screen .panel-button {
+    color: #e6e6e6;
+}
+
+#panel.unlock-screen .panel-button:hover,
+#panel.lock-screen .panel-button:hover,
+#panel.login-screen .panel-button:hover,
+#panel.unlock-screen .panel-button:active,
+#panel.lock-screen .panel-button:active,
+#panel.login-screen .panel-button:active,
+#panel.unlock-screen .panel-button:focus,
+#panel.lock-screen .panel-button:focus,
+#panel.login-screen .panel-button:focus {
+    color: white;
+}
+
+.panel-button:hover {
+    color: white;
+    text-shadow: black 0px 2px 2px;
+}
+
+.panel-button:active,
+.panel-button:overview,
+.panel-button:focus {
+    border-image: url("panel-button-border.svg") 6 10 0 2;
+    background-image: url("panel-button-highlight-wide.svg");
+    color: white;
+    text-shadow: black 0px 2px 2px;
+}
+
+.panel-status-button:active,
+.panel-status-button:checked,
+.panel-status-button:focus {
+    background-image: url("panel-button-highlight-narrow.svg");
+}
+
+.panel-button:active > .system-status-icon,
+.panel-button:checked > .system-status-icon,
+.panel-button:focus > .system-status-icon {
+    icon-shadow: black 0px 2px 2px;
+}
+
+.panel-menu {
+    -boxpointer-gap: 4px;
+}
+
+.panel-status-indicators-box,
+.panel-status-menu-box {
+    spacing: 2px;
+}
+
+.system-status-icon {
+    icon-size: 1.09em;
+    padding: 0 5px;
+}
+
+.aggregate-menu {
+    width: 360px;
+}
+
+.aggregate-menu .popup-menu-icon {
+    padding: 0 4px;
+}
+
+.system-switch-user-submenu-icon {
+    icon-size: 24px;
+    border: 1px solid #8b8b8b;
+}
+
+.system-menu-action {
+    color: #e6e6e6;
+    border-radius: 32px; /* wish we could do 50% */
+    padding: 13px;
+    border: 2px solid #5f5f5f; /* using rgba() is flaky unfortunately */
+}
+
+.system-menu-action:hover,
+.system-menu-action:focus {
+    color: white;
+    background-color: #4c4c4c;
+    border: none;
+    padding: 15px;
+}
+
+.system-menu-action:active {
+    color: black;
+    background-color: #6f6f6f;
+
+}
+
+.system-menu-action > StIcon {
+    icon-size: 16px;
+}
+
+.screencast-indicator {
+    color: #ff0000;
+}
+
+/* Overview */
+
+#overview {
+    spacing: 24px;
+}
+
+.overview-controls {
+    padding-bottom: 32px;
+}
+
+.workspace-thumbnails {
+    spacing: 11px;
+    visible-width: 32px; /* Amount visible before hovering */
+    border: 1px solid rgba(128, 128, 128, 0.4);
+    border-right: 0px;
+    border-radius: 9px 0px 0px 9px;
+    background-color: rgba(0, 0, 0, 0.5);
+    padding: 11px 7px 11px 11px;
+}
+
+.workspace-thumbnails:rtl {
+    border-right: 1px;
+    border-left: 0px;
+    border-radius: 0px 9px 9px 0px;
+    padding: 11px 11px 11px 7px;
+}
+
+.workspace-thumbnail-indicator {
+    border: 4px solid rgba(255,255,255,0.7);
+    border-radius: 4px;
+    padding: 1px;
+}
+
+.window-caption {
+    spacing: 25px;
+    background: rgba(0,0,0,0.5);
+    border-radius: 8px;
+    padding: 4px 12px;
+    -shell-caption-spacing: 12px;
+    border: 2px solid rgba(0, 0, 0, 0);
+}
+
+.window-caption:hover {
+    border: 2px solid rgba(255, 255, 255, 0);
+}
+
+.window-close, .notification-close {
+    background-image: url("close-window.svg");
+    background-size: 32px;
+    height: 32px;
+    width: 32px;
+}
+
+.window-close {
+    -shell-close-overlap: 16px;
+}
+
+.window-clone-border {
+    border: 4px solid rgba(255, 255, 255, 0.5);
+    border-radius: 4px;
+}
+
+.notification-close {
+    /* we start out in the top right of the
+     * notification, inset.
+     *
+     * center is 32px/2 = 16px
+     *
+     * adjust left 2px
+     * adjust down 8px */
+
+    -shell-close-overlap-x: 14px;
+    -shell-close-overlap-y: -12px;
+}
+
+.notification-close:rtl {
+    /* as above, but starting out in the top left of the
+     * notification. */
+
+    -shell-close-overlap-x: -14px;
+}
+
+.window-close:rtl {
+    -st-background-image-shadow: 2px 2px 6px rgba(0,0,0,0.5);
+}
+
+.window-picker {
+    -horizontal-spacing: 32px;
+    -vertical-spacing: 32px;
+    padding-left: 32px;
+    padding-right: 32px;
+    padding-bottom: 48px;
+}
+
+.window-picker.external-monitor {
+    padding: 32px;
+}
+
+.messages-indicator {
+    color: #999999;
+    height: 32px;
+}
+
+.messages-indicator-contents {
+    spacing: 12px;
+    padding-bottom: 12px;
+}
+
+.messages-indicator-contents:hover {
+    color: white;
+    text-shadow: black 0px 2px 2px;
+}
+
+.messages-indicator-highlight {
+    background-gradient-start: transparent;
+    background-gradient-end: #999999;
+    background-gradient-direction: vertical;
+
+    height: 6px;
+}
+
+/* Dash */
+
+#dash {
+    color: #5f5f5f;
+    font-size: 9pt;
+    padding: 4px 0px;
+    background-color: rgba(0, 0, 0, 0.5);
+    border: 1px solid rgba(128, 128, 128, 0.4);
+    border-left: 0px;
+    border-radius: 0px 9px 9px 0px;
+}
+
+#dash:rtl {
+    border-left: 1px;
+    border-right: 0px;
+    border-radius: 9px 0px 0px 9px;
+}
+
+.placeholder {
+    background-image: url("dash-placeholder.svg");
+    background-size: contain;
+    height: 24px;
+}
+
+.empty-dash-drop-target {
+    width: 24px;
+    height: 24px;
+}
+
+/* Search Box */
+
+.search-entry {
+    width: 320px;
+}
+
+.search-entry-icon {
+    icon-size: 1em;
+    color: #c0c0c0;
+}
+
+.search-entry:hover .search-entry-icon,
+.search-entry:focus .search-entry-icon {
+    color: #8d8f8a;
+}
+
+/* Search Results */
+
+#searchResults {
+    padding: 20px 10px 0px 10px;
+    spacing: 18px;
+}
+
+#searchResultsBin {
+    max-width: 1000px;
+}
+
+#searchResultsContent {
+    padding-left: 20px;
+    padding-right: 20px;
+    spacing: 16px;
+}
+
+.search-section {
+    /* This should be equal to #searchResultsContent spacing */
+    spacing: 16px;
+}
+
+.search-section-separator {
+    -gradient-height: 1px;
+    -gradient-start: rgba(255,255,255,0);
+    -gradient-end: rgba(255,255,255,0.5);
+    -margin-horizontal: 1.5em;
+    height: 1px;
+}
+
+.search-section-content {
+    /* This is the space between the provider icon and the results container */
+    spacing: 32px;
+}
+
+.search-statustext {
+    color: #efefef;
+    font-size: 2em;
+    font-weight: bold;
+}
+
+.list-search-results {
+    spacing: 3px;
+}
+
+.dash-label {
+    border-radius: 7px;
+    padding: 4px 12px;
+    background-color: rgba(0,0,0,0.5);
+    text-align: center;
+    -x-offset: 8px;
+}
+
+/* Application Launchers, Grid and List results */
+
+.icon-grid {
+    spacing: 30px;
+    -shell-grid-horizontal-item-size: 136px;
+    -shell-grid-vertical-item-size: 136px;
+}
+
+.icon-grid .overview-icon {
+    icon-size: 96px;
+}
+
+.app-display {
+    spacing: 20px;
+}
+
+.app-view-controls {
+    padding-bottom: 32px;
+}
+
+.app-view-control {
+    padding: 4px 32px;
+}
+
+.app-view-control:focus {
+    padding: 3px 31px;
+}
+
+.search-display > StBoxLayout,
+.all-apps,
+.frequent-apps > StBoxLayout {
+    /* horizontal padding to make sure scrollbars or dash don't overlap content */
+    padding: 0px 88px 10px 88px;
+}
+
+.page-indicator {
+    padding: 15px 20px;
+}
+
+.page-indicator .page-indicator-icon {
+    width: 18px;
+    height: 18px;
+    background-image: url(page-indicator-inactive.svg);
+}
+
+.page-indicator:hover .page-indicator-icon {
+    background-image: url(page-indicator-hover.svg);
+}
+
+.page-indicator:active .page-indicator-icon {
+    background-image: url(page-indicator-active.svg);
+}
+
+.page-indicator:checked .page-indicator-icon,
+.page-indicator:checked:active .page-indicator-icon {
+    background-image: url(page-indicator-checked.svg);
+}
+
+.no-frequent-applications-label {
+    font-size: 18pt;
+    color: #999999;
+}
+
+.app-folder-icon {
+    padding: 5px;
+    spacing-rows: 5px;
+    spacing-columns: 5px;
+}
+
+.dash-item-container > StButton {
+    padding: 4px 8px;
+}
+
+.list-search-result-content {
+    spacing: 12px;
+    padding: 12px;
+}
+
+.list-search-result-title {
+    font-weight: bold;
+    font-size: 14pt;
+    color: white;
+}
+
+.list-search-result-description {
+    color: #eeeeec;
+}
+
+.search-provider-icon-more {
+    width: 16px;
+    height: 16px;
+    background-image: url("more-results.svg");
+}
+
+.app-well-app > .overview-icon.overview-icon-with-label,
+.grid-search-result .overview-icon.overview-icon-with-label {
+    /* since the label controls its own spacing, it is visually more
+    consistent to use different padding values for top and bottom */
+    padding: 10px 8px 5px 8px;
+    spacing: 4px;
+}
+
+.app-well-app > .overview-icon,
+.show-apps > .overview-icon,
+.search-provider-icon,
+.list-search-result,
+.grid-search-result .overview-icon {
+    border-radius: 4px;
+    padding: 6px;
+    border: 1px rgba(0,0,0,0);
+    transition-duration: 100ms;
+    text-align: center;
+}
+
+.search-provider-icon {
+    padding: 15px;
+}
+
+.app-folder-popup {
+    -arrow-border-radius: 8px;
+    -arrow-background-color: rgba(0,0,0,0.3);
+    -arrow-base: 24px;
+    -arrow-rise: 11px;
+}
+
+.app-folder-popup-bin {
+    padding: 5px;
+}
+
+.app-well-app.running > .overview-icon {
+    text-shadow: black 0px 2px 2px;
+    background-image: url("running-indicator.svg");
+    background-size: contain;
+}
+
+.app-well-app.app-folder > .overview-icon {
+    background-color: rgba(0,0,0,0.3);
+}
+
+.app-well-app:hover > .overview-icon,
+.show-apps:hover > .overview-icon,
+.search-provider-icon:hover,
+.list-search-result:hover,
+.grid-search-result:hover .overview-icon {
+    background-color: rgba(255,255,255,0.1);
+    text-shadow: black 0px 2px 2px;
+    transition-duration: 100ms;
+    color:white;
+}
+
+.app-display .app-well-app > .overview-icon {
+    border-radius: 4px;
+}
+
+.list-search-result:hover .list-search-result-description {
+    text-shadow: rgba(0,0,0,0.8) 0px 1px 2px;
+}
+
+.show-apps {
+    padding: 4px 0;
+}
+
+.show-apps-icon {
+    color: #a0a0a0;
+}
+
+.show-apps:hover .show-apps-icon {
+    color: white;
+}
+
+.app-well-app:checked > .overview-icon,
+.app-well-app:active > .overview-icon,
+.show-apps:checked > .overview-icon,
+.show-apps:active > .overview-icon,
+.search-provider-icon:active,
+.grid-search-result:active .overview-icon,
+.list-search-result:active {
+    background-gradient-start: rgba(255, 255, 255, .05);
+    background-gradient-end: rgba(255, 255, 255, .15);
+    background-gradient-direction: vertical;
+    border-radius: 4px;
+    box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.7);
+    transition-duration: 100ms;
+}
+
+.show-apps:checked .show-apps-icon,
+.show-apps:focus .show-apps-icon {
+    color: white;
+    transition-duration: 100ms;
+}
+
+.app-well-app:focus > .overview-icon,
+.grid-search-result:focus .overview-icon,
+.show-apps:focus > .overview-icon,
+.search-provider-icon:focus,
+.list-search-result:focus,
+.app-well-app:selected > .overview-icon,
+.grid-search-result:selected .overview-icon,
+.search-provider-icon:selected,
+.list-search-result:selected {
+    background-color: rgba(255,255,255,0.33);
+}
+
+/* LookingGlass */
+
+#LookingGlassDialog {
+    background-color: rgba(0,0,0,0.80);
+    spacing: 4px;
+    padding: 4px;
+    border: 2px solid grey;
+    border-radius: 4px;
+}
+
+#LookingGlassDialog > #Toolbar {
+    border: 1px solid grey;
+    border-radius: 4px;
+}
+
+#LookingGlassDialog .labels {
+    spacing: 4px;
+}
+
+#LookingGlassDialog .notebook-tab {
+    -natural-hpadding: 12px;
+    -minimum-hpadding: 6px;
+    font-weight: bold;
+    color: #ccc;
+    transition-duration: 100ms;
+    padding-left: .3em;
+    padding-right: .3em;
+}
+
+#LookingGlassDialog .notebook-tab:hover {
+    color: white;
+    text-shadow: black 0px 2px 2px;
+}
+
+#LookingGlassDialog .notebook-tab:selected {
+    border-image: url("panel-button-border.svg") 10 10 0 2;
+    background-image: url("panel-button-highlight-wide.svg");
+    color: white;
+    text-shadow: black 0px 2px 2px;
+}
+
+.lg-dialog StEntry {
+    selection-background-color: #bbbbbb;
+    selected-color: #333333;
+}
+
+.lg-completions-text {
+    font-size: .9em;
+    font-style: italic;
+}
+
+.lg-obj-inspector-title {
+    spacing: 4px;
+}
+
+.lg-obj-inspector-button {
+    border: 1px solid gray;
+    padding: 4px;
+    border-radius: 4px;
+}
+
+.lg-obj-inspector-button:hover {
+    border: 1px solid #ffffff;
+}
+
+.lg-dialog .shell-link {
+    color: #999999;
+}
+
+.lg-dialog .shell-link:hover {
+    color: #dddddd;
+}
+
+#LookingGlassDialog StBoxLayout#EvalBox {
+    padding: 4px;
+    spacing: 4px;
+}
+
+#LookingGlassDialog StBoxLayout#ResultsArea {
+    spacing: 4px;
+}
+
+#lookingGlassExtensions {
+    padding: 4px;
+}
+
+.lg-extensions-list {
+    padding: 4px;
+    spacing: 6px;
+}
+
+.lg-extension {
+    border: 1px solid #6f6f6f;
+    border-radius: 4px;
+    padding: 4px;
+}
+
+.lg-extension-name {
+    font-weight: bold;
+}
+
+.lg-extension-meta {
+    spacing: 6px;
+}
+
+#LookingGlassPropertyInspector {
+    background: rgba(0, 0, 0, 0.8);
+    border: 2px solid grey;
+    border-radius: 4px;
+    padding: 6px;
+}
+
+/* Calendar popup */
+
+.calendar-vertical-separator {
+    -stipple-width: 1px;
+    -stipple-color: #505050;
+    width: 0.3em;
+}
+
+.calendar {
+    padding: .4em 1.75em .8em 1.75em;
+}
+
+.calendar-month-label {
+    color: #888a85;
+    font-size: 9.5pt;
+    font-weight: bold;
+    padding-bottom: 8px;
+    padding-top: 8px;
+}
+
+.calendar-month-label:focus {
+    background-color: #999999;
+}
+
+.calendar-change-month-back {
+    width: 18px;
+    height: 12px;
+    background-image: url("calendar-arrow-left.svg");
+    border-radius: 4px;
+}
+
+.calendar-change-month-back:rtl {
+    background-image: url("calendar-arrow-right.svg");
+}
+
+.calendar-change-month-back:hover,
+.calendar-change-month-back:focus {
+    background-color: #999999;
+}
+.calendar-change-month-back:active {
+    background-color: #aaaaaa;
+}
+
+.calendar-change-month-forward {
+    width: 18px;
+    height: 12px;
+    background-image: url("calendar-arrow-right.svg");
+    border-radius: 4px;
+}
+
+.calendar-change-month-forward:rtl {
+    background-image: url("calendar-arrow-left.svg");
+}
+
+.calendar-change-month-forward:hover,
+.calendar-change-month-forward:focus {
+    background-color: #999999;
+}
+.calendar-change-month-forward:active {
+    background-color: #aaaaaa;
+}
+
+.datemenu-date-label {
+    padding: .4em 1.7em;
+    font-weight: bold;
+    text-align: center;
+    color: #eeeeec;
+    border-radius: 4px;
+}
+
+.datemenu-date-label:hover,
+.datemenu-date-label:focus {
+    background-color: #999999;
+}
+
+.datemenu-date-label:active {
+    background-color: #aaaaaa;
+}
+
+.calendar-day-base {
+    font-size: 9pt;
+    text-align: center;
+    width: 2.4em;
+    height: 2.4em;
+}
+
+.calendar-day-base:hover,
+.calendar-day-base:focus {
+    background-color: #777777;
+}
+
+.calendar-day-base:active {
+    font-size: 9pt;
+    background-color: #555555;
+    color: white;
+}
+
+.calendar-day-heading {
+    color: #888a85;
+    padding-top: .2em;
+    height: 1.7em;
+}
+
+.calendar-week-number {
+    color: #babdb6;
+    font-weight: bold;
+}
+
+/* Hack used in lieu of border-collapse - see calendar.js */
+.calendar-day {
+    border: 1px solid #505050;
+    color: #babdb6;
+    border-top-width: 0;
+    border-left-width: 0;
+}
+
+.calendar-day-top {
+    border-top-width: 1px;
+}
+
+.calendar-day-left {
+    border-left-width: 1px;
+}
+
+.calendar-work-day {
+}
+
+.calendar-nonwork-day {
+    background-color: rgba(128, 128, 128, .1);
+}
+
+.calendar-today {
+    background-image: url("calendar-today.svg");
+    text-shadow: black 0px 2px 2px;
+    font-weight: bold;
+}
+
+.calendar-day-with-events {
+    font-weight: bold;
+    color: white;
+}
+
+.calendar-other-month-day {
+    color: #333333;
+}
+
+.events-table {
+    width: 320px;
+    spacing-columns: 6pt;
+    padding: 0 1.4em;
+}
+
+.events-table:ltr {
+    padding-right: 1.9em;
+}
+
+.events-table:rtl {
+    padding-left: 1.9em;
+}
+
+.events-day-header {
+    font-weight: bold;
+    color: #999999;
+    padding-left: 0.4em;
+    padding-top: 1.2em;
+}
+
+.events-day-header:first-child {
+    padding-top: 0;
+}
+
+.events-day-header:rtl {
+    padding-left: 0;
+    padding-right: 0.4em;
+}
+
+.events-day-dayname {
+    color: rgba(153, 153, 153, 1.0);
+    text-align: left;
+    min-width: 20px;
+}
+
+.events-day-dayname:rtl {
+    text-align: right;
+}
+
+.events-day-time {
+    color: #fff;
+    text-align: right;
+}
+
+.events-day-time:rtl {
+    text-align: left;
+}
+
+.events-day-task {
+    color: rgba(153, 153, 153, 1.0);
+    padding-left: 8pt;
+}
+
+.events-day-task:rtl {
+    padding-left: 0px;
+    padding-right: 8pt;
+}
+
+/* Message Tray */
+
+#message-tray {
+    background: #2e3436 url(message-tray-background.png);
+    background-repeat: repeat;
+    height: 72px;
+}
+
+.message-tray-summary {
+    height: 72px;
+}
+
+.message-tray-menu-button StIcon {
+    padding: 0 20px;
+    color: #aaaaaa;
+    icon-size: 24px;
+}
+
+.message-tray-menu-button:hover StIcon,
+.message-tray-menu-button:active StIcon,
+.message-tray-menu-button:focus StIcon {
+    color: #eeeeee;
+}
+
+.url-highlighter {
+    link-color: #ccccff;
+}
+
+.no-messages-label {
+    color: #999999;
+}
+
+.notification {
+    border-radius: 10px 10px 0px 0px;
+    background: rgba(0,0,0,0.9);
+    padding: 8px 8px 4px 8px;
+    spacing-rows: 4px;
+    spacing-columns: 10px;
+}
+
+.notification, #notification-container {
+    font-size: 11pt;
+    width: 34em;
+}
+
+.notification.multi-line-notification {
+    padding-bottom: 8px;
+}
+
+.notification-unexpanded {
+    /* We want to force the actor at a specific size, irrespective
+       of its minimum and preferred size, so we override both */
+    min-height: 36px;
+    height: 36px;
+}
+
+/* We use row-span = 2 for the image cell, which prevents its height preferences to be
+   taken into account during allocation, so its height ends up being limited by the height
+   of the content in the other rows. To avoid showing a stretched image, we set the minimum
+   height of the table to be ICON_SIZE + IMAGE_SIZE + spacing-rows = 24 + 125 + 10 = 159 */
+.notification-with-image {
+    min-height: 159px;
+}
+
+.summary-boxpointer {
+    -arrow-border-radius: 15px;
+    -arrow-background-color: rgba(0,0,0,0.9);
+    -arrow-base: 36px;
+    -arrow-rise: 18px;
+    color: white;
+    -boxpointer-gap: 4px;
+}
+
+.summary-boxpointer .notification {
+    border-radius: 9px;
+    background: rgba(0,0,0,0) !important;
+    padding-bottom: 12px;
+}
+
+.summary-boxpointer #summary-right-click-menu {
+    padding-top: 12px;
+    padding-bottom: 12px;
+}
+
+.summary-notification-stack-scrollview {
+    max-height: 18em;
+    padding-top: 8px;
+    padding-bottom: 8px;
+}
+
+.summary-notification-stack-scrollview:ltr {
+    padding-right: 8px;
+}
+
+.summary-notification-stack-scrollview:rtl {
+    padding-left: 8px;
+}
+
+.notification-scrollview {
+    max-height: 10em;
+    -st-vfade-offset: 24px;
+}
+
+.notification-scrollview:ltr > StScrollBar {
+    padding-left: 6px;
+}
+
+.notification-scrollview:rtl > StScrollBar {
+    padding-right: 6px;
+}
+
+.notification-body {
+    spacing: 5px;
+}
+
+.notification-actions {
+    padding-top: 18px;
+    spacing: 10px;
+}
+
+.notification-button {
+    -st-natural-width: 140px;
+    padding: 4px 4px 5px;
+}
+
+.notification-button:focus {
+    -st-natural-width: 138px;
+    padding: 3px 4px 4px;
+}
+
+.notification-icon-button {
+    border-radius: 5px;
+    padding: 5px;
+}
+
+.notification-icon-button:focus {
+    padding: 4px;
+}
+
+.notification-icon-button > StIcon {
+    icon-size: 16px;
+    padding: 8px;
+}
+
+.secondary-icon {
+    icon-size: 1.09em;
+}
+
+.hotplug-transient-box {
+    spacing: 6px;
+    padding: 2px 72px 2px 12px;
+}
+
+.hotplug-notification-item {
+    padding: 2px 10px;
+}
+
+.hotplug-notification-item:focus {
+    padding: 1px 71px 1px 11px;
+}
+
+.hotplug-notification-item-icon {
+    icon-size: 24px;
+    padding: 2px 5px;
+}
+
+.hotplug-resident-box {
+    spacing: 8px;
+}
+
+.hotplug-resident-mount {
+    spacing: 8px;
+    border-radius: 4px;
+
+    color: #ccc;
+}
+
+.hotplug-resident-mount:hover {
+    background-gradient-direction: horizontal;
+    background-gradient-start: rgba(255, 255, 255, 0.1);
+    background-gradient-end: rgba(255, 255, 255, 0);
+
+    color: #fff;
+}
+
+.hotplug-resident-mount-label {
+    color: inherit;
+    padding-left: 6px;
+}
+
+.hotplug-resident-mount-icon {
+    icon-size: 24px;
+    padding-left: 6px;
+}
+
+.hotplug-resident-eject-icon {
+    icon-size: 16px;
+}
+
+.hotplug-resident-eject-button {
+    padding: 7px;
+    border-radius: 5px;
+    color: #ccc;
+}
+
+.chat-log-message {
+    color: #888888;
+}
+
+.chat-empty-line {
+    font-size: 4px;
+}
+
+.chat-received {
+    padding-left: 4px;
+}
+
+.chat-received:rtl {
+    padding-left: 0px;
+    padding-right: 4px;
+}
+
+.chat-sent {
+    padding-left: 18pt;
+    color: #959595;
+}
+
+.chat-sent:rtl {
+    padding-left: 0px;
+    padding-right: 18pt;
+}
+
+.chat-meta-message {
+    padding-left: 4px;
+    font-size: 9pt;
+    font-weight: bold;
+    color: #bbbbbb;
+}
+
+.chat-meta-message:rtl {
+    padding-left: 0px;
+    padding-right: 4px;
+}
+
+.chat-notification-scrollview{
+    max-height: 22em;
+}
+
+.subscription-message {
+    font-style: italic;
+}
+
+.notification StEntry {
+    border-radius: 4px;
+}
+
+.summary-source-button {
+    padding: 6px 3px 6px 3px;
+}
+
+.summary-source-button:last-child:ltr {
+    padding-right: 6px;
+}
+
+.summary-source-button:last-child:rtl {
+    padding-left: 6px;
+}
+
+.summary-source-button:hover .summary-source {
+    background-color: rgba(255,255,255,0.1);
+}
+
+.summary-source-button:focus .summary-source,
+.summary-source-button:selected .summary-source {
+    background-color: rgba(255,255,255,0.33);
+}
+
+.summary-source {
+    border-radius: 4px;
+    padding: 0 6px 0 6px;
+    transition-duration: 100ms;
+}
+
+.summary-source-counter {
+    background-image: url("summary-counter.svg");
+    background-size: 2.4em;
+    font-size: 10pt;
+    font-weight: bold;
+    height: 2.4em;
+    width: 2.4em;
+    -shell-counter-overlap-x: 13px;
+    -shell-counter-overlap-y: 13px;
+}
+
+/* OSD */
+.osd-window {
+    text-align: center;
+    font-weight: bold;
+    spacing: 1em;
+}
+
+.osd-window .level {
+    height: 0.6em;
+    border-radius: 0.3em;
+    background-color: rgba(190,190,190,0.2);
+}
+
+/* App Switcher */
+.switcher-popup {
+    padding: 8px;
+    spacing: 16px;
+}
+
+.osd-window,
+.switcher-list {
+    background: rgba(0,0,0,0.8);
+    border: 1px solid rgba(128,128,128,0.40);
+    border-radius: 24px;
+    padding: 20px;
+}
+
+.switcher-list-item-container {
+    spacing: 8px;
+}
+
+.switcher-list .item-box {
+    padding: 8px;
+    border-radius: 8px;
+}
+
+.switcher-list .item-box:outlined {
+    padding: 6px;
+    border: 2px solid rgba(85,85,85,1.0);
+}
+
+.switcher-list .item-box:selected {
+    background: rgba(255,255,255,0.33);
+}
+
+.switcher-list .thumbnail-box {
+    padding: 2px;
+    spacing: 4px;
+}
+
+.switcher-list .thumbnail {
+    width:  256px;
+}
+
+.switcher-list .separator {
+    width: 1px;
+    background: rgba(255,255,255,0.33);
+}
+
+.ripple-box {
+    width: 52px;
+    height: 52px;
+    background-image: url("corner-ripple-ltr.png");
+    background-size: contain;
+}
+
+.ripple-box:rtl {
+    background-image: url("corner-ripple-rtl.png");
+}
+
+.switcher-arrow {
+    border-color: rgba(0,0,0,0);
+    color: #808080;
+}
+
+.switcher-arrow:highlighted {
+    border-color: rgba(0,0,0,0);
+    color: white;
+}
+
+/* Workspace Switcher */
+.workspace-switcher-group {
+    padding: 12px;
+}
+
+.workspace-switcher-container {
+    background: rgba(0,0,0,0.8);
+    border: 1px solid rgba(128,128,128,0.40);
+    border-radius: 24px;
+    padding: 20px;
+}
+
+.workspace-switcher {
+    background: transparent;
+    border: 0px;
+    border-radius: 0px;
+    padding: 0px;
+    spacing: 8px;
+}
+
+.ws-switcher-active-up {
+    height: 100px;
+    border: 0px;
+    background: rgba(255,255,255,0.5);
+    background-image: url("ws-switch-arrow-up.png");
+    border-radius: 8px;
+}
+
+.ws-switcher-active-down {
+    height: 100px;
+    border: 0px;
+    background: rgba(255,255,255,0.5);
+    background-image: url("ws-switch-arrow-down.png");
+    border-radius: 8px;
+}
+
+.ws-switcher-box {
+    height: 96px;
+    border: 2px solid rgba(85,85,85,0.5);
+    background: transparent;
+    border-radius: 8px;
+}
+
+/* Tile previews */
+.tile-preview {
+    background-color: rgba(74, 144, 217, 0.35);
+    border: 1px solid #4a90d9; /* Adwaita selected bg color */
+}
+
+.tile-preview-left.on-primary {
+    /* keep in sync with -panel-corner-radius */
+    border-radius: 6px 0 0 0;
+}
+
+.tile-preview-right.on-primary {
+    /* keep in sync with -panel-corner-radius */
+    border-radius: 0 6px 0 0;
+}
+
+.tile-preview-left.tile-preview-right.on-primary {
+    /* keep in sync with -panel-corner-radius */
+    border-radius: 6px 6px 0 0;
+}
+
+/* Modal Dialogs */
+
+/* Dialog Subject Text Style */
+.show-processes-dialog-subject,
+.mount-question-dialog-subject,
+.end-session-dialog-subject {
+    font-size: 14pt;
+    font-weight: bold;
+    color: #999999;
+}
+
+.modal-dialog {
+    border-radius: 24px;
+    background-color: rgba(0.0, 0.0, 0.0, 0.9);
+    border: 2px solid #868686;
+
+    padding-right: 42px;
+    padding-left: 42px;
+    padding-bottom: 30px;
+    padding-top: 30px;
+}
+
+.modal-dialog-button-box {
+    spacing: 21px;
+    padding-top: 50px;
+}
+
+.modal-dialog-button {
+    padding: 4px 32px 5px;
+}
+
+.modal-dialog-button:focus {
+    padding: 3px 31px 4px;
+}
+
+/* Run Dialog */
+
+.run-dialog-label {
+    font-size: 12pt;
+    font-weight: bold;
+    color: #999999;
+    padding-bottom: .4em;
+}
+
+.run-dialog-error-box {
+    padding-top: 15px;
+    spacing: 5px;
+}
+
+.modal-dialog .run-dialog-entry {
+    width: 20em;
+}
+
+.lightbox {
+    background-color: black;
+}
+
+.flashspot {
+    background-color: white;
+}
+
+/* End Session Dialog */
+.end-session-dialog {
+    spacing: 42px;
+}
+
+.end-session-dialog-list {
+    padding-top: 20px;
+}
+
+.end-session-dialog-layout {
+    padding-left: 17px;
+}
+
+.end-session-dialog-layout:rtl {
+    padding-right: 17px;
+}
+
+.end-session-dialog-description {
+    width: 28em;
+    padding-bottom: 10px;
+}
+
+.end-session-dialog-description:rtl {
+    width: 28em;
+    padding-bottom: 10px;
+    text-align: right;
+}
+
+.end-session-dialog-warning {
+    width: 28em;
+    color: #f57900;
+    padding-top: 6px;
+}
+
+.end-session-dialog-warning:rtl {
+    width: 28em;
+    color: #f57900;
+    padding-top: 6px;
+    text-align: right;
+}
+
+.end-session-dialog-logout-icon {
+    border: 2px solid #8b8b8b;
+    border-radius: 5px;
+    width: 48px;
+    height: 48px;
+    background-size: contain;
+}
+
+.end-session-dialog-shutdown-icon {
+    color: #bebebe;
+    width: 48px;
+    height: 48px;
+}
+
+.end-session-dialog-inhibitor-layout {
+    spacing: 16px;
+    max-height: 200px;
+    padding-right: 65px;
+    padding-left: 65px;
+}
+
+.end-session-dialog-session-list,
+.end-session-dialog-app-list {
+    spacing: 1em;
+}
+
+.end-session-dialog-list-header {
+    font-weight: bold;
+}
+
+.end-session-dialog-list-header:rtl {
+    text-align: right;
+}
+
+.end-session-dialog-app-list-item,
+.end-session-dialog-session-list-item {
+    spacing: 1em;
+}
+
+.end-session-dialog-app-list-item-name,
+.end-session-dialog-session-list-item-name {
+    font-weight: bold;
+}
+
+.end-session-dialog-app-list-item-description {
+    color: #cccccc;
+    font-size: 10pt;
+}
+
+/* Restart message */
+.restart-message {
+    font-size: 14pt;
+}
+
+/* ShellMountOperation Dialogs */
+.shell-mount-operation-icon {
+    icon-size: 48px;
+}
+
+.show-processes-dialog,
+.mount-question-dialog {
+    spacing: 24px;
+}
+
+.show-processes-dialog-subject,
+.mount-question-dialog-subject {
+    padding-top: 10px;
+    padding-left: 17px;
+    padding-bottom: 6px;
+}
+
+.mount-question-dialog-subject {
+    max-width: 500px;
+}
+
+.show-processes-dialog-subject:rtl,
+.mount-question-dialog-subject:rtl {
+    padding-left: 0px;
+    padding-right: 17px;
+}
+
+.show-processes-dialog-description,
+.mount-question-dialog-description {
+    padding-left: 17px;
+    width: 28em;
+}
+
+.show-processes-dialog-description:rtl,
+.mount-question-dialog-description:rtl {
+    padding-right: 17px;
+}
+
+.show-processes-dialog-app-list {
+    font-size: 10pt;
+    max-height: 200px;
+    padding-top: 24px;
+    padding-left: 49px;
+    padding-right: 32px;
+}
+
+.show-processes-dialog-app-list:rtl {
+    padding-right: 49px;
+    padding-left: 32px;
+}
+
+.show-processes-dialog-app-list-item {
+    color: #ccc;
+}
+
+.show-processes-dialog-app-list-item:hover {
+    color: white;
+}
+
+.show-processes-dialog-app-list-item:ltr {
+    padding-right: 1em;
+}
+
+.show-processes-dialog-app-list-item:rtl {
+    padding-left: 1em;
+}
+
+.show-processes-dialog-app-list-item-icon:ltr {
+    padding-right: 17px;
+}
+
+.show-processes-dialog-app-list-item-icon:rtl {
+    padding-left: 17px;
+}
+
+.show-processes-dialog-app-list-item-name {
+    font-size: 10pt;
+}
+
+/* Password or Authentication Dialog */
+.prompt-dialog {
+    /* this is the width of the entire modal popup */
+    width: 500px;
+}
+
+.prompt-dialog-main-layout {
+    spacing: 24px;
+    padding: 10px;
+}
+
+.prompt-dialog-message-layout {
+    spacing: 16px;
+}
+
+.prompt-dialog-headline {
+    font-size: 12pt;
+    font-weight: bold;
+    color: #666666;
+}
+
+.prompt-dialog-description:rtl {
+    text-align: right;
+}
+
+.prompt-dialog-password-box {
+    spacing: 1em;
+    padding-bottom: 1em;
+}
+
+.prompt-dialog-error-label {
+    font-size: 10pt;
+    color: #ffff00;
+    padding-bottom: 8px;
+}
+
+.prompt-dialog-info-label {
+    font-size: 10pt;
+    padding-bottom: 8px;
+}
+
+.hidden {
+    color: rgba(0,0,0,0);
+}
+
+.prompt-dialog-null-label {
+    font-size: 10pt;
+    padding-bottom: 8px;
+}
+
+/* Polkit Dialog */
+
+.polkit-dialog-user-layout {
+    padding-left: 10px;
+    spacing: 10px;
+}
+
+.polkit-dialog-user-layout:rtl {
+    padding-left: 0px;
+    padding-right: 10px;
+}
+
+.polkit-dialog-user-root-label {
+    color: #ff0000;
+}
+
+.polkit-dialog-user-icon {
+    border: 2px solid #8b8b8b;
+    border-radius: 5px;
+    background-size: contain;
+    width: 48px;
+    height: 48px;
+}
+
+/* Network Agent Dialog */
+
+.network-dialog-secret-table {
+    spacing-rows: 15px;
+    spacing-columns: 1em;
+}
+
+.keyring-dialog-control-table {
+    spacing-rows: 15px;
+    spacing-columns: 1em;
+}
+
+/* Magnifier */
+
+.magnifier-zoom-region {
+    border: 2px solid rgba(128, 0, 0, 255);
+}
+
+.magnifier-zoom-region.full-screen {
+    border-width: 0px;
+}
+
+/* On-screen Keyboard */
+
+#keyboard {
+    background: rgba(0,0,0,0.8);
+}
+
+.keyboard-layout {
+    spacing: 10px;
+    padding: 10px;
+}
+
+.keyboard-row {
+    spacing: 15px;
+}
+
+.keyboard-key {
+    min-height: 30px;
+    min-width: 30px;
+    background-gradient-start: rgba(255,245,245,0.4);
+    background-gradient-end: rgba(105,105,105,0.1);
+    background-gradient-direction: vertical;
+    font-size: 14pt;
+    font-weight: bold;
+    border-radius: 10px;
+    border: 2px solid #a0a0a0;
+    color: white;
+}
+
+.keyboard-key:grayed {
+   color: #808080;
+   border-color: #808080;
+}
+
+.keyboard-key:checked,
+.keyboard-key:hover {
+    background: #303030;
+    border: 3px solid white;
+}
+
+.keyboard-key:active {
+    background: #808080;
+}
+
+.keyboard-subkeys {
+    color: white;
+    padding: 5px;
+    -arrow-border-radius: 10px;
+    -arrow-background-color: #090909;
+    -arrow-border-width: 2px;
+    -arrow-border-color: white;
+    -arrow-base: 20px;
+    -arrow-rise: 10px;
+    -boxpointer-gap: 5px;
+}
+
+/* IBus Candidate Popup */
+
+.candidate-popup-content {
+    padding: 0.5em;
+    spacing: 0.3em;
+}
+
+.candidate-index {
+    padding: 0 0.5em 0 0;
+    color: #cccccc;
+}
+
+.candidate-box {
+    padding: 0.3em 0.5em 0.3em 0.5em;
+}
+
+.candidate-box:selected {
+    border-radius: 4px;
+    background-color: rgba(255,255,255,0.2);
+}
+
+.candidate-box:hover {
+    border-radius: 4px;
+    background-color: rgba(255,255,255,0.1);
+}
+.candidate-page-button-box {
+    height: 2em;
+    width: 80px;
+}
+
+.vertical .candidate-page-button-box {
+    padding-top: 0.5em;
+}
+
+.horizontal .candidate-page-button-box {
+    padding-left: 0.5em;
+}
+
+.candidate-page-button-previous {
+    border-radius: 4px 0px 0px 4px;
+}
+
+.candidate-page-button-next {
+    border-radius: 0px 4px 4px 0px;
+}
+
+.candidate-page-button-icon {
+    icon-size: 1em;
+}
+
+/* Login Dialog */
+
+.framed-user-icon {
+    border: 2px solid #8b8b8b;
+    border-radius: 3px;
+    background-size: contain;
+}
+
+.framed-user-icon:hover {
+    border: 2px solid #bbbbbb;
+}
+
+.login-dialog-banner {
+    font-size: 10pt;
+    font-weight: bold;
+    text-align: center;
+    color: #666666;
+    padding-bottom: 1em;
+}
+
+.login-dialog {
+    /* Reset border and background */
+    border: none;
+    background-color: transparent;
+}
+
+.login-dialog-button-box {
+    spacing: 5px;
+}
+
+.login-dialog-user-list-view {
+    -st-vfade-offset: 1em;
+}
+
+.login-dialog-user-list {
+    spacing: 12px;
+    padding: .2em;
+    width: 23em;
+}
+
+.login-dialog-user-list-item {
+    border-radius: 5px;
+    padding: .2em;
+    color: #bfbfbf;
+    text-shadow: black 0px 2px 2px;
+}
+
+.login-dialog-user-list-item:ltr {
+    padding-right: 1em;
+}
+
+.login-dialog-user-list-item:rtl {
+    padding-left: 1em;
+}
+
+.login-dialog-user-list-item:hover {
+    background-color: rgba(255,255,255,0.1);
+}
+
+.login-dialog-user-list:expanded .login-dialog-user-list-item:focus {
+    background-color: rgba(255,255,255,0.33);
+}
+
+.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in {
+    background-image: url("logged-in-indicator.svg");
+    background-size: contain;
+}
+
+.login-dialog-user-list-item .login-dialog-timed-login-indicator {
+    background-color: rgba(0,0,0,0.0);
+    height: 2px;
+}
+
+.login-dialog-user-list-item:focus .login-dialog-timed-login-indicator {
+    background-color: #8b8b8b;
+}
+
+.login-dialog-not-listed-label {
+    font-size: 10.5pt;
+    font-weight: bold;
+    color: #666666;
+    padding-top: 1em;
+}
+
+.login-dialog-user-selection-box {
+    padding: 100px 0;
+}
+
+.login-dialog-user-selection-box .login-dialog-not-listed-label {
+    padding-left: 2px;
+}
+
+.login-dialog-not-listed-button:focus .login-dialog-not-listed-label,
+.login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
+    color: #E8E8E8;
+}
+
+.login-dialog-username,
+.user-widget-label {
+    font-size: 16pt;
+    font-weight: bold;
+    text-align: left;
+    padding-left: 15px;
+    text-shadow: rgba(0, 0, 0, 0.5) 0px 2px 1px 0px;
+}
+
+.login-dialog-prompt-layout {
+    padding-top: 24px;
+    padding-bottom: 12px;
+    spacing: 8px;
+    width: 23em;
+}
+
+.login-dialog-prompt-label {
+    color: #eeeeee;
+    font-size: 14px;
+    padding-top: 11px;
+}
+
+.login-dialog-session-list-button StIcon {
+    icon-size: 1.25em;
+}
+
+.login-dialog-session-list-button {
+    color: #8b8b8b;
+}
+
+.login-dialog-session-list-button:hover,
+.login-dialog-session-list-button:focus,
+.login-dialog-session-list-button:active {
+    color: white;
+}
+
+.login-dialog-logo-bin {
+    padding: 24px 0px;
+}
+
+.login-dialog .modal-dialog-button-box {
+    spacing: 3px;
+}
+
+.login-dialog .modal-dialog-button {
+    border-radius: 5px;
+    padding: 3px 18px;
+}
+
+.login-dialog .modal-dialog-button:focus {
+    padding: 2px 17px;
+}
+
+.login-dialog .modal-dialog-button:default {
+    background-gradient-start: #6793c4;
+    background-gradient-end: #335d8f;
+    background-gradient-direction: vertical;
+    border-color: #16335d;
+}
+
+.login-dialog .modal-dialog-button:default:focus {
+    border: 2px solid #377fe7;
+}
+
+.login-dialog .modal-dialog-button:default:hover {
+    background-gradient-start: #74a0d0;
+    background-gradient-end: #436d9f;
+}
+
+.login-dialog .modal-dialog-button:default:active,
+.login-dialog .modal-dialog-button:default:pressed {
+    background-gradient-start: #436d9f;
+    background-gradient-end: #74a0d0;
+}
+
+.login-dialog .modal-dialog-button:default:insensitive {
+    border-color: #666666;
+    color: #9f9f9f;
+    background-gradient-direction: none;
+    background-color: rgba(102, 102, 102, 0.15);
+}
+
+.login-dialog-message {
+    padding-top: 4px;
+    padding-bottom: 16px;
+    min-height: 2em;
+}
+
+.login-dialog-message-warning {
+    color: orange;
+}
+
+.login-dialog-message-hint {
+    padding-top: 0px;
+    padding-bottom: 20px;
+}
+
+.user-widget-label {
+}
+
+.user-widget-label:ltr {
+    padding-left: 18px;
+}
+
+.user-widget-label:rtl {
+    padding-right: 18px;
+}
+
+/* Screen shield */
+
+#panel.lock-screen,
+#screenShieldNotifications {
+    background-color: rgba(0,0,0,0.3);
+}
+
+.screen-shield-background {
+    background: black;
+    box-shadow: 0px 4px 8px rgba(0,0,0,0.9);
+}
+
+#lockDialogGroup {
+    background: #2e3436 url(debian-edu-softwaves-gdm.svg);
+    background-size: cover;
+}
+
+.screen-shield-arrows {
+    padding-bottom: 3em;
+}
+
+.screen-shield-arrows Gjs_Arrow {
+    color: white;
+    width: 80px;
+    height: 48px;
+    -arrow-thickness: 12px;
+    -arrow-shadow: 0 1px 1px rgba(0,0,0,0.4);
+}
+
+.screen-shield-contents-box {
+    spacing: 48px;
+}
+
+.screen-shield-clock {
+    color: white;
+    text-shadow: 0px 1px 2px rgba(0,0,0,0.6);
+    font-weight: bold;
+    text-align: center;
+    padding-bottom: 1.5em;
+}
+
+.screen-shield-clock-time {
+    font-size: 72pt;
+    text-shadow: 0px 2px 2px rgba(0,0,0,0.4);
+}
+
+.screen-shield-clock-date {
+    font-size: 28pt;
+}
+
+#screenShieldNotifications {
+    max-height: 500px;
+    padding: 12px;
+}
+
+.screen-shield-notifications-box {
+    spacing: 12px;
+    width: 30em;
+}
+
+.screen-shield-notification-source {
+    padding: 3px 6px;
+    spacing: 5px;
+}
+
+.screen-shield-notification-label {
+    font-weight: bold;
+    padding: 0px 0px 0px 12px;
+}
+
+.screen-shield-notification-count-text {
+    padding: 0px 0px 0px 12px;
+}
+
+/* Remove background from notifications, otherwise
+   opacity is doubled and they look darker
+*/
+.screen-shield-notifications-box .notification {
+    background-color: transparent;
+}
+
+/* Override padding on resident notifications, since
+   the notifications box has its own spacing
+*/
+.screen-shield-notifications-box .summary-notification-stack-scrollview {
+    padding-top: 0px;
+    padding-bottom: 0px;
+}
+
+#screenShieldNotifications .notification-button,
+#screenShieldNotifications .notification-icon-button {
+    border: 1px rgba(255,255,255,0.5);
+}
+
+#screenShieldNotifications StScrollBar StBin#trough {
+    background-color: rgba(0,0,0,0.2);
+}
+
+#screenShieldNotifications StScrollBar StButton#vhandle,
+#screenShieldNotifications StScrollBar StButton#hhandle {
+    background-color: rgba(0,0,0,0.3);
+    border: none;
+}
+
+#screenShieldNotifications StScrollBar StButton#vhandle:hover,
+#screenShieldNotifications StScrollBar StButton#hhandle {
+    background-color: rgba(0,0,0,0.6);
+}
+
+#screenShieldNotifications StScrollBar StButton#vhandle:active,
+#screenShieldNotifications StScrollBar StButton#hhandle {
+    background-color: rgba(0,0,0,0.8);
+}
+
+.input-source-switcher-symbol {
+   font-size: 34pt;
+   width: 96px;
+   height: 96px;
+}
+
+/* Background menu */
+
+.background-menu {
+    -boxpointer-gap: 4px;
+    -arrow-rise: 0px;
+}
diff --git a/art-softwaves/ldm/Makefile.am b/art-softwaves/ldm/Makefile.am
new file mode 100644
index 0000000..08383d6
--- /dev/null
+++ b/art-softwaves/ldm/Makefile.am
@@ -0,0 +1,15 @@
+THEME = softwaves
+ldmdir   = $(datadir)/ldm/themes/debian-edu-$(THEME)
+ldm_DATA = logo.png greeter-gtkrc bg.png preview.png
+
+# Build rule for the PNG using the SVG as the source
+bg.png: bg.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+install-data-local:
+	$(mkinstalldirs) $(DESTDIR)$(ldmdir)
+
+EXTRA_DIST = $(ldm_DATA)
+
diff --git a/art-softwaves/ldm/bg.png b/art-softwaves/ldm/bg.png
new file mode 100644
index 0000000..c15da95
Binary files /dev/null and b/art-softwaves/ldm/bg.png differ
diff --git a/art-softwaves/ldm/bg.svg b/art-softwaves/ldm/bg.svg
new file mode 120000
index 0000000..1247fc9
--- /dev/null
+++ b/art-softwaves/ldm/bg.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-grub.svg
\ No newline at end of file
diff --git a/art-softwaves/ldm/greeter-gtkrc b/art-softwaves/ldm/greeter-gtkrc
new file mode 100644
index 0000000..d2c8728
--- /dev/null
+++ b/art-softwaves/ldm/greeter-gtkrc
@@ -0,0 +1,91 @@
+
+# LTSP theme for LDM
+#
+# based on, though significantly gutted:
+#
+# Ubuntu Human Colorscheme
+#
+# Authors:
+# Richard Stellingwerff <remenic at gmail.com>
+# Daniel Borgmann <daniel.borgmann at gmail.com>
+# Billy Cantrell <bvcmdk at yahoo.com>
+#
+# Feel free to modify and share!
+
+style "clearlooks-default"
+{
+    font_name="Sans 10"
+    GtkButton      ::default_border    = { 0, 0, 0, 0 }
+    GtkRange       ::trough_border     = 0
+
+    GtkCheckButton ::indicator_size    = 14
+    GtkExpander    ::expander_size     = 16
+
+    GtkButton      ::child-displacement-x = 1
+    GtkButton      ::child-displacement-y = 1
+
+    bg[PRELIGHT]      = "#9baada"
+    bg[SELECTED]      = "#637a9a"
+
+    engine "clearlooks"
+    {
+        menubarstyle      = 0       # 0 = flat, 1 = sunken, 2 = flat gradient
+        menuitemstyle     = 0       # 0 = flat, 1 = 3d-ish (gradient), 2 = 3d-ish (button)
+        listviewitemstyle = 0       # 0 = flat, 1 = 3d-ish (gradient)
+        progressbarstyle  = 0       # 0 = candy bar, 1 = fancy candy bar, 2 = flat
+        animation         = FALSE
+    }
+}
+
+style "clearlooks-wide" = "clearlooks-default"
+{
+    xthickness = 2
+    ythickness = 2
+}
+
+style "clearlooks-wider" = "clearlooks-default"
+{
+    xthickness = 3
+    ythickness = 3
+    font_name="Sans 9"
+}
+
+style "clearlooks-tasklist" = "clearlooks-default"
+{
+    xthickness = 5
+    ythickness = 3
+}
+
+style "clearlooks-menu" = "clearlooks-default"
+{
+    xthickness = 2
+    ythickness = 1
+}
+
+style "clearlooks-menu-item" = "clearlooks-default"
+{
+    xthickness = 2
+    ythickness = 3
+}
+
+style "clearlooks-tooltips" = "clearlooks-default"
+{
+    xthickness = 4
+    ythickness = 4
+    bg[NORMAL] = { 1.0,1.0,0.75 }
+}
+
+# widget styles
+class "GtkWidget"      style "clearlooks-default"
+class "GtkCombo"       style "clearlooks-button"
+class "GtkRange"       style "clearlooks-wide"
+class "GtkFrame"       style "clearlooks-wide"
+class "GtkMenu"        style "clearlooks-menu"
+class "GtkEntry"       style "clearlooks-wider"
+class "GtkMenuItem"    style "clearlooks-menu-item"
+
+widget_class "*MenuItem.*" style "clearlooks-menu-item"
+
+# tooltips stuff
+widget_class "*.tooltips.*.GtkToggleButton" style "clearlooks-tasklist"
+widget "gtk-tooltips" style "clearlooks-tooltips"
diff --git a/art-softwaves/ldm/logo.png b/art-softwaves/ldm/logo.png
new file mode 100644
index 0000000..eae7c23
Binary files /dev/null and b/art-softwaves/ldm/logo.png differ
diff --git a/art-softwaves/ldm/preview.png b/art-softwaves/ldm/preview.png
new file mode 100644
index 0000000..d4246e6
Binary files /dev/null and b/art-softwaves/ldm/preview.png differ
diff --git a/art-softwaves/plymouth/Makefile.am b/art-softwaves/plymouth/Makefile.am
new file mode 100644
index 0000000..992c46e
--- /dev/null
+++ b/art-softwaves/plymouth/Makefile.am
@@ -0,0 +1,28 @@
+THEME = softwaves
+plymouthdir   = $(datadir)/plymouth/themes/debian-edu-$(THEME)
+plymouth_DATA = \
+	background.png \
+	debian-edu-logo.png \
+	password_dot16.png \
+	password_dot.png \
+	password_field16.png \
+	password_field.png \
+	debian-edu-$(THEME).plymouth \
+	debian-edu-$(THEME).script
+
+background.png: debian-edu-$(THEME)-plymouth.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+debian-edu-logo.png: debian-edu-$(THEME)-logo.svg
+	inkscape -z -e $@ $^
+	optipng -o4 -i0 -fix $@
+	advpng -z4 $@
+
+install-data-local:
+	$(mkinstalldirs) $(DESTDIR)$(plymouthdir)
+
+EXTRA_DIST = $(plymouth_DATA)
+
+CLEANFILES = background.png debian-edu-logo.png
diff --git a/art-softwaves/plymouth/README b/art-softwaves/plymouth/README
new file mode 100644
index 0000000..cc2300b
--- /dev/null
+++ b/art-softwaves/plymouth/README
@@ -0,0 +1 @@
+The password* PNG files are taken from stock Debian.
diff --git a/art-softwaves/plymouth/debian-edu-softwaves-logo.svg b/art-softwaves/plymouth/debian-edu-softwaves-logo.svg
new file mode 120000
index 0000000..d996dad
--- /dev/null
+++ b/art-softwaves/plymouth/debian-edu-softwaves-logo.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-logo.svg
\ No newline at end of file
diff --git a/art-softwaves/plymouth/debian-edu-softwaves-plymouth.svg b/art-softwaves/plymouth/debian-edu-softwaves-plymouth.svg
new file mode 120000
index 0000000..00a2783
--- /dev/null
+++ b/art-softwaves/plymouth/debian-edu-softwaves-plymouth.svg
@@ -0,0 +1 @@
+../../playground/stretch/debian-edu-softwaves-plymouth.svg
\ No newline at end of file
diff --git a/art-softwaves/plymouth/debian-edu-softwaves.plymouth b/art-softwaves/plymouth/debian-edu-softwaves.plymouth
new file mode 100644
index 0000000..91e2044
--- /dev/null
+++ b/art-softwaves/plymouth/debian-edu-softwaves.plymouth
@@ -0,0 +1,8 @@
+[Plymouth Theme]
+Name=Default theme for Debian Edu 9 Stretch
+Description=A theme that features 'softWaves' and the Debian Edu logo on a blue background
+ModuleName=script
+
+[script]
+ImageDir=/usr/share/plymouth/themes/debian-edu-softwaves
+ScriptFile=/usr/share/plymouth/themes/debian-edu-softwaves/debian-edu-softwaves.script
diff --git a/art-softwaves/plymouth/debian-edu-softwaves.script b/art-softwaves/plymouth/debian-edu-softwaves.script
new file mode 100644
index 0000000..51eb2a3
--- /dev/null
+++ b/art-softwaves/plymouth/debian-edu-softwaves.script
@@ -0,0 +1,1031 @@
+#  ubuntu-logo.script - boot splash plugin
+# 
+#  Copyright (C) 2009 Canonical Ltd.
+# 
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2, or (at your option)
+#  any later version.
+# 
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+# 
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+#  02111-1307, USA.
+# 
+#  Written by: Alberto Milone <alberto.milone at canonical.com>
+#
+#  Based on the example provided with the "script plugin" written by:
+#              Charlie Brej   <cbrej at cs.man.ac.uk>
+#
+# Lines theme scripting by Juliette Taka BELIN and Aurélien COUDERC
+
+bg_image = Image("background.png");
+
+#------------------------------- Background ----------------------------------------
+# Compute screen/image ratio and scale the background accordingly
+window_max_width = Window.GetX() * 2 + Window.GetWidth();
+window_max_height = Window.GetY() * 2 + Window.GetHeight();
+screen_ratio = window_max_width / window_max_height;
+bg_image_ratio = bg_image.GetWidth() / bg_image.GetHeight();
+if (screen_ratio > bg_image_ratio)
+    bg_scale_factor = window_max_width / bg_image.GetWidth();
+else
+    bg_scale_factor = window_max_height / bg_image.GetHeight();
+scaled_bg_image = bg_image.Scale(bg_image.GetWidth() * bg_scale_factor,
+                                 bg_image.GetHeight() * bg_scale_factor);
+
+# Display background
+bg_sprite = Sprite(scaled_bg_image);
+bg_sprite.SetPosition(Window.GetX() + Window.GetWidth() / 2 - scaled_bg_image.GetWidth() / 2,
+                      Window.GetY() + Window.GetHeight() / 2 - scaled_bg_image.GetHeight() / 2,
+                      -10000);
+
+#------------------------------- Debian8 ----------------------------------------------
+debian8_image = Image("debian-edu-logo.png");
+debian8_width = logo_image.GetWidth();
+debian8_scale_factor = debian8_width / debian8_image.GetWidth() * 0.24;
+if (debian8_scale_factor < 1) {
+	debian8_image = debian8_image.Scale(debian8_image.GetWidth() * debian8_scale_factor,
+                              debian8_image.GetHeight() * debian8_scale_factor);
+}
+debian8_sprite = Sprite(debian8_image);
+debian8_to_bottom_edge = Window.GetHeight() * 0.10;
+debian8_sprite.SetPosition(Window.GetX() + Window.GetWidth() / 2 - debian8_image.GetWidth() / 2,
+                           Window.GetY() + Window.GetHeight() - debian8_to_bottom_edge - debian8_image.GetHeight(),
+                        -90);
+
+# Set the text colour in (rgb / 256)
+text_colour.red = 1.0;
+text_colour.green =  1.0;
+text_colour.blue = 1.0;
+
+# Tinted text #988592
+tinted_text_colour.red = 1.0;
+tinted_text_colour.green = 1.0;
+tinted_text_colour.blue = 1.0;
+
+# Action Text - #ffffff - RGB 255 255 255
+action_text_colour.red = 1.0;
+action_text_colour.green = 1.0;
+action_text_colour.blue = 1.0;
+
+# Orange - #ff4012 - RGB 255 64 18
+debugsprite = Sprite();
+debugsprite_bottom = Sprite();
+debugsprite_medium = Sprite();
+
+# are we currently prompting for a password?
+prompt_active = 0;
+
+# General purpose function to create text
+fun WriteText (text, colour) {
+    image = Image.Text (text, colour.red, colour.green, colour.blue);
+    return image;
+}
+
+fun ImageToText (text) {
+    image = WriteText (text, text_colour);
+    return image;
+}
+
+fun ImageToTintedText (text) {
+    image = WriteText (text, tinted_text_colour);
+    return image;
+}
+
+fun ImageToActionText (text) {
+    image = WriteText (text, action_text_colour);
+    return image;
+}
+
+fun Debug(text) {
+    debugsprite.SetImage(ImageToText (text));
+}
+
+fun DebugBottom(text) {
+    debugsprite_bottom.SetImage(ImageToText (text));
+    debugsprite_bottom.SetPosition(0, (Window.GetHeight (0) - 20), 1);
+}
+
+fun DebugMedium(text) {
+    debugsprite_medium.SetImage(ImageToText (text));
+    debugsprite_medium.SetPosition(0, (Window.GetHeight (0) - 100), 1);
+}
+
+fun TextYOffset() {
+    local.y;
+    local.text_height;
+    local.min_height;
+
+    # Put the 1st line below the logo + some spacing 
+    y = logo_sprite.GetY() + logo_image.GetHeight();
+	#Debug("y = " + y);
+
+    text_height = first_line_height * 7.5;
+
+    min_height = Window.GetHeight();
+    if (y + text_height > min_height)
+        y = min_height - text_height;
+
+    return y;
+}
+
+#------------------------------String functions-------------------------------
+
+# This is the equivalent for strstr()
+fun StringString(string, substring) {
+    start = 0;
+    while (String(string).CharAt (start)) {
+        walk = 0;
+        while (String(substring).CharAt (walk) == String(string).CharAt (start + walk) ) {
+            walk++;
+            if (!String(substring).CharAt (walk)) return start;
+        }
+        start++;
+    }
+    
+    return NULL;
+}
+
+fun StringLength (string) {
+    index = 0;
+    while (String(string).CharAt(index)) index++;
+    return index;
+}
+
+fun StringCopy (source, beginning, end) {
+    local.destination = "";
+    for (index = beginning; ( ( (end == NULL) || (index <= end) ) && (String(source).CharAt(index)) ); index++) {
+        local.destination += String(source).CharAt(index);
+    }
+    
+    return local.destination;
+}
+
+fun StringReplace (source, pattern, replacement) {
+    local.found = StringString(source, pattern);
+    if (local.found == NULL)
+        return source;
+
+    local.new_string = StringCopy (source, 0, local.found - 1) +
+                       replacement +
+                       StringCopy (source, local.found + StringLength(pattern), NULL);
+
+    return local.new_string;
+}
+
+# it makes sense to use it only for
+# numbers up to 100
+fun StringToInteger (str) {
+    int = -1;
+    for (i=0; i<=100; i++) {
+        if (i+"" == str) {
+            int = i;
+            break;
+        }
+    }
+    return int;
+}
+
+#-----------------------------------------------------------------------------
+# Top background colour
+# #489291 --> 0.282, 0.572, 0.569
+# New background colour
+# #0a3649 --> 0.039, 0.212, 0.286
+#
+Window.SetBackgroundTopColor (0.282, 0.572, 0.569);     # Nice colour on top of the screen fading to
+Window.SetBackgroundBottomColor (0.039, 0.212, 0.286);  # an equally nice colour on the bottom
+
+bits_per_pixel = Window.GetBitsPerPixel ();
+# TODO need to handle 16 colors ?
+#if (bits_per_pixel == 4) {
+#    logo_filename = "debian_logo16.png";
+#    progress_dot_off_filename = "progress_dot_off16.png";
+#    progress_dot_on_filename = "progress_dot_on16.png";
+#    password_dot_filename = "password_dot.png";
+#    password_field_filename = "password_field16.png";
+#} else {
+#    logo_filename = "debian_logo.png";
+#    progress_dot_off_filename = "progress_dot_off.png";
+#    progress_dot_on_filename = "progress_dot_on.png";
+    password_dot_filename = "password_dot.png";
+    password_field_filename = "password_field.png";
+#}
+
+message_notification[0].image = ImageToTintedText ("");
+message_notification[1].image = ImageToTintedText ("");
+fsck_notification.image = ImageToActionText ("");
+
+status = "normal";
+
+# use a fixed string with ascending and descending stems to calibrate the
+# bounding box for the first message, so the messages below don't move up
+# and down according to *their* height.
+first_line_height = ImageToTintedText ("AfpqtM").GetHeight();
+
+# if the user has a 640x480 or 800x600 display, we can't quite fit everything
+# (including passphrase prompts) with the target spacing, so scoot the text up
+# a bit if needed.
+top_of_the_text = TextYOffset();
+
+#-----------------------------------------Logo functions------------------------------
+
+# Call this when updating the screen
+fun draw_logo () {
+#    logo.sprite.SetX (logo.x);
+#    logo.sprite.SetY (logo.y);
+#    logo.sprite.SetZ (logo.z);
+#    logo.sprite.SetOpacity (1);
+#    logo_sprite.SetOpacity (1);
+}
+
+
+#-----------------------------------------Progress Indicator--------------------------
+# Implement in boot progress callback
+fun animate_progress_indicator (time, progress) {
+	# Start electrons animation at launch and every 3 seconds
+    if (global.progress_time == NULL || (time - global.progress_time) >= SECS_BETWEEN_ANIMS) {
+        global.progress_time = time;
+		global.anim_status = "start";
+	}
+
+    # Debug ("global progress time =" + global.progress_time + " global anim status = " + global.anim_status + " progress = " + progress + ", time = " + time);
+
+}
+
+
+#-----------------------------------------Label utility functions---------------------
+
+# label should be either a string or NULL
+# Images for n lines will be created and returned as items of the
+# message_label array
+#
+fun get_message_label (label, is_fake, is_action_line) {
+    # Debug("Get Label position");
+    local.message_label;
+    
+    if (is_fake)
+        # Create a fake label so as to get the y coordinate of
+        # a standard-length label.
+        local.message_image = ImageToTintedText ("This is a fake message");
+    else
+        local.message_image = (is_action_line) && ImageToActionText (label) || ImageToTintedText (label);
+        
+    message_label.width = message_image.GetWidth ();
+    message_label.height = message_image.GetHeight ();
+
+    # Center the line horizontally
+    message_label.x = Window.GetX () + Window.GetWidth () / 2 - message_label.width / 2;
+
+    message_label.y = top_of_the_text;
+
+    # Put the 2nd line below the fsck line
+    if (is_action_line) {
+        local.fsck_label.y = message_label.y + (first_line_height + first_line_height / 2);
+        message_label.y = local.fsck_label.y + (first_line_height * 2);
+    }
+
+    # Debug("action label x = " + message_label.x + " y = " + message_label.y );
+
+#    message_debug = "msg_x = " + message_label.x + " msg_y = " + message_label.y +
+#                    "msg_width = " + message_label.width + " msg_height = " +
+#                    message_label.height + " message = " + label;
+#    Debug(message_debug);
+    
+    return message_label;
+
+}
+
+# Create an fsck label and/or get its position
+fun get_fsck_label (label, is_fake) {
+    # Debug("Get Label position");
+    local.fsck_label = global.progress_label;
+    
+    if (is_fake)
+        fsck_label.image = ImageToTintedText ("This is a fake message");
+    else
+        fsck_label.image = ImageToTintedText (label);
+    
+    fsck_label.width = fsck_label.image.GetWidth ();
+    fsck_label.height = fsck_label.image.GetHeight ();
+    
+    # Centre the label horizontally
+    fsck_label.x = Window.GetX () + Window.GetWidth () / 2 - fsck_label.width / 2;
+    
+    local.first_label = get_message_label (label, 1, 0);
+    
+    # Place the label below the 1st message line
+    fsck_label.y = local.first_label.y + local.first_label.height + (local.first_label.height / 2);
+    
+#    message_debug = "msg_x = " + fsck_label.x + " msg_y = " + fsck_label.y +
+#                    "msg_width = " + fsck_label.width + " msg_height = " +
+#                    fsck_label.height + " message = " + label;
+#    Debug(message_debug);
+    
+    return fsck_label;
+}
+
+#-----------------------------------------Message stuff --------------------------------
+#
+
+# Set up a message label
+#
+# NOTE: this is called when doing something like 'plymouth message "hello world"'
+#
+fun setup_message (message_text, x, y, z, index) {
+    # Debug("Message setup");
+    global.message_notification[index].image = (index) && ImageToActionText (message_text) || ImageToTintedText (message_text);
+
+    # Set up the text message, if any
+    message_notification[index].x = x;
+    message_notification[index].y = y;
+    message_notification[index].z = z;
+    
+    message_notification[index].sprite = Sprite ();
+    message_notification[index].sprite.SetImage (message_notification[index].image);
+    message_notification[index].sprite.SetX (message_notification[index].x);
+    message_notification[index].sprite.SetY (message_notification[index].y);
+    message_notification[index].sprite.SetZ (message_notification[index].z);
+
+}
+
+fun show_message (index) {
+    if (global.message_notification[index].sprite) global.message_notification[index].sprite.SetOpacity(1);
+}
+
+fun hide_message (index) {
+    if (global.message_notification[index].sprite) global.message_notification[index].sprite.SetOpacity(0);
+}
+
+
+
+
+# the callback function is called when new message should be displayed.
+# First arg is message to display.
+fun message_callback (message)
+{
+    # Debug("Message callback");
+    is_fake = 0;
+    if (!message || (message == "")) is_fake = 1;
+    
+    local.substring = "keys:";
+    
+    # Look for the "keys:" prefix
+    local.keys = StringString(message, local.substring);
+    
+    local.is_action_line = (keys != NULL);
+    #Debug("keys " + local.keys + " substring length = " + StringLength(local.substring));
+
+    # Get the message without the "keys:" prefix
+    if (keys != NULL)
+        message = StringCopy (message, keys + StringLength(local.substring), NULL);
+
+    local.label.is_fake = is_fake;
+    label = get_message_label(message, is_fake, is_action_line);
+    label.z = 10000;
+    
+    setup_message (message, label.x, label.y, label.z, is_action_line);
+    if (prompt_active && local.is_action_line)
+        hide_message (is_action_line);
+    else
+        show_message (is_action_line);
+
+}
+
+
+#-----------------------------------------Display Password stuff -----------------------
+#
+
+fun password_dialogue_setup (message_label) {
+    # Debug("Password dialog setup");
+    
+    local.entry;
+    local.bullet_image;
+    
+    bullet_image = Image (password_dot_filename);
+    entry.image = Image (password_field_filename);
+    
+    # Hide the normal labels
+    prompt_active = 1;
+    if (message_notification[1].sprite) hide_message (1);
+    
+    # Set the prompt label
+    label = get_message_label(message_label, 0, 1);
+    label.z = 10000;
+    
+    setup_message (message_label, label.x, label.y, label.z, 2);
+    show_message (2);
+
+    # Set up the text entry which contains the bullets
+    entry.sprite = Sprite ();
+    entry.sprite.SetImage (entry.image);
+    
+    # Centre the box horizontally
+    entry.x = Window.GetX () + Window.GetWidth () / 2 - entry.image.GetWidth () / 2;
+
+    # Put the entry below the second label.
+    entry.y = message_notification[2].y + label.height;
+
+    # Debug ("entry x = " + entry.x + ", y = " + entry.y);
+    entry.z = 10000;
+    entry.sprite.SetX (entry.x);
+    entry.sprite.SetY (entry.y);
+    entry.sprite.SetZ (entry.z);
+
+    global.password_dialogue = local;
+}
+
+fun password_dialogue_opacity (opacity) {
+    # Debug("Password dialog opacity");
+    global.password_dialogue.opacity = opacity;
+    local = global.password_dialogue;
+
+    # You can make the box translucent with a float
+    # entry.sprite.SetOpacity (0.3);
+    entry.sprite.SetOpacity (opacity);
+    label.sprite.SetOpacity (opacity);
+    
+    if (bullets) {
+        for (index = 0; bullets[index]; index++) {
+            bullets[index].sprite.SetOpacity (opacity);
+        }
+    }
+}
+
+
+# The callback function is called when the display should display a password dialogue.
+# First arg is prompt string, the second is the number of bullets.
+fun display_password_callback (prompt, bullets) {
+    # Debug("Password dialog setup");
+    
+    global.status = "password";
+    if (!global.password_dialogue) password_dialogue_setup(prompt);
+    password_dialogue_opacity (1);
+    bullet_width = password_dialogue.bullet_image.GetWidth();
+    bullet_y = password_dialogue.entry.y +
+               password_dialogue.entry.image.GetHeight () / 2 -
+               password_dialogue.bullet_image.GetHeight () / 2;
+    margin = bullet_width;
+    spaces = Math.Int( (password_dialogue.entry.image.GetWidth () - (margin * 2)) / (bullet_width / 2 ) );
+    # Debug ("spaces = " + spaces + ", bullets = " + bullets);
+    bullets_area.width = margin + spaces * (bullet_width / 2);
+    bullets_area.x = Window.GetX () + Window.GetWidth () / 2 - bullets_area.width / 2;
+    # DebugBottom ("pwd_entry x = " + password_dialogue.entry.x + ", bullets_area.x = " + bullets_area.x + ", bullets_area.width = " + bullets_area.width);
+    if (bullets > spaces)
+        bullets = spaces;
+    for (index = 0; password_dialogue.bullets[index] || index < bullets; index++){
+        if (!password_dialogue.bullets[index]) {
+            password_dialogue.bullets[index].sprite = Sprite ();
+            password_dialogue.bullets[index].sprite.SetImage (password_dialogue.bullet_image);
+            password_dialogue.bullets[index].x = bullets_area.x + # password_dialogue.entry.x + margin +
+                                                 index * bullet_width / 2;
+            password_dialogue.bullets[index].sprite.SetX (password_dialogue.bullets[index].x);
+            password_dialogue.bullets[index].y = bullet_y;
+            password_dialogue.bullets[index].sprite.SetY (password_dialogue.bullets[index].y);
+            password_dialogue.bullets[index].z = password_dialogue.entry.z + 1;
+            password_dialogue.bullets[index].sprite.SetZ (password_dialogue.bullets[index].z);
+        }
+
+        password_dialogue.bullets[index].sprite.SetOpacity (0);
+
+        if (index < bullets) {
+            password_dialogue.bullets[index].sprite.SetOpacity (1);
+        }
+    }
+}
+
+Plymouth.SetDisplayPasswordFunction (display_password_callback); 
+
+Plymouth.SetMessageFunction (message_callback);
+
+Plymouth.SetBootProgressFunction (animate_progress_indicator);
+
+# Plymouth.SetBootProgressFunction: the callback function is called with two numbers, the progress (between 0 and 1) and the time spent booting so far
+# Plymouth.SetRootMountedFunction: the callback function is called when a new root is mounted
+# Plymouth.SetKeyboardInputFunction: the callback function is called with a string containing a new character entered on the keyboard
+
+#----------------------------------------- FSCK Counter --------------------------------
+
+# Initialise the counter
+fun init_fsck_count () {
+    # The number of fsck checks in this cycle
+    global.counter.total = 0;
+    # The number of fsck checks already performed + the current one
+    global.counter.current = 1;
+    # The previous fsck
+    global.counter.last = 0;
+}
+
+# Increase the total counter
+fun increase_fsck_count () {
+    global.counter.total++;
+}
+
+fun increase_current_fsck_count () {
+    global.counter.last = global.counter.current++;
+}
+
+# Clear the counter
+fun clear_fsck_count () {
+    global.counter = NULL;
+    init_fsck_count ();
+}
+
+#----------------------------------------- Progress Label ------------------------------
+
+
+# Change the opacity level of a progress label
+#
+# opacity = 1 -> show
+# opacity = 0 -> hide
+# opacity = 0.3 (or any other float) -> translucent
+#
+fun set_progress_label_opacity (opacity) {
+    # the label
+    progress_label.sprite.SetOpacity (opacity);
+    
+    # Make the slot available again when hiding the bar
+    # So that another bar can take its place
+    if (opacity == 0) {
+        progress_label.is_available = 1;
+        progress_label.device = "";
+    }
+}
+
+# Set up a new Progress Bar
+#
+# TODO: Make it possible to reuse (rather than recreate) a bar
+#       if .is_available = 1. Ideally this would just reset the
+#       label, the associated
+#       device and the image size of the sprite.
+
+fun init_progress_label (device, status_string) {
+    # Make the slot unavailable
+    global.progress_label.is_available = 0;
+    progress_label.progress = 0;
+    progress_label.device = device;
+    progress_label.status_string = status_string;
+}
+
+# See if the progress label is keeping track of the fsck
+# of "device"
+#
+fun device_has_progress_label (device) {
+    #DebugBottom ("label device = " + progress_label.device + " checking device " + device);
+    return (progress_label.device == device);
+}
+
+# Update the Progress bar which corresponds to index
+#
+fun update_progress_label (progress) {
+    # If progress is NULL then we just refresh the label.
+    # This happens when only counter.total has changed.
+    if (progress != NULL) {
+        progress_label.progress = progress;
+    
+        #Debug("device " + progress_label.device + " progress " + progress);
+    
+        # If progress >= 100% hide the label and make it available again
+        if (progress >= 100) {
+            set_progress_label_opacity (0);
+        
+            # See if we any other fsck check is complete
+            # and, if so, hide the progress bars and the labels
+            on_fsck_completed ();
+       
+            return 0;
+        }
+    }    
+    # Update progress label here
+    #
+    # FIXME: the queue logic from this theme should really be moved into mountall
+    # instead of using string replacement to deal with localised strings.
+    label = StringReplace (progress_label.status_string[0], "%1$d", global.counter.current);
+    label = StringReplace (label, "%2$d",  global.counter.total);
+    label = StringReplace (label, "%3$d",  progress_label.progress);
+    label = StringReplace (label, "%%",  "%");
+
+    progress_label = get_fsck_label (label, 0);
+    #progress_label.progress = progress;
+
+    progress_label.sprite = Sprite (progress_label.image);
+    
+    # Set up the bar
+    progress_label.sprite.SetPosition(progress_label.x, progress_label.y, 1);
+
+    set_progress_label_opacity (1);
+
+}
+
+# Refresh the label so as to update counters
+fun refresh_progress_label () {
+    update_progress_label (NULL);
+}
+
+#----------------------------------------- FSCK Queue ----------------------------------
+
+# Initialise the fsck queue
+fun init_queue () {
+    global.fsck_queue[0].device;
+    global.fsck_queue[0].progress;
+    global.fsck_queue.counter = 0;
+    global.fsck_queue.biggest_item = 0;    
+}
+
+fun clear_queue () {
+    global.fsck_queue = NULL;
+    init_queue ();
+}
+
+# Return either the device index in the queue or -1
+fun queue_look_up_by_device (device) {
+    for (i=0; i <= fsck_queue.biggest_item; i++) {
+        if ((fsck_queue[i]) && (fsck_queue[i].device == device))
+            return i;
+    }
+    return -1;
+}
+
+# Keep track of an fsck process in the queue
+fun add_fsck_to_queue (device, progress) {
+    # Look for an empty slot in the queue
+    for (i=0; global.fsck_queue[i].device; i++) {
+        continue;
+    }
+    local.index = i;
+    
+    # Set device and progress
+    global.fsck_queue[local.index].device = device;
+    global.fsck_queue[local.index].progress = progress;
+    
+    # Increase the queue counter
+    global.fsck_queue.counter++;
+    
+    # Update the max index of the array for iterations
+    if (local.index > global.fsck_queue.biggest_item)
+        global.fsck_queue.biggest_item = local.index;
+    
+    #DebugMedium ("Adding " + device + " at " + local.index);
+}
+
+fun is_queue_empty () {
+    return (fsck_queue.counter == 0);
+}
+
+fun is_progress_label_available () {
+    return (progress_label.is_available == 1);
+}
+
+
+# This should cover the case in which the fsck checks in
+# the queue are completed before the ones showed in the
+# progress label
+fun on_queued_fsck_completed () {
+    if (!is_queue_empty ())
+        return;
+    
+    # Hide the extra label, if any
+    #if (progress_bar.extra_label.sprite)
+    #    progress_bar.extra_label.sprite.SetOpacity(0);
+}
+
+fun remove_fsck_from_queue (index) {
+    # Free memory which was previously allocated for
+    # device and progress
+    global.fsck_queue[index].device = NULL;
+    global.fsck_queue[index].progress = NULL;
+
+    # Decrease the queue counter
+    global.fsck_queue.counter--;
+    
+    # See if there are other processes in the queue
+    # if not, clear the extra_label
+    on_queued_fsck_completed ();
+}
+
+fun on_fsck_completed () {
+    # We have moved on to tracking the next fsck
+    increase_current_fsck_count ();
+
+    if (!is_progress_label_available ())
+        return;
+    
+    if (!is_queue_empty ())
+        return;
+    
+    # Hide the progress label
+    if (progress_label.sprite)
+        progress_label.sprite.SetOpacity (0);
+    
+    # Clear the queue
+    clear_queue ();
+
+    # Clear the fsck counter
+    clear_fsck_count ();
+}
+
+# Update an fsck process that we keep track of in the queue
+fun update_progress_in_queue (index, device, progress) {
+    # If the fsck is complete, remove it from the queue
+    if (progress >= 100) {
+        remove_fsck_from_queue (index);
+        on_queued_fsck_completed ();
+        return;
+    }
+    
+    global.fsck_queue[index].device = device;
+    global.fsck_queue[index].progress = progress;
+    
+}
+
+# TODO: Move it to some function
+# Create an empty queue
+#init_queue ();
+
+
+#----------------------------------------- FSCK Functions ------------------------------
+
+
+# Either add a new bar for fsck checks or update an existing bar
+#
+# NOTE: no more than "progress_bar.max_number" bars are allowed
+#
+fun fsck_check (device, progress, status_string) {
+
+    # The 1st time this will take place
+    if (!global.progress_label) {
+        # Increase the fsck counter
+        increase_fsck_count ();
+
+        # Set up a new label for the check
+        init_progress_label (device, status_string);
+        update_progress_label (progress);
+
+        return;
+    }
+
+    
+    if (device_has_progress_label (device)) {
+        # Update the progress of the existing label
+        update_progress_label (progress);
+    }
+    else {
+        # See if there's already a slot in the queue for the device
+        local.queue_device_index = queue_look_up_by_device(device);
+
+        # See if the progress_label is available
+        if (progress_label.is_available) {
+            
+#            local.my_string = "available index " + local.available_index + " progress_bar counter is " + progress_bar.counter;
+#            Debug(local.my_string);
+            
+                
+            # If the fsck check for the device was in the queue, then
+            # remove it from the queue
+            if (local.queue_device_index >= 0) {
+                remove_fsck_from_queue (index);
+            }
+            else {
+                # Increase the fsck counter
+                increase_fsck_count ();
+            }
+            
+#            local.my_string += local.message;
+            #Debug("setting new label for device " + device + " progress " + progress);
+
+            # Set up a new label for the check
+            init_progress_label (device, status_string);
+            update_progress_label (progress);
+            
+        }
+        # If the progress_label is not available
+        else {
+            
+            # If the fsck check for the device is already in the queue
+            # just update its progress in the queue
+            if (local.queue_device_index >= 0) {
+                #DebugMedium("Updating queue at " + local.queue_device_index + " for device " + device);
+                update_progress_in_queue (local.queue_device_index, device, progress);
+            }
+            # Otherwise add the check to the queue
+            else {
+                #DebugMedium("Adding device " + device + " to queue at " + local.queue_device_index);
+                add_fsck_to_queue (device, progress);
+
+                # Increase the fsck counter
+                increase_fsck_count ();
+
+                refresh_progress_label ();
+            }
+            
+        }
+    }
+    
+#    if (!is_queue_empty ()) {
+#        DebugBottom("Extra label for "+ device);
+    #}
+#    else {
+#        DebugBottom("No extra label for " + device + ". 1st Device in the queue "+ fsck_queue[0].device + " counter = " + global.fsck_queue.counter);
+#    }
+}
+
+
+#-----------------------------------------Update Status stuff --------------------------
+#
+# The update_status_callback is what we can use to pass plymouth whatever we want so
+# as to make use of features which are available only in this program (as opposed to
+# being available for any theme for the script plugin).
+#
+# Example:
+#
+#   Thanks to the current implementation, some scripts can call "plymouth --update=fsck:sda1:40"
+#   and this program will know that 1) we're performing and fsck check, 2) we're checking sda1,
+#   3) the program should set the label progress to 40%
+#
+# Other features can be easily added by parsing the string that we pass plymouth with "--update"
+#
+fun update_status_callback (status) {
+#    Debug(status);
+    if (!status) return;
+    
+    string_it = 0;
+    update_strings[string_it] = "";
+    
+    for (i=0; (String(status).CharAt(i) != ""); i++) {
+        local.temp_char = String(status).CharAt(i);
+        if (temp_char != ":")
+            update_strings[string_it] += temp_char;
+        else
+            update_strings[++string_it] = "";
+    }
+    
+#    my_string = update_strings[0] + " " + update_strings[1] + " " + update_strings[2];
+#    Debug(my_string);
+    # Let's assume that we're dealing with these strings fsck:sda1:40
+    if ((string_it >= 2) && (update_strings[0] == "fsck")) {
+        
+        device = update_strings[1];
+        progress = update_strings[2];
+        status_string[0] = update_strings[3]; # "Checking disk %1$d of %2$d (%3$d %% complete)"
+        if (!status_string[0])
+            status_string[0] = "Checking disk %1$d of %2$d (%3$d %% complete)";
+        
+        if ((device != "") && (progress != "")) {
+            progress = StringToInteger (progress);
+        
+            # Make sure that the fsck_queue is initialised
+            if (!global.fsck_queue)
+                init_queue ();
+
+            # Make sure that the fsck counter is initialised
+            if (!global.counter)
+                init_fsck_count ();
+
+#            if (!global.progress_bar.extra_label.sprite)
+#                create_extra_fsck_label ();
+            
+            # Keep track of the fsck check
+            fsck_check (device, progress, status_string);
+        }
+        
+    }
+
+}
+Plymouth.SetUpdateStatusFunction (update_status_callback); 
+
+#-----------------------------------------Display Question stuff -----------------------
+#
+# TODO: Implement this if needed
+#
+# The callback function is called when the display should display a question dialogue.
+# First arg is prompt string, the second is the entry contents.
+#fun display_question_callback (prompt_string, entry_contents)
+#{
+# time++;
+#}
+#
+#Plymouth.SetDisplayQuestionFunction (display_question_callback); 
+
+
+#-----------------------------------------Refresh stuff --------------------------------
+#
+# Calling Plymouth.SetRefreshFunction with a function will set that function to be
+# called up to 50 times every second, e.g.
+#
+# NOTE: if a refresh function is not set, Plymouth doesn't seem to be able to update
+#       the screen correctly
+#
+fun refresh_callback ()
+{
+	if (global.anim_status == "start") {
+		anim_iter = 0;
+		for (i = 0; i < ELECTRONS_DISPLAYED; i++) {
+			ellipses[i].anim.angle = ellipses[i].anim.start_angle;
+		}
+		global.anim_status = "running";
+	}
+
+	if (global.anim_status == "running") {
+		anim_done = 1;
+		for (i = 0; i < ELECTRONS_DISPLAYED; i++) {	
+			if (anim_iter >= ellipses[i].anim.start_iter && anim_iter < ellipses[i].anim.stop_iter) { 
+				draw_electron(i);
+
+				ellipses[i].anim.angle += ellipses[i].anim.angle_incr;
+				# check if at least one of the animations needs more loops
+				if (ellipses[i].anim.stop_iter > anim_iter) {
+					anim_done = 0;
+				}
+			}
+		}
+		if (anim_done) {
+			global.anim_status = "stopped";
+		}
+		anim_iter++;
+   		# DebugBottom ("anim iter = " + anim_iter);
+	}
+}
+Plymouth.SetRefreshFunction (refresh_callback);
+
+# Acceleration function to have the electrons move faster in there most visible section, in
+# the middle of the ellipses.
+#
+# The function computes the result based on the .anim.angle member value in the given ellipse
+#
+# The angle is adapted so that accel([start_angle,start_angle+arc])->[start_angle,start_angle+arc]
+# is traveled in a sin([0,Pi/2])->[0,1] manner instead of linear increments
+#
+fun compute_angle_with_accel(ellipse) {
+	# first map the [start_angle,start_angle+arc] to [0,Pi/2]
+	angle_in_0_pi_2 = Math.Pi / 2 / ellipse.anim.arc * (ellipse.anim.angle - ellipse.anim.start_angle);
+	# then compute sin and scale output to [start_angle,start_angle+arc]
+	accel_angle = ellipse.anim.arc * Math.Sin(angle_in_0_pi_2) + ellipse.anim.start_angle;
+	return accel_angle;
+}
+
+# Computes the opacity factor so that the electrons visibility somehow matches that of the ellipses:
+# Most visible in a middle part, and invisible at the oposite.
+fun compute_opacity(ellipse) {
+	# map the [start_angle,start_angle+arc] to [0,Pi]
+	transformed_angle = Math.Pi / ellipse.anim.arc * (ellipse.anim.angle - ellipse.anim.start_angle);
+	# and compute Math.Sin^2
+	opacity_factor = Math.Sin(Math.Max(transformed_angle,-transformed_angle));
+	opacity_factor *= opacity_factor;
+	return opacity_factor;
+}
+
+# Draw the 5 electron sprites to create a gradient effect
+#
+# The position is computed based on the .angle field, adapted with the acceleration function above.
+#
+fun draw_electron(index) {
+	base_electron_x = ellipses[index].x - electron_image.GetWidth() / 2;
+	base_electron_y = ellipses[index].y - electron_image.GetHeight() / 2;
+	accel_angle = compute_angle_with_accel(ellipses[index]);
+	opacity_factor = compute_opacity(ellipses[index]);
+	for (j = 0; j < 5; j++) {
+		electron_x = base_electron_x + ellipses[index].width * Math.Cos(accel_angle + electron_sprite[index][j].angle_diff);
+		electron_y = base_electron_y + ellipses[index].height * Math.Sin(accel_angle + electron_sprite[index][j].angle_diff);
+		electron_sprite[index][j].SetOpacity(opacity_factor * electron_sprite[index][j].base_opacity);
+		electron_sprite[index][j].SetPosition(electron_x , electron_y, -10);
+	}
+}
+
+
+#-----------------------------------------Display Normal stuff -----------------------
+#
+# The callback function is called when the display should return to normal
+fun display_normal_callback ()
+{
+    global.status = "normal";
+    if (global.password_dialogue) {
+        password_dialogue_opacity (0);
+        global.password_dialogue = NULL;
+        if (message_notification[2].sprite) hide_message(2);
+        prompt_active = 0;
+    }
+    
+    if (message_notification[1].sprite) show_message (1);
+    
+    
+}
+
+Plymouth.SetDisplayNormalFunction (display_normal_callback);
+
+
+#----------------------------------------- Quit --------------------------------
+
+# TODO: Maybe we should also hide any other dialog
+# Show the logo and make the progress indicator look full when on exit
+fun quit_callback ()
+{
+    logo.sprite.SetOpacity (1);
+    switch_on_bullets (); 
+}
+
+Plymouth.SetQuitFunction(quit_callback);
diff --git a/art-softwaves/plymouth/password_dot.png b/art-softwaves/plymouth/password_dot.png
new file mode 100644
index 0000000..7dd7413
Binary files /dev/null and b/art-softwaves/plymouth/password_dot.png differ
diff --git a/art-softwaves/plymouth/password_dot16.png b/art-softwaves/plymouth/password_dot16.png
new file mode 100644
index 0000000..991a586
Binary files /dev/null and b/art-softwaves/plymouth/password_dot16.png differ
diff --git a/art-softwaves/plymouth/password_field.png b/art-softwaves/plymouth/password_field.png
new file mode 100644
index 0000000..4c0b93e
Binary files /dev/null and b/art-softwaves/plymouth/password_field.png differ
diff --git a/art-softwaves/plymouth/password_field16.png b/art-softwaves/plymouth/password_field16.png
new file mode 100644
index 0000000..962c557
Binary files /dev/null and b/art-softwaves/plymouth/password_field16.png differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-edu/debian-edu-artwork.git



More information about the debian-edu-commits mailing list