chore: remove unused files
This commit is contained in:
parent
6e1781926e
commit
35155e6597
|
|
@ -1,434 +0,0 @@
|
||||||
/* ── Toolbar container ──────────────────────────────────────────────────────
|
|
||||||
* Single-row layout: [left actions] [file tabs flex] [right actions]
|
|
||||||
* The center slot (file tabs) flex-grows and scrolls horizontally so the
|
|
||||||
* action icons on either side stay pinned and visible no matter how narrow
|
|
||||||
* the editor pane gets when the user drags the editor/canvas divider.
|
|
||||||
*
|
|
||||||
* Uses CSS container queries so the Libraries label collapses based on the
|
|
||||||
* toolbar's *own* width (not the viewport) — which is what changes when the
|
|
||||||
* user drags the editor/canvas divider.
|
|
||||||
*/
|
|
||||||
.editor-toolbar-wrapper {
|
|
||||||
container-type: inline-size;
|
|
||||||
container-name: editor-toolbar;
|
|
||||||
}
|
|
||||||
.editor-toolbar {
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
justify-content: flex-start;
|
|
||||||
padding: 0 6px;
|
|
||||||
height: 38px;
|
|
||||||
background: #252526;
|
|
||||||
border-bottom: 1px solid #333;
|
|
||||||
flex-shrink: 0;
|
|
||||||
gap: 4px;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Groups ─────────────────────────────────────── */
|
|
||||||
.toolbar-group {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toolbar-group-right {
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Center slot — a flexible spacer between the left and right action groups
|
|
||||||
that keeps the right icons pinned to the far right. Normally empty. */
|
|
||||||
.toolbar-center-slot {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Divider ─────────────────────────────────────── */
|
|
||||||
.tb-divider {
|
|
||||||
width: 1px;
|
|
||||||
height: 18px;
|
|
||||||
background: #3a3a3a;
|
|
||||||
margin: 0 3px;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Icon buttons ───────────────────────────────── */
|
|
||||||
.tb-btn {
|
|
||||||
/* 28px — the one control height across the whole editor strip (view-mode
|
|
||||||
segments, Libraries, language select, canvas controls all match). */
|
|
||||||
width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
background: transparent;
|
|
||||||
color: #9d9d9d;
|
|
||||||
transition:
|
|
||||||
background 0.12s,
|
|
||||||
color 0.12s;
|
|
||||||
flex-shrink: 0;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-btn:disabled {
|
|
||||||
opacity: 0.35;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compile — accent blue (token, not neon) */
|
|
||||||
.tb-btn-compile {
|
|
||||||
color: var(--color-action-primary);
|
|
||||||
}
|
|
||||||
.tb-btn-compile:hover:not(:disabled) {
|
|
||||||
background: rgba(0, 113, 227, 0.14);
|
|
||||||
color: var(--color-action-primary-hover);
|
|
||||||
}
|
|
||||||
.tb-btn-compile:active:not(:disabled) {
|
|
||||||
background: rgba(0, 113, 227, 0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run — semantic success green (token) */
|
|
||||||
.tb-btn-run {
|
|
||||||
color: var(--color-feedback-success);
|
|
||||||
}
|
|
||||||
.tb-btn-run:hover:not(:disabled) {
|
|
||||||
background: rgba(48, 209, 88, 0.14);
|
|
||||||
color: var(--color-feedback-success);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop — semantic error red (token) */
|
|
||||||
.tb-btn-stop {
|
|
||||||
color: var(--color-feedback-error);
|
|
||||||
}
|
|
||||||
.tb-btn-stop:hover:not(:disabled) {
|
|
||||||
background: rgba(255, 69, 58, 0.14);
|
|
||||||
color: var(--color-feedback-error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset */
|
|
||||||
.tb-btn-reset:hover:not(:disabled) {
|
|
||||||
background: #2a2d2e;
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Libraries button (always visible, with label) */
|
|
||||||
.tb-btn-libraries {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
height: 28px;
|
|
||||||
padding: 0 8px 0 7px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
background: var(--color-action-primary);
|
|
||||||
color: #fff;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
white-space: nowrap;
|
|
||||||
transition:
|
|
||||||
background 0.15s,
|
|
||||||
color 0.15s;
|
|
||||||
flex-shrink: 0;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
.tb-btn-libraries:hover {
|
|
||||||
background: var(--color-action-primary-hover);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.tb-libraries-label {
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
/* Hide the label only when the toolbar is genuinely cramped — keep the
|
|
||||||
"Libraries" text visible in the default 50/50 split (~376px toolbar) so
|
|
||||||
the button reads clearly. Below 360px the icon alone keeps it reachable
|
|
||||||
without stealing horizontal space from the file tabs. The container query
|
|
||||||
reacts to the toolbar's own width, so it triggers when the user drags the
|
|
||||||
editor/canvas divider very narrow, not just on small viewports. */
|
|
||||||
@container editor-toolbar (max-width: 360px) {
|
|
||||||
.tb-libraries-label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tb-btn-libraries {
|
|
||||||
padding: 0 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* When even narrower, also collapse the board pill label. */
|
|
||||||
@container editor-toolbar (max-width: 460px) {
|
|
||||||
.tb-board-pill-label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.tb-board-pill {
|
|
||||||
padding: 3px 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Import / Export moved to the File menu in the header (EditorMenuBar):
|
|
||||||
their inline buttons and the responsive overflow twins are gone, which
|
|
||||||
is ~70px the row no longer has to find on laptop widths. */
|
|
||||||
|
|
||||||
/* Legacy lib icon-only button (for overflow items) */
|
|
||||||
.tb-btn-lib {
|
|
||||||
color: var(--color-action-primary);
|
|
||||||
}
|
|
||||||
.tb-btn-lib:hover {
|
|
||||||
background: rgba(0, 113, 227, 0.12);
|
|
||||||
color: var(--color-action-primary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Missing library hint banner */
|
|
||||||
.tb-lib-hint {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
padding: 5px 12px;
|
|
||||||
background: rgba(255, 159, 10, 0.1);
|
|
||||||
border-bottom: 1px solid rgba(255, 159, 10, 0.25);
|
|
||||||
color: var(--color-feedback-warning);
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
.tb-lib-hint svg {
|
|
||||||
flex-shrink: 0;
|
|
||||||
color: var(--color-feedback-warning);
|
|
||||||
}
|
|
||||||
.tb-lib-hint-btn {
|
|
||||||
background: var(--color-action-primary);
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
font-family: inherit;
|
|
||||||
padding: 2px 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 0.12s;
|
|
||||||
}
|
|
||||||
.tb-lib-hint-btn:hover {
|
|
||||||
background: var(--color-action-primary-hover);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.tb-lib-hint-close {
|
|
||||||
margin-left: auto;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
color: #888;
|
|
||||||
font-size: 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0 4px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
.tb-lib-hint-close:hover {
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Output Console toggle */
|
|
||||||
.tb-btn-output {
|
|
||||||
color: #9d9d9d;
|
|
||||||
}
|
|
||||||
.tb-btn-output:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.06);
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
.tb-btn-output-active {
|
|
||||||
color: var(--color-action-primary);
|
|
||||||
background: rgba(0, 113, 227, 0.12);
|
|
||||||
}
|
|
||||||
.tb-btn-output-active:hover {
|
|
||||||
background: rgba(0, 113, 227, 0.2);
|
|
||||||
color: var(--color-action-primary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Spin animation (compiling) ─────────────────── */
|
|
||||||
@keyframes spin {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.spin {
|
|
||||||
animation: spin 0.8s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Status inline message ──────────────────────── */
|
|
||||||
.tb-status {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
padding: 3px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
max-width: 280px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-status-success {
|
|
||||||
color: var(--color-feedback-success);
|
|
||||||
background: rgba(48, 209, 88, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-status-error {
|
|
||||||
color: var(--color-feedback-error);
|
|
||||||
background: rgba(255, 69, 58, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-status-text {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Compile All / Run All buttons ─────────────── */
|
|
||||||
.tb-btn-compile-all {
|
|
||||||
color: var(--color-action-primary);
|
|
||||||
}
|
|
||||||
.tb-btn-compile-all:hover:not(:disabled) {
|
|
||||||
background: rgba(0, 113, 227, 0.14);
|
|
||||||
color: var(--color-action-primary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-btn-run-all {
|
|
||||||
color: var(--color-feedback-success);
|
|
||||||
}
|
|
||||||
.tb-btn-run-all:hover:not(:disabled) {
|
|
||||||
background: rgba(48, 209, 88, 0.14);
|
|
||||||
color: var(--color-feedback-success);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Board context pill ─────────────────────────── */
|
|
||||||
.tb-board-pill {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
padding: 3px 9px 3px 7px;
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
white-space: nowrap;
|
|
||||||
opacity: 0.85;
|
|
||||||
flex-shrink: 0;
|
|
||||||
background: rgba(255, 255, 255, 0.04);
|
|
||||||
max-width: 170px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-board-pill-icon {
|
|
||||||
font-size: 9px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-board-pill-label {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-board-pill-running {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: var(--color-feedback-success);
|
|
||||||
flex-shrink: 0;
|
|
||||||
animation: pulse-run 1.4s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse-run {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
opacity: 0.3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Overflow (…) menu ──────────────────────────── */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ── Run split-button (multi-board: primary Run = all boards + menu) ──── */
|
|
||||||
.tb-run-split {
|
|
||||||
position: relative;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.tb-btn-run-caret {
|
|
||||||
width: 16px;
|
|
||||||
color: var(--color-feedback-success);
|
|
||||||
}
|
|
||||||
.tb-btn-run-caret:hover:not(:disabled) {
|
|
||||||
background: rgba(48, 209, 88, 0.14);
|
|
||||||
color: var(--color-feedback-success);
|
|
||||||
}
|
|
||||||
.tb-run-menu {
|
|
||||||
position: absolute;
|
|
||||||
top: calc(100% + 6px);
|
|
||||||
left: 0;
|
|
||||||
z-index: 200;
|
|
||||||
background: #2a2a2c;
|
|
||||||
border: 1px solid #3a3a3c;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 6px;
|
|
||||||
min-width: 200px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
}
|
|
||||||
.tb-run-menu-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
padding: 8px 10px;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
border-radius: 7px;
|
|
||||||
color: #ccc;
|
|
||||||
font-size: 13px;
|
|
||||||
font-family: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: left;
|
|
||||||
white-space: nowrap;
|
|
||||||
transition:
|
|
||||||
background 0.12s,
|
|
||||||
color 0.12s;
|
|
||||||
}
|
|
||||||
.tb-run-menu-item:hover:not(:disabled) {
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.tb-run-menu-item:disabled {
|
|
||||||
opacity: 0.5;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Pro pill — signals premium items in the overflow menu BEFORE the user
|
|
||||||
clicks. Used in place of a hidden gate so free users aren't surprised
|
|
||||||
by an upgrade prompt on what looked like a free button. */
|
|
||||||
|
|
||||||
/* ── Error detail bar (for long compiler errors) ── */
|
|
||||||
.toolbar-error-detail {
|
|
||||||
background: #1a0000;
|
|
||||||
border-bottom: 1px solid #5a1a1a;
|
|
||||||
color: #f48fb1;
|
|
||||||
font-size: 11px;
|
|
||||||
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
||||||
padding: 4px 12px;
|
|
||||||
max-height: 80px;
|
|
||||||
overflow-y: auto;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,585 +0,0 @@
|
||||||
.simulator-canvas-container {
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.simulator-canvas {
|
|
||||||
flex: 1;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
color: #e0e0e0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Canvas header ───────────────────────────────── */
|
|
||||||
.canvas-header {
|
|
||||||
height: 46px;
|
|
||||||
padding: 0 10px;
|
|
||||||
background: #252526;
|
|
||||||
border-bottom: 1px solid #333;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When portaled into the unified top toolbar, drop the standalone chrome
|
|
||||||
(border + background) and shrink to match the editor toolbar height so
|
|
||||||
the two halves read as a single bar. Also drop space-between so the
|
|
||||||
left/right groups sit adjacent to each other inside the slot. */
|
|
||||||
.canvas-header--portaled {
|
|
||||||
height: 38px;
|
|
||||||
padding: 0 8px;
|
|
||||||
background: transparent;
|
|
||||||
border-bottom: none;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-header-left,
|
|
||||||
.canvas-header-right {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Status LED dot ──────────────────────────────── */
|
|
||||||
.status-dot {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 50%;
|
|
||||||
flex-shrink: 0;
|
|
||||||
transition:
|
|
||||||
background 0.3s,
|
|
||||||
box-shadow 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-dot.running {
|
|
||||||
background: #4caf50;
|
|
||||||
box-shadow: 0 0 6px rgba(76, 175, 80, 0.7);
|
|
||||||
animation: pulse-green 2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-dot.stopped {
|
|
||||||
background: #555;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse-green {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
box-shadow: 0 0 4px rgba(76, 175, 80, 0.5);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
box-shadow: 0 0 10px rgba(76, 175, 80, 0.9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Board Selector ──────────────────────────────── */
|
|
||||||
.board-selector {
|
|
||||||
padding: 4px 8px;
|
|
||||||
background: #1e2a38;
|
|
||||||
color: #c9d1d9;
|
|
||||||
border: 1px solid #3a4a5a;
|
|
||||||
border-radius: 5px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.15s;
|
|
||||||
height: 28px;
|
|
||||||
appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: right 6px center;
|
|
||||||
padding-right: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.board-selector:hover:not(:disabled) {
|
|
||||||
border-color: var(--color-action-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.board-selector:disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Serial Monitor button ───────────────────────── */
|
|
||||||
.canvas-serial-btn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
padding: 0 10px;
|
|
||||||
height: 28px;
|
|
||||||
background: transparent;
|
|
||||||
border: 1px solid #3a4a5a;
|
|
||||||
border-radius: 5px;
|
|
||||||
color: #9d9d9d;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition:
|
|
||||||
border-color 0.15s,
|
|
||||||
background 0.15s,
|
|
||||||
color 0.15s;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-serial-btn:hover {
|
|
||||||
border-color: var(--color-action-primary);
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-serial-btn-active {
|
|
||||||
background: #0e3a5a;
|
|
||||||
border-color: var(--color-action-primary);
|
|
||||||
color: var(--color-action-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Canvas icon-only buttons (undo/redo, …) ─────── */
|
|
||||||
.canvas-icon-btn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
background: transparent;
|
|
||||||
border: 1px solid #3a4a5a;
|
|
||||||
border-radius: 5px;
|
|
||||||
color: #9d9d9d;
|
|
||||||
cursor: pointer;
|
|
||||||
transition:
|
|
||||||
border-color 0.15s,
|
|
||||||
background 0.15s,
|
|
||||||
color 0.15s,
|
|
||||||
opacity 0.15s;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-icon-btn:hover:not(:disabled) {
|
|
||||||
border-color: var(--color-action-primary);
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-icon-btn:disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Component count ─────────────────────────────── */
|
|
||||||
.component-count {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Add Component button ────────────────────────── */
|
|
||||||
.add-component-btn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
padding: 0 10px;
|
|
||||||
height: 28px;
|
|
||||||
background: var(--color-action-primary);
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 0.15s;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-component-btn:hover:not(:disabled) {
|
|
||||||
background: var(--color-action-primary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-component-btn:disabled {
|
|
||||||
opacity: 0.35;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Canvas content (viewport) ───────────────────── */
|
|
||||||
.canvas-content {
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
background-image:
|
|
||||||
repeating-linear-gradient(
|
|
||||||
0deg,
|
|
||||||
transparent,
|
|
||||||
transparent 19px,
|
|
||||||
rgba(255, 255, 255, 0.025) 19px,
|
|
||||||
rgba(255, 255, 255, 0.025) 20px
|
|
||||||
),
|
|
||||||
repeating-linear-gradient(
|
|
||||||
90deg,
|
|
||||||
transparent,
|
|
||||||
transparent 19px,
|
|
||||||
rgba(255, 255, 255, 0.025) 19px,
|
|
||||||
rgba(255, 255, 255, 0.025) 20px
|
|
||||||
);
|
|
||||||
user-select: none;
|
|
||||||
touch-action: none; /* Disable browser scroll/zoom so JS handlers take full control */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Infinite canvas world ───────────────────────── */
|
|
||||||
.canvas-world {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
transform-origin: 0 0;
|
|
||||||
width: 4000px;
|
|
||||||
height: 3000px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Components area ─────────────────────────────── */
|
|
||||||
.components-area {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
/* Hit-test transparent: this full-canvas div sits later in the DOM than
|
|
||||||
the boards, so with pointer events it would swallow clicks meant for
|
|
||||||
board pins / board drag overlays (their z-index is local to each
|
|
||||||
board's stacking context). Component groups re-enable their own. */
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Zoom controls ───────────────────────────────── */
|
|
||||||
.zoom-controls {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 2px;
|
|
||||||
background: #1e1e1e;
|
|
||||||
border: 1px solid #3a3a3a;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 0 2px;
|
|
||||||
height: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-btn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #9d9d9d;
|
|
||||||
cursor: pointer;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-btn:hover {
|
|
||||||
background: #3a3a3a;
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-level {
|
|
||||||
min-width: 42px;
|
|
||||||
text-align: center;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
color: #9d9d9d;
|
|
||||||
font-size: 11px;
|
|
||||||
font-family: monospace;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0 2px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-level:hover {
|
|
||||||
background: #3a3a3a;
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.component-label {
|
|
||||||
font-size: 11px;
|
|
||||||
background-color: #252526;
|
|
||||||
padding: 3px 8px;
|
|
||||||
border-radius: 3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
margin-top: 5px;
|
|
||||||
text-align: center;
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Wire creation mode banner ──────────────────── */
|
|
||||||
.wire-mode-banner {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 12px;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
z-index: 100;
|
|
||||||
background: rgba(0, 113, 227, 0.92);
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 16px;
|
|
||||||
border-radius: 8px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
font-size: 13px;
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
|
|
||||||
backdrop-filter: blur(4px);
|
|
||||||
white-space: nowrap;
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wire-mode-banner button {
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
color: #fff;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.4);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 4px 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: background 0.15s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wire-mode-banner button:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.35);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Mobile-friendly adjustments ────────────────── */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.canvas-header {
|
|
||||||
height: 42px;
|
|
||||||
padding: 0 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-header-left,
|
|
||||||
.canvas-header-right {
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-serial-btn {
|
|
||||||
padding: 0 6px;
|
|
||||||
font-size: 0; /* hide text, show icon only */
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-serial-btn svg {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-component-btn {
|
|
||||||
padding: 0 8px;
|
|
||||||
font-size: 0; /* hide text, show icon only */
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-component-btn svg {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.board-selector {
|
|
||||||
font-size: 11px;
|
|
||||||
max-width: 90px;
|
|
||||||
padding: 4px 20px 4px 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoom-controls {
|
|
||||||
display: none; /* Use pinch-to-zoom on mobile */
|
|
||||||
}
|
|
||||||
|
|
||||||
.component-count {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wire-mode-banner {
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
gap: 8px;
|
|
||||||
bottom: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Narrow shared toolbar (desktop, AI chat open) ────────────────────────
|
|
||||||
When the canvas header is portaled into the unified top toolbar, it shares
|
|
||||||
one row with the editor actions. As that *bar* narrows (mainly when the
|
|
||||||
right-docked AI chat opens), collapse the canvas controls the same way the
|
|
||||||
mobile block does — but keyed to the bar's own width via a container query,
|
|
||||||
not the viewport, so it triggers on a wide screen with the chat open too.
|
|
||||||
Priority: labels -> icons, then drop the non-interactive count, then the
|
|
||||||
zoom buttons (mouse-wheel zoom still works). Mirrors the thresholds the
|
|
||||||
editor toolbar and view-mode toggle collapse at, so the whole bar degrades
|
|
||||||
together and nothing overlaps. */
|
|
||||||
@container unified-toolbar (max-width: 1010px) {
|
|
||||||
.canvas-serial-btn {
|
|
||||||
padding: 0 8px;
|
|
||||||
font-size: 0; /* hide "Serial" / "Scope" text, keep the icon */
|
|
||||||
}
|
|
||||||
.canvas-serial-btn svg {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
.add-component-btn {
|
|
||||||
padding: 0 9px;
|
|
||||||
font-size: 0; /* hide "Add" text, keep the icon */
|
|
||||||
}
|
|
||||||
.add-component-btn svg {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
.board-selector {
|
|
||||||
max-width: 120px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@container unified-toolbar (max-width: 905px) {
|
|
||||||
.component-count {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.board-selector {
|
|
||||||
max-width: 96px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@container unified-toolbar (max-width: 835px) {
|
|
||||||
.zoom-controls {
|
|
||||||
display: none; /* mouse-wheel / trackpad zoom still available */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── WiFi / BLE status badges ─────────────────────────────────────────── */
|
|
||||||
.canvas-wifi-badge,
|
|
||||||
.canvas-ble-badge {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: default;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-wifi-badge svg,
|
|
||||||
.canvas-ble-badge svg {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WiFi status colours */
|
|
||||||
.canvas-wifi-initializing {
|
|
||||||
color: #f59e0b;
|
|
||||||
}
|
|
||||||
.canvas-wifi-connected {
|
|
||||||
color: #f59e0b;
|
|
||||||
}
|
|
||||||
.canvas-wifi-got_ip {
|
|
||||||
color: #22c55e;
|
|
||||||
}
|
|
||||||
.canvas-wifi-disconnected {
|
|
||||||
color: #6b7280;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-wifi-clickable {
|
|
||||||
cursor: pointer !important;
|
|
||||||
transition:
|
|
||||||
transform 0.2s,
|
|
||||||
filter 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-wifi-clickable:hover {
|
|
||||||
transform: scale(1.15);
|
|
||||||
filter: drop-shadow(0 0 5px currentColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
.canvas-wifi-clickable:active {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BLE status colours */
|
|
||||||
.canvas-ble-initialized {
|
|
||||||
color: var(--color-action-primary);
|
|
||||||
}
|
|
||||||
.canvas-ble-advertising {
|
|
||||||
color: #6366f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Selection action bar (floating toolbar for selected wire/component/board) ─── */
|
|
||||||
.selection-action-bar button:hover {
|
|
||||||
background: #2a2d2e !important;
|
|
||||||
border-color: #3c3c3c !important;
|
|
||||||
}
|
|
||||||
.selection-action-bar button:active {
|
|
||||||
transform: scale(0.97);
|
|
||||||
}
|
|
||||||
.selection-action-bar button:focus-visible {
|
|
||||||
outline: 2px solid var(--color-action-primary);
|
|
||||||
outline-offset: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide button labels on narrow viewports — keep just the icons */
|
|
||||||
@media (max-width: 520px) {
|
|
||||||
.selection-action-bar .selection-action-bar__label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Runtime burnout (P4): a component destroyed mid-simulation renders charred,
|
|
||||||
with a red dashed outline + a smoke badge (the badge is a sibling of the
|
|
||||||
container, so it stays full-colour). Cleared on Reset. */
|
|
||||||
.velxio-burnt .web-component-container {
|
|
||||||
filter: grayscale(0.85) brightness(0.4) sepia(0.5) contrast(1.15);
|
|
||||||
transition: filter 0.25s ease;
|
|
||||||
}
|
|
||||||
.velxio-burnt {
|
|
||||||
outline: 1px dashed rgba(220, 38, 38, 0.65);
|
|
||||||
outline-offset: 1px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Selected component: marching ants.
|
|
||||||
A newly added part lands in a corner of the viewport and the previous
|
|
||||||
flat dashed border was easy to miss on a busy canvas — a moving outline
|
|
||||||
is what the eye actually catches. Drawn on a pseudo-element just OUTSIDE
|
|
||||||
the body so it never covers the artwork, and pointer-events: none so it
|
|
||||||
never steals a click or a pin.
|
|
||||||
|
|
||||||
Animating a dashed border is not possible (dash offset is not an
|
|
||||||
animatable property), hence the four gradient edges with a moving
|
|
||||||
background-position — the standard recipe. */
|
|
||||||
.velxio-ants::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: -3px;
|
|
||||||
border-radius: 5px;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 6;
|
|
||||||
background-image:
|
|
||||||
linear-gradient(90deg, var(--ant-color) 50%, transparent 0),
|
|
||||||
linear-gradient(90deg, var(--ant-color) 50%, transparent 0),
|
|
||||||
linear-gradient(0deg, var(--ant-color) 50%, transparent 0),
|
|
||||||
linear-gradient(0deg, var(--ant-color) 50%, transparent 0);
|
|
||||||
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
|
|
||||||
background-size: 10px 2px, 10px 2px, 2px 10px, 2px 10px;
|
|
||||||
background-position: 0 0, 0 100%, 0 0, 100% 0;
|
|
||||||
animation: velxio-ants 0.55s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.velxio-ants {
|
|
||||||
--ant-color: #2f9bff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes velxio-ants {
|
|
||||||
to {
|
|
||||||
background-position: 10px 0, -10px 100%, 0 -10px, 100% 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Respect the OS setting: the outline still marks the selection, it just
|
|
||||||
stops moving. */
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
.velxio-ants::after {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue