← back to Whatsmystyle

public/index.html

666 lines

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>WhatsMyStyle — Better A or B?</title>
<meta name="description" content="The optometrist for your closet. Show me two outfits, I'll tell you what's you.">
<link rel="stylesheet" href="/css/app.css">
    <link rel="icon" type="image/svg+xml" href="/favicon.svg">
  </head>
<body>
<a href="#main" class="skip-link">Skip to main content</a>
<div id="role-banner" class="role-banner" hidden></div>
<!-- Active production selector — set-decorator only. Every closet upload + try-on
     inherits this id. Live across page sessions (localStorage). -->
<div id="active-prod-bar" class="active-prod-bar" data-role-only="set_decorator" hidden>
  <label for="active-prod-select">Active production</label>
  <select id="active-prod-select" name="production_id">
    <option value="">— untagged —</option>
  </select>
  <a href="#" data-screen="productions" class="active-prod-edit">manage →</a>
</div>
<header class="topbar" role="banner">
  <button class="logo" aria-label="Home — WhatsMyStyle" onclick="route('home')">WhatsMyStyle<span class="bullet" aria-hidden="true">·</span><em>placeholder</em></button>
  <button class="hamburger" aria-label="Open menu" aria-expanded="false" aria-controls="menu" onclick="toggleMenu()">
    <span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
  </button>
</header>

<nav id="menu" class="menu" aria-label="Main menu" hidden>
  <a href="#" data-screen="home">Duel</a>
  <a href="#" data-screen="closet">My Closet</a>
  <a href="#" data-screen="stylepiece">Style this Piece</a>
  <a href="#" data-screen="recs">For You</a>
  <a href="#" data-screen="avatar">My Avatar</a>
  <a href="#" data-screen="live">Live as Puppet</a>
  <a href="#" data-screen="timetravel">Time-Travel Wardrobe</a>
  <a href="#" data-screen="tt-demo">Time-Travel Demo</a>
  <a href="#" data-screen="taste">My Taste</a>
  <a href="#" data-screen="studio">Studio</a>
  <a href="#" data-screen="tryons">My Try-Ons</a>
  <a href="#" data-screen="favorites">My Favorites</a>
  <a href="/brands">Brands</a>
  <a href="#" data-screen="productions" data-role-only="set_decorator">My Productions</a>
  <a href="#" data-screen="couple" data-role-only="couples_pilot">Couple</a>
  <a href="/admin-config" data-role-only="admin">Admin Config</a>
  <a href="#" data-screen="stores">Stores Near Me</a>
  <a href="#" data-screen="connect">Connections</a>
  <a href="#" data-screen="about">About</a>
  <a href="#" data-screen="privacy">Privacy</a>
  <a href="#" data-screen="onboard">Re-onboard</a>
</nav>

