| |
| :root { |
| --color-room: #E69F00; |
| --color-door: #009E73; |
| --color-corridor: #CC79A7; |
| --color-outside: #56B4E9; |
| --color-transition: #D55E00; |
|
|
| --bg-primary: #f8f9fa; |
| --bg-card: #ffffff; |
| --bg-sidebar: #ffffff; |
| --border-color: #dee2e6; |
| --text-primary: #212529; |
| --text-secondary: #6c757d; |
| --accent: #0d6efd; |
| --accent-hover: #0b5ed7; |
|
|
| --sidebar-width: 320px; |
| } |
|
|
| |
| *, |
| *::before, |
| *::after { |
| box-sizing: border-box; |
| margin: 0; |
| padding: 0; |
| } |
|
|
| body { |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, |
| 'Helvetica Neue', Arial, sans-serif; |
| background: var(--bg-primary); |
| color: var(--text-primary); |
| line-height: 1.5; |
| } |
|
|
| |
| .app { |
| display: flex; |
| flex-direction: column; |
| height: 100vh; |
| overflow: hidden; |
| } |
|
|
| |
| .header { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| padding: 12px 24px; |
| background: var(--bg-card); |
| border-bottom: 1px solid var(--border-color); |
| flex-shrink: 0; |
| } |
|
|
| .header h1 { |
| font-size: 1.25rem; |
| font-weight: 700; |
| letter-spacing: -0.01em; |
| } |
|
|
| .header h1 span { |
| color: var(--accent); |
| } |
|
|
| .header-subtitle { |
| font-size: 0.8rem; |
| color: var(--text-secondary); |
| } |
|
|
| |
| .main-content { |
| flex: 1; |
| display: flex; |
| overflow: hidden; |
| } |
|
|
| |
| .results-layout { |
| display: flex; |
| width: 100%; |
| height: 100%; |
| } |
|
|
| .graph-area { |
| flex: 1; |
| position: relative; |
| background: #fff; |
| overflow: hidden; |
| } |
|
|
| .sidebar { |
| width: var(--sidebar-width); |
| min-width: var(--sidebar-width); |
| background: var(--bg-sidebar); |
| overflow-y: auto; |
| padding: 16px; |
| display: flex; |
| flex-direction: column; |
| gap: 16px; |
| } |
|
|
| .sidebar-left { |
| border-right: 1px solid var(--border-color); |
| } |
|
|
| .sidebar-right { |
| border-left: 1px solid var(--border-color); |
| } |
|
|
| |
| .panel { |
| background: var(--bg-card); |
| border: 1px solid var(--border-color); |
| border-radius: 8px; |
| padding: 16px; |
| } |
|
|
| .panel h3 { |
| font-size: 0.85rem; |
| font-weight: 600; |
| text-transform: uppercase; |
| letter-spacing: 0.04em; |
| color: var(--text-secondary); |
| margin-bottom: 12px; |
| } |
|
|
| |
| .upload-container { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: flex-start; |
| width: 100%; |
| height: 100%; |
| padding: 48px 40px; |
| overflow-y: auto; |
| } |
|
|
| |
| .intro { |
| text-align: center; |
| max-width: 680px; |
| margin-bottom: 28px; |
| } |
|
|
| .intro-title { |
| font-size: 2rem; |
| font-weight: 700; |
| letter-spacing: -0.02em; |
| margin-bottom: 14px; |
| } |
|
|
| .intro-title span { |
| color: var(--accent); |
| } |
|
|
| .intro-abstract { |
| font-size: 0.95rem; |
| color: var(--text-secondary); |
| line-height: 1.6; |
| } |
|
|
| .intro-footer { |
| margin-top: 36px; |
| padding-bottom: 8px; |
| font-size: 0.8rem; |
| color: var(--text-secondary); |
| text-align: center; |
| } |
|
|
| .intro-footer a { |
| color: var(--accent); |
| text-decoration: none; |
| } |
|
|
| .intro-footer a:hover { |
| text-decoration: underline; |
| } |
|
|
| .dropzone { |
| width: 100%; |
| max-width: 600px; |
| border: 2px dashed var(--border-color); |
| border-radius: 12px; |
| padding: 48px 32px; |
| text-align: center; |
| cursor: pointer; |
| transition: border-color 0.2s, background 0.2s; |
| } |
|
|
| .dropzone:hover, |
| .dropzone.drag-over { |
| border-color: var(--accent); |
| background: rgba(13, 110, 253, 0.04); |
| } |
|
|
| .dropzone-icon { |
| display: block; |
| margin: 0 auto 14px; |
| color: var(--accent); |
| opacity: 0.85; |
| transition: transform 0.2s, opacity 0.2s; |
| } |
|
|
| .dropzone:hover .dropzone-icon, |
| .dropzone.drag-over .dropzone-icon { |
| opacity: 1; |
| transform: translateY(-2px); |
| } |
|
|
| .dropzone-text { |
| font-size: 1rem; |
| color: var(--text-secondary); |
| margin-bottom: 8px; |
| } |
|
|
| .dropzone-sub { |
| font-size: 0.8rem; |
| color: var(--text-secondary); |
| } |
|
|
| |
| .examples-section { |
| margin-top: 32px; |
| width: 100%; |
| max-width: 600px; |
| } |
|
|
| .examples-section h2 { |
| font-size: 0.95rem; |
| font-weight: 600; |
| margin-bottom: 16px; |
| color: var(--text-primary); |
| } |
|
|
| .example-grid { |
| display: grid; |
| grid-template-columns: repeat(3, minmax(0, 1fr)); |
| gap: 14px; |
| } |
|
|
| .example-card { |
| position: relative; |
| border: 1px solid var(--border-color); |
| border-radius: 8px; |
| overflow: hidden; |
| cursor: pointer; |
| transition: box-shadow 0.2s, border-color 0.2s; |
| background: var(--bg-card); |
| } |
|
|
| .example-card:hover { |
| border-color: var(--accent); |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); |
| } |
|
|
| .example-card img { |
| width: 100%; |
| height: 100px; |
| object-fit: cover; |
| display: block; |
| } |
|
|
| .example-card-info { |
| padding: 8px 10px; |
| } |
|
|
| .example-card-name { |
| font-size: 0.78rem; |
| font-weight: 500; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| } |
|
|
| .example-card-meta { |
| font-size: 0.7rem; |
| color: var(--text-secondary); |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-top: 4px; |
| } |
|
|
| .cached-badge { |
| background: #d4edda; |
| color: #155724; |
| font-size: 0.65rem; |
| font-weight: 600; |
| padding: 1px 6px; |
| border-radius: 4px; |
| } |
|
|
| |
| .processing-overlay { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: center; |
| width: 100%; |
| height: 100%; |
| gap: 16px; |
| } |
|
|
| .spinner { |
| width: 48px; |
| height: 48px; |
| border: 4px solid var(--border-color); |
| border-top-color: var(--accent); |
| border-radius: 50%; |
| animation: spin 0.8s linear infinite; |
| } |
|
|
| @keyframes spin { |
| to { transform: rotate(360deg); } |
| } |
|
|
| .processing-text { |
| font-size: 1rem; |
| color: var(--text-secondary); |
| } |
|
|
| .processing-stage { |
| font-size: 0.85rem; |
| color: var(--accent); |
| font-weight: 500; |
| } |
|
|
| |
| .error-container { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: center; |
| width: 100%; |
| height: 100%; |
| gap: 12px; |
| } |
|
|
| .error-message { |
| color: #dc3545; |
| font-size: 0.95rem; |
| max-width: 400px; |
| text-align: center; |
| } |
|
|
| |
| .type-toggle { |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| padding: 4px 0; |
| } |
|
|
| .type-toggle label { |
| font-size: 0.82rem; |
| cursor: pointer; |
| display: flex; |
| align-items: center; |
| gap: 6px; |
| } |
|
|
| .type-swatch { |
| display: inline-block; |
| width: 12px; |
| height: 12px; |
| border-radius: 3px; |
| } |
|
|
| |
| .type-control-group { |
| padding: 2px 0; |
| } |
|
|
| .size-slider { |
| display: flex; |
| align-items: center; |
| gap: 6px; |
| padding-left: 24px; |
| } |
|
|
| .size-slider input[type="range"] { |
| flex: 1; |
| height: 4px; |
| -webkit-appearance: none; |
| appearance: none; |
| background: var(--border-color); |
| border-radius: 2px; |
| outline: none; |
| } |
|
|
| .size-slider input[type="range"]::-webkit-slider-thumb { |
| -webkit-appearance: none; |
| width: 14px; |
| height: 14px; |
| border-radius: 50%; |
| background: var(--accent); |
| cursor: pointer; |
| } |
|
|
| .size-slider input[type="range"]::-moz-range-thumb { |
| width: 14px; |
| height: 14px; |
| border-radius: 50%; |
| background: var(--accent); |
| cursor: pointer; |
| border: none; |
| } |
|
|
| .size-value { |
| font-size: 0.72rem; |
| color: var(--text-secondary); |
| min-width: 20px; |
| text-align: right; |
| } |
|
|
| |
| .stat-row { |
| display: flex; |
| justify-content: space-between; |
| padding: 4px 0; |
| font-size: 0.82rem; |
| } |
|
|
| .stat-row .label { |
| color: var(--text-secondary); |
| } |
|
|
| .stat-row .value { |
| font-weight: 600; |
| } |
|
|
| .stat-divider { |
| border: none; |
| border-top: 1px solid var(--border-color); |
| margin: 8px 0; |
| } |
|
|
| |
| .export-buttons { |
| display: flex; |
| gap: 8px; |
| } |
|
|
| .btn { |
| padding: 8px 16px; |
| border: 1px solid var(--border-color); |
| border-radius: 6px; |
| background: var(--bg-card); |
| cursor: pointer; |
| font-size: 0.82rem; |
| font-weight: 500; |
| transition: background 0.15s, border-color 0.15s; |
| } |
|
|
| .btn:hover { |
| background: var(--bg-primary); |
| border-color: var(--accent); |
| } |
|
|
| .btn-primary { |
| background: var(--accent); |
| color: #fff; |
| border-color: var(--accent); |
| } |
|
|
| .btn-primary:hover { |
| background: var(--accent-hover); |
| } |
|
|
| .btn-block { |
| width: 100%; |
| } |
|
|
| |
| .node-tooltip { |
| position: absolute; |
| z-index: 1000; |
| background: rgba(33, 37, 41, 0.95); |
| color: #fff; |
| padding: 8px 12px; |
| border-radius: 6px; |
| font-size: 0.75rem; |
| line-height: 1.5; |
| pointer-events: none; |
| max-width: 220px; |
| white-space: nowrap; |
| } |
|
|
| .tooltip-type { |
| font-weight: 600; |
| text-transform: capitalize; |
| } |
|
|
| |
| .stage-label { |
| font-size: 0.78rem; |
| font-weight: 500; |
| color: var(--text-secondary); |
| display: block; |
| margin-bottom: 6px; |
| } |
|
|
| .stage-toggle { |
| display: flex; |
| gap: 0; |
| border: 1px solid var(--border-color); |
| border-radius: 6px; |
| overflow: hidden; |
| } |
|
|
| .stage-btn { |
| flex: 1; |
| padding: 6px 12px; |
| font-size: 0.78rem; |
| font-weight: 500; |
| border: none; |
| background: var(--bg-card); |
| cursor: pointer; |
| transition: background 0.15s, color 0.15s; |
| color: var(--text-secondary); |
| } |
|
|
| .stage-btn:not(:last-child) { |
| border-right: 1px solid var(--border-color); |
| } |
|
|
| .stage-btn.active { |
| background: var(--accent); |
| color: #fff; |
| } |
|
|
| .stage-btn:hover:not(.active) { |
| background: var(--bg-primary); |
| } |
|
|
| |
| .back-btn-row { |
| padding: 8px 0; |
| } |
|
|
| |
| .route-hint { |
| font-size: 0.72rem; |
| color: var(--text-secondary); |
| margin-bottom: 12px; |
| line-height: 1.4; |
| } |
|
|
| .route-field { |
| display: flex; |
| align-items: center; |
| gap: 6px; |
| font-size: 0.78rem; |
| font-weight: 500; |
| margin-bottom: 8px; |
| } |
|
|
| .route-dot { |
| display: inline-block; |
| width: 10px; |
| height: 10px; |
| border-radius: 50%; |
| flex-shrink: 0; |
| } |
|
|
| .route-select { |
| flex: 1; |
| min-width: 0; |
| padding: 5px 8px; |
| font-size: 0.78rem; |
| border: 1px solid var(--border-color); |
| border-radius: 6px; |
| background: var(--bg-card); |
| color: var(--text-primary); |
| cursor: pointer; |
| } |
|
|
| .route-select:focus { |
| outline: none; |
| border-color: var(--accent); |
| } |
|
|
| .route-buttons { |
| display: flex; |
| gap: 8px; |
| margin-top: 4px; |
| } |
|
|
| .route-buttons .btn { |
| flex: 1; |
| } |
|
|
| .route-buttons .btn:disabled { |
| opacity: 0.5; |
| cursor: not-allowed; |
| } |
|
|
| .route-result { |
| margin-top: 12px; |
| padding: 10px 12px; |
| border: 1px solid var(--border-color); |
| border-left: 3px solid var(--accent); |
| border-radius: 6px; |
| background: var(--bg-primary); |
| } |
|
|
| .route-result-fail { |
| border-left-color: #dc3545; |
| font-size: 0.78rem; |
| color: #dc3545; |
| } |
|
|
| .route-result-row { |
| display: flex; |
| justify-content: space-between; |
| font-size: 0.8rem; |
| padding: 2px 0; |
| } |
|
|
| .route-result-row .label { |
| color: var(--text-secondary); |
| } |
|
|
| .route-result-row .value { |
| font-weight: 600; |
| } |
|
|
| .route-badge { |
| display: inline-block; |
| margin-top: 6px; |
| background: #fde2d4; |
| color: #8a3b12; |
| font-size: 0.68rem; |
| font-weight: 600; |
| padding: 2px 8px; |
| border-radius: 4px; |
| } |
|
|
| |
| .header-left { |
| display: flex; |
| align-items: center; |
| gap: 14px; |
| } |
|
|
| .back-btn { |
| display: inline-flex; |
| align-items: center; |
| gap: 4px; |
| padding: 6px 12px; |
| border: 1px solid var(--border-color); |
| border-radius: 6px; |
| background: var(--bg-card); |
| cursor: pointer; |
| font-size: 0.82rem; |
| font-weight: 500; |
| transition: background 0.15s, border-color 0.15s; |
| } |
|
|
| .back-btn:hover { |
| background: var(--bg-primary); |
| border-color: var(--accent); |
| } |
|
|
| .back-arrow { |
| font-size: 1.1rem; |
| line-height: 1; |
| } |
|
|
| |
| .panel-collapse-header { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| width: 100%; |
| background: none; |
| border: none; |
| padding: 0; |
| margin: 0; |
| cursor: pointer; |
| } |
|
|
| .panel-collapse-header h3 { |
| margin-bottom: 0; |
| } |
|
|
| .panel-collapse-header .chevron { |
| color: var(--text-secondary); |
| transition: transform 0.18s; |
| font-size: 1rem; |
| } |
|
|
| .panel-collapse-header .chevron.open { |
| transform: rotate(90deg); |
| } |
|
|
| .panel-collapse-body { |
| margin-top: 12px; |
| } |
|
|
| .stat-image { |
| max-width: 150px; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| } |
|
|
| |
| .opacity-slider { |
| padding-left: 0; |
| margin-top: 6px; |
| } |
|
|
| .opacity-label { |
| font-size: 0.72rem; |
| color: var(--text-secondary); |
| min-width: 48px; |
| } |
|
|
| |
| .canvas-toolbar { |
| position: absolute; |
| right: 14px; |
| bottom: 14px; |
| display: flex; |
| align-items: center; |
| gap: 4px; |
| background: rgba(255, 255, 255, 0.95); |
| border: 1px solid var(--border-color); |
| border-radius: 8px; |
| padding: 4px; |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12); |
| z-index: 50; |
| } |
|
|
| .zoom-btn { |
| min-width: 30px; |
| height: 30px; |
| padding: 0 8px; |
| border: none; |
| border-radius: 6px; |
| background: transparent; |
| cursor: pointer; |
| font-size: 1.1rem; |
| font-weight: 600; |
| color: var(--text-primary); |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| } |
|
|
| .zoom-btn:hover { |
| background: var(--bg-primary); |
| } |
|
|
| .zoom-btn.fit-btn { |
| font-size: 0.8rem; |
| font-weight: 600; |
| border-left: 1px solid var(--border-color); |
| margin-left: 2px; |
| } |
|
|
| .zoom-readout { |
| font-size: 0.74rem; |
| color: var(--text-secondary); |
| min-width: 42px; |
| text-align: center; |
| } |
|
|
| |
| .mode-banner { |
| position: absolute; |
| top: 14px; |
| left: 50%; |
| transform: translateX(-50%); |
| background: var(--accent); |
| color: #fff; |
| padding: 7px 16px; |
| border-radius: 999px; |
| font-size: 0.8rem; |
| font-weight: 500; |
| box-shadow: 0 2px 8px rgba(13, 110, 253, 0.3); |
| z-index: 50; |
| pointer-events: none; |
| } |
|
|
| |
| .route-pick { |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| margin-bottom: 8px; |
| } |
|
|
| .route-pick-btn { |
| display: inline-flex; |
| align-items: center; |
| gap: 6px; |
| flex: 0 0 auto; |
| min-width: 130px; |
| } |
|
|
| .route-pick-btn.arming { |
| background: var(--accent); |
| color: #fff; |
| border-color: var(--accent); |
| } |
|
|
| .route-current { |
| font-size: 0.78rem; |
| color: var(--text-secondary); |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| } |
|
|
| .route-advanced { |
| margin-top: 10px; |
| } |
|
|
| .route-advanced summary { |
| font-size: 0.74rem; |
| color: var(--text-secondary); |
| cursor: pointer; |
| margin-bottom: 8px; |
| } |
|
|
| |
| .edit-tools { |
| display: flex; |
| gap: 6px; |
| margin-bottom: 6px; |
| } |
|
|
| .edit-tool { |
| flex: 1; |
| padding: 7px 6px; |
| border: 1px solid var(--border-color); |
| border-radius: 6px; |
| background: var(--bg-card); |
| cursor: pointer; |
| font-size: 0.78rem; |
| font-weight: 500; |
| transition: background 0.15s, color 0.15s, border-color 0.15s; |
| } |
|
|
| .edit-tool:hover { |
| border-color: var(--accent); |
| } |
|
|
| .edit-tool.active { |
| background: var(--accent); |
| color: #fff; |
| border-color: var(--accent); |
| } |
|
|
| .edit-nodetype { |
| margin-top: 10px; |
| } |
|
|
| .nodetype-grid { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: 6px; |
| margin-top: 6px; |
| } |
|
|
| .nodetype-chip { |
| display: inline-flex; |
| align-items: center; |
| gap: 6px; |
| padding: 6px 8px; |
| border: 1px solid var(--border-color); |
| border-radius: 6px; |
| background: var(--bg-card); |
| cursor: pointer; |
| font-size: 0.74rem; |
| transition: border-color 0.15s, background 0.15s; |
| } |
|
|
| .nodetype-chip.active { |
| border-color: var(--accent); |
| background: rgba(13, 110, 253, 0.06); |
| font-weight: 600; |
| } |
|
|
| .edit-hint { |
| margin-top: 10px; |
| padding: 8px 10px; |
| background: var(--bg-primary); |
| border-left: 3px solid var(--accent); |
| border-radius: 6px; |
| font-size: 0.76rem; |
| color: var(--text-primary); |
| } |
|
|
| .edit-undo-note { |
| margin-top: 10px; |
| font-size: 0.7rem; |
| color: var(--text-secondary); |
| line-height: 1.4; |
| } |
|
|
| |
| .conn-ok { |
| color: #1a7f37; |
| font-weight: 700; |
| margin-left: 4px; |
| } |
|
|
| .conn-warn { |
| border: none; |
| background: none; |
| cursor: pointer; |
| color: #d39e00; |
| font-size: 0.95rem; |
| margin-left: 4px; |
| padding: 0 2px; |
| line-height: 1; |
| } |
|
|
| .conn-warn:hover { |
| color: #b8860b; |
| } |
|
|
| .conn-list { |
| margin: 6px 0 4px; |
| padding: 8px; |
| background: #fff8e6; |
| border: 1px solid #f0d98c; |
| border-radius: 6px; |
| } |
|
|
| .conn-list-title { |
| font-size: 0.72rem; |
| color: #7a5b00; |
| margin-bottom: 6px; |
| line-height: 1.4; |
| } |
|
|
| .conn-node { |
| display: inline-flex; |
| align-items: center; |
| gap: 6px; |
| width: 100%; |
| text-align: left; |
| border: none; |
| background: none; |
| cursor: pointer; |
| font-size: 0.74rem; |
| color: var(--text-primary); |
| padding: 3px 4px; |
| border-radius: 4px; |
| } |
|
|
| .conn-node:hover { |
| background: rgba(0, 0, 0, 0.05); |
| } |
|
|
| .conn-more { |
| font-size: 0.7rem; |
| color: var(--text-secondary); |
| margin-top: 4px; |
| padding-left: 4px; |
| } |
|
|
| .conn-flag { |
| color: #b02a37; |
| font-weight: 700; |
| } |
|
|
| .conn-locate { |
| margin-top: 4px; |
| font-style: italic; |
| } |
|
|
| .conn-node-id { |
| flex: 1; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| } |
|
|
| .conn-reason { |
| font-size: 0.64rem; |
| font-weight: 600; |
| padding: 1px 6px; |
| border-radius: 4px; |
| flex-shrink: 0; |
| } |
|
|
| .conn-reason-isolated { |
| background: #f8d7da; |
| color: #842029; |
| } |
|
|
| .conn-reason-room { |
| background: #fff3cd; |
| color: #664d03; |
| } |
|
|
| .conn-reason-exit { |
| background: #cfe2ff; |
| color: #084298; |
| } |
|
|