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>
@@ -0,0 +1,67 @@
|
|||||||
|
# WeVisto · atmospheric redesign
|
||||||
|
|
||||||
|
Iterative design proposal landed on 2026-05-15. Captures the **brand-as-surface**
|
||||||
|
direction: the Camogli harbor photograph is the actual background of every
|
||||||
|
authenticated view, frosted-glass cards float on it, and the six user themes
|
||||||
|
get rebuilt as atmospheric **dusks** (tinted filters over the same photo)
|
||||||
|
instead of cream variants.
|
||||||
|
|
||||||
|
## What's here
|
||||||
|
|
||||||
|
```
|
||||||
|
atmospheric-redesign/
|
||||||
|
├── index.html — entry point, links to every mockup
|
||||||
|
├── login-cinematic.html — pre-auth canonical example
|
||||||
|
├── spa/
|
||||||
|
│ ├── home.html — HomeView with new chrome + frame card + up-next strip
|
||||||
|
│ ├── library.html — LibraryView empty state (mark in halo)
|
||||||
|
│ ├── settings.html — SettingsView with the dusk picker
|
||||||
|
│ ├── _tokens.css — type + dusks (replaces cream theme system)
|
||||||
|
│ └── _chrome.css — frosted-glass app bar / bottom nav / signature
|
||||||
|
├── favicons/ — A/B/C/D icon directions (still iterating)
|
||||||
|
└── assets/
|
||||||
|
├── harbor.jpg — the brand photograph (extracted from logo.svg)
|
||||||
|
├── wordmark.svg — full WeVisto wordmark + harbor
|
||||||
|
├── mark-photo.png — split-W on harbor (512px)
|
||||||
|
├── mark-photo-64.png — same, 64px for small uses
|
||||||
|
└── mark-navy.svg — split-W on solid navy (lightweight vector mark)
|
||||||
|
```
|
||||||
|
|
||||||
|
## To view
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd webApp/_design/atmospheric-redesign
|
||||||
|
python3 -m http.server 8766 --bind 0.0.0.0
|
||||||
|
# → open http://<host>:8766/
|
||||||
|
```
|
||||||
|
|
||||||
|
Every SPA mockup defaults to Ocean Dusk and has a floating dusk-switcher
|
||||||
|
in the bottom-right — click any chip to flip the room to that dusk.
|
||||||
|
|
||||||
|
## The principle
|
||||||
|
|
||||||
|
**Brand layer (fixed):** the harbor photograph, the wordmark, the yellow V,
|
||||||
|
the split-W mark. Permanent fixed backdrop. Never changes with theme.
|
||||||
|
|
||||||
|
**Theme layer (yours):** six dusks — Ocean, Amber, Sage, Rose, Mauve, Honey.
|
||||||
|
Each is an `rgba` multiplied over the photo plus a theme-coloured accent for
|
||||||
|
primary CTAs. Same room, different time of day.
|
||||||
|
|
||||||
|
## Open work
|
||||||
|
|
||||||
|
- **Favicon mark** — A/B/C/D directions saved; Matt's feedback was that the
|
||||||
|
small mark needs more WeVisto presence "in the image itself", not just
|
||||||
|
initials. Next iteration to integrate the wordmark into the mark.
|
||||||
|
- **Logo usage across app** — currently the full wordmark logo only appears
|
||||||
|
in emails. To propagate to login splash / library hero / welcome moments /
|
||||||
|
upload success states.
|
||||||
|
- **Implementation** — these are HTML/CSS mockups, not Vue components. The
|
||||||
|
real port needs:
|
||||||
|
- Migrate `frontend/src/styles/global.scss` from six cream themes to six
|
||||||
|
dusks (replace `--color-*` cream tokens with the `--bg-tint / --glass /
|
||||||
|
--accent` tokens shown in `spa/_tokens.css`).
|
||||||
|
- Apply the harbor backdrop via `body::before` in global.scss.
|
||||||
|
- Add the top app bar component (mark + wordmark + sub + actions).
|
||||||
|
- Rebuild HomeView / LibraryView / SettingsView to use `.glass` surfaces.
|
||||||
|
- Update the Twig login / register / setup templates to share the same
|
||||||
|
backdrop + frosted-glass card pattern.
|
||||||
|
After Width: | Height: | Size: 264 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="wv-left"><rect x="0" y="0" width="32" height="64"/></clipPath>
|
||||||
|
<clipPath id="wv-right"><rect x="32" y="0" width="32" height="64"/></clipPath>
|
||||||
|
</defs>
|
||||||
|
<rect width="64" height="64" rx="12" fill="#1a3a5c"/>
|
||||||
|
<g font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif"
|
||||||
|
font-weight="900" font-size="56" text-anchor="middle">
|
||||||
|
<text x="32" y="50" fill="#fafafa" clip-path="url(#wv-left)">W</text>
|
||||||
|
<text x="32" y="50" fill="#f0d000" clip-path="url(#wv-right)">W</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 599 B |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 352 KiB |
|
After Width: | Height: | Size: 470 B |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 905 B |
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,8 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||||
|
<rect width="64" height="64" rx="10" fill="#fdf6ee"/>
|
||||||
|
<rect x="4" y="4" width="56" height="56" rx="7" fill="none" stroke="#1a3a5c" stroke-width="1.5"/>
|
||||||
|
<!-- house silhouette: roof V over a small base, with bright yellow accent in negative -->
|
||||||
|
<path d="M14 44 L32 18 L50 44 Z" fill="#1a3a5c"/>
|
||||||
|
<path d="M22 44 L32 28 L42 44 Z" fill="#fdf6ee"/>
|
||||||
|
<rect x="29" y="36" width="6" height="8" fill="#f0d000"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 481 B |
|
After Width: | Height: | Size: 428 B |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 715 B |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||||
|
<rect width="64" height="64" rx="10" fill="#1a3a5c"/>
|
||||||
|
<!-- inner frame -->
|
||||||
|
<rect x="10" y="10" width="44" height="44" rx="3" fill="#fdf6ee"/>
|
||||||
|
<rect x="13" y="13" width="38" height="38" fill="#cfe2ea"/>
|
||||||
|
<!-- sea -->
|
||||||
|
<rect x="13" y="35" width="38" height="16" fill="#4a7a9a"/>
|
||||||
|
<!-- sun -->
|
||||||
|
<circle cx="32" cy="32" r="9" fill="#f0d000"/>
|
||||||
|
<!-- frame matt highlights -->
|
||||||
|
<rect x="10" y="10" width="44" height="44" rx="3" fill="none" stroke="#0e2640" stroke-width="0.8" opacity="0.6"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 568 B |
|
After Width: | Height: | Size: 482 B |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 586 B |
|
After Width: | Height: | Size: 733 B |
@@ -0,0 +1,29 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||||
|
<rect width="64" height="64" rx="10" fill="#1a3a5c"/>
|
||||||
|
<!-- sky highlight -->
|
||||||
|
<rect x="0" y="0" width="64" height="36" fill="#2a5478"/>
|
||||||
|
<!-- buildings as colored vertical bars (Camogli houses are tall narrow row-houses in ochre/coral/cream) -->
|
||||||
|
<g>
|
||||||
|
<rect x="6" y="22" width="6" height="34" fill="#c97c3a"/>
|
||||||
|
<rect x="13" y="18" width="7" height="38" fill="#dba068"/>
|
||||||
|
<rect x="21" y="14" width="6" height="42" fill="#e8c889"/>
|
||||||
|
<rect x="28" y="20" width="7" height="36" fill="#c45230"/>
|
||||||
|
<rect x="36" y="16" width="6" height="40" fill="#dba068"/>
|
||||||
|
<rect x="43" y="22" width="7" height="34" fill="#c97c3a"/>
|
||||||
|
<rect x="51" y="19" width="6" height="37" fill="#e8c889"/>
|
||||||
|
<!-- tiny dark windows for character (only readable at >=32) -->
|
||||||
|
<g fill="#1a3a5c" opacity="0.85">
|
||||||
|
<rect x="8" y="28" width="2" height="2"/><rect x="8" y="36" width="2" height="2"/><rect x="8" y="44" width="2" height="2"/>
|
||||||
|
<rect x="15" y="24" width="2" height="2"/><rect x="15" y="32" width="2" height="2"/><rect x="15" y="40" width="2" height="2"/><rect x="15" y="48" width="2" height="2"/>
|
||||||
|
<rect x="23" y="20" width="2" height="2"/><rect x="23" y="30" width="2" height="2"/><rect x="23" y="40" width="2" height="2"/><rect x="23" y="50" width="2" height="2"/>
|
||||||
|
<rect x="30" y="26" width="2" height="2"/><rect x="30" y="36" width="2" height="2"/><rect x="30" y="46" width="2" height="2"/>
|
||||||
|
<rect x="38" y="22" width="2" height="2"/><rect x="38" y="32" width="2" height="2"/><rect x="38" y="42" width="2" height="2"/><rect x="38" y="52" width="2" height="2"/>
|
||||||
|
<rect x="45" y="28" width="2" height="2"/><rect x="45" y="38" width="2" height="2"/><rect x="45" y="48" width="2" height="2"/>
|
||||||
|
<rect x="53" y="25" width="2" height="2"/><rect x="53" y="35" width="2" height="2"/><rect x="53" y="45" width="2" height="2"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<!-- water reflection band -->
|
||||||
|
<rect x="0" y="56" width="64" height="8" fill="#5e8cb0"/>
|
||||||
|
<!-- yellow sun above buildings (the "V" accent reduced to a single dot) -->
|
||||||
|
<circle cx="51" cy="10" r="4" fill="#f0d000"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 672 B |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,32 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="wax" cx="40%" cy="35%" r="65%">
|
||||||
|
<stop offset="0%" stop-color="#b04a35"/>
|
||||||
|
<stop offset="55%" stop-color="#8a2418"/>
|
||||||
|
<stop offset="100%" stop-color="#5a140a"/>
|
||||||
|
</radialGradient>
|
||||||
|
<filter id="bevel" x="-20%" y="-20%" width="140%" height="140%">
|
||||||
|
<feGaussianBlur stdDeviation="0.6"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<rect width="64" height="64" rx="10" fill="#fdf6ee"/>
|
||||||
|
<!-- wax circle with serrated edge -->
|
||||||
|
<g transform="translate(32 33)">
|
||||||
|
<circle r="24" fill="url(#wax)"/>
|
||||||
|
<g fill="url(#wax)">
|
||||||
|
<!-- subtle serration: tiny notches around perimeter -->
|
||||||
|
<circle cx="0" cy="-24" r="1.6"/>
|
||||||
|
<circle cx="17" cy="-17" r="1.6"/>
|
||||||
|
<circle cx="24" cy="0" r="1.6"/>
|
||||||
|
<circle cx="17" cy="17" r="1.6"/>
|
||||||
|
<circle cx="0" cy="24" r="1.6"/>
|
||||||
|
<circle cx="-17" cy="17" r="1.6"/>
|
||||||
|
<circle cx="-24" cy="0" r="1.6"/>
|
||||||
|
<circle cx="-17" cy="-17" r="1.6"/>
|
||||||
|
</g>
|
||||||
|
<circle r="20" fill="none" stroke="#5a140a" stroke-width="0.8" opacity="0.65"/>
|
||||||
|
<!-- engraved V (slightly recessed/darker) -->
|
||||||
|
<path d="M-10 -10 L0 12 L10 -10" fill="none" stroke="#3a0a04" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" opacity="0.85"/>
|
||||||
|
<path d="M-10 -10 L0 12 L10 -10" fill="none" stroke="#d8a89a" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" opacity="0.5" transform="translate(-0.5 -0.5)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,262 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>WeVisto · atmospheric redesign</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">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--cream: #fdf6ee;
|
||||||
|
--cream-deep: #f5ead4;
|
||||||
|
--ink: #2a1f15;
|
||||||
|
--ink-soft: #6e6450;
|
||||||
|
--navy: #0e2740;
|
||||||
|
--yellow: #f0d000;
|
||||||
|
--rule: rgba(42,31,21,0.15);
|
||||||
|
}
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
html, body { background: var(--cream); color: var(--ink); }
|
||||||
|
body {
|
||||||
|
font-family: 'Nunito', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.55;
|
||||||
|
padding: 48px 40px 96px;
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.top { display: grid; grid-template-columns: auto 1fr auto; align-items: end; gap: 24px; padding-bottom: 14px; border-bottom: 1px solid var(--rule); }
|
||||||
|
.top .l, .top .r { font-family: 'DM Mono', monospace; font-size: 10px; letter-spacing: 0.28em; text-transform: uppercase; color: var(--ink-soft); }
|
||||||
|
.top .r { text-align: right; }
|
||||||
|
.top .name { font-family: 'Marcellus', serif; font-size: 44px; color: var(--navy); text-align: center; letter-spacing: 0.01em; }
|
||||||
|
.top .name .v { color: var(--yellow); }
|
||||||
|
.subhead { margin-top: 12px; padding-bottom: 22px; border-bottom: 1px solid var(--rule); text-align: center; font-family: 'Cormorant Garamond', serif; font-style: italic; font-size: 22px; color: var(--ink); }
|
||||||
|
|
||||||
|
h2.section { margin: 56px 0 6px; font-family: 'Marcellus', serif; font-weight: 400; font-size: 30px; color: var(--navy); }
|
||||||
|
h2.section .num { color: var(--yellow); margin-right: 8px; }
|
||||||
|
.lede { font-family: 'Cormorant Garamond', serif; font-style: italic; font-size: 19px; color: var(--ink); margin-bottom: 28px; max-width: 76ch; line-height: 1.5; }
|
||||||
|
.lede em { color: var(--navy); }
|
||||||
|
.lede strong { font-weight: 600; font-style: normal; color: var(--navy); }
|
||||||
|
|
||||||
|
.principles { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; margin: 32px 0; padding: 28px 32px; background: var(--cream-deep); border: 1px dashed rgba(42,31,21,0.25); border-radius: 8px; }
|
||||||
|
.principle h3 { font-family: 'Marcellus', serif; font-weight: 400; font-size: 18px; color: var(--navy); margin-bottom: 6px; }
|
||||||
|
.principle h3 .yellow { color: var(--yellow); }
|
||||||
|
.principle p { font-size: 14.5px; line-height: 1.55; color: var(--ink); }
|
||||||
|
.principle p strong { color: var(--navy); font-weight: 700; }
|
||||||
|
|
||||||
|
.stack { display: grid; gap: 32px; margin-top: 24px; }
|
||||||
|
.row-2 { display: grid; grid-template-columns: 1.4fr 1fr; gap: 28px; }
|
||||||
|
.row-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
|
||||||
|
.card { background: #fff9ee; border: 1px solid var(--rule); display: flex; flex-direction: column; overflow: hidden; }
|
||||||
|
.card .preview { position: relative; background: #06121f; }
|
||||||
|
.card .preview iframe { border: 0; display: block; }
|
||||||
|
.card.phone .preview { aspect-ratio: 9/16; }
|
||||||
|
.card.phone .preview iframe { width: 250%; height: 250%; transform: scale(0.4); transform-origin: top left; }
|
||||||
|
.card.wide .preview { aspect-ratio: 16/10; }
|
||||||
|
.card.wide .preview iframe { width: 200%; height: 200%; transform: scale(0.5); transform-origin: top left; }
|
||||||
|
.card .open { position: absolute; bottom: 12px; right: 12px; z-index: 5; font-family: 'DM Mono', monospace; font-size: 10px; letter-spacing: 0.28em; text-transform: uppercase; color: #fff; background: rgba(7,23,42,0.75); padding: 8px 14px; text-decoration: none; backdrop-filter: blur(6px); transition: background 150ms; }
|
||||||
|
.card .open:hover { background: var(--yellow); color: var(--navy); }
|
||||||
|
.card .body { padding: 22px 24px 24px; }
|
||||||
|
.card .body .roman { font-family: 'Marcellus', serif; font-size: 22px; color: var(--yellow); line-height: 1; margin-bottom: 4px; }
|
||||||
|
.card .body h3 { font-family: 'Marcellus', serif; font-weight: 400; font-size: 24px; color: var(--navy); margin-bottom: 6px; }
|
||||||
|
.card .body .surface { font-family: 'DM Mono', monospace; font-size: 10px; letter-spacing: 0.26em; text-transform: uppercase; color: var(--ink-soft); margin-bottom: 12px; }
|
||||||
|
.card .body p { font-size: 15px; color: var(--ink); line-height: 1.5; }
|
||||||
|
.card .body p em { color: var(--navy); font-style: italic; }
|
||||||
|
|
||||||
|
/* dusks reference strip */
|
||||||
|
.dusks { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; margin-top: 24px; }
|
||||||
|
.dusk { padding: 10px; border: 1px solid var(--rule); background: #fff9ee; text-align: center; }
|
||||||
|
.dusk .swatch { aspect-ratio: 3/2; border-radius: 4px; background-image: url('assets/harbor.jpg'); background-size: cover; position: relative; margin-bottom: 8px; overflow: hidden; }
|
||||||
|
.dusk .swatch::after { content:''; position: absolute; inset: 0; mix-blend-mode: multiply; }
|
||||||
|
.dusk[data-d="ocean"] .swatch::after { background: rgba(8, 22, 38, 0.55); }
|
||||||
|
.dusk[data-d="amber"] .swatch::after { background: rgba(60, 25, 8, 0.55); }
|
||||||
|
.dusk[data-d="sage"] .swatch::after { background: rgba(20, 40, 22, 0.55); }
|
||||||
|
.dusk[data-d="rose"] .swatch::after { background: rgba(56, 16, 38, 0.55); }
|
||||||
|
.dusk[data-d="mauve"] .swatch::after { background: rgba(40, 18, 56, 0.55); }
|
||||||
|
.dusk[data-d="honey"] .swatch::after { background: rgba(48, 36, 14, 0.55); }
|
||||||
|
.dusk .name { font-family: 'Marcellus', serif; font-size: 14px; color: var(--navy); }
|
||||||
|
.dusk .italic { font-family: 'Cormorant Garamond', serif; font-style: italic; font-size: 12px; color: var(--ink-soft); }
|
||||||
|
|
||||||
|
/* favicon section (in-progress note) */
|
||||||
|
.fav-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-top: 24px; }
|
||||||
|
.fav { background: #fff9ee; border: 1px solid var(--rule); padding: 18px; }
|
||||||
|
.fav__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
|
||||||
|
.fav__letter { font-family: 'Marcellus', serif; font-size: 22px; color: var(--yellow); line-height: 1; }
|
||||||
|
.fav__label { font-family: 'DM Mono', monospace; font-size: 9px; letter-spacing: 0.24em; text-transform: uppercase; color: var(--ink-soft); }
|
||||||
|
.fav h4 { font-family: 'Marcellus', serif; font-weight: 400; font-size: 18px; color: var(--navy); margin-bottom: 4px; }
|
||||||
|
.fav .desc { font-size: 13px; color: var(--ink); line-height: 1.45; margin-bottom: 12px; min-height: 50px; }
|
||||||
|
.fav .desc em { color: var(--navy); font-style: italic; }
|
||||||
|
.fav .pips { display: flex; gap: 10px; align-items: flex-end; padding: 10px 0; border-top: 1px solid var(--rule); }
|
||||||
|
.fav .pip { text-align: center; }
|
||||||
|
.fav .pip img { display: block; image-rendering: pixelated; margin: 0 auto 4px; border-radius: 2px; }
|
||||||
|
.fav .pip .cap { font-family: 'DM Mono', monospace; font-size: 9px; color: var(--ink-soft); }
|
||||||
|
|
||||||
|
.wip { padding: 16px 20px; background: rgba(240,208,0,0.18); border-left: 4px solid var(--yellow); margin-top: 16px; font-style: italic; color: var(--ink); font-size: 15px; }
|
||||||
|
|
||||||
|
footer { margin-top: 64px; padding-top: 22px; border-top: 1px solid var(--rule); text-align: center; font-family: 'Cormorant Garamond', serif; font-style: italic; font-size: 14px; color: var(--ink-soft); }
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
body { padding: 32px 20px; }
|
||||||
|
.row-2, .row-3, .fav-row, .principles, .dusks { grid-template-columns: 1fr; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="top">
|
||||||
|
<div class="l">Design proposal · 2026-05-15 · settled</div>
|
||||||
|
<div class="name">We<span class="v">V</span>isto</div>
|
||||||
|
<div class="r">Atmospheric system<br>login → app, one room</div>
|
||||||
|
</div>
|
||||||
|
<div class="subhead">— the brand is the surface, the theme is the tint, the photograph runs through.</div>
|
||||||
|
|
||||||
|
<h2 class="section"><span class="num">○</span>The principle, after several mis-tries</h2>
|
||||||
|
<p class="lede">The earlier proposals kept the app on cream while only the login was atmospheric. That made login feel like a different product. <strong>The right answer was to rebuild the theme system itself.</strong></p>
|
||||||
|
|
||||||
|
<div class="principles">
|
||||||
|
<div class="principle">
|
||||||
|
<h3><span class="yellow">●</span> Brand <em>is</em> the surface</h3>
|
||||||
|
<p>The Camogli harbor photograph is the permanent fixed backdrop on every authenticated view — same as the login. Cards become <strong>frosted glass</strong> floating on it. Light text on dark, Marcellus / Cormorant italic / Nunito body, the same recipe as the login. The wordmark and split-W mark live in the persistent top app bar.</p>
|
||||||
|
</div>
|
||||||
|
<div class="principle">
|
||||||
|
<h3><span class="yellow">●</span> Theme <em>is</em> the dusk</h3>
|
||||||
|
<p>The six user themes get reborn as <strong>atmospheric dusks</strong>: a tinted overlay multiplied over the same harbor photo, plus a theme-coloured accent for primary CTAs. Same room, different time of day. The yellow V is the one brand colour that survives across every dusk — wordmark, hairlines, plate numbers.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="section"><span class="num">I.</span>The dusks (replaces the six cream themes)</h2>
|
||||||
|
<p class="lede">Each chip below is the harbor photo with the dusk's tint multiplied over it — the actual recipe used in the body backdrop. Same photo, six moods.</p>
|
||||||
|
<div class="dusks">
|
||||||
|
<div class="dusk" data-d="ocean"><div class="swatch"></div><div class="name">Ocean</div><div class="italic">— the harbor</div></div>
|
||||||
|
<div class="dusk" data-d="amber"><div class="swatch"></div><div class="name">Amber</div><div class="italic">— the workshop</div></div>
|
||||||
|
<div class="dusk" data-d="sage"><div class="swatch"></div><div class="name">Sage</div><div class="italic">— the garden</div></div>
|
||||||
|
<div class="dusk" data-d="rose"><div class="swatch"></div><div class="name">Rose</div><div class="italic">— the parlor</div></div>
|
||||||
|
<div class="dusk" data-d="mauve"><div class="swatch"></div><div class="name">Mauve</div><div class="italic">— the study</div></div>
|
||||||
|
<div class="dusk" data-d="honey"><div class="swatch"></div><div class="name">Honey</div><div class="italic">— the alcove</div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="section"><span class="num">II.</span>The front door — login</h2>
|
||||||
|
<p class="lede">The canonical example of the visual language. Same harbor backdrop, deep navy filter, frosted-glass card, staggered wordmark reveal. Now also: the home page lives in the same room.</p>
|
||||||
|
<div class="stack">
|
||||||
|
<div class="card wide">
|
||||||
|
<div class="preview">
|
||||||
|
<iframe src="login-cinematic.html" loading="lazy"></iframe>
|
||||||
|
<a class="open" href="login-cinematic.html" target="_blank">Open ⟶</a>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="roman">II.</div>
|
||||||
|
<h3>Login · cinematic arrival</h3>
|
||||||
|
<div class="surface">templates/security/login.html.twig · register.html.twig</div>
|
||||||
|
<p>Animated wordmark reveal, frosted-glass card, yellow CTA. Respects <em>prefers-reduced-motion</em>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="section"><span class="num">III.</span>The room — in-app views</h2>
|
||||||
|
<p class="lede">All three default to Ocean Dusk. Use the floating chip cluster in the bottom-right of any mockup to switch dusks live — the photo re-tints, glass cards re-tint, accent button changes, the wordmark and yellow V stay constant.</p>
|
||||||
|
|
||||||
|
<div class="stack">
|
||||||
|
<div class="row-3">
|
||||||
|
|
||||||
|
<div class="card phone">
|
||||||
|
<div class="preview">
|
||||||
|
<iframe src="spa/home.html" loading="lazy"></iframe>
|
||||||
|
<a class="open" href="spa/home.html" target="_blank">Open ⟶</a>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="roman">III·a</div>
|
||||||
|
<h3>Home</h3>
|
||||||
|
<div class="surface">/ · HomeView.vue</div>
|
||||||
|
<p>Top app bar; editorial hero ("Good morning, <em>Alice.</em>"); frame card as glass with the user's frame photo inside; up-next strip of queued thumbnails.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card phone">
|
||||||
|
<div class="preview">
|
||||||
|
<iframe src="spa/library.html" loading="lazy"></iframe>
|
||||||
|
<a class="open" href="spa/library.html" target="_blank">Open ⟶</a>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="roman">III·b</div>
|
||||||
|
<h3>Library · empty state</h3>
|
||||||
|
<div class="surface">/library · LibraryView.vue</div>
|
||||||
|
<p>A 112px mark in a yellow halo, "A library, <em>waiting.</em>" in display serif, three-step glass card explaining how it works, signature.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card phone">
|
||||||
|
<div class="preview">
|
||||||
|
<iframe src="spa/settings.html" loading="lazy"></iframe>
|
||||||
|
<a class="open" href="spa/settings.html" target="_blank">Open ⟶</a>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="roman">III·c</div>
|
||||||
|
<h3>Settings</h3>
|
||||||
|
<div class="surface">/settings · SettingsView.vue</div>
|
||||||
|
<p>Glass list rows. <em>Dusk picker</em> grid showing each dusk as a tinted harbor preview — click to switch the page live.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="section"><span class="num">IV.</span>The small mark — favicon directions (work in progress)</h2>
|
||||||
|
<p class="lede">Four icon directions explored so far. Matt's still iterating here — wants WeVisto to be more present <em>inside the image itself</em>, not just initials beside the brand.</p>
|
||||||
|
|
||||||
|
<div class="wip">In progress — next iteration to integrate the wordmark into the mark and propagate the wordmark logo throughout more app surfaces.</div>
|
||||||
|
|
||||||
|
<div class="fav-row">
|
||||||
|
<div class="fav">
|
||||||
|
<div class="fav__head"><span class="fav__letter">A.</span><span class="fav__label">Warmth / home</span></div>
|
||||||
|
<h4>Roof V</h4>
|
||||||
|
<div class="desc">House silhouette where the rooftop is the V. Yellow door at centre.</div>
|
||||||
|
<div class="pips">
|
||||||
|
<div class="pip"><img src="favicons/A-roof-16.png" width="32" height="32"><div class="cap">16</div></div>
|
||||||
|
<div class="pip"><img src="favicons/A-roof-32.png" width="48" height="48"><div class="cap">32</div></div>
|
||||||
|
<div class="pip"><img src="favicons/A-roof-64.png" width="64" height="64"><div class="cap">64</div></div>
|
||||||
|
<div class="pip"><img src="favicons/A-roof-180.png" width="90" height="90"><div class="cap">180</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="fav">
|
||||||
|
<div class="fav__head"><span class="fav__letter">B.</span><span class="fav__label">Literal / poetic</span></div>
|
||||||
|
<h4>Frame + horizon</h4>
|
||||||
|
<div class="desc">A tiny photo frame with a sun over the sea. Most legible at 16.</div>
|
||||||
|
<div class="pips">
|
||||||
|
<div class="pip"><img src="favicons/B-frame-horizon-16.png" width="32" height="32"><div class="cap">16</div></div>
|
||||||
|
<div class="pip"><img src="favicons/B-frame-horizon-32.png" width="48" height="48"><div class="cap">32</div></div>
|
||||||
|
<div class="pip"><img src="favicons/B-frame-horizon-64.png" width="64" height="64"><div class="cap">64</div></div>
|
||||||
|
<div class="pip"><img src="favicons/B-frame-horizon-180.png" width="90" height="90"><div class="cap">180</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="fav">
|
||||||
|
<div class="fav__head"><span class="fav__letter">C.</span><span class="fav__label">Origin-specific</span></div>
|
||||||
|
<h4>Camogli skyline</h4>
|
||||||
|
<div class="desc">Camogli's coloured row-houses as silhouette. Risk: generic city at 16.</div>
|
||||||
|
<div class="pips">
|
||||||
|
<div class="pip"><img src="favicons/C-skyline-16.png" width="32" height="32"><div class="cap">16</div></div>
|
||||||
|
<div class="pip"><img src="favicons/C-skyline-32.png" width="48" height="48"><div class="cap">32</div></div>
|
||||||
|
<div class="pip"><img src="favicons/C-skyline-64.png" width="64" height="64"><div class="cap">64</div></div>
|
||||||
|
<div class="pip"><img src="favicons/C-skyline-180.png" width="90" height="90"><div class="cap">180</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="fav">
|
||||||
|
<div class="fav__head"><span class="fav__letter">D.</span><span class="fav__label">Gift / stationery</span></div>
|
||||||
|
<h4>Wax seal V</h4>
|
||||||
|
<div class="desc">Pressed-wax seal with V. Strong at 64+, softens at 16.</div>
|
||||||
|
<div class="pips">
|
||||||
|
<div class="pip"><img src="favicons/D-seal-16.png" width="32" height="32"><div class="cap">16</div></div>
|
||||||
|
<div class="pip"><img src="favicons/D-seal-32.png" width="48" height="48"><div class="cap">32</div></div>
|
||||||
|
<div class="pip"><img src="favicons/D-seal-64.png" width="64" height="64"><div class="cap">64</div></div>
|
||||||
|
<div class="pip"><img src="favicons/D-seal-180.png" width="90" height="90"><div class="cap">180</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Saved at <code>webApp/_design/atmospheric-redesign/</code>. Reload any mockup to replay animations.
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,349 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
|
<title>Sign in — 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=Marcellus&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--navy: #0e2740;
|
||||||
|
--navy-deep: #07172a;
|
||||||
|
--yellow: #f0d000;
|
||||||
|
--yellow-soft: #c4a700;
|
||||||
|
--cream: #faf3e4;
|
||||||
|
--cream-dim: #d8cbb0;
|
||||||
|
}
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
html, body { width: 100%; min-height: 100%; background: var(--navy-deep); color: var(--cream); }
|
||||||
|
body {
|
||||||
|
font-family: 'Cormorant Garamond', serif;
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
overflow-x: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 56px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ken-Burns harbor backdrop */
|
||||||
|
.backdrop {
|
||||||
|
position: fixed;
|
||||||
|
inset: -4%;
|
||||||
|
background: url('/assets/harbor.jpg') center/cover no-repeat;
|
||||||
|
filter: brightness(0.5) saturate(0.85);
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(1.04);
|
||||||
|
z-index: 0;
|
||||||
|
animation:
|
||||||
|
bd-fade 1.6s 0.1s cubic-bezier(.2,.7,.2,1) forwards,
|
||||||
|
bd-zoom 28s 0.1s linear forwards;
|
||||||
|
}
|
||||||
|
@keyframes bd-fade { to { opacity: 0.42; } }
|
||||||
|
@keyframes bd-zoom { from { transform: scale(1.04); } to { transform: scale(1.13) translate(-1.5%, -0.8%); } }
|
||||||
|
|
||||||
|
.vignette {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse 70% 65% at 50% 50%, transparent 0%, rgba(7,23,42,0.6) 65%, rgba(7,23,42,0.95) 100%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.grain {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 2;
|
||||||
|
background-image: 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.16 0'/></filter><rect width='320' height='320' filter='url(%23n)'/></svg>");
|
||||||
|
mix-blend-mode: overlay;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* upper stamps */
|
||||||
|
.stamp {
|
||||||
|
position: fixed;
|
||||||
|
top: 30px;
|
||||||
|
left: 32px;
|
||||||
|
font-family: 'Marcellus', serif;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.46em;
|
||||||
|
color: var(--cream);
|
||||||
|
opacity: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
z-index: 10;
|
||||||
|
animation: tag-in 1.4s 0.9s ease forwards;
|
||||||
|
}
|
||||||
|
.stamp .yellow { color: var(--yellow); }
|
||||||
|
.corner {
|
||||||
|
position: fixed;
|
||||||
|
top: 30px;
|
||||||
|
right: 32px;
|
||||||
|
font-family: 'Marcellus', serif;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.4em;
|
||||||
|
color: var(--cream);
|
||||||
|
opacity: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
z-index: 10;
|
||||||
|
animation: tag-in 1.4s 1.0s ease forwards;
|
||||||
|
}
|
||||||
|
@keyframes tag-in { to { opacity: 0.85; transform: translateY(0); } }
|
||||||
|
|
||||||
|
/* the central composition */
|
||||||
|
.stage {
|
||||||
|
position: relative;
|
||||||
|
z-index: 5;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 440px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wordmark — same staggered reveal as splash, but smaller */
|
||||||
|
.wordmark {
|
||||||
|
font-family: 'Marcellus', serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: clamp(48px, 10vw, 76px);
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--cream);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 0.005em;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
.wordmark .letter {
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0.35em) rotate(2deg);
|
||||||
|
animation: letter-in 1.0s cubic-bezier(.2,.7,.2,1) forwards;
|
||||||
|
}
|
||||||
|
.wordmark .v {
|
||||||
|
color: var(--yellow);
|
||||||
|
text-shadow: 0 1px 0 rgba(0,0,0,0.25), 0 12px 24px rgba(240,208,0,0.18);
|
||||||
|
}
|
||||||
|
.wordmark .letter:nth-child(1) { animation-delay: 0.45s; }
|
||||||
|
.wordmark .letter:nth-child(2) { animation-delay: 0.52s; }
|
||||||
|
.wordmark .letter:nth-child(3) { animation-delay: 0.66s; }
|
||||||
|
.wordmark .letter:nth-child(4) { animation-delay: 0.78s; }
|
||||||
|
.wordmark .letter:nth-child(5) { animation-delay: 0.85s; }
|
||||||
|
.wordmark .letter:nth-child(6) { animation-delay: 0.92s; }
|
||||||
|
.wordmark .letter:nth-child(7) { animation-delay: 0.99s; }
|
||||||
|
@keyframes letter-in { to { opacity: 1; transform: translateY(0) rotate(0); } }
|
||||||
|
|
||||||
|
/* tiny rule + tagline below wordmark */
|
||||||
|
.underline {
|
||||||
|
width: 0;
|
||||||
|
height: 1px;
|
||||||
|
margin: 6px auto 14px;
|
||||||
|
background: linear-gradient(90deg, transparent, var(--yellow), transparent);
|
||||||
|
animation: rule-grow 1.4s 1.25s cubic-bezier(.2,.7,.2,1) forwards;
|
||||||
|
}
|
||||||
|
@keyframes rule-grow { to { width: 180px; } }
|
||||||
|
|
||||||
|
.tagline {
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 17px;
|
||||||
|
color: var(--cream);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(8px);
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
text-align: center;
|
||||||
|
animation: tag-in 1.2s 1.7s cubic-bezier(.2,.7,.2,1) forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the sign-in panel — frosted glass card */
|
||||||
|
.panel {
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(7, 23, 42, 0.55);
|
||||||
|
border: 1px solid rgba(255, 240, 200, 0.18);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
box-shadow:
|
||||||
|
0 1px 0 rgba(255,255,255,0.06) inset,
|
||||||
|
0 30px 60px -20px rgba(0,0,0,0.65);
|
||||||
|
padding: 36px 36px 32px;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(16px);
|
||||||
|
animation: panel-in 1.2s 2.0s cubic-bezier(.2,.7,.2,1) forwards;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
@keyframes panel-in { to { opacity: 1; transform: translateY(0); } }
|
||||||
|
|
||||||
|
.panel h1 {
|
||||||
|
font-family: 'Cormorant Garamond', serif;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26px;
|
||||||
|
color: var(--cream);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
.panel .greeting {
|
||||||
|
font-family: 'Cormorant Garamond', serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--cream-dim);
|
||||||
|
margin-bottom: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field { margin-bottom: 18px; }
|
||||||
|
.field label {
|
||||||
|
display: block;
|
||||||
|
font-family: 'Marcellus', serif;
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 0.32em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--cream-dim);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.field input {
|
||||||
|
width: 100%;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid rgba(255, 240, 200, 0.28);
|
||||||
|
color: var(--cream);
|
||||||
|
font-family: 'Cormorant Garamond', serif;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 400;
|
||||||
|
padding: 8px 0 10px;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.25s ease;
|
||||||
|
}
|
||||||
|
.field input:focus {
|
||||||
|
border-color: var(--yellow);
|
||||||
|
}
|
||||||
|
.field input::placeholder { color: rgba(216, 203, 176, 0.45); font-style: italic; }
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 18px;
|
||||||
|
background: var(--yellow);
|
||||||
|
color: var(--navy-deep);
|
||||||
|
border: 0;
|
||||||
|
padding: 16px 24px;
|
||||||
|
font-family: 'Marcellus', serif;
|
||||||
|
font-size: 13px;
|
||||||
|
letter-spacing: 0.34em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.25s ease, transform 0.2s ease, box-shadow 0.25s ease;
|
||||||
|
box-shadow: 0 8px 18px -4px rgba(240,208,0,0.35);
|
||||||
|
}
|
||||||
|
.btn:hover {
|
||||||
|
background: var(--cream);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 12px 24px -4px rgba(255,240,200,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-link {
|
||||||
|
margin-top: 22px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 15px;
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--cream-dim);
|
||||||
|
}
|
||||||
|
.register-link a {
|
||||||
|
color: var(--yellow);
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid rgba(240,208,0,0.4);
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}
|
||||||
|
.register-link a:hover { border-bottom-color: var(--yellow); }
|
||||||
|
|
||||||
|
/* bottom stamp */
|
||||||
|
.footstamp {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 28px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-family: 'Marcellus', serif;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.4em;
|
||||||
|
color: var(--cream);
|
||||||
|
opacity: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
z-index: 10;
|
||||||
|
animation: tag-in 1.4s 2.6s ease forwards;
|
||||||
|
}
|
||||||
|
.footstamp .sep { margin: 0 10px; color: var(--yellow); opacity: 0.7; }
|
||||||
|
|
||||||
|
/* loader dots top-right */
|
||||||
|
.loader {
|
||||||
|
position: fixed;
|
||||||
|
top: 32px;
|
||||||
|
right: 32px;
|
||||||
|
display: none; /* mute loader on login — keep stamps only */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 520px) {
|
||||||
|
.stamp, .corner { font-size: 10px; top: 20px; }
|
||||||
|
.stamp { left: 20px; letter-spacing: 0.32em; }
|
||||||
|
.corner { right: 20px; }
|
||||||
|
.panel { padding: 28px 24px 24px; }
|
||||||
|
.footstamp { bottom: 16px; font-size: 10px; }
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.backdrop, .wordmark .letter, .tagline, .underline, .panel, .stamp, .corner, .footstamp {
|
||||||
|
animation: none !important; opacity: 1 !important; transform: none !important; width: auto !important;
|
||||||
|
}
|
||||||
|
.underline { width: 180px !important; }
|
||||||
|
.backdrop { opacity: 0.42; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="backdrop"></div>
|
||||||
|
<div class="vignette"></div>
|
||||||
|
<div class="grain"></div>
|
||||||
|
|
||||||
|
<div class="stamp">WeVisto <span class="yellow">·</span> Plate I</div>
|
||||||
|
<div class="corner">Sign in</div>
|
||||||
|
|
||||||
|
<div class="stage">
|
||||||
|
<div class="wordmark" aria-label="WeVisto">
|
||||||
|
<span class="letter">W</span>
|
||||||
|
<span class="letter">e</span>
|
||||||
|
<span class="letter v">V</span>
|
||||||
|
<span class="letter">i</span>
|
||||||
|
<span class="letter">s</span>
|
||||||
|
<span class="letter">t</span>
|
||||||
|
<span class="letter">o</span>
|
||||||
|
</div>
|
||||||
|
<div class="underline"></div>
|
||||||
|
<div class="tagline">Photographs, gifted. Quietly. Forever.</div>
|
||||||
|
|
||||||
|
<form class="panel" method="post" action="#" novalidate>
|
||||||
|
<h1>Welcome back.</h1>
|
||||||
|
<p class="greeting">— sign in to your account</p>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label for="inputEmail">Email address</label>
|
||||||
|
<input type="email" id="inputEmail" name="_username" autocomplete="email" placeholder="you@somewhere.com" autofocus>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label for="inputPassword">Password</label>
|
||||||
|
<input type="password" id="inputPassword" name="_password" autocomplete="current-password" placeholder="••••••••">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn">Sign in</button>
|
||||||
|
|
||||||
|
<p class="register-link">Don't have an account? <a href="/register">Create one</a></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footstamp">Edizione I <span class="sep">·</span> MMXXVI <span class="sep">·</span> A frame, by hand</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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>");
|
||||||
|
}
|
||||||
@@ -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>
|
||||||