From 2515258dd43ec94e625e5e86e3c59a2b76cd1b4a Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Sat, 23 May 2026 10:56:10 -0400 Subject: [PATCH] style(home): launcher styles + sidebar brand-logo treatment Adds .launcher, .launcher-tile, .launcher-hero, .launcher-grid styles plus .brand-logo replacement for the gradient-D mark in the sidebar. The shipped img/dragon-logo.png has a light-gray background; we use mix-blend-mode: screen so the black dragon silhouette sits on the dark theme without showing the gray box, and a soft accent glow under the hero version. Smaller sidebar version uses the same trick. --- services/web-ui/public/styles-fixes.css | 284 ++++++++++++++++++++++++ 1 file changed, 284 insertions(+) diff --git a/services/web-ui/public/styles-fixes.css b/services/web-ui/public/styles-fixes.css index 1a39d65..13d5ffb 100644 --- a/services/web-ui/public/styles-fixes.css +++ b/services/web-ui/public/styles-fixes.css @@ -233,3 +233,287 @@ .row-menu button { padding: 7px 10px; border-radius: 5px; } .row-menu button:hover { background: var(--accent-soft); color: var(--accent-text); } .row-menu button.danger:hover { background: var(--danger-soft); color: var(--danger); } + +/* ============================================================ + Sidebar brand logo — replace the gradient "D" tile with the + actual dragon-coiled-D logo. mix-blend-mode: screen drops the + light-gray PNG background so only the black silhouette + blue + flame remain over the dark sidebar. + ============================================================ */ +.brand-logo { + width: 32px; + height: 32px; + flex-shrink: 0; + object-fit: contain; + /* The PNG has a light-gray background. Invert it so the black + dragon becomes white-ish, then multiply against the sidebar + so the (now-bright) gray background falls back out. Simpler + route: a subtle drop-shadow + mix-blend. */ + mix-blend-mode: screen; + filter: drop-shadow(0 0 6px rgba(91, 124, 250, 0.25)); +} +.sidebar-header:hover .brand-logo { + filter: drop-shadow(0 0 10px rgba(91, 124, 250, 0.45)); +} +/* If you ever drop a transparent-PNG version into img/dragon-logo.png + you can remove the mix-blend; the screen blend is harmless on a + transparent PNG (just slightly brightens). */ + +/* ============================================================ + Launcher home — full-bleed landing page with the logo as hero + and big section tiles. + ============================================================ */ +.launcher { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + background: + radial-gradient(1100px 600px at 50% 0%, rgba(91, 124, 250, 0.10), transparent 65%), + radial-gradient(900px 600px at 50% 100%, rgba(181, 124, 250, 0.06), transparent 60%), + var(--bg-0); + display: flex; + align-items: flex-start; + justify-content: center; + padding: 48px 32px 64px; +} +.launcher-inner { + width: 100%; + max-width: 1160px; + display: flex; + flex-direction: column; + align-items: center; + gap: 40px; +} + +.launcher-hero { + display: flex; + flex-direction: column; + align-items: center; + gap: 14px; + text-align: center; + margin-top: 8px; +} +.launcher-logo { + width: 180px; + height: 180px; + object-fit: contain; + /* Drop the gray PNG background — see .brand-logo comment for the + trick. Soft accent halo so the silhouette has presence. */ + mix-blend-mode: screen; + filter: + drop-shadow(0 0 24px rgba(91, 124, 250, 0.28)) + drop-shadow(0 0 48px rgba(91, 124, 250, 0.18)); + animation: launcherLogoIn 600ms cubic-bezier(0.2, 0.7, 0.2, 1) both; +} +@keyframes launcherLogoIn { + from { opacity: 0; transform: translateY(8px) scale(0.96); } + to { opacity: 1; transform: translateY(0) scale(1); } +} +.launcher-wordmark { + margin: 0; + font-size: 44px; + font-weight: 700; + letter-spacing: 0.12em; + line-height: 1; + background: linear-gradient(180deg, var(--text-1) 0%, #B4C3FF 100%); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + text-shadow: 0 0 32px rgba(91, 124, 250, 0.15); +} +.launcher-tagline { + margin: 0; + color: var(--text-3); + font-size: 13.5px; + letter-spacing: 0.02em; +} + +.launcher-grid { + width: 100%; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 14px; +} +@media (max-width: 960px) { .launcher-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } +@media (max-width: 620px) { .launcher-grid { grid-template-columns: 1fr; } } + +.launcher-tile { + position: relative; + display: grid; + grid-template-areas: + "icon arrow" + "label label" + "sub sub" + "desc desc"; + grid-template-columns: 1fr auto; + align-items: start; + gap: 6px; + text-align: left; + padding: 20px 22px 22px; + border-radius: var(--r-lg); + background: + linear-gradient(180deg, rgba(255,255,255,0.04), transparent 45%), + var(--bg-1); + border: 1px solid var(--border); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.03), + 0 12px 28px rgba(0, 0, 0, 0.28); + color: var(--text-1); + cursor: pointer; + transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease, background 140ms ease; + min-height: 168px; + overflow: hidden; + isolation: isolate; +} +.launcher-tile::before { + /* Tinted accent halo that brightens on hover. Sits behind content + (z-index lower than children which inherit 1). */ + content: ""; + position: absolute; + inset: -1px; + border-radius: inherit; + pointer-events: none; + background: radial-gradient(120% 80% at 0% 0%, var(--tile-tint, transparent), transparent 60%); + opacity: 0; + transition: opacity 160ms ease; + z-index: 0; +} +.launcher-tile > * { position: relative; z-index: 1; } +.launcher-tile:hover { + transform: translateY(-2px); + border-color: var(--border-stronger); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.05), + 0 18px 40px rgba(0, 0, 0, 0.42); +} +.launcher-tile:hover::before { opacity: 1; } +.launcher-tile:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} +.launcher-tile:active { transform: translateY(0); } + +.launcher-tile-icon { + grid-area: icon; + width: 44px; height: 44px; + border-radius: 10px; + display: grid; + place-items: center; + background: var(--tile-icon-bg, var(--bg-3)); + color: var(--tile-icon-fg, var(--text-1)); + border: 1px solid var(--tile-icon-border, var(--border-strong)); + margin-bottom: 6px; +} +.launcher-tile-icon svg { width: 22px; height: 22px; } + +.launcher-tile-label { + grid-area: label; + font-size: 18px; + font-weight: 600; + letter-spacing: -0.01em; +} +.launcher-tile-sub { + grid-area: sub; + font-size: 11.5px; + font-family: var(--font-mono); + color: var(--tile-sub-fg, var(--text-3)); + text-transform: uppercase; + letter-spacing: 0.06em; +} +.launcher-tile-desc { + grid-area: desc; + font-size: 12.5px; + color: var(--text-3); + line-height: 1.5; + margin-top: 4px; +} +.launcher-tile-arrow { + grid-area: arrow; + align-self: start; + color: var(--text-4); + transform: translateX(-4px); + transition: transform 140ms ease, color 140ms ease; +} +.launcher-tile:hover .launcher-tile-arrow { + transform: translateX(0); + color: var(--tile-icon-fg, var(--accent-text)); +} + +/* Tone variants — colour the icon tile + halo, leave the body text + neutral so the tile reads as a button, not a banner. */ +.launcher-tile.tone-accent { + --tile-tint: rgba(91, 124, 250, 0.18); + --tile-icon-bg: var(--accent-soft); + --tile-icon-fg: var(--accent-text); + --tile-icon-border: rgba(91, 124, 250, 0.30); +} +.launcher-tile.tone-live { + --tile-tint: rgba(255, 59, 48, 0.18); + --tile-icon-bg: var(--live-soft); + --tile-icon-fg: var(--live); + --tile-icon-border: rgba(255, 59, 48, 0.30); +} +.launcher-tile.tone-purple { + --tile-tint: rgba(181, 124, 250, 0.18); + --tile-icon-bg: var(--purple-soft); + --tile-icon-fg: var(--purple); + --tile-icon-border: rgba(181, 124, 250, 0.30); +} +.launcher-tile.tone-success { + --tile-tint: rgba(45, 212, 168, 0.16); + --tile-icon-bg: var(--success-soft); + --tile-icon-fg: var(--success); + --tile-icon-border: rgba(45, 212, 168, 0.30); +} +.launcher-tile.tone-warn { + --tile-tint: rgba(245, 166, 35, 0.18); + --tile-icon-bg: var(--warning-soft); + --tile-icon-fg: var(--warning); + --tile-icon-border: rgba(245, 166, 35, 0.30); +} +.launcher-tile.tone-neutral { + --tile-tint: rgba(255, 255, 255, 0.06); + --tile-icon-bg: var(--bg-3); + --tile-icon-fg: var(--text-1); + --tile-icon-border: var(--border-stronger); +} +.launcher-tile.tone-ghost { + --tile-tint: rgba(255, 255, 255, 0.04); + --tile-icon-bg: transparent; + --tile-icon-fg: var(--text-2); + --tile-icon-border: var(--border); + background: + linear-gradient(180deg, rgba(255,255,255,0.02), transparent 50%), + var(--bg-1); +} + +.launcher-status { + display: flex; + gap: 16px; + align-items: center; + flex-wrap: wrap; + justify-content: center; + margin-top: 4px; +} +.launcher-status-pip { + display: inline-flex; + align-items: center; + gap: 8px; + font-size: 11.5px; + font-family: var(--font-mono); + color: var(--text-3); + letter-spacing: 0.02em; + padding: 6px 12px; + border-radius: 99px; + border: 1px solid var(--border); + background: var(--bg-1); +} +.launcher-status-pip .dot { + width: 6px; height: 6px; border-radius: 50%; + box-shadow: 0 0 0 3px var(--success-soft); +} +.launcher-status-pip .muted { color: var(--text-4); margin-left: 2px; } +.launcher-status-pip.live .dot { + box-shadow: 0 0 0 3px var(--live-soft); + animation: pulse 1.6s ease-in-out infinite; +}