diff --git a/web/README.md b/web/README.md index 060d046..a385f3d 100644 --- a/web/README.md +++ b/web/README.md @@ -1,12 +1,12 @@ -# Adaptive Agent Lab dashboard +# Adaptive Agent Lab interactive research artifact -This vinext application replays warehouse trajectories and compares operational -metrics for the six Adaptive Agent Lab treatments. It reads +This vinext application presents an academic-style replay of warehouse +trajectories and descriptive metrics for the six Adaptive Agent Lab treatments. It reads `public/demo-data.json`, which is generated from real simulator transitions by the Python package. The bundled data is a **non-confirmatory demonstration**. Learners receive small -convenience training budgets on the displayed scenario, so the dashboard is +convenience training budgets on the displayed scenario, so the artifact is useful for inspecting behavior and testing the replay UI—not for claiming an algorithm ranking or a held-out benchmark result. diff --git a/web/app/globals.css b/web/app/globals.css index 5fb0811..12dfe66 100644 --- a/web/app/globals.css +++ b/web/app/globals.css @@ -1,27 +1,23 @@ @import "tailwindcss"; :root { - --bg: #070b0f; - --bg-raised: #0a1015; - --panel: #0d151b; - --panel-raised: #101b22; - --panel-soft: #121f27; - --line: #24323b; - --line-bright: #354852; - --text: #dce7ea; - --text-strong: #f3f8f9; - --muted: #82949c; - --muted-deep: #71858e; - --cyan: #56e0c1; - --cyan-soft: rgba(86, 224, 193, 0.14); - --blue: #53a7ff; - --amber: #f3b94f; - --orange: #ff8f5a; - --danger: #ff5d62; - --safe: #6be29f; - --agent-color: #dc735b; - --mono: "SFMono-Regular", "Cascadia Code", "Roboto Mono", Consolas, monospace; + --page: #f6f6f3; + --paper: #ffffff; + --paper-soft: #fafaf8; + --ink: #202124; + --ink-soft: #5f6368; + --ink-faint: #7b8085; + --line: #d9dde1; + --line-dark: #bcc2c8; + --blue: #2f5d8c; + --blue-soft: #e8eff6; + --green: #2f7048; + --amber: #9a6719; + --red: #a63c3c; + --agent-color: #2f5d8c; + --serif: Georgia, "Times New Roman", Times, serif; --sans: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --mono: "SFMono-Regular", "Cascadia Code", "Roboto Mono", Consolas, monospace; } * { @@ -29,32 +25,30 @@ } html { - background: var(--bg); - color-scheme: dark; + background: var(--page); + color-scheme: light; scroll-behavior: smooth; } body { min-width: 320px; margin: 0; - color: var(--text); - background: - radial-gradient(circle at 72% -10%, rgba(42, 101, 114, 0.22), transparent 34rem), - linear-gradient(rgba(98, 130, 140, 0.032) 1px, transparent 1px), - linear-gradient(90deg, rgba(98, 130, 140, 0.032) 1px, transparent 1px), - var(--bg); - background-size: auto, 32px 32px, 32px 32px, auto; + color: var(--ink); + background: var(--page); font-family: var(--sans); text-rendering: optimizeLegibility; } button, -input { +input, +select { font: inherit; } button, -a { +a, +select, +input { -webkit-tap-highlight-color: transparent; } @@ -69,514 +63,251 @@ a { button:focus-visible, a:focus-visible, -input:focus-visible { - outline: 2px solid var(--cyan); +select:focus-visible, +input:focus-visible, +summary:focus-visible { + outline: 2px solid var(--blue); outline-offset: 3px; } -.app-shell { +.site-shell { min-height: 100vh; } -.system-label { - display: block; - margin: 0 0 10px; - color: var(--muted); - font: 600 10px/1.3 var(--mono); - letter-spacing: 0.16em; - text-transform: uppercase; -} - -.command-bar { - position: sticky; - z-index: 50; - top: 0; - height: 66px; - padding: 0 max(24px, calc((100vw - 1600px) / 2)); +.site-header { + width: min(1220px, calc(100% - 48px)); + min-height: 58px; + margin: 0 auto; display: flex; align-items: center; justify-content: space-between; - border-bottom: 1px solid var(--line); - background: rgba(7, 11, 15, 0.9); - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.24); - backdrop-filter: blur(18px); -} - -.brand-lockup { - display: flex; - align-items: center; - gap: 12px; -} - -.brand-lockup > span:last-child { - display: flex; - flex-direction: column; - gap: 2px; + gap: 24px; + border-bottom: 1px solid var(--line-dark); } -.brand-lockup strong { - color: var(--text-strong); - font-size: 13px; +.wordmark { + font: 600 14px/1 var(--serif); letter-spacing: 0.01em; } -.brand-lockup small { - color: var(--muted); - font: 9px/1.2 var(--mono); - letter-spacing: 0.08em; - text-transform: uppercase; -} - -.brand-mark { - position: relative; - width: 36px; - height: 36px; - border: 1px solid #3c515a; - background: #0c171d; - box-shadow: inset 0 0 0 3px #081014; -} - -.brand-mark::before, -.brand-mark::after { - position: absolute; - content: ""; - background: var(--cyan); -} - -.brand-mark::before { - inset: 9px 16px; -} - -.brand-mark::after { - inset: 16px 9px; -} - -.brand-mark i { - position: absolute; - z-index: 1; - width: 5px; - height: 5px; - border: 1px solid var(--cyan); - background: #0c171d; -} - -.brand-mark i:nth-child(1) { top: 7px; left: 7px; } -.brand-mark i:nth-child(2) { top: 7px; right: 7px; } -.brand-mark i:nth-child(3) { right: 7px; bottom: 7px; } - -.command-meta { +.site-header nav { display: flex; align-items: center; - gap: 16px; - color: var(--muted); - font: 600 9px/1 var(--mono); - letter-spacing: 0.09em; - text-transform: uppercase; -} - -.command-meta a { - padding: 9px 11px; - border: 1px solid var(--line); - color: #bdc9cd; - transition: border-color 160ms ease, color 160ms ease, background 160ms ease; -} - -.command-meta a:hover { - border-color: var(--cyan); - color: var(--text-strong); - background: var(--cyan-soft); -} - -.command-meta a b { - color: var(--cyan); -} - -.demo-status { - display: inline-flex; - align-items: center; - gap: 8px; - color: #f1c875; + gap: 24px; + color: var(--ink-soft); + font-size: 12px; } -.demo-status i, -.unit-status i, -.evidence-status i { - width: 6px; - height: 6px; - border-radius: 50%; +.site-header nav a { + padding: 8px 0; + border-bottom: 1px solid transparent; } -.demo-status i, -.evidence-status i { - background: var(--amber); - box-shadow: 0 0 0 4px rgba(243, 185, 79, 0.08), 0 0 12px rgba(243, 185, 79, 0.4); +.site-header nav a:hover { + color: var(--ink); + border-color: var(--ink); } -.unit-status.is-nominal i { - background: var(--safe); - box-shadow: 0 0 0 4px rgba(107, 226, 159, 0.08), 0 0 12px rgba(107, 226, 159, 0.45); +.research-page { + width: min(1220px, calc(100% - 48px)); + margin: 0 auto; } -.command-divider { - width: 1px; - height: 18px; - background: var(--line); +.paper-header { + padding: 68px 0 54px; + border-bottom: 1px solid var(--line-dark); } -.shell-content { - width: min(1600px, 100%); - margin: 0 auto; - padding: 0 24px 80px; +.paper-label, +.section-number { + margin: 0; + color: var(--blue); + font: 600 11px/1.4 var(--sans); + letter-spacing: 0.08em; + text-transform: uppercase; } -.mission-intro { - padding: 52px 0 38px; - display: grid; - grid-template-columns: minmax(0, 1.05fr) minmax(390px, 0.95fr); - gap: clamp(48px, 8vw, 128px); - align-items: end; - border-bottom: 1px solid var(--line); +.paper-header h1 { + max-width: 920px; + margin: 15px 0 21px; + color: #17181a; + font: 500 clamp(36px, 4.6vw, 54px)/1.08 var(--serif); + letter-spacing: -0.032em; } -.mission-intro h1 { - max-width: 780px; +.abstract-copy { + max-width: 830px; margin: 0; - color: var(--text-strong); - font-size: clamp(40px, 5.6vw, 78px); - font-weight: 650; - line-height: 0.93; - letter-spacing: -0.055em; + color: #3f4347; + font: 400 17px/1.7 var(--serif); } -.mission-intro h1 span { - color: #748790; - font-weight: 450; +.artifact-note { + max-width: 940px; + margin-top: 30px; + padding: 15px 17px; + border-left: 3px solid var(--amber); + background: #f6f1e8; + color: #51452f; + font-size: 13px; + line-height: 1.6; } -.intro-brief > p { - max-width: 620px; - margin: 0 0 26px; - color: #a8b7bd; - font-size: 14px; - line-height: 1.65; +.artifact-note strong { + color: #3d3425; } -.intro-brief dl { - margin: 0; +.study-metadata { + max-width: 940px; + margin: 34px 0 0; display: grid; - grid-template-columns: repeat(4, 1fr); + grid-template-columns: repeat(5, 1fr); border-top: 1px solid var(--line); + border-bottom: 1px solid var(--line); } -.intro-brief dl div { - padding: 13px 12px 0 0; +.study-metadata > div { + padding: 13px 14px; border-right: 1px solid var(--line); } -.intro-brief dl div:not(:first-child) { - padding-left: 12px; +.study-metadata > div:first-child { + padding-left: 0; } -.intro-brief dl div:last-child { +.study-metadata > div:last-child { border-right: 0; } -.intro-brief dt { - margin-bottom: 5px; - color: var(--muted-deep); - font: 600 8px/1.2 var(--mono); - letter-spacing: 0.13em; - text-transform: uppercase; +.study-metadata dt, +.state-table dt, +.method-workload dt { + color: var(--ink-faint); + font-size: 11px; + line-height: 1.3; } -.intro-brief dd { - margin: 0; - color: var(--text-strong); - font: 600 13px/1.2 var(--mono); +.study-metadata dd { + margin: 5px 0 0; + font: 600 13px/1.3 var(--mono); } -.agent-deck { - padding: 28px 0 22px; +.viewer-section, +.results-section { + padding: 58px 0 64px; + border-bottom: 1px solid var(--line-dark); } -.section-kicker { - margin-bottom: 13px; - display: grid; - grid-template-columns: auto 1fr auto; - gap: 18px; - align-items: baseline; +.section-heading { + margin-bottom: 24px; + display: flex; + align-items: end; + justify-content: space-between; + gap: 32px; } -.section-kicker > span, -.section-kicker > p { - margin: 0; - color: var(--muted); - font: 600 9px/1.2 var(--mono); - letter-spacing: 0.11em; - text-transform: uppercase; +.section-heading h2, +.interpretation-section h2 { + margin: 7px 0 0; + font: 500 30px/1.16 var(--serif); + letter-spacing: -0.018em; } -.section-kicker h2 { - margin: 0; - color: #c9d5d9; +.section-heading > div > p:last-child { + margin: 9px 0 0; + color: var(--ink-soft); font-size: 13px; - font-weight: 600; -} - -.agent-grid { - display: grid; - grid-template-columns: repeat(6, minmax(0, 1fr)); - border: 1px solid var(--line); - background: var(--bg-raised); -} - -.agent-card { - position: relative; - min-width: 0; - min-height: 92px; - padding: 16px 15px 18px; - display: grid; - grid-template-columns: 28px minmax(0, 1fr) auto; - gap: 9px; - align-items: start; - border: 0; - border-right: 1px solid var(--line); - background: transparent; - text-align: left; - cursor: pointer; - transition: background 160ms ease, color 160ms ease; -} - -.agent-card:last-child { - border-right: 0; -} - -.agent-card::before { - position: absolute; - inset: -1px auto -1px -1px; - width: 3px; - content: ""; - background: var(--candidate-color); - opacity: 0; -} - -.agent-card:hover { - background: #111b21; -} - -.agent-card.is-active { - background: - linear-gradient(135deg, color-mix(in srgb, var(--candidate-color) 13%, transparent), transparent 62%), - #111b21; -} - -.agent-card.is-active::before { - opacity: 1; -} - -.agent-index { - color: var(--muted-deep); - font: 600 9px/1.2 var(--mono); + line-height: 1.5; } -.agent-name { - min-width: 0; +.algorithm-select { + min-width: 250px; display: flex; flex-direction: column; - gap: 5px; + gap: 7px; } -.agent-name strong { - overflow: hidden; - color: #d5e0e3; +.algorithm-select span { + color: var(--ink-soft); font-size: 11px; - white-space: nowrap; - text-overflow: ellipsis; -} - -.agent-name small { - overflow: hidden; - color: var(--muted); - font: 8px/1.2 var(--mono); - letter-spacing: 0.08em; - text-transform: uppercase; - white-space: nowrap; - text-overflow: ellipsis; -} - -.agent-score { - color: var(--text-strong); - font: 600 12px/1.2 var(--mono); -} - -.agent-progress { - position: absolute; - right: 15px; - bottom: 13px; - left: 52px; - height: 2px; - background: #1d2a31; } -.agent-progress i { - display: block; - height: 100%; - background: var(--candidate-color); - transition: width 240ms ease; +.algorithm-select select { + width: 100%; + height: 40px; + padding: 0 36px 0 11px; + border: 1px solid var(--line-dark); + border-radius: 2px; + color: var(--ink); + background: var(--paper); } .operations-grid { display: grid; - grid-template-columns: minmax(0, 1fr) 360px; - gap: 14px; + grid-template-columns: minmax(0, 2.2fr) minmax(280px, 0.8fr); align-items: start; + gap: 18px; } -.console-panel { - min-width: 0; - border: 1px solid var(--line); - background: rgba(12, 20, 26, 0.96); - box-shadow: 0 18px 50px rgba(0, 0, 0, 0.22); +.trajectory-figure, +.state-panel { + margin: 0; + border: 1px solid var(--line-dark); + background: var(--paper); } -.console-header { - min-height: 76px; - padding: 16px 19px; +.figure-heading { + min-height: 67px; + padding: 13px 16px; display: flex; align-items: center; justify-content: space-between; - gap: 24px; - border-bottom: 1px solid var(--line); - background: #0d161c; -} - -.console-header .system-label { - margin-bottom: 5px; -} - -.console-header h2 { - margin: 0; - color: var(--text-strong); - font-size: 17px; - font-weight: 640; - letter-spacing: -0.015em; -} - -.tick-readout { - display: flex; - align-items: baseline; - gap: 13px; -} - -.tick-readout span { - color: var(--muted); - font: 600 8px/1 var(--mono); - letter-spacing: 0.11em; - text-transform: uppercase; -} - -.tick-readout strong { - color: var(--cyan); - font: 650 24px/1 var(--mono); - letter-spacing: -0.05em; - text-shadow: 0 0 16px rgba(86, 224, 193, 0.2); -} - -.zone-rail { - display: grid; - grid-template-columns: repeat(5, 1fr); + gap: 20px; border-bottom: 1px solid var(--line); - background: #091116; } -.zone-rail > span { - min-width: 0; - padding: 9px 11px; - display: flex; - align-items: center; - gap: 7px; - border-right: 1px solid var(--line); - color: #95a7ae; - font: 600 8px/1 var(--mono); - letter-spacing: 0.07em; +.figure-heading span { + color: var(--ink-faint); + font-size: 10px; + letter-spacing: 0.06em; text-transform: uppercase; } -.zone-rail > span:last-child { - border-right: 0; +.figure-heading h3 { + margin: 4px 0 0; + font: 500 18px/1.2 var(--serif); } -.zone-rail i { - width: 7px; - height: 7px; - border: 1px solid currentColor; +.figure-heading > p { + margin: 0; + color: var(--ink-soft); + font: 12px/1.2 var(--mono); } -.zone-rail small { - margin-left: auto; - color: var(--muted-deep); - font: inherit; +.figure-heading > p strong { + color: var(--ink); + font-size: 15px; } -.zone-receiving { color: #5eb6db !important; } -.zone-storage { color: #8999a0 !important; } -.zone-packing { color: #dd9c55 !important; } -.zone-dispatch { color: #da7482 !important; } -.zone-charging { color: #65c6a0 !important; } - .map-wrap { - padding: 20px; - display: grid; - place-items: center; - background: - linear-gradient(rgba(62, 91, 101, 0.035) 1px, transparent 1px), - linear-gradient(90deg, rgba(62, 91, 101, 0.035) 1px, transparent 1px), - #071015; - background-size: 20px 20px; + padding: 17px; + background: var(--paper-soft); } .warehouse-map { position: relative; - width: min(100%, 940px); - min-height: 420px; - padding: 16px; - border: 1px solid #394952; - background: #091116; - box-shadow: - inset 0 0 0 4px #060b0e, - inset 0 0 0 5px #1c2b32, - 0 22px 70px rgba(0, 0, 0, 0.36); + width: 100%; + min-height: 0; + padding: 12px; + border: 1px solid #aeb6bc; + background: #fdfdfb; isolation: isolate; } -.warehouse-map::before, -.warehouse-map::after { - position: absolute; - z-index: 20; - width: 20px; - height: 20px; - pointer-events: none; - content: ""; -} - -.warehouse-map::before { - top: 7px; - left: 7px; - border-top: 1px solid var(--cyan); - border-left: 1px solid var(--cyan); -} - -.warehouse-map::after { - right: 7px; - bottom: 7px; - border-right: 1px solid var(--cyan); - border-bottom: 1px solid var(--cyan); -} - .map-grid, .route-layer { display: grid; - gap: 3px; + gap: 2px; } .map-grid { @@ -589,84 +320,61 @@ input:focus-visible { min-width: 0; min-height: 0; overflow: visible; - border: 1px solid rgba(116, 144, 154, 0.09); - background: - radial-gradient(circle at 22% 30%, rgba(174, 197, 201, 0.08) 0 1px, transparent 1.5px), - #142128; - background-size: 9px 9px, auto; + border: 1px solid #eaebe8; + background: #fafaf7; } .map-cell.receiving-zone { - background-color: #112631; - box-shadow: inset 3px 0 rgba(64, 152, 190, 0.22); + background: #f1f6f8; } .map-cell.dispatch-zone { - background-color: #251b23; - box-shadow: inset -3px 0 rgba(210, 94, 112, 0.18); + background: #faf2f1; } .map-cell.packing-zone { - background-color: #241f18; - box-shadow: inset 0 -3px rgba(217, 145, 65, 0.2); + background: #faf7ef; } .map-cell.charging-zone { - background-color: #10251f; - box-shadow: inset 0 0 0 2px rgba(86, 213, 162, 0.22); + background: #eff7f1; } .map-cell.obstacle { - z-index: 5; + z-index: 2; overflow: hidden; - border-color: #41515a; - background: - linear-gradient(90deg, transparent 12%, rgba(189, 204, 208, 0.13) 13% 17%, transparent 18% 45%, rgba(189, 204, 208, 0.13) 46% 50%, transparent 51% 78%, rgba(189, 204, 208, 0.13) 79% 83%, transparent 84%), - repeating-linear-gradient(0deg, #29353b 0 5px, #1e292f 5px 10px); - box-shadow: - inset 3px 0 #52626a, - inset -3px 0 #111a1f, - 0 4px 8px rgba(0, 0, 0, 0.45); -} - -.map-cell.obstacle::before, -.map-cell.obstacle::after { - position: absolute; - right: 4px; - left: 4px; - height: 2px; - content: ""; - background: #78868b; - opacity: 0.36; + border-color: #acb0b1; + background: repeating-linear-gradient(0deg, #d0d2d0 0 5px, #c3c6c4 5px 7px); + box-shadow: inset 2px 0 #b3b7b5, inset -2px 0 #dfe1df; } -.map-cell.obstacle::before { top: 4px; } -.map-cell.obstacle::after { bottom: 4px; } +.rack-label, +.zone-tag { + position: absolute; + z-index: 3; + font-family: var(--mono); + font-style: normal; + font-weight: 600; +} .rack-label { - position: absolute; - z-index: 1; - right: 4px; + right: 3px; bottom: 3px; - color: rgba(206, 220, 222, 0.52); - font: 600 6px/1 var(--mono); - letter-spacing: 0.06em; + color: #5e6463; + font-size: 7px; } .zone-tag { - position: absolute; - z-index: 2; - top: 4px; - left: 4px; - color: rgba(202, 219, 223, 0.38); - font: 700 6px/1 var(--mono); - letter-spacing: 0.12em; + top: 3px; + left: 3px; + color: #83898b; + font-size: 7px; } .route-layer { position: absolute; - z-index: 3; - inset: 16px; + z-index: 4; + inset: 12px; pointer-events: none; } @@ -686,8 +394,8 @@ input:focus-visible { z-index: 2; top: 50%; left: 50%; - width: 5px; - height: 5px; + width: 4px; + height: 4px; border-radius: 50%; transform: translate(-50%, -50%); } @@ -700,260 +408,147 @@ input:focus-visible { .route-south { left: calc(50% - 1px); width: 2px; - height: calc(50% + 4px); + height: calc(50% + 3px); } -.route-north { top: -3px; } +.route-north { top: -2px; } .route-south { top: 50%; } .route-east, .route-west { top: calc(50% - 1px); - width: calc(50% + 4px); + width: calc(50% + 3px); height: 2px; } .route-east { left: 50%; } -.route-west { left: -3px; } +.route-west { left: -2px; } .route-projected .route-node { width: 3px; height: 3px; - background: rgba(87, 169, 255, 0.32); + background: #9db2c8; } .route-projected .route-branch { - background: repeating-linear-gradient(90deg, rgba(87, 169, 255, 0.36) 0 3px, transparent 3px 6px); + background: repeating-linear-gradient(90deg, #9db2c8 0 3px, transparent 3px 6px); } .route-projected .route-north, .route-projected .route-south { - background: repeating-linear-gradient(0deg, rgba(87, 169, 255, 0.36) 0 3px, transparent 3px 6px); + background: repeating-linear-gradient(0deg, #9db2c8 0 3px, transparent 3px 6px); } .route-travelled { - z-index: 4; + z-index: 5; } .route-travelled .route-node, .route-travelled .route-branch { - background: var(--cyan); - box-shadow: 0 0 7px rgba(86, 224, 193, 0.52); + background: var(--agent-color); } -.charger { +.charger, +.order-marker, +.closure-marker, +.robot-marker { position: absolute; - z-index: 6; - right: 3px; - bottom: 3px; - padding: 2px 3px; - display: flex; - align-items: center; - gap: 2px; - border: 1px solid rgba(93, 220, 169, 0.52); - color: #83e6bd; - background: rgba(7, 24, 18, 0.9); - font: 700 5px/1 var(--mono); - letter-spacing: 0.05em; + z-index: 8; + display: grid; + place-items: center; + font: 700 7px/1 var(--mono); } -.charger i { - width: 3px; - height: 5px; - background: #83e6bd; - clip-path: polygon(50% 0, 100% 0, 65% 43%, 100% 43%, 25% 100%, 40% 55%, 0 55%); +.charger { + right: 3px; + bottom: 3px; + width: 14px; + height: 14px; + border: 1px solid #5c876b; + border-radius: 50%; + color: #3f694f; + background: #f7fbf8; } .order-marker { - position: absolute; - z-index: 7; - width: 19px; - height: 19px; - display: grid; - place-items: center; + width: 18px; + height: 18px; border: 1px solid currentColor; - background: #071015; - box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); - font: 750 7px/1 var(--mono); - transition: opacity 180ms ease, transform 180ms ease; -} - -.order-marker i { - position: absolute; - width: 3px; - height: 3px; - border-radius: 50%; - background: currentColor; + background: var(--paper); + transition: opacity 160ms ease; } .pickup-marker { top: 3px; left: 3px; - color: #59dcba; -} - -.pickup-marker i { - right: -2px; - bottom: -2px; + color: #376b64; } .dropoff-marker { right: 3px; bottom: 3px; - color: var(--amber); - transform: rotate(45deg); -} - -.dropoff-marker b { - transform: rotate(-45deg); -} - -.dropoff-marker i { - top: -2px; - right: -2px; + color: #91651f; } .order-marker.is-queued { - opacity: 0.34; + opacity: 0.3; } .order-marker.is-carried { - box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.18), 0 0 14px currentColor; + border-width: 2px; } -.order-marker.is-picked, -.order-marker.is-expired { +.order-marker.is-picked { opacity: 0.18; - filter: grayscale(0.85); + filter: grayscale(0.8); } .order-marker.is-delivered { - opacity: 0.28; + border-color: var(--green); + color: var(--green); + background: #eff7f1; + opacity: 0.42; } -.closure-gate { - position: absolute; - z-index: 12; +.order-marker.is-expired { + border-color: var(--red); + border-style: dashed; + color: var(--red); + background: #fbf0ef; + opacity: 0.72; +} + +.closure-marker { inset: 2px; - overflow: hidden; - display: grid; - place-items: center; - border: 1px solid var(--danger); - background: repeating-linear-gradient(135deg, rgba(255, 93, 98, 0.46) 0 5px, rgba(80, 14, 18, 0.78) 5px 10px); - box-shadow: 0 0 15px rgba(255, 93, 98, 0.28); + border: 1px solid var(--red); + color: var(--red); + background: rgba(255, 255, 255, 0.84); + font-size: 15px; } -.closure-gate::before, -.closure-gate::after { - position: absolute; - width: 140%; - height: 2px; - content: ""; - background: #ff9497; - transform: rotate(32deg); -} - -.closure-gate::after { - transform: rotate(-32deg); -} - -.closure-gate b { - z-index: 1; - padding: 2px 3px; - color: white; - background: #9c262b; - font: 800 5px/1 var(--mono); - letter-spacing: 0.08em; -} - -.robot { - position: absolute; - z-index: 15; +.robot-marker { + z-index: 11; top: 50%; left: 50%; - width: clamp(25px, 60%, 39px); + width: min(68%, 30px); aspect-ratio: 1; - display: grid; - place-items: center; - border: 2px solid rgba(255, 255, 255, 0.92); - border-radius: 8px; - color: white; - transform: translate(-50%, -50%); - box-shadow: - 0 0 0 2px rgba(5, 10, 12, 0.85), - 0 8px 18px rgba(0, 0, 0, 0.55), - 0 0 20px color-mix(in srgb, var(--agent-color) 40%, transparent); -} - -.robot::before { - position: absolute; - inset: 5px; - border: 1px solid rgba(255, 255, 255, 0.38); - border-radius: 4px; - content: ""; -} - -.robot::after { - position: absolute; - top: 6px; - right: 6px; - bottom: 6px; - left: 6px; - border-top: 2px solid rgba(255, 255, 255, 0.22); - border-bottom: 2px solid rgba(0, 0, 0, 0.18); - content: ""; -} - -.robot b { - z-index: 2; - font: 800 7px/1 var(--mono); - letter-spacing: 0.03em; -} - -.robot-status { - position: absolute; - z-index: 3; - right: 4px; - bottom: 4px; - width: 4px; - height: 4px; + border: 2px solid #ffffff; border-radius: 50%; - background: #d3ff78; - box-shadow: 0 0 6px #d3ff78; + color: #ffffff; + background: var(--agent-color); + transform: translate(-50%, -50%); + box-shadow: 0 0 0 1px #555b60; } -.robot-heading { - position: absolute; - z-index: 3; - width: 0; - height: 0; - border-right: 4px solid transparent; - border-bottom: 6px solid white; - border-left: 4px solid transparent; -} - -.heading-up .robot-heading { top: -8px; left: calc(50% - 4px); } -.heading-down .robot-heading { bottom: -8px; left: calc(50% - 4px); transform: rotate(180deg); } -.heading-left .robot-heading { top: calc(50% - 3px); left: -9px; transform: rotate(-90deg); } -.heading-right .robot-heading { top: calc(50% - 3px); right: -9px; transform: rotate(90deg); } -.heading-pickup .robot-heading, -.heading-dropoff .robot-heading, -.heading-charge .robot-heading, -.heading-wait .robot-heading { display: none; } - .map-legend { - padding: 11px 18px; + padding: 10px 16px; display: flex; flex-wrap: wrap; - justify-content: center; - gap: 10px 19px; + gap: 9px 19px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); - color: var(--muted); - background: #0a1217; - font: 600 7px/1.2 var(--mono); - letter-spacing: 0.08em; - text-transform: uppercase; + color: var(--ink-soft); + font-size: 10px; } .map-legend span { @@ -963,135 +558,132 @@ input:focus-visible { } .map-legend i { - width: 8px; - height: 8px; + width: 10px; + height: 10px; display: inline-block; } -.legend-robot { border: 1px solid white; border-radius: 2px; background: var(--agent-color); } -.legend-route { height: 2px !important; background: var(--cyan); box-shadow: 0 0 5px rgba(86, 224, 193, 0.45); } -.legend-projected { height: 2px !important; background: repeating-linear-gradient(90deg, var(--blue) 0 2px, transparent 2px 4px); } -.legend-pickup { border: 1px solid var(--cyan); } -.legend-dropoff { border: 1px solid var(--amber); transform: rotate(45deg); } -.legend-blocked { border: 1px solid var(--danger); background: repeating-linear-gradient(135deg, #9b292d 0 2px, #311318 2px 4px); } +.legend-robot { border: 1px solid #555b60; border-radius: 50%; background: var(--agent-color); } +.legend-route { height: 2px !important; background: var(--agent-color); } +.legend-projected { height: 2px !important; background: repeating-linear-gradient(90deg, #9db2c8 0 2px, transparent 2px 4px); } +.legend-pickup { border: 1px solid #376b64; } +.legend-dropoff { border: 1px solid #91651f; } +.legend-blocked { border: 1px solid var(--red); background: #fff5f4; } +.legend-delivered { border: 1px solid var(--green); background: #eff7f1; opacity: 0.55; } +.legend-expired { border: 1px dashed var(--red); background: #fbf0ef; } -.timeline-console { - min-height: 84px; - padding: 14px 18px 16px; +.replay-controls { + padding: 14px 16px 12px; display: grid; - grid-template-columns: 140px minmax(0, 1fr) 64px; - gap: 20px; - align-items: center; - background: #0c151b; -} - -.transport-controls { - display: flex; - align-items: center; - gap: 10px; -} - -.transport-controls > div { - display: flex; - flex-direction: column; - gap: 3px; + grid-template-columns: auto minmax(0, 1fr) auto; + align-items: end; + gap: 14px; } -.transport-controls small, -.speed-button small, -.timeline-labels { - color: var(--muted); - font: 600 7px/1 var(--mono); - letter-spacing: 0.08em; - text-transform: uppercase; +.play-control, +.reset-control { + min-width: 62px; + height: 34px; + padding: 0 12px; + border: 1px solid var(--line-dark); + border-radius: 2px; + background: var(--paper); + cursor: pointer; } -.transport-controls strong { - color: #cbd7da; - font: 600 8px/1 var(--mono); - letter-spacing: 0.07em; +.play-control { + border-color: var(--blue); + color: var(--blue); } -.play-button { - width: 40px; - height: 40px; - border: 1px solid #38525d; - background: #101e25; - color: var(--cyan); - cursor: pointer; - transition: background 150ms ease, border-color 150ms ease; +.play-control:hover, +.reset-control:hover { + background: var(--blue-soft); } -.play-button:hover { - border-color: var(--cyan); - background: var(--cyan-soft); +.timeline-control { + min-width: 0; } .timeline-labels { - margin-bottom: 10px; + margin-bottom: 7px; display: flex; justify-content: space-between; + gap: 14px; + color: var(--ink-faint); + font: 10px/1.2 var(--mono); } -.timeline-labels strong { - color: #9dabb0; - font: inherit; +.timeline-labels span:nth-child(2) { + font-family: var(--sans); } .range-wrap { position: relative; - height: 16px; + height: 34px; } input[type="range"] { position: relative; z-index: 3; + top: 8px; width: 100%; - height: 3px; + height: 17px; margin: 0; appearance: none; + background: transparent; + cursor: pointer; +} + +input[type="range"]::-webkit-slider-runnable-track { + height: 3px; + border-radius: 0; + background: linear-gradient(90deg, var(--agent-color) var(--timeline-progress), #d5d9dc var(--timeline-progress)); +} + +input[type="range"]::-moz-range-track { + height: 3px; border-radius: 0; - background: linear-gradient(90deg, var(--agent-color) 0 var(--timeline-progress), #293840 var(--timeline-progress) 100%); + background: linear-gradient(90deg, var(--agent-color) var(--timeline-progress), #d5d9dc var(--timeline-progress)); } input[type="range"]::-webkit-slider-thumb { - width: 14px; - height: 14px; + width: 13px; + height: 13px; + margin-top: -5px; appearance: none; - border: 2px solid #0a1115; - border-radius: 2px; + border: 2px solid var(--paper); + border-radius: 50%; background: var(--agent-color); - box-shadow: 0 0 0 1px #dfe8e9, 0 0 12px color-mix(in srgb, var(--agent-color) 45%, transparent); - cursor: grab; + box-shadow: 0 0 0 1px #6a7074; } input[type="range"]::-moz-range-thumb { width: 11px; height: 11px; - border: 2px solid #0a1115; - border-radius: 2px; + border: 2px solid var(--paper); + border-radius: 50%; background: var(--agent-color); - box-shadow: 0 0 0 1px #dfe8e9; - cursor: grab; + box-shadow: 0 0 0 1px #6a7074; } .timeline-events { position: absolute; z-index: 4; - top: 8px; + top: 13px; right: 0; left: 0; - height: 8px; + height: 7px; pointer-events: none; } .timeline-event { position: absolute; - top: 0; - width: 6px; - height: 6px; + top: calc((var(--event-lane) * 18px) - 9px); + width: 7px; + height: 7px; padding: 0; - border: 1px solid #071015; + border: 1px solid var(--paper); border-radius: 50%; background: var(--amber); transform: translateX(-50%); @@ -1101,459 +693,200 @@ input[type="range"]::-moz-range-thumb { .timeline-event::before { position: absolute; - inset: -10px; + inset: -7px; content: ""; } -.timeline-event.event-cell_blocked { background: var(--danger); } -.timeline-event.event-cell_unblocked { border-color: var(--danger); background: #0c151b; } -.timeline-event.event-order_arrival { background: var(--cyan); } - -.speed-button { - height: 42px; - padding: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - border: 1px solid var(--line); - background: transparent; - cursor: pointer; -} +.timeline-event.event-cell_blocked { background: var(--red); } +.timeline-event.event-cell_unblocked { border-color: var(--red); background: var(--paper); } +.timeline-event.event-order_arrival { background: var(--blue); } -.speed-button:hover { - border-color: var(--cyan); - background: var(--cyan-soft); +.trajectory-figure figcaption { + padding: 0 16px 15px; + color: var(--ink-soft); + font: 12px/1.55 var(--serif); } -.speed-button strong { - color: var(--text-strong); - font: 650 11px/1 var(--mono); +.state-panel { + padding: 19px; } -.telemetry-console { - position: sticky; - top: 80px; -} - -.compact-header { - min-height: 76px; -} - -.unit-status { - display: flex; - align-items: center; - gap: 7px; - color: #a7c8b2; - font: 600 8px/1 var(--mono); - letter-spacing: 0.08em; - text-transform: uppercase; -} - -.unit-status.is-warning { - color: #e8c06f; -} - -.unit-status.is-warning i { - background: var(--amber); - box-shadow: 0 0 0 4px rgba(243, 185, 79, 0.08), 0 0 12px rgba(243, 185, 79, 0.4); -} - -.unit-status.is-alert { - color: #ff9699; -} - -.unit-status.is-alert i { - background: var(--danger); - box-shadow: 0 0 0 4px rgba(255, 93, 98, 0.08), 0 0 12px rgba(255, 93, 98, 0.4); -} - -.active-policy { +.method-summary { position: relative; - padding: 20px 20px 20px 28px; + padding: 0 0 19px 16px; border-bottom: 1px solid var(--line); - background: linear-gradient(110deg, color-mix(in srgb, var(--agent-color) 12%, transparent), transparent 62%); } -.policy-line { +.method-swatch { position: absolute; - top: 21px; - bottom: 22px; - left: 18px; - width: 2px; + top: 1px; + bottom: 20px; + left: 0; + width: 3px; background: var(--agent-color); - box-shadow: 0 0 10px color-mix(in srgb, var(--agent-color) 55%, transparent); } -.active-policy small, -.decision-readout span, -.battery-module span, -.metric-grid article > span { - color: var(--muted); - font: 600 8px/1.2 var(--mono); - letter-spacing: 0.11em; +.method-summary p { + margin: 0 0 5px; + color: var(--ink-faint); + font-size: 10px; text-transform: uppercase; + letter-spacing: 0.06em; } -.active-policy h3 { - margin: 7px 0 9px; - color: var(--text-strong); - font-size: 20px; - letter-spacing: -0.025em; -} - -.active-policy p { +.method-summary h3 { margin: 0; - color: #86989f; - font-size: 11px; - line-height: 1.55; -} - -.decision-readout { - min-height: 104px; - padding: 18px 20px; - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - border-bottom: 1px solid var(--line); - background: #0a1217; -} - -.decision-readout > div { - min-width: 0; + font: 500 22px/1.2 var(--serif); } -.decision-readout strong { +.method-summary > span:last-child { display: block; - margin-top: 8px; - color: var(--text-strong); - font-size: 19px; - font-weight: 620; - letter-spacing: -0.025em; -} - -.action-glyph { - position: relative; - width: 42px; - height: 42px; - flex: 0 0 auto; - border: 1px solid color-mix(in srgb, var(--agent-color) 70%, #70838b); - background: color-mix(in srgb, var(--agent-color) 14%, transparent); -} - -.action-glyph::before, -.action-glyph::after { - position: absolute; - content: ""; -} - -.action-glyph::before { - top: 9px; - left: 19px; - width: 2px; - height: 21px; - background: var(--agent-color); -} - -.action-glyph::after { - top: 9px; - left: 15px; - width: 8px; - height: 8px; - border-top: 2px solid var(--agent-color); - border-left: 2px solid var(--agent-color); - transform: rotate(45deg); -} - -.action-down { transform: rotate(180deg); } -.action-left { transform: rotate(-90deg); } -.action-right { transform: rotate(90deg); } -.action-pickup::before, -.action-dropoff::before, -.action-charge::before, -.action-wait::before { inset: 13px; width: auto; height: auto; border: 2px solid var(--agent-color); background: transparent; } -.action-pickup::after { top: 18px; left: 18px; width: 7px; height: 2px; border: 0; background: var(--agent-color); transform: none; box-shadow: 2px -2px var(--agent-color); } -.action-dropoff::after { top: 16px; left: 16px; width: 7px; height: 7px; border-right: 2px solid var(--agent-color); border-bottom: 2px solid var(--agent-color); border-top: 0; border-left: 0; transform: rotate(45deg); } -.action-charge::after { top: 13px; left: 17px; width: 10px; height: 16px; border: 0; background: var(--agent-color); transform: none; clip-path: polygon(50% 0, 100% 0, 65% 43%, 100% 43%, 25% 100%, 40% 55%, 0 55%); } -.action-wait::after { top: 15px; left: 20px; width: 1px; height: 11px; border: 0; background: var(--agent-color); transform: rotate(-45deg); transform-origin: bottom; } - -.battery-module { - padding: 15px 20px 17px; - border-bottom: 1px solid var(--line); -} - -.battery-module > div:first-child { - margin-bottom: 10px; - display: flex; - align-items: baseline; - justify-content: space-between; -} - -.battery-module strong { - color: #dfe8e9; - font: 650 15px/1 var(--mono); -} - -.battery-module strong small { - color: var(--muted); - font: 500 8px/1 var(--mono); -} - -.battery-track { - height: 5px; - padding-right: 7px; - background: repeating-linear-gradient(90deg, #213038 0 16px, #0c151b 16px 19px); + margin-top: 9px; + color: var(--ink-soft); + font-size: 12px; + line-height: 1.55; } -.battery-track i { - display: block; - height: 100%; - background: linear-gradient(90deg, var(--amber), var(--safe)); - box-shadow: 0 0 10px rgba(107, 226, 159, 0.22); - transition: width 200ms ease; +.state-panel > h4, +.method-workload h4 { + margin: 18px 0 8px; + font: 600 12px/1.3 var(--sans); } -.state-grid { +.state-table, +.method-workload dl { margin: 0; - display: grid; - grid-template-columns: 1fr 1fr; - border-bottom: 1px solid var(--line); + border-top: 1px solid var(--line); } -.state-grid > div { - min-width: 0; - padding: 13px 15px; - border-right: 1px solid var(--line); +.state-table > div, +.method-workload dl > div { + min-height: 36px; + padding: 8px 0; + display: grid; + grid-template-columns: 1fr 1.25fr; + align-items: baseline; + gap: 12px; border-bottom: 1px solid var(--line); } -.state-grid > div:nth-child(even) { border-right: 0; } -.state-grid > div:nth-last-child(-n + 2) { border-bottom: 0; } - -.state-grid dt { - margin-bottom: 6px; - color: var(--muted-deep); - font: 600 7px/1.2 var(--mono); - letter-spacing: 0.1em; - text-transform: uppercase; -} - -.state-grid dd { +.state-table dd, +.method-workload dd { margin: 0; - overflow: hidden; - color: #c7d2d6; - font: 600 10px/1.2 var(--mono); - white-space: nowrap; - text-overflow: ellipsis; -} - -.safe-value { color: var(--safe) !important; } -.warning-value { color: var(--danger) !important; } - -.event-log { - padding: 17px 17px 14px; -} - -.module-heading { - margin-bottom: 11px; - display: flex; - align-items: baseline; - justify-content: space-between; + overflow-wrap: anywhere; + color: #313438; + font: 500 11px/1.4 var(--mono); + text-align: right; } -.module-heading h3 { - margin: 0; - color: #c6d2d6; +.state-status { + margin: 14px 0 0; + padding: 8px 9px; + border-left: 3px solid var(--line-dark); + color: var(--ink-soft); + background: var(--paper-soft); font-size: 11px; - font-weight: 650; } -.module-heading span { - color: var(--muted-deep); - font: 600 7px/1 var(--mono); - letter-spacing: 0.08em; - text-transform: uppercase; +.state-status.is-warning { + border-color: var(--amber); + color: #6e4c16; + background: #faf6ec; } -.event-scroll { - max-height: 275px; - overflow: auto; - border-top: 1px solid var(--line); - scrollbar-color: var(--line-bright) transparent; - scrollbar-width: thin; +.state-status.is-alert { + border-color: var(--red); + color: #7e3030; + background: #fbf0ef; } -.event-row { - width: 100%; - min-height: 48px; - padding: 8px 3px; - display: grid; - grid-template-columns: 35px 7px minmax(0, 1fr) auto; - gap: 8px; - align-items: center; - border: 0; - border-bottom: 1px solid #1d2a31; - background: transparent; - text-align: left; - cursor: pointer; -} - -.event-row:hover:not(:disabled) { - background: #111c22; -} - -.event-row:disabled { - cursor: not-allowed; -} - -.event-row time { - color: #90a0a6; - font: 600 8px/1 var(--mono); -} - -.event-row > i { - width: 6px; - height: 6px; - border-radius: 50%; - background: var(--cyan); - box-shadow: 0 0 7px currentColor; -} - -.event-row.event-cell_blocked > i { background: var(--danger); } -.event-row.event-cell_unblocked > i { border: 1px solid var(--danger); background: transparent; } - -.event-row > span { - min-width: 0; - display: flex; - flex-direction: column; - gap: 4px; -} - -.event-row > span strong { - overflow: hidden; - color: #bcc8cc; - font-size: 9px; - white-space: nowrap; - text-overflow: ellipsis; +.method-workload { + margin-top: 20px; } -.event-row > span small { - overflow: hidden; - color: var(--muted-deep); - font: 7px/1 var(--mono); - white-space: nowrap; - text-overflow: ellipsis; -} - -.event-row > b { - color: var(--safe); - font: 600 6px/1 var(--mono); - letter-spacing: 0.08em; -} - -.event-row.is-future { - opacity: 0.46; +.event-annotations { + margin-top: 18px; + border: 1px solid var(--line-dark); + background: var(--paper); } -.event-row.is-future > b { - color: var(--muted); +.event-annotations summary { + padding: 13px 15px; + color: #34373a; + font: 600 12px/1.3 var(--sans); + cursor: pointer; } -.evidence-section { - padding: 78px 0 0; +.event-table-wrap, +.comparison-shell { + overflow-x: auto; } -.evidence-heading { - margin-bottom: 28px; - display: flex; - align-items: end; - justify-content: space-between; - gap: 28px; +.event-annotations table, +.comparison-table { + width: 100%; + border-collapse: collapse; + font-size: 12px; } -.evidence-heading h2 { - max-width: 800px; - margin: 0; - color: var(--text-strong); - font-size: clamp(30px, 4vw, 52px); - font-weight: 560; - line-height: 1; - letter-spacing: -0.045em; +.event-annotations table { + min-width: 620px; + border-top: 1px solid var(--line); } -.evidence-status { - max-width: 360px; - padding: 10px 12px; - display: flex; - align-items: center; - gap: 9px; - border: 1px solid #594929; - color: #f1c875; - background: rgba(119, 88, 31, 0.11); - font: 600 8px/1.3 var(--mono); - letter-spacing: 0.07em; - text-transform: uppercase; +.event-annotations th, +.event-annotations td { + height: 39px; + padding: 0 15px; + border-bottom: 1px solid var(--line); + text-align: left; } -.metric-grid { - display: grid; - grid-template-columns: repeat(4, 1fr); - border: 1px solid var(--line); - background: rgba(10, 16, 21, 0.82); +.event-annotations th { + color: var(--ink-faint); + background: var(--paper-soft); + font-size: 10px; + font-weight: 600; } -.metric-grid article { - position: relative; - min-height: 150px; - padding: 22px; - border-right: 1px solid var(--line); +.event-annotations tbody tr:last-child td { + border-bottom: 0; } -.metric-grid article:last-child { - border-right: 0; +.event-annotations tr.is-observed td:first-child { + color: var(--blue); + font-weight: 600; } -.metric-grid article > strong { - display: block; - margin: 20px 0 11px; - color: var(--text-strong); - font: 560 clamp(28px, 3vw, 42px)/1 var(--mono); - letter-spacing: -0.06em; +.event-annotations td:last-child, +.event-annotations th:last-child { + width: 72px; + text-align: right; } -.metric-grid article p { - margin: 0; - color: var(--muted); - font: 500 9px/1.3 var(--mono); +.event-annotations td button { + padding: 4px 8px; + border: 1px solid var(--line-dark); + border-radius: 2px; + color: var(--blue); + background: var(--paper); + font-size: 10px; + cursor: pointer; } -.metric-grid article > i { - position: absolute; - right: 0; - bottom: -1px; - left: 0; - width: 0; - height: 3px; - background: var(--agent-color); - box-shadow: 0 0 12px color-mix(in srgb, var(--agent-color) 35%, transparent); - transition: width 220ms ease; +.event-annotations td button:disabled { + color: var(--ink-faint); + cursor: not-allowed; + opacity: 0.45; } .comparison-shell { - margin-top: 18px; - overflow-x: auto; - border: 1px solid var(--line); - background: rgba(10, 16, 21, 0.68); + border: 1px solid var(--line-dark); + background: var(--paper); } .comparison-table { - width: 100%; - min-width: 780px; - border-collapse: collapse; - color: #b8c5c9; - font: 500 10px/1.2 var(--mono); + min-width: 760px; } .comparison-table caption { @@ -1569,23 +902,23 @@ input[type="range"]::-moz-range-thumb { .comparison-table th, .comparison-table td { - height: 55px; - padding: 0 18px; + height: 50px; + padding: 0 16px; border-bottom: 1px solid var(--line); text-align: right; } .comparison-table thead th { - height: 37px; - color: var(--muted-deep); - background: #0a1217; - font-size: 7px; - letter-spacing: 0.1em; - text-transform: uppercase; + height: 39px; + color: var(--ink-faint); + background: var(--paper-soft); + font-size: 10px; + font-weight: 600; + letter-spacing: 0.03em; } .comparison-table th:first-child { - width: 32%; + width: 34%; text-align: left; } @@ -1594,16 +927,8 @@ input[type="range"]::-moz-range-thumb { border-bottom: 0; } -.comparison-table tbody tr { - transition: background 140ms ease; -} - -.comparison-table tbody tr:hover, -.comparison-table tbody tr.is-selected { - background: #101b21; -} - .comparison-table tbody tr.is-selected { + background: #f2f6fa; box-shadow: inset 3px 0 var(--agent-color); } @@ -1612,7 +937,7 @@ input[type="range"]::-moz-range-thumb { padding: 0; display: flex; align-items: center; - gap: 11px; + gap: 10px; border: 0; background: transparent; text-align: left; @@ -1621,7 +946,7 @@ input[type="range"]::-moz-range-thumb { .comparison-table th button > i { width: 8px; - height: 24px; + height: 26px; flex: 0 0 auto; } @@ -1633,189 +958,283 @@ input[type="range"]::-moz-range-thumb { } .comparison-table th button strong { - color: #d0dcdf; - font-size: 10px; + color: #282b2e; + font-size: 12px; + font-weight: 600; } .comparison-table th button small { - color: var(--muted-deep); - font: 7px/1 var(--mono); - letter-spacing: 0.07em; - text-transform: uppercase; + color: var(--ink-faint); + font-size: 10px; + font-weight: 400; } -.comparison-table td > strong { - color: var(--text-strong); +.table-note { + max-width: 860px; + margin: 14px 0 0; + color: var(--ink-soft); + font: 12px/1.6 var(--serif); } -.table-meter { - width: 70px; - height: 2px; - margin-left: 12px; - display: inline-block; - background: #213038; - vertical-align: middle; +.interpretation-section { + padding: 56px 0 62px; + display: grid; + grid-template-columns: 280px minmax(0, 1fr); + gap: 48px; + border-bottom: 1px solid var(--line-dark); } -.table-meter i { - display: block; - height: 100%; +.interpretation-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0; + border-top: 1px solid var(--line); } -.site-footer { - width: min(1600px, calc(100% - 48px)); - margin: 0 auto; - padding: 25px 0 32px; +.interpretation-grid article { + padding: 18px; + border-right: 1px solid var(--line); +} + +.interpretation-grid article:first-child { + padding-left: 0; +} + +.interpretation-grid article:last-child { + border-right: 0; +} + +.interpretation-grid h3 { + margin: 0 0 8px; + font: 600 13px/1.3 var(--sans); +} + +.interpretation-grid p { + margin: 0; + color: var(--ink-soft); + font: 13px/1.65 var(--serif); +} + +.paper-footer { + padding: 27px 0 50px; display: flex; - align-items: end; + align-items: flex-start; justify-content: space-between; - gap: 30px; - border-top: 1px solid var(--line); + gap: 32px; + color: var(--ink-faint); + font-size: 10px; } -.site-footer .system-label { - margin-bottom: 7px; +.paper-footer > div { + min-width: 0; + display: flex; + flex-direction: column; + gap: 6px; } -.site-footer code { - color: #7f9299; - font: 500 8px/1.4 var(--mono); - word-break: break-all; +.paper-footer code { + max-width: 680px; + overflow-wrap: anywhere; + color: var(--ink-soft); + font: 10px/1.5 var(--mono); } -.site-footer p { +.paper-footer p { margin: 0; - flex: 0 0 auto; - color: var(--muted-deep); - font: 600 7px/1.6 var(--mono); - letter-spacing: 0.08em; text-align: right; - text-transform: uppercase; } .loading-shell { min-height: 100vh; - padding: 40px; + padding: 30px; display: grid; place-content: center; + justify-items: center; text-align: center; } .loading-shell h1 { - margin: 0 0 13px; - color: var(--text-strong); - font-size: clamp(34px, 5vw, 58px); - font-weight: 560; - letter-spacing: -0.045em; + margin: 9px 0 0; + font: 500 34px/1.15 var(--serif); } -.loading-shell > p { - margin: 0; - color: var(--muted); +.loading-shell > p:not(.paper-label) { + max-width: 520px; + margin: 14px auto 0; + color: var(--ink-soft); } .loading-shell > a { - width: fit-content; - margin: 24px auto 0; - padding-bottom: 3px; - border-bottom: 1px solid var(--cyan); - color: var(--cyan); - font-size: 12px; + margin-top: 20px; + padding-bottom: 2px; + border-bottom: 1px solid var(--blue); + color: var(--blue); + font-size: 13px; +} + +.loading-rule { + width: 40px; + height: 2px; + margin-bottom: 24px; + background: var(--blue); + animation: loading 1.2s infinite ease-in-out; +} + +@keyframes loading { + 50% { width: 78px; opacity: 0.35; } +} + +@media (max-width: 980px) { + .operations-grid { + grid-template-columns: 1fr; + } + + .interpretation-section { + grid-template-columns: 1fr; + gap: 24px; + } } -.loading-pulse { - width: 12px; - height: 12px; - margin: 0 auto 28px; - border: 2px solid var(--cyan); - box-shadow: 0 0 18px rgba(86, 224, 193, 0.35); - animation: pulse 1.15s infinite ease-in-out; -} - -@keyframes pulse { - 50% { transform: rotate(45deg) scale(1.55); opacity: 0.4; } -} - -@media (max-width: 1260px) { - .agent-grid { grid-template-columns: repeat(3, 1fr); } - .agent-card:nth-child(3) { border-right: 0; } - .agent-card:nth-child(-n + 3) { border-bottom: 1px solid var(--line); } - .operations-grid { grid-template-columns: minmax(0, 1fr); } - .telemetry-console { position: static; } - .telemetry-console { display: grid; grid-template-columns: repeat(2, 1fr); } - .telemetry-console .console-header { grid-column: 1 / -1; } - .active-policy, .decision-readout, .battery-module, .state-grid { border-right: 1px solid var(--line); } - .event-log { grid-column: 1 / -1; } - .event-scroll { max-height: none; display: grid; grid-template-columns: repeat(2, 1fr); border-left: 1px solid var(--line); } - .event-row { border-right: 1px solid var(--line); } -} - -@media (max-width: 900px) { - .command-bar { padding: 0 18px; } - .command-meta > span:not(.demo-status) { display: none; } - .command-divider { display: none; } - .shell-content { padding: 0 18px 64px; } - .mission-intro { grid-template-columns: 1fr; gap: 30px; padding-top: 40px; } - .mission-intro h1 { font-size: clamp(43px, 10vw, 70px); } - .zone-rail { overflow-x: auto; grid-template-columns: repeat(5, minmax(145px, 1fr)); } - .warehouse-map { min-height: 0; } - .timeline-console { grid-template-columns: 115px minmax(0, 1fr) 58px; gap: 12px; } - .metric-grid { grid-template-columns: repeat(2, 1fr); } - .metric-grid article:nth-child(2) { border-right: 0; } - .metric-grid article:nth-child(-n + 2) { border-bottom: 1px solid var(--line); } - .evidence-heading { align-items: flex-start; flex-direction: column; } -} - -@media (max-width: 640px) { - .command-bar { height: 60px; } - .brand-lockup small { display: none; } - .command-meta { gap: 10px; } - .command-meta > span.demo-status { font-size: 0; } - .command-meta > span.demo-status::after { content: "Non-confirmatory demo"; font-size: 8px; } - .shell-content { padding: 0 12px 52px; } - .mission-intro { padding: 34px 4px 28px; } - .mission-intro h1 { font-size: clamp(38px, 13vw, 58px); } - .intro-brief dl { grid-template-columns: 1fr 1fr; } - .intro-brief dl div { padding: 11px 8px; border-bottom: 1px solid var(--line); } - .intro-brief dl div:nth-child(even) { border-right: 0; } - .section-kicker { grid-template-columns: 1fr auto; } - .section-kicker > span { grid-column: 1 / -1; } - .agent-grid { grid-template-columns: repeat(2, 1fr); } - .agent-card { min-height: 88px; padding: 14px 12px 17px; grid-template-columns: 22px minmax(0, 1fr) auto; } - .agent-card:nth-child(2n) { border-right: 0; } - .agent-card:nth-child(3) { border-right: 1px solid var(--line); } - .agent-card:nth-child(-n + 4) { border-bottom: 1px solid var(--line); } - .agent-progress { left: 43px; right: 12px; } - .console-header { padding: 14px; } - .console-header h2 { font-size: 14px; } - .tick-readout { display: block; text-align: right; } - .tick-readout span { display: block; margin-bottom: 5px; } - .tick-readout strong { font-size: 20px; } - .map-wrap { padding: 8px; } - .warehouse-map { min-height: 0; padding: 10px; } - .route-layer { inset: 10px; } - .map-grid, .route-layer { gap: 2px; } - .route-north { top: -2px; } - .route-west { left: -2px; } - .order-marker { width: 15px; height: 15px; font-size: 6px; } - .rack-label, .zone-tag { display: none; } - .robot { width: 70%; min-width: 0; border-width: 1px; border-radius: 4px; } - .robot::before, .robot::after, .robot b, .robot-status { display: none; } - .map-legend { justify-content: flex-start; } - .timeline-console { grid-template-columns: auto 1fr auto; padding: 12px; } - .transport-controls > div { display: none; } - .play-button { width: 38px; height: 38px; } - .timeline-labels strong { display: none; } - .telemetry-console { display: block; } - .active-policy, .decision-readout, .battery-module, .state-grid { border-right: 0; } - .event-scroll { display: block; border-left: 0; } - .event-row { border-right: 0; } - .evidence-section { padding-top: 58px; } - .evidence-heading h2 { font-size: 36px; } - .metric-grid article { min-height: 135px; padding: 17px; } - .metric-grid article > strong { margin-top: 18px; font-size: 27px; } - .site-footer { width: calc(100% - 24px); display: block; } - .site-footer p { margin-top: 18px; text-align: left; } +@media (max-width: 720px) { + .site-header, + .research-page { + width: min(100% - 28px, 1220px); + } + + .site-header nav { + gap: 14px; + } + + .site-header nav a:not(:last-child) { + display: none; + } + + .paper-header { + padding: 45px 0 40px; + } + + .paper-header h1 { + font-size: clamp(36px, 11vw, 50px); + } + + .abstract-copy { + font-size: 16px; + } + + .study-metadata { + grid-template-columns: repeat(2, 1fr); + } + + .study-metadata > div, + .study-metadata > div:first-child { + padding-left: 10px; + border-right: 1px solid var(--line); + border-bottom: 1px solid var(--line); + } + + .study-metadata > div:nth-child(2n) { + border-right: 0; + } + + .study-metadata > div:last-child { + border-bottom: 0; + } + + .viewer-section, + .results-section { + padding: 43px 0 48px; + } + + .section-heading { + align-items: stretch; + flex-direction: column; + gap: 20px; + } + + .algorithm-select { + min-width: 0; + } + + .map-wrap { + padding: 8px; + } + + .warehouse-map { + padding: 8px; + } + + .route-layer { + inset: 8px; + } + + .map-grid, + .route-layer { + gap: 1px; + } + + .rack-label, + .zone-tag, + .charger { + display: none; + } + + .order-marker { + width: 14px; + height: 14px; + font-size: 6px; + } + + .robot-marker { + width: 70%; + min-width: 0; + border-width: 1px; + font-size: 6px; + } + + .closure-marker { + inset: 1px; + font-size: 11px; + } + + .replay-controls { + grid-template-columns: 1fr auto; + } + + .timeline-control { + grid-column: 1 / -1; + grid-row: 1; + } + + .state-panel { + display: block; + } + + .method-workload { + margin-top: 20px; + } + + .interpretation-grid { + grid-template-columns: 1fr; + } + + .interpretation-grid article, + .interpretation-grid article:first-child { + padding: 14px 0; + border-right: 0; + border-bottom: 1px solid var(--line); + } + + .interpretation-grid article:last-child { + border-bottom: 0; + } + + .paper-footer { + flex-direction: column; + } + + .paper-footer p { + text-align: left; + } } @media (prefers-reduced-motion: reduce) { @@ -1823,16 +1242,17 @@ input[type="range"]::-moz-range-thumb { *::before, *::after { scroll-behavior: auto !important; - transition: none !important; - animation: none !important; + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; } } @media (forced-colors: active) { - .agent-card.is-active, - .comparison-table tbody tr.is-selected, - .map-cell.blocked { - outline: 2px solid Highlight; - outline-offset: -2px; + .route-node, + .route-branch, + .method-swatch, + .comparison-table th button > i { + background: CanvasText !important; } } diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 8cabbe3..1e1cdc2 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -14,9 +14,9 @@ export async function generateMetadata(): Promise { return { metadataBase: new URL(pagesBasePath, `${origin}/`), - title: "Adaptive Agent Lab — Planning × Learning", + title: "Adaptive Agent Lab — Planning and Learning in Dynamic Warehouses", description: - "Replay six planning, reinforcement-learning, and hybrid controllers inside a dynamic warehouse maze.", + "An interactive, non-confirmatory research artifact for comparing planning and learning controllers in a dynamic warehouse maze.", applicationName: "Adaptive Agent Lab", keywords: [ "reinforcement learning", @@ -33,31 +33,31 @@ export async function generateMetadata(): Promise { type: "website", url: "./", siteName: "Adaptive Agent Lab", - title: "Adaptive Agent Lab — Warehouse Autonomy Replay", + title: "Adaptive Agent Lab — Planning × Learning", description: - "Inspect how six controllers navigate the same orders, rack maze, and dynamic aisle closures.", + "A paired-episode research replay for six controllers in a dynamic warehouse maze.", images: [ { url: "./og.png", - width: 1731, - height: 909, - alt: "Adaptive Agent Lab warehouse autonomy control room", + width: 1536, + height: 1024, + alt: "Academic graphical abstract showing a robot trajectory through a warehouse maze", }, ], }, twitter: { card: "summary_large_image", - title: "Adaptive Agent Lab — Warehouse Autonomy Replay", + title: "Adaptive Agent Lab — Planning × Learning", description: - "Planning and reinforcement learning under identical warehouse disruptions.", + "A paired-episode research replay for planning and reinforcement learning.", images: ["./og.png"], }, }; } export const viewport: Viewport = { - colorScheme: "dark", - themeColor: "#070b0f", + colorScheme: "light", + themeColor: "#f6f6f3", }; export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { diff --git a/web/app/page.tsx b/web/app/page.tsx index d9ceb2e..69813ba 100644 --- a/web/app/page.tsx +++ b/web/app/page.tsx @@ -78,27 +78,27 @@ const actionLabels: Record = { down: "Move south", left: "Move west", right: "Move east", - pickup: "Secure payload", - dropoff: "Complete dispatch", - charge: "Recharge at dock", - wait: "Hold position", + pickup: "Pick up order", + dropoff: "Deliver order", + charge: "Recharge", + wait: "Wait", }; const eventLabels: Record = { order_arrival: "Order released", - cell_blocked: "Aisle closure", + cell_blocked: "Aisle closed", cell_unblocked: "Aisle reopened", }; const cellKey = (point: Point) => `${point.x}:${point.y}`; const rackIslandLabels = new Map([ - ["2:2", "R01"], - ["2:7", "R02"], - ["6:2", "R03"], - ["6:7", "R04"], - ["10:2", "R05"], - ["10:7", "R06"], + ["2:2", "R1"], + ["2:7", "R2"], + ["6:2", "R3"], + ["6:7", "R4"], + ["10:2", "R5"], + ["10:7", "R6"], ]); function blockedCells(events: Event[], time: number) { @@ -198,10 +198,9 @@ function RouteLayer({ export default function Home() { const [data, setData] = useState(null); const [error, setError] = useState(null); - const [agentId, setAgentId] = useState("replanning"); + const [agentId, setAgentId] = useState("hybrid"); const [frame, setFrame] = useState(0); const [playing, setPlaying] = useState(false); - const [speed, setSpeed] = useState(1); useEffect(() => { fetch("./demo-data.json") @@ -238,9 +237,9 @@ export default function Home() { } return current + 1; }); - }, 700 / speed); + }, 560); return () => window.clearInterval(timer); - }, [playing, maximumFrame, speed]); + }, [playing, maximumFrame]); const currentStep = agent?.trace[Math.min(frame, maximumFrame)] ?? null; const currentTime = currentStep?.time ?? 0; @@ -251,10 +250,10 @@ export default function Home() { if (error) { return (
- System / artifact error -

