feat(frontend): mockup-uri realiste ale aplicației în landing

- logo Romfast mărit; iconița aplicației (indigo) lângă „ROA Space"
- „ROA Space" în culoarea reală a aplicației (#6366f1)
- înlocuit secțiunile benefit cu screenshot-uri fidele: Dashboard, Spaces, calendar
- cardul din hero adus la același stil de screenshot al aplicației
- spațiere mai strânsă și curățat CSS-ul nefolosit

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-07-10 19:32:56 +00:00
parent 9bf407b841
commit c5a882ba6f

View File

@@ -7,6 +7,7 @@
<div class="brand"> <div class="brand">
<img src="/romfast_logo.png" alt="Romfast" class="brand-logo" /> <img src="/romfast_logo.png" alt="Romfast" class="brand-logo" />
<span class="brand-divider"></span> <span class="brand-divider"></span>
<span class="brand-app-icon"><LayoutDashboard :size="26" /></span>
<span class="brand-text"> <span class="brand-text">
<span class="brand-word">ROA Space</span> <span class="brand-word">ROA Space</span>
<span class="brand-sub">Rezervări de spații</span> <span class="brand-sub">Rezervări de spații</span>
@@ -49,106 +50,183 @@
<p class="hero-note">Cont gratuit, gata în câteva secunde.</p> <p class="hero-note">Cont gratuit, gata în câteva secunde.</p>
</div> </div>
<!-- Interactive booking card --> <!-- Interactive booking card (same app style as the mockups below) -->
<div class="demo-card"> <div class="app-window demo-window">
<div class="demo-head"> <div class="app-bar">
<div class="demo-head-title"> <span class="app-dot"></span><span class="app-dot"></span><span class="app-dot"></span>
<span class="demo-room">Sala Aurora</span> <span class="app-url">roa.space/spaces/aurora-room</span>
<span class="demo-meta">azi · 6 locuri</span>
</div> </div>
<span class="badge badge-success"><span class="badge-live-dot"></span>Live</span> <div class="demo-app">
<div class="demo-head">
<div>
<h4>Aurora Room</h4>
<p class="app-subtitle">Today · 6 seats</p>
</div>
<span class="demo-live"><span class="demo-live-dot"></span>Live</span>
</div> </div>
<div class="demo-slots"> <div class="demo-slots">
<button <button
v-for="(slot, i) in slots" v-for="(slot, i) in slots"
:key="i" :key="i"
type="button" type="button"
class="slot" class="demo-slot"
:class="{ selected: i === selected }" :class="{ selected: i === selected }"
@click="selected = i" @click="selected = i"
> >
<span class="slot-time">{{ slot.time }}</span> <span class="demo-slot-time">{{ slot.time }}</span>
<span class="slot-title" :class="{ free: !slot.booked }">{{ slot.title }}</span> <span class="demo-slot-title" :class="{ free: !slot.booked }">{{ slot.title }}</span>
<span class="badge" :class="slot.booked ? 'badge-success' : 'badge-neutral'"> <span class="demo-slot-badge" :class="slot.booked ? 'booked' : 'free'">{{ slot.statusText }}</span>
<span class="badge-dot"></span>{{ slot.statusText }}
</span>
</button> </button>
</div> </div>
<div class="demo-foot"> <div class="demo-foot">
<span class="demo-selected">{{ selectedLabel }}</span> <span class="demo-selected">{{ selectedLabel }}</span>
<button type="button" class="btn btn-primary btn-sm">Rezervă</button> <span class="app-btn">Reserve</span>
</div>
</div>
</section>
<!-- BENEFIT 1 -->
<section class="band">
<div class="split">
<div class="mini-card">
<div class="mini-card-head">
<span class="dot-red"></span>
<span class="mini-card-title">Sala Aurora 10:00</span>
<span class="mini-card-meta">deja rezervată</span>
</div>
<div class="conflict">
<span class="conflict-x"></span>
<span>Nu poți rezerva se suprapune cu ședința lui Andrei.</span>
</div>
</div>
<div>
<h2>Nicio sală rezervată de două ori.</h2>
<p>
Dacă un interval e prins, ROA Space pur și simplu nu te lasă treci peste.
Fără suprapuneri, fără discuții dar eu credeam e liberă".
</p>
</div>
</div>
</section>
<!-- BENEFIT 2 -->
<section id="cum" class="split split-steps">
<div>
<h2>Trei pași, și ai sala.</h2>
<p>
Nimeni nu are timp de formulare. Alegi, pui ora, gata — durează mai puțin decât
să scrii mesajul pe grup.
</p>
</div>
<div class="steps">
<div v-for="step in steps" :key="step.n" class="step">
<span class="step-n">{{ step.n }}</span>
<div>
<h4>{{ step.title }}</h4>
<p>{{ step.body }}</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- BENEFIT 3 --> <!-- PRODUCT SHOWCASE -->
<section class="band"> <section id="cum" class="showcase">
<div class="split"> <!-- Screen 1 Dashboard -->
<div class="app-window">
<div class="app-bar">
<span class="app-dot"></span><span class="app-dot"></span><span class="app-dot"></span>
<span class="app-url">roa.space/dashboard</span>
</div>
<div class="app-body">
<aside class="app-side">
<div class="app-brand"><LayoutDashboard :size="20" /><span>ROA Space</span></div>
<div class="app-nav-label">Main</div>
<nav class="app-nav">
<span
v-for="item in appNav"
:key="item.label"
class="app-nav-link"
:class="{ active: item.label === 'Dashboard' }"
>
<component :is="item.icon" :size="18" />
<span>{{ item.label }}</span>
</span>
</nav>
</aside>
<div class="app-content">
<div class="app-head">
<h3>Dashboard</h3>
<span class="app-btn"><Plus :size="15" />Book a Space</span>
</div>
<div class="app-pills">
<span v-for="p in dashPills" :key="p.label" class="app-pill" :class="p.tone">
<span class="app-pill-num">{{ p.num }}</span>{{ p.label }}
</span>
</div>
<div class="app-group">Today</div>
<div class="app-rows">
<div v-for="b in dashRows" :key="b.title" class="app-row" :class="b.st">
<span class="app-row-time">{{ b.time }}</span>
<span class="app-row-space">{{ b.space }}</span>
<span class="app-row-title">{{ b.title }}</span>
<span class="app-row-badge" :class="b.st">{{ b.status }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- Screen 2 Spaces -->
<div class="app-window">
<div class="app-bar">
<span class="app-dot"></span><span class="app-dot"></span><span class="app-dot"></span>
<span class="app-url">roa.space/spaces</span>
</div>
<div class="app-body">
<aside class="app-side">
<div class="app-brand"><LayoutDashboard :size="20" /><span>ROA Space</span></div>
<div class="app-nav-label">Main</div>
<nav class="app-nav">
<span
v-for="item in appNav"
:key="item.label"
class="app-nav-link"
:class="{ active: item.label === 'Spaces' }"
>
<component :is="item.icon" :size="18" />
<span>{{ item.label }}</span>
</span>
</nav>
</aside>
<div class="app-content">
<div class="app-head app-head-col">
<div> <div>
<h2>Spațiile publice, fără înregistrare obligatorie.</h2> <h3>Available Spaces</h3>
<p> <p class="app-subtitle">Browse and reserve meeting rooms and desk spaces</p>
Marchezi un spațiu ca public și poate fi rezervat și fără cont — cu nume, e-mail </div>
și ora dorită. Cine vrea își face cont, cine nu, rezervă direct. Tu păstrezi <div class="app-search"><Search :size="15" /><span>Search spaces</span></div>
controlul: fiecare cerere ajunge tot la tine spre aprobare. </div>
</p> <div class="app-grid">
<router-link to="/register" class="text-link">Deschide un spațiu public →</router-link> <div v-for="s in spaceCards" :key="s.name" class="app-card">
<div class="app-card-head">
<h4>{{ s.name }}</h4>
<span class="app-card-badge" :class="s.active ? 'ok' : 'off'">
{{ s.active ? 'Active' : 'Inactive' }}
</span>
</div>
<div class="app-card-info"><Tag :size="15" /><span class="app-lbl">Type:</span><span>{{ s.type }}</span></div>
<div class="app-card-info"><Users :size="15" /><span class="app-lbl">Capacity:</span><span>{{ s.cap }}</span></div>
<div class="app-card-info"><MapPin :size="15" /><span class="app-lbl">Location:</span><span>{{ s.loc }}</span></div>
</div>
</div>
</div>
</div>
</div>
<!-- Screen 3 Space calendar -->
<div class="app-window">
<div class="app-bar">
<span class="app-dot"></span><span class="app-dot"></span><span class="app-dot"></span>
<span class="app-url">roa.space/spaces/aurora-room</span>
</div>
<div class="app-body">
<aside class="app-side">
<div class="app-brand"><LayoutDashboard :size="20" /><span>ROA Space</span></div>
<div class="app-nav-label">Main</div>
<nav class="app-nav">
<span
v-for="item in appNav"
:key="item.label"
class="app-nav-link"
:class="{ active: item.label === 'Spaces' }"
>
<component :is="item.icon" :size="18" />
<span>{{ item.label }}</span>
</span>
</nav>
</aside>
<div class="app-content">
<div class="app-head">
<div>
<h3>Aurora Room</h3>
<p class="app-subtitle">Meeting Room · 8 people · Floor 2</p>
</div>
<span class="app-week"> Jul 6 10 </span>
</div>
<div class="app-cal">
<div class="app-cal-times">
<span v-for="t in calTimes" :key="t">{{ t }}</span>
</div>
<div v-for="day in calDays" :key="day.name" class="app-cal-col">
<div class="app-cal-day">{{ day.name }}</div>
<div class="app-cal-track">
<div
v-for="(ev, i) in day.events"
:key="i"
class="app-ev"
:class="ev.type"
:style="{ top: ev.top, height: ev.h }"
>{{ ev.label }}</div>
</div> </div>
<div class="mini-card">
<span class="eyebrow">Rezervare oaspete</span>
<div class="guest-form">
<div class="field">
<span class="field-label">Nume</span>
<div class="field-box strong">Maria Ionescu</div>
</div> </div>
<div class="field">
<span class="field-label">E-mail</span>
<div class="field-box muted">maria@exemplu.ro</div>
</div> </div>
<button type="button" class="btn btn-primary btn-md btn-block">Trimite cererea</button>
</div> </div>
</div> </div>
</div> </div>
@@ -186,6 +264,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { useLandingTheme } from '@/composables/useLandingTheme' import { useLandingTheme } from '@/composables/useLandingTheme'
import {
LayoutDashboard,
Building2,
CalendarDays,
User,
Tag,
Users,
MapPin,
Plus,
Search
} from 'lucide-vue-next'
const ctaText = 'Creează cont gratuit' const ctaText = 'Creează cont gratuit'
@@ -199,24 +288,67 @@ interface Slot {
} }
const slots: Slot[] = [ const slots: Slot[] = [
{ time: '09:00 10:00', title: 'Standup echipă', statusText: 'Ocupat', booked: true }, { time: '9:00 10:00 AM', title: 'Team standup', statusText: 'Booked', booked: true },
{ time: '11:30 12:30', title: 'Interviu', statusText: 'Ocupat', booked: true }, { time: '11:30 12:30', title: 'Interview', statusText: 'Booked', booked: true },
{ time: '13:00 — 14:00', title: 'Liber', statusText: 'Liber', booked: false }, { time: '1:00 2:00 PM', title: 'Free', statusText: 'Free', booked: false },
{ time: '14:00 — 15:30', title: 'Liber', statusText: 'Liber', booked: false }, { time: '2:00 3:30 PM', title: 'Free', statusText: 'Free', booked: false },
{ time: '16:00 — 17:00', title: 'Demo client', statusText: 'Ocupat', booked: true } { time: '4:00 5:00 PM', title: 'Client demo', statusText: 'Booked', booked: true }
] ]
const steps = [ /* ── Mockup data (faithful to the real app) ── */
{ n: '01', title: 'Alegi spațiul', body: 'Birou sau sală de ședință, din orice sediu.' }, const appNav = [
{ n: '02', title: 'Pui ora', body: 'Vezi pe loc ce e liber. Se repetă săptămânal? O bifă.' }, { label: 'Dashboard', icon: LayoutDashboard },
{ n: '03', title: 'Ești pe listă', body: 'Confirmare pe loc, sincronizată în Google Calendar.' } { label: 'Spaces', icon: Building2 },
{ label: 'History', icon: CalendarDays },
{ label: 'Profile', icon: User }
]
const dashPills = [
{ num: '12', label: 'Total', tone: 'primary' },
{ num: '3', label: 'My Pending', tone: 'warning' },
{ num: '9', label: 'Approved', tone: 'success' },
{ num: '5', label: 'Needs Approval', tone: 'danger' }
]
const dashRows = [
{ time: '9:00 AM 10:00 AM', space: 'Aurora Room', title: 'Team standup', status: 'Approved', st: 'approved' },
{ time: '11:00 AM 1:00 PM', space: 'Desk 12', title: 'Design review', status: 'Pending', st: 'pending' },
{ time: '2:30 PM 3:30 PM', space: 'North Hall', title: 'Client demo', status: 'Approved', st: 'approved' }
]
const spaceCards = [
{ name: 'Aurora Room', type: 'Meeting Room', cap: '8 people', loc: 'Floor 2 · East wing', active: true },
{ name: 'North Hall', type: 'Conference Room', cap: '20 people', loc: 'Floor 1 · Main', active: true },
{ name: 'Desk 12', type: 'Desk', cap: '1 person', loc: 'Open space A', active: true },
{ name: 'Studio B', type: 'Meeting Room', cap: '6 people', loc: 'Floor 3', active: false }
]
const calTimes = ['9 AM', '11 AM', '1 PM', '3 PM', '5 PM']
const calDays = [
{ name: 'Mon', events: [
{ label: 'Standup', type: 'busy', top: '3%', h: '13%' },
{ label: 'Interview', type: 'busy', top: '44%', h: '19%' }
] },
{ name: 'Tue', events: [
{ label: 'Design review', type: 'busy', top: '28%', h: '18%' }
] },
{ name: 'Wed', events: [
{ label: 'Planning', type: 'busy', top: '6%', h: '21%' },
{ label: 'Your booking', type: 'mine', top: '58%', h: '24%' }
] },
{ name: 'Thu', events: [
{ label: 'Client demo', type: 'busy', top: '50%', h: '19%' }
] },
{ name: 'Fri', events: [
{ label: 'Retro', type: 'mine', top: '18%', h: '17%' }
] }
] ]
const selected = ref(3) const selected = ref(3)
const selectedLabel = computed(() => { const selectedLabel = computed(() => {
const s = slots[selected.value] const s = slots[selected.value]
return s.booked ? `Ocupat · ${s.time}` : `Ai ales · ${s.time}` return s.booked ? `Booked · ${s.time}` : `Selected · ${s.time}`
}) })
</script> </script>
@@ -354,22 +486,24 @@ const selectedLabel = computed(() => {
.nav-inner { .nav-inner {
max-width: var(--container); max-width: var(--container);
margin: 0 auto; margin: 0 auto;
height: 64px; height: 80px;
padding: 0 32px; padding: 0 32px;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 28px; gap: 28px;
} }
.brand { display: flex; align-items: center; gap: 12px; } .brand { display: flex; align-items: center; gap: 14px; }
.brand-logo { height: 42px; width: auto; display: block; } .brand-logo { height: 60px; width: auto; display: block; }
.brand-divider { width: 1px; height: 30px; background: var(--border-default); } .brand-divider { width: 1px; height: 38px; background: var(--border-default); }
/* App brand color — the real accent used inside the ROA app (indigo). */
.brand-app-icon { display: flex; align-items: center; color: #6366f1; flex: none; }
.brand-text { display: flex; flex-direction: column; gap: 1px; line-height: 1.1; } .brand-text { display: flex; flex-direction: column; gap: 1px; line-height: 1.1; }
.brand-word { .brand-word {
font-family: var(--font-mark); font-family: var(--font-mark);
font-weight: 700; font-weight: 700;
font-size: 18px; font-size: 18px;
letter-spacing: -0.01em; letter-spacing: -0.01em;
color: var(--brand); color: #6366f1;
} }
.brand-sub { .brand-sub {
font-size: 0.6875rem; font-size: 0.6875rem;
@@ -403,7 +537,7 @@ const selectedLabel = computed(() => {
.hero { .hero {
max-width: var(--container); max-width: var(--container);
margin: 0 auto; margin: 0 auto;
padding: 96px 32px 72px; padding: 72px 32px 56px;
display: grid; display: grid;
grid-template-columns: 1.05fr 0.95fr; grid-template-columns: 1.05fr 0.95fr;
gap: 64px; gap: 64px;
@@ -425,173 +559,85 @@ const selectedLabel = computed(() => {
.hero-cta { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; } .hero-cta { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.hero-note { font-size: 0.875rem; color: var(--text-subtle); margin: 20px 0 0; } .hero-note { font-size: 0.875rem; color: var(--text-subtle); margin: 20px 0 0; }
/* ── Demo booking card ── */ /* ── Hero booking card (same app style as the mockups below) ── */
.demo-card { .demo-window { margin-bottom: 0; }
background: var(--surface-card); .demo-app { background: var(--sf); padding: 4px 0 0; }
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-lg);
overflow: hidden;
}
.demo-head { .demo-head {
display: flex; display: flex;
align-items: center; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
padding: 16px 20px; padding: 16px 20px 14px;
border-bottom: 1px solid var(--border-subtle); border-bottom: 1px solid var(--bd);
} }
.demo-head-title { display: flex; flex-direction: column; gap: 2px; } .demo-head h4 { font-size: 1.0625rem; font-weight: 700; color: var(--tp); margin: 0; }
.demo-room { font-size: 0.875rem; font-weight: 700; color: var(--text-strong); letter-spacing: -0.01em; } .demo-head .app-subtitle { margin-top: 3px; }
.demo-meta { font-size: 0.75rem; color: var(--text-muted); } .demo-live {
.demo-slots { display: flex; flex-direction: column; gap: 8px; padding: 16px 20px 12px; }
.slot {
display: flex;
align-items: center;
gap: 12px;
padding: 11px 12px;
border-radius: var(--radius-md);
cursor: pointer;
background: var(--surface-card);
border: 1px solid var(--border-subtle);
text-align: left;
font-family: inherit;
transition: background 180ms ease, border-color 180ms ease;
}
.slot:hover { border-color: var(--brand); }
.slot.selected { background: var(--brand-tint); border-color: var(--brand); }
.slot-time {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--text-muted);
width: 96px;
flex: none;
}
.slot-title { flex: 1; font-size: 0.875rem; font-weight: 500; color: var(--text-strong); }
.slot-title.free { color: var(--text-subtle); }
.demo-foot {
padding: 14px 20px;
border-top: 1px solid var(--border-subtle);
background: var(--surface-page);
display: flex;
align-items: center;
justify-content: space-between;
}
.demo-selected { font-size: 0.875rem; color: var(--text-body); }
/* ── Badges ── */
.badge {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
font-size: 0.6875rem;
font-weight: 600;
padding: 3px 10px; padding: 3px 10px;
border-radius: 999px; border-radius: 10px;
font-size: 0.75rem; background: color-mix(in srgb, var(--ok) 12%, transparent);
font-weight: 600; color: var(--ok);
line-height: 1;
} }
.badge-dot, .badge-live-dot { .demo-live-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: pulse 1.6s ease-in-out infinite; }
width: 6px; .demo-slots { display: flex; flex-direction: column; gap: 6px; padding: 14px 18px 10px; }
height: 6px; .demo-slot {
border-radius: 50%; display: flex;
background: currentColor; align-items: center;
gap: 12px;
padding: 10px 12px;
border-radius: 7px;
cursor: pointer;
background: var(--bg2);
border: 1px solid transparent;
text-align: left;
font-family: inherit;
transition: background 150ms ease, border-color 150ms ease;
}
.demo-slot:hover { border-color: var(--a); }
.demo-slot.selected { background: var(--a-light); border-color: var(--a); }
.demo-slot-time {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--ts);
width: 108px;
flex: none; flex: none;
} }
.badge-live-dot { animation: pulse 1.6s ease-in-out infinite; } .demo-slot-title { flex: 1; font-size: 0.8125rem; font-weight: 500; color: var(--tp); }
.badge-success { background: var(--ok-tint); color: var(--okt); } .demo-slot-title.free { color: var(--tm); }
.badge-neutral { background: color-mix(in srgb, var(--sub) 15%, var(--card)); color: var(--text-muted); } .demo-slot-badge {
font-size: 0.6875rem;
font-weight: 600;
padding: 2px 10px;
border-radius: 10px;
white-space: nowrap;
flex: none;
}
.demo-slot-badge.booked { background: var(--bg3); color: var(--ts); }
.demo-slot-badge.free { background: color-mix(in srgb, var(--ok) 15%, transparent); color: var(--ok); }
.demo-foot {
padding: 14px 18px;
border-top: 1px solid var(--bd);
background: var(--bg2);
display: flex;
align-items: center;
justify-content: space-between;
}
.demo-selected { font-size: 0.8125rem; color: var(--ts); font-weight: 500; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
/* ── Sections / splits ── */
.band { border-top: 1px solid var(--border-subtle); background: var(--surface-card); }
.split {
max-width: var(--container);
margin: 0 auto;
padding: 88px 32px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 72px;
align-items: center;
}
.split-steps { grid-template-columns: 0.85fr 1.15fr; }
.split h2, .cta-band h2 { font-size: 1.875rem; letter-spacing: -0.02em; margin-bottom: 16px; }
.split p { font-size: 1rem; line-height: 1.55; color: var(--text-muted); margin: 0; max-width: 440px; }
.text-link { display: inline-block; margin-top: 20px; font-size: 1rem; font-weight: 600; color: var(--brand); }
.text-link:hover { color: var(--brand-hover); }
/* ── Mini cards (benefit visuals) ── */
.mini-card {
background: var(--surface-page);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-md);
padding: 28px;
}
.band .mini-card { background: var(--surface-page); }
.mini-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.dot-red { width: 10px; height: 10px; border-radius: 50%; background: var(--errt); flex: none; }
.mini-card-title { font-size: 0.875rem; font-weight: 600; color: var(--text-strong); }
.mini-card-meta { font-size: 0.75rem; color: var(--text-muted); margin-left: auto; }
.conflict {
padding: 14px 16px;
border: 1px dashed var(--err-border);
background: var(--err-tint);
border-radius: var(--radius-md);
display: flex;
align-items: center;
gap: 10px;
}
.conflict-x { color: var(--errt); font-size: 18px; flex: none; }
.conflict span:last-child { font-size: 0.875rem; color: var(--errt); }
.eyebrow {
font-size: 0.75rem;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--text-subtle);
}
.guest-form { display: flex; flex-direction: column; gap: 12px; margin-top: 16px; }
.field { display: flex; flex-direction: column; gap: 5px; }
.field-label { font-size: 0.75rem; color: var(--text-muted); }
.field-box {
padding: 11px 14px;
background: var(--surface-card);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
font-size: 0.875rem;
}
.field-box.strong { color: var(--text-strong); }
.field-box.muted { color: var(--text-muted); }
/* ── Steps ── */
.steps { display: flex; flex-direction: column; }
.step {
display: flex;
gap: 20px;
align-items: flex-start;
padding: 20px 0;
border-bottom: 1px solid var(--border-subtle);
}
.step:last-child { border-bottom: none; }
.step-n {
font-family: var(--font-mark);
font-size: 24px;
font-weight: 700;
color: var(--brand);
flex: none;
width: 40px;
}
.step h4 { font-size: 1.125rem; font-weight: 600; margin-bottom: 4px; }
.step p { font-size: 0.875rem; line-height: 1.55; color: var(--text-muted); margin: 0; }
/* ── CTA band (subtle accent-tinted surface — accent stays on the button) ── */ /* ── CTA band (subtle accent-tinted surface — accent stays on the button) ── */
.cta-band { .cta-band {
background: color-mix(in srgb, var(--accent) 7%, var(--card)); background: color-mix(in srgb, var(--accent) 7%, var(--card));
border-top: 1px solid var(--border-subtle); border-top: 1px solid var(--border-subtle);
border-bottom: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle);
} }
.cta-inner { max-width: var(--container-narrow); margin: 0 auto; padding: 88px 32px; text-align: center; } .cta-inner { max-width: var(--container-narrow); margin: 0 auto; padding: 72px 32px; text-align: center; }
.cta-band h2 { color: var(--text-strong); margin-bottom: 14px; } .cta-band h2 { font-size: 1.875rem; letter-spacing: -0.02em; color: var(--text-strong); margin-bottom: 14px; }
.cta-inner p { font-size: 1.125rem; line-height: 1.55; color: var(--text-muted); margin: 0 auto 30px; max-width: 440px; } .cta-inner p { font-size: 1.125rem; line-height: 1.55; color: var(--text-muted); margin: 0 auto 30px; max-width: 440px; }
.cta-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; } .cta-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
@@ -612,16 +658,267 @@ const selectedLabel = computed(() => {
.footer-links a:hover { color: var(--brand); } .footer-links a:hover { color: var(--brand); }
.footer-copy { font-size: 0.8125rem; color: var(--text-subtle); } .footer-copy { font-size: 0.8125rem; color: var(--text-subtle); }
/* ── Product showcase (faithful app screenshots) ── */
.showcase {
max-width: 1040px;
margin: 0 auto;
padding: 40px 32px 64px;
}
/* App tokens — fixed to the real app's light theme so the mockups read as
genuine screenshots regardless of the landing theme. */
.app-window {
--a: #6366f1; --a-light: #eef2ff;
--ok: #10b981; --warn: #f59e0b; --dan: #ef4444;
--sf: #ffffff; --bg2: #f8f9fa; --bg3: #f1f3f5;
--tp: #1a1a2e; --ts: #6b7280; --tm: #9ca3af;
--bd: #e5e7eb; --bdl: #f3f4f6;
border: 1px solid var(--border-default);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-lg);
overflow: hidden;
background: var(--sf);
margin-bottom: 28px;
}
.app-window:last-child { margin-bottom: 0; }
.app-bar {
display: flex;
align-items: center;
gap: 7px;
padding: 10px 14px;
background: var(--bg3);
border-bottom: 1px solid var(--bd);
}
.app-dot { width: 10px; height: 10px; border-radius: 50%; background: #cfd3da; flex: none; }
.app-url {
margin-left: 10px;
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--ts);
background: var(--sf);
border: 1px solid var(--bd);
border-radius: 6px;
padding: 3px 12px;
}
.app-body { display: flex; background: var(--bg2); min-height: 340px; }
/* Sidebar */
.app-side {
width: 180px;
flex: none;
background: var(--sf);
border-right: 1px solid var(--bd);
padding: 14px 12px;
}
.app-brand {
display: flex;
align-items: center;
gap: 9px;
font-weight: 700;
font-size: 1rem;
color: var(--a);
padding: 6px 8px 14px;
border-bottom: 1px solid var(--bdl);
margin-bottom: 10px;
}
.app-nav-label {
font-size: 0.6875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--tm);
padding: 4px 8px 6px;
}
.app-nav { display: flex; flex-direction: column; gap: 2px; }
.app-nav-link {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 10px;
border-radius: 7px;
font-size: 0.8125rem;
font-weight: 500;
color: var(--ts);
border-left: 3px solid transparent;
}
.app-nav-link.active {
background: var(--bg3);
color: var(--tp);
border-left-color: var(--a);
font-weight: 600;
}
/* Content */
.app-content { flex: 1; padding: 20px 22px; min-width: 0; }
.app-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 14px;
margin-bottom: 18px;
}
.app-head-col { align-items: flex-start; }
.app-content h3 { font-size: 1.25rem; font-weight: 700; color: var(--tp); margin: 0; }
.app-subtitle { font-size: 0.8125rem; color: var(--ts); margin: 4px 0 0; }
.app-btn {
display: inline-flex;
align-items: center;
gap: 6px;
background: var(--a);
color: #fff;
font-size: 0.8125rem;
font-weight: 600;
padding: 8px 14px;
border-radius: 7px;
white-space: nowrap;
flex: none;
}
.app-search {
display: inline-flex;
align-items: center;
gap: 7px;
color: var(--tm);
font-size: 0.8125rem;
background: var(--sf);
border: 1px solid var(--bd);
border-radius: 7px;
padding: 8px 12px;
flex: none;
}
/* Dashboard — stat pills */
.app-pills { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
.app-pill {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 0.75rem;
font-weight: 500;
padding: 5px 11px;
border-radius: 12px;
border: 1px solid transparent;
}
.app-pill-num { font-size: 0.875rem; font-weight: 700; }
.app-pill.primary { background: var(--a-light); color: var(--a); border-color: color-mix(in srgb, var(--a) 20%, transparent); }
.app-pill.warning { background: color-mix(in srgb, var(--warn) 12%, transparent); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 22%, transparent); }
.app-pill.success { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 22%, transparent); }
.app-pill.danger { background: color-mix(in srgb, var(--dan) 12%, transparent); color: var(--dan); border-color: color-mix(in srgb, var(--dan) 22%, transparent); }
/* Dashboard — grouped rows */
.app-group {
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--ts);
padding-bottom: 6px;
border-bottom: 1px solid var(--bdl);
margin-bottom: 8px;
}
.app-rows { display: flex; flex-direction: column; gap: 5px; }
.app-row {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
min-height: 44px;
background: var(--bg2);
border-radius: 6px;
border-left: 3px solid transparent;
}
.app-row.approved { border-left-color: var(--ok); }
.app-row.pending { border-left-color: var(--warn); }
.app-row-time { font-size: 0.8125rem; font-weight: 600; color: var(--tp); white-space: nowrap; }
.app-row-space { font-size: 0.8125rem; font-weight: 500; color: var(--a); white-space: nowrap; }
.app-row-title { flex: 1; font-size: 0.8125rem; color: var(--tp); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-row-badge {
font-size: 0.6875rem;
font-weight: 600;
padding: 2px 10px;
border-radius: 10px;
white-space: nowrap;
flex: none;
}
.app-row-badge.approved { background: color-mix(in srgb, var(--ok) 15%, transparent); color: var(--ok); }
.app-row-badge.pending { background: color-mix(in srgb, var(--warn) 15%, transparent); color: var(--warn); }
/* Spaces — cards */
.app-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.app-card {
background: var(--sf);
border: 1px solid var(--bd);
border-radius: 8px;
box-shadow: var(--shadow-sm);
padding: 16px 18px;
}
.app-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.app-card-head h4 { font-size: 1.0625rem; font-weight: 700; color: var(--tp); margin: 0; }
.app-card-badge { font-size: 0.6875rem; font-weight: 600; padding: 3px 10px; border-radius: 10px; white-space: nowrap; }
.app-card-badge.ok { background: color-mix(in srgb, var(--ok) 15%, transparent); color: var(--ok); }
.app-card-badge.off { background: color-mix(in srgb, var(--dan) 15%, transparent); color: var(--dan); }
.app-card-info { display: flex; align-items: center; gap: 8px; font-size: 0.8125rem; color: var(--tp); padding: 4px 0; }
.app-card-info svg { color: var(--tm); flex: none; }
.app-lbl { color: var(--ts); font-weight: 500; }
/* Space calendar — week grid */
.app-week { font-size: 0.8125rem; font-weight: 600; color: var(--ts); background: var(--sf); border: 1px solid var(--bd); border-radius: 7px; padding: 7px 12px; white-space: nowrap; flex: none; }
.app-cal { display: grid; grid-template-columns: 40px repeat(5, 1fr); gap: 6px; }
.app-cal-times {
display: flex;
flex-direction: column;
justify-content: space-between;
padding-top: 30px;
font-family: var(--font-mono);
font-size: 0.625rem;
color: var(--tm);
}
.app-cal-col { display: flex; flex-direction: column; }
.app-cal-day { font-size: 0.75rem; font-weight: 600; color: var(--ts); text-align: center; margin-bottom: 8px; }
.app-cal-track {
position: relative;
height: 240px;
border: 1px solid var(--bd);
border-radius: 8px;
background: var(--sf);
background-image: repeating-linear-gradient(
to bottom, transparent, transparent 47px,
var(--bdl) 47px, var(--bdl) 48px
);
}
.app-ev {
position: absolute;
left: 4px; right: 4px;
border-radius: 6px;
font-size: 0.6875rem;
font-weight: 600;
padding: 4px 7px;
overflow: hidden;
line-height: 1.25;
}
.app-ev.busy { background: var(--bg3); color: var(--ts); border-left: 3px solid var(--tm); }
.app-ev.mine { background: var(--a-light); color: var(--a); border-left: 3px solid var(--a); }
/* ── Responsive ── */ /* ── Responsive ── */
@media (max-width: 900px) { @media (max-width: 900px) {
.hero, .split, .split-steps { grid-template-columns: 1fr; gap: 40px; } .hero { grid-template-columns: 1fr; gap: 40px; }
.hero { padding: 56px 24px 48px; } .hero { padding: 56px 24px 48px; }
.hero-copy h1 { font-size: 2.5rem; } .hero-copy h1 { font-size: 2.5rem; }
.split { padding: 56px 24px; }
.nav-inner { padding: 0 20px; gap: 16px; } .nav-inner { padding: 0 20px; gap: 16px; }
.nav-links { display: none; } .nav-links { display: none; }
.cta-inner { padding: 64px 24px; } .cta-inner { padding: 64px 24px; }
.footer-inner { padding: 32px 24px; } .footer-inner { padding: 32px 24px; }
.showcase { padding: 32px 20px 48px; }
}
@media (max-width: 620px) {
.app-side { display: none; }
.app-grid { grid-template-columns: 1fr; }
.app-row-title { display: none; }
.app-cal { grid-template-columns: 32px repeat(5, 1fr); gap: 4px; }
.app-cal-track { height: 180px; }
.app-search { display: none; }
} }
@media (max-width: 560px) { @media (max-width: 560px) {
.theme-label { display: none; } .theme-label { display: none; }
@@ -631,5 +928,6 @@ const selectedLabel = computed(() => {
.hero-copy h1 { font-size: 2rem; } .hero-copy h1 { font-size: 2rem; }
.btn-lg { padding: 12px 20px; font-size: 0.9375rem; } .btn-lg { padding: 12px 20px; font-size: 0.9375rem; }
.nav-login { display: none; } .nav-login { display: none; }
.app-pills { gap: 6px; }
} }
</style> </style>