Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>Third Eye — Aqua-Tech Design Preview</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:ital,wght@0,400;0,700;1,400&family=Sora:wght@400;500;600;700;800&display=swap" rel="stylesheet"> | |
| <style> | |
| /* ---------- Tokens: LIGHT default, .dark overrides ---------- */ | |
| :root { | |
| color-scheme: light; | |
| --bg-0:#e9f1f7; | |
| --aurora-1:rgba(6,182,212,.20); --aurora-2:rgba(56,189,248,.18); --aurora-3:rgba(37,99,235,.12); | |
| --text:#0b2230; --text-strong:#051722; --muted:#45647a; --faint:#7e98ab; | |
| --accent:#0891b2; --accent-2:#2563eb; --accent-glow:rgba(8,145,178,.35); --accent-ink:#fff; | |
| --glass-bg:linear-gradient(158deg,rgba(255,255,255,.88),rgba(229,244,251,.64)); | |
| --glass-border:rgba(12,110,140,.16); --glass-border-strong:rgba(8,145,178,.55); | |
| --glass-shadow:0 22px 54px rgba(12,74,110,.14); --glass-highlight:rgba(255,255,255,.9); | |
| --field-bg:rgba(255,255,255,.92); --field-border:rgba(12,90,120,.16); --ring:rgba(8,145,178,.85); | |
| --radius:24px; --radius-md:18px; --radius-sm:13px; | |
| --display:"Sora",system-ui,sans-serif; --body:"Atkinson Hyperlegible",system-ui,sans-serif; | |
| } | |
| .dark { | |
| color-scheme: dark; | |
| --bg-0:#060a13; | |
| --aurora-1:rgba(34,211,238,.20); --aurora-2:rgba(56,189,248,.16); --aurora-3:rgba(99,102,241,.16); | |
| --text:#e7f1fa; --text-strong:#fff; --muted:#93a8c0; --faint:#62748f; | |
| --accent:#22d3ee; --accent-2:#5b8cff; --accent-glow:rgba(34,211,238,.40); --accent-ink:#04121a; | |
| --glass-bg:linear-gradient(158deg,rgba(22,32,52,.78),rgba(9,14,27,.6)); | |
| --glass-border:rgba(120,190,230,.16); --glass-border-strong:rgba(34,211,238,.5); | |
| --glass-shadow:0 24px 60px rgba(0,0,0,.5); --glass-highlight:rgba(255,255,255,.07); | |
| --field-bg:rgba(9,15,28,.66); --field-border:rgba(120,190,230,.16); --ring:rgba(34,211,238,.9); | |
| } | |
| * { box-sizing:border-box; } | |
| html { background:var(--bg-0); } | |
| body { | |
| margin:0; min-height:100vh; color:var(--text); font-family:var(--body); font-size:18px; | |
| position:relative; overflow-x:hidden; padding:clamp(1rem,3vw,2.6rem); | |
| } | |
| body::before { | |
| content:""; position:fixed; inset:-15%; z-index:0; pointer-events:none; | |
| background: | |
| radial-gradient(38% 40% at 16% 18%,var(--aurora-1),transparent 70%), | |
| radial-gradient(44% 44% at 88% 12%,var(--aurora-2),transparent 70%), | |
| radial-gradient(52% 52% at 62% 96%,var(--aurora-3),transparent 70%); | |
| filter:blur(26px); animation:drift 30s ease-in-out infinite alternate; | |
| } | |
| body::after { | |
| content:""; position:fixed; inset:0; z-index:0; pointer-events:none; opacity:.5; | |
| background-image:linear-gradient(to right,var(--glass-border) 1px,transparent 1px), | |
| linear-gradient(to bottom,var(--glass-border) 1px,transparent 1px); | |
| background-size:64px 64px; | |
| -webkit-mask-image:radial-gradient(circle at 50% 28%,#000,transparent 78%); | |
| mask-image:radial-gradient(circle at 50% 28%,#000,transparent 78%); | |
| } | |
| .wrap { position:relative; z-index:1; max-width:1200px; margin:0 auto; } | |
| /* ---------- Header ---------- */ | |
| .header { display:flex; align-items:center; gap:16px; margin-bottom:1rem; flex-wrap:wrap; animation:rise .6s ease both; } | |
| .brand { display:flex; align-items:center; gap:15px; flex:1 1 auto; } | |
| .iris-sm { | |
| position:relative; display:grid; place-items:center; width:48px; height:48px; flex:none; | |
| border:1.5px solid var(--glass-border-strong); border-radius:50%; | |
| background:radial-gradient(circle at 46% 40%,#fff 0 6%,var(--accent) 7% 26%,var(--accent-2) 52%,#0a2540 86%); | |
| box-shadow:0 0 22px var(--accent-glow), inset 0 0 12px rgba(0,0,0,.25); | |
| } | |
| .iris-sm i { width:11px; height:11px; border-radius:50%; background:#fff; box-shadow:0 0 12px var(--accent),0 0 4px #fff; } | |
| .brand h1 { margin:0; font-family:var(--display); font-size:1.85rem; font-weight:800; letter-spacing:-.04em; color:var(--text-strong); } | |
| .brand p { margin:4px 0 0; font-size:.9rem; color:var(--muted); } | |
| .pill { | |
| display:inline-flex; align-items:center; gap:8px; border-radius:999px; padding:10px 16px; | |
| border:1px solid var(--glass-border); background:var(--glass-bg); color:var(--text); | |
| font-family:var(--display); font-weight:600; font-size:.9rem; cursor:pointer; backdrop-filter:blur(12px); | |
| transition:border-color .15s, box-shadow .15s; | |
| } | |
| .pill:hover { border-color:var(--glass-border-strong); box-shadow:0 0 20px var(--accent-glow); } | |
| /* ---------- Mode cards ---------- */ | |
| .modes { display:grid; grid-template-columns:repeat(3,1fr); gap:14px; margin-bottom:1.2rem; animation:rise .6s ease .08s both; } | |
| .mode { | |
| position:relative; display:flex; flex-direction:column; gap:5px; min-height:94px; | |
| padding:18px 18px 18px 64px; border:1px solid var(--glass-border); border-radius:var(--radius-md); | |
| background:var(--glass-bg); box-shadow:var(--glass-shadow), inset 0 1px 0 var(--glass-highlight); | |
| backdrop-filter:blur(16px) saturate(1.25); cursor:pointer; overflow:hidden; | |
| transition:transform .16s, border-color .16s, box-shadow .16s; | |
| } | |
| .mode::before { content:""; position:absolute; left:0; top:0; bottom:0; width:3px; | |
| background:linear-gradient(var(--accent),var(--accent-2)); opacity:0; transition:opacity .16s; } | |
| .mode:hover { transform:translateY(-3px); border-color:var(--glass-border-strong); } | |
| .mode .ic { position:absolute; left:20px; top:19px; width:28px; height:28px; background:var(--accent); | |
| -webkit-mask:var(--ic) center/contain no-repeat; mask:var(--ic) center/contain no-repeat; } | |
| .mode h3 { margin:0; font-family:var(--display); font-size:1.08rem; font-weight:700; letter-spacing:-.01em; color:var(--text-strong); } | |
| .mode p { margin:0; font-size:.82rem; color:var(--muted); line-height:1.42; } | |
| .mode.active { border-color:var(--glass-border-strong); | |
| box-shadow:0 0 0 1.5px var(--accent), var(--glass-shadow), 0 0 32px var(--accent-glow); } | |
| .mode.active::before { opacity:1; } | |
| .mode.active .ic { filter:drop-shadow(0 0 7px var(--accent-glow)); } | |
| /* ---------- Work area ---------- */ | |
| .work { display:grid; grid-template-columns:1fr 1fr; gap:16px; align-items:stretch; animation:rise .6s ease .16s both; } | |
| .card { border:1px solid var(--glass-border); border-radius:var(--radius); background:var(--glass-bg); | |
| box-shadow:var(--glass-shadow), inset 0 1px 0 var(--glass-highlight); backdrop-filter:blur(20px) saturate(1.3); padding:22px; } | |
| .card-head { display:flex; align-items:baseline; justify-content:space-between; margin-bottom:16px; } | |
| .card-title { font-family:var(--display); font-size:.72rem; font-weight:700; letter-spacing:.22em; color:var(--accent); } | |
| .card-hint { font-size:.78rem; color:var(--faint); } | |
| .frame { border-radius:var(--radius-md); aspect-ratio:4/3; display:grid; place-items:center; position:relative; | |
| border:1px solid var(--glass-border); color:var(--faint); overflow:hidden; | |
| background:radial-gradient(120% 90% at 50% 0%, rgba(8,145,178,.10), transparent 60%), var(--field-bg); } | |
| .frame .ph { text-align:center; } .frame svg { width:42px; height:42px; opacity:.6; } | |
| .frame .ph span { display:block; margin-top:8px; font-size:.85rem; } | |
| .frame .badge { position:absolute; left:12px; top:12px; font-size:.7rem; font-weight:600; color:var(--accent); | |
| background:var(--glass-bg); border:1px solid var(--glass-border); border-radius:999px; padding:5px 11px; backdrop-filter:blur(8px); } | |
| .examples { display:flex; gap:10px; margin-top:14px; } | |
| .ex { flex:1; aspect-ratio:1; border-radius:11px; border:1px solid var(--glass-border); background:var(--field-bg); | |
| display:grid; place-items:center; color:var(--faint); font-size:.72rem; cursor:pointer; transition:border-color .12s, transform .12s; } | |
| .ex:hover { border-color:var(--accent); transform:translateY(-2px); } | |
| .ex-label { font-family:var(--display); font-size:.72rem; font-weight:700; letter-spacing:.1em; color:var(--muted); margin:18px 0 8px; } | |
| .voice { margin-top:16px; display:none; } | |
| .voice.show { display:block; } | |
| .voice .rec { display:flex; align-items:center; gap:12px; background:var(--field-bg); border:1px solid var(--field-border); | |
| border-radius:999px; padding:10px 16px; } | |
| .voice .dot { width:30px; height:30px; border-radius:50%; background:var(--accent); display:grid; place-items:center; flex:none; } | |
| .voice .dot::after { content:""; width:11px; height:11px; border-radius:50%; background:#fff; } | |
| .voice .rectxt { font-size:.9rem; color:var(--muted); } | |
| .voice input { margin-top:10px; width:100%; padding:11px 14px; border-radius:12px; border:1px solid var(--field-border); | |
| background:var(--field-bg); color:var(--text); font-family:var(--body); font-size:.92rem; } | |
| .cta { margin-top:18px; width:100%; min-height:72px; border:none; border-radius:999px; cursor:pointer; | |
| background:linear-gradient(120deg,var(--accent),var(--accent-2)); color:var(--accent-ink); | |
| font-family:var(--display); font-size:1.12rem; font-weight:700; | |
| box-shadow:0 14px 32px var(--accent-glow), 0 2px 0 rgba(255,255,255,.25) inset; | |
| transition:transform .14s, filter .14s, box-shadow .14s; display:flex; align-items:center; justify-content:center; gap:10px; } | |
| .cta:hover { transform:translateY(-2px); filter:brightness(1.05); box-shadow:0 18px 40px var(--accent-glow); } | |
| .cta svg { width:20px; height:20px; } | |
| /* iris orb (answer) */ | |
| .iris-stage { display:grid; justify-items:center; gap:.9rem; padding:.2rem 0 1.2rem; } | |
| .iris { position:relative; display:grid; width:116px; height:116px; place-items:center; overflow:hidden; | |
| border:2px solid var(--glass-border-strong); border-radius:50%; | |
| background:radial-gradient(circle at 47% 42%,#fff 0 4%,var(--accent) 5% 12%,var(--accent-2) 30%,#0a2540 60%,#04111c 82%); | |
| box-shadow:0 0 18px var(--accent-glow), 0 0 46px var(--aurora-2), inset 0 0 24px rgba(0,0,0,.3); | |
| animation:breathe 4s ease-in-out infinite; } | |
| .iris::before, .iris::after { position:absolute; border:1px solid var(--glass-border-strong); border-radius:50%; content:""; inset:14%; opacity:.5; } | |
| .iris::after { border-style:dashed; inset:27%; } | |
| .iris i { width:20px; height:20px; border-radius:50%; background:#fff; box-shadow:0 0 18px var(--accent),0 0 6px #fff; } | |
| .state { margin:0; font-family:var(--display); font-size:.78rem; font-weight:700; letter-spacing:.18em; text-transform:uppercase; color:var(--text-strong); } | |
| .flabel { font-family:var(--display); font-size:.7rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--muted); margin:18px 0 7px; } | |
| .qbox { background:var(--field-bg); border:1px solid var(--field-border); border-radius:12px; padding:12px 15px; font-size:.95rem; color:var(--accent); font-weight:700; } | |
| .answer { background:var(--field-bg); border:1px solid var(--field-border); border-radius:12px; padding:16px 18px; | |
| font-size:1.2rem; line-height:1.7; color:var(--text-strong); min-height:130px; } | |
| .answer b { color:var(--accent); } | |
| .audio { margin-top:14px; display:flex; align-items:center; gap:12px; background:var(--field-bg); border:1px solid var(--field-border); border-radius:999px; padding:9px 15px; } | |
| .audio .play { width:34px; height:34px; border-radius:50%; background:linear-gradient(120deg,var(--accent),var(--accent-2)); color:var(--accent-ink); display:grid; place-items:center; flex:none; } | |
| .audio .play svg { width:14px; height:14px; } | |
| .audio .bar { flex:1; height:4px; border-radius:2px; background:var(--glass-border); position:relative; } | |
| .audio .bar::after { content:""; position:absolute; left:0; top:0; bottom:0; width:42%; background:linear-gradient(90deg,var(--accent),var(--accent-2)); border-radius:2px; } | |
| .audio .t { font-size:.78rem; color:var(--muted); font-variant-numeric:tabular-nums; } | |
| .foot { text-align:center; margin-top:2rem; font-family:var(--display); font-size:.76rem; letter-spacing:.06em; color:var(--faint); } | |
| .foot .priv { color:var(--accent); font-weight:600; } | |
| .tag { text-align:center; font-size:.72rem; color:var(--faint); margin-top:.6rem; } | |
| @media (max-width:820px){ .modes{grid-template-columns:1fr;} .work{grid-template-columns:1fr;} } | |
| @keyframes rise { from{opacity:0; transform:translateY(12px);} to{opacity:1; transform:none;} } | |
| @keyframes drift { to{ transform:translate3d(3%,2%,0) rotate(4deg) scale(1.08);} } | |
| @keyframes breathe { 50%{ transform:scale(1.04); box-shadow:0 0 24px var(--accent-glow), 0 0 60px var(--aurora-2);} } | |
| @media (prefers-reduced-motion: reduce){ *{animation-duration:.001ms;} } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="wrap"> | |
| <!-- Header --> | |
| <div class="header"> | |
| <div class="brand"> | |
| <div class="iris-sm"><i></i></div> | |
| <div> | |
| <h1>Third Eye</h1> | |
| <p>Point your camera. Ask out loud. Listen to the answer.</p> | |
| </div> | |
| </div> | |
| <div class="pill" role="button">🌐 English ▾</div> | |
| <div class="pill" id="themeBtn" role="button">◐ Theme</div> | |
| </div> | |
| <!-- Mode cards --> | |
| <div class="modes" id="modes"> | |
| <div class="mode active" data-mode="Describe"> | |
| <span class="ic" style="--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");"></span> | |
| <h3>Describe</h3><p>Tell me everything in the scene.</p> | |
| </div> | |
| <div class="mode" data-mode="Ask"> | |
| <span class="ic" style="--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z'/%3E%3Cpath d='M19 10v2a7 7 0 0 1-14 0v-2'/%3E%3Cline x1='12' y1='19' x2='12' y2='23'/%3E%3C/svg%3E");"></span> | |
| <h3>Ask</h3><p>Speak a question about what I see.</p> | |
| </div> | |
| <div class="mode" data-mode="Read Text"> | |
| <span class="ic" style="--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3C/svg%3E");"></span> | |
| <h3>Read Text</h3><p>Read labels, menus, and signs aloud.</p> | |
| </div> | |
| </div> | |
| <!-- Work area --> | |
| <div class="work"> | |
| <!-- Capture --> | |
| <div class="card"> | |
| <div class="card-head"><span class="card-title">CAPTURE</span><span class="card-hint">Camera or upload</span></div> | |
| <div class="frame"> | |
| <span class="badge">● Live camera</span> | |
| <div class="ph"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg> | |
| <span>Point your camera, or upload a photo</span> | |
| </div> | |
| </div> | |
| <div class="ex-label">OR TRY AN EXAMPLE</div> | |
| <div class="examples"><div class="ex">Menu</div><div class="ex">Label</div><div class="ex">Sign</div></div> | |
| <div class="voice" id="voice"> | |
| <div class="rec"><span class="dot"></span><span class="rectxt">Tap to record your question…</span></div> | |
| <input placeholder="Optional: type only if the microphone is unavailable." /> | |
| </div> | |
| <button class="cta" id="cta"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z"/><circle cx="12" cy="12" r="3"/></svg> | |
| <span id="ctaLabel">Describe what I see</span> | |
| </button> | |
| </div> | |
| <!-- Answer --> | |
| <div class="card"> | |
| <div class="card-head"><span class="card-title">ANSWER</span></div> | |
| <div class="iris-stage"> | |
| <div class="iris"><i></i></div> | |
| <p class="state">Speaking</p> | |
| </div> | |
| <div class="flabel">You asked</div> | |
| <div class="qbox">Describe this image for a blind person, including any text.</div> | |
| <div class="flabel">Answer</div> | |
| <div class="answer">A medicine label on a white box. The brand reads <b>“Paracetamol 500 mg”</b>. Below it: “Take one tablet every 6 hours. Do not exceed 8 tablets in 24 hours.” The expiry date is <b>09 / 2027</b>.</div> | |
| <div class="audio"> | |
| <div class="play"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg></div> | |
| <div class="bar"></div><div class="t">0:06 / 0:14</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="foot"> | |
| Vision & OCR by Qwen2.5-VL · Speech by Cohere Transcribe · Voice by VoxCPM2. | |
| <span class="priv">Your image is processed only for your request and never stored.</span> | |
| </div> | |
| <div class="tag">Static design preview — interactive (try the mode cards & theme toggle). The live app runs in Gradio.</div> | |
| </div> | |
| <script> | |
| // Theme toggle | |
| document.getElementById('themeBtn').addEventListener('click', () => { | |
| document.documentElement.classList.toggle('dark'); | |
| }); | |
| // Mode switching | |
| const labels = { "Describe":"Describe what I see", "Ask":"Ask Third Eye", "Read Text":"Read this text" }; | |
| document.querySelectorAll('.mode').forEach(card => { | |
| card.addEventListener('click', () => { | |
| document.querySelectorAll('.mode').forEach(c => c.classList.remove('active')); | |
| card.classList.add('active'); | |
| const m = card.dataset.mode; | |
| document.getElementById('ctaLabel').textContent = labels[m]; | |
| document.getElementById('voice').classList.toggle('show', m === 'Ask'); | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |