39 lines
23 KiB
HTML
39 lines
23 KiB
HTML
<!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> |