homeos/resources/css/app.css

144 lines
5.7 KiB
CSS

@import 'tailwindcss';
/* Scan Blade sources for utility classes */
@source '../views';
@source '../../app/Livewire';
/* wire-elements/modal builds width classes in PHP — force-generate them */
@source inline("sm:max-w-md md:max-w-lg md:max-w-xl lg:max-w-2xl lg:max-w-3xl");
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
/* ── Design tokens — "Enterprise Ops, dark OLED" (handoff §8, ported verbatim) ── */
@theme {
/* surfaces */
--color-base: #080D18; /* page bg, blue-biased OLED black */
--color-surface: #0D1424; /* cards */
--color-raised: #121C31; /* nested surfaces, chips */
--color-inset: #18233D; /* icon wells, kbd */
/* text ramp */
--color-ink: #EAF0FB;
--color-ink-2: #93A1BD;
--color-ink-3: #5E6C8A;
/* brand */
--color-accent: #4FC1FF; /* cyan — interaction, active nav, toggles */
/* status triad — reserved, never decorative */
--color-online: #34D399;
--color-warning: #FBBF24;
--color-offline: #F87171;
/* hairlines */
--color-line: #1C2846;
--color-line-soft: #141E36;
/* radius */
--radius-card: 10px;
/* fonts (self-hosted, R14) */
--font-sans: 'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif;
--font-mono: 'IBM Plex Mono', ui-monospace, monospace;
}
/* ── Self-hosted fonts (R14 — no CDN/Google Fonts) ── */
@font-face {
font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 400;
font-display: swap; src: url('../fonts/plus-jakarta-sans-latin-400-normal.woff2') format('woff2');
}
@font-face {
font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 500;
font-display: swap; src: url('../fonts/plus-jakarta-sans-latin-500-normal.woff2') format('woff2');
}
@font-face {
font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 600;
font-display: swap; src: url('../fonts/plus-jakarta-sans-latin-600-normal.woff2') format('woff2');
}
@font-face {
font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 700;
font-display: swap; src: url('../fonts/plus-jakarta-sans-latin-700-normal.woff2') format('woff2');
}
@font-face {
font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400;
font-display: swap; src: url('../fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500;
font-display: swap; src: url('../fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
}
@font-face {
font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600;
font-display: swap; src: url('../fonts/ibm-plex-mono-latin-600-normal.woff2') format('woff2');
}
/* ── Base ── */
@layer base {
[x-cloak] { display: none !important; }
html { scrollbar-color: var(--color-line) transparent; }
body {
background-color: var(--color-base);
color: var(--color-ink);
font-family: var(--font-sans);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--color-line); border-radius: 20px; border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }
}
/* ── Component helpers that must reference tokens (keeps raw color out of markup, R3) ── */
@layer components {
.dot-glow-online { box-shadow: 0 0 8px color-mix(in srgb, var(--color-online) 60%, transparent); }
.dot-glow-warning { box-shadow: 0 0 8px color-mix(in srgb, var(--color-warning) 55%, transparent); }
.dot-glow-offline { box-shadow: 0 0 8px color-mix(in srgb, var(--color-offline) 55%, transparent); }
.logo-mark {
background: linear-gradient(140deg, #123049, #0C1B33);
border: 1px solid color-mix(in srgb, var(--color-accent) 35%, transparent);
box-shadow: 0 0 18px color-mix(in srgb, var(--color-accent) 18%, transparent);
}
.topbar-blur {
background: color-mix(in srgb, var(--color-base) 85%, transparent);
backdrop-filter: blur(14px);
}
/* Opaque — the mobile drawer overlays bright content, so it must be fully readable. */
.sidebar-tint { background: #0A101E; }
.pulse-live { animation: pulse 2.2s ease-in-out infinite; }
.reveal { opacity: 0; transform: translateY(10px); animation: reveal .5s cubic-bezier(.2,.7,.3,1) forwards; }
/* Themed checkbox — the native one looks off on OLED dark; this matches the console. */
.checkbox {
appearance: none; -webkit-appearance: none;
width: 1.05rem; height: 1.05rem; flex-shrink: 0;
border-radius: 5px;
border: 1px solid var(--color-line);
background: var(--color-raised);
cursor: pointer; position: relative;
transition: background-color .15s, border-color .15s;
}
.checkbox:hover { border-color: color-mix(in srgb, var(--color-accent) 50%, var(--color-line)); }
.checkbox:checked { background: var(--color-accent); border-color: var(--color-accent); }
.checkbox:checked::after {
content: ""; position: absolute; left: 5px; top: 2px;
width: 4px; height: 8px;
border: solid var(--color-base); border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.checkbox:focus-visible {
outline: 2px solid color-mix(in srgb, var(--color-accent) 55%, transparent);
outline-offset: 1px;
}
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes reveal { to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
.pulse-live { animation: none; }
.reveal { opacity: 1; transform: none; animation: none; }
}