Files
2026-10-02 16:07:24 -04:00

38 lines
30 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="light"><title>Hope · OPAL</title><style>
:root{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#302b40;background:#eeeaf7;--ink:#302b40;--muted:#6e657c;--violet:#7453ab;--pink:#f8edf2;--lilac:#f1edfa;--ice:#eaf4fb}*{box-sizing:border-box}body{margin:0}button,input,select{font:inherit}button,a,input,select{-webkit-tap-highlight-color:transparent}button{cursor:pointer;color:inherit;border:0;min-width:44px;min-height:44px;background:none}button:hover{background-color:#f2eef8}button:active{transform:scale(.97)}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible{outline:3px solid #8763bd;outline-offset:4px}a{color:inherit}button,select{transition:background .18s,transform .18s}[hidden]{display:none!important}.layout{min-height:100vh;max-width:1150px;margin:auto;display:grid;grid-template-columns:1fr 414px;gap:115px;align-items:center;padding:58px 48px}.presentation{max-width:430px}.back-link{display:inline-flex;min-height:44px;align-items:center;gap:10px;text-decoration:none;font-size:13px;color:#675d79;margin-bottom:37px}.concept{font-size:13px;color:#675d79;display:flex;gap:10px;align-items:center}.concept:before{content:"";height:7px;width:7px;border-radius:50%;background:#a281c2}.presentation h1{font-size:82px;font-weight:400;letter-spacing:-.04em;line-height:1;margin:19px 0 23px}.lead{font-size:23px;letter-spacing:-.025em;line-height:1.5;max-width:25ch;margin:0 0 35px}.notes{padding:0;list-style:none;margin:0}.notes li{padding:18px 0;border-top:1px solid #d8d0e6;font-size:14px;line-height:1.6;color:#675d79}.notes strong{display:block;font-weight:550;font-size:15px;color:#302b40;margin-bottom:3px}.identity{display:flex;align-items:center;gap:24px;margin-top:29px}.icon-large{width:100px;height:100px;filter:drop-shadow(0 8px 12px #64508118)}.icon-small{width:32px;height:32px}.identity p{font-size:12px;color:#675d79;line-height:1.6;margin:8px 0 0}.demo-note{font-size:12px;line-height:1.75;color:#675d79;margin-top:28px;max-width:43ch}.device{width:414px;padding:11px;background:#faf9fd;border-radius:53px;box-shadow:0 28px 65px #5e4f7c20,0 0 0 1px #ffffffaa,inset 0 0 0 2px #e8e3ed}.screen{width:390px;height:800px;border-radius:43px;background:#fff;overflow:hidden;position:relative;isolation:isolate;box-shadow:0 0 0 1px #ded9e6}.statusbar{height:52px;display:flex;align-items:center;justify-content:space-between;padding:0 27px;font-size:14px;font-weight:600;position:relative}.island{width:110px;height:29px;border-radius:30px;background:#201d26;position:absolute;left:50%;top:10px;transform:translateX(-50%)}.status-icons{display:flex;gap:5px;align-items:center}.status-icons svg{width:15px;height:15px}.status-icons .battery{width:23px}.app-header{height:66px;display:flex;align-items:center;padding:0 21px;gap:8px}.brand{display:flex;align-items:center;gap:8px;margin-right:auto;font-size:21px;font-weight:530;letter-spacing:-.03em}.brand svg{width:28px;height:28px}.round-button{display:grid;place-items:center;border-radius:50%;width:44px;height:44px}.round-button svg,.glyph{width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.65;stroke-linecap:round;stroke-linejoin:round}.app-header .round-button{color:#7b708b}.content{height:552px;overflow-y:auto;scrollbar-width:thin;padding:0 27px}.home{text-align:center;padding-top:26px}.greeting{font-size:32px;line-height:1.24;letter-spacing:-.035em;font-weight:400;margin:0}.greeting em{font-family:Georgia,serif;font-weight:400}.welcome-copy{color:var(--muted);font-size:13px;margin:15px 0 0;line-height:1.6}.pearl-wrap{width:240px;height:210px;margin:8px auto 0;position:relative}.pearl{width:100%;height:100%;overflow:visible}.pearl-shadow{position:absolute;width:120px;height:8px;bottom:6px;left:calc(50% - 60px);background:#c9c0df;opacity:.22;filter:blur(8px);border-radius:50%}.voice-start{display:flex;gap:10px;align-items:center;justify-content:center;margin:5px auto 0;font-size:14px;font-weight:500;padding:0 17px 0 7px;border-radius:40px;background:#faf7fc;min-height:52px}.mic-halo{width:39px;height:39px;display:grid;place-items:center;border-radius:50%;background:radial-gradient(circle at 35% 20%,#fff 0,#eee1f5 60%,#eadff6 100%);box-shadow:0 0 0 5px #f8f2fb;color:#775393}.mic-halo svg{width:19px}.prompts{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:23px}.prompt{font-size:12px;border-radius:30px;padding:0 15px;min-height:44px;color:#63586f}.prompt:nth-child(1){background:var(--pink)}.prompt:nth-child(2){background:var(--lilac)}.prompt:nth-child(3){background:var(--ice)}.composer-zone{position:absolute;bottom:27px;left:19px;right:19px;z-index:2}.composer{display:flex;align-items:center;height:64px;padding:8px 9px 8px 19px;border-radius:34px;background:#fff;box-shadow:0 5px 22px #69587814,0 1px 4px #69587812;gap:5px}.composer input{min-width:0;flex:1;border:0;outline:0;background:none;font-size:14px;color:var(--ink);height:44px}.composer input::placeholder{color:#756b81}.composer input:focus-visible{outline:0}.composer:focus-within{box-shadow:0 0 0 2px #b59bcf,0 5px 22px #69587814}.composer .mic-button{border-radius:50%;background:#f1e9f8;width:44px;color:#725199}.composer .send-button{border-radius:50%;background:#76579d;color:#fff;width:44px}.simulation{font-size:10px;text-align:center;color:#796e84;margin:12px 0 0}.home-indicator{position:absolute;bottom:9px;left:50%;transform:translateX(-50%);width:125px;height:4px;background:#292331;border-radius:4px}.device-caption{text-align:center;font-size:11px;color:#756982;margin:20px 0 0}.page-heading{font-size:29px;letter-spacing:-.035em;font-weight:450;margin:22px 0 10px}.page-description{color:var(--muted);font-size:13px;line-height:1.7;margin:0 0 25px}.back{display:flex;gap:7px;align-items:center;padding:0;color:#77608d;font-size:12px}.back svg{width:17px}.history-label{font-size:12px;color:#7d7188;margin:25px 0 8px}.history-row{display:flex;align-items:center;width:100%;text-align:left;padding:16px 0;gap:15px;border-bottom:1px solid #f0edf4;border-radius:0}.history-row .history-symbol{width:39px;height:39px;background:#f4effa;border-radius:50%;display:grid;place-items:center;color:#9779b1}.history-symbol svg{width:20px}.history-row strong{font-size:14px;font-weight:500;display:block}.history-row small{font-size:11px;color:var(--muted);display:block;margin-top:7px}.history-row .chevron{margin-left:auto;width:17px;color:#94869e}.thread-title{font-size:23px;font-weight:450;letter-spacing:-.025em;margin:15px 0 20px}.transcript{display:flex;flex-direction:column;gap:20px;padding-bottom:24px}.message{font-size:14px;line-height:1.65;max-width:94%}.message small{display:block;font-size:10px;font-weight:500;color:#786a88;margin-bottom:6px}.message p{margin:0}.message.you{background:#f5f0fa;padding:13px 17px;border-radius:16px 16px 4px 16px;align-self:flex-end}.message.hope{padding:0 5px;align-self:flex-start}.settings-group{margin-top:26px}.settings-group h3{font-size:12px;font-weight:500;color:#786a88;margin-bottom:10px}.setting{min-height:72px;display:flex;align-items:center;justify-content:space-between;gap:15px;border-bottom:1px solid #eeebf2}.setting span{font-size:14px}.setting small{display:block;color:var(--muted);font-size:11px;margin-top:6px;line-height:1.5}.setting select{height:44px;border:0;border-radius:10px;background:#f3eef9;color:#685079;padding:0 9px;font-size:12px}.setting input{accent-color:#8764af;width:22px;height:22px;cursor:pointer}.settings-footer{font-size:12px;line-height:1.8;color:var(--muted);margin-top:26px}.settings-save{width:100%;border-radius:30px;background:#f1e9f8;color:#705088;margin-top:20px;font-size:13px}.saved-note{font-size:12px;text-align:center;color:#705088;margin-top:12px;min-height:20px}.live{position:absolute;inset:52px 0 21px;z-index:3;background:#fff;display:flex;flex-direction:column;align-items:center;padding:20px 26px 14px}.live-top{width:100%;display:flex;align-items:center;justify-content:space-between;font-size:13px}.live-top span{color:#786b86;font-size:11px}.live-pearl{width:142px;height:150px;margin-top:30px}.live h2{font-size:27px;letter-spacing:-.025em;font-weight:400;margin:10px 0}.live-state{font-size:12px;color:#796489;display:flex;gap:6px;align-items:center}.state-dot{width:5px;height:5px;border-radius:50%;background:#a78cc3}.elapsed{font-variant-numeric:tabular-nums;color:#8c7f95;font-size:11px;margin-top:10px}.ribbon{width:310px;height:67px;margin-top:13px;overflow:visible}.live-log{width:100%;overflow:auto;flex:1;min-height:0;padding:14px 4px 0;scrollbar-width:thin}.live-log .message{margin-bottom:18px;font-size:13px}.live-controls{display:flex;align-items:center;justify-content:center;gap:28px;padding-top:20px}.control-group{text-align:center;font-size:10px;color:#796c86}.control-group button{display:grid;place-items:center;width:54px;height:54px;border-radius:50%;background:#f4eff9;margin-bottom:9px}.control-group .listen{width:65px;height:65px;background:#eee2f5;box-shadow:0 0 0 7px #faf5fc}.control-group .end{background:#fbedf1;color:#a66b7d}.live-note{font-size:10px;color:#7b6e85;margin:18px 0 0}.listening .ribbon{animation:breathe 3s ease-in-out infinite}.listening .live-pearl{animation:pearl-breathe 4s ease-in-out infinite}@keyframes breathe{50%{transform:scaleY(.65);opacity:.65}}@keyframes pearl-breathe{50%{transform:translateY(-4px)}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
@media(max-width:1050px){.layout{gap:55px;padding:40px 30px}.presentation h1{font-size:70px}.lead{font-size:21px}}@media(max-width:780px){.layout{display:flex;flex-direction:column;padding:30px 20px;gap:35px}.presentation{width:100%;max-width:414px}.presentation h1{font-size:56px;margin:12px 0 14px}.back-link{margin-bottom:20px}.lead{font-size:19px;margin-bottom:20px;max-width:33ch}.notes{display:none}.identity{margin-top:20px}.icon-large{width:64px;height:64px}.demo-note{margin-top:18px}.device-wrap{max-width:100%}}@media(max-width:440px){body{background:#fff}.layout{padding:0;gap:0}.presentation,.device-caption{display:none}.device{width:100vw;padding:0;border-radius:0;background:#fff;box-shadow:none}.screen{width:100%;height:100svh;min-height:760px;border-radius:0;box-shadow:none}.content{height:calc(100% - 248px)}.home{padding-top:20px}.composer-zone{bottom:max(27px,env(safe-area-inset-bottom))}.statusbar{padding-left:29px;padding-right:29px}.home-indicator{bottom:8px}.live{bottom:21px}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
</style></head><body>
<svg width="0" height="0" aria-hidden="true" style="position:absolute"><defs>
<linearGradient id="opal-fill" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#fef7fc" stop-opacity=".75"/><stop offset=".26" stop-color="#eae4ff" stop-opacity=".35"/><stop offset=".57" stop-color="#fff" stop-opacity=".05"/><stop offset=".79" stop-color="#d8edf9" stop-opacity=".45"/><stop offset="1" stop-color="#e4d7f4" stop-opacity=".8"/></linearGradient>
<radialGradient id="pearl-core" cx="40%" cy="30%" r="74%"><stop stop-color="white" stop-opacity=".05"/><stop offset=".54" stop-color="#fff" stop-opacity=".02"/><stop offset=".79" stop-color="#e2daf5" stop-opacity=".3"/><stop offset=".92" stop-color="#e2d1ed" stop-opacity=".65"/><stop offset=".98" stop-color="#faf6fd"/><stop offset="1" stop-color="#bdb2d8" stop-opacity=".6"/></radialGradient>
<linearGradient id="rim" x1="0" y1="1" x2="1" y2="0"><stop stop-color="#e7c9e7"/><stop offset=".24" stop-color="#fff"/><stop offset=".42" stop-color="#c3d4ed"/><stop offset=".68" stop-color="#fff"/><stop offset=".86" stop-color="#dcc6ea"/><stop offset="1" stop-color="#f8e8f7"/></linearGradient>
<linearGradient id="pink-reflection" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#e4c1dd" stop-opacity=".8"/><stop offset=".35" stop-color="#f8e6f1" stop-opacity=".6"/><stop offset=".7" stop-color="#fff" stop-opacity="0"/><stop offset="1" stop-color="#bcade1" stop-opacity=".7"/></linearGradient>
<linearGradient id="blue-reflection" x1="1" y1="0" x2="0" y2="1"><stop stop-color="#d0e9f8" stop-opacity=".1"/><stop offset=".5" stop-color="#b7d9f0" stop-opacity=".6"/><stop offset=".78" stop-color="#e2d3f5" stop-opacity=".3"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient>
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#fff" stop-opacity=".95"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><filter id="soft"><feGaussianBlur stdDeviation="2.7"/></filter><filter id="soft-light"><feGaussianBlur stdDeviation=".6"/></filter>
<symbol id="pearl-art" viewBox="0 0 280 280"><circle cx="140" cy="136" r="110" fill="url(#opal-fill)"/><circle cx="140" cy="136" r="110" fill="url(#pearl-core)"/>
<path d="M62 61C91 25 142 16 182 37C132 26 106 52 99 93C88 143 74 166 45 175C33 135 36 91 62 61Z" fill="url(#pink-reflection)" filter="url(#soft)"/>
<path d="M205 58C240 91 254 152 229 196C211 226 171 247 128 244C194 227 179 189 201 165C226 138 239 105 205 58Z" fill="url(#blue-reflection)"/>
<path d="M50 92C76 32 156 22 205 64C144 23 106 54 99 104C90 155 59 189 45 166C62 175 86 139 89 99C91 62 117 36 150 36C111 24 68 46 50 92Z" fill="url(#shine)" opacity=".87"/>
<path d="M47 163C70 182 105 134 126 112C152 85 181 84 213 102C194 95 174 100 155 114C120 140 96 189 68 190C58 187 52 178 47 163Z" fill="url(#pink-reflection)" opacity=".62" filter="url(#soft)"/>
<path d="M64 187C110 218 174 121 218 141C173 136 142 222 101 224C82 221 71 207 64 187Z" fill="url(#blue-reflection)" opacity=".63"/>
<path d="M84 223C142 250 196 221 223 181" fill="none" stroke="white" stroke-width="3" opacity=".8" filter="url(#soft-light)"/>
<circle cx="140" cy="136" r="110" fill="none" stroke="url(#rim)" stroke-width="1.6"/><circle cx="140" cy="136" r="106.5" fill="none" stroke="white" stroke-width=".8" opacity=".8"/>
<path d="M40 106C47 75 69 49 95 39" fill="none" stroke="white" stroke-width="4" stroke-linecap="round" opacity=".85"/><path d="M167 31C209 40 239 73 247 111" fill="none" stroke="#f1d9ee" stroke-width="2" opacity=".8"/><path d="M240 173C228 213 194 240 153 245" fill="none" stroke="#d7daf6" stroke-width="2.2"/><ellipse cx="77" cy="69" rx="6" ry="14" transform="rotate(40 77 69)" fill="#fff" opacity=".9" filter="url(#soft)"/>
</symbol>
<linearGradient id="icon-pearl" x1="0" y1="0" x2="1" y2="1"><stop stop-color="white"/><stop offset=".4" stop-color="#f2ddec"/><stop offset=".7" stop-color="#dbe8f8"/><stop offset="1" stop-color="#cbb7eb"/></linearGradient>
<symbol id="app-icon" viewBox="0 0 100 100"><rect width="100" height="100" rx="23" fill="#9b7fbe"/><circle cx="40" cy="42" r="25" fill="url(#icon-pearl)"/><path d="m23 56-3 16 16-9" fill="url(#icon-pearl)"/><circle cx="63" cy="58" r="23" fill="url(#icon-pearl)" stroke="#9b7fbe" stroke-width="2"/><path d="m70 77 13 9-2-17" fill="url(#icon-pearl)"/><path d="M21 39C23 28 31 22 42 21M46 57C46 46 53 39 63 38" stroke="#fff" stroke-width="2" stroke-linecap="round" opacity=".9" fill="none"/><path d="M55 23C69 34 65 53 52 63" stroke="#b5a2d1" fill="none" opacity=".7"/></symbol>
<symbol id="brand-mark" viewBox="0 0 32 32"><circle cx="13" cy="13" r="9" fill="#d9c9ec"/><path d="m6 18-1 6 6-4" fill="#d9c9ec"/><circle cx="21" cy="21" r="8" fill="#eddef0" stroke="white" stroke-width="1.5"/><path d="m24 26 5 4-1-6" fill="#eddef0"/></symbol>
<symbol id="mic" viewBox="0 0 24 24"><rect x="9" y="3" width="6" height="12" rx="3"/><path d="M5 11v2a7 7 0 0 0 14 0v-2M12 20v2M8 22h8"/></symbol><symbol id="mute" viewBox="0 0 24 24"><path d="m3 3 18 18M9 9v3a3 3 0 0 0 5 2M9 5a3 3 0 0 1 6 0v6M5 11v2a7 7 0 0 0 12 5M19 11v2M12 20v2"/></symbol><symbol id="history" viewBox="0 0 24 24"><path d="M4 8a9 9 0 1 1-1 7M4 3v5h5M12 7v5l3 2"/></symbol><symbol id="settings" viewBox="0 0 24 24"><path d="M4 7h16M4 17h16"/><circle cx="9" cy="7" r="3" fill="white"/><circle cx="16" cy="17" r="3" fill="white"/></symbol><symbol id="arrow" viewBox="0 0 24 24"><path d="M12 19V5m-6 6 6-6 6 6"/></symbol><symbol id="back" viewBox="0 0 24 24"><path d="m14 6-6 6 6 6"/></symbol><symbol id="chevron" viewBox="0 0 24 24"><path d="m9 6 6 6-6 6"/></symbol><symbol id="chat" viewBox="0 0 24 24"><path d="M20 11a8 8 0 0 1-8 8 9 9 0 0 1-4-1l-5 3 1-6a8 8 0 1 1 16-4Z"/></symbol><symbol id="end" viewBox="0 0 24 24"><path d="M5 16v-4h14v4M3 12c4-5 14-5 18 0"/></symbol>
</defs></svg>
<main class="layout"><aside class="presentation" aria-label="Design direction"><a class="back-link" href="new-index.html">← Explore the new directions</a><div class="concept">Hope · A new direction</div><h1>OPAL</h1><p class="lead">A little space to think.<br>A softer way to be heard.</p><ul class="notes"><li><strong>Light, held in a pearl.</strong>Transparent layers, curved reflections, and an iridescent edge give Hope a quiet physical presence.</li><li><strong>The conversation has room.</strong>A luminous white canvas. A personal greeting. Everyday prompts that don’t compete for attention.</li><li><strong>Always within reach.</strong>One floating composer for a thought in text or a conversation out loud. Voice opens into a focused, uncluttered space.</li></ul><div class="identity"><svg class="icon-large" role="img" aria-label="Hope icon, two overlapping pearlescent circular speech forms on violet"><use href="#app-icon"/></svg><div><svg class="icon-small" role="img" aria-label="Hope icon at 32 pixels"><use href="#app-icon"/></svg><p>Two voices, a shared space.<br>App icon · 100 / 32 px</p></div></div><p class="demo-note">Interactive design study. All conversations are simulated and stay on this page. No microphone, audio, network, or account access.</p></aside>
<section class="device-wrap" aria-label="Interactive Hope phone"><div class="device"><div class="screen" id="screen"><div class="statusbar" aria-hidden="true"><span>9:41</span><span class="island"></span><div class="status-icons"><svg viewBox="0 0 20 20" fill="currentColor"><rect x="1" y="12" width="3" height="5" rx="1"/><rect x="6" y="9" width="3" height="8" rx="1"/><rect x="11" y="6" width="3" height="11" rx="1"/><rect x="16" y="3" width="3" height="14" rx="1"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9a14 14 0 0 1 18 0M6 12a9 9 0 0 1 12 0M9 15a4 4 0 0 1 6 0"/><circle cx="12" cy="18" r="1" fill="currentColor"/></svg><svg class="battery" viewBox="0 0 25 16" fill="none" stroke="currentColor"><rect x="1" y="2" width="20" height="12" rx="3"/><rect x="3" y="4" width="16" height="8" rx="1" fill="currentColor"/><path d="M23 6v4" stroke-width="2"/></svg></div></div>
<header class="app-header"><div class="brand"><svg aria-hidden="true"><use href="#brand-mark"/></svg>hope</div><button class="round-button" id="history-button" aria-label="Open history"><svg class="glyph"><use href="#history"/></svg></button><button class="round-button" id="settings-button" aria-label="Open settings"><svg class="glyph"><use href="#settings"/></svg></button></header>
<div class="content" id="content" tabindex="-1"><section class="home"><h2 class="greeting">A little room for you,<br><em>Shane.</em></h2><p class="welcome-copy">No perfect words needed. Start anywhere.</p><div class="pearl-wrap"><span class="pearl-shadow"></span><svg class="pearl" role="img" aria-label="A translucent pearl with pink, lilac and ice-blue reflections"><use href="#pearl-art"/></svg></div><button class="voice-start" id="start-voice"><span class="mic-halo"><svg class="glyph"><use href="#mic"/></svg></span>Let’s talk</button><div class="prompts"><button class="prompt" data-prompt="day">Talk through my day</button><button class="prompt" data-prompt="idea">Explore an idea</button><button class="prompt" data-prompt="plan">Make a plan</button></div></section></div>
<div class="composer-zone"><form class="composer" id="composer"><label for="message" class="sr-only">Message Hope</label><input id="message" placeholder="What’s on your mind?" maxlength="2000" autocomplete="off"><button type="submit" class="send-button" id="send-message" aria-label="Send message" hidden><svg class="glyph"><use href="#arrow"/></svg></button><button type="button" class="mic-button" id="composer-mic" aria-label="Start voice conversation"><svg class="glyph"><use href="#mic"/></svg></button></form><p class="simulation">Local demo · Your microphone stays off</p></div>
<section class="live" id="live" aria-label="Simulated voice conversation" hidden><div class="live-top"><strong>With Hope</strong><span>Simulated voice</span></div><svg class="live-pearl" aria-hidden="true"><use href="#pearl-art"/></svg><h2 id="live-heading">I’m here. Take your time.</h2><div class="live-state" role="status"><span class="state-dot"></span><span id="voice-state">Listening</span></div><div class="elapsed" id="elapsed">00:00</div><svg class="ribbon" viewBox="0 0 320 65" aria-hidden="true"><defs><linearGradient id="ribbon-color"><stop stop-color="#eacbde"/><stop offset=".5" stop-color="#d8c7ed"/><stop offset="1" stop-color="#c4e1f0"/></linearGradient></defs><path d="M0 34C35 34 42 10 76 17S114 57 147 36 190 7 217 27 258 54 284 37 309 29 320 33" fill="none" stroke="url(#ribbon-color)" stroke-width="1.3"/><path d="M0 34C32 34 53 29 77 28S116 44 147 34 189 17 219 31 261 41 284 35 309 32 320 33" fill="none" stroke="url(#ribbon-color)" stroke-width="6" opacity=".4"/><path d="M0 34C34 33 49 44 78 41S115 14 145 31 183 56 217 38 257 20 284 31 309 35 320 33" fill="none" stroke="url(#ribbon-color)" stroke-width="1" opacity=".8"/></svg><div class="live-log" id="live-log" role="log" aria-label="Voice transcript" aria-live="polite"></div><div class="live-controls"><div class="control-group"><button id="mute-button" aria-label="Mute simulated microphone" aria-pressed="false"><svg class="glyph"><use href="#mute"/></svg></button><span id="mute-label">Mute</span></div><div class="control-group"><button class="listen" id="voice-turn" aria-label="Try a simulated voice turn"><svg class="glyph"><use href="#mic"/></svg></button><span>Speak again</span></div><div class="control-group"><button class="end" id="end-call" aria-label="End conversation"><svg class="glyph"><use href="#end"/></svg></button><span>End</span></div></div><p class="live-note">No audio is recorded or played</p></section><div class="home-indicator" aria-hidden="true"></div><div id="announce" class="sr-only" role="status"></div></div></div><p class="device-caption">OPAL · A luminous space for conversation</p></section></main>
<script>
(()=>{'use strict';const $=id=>document.getElementById(id),content=$('content'),homeMarkup=content.innerHTML,live=$('live'),field=$('message');let page='home',voice='Ava',spoken=true,muted=false,interval=null,timers=[],seconds=0,active=null;const history=[{title:'A little breathing room',when:'Today · 9:12 am',messages:[['You','Today feels a little full. I don’t know where to start.'],['Hope','Let’s make it smaller. What’s one thing that needs your attention, and one thing that can wait?']]},{title:'An idea for the weekend',when:'Yesterday · 6:40 pm',messages:[['You','I’d love to spend a day by the sea.'],['Hope','A morning train, a long walk, and lunch somewhere unhurried. Want to start with a place or a date?']]}];const prompts={day:['Talk through my day','What’s been taking up the most space in your day? We can start there.'],idea:['Explore an idea','Tell me the rough version. It doesn’t need to make sense yet.'],plan:['Make a plan','What would you like to make room for? We can find a small first step.']};const icon=name=>'<svg class="glyph" aria-hidden="true"><use href="#'+name+'"/></svg>';const announce=text=>$('announce').textContent=text;function cancel(){timers.forEach(clearTimeout);timers=[]}function schedule(fn,time){timers.push(setTimeout(fn,time))}function show(markup,next){page=next;content.innerHTML=markup;content.scrollTop=0;content.focus({preventScroll:true})}function home(){active=null;show(homeMarkup,'home');field.placeholder='What’s on your mind?'}function back(){return '<button class="back" id="back-home">'+icon('back')+'Back to your space</button>'}function message(target,role,text){const el=document.createElement('div');el.className='message '+(role==='You'?'you':'hope');const label=document.createElement('small');label.textContent=role;const p=document.createElement('p');p.textContent=text;el.append(label,p);target.append(el)}function renderThread(item){active=item;show(back()+'<h2 class="thread-title" id="thread-title"></h2><div class="transcript" id="transcript" role="log" aria-live="polite" aria-label="Conversation transcript"></div>','thread');$('thread-title').textContent=item.title;item.messages.forEach(m=>message($('transcript'),...m));field.placeholder='Keep the thought going…'}function newThread(title,first,reply){const item={title,when:'Just now · Demo',messages:[['You',first],['Hope',reply]]};history.unshift(item);renderThread(item)}function showHistory(){show(back()+'<h2 class="page-heading">Your conversations</h2><p class="page-description">Thoughts you can come back to.<br>Sample threads and your local demo conversations.</p><div class="history-label">Recently</div><div id="history-list"></div>','history');history.forEach((item,index)=>{const button=document.createElement('button');button.className='history-row';button.dataset.thread=index;button.innerHTML='<span class="history-symbol">'+icon('chat')+'</span><span><strong></strong><small></small></span>'+icon('chevron');button.querySelector('strong').textContent=item.title;button.querySelector('small').textContent=item.when;$('history-list').append(button)})}function settings(){show(back()+'<h2 class="page-heading">Make yourself at home.</h2><p class="page-description">A few small choices for your conversations.</p><div class="settings-group"><h3>Conversation</h3><label class="setting"><span>Hope’s voice<small>A preference for this demo</small></span><select id="voice-choice" aria-label="Hope voice"><option>Ava</option><option>Emma</option><option>Andrew</option></select></label><label class="setting"><span>Spoken replies<small>No audio plays in this demo</small></span><input type="checkbox" id="spoken"></label></div><div class="settings-group"><h3>Privacy</h3><div class="setting"><span>Just between us<small>Your text stays on this page.<br>No account or microphone is connected.</small></span>'+icon('chat')+'</div></div><button class="settings-save" id="save-settings">Save preferences</button><p class="saved-note" id="saved-note" role="status"></p><p class="settings-footer">Hope · OPAL design study<br>Preferences and conversations reset when you reload.</p>','settings');$('voice-choice').value=voice;$('spoken').checked=spoken}function state(text,heading){$('voice-state').textContent=text;if(heading)$('live-heading').textContent=heading;live.classList.toggle('listening',text==='Listening');announce(text)}function turn(){cancel();if(muted)return;state('Listening','I’m here. Take your time.');$('voice-turn').disabled=true;schedule(()=>{const text='Help me make a little space in my day.';message($('live-log'),'You',text);active.messages.push(['You',text]);state('Thinking','Let’s find a little room.');},1800);schedule(()=>{const text='Choose one thing that can wait. Then give yourself ten minutes with nothing to solve. What would feel good in that little space?';message($('live-log'),'Hope',text);active.messages.push(['Hope',text]);$('live-log').scrollTop=$('live-log').scrollHeight;state(spoken?'Hope is replying · simulated':'Sample reply ready','One small thing at a time.');},3200);schedule(()=>{state('Listening','What’s on your mind now?');$('voice-turn').disabled=false;},5200)}function startVoice(){cancel();muted=false;seconds=0;active={title:'A little room in my day',when:'Just now · Voice demo',messages:[]};live.hidden=false;$('composer').inert=true;content.inert=true;document.querySelector('.app-header').inert=true;$('live-log').replaceChildren();$('elapsed').textContent='00:00';$('mute-button').setAttribute('aria-pressed','false');$('mute-button').setAttribute('aria-label','Mute simulated microphone');$('mute-label').textContent='Mute';$('voice-turn').disabled=false;interval=setInterval(()=>{seconds++;$('elapsed').textContent=String(Math.floor(seconds/60)).padStart(2,'0')+':'+String(seconds%60).padStart(2,'0')},1000);$('mute-button').focus();turn()}function endVoice(){cancel();clearInterval(interval);interval=null;live.hidden=true;$('composer').inert=false;content.inert=false;document.querySelector('.app-header').inert=false;if(active.messages.length){history.unshift(active);renderThread(active);announce('Conversation ended. Demo transcript saved in history.')}else{home();announce('Conversation ended. Your microphone was never accessed.')} $('composer-mic').focus()}
$('history-button').onclick=showHistory;$('settings-button').onclick=settings;$('composer-mic').onclick=startVoice;content.onclick=e=>{const b=e.target.closest('button');if(!b)return;if(b.id==='back-home')home();if(b.id==='start-voice')startVoice();if(b.dataset.prompt){const p=prompts[b.dataset.prompt];newThread(p[0],p[0],p[1]);field.focus()}if(b.dataset.thread!==undefined)renderThread(history[Number(b.dataset.thread)]);if(b.id==='save-settings'){voice=$('voice-choice').value;spoken=$('spoken').checked;$('saved-note').textContent='Preferences saved for this demo.';announce('Preferences saved')}};field.oninput=()=>{$('send-message').hidden=!field.value.trim()};$('composer').onsubmit=e=>{e.preventDefault();const text=field.value.trim();if(!text)return;const reply='Let’s take it one thought at a time. What feels most important about that to you?';if(page!=='thread')newThread('A thought to talk through',text,reply);else{active.messages.push(['You',text],['Hope',reply]);message($('transcript'),'You',text);message($('transcript'),'Hope',reply);content.scrollTop=content.scrollHeight}field.value='';$('send-message').hidden=true;field.focus();announce('Local message added. Hope’s reply is a prewritten example.')};$('mute-button').onclick=()=>{muted=!muted;cancel();$('mute-button').setAttribute('aria-pressed',String(muted));$('mute-button').setAttribute('aria-label',muted?'Unmute simulated microphone':'Mute simulated microphone');$('mute-label').textContent=muted?'Unmute':'Mute';$('voice-turn').disabled=muted;state(muted?'Microphone muted · simulation paused':'Listening',muted?'A quiet moment.':'Ready when you are.');if(!muted)turn()};$('voice-turn').onclick=turn;$('end-call').onclick=endVoice;document.addEventListener('keydown',e=>{if(e.key==='Escape'){if(!live.hidden)endVoice();else if(page!=='home')home()}});live.addEventListener('keydown',e=>{if(e.key!=='Tab')return;const buttons=[...live.querySelectorAll('button:not(:disabled)')];if(e.shiftKey&&document.activeElement===buttons[0]){e.preventDefault();buttons.at(-1).focus()}else if(!e.shiftKey&&document.activeElement===buttons.at(-1)){e.preventDefault();buttons[0].focus()}});
})();
</script></body></html>