diff --git a/docs/md/installation.md b/docs/md/installation.md
index 8eafd2b..ca7d752 100644
--- a/docs/md/installation.md
+++ b/docs/md/installation.md
@@ -35,7 +35,7 @@ The TUI walks you through:
- `core` — 100+ base system packages
- `svc` — core services (NetworkManager, cronie, fail2ban, greetd)
- `shell` — zsh, Neovim, Yazi, Micro, Starship
- - `plymouth` — boot splash screen (skull logo + magenta spinner, **on by default**)
+ - `plymouth` — boot splash screen (skull logo + boot-log tail, **on by default**)
3. **Desktop Environment** — HyprLua, Niri, Hyprland, Sway, KDE Plasma, GNOME, COSMIC, XFCE, LXQt, or none
4. **Applications** — checklist of ~50 optional apps (see [Modules](modules.md))
5. **Colorway** — optional; enter hex values to customise the CyberQueer palette
diff --git a/docs/md/modules.md b/docs/md/modules.md
index 3b834bc..7edd214 100644
--- a/docs/md/modules.md
+++ b/docs/md/modules.md
@@ -133,7 +133,7 @@ bash ~/Dotfiles/setup/install-modules.sh
| `timeshift` | system snapshot and backup with autosnap |
| `zfs` | zfs-dkms kernel module |
| `wprs` | Wayland proxy for remote sessions (wprs-git, AUR) |
-| `plymouth` | boot splash — bundled skull logo and spinner |
+| `plymouth` | boot splash — bundled skull logo + boot-log tail |
| `plymouth-custom` | boot splash with a user-supplied image |
| `lightdm` | LightDM GTK greeter, cyberqueer-themed (HyprLua default) |
| `ly` | ly TUI display manager, cyberqueer-themed |
diff --git a/resources/bg-skull.svg b/resources/bg-skull.svg
index 230d044..128441e 100644
--- a/resources/bg-skull.svg
+++ b/resources/bg-skull.svg
@@ -1,63 +1,2 @@
-
-
-
-
+
+
diff --git a/setup/install-modules.sh b/setup/install-modules.sh
index 1eae7c1..ddc6340 100755
--- a/setup/install-modules.sh
+++ b/setup/install-modules.sh
@@ -212,7 +212,7 @@ SELECTED=$(dialog --backtitle "$BACKTITLE" \
"ffmpeg" "FFmpeg extras thumbnailer · GStreamer codecs" off \
"localtunnel" "LocalTunnel expose localhost via tunnel" off \
"butter" "butter btrfs snapshot backup (AUR)" off \
- "plymouth" "Plymouth boot splash — skull logo + spinner" off \
+ "plymouth" "Plymouth boot splash — skull logo + boot-log tail" off \
"plymouth-custom" "Plymouth (custom) boot splash — supply your own image" off \
"lightdm" "LightDM GTK greeter, cyberqueer-themed" off \
"ly" "ly TUI display manager, cyberqueer" off \
diff --git a/setup/modules.conf b/setup/modules.conf
index e07da11..17233b8 100644
--- a/setup/modules.conf
+++ b/setup/modules.conf
@@ -49,7 +49,7 @@ localtunnel|system|expose localhost over a public URL|off|
timeshift|system|system snapshot and backup with autosnap|on|
zfs|system|zfs-dkms kernel module|off|
wprs|system|Wayland proxy for remote sessions (wprs-git, AUR)|off|
-plymouth|system|boot splash — bundled skull logo and spinner|on|plymouth-custom
+plymouth|system|boot splash — bundled skull logo + boot-log tail|on|plymouth-custom
plymouth-custom|system|boot splash with a user-supplied image|off|plymouth
lightdm|system|LightDM GTK greeter, cyberqueer-themed (HyprLua default)|off|ly
ly|system|ly TUI display manager, cyberqueer-themed|off|lightdm
diff --git a/setup/modules/optional-Modules/apps/plymouth.sh b/setup/modules/optional-Modules/apps/plymouth.sh
index 5f43ba1..66cdfe7 100644
--- a/setup/modules/optional-Modules/apps/plymouth.sh
+++ b/setup/modules/optional-Modules/apps/plymouth.sh
@@ -1,9 +1,9 @@
#!/bin/bash
# plymouth.sh — Plymouth boot splash installer
#
-# Installs the M-Archy Plymouth theme: the transparent skull/CRT artwork scaled
-# to fill the screen over a dark background, with a magenta spinning-dot
-# animation near the bottom.
+# Installs the M-Archy Plymouth theme: the magenta skull-monitor logo centred
+# on a dark background, with the latest 3 boot-log lines polled underneath it
+# as plain text (no spinner).
#
# SVG NOTE: Plymouth's image loader (ply-image) is PNG-only — it links against
# libpng and has no SVG or gdk-pixbuf dependency. The ply-image.h header is
@@ -19,14 +19,13 @@
#
# Steps:
# 1. Install plymouth (extra repo)
-# 2. Install librsvg (rsvg-convert) if logo is SVG; imagemagick for dot
-# 3. Produce logo.png (native 1920 px wide) from the resolved source
-# 4. Generate a 10×10 magenta dot.png for the spinner
-# 5. Write the m-archy theme (.plymouth descriptor + .script animation)
-# 6. Register with plymouth-set-default-theme
-# 7. Inject plymouth / sd-plymouth hook into /etc/mkinitcpio.conf
-# 8. Add 'quiet splash' to GRUB_CMDLINE_LINUX_DEFAULT
-# 9. Regenerate GRUB config and initramfs
+# 2. Install librsvg (rsvg-convert) if logo is SVG
+# 3. Produce logo.png (600 px wide) from the resolved source
+# 4. Write the m-archy theme (.plymouth descriptor + .script animation)
+# 5. Register with plymouth-set-default-theme
+# 6. Inject plymouth / sd-plymouth hook into /etc/mkinitcpio.conf
+# 7. Add 'quiet splash' to GRUB_CMDLINE_LINUX_DEFAULT
+# 8. Regenerate GRUB config and initramfs
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/../../lib/logging.sh"
@@ -54,22 +53,17 @@ fi
log "Installing Plymouth..."
sudo pacman -S --noconfirm --needed plymouth
-# ── Ensure conversion tools ───────────────────────────────────────────────────
-# imagemagick is always needed for the spinner dot.
-# librsvg (rsvg-convert) is only needed when the logo source is an SVG.
-if ! command -v convert &>/dev/null; then
- log "Installing imagemagick (dot generation)..."
- sudo pacman -S --noconfirm --needed imagemagick
-fi
-
# ── Produce logo.png ──────────────────────────────────────────────────────────
TMP_LOGO="$(mktemp /tmp/plymouth-logo.XXXXXX.png)"
-TMP_DOT="/tmp/plymouth-dot.png"
-trap 'rm -f "$TMP_LOGO" "$TMP_DOT"' EXIT
+trap 'rm -f "$TMP_LOGO"' EXIT
if [[ -z "$LOGO_SRC" ]]; then
warn "No logo source found — using transparent placeholder."
- convert -size 1920x1080 xc:transparent "$TMP_LOGO"
+ if ! command -v convert &>/dev/null; then
+ log "Installing imagemagick (placeholder generation)..."
+ sudo pacman -S --noconfirm --needed imagemagick
+ fi
+ convert -size 600x600 xc:transparent "$TMP_LOGO"
elif [[ "${LOGO_SRC,,}" == *.png ]]; then
log "Using PNG directly: $LOGO_SRC"
cp "$LOGO_SRC" "$TMP_LOGO"
@@ -79,29 +73,22 @@ else
log "Installing librsvg (rsvg-convert) for SVG→PNG conversion..."
sudo pacman -S --noconfirm --needed librsvg
fi
- # Render at native width so the full-screen splash keeps detail when the
- # Plymouth script scales it to the display resolution.
- log "Converting $LOGO_SRC → PNG (1920 px wide)..."
- rsvg-convert -w 1920 "$LOGO_SRC" -o "$TMP_LOGO"
+ # Render at 600 px wide — the skull is centred (not full-screen), and the
+ # Plymouth script scales it down to a fraction of the display height, so we
+ # only need enough resolution to stay crisp on high-DPI panels.
+ log "Converting $LOGO_SRC → PNG (600 px wide)..."
+ rsvg-convert -w 600 "$LOGO_SRC" -o "$TMP_LOGO"
fi
-# ── Generate spinner dot ──────────────────────────────────────────────────────
-# 10×10 magenta circle — centred at (5,5), radius 4 px
-convert -size 10x10 xc:transparent \
- -fill '#E40046' \
- -draw 'circle 5,5 5,1' \
- "$TMP_DOT"
-
# ── Install theme files ───────────────────────────────────────────────────────
log "Installing M-Archy Plymouth theme..."
sudo mkdir -p "$THEME_DIR"
sudo cp "$TMP_LOGO" "$THEME_DIR/logo.png"
-sudo cp "$TMP_DOT" "$THEME_DIR/dot.png"
sudo tee "$THEME_DIR/m-archy.plymouth" > /dev/null <<'EOF'
[Plymouth Theme]
Name=M-Archy
-Description=M-Archy boot splash — skull logo with spinning dots
+Description=M-Archy boot splash — centred skull logo with a boot-log tail
ModuleName=script
[script]
@@ -110,7 +97,7 @@ ScriptFile=/usr/share/plymouth/themes/m-archy/m-archy.script
EOF
sudo tee "$THEME_DIR/m-archy.script" > /dev/null <<'EOF'
-# M-Archy Plymouth splash — full-screen skull background + magenta spinner
+# M-Archy Plymouth splash — centred skull logo + latest 3 boot-log lines.
Window.SetBackgroundTopColor (0.10, 0.10, 0.10);
Window.SetBackgroundBottomColor (0.07, 0.07, 0.07);
@@ -118,47 +105,65 @@ Window.SetBackgroundBottomColor (0.07, 0.07, 0.07);
screen_width = Window.GetWidth ();
screen_height = Window.GetHeight ();
-# Full-screen skull background. bg-skull.svg is a 1920x1080 composition with a
-# transparent field, so we scale it to fill the display and pin it at the
-# origin; the transparent areas reveal the dark background gradient above.
-logo.image = Image ("logo.png");
-scaled = logo.image.Scale (screen_width, screen_height);
+# ── Skull logo, centred ───────────────────────────────────────────────────────
+# logo.png is the tight skull-monitor artwork (roughly square). Scale it to a
+# fraction of the screen height, preserving aspect ratio, then centre it and
+# nudge it up a little so the log lines below have room to breathe.
+logo.image = Image ("logo.png");
+target_h = screen_height * 0.42;
+scale = target_h / logo.image.GetHeight ();
+scaled = logo.image.Scale (logo.image.GetWidth () * scale, target_h);
+
logo.sprite = Sprite (scaled);
-logo.sprite.SetX (0);
-logo.sprite.SetY (0);
+logo.sprite.SetX ((screen_width - scaled.GetWidth ()) / 2);
+logo.sprite.SetY ((screen_height - scaled.GetHeight ()) / 2 - screen_height * 0.08);
logo.sprite.SetZ (10);
-# 12-dot spinner near the bottom of the screen. The centre is a fixed fraction
-# of the screen height (not derived from the logo size) so it stays put
-# regardless of the source image's dimensions.
-num_dots = 12;
-dot_r = 5;
-orbit = 35;
-cx = screen_width / 2;
-cy = Math.Int (screen_height * 0.93);
-dot.image = Image ("dot.png");
+# ── Boot-log tail — latest 3 lines ────────────────────────────────────────────
+# A rolling buffer of the three most recent status/message strings Plymouth
+# hands us, drawn as centred text beneath the logo. The newest line is the
+# brightest; older lines fade back.
+num_lines = 3;
+line_gap = 26; # px between successive baselines
+text_top = Math.Int (screen_height * 0.72); # y of the oldest (top) line
-for (i = 0; i < num_dots; i++) {
- dot[i].sprite = Sprite (dot.image);
- dot[i].sprite.SetZ (20);
+for (i = 0; i < num_lines; i++) {
+ log_line[i] = "";
+ log_sprite[i] = Sprite ();
+ log_sprite[i].SetZ (20);
}
-frame = 0;
-
-fun refresh_callback () {
- frame++;
- step = 2 * Math.Pi / num_dots;
- for (i = 0; i < num_dots; i++) {
- angle = step * i + frame * 0.15;
- dot[i].sprite.SetX (Math.Int (cx + Math.Cos (angle) * orbit - dot_r));
- dot[i].sprite.SetY (Math.Int (cy + Math.Sin (angle) * orbit - dot_r));
- t = (i + Math.Int (frame / 4) % num_dots) % num_dots;
- f = t / num_dots;
- dot[i].sprite.SetOpacity (0.15 + 0.85 * f * f);
+fun draw_lines () {
+ for (i = 0; i < num_lines; i++) {
+ # Empty slots (before the buffer fills) stay hidden — Image.Text ("")
+ # is unreliable across Plymouth versions, so never render it.
+ if (log_line[i] == "") {
+ log_sprite[i].SetOpacity (0);
+ } else {
+ shade = 0.40 + 0.25 * i; # 0.40, 0.65, 0.90 top→bottom
+ image = Image.Text (log_line[i], shade, shade, shade);
+ log_sprite[i].SetImage (image);
+ log_sprite[i].SetX ((screen_width - image.GetWidth ()) / 2);
+ log_sprite[i].SetY (text_top + i * line_gap);
+ log_sprite[i].SetOpacity (1);
+ }
}
}
-Plymouth.SetRefreshFunction (refresh_callback);
+fun push_line (text) {
+ # Scroll the buffer up by one line and append the newcomer at the bottom.
+ for (i = 0; i < num_lines - 1; i++) {
+ log_line[i] = log_line[i + 1];
+ }
+ log_line[num_lines - 1] = text;
+ draw_lines ();
+}
+
+# Both callbacks feed the same tail: systemd unit progress arrives via the
+# status function, explicit `plymouth display-message` strings via the message
+# function.
+Plymouth.SetUpdateStatusFunction (fun (status) { push_line (status); });
+Plymouth.SetDisplayMessageFunction (fun (text) { push_line (text); });
EOF
# ── Register theme ────────────────────────────────────────────────────────────
diff --git a/setup/tools/generate-answerfile.sh b/setup/tools/generate-answerfile.sh
index 264637d..e806cff 100755
--- a/setup/tools/generate-answerfile.sh
+++ b/setup/tools/generate-answerfile.sh
@@ -272,7 +272,7 @@ if [[ "$AF_RUN_TUI" == "true" ]]; then
"timeshift" "timeshift system snapshot and backup with autosnap" on \
"zfs" "zfs zfs-dkms kernel module" off \
"wprs" "wprs Wayland proxy for remote sessions (wprs-git, AUR)" off \
- "plymouth" "plymouth boot splash — bundled skull logo and spinner" on \
+ "plymouth" "plymouth boot splash — bundled skull logo + boot-log tail" on \
"plymouth-custom" "plymouth-custom boot splash with a user-supplied image" off \
"lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (HyprLua default)" off \
"ly" "ly ly TUI display manager, cyberqueer-themed" off \
diff --git a/setup/tools/migrate-to-lightdm.sh b/setup/tools/migrate-to-lightdm.sh
index a0febd7..ccdd046 100755
--- a/setup/tools/migrate-to-lightdm.sh
+++ b/setup/tools/migrate-to-lightdm.sh
@@ -14,13 +14,21 @@
# reboot yourself.
# 3. Runs the lightdm module (installs LightDM + lightdm-gtk-greeter, deploys
# the cyberqueer greeter config + skull background, enables lightdm.service).
-# 4. Runs the plymouth module (skull splash, initramfs + GRUB cmdline) unless
+# 4. Purges obsolete Plymouth artifacts left by earlier versions of this repo
+# (e.g. the spinner's dot.png) so an upgraded install ends up byte-clean.
+# 5. Runs the plymouth module (skull splash, initramfs + GRUB cmdline) unless
# --no-plymouth is given.
#
# It reuses the real module scripts under optional-Modules/apps/ so there is no
# duplicated install logic — this tool only handles detection, teardown of the
# OLD display manager, and orchestration.
#
+# Double duty: on a machine that is ALREADY on Plymouth + LightDM (an install
+# migrated by an earlier version of this repo) re-running simply refreshes the
+# greeter config and re-installs the current Plymouth theme — the clean upgrade
+# path from the old full-screen-skull + spinner splash to the centred-skull +
+# boot-log-tail one.
+#
# Safe to re-run (idempotent). Reboot to complete the switch.
#
# Usage:
@@ -177,6 +185,19 @@ run bash "$APPS/lightdm.sh"
# ── 5. Plymouth splash (delegated to the module) ──────────────────────────────
if (( DO_PLYMOUTH )); then
+ # Upgrade cleanup: the current theme is a centred skull + boot-log tail. The
+ # previous version scaled the skull full-screen and drew a spinning-dot
+ # throbber from dot.png. That file is now dead weight — strip it (and any
+ # other stale theme assets) BEFORE re-running the module, so it is neither
+ # rendered nor baked into the initramfs that plymouth.sh rebuilds.
+ THEME_DIR="/usr/share/plymouth/themes/m-archy"
+ for stale in "$THEME_DIR/dot.png"; do
+ if [[ -e "$stale" ]]; then
+ log "Removing obsolete Plymouth asset: $stale"
+ run sudo rm -f "$stale"
+ fi
+ done
+
log "Setting up the Plymouth splash via the plymouth module..."
run bash "$APPS/plymouth.sh"
else
diff --git a/setup/tui-install.sh b/setup/tui-install.sh
index 7ba9b7b..9220a73 100755
--- a/setup/tui-install.sh
+++ b/setup/tui-install.sh
@@ -589,7 +589,7 @@ else
"timeshift" "timeshift system snapshot and backup with autosnap" on \
"zfs" "zfs zfs-dkms kernel module" off \
"wprs" "wprs Wayland proxy for remote sessions (wprs-git, AUR)" off \
- "plymouth" "plymouth boot splash — bundled skull logo and spinner" on \
+ "plymouth" "plymouth boot splash — bundled skull logo + boot-log tail" on \
"plymouth-custom" "plymouth-custom boot splash with a user-supplied image" off \
"lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (HyprLua default)" off \
"ly" "ly ly TUI display manager, cyberqueer-themed" off \