dvorakmortonxd.dev/src/app/skeuo.css

1635 lines
35 KiB
CSS

/* ============================================================
SKEUOMORPHIC THEME
------------------------------------------------------------
Desktop -> KDE Plasma (Breeze)
Active when <html data-theme="skeuo">. The web editorial
site is the default; this is the alternate, reachable from
the editorial page's Desktop-mode button or the tray.
============================================================ */
html[data-theme="skeuo"] {
--bg: #1b1e20;
--white: #31363b;
--gray: #5c6167;
--accent: #3daee9;
--accent2: #2980b9;
--green: #27ae60;
--blue: #3daee9;
--purple: #9b59b6;
--fg: #31363b;
--font-custom-mono: "Noto Sans", "Segoe UI", Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif;
}
html[data-theme="skeuo"] body {
overflow: hidden;
background: #1b1e20;
color: var(--fg);
font-family: var(--font-custom-mono);
}
/* The desktop root and its visibility are decided in JS (ThemeRoot); phones
never mount it, and the CSS `.desktop-toggle` rule hides the entry button. */
/* ============================================================
DESKTOP (Plasma)
============================================================ */
.win-desktop {
position: fixed;
inset: 0;
overflow: hidden;
background-color: #1b1e20;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
color: #eff0f1;
user-select: none;
}
.win-wallpaper-tint {
position: absolute;
inset: 0;
pointer-events: none;
background: linear-gradient(
to bottom,
rgba(0, 0, 0, 0.3),
rgba(0, 0, 0, 0) 22%,
rgba(0, 0, 0, 0) 70%,
rgba(0, 0, 0, 0.35)
);
}
/* Desktop icons (Folder View) */
.win-icons {
position: absolute;
top: 12px;
left: 10px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: flex-start;
gap: 4px;
max-height: calc(100% - 68px);
}
.win-icon {
width: 92px;
padding: 6px 4px 9px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
border: 1px solid transparent;
border-radius: 4px;
background: transparent;
color: #ffffff;
cursor: default;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95);
transition: background-color 0.12s ease, border-color 0.12s ease;
/* Icons are dragged by our own pointer handlers. Without this, the browser's
native image/link drag hijacks the gesture (it fires pointercancel), which
broke dragging for icons whose glyph is an <img> - the friend shortcuts. */
-webkit-user-drag: none;
user-select: none;
}
.win-icon img,
.win-icon-glyph img,
.win-icon-label {
-webkit-user-drag: none;
user-drag: none;
pointer-events: none;
}
.win-icon:hover,
.win-icon.selected {
background: rgba(61, 174, 233, 0.16);
border-color: rgba(61, 174, 233, 0.4);
}
.win-icon.dragging {
opacity: 0.55;
border-color: rgba(61, 174, 233, 0.8);
}
.win-icon-glyph {
width: 48px;
height: 48px;
display: grid;
place-items: center;
font-size: 40px;
line-height: 1;
background: transparent !important;
border: none;
box-shadow: none;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.75));
}
.win-icon-label {
font-size: 0.72rem;
line-height: 1.2;
text-align: center;
}
a.win-icon {
text-decoration: none;
}
.win-icons-tr {
top: 12px;
right: 10px;
left: auto;
align-items: flex-end;
/* Wrap into extra columns on short screens so the service shortcuts never
collide with the friends stack anchored to the bottom-right. */
flex-wrap: wrap;
align-content: flex-start;
max-height: calc(100% - 350px);
}
.win-icons-br {
top: auto;
bottom: 62px;
right: 10px;
left: auto;
align-items: flex-end;
flex-wrap: nowrap;
max-height: none;
}
.win-icon-img {
width: 38px;
height: 38px;
object-fit: contain;
filter: brightness(0) invert(1);
opacity: 0.92;
}
/* Cramped desktops: shrink the icons so the grid always has a cell for every
icon (so they can never collide) and the launcher stacks stay on screen. The
grid is measured from the rendered icons, so it adapts automatically. */
@media (max-width: 900px), (max-height: 600px) {
.win-icon {
width: 80px;
padding: 5px 4px 7px;
gap: 6px;
}
.win-icon-glyph {
width: 40px;
height: 40px;
font-size: 32px;
}
.win-icon-label {
font-size: 0.68rem;
}
.win-icon-img {
width: 32px;
height: 32px;
}
}
@media (max-width: 720px), (max-height: 440px) {
.win-icon {
width: 66px;
padding: 4px 3px 5px;
gap: 4px;
}
.win-icon-glyph {
width: 32px;
height: 32px;
font-size: 26px;
}
.win-icon-label {
font-size: 0.6rem;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.win-icon-img {
width: 26px;
height: 26px;
}
}
@media (max-height: 380px) {
.win-icon {
width: 56px;
padding: 3px 3px 4px;
gap: 3px;
}
.win-icon-glyph {
width: 28px;
height: 28px;
font-size: 22px;
}
.win-icon-label {
font-size: 0.54rem;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.win-icon-img {
width: 22px;
height: 22px;
}
}
/* The three default stacks are laid out once so the grid columns can be read
off them. They stay in the DOM (keeping the same metrics) but must never be
seen or clicked - the visible icons all come from .win-icon-layer. */
.win-icons.win-measure {
visibility: hidden;
pointer-events: none;
z-index: 0;
}
/* Icon grid layer: every icon is absolutely positioned on the grid. The layer
itself is click-through so empty-desktop clicks still reach the desktop
(closing the launcher / clearing the selection). */
.win-icon-layer {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 1;
}
.win-icon-layer .win-icon {
position: absolute;
pointer-events: auto;
}
/* Translucent copy of the icon that follows the cursor while dragging. */
.win-icon-ghost {
position: fixed;
z-index: 9999;
margin: 0;
pointer-events: none;
cursor: grabbing;
transform-origin: top left;
opacity: 0.9;
border-color: rgba(61, 174, 233, 0.9) !important;
background: rgba(61, 174, 233, 0.22) !important;
box-shadow: 0 12px 26px rgba(0, 0, 0, 0.55);
filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.45));
will-change: transform;
}
/* Window layer */
.win-layer {
position: absolute;
inset: 0;
pointer-events: none;
}
.win-layer .win-window {
pointer-events: auto;
}
/* ============================================================
BREEZE WINDOWS
============================================================ */
.win-window {
position: absolute;
display: flex;
flex-direction: column;
min-width: 260px;
min-height: 150px;
border-radius: 8px;
background: #232629;
border: 1px solid #17191c;
box-shadow: 0 10px 32px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.04);
overflow: hidden;
user-select: text;
animation: winOpen 0.16s ease-out;
}
.win-window.active {
border-color: #3a444d;
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.66), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.win-window.minimized {
display: none;
}
.win-window.maximized {
border-radius: 0;
/* 54px panel top + 5px gap, so maximized windows also stop above the panel. */
height: calc(100% - 59px) !important;
}
.win-window.centered {
left: 0;
right: 0;
top: 0;
bottom: 59px;
margin: auto;
/* Never let a centred window (e.g. Welcome) overflow a small viewport. */
max-width: calc(100vw - 20px);
max-height: calc(100vh - 79px);
}
/* On very short viewports the default min-height would win over max-height and
push the window off-screen; let it shrink further so it still fits. */
@media (max-height: 320px) {
.win-window {
min-height: 110px;
}
}
.win-window.closing {
animation: winClose 0.14s ease-in forwards;
pointer-events: none;
}
.win-window.minimizing {
animation: winClose 0.14s ease-in forwards;
pointer-events: none;
}
/* Resize handles */
.win-resize-layer {
position: absolute;
inset: 0;
pointer-events: none;
}
.win-resize {
position: absolute;
pointer-events: auto;
z-index: 6;
}
.win-resize-n {
top: 0;
left: 8px;
right: 8px;
height: 5px;
cursor: ns-resize;
}
.win-resize-s {
bottom: 0;
left: 8px;
right: 8px;
height: 5px;
cursor: ns-resize;
}
.win-resize-e {
right: 0;
top: 8px;
bottom: 8px;
width: 5px;
cursor: ew-resize;
}
.win-resize-w {
left: 0;
top: 8px;
bottom: 8px;
width: 5px;
cursor: ew-resize;
}
.win-resize-ne {
top: 0;
right: 0;
width: 12px;
height: 12px;
cursor: nesw-resize;
}
.win-resize-nw {
top: 0;
left: 0;
width: 12px;
height: 12px;
cursor: nwse-resize;
}
.win-resize-se {
bottom: 0;
right: 0;
width: 14px;
height: 14px;
cursor: nwse-resize;
}
.win-resize-sw {
bottom: 0;
left: 0;
width: 12px;
height: 12px;
cursor: nesw-resize;
}
@keyframes winOpen {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes winClose {
from {
opacity: 1;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(0.95);
}
}
.win-titlebar {
position: relative;
flex: 0 0 30px;
height: 30px;
display: flex;
align-items: center;
padding: 0 8px;
cursor: default;
touch-action: none;
user-select: none;
-webkit-user-select: none;
background: #26292e;
border-bottom: 1px solid #1a1d20;
}
.win-window.active .win-titlebar {
background: #2d3540;
border-bottom-color: rgba(61, 174, 233, 0.5);
}
.win-titlebar-text {
position: absolute;
left: 50%;
transform: translateX(-50%);
max-width: calc(100% - 110px);
font-size: 0.79rem;
font-weight: 600;
color: #eff0f1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.win-controls {
position: absolute;
right: 5px;
top: 0;
height: 30px;
display: flex;
align-items: center;
gap: 1px;
}
.win-ctl {
position: relative;
width: 24px;
height: 22px;
padding: 0;
border: none;
border-radius: 4px;
background: transparent;
color: #d3dae3;
cursor: default;
}
.win-ctl:hover {
background: rgba(255, 255, 255, 0.16);
}
.win-ctl-min::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 1.5px;
border-radius: 1px;
background: currentColor;
transform: translate(-50%, -50%);
}
.win-ctl-max::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 9px;
height: 9px;
border: 1.5px solid currentColor;
border-radius: 1px;
transform: translate(-50%, -50%);
}
.win-ctl-close::before,
.win-ctl-close::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 1.5px;
border-radius: 1px;
background: currentColor;
}
.win-ctl-close::before {
transform: translate(-50%, -50%) rotate(45deg);
}
.win-ctl-close::after {
transform: translate(-50%, -50%) rotate(-45deg);
}
.win-ctl-www {
width: 36px;
font-size: 0.6rem;
font-weight: 700;
letter-spacing: 0.02em;
color: #9fd0f5;
cursor: pointer;
}
.win-ctl-www:hover {
background: rgba(61, 174, 233, 0.3);
}
.win-body {
flex: 1;
overflow: auto;
background: #232629;
}
/* ============================================================
APP CONTENT SURFACE (shared by desktop windows + mobile apps)
============================================================ */
.app-surface {
--white: #0e3355;
--gray: #4a6480;
--accent: #0d5aa7;
--accent2: #0a7cc1;
--accent3: #1f78c9;
--green: #157347;
--aqua: #0f7d8a;
--blue: #1257a0;
--purple: #6a4fb3;
--red: #c0392b;
--darkpink: #b3005f;
--fg: #10263a;
color: #10263a;
}
.app-pad {
padding: 16px;
}
.app-surface .tui-panel,
.app-surface .hero-panel,
.app-surface .subsection-panel {
background: transparent !important;
border: none;
border-radius: 0;
box-shadow: none;
padding: 0;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
.app-surface .tui-panel-label,
.app-surface .hero-panel-label,
.app-surface .subsection-panel-label {
display: none;
}
.app-surface .social-button {
margin: 3px 4px;
border: 1px solid rgba(0, 0, 0, 0.16);
border-radius: 4px;
background: linear-gradient(to bottom, #ffffff, #e9eef5);
color: #123a5e;
box-shadow: inset 0 1px 0 #ffffff, 0 1px 2px rgba(0, 0, 0, 0.12);
}
.app-surface .social-button::before {
content: none;
}
.app-surface .social-button:hover {
background: linear-gradient(to bottom, #eaf5ff, #b9d7f3);
border-color: #7db9e8;
color: #062b4d;
box-shadow: 0 0 0 1px #7db9e8, 0 0 10px rgba(95, 175, 255, 0.55);
}
.app-surface .social-icon {
opacity: 0.9;
filter: drop-shadow(0 0 0.5px rgba(0, 0, 0, 0.55));
}
.app-surface .mail-contact {
color: #33475c;
}
.app-surface .mail-contact a {
color: var(--accent2);
}
.app-surface .service-button {
margin: 3px;
border: 1px solid rgba(0, 0, 0, 0.16);
border-radius: 5px;
background: linear-gradient(to bottom, #ffffff, #eef2f8);
color: #123a5e;
box-shadow: inset 0 1px 0 #ffffff, 0 1px 3px rgba(0, 0, 0, 0.12);
}
.app-surface .service-button::before {
content: none;
}
/* Emoji glyphs get a square drop-shadow, so the status glow is drawn with the
status dot behind the icon instead of a filter on the glyph. */
.app-surface .service-button:not(.friend) .service-icon {
filter: none;
}
.app-surface .service-button:not(.friend) .service-status-dot {
width: 34px;
height: 34px;
background: radial-gradient(circle, var(--status-glow) 0%, rgba(0, 0, 0, 0) 70%);
filter: blur(1px);
}
.app-surface .service-button:hover {
background: linear-gradient(to bottom, #f2f9ff, #cfe4f8);
border-color: #7db9e8;
box-shadow: 0 0 0 1px #7db9e8, 0 0 12px rgba(95, 175, 255, 0.5);
transform: translateY(-2px);
}
.app-surface .service-name {
color: #0e3355;
}
.app-surface .service-desc {
color: #4a6480;
}
.app-surface .service-button:hover .service-desc {
color: #1d3e5c;
}
/* External website "apps" opened from a shortcut icon */
.website-app {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.website-app-icon {
display: grid;
place-items: center;
width: 96px;
height: 96px;
margin-bottom: 8px;
border-radius: 22px;
background: linear-gradient(to bottom, #ffffff, #eef2f8);
border: 1px solid rgba(0, 0, 0, 0.15);
box-shadow: inset 0 1px 0 #ffffff, 0 2px 6px rgba(0, 0, 0, 0.12);
}
.website-app-emoji {
font-size: 3rem;
line-height: 1;
}
.website-app-img {
width: 84px;
height: 84px;
object-fit: contain;
filter: brightness(0);
}
.website-app-link {
margin-top: 14px;
padding: 8px 16px;
border-radius: 6px;
background: linear-gradient(to bottom, #ffffff, #dfeaf6);
border: 1px solid #7db9e8;
color: #0d5aa7;
font-family: var(--font-custom-mono), "JetBrains Mono", monospace;
font-size: 0.8rem;
text-decoration: none;
}
.website-app-link:hover {
box-shadow: 0 0 0 1px #7db9e8, 0 0 12px rgba(95, 175, 255, 0.5);
}
/* Live service sites rendered inside the window. The site fills the window
body edge-to-edge, so the iframe owns all the scrolling. */
.website-embed {
position: relative;
width: 100%;
height: 100%;
min-height: 0;
background: #ffffff;
}
.website-embed-frame {
display: block;
width: 100%;
height: 100%;
border: 0;
background: #ffffff;
}
/* While the window is dragged/resized, disown the iframe's pointer so the
gesture isn't swallowed when the cursor passes over the embedded site. */
.win-window.interacting .website-embed-frame {
pointer-events: none;
}
/* Navidrome/Forgejo are full SPAs, so the frame is blank for a moment while
they boot — cover it with a spinner until the iframe reports load. */
.website-embed-loading {
position: absolute;
inset: 0;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
background: #232629;
color: #9fd0f5;
font-size: 0.9rem;
}
.website-embed-spinner {
width: 26px;
height: 26px;
border-radius: 50%;
border: 3px solid rgba(159, 208, 245, 0.25);
border-top-color: #3daee9;
animation: website-embed-spin 0.8s linear infinite;
}
@keyframes website-embed-spin {
to {
transform: rotate(360deg);
}
}
/* ============================================================
MINECRAFT SMP JOIN MENU (opened from the SMP service shortcut)
============================================================ */
.smp {
display: flex;
flex-direction: column;
justify-content: center;
gap: 14px;
/* Fill the window body so the menu centres instead of leaving a gap under it;
a short window scrolls via .win-body's overflow. */
min-height: 100%;
font-family: "Monocraft", "JetBrains Mono", monospace;
color: #e6e6e6;
background-color: #313131;
background-image:
linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
background-size: 16px 16px;
}
.smp-header {
text-align: center;
}
.smp-title {
margin: 0;
font-size: 1.4rem;
color: #ffffff;
text-shadow: 2px 2px 0 #1d1d1d;
}
.smp-subtitle {
margin: 6px 0 0;
font-size: 0.8rem;
color: #a8a8a8;
}
.smp-server {
display: flex;
align-items: center;
gap: 12px;
padding: 8px 10px;
background: rgba(0, 0, 0, 0.4);
border: 2px solid #000000;
box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.08);
}
.smp-server-offline {
opacity: 0.85;
}
.smp-server-icon {
flex-shrink: 0;
width: 48px;
height: 48px;
display: grid;
place-items: center;
overflow: hidden;
background: #111111;
border: 2px solid #000000;
image-rendering: pixelated;
}
.smp-server-icon img {
width: 100%;
height: 100%;
image-rendering: pixelated;
}
.smp-server-icon-fallback {
font-size: 1.6rem;
}
.smp-server-info {
flex: 1;
min-width: 0;
}
.smp-server-name {
color: #ffffff;
font-weight: 700;
text-shadow: 2px 2px 0 #1d1d1d;
}
.smp-server-motd {
margin-top: 3px;
font-size: 0.76rem;
color: #a8a8a8;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.smp-server-addr {
margin-top: 4px;
font-size: 0.7rem;
color: #7a7a7a;
}
.smp-server-meta {
flex-shrink: 0;
text-align: right;
}
.smp-server-players {
font-size: 0.85rem;
color: #ffffff;
}
.smp-ping {
display: flex;
align-items: flex-end;
justify-content: flex-end;
gap: 2px;
height: 16px;
margin-top: 5px;
}
.smp-ping span {
width: 3px;
background: #4a4a4a;
}
.smp-ping-on span {
background: #4ade80;
}
.smp-actions {
display: flex;
gap: 10px;
}
.smp .smp-btn {
flex: 1;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 10px 14px;
font-family: inherit;
font-size: 0.82rem;
color: #ffffff;
text-decoration: none;
text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.55);
background: #6c6c6c;
border: 2px solid;
border-color: #a6a6a6 #2e2e2e #2e2e2e #a6a6a6;
cursor: pointer;
}
.smp .smp-btn:hover {
background: #7d7d7d;
}
.smp .smp-btn:active {
border-color: #2e2e2e #a6a6a6 #a6a6a6 #2e2e2e;
}
.smp .smp-btn-green {
background: #3f8f3f;
border-color: #74d174 #1f4f1f #1f4f1f #74d174;
}
.smp .smp-btn-green:hover {
background: #4aa34a;
}
.smp-hint {
margin: 0;
font-size: 0.7rem;
line-height: 1.5;
text-align: center;
color: #9a9a9a;
}
.app-surface .project-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 12px;
}
.app-surface .project-card {
padding: 10px;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 6px;
background: linear-gradient(to bottom, #ffffff, #f0f4fa);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14);
}
.app-surface .project-card:hover {
border-color: #7db9e8;
background: #ffffff;
box-shadow: 0 0 0 1px #7db9e8, 0 0 14px rgba(110, 185, 255, 0.5),
0 8px 18px rgba(0, 25, 55, 0.2);
}
.app-surface .project-image {
height: 150px;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.12);
}
.app-surface .project-title {
color: #0e3355;
}
.app-surface .project-card:hover .project-title {
color: #0d5aa7;
}
.app-surface .project-desc {
color: #43607c;
}
.app-surface .project-card:hover .project-desc {
color: #1d3e5c;
}
.app-surface .gym-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
padding: 8px 0;
}
.app-surface .gym-item {
padding: 14px 10px;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 6px;
background: linear-gradient(to bottom, #ffffff, #eef2f8);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}
.app-surface .gym-label {
color: #4a6480;
}
.app-surface .gym-weight {
color: #0e3355;
}
.app-surface .gym-date {
margin-top: 2px;
font-size: 0.65rem;
color: #6b8299;
}
.app-surface .heatmap-container {
border-color: rgba(90, 150, 205, 0.6);
border-radius: 5px;
background: rgba(255, 255, 255, 0.6);
}
.app-surface .heatmap-cell,
.app-surface .heatmap-legend-cell {
border-radius: 2px;
background-color: rgba(80, 120, 160, 0.18);
}
.app-surface .heatmap-cell[data-level="1"],
.app-surface .heatmap-legend-cell[data-level="1"] { background-color: rgba(60, 150, 230, 0.35); }
.app-surface .heatmap-cell[data-level="2"],
.app-surface .heatmap-legend-cell[data-level="2"] { background-color: rgba(45, 130, 215, 0.6); }
.app-surface .heatmap-cell[data-level="3"],
.app-surface .heatmap-legend-cell[data-level="3"] { background-color: rgba(30, 110, 195, 0.85); }
.app-surface .heatmap-cell[data-level="4"],
.app-surface .heatmap-legend-cell[data-level="4"] { background-color: #0d5aa7; }
.app-surface .heatmap-cell:hover {
box-shadow: 0 0 6px rgba(90, 170, 255, 0.9);
}
.app-surface .contribution-command,
.app-surface .contribution-entry,
.app-surface .contribution-total-title,
.app-surface .contribution-message {
color: #10263a;
}
.app-surface .contribution-date {
color: #157347;
}
.app-surface .about-content {
padding: 0;
color: #10263a;
}
.app-surface .about-content > div {
color: #2f465e !important;
}
.app-surface .app-cmd {
color: #33475c;
margin-bottom: 10px;
}
.app-surface .app-user {
color: #157347;
}
.app-surface .app-path {
color: #1257a0;
}
.app-surface .app-text {
color: #2f465e;
line-height: 1.65;
}
.app-surface a {
color: #0a6bb0;
}
.app-inline-link {
padding: 0;
border: none;
background: none;
color: var(--accent);
font: inherit;
text-decoration: underline;
cursor: pointer;
}
.app-inline-link:hover {
color: var(--accent2);
}
.app-preference {
margin-top: 14px;
font-size: 0.95rem;
font-weight: 600;
color: var(--fg);
}
.app-preference .app-inline-link {
font-weight: 700;
}
.app-surface .app-center {
text-align: center;
}
.app-surface .app-h1 {
font-size: 2rem;
font-weight: 700;
color: #0e3355;
margin-bottom: 8px;
}
.app-surface .app-h2 {
font-size: 1.3rem;
font-weight: 600;
color: #0e3355;
margin: 14px 0 8px;
}
.app-surface .app-shot {
border-radius: 8px;
overflow: hidden;
border: 1px solid rgba(0, 0, 0, 0.2);
margin: 12px 0;
}
.app-surface .app-shot-glow {
box-shadow: 0 0 26px rgba(120, 190, 255, 0.35);
}
.app-surface .app-shot-light {
box-shadow: 0 0 26px rgba(0, 0, 0, 0.22);
}
.app-surface .app-list {
margin: 10px 0 10px 20px;
line-height: 1.8;
color: #2f465e;
list-style: "▸ ";
}
.app-surface .app-muted {
color: #5c7290;
}
.app-surface .app-fineprint {
font-size: 0.78rem;
margin-top: 14px;
}
.app-surface .app-welcome-head {
display: flex;
gap: 14px;
align-items: center;
margin-bottom: 12px;
}
.app-surface .app-welcome-head img {
width: 52px;
height: 52px;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.15);
}
.app-surface .app-welcome-head h2 {
font-size: 1.25rem;
color: #0e3355;
}
.app-surface .friends-extra {
margin-top: 16px;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.app-surface .friends-extra h3 {
color: #0d5aa7;
font-size: 1.2rem;
}
.app-surface .app-linkrow {
display: flex;
gap: 12px;
flex-wrap: wrap;
justify-content: center;
}
.app-surface .app-linkrow a {
padding: 6px 16px;
border-radius: 6px;
border: 1px solid rgba(0, 0, 0, 0.2);
background: linear-gradient(to bottom, #ffffff, #eef2f8);
color: #0e3355;
text-decoration: none;
}
/* Dark app content inside Breeze Dark windows */
.win-window .app-surface {
--white: #eff0f1;
--gray: #9aa0a6;
--accent: #3daee9;
--accent2: #3daee9;
--accent3: #3daee9;
--green: #27ae60;
--aqua: #16a085;
--blue: #3daee9;
--purple: #9b59b6;
--red: #da4453;
--darkpink: #e84393;
--fg: #eff0f1;
color: #eff0f1;
}
.win-body .about-content,
.win-body .about-content > div {
color: #c7cdd3 !important;
}
.win-body .app-cmd {
color: #b0b6bc;
}
.win-body .app-text {
color: #c7cdd3;
}
.win-body .app-list {
color: #c7cdd3;
}
.win-body .app-user {
color: #2ecc71;
}
.win-body .app-path {
color: #3daee9;
}
.win-body .app-muted {
color: #9aa0a6;
}
.win-body .app-h1,
.win-body .app-h2,
.win-body .app-welcome-head h2 {
color: #eff0f1;
}
.win-body a {
color: #3daee9;
}
.win-body .mail-contact {
color: #c7cdd3;
}
.win-body .mail-contact a {
color: #3daee9;
}
.win-body .app-welcome-head img {
border-color: #1b1e20;
}
.win-body .social-button {
border-color: #1b1e20;
background: linear-gradient(to bottom, #3b4147, #31363b);
color: #eff0f1;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.4);
}
.win-body .social-button:hover {
border-color: #3daee9;
background: linear-gradient(to bottom, #2c6e93, #234f68);
color: #ffffff;
box-shadow: 0 0 0 1px #3daee9, 0 0 10px rgba(61, 174, 233, 0.5);
}
.win-body .social-icon {
filter: none;
opacity: 0.95;
}
.win-body .service-button {
border-color: #1b1e20;
background: linear-gradient(to bottom, #3b4147, #31363b);
color: #eff0f1;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 3px rgba(0, 0, 0, 0.4);
}
.win-body .service-button:hover {
border-color: #3daee9;
background: linear-gradient(to bottom, #2c6e93, #234f68);
box-shadow: 0 0 0 1px #3daee9, 0 0 12px rgba(61, 174, 233, 0.5);
}
.win-body .service-name {
color: #eff0f1;
}
.win-body .service-desc {
color: #9aa0a6;
}
.win-body .service-button:hover .service-desc {
color: #d3dae3;
}
.win-body .friend-icon {
filter: invert(1) brightness(1.5);
}
.win-body .project-card {
border-color: #1b1e20;
background: linear-gradient(to bottom, #31363b, #2a2e32);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.win-body .project-card:hover {
border-color: #3daee9;
background: #353b40;
box-shadow: 0 0 0 1px #3daee9, 0 0 14px rgba(61, 174, 233, 0.45);
}
.win-body .project-image {
border-color: #1b1e20;
}
.win-body .project-title {
color: #eff0f1;
}
.win-body .project-card:hover .project-title {
color: #3daee9;
}
.win-body .project-desc {
color: #b0b6bc;
}
.win-body .project-card:hover .project-desc {
color: #d3dae3;
}
.win-body .gym-item {
border-color: #1b1e20;
background: linear-gradient(to bottom, #31363b, #2a2e32);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.win-body .gym-label,
.win-body .gym-date {
color: #9aa0a6;
}
.win-body .gym-weight {
color: #eff0f1;
}
.win-body .heatmap-container {
border-color: #3daee9;
background: rgba(255, 255, 255, 0.04);
}
.win-body .heatmap-cell,
.win-body .heatmap-legend-cell {
background-color: #31363b;
}
.win-body .heatmap-cell[data-level="1"],
.win-body .heatmap-legend-cell[data-level="1"] { background-color: rgba(61, 174, 233, 0.35); }
.win-body .heatmap-cell[data-level="2"],
.win-body .heatmap-legend-cell[data-level="2"] { background-color: rgba(61, 174, 233, 0.6); }
.win-body .heatmap-cell[data-level="3"],
.win-body .heatmap-legend-cell[data-level="3"] { background-color: rgba(61, 174, 233, 0.85); }
.win-body .heatmap-cell[data-level="4"],
.win-body .heatmap-legend-cell[data-level="4"] { background-color: #3daee9; }
.win-body .heatmap-cell:hover {
box-shadow: 0 0 6px #3daee9;
}
.win-body .contribution-command,
.win-body .contribution-entry,
.win-body .contribution-total-title,
.win-body .contribution-message {
color: #eff0f1;
}
.win-body .contribution-date {
color: #27ae60;
}
.win-body .app-shot {
border-color: #1b1e20;
}
.win-body .app-linkrow a {
border-color: #1b1e20;
background: linear-gradient(to bottom, #3b4147, #31363b);
color: #eff0f1;
}
.win-body .friends-extra h3 {
color: #3daee9;
}
/* Alacritty easter egg */
.alacritty {
min-height: 100%;
box-sizing: border-box;
background: #1d1f21;
color: #c5c8c6;
font-family: "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo,
Consolas, monospace;
padding: 16px;
overflow: auto;
}
.alacritty-line {
margin-bottom: 12px;
font-size: 0.85rem;
}
.alacritty-prompt { color: #b8bb26; }
.alacritty-path { color: #83a598; }
.alacritty-cmd { color: #ebdbb2; }
.alacritty-out-text { color: #c5c8c6; white-space: pre-wrap; }
.alacritty-inputline {
display: flex;
align-items: center;
margin-bottom: 0;
}
.alacritty-input {
flex: 1;
min-width: 0;
padding: 0;
border: none;
outline: none;
background: transparent;
color: #ebdbb2;
font: inherit;
caret-color: #ebdbb2;
}
.alacritty-art {
margin: 0 0 12px;
font-family: inherit;
font-size: 0.6rem;
line-height: 1.05;
color: #ebdbb2;
white-space: pre;
}
.alacritty-cursor {
display: inline-block;
width: 8px;
height: 1em;
background: #ebdbb2;
vertical-align: text-bottom;
margin-left: 2px;
animation: cursorBlink 1s step-end infinite;
}
/* ============================================================
PLASMA PANEL
============================================================ */
.win-taskbar {
position: absolute;
left: 10px;
right: 10px;
bottom: 10px;
height: 44px;
z-index: 9000;
display: flex;
align-items: stretch;
gap: 2px;
border-radius: 8px;
background: rgba(35, 38, 41, 0.85);
border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.06);
-webkit-backdrop-filter: blur(24px) saturate(140%);
backdrop-filter: blur(24px) saturate(140%);
color: #eff0f1;
}
.win-start {
display: flex;
align-items: center;
justify-content: center;
padding: 0 8px;
border: none;
border-radius: 8px 0 0 8px;
background: transparent;
cursor: pointer;
}
.win-start:hover,
.win-start.open {
background: rgba(61, 174, 233, 0.28);
}
.win-start-orb {
width: 34px;
height: 34px;
display: grid;
place-items: center;
}
.gentoo-logo {
width: 26px;
height: 27px;
object-fit: contain;
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
}
.win-tb-buttons {
display: flex;
align-items: stretch;
gap: 2px;
padding: 4px 4px;
min-width: 0;
position: relative;
/* Grow into the free space, then shrink the buttons, then scroll once even
the shrunken buttons no longer fit (see .win-tb-btn min-width). */
flex: 1 1 auto;
overflow-x: auto;
overflow-y: hidden;
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.28) transparent;
}
.win-tb-buttons::-webkit-scrollbar {
height: 4px;
}
.win-tb-buttons::-webkit-scrollbar-track {
background: transparent;
}
.win-tb-buttons::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.28);
border-radius: 2px;
}
.win-tb-buttons::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.45);
}
.win-tb-btn {
position: relative;
display: flex;
align-items: center;
gap: 7px;
flex: 0 1 auto;
min-width: 0;
max-width: 172px;
padding: 0 10px;
border: 1px solid transparent;
border-radius: 5px;
background: transparent;
color: #eff0f1;
cursor: pointer;
animation: tbBtnIn 0.16s ease-out;
}
.win-tb-btn.closing {
animation: tbBtnOut 0.12s ease-in forwards;
pointer-events: none;
}
@keyframes tbBtnIn {
from {
opacity: 0;
transform: translateY(6px) scale(0.92);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes tbBtnOut {
from {
opacity: 1;
transform: translateY(0) scale(1);
}
to {
opacity: 0;
transform: translateY(6px) scale(0.92);
}
}
.win-tb-btn::after {
content: "";
position: absolute;
left: 50%;
bottom: 2px;
width: 0;
height: 2px;
border-radius: 1px;
background: #3daee9;
transform: translateX(-50%);
transition: width 0.15s ease;
}
.win-tb-btn.active::after {
width: 24px;
}
.win-tb-btn:hover {
background: rgba(255, 255, 255, 0.1);
}
.win-tb-btn.active {
background: rgba(61, 174, 233, 0.32);
border-color: rgba(61, 174, 233, 0.55);
}
.win-tb-btn.minimized {
opacity: 0.7;
}
.win-tb-btn-icon {
width: 18px;
height: 18px;
display: grid;
place-items: center;
font-size: 14px;
line-height: 1;
flex-shrink: 0;
}
.win-tb-btn-label {
font-size: 0.75rem;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.win-tray {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
padding: 0 4px 0 4px;
flex-shrink: 0;
}
.win-theme-toggle {
display: inline-flex;
align-items: center;
gap: 6px;
height: 26px;
padding: 0 12px;
border-radius: 13px;
border: 1px solid rgba(255, 255, 255, 0.15);
background: rgba(255, 255, 255, 0.06);
color: #eff0f1;
font-size: 0.72rem;
cursor: pointer;
}
.win-theme-toggle:hover {
background: rgba(61, 174, 233, 0.3);
border-color: rgba(61, 174, 233, 0.6);
}
.win-clock {
font-size: 0.75rem;
color: #eff0f1;
white-space: nowrap;
}
.win-showdesktop {
width: 10px;
border: none;
border-left: 1px solid rgba(255, 255, 255, 0.15);
background: transparent;
cursor: pointer;
}
.win-showdesktop:hover {
background: rgba(255, 255, 255, 0.12);
}
/* ============================================================
KICKOFF LAUNCHER
============================================================ */
.kickoff {
position: absolute;
left: 10px;
bottom: 62px;
z-index: 9500;
width: 320px;
max-width: calc(100vw - 20px);
border-radius: 8px;
background: rgba(35, 38, 41, 0.94);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
-webkit-backdrop-filter: blur(28px) saturate(150%);
backdrop-filter: blur(28px) saturate(150%);
color: #eff0f1;
overflow: hidden;
transform-origin: bottom left;
animation: kickoffIn 0.16s ease-out;
}
@keyframes kickoffIn {
from {
opacity: 0;
transform: translateY(10px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.kickoff-content {
max-height: 60vh;
overflow: auto;
padding: 10px 12px;
}
.kickoff.closing {
animation: kickoffOut 0.16s ease-in forwards;
pointer-events: none;
}
@keyframes kickoffOut {
from {
opacity: 1;
transform: translateY(0) scale(1);
}
to {
opacity: 0;
transform: translateY(10px) scale(0.98);
}
}
.kickoff-section-title {
margin: 4px 2px 8px;
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: rgba(239, 240, 241, 0.55);
}
.kickoff-icon {
width: 22px;
height: 22px;
display: grid;
place-items: center;
font-size: 15px;
flex-shrink: 0;
}
.kickoff-icon-img {
width: 20px;
height: 20px;
object-fit: contain;
filter: brightness(0) invert(1);
opacity: 0.92;
}
.kickoff-label {
font-size: 0.84rem;
line-height: 1.2;
text-align: left;
}
.kickoff-list {
display: grid;
gap: 1px;
}
.kickoff-item {
display: flex;
align-items: center;
gap: 10px;
padding: 7px 8px;
border: none;
border-radius: 5px;
background: transparent;
color: #eff0f1;
font-size: 0.84rem;
text-align: left;
text-decoration: none;
cursor: pointer;
}
.kickoff-item:hover {
background: rgba(61, 174, 233, 0.3);
}
/* Respect reduced-motion preferences without breaking animationend callbacks
(a near-zero duration still fires them so closing windows/apps unmount). */
@media (prefers-reduced-motion: reduce) {
.win-window,
.win-window.closing,
.kickoff {
animation-duration: 0.01ms !important;
}
.win-icon {
transition: none;
}
}