// ─── 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); } // FrameCard settings cog: was white (95% opacity) — replace with dark glass + light icon .frame-card__settings-btn { background: rgba(8, 18, 30, 0.55) !important; color: var(--color-text) !important; border: 1px solid var(--color-border) !important; box-shadow: 0 4px 12px -4px rgba(0,0,0,0.5) !important; } .frame-card__settings-btn:hover { background: rgba(8, 18, 30, 0.75) !important; } // Orientation picker: active border in YELLOW (was theme primary) .orientation-opt--active { border-color: var(--brand-yellow) !important; background: color-mix(in srgb, var(--brand-yellow) 12%, var(--color-surface)) !important; } .orientation-opt { background: var(--color-surface); border-color: var(--color-border); color: var(--color-text); } .orientation-opt__label { color: var(--color-text); } .orientation-opt__sub { color: var(--color-text-muted); } .orientation-opt__diagram { color: var(--color-text-muted); } .orientation-opt--active .orientation-opt__diagram { color: var(--brand-yellow); } .home-view__empty-title { font-family: var(--font-display-v2); } .library__add-btn { background: var(--color-primary); color: var(--color-primary-fg); } // Library tile becomes a single connected card — photo and Manage button // share the same surface, no gap between them. Manage gets a button-bar feel. // Uses --color-surface-2 (lighter shade) so the card pops above the harbor // multiplied backdrop that's already at --color-surface tone. .library__item { background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; gap: 0 !important; box-shadow: 0 1px 0 color-mix(in srgb, var(--color-text) 10%, transparent) inset, 0 12px 28px -8px rgba(0,0,0,0.55); backdrop-filter: saturate(160%) blur(20px); -webkit-backdrop-filter: saturate(160%) blur(20px); } .library__thumb { border-radius: 0 !important; background: var(--color-surface-2); } .library__manage { background: rgba(0,0,0,0.35) !important; border-top: 1px solid var(--color-border); border-radius: 0 !important; padding: var(--space-3) var(--space-4) !important; transition: background var(--duration-fast) var(--ease-out); &:hover { background: rgba(0,0,0,0.5) !important; } } .library__manage-summary { color: var(--color-text-muted); font-size: var(--text-sm); font-family: var(--font-family); b { color: var(--color-text); } } .library__manage-action { color: var(--brand-yellow) !important; font-weight: 700; font-size: var(--text-sm); } .library__manage-lock { color: var(--color-text-muted); } // ── 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); } // Each section gets a glass card background so it reads against the harbor &__section { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--space-5); backdrop-filter: saturate(160%) blur(20px); -webkit-backdrop-filter: saturate(160%) blur(20px); box-shadow: 0 1px 0 color-mix(in srgb, var(--color-text) 8%, transparent) inset, 0 16px 32px -12px rgba(0,0,0,0.5); // override the v1 margin-bottom which collapses between cards margin-bottom: var(--space-4); } } // Desktop: 2-column settings layout — first 4 sections in pairs, // each section is a column-flex auto. Sections naturally pack in pairs. @media (min-width: 960px) { .settings { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-5); align-items: start; &__title { grid-column: 1 / -1; } &__section { margin-bottom: 0; } } } .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; } }