Spaces:
Running
Running
Juan Jimenez Carrero
feat: voice — talk to Reachy via OpenAI Realtime, wired to the kitchen tools
e6c8aff | :root { | |
| --bg: #f7f7f9; | |
| --surface: #ffffff; | |
| --surface-2: #eef0f4; | |
| --text: #16181d; | |
| --text-dim: #5b6270; | |
| --accent: #2563eb; | |
| --accent-text: #ffffff; | |
| --warn: #b45309; | |
| --warn-bg: #fef3c7; | |
| --danger: #b91c1c; | |
| --danger-bg: #fee2e2; | |
| --ok: #15803d; | |
| --border: #d7dbe2; | |
| --shadow: 0 1px 3px rgba(15, 23, 42, 0.12); | |
| } | |
| [data-theme="dark"] { | |
| --bg: #101216; | |
| --surface: #1a1d23; | |
| --surface-2: #23272f; | |
| --text: #eceef2; | |
| --text-dim: #9aa3b2; | |
| --accent: #3b82f6; | |
| --accent-text: #ffffff; | |
| --warn: #fbbf24; | |
| --warn-bg: #3a2e10; | |
| --danger: #f87171; | |
| --danger-bg: #3b1414; | |
| --ok: #4ade80; | |
| --border: #323844; | |
| --shadow: 0 1px 3px rgba(0, 0, 0, 0.4); | |
| } | |
| * { | |
| box-sizing: border-box; | |
| } | |
| html, | |
| body { | |
| margin: 0; | |
| padding: 0; | |
| height: 100%; | |
| } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; | |
| background: var(--bg); | |
| color: var(--text); | |
| -webkit-font-smoothing: antialiased; | |
| } | |
| #root { | |
| display: flex; | |
| flex-direction: column; | |
| height: 100dvh; | |
| } | |
| .app-main { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px)); | |
| max-width: 640px; | |
| width: 100%; | |
| margin: 0 auto; | |
| } | |
| .app-tabs { | |
| display: flex; | |
| border-top: 1px solid var(--border); | |
| background: var(--surface); | |
| padding-bottom: env(safe-area-inset-bottom, 0px); | |
| } | |
| .app-tabs button { | |
| flex: 1; | |
| min-height: 56px; | |
| border: none; | |
| background: none; | |
| color: var(--text-dim); | |
| font-size: 0.72rem; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.2rem; | |
| cursor: pointer; | |
| padding: 0.4rem 0.2rem; | |
| } | |
| .app-tabs button .tab-icon { | |
| font-size: 1.3rem; | |
| line-height: 1; | |
| } | |
| .app-tabs button.active { | |
| color: var(--accent); | |
| font-weight: 600; | |
| } | |
| h1 { | |
| font-size: 1.3rem; | |
| margin: 0.2rem 0 1rem; | |
| } | |
| h2 { | |
| font-size: 1rem; | |
| margin: 1.4rem 0 0.6rem; | |
| color: var(--text-dim); | |
| text-transform: uppercase; | |
| letter-spacing: 0.04em; | |
| } | |
| .card { | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: 12px; | |
| padding: 0.85rem 1rem; | |
| margin-bottom: 0.6rem; | |
| box-shadow: var(--shadow); | |
| } | |
| .row { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.6rem; | |
| } | |
| .row .grow { | |
| flex: 1; | |
| min-width: 0; | |
| } | |
| .item-title { | |
| font-weight: 600; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .item-sub { | |
| color: var(--text-dim); | |
| font-size: 0.85rem; | |
| margin-top: 0.15rem; | |
| } | |
| .chip { | |
| display: inline-block; | |
| font-size: 0.72rem; | |
| border-radius: 999px; | |
| padding: 0.15rem 0.55rem; | |
| margin-left: 0.4rem; | |
| vertical-align: middle; | |
| } | |
| .chip.warn { | |
| background: var(--warn-bg); | |
| color: var(--warn); | |
| } | |
| .chip.danger { | |
| background: var(--danger-bg); | |
| color: var(--danger); | |
| } | |
| button.btn { | |
| min-height: 44px; | |
| min-width: 44px; | |
| border-radius: 10px; | |
| border: 1px solid var(--border); | |
| background: var(--surface-2); | |
| color: var(--text); | |
| font-size: 0.95rem; | |
| padding: 0 1rem; | |
| cursor: pointer; | |
| } | |
| button.btn.primary { | |
| background: var(--accent); | |
| border-color: var(--accent); | |
| color: var(--accent-text); | |
| font-weight: 600; | |
| } | |
| button.btn.small { | |
| min-height: 44px; | |
| font-size: 0.85rem; | |
| padding: 0 0.7rem; | |
| } | |
| button.btn.block { | |
| width: 100%; | |
| margin: 0.4rem 0; | |
| } | |
| input, | |
| select { | |
| min-height: 44px; | |
| width: 100%; | |
| border-radius: 10px; | |
| border: 1px solid var(--border); | |
| background: var(--surface); | |
| color: var(--text); | |
| font-size: 1rem; | |
| padding: 0 0.75rem; | |
| } | |
| label { | |
| display: block; | |
| font-size: 0.8rem; | |
| color: var(--text-dim); | |
| margin: 0.6rem 0 0.25rem; | |
| } | |
| .form-grid { | |
| display: grid; | |
| grid-template-columns: 2fr 1fr; | |
| gap: 0 0.6rem; | |
| } | |
| .empty { | |
| color: var(--text-dim); | |
| text-align: center; | |
| padding: 2rem 1rem; | |
| } | |
| .day-card .day-name { | |
| font-weight: 700; | |
| margin-bottom: 0.4rem; | |
| } | |
| .meal { | |
| border-top: 1px solid var(--border); | |
| padding: 0.5rem 0; | |
| } | |
| .meal:first-of-type { | |
| border-top: none; | |
| } | |
| .meal .meal-kind { | |
| font-size: 0.75rem; | |
| color: var(--accent); | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| } | |
| .meal .meal-name { | |
| font-weight: 600; | |
| margin: 0.1rem 0; | |
| } | |
| .meal .meal-ing { | |
| color: var(--text-dim); | |
| font-size: 0.85rem; | |
| } | |
| .toast { | |
| position: fixed; | |
| left: 50%; | |
| bottom: calc(76px + env(safe-area-inset-bottom, 0px)); | |
| transform: translateX(-50%); | |
| background: var(--text); | |
| color: var(--bg); | |
| border-radius: 10px; | |
| padding: 0.6rem 1rem; | |
| font-size: 0.9rem; | |
| box-shadow: var(--shadow); | |
| z-index: 10; | |
| max-width: 90vw; | |
| } | |
| .hint { | |
| font-size: 0.82rem; | |
| color: var(--text-dim); | |
| line-height: 1.45; | |
| } | |
| .lang-toggle { | |
| display: flex; | |
| gap: 0.5rem; | |
| } | |
| .lang-toggle button { | |
| flex: 1; | |
| } | |
| .lang-toggle button.active { | |
| background: var(--accent); | |
| color: var(--accent-text); | |
| border-color: var(--accent); | |
| } | |
| .voice-fab { | |
| position: fixed; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| bottom: calc(72px + env(safe-area-inset-bottom, 0px)); | |
| z-index: 9; | |
| min-height: 48px; | |
| padding: 0 1.2rem; | |
| border-radius: 999px; | |
| border: none; | |
| background: var(--accent); | |
| color: var(--accent-text); | |
| font-size: 0.95rem; | |
| font-weight: 600; | |
| box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3); | |
| cursor: pointer; | |
| max-width: 90vw; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .voice-fab.active { | |
| background: var(--danger); | |
| } | |
| .voice-fab.speaking { | |
| background: var(--ok); | |
| animation: voice-pulse 1.1s ease-in-out infinite; | |
| } | |
| @keyframes voice-pulse { | |
| 0%, 100% { box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3); } | |
| 50% { box-shadow: 0 6px 28px rgba(74, 222, 128, 0.7); } | |
| } | |