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

39 lines
23 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="dark"><title>Hope — SIGNAL design study</title>
<style>
:root{--petroleum:#10272d;--cyan:#9ee3e9;--ink:#eff7f7;--muted:#b3c7ca;--line:#345057;--panel:#173239;--page:#0c1c21;--mono:ui-monospace,"SFMono-Regular",Menlo,monospace;color-scheme:dark}*{box-sizing:border-box}body{margin:0;background:var(--page);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text",system-ui,sans-serif;-webkit-font-smoothing:antialiased}button,input,select{font:inherit}button{cursor:pointer;color:inherit;background:none;border:0;min-height:44px}button:focus-visible,input:focus-visible,select:focus-visible{outline:2px solid var(--cyan);outline-offset:4px}button:disabled{cursor:default;opacity:.5}button:hover:not(:disabled){background-color:#25464d}a{color:var(--cyan)}[hidden]{display:none!important}.presentation{max-width:1120px;margin:auto;min-height:100vh;display:grid;grid-template-columns:1fr 390px;gap:100px;align-items:center;padding:64px 72px}.intro{max-width:390px}.brand{display:flex;align-items:center;gap:12px;font-size:19px;font-weight:600}.brand svg{width:32px;height:32px}.direction{font-family:var(--mono);font-size:12px;color:var(--cyan);margin:52px 0 16px}.intro h1{font-size:64px;line-height:1.03;font-weight:450;letter-spacing:-.035em;margin:0 0 26px}.intro>p{font-size:17px;line-height:1.65;color:var(--muted);max-width:34ch}.principles{margin:32px 0 40px;padding:0;list-style:none}.principles li{padding:12px 0;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:20px;font-size:14px}.principles span:last-child{color:var(--muted);text-align:right}.icon-study{display:flex;align-items:flex-end;gap:24px}.icon-study svg:first-child{width:104px;height:104px}.icon-study svg.small{width:32px;height:32px}.icon-caption{font-size:12px;color:var(--muted);line-height:1.5;margin-top:12px}.demo-note{font-size:12px!important;margin-top:32px;color:var(--muted)}.phone{width:390px;height:800px;padding:9px;border:1px solid #456067;border-radius:49px;background:#08171c;position:relative}.screen{height:100%;background:var(--petroleum);border-radius:40px;overflow:hidden;display:flex;flex-direction:column;position:relative}.statusbar{height:45px;flex-shrink:0;padding:15px 25px 0;display:flex;justify-content:space-between;font-size:13px;font-weight:600}.island{position:absolute;top:11px;left:50%;transform:translateX(-50%);height:25px;width:104px;background:#08171c;border-radius:20px}.status-icons{display:flex;align-items:center;gap:5px}.status-icons svg{width:17px;height:12px}.app-header{padding:17px 24px 10px;display:flex;align-items:center;justify-content:space-between}.wordmark{font-size:25px;font-weight:550;letter-spacing:-.03em}.sim-label{font-family:var(--mono);font-size:10px;color:var(--muted);border:1px solid var(--line);padding:5px 7px;border-radius:4px}.view{flex:1;min-height:0;overflow-y:auto}.talk{display:flex;flex-direction:column;height:100%;padding:0 24px}.state-line{display:flex;justify-content:space-between;align-items:center;color:var(--cyan);font:11px var(--mono);margin-top:23px}.voice-zone{padding:40px 0 12px;text-align:center}.voice-zone h2{margin:0;font-size:39px;letter-spacing:-.035em;line-height:1.13;font-weight:450;min-height:89px}.voice-zone h2 span{display:block}.wave{width:100%;height:85px;margin:12px 0 2px;display:block;color:var(--cyan)}.wave line{stroke:var(--line);stroke-width:1}.wave path{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}.voice-hint{margin:0 0 16px;color:var(--muted);font-size:12px}.primary{background:var(--cyan);color:var(--petroleum);border:1px solid var(--cyan);border-radius:12px;font-weight:600;width:100%;height:57px;display:flex;align-items:center;justify-content:center;gap:10px;font-size:15px}.primary:hover:not(:disabled){background:#b8eff2!important}.primary svg,.secondary svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.7}.session-controls{display:flex;gap:10px}.session-controls .primary{flex:1}.secondary{border:1px solid var(--line);border-radius:12px;display:flex;gap:7px;align-items:center;justify-content:center;min-width:92px;font-size:13px}.transcript-area{margin-top:25px;padding-top:8px;border-top:1px solid var(--line);flex:1;min-height:115px;display:flex;flex-direction:column}.transcript-header{display:flex;align-items:center;justify-content:space-between}.transcript-header p{font:10px var(--mono);color:var(--muted);margin:0}.mode-toggle{display:flex;gap:2px}.mode-toggle button{min-width:48px;font-size:12px;color:var(--muted);padding:0 8px}.mode-toggle button[aria-pressed=true]{color:var(--cyan)}.messages{overflow:auto;max-height:142px;scroll-behavior:smooth;padding-bottom:12px}.message{margin:9px 0 16px}.message .who{color:var(--muted);font:10px var(--mono);display:flex;gap:10px;margin-bottom:6px}.message p{font-size:14px;line-height:1.5;margin:0}.message.answer p{color:var(--cyan)}.composer{display:flex;gap:8px;margin:8px 0 15px}.composer input{width:100%;min-width:0;height:48px;background:var(--panel);border:1px solid var(--line);color:var(--ink);border-radius:8px;padding:0 12px;font-size:14px}.composer input::placeholder{color:var(--muted)}.composer button{width:48px;flex-shrink:0;background:var(--cyan);color:var(--petroleum);border-radius:8px;font-size:22px}.nav{display:flex;flex-shrink:0;border-top:1px solid var(--line);padding:7px 16px 9px;gap:4px}.nav button{flex:1;display:flex;align-items:center;flex-direction:column;justify-content:center;gap:5px;font-size:10px;color:var(--muted);height:53px;border-radius:8px}.nav button[aria-current=page]{color:var(--cyan)}.nav svg{height:20px;width:20px;fill:none;stroke:currentColor;stroke-width:1.5}.home-indicator{width:112px;height:4px;background:var(--ink);border-radius:4px;margin:0 auto 9px;flex-shrink:0}.inner-view{padding:25px 24px}.inner-view h2{font-size:30px;font-weight:450;letter-spacing:-.025em;margin:0 0 8px}.view-description{font-size:13px;color:var(--muted);line-height:1.6;margin:0 0 26px}.task{padding:20px 0;border-top:1px solid var(--line)}.task-top{display:flex;justify-content:space-between;gap:10px;font-size:15px}.task-tag{font:10px var(--mono);color:var(--cyan)}.task p{font-size:13px;line-height:1.5;color:var(--muted)}progress{width:100%;height:4px;accent-color:var(--cyan);display:block;margin:14px 0;background:var(--line)}progress::-webkit-progress-bar{background:var(--line)}progress::-webkit-progress-value{background:var(--cyan)}.task button{border:1px solid var(--line);padding:0 14px;border-radius:8px;font-size:13px}.task-detail{font-size:13px;line-height:1.7;color:var(--ink)}.setting{padding:19px 0;border-top:1px solid var(--line)}.setting label,.setting-name{display:block;font-size:14px;margin-bottom:12px}.setting select{width:100%;height:46px;padding:0 12px;background:var(--panel);border:1px solid var(--line);border-radius:8px;color:var(--ink)}.setting input[type=range]{width:100%;min-height:44px;accent-color:var(--cyan)}.setting small{color:var(--muted);font-size:12px;line-height:1.6}.setting-row{display:flex;align-items:center;justify-content:space-between}.setting-row .setting-name{margin:0}.switch{width:52px;position:relative;border:1px solid var(--line);border-radius:24px;height:44px;background:var(--panel)}.switch:before{content:"";display:block;width:20px;height:20px;border-radius:50%;background:var(--muted);margin-left:2px}.switch[aria-checked=true]{background:var(--cyan)}.switch[aria-checked=true]:before{background:var(--petroleum);margin-left:22px}.signout{color:#f1b8a7;border:1px solid #78645e;border-radius:8px;width:100%;margin-top:18px}.feedback{font-size:12px;color:var(--cyan);line-height:1.5;min-height:18px}.sample-caption{font:10px var(--mono);color:var(--muted);margin-top:22px}.session-note{font-size:12px;color:var(--muted);margin:0 0 10px}.account-confirm{margin-top:12px;background:var(--panel);padding:14px;border-radius:8px;font-size:13px;line-height:1.6}.account-confirm button{padding:0 12px;border:1px solid var(--line);border-radius:6px;margin-top:8px}.account-confirm button:first-of-type{color:var(--cyan)}
@media(max-width:980px){.presentation{gap:40px;padding:40px;grid-template-columns:1fr 390px}.intro h1{font-size:52px}}@media(max-width:740px){.presentation{display:flex;flex-direction:column;padding:30px 16px;gap:30px}.intro{max-width:390px;width:100%}.brand{font-size:17px}.direction{margin-top:26px}.intro h1{font-size:44px}.intro>p{font-size:15px;max-width:40ch}.principles{margin:22px 0}.icon-study{display:none}.icon-caption{display:none}.demo-note{margin-top:18px}.phone{max-width:100%;width:390px}.presentation{padding-bottom:30px}}@media(max-width:410px){.presentation{padding-left:8px;padding-right:8px}.phone{border-radius:37px;padding:5px;height:800px}.screen{border-radius:32px}.intro{padding:0 12px}.talk{padding:0 20px}.voice-zone h2{font-size:36px}}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important;animation:none!important}}
</style></head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true"><defs><symbol id="hope-icon" viewBox="0 0 256 256"><rect width="256" height="256" rx="56" fill="#10272d"/><g fill="#9ee3e9"><rect x="66" y="54" width="28" height="148" rx="3"/><rect x="114" y="108" width="28" height="94" rx="3"/><rect x="162" y="88" width="28" height="114" rx="3"/><rect x="80" y="108" width="96" height="26"/></g></symbol><symbol id="mic" viewBox="0 0 24 24"><rect x="9" y="3" width="6" height="12" rx="3"/><path d="M5 10v2a7 7 0 0 0 14 0v-2M12 19v3m-4 0h8"/></symbol></defs></svg>
<main class="presentation">
<aside class="intro"><a href="index.html" style="display:inline-flex;align-items:center;min-height:44px;font-size:14px;text-decoration:none;margin-bottom:18px">← All three directions</a><div class="brand"><svg aria-hidden="true"><use href="#hope-icon"/></svg>hope</div><div class="direction">Design direction / SIGNAL</div><h1>A little space<br>to think<br>out loud.</h1><p>A voice-first companion with the calm precision of an audio instrument. Less to look at. More room to be heard.</p><ul class="principles"><li><span>Petroleum + soft cyan</span><span>Low-light, clear contrast</span></li><li><span>A line with a purpose</span><span>Voice state, not decoration</span></li><li><span>Your words stay close</span><span>A readable conversation</span></li></ul><div class="icon-study"><svg role="img" aria-label="Hope audio bar h icon, large"><use href="#hope-icon"/></svg><svg class="small" role="img" aria-label="Hope icon at 32 pixels"><use href="#hope-icon"/></svg></div><div class="icon-caption">Three audio bars. One unmistakable h.<br>104 px / 32 px · solid, never glowing.</div><p class="demo-note">Interactive design study · Sample data only.<br>No microphone, network, or account access.</p></aside>
<section class="phone" aria-label="Interactive Hope iOS design demo"><div class="screen"><div class="island" aria-hidden="true"></div><div class="statusbar" aria-hidden="true"><span>9:41</span><span class="status-icons"><svg viewBox="0 0 20 14" fill="currentColor"><path d="M1 10h3v4H1zm5-3h3v7H6zm5-3h3v10h-3zm5-3h3v13h-3z"/></svg><svg viewBox="0 0 22 12" fill="none" stroke="currentColor"><rect x="1" y="1" width="17" height="10" rx="2"/><path d="M20 4v4"/><path fill="currentColor" d="M3 3h13v6H3z"/></svg></span></div><header class="app-header"><span class="wordmark">hope</span><span class="sim-label">LOCAL SIMULATION</span></header>
<div class="view" id="talk-view"><div class="talk"><div class="state-line"><span id="state-label" role="status">READY WHEN YOU ARE</span><span id="timer">00:00</span></div><div class="voice-zone"><h2 id="voice-title"><span>Go ahead.</span><span>I’m listening.</span></h2><svg class="wave" viewBox="0 0 320 85" role="img" aria-label="Voice signal: ready"><line x1="0" x2="320" y1="43" y2="43"/><path id="wave-path" d="M0 43 L320 43"/></svg><p class="voice-hint" id="voice-hint">Tap to begin a simulated conversation</p></div><div class="session-controls"><button class="primary" id="start"><svg aria-hidden="true"><use href="#mic"/></svg><span>Start talking</span></button><button class="secondary" id="mute" hidden aria-pressed="false">Mute</button><button class="primary" id="end" hidden>End conversation</button></div><div class="transcript-area"><div class="transcript-header"><p>SAMPLE CONVERSATION</p><div class="mode-toggle" aria-label="Conversation input"><button id="voice-mode" aria-pressed="true">Voice</button><button id="text-mode" aria-pressed="false">Text</button></div></div><div class="messages" id="messages" role="log" aria-label="Conversation transcript" aria-live="polite"><article class="message"><div class="who">YOU <span>09:40</span></div><p>Help me make a little room in my day.</p></article><article class="message answer"><div class="who">HOPE <span>09:40</span></div><p>Let’s start with one thing. What can wait until tomorrow?</p></article></div><form class="composer" id="composer" hidden><input id="text-input" aria-label="Message Hope" placeholder="Think out loud, in text…" maxlength="1200" autocomplete="off"><button type="submit" aria-label="Send message">↑</button></form></div></div></div>
<div class="view inner-view" id="activity-view" hidden><h2>Activity</h2><p class="view-description">A quiet place for the things you’ve asked Hope to work on.</p><article class="task"><div class="task-top"><span>A little room in your day</span><span class="task-tag" id="task-status">READY</span></div><p id="task-description">A sample task. Start a conversation to watch its progress.</p><progress id="task-progress" max="100" value="0" aria-label="Sample task progress"></progress><button id="task-toggle" aria-expanded="false">View steps</button><div class="task-detail" id="task-detail" hidden><p>1. Listen to what needs your attention<br>2. Find one thing that can wait<br>3. Write a simple next step</p></div></article><article class="task"><div class="task-top"><span>Weekend walking ideas</span><span class="task-tag">DONE</span></div><p>Three easy ways to get outside.<br>Yesterday · 4:12 PM · Sample data</p><button id="sample-result" aria-expanded="false">Read result</button><div id="sample-detail" class="task-detail" hidden><p>Take a short park loop, walk to a nearby café, or try a new neighborhood. Pick the easiest one and leave the rest for another day.</p></div></article><p class="sample-caption">Demo tasks only. Nothing is scheduled or saved.</p></div>
<div class="view inner-view" id="settings-view" hidden><h2>Settings</h2><p class="view-description">Make the conversation feel like yours.</p><div class="setting"><label for="voice-choice">Hope’s voice</label><select id="voice-choice"><option>Ava · warm & clear</option><option>Andrew · calm & grounded</option><option>Emma · bright & natural</option></select><button id="preview" class="secondary" style="margin-top:12px;width:100%">Preview voice · simulation</button><p class="feedback" id="voice-feedback" role="status"></p></div><div class="setting"><label for="speed">Speaking pace <span id="speed-label" style="float:right;font-family:var(--mono)">1.0×</span></label><input type="range" id="speed" min="0.8" max="1.2" step="0.1" value="1"><small>Give each thought a little breathing room.</small></div><div class="setting setting-row"><span class="setting-name">Keep transcript visible</span><button id="transcript-switch" class="switch" role="switch" aria-checked="true" aria-label="Keep transcript visible"></button></div><div class="setting"><span class="setting-name">Demo account</span><small>[email protected] · Sample data<br>Settings apply only to this open demo.</small><button class="signout" id="signout">Sign out · simulated</button><div class="account-confirm" id="account-confirm" hidden>Simulate signing out? Your real account is never accessed.<br><button id="confirm-signout">Simulate sign out</button> <button id="cancel-signout">Cancel</button></div><p id="account-feedback" class="feedback" role="status"></p></div></div>
<nav class="nav" aria-label="Main sections"><button data-view="talk" aria-current="page"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 12h2l2-5 3 10 3-13 3 15 2-7h3"/></svg>Talk</button><button data-view="activity"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 5h14M5 12h14M5 19h9"/><circle cx="19" cy="19" r="2"/></svg>Activity</button><button data-view="settings"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h16"/><path d="M8 3v6m8 0v6M10 15v6"/></svg>Settings</button></nav><div class="home-indicator" aria-hidden="true"></div></div></section></main>
<script>
'use strict';
const $=id=>document.getElementById(id);let state='idle',muted=false,seconds=0,timers=[],clock=null,phase=0;const reduced=matchMedia('(prefers-reduced-motion: reduce)').matches;
function clearTimers(){timers.forEach(clearTimeout);timers=[];clearInterval(clock);clock=null;}
function later(fn,delay){timers.push(setTimeout(fn,delay));}
function message(role,text){const article=document.createElement('article');article.className='message'+(role==='HOPE'?' answer':'');const who=document.createElement('div');who.className='who';who.textContent=role+' · DEMO';const p=document.createElement('p');p.textContent=text;article.append(who,p);$('messages').append(article);$('messages').scrollTop=$('messages').scrollHeight;}
function title(a,b){$('voice-title').replaceChildren();[a,b].forEach(text=>{if(text){const span=document.createElement('span');span.textContent=text;$('voice-title').append(span);}});}
function task(value,status,description){$('task-progress').value=value;$('task-status').textContent=status;$('task-description').textContent=description;}
function render(){const active=state!=='idle';$('start').hidden=active;$('mute').hidden=!active;$('end').hidden=!active;$('mute').textContent=muted?'Unmute':'Mute';$('mute').setAttribute('aria-pressed',String(muted));const descriptions={idle:'ready',listening:'listening',working:'working',answer:'answering'};document.querySelector('.wave').setAttribute('aria-label','Voice signal: '+(muted?'muted':descriptions[state]));if(muted){$('state-label').textContent='MICROPHONE MUTED · DEMO';title('Take your time.','I’m here.');$('voice-hint').textContent='Unmute to continue the simulation';}else if(state==='idle'){$('state-label').textContent='READY WHEN YOU ARE';title('Go ahead.','I’m listening.');$('voice-hint').textContent='Tap to begin a simulated conversation';}else if(state==='listening'){$('state-label').textContent='LISTENING · DEMO';title('Go ahead.','I’m listening.');$('voice-hint').textContent='Sample voice input · no microphone access';}else if(state==='working'){$('state-label').textContent='WORKING · DEMO';title('One thought','at a time.');$('voice-hint').textContent='Finding a little room in your day';}else{$('state-label').textContent='HOPE IS SPEAKING · DEMO';title('Make room','for what matters.');$('voice-hint').textContent='Simulated answer · no audio is played';}draw();}
function draw(){let d='';for(let x=0;x<=320;x+=2){const envelope=Math.pow(Math.sin(Math.PI*x/320),4);let y=43;if(state!=='idle'&&!muted){const amp=state==='listening'?23:state==='working'?6:17;y+=Math.sin(x*.18+phase)*Math.sin(x*.035+phase*.4)*envelope*amp;}d+=(x?' L':'M')+x+' '+y.toFixed(2);}$('wave-path').setAttribute('d',d);}
function stages(){later(()=>{if(state!=='listening'||muted)return;message('YOU','Help me make a little room in my day.');state='working';task(45,'WORKING','Finding one thing you can move to tomorrow.');render();later(()=>{if(state!=='working'||muted)return;state='answer';task(100,'DONE','One next step, ready to read in your transcript.');message('HOPE','You don’t have to do it all today. Move one non-urgent task to tomorrow, and keep ten minutes just for yourself.');render();later(()=>{if(state==='answer'&&!muted){state='listening';render();$('voice-hint').textContent='Try text, or end when you’re ready';}},4500);},2300);},3000);}
function start(){clearTimers();muted=false;state='listening';seconds=0;$('timer').textContent='00:00';task(15,'LISTENING','Listening to the sample request.');clock=setInterval(()=>{seconds++;$('timer').textContent=String(Math.floor(seconds/60)).padStart(2,'0')+':'+String(seconds%60).padStart(2,'0');},1000);render();stages();}
$('start').onclick=start;$('end').onclick=()=>{clearTimers();state='idle';muted=false;render();$('state-label').textContent='CONVERSATION ENDED · DEMO';$('voice-hint').textContent='Your sample transcript is still here';};
$('mute').onclick=()=>{muted=!muted;timers.forEach(clearTimeout);timers=[];render();if(!muted){state='listening';render();stages();}};
document.querySelectorAll('[data-view]').forEach(button=>button.onclick=()=>{document.querySelectorAll('[data-view]').forEach(b=>b.removeAttribute('aria-current'));button.setAttribute('aria-current','page');['talk','activity','settings'].forEach(v=>$(v+'-view').hidden=v!==button.dataset.view);});
function mode(text){$('composer').hidden=!text;$('voice-mode').setAttribute('aria-pressed',String(!text));$('text-mode').setAttribute('aria-pressed',String(text));$('messages').hidden=false;if(text)$('text-input').focus();}
$('voice-mode').onclick=()=>mode(false);$('text-mode').onclick=()=>mode(true);
$('composer').onsubmit=event=>{event.preventDefault();const input=$('text-input').value.trim();if(!input)return;message('YOU',input);$('text-input').value='';timers.forEach(clearTimeout);timers=[];state='working';muted=false;task(50,'WORKING','Preparing a local sample reply to your text.');render();later(()=>{state='answer';task(100,'DONE','Sample text reply added to the transcript.');message('HOPE','This is a local sample reply. Take one small next step, and let the rest wait for a moment.');render();later(()=>{clearInterval(clock);clock=null;state='idle';render();},3500);},1500);};
$('task-toggle').onclick=()=>{const show=$('task-detail').hidden;$('task-detail').hidden=!show;$('task-toggle').setAttribute('aria-expanded',String(show));$('task-toggle').textContent=show?'Hide steps':'View steps';};$('sample-result').onclick=()=>{const show=$('sample-detail').hidden;$('sample-detail').hidden=!show;$('sample-result').setAttribute('aria-expanded',String(show));$('sample-result').textContent=show?'Hide result':'Read result';};
$('voice-choice').onchange=()=>{$('voice-feedback').textContent='Demo voice changed to '+$('voice-choice').value.split(' · ')[0]+'.';};$('preview').onclick=()=>{$('voice-feedback').textContent='“Take your time. I’m here.” — '+$('voice-choice').value.split(' · ')[0]+'. Text preview only; no audio is played.';};$('speed').oninput=()=>{$('speed-label').textContent=Number($('speed').value).toFixed(1)+'×';};$('transcript-switch').onclick=()=>{const on=$('transcript-switch').getAttribute('aria-checked')!=='true';$('transcript-switch').setAttribute('aria-checked',String(on));$('messages').hidden=!on;};$('signout').onclick=()=>{$('account-confirm').hidden=false;};$('cancel-signout').onclick=()=>{$('account-confirm').hidden=true;};$('confirm-signout').onclick=()=>{clearTimers();state='idle';muted=false;render();$('account-confirm').hidden=true;$('account-feedback').textContent='Simulated sign out complete. No real account was changed.';};
if(!reduced){setInterval(()=>{if(state!=='idle'&&!muted){phase+=.3;draw();}},90);}render();
</script></body></html>