Mission replay unavailable.

+

Artifact error

+

Replay unavailable

{error}

- Inspect the project on GitHub + Open the repository
); } @@ -262,9 +261,9 @@ export default function Home() { if (!data || !agent || !currentStep) { return (
-
); } @@ -286,13 +285,13 @@ export default function Home() { const traceEndTime = agent.trace[maximumFrame]?.time ?? data.scenario.horizon; const completedPercent = maximumFrame ? (frame / maximumFrame) * 100 : 100; const activeStyle = { "--agent-color": agent.color } as CSSProperties; - const unitStatus = currentStep.violations.length - ? { label: "Constraint alert", tone: "alert" } + const stateStatus = currentStep.violations.length + ? { label: "Constraint violation recorded", tone: "alert" } : currentStep.battery <= 0 ? { label: "Battery depleted", tone: "alert" } : batteryPercent <= 20 - ? { label: "Energy low", tone: "warning" } - : { label: "Nominal", tone: "nominal" }; + ? { label: "Low battery", tone: "warning" } + : { label: "No active constraint flag", tone: "neutral" }; const orderState = (order: Order): OrderState => { if (deliveredOrderIds.has(order.id)) return "delivered"; @@ -302,6 +301,11 @@ export default function Home() { return "ready"; }; + const orderStates = data.scenario.orders.map(orderState); + const deliveredOrderCount = orderStates.filter((state) => state === "delivered").length; + const expiredOrderCount = orderStates.filter((state) => state === "expired").length; + const carriedOrderCount = orderStates.filter((state) => state === "carried").length; + const seekToTime = (time: number) => { const nextFrame = agent.trace.findIndex((step) => step.time >= time); setPlaying(false); @@ -309,375 +313,340 @@ export default function Home() { }; return ( -
-
- - - - Adaptive Agent Lab - Warehouse autonomy testbed - - -
- {data.verificationStatus} -
+
+
+ Adaptive Agent Lab +
-
-
-
-

Mission control / paired episode 0042

-

Dynamic warehouse
adaptation replay

-
-
-

- Six controllers enter the same maze of racks, orders, and recorded aisle closures. - Replay the committed trajectory and inspect how each policy responds. -

-
-
World
{data.scenario.width} × {data.scenario.height}
-
Orders
{data.scenario.orders.length}
-
Disruptions
{data.scenario.events.filter((event) => event.kind !== "order_arrival").length}
-
Horizon
T+{data.scenario.horizon}
-
-
-
- -
-
- 01 / controller matrix -

Select an autonomy stack

-

Demo-only weighted completion

+
+
+

Interactive research artifact · {data.scenario.id}

+

Planning and learning in a dynamic warehouse maze

+

+ This page replays six planning, reinforcement-learning, and hybrid controllers on one + shared warehouse episode. Use the viewer to inspect trajectories and state transitions + under the same order releases and temporary aisle closures. +

+
+ Interpretation. {data.verificationStatus}. The values below describe a + committed demonstration tape; they are not a held-out benchmark or an algorithm ranking.
-
- {data.agents.map((candidate, index) => ( - - ))} +
+
Grid
{data.scenario.width} × {data.scenario.height}
+
Controllers
{data.agents.length}
+
Orders
{data.scenario.orders.length}
+
Event records
{data.scenario.events.length}
+
Horizon
t = {data.scenario.horizon}
+
+
+ +
+
+
+

01

+

Paired-episode replay

+

All controllers use the same scenario and recorded event schedule.

+
+
-
-
-
-
-
-

02 / recorded floor replay

-

Warehouse Maze / Floor 07

-
-
- Simulation tick - T+{String(currentTime).padStart(3, "0")} -
-
- -
- Receiving R01 - Rack maze S02 - Packing P03 - Dispatch D04 - Charging C05 -
+
+
+
+
+ Figure 1 +

Scenario trajectory

+
+

+ t = {currentTime} / {traceEndTime} +

+
-
-
+
- -
-
-
- AMR-01 - travelled route - recorded route - pickup - drop-off - dynamic closure -
+
+ robot + observed path + remaining recorded path + pickup + drop-off + closure + delivered + expired +
-
-
+
-
Replay{playing ? "RUNNING" : frame >= maximumFrame ? "COMPLETE" : "PAUSED"}
-
-
-
T+001Event tapeT+{String(traceEndTime).padStart(3, "0")}
-
- { - setPlaying(false); - setFrame(Number(event.target.value)); - }} - /> -
- {data.scenario.events - .filter((event) => event.time <= traceEndTime) - .map((event, index) => ( -
+
- -
-
-