198 lines
7.2 KiB
SCSS
198 lines
7.2 KiB
SCSS
// ─── Design v2 — SPA-specific component styles ──────────────────────────
|
|
// Tokens (CSS vars), font imports, base body bg, and Twig-template overrides
|
|
// live in /public/css/wevisto-design.css — loaded by both Twig and the SPA so
|
|
// changing a v2 color flows everywhere.
|
|
//
|
|
// This file holds only the SPA-specific compositions: side rail, frame card,
|
|
// library/settings inner styling, theme swatches.
|
|
|
|
[data-design="v2"] {
|
|
// ── TopNav: shown at ALL sizes in v2 (v1 hides it below 960px).
|
|
// Mobile/tablet → slim horizontal top bar (~52px) with brand only.
|
|
// Desktop → left side rail (overrides below).
|
|
.top-nav {
|
|
display: flex !important; // beat v1 scoped style's `display: none`
|
|
align-items: center;
|
|
gap: var(--space-3);
|
|
height: 52px;
|
|
padding: 0 var(--space-4);
|
|
padding-top: env(safe-area-inset-top);
|
|
background: color-mix(in srgb, var(--color-bg) 90%, transparent);
|
|
backdrop-filter: saturate(160%) blur(18px);
|
|
-webkit-backdrop-filter: saturate(160%) blur(18px);
|
|
border-bottom-color: var(--color-border);
|
|
|
|
&__wordmark { color: var(--color-text); font-family: var(--font-display-v2); font-weight: 400; }
|
|
&__sub { display: block !important; font-family: var(--font-accent-v2); }
|
|
|
|
// Hide the nav tabs at mobile/tablet — the bottom nav handles routing
|
|
&__tabs { display: none !important; }
|
|
|
|
&__tab {
|
|
color: var(--color-text-muted);
|
|
&:hover { background: var(--color-surface); color: var(--color-text); }
|
|
&--active { background: var(--color-surface); color: var(--brand-yellow); }
|
|
}
|
|
}
|
|
|
|
// Push main content below the mobile/tablet top bar
|
|
@media (max-width: 959px) {
|
|
.top-nav { position: sticky; top: 0; z-index: 30; }
|
|
main { padding-top: var(--space-3); }
|
|
}
|
|
|
|
@media (min-width: 960px) {
|
|
.top-nav {
|
|
position: fixed;
|
|
top: 0; left: 0; bottom: 0;
|
|
width: 240px;
|
|
height: auto;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
gap: 0;
|
|
padding: 28px 18px 24px;
|
|
padding-top: calc(28px + env(safe-area-inset-top));
|
|
background: color-mix(in srgb, var(--color-bg) 96%, transparent);
|
|
border-right: 1px solid var(--color-border);
|
|
border-bottom: 0;
|
|
z-index: 50;
|
|
|
|
&__brand {
|
|
padding-bottom: 20px;
|
|
margin-bottom: 16px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
align-items: flex-start;
|
|
}
|
|
&__mark {
|
|
width: 44px !important;
|
|
height: 44px !important;
|
|
border-radius: 10px !important;
|
|
}
|
|
&__wordmark { font-size: var(--text-xl); font-family: var(--font-display-v2); font-weight: 400; }
|
|
|
|
// !important needed because TopNav's scoped style hides these by default
|
|
// at the same specificity and cascades after the main bundle.
|
|
&__sub {
|
|
display: block !important;
|
|
font-family: var(--font-accent-v2);
|
|
}
|
|
|
|
&__tabs {
|
|
display: flex !important; // re-show at desktop (mobile/tablet had display:none)
|
|
flex: 0 0 auto !important;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
align-items: stretch;
|
|
margin-left: 0;
|
|
}
|
|
&__tab {
|
|
width: 100%;
|
|
justify-content: flex-start;
|
|
padding: 12px 14px;
|
|
gap: 12px;
|
|
border-radius: var(--radius-md);
|
|
|
|
&--active {
|
|
background: var(--color-surface);
|
|
box-shadow: inset 3px 0 0 var(--brand-yellow);
|
|
}
|
|
}
|
|
}
|
|
|
|
body { padding-left: 240px; }
|
|
}
|
|
|
|
.bottom-nav {
|
|
background: color-mix(in srgb, var(--color-bg) 95%, transparent);
|
|
border-top-color: var(--color-border);
|
|
.bottom-nav__tab--active { color: var(--brand-yellow); }
|
|
}
|
|
|
|
// ── Glass cards everywhere v1 uses --color-surface ─────────────────
|
|
.frame-card,
|
|
.home-view__empty-card,
|
|
.library__tile,
|
|
.settings__section-card {
|
|
background: var(--color-surface);
|
|
border-color: var(--color-border);
|
|
box-shadow:
|
|
0 1px 0 color-mix(in srgb, var(--color-text) 8%, transparent) inset,
|
|
0 24px 48px -16px rgba(0,0,0,0.6);
|
|
}
|
|
.frame-card__hero { background: var(--color-surface-2); }
|
|
.frame-card__name {
|
|
font-family: var(--font-display-v2);
|
|
font-weight: 400;
|
|
font-size: var(--text-xl);
|
|
}
|
|
|
|
.home-view__empty-title { font-family: var(--font-display-v2); }
|
|
.library__add-btn { background: var(--color-primary); color: var(--color-primary-fg); }
|
|
|
|
// ── Settings polish ────────────────────────────────────────────────
|
|
.settings {
|
|
&__title { font-family: var(--font-display-v2); font-weight: 400; letter-spacing: 0.005em; }
|
|
&__section-title {
|
|
font-family: var(--font-mono-v2);
|
|
font-size: 11px;
|
|
letter-spacing: 0.28em;
|
|
color: var(--color-text-muted);
|
|
}
|
|
&__hint {
|
|
font-family: var(--font-accent-v2);
|
|
font-style: italic;
|
|
color: var(--color-text-muted);
|
|
}
|
|
&__install { color: var(--color-primary-fg); font-weight: 700; }
|
|
&__row,
|
|
&__action-link { border-color: var(--color-border); }
|
|
&__row-label { color: var(--color-text-muted); }
|
|
&__row-value,
|
|
&__action-link { color: var(--color-text); }
|
|
&__logout { color: var(--color-destructive); }
|
|
}
|
|
|
|
.design-toggle__opt {
|
|
background: var(--color-surface);
|
|
border-color: var(--color-border);
|
|
color: var(--color-text);
|
|
&--active { border-color: var(--brand-yellow); background: var(--color-surface-2); }
|
|
}
|
|
.design-toggle__sub { color: var(--color-text-muted); }
|
|
|
|
// ── Theme swatches preview their dusk via the harbor.jpg ───────────
|
|
// `!important` needed because Vue's scoped style on SettingsView
|
|
// (.theme-swatch__preview[data-v-xxx] { background: var(--swatch-bg) })
|
|
// ties on specificity and cascades later. v2 is opt-in so overriding is OK.
|
|
.theme-swatch {
|
|
border-color: var(--color-border);
|
|
background: var(--color-surface) !important;
|
|
color: var(--color-text);
|
|
|
|
&--active { border-color: var(--brand-yellow); }
|
|
&__label { color: var(--color-text); }
|
|
|
|
&__preview {
|
|
background: transparent !important;
|
|
background-image: url('/build/assets/harbor.jpg') !important;
|
|
background-size: cover !important;
|
|
background-position: center !important;
|
|
position: relative;
|
|
overflow: hidden;
|
|
&::after {
|
|
content: '';
|
|
position: absolute; inset: 0;
|
|
mix-blend-mode: multiply;
|
|
}
|
|
}
|
|
}
|
|
.theme-swatch[aria-label*="Warm Craft" i] .theme-swatch__preview::after { background: rgba(60, 25, 8, 0.55); }
|
|
.theme-swatch[aria-label*="Ocean Dusk" i] .theme-swatch__preview::after { background: rgba(8, 22, 38, 0.55); }
|
|
.theme-swatch[aria-label*="Sage" i] .theme-swatch__preview::after { background: rgba(20, 40, 22, 0.55); }
|
|
.theme-swatch[aria-label*="Playful" i] .theme-swatch__preview::after { background: rgba(56, 16, 38, 0.55); }
|
|
.theme-swatch[aria-label*="Dusty" i] .theme-swatch__preview::after { background: rgba(40, 18, 56, 0.55); }
|
|
.theme-swatch[aria-label*="Honey" i] .theme-swatch__preview::after { background: rgba(48, 36, 14, 0.55); }
|
|
.theme-swatch__bar,
|
|
.theme-swatch__dot { display: none; }
|
|
}
|