- Create settings table for site-wide key-value configuration - Create images table for BLOB storage of logo/header images - Add Setting schema with JSON/string/integer/boolean support - Add ThemeSettings embedded schema with all theme options - Add Settings context with get/put/update operations - Add Media context for image uploads and retrieval - Add Image schema with SVG detection and storage - Add 9 curated theme presets (gallery, studio, boutique, etc.) - Add comprehensive tests for Settings and Media contexts - Add seeds with default Studio preset - All tests passing (29 tests, 0 failures)
6278 lines
204 KiB
HTML
6278 lines
204 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>SimpleShop Theme Studio v28</title>
|
||
|
||
<!-- Google Fonts -->
|
||
<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=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600;9..144,700&family=Inter:wght@400;500;600;700&family=Libre+Baskerville:wght@400;700&family=Nunito:wght@400;600;700&family=Nunito+Sans:opsz,wght@6..12,300;6..12,400;6..12,500;6..12,600&family=Outfit:wght@300;400;500;600&family=Source+Sans+3:wght@400;500;600&family=Space+Grotesk:wght@400;500;600&display=swap" rel="stylesheet">
|
||
|
||
<style>
|
||
/* ========================================
|
||
LAYER 1: PRIMITIVES
|
||
======================================== */
|
||
:root {
|
||
--p-space-1: 0.25rem;
|
||
--p-space-2: 0.5rem;
|
||
--p-space-3: 0.75rem;
|
||
--p-space-4: 1rem;
|
||
--p-space-6: 1.5rem;
|
||
--p-space-8: 2rem;
|
||
--p-space-12: 3rem;
|
||
--p-space-16: 4rem;
|
||
--p-space-24: 6rem;
|
||
|
||
--p-radius-none: 0;
|
||
--p-radius-sm: 0.25rem;
|
||
--p-radius-md: 0.5rem;
|
||
--p-radius-lg: 0.75rem;
|
||
--p-radius-xl: 1rem;
|
||
--p-radius-full: 9999px;
|
||
|
||
--p-font-inter: 'Inter', system-ui, sans-serif;
|
||
--p-font-fraunces: 'Fraunces', serif;
|
||
--p-font-source: 'Source Sans 3', system-ui, sans-serif;
|
||
--p-font-space: 'Space Grotesk', system-ui, sans-serif;
|
||
--p-font-baskerville: 'Libre Baskerville', Georgia, serif;
|
||
--p-font-nunito: 'Nunito', system-ui, sans-serif;
|
||
--p-font-outfit: 'Outfit', system-ui, sans-serif;
|
||
--p-font-avenir: 'Nunito Sans', 'Avenir Next', 'Avenir', system-ui, sans-serif;
|
||
|
||
--p-text-xs: 0.75rem;
|
||
--p-text-sm: 0.875rem;
|
||
--p-text-base: 1rem;
|
||
--p-text-lg: 1.125rem;
|
||
--p-text-xl: 1.25rem;
|
||
--p-text-2xl: 1.5rem;
|
||
--p-text-3xl: 1.875rem;
|
||
--p-text-4xl: 2.25rem;
|
||
|
||
--p-duration-fast: 0.1s;
|
||
--p-duration-normal: 0.2s;
|
||
--p-duration-slow: 0.35s;
|
||
|
||
--p-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||
--p-ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
|
||
--p-shadow-color: 0 0% 0%;
|
||
--p-shadow-strength: 0.06;
|
||
}
|
||
|
||
/* ========================================
|
||
LAYER 2: THEME TOKENS
|
||
======================================== */
|
||
|
||
.preview-frame {
|
||
--t-surface-base: #ffffff;
|
||
--t-surface-raised: #ffffff;
|
||
--t-surface-sunken: #f5f5f5;
|
||
--t-surface-overlay: rgba(255, 255, 255, 0.95);
|
||
--t-text-primary: #171717;
|
||
--t-text-secondary: #525252;
|
||
--t-text-tertiary: #a3a3a3;
|
||
--t-text-inverse: #ffffff;
|
||
--t-border-default: #e5e5e5;
|
||
--t-border-subtle: #f0f0f0;
|
||
}
|
||
|
||
.preview-frame[data-mood="warm"] {
|
||
--t-surface-base: #fdf8f3;
|
||
--t-surface-raised: #fffcf8;
|
||
--t-surface-sunken: #f5ebe0;
|
||
--t-text-primary: #1c1917;
|
||
--t-text-secondary: #57534e;
|
||
--t-text-tertiary: #a8a29e;
|
||
--t-border-default: #e7e0d8;
|
||
--t-border-subtle: #f0ebe4;
|
||
}
|
||
|
||
.preview-frame[data-mood="cool"] {
|
||
--t-surface-base: #f4f7fb;
|
||
--t-surface-raised: #f8fafc;
|
||
--t-surface-sunken: #e8eff7;
|
||
--t-text-primary: #0f172a;
|
||
--t-text-secondary: #475569;
|
||
--t-text-tertiary: #94a3b8;
|
||
--t-border-default: #d4dce8;
|
||
--t-border-subtle: #e8eff5;
|
||
}
|
||
|
||
.preview-frame[data-mood="dark"] {
|
||
--t-surface-base: #0a0a0a;
|
||
--t-surface-raised: #171717;
|
||
--t-surface-sunken: #000000;
|
||
--t-surface-overlay: rgba(23, 23, 23, 0.95);
|
||
--t-text-primary: #fafafa;
|
||
--t-text-secondary: #a3a3a3;
|
||
--t-text-tertiary: #737373;
|
||
--t-text-inverse: #171717;
|
||
--t-border-default: #262626;
|
||
--t-border-subtle: #1c1c1c;
|
||
--p-shadow-strength: 0.25;
|
||
}
|
||
|
||
/* Typography */
|
||
.preview-frame {
|
||
--t-font-heading: var(--p-font-inter);
|
||
--t-font-body: var(--p-font-inter);
|
||
--t-heading-weight: 600;
|
||
--t-heading-tracking: -0.025em;
|
||
}
|
||
|
||
.preview-frame[data-typography="editorial"] {
|
||
--t-font-heading: var(--p-font-fraunces);
|
||
--t-font-body: var(--p-font-source);
|
||
--t-heading-weight: 600;
|
||
--t-heading-tracking: -0.02em;
|
||
}
|
||
|
||
.preview-frame[data-typography="modern"] {
|
||
--t-font-heading: var(--p-font-space);
|
||
--t-font-body: var(--p-font-space);
|
||
--t-heading-weight: 500;
|
||
--t-heading-tracking: -0.03em;
|
||
}
|
||
|
||
.preview-frame[data-typography="classic"] {
|
||
--t-font-heading: var(--p-font-baskerville);
|
||
--t-font-body: var(--p-font-source);
|
||
--t-heading-weight: 400;
|
||
--t-heading-tracking: 0;
|
||
}
|
||
|
||
.preview-frame[data-typography="friendly"] {
|
||
--t-font-heading: var(--p-font-nunito);
|
||
--t-font-body: var(--p-font-nunito);
|
||
--t-heading-weight: 700;
|
||
--t-heading-tracking: -0.01em;
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] {
|
||
--t-font-heading: var(--p-font-outfit);
|
||
--t-font-body: var(--p-font-outfit);
|
||
--t-heading-weight: 300;
|
||
--t-heading-tracking: 0;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] {
|
||
--t-font-heading: var(--p-font-avenir);
|
||
--t-font-body: var(--p-font-avenir);
|
||
--t-heading-weight: 300;
|
||
--t-heading-tracking: 0.02em;
|
||
}
|
||
|
||
/* Shape */
|
||
.preview-frame {
|
||
--t-radius-sm: var(--p-radius-sm);
|
||
--t-radius-md: var(--p-radius-md);
|
||
--t-radius-lg: var(--p-radius-lg);
|
||
--t-radius-button: var(--p-radius-md);
|
||
--t-radius-card: var(--p-radius-lg);
|
||
--t-radius-input: var(--p-radius-md);
|
||
--t-radius-image: var(--p-radius-md);
|
||
}
|
||
|
||
.preview-frame[data-shape="sharp"] {
|
||
--t-radius-sm: 0;
|
||
--t-radius-md: 0;
|
||
--t-radius-lg: 0;
|
||
--t-radius-button: 0;
|
||
--t-radius-card: 0;
|
||
--t-radius-input: 0;
|
||
--t-radius-image: 0;
|
||
}
|
||
|
||
.preview-frame[data-shape="round"] {
|
||
--t-radius-sm: var(--p-radius-md);
|
||
--t-radius-md: var(--p-radius-lg);
|
||
--t-radius-lg: var(--p-radius-xl);
|
||
--t-radius-button: var(--p-radius-lg);
|
||
--t-radius-card: var(--p-radius-xl);
|
||
--t-radius-input: var(--p-radius-lg);
|
||
--t-radius-image: var(--p-radius-lg);
|
||
}
|
||
|
||
.preview-frame[data-shape="pill"] {
|
||
--t-radius-sm: var(--p-radius-full);
|
||
--t-radius-md: var(--p-radius-full);
|
||
--t-radius-lg: var(--p-radius-xl);
|
||
--t-radius-button: var(--p-radius-full);
|
||
--t-radius-card: var(--p-radius-xl);
|
||
--t-radius-input: var(--p-radius-full);
|
||
--t-radius-image: var(--p-radius-lg);
|
||
}
|
||
|
||
/* Density */
|
||
.preview-frame {
|
||
--t-density: 1;
|
||
}
|
||
|
||
.preview-frame[data-density="spacious"] {
|
||
--t-density: 1.25;
|
||
}
|
||
|
||
.preview-frame[data-density="compact"] {
|
||
--t-density: 0.85;
|
||
}
|
||
|
||
/* ========================================
|
||
LAYER 3: SEMANTIC TOKENS
|
||
======================================== */
|
||
|
||
.preview-frame {
|
||
--t-accent-h: 24;
|
||
--t-accent-s: 95%;
|
||
--t-accent-l: 53%;
|
||
|
||
--t-accent: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
|
||
--t-accent-hover: hsl(var(--t-accent-h) var(--t-accent-s) calc(var(--t-accent-l) - 8%));
|
||
--t-accent-subtle: hsl(var(--t-accent-h) 40% 95%);
|
||
--t-accent-ring: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l) / 0.4);
|
||
|
||
--t-secondary-accent: #ea580c;
|
||
--t-sale-color: #dc2626;
|
||
|
||
--t-font-size-scale: 1;
|
||
--t-heading-weight: 600;
|
||
|
||
--t-layout-max-width: 1400px;
|
||
--t-button-style: filled;
|
||
--t-card-shadow: none;
|
||
--t-product-text-align: left;
|
||
|
||
--color-page: var(--t-surface-base);
|
||
--color-card: var(--t-surface-raised);
|
||
--color-input: var(--t-surface-raised);
|
||
|
||
--color-heading: var(--t-text-primary);
|
||
--color-body: var(--t-text-secondary);
|
||
--color-caption: var(--t-text-tertiary);
|
||
|
||
--color-button-primary: var(--t-accent);
|
||
--color-button-primary-hover: var(--t-secondary-accent);
|
||
--color-button-primary-text: var(--t-text-inverse);
|
||
|
||
--color-border: var(--t-border-default);
|
||
|
||
--font-heading: var(--t-font-heading);
|
||
--font-body: var(--t-font-body);
|
||
--weight-heading: var(--t-heading-weight);
|
||
--tracking-heading: var(--t-heading-tracking);
|
||
|
||
--space-xs: calc(var(--p-space-2) * var(--t-density));
|
||
--space-sm: calc(var(--p-space-3) * var(--t-density));
|
||
--space-md: calc(var(--p-space-4) * var(--t-density));
|
||
--space-lg: calc(var(--p-space-6) * var(--t-density));
|
||
--space-xl: calc(var(--p-space-8) * var(--t-density));
|
||
--space-2xl: calc(var(--p-space-12) * var(--t-density));
|
||
|
||
--radius-button: var(--t-radius-button);
|
||
--radius-card: var(--t-radius-card);
|
||
--radius-input: var(--t-radius-input);
|
||
--radius-image: var(--t-radius-image);
|
||
|
||
--shadow-sm:
|
||
0 1px 2px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5)),
|
||
0 1px 3px hsl(var(--p-shadow-color) / var(--p-shadow-strength));
|
||
--shadow-md:
|
||
0 2px 4px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5)),
|
||
0 4px 8px hsl(var(--p-shadow-color) / var(--p-shadow-strength)),
|
||
0 8px 16px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5));
|
||
|
||
--transition-fast: var(--p-duration-fast) var(--p-ease-out);
|
||
--transition-normal: var(--p-duration-normal) var(--p-ease-out);
|
||
--transition-bounce: var(--p-duration-normal) var(--p-ease-out-back);
|
||
}
|
||
|
||
.preview-frame[data-mood="dark"] {
|
||
--t-accent-subtle: hsl(var(--t-accent-h) 30% 15%);
|
||
}
|
||
|
||
/* ========================================
|
||
PAGE LAYOUT
|
||
======================================== */
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
html {
|
||
font-size: 16px;
|
||
}
|
||
|
||
body {
|
||
font-family: var(--p-font-inter);
|
||
background: #f5f5f5;
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
color: #171717;
|
||
}
|
||
|
||
.page-layout {
|
||
display: grid;
|
||
grid-template-columns: 380px 1fr;
|
||
height: 100vh;
|
||
}
|
||
|
||
@media (max-width: 1000px) {
|
||
.page-layout {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
/* ========================================
|
||
CONTROLS PANEL
|
||
======================================== */
|
||
|
||
.controls-panel {
|
||
background: #ffffff;
|
||
border-right: 1px solid #e5e5e5;
|
||
padding: var(--p-space-6);
|
||
overflow-y: auto;
|
||
max-height: 100vh;
|
||
position: sticky;
|
||
top: 0;
|
||
}
|
||
|
||
.controls-header {
|
||
margin-bottom: var(--p-space-6);
|
||
}
|
||
|
||
.controls-header h1 {
|
||
font-size: var(--p-text-xl);
|
||
font-weight: 600;
|
||
margin-bottom: var(--p-space-2);
|
||
letter-spacing: -0.025em;
|
||
}
|
||
|
||
.controls-header p {
|
||
font-size: var(--p-text-sm);
|
||
color: #737373;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.control-section {
|
||
margin-bottom: var(--p-space-6);
|
||
}
|
||
|
||
.control-label {
|
||
font-size: var(--p-text-xs);
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
color: #737373;
|
||
margin-bottom: var(--p-space-3);
|
||
display: block;
|
||
}
|
||
|
||
/* Customise accordion */
|
||
.customise-section {
|
||
border-top: 1px solid #e5e5e5;
|
||
margin-top: var(--p-space-6);
|
||
padding-top: var(--p-space-4);
|
||
}
|
||
|
||
.customise-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--p-space-3) 0;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.customise-header:hover .customise-title {
|
||
color: #171717;
|
||
}
|
||
|
||
.customise-title {
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 600;
|
||
color: #525252;
|
||
transition: color 0.15s ease;
|
||
}
|
||
|
||
.customise-icon {
|
||
width: 20px;
|
||
height: 20px;
|
||
color: #a3a3a3;
|
||
transition: transform 0.2s ease;
|
||
}
|
||
|
||
.customise-section.open .customise-icon {
|
||
transform: rotate(180deg);
|
||
}
|
||
|
||
.customise-content {
|
||
display: none;
|
||
padding-top: var(--p-space-4);
|
||
}
|
||
|
||
.customise-section.open .customise-content {
|
||
display: block;
|
||
}
|
||
|
||
/* Control groups within customise */
|
||
.control-group {
|
||
margin-bottom: var(--p-space-6);
|
||
padding-bottom: var(--p-space-6);
|
||
border-bottom: 1px solid #f0f0f0;
|
||
}
|
||
|
||
.control-group:last-child {
|
||
margin-bottom: 0;
|
||
padding-bottom: 0;
|
||
border-bottom: none;
|
||
}
|
||
|
||
.control-group-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--p-space-2);
|
||
margin-bottom: var(--p-space-4);
|
||
}
|
||
|
||
.control-group-icon {
|
||
width: 16px;
|
||
height: 16px;
|
||
color: #a3a3a3;
|
||
}
|
||
|
||
.control-group-title {
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 600;
|
||
color: #171717;
|
||
}
|
||
|
||
.control-group .control-section {
|
||
margin-bottom: var(--p-space-4);
|
||
}
|
||
|
||
.control-group .control-section:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
/* Text input */
|
||
.text-input {
|
||
width: 100%;
|
||
padding: var(--p-space-3) var(--p-space-4);
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: var(--p-radius-md);
|
||
font-size: var(--p-text-base);
|
||
font-family: inherit;
|
||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||
}
|
||
|
||
.text-input:focus {
|
||
outline: none;
|
||
border-color: #171717;
|
||
box-shadow: 0 0 0 3px rgba(0,0,0,0.05);
|
||
}
|
||
|
||
/* Logo/Header section */
|
||
.branding-section {
|
||
background: #f9f9f9;
|
||
border-radius: var(--p-radius-lg);
|
||
padding: var(--p-space-4);
|
||
margin-bottom: var(--p-space-6);
|
||
}
|
||
|
||
.branding-section .control-label {
|
||
margin-bottom: var(--p-space-4);
|
||
}
|
||
|
||
.logo-mode-options {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--p-space-2);
|
||
margin-bottom: var(--p-space-4);
|
||
}
|
||
|
||
.logo-mode-option {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--p-space-3);
|
||
padding: var(--p-space-3);
|
||
background: #ffffff;
|
||
border: 2px solid transparent;
|
||
border-radius: var(--p-radius-md);
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.logo-mode-option:hover {
|
||
border-color: #e5e5e5;
|
||
}
|
||
|
||
.logo-mode-option.active {
|
||
border-color: #171717;
|
||
}
|
||
|
||
.logo-mode-option input[type="radio"] {
|
||
display: none;
|
||
}
|
||
|
||
.logo-mode-radio {
|
||
width: 18px;
|
||
height: 18px;
|
||
border: 2px solid #d4d4d4;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.logo-mode-option.active .logo-mode-radio {
|
||
border-color: #171717;
|
||
}
|
||
|
||
.logo-mode-radio::after {
|
||
content: '';
|
||
width: 8px;
|
||
height: 8px;
|
||
background: #171717;
|
||
border-radius: 50%;
|
||
opacity: 0;
|
||
transform: scale(0);
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.logo-mode-option.active .logo-mode-radio::after {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
|
||
.logo-mode-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.logo-mode-title {
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.logo-mode-desc {
|
||
font-size: var(--p-text-xs);
|
||
color: #737373;
|
||
}
|
||
|
||
/* Upload areas */
|
||
.upload-section {
|
||
margin-top: var(--p-space-4);
|
||
padding-top: var(--p-space-4);
|
||
border-top: 1px solid #e5e5e5;
|
||
}
|
||
|
||
.upload-row {
|
||
display: none;
|
||
margin-bottom: var(--p-space-3);
|
||
}
|
||
|
||
.upload-row.visible {
|
||
display: block;
|
||
}
|
||
|
||
.upload-label {
|
||
font-size: var(--p-text-xs);
|
||
font-weight: 500;
|
||
color: #525252;
|
||
margin-bottom: var(--p-space-2);
|
||
display: block;
|
||
}
|
||
|
||
.upload-area {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--p-space-3);
|
||
}
|
||
|
||
.upload-btn {
|
||
flex: 1;
|
||
background: #ffffff;
|
||
border: 1px dashed #d4d4d4;
|
||
border-radius: var(--p-radius-md);
|
||
padding: var(--p-space-3);
|
||
font-size: var(--p-text-sm);
|
||
color: #737373;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
text-align: center;
|
||
}
|
||
|
||
.upload-btn:hover {
|
||
border-color: #a3a3a3;
|
||
color: #525252;
|
||
}
|
||
|
||
.upload-btn input {
|
||
display: none;
|
||
}
|
||
|
||
.upload-preview {
|
||
width: 64px;
|
||
height: 40px;
|
||
background: #ffffff;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: var(--p-radius-md);
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
|
||
.upload-preview.has-image {
|
||
display: flex;
|
||
}
|
||
|
||
.upload-preview img {
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
object-fit: contain;
|
||
}
|
||
|
||
.upload-preview-wide {
|
||
width: 100%;
|
||
height: 60px;
|
||
margin-top: var(--p-space-2);
|
||
}
|
||
|
||
.upload-preview-wide img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.remove-upload {
|
||
position: absolute;
|
||
top: -6px;
|
||
right: -6px;
|
||
width: 18px;
|
||
height: 18px;
|
||
background: #171717;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 50%;
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* Size control slider */
|
||
.size-control {
|
||
margin-top: var(--p-space-3);
|
||
display: none;
|
||
}
|
||
|
||
.size-control.visible {
|
||
display: block;
|
||
}
|
||
|
||
.size-control-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: var(--p-space-2);
|
||
}
|
||
|
||
.size-control-label {
|
||
font-size: var(--p-text-xs);
|
||
font-weight: 500;
|
||
color: #525252;
|
||
}
|
||
|
||
.size-control-value {
|
||
font-family: 'SF Mono', Monaco, monospace;
|
||
font-size: var(--p-text-xs);
|
||
color: #737373;
|
||
}
|
||
|
||
.size-slider {
|
||
width: 100%;
|
||
height: 6px;
|
||
border-radius: 3px;
|
||
background: #e5e5e5;
|
||
outline: none;
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
}
|
||
|
||
.size-slider::-webkit-slider-thumb {
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 50%;
|
||
background: #171717;
|
||
cursor: pointer;
|
||
transition: transform 0.1s ease;
|
||
}
|
||
|
||
.size-slider::-webkit-slider-thumb:hover {
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
.size-slider::-moz-range-thumb {
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 50%;
|
||
background: #171717;
|
||
cursor: pointer;
|
||
border: none;
|
||
}
|
||
|
||
/* Header image controls */
|
||
.header-image-controls {
|
||
margin-top: var(--p-space-3);
|
||
display: none;
|
||
flex-direction: column;
|
||
gap: var(--p-space-3);
|
||
}
|
||
|
||
.header-image-controls.visible {
|
||
display: flex;
|
||
}
|
||
|
||
.control-row {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--p-space-2);
|
||
}
|
||
|
||
#header-position-x-row {
|
||
display: none;
|
||
}
|
||
|
||
#header-position-x-row.visible {
|
||
display: flex;
|
||
}
|
||
|
||
/* Logo color control */
|
||
.logo-color-control {
|
||
margin-top: var(--p-space-3);
|
||
display: none;
|
||
}
|
||
|
||
.logo-color-control.visible {
|
||
display: block;
|
||
}
|
||
|
||
.logo-color-toggle {
|
||
margin-bottom: var(--p-space-2);
|
||
}
|
||
|
||
.toggle-label {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--p-space-2);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.toggle-label input[type="checkbox"] {
|
||
display: none;
|
||
}
|
||
|
||
.toggle-switch {
|
||
width: 36px;
|
||
height: 20px;
|
||
background: #e5e5e5;
|
||
border-radius: 10px;
|
||
position: relative;
|
||
transition: background 0.2s ease;
|
||
}
|
||
|
||
.toggle-switch::after {
|
||
content: '';
|
||
position: absolute;
|
||
width: 16px;
|
||
height: 16px;
|
||
background: white;
|
||
border-radius: 50%;
|
||
top: 2px;
|
||
left: 2px;
|
||
transition: transform 0.2s ease;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||
}
|
||
|
||
.toggle-label input:checked + .toggle-switch {
|
||
background: #171717;
|
||
}
|
||
|
||
.toggle-label input:checked + .toggle-switch::after {
|
||
transform: translateX(16px);
|
||
}
|
||
|
||
.toggle-text {
|
||
font-size: var(--p-text-sm);
|
||
color: #525252;
|
||
}
|
||
|
||
.toggle-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--p-space-2);
|
||
}
|
||
|
||
.toggle-list .toggle-label {
|
||
padding: var(--p-space-2) 0;
|
||
}
|
||
|
||
.logo-color-picker-row {
|
||
display: none;
|
||
align-items: center;
|
||
gap: var(--p-space-3);
|
||
margin-top: var(--p-space-2);
|
||
}
|
||
|
||
.logo-color-picker-row.visible {
|
||
display: flex;
|
||
}
|
||
|
||
.color-picker-small {
|
||
width: 36px;
|
||
height: 36px;
|
||
}
|
||
|
||
/* Preset grid */
|
||
.preset-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: var(--p-space-2);
|
||
margin-bottom: var(--p-space-6);
|
||
}
|
||
|
||
.preset-button {
|
||
background: #f5f5f5;
|
||
border: 2px solid transparent;
|
||
border-radius: var(--p-radius-md);
|
||
padding: var(--p-space-3);
|
||
cursor: pointer;
|
||
text-align: left;
|
||
transition: all var(--p-duration-normal) var(--p-ease-out);
|
||
font-family: inherit;
|
||
}
|
||
|
||
.preset-button:hover {
|
||
background: #ebebeb;
|
||
}
|
||
|
||
.preset-button.active {
|
||
border-color: #171717;
|
||
background: #ffffff;
|
||
}
|
||
|
||
.preset-button .preset-name {
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 600;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.preset-button .preset-desc {
|
||
font-size: var(--p-text-xs);
|
||
color: #737373;
|
||
}
|
||
|
||
/* Option buttons */
|
||
.option-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--p-space-2);
|
||
}
|
||
|
||
.option-button {
|
||
background: #f5f5f5;
|
||
border: 2px solid transparent;
|
||
border-radius: var(--p-radius-md);
|
||
padding: var(--p-space-2) var(--p-space-3);
|
||
cursor: pointer;
|
||
font-size: var(--p-text-sm);
|
||
font-family: inherit;
|
||
transition: all var(--p-duration-normal) var(--p-ease-out);
|
||
}
|
||
|
||
.option-button:hover {
|
||
background: #ebebeb;
|
||
}
|
||
|
||
.option-button.active {
|
||
border-color: #171717;
|
||
background: #ffffff;
|
||
}
|
||
|
||
/* Color picker */
|
||
.color-picker-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--p-space-3);
|
||
}
|
||
|
||
.color-picker {
|
||
width: 48px;
|
||
height: 48px;
|
||
border: none;
|
||
border-radius: var(--p-radius-md);
|
||
cursor: pointer;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.color-picker::-webkit-color-swatch-wrapper {
|
||
padding: 0;
|
||
}
|
||
|
||
.color-picker::-webkit-color-swatch {
|
||
border: 2px solid rgba(0,0,0,0.1);
|
||
border-radius: var(--p-radius-md);
|
||
}
|
||
|
||
.color-value {
|
||
font-family: 'SF Mono', Monaco, monospace;
|
||
font-size: var(--p-text-sm);
|
||
color: #525252;
|
||
}
|
||
|
||
/* Combo display */
|
||
.combo-display {
|
||
background: #f5f5f5;
|
||
border-radius: var(--p-radius-md);
|
||
padding: var(--p-space-4);
|
||
margin-top: var(--p-space-6);
|
||
}
|
||
|
||
.combo-display .combo-label {
|
||
font-size: var(--p-text-xs);
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
color: #737373;
|
||
margin-bottom: var(--p-space-2);
|
||
}
|
||
|
||
.combo-display .combo-value {
|
||
font-size: var(--p-text-sm);
|
||
color: #171717;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.combo-display .combo-count {
|
||
font-size: var(--p-text-xs);
|
||
color: #a3a3a3;
|
||
margin-top: var(--p-space-2);
|
||
}
|
||
|
||
/* ========================================
|
||
PREVIEW AREA
|
||
======================================== */
|
||
|
||
.preview-area {
|
||
padding: var(--p-space-6);
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
height: 100%;
|
||
}
|
||
|
||
.preview-container {
|
||
width: 100%;
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 1;
|
||
min-height: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.page-toggle {
|
||
display: flex;
|
||
gap: var(--p-space-1);
|
||
margin-bottom: var(--p-space-3);
|
||
background: #e5e5e5;
|
||
padding: 4px;
|
||
border-radius: var(--p-radius-md);
|
||
width: fit-content;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.page-toggle-btn {
|
||
padding: var(--p-space-2) var(--p-space-4);
|
||
border: none;
|
||
background: transparent;
|
||
border-radius: var(--p-radius-sm);
|
||
font-family: inherit;
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: #525252;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.page-toggle-btn:hover {
|
||
color: #171717;
|
||
}
|
||
|
||
.page-toggle-btn.active {
|
||
background: #ffffff;
|
||
color: #171717;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
/* Browser Chrome Mockup - macOS style */
|
||
.browser-chrome {
|
||
display: flex;
|
||
align-items: center;
|
||
background: linear-gradient(180deg, #e8e8e8 0%, #d8d8d8 100%);
|
||
border: 1px solid #c0c0c0;
|
||
border-bottom: 1px solid #b0b0b0;
|
||
border-radius: 10px 10px 0 0;
|
||
padding: 10px 14px;
|
||
gap: 14px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.browser-traffic-lights {
|
||
display: flex;
|
||
gap: 8px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.traffic-light {
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.traffic-light.red { background: #ff5f57; border-color: #e14640; }
|
||
.traffic-light.yellow { background: #ffbd2e; border-color: #dfa123; }
|
||
.traffic-light.green { background: #28c940; border-color: #1aab29; }
|
||
|
||
.browser-nav {
|
||
display: flex;
|
||
gap: 6px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.browser-nav-btn {
|
||
width: 24px;
|
||
height: 24px;
|
||
border-radius: 4px;
|
||
background: transparent;
|
||
border: none;
|
||
color: #999;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: default;
|
||
}
|
||
|
||
.browser-nav-btn svg {
|
||
width: 14px;
|
||
height: 14px;
|
||
}
|
||
|
||
.browser-url-bar {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
background: #ffffff;
|
||
border: 1px solid #c0c0c0;
|
||
border-radius: 6px;
|
||
padding: 5px 12px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.browser-url-icon {
|
||
width: 14px;
|
||
height: 14px;
|
||
color: #28c940;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.browser-favicon {
|
||
width: 16px;
|
||
height: 16px;
|
||
border-radius: 3px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
flex-shrink: 0;
|
||
background: var(--t-accent, #e85d04);
|
||
}
|
||
|
||
.browser-favicon.has-logo {
|
||
background: transparent;
|
||
}
|
||
|
||
.favicon-letter {
|
||
font-family: system-ui, sans-serif;
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
color: white;
|
||
}
|
||
|
||
.browser-favicon.has-logo .favicon-letter {
|
||
display: none;
|
||
}
|
||
|
||
.favicon-logo {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
}
|
||
|
||
.browser-url-text {
|
||
font-family: system-ui, sans-serif;
|
||
font-size: 12px;
|
||
color: #333;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.browser-url-text .domain {
|
||
color: #111;
|
||
}
|
||
|
||
.browser-actions {
|
||
display: flex;
|
||
gap: 8px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.browser-action-btn {
|
||
width: 24px;
|
||
height: 24px;
|
||
border-radius: 4px;
|
||
background: transparent;
|
||
border: none;
|
||
color: #666;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: default;
|
||
}
|
||
|
||
.browser-action-btn svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
|
||
.preview-frame {
|
||
width: 100%;
|
||
flex: 1;
|
||
min-height: 0;
|
||
background: var(--color-page);
|
||
border-radius: 0 0 var(--p-radius-lg) var(--p-radius-lg);
|
||
border: 1px solid #c0c0c0;
|
||
border-top: none;
|
||
box-shadow:
|
||
0 4px 6px rgba(0,0,0,0.05),
|
||
0 10px 20px rgba(0,0,0,0.05),
|
||
0 20px 40px rgba(0,0,0,0.05);
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
transition: background-color var(--p-duration-slow) var(--p-ease-out);
|
||
}
|
||
|
||
/* Styled scrollbar for the preview */
|
||
.preview-frame::-webkit-scrollbar {
|
||
width: 10px;
|
||
}
|
||
|
||
.preview-frame::-webkit-scrollbar-track {
|
||
background: rgba(0,0,0,0.05);
|
||
}
|
||
|
||
.preview-frame::-webkit-scrollbar-thumb {
|
||
background: rgba(0,0,0,0.2);
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.preview-frame::-webkit-scrollbar-thumb:hover {
|
||
background: rgba(0,0,0,0.3);
|
||
}
|
||
|
||
/* Announcement bar */
|
||
.announcement-bar {
|
||
background: var(--t-accent);
|
||
color: var(--t-text-inverse);
|
||
text-align: center;
|
||
padding: var(--space-xs) var(--space-md);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
.announcement-bar.hidden {
|
||
display: none;
|
||
}
|
||
|
||
.announcement-bar p {
|
||
margin: 0;
|
||
}
|
||
|
||
/* Sticky header */
|
||
.preview-frame[data-sticky-header="true"] .shop-header {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
box-shadow: var(--shadow-sm);
|
||
}
|
||
|
||
.preview-frame[data-sticky-header="true"][data-has-announcement="true"] .shop-header {
|
||
top: 0;
|
||
}
|
||
|
||
/* ========================================
|
||
SHOP HEADER MODES
|
||
======================================== */
|
||
|
||
.shop-header {
|
||
padding: var(--space-md) var(--space-lg);
|
||
border-bottom: 1px solid var(--color-border);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
transition: all var(--transition-normal);
|
||
position: relative;
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.shop-header[data-header="centered"] {
|
||
flex-direction: column;
|
||
gap: var(--space-sm);
|
||
text-align: center;
|
||
}
|
||
|
||
.shop-header[data-header="minimal"] .shop-nav {
|
||
display: none;
|
||
}
|
||
|
||
/* Header with background image */
|
||
.shop-header[data-logo-mode="header-image"] {
|
||
min-height: 160px;
|
||
padding: var(--space-lg);
|
||
border-bottom: none;
|
||
background-size: cover;
|
||
background-position: center;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="header-image"]::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background: linear-gradient(to bottom, rgba(0,0,0,0.3), rgba(0,0,0,0.5));
|
||
pointer-events: none;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="header-image"] .shop-logo,
|
||
.shop-header[data-logo-mode="header-image"] .shop-nav a,
|
||
.shop-header[data-logo-mode="header-image"] .shop-cart {
|
||
position: relative;
|
||
z-index: 1;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="header-image"] .shop-logo-text {
|
||
color: #ffffff;
|
||
text-shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||
}
|
||
|
||
.shop-header[data-logo-mode="header-image"] .cart-icon {
|
||
stroke: #ffffff;
|
||
}
|
||
|
||
/* Header with logo + background image */
|
||
.shop-header[data-logo-mode="logo-header-image"] {
|
||
min-height: 160px;
|
||
padding: var(--space-lg);
|
||
border-bottom: none;
|
||
background-size: cover;
|
||
background-position: center;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="logo-header-image"]::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background: linear-gradient(to bottom, rgba(0,0,0,0.3), rgba(0,0,0,0.5));
|
||
pointer-events: none;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="logo-header-image"] .shop-logo,
|
||
.shop-header[data-logo-mode="logo-header-image"] .shop-nav a,
|
||
.shop-header[data-logo-mode="logo-header-image"] .shop-cart {
|
||
position: relative;
|
||
z-index: 1;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="logo-header-image"] .cart-icon {
|
||
stroke: #ffffff;
|
||
}
|
||
|
||
/* Logo display */
|
||
.shop-logo {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
.shop-logo-text {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
.shop-logo-image {
|
||
height: 36px;
|
||
width: auto;
|
||
display: none;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.shop-logo-image.visible {
|
||
display: block;
|
||
}
|
||
|
||
.shop-logo-image img {
|
||
height: 100%;
|
||
width: auto;
|
||
object-fit: contain;
|
||
}
|
||
|
||
.shop-nav {
|
||
display: flex;
|
||
gap: var(--space-lg);
|
||
}
|
||
|
||
.shop-nav a {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
text-decoration: none;
|
||
transition: color var(--transition-fast);
|
||
}
|
||
|
||
.shop-nav a:hover {
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.shop-cart {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.cart-count {
|
||
background: var(--t-accent);
|
||
color: var(--t-text-inverse);
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* Hero */
|
||
.shop-hero {
|
||
padding: var(--space-2xl) var(--space-lg);
|
||
text-align: center;
|
||
transition: all var(--transition-normal);
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.shop-hero h1 {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-4xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
margin-bottom: var(--space-sm);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
/* Minimal/Impulse style - much larger, lighter hero text */
|
||
.preview-frame[data-typography="minimal"] .shop-hero {
|
||
padding: var(--space-2xl) var(--space-lg) calc(var(--space-2xl) * 1.5);
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] .shop-hero h1 {
|
||
font-size: clamp(2.5rem, 5vw, 4rem);
|
||
font-weight: 300;
|
||
letter-spacing: -0.02em;
|
||
margin-bottom: var(--space-md);
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] .shop-hero p {
|
||
font-weight: 300;
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.shop-hero p {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-lg);
|
||
color: var(--color-body);
|
||
max-width: 500px;
|
||
margin: 0 auto var(--space-lg);
|
||
line-height: 1.6;
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
/* Buttons */
|
||
.btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-family: var(--font-body);
|
||
font-weight: 500;
|
||
font-size: var(--p-text-sm);
|
||
padding: var(--space-sm) var(--space-lg);
|
||
border-radius: var(--radius-button);
|
||
border: none;
|
||
cursor: pointer;
|
||
transition:
|
||
transform var(--transition-bounce),
|
||
box-shadow var(--transition-normal),
|
||
background-color var(--transition-fast);
|
||
}
|
||
|
||
.btn:hover {
|
||
transform: translateY(-1px);
|
||
box-shadow: var(--shadow-md);
|
||
}
|
||
|
||
.btn:active {
|
||
transform: translateY(0);
|
||
transition-duration: 0.05s;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: var(--color-button-primary);
|
||
color: var(--color-button-primary-text);
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background: var(--color-button-primary-hover);
|
||
}
|
||
|
||
/* Button style variations */
|
||
.preview-frame[data-button-style="outline"] .btn-primary {
|
||
background: transparent;
|
||
color: var(--color-button-primary);
|
||
border: 2px solid var(--color-button-primary);
|
||
}
|
||
|
||
.preview-frame[data-button-style="outline"] .btn-primary:hover {
|
||
background: var(--color-button-primary);
|
||
color: var(--color-button-primary-text);
|
||
}
|
||
|
||
.preview-frame[data-button-style="soft"] .btn-primary {
|
||
background: var(--t-accent-subtle);
|
||
color: var(--color-button-primary);
|
||
}
|
||
|
||
.preview-frame[data-button-style="soft"] .btn-primary:hover {
|
||
background: var(--color-button-primary);
|
||
color: var(--color-button-primary-text);
|
||
}
|
||
|
||
/* Layout width variations - controls content width within the full-width browser */
|
||
.preview-frame[data-layout-width="contained"] .shop-hero,
|
||
.preview-frame[data-layout-width="contained"] .product-section,
|
||
.preview-frame[data-layout-width="contained"] .home-categories,
|
||
.preview-frame[data-layout-width="contained"] .home-about,
|
||
.preview-frame[data-layout-width="contained"] .pdp-container,
|
||
.preview-frame[data-layout-width="contained"] .pdp-reviews,
|
||
.preview-frame[data-layout-width="contained"] .pdp-related,
|
||
.preview-frame[data-layout-width="contained"] .cart-container,
|
||
.preview-frame[data-layout-width="contained"] .content-page,
|
||
.preview-frame[data-layout-width="contained"] .error-container,
|
||
.preview-frame[data-layout-width="contained"] .collection-header,
|
||
.preview-frame[data-layout-width="contained"] .collection-grid-container {
|
||
max-width: 800px;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
padding-left: var(--space-lg);
|
||
padding-right: var(--space-lg);
|
||
}
|
||
|
||
.preview-frame[data-layout-width="wide"] .shop-hero,
|
||
.preview-frame[data-layout-width="wide"] .product-section,
|
||
.preview-frame[data-layout-width="wide"] .home-categories,
|
||
.preview-frame[data-layout-width="wide"] .home-about,
|
||
.preview-frame[data-layout-width="wide"] .pdp-container,
|
||
.preview-frame[data-layout-width="wide"] .pdp-reviews,
|
||
.preview-frame[data-layout-width="wide"] .pdp-related,
|
||
.preview-frame[data-layout-width="wide"] .cart-container,
|
||
.preview-frame[data-layout-width="wide"] .content-page,
|
||
.preview-frame[data-layout-width="wide"] .error-container,
|
||
.preview-frame[data-layout-width="wide"] .collection-header,
|
||
.preview-frame[data-layout-width="wide"] .collection-grid-container {
|
||
max-width: 1000px;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
/* Full width has no max-width constraint */
|
||
.preview-frame[data-layout-width="full"] .shop-hero,
|
||
.preview-frame[data-layout-width="full"] .product-section,
|
||
.preview-frame[data-layout-width="full"] .home-categories,
|
||
.preview-frame[data-layout-width="full"] .home-about,
|
||
.preview-frame[data-layout-width="full"] .pdp-container,
|
||
.preview-frame[data-layout-width="full"] .pdp-reviews,
|
||
.preview-frame[data-layout-width="full"] .pdp-related,
|
||
.preview-frame[data-layout-width="full"] .cart-container,
|
||
.preview-frame[data-layout-width="full"] .content-page,
|
||
.preview-frame[data-layout-width="full"] .error-container,
|
||
.preview-frame[data-layout-width="full"] .collection-header,
|
||
.preview-frame[data-layout-width="full"] .collection-grid-container {
|
||
max-width: none;
|
||
}
|
||
|
||
/* Font size scale */
|
||
.preview-frame[data-font-size="small"] {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.preview-frame[data-font-size="medium"] {
|
||
font-size: 16px;
|
||
}
|
||
|
||
.preview-frame[data-font-size="large"] {
|
||
font-size: 18px;
|
||
}
|
||
|
||
/* Heading weight */
|
||
.preview-frame[data-heading-weight="regular"] {
|
||
--weight-heading: 400;
|
||
}
|
||
|
||
.preview-frame[data-heading-weight="medium"] {
|
||
--weight-heading: 500;
|
||
}
|
||
|
||
.preview-frame[data-heading-weight="bold"] {
|
||
--weight-heading: 700;
|
||
}
|
||
|
||
/* Impulse typography special styling */
|
||
.preview-frame[data-typography="impulse"] {
|
||
--weight-heading: 300;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .shop-hero h1 {
|
||
font-size: 3.5rem;
|
||
font-weight: 300;
|
||
letter-spacing: 0.04em;
|
||
text-transform: uppercase;
|
||
line-height: 1.1;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .shop-hero p {
|
||
font-size: 1.125rem;
|
||
font-weight: 300;
|
||
letter-spacing: 0.02em;
|
||
max-width: 500px;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .section-title {
|
||
font-size: 1.5rem;
|
||
font-weight: 400;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .product-title {
|
||
font-weight: 400;
|
||
letter-spacing: 0.02em;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .product-price {
|
||
font-weight: 300;
|
||
letter-spacing: 0.01em;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .btn-primary {
|
||
font-weight: 500;
|
||
letter-spacing: 0.1em;
|
||
text-transform: uppercase;
|
||
font-size: 0.75rem;
|
||
padding: 1rem 2rem;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .shop-nav a {
|
||
font-weight: 400;
|
||
letter-spacing: 0.04em;
|
||
text-transform: uppercase;
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .announcement-bar {
|
||
font-weight: 400;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
font-size: 0.7rem;
|
||
}
|
||
|
||
.preview-frame[data-typography="impulse"] .category-name {
|
||
font-weight: 400;
|
||
letter-spacing: 0.04em;
|
||
text-transform: uppercase;
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
/* Product grid */
|
||
.product-section {
|
||
padding: var(--space-xl) var(--space-lg);
|
||
transition: all var(--transition-normal);
|
||
background: var(--t-surface-sunken);
|
||
}
|
||
|
||
.section-title {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-2xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
margin-bottom: var(--space-lg);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
.product-grid {
|
||
display: grid;
|
||
gap: var(--space-lg);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
.product-grid[data-grid="2"] { grid-template-columns: repeat(2, 1fr); }
|
||
.product-grid[data-grid="3"] { grid-template-columns: repeat(3, 1fr); }
|
||
.product-grid[data-grid="4"] { grid-template-columns: repeat(4, 1fr); }
|
||
|
||
.product-card {
|
||
background: var(--t-surface-raised);
|
||
border-radius: var(--radius-card);
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* Card shadow variations */
|
||
.preview-frame[data-card-shadow="subtle"] .product-card {
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.08), 0 2px 8px rgba(0,0,0,0.06);
|
||
}
|
||
|
||
.preview-frame[data-card-shadow="pronounced"] .product-card {
|
||
box-shadow: 0 4px 12px rgba(0,0,0,0.1), 0 8px 24px rgba(0,0,0,0.08);
|
||
}
|
||
|
||
/* Product text alignment */
|
||
.preview-frame[data-product-text="center"] .product-info {
|
||
text-align: center;
|
||
}
|
||
|
||
/* Show/hide prices */
|
||
.preview-frame[data-show-prices="false"] .product-price {
|
||
display: none;
|
||
}
|
||
transition:
|
||
transform var(--transition-normal),
|
||
box-shadow var(--transition-normal);
|
||
cursor: pointer;
|
||
box-shadow: var(--shadow-sm);
|
||
position: relative;
|
||
}
|
||
|
||
.product-card:hover {
|
||
transform: translateY(-4px);
|
||
box-shadow: var(--shadow-md);
|
||
}
|
||
|
||
.product-image {
|
||
aspect-ratio: 1;
|
||
overflow: hidden;
|
||
border-radius: var(--radius-image) var(--radius-image) 0 0;
|
||
position: relative;
|
||
}
|
||
|
||
.product-image-primary,
|
||
.product-image-hover {
|
||
position: absolute;
|
||
inset: 0;
|
||
background-size: cover;
|
||
background-position: center;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
.product-image-hover {
|
||
opacity: 0;
|
||
}
|
||
|
||
.preview-frame[data-hover-image="true"] .product-card:hover .product-image-hover {
|
||
opacity: 1;
|
||
}
|
||
|
||
.quick-add-btn {
|
||
position: absolute;
|
||
bottom: var(--space-sm);
|
||
left: var(--space-sm);
|
||
right: var(--space-sm);
|
||
background: var(--t-surface-raised);
|
||
color: var(--color-heading);
|
||
border: none;
|
||
padding: var(--space-xs) var(--space-sm);
|
||
border-radius: var(--radius-button);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
opacity: 0;
|
||
transform: translateY(8px);
|
||
transition: all 0.2s ease;
|
||
box-shadow: var(--shadow-sm);
|
||
}
|
||
|
||
.preview-frame[data-quick-add="true"] .product-card:hover .quick-add-btn {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.quick-add-btn:hover {
|
||
background: var(--color-heading);
|
||
color: var(--t-text-inverse);
|
||
}
|
||
|
||
/* Product badges */
|
||
.product-badge {
|
||
position: absolute;
|
||
top: var(--space-sm);
|
||
left: var(--space-sm);
|
||
padding: 4px 10px;
|
||
border-radius: var(--radius-button);
|
||
font-family: var(--font-body);
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
z-index: 1;
|
||
}
|
||
|
||
.badge-new {
|
||
background: var(--t-accent);
|
||
color: var(--t-text-inverse);
|
||
}
|
||
|
||
.badge-sale {
|
||
background: var(--t-sale-color);
|
||
color: white;
|
||
}
|
||
|
||
.badge-sold {
|
||
background: var(--t-surface-raised);
|
||
color: var(--color-body);
|
||
border: 1px solid var(--color-border);
|
||
}
|
||
|
||
.price-was {
|
||
text-decoration: line-through;
|
||
color: var(--color-caption);
|
||
margin-right: 4px;
|
||
}
|
||
|
||
/* Aspect ratios */
|
||
.preview-frame[data-aspect="square"] .product-image {
|
||
aspect-ratio: 1;
|
||
}
|
||
|
||
.preview-frame[data-aspect="portrait"] .product-image {
|
||
aspect-ratio: 3 / 4;
|
||
}
|
||
|
||
.preview-frame[data-aspect="landscape"] .product-image {
|
||
aspect-ratio: 4 / 3;
|
||
}
|
||
|
||
/* Header icons */
|
||
.header-icon-btn {
|
||
background: none;
|
||
border: none;
|
||
padding: var(--space-xs);
|
||
cursor: pointer;
|
||
color: var(--color-body);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: var(--radius-button);
|
||
transition: all 0.15s ease;
|
||
position: relative;
|
||
}
|
||
|
||
.header-icon-btn:hover {
|
||
color: var(--color-heading);
|
||
background: var(--t-surface-sunken);
|
||
}
|
||
|
||
.shop-cart {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.cart-count {
|
||
position: absolute;
|
||
top: -2px;
|
||
right: -2px;
|
||
background: var(--t-accent);
|
||
color: var(--t-text-inverse);
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
min-width: 16px;
|
||
height: 16px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="header-image"] .header-icon-btn,
|
||
.shop-header[data-logo-mode="logo-header-image"] .header-icon-btn {
|
||
color: #ffffff;
|
||
}
|
||
|
||
.shop-header[data-logo-mode="header-image"] .header-icon-btn:hover,
|
||
.shop-header[data-logo-mode="logo-header-image"] .header-icon-btn:hover {
|
||
background: rgba(255,255,255,0.1);
|
||
}
|
||
|
||
.product-info {
|
||
padding: var(--space-md);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
.product-title {
|
||
font-family: var(--font-body);
|
||
font-weight: 500;
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-heading);
|
||
margin-bottom: var(--space-xs);
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
.product-price {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
font-variant-numeric: tabular-nums;
|
||
transition: all var(--transition-normal);
|
||
}
|
||
|
||
/* Minimal/Impulse style product cards - cleaner, lighter */
|
||
.preview-frame[data-typography="minimal"] .product-info {
|
||
padding: var(--space-sm) 0;
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] .product-title {
|
||
font-weight: 400;
|
||
font-size: var(--p-text-base);
|
||
letter-spacing: 0;
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] .product-price {
|
||
font-weight: 300;
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] .product-card {
|
||
background: transparent;
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] .quick-add-btn {
|
||
opacity: 0;
|
||
transition: opacity 0.2s ease;
|
||
}
|
||
|
||
.preview-frame[data-typography="minimal"] .product-card:hover .quick-add-btn {
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Minimal section titles */
|
||
.preview-frame[data-typography="minimal"] .section-title {
|
||
font-weight: 300;
|
||
font-size: var(--p-text-xl);
|
||
letter-spacing: 0.05em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
/* Footer */
|
||
.shop-footer {
|
||
padding: var(--space-xl) var(--space-lg);
|
||
border-top: 1px solid var(--color-border);
|
||
transition: all var(--transition-normal);
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.footer-content {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: var(--space-xl);
|
||
margin-bottom: var(--space-lg);
|
||
padding-bottom: var(--space-lg);
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.footer-newsletter {
|
||
max-width: 320px;
|
||
}
|
||
|
||
.footer-heading {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-lg);
|
||
color: var(--color-heading);
|
||
margin-bottom: var(--space-xs);
|
||
}
|
||
|
||
.footer-text {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
margin-bottom: var(--space-sm);
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.newsletter-form {
|
||
display: flex;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.newsletter-input {
|
||
flex: 1;
|
||
padding: var(--space-xs) var(--space-sm);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-input);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
background: var(--t-surface-raised);
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.newsletter-input::placeholder {
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.newsletter-btn {
|
||
padding: var(--space-xs) var(--space-md);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.footer-links {
|
||
display: flex;
|
||
gap: var(--space-xl);
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.footer-column {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.footer-column-title {
|
||
font-family: var(--font-body);
|
||
font-weight: 600;
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-heading);
|
||
margin-bottom: var(--space-xs);
|
||
}
|
||
|
||
.footer-column a {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
text-decoration: none;
|
||
transition: color 0.15s ease;
|
||
}
|
||
|
||
.footer-column a:hover {
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.footer-bottom {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.footer-bottom p {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-caption);
|
||
margin: 0;
|
||
}
|
||
|
||
.footer-social {
|
||
display: flex;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.social-link {
|
||
width: 36px;
|
||
height: 36px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--color-body);
|
||
border-radius: var(--radius-button);
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.social-link:hover {
|
||
color: var(--color-heading);
|
||
background: var(--t-surface-sunken);
|
||
}
|
||
|
||
.social-link svg {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
/* Product images - using picsum.photos with alt views */
|
||
.product-image-primary.img-1 {
|
||
background-color: #e8e4df;
|
||
background-image: url('https://picsum.photos/seed/fern/400/400');
|
||
}
|
||
.product-image-hover.img-1-alt {
|
||
background-color: #e8e4df;
|
||
background-image: url('https://picsum.photos/seed/fern-alt/400/400');
|
||
}
|
||
.product-image-primary.img-2 {
|
||
background-color: #f5e6e0;
|
||
background-image: url('https://picsum.photos/seed/roses/400/400');
|
||
}
|
||
.product-image-hover.img-2-alt {
|
||
background-color: #f5e6e0;
|
||
background-image: url('https://picsum.photos/seed/roses-alt/400/400');
|
||
}
|
||
.product-image-primary.img-3 {
|
||
background-color: #e0e8e4;
|
||
background-image: url('https://picsum.photos/seed/morning/400/400');
|
||
}
|
||
.product-image-hover.img-3-alt {
|
||
background-color: #e0e8e4;
|
||
background-image: url('https://picsum.photos/seed/morning-alt/400/400');
|
||
}
|
||
.product-image-primary.img-4 {
|
||
background-color: #e4e8e0;
|
||
background-image: url('https://picsum.photos/seed/oak/400/400');
|
||
}
|
||
.product-image-hover.img-4-alt {
|
||
background-color: #e4e8e0;
|
||
background-image: url('https://picsum.photos/seed/oak-alt/400/400');
|
||
}
|
||
.product-image-primary.img-5 {
|
||
background-color: #f0e8e4;
|
||
background-image: url('https://picsum.photos/seed/bloom/400/400');
|
||
}
|
||
.product-image-hover.img-5-alt {
|
||
background-color: #f0e8e4;
|
||
background-image: url('https://picsum.photos/seed/bloom-alt/400/400');
|
||
}
|
||
.product-image-primary.img-6 {
|
||
background-color: #e8e0f0;
|
||
background-image: url('https://picsum.photos/seed/lavender/400/400');
|
||
}
|
||
.product-image-hover.img-6-alt {
|
||
background-color: #e8e0f0;
|
||
background-image: url('https://picsum.photos/seed/lavender-alt/400/400');
|
||
}
|
||
|
||
.icon {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
.preview-frame ::selection {
|
||
background: var(--t-accent-subtle);
|
||
}
|
||
|
||
/* Page views */
|
||
.page-view {
|
||
display: none;
|
||
}
|
||
|
||
.page-view.active {
|
||
display: block;
|
||
}
|
||
|
||
/* PDP Styles */
|
||
.pdp-container {
|
||
padding: var(--space-lg);
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.pdp-breadcrumb {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-caption);
|
||
margin-bottom: var(--space-lg);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.pdp-breadcrumb a {
|
||
color: var(--color-body);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.pdp-breadcrumb a:hover {
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.breadcrumb-sep {
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.pdp-layout {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: var(--space-xl);
|
||
}
|
||
|
||
/* Gallery position */
|
||
.preview-frame[data-gallery-position="right"] .pdp-layout {
|
||
direction: rtl;
|
||
}
|
||
|
||
.preview-frame[data-gallery-position="right"] .pdp-layout > * {
|
||
direction: ltr;
|
||
}
|
||
|
||
/* PDP section visibility */
|
||
.preview-frame[data-pdp-trust="false"] .pdp-trust-badges {
|
||
display: none;
|
||
}
|
||
|
||
.preview-frame[data-pdp-reviews="false"] .pdp-reviews {
|
||
display: none;
|
||
}
|
||
|
||
.preview-frame[data-pdp-related="false"] .pdp-related {
|
||
display: none;
|
||
}
|
||
|
||
.pdp-gallery {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.pdp-main-image {
|
||
aspect-ratio: 1;
|
||
border-radius: var(--radius-image);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.pdp-thumbnails {
|
||
display: flex;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.pdp-thumb {
|
||
width: 64px;
|
||
height: 64px;
|
||
border-radius: var(--t-radius-sm);
|
||
cursor: pointer;
|
||
opacity: 0.6;
|
||
transition: opacity 0.15s ease;
|
||
border: 2px solid transparent;
|
||
}
|
||
|
||
.pdp-thumb:hover {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.pdp-thumb.active {
|
||
opacity: 1;
|
||
border-color: var(--color-heading);
|
||
}
|
||
|
||
/* PDP images */
|
||
.pdp-main-image {
|
||
background-color: #e8e4df;
|
||
background-size: cover;
|
||
background-position: center;
|
||
}
|
||
|
||
.pdp-thumb {
|
||
background-color: #e8e4df;
|
||
background-size: cover;
|
||
background-position: center;
|
||
}
|
||
|
||
.pdp-thumb[data-image*="fern/"] { background-image: url('https://picsum.photos/seed/fern/100/100'); }
|
||
.pdp-thumb[data-image*="fern-alt"] { background-image: url('https://picsum.photos/seed/fern-alt/100/100'); }
|
||
.pdp-thumb[data-image*="fern-detail"] { background-image: url('https://picsum.photos/seed/fern-detail/100/100'); }
|
||
|
||
.pdp-details {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-md);
|
||
}
|
||
|
||
.pdp-title {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-3xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
margin: 0;
|
||
}
|
||
|
||
.pdp-price {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-xl);
|
||
color: var(--color-heading);
|
||
font-variant-numeric: tabular-nums;
|
||
margin: 0;
|
||
}
|
||
|
||
.pdp-description {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-body);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.pdp-description p {
|
||
margin: 0;
|
||
}
|
||
|
||
.pdp-options {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-md);
|
||
padding: var(--space-md) 0;
|
||
border-top: 1px solid var(--color-border);
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.pdp-option-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.pdp-option-label {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.pdp-option-buttons {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.pdp-option-btn {
|
||
padding: var(--space-xs) var(--space-sm);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-button);
|
||
background: var(--t-surface-raised);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.pdp-option-btn:hover {
|
||
border-color: var(--color-heading);
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.pdp-option-btn.active {
|
||
border-color: var(--color-heading);
|
||
background: var(--color-heading);
|
||
color: var(--t-text-inverse);
|
||
}
|
||
|
||
.pdp-add-btn {
|
||
width: 100%;
|
||
padding: var(--space-md);
|
||
font-size: var(--p-text-base);
|
||
}
|
||
|
||
/* PDP Expandable Details */
|
||
.pdp-details-sections {
|
||
display: flex;
|
||
flex-direction: column;
|
||
border-top: 1px solid var(--color-border);
|
||
}
|
||
|
||
.pdp-details {
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.pdp-details-summary {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: var(--space-md) 0;
|
||
cursor: pointer;
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: var(--color-heading);
|
||
list-style: none;
|
||
}
|
||
|
||
.pdp-details-summary::-webkit-details-marker {
|
||
display: none;
|
||
}
|
||
|
||
.pdp-details-summary::marker {
|
||
display: none;
|
||
}
|
||
|
||
.pdp-details-icon {
|
||
width: 18px;
|
||
height: 18px;
|
||
color: var(--color-caption);
|
||
transition: transform 0.2s ease;
|
||
}
|
||
|
||
.pdp-details[open] .pdp-details-icon {
|
||
transform: rotate(180deg);
|
||
}
|
||
|
||
.pdp-details-content {
|
||
padding-bottom: var(--space-md);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.size-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: var(--p-text-sm);
|
||
}
|
||
|
||
.size-table th,
|
||
.size-table td {
|
||
padding: var(--space-xs) var(--space-sm);
|
||
text-align: left;
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.size-table th {
|
||
font-weight: 500;
|
||
color: var(--color-heading);
|
||
background: var(--t-surface-sunken);
|
||
}
|
||
|
||
.size-table td {
|
||
color: var(--color-body);
|
||
}
|
||
|
||
.details-list {
|
||
margin: 0;
|
||
padding-left: var(--space-md);
|
||
}
|
||
|
||
.details-list li {
|
||
margin-bottom: var(--space-xs);
|
||
}
|
||
|
||
.details-list li:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.pdp-meta {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-sm);
|
||
padding-top: var(--space-sm);
|
||
}
|
||
|
||
.pdp-meta-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
}
|
||
|
||
.pdp-meta-icon {
|
||
width: 18px;
|
||
height: 18px;
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.pdp-trust-badges {
|
||
display: flex;
|
||
gap: var(--space-md);
|
||
padding-top: var(--space-md);
|
||
border-top: 1px solid var(--color-border);
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.trust-badge {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-xs);
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.trust-badge-icon {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
|
||
.pdp-related {
|
||
padding: var(--space-xl) 0;
|
||
border-top: 1px solid var(--color-border);
|
||
margin-top: var(--space-xl);
|
||
}
|
||
|
||
/* Reviews Section */
|
||
.pdp-reviews {
|
||
padding: var(--space-xl) var(--space-lg);
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.reviews-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
flex-wrap: wrap;
|
||
gap: var(--space-md);
|
||
margin-bottom: var(--space-lg);
|
||
}
|
||
|
||
.reviews-summary {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.reviews-stars,
|
||
.review-stars {
|
||
display: flex;
|
||
gap: 2px;
|
||
}
|
||
|
||
.star {
|
||
width: 16px;
|
||
height: 16px;
|
||
color: var(--color-border);
|
||
}
|
||
|
||
.star.filled {
|
||
color: #f59e0b;
|
||
}
|
||
|
||
.reviews-count {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.reviews-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-lg);
|
||
margin-bottom: var(--space-lg);
|
||
}
|
||
|
||
.review {
|
||
padding-bottom: var(--space-lg);
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.review:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.review-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: var(--space-xs);
|
||
}
|
||
|
||
.review-date {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-xs);
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.review-title {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
font-weight: 600;
|
||
color: var(--color-heading);
|
||
margin: 0 0 var(--space-xs);
|
||
}
|
||
|
||
.review-text {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
line-height: 1.6;
|
||
margin: 0 0 var(--space-sm);
|
||
}
|
||
|
||
.review-author {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.review-name {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.review-verified {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-xs);
|
||
color: var(--color-caption);
|
||
background: var(--t-surface-sunken);
|
||
padding: 2px 8px;
|
||
border-radius: var(--radius-button);
|
||
}
|
||
|
||
.reviews-load-more {
|
||
display: block;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.related-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: var(--space-md);
|
||
}
|
||
|
||
/* Section CTA */
|
||
.section-cta {
|
||
text-align: center;
|
||
margin-top: var(--space-lg);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: transparent;
|
||
color: var(--color-heading);
|
||
border: 1px solid var(--color-heading);
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: var(--color-heading);
|
||
color: var(--t-text-inverse);
|
||
}
|
||
|
||
/* Home About Section */
|
||
.home-about {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: var(--space-xl);
|
||
padding: var(--space-2xl) var(--space-lg);
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.home-about-image {
|
||
height: 300px;
|
||
border-radius: var(--radius-image);
|
||
background: url('https://picsum.photos/seed/studio/600/400') center/cover;
|
||
}
|
||
|
||
.home-about-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
}
|
||
|
||
.home-about-content h2 {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-2xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
margin: 0 0 var(--space-md);
|
||
}
|
||
|
||
.home-about-content p {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-body);
|
||
line-height: 1.7;
|
||
margin: 0 0 var(--space-md);
|
||
}
|
||
|
||
.text-link {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: var(--t-accent);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.text-link:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
/* Home Categories */
|
||
.home-categories {
|
||
padding: var(--space-xl) var(--space-lg);
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.category-links {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: var(--space-md);
|
||
max-width: 800px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.category-link {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
text-decoration: none;
|
||
padding: var(--space-md);
|
||
border-radius: var(--radius-card);
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.category-link:hover {
|
||
background: var(--t-surface-sunken);
|
||
}
|
||
|
||
.category-link:focus {
|
||
outline: 2px solid var(--t-accent);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.category-image {
|
||
width: 100px;
|
||
height: 100px;
|
||
border-radius: 50%;
|
||
background-size: cover;
|
||
background-position: center;
|
||
transition: transform 0.2s ease;
|
||
}
|
||
|
||
.category-link:hover .category-image {
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.cat-img-1 { background-image: url('https://picsum.photos/seed/botanicals/200/200'); }
|
||
.cat-img-2 { background-image: url('https://picsum.photos/seed/florals/200/200'); }
|
||
.cat-img-3 { background-image: url('https://picsum.photos/seed/landscapes/200/200'); }
|
||
|
||
.category-name {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
/* Utility: visually hidden but accessible */
|
||
.visually-hidden {
|
||
position: absolute;
|
||
width: 1px;
|
||
height: 1px;
|
||
padding: 0;
|
||
margin: -1px;
|
||
overflow: hidden;
|
||
clip: rect(0, 0, 0, 0);
|
||
white-space: nowrap;
|
||
border: 0;
|
||
}
|
||
|
||
/* Collection Page */
|
||
.collection-header {
|
||
padding: var(--space-xl) var(--space-lg) var(--space-md);
|
||
background: var(--t-surface-base);
|
||
text-align: center;
|
||
}
|
||
|
||
.collection-title {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-3xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
margin: 0 0 var(--space-xs);
|
||
}
|
||
|
||
.collection-count {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-caption);
|
||
margin: 0;
|
||
}
|
||
|
||
.collection-toolbar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: var(--space-lg);
|
||
gap: var(--space-md);
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.collection-filter {
|
||
display: flex;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.filter-btn {
|
||
padding: var(--space-xs) var(--space-md);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-button);
|
||
background: var(--t-surface-raised);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.filter-btn:hover {
|
||
border-color: var(--color-heading);
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.filter-btn.active {
|
||
background: var(--color-heading);
|
||
border-color: var(--color-heading);
|
||
color: var(--t-text-inverse);
|
||
}
|
||
|
||
.sort-select {
|
||
padding: var(--space-xs) var(--space-md);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-button);
|
||
background: var(--t-surface-raised);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-heading);
|
||
cursor: pointer;
|
||
}
|
||
|
||
@media (max-width: 1000px) {
|
||
.controls-panel {
|
||
position: relative;
|
||
max-height: none;
|
||
border-right: none;
|
||
border-bottom: 1px solid #e5e5e5;
|
||
}
|
||
|
||
.preview-area {
|
||
padding: var(--p-space-4);
|
||
}
|
||
|
||
.product-grid[data-grid="4"] {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
|
||
.pdp-layout {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.related-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
|
||
.footer-content {
|
||
grid-template-columns: 1fr;
|
||
gap: var(--space-lg);
|
||
}
|
||
|
||
.footer-links {
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.cart-layout {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.contact-layout {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.home-about {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.home-about-image {
|
||
height: 200px;
|
||
}
|
||
|
||
.category-links {
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.category-image {
|
||
width: 70px;
|
||
height: 70px;
|
||
}
|
||
}
|
||
|
||
/* Cart Page */
|
||
.cart-container {
|
||
padding: var(--space-lg);
|
||
background: var(--t-surface-base);
|
||
min-height: 60vh;
|
||
}
|
||
|
||
.cart-header-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: var(--space-lg);
|
||
}
|
||
|
||
.cart-title {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-3xl);
|
||
color: var(--color-heading);
|
||
margin: 0;
|
||
}
|
||
|
||
.cart-state-toggle {
|
||
background: none;
|
||
border: none;
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-xs);
|
||
color: var(--color-caption);
|
||
cursor: pointer;
|
||
text-decoration: underline;
|
||
padding: var(--space-xs);
|
||
}
|
||
|
||
.cart-state-toggle:hover {
|
||
color: var(--color-body);
|
||
}
|
||
|
||
.cart-state[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
/* Empty State */
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
padding: var(--space-2xl) var(--space-lg);
|
||
min-height: 40vh;
|
||
}
|
||
|
||
.empty-state-illustration {
|
||
width: 120px;
|
||
height: 120px;
|
||
margin-bottom: var(--space-lg);
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.empty-state-illustration svg {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.empty-state-title {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-2xl);
|
||
color: var(--color-heading);
|
||
margin: 0 0 var(--space-sm);
|
||
}
|
||
|
||
.empty-state-message {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-body);
|
||
max-width: 400px;
|
||
margin: 0 0 var(--space-lg);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
/* Error Page */
|
||
.error-container {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 70vh;
|
||
padding: var(--space-xl) var(--space-lg);
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.error-content {
|
||
text-align: center;
|
||
max-width: 500px;
|
||
}
|
||
|
||
.error-illustration {
|
||
width: 200px;
|
||
height: 160px;
|
||
margin: 0 auto var(--space-xl);
|
||
color: var(--t-accent);
|
||
}
|
||
|
||
.error-illustration svg {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.error-title {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-3xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
margin: 0 0 var(--space-sm);
|
||
}
|
||
|
||
.error-message {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-body);
|
||
line-height: 1.6;
|
||
margin: 0 0 var(--space-xl);
|
||
}
|
||
|
||
.error-actions {
|
||
display: flex;
|
||
gap: var(--space-sm);
|
||
justify-content: center;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.cart-layout {
|
||
display: grid;
|
||
grid-template-columns: 1fr 360px;
|
||
gap: var(--space-xl);
|
||
align-items: start;
|
||
}
|
||
|
||
.cart-items {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-md);
|
||
}
|
||
|
||
.cart-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-md);
|
||
padding: var(--space-md);
|
||
background: var(--t-surface-raised);
|
||
border-radius: var(--radius-card);
|
||
border: 1px solid var(--color-border);
|
||
}
|
||
|
||
.cart-item-image {
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: var(--radius-image);
|
||
background-size: cover;
|
||
background-position: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.cart-item-image.img-1 { background-image: url('https://picsum.photos/seed/fern/200/200'); }
|
||
.cart-item-image.img-2 { background-image: url('https://picsum.photos/seed/roses/200/200'); }
|
||
|
||
.cart-item-details {
|
||
flex: 1;
|
||
}
|
||
|
||
.cart-item-title {
|
||
font-family: var(--font-body);
|
||
font-weight: 500;
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-heading);
|
||
margin: 0 0 4px;
|
||
}
|
||
|
||
.cart-item-variant {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-caption);
|
||
margin: 0 0 4px;
|
||
}
|
||
|
||
.cart-item-price {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-heading);
|
||
margin: 0;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
.cart-item-quantity {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.qty-btn {
|
||
width: 32px;
|
||
height: 32px;
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-button);
|
||
background: var(--t-surface-raised);
|
||
color: var(--color-heading);
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
.qty-btn:hover {
|
||
border-color: var(--color-heading);
|
||
}
|
||
|
||
.qty-value {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-heading);
|
||
min-width: 24px;
|
||
text-align: center;
|
||
}
|
||
|
||
.cart-item-remove {
|
||
background: none;
|
||
border: none;
|
||
padding: var(--space-xs);
|
||
color: var(--color-caption);
|
||
cursor: pointer;
|
||
transition: color 0.15s ease;
|
||
}
|
||
|
||
.cart-item-remove:hover {
|
||
color: #dc2626;
|
||
}
|
||
|
||
.cart-item-remove svg {
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
|
||
.cart-summary {
|
||
padding: var(--space-lg);
|
||
background: var(--t-surface-sunken);
|
||
border-radius: var(--radius-card);
|
||
}
|
||
|
||
.cart-summary-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: var(--space-sm) 0;
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.cart-summary-row.cart-total {
|
||
font-weight: 600;
|
||
font-size: var(--p-text-base);
|
||
color: var(--color-heading);
|
||
border-bottom: none;
|
||
padding-top: var(--space-md);
|
||
}
|
||
|
||
.cart-checkout-btn {
|
||
width: 100%;
|
||
margin-top: var(--space-md);
|
||
padding: var(--space-md);
|
||
}
|
||
|
||
.cart-secure-note {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: var(--space-xs);
|
||
margin-top: var(--space-md);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-xs);
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.cart-secure-note svg {
|
||
width: 14px;
|
||
height: 14px;
|
||
}
|
||
|
||
/* Content Pages (About/Contact) */
|
||
.content-page {
|
||
background: var(--t-surface-base);
|
||
}
|
||
|
||
.content-hero {
|
||
padding: var(--space-2xl) var(--space-lg);
|
||
text-align: center;
|
||
background: var(--t-surface-sunken);
|
||
}
|
||
|
||
.content-title {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-4xl);
|
||
letter-spacing: var(--tracking-heading);
|
||
color: var(--color-heading);
|
||
margin: 0 0 var(--space-xs);
|
||
}
|
||
|
||
.content-subtitle {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-lg);
|
||
color: var(--color-body);
|
||
margin: 0;
|
||
}
|
||
|
||
.content-body {
|
||
padding: var(--space-xl) var(--space-lg);
|
||
max-width: 800px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.content-image {
|
||
width: 100%;
|
||
height: 300px;
|
||
border-radius: var(--radius-image);
|
||
margin-bottom: var(--space-lg);
|
||
background-size: cover;
|
||
background-position: center;
|
||
}
|
||
|
||
.about-image {
|
||
background-image: url('https://picsum.photos/seed/studio/800/400');
|
||
}
|
||
|
||
.content-text {
|
||
font-family: var(--font-body);
|
||
color: var(--color-body);
|
||
line-height: 1.7;
|
||
}
|
||
|
||
.content-text p {
|
||
margin: 0 0 var(--space-md);
|
||
}
|
||
|
||
.content-text .lead-text {
|
||
font-size: var(--p-text-lg);
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.content-text h2 {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-xl);
|
||
color: var(--color-heading);
|
||
margin: var(--space-lg) 0 var(--space-sm);
|
||
}
|
||
|
||
/* Contact Page */
|
||
.contact-layout {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: var(--space-xl);
|
||
padding: var(--space-xl) var(--space-lg);
|
||
max-width: 1000px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.contact-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-lg);
|
||
}
|
||
|
||
.contact-block h3 {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-lg);
|
||
color: var(--color-heading);
|
||
margin: 0 0 var(--space-xs);
|
||
}
|
||
|
||
.contact-block p {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
margin: 0 0 var(--space-sm);
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.contact-link {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--t-accent);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.contact-link:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.contact-social {
|
||
display: flex;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.contact-form {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-md);
|
||
}
|
||
|
||
.form-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-xs);
|
||
}
|
||
|
||
.form-label {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.form-input {
|
||
padding: var(--space-sm);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-input);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
background: var(--t-surface-raised);
|
||
color: var(--color-heading);
|
||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||
}
|
||
|
||
.form-input:focus {
|
||
outline: none;
|
||
border-color: var(--t-accent);
|
||
box-shadow: 0 0 0 3px var(--t-accent-ring);
|
||
}
|
||
|
||
.form-input::placeholder {
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.form-select {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.form-textarea {
|
||
resize: vertical;
|
||
min-height: 120px;
|
||
}
|
||
|
||
.form-submit {
|
||
align-self: flex-start;
|
||
padding: var(--space-sm) var(--space-xl);
|
||
}
|
||
|
||
/* Cart Drawer */
|
||
.cart-drawer {
|
||
position: fixed;
|
||
top: 0;
|
||
right: -400px;
|
||
width: 400px;
|
||
max-width: 90vw;
|
||
height: 100%;
|
||
background: var(--t-surface-raised);
|
||
z-index: 1000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
transition: right 0.3s ease;
|
||
box-shadow: -4px 0 20px rgba(0,0,0,0.15);
|
||
}
|
||
|
||
.cart-drawer.open {
|
||
right: 0;
|
||
}
|
||
|
||
.cart-drawer-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: var(--space-md) var(--space-lg);
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.cart-drawer-header h2 {
|
||
font-family: var(--font-heading);
|
||
font-weight: var(--weight-heading);
|
||
font-size: var(--p-text-lg);
|
||
color: var(--color-heading);
|
||
margin: 0;
|
||
}
|
||
|
||
.cart-drawer-close {
|
||
background: none;
|
||
border: none;
|
||
padding: var(--space-xs);
|
||
cursor: pointer;
|
||
color: var(--color-body);
|
||
}
|
||
|
||
.cart-drawer-close svg {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
.cart-drawer-items {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding: var(--space-md);
|
||
}
|
||
|
||
.cart-drawer-item {
|
||
display: flex;
|
||
gap: var(--space-sm);
|
||
padding: var(--space-sm) 0;
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.cart-drawer-item-image {
|
||
width: 60px;
|
||
height: 60px;
|
||
border-radius: var(--radius-image);
|
||
background-size: cover;
|
||
background-position: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.cart-drawer-item-image.img-1 { background-image: url('https://picsum.photos/seed/fern/120/120'); }
|
||
.cart-drawer-item-image.img-2 { background-image: url('https://picsum.photos/seed/roses/120/120'); }
|
||
|
||
.cart-drawer-item-details h3 {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
font-weight: 500;
|
||
color: var(--color-heading);
|
||
margin: 0 0 2px;
|
||
}
|
||
|
||
.cart-drawer-item-details p {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-xs);
|
||
color: var(--color-caption);
|
||
margin: 0;
|
||
}
|
||
|
||
.cart-drawer-item-price {
|
||
color: var(--color-heading) !important;
|
||
font-weight: 500;
|
||
margin-top: 4px !important;
|
||
}
|
||
|
||
.cart-drawer-footer {
|
||
padding: var(--space-md) var(--space-lg);
|
||
border-top: 1px solid var(--color-border);
|
||
background: var(--t-surface-sunken);
|
||
}
|
||
|
||
.cart-drawer-total {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-base);
|
||
font-weight: 600;
|
||
color: var(--color-heading);
|
||
margin-bottom: var(--space-md);
|
||
}
|
||
|
||
.cart-drawer-checkout {
|
||
width: 100%;
|
||
margin-bottom: var(--space-sm);
|
||
}
|
||
|
||
.cart-drawer-link {
|
||
display: block;
|
||
text-align: center;
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-body);
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.cart-drawer-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(0,0,0,0.4);
|
||
z-index: 999;
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||
}
|
||
|
||
.cart-drawer-overlay.open {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
}
|
||
|
||
/* Search Modal */
|
||
.search-modal {
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(0,0,0,0.5);
|
||
z-index: 1001;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: center;
|
||
padding-top: 100px;
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
transition: opacity 0.2s ease, visibility 0.2s ease;
|
||
}
|
||
|
||
.search-modal.open {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
}
|
||
|
||
.search-modal-content {
|
||
background: var(--t-surface-raised);
|
||
border-radius: var(--radius-card);
|
||
width: 100%;
|
||
max-width: 600px;
|
||
margin: 0 var(--space-md);
|
||
box-shadow: 0 20px 40px rgba(0,0,0,0.2);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.search-input-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: var(--space-md);
|
||
gap: var(--space-sm);
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
.search-icon {
|
||
width: 20px;
|
||
height: 20px;
|
||
color: var(--color-caption);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.search-input {
|
||
flex: 1;
|
||
border: none;
|
||
background: none;
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-lg);
|
||
color: var(--color-heading);
|
||
outline: none;
|
||
}
|
||
|
||
.search-input::placeholder {
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.search-close {
|
||
background: none;
|
||
border: none;
|
||
padding: var(--space-xs);
|
||
cursor: pointer;
|
||
color: var(--color-caption);
|
||
}
|
||
|
||
.search-close:hover {
|
||
color: var(--color-heading);
|
||
}
|
||
|
||
.search-close svg {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
.search-results {
|
||
padding: var(--space-lg);
|
||
}
|
||
|
||
.search-hint {
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
color: var(--color-caption);
|
||
text-align: center;
|
||
margin: 0;
|
||
}
|
||
|
||
/* Zoom button on PDP image */
|
||
.pdp-main-image {
|
||
position: relative;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.zoom-btn {
|
||
position: absolute;
|
||
bottom: var(--space-sm);
|
||
right: var(--space-sm);
|
||
width: 40px;
|
||
height: 40px;
|
||
background: var(--t-surface-raised);
|
||
border: none;
|
||
border-radius: var(--radius-button);
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--color-heading);
|
||
box-shadow: var(--shadow-sm);
|
||
transition: all 0.15s ease;
|
||
opacity: 0;
|
||
}
|
||
|
||
.pdp-main-image:hover .zoom-btn,
|
||
.zoom-btn:focus {
|
||
opacity: 1;
|
||
}
|
||
|
||
.zoom-btn:hover {
|
||
background: var(--color-heading);
|
||
color: var(--t-text-inverse);
|
||
}
|
||
|
||
.zoom-btn svg {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
/* Lightbox - using native dialog */
|
||
.lightbox {
|
||
position: fixed;
|
||
inset: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
background: rgba(0, 0, 0, 0.95);
|
||
border: none;
|
||
padding: 0;
|
||
z-index: 1002;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.lightbox::backdrop {
|
||
background: rgba(0, 0, 0, 0.95);
|
||
}
|
||
|
||
.lightbox:not([open]) {
|
||
display: none;
|
||
}
|
||
|
||
.lightbox-content {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.lightbox-close {
|
||
position: absolute;
|
||
top: var(--space-md);
|
||
right: var(--space-md);
|
||
width: 44px;
|
||
height: 44px;
|
||
background: transparent;
|
||
border: none;
|
||
cursor: pointer;
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: var(--radius-button);
|
||
transition: background 0.15s ease;
|
||
z-index: 1;
|
||
}
|
||
|
||
.lightbox-close:hover {
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.lightbox-close svg {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
|
||
.lightbox-nav {
|
||
position: absolute;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 50px;
|
||
height: 50px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
border: none;
|
||
cursor: pointer;
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 50%;
|
||
transition: background 0.15s ease;
|
||
}
|
||
|
||
.lightbox-nav:hover {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
.lightbox-nav svg {
|
||
width: 24px;
|
||
height: 24px;
|
||
}
|
||
|
||
.lightbox-prev {
|
||
left: var(--space-md);
|
||
}
|
||
|
||
.lightbox-next {
|
||
right: var(--space-md);
|
||
}
|
||
|
||
.lightbox-image-container {
|
||
max-width: 90vw;
|
||
max-height: 75vh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.lightbox-image {
|
||
max-width: 100%;
|
||
max-height: 75vh;
|
||
object-fit: contain;
|
||
border-radius: var(--radius-image);
|
||
}
|
||
|
||
.lightbox-figure {
|
||
margin: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: var(--space-md);
|
||
}
|
||
|
||
.lightbox-caption {
|
||
color: rgba(255, 255, 255, 0.8);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
text-align: center;
|
||
max-width: 500px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.lightbox-counter {
|
||
position: absolute;
|
||
bottom: var(--space-md);
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
color: rgba(255, 255, 255, 0.7);
|
||
font-family: var(--font-body);
|
||
font-size: var(--p-text-sm);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="page-layout">
|
||
<!-- Controls Panel -->
|
||
<div class="controls-panel">
|
||
<div class="controls-header">
|
||
<h1>Theme Studio</h1>
|
||
<p>One theme, infinite possibilities. Every combination is designed to work beautifully.</p>
|
||
</div>
|
||
|
||
<!-- Shop Name -->
|
||
<div class="control-section">
|
||
<label class="control-label">Shop name</label>
|
||
<input type="text" class="text-input" id="shop-name" value="Botanical Studio" placeholder="Your shop name">
|
||
</div>
|
||
|
||
<!-- Branding Section -->
|
||
<div class="branding-section">
|
||
<label class="control-label">Logo & header</label>
|
||
|
||
<div class="logo-mode-options">
|
||
<label class="logo-mode-option active" data-mode="text-only">
|
||
<input type="radio" name="logo-mode" value="text-only" checked>
|
||
<span class="logo-mode-radio"></span>
|
||
<div class="logo-mode-content">
|
||
<div class="logo-mode-title">Shop name only</div>
|
||
<div class="logo-mode-desc">Your name in the heading font</div>
|
||
</div>
|
||
</label>
|
||
|
||
<label class="logo-mode-option" data-mode="logo-and-text">
|
||
<input type="radio" name="logo-mode" value="logo-and-text">
|
||
<span class="logo-mode-radio"></span>
|
||
<div class="logo-mode-content">
|
||
<div class="logo-mode-title">Logo + shop name</div>
|
||
<div class="logo-mode-desc">Your logo image with name beside it</div>
|
||
</div>
|
||
</label>
|
||
|
||
<label class="logo-mode-option" data-mode="logo-only">
|
||
<input type="radio" name="logo-mode" value="logo-only">
|
||
<span class="logo-mode-radio"></span>
|
||
<div class="logo-mode-content">
|
||
<div class="logo-mode-title">Logo only</div>
|
||
<div class="logo-mode-desc">Just your logo (with text built in)</div>
|
||
</div>
|
||
</label>
|
||
|
||
<label class="logo-mode-option" data-mode="header-image">
|
||
<input type="radio" name="logo-mode" value="header-image">
|
||
<span class="logo-mode-radio"></span>
|
||
<div class="logo-mode-content">
|
||
<div class="logo-mode-title">Header background</div>
|
||
<div class="logo-mode-desc">Full-width image with name overlay</div>
|
||
</div>
|
||
</label>
|
||
|
||
<label class="logo-mode-option" data-mode="logo-header-image">
|
||
<input type="radio" name="logo-mode" value="logo-header-image">
|
||
<span class="logo-mode-radio"></span>
|
||
<div class="logo-mode-content">
|
||
<div class="logo-mode-title">Logo + header background</div>
|
||
<div class="logo-mode-desc">Your logo (use white/light version) on a full-width image</div>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="upload-section">
|
||
<!-- Logo upload (for logo-and-text and logo-only modes) -->
|
||
<div class="upload-row" id="logo-upload-row">
|
||
<span class="upload-label" id="logo-upload-label">Upload logo (SVG or PNG)</span>
|
||
<div class="upload-area">
|
||
<label class="upload-btn">
|
||
<span>Choose file...</span>
|
||
<input type="file" id="logo-upload" accept=".svg,.png,.jpg,.jpeg,.webp">
|
||
</label>
|
||
<div class="upload-preview" id="logo-preview">
|
||
<img id="logo-preview-img" src="" alt="Logo preview">
|
||
<button class="remove-upload" id="remove-logo">×</button>
|
||
</div>
|
||
</div>
|
||
<div class="size-control" id="logo-size-control">
|
||
<div class="size-control-header">
|
||
<span class="size-control-label">Logo size</span>
|
||
<span class="size-control-value" id="logo-size-value">36px</span>
|
||
</div>
|
||
<input type="range" class="size-slider" id="logo-size-slider" min="24" max="120" value="36">
|
||
</div>
|
||
|
||
<div class="logo-color-control" id="logo-color-control">
|
||
<div class="logo-color-toggle">
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="recolor-logo-checkbox">
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Recolour logo</span>
|
||
</label>
|
||
</div>
|
||
<div class="logo-color-picker-row" id="logo-color-picker-row">
|
||
<input type="color" class="color-picker color-picker-small" id="logo-color-picker" value="#171717">
|
||
<span class="color-value" id="logo-color-value">#171717</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Header background upload -->
|
||
<div class="upload-row" id="header-upload-row">
|
||
<span class="upload-label">Upload header image</span>
|
||
<div class="upload-area">
|
||
<label class="upload-btn">
|
||
<span>Choose file...</span>
|
||
<input type="file" id="header-upload" accept=".jpg,.jpeg,.png,.webp">
|
||
</label>
|
||
</div>
|
||
<div class="upload-preview upload-preview-wide" id="header-preview">
|
||
<img id="header-preview-img" src="" alt="Header preview">
|
||
<button class="remove-upload" id="remove-header">×</button>
|
||
</div>
|
||
|
||
<div class="header-image-controls" id="header-image-controls">
|
||
<div class="control-row">
|
||
<div class="size-control-header">
|
||
<span class="size-control-label">Zoom</span>
|
||
<span class="size-control-value" id="header-zoom-value">100%</span>
|
||
</div>
|
||
<input type="range" class="size-slider" id="header-zoom-slider" min="100" max="200" value="100">
|
||
</div>
|
||
|
||
<div class="control-row" id="header-position-x-row">
|
||
<div class="size-control-header">
|
||
<span class="size-control-label">Horizontal position</span>
|
||
<span class="size-control-value" id="header-position-x-value">50%</span>
|
||
</div>
|
||
<input type="range" class="size-slider" id="header-position-x-slider" min="0" max="100" value="50">
|
||
</div>
|
||
|
||
<div class="control-row">
|
||
<div class="size-control-header">
|
||
<span class="size-control-label">Vertical position</span>
|
||
<span class="size-control-value" id="header-position-value">50%</span>
|
||
</div>
|
||
<input type="range" class="size-slider" id="header-position-slider" min="0" max="100" value="50">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Presets -->
|
||
<div class="control-section">
|
||
<label class="control-label">Start with a preset</label>
|
||
<div class="preset-grid" id="preset-grid">
|
||
<button class="preset-button active" data-preset="gallery">
|
||
<div class="preset-name">Gallery</div>
|
||
<div class="preset-desc">Warm & spacious</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="studio">
|
||
<div class="preset-name">Studio</div>
|
||
<div class="preset-desc">Clean & balanced</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="boutique">
|
||
<div class="preset-name">Boutique</div>
|
||
<div class="preset-desc">Classic & refined</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="bold">
|
||
<div class="preset-name">Bold</div>
|
||
<div class="preset-desc">Sharp & modern</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="playful">
|
||
<div class="preset-name">Playful</div>
|
||
<div class="preset-desc">Friendly & round</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="minimal">
|
||
<div class="preset-name">Minimal</div>
|
||
<div class="preset-desc">Cool & focused</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="night">
|
||
<div class="preset-name">Night</div>
|
||
<div class="preset-desc">Dark & premium</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="classic">
|
||
<div class="preset-name">Classic</div>
|
||
<div class="preset-desc">Timeless elegance</div>
|
||
</button>
|
||
<button class="preset-button" data-preset="impulse">
|
||
<div class="preset-name">Impulse</div>
|
||
<div class="preset-desc">Fashion editorial</div>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Accent Color - stays in essentials -->
|
||
<div class="control-section">
|
||
<label class="control-label">Accent colour</label>
|
||
<div class="color-picker-wrapper">
|
||
<input type="color" class="color-picker" id="accent-picker" value="#f97316">
|
||
<span class="color-value" id="color-value">#f97316</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Customise Section (collapsible) -->
|
||
<div class="customise-section" id="customise-section">
|
||
<div class="customise-header" id="customise-header">
|
||
<span class="customise-title">Customise</span>
|
||
<svg class="customise-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="6 9 12 15 18 9"></polyline>
|
||
</svg>
|
||
</div>
|
||
|
||
<div class="customise-content">
|
||
<!-- Typography Group -->
|
||
<div class="control-group">
|
||
<div class="control-group-header">
|
||
<svg class="control-group-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="4 7 4 4 20 4 20 7"></polyline>
|
||
<line x1="9" y1="20" x2="15" y2="20"></line>
|
||
<line x1="12" y1="4" x2="12" y2="20"></line>
|
||
</svg>
|
||
<span class="control-group-title">Typography</span>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Font style</label>
|
||
<div class="option-group" id="typography-options">
|
||
<button class="option-button active" data-typography="clean">Clean</button>
|
||
<button class="option-button" data-typography="editorial">Editorial</button>
|
||
<button class="option-button" data-typography="modern">Modern</button>
|
||
<button class="option-button" data-typography="classic">Classic</button>
|
||
<button class="option-button" data-typography="friendly">Friendly</button>
|
||
<button class="option-button" data-typography="minimal">Minimal</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Font size</label>
|
||
<div class="option-group" id="font-size-options">
|
||
<button class="option-button" data-font-size="small">Small</button>
|
||
<button class="option-button active" data-font-size="medium">Medium</button>
|
||
<button class="option-button" data-font-size="large">Large</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Heading weight</label>
|
||
<div class="option-group" id="heading-weight-options">
|
||
<button class="option-button" data-heading-weight="regular">Regular</button>
|
||
<button class="option-button" data-heading-weight="medium">Medium</button>
|
||
<button class="option-button active" data-heading-weight="bold">Bold</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Colours Group -->
|
||
<div class="control-group">
|
||
<div class="control-group-header">
|
||
<svg class="control-group-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="12" r="10"></circle>
|
||
<circle cx="12" cy="12" r="3"></circle>
|
||
</svg>
|
||
<span class="control-group-title">Colours</span>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Colour mood</label>
|
||
<div class="option-group" id="mood-options">
|
||
<button class="option-button" data-mood="warm">Warm</button>
|
||
<button class="option-button active" data-mood="neutral">Neutral</button>
|
||
<button class="option-button" data-mood="cool">Cool</button>
|
||
<button class="option-button" data-mood="dark">Dark</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Hover colour</label>
|
||
<div class="color-picker-wrapper">
|
||
<input type="color" class="color-picker" id="secondary-accent-picker" value="#ea580c">
|
||
<span class="color-value" id="secondary-color-value">#ea580c</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Sale badge colour</label>
|
||
<div class="color-picker-wrapper">
|
||
<input type="color" class="color-picker" id="sale-color-picker" value="#dc2626">
|
||
<span class="color-value" id="sale-color-value">#dc2626</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Layout Group -->
|
||
<div class="control-group">
|
||
<div class="control-group-header">
|
||
<svg class="control-group-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||
<line x1="3" y1="9" x2="21" y2="9"></line>
|
||
<line x1="9" y1="21" x2="9" y2="9"></line>
|
||
</svg>
|
||
<span class="control-group-title">Layout</span>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Layout width</label>
|
||
<div class="option-group" id="layout-width-options">
|
||
<button class="option-button" data-layout-width="contained">Contained</button>
|
||
<button class="option-button active" data-layout-width="wide">Wide</button>
|
||
<button class="option-button" data-layout-width="full">Full width</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Density</label>
|
||
<div class="option-group" id="density-options">
|
||
<button class="option-button" data-density="spacious">Spacious</button>
|
||
<button class="option-button active" data-density="balanced">Balanced</button>
|
||
<button class="option-button" data-density="compact">Compact</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Corner style</label>
|
||
<div class="option-group" id="shape-options">
|
||
<button class="option-button" data-shape="sharp">Sharp</button>
|
||
<button class="option-button active" data-shape="soft">Soft</button>
|
||
<button class="option-button" data-shape="round">Round</button>
|
||
<button class="option-button" data-shape="pill">Pill</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Button style</label>
|
||
<div class="option-group" id="button-style-options">
|
||
<button class="option-button active" data-button-style="filled">Filled</button>
|
||
<button class="option-button" data-button-style="outline">Outline</button>
|
||
<button class="option-button" data-button-style="soft">Soft</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Product Cards Group -->
|
||
<div class="control-group">
|
||
<div class="control-group-header">
|
||
<svg class="control-group-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
|
||
<line x1="8" y1="21" x2="16" y2="21"></line>
|
||
<line x1="12" y1="17" x2="12" y2="21"></line>
|
||
</svg>
|
||
<span class="control-group-title">Product cards</span>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Products per row</label>
|
||
<div class="option-group" id="grid-options">
|
||
<button class="option-button" data-grid="2">2</button>
|
||
<button class="option-button" data-grid="3">3</button>
|
||
<button class="option-button active" data-grid="4">4</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Image ratio</label>
|
||
<div class="option-group" id="aspect-options">
|
||
<button class="option-button active" data-aspect="square">Square</button>
|
||
<button class="option-button" data-aspect="portrait">Portrait</button>
|
||
<button class="option-button" data-aspect="landscape">Landscape</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Text alignment</label>
|
||
<div class="option-group" id="product-text-options">
|
||
<button class="option-button active" data-product-text="left">Left</button>
|
||
<button class="option-button" data-product-text="center">Center</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Card shadow</label>
|
||
<div class="option-group" id="card-shadow-options">
|
||
<button class="option-button active" data-card-shadow="none">None</button>
|
||
<button class="option-button" data-card-shadow="subtle">Subtle</button>
|
||
<button class="option-button" data-card-shadow="pronounced">Pronounced</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Features</label>
|
||
<div class="toggle-list">
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="hover-image-toggle" checked>
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Second image on hover</span>
|
||
</label>
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="quick-add-toggle" checked>
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Quick add button</span>
|
||
</label>
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="show-prices-toggle" checked>
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Show prices</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Product Page Group -->
|
||
<div class="control-group">
|
||
<div class="control-group-header">
|
||
<svg class="control-group-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||
<polyline points="14 2 14 8 20 8"></polyline>
|
||
</svg>
|
||
<span class="control-group-title">Product page</span>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Gallery position</label>
|
||
<div class="option-group" id="gallery-position-options">
|
||
<button class="option-button active" data-gallery-position="left">Left</button>
|
||
<button class="option-button" data-gallery-position="right">Right</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Sections</label>
|
||
<div class="toggle-list">
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="pdp-trust-toggle" checked>
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Trust badges</span>
|
||
</label>
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="pdp-reviews-toggle" checked>
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Reviews section</span>
|
||
</label>
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="pdp-related-toggle" checked>
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Related products</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Header Group -->
|
||
<div class="control-group">
|
||
<div class="control-group-header">
|
||
<svg class="control-group-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||
<line x1="3" y1="9" x2="21" y2="9"></line>
|
||
</svg>
|
||
<span class="control-group-title">Header</span>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Layout</label>
|
||
<div class="option-group" id="header-options">
|
||
<button class="option-button active" data-header="standard">Standard</button>
|
||
<button class="option-button" data-header="centered">Centered</button>
|
||
<button class="option-button" data-header="minimal">Minimal</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="control-section">
|
||
<label class="control-label">Features</label>
|
||
<div class="toggle-list">
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="announcement-bar-toggle" checked>
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Announcement bar</span>
|
||
</label>
|
||
<label class="toggle-label">
|
||
<input type="checkbox" id="sticky-header-toggle">
|
||
<span class="toggle-switch"></span>
|
||
<span class="toggle-text">Sticky header</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Current combination -->
|
||
<div class="combo-display">
|
||
<div class="combo-label">Current combination</div>
|
||
<div class="combo-value" id="combo-value">Neutral · Clean · Soft · Balanced · 4-up · Standard</div>
|
||
<div class="combo-count">One of 100,000+ possible combinations</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Preview Area -->
|
||
<div class="preview-area">
|
||
<div class="preview-container">
|
||
<div class="page-toggle">
|
||
<button class="page-toggle-btn active" data-page="home">Home</button>
|
||
<button class="page-toggle-btn" data-page="collection">Collection</button>
|
||
<button class="page-toggle-btn" data-page="pdp">Product</button>
|
||
<button class="page-toggle-btn" data-page="cart">Cart</button>
|
||
<button class="page-toggle-btn" data-page="about">About</button>
|
||
<button class="page-toggle-btn" data-page="contact">Contact</button>
|
||
<button class="page-toggle-btn" data-page="error">Error</button>
|
||
</div>
|
||
|
||
<div class="browser-chrome">
|
||
<div class="browser-traffic-lights">
|
||
<span class="traffic-light red"></span>
|
||
<span class="traffic-light yellow"></span>
|
||
<span class="traffic-light green"></span>
|
||
</div>
|
||
<div class="browser-nav">
|
||
<button class="browser-nav-btn" aria-label="Back">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 18l-6-6 6-6"/></svg>
|
||
</button>
|
||
<button class="browser-nav-btn" aria-label="Forward">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>
|
||
</button>
|
||
</div>
|
||
<div class="browser-url-bar">
|
||
<svg class="browser-url-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
|
||
<path d="M7 11V7a5 5 0 0 1 10 0v4"/>
|
||
</svg>
|
||
<div class="browser-favicon" id="browser-favicon">
|
||
<span class="favicon-letter" id="favicon-letter">B</span>
|
||
</div>
|
||
<span class="browser-url-text"><span class="domain" id="browser-domain">botanicalstudio</span>.simpleshop.uk</span>
|
||
</div>
|
||
<div class="browser-actions">
|
||
<button class="browser-action-btn" aria-label="Share">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"/>
|
||
<polyline points="16 6 12 2 8 6"/>
|
||
<line x1="12" y1="2" x2="12" y2="15"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="preview-frame" id="preview-frame"
|
||
data-mood="neutral"
|
||
data-typography="clean"
|
||
data-shape="soft"
|
||
data-density="balanced">
|
||
|
||
<!-- Announcement Bar -->
|
||
<div class="announcement-bar" id="announcement-bar">
|
||
<p>Free UK shipping on orders over £50 ✨</p>
|
||
</div>
|
||
|
||
<!-- Shop Header -->
|
||
<header class="shop-header" id="shop-header" data-header="standard" data-logo-mode="text-only">
|
||
<div class="shop-logo" id="shop-logo">
|
||
<div class="shop-logo-image" id="shop-logo-image">
|
||
<img id="shop-logo-img" src="" alt="">
|
||
</div>
|
||
<span class="shop-logo-text" id="shop-logo-text">Botanical Studio</span>
|
||
</div>
|
||
<nav class="shop-nav">
|
||
<a href="#" data-nav="home">Home</a>
|
||
<a href="#" data-nav="collection">Shop All</a>
|
||
<a href="#" data-nav="about">About</a>
|
||
<a href="#" data-nav="contact">Contact</a>
|
||
</nav>
|
||
<div class="shop-cart">
|
||
<button class="header-icon-btn search-btn" id="search-btn" aria-label="Search">
|
||
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="8"></circle>
|
||
<path d="M21 21l-4.35-4.35"></path>
|
||
</svg>
|
||
</button>
|
||
<button class="header-icon-btn cart-btn" id="cart-btn" aria-label="Cart">
|
||
<svg class="icon cart-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"></path>
|
||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||
<path d="M16 10a4 4 0 01-8 0"></path>
|
||
</svg>
|
||
<span class="cart-count">2</span>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Home View -->
|
||
<div class="page-view home-view active" id="home-view">
|
||
<!-- Hero -->
|
||
<section class="shop-hero">
|
||
<h1 id="hero-title">Nature-inspired art prints</h1>
|
||
<p>Original botanical illustrations, printed on premium archival paper. Each piece brings a little bit of the outside, inside.</p>
|
||
<button class="btn btn-primary" id="shop-collection-btn" data-nav="collection">Shop the collection</button>
|
||
</section>
|
||
|
||
<!-- Categories -->
|
||
<section class="home-categories">
|
||
<nav class="category-links" aria-label="Product categories">
|
||
<a href="#" class="category-link" data-nav="collection">
|
||
<div class="category-image cat-img-1"></div>
|
||
<span class="category-name">Botanicals</span>
|
||
</a>
|
||
<a href="#" class="category-link" data-nav="collection">
|
||
<div class="category-image cat-img-2"></div>
|
||
<span class="category-name">Florals</span>
|
||
</a>
|
||
<a href="#" class="category-link" data-nav="collection">
|
||
<div class="category-image cat-img-3"></div>
|
||
<span class="category-name">Landscapes</span>
|
||
</a>
|
||
</nav>
|
||
</section>
|
||
|
||
<!-- Featured Products -->
|
||
<section class="product-section">
|
||
<h2 class="section-title">Featured prints</h2>
|
||
<div class="product-grid" id="product-grid" data-grid="4">
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<span class="product-badge badge-new">New</span>
|
||
<div class="product-image-primary img-1"></div>
|
||
<div class="product-image-hover img-1-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Autumn Fern</h3>
|
||
<p class="product-price">£24.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<span class="product-badge badge-sale">Sale</span>
|
||
<div class="product-image-primary img-2"></div>
|
||
<div class="product-image-hover img-2-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Wild Roses</h3>
|
||
<p class="product-price"><span class="price-was">£35.00</span> £28.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-3"></div>
|
||
<div class="product-image-hover img-3-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Morning Dew</h3>
|
||
<p class="product-price">£24.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-5"></div>
|
||
<div class="product-image-hover img-5-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Spring Bloom</h3>
|
||
<p class="product-price">£28.00</p>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
<div class="section-cta">
|
||
<button class="btn btn-secondary" data-nav="collection">View all products</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- About Snippet -->
|
||
<section class="home-about">
|
||
<div class="home-about-image"></div>
|
||
<div class="home-about-content">
|
||
<h2>Made with care in Yorkshire</h2>
|
||
<p>Every illustration starts as a pencil sketch, inspired by the plants and flowers found in British woodlands, meadows, and gardens. Printed on museum-quality archival paper using pigment-based inks that will last a lifetime.</p>
|
||
<a href="#" class="text-link" data-nav="about">Learn more about the studio →</a>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Footer -->
|
||
<footer class="shop-footer" id="home-footer">
|
||
<div class="footer-content">
|
||
<div class="footer-newsletter">
|
||
<h3 class="footer-heading">Join the studio</h3>
|
||
<p class="footer-text">Get 10% off your first order and be the first to know about new prints.</p>
|
||
<form class="newsletter-form">
|
||
<input type="email" class="newsletter-input" placeholder="your@email.com">
|
||
<button type="submit" class="btn btn-primary newsletter-btn">Subscribe</button>
|
||
</form>
|
||
</div>
|
||
<div class="footer-links">
|
||
<div class="footer-column">
|
||
<h4 class="footer-column-title">Shop</h4>
|
||
<a href="#" data-nav="collection">All products</a>
|
||
<a href="#" data-nav="collection">New arrivals</a>
|
||
<a href="#" data-nav="collection">Best sellers</a>
|
||
</div>
|
||
<div class="footer-column">
|
||
<h4 class="footer-column-title">Help</h4>
|
||
<a href="#" data-nav="contact">Shipping</a>
|
||
<a href="#" data-nav="contact">Returns</a>
|
||
<a href="#" data-nav="contact">Contact</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="footer-bottom">
|
||
<p id="footer-text">© 2025 Botanical Studio</p>
|
||
<div class="footer-social">
|
||
<a href="#" class="social-link" aria-label="Instagram">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect>
|
||
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path>
|
||
<line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line>
|
||
</svg>
|
||
</a>
|
||
<a href="#" class="social-link" aria-label="Pinterest">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="12" r="10"></circle>
|
||
<path d="M8 12c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4"></path>
|
||
<line x1="12" y1="16" x2="9" y2="21"></line>
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- Collection View -->
|
||
<div class="page-view collection-view" id="collection-view">
|
||
<div class="collection-header">
|
||
<h1 class="collection-title">Shop All</h1>
|
||
<p class="collection-count">12 products</p>
|
||
</div>
|
||
|
||
<section class="product-section">
|
||
<div class="collection-toolbar">
|
||
<div class="collection-filter" role="group" aria-label="Filter by category">
|
||
<button class="filter-btn active">All</button>
|
||
<button class="filter-btn">Botanicals</button>
|
||
<button class="filter-btn">Florals</button>
|
||
<button class="filter-btn">Landscapes</button>
|
||
</div>
|
||
<div class="collection-sort">
|
||
<label for="sort-select" class="visually-hidden">Sort products</label>
|
||
<select id="sort-select" class="sort-select">
|
||
<option>Featured</option>
|
||
<option>Price: Low to high</option>
|
||
<option>Price: High to low</option>
|
||
<option>Newest</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="product-grid" data-grid="4">
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<span class="product-badge badge-new">New</span>
|
||
<div class="product-image-primary img-1"></div>
|
||
<div class="product-image-hover img-1-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Autumn Fern</h3>
|
||
<p class="product-price">£24.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<span class="product-badge badge-sale">Sale</span>
|
||
<div class="product-image-primary img-2"></div>
|
||
<div class="product-image-hover img-2-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Wild Roses</h3>
|
||
<p class="product-price"><span class="price-was">£35.00</span> £28.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-3"></div>
|
||
<div class="product-image-hover img-3-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Morning Dew</h3>
|
||
<p class="product-price">£24.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<span class="product-badge badge-sold">Sold out</span>
|
||
<div class="product-image-primary img-4"></div>
|
||
<div class="product-image-hover img-4-alt"></div>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Oak Leaves</h3>
|
||
<p class="product-price">£32.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-5"></div>
|
||
<div class="product-image-hover img-5-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Spring Bloom</h3>
|
||
<p class="product-price">£28.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-6"></div>
|
||
<div class="product-image-hover img-6-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Lavender Fields</h3>
|
||
<p class="product-price">£24.00</p>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
|
||
<footer class="shop-footer" id="collection-footer">
|
||
<div class="footer-bottom">
|
||
<p id="footer-text-collection">© 2025 Botanical Studio</p>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- PDP View -->
|
||
<div class="page-view pdp-view" id="pdp-view">
|
||
<div class="pdp-container">
|
||
<nav class="pdp-breadcrumb">
|
||
<a href="#" data-nav="home">Home</a>
|
||
<span class="breadcrumb-sep">›</span>
|
||
<a href="#" data-nav="collection">Shop All</a>
|
||
<span class="breadcrumb-sep">›</span>
|
||
<span>Autumn Fern</span>
|
||
</nav>
|
||
|
||
<div class="pdp-layout">
|
||
<div class="pdp-gallery">
|
||
<div class="pdp-main-image" id="pdp-main-image" style="background-image: url('https://picsum.photos/seed/fern/600/600')">
|
||
<button class="zoom-btn" id="zoom-btn" aria-label="View larger image">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="8"></circle>
|
||
<path d="M21 21l-4.35-4.35"></path>
|
||
<line x1="11" y1="8" x2="11" y2="14"></line>
|
||
<line x1="8" y1="11" x2="14" y2="11"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div class="pdp-thumbnails">
|
||
<div class="pdp-thumb active"
|
||
data-image="https://picsum.photos/seed/fern/600/600"
|
||
data-alt="Autumn Fern botanical illustration - front view"
|
||
data-description="Delicate hand-drawn fern fronds in graphite and watercolour, showing the full composition"></div>
|
||
<div class="pdp-thumb"
|
||
data-image="https://picsum.photos/seed/fern-alt/600/600"
|
||
data-alt="Autumn Fern botanical illustration - detail view"
|
||
data-description="Close-up detail showing the intricate vein patterns and subtle colour gradations"></div>
|
||
<div class="pdp-thumb"
|
||
data-image="https://picsum.photos/seed/fern-detail/600/600"
|
||
data-alt="Autumn Fern botanical illustration - framed example"
|
||
data-description="Example of the print displayed in an oak frame, showing scale and presentation"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pdp-details">
|
||
<h1 class="pdp-title">Autumn Fern</h1>
|
||
<p class="pdp-price">£24.00</p>
|
||
|
||
<div class="pdp-description">
|
||
<p>A delicate botanical illustration capturing the intricate fronds of an autumn fern. Each piece is printed on museum-quality 300gsm cotton rag paper using archival inks.</p>
|
||
</div>
|
||
|
||
<div class="pdp-options">
|
||
<div class="pdp-option-group">
|
||
<label class="pdp-option-label">Size</label>
|
||
<div class="pdp-option-buttons">
|
||
<button class="pdp-option-btn active">A5</button>
|
||
<button class="pdp-option-btn">A4</button>
|
||
<button class="pdp-option-btn">A3</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pdp-option-group">
|
||
<label class="pdp-option-label">Frame</label>
|
||
<div class="pdp-option-buttons">
|
||
<button class="pdp-option-btn active">Unframed</button>
|
||
<button class="pdp-option-btn">Oak</button>
|
||
<button class="pdp-option-btn">Black</button>
|
||
<button class="pdp-option-btn">White</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pdp-details-sections">
|
||
<details class="pdp-details">
|
||
<summary class="pdp-details-summary">
|
||
<span>Size guide</span>
|
||
<svg class="pdp-details-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="6 9 12 15 18 9"></polyline>
|
||
</svg>
|
||
</summary>
|
||
<div class="pdp-details-content">
|
||
<table class="size-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Size</th>
|
||
<th>Dimensions</th>
|
||
<th>Best for</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>A5</td>
|
||
<td>14.8 × 21 cm</td>
|
||
<td>Desks, shelves</td>
|
||
</tr>
|
||
<tr>
|
||
<td>A4</td>
|
||
<td>21 × 29.7 cm</td>
|
||
<td>Small wall spaces</td>
|
||
</tr>
|
||
<tr>
|
||
<td>A3</td>
|
||
<td>29.7 × 42 cm</td>
|
||
<td>Statement pieces</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="pdp-details">
|
||
<summary class="pdp-details-summary">
|
||
<span>Materials & quality</span>
|
||
<svg class="pdp-details-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="6 9 12 15 18 9"></polyline>
|
||
</svg>
|
||
</summary>
|
||
<div class="pdp-details-content">
|
||
<ul class="details-list">
|
||
<li>Printed on 300gsm museum-quality cotton rag paper</li>
|
||
<li>Archival pigment inks rated 100+ years</li>
|
||
<li>FSC-certified sustainable paper</li>
|
||
<li>Each print is hand-checked before shipping</li>
|
||
</ul>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="pdp-details">
|
||
<summary class="pdp-details-summary">
|
||
<span>Shipping & returns</span>
|
||
<svg class="pdp-details-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="6 9 12 15 18 9"></polyline>
|
||
</svg>
|
||
</summary>
|
||
<div class="pdp-details-content">
|
||
<ul class="details-list">
|
||
<li>Free UK shipping on orders over £50</li>
|
||
<li>Dispatched within 2-3 business days</li>
|
||
<li>Plastic-free packaging</li>
|
||
<li>30-day returns for unused items</li>
|
||
</ul>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
|
||
<button class="btn btn-primary pdp-add-btn">Add to basket</button>
|
||
|
||
<div class="pdp-meta">
|
||
<div class="pdp-meta-item">
|
||
<svg class="pdp-meta-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M12 22s-8-4.5-8-11.8A8 8 0 0 1 12 2a8 8 0 0 1 8 8.2c0 7.3-8 11.8-8 11.8z"/>
|
||
<circle cx="12" cy="10" r="3"/>
|
||
</svg>
|
||
<span>Printed in the UK</span>
|
||
</div>
|
||
<div class="pdp-meta-item">
|
||
<svg class="pdp-meta-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="1" y="3" width="15" height="13"></rect>
|
||
<polygon points="16 8 20 8 23 11 23 16 16 16 16 8"></polygon>
|
||
<circle cx="5.5" cy="18.5" r="2.5"></circle>
|
||
<circle cx="18.5" cy="18.5" r="2.5"></circle>
|
||
</svg>
|
||
<span>Free UK shipping over £50</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pdp-trust-badges">
|
||
<div class="trust-badge">
|
||
<svg class="trust-badge-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
|
||
<polyline points="9 12 11 14 15 10"></polyline>
|
||
</svg>
|
||
<span>Secure checkout</span>
|
||
</div>
|
||
<div class="trust-badge">
|
||
<svg class="trust-badge-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
|
||
<circle cx="12" cy="10" r="3"></circle>
|
||
</svg>
|
||
<span>UK based</span>
|
||
</div>
|
||
<div class="trust-badge">
|
||
<svg class="trust-badge-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="20 6 9 17 4 12"></polyline>
|
||
</svg>
|
||
<span>Quality guaranteed</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Reviews Section -->
|
||
<div class="pdp-reviews">
|
||
<div class="reviews-header">
|
||
<h2 class="section-title">Customer reviews</h2>
|
||
<div class="reviews-summary">
|
||
<div class="reviews-stars">
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
</div>
|
||
<span class="reviews-count">Based on 24 reviews</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="reviews-list">
|
||
<article class="review">
|
||
<div class="review-header">
|
||
<div class="review-stars">
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
</div>
|
||
<span class="review-date">2 weeks ago</span>
|
||
</div>
|
||
<h3 class="review-title">Absolutely beautiful</h3>
|
||
<p class="review-text">The quality exceeded my expectations. The colours are vibrant and the paper feels premium. It's now pride of place in my living room.</p>
|
||
<div class="review-author">
|
||
<span class="review-name">Sarah M.</span>
|
||
<span class="review-verified">Verified purchase</span>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="review">
|
||
<div class="review-header">
|
||
<div class="review-stars">
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star filled" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
<svg class="star" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" fill="currentColor"/></svg>
|
||
</div>
|
||
<span class="review-date">1 month ago</span>
|
||
</div>
|
||
<h3 class="review-title">Great gift</h3>
|
||
<p class="review-text">Bought this as a gift and it arrived beautifully packaged. Fast shipping too. Would definitely order again.</p>
|
||
<div class="review-author">
|
||
<span class="review-name">James T.</span>
|
||
<span class="review-verified">Verified purchase</span>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
|
||
<button class="btn btn-secondary reviews-load-more">Load more reviews</button>
|
||
</div>
|
||
|
||
<!-- Related Products -->
|
||
<div class="pdp-related">
|
||
<h2 class="section-title">You might also like</h2>
|
||
<div class="related-grid">
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-2"></div>
|
||
<div class="product-image-hover img-2-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Wild Roses</h3>
|
||
<p class="product-price">£28.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-3"></div>
|
||
<div class="product-image-hover img-3-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Morning Dew</h3>
|
||
<p class="product-price">£24.00</p>
|
||
</div>
|
||
</article>
|
||
<article class="product-card">
|
||
<div class="product-image">
|
||
<div class="product-image-primary img-4"></div>
|
||
<div class="product-image-hover img-4-alt"></div>
|
||
<button class="quick-add-btn">Quick add</button>
|
||
</div>
|
||
<div class="product-info">
|
||
<h3 class="product-title">Oak Leaves</h3>
|
||
<p class="product-price">£32.00</p>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<footer class="shop-footer" id="pdp-footer">
|
||
<div class="footer-content">
|
||
<div class="footer-newsletter">
|
||
<h3 class="footer-heading">Join the studio</h3>
|
||
<p class="footer-text">Get 10% off your first order and be the first to know about new prints.</p>
|
||
<form class="newsletter-form">
|
||
<input type="email" class="newsletter-input" placeholder="your@email.com">
|
||
<button type="submit" class="btn btn-primary newsletter-btn">Subscribe</button>
|
||
</form>
|
||
</div>
|
||
<div class="footer-links">
|
||
<div class="footer-column">
|
||
<h4 class="footer-column-title">Shop</h4>
|
||
<a href="#">All prints</a>
|
||
<a href="#">New arrivals</a>
|
||
<a href="#">Best sellers</a>
|
||
</div>
|
||
<div class="footer-column">
|
||
<h4 class="footer-column-title">Help</h4>
|
||
<a href="#">Shipping</a>
|
||
<a href="#">Returns</a>
|
||
<a href="#">Contact</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="footer-bottom">
|
||
<p id="footer-text-pdp">© 2025 Botanical Studio</p>
|
||
<div class="footer-social">
|
||
<a href="#" class="social-link" aria-label="Instagram">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect>
|
||
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path>
|
||
<line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line>
|
||
</svg>
|
||
</a>
|
||
<a href="#" class="social-link" aria-label="Pinterest">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="12" r="10"></circle>
|
||
<path d="M8 12c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4"></path>
|
||
<line x1="12" y1="16" x2="9" y2="21"></line>
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- Cart Page -->
|
||
<div class="page-view cart-view" id="cart-view">
|
||
<div class="cart-container">
|
||
<div class="cart-header-row">
|
||
<h1 class="cart-title">Your basket</h1>
|
||
<button class="cart-state-toggle" id="cart-state-toggle">Preview empty state</button>
|
||
</div>
|
||
|
||
<!-- Full Cart State -->
|
||
<div class="cart-state cart-state-full" id="cart-full">
|
||
<div class="cart-layout">
|
||
<div class="cart-items">
|
||
<div class="cart-item">
|
||
<div class="cart-item-image img-1"></div>
|
||
<div class="cart-item-details">
|
||
<h3 class="cart-item-title">Autumn Fern</h3>
|
||
<p class="cart-item-variant">A4 / Unframed</p>
|
||
<p class="cart-item-price">£24.00</p>
|
||
</div>
|
||
<div class="cart-item-quantity">
|
||
<button class="qty-btn">−</button>
|
||
<span class="qty-value">1</span>
|
||
<button class="qty-btn">+</button>
|
||
</div>
|
||
<button class="cart-item-remove" aria-label="Remove">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="cart-item">
|
||
<div class="cart-item-image img-2"></div>
|
||
<div class="cart-item-details">
|
||
<h3 class="cart-item-title">Wild Roses</h3>
|
||
<p class="cart-item-variant">A3 / Oak frame</p>
|
||
<p class="cart-item-price">£48.00</p>
|
||
</div>
|
||
<div class="cart-item-quantity">
|
||
<button class="qty-btn">−</button>
|
||
<span class="qty-value">1</span>
|
||
<button class="qty-btn">+</button>
|
||
</div>
|
||
<button class="cart-item-remove" aria-label="Remove">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="cart-summary">
|
||
<div class="cart-summary-row">
|
||
<span>Subtotal</span>
|
||
<span>£72.00</span>
|
||
</div>
|
||
<div class="cart-summary-row">
|
||
<span>Shipping</span>
|
||
<span>Calculated at checkout</span>
|
||
</div>
|
||
<div class="cart-summary-row cart-total">
|
||
<span>Total</span>
|
||
<span>£72.00</span>
|
||
</div>
|
||
<button class="btn btn-primary cart-checkout-btn">Checkout</button>
|
||
<p class="cart-secure-note">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||
</svg>
|
||
Secure checkout powered by Stripe
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Empty Cart State -->
|
||
<div class="cart-state cart-state-empty" id="cart-empty" hidden>
|
||
<div class="empty-state">
|
||
<div class="empty-state-illustration">
|
||
<svg viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<!-- Soft background -->
|
||
<circle cx="60" cy="60" r="48" fill="currentColor" opacity="0.04"/>
|
||
|
||
<!-- Simple elegant shopping bag -->
|
||
<rect x="32" y="44" width="56" height="52" rx="4"
|
||
stroke="currentColor" stroke-width="2" fill="none" opacity="0.6"/>
|
||
|
||
<!-- Bag handles -->
|
||
<path d="M44 44 C44 44 44 32 60 32 C76 32 76 44 76 44"
|
||
stroke="currentColor" stroke-width="2" fill="none"
|
||
stroke-linecap="round" opacity="0.6"/>
|
||
|
||
<!-- Simple fold line -->
|
||
<line x1="32" y1="52" x2="88" y2="52"
|
||
stroke="currentColor" stroke-width="1" opacity="0.2"/>
|
||
</svg>
|
||
</div>
|
||
<h2 class="empty-state-title">Your basket is empty</h2>
|
||
<p class="empty-state-message">Looks like you haven't added anything yet. Start exploring our collection to find something you'll love.</p>
|
||
<button class="btn btn-primary" data-nav="collection">Continue shopping</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="shop-footer" id="cart-footer">
|
||
<div class="footer-bottom">
|
||
<p id="footer-text-cart">© 2025 Botanical Studio</p>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- About Page -->
|
||
<div class="page-view about-view" id="about-view">
|
||
<div class="content-page">
|
||
<div class="content-hero">
|
||
<h1 class="content-title">About the studio</h1>
|
||
<p class="content-subtitle">Nature-inspired art, made with care</p>
|
||
</div>
|
||
|
||
<div class="content-body">
|
||
<div class="content-image about-image"></div>
|
||
|
||
<div class="content-text">
|
||
<p class="lead-text">Botanical Studio was born from a love of the natural world and a desire to bring its beauty indoors.</p>
|
||
|
||
<p>Every illustration starts as a pencil sketch, inspired by the plants and flowers found in British woodlands, meadows, and gardens. These sketches are then refined and printed on museum-quality archival paper using pigment-based inks that will last a lifetime.</p>
|
||
|
||
<p>Based in the Yorkshire countryside, I work from a small garden studio surrounded by the very nature that inspires each piece. Every print is checked by hand before being carefully packaged and sent on its way.</p>
|
||
|
||
<h2>Sustainability</h2>
|
||
<p>I believe beautiful art shouldn't cost the earth. All prints are produced on FSC-certified paper, shipped in plastic-free packaging, and printed locally to reduce transport emissions.</p>
|
||
|
||
<h2>The process</h2>
|
||
<p>Each botanical illustration takes between 20-40 hours to complete, from initial field sketches through to the final digital refinement. I work primarily in graphite and watercolour, which are then scanned and carefully colour-corrected to ensure the prints match the original artwork.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="shop-footer" id="about-footer">
|
||
<div class="footer-bottom">
|
||
<p id="footer-text-about">© 2025 Botanical Studio</p>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- Contact Page -->
|
||
<div class="page-view contact-view" id="contact-view">
|
||
<div class="content-page">
|
||
<div class="content-hero">
|
||
<h1 class="content-title">Get in touch</h1>
|
||
<p class="content-subtitle">I'd love to hear from you</p>
|
||
</div>
|
||
|
||
<div class="contact-layout">
|
||
<div class="contact-info">
|
||
<div class="contact-block">
|
||
<h3>General enquiries</h3>
|
||
<p>For questions about prints, shipping, or custom orders.</p>
|
||
<a href="mailto:hello@botanicalstudio.com" class="contact-link">hello@botanicalstudio.com</a>
|
||
</div>
|
||
|
||
<div class="contact-block">
|
||
<h3>Response time</h3>
|
||
<p>I typically respond within 1-2 business days. For urgent order queries, please include your order number.</p>
|
||
</div>
|
||
|
||
<div class="contact-block">
|
||
<h3>Follow along</h3>
|
||
<p>See works in progress and behind-the-scenes on Instagram.</p>
|
||
<div class="contact-social">
|
||
<a href="#" class="social-link" aria-label="Instagram">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect>
|
||
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path>
|
||
<line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line>
|
||
</svg>
|
||
</a>
|
||
<a href="#" class="social-link" aria-label="Pinterest">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="12" r="10"></circle>
|
||
<path d="M8 12c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4"></path>
|
||
<line x1="12" y1="16" x2="9" y2="21"></line>
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<form class="contact-form">
|
||
<div class="form-group">
|
||
<label class="form-label" for="contact-name">Name</label>
|
||
<input type="text" id="contact-name" class="form-input" placeholder="Your name">
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="contact-email">Email</label>
|
||
<input type="email" id="contact-email" class="form-input" placeholder="your@email.com">
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="contact-subject">Subject</label>
|
||
<select id="contact-subject" class="form-input form-select">
|
||
<option>General enquiry</option>
|
||
<option>Order question</option>
|
||
<option>Custom order</option>
|
||
<option>Wholesale / Trade</option>
|
||
<option>Press / Collaboration</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="form-label" for="contact-message">Message</label>
|
||
<textarea id="contact-message" class="form-input form-textarea" rows="5" placeholder="How can I help?"></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary form-submit">Send message</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="shop-footer" id="contact-footer">
|
||
<div class="footer-bottom">
|
||
<p id="footer-text-contact">© 2025 Botanical Studio</p>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- Error Page -->
|
||
<div class="page-view error-view" id="error-view">
|
||
<div class="error-container">
|
||
<div class="error-content">
|
||
<div class="error-illustration">
|
||
<svg viewBox="0 0 200 160" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<!-- Soft background -->
|
||
<circle cx="100" cy="75" r="55" fill="currentColor" opacity="0.04"/>
|
||
|
||
<!-- Magnifying glass - universal "not found" symbol -->
|
||
<circle cx="90" cy="70" r="32"
|
||
stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.5"/>
|
||
<line x1="113" y1="93" x2="140" y2="120"
|
||
stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
|
||
|
||
<!-- Question mark inside magnifying glass -->
|
||
<path d="M82 60 C82 52 88 48 95 48 C102 48 108 52 108 60 C108 66 102 68 95 72"
|
||
stroke="currentColor" stroke-width="2" fill="none"
|
||
stroke-linecap="round" opacity="0.4"/>
|
||
<circle cx="95" cy="82" r="2.5" fill="currentColor" opacity="0.4"/>
|
||
|
||
<!-- Small decorative dots suggesting scattered/lost -->
|
||
<circle cx="45" cy="45" r="3" fill="currentColor" opacity="0.15"/>
|
||
<circle cx="155" cy="55" r="2" fill="currentColor" opacity="0.1"/>
|
||
<circle cx="160" cy="100" r="2.5" fill="currentColor" opacity="0.12"/>
|
||
<circle cx="40" cy="110" r="2" fill="currentColor" opacity="0.1"/>
|
||
</svg>
|
||
</div>
|
||
<h1 class="error-title">Something went wrong</h1>
|
||
<p class="error-message">We couldn't find what you were looking for. The page may have moved, or perhaps it never existed in the first place.</p>
|
||
<div class="error-actions">
|
||
<button class="btn btn-primary" data-nav="home">Go to homepage</button>
|
||
<button class="btn btn-secondary" data-nav="collection">Browse products</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="shop-footer" id="error-footer">
|
||
<div class="footer-bottom">
|
||
<p id="footer-text-error">© 2025 Botanical Studio</p>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- Cart Drawer -->
|
||
<div class="cart-drawer" id="cart-drawer">
|
||
<div class="cart-drawer-header">
|
||
<h2>Your basket</h2>
|
||
<button class="cart-drawer-close" id="cart-drawer-close">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div class="cart-drawer-items">
|
||
<div class="cart-drawer-item">
|
||
<div class="cart-drawer-item-image img-1"></div>
|
||
<div class="cart-drawer-item-details">
|
||
<h3>Autumn Fern</h3>
|
||
<p>A4 / Unframed</p>
|
||
<p class="cart-drawer-item-price">£24.00</p>
|
||
</div>
|
||
</div>
|
||
<div class="cart-drawer-item">
|
||
<div class="cart-drawer-item-image img-2"></div>
|
||
<div class="cart-drawer-item-details">
|
||
<h3>Wild Roses</h3>
|
||
<p>A3 / Oak frame</p>
|
||
<p class="cart-drawer-item-price">£48.00</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cart-drawer-footer">
|
||
<div class="cart-drawer-total">
|
||
<span>Subtotal</span>
|
||
<span>£72.00</span>
|
||
</div>
|
||
<button class="btn btn-primary cart-drawer-checkout">Checkout</button>
|
||
<a href="#" class="cart-drawer-link" id="view-cart-link">View basket</a>
|
||
</div>
|
||
</div>
|
||
<div class="cart-drawer-overlay" id="cart-drawer-overlay"></div>
|
||
|
||
<!-- Search Modal -->
|
||
<div class="search-modal" id="search-modal">
|
||
<div class="search-modal-content">
|
||
<div class="search-input-wrapper">
|
||
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="11" cy="11" r="8"></circle>
|
||
<path d="M21 21l-4.35-4.35"></path>
|
||
</svg>
|
||
<input type="text" class="search-input" placeholder="Search products..." autofocus>
|
||
<button class="search-close" id="search-close">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div class="search-results">
|
||
<p class="search-hint">Try searching for "fern", "roses", or "botanical"</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Image Lightbox -->
|
||
<dialog class="lightbox" id="lightbox" aria-label="Product image gallery">
|
||
<div class="lightbox-content">
|
||
<button class="lightbox-close" id="lightbox-close" aria-label="Close gallery">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||
</svg>
|
||
</button>
|
||
<button class="lightbox-nav lightbox-prev" id="lightbox-prev" aria-label="Previous image">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="15 18 9 12 15 6"></polyline>
|
||
</svg>
|
||
</button>
|
||
<figure class="lightbox-figure">
|
||
<div class="lightbox-image-container">
|
||
<img class="lightbox-image" id="lightbox-image" src="" alt="">
|
||
</div>
|
||
<figcaption class="lightbox-caption" id="lightbox-caption"></figcaption>
|
||
</figure>
|
||
<button class="lightbox-nav lightbox-next" id="lightbox-next" aria-label="Next image">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<polyline points="9 18 15 12 9 6"></polyline>
|
||
</svg>
|
||
</button>
|
||
<div class="lightbox-counter" id="lightbox-counter" aria-live="polite">1 / 3</div>
|
||
</div>
|
||
</dialog>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// Presets configuration
|
||
const presets = {
|
||
gallery: {
|
||
mood: 'warm',
|
||
typography: 'editorial',
|
||
shape: 'soft',
|
||
density: 'spacious',
|
||
grid: '3',
|
||
header: 'centered',
|
||
accent: '#e85d04'
|
||
},
|
||
studio: {
|
||
mood: 'neutral',
|
||
typography: 'clean',
|
||
shape: 'soft',
|
||
density: 'balanced',
|
||
grid: '4',
|
||
header: 'standard',
|
||
accent: '#3b82f6'
|
||
},
|
||
boutique: {
|
||
mood: 'warm',
|
||
typography: 'classic',
|
||
shape: 'soft',
|
||
density: 'balanced',
|
||
grid: '3',
|
||
header: 'centered',
|
||
accent: '#b45309'
|
||
},
|
||
bold: {
|
||
mood: 'neutral',
|
||
typography: 'modern',
|
||
shape: 'sharp',
|
||
density: 'compact',
|
||
grid: '4',
|
||
header: 'standard',
|
||
accent: '#dc2626'
|
||
},
|
||
playful: {
|
||
mood: 'neutral',
|
||
typography: 'friendly',
|
||
shape: 'pill',
|
||
density: 'balanced',
|
||
grid: '4',
|
||
header: 'standard',
|
||
accent: '#8b5cf6'
|
||
},
|
||
minimal: {
|
||
mood: 'cool',
|
||
typography: 'clean',
|
||
shape: 'sharp',
|
||
density: 'spacious',
|
||
grid: '2',
|
||
header: 'minimal',
|
||
accent: '#171717'
|
||
},
|
||
night: {
|
||
mood: 'dark',
|
||
typography: 'modern',
|
||
shape: 'soft',
|
||
density: 'balanced',
|
||
grid: '4',
|
||
header: 'standard',
|
||
accent: '#f97316'
|
||
},
|
||
classic: {
|
||
mood: 'warm',
|
||
typography: 'classic',
|
||
shape: 'soft',
|
||
density: 'spacious',
|
||
grid: '3',
|
||
header: 'standard',
|
||
accent: '#166534'
|
||
},
|
||
impulse: {
|
||
mood: 'neutral',
|
||
typography: 'impulse',
|
||
shape: 'sharp',
|
||
density: 'spacious',
|
||
grid: '3',
|
||
header: 'centered',
|
||
accent: '#000000',
|
||
// Additional Impulse-specific settings
|
||
fontSize: 'medium',
|
||
headingWeight: 'regular',
|
||
layoutWidth: 'full',
|
||
buttonStyle: 'filled',
|
||
cardShadow: 'none',
|
||
productText: 'center'
|
||
}
|
||
};
|
||
|
||
// State
|
||
let currentSettings = {
|
||
mood: 'neutral',
|
||
typography: 'clean',
|
||
shape: 'soft',
|
||
density: 'balanced',
|
||
grid: '4',
|
||
header: 'standard',
|
||
accent: '#f97316'
|
||
};
|
||
|
||
let shopName = 'Botanical Studio';
|
||
let logoMode = 'text-only';
|
||
let logoUrl = null;
|
||
let logoSvgContent = null; // Store original SVG content
|
||
let logoIsSvg = false;
|
||
let headerImageUrl = null;
|
||
let logoSize = 36;
|
||
let headerPositionX = 50; // percentage 0-100
|
||
let headerPositionY = 50; // percentage 0-100
|
||
let headerZoom = 100;
|
||
let recolorLogo = false;
|
||
let logoColor = '#171717';
|
||
|
||
// Feature toggles
|
||
let showAnnouncementBar = true;
|
||
let stickyHeader = false;
|
||
let hoverImage = true;
|
||
let quickAdd = true;
|
||
let aspectRatio = 'square';
|
||
|
||
// DOM elements
|
||
const previewFrame = document.getElementById('preview-frame');
|
||
const shopHeader = document.getElementById('shop-header');
|
||
const productGrid = document.getElementById('product-grid');
|
||
const accentPicker = document.getElementById('accent-picker');
|
||
const colorValue = document.getElementById('color-value');
|
||
const comboValue = document.getElementById('combo-value');
|
||
const shopNameInput = document.getElementById('shop-name');
|
||
|
||
const logoUploadRow = document.getElementById('logo-upload-row');
|
||
const headerUploadRow = document.getElementById('header-upload-row');
|
||
const logoUpload = document.getElementById('logo-upload');
|
||
const headerUpload = document.getElementById('header-upload');
|
||
const logoPreview = document.getElementById('logo-preview');
|
||
const logoPreviewImg = document.getElementById('logo-preview-img');
|
||
const headerPreview = document.getElementById('header-preview');
|
||
const headerPreviewImg = document.getElementById('header-preview-img');
|
||
|
||
const shopLogoImage = document.getElementById('shop-logo-image');
|
||
const shopLogoImg = document.getElementById('shop-logo-img');
|
||
const shopLogoText = document.getElementById('shop-logo-text');
|
||
|
||
const logoSizeControl = document.getElementById('logo-size-control');
|
||
const logoSizeSlider = document.getElementById('logo-size-slider');
|
||
const logoSizeValue = document.getElementById('logo-size-value');
|
||
|
||
const logoColorControl = document.getElementById('logo-color-control');
|
||
const recolorLogoCheckbox = document.getElementById('recolor-logo-checkbox');
|
||
const logoColorPickerRow = document.getElementById('logo-color-picker-row');
|
||
const logoColorPicker = document.getElementById('logo-color-picker');
|
||
const logoColorValue = document.getElementById('logo-color-value');
|
||
|
||
const headerImageControls = document.getElementById('header-image-controls');
|
||
const headerPositionXRow = document.getElementById('header-position-x-row');
|
||
const headerPositionXSlider = document.getElementById('header-position-x-slider');
|
||
const headerPositionXValue = document.getElementById('header-position-x-value');
|
||
const headerPositionSlider = document.getElementById('header-position-slider');
|
||
const headerPositionValue = document.getElementById('header-position-value');
|
||
const headerZoomSlider = document.getElementById('header-zoom-slider');
|
||
const headerZoomValue = document.getElementById('header-zoom-value');
|
||
|
||
// Recolor SVG by replacing fill and stroke colors
|
||
function recolorSvg(svgContent, newColor) {
|
||
if (!svgContent) return svgContent;
|
||
|
||
// Replace fill attributes (but not fill="none")
|
||
let recolored = svgContent.replace(/fill="(?!none)[^"]*"/gi, `fill="${newColor}"`);
|
||
|
||
// Replace stroke attributes (but not stroke="none")
|
||
recolored = recolored.replace(/stroke="(?!none)[^"]*"/gi, `stroke="${newColor}"`);
|
||
|
||
// Also handle style attributes with fill/stroke
|
||
recolored = recolored.replace(/fill:\s*(?!none)[^;}"']+/gi, `fill: ${newColor}`);
|
||
recolored = recolored.replace(/stroke:\s*(?!none)[^;}"']+/gi, `stroke: ${newColor}`);
|
||
|
||
return recolored;
|
||
}
|
||
|
||
// Update the logo image in the preview
|
||
function updateLogoImage() {
|
||
if (logoIsSvg && logoSvgContent) {
|
||
let svgToUse = logoSvgContent;
|
||
if (recolorLogo) {
|
||
svgToUse = recolorSvg(logoSvgContent, logoColor);
|
||
}
|
||
logoUrl = 'data:image/svg+xml,' + encodeURIComponent(svgToUse);
|
||
|
||
// Also update the preview thumbnail
|
||
logoPreviewImg.src = logoUrl;
|
||
}
|
||
}
|
||
|
||
// Helper: Convert hex to HSL
|
||
function hexToHSL(hex) {
|
||
let r = parseInt(hex.slice(1, 3), 16) / 255;
|
||
let g = parseInt(hex.slice(3, 5), 16) / 255;
|
||
let b = parseInt(hex.slice(5, 7), 16) / 255;
|
||
|
||
let max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||
let h, s, l = (max + min) / 2;
|
||
|
||
if (max === min) {
|
||
h = s = 0;
|
||
} else {
|
||
let d = max - min;
|
||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||
switch (max) {
|
||
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
|
||
case g: h = ((b - r) / d + 2) / 6; break;
|
||
case b: h = ((r - g) / d + 4) / 6; break;
|
||
}
|
||
}
|
||
|
||
return {
|
||
h: Math.round(h * 360),
|
||
s: Math.round(s * 100),
|
||
l: Math.round(l * 100)
|
||
};
|
||
}
|
||
|
||
// Update logo/header mode display
|
||
function updateLogoDisplay() {
|
||
// Update upload row visibility
|
||
const needsLogo = logoMode === 'logo-and-text' || logoMode === 'logo-only' || logoMode === 'logo-header-image';
|
||
const needsHeader = logoMode === 'header-image' || logoMode === 'logo-header-image';
|
||
|
||
logoUploadRow.classList.toggle('visible', needsLogo);
|
||
headerUploadRow.classList.toggle('visible', needsHeader);
|
||
|
||
// Show size control only when logo is uploaded and mode uses a logo
|
||
const hasLogo = logoUrl || (logoIsSvg && logoSvgContent);
|
||
const showSizeControl = needsLogo && hasLogo;
|
||
logoSizeControl.classList.toggle('visible', showSizeControl);
|
||
|
||
// Show color control only for SVG logos
|
||
const showColorControl = needsLogo && logoIsSvg && logoSvgContent;
|
||
logoColorControl.classList.toggle('visible', showColorControl);
|
||
|
||
// Show header image controls when header image is uploaded
|
||
const showHeaderControls = needsHeader && headerImageUrl;
|
||
headerImageControls.classList.toggle('visible', showHeaderControls);
|
||
|
||
// Only show horizontal position when zoomed in
|
||
if (showHeaderControls) {
|
||
headerPositionXRow.classList.toggle('visible', headerZoom > 100);
|
||
}
|
||
|
||
// Update logo upload label based on mode
|
||
const logoUploadLabel = document.getElementById('logo-upload-label');
|
||
if (logoMode === 'logo-header-image') {
|
||
logoUploadLabel.textContent = 'Upload logo (use white/light version)';
|
||
} else {
|
||
logoUploadLabel.textContent = 'Upload logo (SVG or PNG)';
|
||
}
|
||
|
||
// Update preview header
|
||
shopHeader.dataset.logoMode = logoMode;
|
||
|
||
// Apply logo size
|
||
shopLogoImage.style.height = logoSize + 'px';
|
||
|
||
// Update logo visibility and header background
|
||
if (logoMode === 'text-only') {
|
||
shopLogoImage.classList.remove('visible');
|
||
shopLogoText.style.display = 'block';
|
||
shopHeader.style.backgroundImage = '';
|
||
shopHeader.style.backgroundPosition = '';
|
||
shopHeader.style.backgroundSize = '';
|
||
} else if (logoMode === 'logo-and-text') {
|
||
if (logoUrl) {
|
||
shopLogoImage.classList.add('visible');
|
||
shopLogoImg.src = logoUrl;
|
||
} else {
|
||
shopLogoImage.classList.remove('visible');
|
||
}
|
||
shopLogoText.style.display = 'block';
|
||
shopHeader.style.backgroundImage = '';
|
||
shopHeader.style.backgroundPosition = '';
|
||
shopHeader.style.backgroundSize = '';
|
||
} else if (logoMode === 'logo-only') {
|
||
if (logoUrl) {
|
||
shopLogoImage.classList.add('visible');
|
||
shopLogoImg.src = logoUrl;
|
||
} else {
|
||
shopLogoImage.classList.remove('visible');
|
||
}
|
||
shopLogoText.style.display = 'none';
|
||
shopHeader.style.backgroundImage = '';
|
||
shopHeader.style.backgroundPosition = '';
|
||
shopHeader.style.backgroundSize = '';
|
||
} else if (logoMode === 'header-image') {
|
||
shopLogoImage.classList.remove('visible');
|
||
shopLogoText.style.display = 'block';
|
||
if (headerImageUrl) {
|
||
shopHeader.style.backgroundImage = `url(${headerImageUrl})`;
|
||
shopHeader.style.backgroundPosition = `${headerPositionX}% ${headerPositionY}%`;
|
||
shopHeader.style.backgroundSize = `${headerZoom}% auto`;
|
||
} else {
|
||
// Default placeholder gradient
|
||
shopHeader.style.backgroundImage = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
|
||
shopHeader.style.backgroundPosition = 'center center';
|
||
shopHeader.style.backgroundSize = 'cover';
|
||
}
|
||
} else if (logoMode === 'logo-header-image') {
|
||
if (logoUrl) {
|
||
shopLogoImage.classList.add('visible');
|
||
shopLogoImg.src = logoUrl;
|
||
} else {
|
||
shopLogoImage.classList.remove('visible');
|
||
}
|
||
shopLogoText.style.display = 'none';
|
||
if (headerImageUrl) {
|
||
shopHeader.style.backgroundImage = `url(${headerImageUrl})`;
|
||
shopHeader.style.backgroundPosition = `${headerPositionX}% ${headerPositionY}%`;
|
||
shopHeader.style.backgroundSize = `${headerZoom}% auto`;
|
||
} else {
|
||
// Default placeholder gradient
|
||
shopHeader.style.backgroundImage = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
|
||
shopHeader.style.backgroundPosition = 'center center';
|
||
shopHeader.style.backgroundSize = 'cover';
|
||
}
|
||
}
|
||
}
|
||
|
||
// Apply settings to preview
|
||
function applySettings() {
|
||
// Apply data attributes
|
||
previewFrame.dataset.mood = currentSettings.mood;
|
||
previewFrame.dataset.typography = currentSettings.typography;
|
||
previewFrame.dataset.shape = currentSettings.shape;
|
||
previewFrame.dataset.density = currentSettings.density;
|
||
|
||
shopHeader.dataset.header = currentSettings.header;
|
||
productGrid.dataset.grid = currentSettings.grid;
|
||
|
||
// Apply Impulse-specific settings if present
|
||
if (currentSettings.fontSize) {
|
||
previewFrame.dataset.fontSize = currentSettings.fontSize;
|
||
document.querySelectorAll('#font-size-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.fontSize === currentSettings.fontSize);
|
||
});
|
||
}
|
||
if (currentSettings.headingWeight) {
|
||
previewFrame.dataset.headingWeight = currentSettings.headingWeight;
|
||
document.querySelectorAll('#heading-weight-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.headingWeight === currentSettings.headingWeight);
|
||
});
|
||
}
|
||
if (currentSettings.layoutWidth) {
|
||
previewFrame.dataset.layoutWidth = currentSettings.layoutWidth;
|
||
document.querySelectorAll('#layout-width-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.layoutWidth === currentSettings.layoutWidth);
|
||
});
|
||
}
|
||
if (currentSettings.buttonStyle) {
|
||
previewFrame.dataset.buttonStyle = currentSettings.buttonStyle;
|
||
document.querySelectorAll('#button-style-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.buttonStyle === currentSettings.buttonStyle);
|
||
});
|
||
}
|
||
if (currentSettings.cardShadow) {
|
||
previewFrame.dataset.cardShadow = currentSettings.cardShadow;
|
||
document.querySelectorAll('#card-shadow-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.cardShadow === currentSettings.cardShadow);
|
||
});
|
||
}
|
||
if (currentSettings.productText) {
|
||
previewFrame.dataset.productText = currentSettings.productText;
|
||
document.querySelectorAll('#product-text-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.productText === currentSettings.productText);
|
||
});
|
||
}
|
||
|
||
// Apply accent color
|
||
const hsl = hexToHSL(currentSettings.accent);
|
||
previewFrame.style.setProperty('--t-accent-h', hsl.h);
|
||
previewFrame.style.setProperty('--t-accent-s', hsl.s + '%');
|
||
previewFrame.style.setProperty('--t-accent-l', hsl.l + '%');
|
||
|
||
// Update color picker and display
|
||
accentPicker.value = currentSettings.accent;
|
||
colorValue.textContent = currentSettings.accent;
|
||
|
||
// Update shop name in preview
|
||
shopLogoText.textContent = shopName;
|
||
const footerTexts = ['footer-text', 'footer-text-collection', 'footer-text-pdp', 'footer-text-cart', 'footer-text-about', 'footer-text-contact', 'footer-text-error'];
|
||
footerTexts.forEach(id => {
|
||
const el = document.getElementById(id);
|
||
if (el) el.textContent = `© 2025 ${shopName}`;
|
||
});
|
||
|
||
// Update browser tab
|
||
document.getElementById('favicon-letter').textContent = shopName.charAt(0).toUpperCase();
|
||
document.getElementById('browser-domain').textContent = shopName.toLowerCase().replace(/\s+/g, '');
|
||
|
||
// Update logo display
|
||
updateLogoDisplay();
|
||
|
||
// Update combo display
|
||
const labels = {
|
||
mood: { warm: 'Warm', neutral: 'Neutral', cool: 'Cool', dark: 'Dark' },
|
||
typography: { clean: 'Clean', editorial: 'Editorial', modern: 'Modern', classic: 'Classic', friendly: 'Friendly', minimal: 'Minimal', impulse: 'Impulse' },
|
||
shape: { sharp: 'Sharp', soft: 'Soft', round: 'Round', pill: 'Pill' },
|
||
density: { spacious: 'Spacious', balanced: 'Balanced', compact: 'Compact' },
|
||
header: { standard: 'Standard', centered: 'Centered', minimal: 'Minimal' }
|
||
};
|
||
|
||
comboValue.textContent = [
|
||
labels.mood[currentSettings.mood],
|
||
labels.typography[currentSettings.typography],
|
||
labels.shape[currentSettings.shape],
|
||
labels.density[currentSettings.density],
|
||
currentSettings.grid + '-up',
|
||
labels.header[currentSettings.header]
|
||
].join(' · ');
|
||
|
||
updateActiveStates();
|
||
}
|
||
|
||
// Update active states on buttons
|
||
function updateActiveStates() {
|
||
document.querySelectorAll('#mood-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.mood === currentSettings.mood);
|
||
});
|
||
document.querySelectorAll('#typography-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.typography === currentSettings.typography);
|
||
});
|
||
document.querySelectorAll('#shape-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.shape === currentSettings.shape);
|
||
});
|
||
document.querySelectorAll('#density-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.density === currentSettings.density);
|
||
});
|
||
document.querySelectorAll('#grid-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.grid === currentSettings.grid);
|
||
});
|
||
document.querySelectorAll('#header-options .option-button').forEach(btn => {
|
||
btn.classList.toggle('active', btn.dataset.header === currentSettings.header);
|
||
});
|
||
}
|
||
|
||
// Preset buttons
|
||
document.querySelectorAll('.preset-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const presetName = btn.dataset.preset;
|
||
const preset = presets[presetName];
|
||
|
||
currentSettings = { ...preset };
|
||
|
||
document.querySelectorAll('.preset-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
|
||
applySettings();
|
||
});
|
||
});
|
||
|
||
// Individual option buttons
|
||
function setupOptionGroup(groupId, settingKey) {
|
||
document.querySelectorAll(`#${groupId} .option-button`).forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
currentSettings[settingKey] = btn.dataset[settingKey];
|
||
document.querySelectorAll('.preset-button').forEach(b => b.classList.remove('active'));
|
||
applySettings();
|
||
});
|
||
});
|
||
}
|
||
|
||
setupOptionGroup('mood-options', 'mood');
|
||
setupOptionGroup('typography-options', 'typography');
|
||
setupOptionGroup('shape-options', 'shape');
|
||
setupOptionGroup('density-options', 'density');
|
||
setupOptionGroup('grid-options', 'grid');
|
||
setupOptionGroup('header-options', 'header');
|
||
|
||
// Accent color picker
|
||
accentPicker.addEventListener('input', (e) => {
|
||
currentSettings.accent = e.target.value;
|
||
document.querySelectorAll('.preset-button').forEach(b => b.classList.remove('active'));
|
||
applySettings();
|
||
});
|
||
|
||
// Secondary accent (hover) color picker
|
||
const secondaryAccentPicker = document.getElementById('secondary-accent-picker');
|
||
const secondaryColorValue = document.getElementById('secondary-color-value');
|
||
secondaryAccentPicker.addEventListener('input', (e) => {
|
||
previewFrame.style.setProperty('--t-secondary-accent', e.target.value);
|
||
secondaryColorValue.textContent = e.target.value;
|
||
});
|
||
|
||
// Sale color picker
|
||
const saleColorPicker = document.getElementById('sale-color-picker');
|
||
const saleColorValue = document.getElementById('sale-color-value');
|
||
saleColorPicker.addEventListener('input', (e) => {
|
||
previewFrame.style.setProperty('--t-sale-color', e.target.value);
|
||
saleColorValue.textContent = e.target.value;
|
||
});
|
||
|
||
// Font size options
|
||
document.querySelectorAll('#font-size-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('#font-size-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
previewFrame.dataset.fontSize = btn.dataset.fontSize;
|
||
});
|
||
});
|
||
|
||
// Heading weight options
|
||
document.querySelectorAll('#heading-weight-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('#heading-weight-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
previewFrame.dataset.headingWeight = btn.dataset.headingWeight;
|
||
});
|
||
});
|
||
|
||
// Layout width options
|
||
document.querySelectorAll('#layout-width-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('#layout-width-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
previewFrame.dataset.layoutWidth = btn.dataset.layoutWidth;
|
||
});
|
||
});
|
||
|
||
// Button style options
|
||
document.querySelectorAll('#button-style-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('#button-style-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
previewFrame.dataset.buttonStyle = btn.dataset.buttonStyle;
|
||
});
|
||
});
|
||
|
||
// Card shadow options
|
||
document.querySelectorAll('#card-shadow-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('#card-shadow-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
previewFrame.dataset.cardShadow = btn.dataset.cardShadow;
|
||
});
|
||
});
|
||
|
||
// Product text alignment options
|
||
document.querySelectorAll('#product-text-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('#product-text-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
previewFrame.dataset.productText = btn.dataset.productText;
|
||
});
|
||
});
|
||
|
||
// Gallery position options
|
||
document.querySelectorAll('#gallery-position-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('#gallery-position-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
previewFrame.dataset.galleryPosition = btn.dataset.galleryPosition;
|
||
});
|
||
});
|
||
|
||
// Show prices toggle
|
||
document.getElementById('show-prices-toggle').addEventListener('change', (e) => {
|
||
previewFrame.dataset.showPrices = e.target.checked;
|
||
});
|
||
|
||
// PDP toggles
|
||
document.getElementById('pdp-trust-toggle').addEventListener('change', (e) => {
|
||
previewFrame.dataset.pdpTrust = e.target.checked;
|
||
});
|
||
|
||
document.getElementById('pdp-reviews-toggle').addEventListener('change', (e) => {
|
||
previewFrame.dataset.pdpReviews = e.target.checked;
|
||
});
|
||
|
||
document.getElementById('pdp-related-toggle').addEventListener('change', (e) => {
|
||
previewFrame.dataset.pdpRelated = e.target.checked;
|
||
});
|
||
|
||
// Shop name input
|
||
shopNameInput.addEventListener('input', (e) => {
|
||
shopName = e.target.value || 'My Shop';
|
||
applySettings();
|
||
});
|
||
|
||
// Logo mode options
|
||
document.querySelectorAll('.logo-mode-option').forEach(option => {
|
||
option.addEventListener('click', () => {
|
||
const mode = option.dataset.mode;
|
||
logoMode = mode;
|
||
|
||
document.querySelectorAll('.logo-mode-option').forEach(opt => {
|
||
opt.classList.toggle('active', opt.dataset.mode === mode);
|
||
});
|
||
|
||
updateLogoDisplay();
|
||
});
|
||
});
|
||
|
||
// Logo upload
|
||
logoUpload.addEventListener('change', (e) => {
|
||
const file = e.target.files[0];
|
||
if (!file) return;
|
||
|
||
const browserFavicon = document.getElementById('browser-favicon');
|
||
|
||
logoIsSvg = file.type === 'image/svg+xml' || file.name.toLowerCase().endsWith('.svg');
|
||
|
||
if (logoIsSvg) {
|
||
// Read SVG as text so we can manipulate it
|
||
const textReader = new FileReader();
|
||
textReader.onload = (event) => {
|
||
logoSvgContent = event.target.result;
|
||
updateLogoImage();
|
||
logoPreviewImg.src = 'data:image/svg+xml,' + encodeURIComponent(logoSvgContent);
|
||
logoPreview.classList.add('has-image');
|
||
updateLogoDisplay();
|
||
|
||
// Update favicon with logo
|
||
browserFavicon.classList.add('has-logo');
|
||
let faviconImg = browserFavicon.querySelector('.favicon-logo');
|
||
if (!faviconImg) {
|
||
faviconImg = document.createElement('img');
|
||
faviconImg.className = 'favicon-logo';
|
||
browserFavicon.appendChild(faviconImg);
|
||
}
|
||
faviconImg.src = 'data:image/svg+xml,' + encodeURIComponent(logoSvgContent);
|
||
};
|
||
textReader.readAsText(file);
|
||
} else {
|
||
// Read as data URL for non-SVG images
|
||
logoSvgContent = null;
|
||
const reader = new FileReader();
|
||
reader.onload = (event) => {
|
||
logoUrl = event.target.result;
|
||
logoPreviewImg.src = logoUrl;
|
||
logoPreview.classList.add('has-image');
|
||
updateLogoDisplay();
|
||
|
||
// Update favicon with logo
|
||
browserFavicon.classList.add('has-logo');
|
||
let faviconImg = browserFavicon.querySelector('.favicon-logo');
|
||
if (!faviconImg) {
|
||
faviconImg = document.createElement('img');
|
||
faviconImg.className = 'favicon-logo';
|
||
browserFavicon.appendChild(faviconImg);
|
||
}
|
||
faviconImg.src = logoUrl;
|
||
};
|
||
reader.readAsDataURL(file);
|
||
}
|
||
});
|
||
|
||
// Header upload
|
||
headerUpload.addEventListener('change', (e) => {
|
||
const file = e.target.files[0];
|
||
if (!file) return;
|
||
|
||
const reader = new FileReader();
|
||
reader.onload = (event) => {
|
||
headerImageUrl = event.target.result;
|
||
headerPreviewImg.src = headerImageUrl;
|
||
headerPreview.classList.add('has-image');
|
||
updateLogoDisplay();
|
||
};
|
||
reader.readAsDataURL(file);
|
||
});
|
||
|
||
// Remove logo
|
||
document.getElementById('remove-logo').addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
logoUrl = null;
|
||
logoSvgContent = null;
|
||
logoIsSvg = false;
|
||
recolorLogo = false;
|
||
recolorLogoCheckbox.checked = false;
|
||
logoColorPickerRow.classList.remove('visible');
|
||
logoPreview.classList.remove('has-image');
|
||
logoUpload.value = '';
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Remove header
|
||
document.getElementById('remove-header').addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
headerImageUrl = null;
|
||
headerPreview.classList.remove('has-image');
|
||
headerUpload.value = '';
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Logo size slider
|
||
logoSizeSlider.addEventListener('input', (e) => {
|
||
logoSize = parseInt(e.target.value);
|
||
logoSizeValue.textContent = logoSize + 'px';
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Recolor logo toggle
|
||
recolorLogoCheckbox.addEventListener('change', (e) => {
|
||
recolorLogo = e.target.checked;
|
||
logoColorPickerRow.classList.toggle('visible', recolorLogo);
|
||
updateLogoImage();
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Logo color picker
|
||
logoColorPicker.addEventListener('input', (e) => {
|
||
logoColor = e.target.value;
|
||
logoColorValue.textContent = logoColor;
|
||
updateLogoImage();
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Header horizontal position slider
|
||
headerPositionXSlider.addEventListener('input', (e) => {
|
||
headerPositionX = parseInt(e.target.value);
|
||
headerPositionXValue.textContent = headerPositionX + '%';
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Header vertical position slider
|
||
headerPositionSlider.addEventListener('input', (e) => {
|
||
headerPositionY = parseInt(e.target.value);
|
||
headerPositionValue.textContent = headerPositionY + '%';
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Header zoom slider
|
||
headerZoomSlider.addEventListener('input', (e) => {
|
||
headerZoom = parseInt(e.target.value);
|
||
headerZoomValue.textContent = headerZoom + '%';
|
||
|
||
// Only show horizontal position when zoomed in
|
||
headerPositionXRow.classList.toggle('visible', headerZoom > 100);
|
||
|
||
updateLogoDisplay();
|
||
});
|
||
|
||
// Initialize with Gallery preset
|
||
document.querySelector('[data-preset="gallery"]').click();
|
||
|
||
// Page view toggle
|
||
document.querySelectorAll('.page-toggle-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const page = btn.dataset.page;
|
||
|
||
document.querySelectorAll('.page-toggle-btn').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
|
||
document.querySelectorAll('.page-view').forEach(view => view.classList.remove('active'));
|
||
document.getElementById(page + '-view').classList.add('active');
|
||
});
|
||
});
|
||
|
||
// Feature toggles
|
||
document.getElementById('announcement-bar-toggle').addEventListener('change', (e) => {
|
||
showAnnouncementBar = e.target.checked;
|
||
document.getElementById('announcement-bar').classList.toggle('hidden', !showAnnouncementBar);
|
||
});
|
||
|
||
document.getElementById('sticky-header-toggle').addEventListener('change', (e) => {
|
||
stickyHeader = e.target.checked;
|
||
previewFrame.dataset.stickyHeader = stickyHeader;
|
||
});
|
||
|
||
document.getElementById('hover-image-toggle').addEventListener('change', (e) => {
|
||
hoverImage = e.target.checked;
|
||
previewFrame.dataset.hoverImage = hoverImage;
|
||
});
|
||
|
||
document.getElementById('quick-add-toggle').addEventListener('change', (e) => {
|
||
quickAdd = e.target.checked;
|
||
previewFrame.dataset.quickAdd = quickAdd;
|
||
});
|
||
|
||
// Initialize feature data attributes
|
||
previewFrame.dataset.hoverImage = hoverImage;
|
||
previewFrame.dataset.quickAdd = quickAdd;
|
||
previewFrame.dataset.aspect = aspectRatio;
|
||
previewFrame.dataset.fontSize = 'medium';
|
||
previewFrame.dataset.headingWeight = 'bold';
|
||
previewFrame.dataset.layoutWidth = 'wide';
|
||
previewFrame.dataset.buttonStyle = 'filled';
|
||
previewFrame.dataset.cardShadow = 'none';
|
||
previewFrame.dataset.productText = 'left';
|
||
previewFrame.dataset.galleryPosition = 'left';
|
||
previewFrame.dataset.showPrices = 'true';
|
||
previewFrame.dataset.pdpTrust = 'true';
|
||
previewFrame.dataset.pdpReviews = 'true';
|
||
previewFrame.dataset.pdpRelated = 'true';
|
||
|
||
// Aspect ratio options
|
||
document.querySelectorAll('#aspect-options .option-button').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
aspectRatio = btn.dataset.aspect;
|
||
previewFrame.dataset.aspect = aspectRatio;
|
||
document.querySelectorAll('#aspect-options .option-button').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
});
|
||
});
|
||
|
||
// Customise section toggle
|
||
const customiseSection = document.getElementById('customise-section');
|
||
const customiseHeader = document.getElementById('customise-header');
|
||
customiseHeader.addEventListener('click', () => {
|
||
customiseSection.classList.toggle('open');
|
||
});
|
||
|
||
// Cart drawer
|
||
const cartDrawer = document.getElementById('cart-drawer');
|
||
const cartDrawerOverlay = document.getElementById('cart-drawer-overlay');
|
||
const cartBtn = document.getElementById('cart-btn');
|
||
const cartDrawerClose = document.getElementById('cart-drawer-close');
|
||
const viewCartLink = document.getElementById('view-cart-link');
|
||
|
||
function openCartDrawer() {
|
||
cartDrawer.classList.add('open');
|
||
cartDrawerOverlay.classList.add('open');
|
||
}
|
||
|
||
function closeCartDrawer() {
|
||
cartDrawer.classList.remove('open');
|
||
cartDrawerOverlay.classList.remove('open');
|
||
}
|
||
|
||
cartBtn.addEventListener('click', openCartDrawer);
|
||
cartDrawerClose.addEventListener('click', closeCartDrawer);
|
||
cartDrawerOverlay.addEventListener('click', closeCartDrawer);
|
||
|
||
viewCartLink.addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
closeCartDrawer();
|
||
document.querySelector('[data-page="cart"]').click();
|
||
});
|
||
|
||
// Quick add buttons open cart drawer
|
||
document.querySelectorAll('.quick-add-btn').forEach(btn => {
|
||
btn.addEventListener('click', (e) => {
|
||
e.stopPropagation();
|
||
openCartDrawer();
|
||
});
|
||
});
|
||
|
||
// Search modal
|
||
const searchModal = document.getElementById('search-modal');
|
||
const searchBtn = document.getElementById('search-btn');
|
||
const searchClose = document.getElementById('search-close');
|
||
|
||
searchBtn.addEventListener('click', () => {
|
||
searchModal.classList.add('open');
|
||
searchModal.querySelector('.search-input').focus();
|
||
});
|
||
|
||
searchClose.addEventListener('click', () => {
|
||
searchModal.classList.remove('open');
|
||
});
|
||
|
||
searchModal.addEventListener('click', (e) => {
|
||
if (e.target === searchModal) {
|
||
searchModal.classList.remove('open');
|
||
}
|
||
});
|
||
|
||
// Escape key closes modals (dialog handles its own escape)
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Escape') {
|
||
closeCartDrawer();
|
||
searchModal.classList.remove('open');
|
||
}
|
||
});
|
||
|
||
// PDP thumbnail gallery
|
||
const pdpMainImage = document.getElementById('pdp-main-image');
|
||
document.querySelectorAll('.pdp-thumb').forEach(thumb => {
|
||
thumb.addEventListener('click', () => {
|
||
// Update main image
|
||
const imageUrl = thumb.dataset.image;
|
||
pdpMainImage.style.backgroundImage = `url('${imageUrl}')`;
|
||
|
||
// Update active state
|
||
document.querySelectorAll('.pdp-thumb').forEach(t => t.classList.remove('active'));
|
||
thumb.classList.add('active');
|
||
});
|
||
});
|
||
|
||
// Lightbox - using native dialog
|
||
const lightbox = document.getElementById('lightbox');
|
||
const lightboxImage = document.getElementById('lightbox-image');
|
||
const lightboxCaption = document.getElementById('lightbox-caption');
|
||
const lightboxCounter = document.getElementById('lightbox-counter');
|
||
const lightboxClose = document.getElementById('lightbox-close');
|
||
const lightboxPrev = document.getElementById('lightbox-prev');
|
||
const lightboxNext = document.getElementById('lightbox-next');
|
||
const zoomBtn = document.getElementById('zoom-btn');
|
||
|
||
// Get all product images with metadata from thumbnails
|
||
function getLightboxImages() {
|
||
return Array.from(document.querySelectorAll('.pdp-thumb')).map(thumb => ({
|
||
src: thumb.dataset.image,
|
||
alt: thumb.dataset.alt || 'Product image',
|
||
description: thumb.dataset.description || ''
|
||
}));
|
||
}
|
||
|
||
let currentLightboxIndex = 0;
|
||
|
||
function openLightbox(startIndex = 0) {
|
||
const images = getLightboxImages();
|
||
currentLightboxIndex = startIndex;
|
||
updateLightboxImage(images);
|
||
lightbox.showModal();
|
||
}
|
||
|
||
function closeLightbox() {
|
||
lightbox.close();
|
||
zoomBtn.focus();
|
||
}
|
||
|
||
function updateLightboxImage(images) {
|
||
const current = images[currentLightboxIndex];
|
||
lightboxImage.src = current.src;
|
||
lightboxImage.alt = current.alt;
|
||
lightboxCaption.textContent = current.description;
|
||
lightboxCounter.textContent = `${currentLightboxIndex + 1} / ${images.length}`;
|
||
}
|
||
|
||
function nextImage() {
|
||
const images = getLightboxImages();
|
||
currentLightboxIndex = (currentLightboxIndex + 1) % images.length;
|
||
updateLightboxImage(images);
|
||
}
|
||
|
||
function prevImage() {
|
||
const images = getLightboxImages();
|
||
currentLightboxIndex = (currentLightboxIndex - 1 + images.length) % images.length;
|
||
updateLightboxImage(images);
|
||
}
|
||
|
||
// Open lightbox from zoom button or clicking main image
|
||
zoomBtn.addEventListener('click', (e) => {
|
||
e.stopPropagation();
|
||
const activeThumb = document.querySelector('.pdp-thumb.active');
|
||
const thumbs = Array.from(document.querySelectorAll('.pdp-thumb'));
|
||
const startIndex = thumbs.indexOf(activeThumb);
|
||
openLightbox(startIndex >= 0 ? startIndex : 0);
|
||
});
|
||
|
||
pdpMainImage.addEventListener('click', () => {
|
||
const activeThumb = document.querySelector('.pdp-thumb.active');
|
||
const thumbs = Array.from(document.querySelectorAll('.pdp-thumb'));
|
||
const startIndex = thumbs.indexOf(activeThumb);
|
||
openLightbox(startIndex >= 0 ? startIndex : 0);
|
||
});
|
||
|
||
lightboxClose.addEventListener('click', closeLightbox);
|
||
lightboxNext.addEventListener('click', nextImage);
|
||
lightboxPrev.addEventListener('click', prevImage);
|
||
|
||
// Close on clicking backdrop (native dialog handles escape key)
|
||
lightbox.addEventListener('click', (e) => {
|
||
if (e.target === lightbox) {
|
||
closeLightbox();
|
||
}
|
||
});
|
||
|
||
// Arrow key navigation
|
||
lightbox.addEventListener('keydown', (e) => {
|
||
if (e.key === 'ArrowRight') {
|
||
nextImage();
|
||
} else if (e.key === 'ArrowLeft') {
|
||
prevImage();
|
||
}
|
||
});
|
||
|
||
// Internal navigation links
|
||
function navigateToPage(pageId) {
|
||
document.querySelectorAll('.page-toggle-btn').forEach(b => b.classList.remove('active'));
|
||
document.querySelector(`[data-page="${pageId}"]`).classList.add('active');
|
||
|
||
document.querySelectorAll('.page-view').forEach(view => view.classList.remove('active'));
|
||
document.getElementById(pageId + '-view').classList.add('active');
|
||
}
|
||
|
||
document.querySelectorAll('[data-nav]').forEach(link => {
|
||
link.addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
navigateToPage(link.dataset.nav);
|
||
});
|
||
});
|
||
|
||
// Product cards link to PDP
|
||
document.querySelectorAll('.product-card').forEach(card => {
|
||
card.addEventListener('click', (e) => {
|
||
// Don't navigate if clicking quick-add button
|
||
if (e.target.closest('.quick-add-btn')) return;
|
||
navigateToPage('pdp');
|
||
});
|
||
});
|
||
|
||
// PDP Add to basket button opens cart drawer
|
||
document.querySelector('.pdp-add-btn').addEventListener('click', openCartDrawer);
|
||
|
||
// Cart state toggle (full/empty)
|
||
const cartStateToggle = document.getElementById('cart-state-toggle');
|
||
const cartFull = document.getElementById('cart-full');
|
||
const cartEmpty = document.getElementById('cart-empty');
|
||
let isCartEmpty = false;
|
||
|
||
cartStateToggle.addEventListener('click', () => {
|
||
isCartEmpty = !isCartEmpty;
|
||
cartFull.hidden = isCartEmpty;
|
||
cartEmpty.hidden = !isCartEmpty;
|
||
cartStateToggle.textContent = isCartEmpty ? 'Preview full cart' : 'Preview empty state';
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |