design: atmospheric redesign mockups (login + SPA, six dusks)
CI / test (push) Has been cancelled

Self-contained HTML/CSS mockups proposing the brand-as-surface direction:
- Camogli harbor photo as the permanent backdrop on every authenticated view
- Six user themes rebuilt as atmospheric "dusks" (tinted overlays + accents)
  instead of cream variants
- Frosted-glass cards on top of the photo
- Same type system (Marcellus / Cormorant Garamond italic / Nunito body)
  shared between login and in-app

Includes:
- login-cinematic.html: canonical pre-auth example with Ken-Burns + grain
- spa/home.html, library.html, settings.html: in-app views with the new chrome
- spa/_tokens.css + _chrome.css: dusk system and frosted-glass primitives
- favicons/A-D: in-progress icon directions
- README.md with serving instructions and the porting checklist

Saved as a durable design artifact so the iteration survives /tmp wipes
and can be referred back to when porting to Vue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 09:44:26 -04:00
parent 6c9959c00d
commit 01b6007b1c
34 changed files with 2064 additions and 0 deletions
@@ -0,0 +1,183 @@
/* Frosted-glass chrome — same vocabulary as the login.
Every surface that holds content is a glass card over the harbor backdrop. */
/* ─── Top app bar — translucent dark band ────────────────────────────── */
.app-bar {
position: sticky;
top: 0;
z-index: 40;
background: var(--glass-2);
backdrop-filter: saturate(180%) blur(18px);
-webkit-backdrop-filter: saturate(180%) blur(18px);
border-bottom: 1px solid var(--glass-bord);
padding: 12px 18px;
padding-top: calc(12px + env(safe-area-inset-top));
display: flex;
align-items: center;
gap: 12px;
}
.app-bar__mark {
width: 34px;
height: 34px;
border-radius: 9px;
overflow: hidden;
box-shadow: 0 2px 6px rgba(0,0,0,0.4);
flex-shrink: 0;
}
.app-bar__mark img { width: 100%; height: 100%; display: block; }
.app-bar__title-group { display: flex; flex-direction: column; }
.app-bar__wordmark {
font: 400 var(--text-lg)/1 var(--font-display);
letter-spacing: 0.005em;
color: var(--text);
}
.app-bar__wordmark .v { color: var(--brand-yellow); }
.app-bar__sub {
font: italic 400 13px/1 var(--font-accent);
color: var(--text-muted);
letter-spacing: 0.02em;
margin-top: 4px;
}
.app-bar__spacer { flex: 1; }
.app-bar__icon {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
background: transparent;
border: 0;
border-radius: var(--radius-full);
cursor: pointer;
transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.app-bar__icon:hover { background: var(--glass); color: var(--text); }
.app-bar__icon svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* ─── Glass surface mixin ──────────────────────────────────────────────── */
.glass {
background: var(--glass);
backdrop-filter: saturate(160%) blur(20px);
-webkit-backdrop-filter: saturate(160%) blur(20px);
border: 1px solid var(--glass-bord);
box-shadow:
0 1px 0 rgba(255,255,255,0.06) inset,
0 20px 40px -16px rgba(0,0,0,0.5);
}
/* ─── Bottom nav — translucent dark band ─────────────────────────────── */
.bottom-nav {
position: fixed;
bottom: 0; left: 0; right: 0;
background: var(--glass-2);
backdrop-filter: saturate(180%) blur(20px);
-webkit-backdrop-filter: saturate(180%) blur(20px);
border-top: 1px solid var(--glass-bord);
display: flex;
z-index: 50;
padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav__tab {
flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 2px; height: 64px; color: var(--text-muted);
text-decoration: none; min-height: 44px;
transition: color var(--duration-fast);
}
.bottom-nav__tab.active {
color: var(--brand-yellow);
}
.bottom-nav__tab.active .label { color: var(--text); }
.bottom-nav__tab svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; }
.bottom-nav__tab .label {
font-family: var(--font-display);
font-size: var(--text-xs);
letter-spacing: 0.16em;
text-transform: uppercase;
}
.main-scroll {
padding-bottom: calc(64px + env(safe-area-inset-bottom) + 32px);
min-height: 100dvh;
}
/* ─── Brand signature ─────────────────────────────────────────────────── */
.signature {
margin-top: 32px;
padding: 32px 0 16px;
border-top: 1px solid var(--glass-bord);
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.signature__mark {
width: 44px;
height: 44px;
border-radius: 10px;
overflow: hidden;
opacity: 0.9;
}
.signature__mark img { width: 100%; height: 100%; display: block; }
.signature__text {
font: 400 14px/1.2 var(--font-display);
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--text-muted);
display: flex;
align-items: center;
gap: 10px;
}
.signature__text .v-mark { color: var(--brand-yellow); }
.signature__version {
font: 400 italic 14px/1.3 var(--font-accent);
letter-spacing: 0.02em;
color: var(--text-muted);
opacity: 0.7;
}
/* ─── Theme switcher (mockup only) ─────────────────────────────────────── */
.theme-switcher {
position: fixed;
bottom: 84px;
right: 16px;
z-index: 60;
background: var(--glass-2);
backdrop-filter: saturate(180%) blur(20px);
border: 1px solid var(--glass-bord);
border-radius: var(--radius-md);
box-shadow: 0 12px 24px -8px rgba(0,0,0,0.5);
padding: 10px;
display: flex;
flex-direction: column;
gap: 8px;
max-width: 220px;
}
.theme-switcher__label {
font: var(--type-label);
letter-spacing: 0.24em;
text-transform: uppercase;
color: var(--text-muted);
}
.theme-switcher__chips {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.theme-switcher__chip {
width: 26px; height: 26px;
border: 2px solid var(--glass-bord);
border-radius: var(--radius-full);
cursor: pointer;
position: relative;
transition: transform var(--duration-fast);
}
.theme-switcher__chip:hover { transform: scale(1.1); }
.theme-switcher__chip.active { box-shadow: 0 0 0 2px var(--brand-yellow); }
/* each chip shows that theme's accent over its bg-base */
.theme-switcher__chip[data-theme="ocean-dusk"] { background: linear-gradient(135deg, #06121f 50%, #4e9fc8 50%); }
.theme-switcher__chip[data-theme="amber-dusk"] { background: linear-gradient(135deg, #1a0d05 50%, #e89048 50%); }
.theme-switcher__chip[data-theme="sage-dusk"] { background: linear-gradient(135deg, #081208 50%, #88c068 50%); }
.theme-switcher__chip[data-theme="rose-dusk"] { background: linear-gradient(135deg, #1a060f 50%, #d878a0 50%); }
.theme-switcher__chip[data-theme="mauve-dusk"] { background: linear-gradient(135deg, #100618 50%, #b890d8 50%); }
.theme-switcher__chip[data-theme="honey-dusk"] { background: linear-gradient(135deg, #18120a 50%, #e8c050 50%); }
@@ -0,0 +1,19 @@
<div class="theme-switcher" role="region" aria-label="Theme switcher (mockup only)">
<span class="theme-switcher__label">User-pref theme</span>
<div class="theme-switcher__chips">
<button class="theme-switcher__chip active" data-theme="warm-craft" title="warm-craft"></button>
<button class="theme-switcher__chip" data-theme="ocean-dusk" title="ocean-dusk"></button>
<button class="theme-switcher__chip" data-theme="sage-cream" title="sage-cream"></button>
<button class="theme-switcher__chip" data-theme="playful-pop" title="playful-pop"></button>
<button class="theme-switcher__chip" data-theme="dusty-mauve" title="dusty-mauve"></button>
<button class="theme-switcher__chip" data-theme="honey-slate" title="honey-slate"></button>
</div>
</div>
<script>
document.querySelectorAll('.theme-switcher__chip').forEach(chip => {
chip.addEventListener('click', () => {
document.documentElement.setAttribute('data-theme', chip.dataset.theme);
document.querySelectorAll('.theme-switcher__chip').forEach(c => c.classList.toggle('active', c === chip));
});
});
</script>
@@ -0,0 +1,164 @@
/* Atmospheric design tokens — themes as dusks layered over the harbor photo.
The whole app shares the login's surface vocabulary. */
:root {
/* Type — same recipe as login */
--font-family: 'Nunito', system-ui, sans-serif;
--font-display: 'Marcellus', Georgia, serif;
--font-accent: 'Cormorant Garamond', Georgia, serif;
--font-mono: 'DM Mono', ui-monospace, monospace;
--text-xs: 11px; --text-sm: 13px; --text-base: 15px; --text-md: 17px;
--text-lg: 20px; --text-xl: 24px; --text-2xl: 28px; --text-3xl: 36px;
--space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
--space-5: 20px; --space-6: 24px; --space-8: 32px;
--radius-sm: 6px; --radius-md: 12px; --radius-lg: 20px; --radius-full: 9999px;
--duration-fast: 150ms; --duration-base: 250ms;
--ease-out: cubic-bezier(0, 0, 0.2, 1);
/* Brand layer — fixed regardless of theme. */
--brand-yellow: #f0d000;
--brand-yellow-soft: #c4a700;
/* Editorial recipes */
--type-display-xl: 400 var(--text-3xl)/1.05 var(--font-display);
--type-display-lg: 400 var(--text-2xl)/1.1 var(--font-display);
--type-display-md: 400 var(--text-xl)/1.15 var(--font-display);
--type-accent-md: 400 italic var(--text-md)/1.4 var(--font-accent);
--type-label: 700 var(--text-xs)/1 var(--font-mono);
}
/* ─── DUSKS ──────────────────────────────────────────────────────────────
Each dusk is:
--bg-base : the deep base color behind everything
--bg-tint : an rgba multiplied over the harbor photo (the "filter")
--glass : rgba background of cards (frosted, sits on photo)
--glass-2 : a more opaque variant for nav strips
--glass-bord : hairline border on glass surfaces
--accent : theme accent (was --color-primary) — CTAs that aren't brand
--accent-fg : text on accent
--text : main text on glass (always light)
--text-muted : muted text on glass
The yellow V brand constant survives across all dusks.
*/
/* OCEAN DUSK — default, closest to login */
[data-theme="ocean-dusk"], :root {
--bg-base: #06121f;
--bg-tint: rgba(8, 22, 38, 0.45);
--glass: rgba(10, 28, 48, 0.55);
--glass-2: rgba(8, 22, 38, 0.72);
--glass-bord: rgba(180, 210, 235, 0.18);
--accent: #4e9fc8;
--accent-fg: #06121f;
--text: #f4eed8;
--text-muted: #b8c8d8;
}
/* AMBER DUSK — successor to warm-craft */
[data-theme="amber-dusk"] {
--bg-base: #1a0d05;
--bg-tint: rgba(60, 25, 8, 0.45);
--glass: rgba(50, 22, 8, 0.55);
--glass-2: rgba(35, 14, 5, 0.72);
--glass-bord: rgba(230, 180, 130, 0.2);
--accent: #e89048;
--accent-fg: #1a0d05;
--text: #faecd0;
--text-muted: #d8b890;
}
/* SAGE DUSK — successor to sage-cream */
[data-theme="sage-dusk"] {
--bg-base: #081208;
--bg-tint: rgba(20, 40, 22, 0.45);
--glass: rgba(18, 38, 22, 0.55);
--glass-2: rgba(12, 26, 14, 0.72);
--glass-bord: rgba(180, 220, 180, 0.18);
--accent: #88c068;
--accent-fg: #081208;
--text: #ecf3e0;
--text-muted: #a8c0a0;
}
/* ROSE DUSK — warmer, classier replacement for playful-pop */
[data-theme="rose-dusk"] {
--bg-base: #1a060f;
--bg-tint: rgba(56, 16, 38, 0.45);
--glass: rgba(48, 14, 36, 0.55);
--glass-2: rgba(32, 8, 22, 0.72);
--glass-bord: rgba(230, 180, 200, 0.2);
--accent: #d878a0;
--accent-fg: #1a060f;
--text: #f8e8ec;
--text-muted: #c898ac;
}
/* MAUVE DUSK — replaces dusty-mauve */
[data-theme="mauve-dusk"] {
--bg-base: #100618;
--bg-tint: rgba(40, 18, 56, 0.45);
--glass: rgba(36, 14, 50, 0.55);
--glass-2: rgba(24, 10, 34, 0.72);
--glass-bord: rgba(210, 190, 230, 0.18);
--accent: #b890d8;
--accent-fg: #100618;
--text: #f0e8f8;
--text-muted: #b8a8c8;
}
/* HONEY DUSK — replaces honey-slate */
[data-theme="honey-dusk"] {
--bg-base: #18120a;
--bg-tint: rgba(48, 36, 14, 0.45);
--glass: rgba(42, 32, 12, 0.55);
--glass-2: rgba(28, 22, 8, 0.72);
--glass-bord: rgba(232, 200, 130, 0.22);
--accent: #e8c050;
--accent-fg: #18120a;
--text: #faf0d8;
--text-muted: #c8b888;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { background: var(--bg-base); color: var(--text); }
body {
font-family: var(--font-family);
font-size: var(--text-base);
line-height: 1.5;
min-height: 100dvh;
position: relative;
-webkit-font-smoothing: antialiased;
}
/* ─── PERMANENT ATMOSPHERIC BACKDROP ──────────────────────────────────── */
/* harbor photo fixed under everything */
body::before {
content: '';
position: fixed;
inset: 0;
background: url('../assets/harbor.jpg') center/cover no-repeat;
filter: brightness(0.6) saturate(0.85);
z-index: -3;
}
/* theme tint multiplied over photo */
body::after {
content: '';
position: fixed;
inset: 0;
background: var(--bg-tint);
mix-blend-mode: multiply;
z-index: -2;
pointer-events: none;
}
/* global vignette + film grain via one extra layer */
.atmosphere {
position: fixed;
inset: 0;
pointer-events: none;
z-index: -1;
background:
radial-gradient(ellipse 80% 70% at 50% 45%, transparent 0%, rgba(0,0,0,0.35) 70%, rgba(0,0,0,0.65) 100%),
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='320' height='320'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='5'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.1 0'/></filter><rect width='320' height='320' filter='url(%23n)'/></svg>");
}
+310
View File
@@ -0,0 +1,310 @@
<!doctype html>
<html lang="en" data-theme="ocean-dusk">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Home — WeVisto</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;900&family=Marcellus&family=Cormorant+Garamond:ital,wght@1,400&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="_tokens.css">
<link rel="stylesheet" href="_chrome.css">
<style>
/* ─── hero — editorial moment, sits directly on the photo ──────────── */
.hero {
padding: var(--space-6) var(--space-5) var(--space-5);
position: relative;
}
.hero__plate {
font: var(--type-label);
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: var(--space-3);
display: flex; align-items: center; gap: 10px;
}
.hero__plate .roman { color: var(--brand-yellow); font-family: var(--font-display); font-size: var(--text-md); }
.hero__plate .sep { width: 24px; height: 1px; background: var(--glass-bord); }
.hero__greeting {
font: var(--type-display-lg);
color: var(--text);
margin-bottom: 8px;
}
.hero__greeting em {
font-family: var(--font-accent);
font-style: italic;
color: var(--brand-yellow);
}
.hero__sub {
font: var(--type-accent-md);
color: var(--text-muted);
line-height: 1.5;
max-width: 38ch;
}
.hero__sub strong { color: var(--text); font-style: normal; font-family: var(--font-display); font-weight: 400; }
.hero__rule {
margin-top: var(--space-4);
width: 80px; height: 1px;
background: linear-gradient(90deg, var(--brand-yellow), transparent);
}
/* ─── frame card — frosted glass, the user's photo is the inner content ── */
.frame-card {
margin: var(--space-5);
border-radius: var(--radius-lg);
overflow: hidden;
/* uses .glass class for the frost effect */
}
.frame-card__hero {
aspect-ratio: 4/3;
background-image: url('../assets/harbor.jpg');
background-size: cover;
background-position: center;
position: relative;
/* the user's frame photo — keep at full saturation (it's user content, not brand backdrop) */
}
.frame-card__status {
position: absolute;
top: 14px; left: 14px;
display: inline-flex;
align-items: center;
gap: 6px;
background: rgba(8, 18, 30, 0.7);
backdrop-filter: blur(8px);
padding: 6px 12px;
border-radius: var(--radius-full);
font: var(--type-label);
color: var(--text);
letter-spacing: 0.22em;
text-transform: uppercase;
}
.frame-card__status .dot {
width: 7px; height: 7px;
background: #6cd498;
border-radius: 50%;
box-shadow: 0 0 0 3px rgba(108, 212, 152, 0.25);
}
.frame-card__plate {
position: absolute;
bottom: 14px; left: 14px;
font: var(--type-label);
background: rgba(8, 18, 30, 0.7);
color: var(--text);
padding: 5px 10px;
letter-spacing: 0.28em;
text-transform: uppercase;
backdrop-filter: blur(6px);
}
.frame-card__body { padding: var(--space-5) var(--space-5) var(--space-4); }
.frame-card__name {
font: var(--type-display-md);
color: var(--text);
margin-bottom: 4px;
}
.frame-card__meta {
font: italic 400 15px/1.4 var(--font-accent);
color: var(--text-muted);
margin-bottom: var(--space-4);
}
.frame-card__meta .sep { margin: 0 8px; opacity: 0.4; }
.frame-card__schedule {
background: rgba(255, 255, 255, 0.06);
border: 1px solid var(--glass-bord);
border-radius: var(--radius-md);
padding: var(--space-4);
margin-bottom: var(--space-4);
display: flex;
align-items: flex-start;
gap: var(--space-3);
font-size: var(--text-sm);
line-height: 1.5;
}
.frame-card__schedule svg {
width: 18px; height: 18px;
stroke: var(--brand-yellow);
fill: none;
stroke-width: 2;
flex-shrink: 0;
margin-top: 2px;
}
.frame-card__schedule strong { font-family: var(--font-display); font-size: var(--text-base); font-weight: 400; color: var(--text); display: block; margin-bottom: 2px; }
.frame-card__schedule span { color: var(--text-muted); }
.frame-card__actions { display: flex; gap: var(--space-3); }
.btn {
flex: 1;
padding: 14px 20px;
font-family: var(--font-family);
font-size: var(--text-base);
font-weight: 700;
border-radius: var(--radius-md);
border: 1px solid var(--glass-bord);
background: rgba(255, 255, 255, 0.06);
color: var(--text);
cursor: pointer;
transition: background var(--duration-fast);
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn:hover { background: rgba(255, 255, 255, 0.12); }
.btn--primary {
background: var(--accent);
color: var(--accent-fg);
border-color: var(--accent);
font-weight: 700;
}
.btn--primary:hover { filter: brightness(1.08); }
.btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; }
/* ─── upcoming photos strip — quiet teaser of what's queued ─────────── */
.upcoming {
margin: var(--space-5);
padding: var(--space-5);
border-radius: var(--radius-lg);
}
.upcoming__head {
display: flex; align-items: baseline; justify-content: space-between;
margin-bottom: var(--space-4);
}
.upcoming__title {
font: var(--type-display-md);
color: var(--text);
}
.upcoming__hint {
font: var(--type-accent-md);
color: var(--text-muted);
}
.upcoming__row {
display: flex; gap: var(--space-3); overflow-x: auto; padding-bottom: 4px;
}
.upcoming__row::-webkit-scrollbar { display: none; }
.upcoming__row { scrollbar-width: none; }
.thumb {
flex-shrink: 0;
width: 92px; height: 92px;
border-radius: var(--radius-md);
overflow: hidden;
background: rgba(0,0,0,0.3);
position: relative;
border: 1px solid var(--glass-bord);
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb .when {
position: absolute;
bottom: 4px; left: 4px;
font: var(--type-label);
background: rgba(0,0,0,0.7);
color: var(--text);
padding: 2px 6px;
letter-spacing: 0.18em;
}
</style>
</head>
<body>
<div class="atmosphere"></div>
<header class="app-bar">
<div class="app-bar__mark"><img src="../assets/mark-photo-64.png" alt=""></div>
<div class="app-bar__title-group">
<div class="app-bar__wordmark">We<span class="v">V</span>isto</div>
<div class="app-bar__sub">— Margaret's frame</div>
</div>
<div class="app-bar__spacer"></div>
<button class="app-bar__icon" aria-label="Notifications">
<svg viewBox="0 0 24 24"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
</button>
</header>
<main class="main-scroll">
<section class="hero">
<div class="hero__plate"><span class="roman">I.</span><span class="sep"></span><span>Plate · today</span></div>
<h1 class="hero__greeting">Good morning, <em>Alice.</em></h1>
<p class="hero__sub">Margaret's frame is in sync. The next photograph will arrive at <strong>7:00 AM</strong>, quietly, on its own.</p>
<div class="hero__rule"></div>
</section>
<article class="frame-card glass">
<div class="frame-card__hero">
<div class="frame-card__status">
<span class="dot"></span><span>Synced 12 min ago</span>
</div>
<div class="frame-card__plate">Plate XII</div>
</div>
<div class="frame-card__body">
<h2 class="frame-card__name">Margaret's frame</h2>
<p class="frame-card__meta">7.3″ landscape <span class="sep">·</span> Camden, Maine <span class="sep">·</span> est. May 2026</p>
<div class="frame-card__schedule">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
<div>
<strong>Next photograph at 7:00 AM</strong>
<span>then again at 12:00 PM and 6:00 PM</span>
</div>
</div>
<div class="frame-card__actions">
<button class="btn btn--primary">
<svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
Add photograph
</button>
<button class="btn">
<svg viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
Settings
</button>
</div>
</div>
</article>
<section class="upcoming glass">
<div class="upcoming__head">
<h3 class="upcoming__title">Up next</h3>
<span class="upcoming__hint">— in the library queue</span>
</div>
<div class="upcoming__row">
<div class="thumb"><img src="../assets/harbor.jpg" alt=""><span class="when">7am</span></div>
<div class="thumb"><img src="../assets/harbor.jpg" alt="" style="filter: hue-rotate(40deg);"><span class="when">noon</span></div>
<div class="thumb"><img src="../assets/harbor.jpg" alt="" style="filter: hue-rotate(-30deg) saturate(1.2);"><span class="when">6pm</span></div>
<div class="thumb"><img src="../assets/harbor.jpg" alt="" style="filter: brightness(0.85);"><span class="when">tmrw</span></div>
<div class="thumb"><img src="../assets/harbor.jpg" alt="" style="filter: sepia(0.4);"><span class="when">+5</span></div>
</div>
</section>
</main>
<nav class="bottom-nav">
<a class="bottom-nav__tab active" href="home.html">
<svg viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9,22 9,12 15,12 15,22"/></svg>
<span class="label">Home</span>
</a>
<a class="bottom-nav__tab" href="library.html">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
<span class="label">Library</span>
</a>
<a class="bottom-nav__tab" href="settings.html">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
<span class="label">Settings</span>
</a>
</nav>
<div class="theme-switcher" role="region" aria-label="Theme switcher (mockup only)">
<span class="theme-switcher__label">Dusk</span>
<div class="theme-switcher__chips">
<button class="theme-switcher__chip active" data-theme="ocean-dusk" title="Ocean dusk"></button>
<button class="theme-switcher__chip" data-theme="amber-dusk" title="Amber dusk"></button>
<button class="theme-switcher__chip" data-theme="sage-dusk" title="Sage dusk"></button>
<button class="theme-switcher__chip" data-theme="rose-dusk" title="Rose dusk"></button>
<button class="theme-switcher__chip" data-theme="mauve-dusk" title="Mauve dusk"></button>
<button class="theme-switcher__chip" data-theme="honey-dusk" title="Honey dusk"></button>
</div>
</div>
<script>
document.querySelectorAll('.theme-switcher__chip').forEach(chip => {
chip.addEventListener('click', () => {
document.documentElement.setAttribute('data-theme', chip.dataset.theme);
document.querySelectorAll('.theme-switcher__chip').forEach(c => c.classList.toggle('active', c === chip));
});
});
</script>
</body>
</html>
@@ -0,0 +1,249 @@
<!doctype html>
<html lang="en" data-theme="ocean-dusk">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Library — WeVisto</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;900&family=Marcellus&family=Cormorant+Garamond:ital,wght@1,400&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="_tokens.css">
<link rel="stylesheet" href="_chrome.css">
<style>
.library-empty {
padding: 56px 24px 0;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
position: relative;
}
.library-empty__plate {
font: var(--type-label);
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: var(--space-5);
display: flex; align-items: center; gap: 10px;
}
.library-empty__plate .roman { color: var(--brand-yellow); font-family: var(--font-display); font-size: var(--text-md); }
.library-empty__plate .sep { width: 24px; height: 1px; background: var(--glass-bord); }
.library-empty__halo { position: relative; margin-bottom: var(--space-5); }
.library-empty__halo::before {
content: '';
position: absolute;
top: 50%; left: 50%;
width: 240px; height: 240px;
transform: translate(-50%, -50%);
background: radial-gradient(circle, color-mix(in srgb, var(--brand-yellow) 25%, transparent), transparent 65%);
border-radius: 50%;
pointer-events: none;
z-index: -1;
}
.library-empty__mark {
width: 112px;
height: 112px;
border-radius: 24px;
overflow: hidden;
box-shadow:
0 1px 0 rgba(255,255,255,0.18) inset,
0 20px 40px -10px rgba(0,0,0,0.6),
0 8px 20px -6px rgba(0,0,0,0.4);
}
.library-empty__mark img { width: 100%; height: 100%; display: block; }
.library-empty__title {
font: var(--type-display-xl);
color: var(--text);
margin-bottom: var(--space-2);
text-shadow: 0 2px 10px rgba(0,0,0,0.3);
}
.library-empty__title em {
font-family: var(--font-accent);
font-style: italic;
color: var(--brand-yellow);
font-weight: 400;
}
.library-empty__sub {
font: italic 400 18px/1.55 var(--font-accent);
color: var(--text-muted);
max-width: 36ch;
margin-bottom: var(--space-6);
}
.library-empty__rule {
width: 96px; height: 1px;
background: linear-gradient(90deg, transparent, var(--brand-yellow), transparent);
margin: 0 auto var(--space-6);
}
.library-empty__cta {
display: inline-flex;
align-items: center;
gap: 10px;
background: var(--accent);
color: var(--accent-fg);
padding: 14px 28px;
border-radius: var(--radius-full);
font-family: var(--font-family);
font-weight: 700;
font-size: var(--text-base);
text-decoration: none;
box-shadow: 0 8px 22px -4px color-mix(in srgb, var(--accent) 50%, transparent);
transition: transform var(--duration-fast) var(--ease-out), filter var(--duration-fast) var(--ease-out);
}
.library-empty__cta:hover { transform: translateY(-1px); filter: brightness(1.08); }
.library-empty__cta svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2.5; stroke-linecap: round; }
.library-empty__or {
margin-top: var(--space-5);
font: italic 400 var(--text-md)/1.4 var(--font-accent);
color: var(--text-muted);
}
.library-empty__or a {
color: var(--text);
border-bottom: 1px solid var(--glass-bord);
text-decoration: none;
padding-bottom: 1px;
}
/* steps card — frosted */
.intro-steps {
margin: 48px var(--space-5) 0;
padding: var(--space-5) var(--space-5) var(--space-6);
border-radius: var(--radius-lg);
position: relative;
}
.intro-steps__rule {
position: absolute;
top: -1px; left: 50%;
transform: translateX(-50%);
width: 60px; height: 1px;
background: var(--brand-yellow);
}
.intro-steps__title {
font: var(--type-display-md);
color: var(--text);
text-align: center;
margin-bottom: var(--space-2);
}
.intro-steps__title .v-mark { color: var(--brand-yellow); }
.intro-steps__sub {
font: var(--type-accent-md);
color: var(--text-muted);
text-align: center;
margin-bottom: var(--space-5);
}
.intro-steps__list { display: flex; gap: var(--space-3); }
.step { flex: 1; text-align: center; padding: var(--space-3); }
.step__num {
font-family: var(--font-display);
font-size: var(--text-2xl);
color: var(--brand-yellow);
line-height: 1;
margin-bottom: var(--space-2);
}
.step__label {
font-size: var(--text-xs);
color: var(--text-muted);
line-height: 1.4;
}
.step__label strong {
font-family: var(--font-display);
font-weight: 400;
font-size: var(--text-sm);
color: var(--text);
display: block;
margin-bottom: 2px;
}
.signature { margin: 64px var(--space-5) 0; }
</style>
</head>
<body>
<div class="atmosphere"></div>
<header class="app-bar">
<div class="app-bar__mark"><img src="../assets/mark-photo-64.png" alt=""></div>
<div class="app-bar__title-group">
<div class="app-bar__wordmark">We<span class="v">V</span>isto</div>
<div class="app-bar__sub">— the library</div>
</div>
<div class="app-bar__spacer"></div>
<button class="app-bar__icon" aria-label="Filter">
<svg viewBox="0 0 24 24"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></svg>
</button>
</header>
<main class="main-scroll">
<div class="library-empty">
<div class="library-empty__plate"><span class="roman"></span><span class="sep"></span><span>Accession no. 001</span></div>
<div class="library-empty__halo">
<div class="library-empty__mark"><img src="../assets/mark-photo.png" alt=""></div>
</div>
<h1 class="library-empty__title">A library, <em>waiting.</em></h1>
<p class="library-empty__sub">Photographs you upload will rotate through Margaret's frame, one at a time. We'll hold them here until the frame is ready.</p>
<div class="library-empty__rule"></div>
<a class="library-empty__cta" href="#">
<svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
Upload the first photograph
</a>
<div class="library-empty__or">— or <a href="#">invite someone else</a> to send one</div>
</div>
<div class="intro-steps glass">
<div class="intro-steps__rule"></div>
<div class="intro-steps__title">How <span class="v-mark">V</span>isto works, briefly</div>
<div class="intro-steps__sub">— three steps, then forever</div>
<div class="intro-steps__list">
<div class="step"><div class="step__num">I.</div><div class="step__label"><strong>You upload</strong>family photos</div></div>
<div class="step"><div class="step__num">II.</div><div class="step__label"><strong>We hold</strong>them in the library</div></div>
<div class="step"><div class="step__num">III.</div><div class="step__label"><strong>Frame picks</strong>one each interval</div></div>
</div>
</div>
<div class="signature">
<div class="signature__mark"><img src="../assets/mark-photo-64.png" alt=""></div>
<div class="signature__text">WeVisto <span class="v-mark">·</span> a frame, gifted</div>
<div class="signature__version">Edizione I · MMXXVI</div>
</div>
</main>
<nav class="bottom-nav">
<a class="bottom-nav__tab" href="home.html">
<svg viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9,22 9,12 15,12 15,22"/></svg>
<span class="label">Home</span>
</a>
<a class="bottom-nav__tab active" href="library.html">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
<span class="label">Library</span>
</a>
<a class="bottom-nav__tab" href="settings.html">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
<span class="label">Settings</span>
</a>
</nav>
<div class="theme-switcher" role="region" aria-label="Theme switcher (mockup only)">
<span class="theme-switcher__label">Dusk</span>
<div class="theme-switcher__chips">
<button class="theme-switcher__chip active" data-theme="ocean-dusk" title="Ocean dusk"></button>
<button class="theme-switcher__chip" data-theme="amber-dusk" title="Amber dusk"></button>
<button class="theme-switcher__chip" data-theme="sage-dusk" title="Sage dusk"></button>
<button class="theme-switcher__chip" data-theme="rose-dusk" title="Rose dusk"></button>
<button class="theme-switcher__chip" data-theme="mauve-dusk" title="Mauve dusk"></button>
<button class="theme-switcher__chip" data-theme="honey-dusk" title="Honey dusk"></button>
</div>
</div>
<script>
document.querySelectorAll('.theme-switcher__chip').forEach(chip => {
chip.addEventListener('click', () => {
document.documentElement.setAttribute('data-theme', chip.dataset.theme);
document.querySelectorAll('.theme-switcher__chip').forEach(c => c.classList.toggle('active', c === chip));
});
});
</script>
</body>
</html>
@@ -0,0 +1,349 @@
<!doctype html>
<html lang="en" data-theme="ocean-dusk">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Settings — WeVisto</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;900&family=Marcellus&family=Cormorant+Garamond:ital,wght@1,400&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="_tokens.css">
<link rel="stylesheet" href="_chrome.css">
<style>
.page-title {
padding: var(--space-6) var(--space-5) var(--space-3);
text-align: center;
}
.page-title__plate {
font: var(--type-label);
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: var(--space-2);
}
.page-title__plate .v-mark { color: var(--brand-yellow); font-family: var(--font-display); font-size: var(--text-md); margin: 0 8px; }
.page-title__title {
font: var(--type-display-lg);
color: var(--text);
text-shadow: 0 2px 10px rgba(0,0,0,0.3);
}
.page-title__rule {
width: 60px; height: 1px;
margin: var(--space-3) auto 0;
background: linear-gradient(90deg, transparent, var(--brand-yellow), transparent);
}
.section { margin: var(--space-6) var(--space-5) 0; }
.section__head {
display: flex;
align-items: baseline;
gap: 12px;
margin-bottom: var(--space-3);
padding: 0 var(--space-2);
}
.section__roman {
font-family: var(--font-display);
font-size: var(--text-lg);
color: var(--brand-yellow);
line-height: 1;
}
.section__label {
font: var(--type-label);
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--text-muted);
}
.section__rule { flex: 1; height: 1px; background: var(--glass-bord); }
.list {
border-radius: var(--radius-lg);
overflow: hidden;
}
.row {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-4) var(--space-5);
border-bottom: 1px solid var(--glass-bord);
text-decoration: none;
color: inherit;
cursor: pointer;
transition: background var(--duration-fast);
}
.row:last-child { border-bottom: 0; }
.row:hover { background: rgba(255,255,255,0.05); }
.row__icon { width: 22px; height: 22px; flex-shrink: 0; color: var(--text-muted); }
.row__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 2; }
.row__label {
flex: 1;
font-family: var(--font-family);
font-size: var(--text-base);
font-weight: 700;
color: var(--text);
}
.row__value {
font: italic 400 14px/1.3 var(--font-accent);
color: var(--text-muted);
}
.row__chevron { color: var(--text-muted); opacity: 0.6; }
/* DUSK PICKER */
.theme-picker {
border-radius: var(--radius-lg);
padding: var(--space-5);
}
.theme-picker__head {
display: flex;
align-items: baseline;
justify-content: space-between;
margin-bottom: var(--space-4);
}
.theme-picker__title {
font: var(--type-display-md);
color: var(--text);
}
.theme-picker__hint {
font: var(--type-accent-md);
color: var(--text-muted);
}
.theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); }
.theme-swatch {
border-radius: var(--radius-md);
padding: var(--space-3);
border: 1px solid var(--glass-bord);
background: rgba(0,0,0,0.25);
cursor: pointer;
text-align: left;
transition: transform var(--duration-fast), box-shadow var(--duration-fast);
font-family: inherit;
color: var(--text);
position: relative;
overflow: hidden;
}
.theme-swatch.active {
border-color: var(--brand-yellow);
box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-yellow) 35%, transparent);
}
.theme-swatch:hover { transform: translateY(-2px); }
/* a tinted preview of harbor inside each swatch */
.theme-swatch__preview {
aspect-ratio: 3/2;
border-radius: var(--radius-sm);
overflow: hidden;
margin-bottom: var(--space-2);
background-image: url('../assets/harbor.jpg');
background-size: cover;
background-position: center;
position: relative;
}
.theme-swatch__preview::after {
content: '';
position: absolute;
inset: 0;
mix-blend-mode: multiply;
}
.theme-swatch[data-pref="ocean-dusk"] .theme-swatch__preview::after { background: rgba(8, 22, 38, 0.55); }
.theme-swatch[data-pref="amber-dusk"] .theme-swatch__preview::after { background: rgba(60, 25, 8, 0.55); }
.theme-swatch[data-pref="sage-dusk"] .theme-swatch__preview::after { background: rgba(20, 40, 22, 0.55); }
.theme-swatch[data-pref="rose-dusk"] .theme-swatch__preview::after { background: rgba(56, 16, 38, 0.55); }
.theme-swatch[data-pref="mauve-dusk"] .theme-swatch__preview::after { background: rgba(40, 18, 56, 0.55); }
.theme-swatch[data-pref="honey-dusk"] .theme-swatch__preview::after { background: rgba(48, 36, 14, 0.55); }
.theme-swatch__name {
font-family: var(--font-display);
font-size: 13px;
color: var(--text);
letter-spacing: 0.04em;
}
.theme-swatch__italic {
font: italic 400 12px/1.2 var(--font-accent);
color: var(--text-muted);
margin-top: 2px;
display: block;
}
.sign-out { margin: var(--space-6) var(--space-5); text-align: center; }
.sign-out a {
color: #e08070;
font-family: var(--font-family);
font-weight: 700;
text-decoration: none;
font-size: var(--text-base);
padding: var(--space-4) var(--space-5);
display: inline-block;
}
.sign-out a:hover { text-decoration: underline; }
.signature { margin: 0 var(--space-5); }
</style>
</head>
<body>
<div class="atmosphere"></div>
<header class="app-bar">
<div class="app-bar__mark"><img src="../assets/mark-photo-64.png" alt=""></div>
<div class="app-bar__title-group">
<div class="app-bar__wordmark">We<span class="v">V</span>isto</div>
<div class="app-bar__sub">— settings</div>
</div>
<div class="app-bar__spacer"></div>
</header>
<main class="main-scroll">
<div class="page-title">
<div class="page-title__plate">Settings <span class="v-mark">·</span> Plate i</div>
<h1 class="page-title__title">A few quiet choices.</h1>
<div class="page-title__rule"></div>
</div>
<div class="section">
<div class="section__head"><span class="section__roman">I.</span><span class="section__label">Account</span><span class="section__rule"></span></div>
<div class="list glass">
<a class="row">
<span class="row__icon"><svg viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/></svg></span>
<span class="row__label">Alice Wexler</span>
<span class="row__value">alice@example.com</span>
<span class="row__chevron"></span>
</a>
<a class="row">
<span class="row__icon"><svg viewBox="0 0 24 24"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg></span>
<span class="row__label">Notification email</span>
<span class="row__value">daily digest</span>
<span class="row__chevron"></span>
</a>
</div>
</div>
<div class="section">
<div class="section__head"><span class="section__roman">II.</span><span class="section__label">Appearance</span><span class="section__rule"></span></div>
<div class="theme-picker glass">
<div class="theme-picker__head">
<div class="theme-picker__title">Dusk</div>
<div class="theme-picker__hint">— pick a tint for the room</div>
</div>
<div class="theme-grid">
<button class="theme-swatch active" data-pref="ocean-dusk">
<div class="theme-swatch__preview"></div>
<div class="theme-swatch__name">Ocean dusk</div>
<span class="theme-swatch__italic">— the harbor</span>
</button>
<button class="theme-swatch" data-pref="amber-dusk">
<div class="theme-swatch__preview"></div>
<div class="theme-swatch__name">Amber dusk</div>
<span class="theme-swatch__italic">— the workshop</span>
</button>
<button class="theme-swatch" data-pref="sage-dusk">
<div class="theme-swatch__preview"></div>
<div class="theme-swatch__name">Sage dusk</div>
<span class="theme-swatch__italic">— the garden</span>
</button>
<button class="theme-swatch" data-pref="rose-dusk">
<div class="theme-swatch__preview"></div>
<div class="theme-swatch__name">Rose dusk</div>
<span class="theme-swatch__italic">— the parlor</span>
</button>
<button class="theme-swatch" data-pref="mauve-dusk">
<div class="theme-swatch__preview"></div>
<div class="theme-swatch__name">Mauve dusk</div>
<span class="theme-swatch__italic">— the study</span>
</button>
<button class="theme-swatch" data-pref="honey-dusk">
<div class="theme-swatch__preview"></div>
<div class="theme-swatch__name">Honey dusk</div>
<span class="theme-swatch__italic">— the alcove</span>
</button>
</div>
</div>
</div>
<div class="section">
<div class="section__head"><span class="section__roman">III.</span><span class="section__label">Frames</span><span class="section__rule"></span></div>
<div class="list glass">
<a class="row">
<span class="row__icon"><svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21,15 16,10 5,21"/></svg></span>
<span class="row__label">Margaret's frame</span>
<span class="row__value">7.3″ landscape</span>
<span class="row__chevron"></span>
</a>
<a class="row">
<span class="row__icon"><svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg></span>
<span class="row__label">Add another frame</span>
<span class="row__chevron"></span>
</a>
</div>
</div>
<div class="section">
<div class="section__head"><span class="section__roman">IV.</span><span class="section__label">Help</span><span class="section__rule"></span></div>
<div class="list glass">
<a class="row">
<span class="row__icon"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span>
<span class="row__label">How WeVisto works</span>
<span class="row__chevron"></span>
</a>
<a class="row">
<span class="row__icon"><svg viewBox="0 0 24 24"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg></span>
<span class="row__label">Contact us</span>
<span class="row__chevron"></span>
</a>
</div>
</div>
<div class="sign-out"><a href="#">Sign out</a></div>
<div class="signature">
<div class="signature__mark"><img src="../assets/mark-photo-64.png" alt=""></div>
<div class="signature__text">WeVisto <span class="v-mark">·</span> a frame, gifted</div>
<div class="signature__version">Edizione I · MMXXVI · Camogli</div>
</div>
</main>
<nav class="bottom-nav">
<a class="bottom-nav__tab" href="home.html">
<svg viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9,22 9,12 15,12 15,22"/></svg>
<span class="label">Home</span>
</a>
<a class="bottom-nav__tab" href="library.html">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
<span class="label">Library</span>
</a>
<a class="bottom-nav__tab active" href="settings.html">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
<span class="label">Settings</span>
</a>
</nav>
<div class="theme-switcher" role="region" aria-label="Theme switcher (mockup only)">
<span class="theme-switcher__label">Dusk</span>
<div class="theme-switcher__chips">
<button class="theme-switcher__chip active" data-theme="ocean-dusk" title="Ocean dusk"></button>
<button class="theme-switcher__chip" data-theme="amber-dusk" title="Amber dusk"></button>
<button class="theme-switcher__chip" data-theme="sage-dusk" title="Sage dusk"></button>
<button class="theme-switcher__chip" data-theme="rose-dusk" title="Rose dusk"></button>
<button class="theme-switcher__chip" data-theme="mauve-dusk" title="Mauve dusk"></button>
<button class="theme-switcher__chip" data-theme="honey-dusk" title="Honey dusk"></button>
</div>
</div>
<script>
document.querySelectorAll('.theme-switcher__chip').forEach(chip => {
chip.addEventListener('click', () => {
const t = chip.dataset.theme;
document.documentElement.setAttribute('data-theme', t);
document.querySelectorAll('.theme-switcher__chip').forEach(c => c.classList.toggle('active', c === chip));
document.querySelectorAll('.theme-swatch').forEach(s => s.classList.toggle('active', s.dataset.pref === t));
});
});
document.querySelectorAll('.theme-swatch').forEach(sw => {
sw.addEventListener('click', () => {
const t = sw.dataset.pref;
document.documentElement.setAttribute('data-theme', t);
document.querySelectorAll('.theme-swatch').forEach(s => s.classList.toggle('active', s === sw));
document.querySelectorAll('.theme-switcher__chip').forEach(c => c.classList.toggle('active', c.dataset.theme === t));
});
});
</script>
</body>
</html>