librelad 875a60f90f LibrePortal v0.1.0 — initial release
A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys,
Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun
VPN routing, and a web dashboard to manage it all.

Free & open forever to self-host; optional paid hosted services fund it.
See PROMISE.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-21 20:37:54 +01:00

156 lines
3.9 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Sidebar layout and category navigation items. Extracted from style.css. */
/* Sidebar — full column height so its glass background paints the
entire side of the viewport even when the items don't fill it.
Internal scroll keeps the list usable without the page scrolling. */
.sidebar {
width: 220px;
height: 100%;
display: flex;
flex-direction: column;
background: var(--sidebar-bg);
color: var(--sidebar-text);
border-right: 1px solid var(--sidebar-border);
position: relative;
z-index: 100;
transition: transform 0.3s ease;
backdrop-filter: blur(12px) saturate(140%);
-webkit-backdrop-filter: blur(12px) saturate(140%);
overflow-y: auto;
}
/* Tasks sidebar only: the first sidebar-category sits flush against the top
without any top padding. Apps and config sidebars don't need this — their
first items already have spacing baked in. */
.tasks-layout .sidebar {
padding-top: 20px;
}
/* Apps sidebar search bar — glass input pinned to the top of the
sidebar above the category list. Toggles the clear (×) button
visibility via .has-value. */
.apps-search {
position: relative;
padding: 14px 20px;
border-bottom: 1px solid var(--sidebar-border);
}
.apps-search-icon {
position: absolute;
left: 32px;
top: 50%;
transform: translateY(-50%);
color: rgba(var(--text-rgb), 0.55);
pointer-events: none;
}
.apps-search-input {
width: 100%;
padding: 9px 34px 9px 36px;
background: rgba(var(--text-rgb), 0.06);
border: 1px solid rgba(var(--text-rgb), 0.12);
border-radius: 8px;
color: var(--text-primary);
font-size: 13px;
font-family: inherit;
transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}
.apps-search-input::placeholder {
color: rgba(var(--text-rgb), 0.5);
}
.apps-search-input:focus {
outline: none;
background: rgba(var(--text-rgb), 0.10);
border-color: rgba(var(--accent-rgb), 0.55);
box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.16);
}
/* Strip the native search-cancel (we render our own × button). */
.apps-search-input::-webkit-search-cancel-button {
-webkit-appearance: none;
appearance: none;
}
.apps-search-clear {
position: absolute;
right: 28px;
top: 50%;
transform: translateY(-50%);
width: 22px;
height: 22px;
border: none;
background: rgba(var(--text-rgb), 0.10);
color: rgba(var(--text-rgb), 0.7);
border-radius: 50%;
font-size: 18px;
line-height: 1;
cursor: pointer;
display: none;
align-items: center;
justify-content: center;
transition: background 0.18s ease, color 0.18s ease;
}
.apps-search-clear:hover {
background: rgba(var(--status-danger-rgb), 0.20);
color: var(--status-danger);
}
.apps-search.has-value .apps-search-clear {
display: flex;
}
.sidebar h2 {
padding: 20px;
text-align: center;
font-size: 20px;
font-weight: 600;
border-bottom: 1px solid var(--sidebar-border);
}
.category {
padding: 15px 20px;
cursor: pointer;
color: var(--text-secondary);
border-bottom: 1px solid var(--sidebar-border);
display: flex;
align-items: center;
gap: 10px;
transition: background 0.2s, color 0.2s;
}
.category:hover,
.category.active {
background: var(--surface-hover);
color: var(--text-primary);
}
.category img,
.category .category-icon {
width: 20px;
height: 20px;
flex-shrink: 0;
}
/* Mobile: take the sidebar out of flex flow entirely so the main
content fills the full viewport. The drawer carries its contents
when the burger is open. Lives here (and not in style.css) because
sidebar.css loads after style.css — without this co-location the
base .sidebar { position: relative } below wins the cascade and the
sidebar keeps its 220px column at mobile widths. */
@media (max-width: 768px) {
.sidebar {
position: fixed;
top: 60px;
left: 0;
height: calc(100vh - 60px);
transform: translateX(-100%);
border-right: none;
z-index: 100;
}
}