steer-a-robot / style.css
imstevenpmwork's picture
Claude Opus 5.5
feat(ui): starting state in the status bar; show the goal as soon as Steer is pressed
66823ff
Raw History Blame Contribute Delete
14.4 kB
/* LeRobot brand, calm workspace: the logo's orange and yellow, black outlines and hard shadows on a warm
light base. Full treatment in the hero; brand colors as signals elsewhere. Shared by the Space and the
local design preview. */
:root {
--orange: #ff9d00;
--yellow: #ffd21e;
--cream: #fff7e8;
--paper: #ffffff;
--ink: #111111;
--muted: #57534e;
--line: #000000;
--soft-line: #e7dcc7;
--shadow: 4px 4px 0 var(--line);
--shadow-lg: 6px 6px 0 var(--line);
}
body, .dark { background: var(--cream) !important; }
/* Gradio prefixes custom selectors with ".gradio-container ... .contain", so rules for the container itself and
Gradio's .main padding only work at top level, never inside @media: scale them with clamp() instead. */
.gradio-container {
max-width: 1360px !important; margin: 0 auto; padding: clamp(12px, 2.4vw, 28px) clamp(12px, 2.8vw, 40px) 32px !important;
background: var(--cream) !important; color: var(--ink); font-family: 'Source Sans 3', system-ui, sans-serif;
}
.gradio-container .main.fillable { padding-left: clamp(0px, 2.2vw, 32px) !important; padding-right: clamp(0px, 2.2vw, 32px) !important; }
.hero-top, .panel-heading, .skills-heading, .how-footer {
display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.eyebrow {
display: inline-block; padding: 4px 9px; border-radius: 6px; background: var(--line); color: var(--yellow);
font: 500 11px/1.4 'IBM Plex Mono', monospace; letter-spacing: .12em;
}
/* Hero: the logo's world, an orange sticker card, kept compact so the demo comes first: title on the left,
copy and models on the right. */
.hero {
display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); grid-template-areas: "top top" "title copy" "title meta";
column-gap: 36px; align-items: end; margin-bottom: 22px; padding: 18px 26px 22px; border: 3px solid var(--line);
border-radius: 22px; background: var(--orange); box-shadow: var(--shadow-lg); color: var(--ink);
}
.hero-top { grid-area: top; }
.hero h1 { grid-area: title; font-size: clamp(32px, 3.4vw, 48px); line-height: 1.06; letter-spacing: -.03em; font-weight: 900; margin: 14px 0 0; color: var(--ink); }
.marker {
display: inline-block; margin-top: 4px; padding: 0 12px 3px; border: 3px solid var(--line); border-radius: 12px;
background: var(--yellow); box-shadow: var(--shadow); rotate: -1deg;
}
.hero p { grid-area: copy; color: var(--ink); font-size: 16px; font-weight: 600; line-height: 1.5; margin: 0; }
.hero-meta { grid-area: meta; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; font: 500 12px/1.4 'IBM Plex Mono', monospace; }
.hero-meta span { padding: 5px 10px; border: 2px solid var(--line); border-radius: 8px; background: var(--paper); }
.hero-meta b { font-weight: 400; color: var(--muted); margin-left: 4px; }
/* Not .built-with: Gradio's own footer link uses that class. */
.lerobot-link {
display: inline-flex; align-items: center; gap: 10px; padding: 8px 14px; border: 3px solid var(--line); border-radius: 12px;
background: var(--paper); box-shadow: var(--shadow); font-size: 16px; font-weight: 800; color: var(--ink) !important;
text-decoration: none !important; white-space: nowrap; transition: transform .1s, box-shadow .1s, background .15s;
}
.lerobot-link:hover { background: var(--yellow); }
.lerobot-link:active { transform: translate(4px, 4px); box-shadow: none; }
/* Workspace */
#workspace { gap: 30px; align-items: flex-start; }
#scene-panel { gap: 16px; }
#conversation-panel {
gap: 14px; padding: 22px; border: 3px solid var(--line); border-radius: 22px; background: var(--paper); box-shadow: var(--shadow-lg);
}
.panel-heading { min-height: 24px; margin-bottom: 2px; }
.panel-meta { color: var(--muted); font: 12px/1.5 'IBM Plex Mono', monospace; }
h2 { font-size: 24px; font-weight: 800; letter-spacing: -.02em; line-height: 1.25; color: var(--ink); margin: 12px 0 6px; }
.section-copy { color: var(--muted); font-size: 15px; line-height: 1.6; margin: 0; }
#view { padding: 0 !important; border: none !important; background: transparent !important; }
/* Gradio pads every gr.HTML; keep the view and status bar flush with the skill chips. */
#view .html-container, #status-bar .html-container { padding: 0; }
#view .player { position: relative; border-radius: 18px; overflow: hidden; background: #0b1215; border: 3px solid var(--line); box-shadow: var(--shadow-lg); }
#view .screen { display: block; width: 100%; aspect-ratio: 2 / 1; }
#view .tag { position: absolute; top: 12px; left: 12px; padding: 6px 9px; border-radius: 6px; background: var(--line); color: var(--paper); font: 500 10px/1.3 'IBM Plex Mono', monospace; }
#view .tag.wrist { left: calc(50% + 12px); }
#view .tag i { display: inline-block; width: 6px; height: 6px; margin-right: 6px; background: var(--yellow); border-radius: 50%; }
#view .loading { position: absolute; inset: 0; display: grid; place-items: center; color: #e5e5e5; font-size: 15px; }
.block.generating, .generating { border-color: var(--line) !important; box-shadow: none !important; }
/* One fixed-height row above the view: the view below never moves as the status or Stop changes. */
#status-bar {
flex-wrap: nowrap; align-items: center; gap: 12px; min-height: 58px; padding: 8px 10px 8px 14px;
border: 3px solid var(--line); border-radius: 14px; background: var(--paper); box-shadow: var(--shadow);
}
#status-bar > .block { min-width: 0 !important; border: none !important; background: transparent !important; }
.status { position: relative; display: flex; align-items: center; gap: 12px; }
/* Starting (GPU, simulator, policy): the bar itself turns yellow with a moving stripe. Not a fixed popup:
on Spaces the app runs in an iframe as tall as the app, so fixed elements sit off screen. */
#status-bar:has(.status.is-starting) { background: #fff1c2; }
.init-progress { position: absolute; left: 0; right: 0; bottom: -4px; height: 4px; overflow: hidden; border-radius: 2px; background: #0000001a; }
.init-progress::after {
content: ""; position: absolute; top: 0; bottom: 0; left: -30%; width: 30%; border-radius: 2px; background: var(--orange);
animation: init-slide 1.3s ease-in-out infinite;
}
@keyframes init-slide { to { left: 100%; } }
.status-text { flex: 1; min-width: 0; }
.pill {
display: inline-flex; align-items: center; border: 2px solid var(--line); border-radius: 7px; padding: 2px 8px;
font: 500 11px/1.4 'IBM Plex Mono', monospace; color: var(--ink); background: #f1eadc;
}
.pill.running, .pill.steering { background: var(--yellow); }
.pill.waiting, .pill.starting, .pill.planner { background: var(--paper); }
.pill.done { background: var(--line); color: var(--yellow); }
.pill.error { background: #ffd9d2; color: #8a1c00; border-color: #8a1c00; }
.metrics { display: flex; gap: 12px; white-space: nowrap; }
.metric { font: 500 12px/1.4 'IBM Plex Mono', monospace; color: var(--muted); }
.status .instruction, .status .goal { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status .instruction { color: var(--ink); font-size: 17px; font-weight: 700; line-height: 1.35; }
.status .goal { margin-top: 1px; color: var(--muted); font-size: 13px; line-height: 1.5; }
#stop {
flex: none; padding: 7px 14px; color: #b42318; background: var(--paper); border: 3px solid var(--line); border-radius: 10px;
box-shadow: 3px 3px 0 var(--line); font-weight: 800; white-space: nowrap;
}
#stop:hover { background: #fff1ee; }
#stop:active { transform: translate(3px, 3px); box-shadow: none; }
/* Skill library: yellow marks the active skill. */
.skills-heading { margin-top: 14px; }
.skill-count { color: var(--muted); font: 12px/1.5 'IBM Plex Mono', monospace; }
.active-key { padding: 0 5px; border: 2px solid var(--line); border-radius: 5px; background: var(--yellow); color: var(--ink); font-weight: 700; }
#chips { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* Display only (not interactive): flat labels, so only the active skill pops out. */
#chips button, #chips button:disabled {
min-width: 0 !important; width: 100%; min-height: 40px; justify-content: flex-start; text-align: left; padding: 9px 13px;
background: var(--paper); border: 2px solid var(--line); border-radius: 10px; box-shadow: none; opacity: 1 !important;
cursor: default !important; color: var(--ink) !important; font-size: 14px; font-weight: 600; line-height: 1.4; transition: background .15s, box-shadow .15s;
}
#chips button.selected { background: var(--yellow) !important; border-width: 3px; box-shadow: var(--shadow); font-weight: 800; }
/* Conversation */
#goal, #question { border: 3px solid var(--line) !important; border-radius: 14px !important; box-shadow: var(--shadow); }
#goal textarea, #question textarea { font-size: 16px; color: var(--ink); }
#goal button, #question button {
border: 2px solid var(--line) !important; border-radius: 10px !important; background: var(--yellow) !important; color: var(--ink) !important;
box-shadow: 2px 2px 0 var(--line); font-weight: 800;
}
/* Gradio leaves the submit button enabled when the textbox is not interactive. */
#question:has(textarea:disabled) { box-shadow: none; border-style: dashed !important; }
#question:has(textarea:disabled) button { opacity: .4; pointer-events: none; }
#question textarea:disabled { cursor: not-allowed; }
.examples { gap: 8px; }
.examples button {
flex: 0 1 auto !important; min-width: 0 !important; border: 2px solid var(--line) !important; border-radius: 999px; padding: 5px 12px;
background: var(--paper); box-shadow: 2px 2px 0 var(--line); color: var(--ink); font-size: 13px; font-weight: 600;
}
.examples button:hover { background: #fff1c2; }
#chat, #qa-chat { background: #fffbf2 !important; border: 2px solid var(--line) !important; border-radius: 14px; font-size: 15px; }
/* Gradio's bubble is the role container (.message.user / .message.bot), not the inner .message element. */
#chat .message.user, #qa-chat .message.user, #chat .message.bot, #qa-chat .message.bot {
padding: 9px 14px !important; border: 2px solid var(--line) !important; border-radius: 14px !important;
box-shadow: 3px 3px 0 var(--line); color: var(--ink) !important;
}
#chat .message.user, #qa-chat .message.user { background: var(--yellow) !important; }
#chat .message.bot, #qa-chat .message.bot { background: var(--paper) !important; }
#chat .message-buttons, #chat .message-buttons-left, #chat .message-buttons-right,
#qa-chat .message-buttons, #qa-chat .message-buttons-left, #qa-chat .message-buttons-right { display: none !important; }
/* Room for the chat's label and clear button above the first bubble. */
#chat .bubble-wrap, #qa-chat .bubble-wrap { padding-top: 40px !important; }
#chat .placeholder, #qa-chat .placeholder { color: var(--muted); font-size: 15px; line-height: 1.6; padding: 24px; }
#chat label[data-testid="block-label"], #qa-chat label[data-testid="block-label"] { border-radius: 0 0 8px 0; font: 500 12px/1.3 'IBM Plex Mono', monospace; }
.qa-heading { border-top: 2px dashed var(--soft-line); padding-top: 18px; margin-top: 4px; }
.qa-heading h3 { color: var(--ink); font-size: 20px; font-weight: 800; margin: 0 0 4px; }
.conversation-hint { color: var(--muted); font-size: 13px; line-height: 1.5; margin: 0; }
/* The idea behind the demo */
.how { margin-top: 48px; padding: 34px 0 0; border-top: 3px solid var(--line); }
.how .eyebrow { margin-bottom: 4px; }
.how-intro h2 { font-size: 34px; font-weight: 900; line-height: 1.2; margin-top: 14px; }
.how-intro h2 span { color: var(--muted); }
.how-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin: 30px 0; }
.how-grid article { padding: 22px; border: 3px solid var(--line); border-radius: 18px; background: var(--paper); box-shadow: var(--shadow-lg); }
.step-number {
display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: var(--line);
color: var(--yellow); font: 500 14px/1 'IBM Plex Mono', monospace;
}
.how h3 { color: var(--ink); font-size: 20px; font-weight: 800; margin: 14px 0 8px; }
.how p { color: var(--muted); font-size: 15px; line-height: 1.7; margin: 0; }
.how-footer { border-top: 2px dashed var(--soft-line); padding-top: 22px; color: var(--ink); font-size: 15px; font-weight: 700; }
.preview-note { padding: 10px 14px; color: var(--ink); background: var(--paper); border: 2px dashed var(--line); border-radius: 10px; font-size: 14px; line-height: 1.6; margin-bottom: 14px; }
.spinner { display: inline-block; width: 10px; height: 10px; margin-right: 6px; border: 2px solid var(--line); border-right-color: transparent; border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
button:focus-visible, a:focus-visible { outline: 3px solid var(--line) !important; outline-offset: 3px; }
@media (max-width: 850px) {
#workspace { flex-direction: column; }
.hero { grid-template-columns: minmax(0, 1fr); grid-template-areas: "top" "title" "copy" "meta"; }
.hero p { margin-top: 12px; }
#scene-panel, #conversation-panel { min-width: 0 !important; width: 100%; }
.how-grid { gap: 20px; }
}
@media (max-width: 520px) {
:root { --shadow: 3px 3px 0 var(--line); --shadow-lg: 4px 4px 0 var(--line); }
.hero { padding: 16px 16px 18px; border-radius: 18px; }
.hero h1 { font-size: clamp(28px, 8vw, 36px); }
.marker { padding: 0 10px 3px; border-radius: 10px; }
.hero-top { gap: 12px; flex-wrap: wrap; }
.lerobot-link { font-size: 15px; padding: 7px 12px; }
.hero p { font-size: 15px; }
.hero-meta { gap: 8px; font-size: 11px; }
#conversation-panel { padding: 16px; }
.panel-meta { font-size: 10px; }
.panel-heading, .skills-heading { flex-wrap: wrap; gap: 6px 12px; }
.eyebrow { white-space: nowrap; }
#chips { grid-template-columns: 1fr; }
.how-grid { grid-template-columns: 1fr; gap: 20px; }
.how-intro h2 { font-size: 26px; }
.how-footer { align-items: flex-start; flex-direction: column; gap: 12px; }
#status-bar { padding: 8px 8px 8px 12px; }
.status { flex-wrap: wrap; gap: 6px 10px; }
.status-text { order: 1; flex-basis: 100%; }
.status .instruction, .status .goal { white-space: normal; }
#view .tag { top: 7px; left: 7px; font-size: 8px; padding: 4px 6px; }
#view .tag.wrist { left: calc(50% + 7px); }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition: none !important; animation: none !important; }
}