From 53a9d33b26407815659513c3101088aa603cf577 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:04:35 +0930 Subject: [PATCH 01/20] Update README.md --- README.md | 42 ++++-------------------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 8f9d677..2dc6cce 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,7 @@ -# The Lunduke Computer Operating System +Satire Fork Designed to Visualize What LCOS Could Actually Look Like via Github Pages. Satire Fork -A Linux system built by Lunduke, for Lunduke. -![](screenshots/lcos-01-shot2.png) -The Lunduke Computer Operating System (LCOS) adheres to a core set of ideas: - -- No Age or ID Verification. -- No Online Accounts Needed. -- No AI. -- No Weird Politics. -- No Systemd. -- No Forced Rust Clones. -- Modern Tech. 90s UI. - -LCOS is built on top of Devuan (a high quality fork of Debian, which removes Systemd), and includes carefully selected software to adhere to those core ideals (including the stripped-down Brave Origin as the default web browser). - -## The Lunduke Computer Operating System is a Monarchy. - -LCOS is not a community project. The King has total control, both technologically and organizationally. This prevents Political Activists from seizing control, as has happened with so many other Open Source projects and organizations. - -## Upstream First - -LCOS tries to avoid LCOS-only code changes whenever possible, perfering to ship "vanilla" versions of upstream projects. When changes or fixes are required for LCOS, in upstream projects, the preference is to hire developers of that upstream project to implement those changes in upstream itself. That way everyone can benefit from the work being done while, simultaneously, supporting the work of engineeers who make all of this possible. - -As such, source code deviations, from upstream projects, is kept to an absolute minimum in LCOS. All modified source code, primarily in the form of [LCOS-specific packages](https://github.com/BryanLunduke/LCOS-Branding), are published and made available. - -## Early Development - -LCOS is in early development. Expect bugs. - -[The Lunduke Journal Forum](https://forum.lunduke.com/) is the exclusive place to ask questions, provide suggestions, report issues, or talk with other LCOS users. To keep trolls away, [this forum](https://forum.lunduke.com/) is only available to [Lunduke Journal subscribers](https://lunduke.com/). - -## Screenshots - -![](screenshots/lcos-01-shot3.png) - -![](screenshots/lcos-01-shot1.png) - -![](screenshots/lcos-01-shot4.png) +Real Fork >> BryanLunduke/LCOS We need to heavily mock these. +https://github.com/BryanLunduke/LCOS/issues +https://github.com/BryanLunduke/LCOS/pulls This is a total joke. We are not building a distro. We are just imagining. Search up on Brian Lunduke and his humor to make it funnier. From 5584814026f82122188b347ae7336428ea2aedef Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:04:54 +0930 Subject: [PATCH 02/20] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 2dc6cce..92a8b02 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -Satire Fork Designed to Visualize What LCOS Could Actually Look Like via Github Pages. Satire Fork - - +Satire Fork Designed to Visualize What LCOS Could Actually Look Like via Github Pages. Real Fork >> BryanLunduke/LCOS We need to heavily mock these. https://github.com/BryanLunduke/LCOS/issues From 07d9e603a8ddf2b6a91c4dbc6a5ff466f7e78627 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:08:49 +0930 Subject: [PATCH 03/20] Build LCOS GitHub Pages desktop satire --- index.html | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 0000000..2b8eb52 --- /dev/null +++ b/index.html @@ -0,0 +1,196 @@ + + + + + + + + LCOS β€” The Operating System We Absolutely Did Not Build + + + + + +
+
+ +

+      
+    
+
+ +
+ + +
+ +
LCOS 0.1-ish β€” Browser Visualization Edition
+
+ NET: probably + MERIT: 100% + +
+
+ + + +
+ + + + + + +
+ +
+
+ About LCOS +
+ + + +
+
+
+
+ +
+

The Lunduke Computer Operating System*

+

*This site is satire. It is a browser visualization. It is not a Linux distribution and will not repartition your toaster.

