/* SPDX-FileCopyrightText: 2026 Adaptive Machine Patterns Ltd SPDX-License-Identifier: LicenseRef-AMP-Proprietary The workbench's dark "console" look, from the desktop app's theme. */ :root { --bg: #141821; --panel: #1c2230; --panel-edge: #2a3348; --text: #dfe6f1; --dim: #8b96ab; --accent: #4cc2ff; --accent-dark: #2a86b8; --good: #5ad18f; --warn: #f2b04a; --bad: #ef6a6a; --entry: #10141d; --entry-edge: #3a4560; --btn: #232c40; --btn-edge: #39456a; --pro: #f2b04a; --radius: 8px; color-scheme: dark; } * { box-sizing: border-box; } html, body { margin: 0; } body { background: var(--bg); color: var(--text); font: 14px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; } button, input { font: inherit; color: inherit; } button { background: var(--btn); border: 1px solid var(--btn-edge); border-radius: 6px; padding: 6px 12px; cursor: pointer; } button:hover:not(:disabled) { border-color: var(--accent); } button:disabled { opacity: .45; cursor: default; } button:focus-visible, input:focus-visible, a:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; } a { color: var(--accent); } .ghost { background: transparent; border: 1px solid var(--btn-edge); border-radius: 6px; padding: 5px 12px; text-decoration: none; color: var(--text); } .link { background: none; border: none; padding: 0; color: var(--accent); text-decoration: underline; } .panel { background: var(--panel); border: 1px solid var(--panel-edge); border-radius: var(--radius); } h2 { font-size: 18px; margin: 0 0 8px; } h3 { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--dim); margin: 10px 0 4px; } /* header */ .top { display: flex; align-items: center; gap: 16px; padding: 10px 16px; background: #10141c; border-bottom: 1px solid var(--panel-edge); flex-wrap: wrap; } .brand { display: flex; align-items: center; gap: 10px; } .logo { height: 40px; width: auto; display: block; } /* white artwork: shown as is on the dark header */ .logo.big { height: 72px; margin: 0 auto; } .name { font-weight: 600; } .badge { font-size: 11px; font-weight: 700; border-radius: 4px; padding: 1px 6px; text-transform: uppercase; letter-spacing: .05em; } .badge.demo { background: var(--btn); color: var(--accent); border: 1px solid var(--accent-dark); } .badge.pro { background: #2b3550; color: #b3c3e0; border: 1px solid #44527a; } /* quiet blue-grey, not a sales sticker */ #pro-dialog .badge.pro { background: var(--pro); color: #1a1406; border-color: var(--pro); } /* gold, once, in the card */ .tabs { display: flex; gap: 4px; } .tabs button { background: transparent; border: none; border-bottom: 2px solid transparent; border-radius: 0; padding: 6px 10px; color: var(--dim); } .tabs button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); } .top-actions { margin-left: auto; display: flex; gap: 8px; } main { max-width: 1240px; margin: 0 auto; padding: 12px 16px 24px; } /* robot view */ .robot-grid { display: grid; grid-template-columns: minmax(0, 620px) 240px 170px; justify-content: center; gap: 10px; align-items: start; } .stage { padding: 8px; position: relative; } .cam-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 6px; color: var(--dim); font-size: 12px; } .cam-bar label { display: flex; align-items: center; gap: 6px; } .cam-bar input[type=range] { width: 110px; accent-color: var(--accent); } .modes { display: flex; } .modes button { border-radius: 0; padding: 3px 9px; font-size: 12px; } .modes button:first-child { border-radius: 6px 0 0 6px; } .modes button:last-child { border-radius: 0 6px 6px 0; } .modes button.on { background: var(--accent-dark); border-color: var(--accent); } #main { width: 100%; height: auto; aspect-ratio: 1; display: block; border-radius: 6px; cursor: grab; touch-action: none; background: #0d1018; } #main:active { cursor: grabbing; } .stage-hint { position: absolute; right: 16px; bottom: 14px; font-size: 11px; color: var(--dim); pointer-events: none; } .hints { padding: 4px 10px 10px; max-height: 620px; overflow: auto; } .hint-group { display: flex; flex-direction: column; gap: 3px; } .hint-group button { text-align: left; padding: 4px 8px; font-size: 13px; display: flex; align-items: center; gap: 6px; background: #192032; } .hint-group button svg { flex: none; } .hint-state { font-size: 12px; color: var(--dim); margin: 8px 0 0; min-height: 2.8em; } .hint-state.good { color: var(--good); } .hint-state.bad { color: var(--bad); } .hint-state.warn { color: var(--warn); } .strip { padding: 4px 10px 10px; } .strip figure { margin: 0 0 6px; } .strip figcaption { font-size: 10px; color: var(--dim); letter-spacing: .06em; } .strip canvas { width: 150px; height: 150px; display: block; border-radius: 4px; background: #0d1018; } .command { margin-top: 10px; padding: 10px 12px; } .row { display: flex; align-items: center; gap: 10px; } .row + .row { margin-top: 8px; } .lbl { color: var(--dim); font-size: 12px; } #text { flex: 1; min-width: 0; background: var(--entry); border: 1px solid var(--entry-edge); border-radius: 6px; padding: 8px 10px; font-size: 15px; } #text.invalid { border-color: var(--bad); } .buttons { flex-wrap: wrap; } .play { color: var(--good); font-weight: 600; } .progress { height: 6px; background: var(--entry); border-radius: 3px; overflow: hidden; margin-top: 10px; } .progress > div { height: 100%; width: 0; background: var(--accent); transition: width .1s linear; } .status { color: var(--dim); font-size: 12px; padding: 6px 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; } .log { list-style: none; margin: 0; padding: 0 2px; font-size: 12.5px; max-height: 130px; overflow: auto; } .log li { padding: 1px 0; color: var(--text); } .log li.err { color: var(--bad); } .log li.warn { color: var(--warn); } .log li.dim { color: var(--dim); } /* backend dropdown: a custom list, so Pro models can be struck through */ .backend { position: relative; margin-left: auto; } .backend-btn { min-width: 170px; text-align: left; } .backend ul { position: absolute; right: 0; bottom: calc(100% + 4px); min-width: 250px; margin: 0; padding: 4px; list-style: none; background: var(--panel); border: 1px solid var(--btn-edge); border-radius: 6px; z-index: 10; box-shadow: 0 8px 24px #0008; } .backend li { padding: 7px 10px; border-radius: 4px; cursor: pointer; display: flex; align-items: center; gap: 8px; } .backend li[aria-selected="true"], .backend li:hover { background: var(--btn); } .backend li .note { font-size: 11px; color: var(--dim); display: block; } .locked { text-decoration: line-through; color: var(--dim); } .backend li.pro-item .badge { margin-left: auto; } /* About this project: consulting, then why some features need the desktop app */ .about { margin-top: 18px; padding: 14px 16px 6px; } .about-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 32px; } .about h2 + p + h2 { margin-top: 4px; } .about h2 { font-size: 16px; margin: 0 0 6px; } .about p { margin: 0 0 12px; color: var(--dim); line-height: 1.5; } .about p b { color: inherit; font-weight: 600; } /* bold only: a bright name reads like a heading */ .pro-list-h { margin: 6px 0 4px; padding-top: 12px; border-top: 1px solid var(--panel-edge); } .pro-list { list-style: none; margin: 0 0 10px; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px 24px; } .pro-list li { display: flex; align-items: flex-start; gap: 10px; } .pro-list li > .badge { margin-top: 7px; } .pro-list button { width: 100%; text-align: left; background: transparent; border: none; padding: 5px 0; display: flex; flex-direction: column; gap: 1px; } .pro-list .pro-item-note { color: var(--dim); font-size: 12.5px; } .pro-item-label { color: var(--text); } .pro-list button:hover .pro-item-label { color: var(--accent); } .pro-why { color: var(--dim); font-size: 13px; } .pro-why[hidden] { display: none; } @media (max-width: 900px) { .pro-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (max-width: 700px) { .pro-list, .about-cols { grid-template-columns: minmax(0, 1fr); } } /* the start screen: the download size, before anything downloads */ #gate[hidden], #loading-run[hidden] { display: none; } #gate p { margin: 10px 0; line-height: 1.5; } #gate-start-btn { margin: 8px 0 4px; padding: 10px 22px; font-size: 15px; } .dim { color: var(--dim); } #v-phone-note[hidden] { display: none; } footer { display: flex; flex-wrap: wrap; gap: 16px; justify-content: center; color: var(--dim); font-size: 12px; padding: 16px; border-top: 1px solid var(--panel-edge); } /* loading */ .loading { position: fixed; inset: 0; background: color-mix(in srgb, var(--bg) 94%, transparent); display: grid; place-items: center; z-index: 50; } .loading[hidden] { display: none; } .loading-box { text-align: center; max-width: 360px; padding: 16px; } .loading .progress { width: 100%; } .small { font-size: 12px; color: var(--dim); } dialog { background: var(--panel); color: var(--text); border: 1px solid var(--btn-edge); border-radius: 10px; max-width: min(520px, calc(100vw - 32px)); padding: 20px 22px; } dialog::backdrop { background: #0009; } .dialog-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 16px; } .button.primary { background: var(--accent); color: #06121b; border-radius: 6px; padding: 6px 14px; text-decoration: none; font-weight: 600; } #credits-body { max-height: 60vh; overflow: auto; font-size: 13px; } #credits-body li { margin-bottom: 6px; } /* narrow screens */ @media (max-width: 1080px) { .robot-grid { grid-template-columns: minmax(0, 620px) 170px; } .hints { grid-column: 1 / -1; grid-row: 2; max-height: none; } .hint-group { flex-direction: row; flex-wrap: wrap; } } @media (max-width: 640px) { .robot-grid { grid-template-columns: minmax(0, 1fr); } .strip { display: flex; gap: 6px; align-items: flex-end; } .strip h3 { display: none; } .strip figure { flex: 1; min-width: 0; } .strip canvas { width: 100%; height: auto; aspect-ratio: 1; } .hints { grid-row: auto; } .backend { margin-left: 0; } .backend ul { left: 0; right: auto; } .top-actions { margin-left: 0; } main { padding: 10px 16px 20px; } } #model-progress { margin-top: 6px; min-height: 1em; } #model-progress:empty { display: none; } /* Listen */ .command { position: relative; } #listen { display: inline-flex; align-items: center; gap: 6px; } #listen[hidden] { display: none; } .mic { width: 9px; height: 9px; border-radius: 50%; background: var(--dim); flex: none; } #listen.busy { border-color: var(--accent); animation: breathe 1.2s ease-in-out infinite; } #listen.busy .mic { background: var(--accent); } #listen.on { border-color: var(--bad); color: var(--text); } #listen.on .mic { background: var(--bad); animation: blink 1s ease-in-out infinite; } @keyframes breathe { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 35%, transparent); } } @keyframes blink { 50% { opacity: .25; } } .voice-wrap { position: relative; display: inline-flex; } .listen-pop { position: absolute; left: 0; bottom: calc(100% + 8px); width: max-content; max-width: min(360px, calc(100vw - 32px)); padding: 10px 12px; z-index: 20; box-shadow: 0 8px 24px #0008; animation: rise .18s ease-out; } .listen-pop[hidden] { display: none; } .listen-pop p { margin: 6px 0; } .listen-pop.error { border-color: var(--bad); } .listen-pop.error .progress { display: none; } #listen-bar.indeterminate { width: 35% !important; animation: slide 1.1s ease-in-out infinite; } @keyframes rise { from { opacity: 0; transform: translateY(6px); } } @keyframes slide { from { margin-left: -35%; } to { margin-left: 100%; } } #text.heard { color: var(--dim); font-style: italic; } @media (prefers-reduced-motion: reduce) { #listen.busy, #listen.on .mic, .listen-pop, #listen-bar.indeterminate { animation: none; } } /* Inside the model */ .inside-intro { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; margin: 0 0 10px; } .inside-intro p { margin: 0; flex: 1 1 420px; color: var(--dim); } .inside-intro b { color: var(--text); } select { background: var(--btn); color: var(--text); border: 1px solid var(--btn-edge); border-radius: 6px; padding: 4px 6px; font: inherit; max-width: 100%; } .v-pickers { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; min-width: 0; max-width: 100%; } .v-scene-label { display: flex; align-items: center; gap: 8px; color: var(--dim); font-size: 12px; min-width: 0; max-width: 100%; } .v-scene-label select, .cam-bar label select { min-width: 0; flex: 1 1 auto; width: 100%; } .cam-bar label { min-width: 0; max-width: 100%; } .inside-grid { display: grid; grid-template-columns: minmax(0, 916px) 380px; justify-content: center; gap: 10px; align-items: start; } .v-stage { padding: 8px; } .v-canvas-wrap { position: relative; } #v-main { width: 100%; height: auto; display: block; border-radius: 6px; background: #141821; cursor: grab; touch-action: none; } #v-main:active { cursor: grabbing; } #v-main:focus-visible { outline: 2px solid var(--accent); } .v-side { padding: 0; overflow: hidden; } #v-side { width: 100%; height: auto; display: block; } .v-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-top: 8px; color: var(--dim); font-size: 12px; } .v-bar label, .cam-bar label { display: flex; align-items: center; gap: 6px; } .v-bar input[type=range] { accent-color: var(--accent); } #v-progress { width: 200px; } #v-spread { width: 110px; } .v-caption { min-height: 1.4em; padding: 4px 2px 0; } .small-btn { font-size: 12px; padding: 3px 10px; } .v-keys { position: absolute; top: 8px; left: 8px; background: #0d1119e6; border: 1px solid var(--panel-edge); border-radius: 6px; padding: 6px 10px; font-size: 11px; color: var(--dim); } .v-keys dl { display: grid; grid-template-columns: auto auto; gap: 1px 10px; margin: 4px 0 0; } .v-keys dt { color: var(--text); font-family: ui-monospace, monospace; } .v-keys dd { margin: 0; } .v-keys.folded dl { display: none; } .v-loading { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; background: #141821ee; border-radius: 6px; padding: 16px; } .v-loading[hidden] { display: none; } .v-loading .progress { width: min(320px, 70vw); margin: 0 auto; } .v-pro { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 10px; } .v-pro button { background: transparent; border: none; padding: 2px 0; display: flex; align-items: center; gap: 8px; } .v-pro button:hover .locked { color: var(--text); } @media (max-width: 1080px) { .inside-grid { grid-template-columns: minmax(0, 1fr); } .v-side { max-width: 380px; } } @media (max-width: 640px) { .v-keys { display: none; } #v-progress { width: 140px; } } /* Glow shows: a list with a note on each choice; Pro choices desaturated */ .glow-pick { position: relative; display: flex; align-items: center; gap: 6px; min-width: 0; color: var(--dim); font-size: 12px; } .glow-btn { font-size: 13px; padding: 3px 10px; max-width: 100%; text-align: left; } .glow-pick ul { position: absolute; left: 0; top: calc(100% + 4px); width: min(380px, 86vw); margin: 0; padding: 4px; list-style: none; background: var(--panel); border: 1px solid var(--btn-edge); border-radius: 6px; z-index: 15; box-shadow: 0 8px 24px #0008; } .glow-pick li { padding: 7px 10px; border-radius: 4px; cursor: pointer; display: flex; gap: 8px; align-items: flex-start; color: var(--text); font-size: 13px; } .glow-pick li[aria-selected="true"], .glow-pick li:hover, .glow-pick li:focus { background: var(--btn); outline: none; } .glow-pick li .note { display: block; font-size: 11.5px; color: var(--dim); margin-top: 2px; line-height: 1.35; } .glow-pick li.pro-item > span:first-child { opacity: .5; } .glow-pick li.pro-item:hover > span:first-child, .glow-pick li.pro-item:focus > span:first-child { opacity: .75; } .glow-pick li.pro-item .badge { margin-left: auto; } /* buttons that belong together sit joined: Play|Stop, Reset|New scene, Read|Listen */ .btn-group { display: inline-flex; } .btn-group > button { border-radius: 0; } .btn-group > button + button { margin-left: -1px; } .btn-group > button:first-child { border-radius: 6px 0 0 6px; } .btn-group > button:last-child, .btn-group > button:has(+ [hidden]) { border-radius: 0 6px 6px 0; } .btn-group > button:only-child, .btn-group > button:first-child:has(+ [hidden]) { border-radius: 6px; } .btn-group > button:hover:not(:disabled), .btn-group > button:focus-visible { position: relative; z-index: 1; } #say { display: inline-flex; align-items: center; gap: 6px; } .speaker { flex: none; } /* the live Listen pop-up: meter beside the status and the talk button */ #listen-live { display: flex; align-items: center; gap: 14px; } #listen-live[hidden] { display: none; } #listen-setup[hidden] { display: none; } #listen-setup { width: min(320px, calc(100vw - 56px)); } .listen-side { display: flex; flex-direction: column; gap: 8px; width: 34ch; } /* as wide as the longest message, so it never resizes */ .listen-buttons { display: flex; gap: 6px; } .listen-status { font: 11px/1.3 ui-monospace, "DejaVu Sans Mono", monospace; color: var(--dim); letter-spacing: .04em; white-space: pre; overflow: hidden; text-overflow: ellipsis; } .listen-status.rec { color: var(--bad); } .listen-hold { flex: 1; font-size: 13px; font-weight: 600; padding: 9px 12px; user-select: none; touch-action: none; } .listen-clear { font-size: 12px; padding: 9px 10px; color: var(--dim); } .listen-hold.on { background: var(--bad); border-color: var(--bad); color: var(--bg); } #listen.open { background: #dfe6f1; border-color: #dfe6f1; color: #141821; } /* light while the pop-up is open: press to close it */ #listen.open .mic { background: #5d6578; } #listen.open.on { background: var(--bad); border-color: var(--bad); } /* the tour's End tour button, beside Previous / Next */ .driver-popover .tour-end { background: transparent; border: 1px solid #c8ced8; color: #5d6578; border-radius: 3px; padding: 3px 8px; font-size: 12px; margin-right: auto; text-shadow: none; } .glow-pick ul.right { left: auto; right: 0; } /* Inside the model: a Pro model's block render, as a preview */ .v-preview { position: absolute; inset: 0; background: #141821; border-radius: 6px; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; overflow: auto; } .v-preview[hidden] { display: none; } .v-preview img { max-width: 100%; max-height: calc(100% - 150px); object-fit: contain; flex: 1 1 auto; min-height: 0; } .v-preview-tag { position: absolute; top: 10px; right: 10px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--pro); border: 1px solid var(--pro); border-radius: 4px; padding: 2px 8px; background: #141821cc; } .v-preview-text { width: 100%; padding: 8px 14px 12px; border-top: 1px solid var(--panel-edge); background: var(--panel); } .v-preview-text p { margin: 4px 0 8px; color: var(--dim); font-size: 13px; } .v-preview-actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; } .v-side { position: relative; } .v-side-note { display: none; position: absolute; inset: 0; padding: 14px 16px; overflow: auto; color: var(--text); font-size: 13px; } .previewing .v-side-note { display: block; } .v-side-note h3 { margin: 0 0 4px; font-size: 16px; text-transform: none; letter-spacing: normal; color: var(--text); } /* a phone: the stage is too short to hold the preview, so it goes in the page at full width */ @media (max-width: 700px) { .previewing #v-main { display: none; } .v-preview { position: static; overflow: visible; } .v-preview img { width: 100%; max-height: none; height: auto; } .v-preview-tag { top: 6px; right: 6px; } } .v-side-note h4 { margin: 14px 0 6px; font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--dim); } .v-side-note .dim { color: var(--dim); margin: 0; } .v-legend { list-style: none; margin: 0; padding: 0; } .v-legend li { display: flex; align-items: center; gap: 8px; margin: 3px 0; } .v-legend i { flex: none; width: 12px; height: 12px; border-radius: 2px; } .v-side-pro { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--panel-edge); color: var(--dim); line-height: 1.5; } .previewing #v-side { visibility: hidden; } .previewing .v-stage .cam-bar, .previewing .v-bar, .previewing .v-caption, .previewing .v-scene-label { opacity: .3; pointer-events: none; } /* ── phones: the arm stays in view; under it the instruction, the hint chips and Play, in that order (the command panel's parts are laid out one by one) ── */ .phone .top { gap: 6px 12px; padding: 8px 12px; } .phone .logo { height: 30px; } .phone .name { font-size: 13px; } .phone .tabs button { padding: 4px 8px; } .phone .top-actions { margin-left: auto; gap: 6px; } .phone .top-actions > * { padding: 4px 10px; } .phone main { padding: 8px 10px 20px; } .phone #view-robot:not([hidden]) { display: flex; flex-direction: column; gap: 8px; } .phone .robot-grid, .phone .command { display: contents; } .phone .stage { order: 1; position: sticky; top: 0; z-index: 5; padding: 6px; box-shadow: 0 6px 12px var(--bg); } .phone .command .row:not(.buttons) { order: 2; } .phone .hints { order: 3; padding: 2px 10px 8px; } .phone .command .buttons { order: 4; } .phone .command .progress { order: 5; margin-top: 0; } .phone #model-progress { order: 5; } .phone .status { order: 6; padding: 0 2px; } .phone .strip { order: 7; } .phone .log { order: 8; } .phone #main { width: auto; max-width: 100%; height: min(36dvh, calc(100vw - 34px)); margin: 0 auto; transition: height .15s; } .phone #view-robot:has(#text:focus) #main { height: 20dvh; } /* typing: the keyboard needs the room */ .phone .cam-bar { margin-bottom: 4px; } .phone .cam-bar label, .phone .stage-hint { display: none; } /* az / el: drag the view instead */ .phone .command .lbl { display: none; } .phone #text { font-size: 16px; padding: 10px; } /* 16px: phones don't zoom in on it */ .phone .buttons { gap: 6px; } .phone .buttons button { padding: 8px 12px; } .phone .backend { margin-left: 0; } .phone .backend-btn { min-width: 0; } .phone .backend ul { left: 0; right: auto; width: min(320px, calc(100vw - 40px)); top: calc(100% + 4px); bottom: auto; } .phone .hints h3 { margin: 6px 0 3px; } .phone .hint-group { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; gap: 5px; padding-bottom: 2px; scrollbar-width: none; } .phone .hint-group button { flex: none; padding: 6px 10px; } .phone .hint-state { min-height: 0; margin-top: 4px; } .phone .inside-intro p { font-size: 13px; } .phone .v-bar { gap: 8px 12px; } .phone .v-bar #v-play { padding: 8px 16px; } .about-link { white-space: nowrap; } .phone .tabs button, .phone .top-actions > * { font-size: 13px; } .phone .tabs { gap: 0; } .phone .top-actions > * { padding: 4px 8px; }