/* =========================================================================== VESTIRÉ STUDIO — root shell, routing, state & Tweaks (Supabase-backed) =========================================================================== */ const { useState, useEffect, useRef, useMemo } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "visualStyle": "atelier", "accent": ["#6f8a63", "#4f6a47", "#e0e8d8"], "requestsLayout": "cards", "statusUI": "stepper" }/*EDITMODE-END*/; /* ---- layout / component CSS --------------------------------------------- */ const VS_LAYOUT_CSS = ` .gown-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(238px,1fr)); gap:24px;} .proc-grid{display:grid; grid-template-columns:repeat(4,1fr); gap:18px;} .stat-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:18px;} .form-grid{display:grid; grid-template-columns:1fr 1fr; gap:14px;} /* prevent flex/grid children from overflowing and text overlapping neighbours */ .field,.form-grid > *,.cart-grid > *,.detail-grid > *,.dash-grid > *,.split-grid > *,.col,.grow{min-width:0;} .input,.select,.textarea{min-width:0; max-width:100%;} .gcard h3,.disp{overflow-wrap:anywhere;} .row.between > *{min-width:0;} /* gown card */ .gcard{cursor:pointer; transition:transform .3s var(--ease);} .gcard:hover{transform:translateY(-5px);} .gcard-media{position:relative; border-radius:var(--r-lg); overflow:hidden; aspect-ratio:4/5; background:var(--surface-2); box-shadow:var(--shadow-sm);} .gcard-media img{width:100%; height:100%; object-fit:cover; transition:transform .55s var(--ease);} .gcard:hover .gcard-media img{transform:scale(1.05);} .gcard-tags{position:absolute; top:12px; left:12px; display:flex; gap:6px; flex-wrap:wrap;} .gcard-quick{position:absolute; left:12px; right:12px; bottom:12px; opacity:0; transform:translateY(8px); transition:.3s var(--ease);} .gcard:hover .gcard-quick{opacity:1; transform:none;} /* qty / icon buttons */ .qbtn{width:26px; height:26px; border-radius:50%; border:none; background:transparent; color:var(--ink); display:flex; align-items:center; justify-content:center; cursor:pointer; transition:.15s;} .qbtn:hover{background:var(--accent-soft);} .iconbtn{width:34px; height:34px; border-radius:50%; border:1px solid var(--line); background:var(--surface); color:var(--ink-2); display:flex; align-items:center; justify-content:center; cursor:pointer; transition:.18s;} .iconbtn:hover{border-color:var(--ink); color:var(--ink); background:var(--surface-2);} .iconbtn--danger:hover{border-color:var(--cancelled); color:var(--cancelled); background:var(--cancelled-bg);} /* customer nav */ .cnav{position:sticky; top:0; z-index:500; background:color-mix(in srgb, var(--paper) 82%, transparent); backdrop-filter:blur(16px); border-bottom:1px solid var(--line);} .cnav-inner{display:flex; align-items:center; justify-content:space-between; gap:20px; padding:14px 28px; max-width:1240px; margin:0 auto;} .cnav-links{display:flex; gap:6px; align-items:center;} .cnav-link{font-size:13px; font-weight:600; letter-spacing:.03em; padding:9px 14px; border-radius:50px; color:var(--ink-2); cursor:pointer; transition:.18s; position:relative;} .cnav-link:hover{color:var(--ink); background:var(--surface-2);} .cnav-link--on{color:var(--ink); background:var(--surface);} .cnav-icon{position:relative; width:40px; height:40px; border-radius:50%; display:flex; align-items:center; justify-content:center; cursor:pointer; color:var(--ink); transition:.18s;} .cnav-icon:hover{background:var(--surface-2);} .cbadge{position:absolute; top:2px; right:2px; min-width:17px; height:17px; padding:0 4px; border-radius:50px; background:var(--accent); color:var(--accent-ink); font-size:10px; font-weight:700; display:flex; align-items:center; justify-content:center;} .menu-btn{display:none;} .dropdown{position:absolute; right:0; top:48px; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-md); box-shadow:var(--shadow-lg); min-width:190px; overflow:hidden; z-index:600; animation:vsPop .18s var(--ease) both;} .dropdown a{display:flex; align-items:center; gap:10px; padding:11px 16px; font-size:13.5px; font-weight:500; cursor:pointer; transition:.15s;} .dropdown a:hover{background:var(--surface-2); color:var(--accent-2);} .dropdown .sep{height:1px; background:var(--line);} /* footer */ .cfoot{background:var(--ink); color:var(--paper); margin-top:40px;} .cfoot a{color:color-mix(in srgb,var(--paper) 72%, transparent); font-size:13.5px; cursor:pointer; transition:.15s;} .cfoot a:hover{color:var(--accent);} .foot-grid{display:grid; grid-template-columns:1.6fr 1fr 1fr 1.4fr; gap:36px; padding:56px 28px 30px; max-width:1240px; margin:0 auto;} /* admin shell */ .ashell{display:grid; grid-template-columns:248px 1fr; min-height:100vh;} .asidebar{position:sticky; top:0; height:100vh; background:var(--surface); border-right:1px solid var(--line); display:flex; flex-direction:column; padding:22px 16px; gap:6px;} .anav{display:flex; align-items:center; gap:12px; padding:11px 14px; border-radius:var(--r-sm); font-size:13.5px; font-weight:600; color:var(--ink-2); cursor:pointer; transition:.16s;} .anav:hover{background:var(--surface-2); color:var(--ink);} .anav--on{background:var(--ink); color:var(--paper);} .anav--on svg{color:var(--accent);} .amain{padding:30px 36px 60px; max-width:1280px; overflow-x:hidden;} .atopbar{display:none;} @media(max-width:980px){ .proc-grid{grid-template-columns:repeat(2,1fr);} .hero-grid,.detail-grid,.cart-grid,.dash-grid,.split-grid,.req-card-grid{grid-template-columns:1fr !important;} .foot-grid{grid-template-columns:1fr 1fr;} .ashell{grid-template-columns:1fr;} .asidebar{position:fixed; left:0; top:0; bottom:0; width:240px; transform:translateX(-100%); transition:transform .3s var(--ease); z-index:700; box-shadow:var(--shadow-lg);} .asidebar--open{transform:none;} .atopbar{display:flex; align-items:center; justify-content:space-between; padding:14px 20px; border-bottom:1px solid var(--line); position:sticky; top:0; background:var(--paper); z-index:300;} .amain{padding:22px 20px 60px;} } @media(max-width:720px){ .cnav-links{display:none;} .menu-btn{display:flex;} .gown-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:14px;} .form-grid{grid-template-columns:1fr;} .foot-grid{grid-template-columns:1fr; gap:26px;} .container{padding:0 18px;} .cnav-inner{padding:12px 18px;} } @media(max-width:440px){ .gown-grid{grid-template-columns:1fr 1fr;} } /* boot loader */ .vs-loader{min-height:100vh; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:18px; color:var(--muted);} .vs-spin{width:30px; height:30px; border-radius:50%; border:3px solid var(--line); border-top-color:var(--accent); animation:vsSpin .8s linear infinite;} @keyframes vsSpin{to{transform:rotate(360deg);}} /* logout transition overlay */ .vs-logout{position:fixed; inset:0; z-index:9999; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:20px; background:color-mix(in srgb, var(--paper) 86%, transparent); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px); animation:vsLogoutIn .3s var(--ease) both;} .vs-logout-mark{width:64px; height:64px; border-radius:50%; object-fit:cover; box-shadow:var(--shadow-md);} .vs-logout-ring{width:30px; height:30px; border-radius:50%; border:3px solid var(--line); border-top-color:var(--accent); animation:vsSpin .8s linear infinite;} .vs-logout-txt{font-family:var(--font-display); font-size:20px; letter-spacing:.04em; color:var(--accent-2);} @keyframes vsLogoutIn{from{opacity:0;} to{opacity:1;}} `; /* ---- CUSTOMER SHELL (top nav — guests & Home) ---------------------------- */ function CustomerShell({ ctx, children }) { const [menu, setMenu] = useState(false); const [prof, setProf] = useState(false); const cartN = ctx.cart.reduce((a, b) => a + b.qty, 0); const links = [["home", "Home"], ["browse", "Collection"], ["requests", "My Requests"], ["contact", "Contact"]]; const active = ctx.route.name; const me = ctx.currentUser; const adminOnly = !me && ctx.isAdmin; return (