Spaces:
Running
Running
| /* Reachy Blocks — global styles. Desktop-first, fluid to tablet. | |
| Theme via [data-theme="light"|"dark"] on <html> (set by index.html | |
| bootstrap; updated live by the host's onThemeChange). */ | |
| :root { | |
| --bg: #ffffff; | |
| --bg-panel: #f4f6fb; | |
| --text: #1c1e26; | |
| --accent: #4c97ff; | |
| --run: #3fbf5a; | |
| --stop: #e94f4f; | |
| --outline: #d5dae6; | |
| } | |
| :root[data-theme="dark"] { | |
| --bg: #17181d; | |
| --bg-panel: #22242c; | |
| --text: #f0f1f5; | |
| --outline: #33363f; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| } | |
| html, | |
| body { | |
| margin: 0; | |
| height: 100%; | |
| overflow: hidden; | |
| background: var(--bg); | |
| color: var(--text); | |
| font-family: system-ui, -apple-system, "Segoe UI", sans-serif; | |
| } | |
| #root { | |
| height: 100%; | |
| } | |
| /* ── App shell: workspace (left) + stage (right) ─────────────────── */ | |
| .app-shell { | |
| display: flex; | |
| height: 100%; | |
| } | |
| .workspace-pane { | |
| position: relative; | |
| flex: 1; | |
| min-width: 0; | |
| } | |
| .blockly-host { | |
| position: absolute; | |
| inset: 0; | |
| } | |
| /* Transparent shield over the workspace while a program runs: blocks | |
| edits (and multi-touch chaos) but keeps the highlight visible. */ | |
| .run-overlay { | |
| position: absolute; | |
| inset: 0; | |
| z-index: 50; | |
| background: transparent; | |
| } | |
| .stage-pane { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 12px; | |
| width: clamp(260px, 28vw, 380px); | |
| padding: 16px; | |
| background: var(--bg-panel); | |
| border-left: 2px solid var(--outline); | |
| } | |
| .stage-title { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| font-size: 1.15rem; | |
| font-weight: 700; | |
| align-self: flex-start; | |
| } | |
| .puppet-host { | |
| width: 100%; | |
| max-width: 340px; | |
| flex: 1; | |
| display: flex; | |
| align-items: center; | |
| min-height: 0; | |
| } | |
| .run-btn { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 12px; | |
| width: 100%; | |
| max-width: 300px; | |
| min-height: 76px; | |
| border: none; | |
| border-radius: 24px; | |
| background: var(--run); | |
| color: #fff; | |
| font-size: 1.6rem; | |
| font-weight: 800; | |
| font-family: inherit; | |
| cursor: pointer; | |
| box-shadow: 0 4px 0 rgb(0 0 0 / 22%); | |
| transition: transform 80ms ease, background 150ms ease; | |
| touch-action: manipulation; | |
| } | |
| .run-btn:active { | |
| transform: translateY(3px); | |
| box-shadow: 0 1px 0 rgb(0 0 0 / 22%); | |
| } | |
| .run-btn.running { | |
| background: var(--stop); | |
| } | |
| .run-btn-glyph { | |
| font-size: 1.9rem; | |
| line-height: 1; | |
| } | |
| /* Portrait tablets / narrow windows: stage moves on top as a bar. */ | |
| @media (max-width: 900px) { | |
| .app-shell { | |
| flex-direction: column-reverse; | |
| } | |
| .stage-pane { | |
| flex-direction: row; | |
| justify-content: space-between; | |
| width: 100%; | |
| height: clamp(150px, 26vh, 220px); | |
| border-left: none; | |
| border-bottom: 2px solid var(--outline); | |
| } | |
| .stage-title { | |
| display: none; | |
| } | |
| .puppet-host { | |
| height: 100%; | |
| width: auto; | |
| max-width: 40vw; | |
| justify-content: center; | |
| } | |
| /* Height-driven in the top-bar layout so the whole robot stays visible. | |
| (Extra specificity: the base .puppet rule appears later in the file.) */ | |
| .stage-pane .puppet { | |
| width: auto; | |
| height: 100%; | |
| } | |
| .run-btn { | |
| width: auto; | |
| min-width: 150px; | |
| } | |
| } | |
| .puppet { | |
| display: block; | |
| width: 100%; | |
| height: auto; | |
| touch-action: none; | |
| user-select: none; | |
| -webkit-user-select: none; | |
| } | |
| .pp-shadow { fill: rgb(0 0 0 / 14%); } | |
| .pp-body { fill: #e7e9f0; stroke: #b9becf; stroke-width: 2; } | |
| .pp-stripe { fill: var(--accent); } | |
| .pp-head { fill: #f7f8fc; stroke: #b9becf; stroke-width: 2; } | |
| .pp-face { fill: #2b2d36; } | |
| .pp-eye { fill: #fafafa; } | |
| .pp-eye-shine { fill: #ffffff; opacity: 0.9; } | |
| .pp-ant-line { stroke: #9aa0b2; stroke-width: 5; stroke-linecap: round; } | |
| .pp-ant-tip-r { fill: #fbbf24; } | |
| .pp-ant-tip-l { fill: #f472b6; } | |
| .pp-ant-hit { fill: transparent; cursor: pointer; } | |
| :root[data-theme="dark"] .pp-shadow { fill: rgb(0 0 0 / 45%); } | |
| :root[data-theme="dark"] .pp-body { fill: #3a3d49; stroke: #565b6b; } | |
| :root[data-theme="dark"] .pp-head { fill: #464a58; stroke: #565b6b; } | |
| :root[data-theme="dark"] .pp-face { fill: #1b1c22; } | |
| .pp-ant.pp-ant-tapped .pp-ant-tip { | |
| animation: ant-flash 0.5s ease-out; | |
| } | |
| /* Idle blink: on the eye circles only — the pose engine never writes | |
| transforms on these, so CSS animation can't fight it. */ | |
| .pp-eye, | |
| .pp-eye-shine { | |
| transform-box: fill-box; | |
| transform-origin: center; | |
| animation: eye-blink 5.2s infinite; | |
| } | |
| @keyframes eye-blink { | |
| 0%, 94%, 100% { transform: scaleY(1); } | |
| 96%, 98% { transform: scaleY(0.08); } | |
| } | |
| @media (prefers-reduced-motion: reduce) { | |
| .pp-eye, | |
| .pp-eye-shine { | |
| animation: none; | |
| } | |
| } | |
| @keyframes ant-flash { | |
| 0% { filter: brightness(1.9); } | |
| 100% { filter: brightness(1); } | |
| } | |