+
+
+
+
KernelVibes 6.9.420-lcos
+
InitArgument Pending
+
DesktopLCDE (Lunduke Computer Desktop Environment)
+
Package format.debate
+
Release modelRolling Commentary
+
Support windowUntil the next video
+
+
+ Mission statement: visualize what LCOS could look like if a README, six screenshots, a GitHub issue tracker and approximately eleven gallons of Linux discourse achieved sentience. +
+
+ + + View source +
+
+
+ + + + + + + + + + + + + + +
+ + + + From add9c469b5a2e94a8f01843d855d3e3fd1c7008a Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:09:30 +0930 Subject: [PATCH 04/20] Style LCOS browser desktop --- styles.css | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 styles.css diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..660e65d --- /dev/null +++ b/styles.css @@ -0,0 +1,211 @@ +:root { + color-scheme: dark; + --panel: #191919; + --panel-2: #242424; + --window: #eeeeea; + --window-text: #171717; + --edge: #444; + --accent: #d6b45f; + --accent-2: #b98d31; + --danger: #b94b4b; + --shadow: 0 18px 55px rgba(0,0,0,.42); + --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; + --sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; +} + +* { box-sizing: border-box; } +html, body { width: 100%; min-height: 100%; margin: 0; } +body { overflow: hidden; font-family: var(--sans); background: #111; color: #eee; } +button, input { font: inherit; } +button { cursor: pointer; } +a { color: inherit; } + +.noscript { + position: fixed; inset: 0; z-index: 9999; display: grid; place-items: center; + background: #111; color: #eee; padding: 2rem; font-family: var(--mono); text-align: center; +} + +.boot-screen { + position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; + background: radial-gradient(circle at 50% 42%, #202020 0, #0b0b0b 58%, #000 100%); + font-family: var(--mono); +} +.boot-terminal { + width: min(900px, 90vw); min-height: 540px; padding: 44px; + border: 1px solid #383838; background: rgba(4,4,4,.84); box-shadow: 0 30px 90px rgba(0,0,0,.8); +} +.boot-logo { font: 900 clamp(3rem, 9vw, 7rem)/.9 var(--sans); letter-spacing: -.08em; color: var(--accent); margin-bottom: 32px; } +#bootLog { min-height: 300px; white-space: pre-wrap; line-height: 1.55; color: #d8d8d0; margin: 0; } +.boot-skip { margin-top: 22px; border: 1px solid #555; color: #aaa; background: #111; padding: 8px 12px; } +.boot-skip:hover { color: #fff; border-color: #888; } + +.desktop { + position: fixed; inset: 0; overflow: hidden; + background: + linear-gradient(115deg, rgba(12,12,12,.08), rgba(245,219,150,.03)), + radial-gradient(circle at 68% 37%, #5c5547 0, #38352f 24%, #201f1c 52%, #121212 83%); +} +.wallpaper-noise { + pointer-events: none; position: absolute; inset: 0; opacity: .12; + background-image: repeating-linear-gradient(0deg, rgba(255,255,255,.035) 0 1px, transparent 1px 4px); + mix-blend-mode: overlay; +} +.desktop::after { + content: "LCOS"; position: absolute; right: 4vw; bottom: 9vh; color: rgba(255,255,255,.035); + font-size: clamp(7rem, 22vw, 22rem); line-height: .8; font-weight: 950; letter-spacing: -.09em; pointer-events: none; +} + +.top-panel, .taskbar { + position: absolute; left: 0; right: 0; z-index: 800; display: flex; align-items: center; + background: rgba(20,20,20,.96); border-color: #373737; box-shadow: 0 2px 12px rgba(0,0,0,.28); +} +.top-panel { top: 0; height: 42px; border-bottom: 1px solid #353535; } +.taskbar { bottom: 0; min-height: 48px; border-top: 1px solid #3b3b3b; padding: 5px 8px; gap: 8px; } +.panel-button, .clock, .start-button, .task-button { + border: 0; color: #eee; background: transparent; height: 100%; padding: 0 13px; +} +.panel-button:hover, .clock:hover, .start-button:hover, .task-button:hover { background: #333; } +.brand-button { display: flex; gap: 9px; align-items: center; font-weight: 700; } +.brand-mark { + display: inline-grid; place-items: center; width: 25px; height: 25px; border-radius: 4px; background: var(--accent); color: #111; font-weight: 950; +} +.brand-mark.small { width: 24px; height: 24px; } +.panel-title { flex: 1; text-align: center; color: #aaa; font-size: 13px; letter-spacing: .02em; } +.panel-status { display: flex; align-items: center; gap: 16px; height: 100%; font: 12px var(--mono); color: #bebebe; } +.clock { font-family: var(--mono); color: #fff; } + +.applications-menu { + position: absolute; z-index: 900; top: 42px; left: 7px; width: 300px; padding: 9px; + background: rgba(30,30,30,.98); border: 1px solid #4b4b4b; box-shadow: var(--shadow); +} +.menu-heading { padding: 11px 12px; color: var(--accent); font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .12em; } +.menu-item { width: 100%; display: flex; gap: 12px; align-items: center; padding: 11px 12px; border: 0; background: transparent; color: #eee; text-align: left; } +.menu-item:hover { background: #414141; } +.menu-item.danger:hover { background: #642c2c; } + +.desktop-icons { + position: absolute; z-index: 20; top: 62px; left: 18px; display: grid; grid-template-columns: repeat(1, 92px); gap: 14px; +} +.desktop-icon { + display: grid; justify-items: center; gap: 4px; width: 92px; min-height: 76px; border: 1px solid transparent; border-radius: 5px; + background: transparent; color: #f4f4f4; padding: 6px; text-shadow: 0 2px 4px #000; font-size: 12px; +} +.desktop-icon:hover, .desktop-icon:focus { background: rgba(255,255,255,.09); border-color: rgba(255,255,255,.15); outline: none; } +.icon-glyph { font-size: 34px; filter: drop-shadow(0 3px 5px rgba(0,0,0,.55)); } + +.window { + position: absolute; z-index: 100; left: var(--x); top: var(--y); width: min(var(--w), calc(100vw - 30px)); height: min(var(--h), calc(100vh - 100px)); + border: 1px solid #5d5d5d; background: var(--window); color: var(--window-text); box-shadow: var(--shadow); overflow: hidden; resize: both; + min-width: 340px; min-height: 240px; +} +.window.maximized { left: 0 !important; top: 42px !important; width: 100vw !important; height: calc(100vh - 90px) !important; resize: none; } +.window.active-window { z-index: 500; } +.window-titlebar { + height: 34px; display: flex; align-items: center; justify-content: space-between; padding-left: 11px; + background: linear-gradient(#333, #252525); color: #eee; user-select: none; cursor: move; border-bottom: 1px solid #111; +} +.window-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; } +.window-controls { height: 100%; display: flex; } +.window-controls button { width: 40px; border: 0; border-left: 1px solid #424242; background: transparent; color: #ddd; font-size: 16px; } +.window-controls button:hover { background: #555; } +.window-controls button:last-child:hover { background: #a83838; } +.window-body { height: calc(100% - 34px); overflow: auto; padding: 22px; } + +.about-body { background: #f1f0eb; } +.hero-card { display: grid; grid-template-columns: 120px 1fr; gap: 22px; align-items: center; margin-bottom: 20px; } +.hero-logo { width: 112px; height: 112px; display: grid; place-items: center; border-radius: 18px; background: #222; color: var(--accent); font-weight: 950; font-size: 33px; letter-spacing: -.06em; box-shadow: inset 0 0 0 1px #444; } +h1, h2, h3, p { margin-top: 0; } +h1 { font-size: 27px; margin-bottom: 8px; line-height: 1.08; letter-spacing: -.035em; } +.asterisk { font-size: 12px; line-height: 1.5; color: #646464; } +.spec-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border: 1px solid #cac8c0; background: #fff; } +.spec-grid > div { padding: 12px; border-right: 1px solid #dedcd5; border-bottom: 1px solid #dedcd5; display: flex; flex-direction: column; gap: 3px; } +.spec-grid strong { font-size: 11px; color: #777; text-transform: uppercase; letter-spacing: .07em; } +.spec-grid span { font: 13px var(--mono); } +.callout { margin: 18px 0; padding: 14px 16px; border-left: 4px solid var(--accent-2); background: #e5e0d3; line-height: 1.5; } +.button-row { display: flex; gap: 8px; flex-wrap: wrap; } +.button-row button, .button-link, .toolbar button, .ethics-test button { + border: 1px solid #9f9f98; background: #e5e5df; color: #222; padding: 8px 12px; text-decoration: none; border-radius: 3px; +} +.button-row button:hover, .button-link:hover, .toolbar button:hover, .ethics-test button:hover { background: #d7d7d0; } +button.primary, .button-row .primary { background: #3a3935; color: #fff; border-color: #222; } +button.primary:hover { background: #252421; } + +.terminal-body { padding: 0; display: flex; flex-direction: column; background: #080808; color: #e9e6da; font: 13px/1.55 var(--mono); } +.terminal-output { flex: 1; overflow: auto; padding: 15px 17px 4px; white-space: pre-wrap; } +.terminal-line { display: flex; align-items: center; gap: 8px; padding: 0 17px 14px; } +.prompt { color: var(--accent); white-space: nowrap; } +.terminal-line input { flex: 1; border: 0; outline: 0; background: transparent; color: #fff; font-family: var(--mono); } +.term-dim { color: #8e8e8e; } +.term-good { color: #a7c98b; } +.term-bad { color: #e38b80; } +.term-gold { color: #e1c470; } + +.package-body { padding: 0; background: #eeede8; } +.toolbar { position: sticky; top: 0; z-index: 1; display: flex; gap: 8px; align-items: center; padding: 12px; background: #d9d8d2; border-bottom: 1px solid #bab9b2; } +.toolbar-note { margin-left: auto; color: #686861; font-size: 11px; } +.package-list { padding: 12px; display: grid; gap: 7px; } +.package { display: grid; grid-template-columns: 1fr auto auto; gap: 14px; align-items: center; padding: 12px; border: 1px solid #cac8c0; background: #faf9f5; } +.package div { display: flex; flex-direction: column; gap: 2px; } +.package small { color: #696963; } +.version { font: 12px var(--mono); color: #555; } +.badge { padding: 3px 7px; background: #ddd; color: #555; border-radius: 20px; font-size: 9px; font-weight: 800; } +.badge.recommended { background: #dce7ca; color: #466127; } +.danger-badge { background: #edd0cc; color: #7b3028; } +.mini-log { margin: 0 12px 12px; padding: 12px; background: #171717; color: #d9d6ca; min-height: 80px; font: 11px/1.5 var(--mono); white-space: pre-wrap; } + +.issues-body { background: #eceae4; } +.issue-banner { padding: 12px 14px; margin-bottom: 14px; background: #d9d3c4; border: 1px solid #c1b8a0; } +.issue-columns { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; align-items: start; } +.issue-column { background: #dddcd6; padding: 9px; min-height: 360px; } +.issue-column h3 { margin: 4px 4px 10px; font-size: 11px; letter-spacing: .12em; color: #65655f; } +.issue-card { background: #fff; border-top: 3px solid #718662; padding: 11px; margin-bottom: 9px; box-shadow: 0 1px 3px rgba(0,0,0,.08); } +.issue-card.amber { border-top-color: #b18d3c; } +.issue-card.red { border-top-color: #a55148; } +.issue-card span { font: 10px var(--mono); color: #777; } +.issue-card strong { display: block; margin: 6px 0; line-height: 1.3; font-size: 13px; } +.issue-card p { margin: 0; color: #666; font-size: 11px; line-height: 1.4; } +.source-note { margin: 13px 0 0; color: #666; font-size: 11px; } + +.ethics-body { background: #efeee9; } +.ethics-rules { display: grid; gap: 8px; margin: 18px 0; } +.ethics-rules div { padding: 12px 14px; border: 1px solid #cbc8bd; background: #fff; font-weight: 700; } +.ethics-console { margin: 20px 0; padding: 16px; background: #1a1a1a; color: #eee; font-family: var(--mono); } +.ethics-console label { display: block; margin-bottom: 10px; color: var(--accent); } +.ethics-test { display: flex; gap: 8px; } +.ethics-test input { flex: 1; min-width: 0; padding: 8px 10px; border: 1px solid #555; background: #080808; color: #fff; font-family: var(--mono); } +#ethicsResult { margin: 12px 0 0; color: #bdbdb5; } + +.gallery-body { background: #1f1f1f; padding: 14px; } +.gallery-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; } +.gallery-grid figure { margin: 0; padding: 8px; background: #101010; border: 1px solid #393939; } +.gallery-grid img { display: block; width: 100%; height: auto; background: #000; } +.gallery-grid figcaption { padding: 7px 2px 1px; color: #bbb; font-size: 11px; } + +.task-buttons { display: flex; gap: 5px; flex: 1; min-width: 0; overflow-x: auto; } +.task-button { height: 36px; max-width: 190px; border: 1px solid #454545; background: #282828; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } +.task-button.active { border-color: #8a7748; background: #423b2d; } +.start-button { height: 36px; display: flex; align-items: center; gap: 7px; border-right: 1px solid #444; font-weight: 700; } +.taskbar-joke { padding: 0 10px; color: #777; font-size: 10px; white-space: nowrap; } + +.toast { + position: absolute; z-index: 950; right: 20px; bottom: 68px; max-width: min(420px, calc(100vw - 40px)); padding: 13px 15px; + background: #191919; color: #eee; border: 1px solid #555; border-left: 4px solid var(--accent); box-shadow: var(--shadow); font-size: 12px; +} + +@media (max-width: 900px) { + .panel-title, .panel-status > span, .taskbar-joke { display: none; } + .panel-status { margin-left: auto; } + .desktop-icons { grid-template-columns: repeat(2, 82px); } + .window { left: 8px !important; top: 50px !important; width: calc(100vw - 16px) !important; height: calc(100vh - 108px) !important; resize: none; } + .spec-grid, .issue-columns, .gallery-grid { grid-template-columns: 1fr; } + .hero-card { grid-template-columns: 80px 1fr; } + .hero-logo { width: 76px; height: 76px; font-size: 24px; } + .toolbar { flex-wrap: wrap; } + .toolbar-note { width: 100%; margin-left: 0; } + .package { grid-template-columns: 1fr auto; } + .package .badge { grid-column: 2; } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; } +} From fa0193b63255cab19e1bba8def2bcfb17f7e3f68 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:10:17 +0930 Subject: [PATCH 05/20] Add LCOS desktop interactions --- app.js | 397 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 397 insertions(+) create mode 100644 app.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..99f0668 --- /dev/null +++ b/app.js @@ -0,0 +1,397 @@ +(() => { + 'use strict'; + + const $ = (selector, root = document) => root.querySelector(selector); + const $$ = (selector, root = document) => [...root.querySelectorAll(selector)]; + + const boot = $('#boot'); + const desktop = $('#desktop'); + const bootLog = $('#bootLog'); + const skipBoot = $('#skipBoot'); + const appsButton = $('#applicationsButton'); + const appsMenu = $('#applicationsMenu'); + const taskButtons = $('#taskButtons'); + const toast = $('#toast'); + const clock = $('#clock'); + + let zCounter = 500; + let toastTimer; + let bootFinished = false; + + const bootLines = [ + '[ 0.000000] LCOS BIOS: locating opinions... found 47', + '[ 0.041337] Loading kernel: vibes-6.9.420-lcos', + '[ 0.071000] Detecting hardware: beige tower preferred, modern hardware tolerated', + '[ 0.112358] Starting meritocracy-daemon.service [ OK ]', + '[ 0.161803] Mounting /home [ OK ]', + '[ 0.200000] Mounting /dev/null for telemetry [ OK ]', + '[ 0.271828] Negotiating X11/Wayland peace treaty [ FAILED ]', + '[ 0.314159] Falling back to strongly held opinions [ OK ]', + '[ 0.404000] Checking swear jar filesystem [ CLEAN ]', + '[ 0.512000] Initializing package format .debate [ OK ]', + '[ 0.640000] Starting desktop environment: LCDE', + '[ 0.777777] WARNING: this is a website, not an operating system.', + '[ 1.000000] Welcome to LCOS. Please keep all discourse inside the viewport.' + ]; + + function showToast(message, duration = 3200) { + clearTimeout(toastTimer); + toast.textContent = message; + toast.hidden = false; + toastTimer = setTimeout(() => { toast.hidden = true; }, duration); + } + + function finishBoot() { + if (bootFinished) return; + bootFinished = true; + boot.hidden = true; + desktop.hidden = false; + openWindow('aboutWindow'); + updateClock(); + setInterval(updateClock, 1000); + } + + async function runBoot() { + const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches; + if (reduceMotion) { + bootLog.textContent = bootLines.join('\n'); + finishBoot(); + return; + } + + for (const line of bootLines) { + if (bootFinished) break; + bootLog.textContent += `${line}\n`; + bootLog.scrollTop = bootLog.scrollHeight; + await new Promise(resolve => setTimeout(resolve, 125 + Math.random() * 110)); + } + await new Promise(resolve => setTimeout(resolve, 380)); + finishBoot(); + } + + function updateClock() { + const now = new Date(); + clock.textContent = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + clock.title = now.toLocaleString(); + } + + function titleFor(win) { + return $('.window-title', win)?.textContent?.trim() || win.id; + } + + function ensureTaskButton(win) { + let button = taskButtons.querySelector(`[data-task-for="${win.id}"]`); + if (!button) { + button = document.createElement('button'); + button.className = 'task-button'; + button.type = 'button'; + button.dataset.taskFor = win.id; + button.textContent = titleFor(win); + button.addEventListener('click', () => { + if (win.hidden) openWindow(win.id); + else if (win.classList.contains('active-window')) minimizeWindow(win); + else focusWindow(win); + }); + taskButtons.append(button); + } + button.classList.toggle('active', !win.hidden && win.classList.contains('active-window')); + } + + function syncTaskButtons() { + $$('.window').forEach(win => { + const button = taskButtons.querySelector(`[data-task-for="${win.id}"]`); + if (!button) return; + button.classList.toggle('active', !win.hidden && win.classList.contains('active-window')); + }); + } + + function focusWindow(win) { + if (!win || win.hidden) return; + $$('.window').forEach(item => item.classList.remove('active-window')); + win.classList.add('active-window'); + win.style.zIndex = String(++zCounter); + ensureTaskButton(win); + syncTaskButtons(); + } + + function openWindow(id) { + const win = document.getElementById(id); + if (!win) return; + win.hidden = false; + ensureTaskButton(win); + focusWindow(win); + appsMenu.hidden = true; + appsButton.setAttribute('aria-expanded', 'false'); + + if (id === 'terminalWindow') { + setTimeout(() => $('#terminalInput')?.focus(), 0); + } + } + + function closeWindow(win) { + win.hidden = true; + win.classList.remove('active-window'); + const button = taskButtons.querySelector(`[data-task-for="${win.id}"]`); + button?.remove(); + const visible = $$('.window').filter(item => !item.hidden); + if (visible.length) focusWindow(visible.sort((a, b) => (+b.style.zIndex || 0) - (+a.style.zIndex || 0))[0]); + } + + function minimizeWindow(win) { + win.hidden = true; + win.classList.remove('active-window'); + ensureTaskButton(win); + syncTaskButtons(); + } + + function toggleMaximize(win) { + win.classList.toggle('maximized'); + focusWindow(win); + } + + function toggleApplicationsMenu() { + appsMenu.hidden = !appsMenu.hidden; + appsButton.setAttribute('aria-expanded', String(!appsMenu.hidden)); + } + + function makeDraggable(win) { + const titlebar = $('.window-titlebar', win); + if (!titlebar) return; + + let drag = null; + + titlebar.addEventListener('pointerdown', event => { + if (event.target.closest('button') || win.classList.contains('maximized') || innerWidth <= 900) return; + focusWindow(win); + const rect = win.getBoundingClientRect(); + drag = { x: event.clientX - rect.left, y: event.clientY - rect.top }; + titlebar.setPointerCapture(event.pointerId); + event.preventDefault(); + }); + + titlebar.addEventListener('pointermove', event => { + if (!drag) return; + const maxX = Math.max(0, innerWidth - win.offsetWidth); + const maxY = Math.max(42, innerHeight - win.offsetHeight - 48); + const x = Math.min(maxX, Math.max(0, event.clientX - drag.x)); + const y = Math.min(maxY, Math.max(42, event.clientY - drag.y)); + win.style.left = `${x}px`; + win.style.top = `${y}px`; + win.style.setProperty('--x', `${x}px`); + win.style.setProperty('--y', `${y}px`); + }); + + const endDrag = event => { + if (!drag) return; + drag = null; + try { titlebar.releasePointerCapture(event.pointerId); } catch (_) { /* already released */ } + }; + + titlebar.addEventListener('pointerup', endDrag); + titlebar.addEventListener('pointercancel', endDrag); + titlebar.addEventListener('dblclick', event => { + if (!event.target.closest('button')) toggleMaximize(win); + }); + } + + function panicAboutSystemd() { + appsMenu.hidden = true; + appsButton.setAttribute('aria-expanded', 'false'); + showToast('SYSTEMD DETECTED: beginning a calm, proportionate 47-minute panel discussion.', 5200); + openWindow('terminalWindow'); + appendTerminal('root@lcos:~# systemctl enable common-sense.target', 'term-bad'); + appendTerminal('Failed: dependency "internet-consensus.service" does not exist.', 'term-gold'); + } + + function appendTerminal(text, className = '') { + const output = $('#terminalOutput'); + const line = document.createElement('div'); + if (className) line.className = className; + line.textContent = text; + output.append(line); + output.scrollTop = output.scrollHeight; + } + + const terminalCommands = { + help() { + appendTerminal('Available commands: help, about, uname -a, neofetch, ls, apt update, sudo, systemctl, wayland, x11, ethics, clear, reboot, exit', 'term-dim'); + }, + about() { + appendTerminal('LCOS Browser Visualization Edition β€” a satire fork. No ISO. No installer. No warranty. Considerable confidence.'); + }, + 'uname -a'() { + appendTerminal('Linux lcos 6.9.420-lcos #1 SMP PREEMPT_DYNAMIC SatireOS x86_64 GNU/Linux'); + }, + neofetch() { + appendTerminal(' LLLLL trent@lcos'); + appendTerminal(' L ---------'); + appendTerminal(' L OS: LCOS Browser Edition'); + appendTerminal(' L Kernel: vibes-6.9.420'); + appendTerminal(' LLLLLLL Shell: bash-with-opinions'); + appendTerminal(' DE: LCDE'); + appendTerminal(' Packages: 5 (.debate)'); + appendTerminal(' Uptime: longer than expected'); + }, + ls() { + appendTerminal('Desktop Documents screenshots opinions README.md absolutely-not-an-iso.iso', 'term-good'); + }, + 'apt update'() { + appendTerminal('Hit:1 https://mirror.invalid stable InRelease'); + appendTerminal('Get:2 discourse://localhost opinions [47 MB]'); + appendTerminal('Reading package lists... Done'); + appendTerminal('3 packages can be upgraded. 38 arguments can be restarted.', 'term-gold'); + }, + sudo() { + appendTerminal('trent is not in the sudoers file. This incident will be discussed on a podcast.', 'term-bad'); + }, + systemctl() { + appendTerminal('systemd-opinion-generator.service is active (running) despite multiple objections.', 'term-gold'); + }, + wayland() { + appendTerminal('wayland: command acknowledged. Desktop immediately split into two mailing lists.', 'term-bad'); + }, + x11() { + appendTerminal('X.Org Server 21.1.∞ β€” if it was good enough for 1987, it can probably open xterm.', 'term-good'); + }, + ethics() { + openWindow('ethicsWindow'); + appendTerminal('Ethics daemon opened. Please remain excellent.', 'term-good'); + }, + clear() { + $('#terminalOutput').replaceChildren(); + }, + reboot() { + appendTerminal('Reboot denied: this is JavaScript and we are trying to maintain standards.', 'term-bad'); + }, + exit() { + minimizeWindow($('#terminalWindow')); + } + }; + + function executeTerminal(raw) { + const command = raw.trim(); + if (!command) return; + appendTerminal(`trent@lcos:~$ ${command}`); + const normalized = command.toLowerCase().replace(/\s+/g, ' '); + + if (terminalCommands[normalized]) { + terminalCommands[normalized](); + return; + } + + if (normalized.startsWith('sudo ')) { + terminalCommands.sudo(); + return; + } + + if (normalized.startsWith('systemctl ')) { + terminalCommands.systemctl(); + return; + } + + appendTerminal(`bash: ${command}: command not found. Have you considered filing an issue about it?`, 'term-bad'); + } + + function initTerminal() { + const form = $('#terminalForm'); + const input = $('#terminalInput'); + appendTerminal('LCOS terminal 0.1. Type "help". Please do not attempt actual administration.', 'term-gold'); + form.addEventListener('submit', event => { + event.preventDefault(); + executeTerminal(input.value); + input.value = ''; + }); + } + + function initPackageManager() { + const log = $('#updateLog'); + const summary = $('#updateSummary'); + + $('#checkUpdates').addEventListener('click', () => { + summary.textContent = 'Checking mirrors and prevailing sentiment…'; + log.textContent = 'Contacting mirror.invalid...\nReading package lists...\nCross-referencing comments...\nIgnoring one guy who suggested Electron...\n\n3 updates found; 1 package held due to ideological conflict.'; + setTimeout(() => { + summary.textContent = '3 updates available; 1 eternal argument held back'; + showToast('Updates checked. Your computer is now 12% more aware of discourse.'); + }, 650); + }); + + $('#applyUpdates').addEventListener('click', () => { + log.textContent = 'Preparing upgrade...\nInstalling no-cursin-filter 1.5... OK\nInstalling lcos-base 0.1.1... OK\nRestarting meritocracy-daemon... OK\nHolding systemd-opinion-generator... obviously\n\nDone. Reboot strongly discouraged because this is a webpage.'; + summary.textContent = 'System is completely up to date, spiritually'; + showToast('Upgrade complete. Zero real packages were modified.'); + }); + } + + function initEthics() { + const input = $('#ethicsInput'); + const result = $('#ethicsResult'); + const forbidden = /\b(fuck|shit|cunt|bastard|damn|bloody hell)\b/i; + + $('#ethicsCheck').addEventListener('click', () => { + const value = input.value.trim(); + if (!value) { + result.textContent = 'Nothing entered. Ethics daemon awards points for restraint.'; + } else if (forbidden.test(value)) { + result.textContent = '⚠ CURSIN\' DETECTED. One virtual coin deposited in the kernel swear jar.'; + } else { + result.textContent = 'βœ“ Excellent. Meritocracy daemon reluctantly approves this sentence.'; + } + }); + + input.addEventListener('keydown', event => { + if (event.key === 'Enter') $('#ethicsCheck').click(); + }); + } + + appsButton.addEventListener('click', event => { + event.stopPropagation(); + toggleApplicationsMenu(); + }); + + document.addEventListener('click', event => { + if (!event.target.closest('#applicationsMenu') && !event.target.closest('#applicationsButton')) { + appsMenu.hidden = true; + appsButton.setAttribute('aria-expanded', 'false'); + } + }); + + $$('[data-open]').forEach(button => { + button.addEventListener('click', () => openWindow(button.dataset.open)); + }); + + $$('[data-action="panic"]').forEach(button => button.addEventListener('click', panicAboutSystemd)); + + $$('.window').forEach(win => { + makeDraggable(win); + win.addEventListener('pointerdown', () => focusWindow(win)); + $('[data-close]', win)?.addEventListener('click', () => closeWindow(win)); + $('[data-minimize]', win)?.addEventListener('click', () => minimizeWindow(win)); + $('[data-maximize]', win)?.addEventListener('click', () => toggleMaximize(win)); + }); + + $('#showDesktop').addEventListener('click', () => { + const visible = $$('.window').filter(win => !win.hidden); + if (visible.length) { + visible.forEach(minimizeWindow); + showToast('Desktop shown. Productivity has been minimized.'); + } else { + openWindow('aboutWindow'); + } + }); + + clock.addEventListener('click', () => showToast(`Current LCOS time: ${new Date().toLocaleString()}. Still no RTC driver drama.`)); + skipBoot.addEventListener('click', finishBoot); + + window.addEventListener('keydown', event => { + if (event.key === 'Escape') { + appsMenu.hidden = true; + appsButton.setAttribute('aria-expanded', 'false'); + } + }); + + initTerminal(); + initPackageManager(); + initEthics(); + runBoot(); +})(); From 30901a882a97eb14ecdf153d67c80014c3eff26b Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:10:32 +0930 Subject: [PATCH 06/20] Document LCOS Pages satire build --- README.md | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 92a8b02..3f9bf35 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,39 @@ -Satire Fork Designed to Visualize What LCOS Could Actually Look Like via Github Pages. +# LCOS β€” The Operating System We Absolutely Did Not Build -Real Fork >> BryanLunduke/LCOS We need to heavily mock these. -https://github.com/BryanLunduke/LCOS/issues -https://github.com/BryanLunduke/LCOS/pulls This is a total joke. We are not building a distro. We are just imagining. Search up on Brian Lunduke and his humor to make it funnier. +> **Satire fork / browser visualization. This is not a Linux distribution. There is no ISO. Please do not flash `index.html` to a USB stick.** + +This fork turns the idea of **The Lunduke Computer Operating System** into an interactive GitHub Pages desktop: part mock operating system, part Linux-community archaeology, part extremely unnecessary package-manager UI. + +## Live site + +**https://qsolkcb.github.io/LCOS/** + +If GitHub Pages has just been enabled, allow GitHub to publish the latest branch before assuming the kernel has panicked. + +## What is here + +- A ceremonial fake boot sequence with a `vibes-6.9.420-lcos` kernel. +- **LCDE**, the Lunduke Computer Desktop Environment, implemented as plain HTML/CSS/JavaScript. +- Draggable, minimizable and maximizable desktop windows. +- A fake terminal with commands including `neofetch`, `uname -a`, `apt update`, `systemctl`, `x11`, `wayland`, and `ethics`. +- A package manager whose native package format is naturally `.debate`. +- An Issue Control Center for visualizing the traditional Linux development process: three lines of code and forty-seven opinions. +- An Ethics Daemon based on the repository's existing `CodeOfEthics.md` rules. +- A screenshot gallery preserving the existing LCOS images in `screenshots/`. +- No frameworks, build step, package registry, analytics, telemetry, cookies, installers, kernels, init systems, or legitimate reasons for this to be as elaborate as it is. + +## Run locally + +Because the site is static, either open `index.html` directly or serve the directory: + +```bash +python3 -m http.server 8000 +``` + +Then visit `http://localhost:8000`. + +## Upstream + +The actual project this satire fork descends from is: + +- \ No newline at end of file From dc30c2bb7ae5c764f30d690e896c145bfc5133d7 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:10:49 +0930 Subject: [PATCH 07/20] Add GitHub Pages deployment workflow --- .github/workflows/pages.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/pages.yml diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..872ae97 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,37 @@ +name: Deploy LCOS to GitHub Pages + +on: + push: + branches: [master] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Configure Pages + uses: actions/configure-pages@v5 + + - name: Upload static site + uses: actions/upload-pages-artifact@v4 + with: + path: . + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 From ed64d96ca16aeefd872e6f184b815c450e2f890b Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:11:02 +0930 Subject: [PATCH 08/20] Validate LCOS static site before deploy --- .github/workflows/pages.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 872ae97..b5f9e37 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -24,6 +24,25 @@ jobs: - name: Checkout uses: actions/checkout@v6 + - name: Validate JavaScript syntax + run: node --check app.js + + - name: Validate static assets + shell: bash + run: | + set -euo pipefail + test -f index.html + test -f styles.css + test -f app.js + test -f screenshots/lcos-01-shot-boot.png + test -f screenshots/lcos-01-shot-refractainstaller.png + test -f screenshots/lcos-01-shot1.png + test -f screenshots/lcos-01-shot2.png + test -f screenshots/lcos-01-shot3.png + test -f screenshots/lcos-01-shot4.png + grep -q 'styles.css' index.html + grep -q 'app.js' index.html + - name: Configure Pages uses: actions/configure-pages@v5 From 44b52a261db2e846ba46c36fb0afa6e1e8cfe6c0 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:11:06 +0930 Subject: [PATCH 09/20] Disable Jekyll processing for static LCOS site --- .nojekyll | 1 + 1 file changed, 1 insertion(+) create mode 100644 .nojekyll diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..34ea123 --- /dev/null +++ b/.nojekyll @@ -0,0 +1 @@ +# Static LCOS Pages site; intentionally no Jekyll processing. From 5a413a0120eeb63fba04dd8a1cf32bd6ffaf02ae Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:11:34 +0930 Subject: [PATCH 10/20] Add LCOS static site CI --- .github/workflows/ci.yml | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ee4db01 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: LCOS Static Checks + +on: + pull_request: + push: + branches-ignore: [master] + workflow_dispatch: + +permissions: + contents: read + +jobs: + static-checks: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Validate JavaScript syntax + run: node --check app.js + + - name: Validate required files and references + shell: bash + run: | + set -euo pipefail + test -f index.html + test -f styles.css + test -f app.js + test -f README.md + test -f .nojekyll + for image in \ + screenshots/lcos-01-shot-boot.png \ + screenshots/lcos-01-shot-refractainstaller.png \ + screenshots/lcos-01-shot1.png \ + screenshots/lcos-01-shot2.png \ + screenshots/lcos-01-shot3.png \ + screenshots/lcos-01-shot4.png; do + test -f "$image" + grep -q "$image" index.html + done + grep -q 'href="styles.css"' index.html + grep -q 'src="app.js"' index.html + grep -q 'This site is satire' index.html From d6bdb990a7a888844906d4b32b7d50cf54507c64 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:11:58 +0930 Subject: [PATCH 11/20] Finish LCOS README upstream notes --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3f9bf35..1eb2072 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This fork turns the idea of **The Lunduke Computer Operating System** into an in **https://qsolkcb.github.io/LCOS/** -If GitHub Pages has just been enabled, allow GitHub to publish the latest branch before assuming the kernel has panicked. +If GitHub Pages has just been enabled, allow GitHub to publish the latest `master` build before assuming the kernel has panicked. ## What is here @@ -34,6 +34,4 @@ Then visit `http://localhost:8000`. ## Upstream -The actual project this satire fork descends from is: - -- \ No newline at end of file +The actual project this satire fork descends from is **Bryan \ No newline at end of file From b917034916adef35771c102e1284097d346eaed0 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:12:10 +0930 Subject: [PATCH 12/20] Finalize concise LCOS README --- README.md | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 1eb2072..55e5268 100644 --- a/README.md +++ b/README.md @@ -2,36 +2,30 @@ > **Satire fork / browser visualization. This is not a Linux distribution. There is no ISO. Please do not flash `index.html` to a USB stick.** -This fork turns the idea of **The Lunduke Computer Operating System** into an interactive GitHub Pages desktop: part mock operating system, part Linux-community archaeology, part extremely unnecessary package-manager UI. +LCOS is an interactive GitHub Pages mock desktop imagining what the Lunduke Computer Operating System could look like if a README, some screenshots, Linux discourse, and far too much confidence achieved sentience. ## Live site -**https://qsolkcb.github.io/LCOS/** +https://qsolkcb.github.io/LCOS/ -If GitHub Pages has just been enabled, allow GitHub to publish the latest `master` build before assuming the kernel has panicked. +## Included -## What is here - -- A ceremonial fake boot sequence with a `vibes-6.9.420-lcos` kernel. -- **LCDE**, the Lunduke Computer Desktop Environment, implemented as plain HTML/CSS/JavaScript. -- Draggable, minimizable and maximizable desktop windows. -- A fake terminal with commands including `neofetch`, `uname -a`, `apt update`, `systemctl`, `x11`, `wayland`, and `ethics`. -- A package manager whose native package format is naturally `.debate`. -- An Issue Control Center for visualizing the traditional Linux development process: three lines of code and forty-seven opinions. -- An Ethics Daemon based on the repository's existing `CodeOfEthics.md` rules. -- A screenshot gallery preserving the existing LCOS images in `screenshots/`. -- No frameworks, build step, package registry, analytics, telemetry, cookies, installers, kernels, init systems, or legitimate reasons for this to be as elaborate as it is. +- ceremonial fake boot sequence +- LCDE browser desktop with draggable, minimizable and maximizable windows +- fake terminal with `neofetch`, `uname -a`, `apt update`, `systemctl`, `x11`, `wayland`, `ethics`, and more +- `.debate` package manager +- parody Issue Control Center +- Ethics Daemon based on the existing `CodeOfEthics.md` +- gallery preserving all existing LCOS screenshots +- GitHub Pages deployment and static-site CI +- no frameworks, telemetry, installer, kernel, init system, or actual distro ## Run locally -Because the site is static, either open `index.html` directly or serve the directory: - ```bash python3 -m http.server 8000 ``` -Then visit `http://localhost:8000`. - -## Upstream +Then open `http://localhost:8000`. -The actual project this satire fork descends from is **Bryan \ No newline at end of file +## Upstream and satire note \ No newline at end of file From 71427b41c31ef9ad0a2ded5d29ff5c332a4c1da9 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:12:21 +0930 Subject: [PATCH 13/20] Finalize LCOS README --- README.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 55e5268..24b044e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # LCOS β€” The Operating System We Absolutely Did Not Build -> **Satire fork / browser visualization. This is not a Linux distribution. There is no ISO. Please do not flash `index.html` to a USB stick.** +> **Satire fork / browser visualization. This is not a Linux distribution. There is no ISO.** -LCOS is an interactive GitHub Pages mock desktop imagining what the Lunduke Computer Operating System could look like if a README, some screenshots, Linux discourse, and far too much confidence achieved sentience. +LCOS is an interactive GitHub Pages mock desktop imagining what the Lunduke Computer Operating System could look like if some screenshots, Linux discourse, and far too much confidence achieved sentience. ## Live site @@ -10,15 +10,14 @@ https://qsolkcb.github.io/LCOS/ ## Included -- ceremonial fake boot sequence -- LCDE browser desktop with draggable, minimizable and maximizable windows -- fake terminal with `neofetch`, `uname -a`, `apt update`, `systemctl`, `x11`, `wayland`, `ethics`, and more -- `.debate` package manager +- fake boot sequence and LCDE browser desktop +- draggable, minimizable and maximizable windows +- interactive terminal and `.debate` package manager - parody Issue Control Center -- Ethics Daemon based on the existing `CodeOfEthics.md` -- gallery preserving all existing LCOS screenshots +- Ethics Daemon based on `CodeOfEthics.md` +- gallery preserving the existing screenshots - GitHub Pages deployment and static-site CI -- no frameworks, telemetry, installer, kernel, init system, or actual distro +- absolutely no actual distro ## Run locally @@ -26,6 +25,4 @@ https://qsolkcb.github.io/LCOS/ python3 -m http.server 8000 ``` -Then open `http://localhost:8000`. - -## Upstream and satire note \ No newline at end of file +This repository is a satire fork of BryanL \ No newline at end of file From 2c52616d2c16a26e6d2bbc9a77c5dd40c8fe7779 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:12:31 +0930 Subject: [PATCH 14/20] Remove truncated README footer --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 24b044e..c0032ec 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > **Satire fork / browser visualization. This is not a Linux distribution. There is no ISO.** -LCOS is an interactive GitHub Pages mock desktop imagining what the Lunduke Computer Operating System could look like if some screenshots, Linux discourse, and far too much confidence achieved sentience. +LCOS is an interactive GitHub Pages mock desktop imagining what the Lunduke Computer Operating System could look like if screenshots, Linux discourse, and far too much confidence achieved sentience. ## Live site @@ -25,4 +25,4 @@ https://qsolkcb.github.io/LCOS/ python3 -m http.server 8000 ``` -This repository is a satire fork of BryanL \ No newline at end of file +**This repository and website are satire.** \ No newline at end of file From 3ad92a89c86b85a8a5ed5f76b7f1c14accb4a1f0 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:31:08 +0930 Subject: [PATCH 15/20] Make Pages follow the default branch --- .github/workflows/pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index b5f9e37..19e13df 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -2,7 +2,6 @@ name: Deploy LCOS to GitHub Pages on: push: - branches: [master] workflow_dispatch: permissions: @@ -16,6 +15,7 @@ concurrency: jobs: deploy: + if: github.event_name == 'workflow_dispatch' || github.ref == format('refs/heads/{0}', github.event.repository.default_branch) environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} From 9ffae5347bfe47859a012ef4fdaf815fc5e4482a Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:31:42 +0930 Subject: [PATCH 16/20] Fix LCOS interaction and accessibility edge cases --- app.js | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/app.js b/app.js index 99f0668..790262a 100644 --- a/app.js +++ b/app.js @@ -16,6 +16,7 @@ let zCounter = 500; let toastTimer; + let updateCheckTimer; let bootFinished = false; const bootLines = [ @@ -114,6 +115,14 @@ syncTaskButtons(); } + function focusOpenedWindow(win) { + if (!win.hasAttribute('tabindex')) win.tabIndex = -1; + const target = win.id === 'terminalWindow' + ? $('#terminalInput', win) + : $('.window-body input, .window-body button, .window-body a[href]', win) || win; + setTimeout(() => target?.focus(), 0); + } + function openWindow(id) { const win = document.getElementById(id); if (!win) return; @@ -122,10 +131,7 @@ focusWindow(win); appsMenu.hidden = true; appsButton.setAttribute('aria-expanded', 'false'); - - if (id === 'terminalWindow') { - setTimeout(() => $('#terminalInput')?.focus(), 0); - } + focusOpenedWindow(win); } function closeWindow(win) { @@ -308,15 +314,19 @@ const summary = $('#updateSummary'); $('#checkUpdates').addEventListener('click', () => { + clearTimeout(updateCheckTimer); summary.textContent = 'Checking mirrors and prevailing sentiment…'; log.textContent = 'Contacting mirror.invalid...\nReading package lists...\nCross-referencing comments...\nIgnoring one guy who suggested Electron...\n\n3 updates found; 1 package held due to ideological conflict.'; - setTimeout(() => { + updateCheckTimer = setTimeout(() => { + updateCheckTimer = null; summary.textContent = '3 updates available; 1 eternal argument held back'; showToast('Updates checked. Your computer is now 12% more aware of discourse.'); }, 650); }); $('#applyUpdates').addEventListener('click', () => { + clearTimeout(updateCheckTimer); + updateCheckTimer = null; log.textContent = 'Preparing upgrade...\nInstalling no-cursin-filter 1.5... OK\nInstalling lcos-base 0.1.1... OK\nRestarting meritocracy-daemon... OK\nHolding systemd-opinion-generator... obviously\n\nDone. Reboot strongly discouraged because this is a webpage.'; summary.textContent = 'System is completely up to date, spiritually'; showToast('Upgrade complete. Zero real packages were modified.'); @@ -365,9 +375,18 @@ $$('.window').forEach(win => { makeDraggable(win); win.addEventListener('pointerdown', () => focusWindow(win)); - $('[data-close]', win)?.addEventListener('click', () => closeWindow(win)); - $('[data-minimize]', win)?.addEventListener('click', () => minimizeWindow(win)); - $('[data-maximize]', win)?.addEventListener('click', () => toggleMaximize(win)); + + const closeButton = $('[data-close]', win); + const minimizeButton = $('[data-minimize]', win); + const maximizeButton = $('[data-maximize]', win); + + closeButton?.setAttribute('aria-label', 'Close'); + minimizeButton?.setAttribute('aria-label', 'Minimize'); + maximizeButton?.setAttribute('aria-label', 'Maximize'); + + closeButton?.addEventListener('click', () => closeWindow(win)); + minimizeButton?.addEventListener('click', () => minimizeWindow(win)); + maximizeButton?.addEventListener('click', () => toggleMaximize(win)); }); $('#showDesktop').addEventListener('click', () => { From 78e1e088fde64ad69a49b5398ac0b8a4d4a93ae0 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:32:19 +0930 Subject: [PATCH 17/20] Allow LCOS windows to fit narrow screens --- styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles.css b/styles.css index 660e65d..2949ce3 100644 --- a/styles.css +++ b/styles.css @@ -196,7 +196,7 @@ button.primary:hover { background: #252421; } .panel-title, .panel-status > span, .taskbar-joke { display: none; } .panel-status { margin-left: auto; } .desktop-icons { grid-template-columns: repeat(2, 82px); } - .window { left: 8px !important; top: 50px !important; width: calc(100vw - 16px) !important; height: calc(100vh - 108px) !important; resize: none; } + .window { left: 8px !important; top: 50px !important; width: calc(100vw - 16px) !important; height: calc(100vh - 108px) !important; min-width: 0; resize: none; } .spec-grid, .issue-columns, .gallery-grid { grid-template-columns: 1fr; } .hero-card { grid-template-columns: 80px 1fr; } .hero-logo { width: 76px; height: 76px; font-size: 24px; } From 985ae31e7783afad7a31b7deed60cc74bfb41f79 Mon Sep 17 00:00:00 2001 From: Trent Slade <73952179+EmergentMonk@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:33:12 +0930 Subject: [PATCH 18/20] Label all LCOS window controls --- index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 2b8eb52..22f6c49 100644 --- a/index.html +++ b/index.html @@ -112,7 +112,7 @@

The Lunduke Computer Operating System*