<main id="main" role="main">

  <!-- Onboarding (one question, large pills) -->
  <section id="onboard" class="screen" hidden>
    <div class="progress"><div class="bar" id="onb-bar"></div></div>
    <div id="onb-q"></div>
    <div class="pills" id="onb-pills"></div>
    <div class="onb-foot">
      <button class="ghost" onclick="onbBack()">← Back</button>
      <button class="ghost" onclick="onbSkip()">Skip</button>
    </div>
  </section>

  <!-- Duel (the optometrist loop) -->
  <section id="home" class="screen" aria-labelledby="duel-q" hidden>
    <!-- Hero strip — sustainability tier-5 highlights, gucci-anatomy rule -->
    <div id="duel-hero" class="duel-hero" hidden aria-hidden="true"></div>
    <h1 class="duel-question" id="duel-q">Loading your duel…</h1>
    <div class="duel" role="group" aria-label="Style duel — pick A or B">
      <button class="card" data-pick="A" onclick="pickDuel('A')" aria-label="Pick option A (left arrow or A key)">
        <img id="img-a" alt="" loading="lazy">
        <div class="meta">
          <div class="title" id="t-a"></div>
          <div class="brand" id="b-a"></div>
          <div class="price" id="p-a"></div>
        </div>
        <div class="pick-tag" aria-hidden="true">A</div>
      </button>
      <div class="vs" aria-hidden="true">vs</div>
      <button class="card" data-pick="B" onclick="pickDuel('B')" aria-label="Pick option B (right arrow or B key)">
        <img id="img-b" alt="" loading="lazy">
        <div class="meta">
          <div class="title" id="t-b"></div>
          <div class="brand" id="b-b"></div>
          <div class="price" id="p-b"></div>
        </div>
        <div class="pick-tag" aria-hidden="true">B</div>
      </button>
    </div>
    <div class="duel-actions">
      <button class="ghost wide" onclick="pickDuel('skip')" aria-label="Skip — show me something else (space)">Neither — show me something else</button>
    </div>
    <div id="duel-kb-hint" class="kb-hint" hidden aria-hidden="true">
      <kbd>A</kbd> left · <kbd>B</kbd> right · <kbd>Space</kbd> skip
    </div>
    <p class="muted" aria-live="polite" id="duel-live"></p>
    <div class="taste-meter">
      <span>Taste lens sharpening:</span>
      <div class="meter"><div class="meter-fill" id="taste-fill"></div></div>
      <span id="taste-pct">0%</span>
    </div>
  </section>

  <!-- Closet -->
  <section id="closet" class="screen" hidden>
    <h2>My Closet</h2>
    <p class="muted" id="closet-empty-state">Upload a photo of your closet — we'll catalogue each piece automatically.</p>
    <form id="closet-form">
      <input type="file" name="photo" accept="image/*" capture="environment" multiple>
      <select name="production_id" id="closet-prod-select" data-role-only="set_decorator" hidden>
        <option value="">— untagged —</option>
      </select>
      <button type="submit" id="closet-upload-btn">Upload</button>
      <span id="closet-upload-status" class="muted" role="status" aria-live="polite" aria-atomic="true"></span>
    </form>
    <div id="closet-grid" class="grid"></div>
  </section>

  <!-- Recommendations -->
  <section id="recs" class="screen" hidden>
    <div class="recs-controls">
      <h2>For You</h2>
      <div class="grid-controls">
        <label>Sort
          <select id="sort">
            <option value="taste">Best Match</option>
            <option value="sustain">Sustainability ↓</option>
            <option value="newest">Newest</option>
            <option value="price_asc">Price ↑</option>
            <option value="price_desc">Price ↓</option>
            <option value="brand">Brand A–Z</option>
            <option value="title">Title A–Z</option>
          </select>
        </label>
        <label>Density
          <input id="density" type="range" min="120" max="320" value="220">
        </label>
        <label class="set-grade-toggle" data-role-only="set_decorator" hidden>
          <input type="checkbox" id="set-grade-only" />
          <span>Set-grade only</span>
        </label>
      </div>
      <!-- Tick 23: color + material facet pills. Tap to toggle. Persisted to localStorage. -->
      <div id="facets-row" class="facets-row" hidden></div>
      <!-- Tick 31: brand filter pill (set by /brands → ?brand= deep link). -->
      <div id="brand-filter-row" class="facets-row" hidden></div>
      <!-- Tick 31: share-this-list — set-decorator + admin only. -->
      <div id="recs-share-row" data-role-only="set_decorator" hidden style="margin-top: 10px;">
        <button type="button" class="ghost" id="recs-share-btn">Share this list →</button>
        <span id="recs-share-out" class="muted" style="margin-left: 10px;"></span>
      </div>
    </div>
    <div id="recs-empty" class="recs-empty" hidden role="status">
      <p class="muted" id="recs-empty-msg">No matches with your current filters.</p>
      <button type="button" class="ghost" id="recs-empty-clear">Clear filters</button>
    </div>
    <!-- Tick 32: inline embedded/catalog status pill — admin only -->
    <div id="recs-embed-status" class="embed-status-pill" data-role-only="admin" hidden aria-live="polite">
      <span id="recs-embed-text">…</span>
      <div class="embed-status-bar"><div class="embed-status-fill" id="recs-embed-fill"></div></div>
    </div>

    <!-- Tailor the view — set-decorator only (tick 16). Sliders re-rank
         the grid to match the show's visual language. Persisted to localStorage. -->
    <section class="tailor-panel" data-role-only="set_decorator" hidden>
      <header class="tailor-header">
        <h3>Tailor the view</h3>
        <p class="muted">Sliders set the visual language so what you see matches the show you're decorating.</p>
      </header>
      <div class="tailor-grid">
        <label class="tailor-slider">
          <span class="tailor-label">Era</span>
          <input id="tailor-era" type="range" min="1900" max="2030" step="1" value="1975" />
          <output id="tailor-era-val">1975</output>
        </label>
        <label class="tailor-slider">
          <span class="tailor-label">Palette</span>
          <input id="tailor-palette" type="range" min="0" max="100" step="1" value="93" />
          <output id="tailor-palette-val">93</output>
        </label>
        <label class="tailor-slider">
          <span class="tailor-label">Density</span>
          <input id="tailor-density" type="range" min="180" max="400" step="1" value="277" />
          <output id="tailor-density-val">277</output>
        </label>
        <label class="tailor-slider">
          <span class="tailor-label">Tone</span>
          <input id="tailor-tone" type="range" min="0" max="100" step="1" value="73" />
          <output id="tailor-tone-val">73</output>
        </label>
        <button type="button" class="tailor-reset" id="tailor-reset" title="Reset to defaults">Reset</button>
      </div>
    </section>

    <div id="recs-grid" class="grid"></div>
  </section>

  <!-- Stores -->
  <section id="stores" class="screen" hidden>
    <h2>Stores Near Me</h2>
    <p class="muted">Turn on location to see real stores carrying brands you've liked.</p>
    <button onclick="requestLocation()">Enable location</button>
    <div id="stores-list"></div>
  </section>

  <!-- Avatar -->
  <section id="avatar" class="screen" hidden>
    <h2>My Avatar</h2>
    <p class="muted">Upload 3–5 photos of yourself (full body works best). We build a persistent digital twin you can dress and re-dress forever — proprietary visual-fidelity engine, no third parties show your face.</p>

    <!-- Drag-drop zone — fires hidden file input on click, accepts drag-drop from desktop -->
    <div id="avatar-dropzone" class="dropzone" tabindex="0" role="button" aria-label="Drop photos here or click to browse">
      <div class="dz-icon" aria-hidden="true">⬆</div>
      <div class="dz-headline">Drop photos here or click to browse</div>
      <div class="dz-sub muted">JPG / PNG / HEIC · 3 to 5 photos · full-body works best</div>
      <input id="avatar-file-input" type="file" accept="image/*" multiple hidden>
    </div>

    <div class="avatar-actions">
      <button type="button" id="avatar-gdrive-btn" class="ghost" hidden>📂 Pick from Google Drive</button>
      <span id="avatar-counter" class="counter-pill counter-empty">0 / 5 photos · drop or pick to add</span>
    </div>

    <div id="avatar-thumbs" class="thumb-row" aria-live="polite"></div>

    <div class="avatar-actions">
      <button type="button" id="avatar-upload-btn" class="pill" disabled>Upload staged photos →</button>
      <button type="button" id="avatar-build-btn" class="ghost">Build my avatar</button>
    </div>

    <div id="avatar-status" class="muted"></div>
    <div id="avatar-preview"></div>
  </section>

  <!-- Style This Piece (outfit-builder) -->
  <section id="stylepiece" class="screen" hidden>
    <h2>Style this piece</h2>
    <p class="muted">Pick something from your closet. We'll build three complete looks around it.</p>
    <div id="sp-anchor"></div>
    <div id="sp-closet" class="grid"></div>
    <div id="sp-outfits"></div>
  </section>

  <!-- About / Pitch -->
  <section id="about" class="screen" hidden>
    <div class="pitch-hero">
      <h1>Better A — or B?</h1>
      <p class="pitch-sub">An honest stylist that learns from a thousand tiny choices, not a single survey. Then dresses you on you — in past photos, today's mirror, tomorrow's plans.</p>
    </div>
    <div class="pitch-feats">
      <article>
        <h3>The optometrist for your closet</h3>
        <p>We don't ask what you like. We show you two outfits and you tap one. After ~30 taps we know your taste. After 100, we can predict any new piece before you've seen it.</p>
      </article>
      <article>
        <h3>Your digital twin, dressed</h3>
        <p>Upload a few photos. We build a private twin that lives in your account. Every piece in the catalog can be rendered on it — you see how it'll actually look on you, not on a model.</p>
      </article>
      <article>
        <h3>Time-Travel Wardrobe</h3>
        <p>"I wish I'd worn the navy gown to my sister's wedding." Pick the dress from your closet, drop the photo, tap the occasion. The wedding party stays. The venue stays. Only your outfit changes.</p>
      </article>
    </div>
    <div class="pitch-privacy">
      <h3>Plainly: how we treat your data</h3>
      <p>Bank receipts read-only. Email read-only. Photos stay yours. Your face is never sold, never trained on. One tap deletes everything.</p>
      <a href="#" data-screen="privacy">Full privacy →</a>
    </div>
    <div class="pitch-waitlist">
      <h3>Want in early?</h3>
      <form id="waitlist-form">
        <input type="email" name="email" placeholder="you@example.com" required aria-label="Email for waitlist">
        <button type="submit">Join the waitlist</button>
      </form>
      <p class="muted" id="waitlist-msg"></p>
    </div>
  </section>

  <!-- Studio — photo on left, sectioned wardrobe panel on right, history below -->
  <section id="studio" class="screen" hidden>
    <h2>Studio</h2>
    <p class="muted">Pick a photo of you. Pick a clothing section on the right. Pick a piece. We re-dress you. Every render lands in your wardrobe history below this photo — your own try-on archive.</p>
    <div class="studio-layout">
      <aside class="studio-left">
        <h3>Your photos</h3>
        <div id="studio-photos" class="studio-photo-list"></div>
        <h3 style="margin-top: 22px;">Current source</h3>
        <div id="studio-current" class="studio-current"></div>
      </aside>
      <main class="studio-mid">
        <div class="studio-mid-head">
          <h3>Result</h3>
          <div class="studio-tools">
            <button id="extract-toggle" class="section-btn">✂︎ Pull a piece from this photo</button>
            <select id="extract-category" style="padding:6px 10px;border-radius:8px;">
              <option value="top">Top</option>
              <option value="outerwear">Coat / Jacket</option>
              <option value="bottom">Pants</option>
              <option value="dress">Dress</option>
              <option value="shoes">Shoes</option>
              <option value="bag">Bag</option>
            </select>
            <button id="extract-save" class="section-btn" disabled>Save piece</button>
          </div>
        </div>
        <div id="studio-result" class="studio-result">
          <p class="muted">Pick a photo on the left, then a category on the right.</p>
        </div>
        <p class="muted" id="extract-hint" hidden>Drag to draw a box around the garment you want to pull out.</p>
        <h3 style="margin-top: 22px;">Wardrobe history on this photo</h3>
        <div id="studio-history" class="studio-history-strip"></div>
      </main>
      <aside class="studio-right">
        <h3>Swap by section</h3>
        <div class="studio-sections">
          <button class="section-btn" data-category="top">Top / Shirt</button>
          <button class="section-btn" data-category="outerwear">Coat / Jacket</button>
          <button class="section-btn" data-category="bottom">Pants / Skirt</button>
          <button class="section-btn" data-category="dress">Dress</button>
          <button class="section-btn" data-category="shoes">Shoes</button>
          <button class="section-btn" data-category="bag">Bag</button>
        </div>
        <h3 style="margin-top: 18px;">Pick a piece</h3>
        <div id="studio-picker" class="studio-picker">
          <p class="muted">Choose a category first.</p>
        </div>
      </aside>
    </div>
  </section>

  <!-- Live puppet — Adobe Character Animator pass-through -->
  <section id="live" class="screen" hidden>
    <h2>Live as your animated self</h2>
    <p class="muted">When your camera passes through Adobe Character Animator's Mercury Transmit (or any NDI/virtual-camera bridge), the puppet shows here. Talk, your puppet moves. Stay on-brand while you walk the catalog.</p>
    <div class="live-wrap">
      <video id="live-video" autoplay playsinline muted></video>
      <canvas id="live-overlay" aria-hidden="true"></canvas>
      <div class="live-controls">
        <label for="live-cam">Camera</label>
        <select id="live-cam" aria-label="Select camera source"></select>
        <label for="live-mic">Microphone</label>
        <select id="live-mic" aria-label="Select microphone source"></select>
        <button id="live-start">Start live</button>
        <button id="live-stop" disabled>Stop</button>
        <button id="live-overlay-toggle" aria-pressed="false">Overlay onto duel</button>
        <button id="live-snap">📸 Snap a frame</button>
      </div>
      <div class="live-tip">
        <strong>How to wire Adobe Character Animator:</strong>
        <ol>
          <li>Open Adobe Character Animator → set your puppet</li>
          <li><strong>Output → Mercury Transmit</strong> → enable <em>NDI</em> or <em>Syphon</em> output</li>
          <li>Run a virtual-camera bridge (e.g. <a href="https://obsproject.com" target="_blank" rel="noopener">OBS</a> → NDI Source → Virtual Camera, or <a href="https://github.com/keijiro/KlakNDI" target="_blank" rel="noopener">KlakNDI</a>)</li>
          <li>Pick the virtual camera from the dropdown above</li>
          <li>Your face is now a puppet on this page</li>
        </ol>
      </div>
    </div>
  </section>

  <!-- Time-Travel Wardrobe (closet → old photo) -->
  <section id="timetravel" class="screen" hidden>
    <h2>Time-Travel Wardrobe</h2>
    <p class="muted">Pick a piece from your closet. Pick an old photo. Tell us the occasion. We re-dress past-you in the outfit you wish you'd worn — face, friends, venue all preserved.</p>
    <div class="tt-step">
      <h3>1. Pick a piece from your closet</h3>
      <div id="tt-closet" class="grid"></div>
    </div>
    <div class="tt-step">
      <h3>2. Drop the old photo</h3>
      <input type="file" id="tt-photo" accept="image/*">
      <img id="tt-photo-preview" style="max-width:300px;border-radius:14px;margin-top:10px;display:none;">
    </div>
    <div class="tt-step">
      <h3>3. What was the occasion?</h3>
      <div class="pills">
        <button class="pill" data-occ="wedding">Wedding</button>
        <button class="pill" data-occ="graduation">Graduation</button>
        <button class="pill" data-occ="prom">Prom</button>
        <button class="pill" data-occ="reunion">Reunion</button>
        <button class="pill" data-occ="bday">Birthday</button>
        <button class="pill" data-occ="work">Big work moment</button>
        <button class="pill" data-occ="firstdate">First date</button>
        <button class="pill" data-occ="other">Other</button>
      </div>
      <input id="tt-occ" placeholder="Or describe it in your own words…" style="margin-top:10px;padding:14px;border-radius:12px;border:1px solid var(--line);width:100%;">
    </div>
    <button id="tt-go" class="pill" disabled>Re-dress me in this photo →</button>
    <div id="tt-result"></div>
  </section>

  <!-- Item Credits — shotonwhat-style résumé for a garment (tick 15) -->
  <section id="credits" class="screen" hidden>
    <a href="#" id="credits-back" class="back-pill">← back</a>
    <header class="credits-header">
      <h2 id="credits-title">Credits</h2>
      <p class="muted">
        <span id="credits-brand"></span>
        <span class="dot">·</span>
        <span id="credits-count">0</span> appearances
      </p>
    </header>
    <div id="credits-list" class="credits-list"></div>
    <p class="muted credits-footnote">
      Inspired by <a href="https://shotonwhat.com" target="_blank" rel="noopener">shotonwhat.com</a> — a single garment's working résumé across every try-on, render, and outfit pick.
    </p>
  </section>

  <!-- Productions (set-decorator role only) — shotonwhat-style project list -->
  <section id="productions" class="screen" hidden>
    <h2>My Productions</h2>
    <p class="muted">Each production groups the closet pieces, try-ons, and outfit picks you built for that show or shoot. Same résumé view as shotonwhat.com — but for the room, not the cast.</p>
    <form id="production-add" class="production-add">
      <input type="text" id="prod-title" placeholder="Show or film title (e.g., 'Westworld')" required />
      <input type="number" id="prod-year" placeholder="Year" min="1900" max="2099" style="max-width:120px;" />
      <select id="prod-kind">
        <option value="tv-episode">TV episode</option>
        <option value="tv-season">TV season</option>
        <option value="film">Film</option>
        <option value="commercial">Commercial</option>
        <option value="theater">Theater</option>
      </select>
      <select id="prod-role">
        <option>Set Decoration Buyer</option>
        <option>Set Decorator</option>
        <option>Production Designer</option>
        <option>Costume Designer</option>
        <option>Wardrobe Supervisor</option>
      </select>
      <button class="ghost wide" type="submit">+ Add production</button>
    </form>
    <div id="productions-list" class="productions-list"></div>
  </section>

  <!-- Couple (flag-gated lifecycle UI — tick 16) -->
  <section id="couple" class="screen" hidden>
    <h2>Couple</h2>
    <p class="muted">Pilot. Each partner controls per-garment privacy. Either of you can exit at any time — exit purges the shared training join.</p>

    <div class="couple-card">
      <h3>Invite a partner</h3>
      <p class="muted">Generate a one-time token. Share it any way you like; your partner pastes it on their device.</p>
      <button type="button" id="couple-invite-btn" class="primary">Generate invite token</button>
      <div id="couple-invite-out" class="couple-token" hidden></div>
    </div>

    <div class="couple-card">
      <h3>Accept a partner's token</h3>
      <p class="muted">Paste the token your partner sent. This links the two of you. Both can opt out later.</p>
      <form id="couple-accept-form" class="couple-accept">
        <input type="text" id="couple-token-input" placeholder="paste token" autocomplete="off" />
        <button type="submit">Accept</button>
      </form>
      <div id="couple-accept-out" class="muted"></div>
    </div>

    <div class="couple-card">
      <h3>Exit couple</h3>
      <p class="muted">This sets the join to exited and purges the cross-twin training. Your individual closet stays intact.</p>
      <button type="button" id="couple-exit-btn" class="ghost">Exit couple</button>
      <div id="couple-exit-out" class="muted"></div>
    </div>
  </section>

  <!-- Favorites (tick 24) — starred catalog + closet items -->
  <section id="favorites" class="screen" hidden>
    <h2>My Favorites</h2>
    <p class="muted">Tap the star on any item to save it here.</p>
    <div class="fav-actions">
      <button id="fav-share-btn" type="button" class="ghost">Share my catalog favorites →</button>
      <span id="fav-share-out" class="muted"></span>
    </div>
    <div id="favorites-grid" class="grid"></div>
  </section>

  <!-- Brand page (tick 24) — list every catalog item for one brand -->
  <section id="brand" class="screen" hidden>
    <a href="#" class="back-pill" id="brand-back">← back</a>
    <header class="brand-header">
      <h2 id="brand-title">Brand</h2>
      <div id="brand-meta" class="muted"></div>
      <p id="brand-bio" class="brand-bio muted"></p>
    </header>
    <div id="brand-grid" class="grid"></div>
  </section>

  <!-- Delta toast (tick 24) — top movers after every duel pick -->
  <div id="delta-toast" class="delta-toast" hidden></div>

  <!-- Quick-look modal (tick 25) — interstitial when tapping card image -->
  <div id="quicklook-modal" class="quicklook-modal" hidden role="dialog" aria-labelledby="ql-title">
    <div class="quicklook-backdrop" data-ql-close></div>
    <article class="quicklook-card">
      <button type="button" class="quicklook-close" data-ql-close aria-label="Close">×</button>
      <img id="ql-img" alt="">
      <div class="quicklook-body">
        <h3 id="ql-title">…</h3>
        <p class="quicklook-brand"><a id="ql-brand-link" href="#" data-brand="">…</a></p>
        <p class="quicklook-meta"><span id="ql-price"></span> <span id="ql-tier"></span></p>
        <div class="quicklook-actions">
          <button id="ql-star" class="quicklook-btn">☆ Save</button>
          <a id="ql-out" class="quicklook-btn primary" target="_blank" rel="noopener">View on brand site →</a>
        </div>
      </div>
    </article>
  </div>

  <!-- Try-on history -->
  <section id="tryons" class="screen" hidden>
    <h2>My Try-Ons</h2>
    <div id="tryons-grid" class="grid"></div>
  </section>

  <!-- Taste-vector visualizer -->
  <section id="taste" class="screen" hidden>
    <h2>Your taste, decoded</h2>
    <p class="muted" id="taste-summary">Pick a few duels to start sharpening the lens.</p>
    <div id="taste-bars"></div>
    <h3 style="margin-top:30px;">How your lens has sharpened</h3>
    <p class="muted">Each snapshot taken every 5 picked duels.</p>
    <div id="taste-timeline"></div>
    <h3 style="margin-top:30px;">All 32 style dimensions</h3>
    <div id="taste-all"></div>
  </section>

  <!-- Time-Travel demo gallery -->
  <section id="tt-demo" class="screen" hidden>
    <h2>What Time-Travel Wardrobe does</h2>
    <p class="muted">Pick a piece from your closet. Pick an old photo. Tell us the occasion. We re-dress past-you in the outfit you wish you'd worn — face, friends, venue all preserved. Here are three examples.</p>
    <div class="tt-demos">
      <article class="tt-demo-card">
        <h3>"I wish I'd worn the navy gown to my sister's wedding"</h3>
        <div class="ba-pair">
          <figure><img src="https://images.unsplash.com/photo-1606216794074-735e91aa2c92?w=600" alt="Wedding photo before"><figcaption>Before — what was worn</figcaption></figure>
          <span class="arrow" aria-hidden="true">→</span>
          <figure><img src="https://images.unsplash.com/photo-1594736797933-d0501ba2fe65?w=600" alt="Wedding photo after, re-dressed"><figcaption>After — the dress from her closet</figcaption></figure>
        </div>
        <p class="muted">Face preserved. Wedding party preserved. Venue preserved. Only the outfit changed.</p>
      </article>
      <article class="tt-demo-card">
        <h3>"My graduation in the suit I outgrew before I bought one I love"</h3>
        <div class="ba-pair">
          <figure><img src="https://images.unsplash.com/photo-1607369329012-5c5f24b91f15?w=600" alt="Graduation photo before"><figcaption>Before</figcaption></figure>
          <span class="arrow" aria-hidden="true">→</span>
          <figure><img src="https://images.unsplash.com/photo-1593032465175-481ac7f401f0?w=600" alt="Graduation photo after"><figcaption>After</figcaption></figure>
        </div>
      </article>
      <article class="tt-demo-card">
        <h3>"First-date photo. Different jacket this time."</h3>
        <div class="ba-pair">
          <figure><img src="https://images.unsplash.com/photo-1495427513693-15f5e80f7adb?w=600" alt="Date photo before"><figcaption>Before</figcaption></figure>
          <span class="arrow" aria-hidden="true">→</span>
          <figure><img src="https://images.unsplash.com/photo-1543076447-215ad9ba6923?w=600" alt="Date photo after"><figcaption>After — denim jacket from closet</figcaption></figure>
        </div>
      </article>
    </div>
    <p class="muted">These are illustrative examples — your actual renders use your own face, your own photos, your own closet.</p>
    <button class="pill" onclick="route('timetravel')">Try it with your own photo →</button>
  </section>

  <!-- Debates — how product decisions get made -->
  <section id="debates" class="screen" hidden>
    <h2>How decisions get made</h2>
    <p class="muted">Every meaningful product decision goes through a three-model adversarial debate before it ships. Verdicts below are the raw output — what shipped is downstream of these.</p>
    <div id="debates-list"></div>
  </section>

  <!-- Support / donations -->
  <section id="support" class="screen" hidden>
    <h2>How this stays honest</h2>
    <p>WhatsMyStyle takes no affiliate cuts and runs no ads. Our dream-team debate panel told us why, in plain terms: any commission on outbound clicks structurally pulls against the repair-first nudges and sustainability score we already shipped. So we just don't take them.</p>
    <p>That means we're <strong>donation-supported</strong>. If the app helped you — if Time-Travel made you smile, if the optometrist loop saved you from buying a wrong piece — kick in.</p>
    <div id="support-cta-wrap" style="margin: 30px 0;">
      <a id="support-cta" class="pill" href="#" target="_blank" rel="noopener" style="display:none;">Send a tip →</a>
      <p id="support-cta-fallback" class="muted">Donation link not configured yet. Steve's setting up Stripe Checkout.</p>
    </div>
    <h3>What your tip pays for</h3>
    <ul class="plain">
      <li>Server time on a small VPS (~$30/mo)</li>
      <li>Local-LLM compute (zero marginal $ — runs on a Mac in Steve's office)</li>
      <li>Domain + SSL renewal</li>
      <li>That's it. There's no team. There's no growth funnel.</li>
    </ul>
  </section>

  <!-- Privacy -->
  <section id="privacy" class="screen" hidden>
    <h2>Your data, plainly</h2>
    <ul class="plain">
      <li><strong>Your face never leaves our servers.</strong> The digital-twin render lives in your account only. We don't share it, we don't sell it, we don't train any public model on it.</li>
      <li><strong>Bank receipts are read-only.</strong> If you connect your bank, we read clothing-merchant transactions to match purchases to your closet. We never see balances, we never move money, we cannot initiate any transaction.</li>
      <li><strong>Email is read-only too.</strong> When you connect Gmail, we use the <code>readonly</code> scope and parse only order/shipping subjects — nothing else.</li>
      <li><strong>Photos stay yours.</strong> Closet uploads, old-photo time-travel inputs, and twin source photos are stored in your account on our servers and are not shared.</li>
      <li><strong>Location is on-demand.</strong> We ask only at the moment you tap "Stores Near Me" and we don't retain it after the query.</li>
      <li><strong>Social isn't scraped.</strong> Social photos only enter the system if you upload them yourself.</li>
      <li><strong>You can delete everything.</strong> One tap, instant: your user row, every duel, every closet item, your twin, every render. Nothing recoverable.</li>
    </ul>
    <button class="pill" onclick="forgetMe()" aria-label="Delete all my data right now">Delete my account + everything →</button>
  </section>

  <!-- Connections -->
  <section id="connect" class="screen" hidden>
    <h2>Let me see…</h2>
    <p class="muted">Each one is OPT-IN. Skip any of them — the optometrist loop alone works fine.</p>
    <div class="connect-list">
      <button class="conn" data-kind="stripe_fc">
        <strong>Your bank receipts</strong>
        <small>Bank-grade read-only access. We match clothing purchases to your closet.</small>
      </button>
      <button class="conn" data-kind="gmail">
        <strong>Email order confirmations</strong>
        <small>Read-only. We parse shipping confirmations from Nordstrom, Net-a-Porter, etc.</small>
      </button>
      <button class="conn" data-kind="camera_roll">
        <strong>Camera roll</strong>
        <small>Only the albums you pick. We see what you actually wear.</small>
      </button>
      <button class="conn" data-kind="social">
        <strong>Social photos</strong>
        <small>You upload them manually. We never scrape.</small>
      </button>
      <button class="conn" data-kind="location">
        <strong>Location</strong>
        <small>Used for Stores Near Me only — never sold, never stored long-term.</small>
      </button>
    </div>
    <div id="connect-state" class="muted"></div>
  </section>


<!-- Picture-in-picture container — survives across screens once Live is started -->
<div id="duel-pip" hidden><video id="pip-video" autoplay playsinline muted></video></div>

</main>

<footer class="footer" role="contentinfo">
  <a href="#" data-screen="about">About</a> ·
  <a href="#" data-screen="support">Support</a> ·
  <a href="#" data-screen="privacy">Privacy</a> ·
  <a href="/privacy-policy">Privacy policy (full)</a> ·
  <a href="#" data-screen="debates">How decisions get made</a> ·
  <button class="link-btn" onclick="forgetMe()" aria-label="Delete all my data">Delete my account + everything</button>
</footer>

<!-- Tick 20: floating embed-progress chip — admin only, lower-right.
     Visible across every screen so Steve sees draining state while clicking. -->
<div id="embed-chip" class="embed-chip" data-role-only="admin" hidden>
  <div class="embed-chip-head">
    <span class="embed-chip-dot" id="embed-chip-dot"></span>
    <span><strong id="embed-chip-pct">0</strong>% · <span id="embed-chip-left">0</span> left</span>
    <span class="embed-chip-mac1" id="embed-chip-mac1">Mac1: …</span>
  </div>
  <div class="embed-chip-track"><div class="embed-chip-fill" id="embed-chip-fill"></div></div>
  <!-- Tick 22: paid-API burn vs budget. Color goes amber > 75%, red > 100%. -->
  <div class="embed-chip-budget" id="embed-chip-budget" title="Paid-API burn this month">
    <span id="embed-chip-spent">$0.00</span> <span class="muted-sm">of $<span id="embed-chip-budget-cap">5.00</span> · </span><span id="embed-chip-burn-by"></span>
  </div>
</div>

<script src="/js/app.js"></script>
</body>
</html>