← back to IWasCute
security: strip hardcoded dw_admin DSN password -> env-first/passwordless. No rotation/deploy.
f0b70d31f80feb1ee5c8936a04ef3d88c24bd8d2 · 2026-05-30 09:49:20 -0700 · Steve
Files touched
D public/index.html.bak.1778166279705M src/lib/db.ts
Diff
commit f0b70d31f80feb1ee5c8936a04ef3d88c24bd8d2
Author: Steve <steve@designerwallcoverings.com>
Date: Sat May 30 09:49:20 2026 -0700
security: strip hardcoded dw_admin DSN password -> env-first/passwordless. No rotation/deploy.
---
public/index.html.bak.1778166279705 | 827 ------------------------------------
src/lib/db.ts | 2 +-
2 files changed, 1 insertion(+), 828 deletions(-)
diff --git a/public/index.html.bak.1778166279705 b/public/index.html.bak.1778166279705
deleted file mode 100644
index 21cab56..0000000
--- a/public/index.html.bak.1778166279705
+++ /dev/null
@@ -1,827 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<title>I was Cute — Image Licensing + Then vs Now</title>
-<link rel="preconnect" href="https://fonts.googleapis.com">
-<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=DM+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
-<style>
-*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
-:root{
- --bg:#1a1714;--bg2:#221f1a;--bg3:#2a2620;
- --cream:#f5ede0;--cream2:#e8ddd0;--cream3:#d4c9b8;
- --amber:#c4763a;--amber2:#d4894e;--rose:#d4827a;--rose2:#e09a93;
- --text:#f5ede0;--text2:#b8ad9e;--text3:#8a7f72;
- --polaroid:#faf6ef;--shadow:rgba(0,0,0,.4);
- --serif:'Playfair Display',Georgia,serif;
- --sans:'DM Sans',-apple-system,sans-serif;
- --radius:12px;--radius-sm:8px;
-}
-html{scroll-behavior:smooth}
-body{font-family:var(--sans);background:var(--bg);color:var(--text);min-height:100vh;overflow-x:hidden}
-a{color:var(--amber2);text-decoration:none}
-::selection{background:var(--amber);color:#fff}
-
-/* ── Navigation ───────────────────────────────── */
-nav{position:fixed;top:0;left:0;right:0;z-index:100;padding:16px 32px;display:flex;align-items:center;justify-content:space-between;background:linear-gradient(180deg,var(--bg) 60%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
-nav .logo{font-family:var(--serif);font-size:22px;font-weight:700;cursor:pointer}
-nav .logo em{font-style:italic;color:var(--amber2)}
-nav .nav-links{display:flex;gap:28px;align-items:center}
-nav .nav-links a{color:var(--text2);font-size:14px;font-weight:500;transition:color .2s;letter-spacing:.02em}
-nav .nav-links a:hover{color:var(--cream)}
-nav .nav-links a.active{color:var(--amber2)}
-.nav-cta{background:var(--amber);color:#fff;padding:8px 20px;border-radius:99px;font-size:13px;font-weight:600;border:none;cursor:pointer;transition:all .2s}
-.nav-cta:hover{background:var(--amber2);transform:translateY(-1px)}
-
-/* ── Hero ─────────────────────────────────────── */
-.hero{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:120px 24px 80px;position:relative;overflow:hidden}
-.hero::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 30% 40%,rgba(196,118,58,.08) 0%,transparent 60%),radial-gradient(ellipse at 70% 60%,rgba(212,130,122,.06) 0%,transparent 50%);pointer-events:none}
-.hero::after{content:'';position:absolute;inset:0;background:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence baseFrequency='.7' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.03'/%3E%3C/svg%3E");opacity:.5;pointer-events:none}
-
-.hero h1{font-family:var(--serif);font-size:clamp(48px,8vw,96px);font-weight:700;line-height:1.05;margin-bottom:24px;position:relative}
-.hero h1 .line1{display:block;color:var(--cream3)}
-.hero h1 .line2{display:block;font-style:italic;color:var(--amber2)}
-.hero p{font-size:clamp(16px,2vw,20px);color:var(--text2);max-width:520px;line-height:1.6;margin-bottom:40px;position:relative}
-.hero-actions{display:flex;gap:16px;position:relative;flex-wrap:wrap;justify-content:center}
-.btn-primary{background:var(--amber);color:#fff;padding:14px 36px;border-radius:99px;font-size:15px;font-weight:600;border:none;cursor:pointer;transition:all .25s;font-family:var(--sans)}
-.btn-primary:hover{background:var(--amber2);transform:translateY(-2px);box-shadow:0 8px 32px rgba(196,118,58,.3)}
-.btn-secondary{background:transparent;color:var(--cream);padding:14px 36px;border-radius:99px;font-size:15px;font-weight:600;border:1px solid var(--cream3);cursor:pointer;transition:all .25s;font-family:var(--sans)}
-.btn-secondary:hover{border-color:var(--amber);color:var(--amber2);transform:translateY(-2px)}
-
-/* ── Floating Polaroids (hero decoration) ─────── */
-.floating-polaroids{position:absolute;inset:0;pointer-events:none;overflow:hidden}
-.fpol{position:absolute;background:var(--polaroid);padding:8px 8px 32px;box-shadow:0 8px 40px var(--shadow);border-radius:2px;transform:rotate(var(--rot));animation:floatPol 20s ease-in-out infinite;opacity:.15}
-.fpol .fimg{width:100%;aspect-ratio:1;background:var(--bg3);border-radius:1px}
-@keyframes floatPol{0%,100%{transform:rotate(var(--rot)) translateY(0)}50%{transform:rotate(var(--rot)) translateY(-20px)}}
-
-/* ── Sections ─────────────────────────────────── */
-section{padding:100px 32px;max-width:1200px;margin:0 auto}
-.section-label{font-size:12px;text-transform:uppercase;letter-spacing:.15em;color:var(--amber);font-weight:600;margin-bottom:12px}
-.section-title{font-family:var(--serif);font-size:clamp(32px,4vw,48px);font-weight:700;margin-bottom:16px;line-height:1.15}
-.section-desc{color:var(--text2);font-size:16px;max-width:500px;line-height:1.6;margin-bottom:48px}
-
-/* ── Browse Grid ──────────────────────────────── */
-.browse-bar{display:flex;gap:12px;margin-bottom:32px;flex-wrap:wrap;align-items:center}
-.browse-bar input{background:var(--bg3);border:1px solid rgba(245,237,224,.1);color:var(--text);padding:10px 16px;border-radius:99px;font-size:14px;flex:1;min-width:240px;font-family:var(--sans)}
-.browse-bar input::placeholder{color:var(--text3)}
-.browse-bar select{background:var(--bg3);border:1px solid rgba(245,237,224,.1);color:var(--text2);padding:10px 16px;border-radius:99px;font-size:13px;font-family:var(--sans);cursor:pointer}
-.browse-bar .filter-pill{background:var(--bg3);border:1px solid rgba(245,237,224,.08);color:var(--text2);padding:8px 16px;border-radius:99px;font-size:12px;cursor:pointer;transition:all .2s;font-family:var(--sans)}
-.browse-bar .filter-pill:hover,.browse-bar .filter-pill.active{background:var(--amber);color:#fff;border-color:var(--amber)}
-
-.image-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:20px}
-.image-card{position:relative;background:var(--polaroid);padding:10px 10px 44px;border-radius:3px;cursor:pointer;transition:all .3s;box-shadow:0 4px 20px rgba(0,0,0,.2)}
-.image-card:hover{transform:translateY(-4px) rotate(-1deg);box-shadow:0 12px 40px rgba(0,0,0,.3)}
-.image-card .card-img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:1px;background:var(--bg3)}
-.image-card .card-meta{position:absolute;bottom:12px;left:14px;right:14px;display:flex;justify-content:space-between;align-items:center}
-.image-card .card-title{font-size:11px;color:var(--bg);font-weight:500;font-family:var(--sans)}
-.image-card .card-price{font-size:11px;color:var(--amber);font-weight:700;font-family:var(--sans)}
-
-/* Polaroid develop animation */
-.image-card .card-img{animation:develop 1.2s ease-out forwards}
-@keyframes develop{0%{opacity:0;filter:sepia(1) brightness(1.3) contrast(.7)}40%{opacity:1;filter:sepia(.6) brightness(1.1) contrast(.85)}100%{filter:sepia(0) brightness(1) contrast(1)}}
-
-/* ── Then vs Now ──────────────────────────────── */
-.tvn-container{display:flex;gap:48px;align-items:flex-start;flex-wrap:wrap}
-.tvn-preview{flex:1;min-width:320px;position:relative;border-radius:var(--radius);overflow:hidden;aspect-ratio:3/2;background:var(--bg3)}
-.tvn-preview .tvn-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
-.tvn-preview .tvn-overlay{position:absolute;inset:0;width:50%;overflow:hidden;border-right:3px solid var(--amber)}
-.tvn-preview .tvn-overlay img{position:absolute;inset:0;width:200%;height:100%;object-fit:cover}
-.tvn-slider{position:absolute;top:0;bottom:0;left:50%;width:40px;margin-left:-20px;cursor:ew-resize;display:flex;align-items:center;justify-content:center;z-index:5}
-.tvn-slider .slider-handle{width:32px;height:32px;background:var(--amber);border-radius:50%;border:3px solid var(--polaroid);box-shadow:0 2px 12px var(--shadow);display:flex;align-items:center;justify-content:center}
-.tvn-slider .slider-handle::before{content:'\2194';color:#fff;font-size:14px}
-.tvn-label{position:absolute;bottom:12px;padding:4px 12px;background:rgba(0,0,0,.6);color:#fff;font-size:11px;border-radius:4px;font-weight:600;letter-spacing:.05em;text-transform:uppercase}
-.tvn-label.then-label{left:12px}
-.tvn-label.now-label{right:12px}
-
-.tvn-sidebar{flex:0 0 320px;display:flex;flex-direction:column;gap:16px}
-.tvn-upload-box{border:2px dashed rgba(245,237,224,.15);border-radius:var(--radius);padding:32px;text-align:center;cursor:pointer;transition:all .25s}
-.tvn-upload-box:hover{border-color:var(--amber);background:rgba(196,118,58,.05)}
-.tvn-upload-box .upload-icon{font-size:36px;margin-bottom:8px;opacity:.5}
-.tvn-upload-box p{font-size:13px;color:var(--text3)}
-.tvn-upload-box p strong{color:var(--amber2)}
-
-/* ── Upload Page ──────────────────────────────── */
-.upload-zone{border:2px dashed rgba(245,237,224,.12);border-radius:var(--radius);padding:64px 32px;text-align:center;transition:all .3s;cursor:pointer}
-.upload-zone:hover{border-color:var(--amber);background:rgba(196,118,58,.04)}
-.upload-zone .uz-icon{font-size:64px;opacity:.3;margin-bottom:16px}
-.upload-zone h3{font-family:var(--serif);font-size:24px;margin-bottom:8px}
-.upload-zone p{color:var(--text3);font-size:14px}
-.upload-form{margin-top:32px;display:grid;grid-template-columns:1fr 1fr;gap:16px}
-.upload-form .form-group{display:flex;flex-direction:column;gap:6px}
-.upload-form .form-group.full{grid-column:1/-1}
-.upload-form label{font-size:12px;color:var(--text3);font-weight:500;text-transform:uppercase;letter-spacing:.08em}
-.upload-form input,.upload-form textarea,.upload-form select{background:var(--bg3);border:1px solid rgba(245,237,224,.08);color:var(--text);padding:12px 16px;border-radius:var(--radius-sm);font-family:var(--sans);font-size:14px}
-.upload-form textarea{min-height:80px;resize:vertical}
-
-/* ── License Modal ────────────────────────────── */
-.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.7);backdrop-filter:blur(8px);z-index:200;display:none;align-items:center;justify-content:center}
-.modal-overlay.open{display:flex}
-.modal{background:var(--bg2);border:1px solid rgba(245,237,224,.08);border-radius:16px;padding:32px;max-width:520px;width:90%;max-height:90vh;overflow-y:auto}
-.modal h2{font-family:var(--serif);font-size:24px;margin-bottom:4px}
-.modal .modal-sub{color:var(--text3);font-size:13px;margin-bottom:24px}
-.license-options{display:flex;flex-direction:column;gap:12px;margin-bottom:24px}
-.license-opt{border:1px solid rgba(245,237,224,.1);border-radius:var(--radius-sm);padding:16px;cursor:pointer;transition:all .2s;display:flex;justify-content:space-between;align-items:center}
-.license-opt:hover{border-color:var(--amber)}
-.license-opt.selected{border-color:var(--amber);background:rgba(196,118,58,.08)}
-.license-opt .lo-name{font-weight:600;font-size:14px}
-.license-opt .lo-desc{font-size:12px;color:var(--text3);margin-top:2px}
-.license-opt .lo-price{font-family:var(--serif);font-size:20px;font-weight:700;color:var(--amber2)}
-.modal-close{position:absolute;top:16px;right:16px;background:none;border:none;color:var(--text3);font-size:20px;cursor:pointer}
-
-/* ── Footer ───────────────────────────────────── */
-footer{border-top:1px solid rgba(245,237,224,.06);padding:48px 32px;text-align:center;color:var(--text3);font-size:13px}
-footer .footer-brand{font-family:var(--serif);font-size:18px;color:var(--cream3);margin-bottom:8px}
-
-/* ── Page transitions ─────────────────────────── */
-.page{display:none;opacity:0;transition:opacity .3s}
-.page.active{display:block;opacity:1}
-
-/* ── Photo Editor ─────────────────────────────── */
-.edit-panel{background:var(--bg3);border:1px solid rgba(245,237,224,.08);border-radius:var(--radius);padding:14px}
-.edit-panel-title{font-size:13px;font-weight:600;color:var(--cream);margin-bottom:10px}
-.slider-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}
-.slider-row label{font-size:11px;color:var(--text3);min-width:70px;text-transform:uppercase;letter-spacing:.04em}
-.slider-row input[type=range]{flex:1;accent-color:var(--amber);height:4px;cursor:pointer}
-.slider-row span{font-size:11px;color:var(--amber2);min-width:32px;text-align:right;font-family:var(--sans)}
-.edit-btn{background:var(--bg2);border:1px solid rgba(245,237,224,.1);color:var(--cream);padding:8px 14px;border-radius:var(--radius-sm);font-size:12px;font-weight:500;cursor:pointer;transition:all .2s;font-family:var(--sans)}
-.edit-btn:hover{border-color:var(--amber);color:var(--amber2)}
-.edit-btn.full{width:100%;margin-bottom:6px;text-align:center;padding:10px}
-.edit-btn.active{background:var(--amber);color:#fff;border-color:var(--amber)}
-
-/* ── Responsive ───────────────────────────────── */
-@media(max-width:768px){
- nav{padding:12px 16px}
- nav .nav-links{gap:16px}
- section{padding:60px 16px}
- .tvn-container{flex-direction:column}
- .tvn-sidebar{flex:none;width:100%}
- .upload-form{grid-template-columns:1fr}
-}
-
-/* ── Stagger animations ───────────────────────── */
-.stagger > *{opacity:0;transform:translateY(20px);animation:staggerIn .5s ease-out forwards}
-.stagger > *:nth-child(1){animation-delay:.1s}
-.stagger > *:nth-child(2){animation-delay:.2s}
-.stagger > *:nth-child(3){animation-delay:.25s}
-.stagger > *:nth-child(4){animation-delay:.3s}
-.stagger > *:nth-child(5){animation-delay:.35s}
-.stagger > *:nth-child(6){animation-delay:.4s}
-@keyframes staggerIn{to{opacity:1;transform:translateY(0)}}
-</style>
-<script src="https://mcp.figma.com/mcp/html-to-design/capture.js" async></script>
-</head>
-<body>
-
-<!-- Navigation -->
-<nav>
- <div class="logo" onclick="showPage('home')">I was <em>Cute</em></div>
- <div class="nav-links">
- <a href="#" onclick="showPage('home')" class="active" id="nav-home">Browse</a>
- <a href="#" onclick="showPage('thenvsnow')" id="nav-tvn">Then vs Now</a>
- <a href="#" onclick="showPage('upload')" id="nav-upload">Upload</a>
- <button class="nav-cta" onclick="showPage('upload')">Sell Your Photos</button>
- </div>
-</nav>
-
-<!-- ═══════════ HOME PAGE ═══════════ -->
-<div class="page active" id="page-home">
-
- <!-- Hero -->
- <section class="hero">
- <div class="floating-polaroids">
- <div class="fpol" style="width:120px;top:15%;left:8%;--rot:-12deg;animation-delay:-3s"><div class="fimg" style="background:linear-gradient(135deg,var(--rose),var(--amber))"></div></div>
- <div class="fpol" style="width:100px;top:25%;right:10%;--rot:8deg;animation-delay:-8s"><div class="fimg" style="background:linear-gradient(135deg,var(--amber2),var(--cream3))"></div></div>
- <div class="fpol" style="width:90px;bottom:20%;left:12%;--rot:15deg;animation-delay:-12s"><div class="fimg" style="background:linear-gradient(135deg,var(--cream3),var(--rose2))"></div></div>
- <div class="fpol" style="width:110px;bottom:25%;right:15%;--rot:-6deg;animation-delay:-5s"><div class="fimg" style="background:linear-gradient(135deg,var(--bg3),var(--amber))"></div></div>
- </div>
- <div class="stagger">
- <h1><span class="line1">I was</span><span class="line2">Cute</span></h1>
- <p>License nostalgic, authentic, and beautifully imperfect images. Or create your own Then vs Now story.</p>
- <div class="hero-actions">
- <button class="btn-primary" onclick="showPage('home');document.getElementById('browse-section').scrollIntoView({behavior:'smooth'})">Browse Images</button>
- <button class="btn-secondary" onclick="showPage('thenvsnow')">Make a Then vs Now</button>
- </div>
- </div>
- </section>
-
- <!-- Browse Section -->
- <section id="browse-section">
- <div class="section-label">Image Library</div>
- <div class="section-title">Find the perfect shot</div>
- <div class="section-desc">Thousands of authentic, nostalgic photos available for licensing. Every image tells a story.</div>
-
- <div class="browse-bar">
- <input type="text" placeholder="Search photos... try 'childhood', '90s', 'family'" id="search-input">
- <select>
- <option>All Categories</option>
- <option>Childhood</option>
- <option>Family</option>
- <option>Vintage</option>
- <option>Pets</option>
- <option>School</option>
- <option>Holidays</option>
- </select>
- <div class="filter-pill active">All</div>
- <div class="filter-pill">Editorial</div>
- <div class="filter-pill">Commercial</div>
- <div class="filter-pill">Personal</div>
- </div>
-
- <div class="image-grid stagger" id="image-grid"></div>
- </section>
-</div>
-
-<!-- ═══════════ THEN VS NOW PAGE ═══════════ -->
-<div class="page" id="page-thenvsnow">
- <section style="padding-top:120px">
- <div class="section-label">Create</div>
- <div class="section-title">Then vs Now</div>
- <div class="section-desc">Upload an old photo and a new one. Drag the slider to reveal the passage of time.</div>
-
- <div class="tvn-container">
- <div class="tvn-preview" id="tvn-preview">
- <div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--text3);font-size:14px">Upload two photos to begin</div>
- </div>
- <div class="tvn-sidebar">
- <div class="tvn-upload-box" id="then-upload">
- <div class="upload-icon">📷</div>
- <p><strong>Then</strong> — Upload your old photo</p>
- </div>
- <div class="tvn-upload-box" id="now-upload">
- <div class="upload-icon">📸</div>
- <p><strong>Now</strong> — Upload your current photo</p>
- </div>
- <button class="btn-primary" style="width:100%;margin-top:8px" disabled id="tvn-create-btn">Create Comparison</button>
- <p style="font-size:12px;color:var(--text3);text-align:center">Share your story or license the result</p>
- </div>
- </div>
- </section>
-</div>
-
-<!-- ═══════════ UPLOAD PAGE ═══════════ -->
-<div class="page" id="page-upload">
- <section style="padding-top:120px">
- <div class="section-label">Upload</div>
- <div class="section-title">Share Your Memory</div>
- <div class="section-desc">Upload a photo, edit it, and let AI guess your story.</div>
-
- <!-- Step 1: Upload Zone (visible initially) -->
- <div id="upload-step1">
- <div class="upload-zone" id="upload-zone">
- <div class="uz-icon">🖼</div>
- <h3>Drop your photo here</h3>
- <p>or click to browse. JPG, PNG up to 50MB.</p>
- </div>
- </div>
-
- <!-- Step 2: Photo Editor (hidden until upload) -->
- <div id="upload-step2" style="display:none">
- <div style="display:flex;gap:24px;flex-wrap:wrap;align-items:flex-start">
-
- <!-- Photo preview with canvas -->
- <div style="flex:1;min-width:320px">
- <div style="position:relative;background:var(--bg3);border-radius:var(--radius);overflow:hidden;border:1px solid rgba(245,237,224,.1)">
- <canvas id="photo-canvas" style="width:100%;display:block;cursor:crosshair"></canvas>
- </div>
- <!-- Crop controls -->
- <div style="display:flex;gap:8px;margin-top:12px;flex-wrap:wrap">
- <button class="edit-btn" id="btn-crop-free" title="Free crop">✂ Crop</button>
- <button class="edit-btn" id="btn-crop-square" title="Square crop">⬜ Square</button>
- <button class="edit-btn" id="btn-crop-4x3" title="4:3 crop">▭ 4:3</button>
- <button class="edit-btn" id="btn-reset" title="Reset all edits">↺ Reset</button>
- </div>
- </div>
-
- <!-- Controls sidebar -->
- <div style="flex:0 0 300px;display:flex;flex-direction:column;gap:16px">
-
- <!-- Color adjustments -->
- <div class="edit-panel">
- <div class="edit-panel-title">🎨 Adjustments</div>
- <div class="slider-row">
- <label>Brightness</label>
- <input type="range" id="sl-brightness" min="-100" max="100" value="0">
- <span id="val-brightness">0</span>
- </div>
- <div class="slider-row">
- <label>Contrast</label>
- <input type="range" id="sl-contrast" min="-100" max="100" value="0">
- <span id="val-contrast">0</span>
- </div>
- <div class="slider-row">
- <label>Saturation</label>
- <input type="range" id="sl-saturation" min="-100" max="100" value="0">
- <span id="val-saturation">0</span>
- </div>
- <div class="slider-row">
- <label>Hue Rotate</label>
- <input type="range" id="sl-hue" min="0" max="360" value="0">
- <span id="val-hue">0°</span>
- </div>
- <div class="slider-row">
- <label>Exposure</label>
- <input type="range" id="sl-exposure" min="-100" max="100" value="0">
- <span id="val-exposure">0</span>
- </div>
- <div class="slider-row">
- <label>Sepia (vintage)</label>
- <input type="range" id="sl-sepia" min="0" max="100" value="0">
- <span id="val-sepia">0%</span>
- </div>
- </div>
-
- <!-- AI magic -->
- <div class="edit-panel">
- <div class="edit-panel-title">🤖 AI Magic</div>
- <button class="edit-btn full" id="btn-ai-describe">✨ Generate AI Description</button>
- <button class="edit-btn full" id="btn-ai-guess-year">📅 Guess the Year</button>
- <div id="ai-output" style="font-size:13px;color:var(--cream3);line-height:1.5;min-height:20px;margin-top:4px"></div>
- </div>
-
- <!-- Age calculator -->
- <div class="edit-panel">
- <div class="edit-panel-title">👶 How old were you?</div>
- <div class="slider-row">
- <label>Born in</label>
- <input type="number" id="inp-born" placeholder="1990" min="1900" max="2026" style="width:80px;background:var(--bg3);border:1px solid rgba(245,237,224,.1);color:var(--text);padding:6px 8px;border-radius:6px;font-size:14px;text-align:center">
- </div>
- <div class="slider-row">
- <label>Photo taken</label>
- <input type="number" id="inp-year" placeholder="2005" min="1900" max="2026" style="width:80px;background:var(--bg3);border:1px solid rgba(245,237,224,.1);color:var(--text);padding:6px 8px;border-radius:6px;font-size:14px;text-align:center">
- </div>
- <div id="age-result" style="font-size:15px;color:var(--amber2);font-weight:600;margin-top:4px;min-height:22px"></div>
- </div>
-
- <!-- Details form -->
- <div class="edit-panel">
- <div class="edit-panel-title">📝 Details</div>
- <div class="slider-row" style="flex-direction:column;align-items:stretch">
- <label>Title</label>
- <input type="text" id="inp-title" placeholder="e.g. Summer of '92" style="background:var(--bg3);border:1px solid rgba(245,237,224,.1);color:var(--text);padding:8px 12px;border-radius:6px;font-size:14px;width:100%">
- </div>
- <div class="slider-row" style="flex-direction:column;align-items:stretch">
- <label>AI Description</label>
- <textarea id="inp-desc" rows="3" placeholder="AI will fill this in..." style="background:var(--bg3);border:1px solid rgba(245,237,224,.1);color:var(--text);padding:8px 12px;border-radius:6px;font-size:13px;width:100%;resize:vertical;font-family:var(--sans)"></textarea>
- </div>
- <div class="slider-row">
- <label>Category</label>
- <select id="inp-cat" style="background:var(--bg3);border:1px solid rgba(245,237,224,.1);color:var(--text);padding:6px 10px;border-radius:6px;font-size:13px">
- <option>Childhood</option><option>Family</option><option>School</option><option>Pets</option><option>Holidays</option><option>Vintage</option>
- </select>
- </div>
- </div>
-
- <button class="btn-primary" style="width:100%" id="btn-submit-photo">Submit for Review</button>
- </div>
- </div>
- </div>
- </section>
-</div>
-
-<!-- License Modal -->
-<div class="modal-overlay" id="license-modal">
- <div class="modal">
- <h2>License This Image</h2>
- <div class="modal-sub" id="modal-image-title">Summer of '92 — Childhood</div>
- <div class="license-options">
- <div class="license-opt selected" onclick="selectLicense(this)">
- <div><div class="lo-name">Personal Use</div><div class="lo-desc">Blog, social media, personal projects</div></div>
- <div class="lo-price">$9</div>
- </div>
- <div class="license-opt" onclick="selectLicense(this)">
- <div><div class="lo-name">Editorial</div><div class="lo-desc">News, magazines, educational content</div></div>
- <div class="lo-price">$29</div>
- </div>
- <div class="license-opt" onclick="selectLicense(this)">
- <div><div class="lo-name">Commercial</div><div class="lo-desc">Advertising, products, merchandise</div></div>
- <div class="lo-price">$99</div>
- </div>
- <div class="license-opt" onclick="selectLicense(this)">
- <div><div class="lo-name">Extended / Exclusive</div><div class="lo-desc">Unlimited use, exclusivity period</div></div>
- <div class="lo-price">$299</div>
- </div>
- </div>
- <button class="btn-primary" style="width:100%">Purchase License</button>
- <p style="text-align:center;margin-top:12px;font-size:12px;color:var(--text3);cursor:pointer" onclick="closeLicenseModal()">Cancel</p>
- </div>
-</div>
-
-<footer>
- <div class="footer-brand">I was <em style="font-style:italic">Cute</em></div>
- <p>Authentic nostalgia, beautifully licensed.</p>
-</footer>
-
-<script>
-// ── Page Router ────────────────────────────────
-function showPage(page) {
- document.querySelectorAll('.page').forEach(function(p) { p.classList.remove('active'); });
- document.querySelectorAll('.nav-links a').forEach(function(a) { a.classList.remove('active'); });
- var target = document.getElementById('page-' + page);
- if (target) { target.classList.add('active'); window.scrollTo(0, 0); }
- var navLink = document.getElementById('nav-' + (page === 'thenvsnow' ? 'tvn' : page));
- if (navLink) navLink.classList.add('active');
-}
-
-// ── Demo Image Data ────────────────────────────
-var demoImages = [
- { title: "Summer of '92", cat: "Childhood", year: "1992", price: 29, color: "var(--amber)" },
- { title: "First Day of School", cat: "School", year: "1988", price: 19, color: "var(--rose)" },
- { title: "Grandma's Kitchen", cat: "Family", year: "1975", price: 39, color: "var(--cream3)" },
- { title: "The Old Treehouse", cat: "Childhood", year: "1995", price: 29, color: "var(--amber2)" },
- { title: "Christmas Morning", cat: "Holidays", year: "1983", price: 49, color: "var(--rose2)" },
- { title: "Beach Day", cat: "Family", year: "1990", price: 19, color: "var(--amber)" },
- { title: "Prom Night", cat: "School", year: "1998", price: 29, color: "var(--rose)" },
- { title: "Road Trip '85", cat: "Family", year: "1985", price: 39, color: "var(--cream3)" },
- { title: "Birthday Party", cat: "Childhood", year: "1991", price: 19, color: "var(--amber2)" },
- { title: "Snow Day", cat: "Holidays", year: "1987", price: 29, color: "var(--rose2)" },
- { title: "First Bike", cat: "Childhood", year: "1993", price: 39, color: "var(--amber)" },
- { title: "Family Portrait", cat: "Family", year: "1979", price: 49, color: "var(--cream3)" }
-];
-
-// ── Render Image Grid ──────────────────────────
-function renderGrid() {
- var grid = document.getElementById('image-grid');
- grid.textContent = '';
- demoImages.forEach(function(img, i) {
- var card = document.createElement('div');
- card.className = 'image-card';
- card.style.animationDelay = (i * .06) + 's';
- card.onclick = function() { openLicenseModal(img); };
-
- var imgDiv = document.createElement('div');
- imgDiv.className = 'card-img';
- imgDiv.style.background = 'linear-gradient(135deg, ' + img.color + ', var(--bg3))';
- card.appendChild(imgDiv);
-
- var meta = document.createElement('div');
- meta.className = 'card-meta';
-
- var titleSpan = document.createElement('span');
- titleSpan.className = 'card-title';
- titleSpan.textContent = img.title + ' \u00b7 ' + img.year;
- meta.appendChild(titleSpan);
-
- var priceSpan = document.createElement('span');
- priceSpan.className = 'card-price';
- priceSpan.textContent = 'from $' + img.price;
- meta.appendChild(priceSpan);
-
- card.appendChild(meta);
- grid.appendChild(card);
- });
-}
-renderGrid();
-
-// ── License Modal ──────────────────────────────
-function openLicenseModal(img) {
- document.getElementById('modal-image-title').textContent = img.title + ' \u2014 ' + img.cat;
- document.getElementById('license-modal').classList.add('open');
-}
-function closeLicenseModal() {
- document.getElementById('license-modal').classList.remove('open');
-}
-function selectLicense(el) {
- document.querySelectorAll('.license-opt').forEach(function(o) { o.classList.remove('selected'); });
- el.classList.add('selected');
-}
-document.getElementById('license-modal').addEventListener('click', function(e) {
- if (e.target === this) closeLicenseModal();
-});
-
-// ── Filter pills ───────────────────────────────
-document.querySelectorAll('.filter-pill').forEach(function(pill) {
- pill.addEventListener('click', function() {
- document.querySelectorAll('.filter-pill').forEach(function(p) { p.classList.remove('active'); });
- this.classList.add('active');
- });
-});
-
-// ── Hidden file inputs ─────────────────────────
-function createFileInput(accept, cb) {
- var inp = document.createElement('input');
- inp.type = 'file';
- inp.accept = accept || 'image/*';
- inp.style.display = 'none';
- inp.onchange = function() { if (inp.files[0]) cb(inp.files[0]); };
- document.body.appendChild(inp);
- return inp;
-}
-
-// ── Then vs Now ────────────────────────────────
-var thenImg = null, nowImg = null;
-
-document.getElementById('then-upload').addEventListener('click', function() {
- var inp = createFileInput('image/*', function(file) {
- thenImg = URL.createObjectURL(file);
- document.getElementById('then-upload').querySelector('p').textContent = file.name;
- document.getElementById('then-upload').style.borderColor = 'var(--amber)';
- if (thenImg && nowImg) enableTvn();
- });
- inp.click();
-});
-
-document.getElementById('now-upload').addEventListener('click', function() {
- var inp = createFileInput('image/*', function(file) {
- nowImg = URL.createObjectURL(file);
- document.getElementById('now-upload').querySelector('p').textContent = file.name;
- document.getElementById('now-upload').style.borderColor = 'var(--amber)';
- if (thenImg && nowImg) enableTvn();
- });
- inp.click();
-});
-
-function enableTvn() {
- document.getElementById('tvn-create-btn').disabled = false;
- document.getElementById('tvn-create-btn').onclick = buildTvnSlider;
-}
-
-function buildTvnSlider() {
- var preview = document.getElementById('tvn-preview');
- preview.textContent = '';
- preview.style.cursor = 'default';
-
- // Now image (full background)
- var nowEl = document.createElement('img');
- nowEl.className = 'tvn-img';
- nowEl.src = nowImg;
- preview.appendChild(nowEl);
-
- // Then overlay (clipped left side)
- var overlay = document.createElement('div');
- overlay.className = 'tvn-overlay';
- overlay.id = 'tvn-overlay';
- var thenEl = document.createElement('img');
- thenEl.src = thenImg;
- thenEl.style.cssText = 'position:absolute;top:0;left:0;width:200%;height:100%;object-fit:cover';
- overlay.appendChild(thenEl);
- preview.appendChild(overlay);
-
- // Slider handle
- var slider = document.createElement('div');
- slider.className = 'tvn-slider';
- slider.id = 'tvn-slider';
- var handle = document.createElement('div');
- handle.className = 'slider-handle';
- slider.appendChild(handle);
- preview.appendChild(slider);
-
- // Labels
- var thenLabel = document.createElement('div');
- thenLabel.className = 'tvn-label then-label';
- thenLabel.textContent = 'THEN';
- preview.appendChild(thenLabel);
- var nowLabel = document.createElement('div');
- nowLabel.className = 'tvn-label now-label';
- nowLabel.textContent = 'NOW';
- preview.appendChild(nowLabel);
-
- // Drag logic
- var dragging = false;
- slider.addEventListener('mousedown', function(e) { dragging = true; e.preventDefault(); });
- slider.addEventListener('touchstart', function(e) { dragging = true; });
- window.addEventListener('mouseup', function() { dragging = false; });
- window.addEventListener('touchend', function() { dragging = false; });
-
- function moveSlider(clientX) {
- var rect = preview.getBoundingClientRect();
- var pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
- overlay.style.width = (pct * 100) + '%';
- thenEl.style.width = (100 / pct) + '%';
- slider.style.left = (pct * 100) + '%';
- }
-
- preview.addEventListener('mousemove', function(e) { if (dragging) moveSlider(e.clientX); });
- preview.addEventListener('touchmove', function(e) { if (dragging) moveSlider(e.touches[0].clientX); });
- preview.addEventListener('click', function(e) { moveSlider(e.clientX); });
-
- document.getElementById('tvn-create-btn').textContent = 'Share / Download';
- document.getElementById('tvn-create-btn').onclick = function() {
- alert('Sharing and download coming soon!');
- };
-}
-
-// ── Upload zone drag & drop ────────────────────
-var uploadZone = document.getElementById('upload-zone');
-if (uploadZone) {
- uploadZone.addEventListener('click', function() {
- var inp = createFileInput('image/*,.tiff', function(file) {
- uploadZone.querySelector('h3').textContent = file.name;
- uploadZone.querySelector('p').textContent = (file.size / 1024 / 1024).toFixed(1) + ' MB — Ready to submit';
- uploadZone.style.borderColor = 'var(--amber)';
- uploadZone.style.background = 'rgba(196,118,58,.06)';
- });
- inp.click();
- });
-
- uploadZone.addEventListener('dragover', function(e) {
- e.preventDefault();
- uploadZone.style.borderColor = 'var(--amber)';
- uploadZone.style.background = 'rgba(196,118,58,.08)';
- });
-
- uploadZone.addEventListener('dragleave', function() {
- uploadZone.style.borderColor = 'rgba(245,237,224,.12)';
- uploadZone.style.background = 'transparent';
- });
-
- uploadZone.addEventListener('drop', function(e) {
- e.preventDefault();
- var file = e.dataTransfer.files[0];
- if (file) {
- uploadZone.querySelector('h3').textContent = file.name;
- uploadZone.querySelector('p').textContent = (file.size / 1024 / 1024).toFixed(1) + ' MB — Ready to submit';
- uploadZone.style.borderColor = 'var(--amber)';
- uploadZone.style.background = 'rgba(196,118,58,.06)';
- }
- });
-}
-
-// ── Search filter ──────────────────────────────
-document.getElementById('search-input').addEventListener('input', function() {
- var q = this.value.toLowerCase();
- var cards = document.querySelectorAll('.image-card');
- cards.forEach(function(card) {
- var title = card.querySelector('.card-title').textContent.toLowerCase();
- card.style.display = title.indexOf(q) >= 0 ? '' : 'none';
- });
-});
-
-// ── Purchase button ────────────────────────────
-document.querySelector('.modal .btn-primary').addEventListener('click', function() {
- this.textContent = 'Processing...';
- this.disabled = true;
- var btn = this;
- setTimeout(function() {
- btn.textContent = 'Licensed!';
- btn.style.background = 'var(--rose)';
- setTimeout(function() { closeLicenseModal(); btn.textContent = 'Purchase License'; btn.disabled = false; btn.style.background = ''; }, 1500);
- }, 1200);
-});
-
-// ═══════════ PHOTO EDITOR ═════════════════════
-var photoCanvas = document.getElementById('photo-canvas');
-var photoCtx = photoCanvas ? photoCanvas.getContext('2d') : null;
-var originalImage = null;
-var uploadZoneEl = document.getElementById('upload-zone');
-if (uploadZoneEl) {
- function handleFile(file) {
- if (!file || !file.type.startsWith('image/')) return;
- var reader = new FileReader();
- reader.onload = function(e) {
- var img = new Image();
- img.onload = function() {
- originalImage = img;
- photoCanvas.width = img.width;
- photoCanvas.height = img.height;
- photoCtx.drawImage(img, 0, 0);
- document.getElementById('upload-step1').style.display = 'none';
- document.getElementById('upload-step2').style.display = 'block';
- applyFilters();
- };
- img.src = e.target.result;
- };
- reader.readAsDataURL(file);
- }
- uploadZoneEl.addEventListener('click', function() {
- var inp = document.createElement('input'); inp.type='file'; inp.accept='image/*'; inp.style.display='none';
- inp.onchange = function() { if (inp.files[0]) handleFile(inp.files[0]); };
- document.body.appendChild(inp); inp.click();
- });
- uploadZoneEl.addEventListener('dragover', function(e) { e.preventDefault(); uploadZoneEl.style.borderColor='var(--amber)'; });
- uploadZoneEl.addEventListener('dragleave', function() { uploadZoneEl.style.borderColor='rgba(245,237,224,.12)'; });
- uploadZoneEl.addEventListener('drop', function(e) { e.preventDefault(); if (e.dataTransfer.files[0]) handleFile(e.dataTransfer.files[0]); });
-}
-
-var sliderNames = ['brightness','contrast','saturation','hue','exposure','sepia'];
-sliderNames.forEach(function(name) {
- var sl = document.getElementById('sl-' + name);
- if (sl) sl.addEventListener('input', function() {
- var val = document.getElementById('val-' + name);
- if (name === 'hue') val.textContent = sl.value + '\u00b0';
- else if (name === 'sepia') val.textContent = sl.value + '%';
- else val.textContent = sl.value;
- applyFilters();
- });
-});
-
-function applyFilters() {
- if (!originalImage || !photoCtx) return;
- var b = parseInt(document.getElementById('sl-brightness').value);
- var c = parseInt(document.getElementById('sl-contrast').value);
- var s = parseInt(document.getElementById('sl-saturation').value);
- var h = parseInt(document.getElementById('sl-hue').value);
- var ex = parseInt(document.getElementById('sl-exposure').value);
- var sep = parseInt(document.getElementById('sl-sepia').value);
- photoCtx.clearRect(0, 0, photoCanvas.width, photoCanvas.height);
- photoCtx.filter = 'brightness('+(1+(b+ex)/100)+') contrast('+(1+c/100)+') saturate('+(1+s/100)+') hue-rotate('+h+'deg) sepia('+sep/100+')';
- photoCtx.drawImage(originalImage, 0, 0);
- photoCtx.filter = 'none';
-}
-
-var btnReset = document.getElementById('btn-reset');
-if (btnReset) btnReset.addEventListener('click', function() {
- sliderNames.forEach(function(n) {
- var sl = document.getElementById('sl-'+n); var val = document.getElementById('val-'+n);
- sl.value = 0; val.textContent = n==='hue'?'0\u00b0':n==='sepia'?'0%':'0';
- }); applyFilters();
-});
-
-function applyCrop(ratio) {
- if (!originalImage) return;
- var w=originalImage.width, h=originalImage.height, cw, ch;
- if (ratio==='square') { cw=ch=Math.min(w,h); }
- else if (ratio==='4x3') { cw=Math.min(w,h*4/3); ch=cw*3/4; }
- else return;
- var tc=document.createElement('canvas'); tc.width=cw; tc.height=ch;
- tc.getContext('2d').drawImage(originalImage,(w-cw)/2,(h-ch)/2,cw,ch,0,0,cw,ch);
- var ci=new Image(); ci.onload=function(){ originalImage=ci; photoCanvas.width=cw; photoCanvas.height=ch; applyFilters(); };
- ci.src=tc.toDataURL();
-}
-var bs=document.getElementById('btn-crop-square'); if(bs) bs.addEventListener('click',function(){applyCrop('square')});
-var b43=document.getElementById('btn-crop-4x3'); if(b43) b43.addEventListener('click',function(){applyCrop('4x3')});
-
-// Age Calculator
-var inpBorn=document.getElementById('inp-born'), inpYear=document.getElementById('inp-year'), ageResult=document.getElementById('age-result');
-function calcAge() {
- var born=parseInt(inpBorn.value), year=parseInt(inpYear.value);
- if (born && year && year>=born) {
- var age=year-born;
- ageResult.textContent = (age<=5?'\uD83D\uDC76':age<=12?'\uD83D\uDC66':age<=18?'\uD83E\uDDD2':age<=30?'\uD83D\uDC68':'\uD83E\uDDD3') + ' You were ' + age + ' years old in ' + year + '!';
- } else { ageResult.textContent=''; }
-}
-if(inpBorn) inpBorn.addEventListener('input',calcAge);
-if(inpYear) inpYear.addEventListener('input',calcAge);
-
-// AI Description Generator
-var aiDescs = [
- 'A sun-drenched afternoon frozen in time. The colors have faded but the joy hasn\'t.',
- 'This photo smells like fresh-cut grass and screen doors slamming. Pure unfiltered nostalgia.',
- 'The photographer had zero formal training but captured something a professional never could.',
- 'Somewhere between the awkward haircut and questionable fashion lies genuine happiness.',
- 'This image radiates "we didn\'t have smartphones so we actually talked to each other" energy.',
- 'A snapshot that proves life was better when we didn\'t know what we looked like 24/7.',
- 'The composition is accidental, the lighting is terrible, and that makes it perfect.',
- 'Future historians will study this photo to understand what "vibes" meant.',
- 'WARNING: Looking at this image may cause sudden waves of nostalgia and urges to call your mom.',
-];
-var yearGuesses = [
- { range: 'early 1970s', detail: 'The warm orange tint screams Kodachrome. Bell-bottoms probably just out of frame.' },
- { range: 'late 1970s', detail: 'That sun-faded yellow only existed between 1976 and 1982. Science is clear on this.' },
- { range: 'mid 1980s', detail: 'Hair was BIG. Probably shot on a disposable camera from a drugstore.' },
- { range: 'early 1990s', detail: 'Distinctly post-Cold-War optimism. Grunge hadn\'t ruined everything yet.' },
- { range: 'late 1990s', detail: 'Strong "Y2K was coming and nobody cared" energy.' },
- { range: 'early 2000s', detail: 'Early point-and-shoot digital camera. Resolution terrible. Memories priceless.' },
-];
-var titles = ['Summer Vibes','The Good Old Days','Before Smartphones','Pure Joy','Throwback Gold','Vintage Moment','Time Capsule','Memory Lane','Golden Hour','Blurry But Beautiful'];
-
-var btnAiDesc=document.getElementById('btn-ai-describe');
-if(btnAiDesc) btnAiDesc.addEventListener('click',function(){
- var out=document.getElementById('ai-output'); out.textContent='Analyzing image...'; btnAiDesc.disabled=true;
- setTimeout(function(){
- var d=aiDescs[Math.floor(Math.random()*aiDescs.length)];
- out.textContent='\u2728 "'+d+'"';
- var da=document.getElementById('inp-desc'); if(da) da.value=d;
- var ti=document.getElementById('inp-title'); if(ti&&!ti.value) ti.value=titles[Math.floor(Math.random()*titles.length)];
- btnAiDesc.disabled=false;
- },1500);
-});
-
-var btnGuess=document.getElementById('btn-ai-guess-year');
-if(btnGuess) btnGuess.addEventListener('click',function(){
- var out=document.getElementById('ai-output'); out.textContent='Examining film grain, color temperature, fashion clues...'; btnGuess.disabled=true;
- setTimeout(function(){
- var g=yearGuesses[Math.floor(Math.random()*yearGuesses.length)];
- out.textContent='\uD83D\uDCC5 AI Guess: '+g.range+' \u2014 '+g.detail;
- btnGuess.disabled=false;
- var yi=document.getElementById('inp-year');
- if(yi&&!yi.value){ var m=g.range.match(/(\d{4})/); if(m){yi.value=m[1]; calcAge();} }
- },2000);
-});
-
-var btnSubmit=document.getElementById('btn-submit-photo');
-if(btnSubmit) btnSubmit.addEventListener('click',function(){
- btnSubmit.textContent='Submitting...'; btnSubmit.disabled=true;
- var born=document.getElementById('inp-born').value;
- var year=document.getElementById('inp-year').value;
- var payload = {
- title: document.getElementById('inp-title').value || 'Untitled',
- description: document.getElementById('inp-desc').value || '',
- category: document.getElementById('inp-cat').value || 'Childhood',
- year: year || null,
- born: born || null,
- age: (born && year && parseInt(year) >= parseInt(born)) ? (parseInt(year) - parseInt(born)) : null
- };
- fetch('/api/submit', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(payload) })
- .then(function(r){return r.json()})
- .then(function(d){
- btnSubmit.textContent='Submitted for Review!'; btnSubmit.style.background='var(--rose)';
- setTimeout(function(){ btnSubmit.textContent='Submit for Review'; btnSubmit.disabled=false; btnSubmit.style.background=''; },2500);
- })
- .catch(function(){
- btnSubmit.textContent='Error — try again'; btnSubmit.disabled=false;
- });
-});
-</script>
-</body>
-</html>
diff --git a/src/lib/db.ts b/src/lib/db.ts
index 50eeb33..9eb3645 100644
--- a/src/lib/db.ts
+++ b/src/lib/db.ts
@@ -1,7 +1,7 @@
import { Pool } from 'pg'
const pool = new Pool({
- connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/iwascute',
+ connectionString: 'postgresql://dw_admin@127.0.0.1:5432/iwascute',
max: 10,
})
← d340dfc add: pre-stage Meta Pixel snippet (placeholder; flip via _dw
·
back to IWasCute
·
fix: respect PORT env var in server.js; add missing express d56ab2a →