Spaces:
Running on Zero
Running on Zero
File size: 7,040 Bytes
26dae50 df6b3ac 26dae50 df6b3ac 26dae50 df6b3ac 26dae50 f7a11cd df6b3ac 26dae50 df6b3ac 26dae50 df6b3ac 26dae50 a3f6cbd f7a11cd 26dae50 a3f6cbd df6b3ac 26dae50 df6b3ac 26dae50 df6b3ac a3f6cbd df6b3ac 26dae50 a3f6cbd 26dae50 f8f5696 26dae50 df6b3ac 26dae50 f8f5696 26dae50 df6b3ac 26dae50 df6b3ac 26dae50 f7a11cd df6b3ac 26dae50 df6b3ac f7a11cd df6b3ac a3f6cbd df6b3ac f7a11cd df6b3ac 26dae50 f7a11cd df6b3ac | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | :root {
--bg: #05060a;
--fg: #ffffff;
--muted: rgba(255, 255, 255, .82);
--accent: #ff7a18;
--listen: #00d4ff;
--ok: #36d399;
--glass: rgba(16, 18, 28, .55);
--stroke: rgba(255, 255, 255, .26);
--focus: #ffd166;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
height: 100%;
background: var(--bg);
color: var(--fg);
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
overflow: hidden;
-webkit-tap-highlight-color: transparent;
}
/* focus is ALWAYS visible (keyboard accessibility) */
:focus-visible {
outline: 4px solid var(--focus);
outline-offset: 3px;
border-radius: 14px;
}
#cam {
position: fixed; inset: 0;
width: 100%; height: 100%;
object-fit: cover;
filter: brightness(.42) saturate(1.05);
z-index: 0;
}
/* depth scrims over the camera: bright in the centre, dark at the edges where text/bars sit */
body::before, body::after {
content: ""; position: fixed; left: 0; right: 0; z-index: 1; pointer-events: none;
}
body::before { top: 0; height: 34vh; background: linear-gradient(to bottom, rgba(5,6,10,.80), transparent); }
body::after { bottom: 0; height: 42vh; background: linear-gradient(to top, rgba(5,6,10,.90), transparent); }
/* tappable stage */
#stage {
position: fixed; inset: 0; z-index: 2;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
text-align: center; padding: 8vmin 6vmin 24vmin;
gap: 2.4vmin; cursor: pointer; user-select: none;
}
#halo {
position: absolute; width: 60vmin; height: 60vmin; border-radius: 50%;
background: radial-gradient(circle, rgba(255,122,24,.16), transparent 62%);
transition: transform .25s ease, background .25s ease; pointer-events: none;
}
body[data-state="listening"] #halo { background: radial-gradient(circle, rgba(0,212,255,.34), transparent 60%); animation: pulse 1.1s ease-in-out infinite; }
body[data-state="thinking"] #halo { background: radial-gradient(circle, rgba(255,122,24,.30), transparent 60%); animation: spin 1.4s linear infinite; }
body[data-state="speaking"] #halo { background: radial-gradient(circle, rgba(54,211,153,.30), transparent 60%); animation: breathe 1.9s ease-in-out infinite; }
@keyframes pulse { 0%,100%{transform:scale(1.06)} 50%{transform:scale(1.20)} }
@keyframes spin { to { transform: rotate(360deg) } }
@keyframes breathe { 0%,100%{transform:scale(1.05);opacity:.88} 50%{transform:scale(1.13);opacity:1} }
/* the answer rises in when Iris starts speaking */
body[data-state="speaking"] #answer { animation: rise .42s cubic-bezier(.2,.7,.2,1); }
@keyframes rise { from{opacity:0;transform:translateY(10px)} to{opacity:1;transform:none} }
/* brand mark (the iris): the product identity, shown at idle only */
#brand {
position: relative; z-index: 2; display: flex; justify-content: center;
margin-bottom: 1.4vmin; filter: drop-shadow(0 6px 26px rgba(0,0,0,.6));
}
.iris-mark { width: clamp(76px, 16vmin, 124px); height: auto; display: block; animation: gaze 5.5s ease-in-out infinite; }
@keyframes gaze { 0%,100%{transform:scale(1)} 50%{transform:scale(1.045)} }
body[data-state="listening"] #brand,
body[data-state="thinking"] #brand,
body[data-state="speaking"] #brand { display: none; }
#status {
position: relative; z-index: 2;
font-size: clamp(24px, 6vmin, 48px); font-weight: 800;
text-shadow: 0 2px 18px rgba(0,0,0,.85);
}
/* at idle, "Iris" reads as a wordmark under the mark */
body[data-state=""] #status, body:not([data-state]) #status { letter-spacing: .16em; }
#answer {
position: relative; z-index: 2;
font-size: clamp(20px, 4.6vmin, 34px); font-weight: 600; line-height: 1.32;
max-width: 92vw; min-height: 1.2em; text-shadow: 0 2px 18px rgba(0,0,0,.9);
}
#hint {
position: relative; z-index: 2;
font-size: clamp(13px, 2.8vmin, 18px); color: var(--muted);
text-shadow: 0 2px 12px rgba(0,0,0,.9);
}
/* top bar */
#topbar {
position: fixed; top: max(3vmin, env(safe-area-inset-top, 0)); left: 0; right: 0;
z-index: 4; display: flex; justify-content: space-between; padding: 0 5vmin;
}
.chip {
min-width: 56px; min-height: 56px; padding: 0 18px;
background: var(--glass); color: var(--fg);
border: 2px solid var(--stroke); border-radius: 999px;
font-size: 20px; font-weight: 800; cursor: pointer;
backdrop-filter: blur(10px);
}
.chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #1a1206; }
/* control bar (low vision / keyboard / screen reader) */
#controls {
position: fixed; left: 0; right: 0;
bottom: max(4vmin, env(safe-area-inset-bottom, 0)); z-index: 4;
display: flex; align-items: flex-end; justify-content: center; gap: 4vmin;
}
.ctl {
display: flex; flex-direction: column; align-items: center; gap: 6px;
min-width: 88px; min-height: 88px; padding: 12px 10px;
background: var(--glass); color: var(--fg);
border: 2px solid var(--stroke); border-radius: 24px;
font-size: 16px; font-weight: 700; cursor: pointer;
backdrop-filter: blur(12px); transition: transform .1s ease, background .15s ease;
}
.ctl:active { transform: scale(.95); }
.ctl .ic { display: flex; align-items: center; justify-content: center; }
.ctl .ic svg { width: 28px; height: 28px; display: block; }
.ctl-lbl { font-size: 15px; letter-spacing: .01em; }
.ctl.primary {
min-width: 116px; min-height: 116px; border-radius: 50%;
background: var(--accent); color: #1a1206; border-color: var(--accent);
font-size: 18px; box-shadow: 0 8px 30px rgba(255,122,24,.4);
}
.ctl.primary .ic svg { width: 42px; height: 42px; }
/* idle: the primary button breathes a warm glow to invite the first tap */
body[data-state=""] .ctl.primary { animation: invite 2.6s ease-in-out infinite; }
@keyframes invite { 0%,100%{box-shadow:0 8px 30px rgba(255,122,24,.40)} 50%{box-shadow:0 10px 46px rgba(255,122,24,.66)} }
#btn-live.on { background: var(--ok); border-color: var(--ok); color: #062018; position: relative; }
/* live recording dot, pulsing like a real "on air" light */
#btn-live.on::after {
content: ""; position: absolute; top: 12px; right: 12px;
width: 12px; height: 12px; border-radius: 50%; background: #ff3b30;
box-shadow: 0 0 0 0 rgba(255,59,48,.65); animation: livedot 1.5s ease-out infinite;
}
@keyframes livedot { 0%{box-shadow:0 0 0 0 rgba(255,59,48,.65)} 100%{box-shadow:0 0 0 11px rgba(255,59,48,0)} }
/* ===== accessible mode (max contrast + larger text) ===== */
body.a11y-boost { --glass: rgba(0,0,0,.92); --stroke: #ffffff; }
body.a11y-boost #cam { filter: brightness(.25); }
body.a11y-boost #status { font-size: clamp(30px, 8vmin, 60px); }
body.a11y-boost #answer { font-size: clamp(26px, 6vmin, 44px); font-weight: 800; }
body.a11y-boost .ctl, body.a11y-boost .chip { font-size: 20px; border-width: 3px; color: #fff; }
body.a11y-boost .ctl-lbl { font-weight: 900; }
/* respect the OS preferences */
@media (prefers-contrast: more) { :root { --glass: rgba(0,0,0,.9); --stroke: #fff; } }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }
|