#2 +

Слито
u23-27eroshko слито 2 коммит(ов) из u23-27eroshko/side в u23-27eroshko/master 2 недель назад
5 измененных файлов с 48 добавлено и 20 удалено
  1. 19 5
      css/base.css
  2. 9 5
      css/circuit.css
  3. 11 3
      css/components.css
  4. 5 4
      index.html
  5. 4 3
      js/circuit.js

+ 19 - 5
css/base.css

@@ -14,9 +14,19 @@
   --on-accent: #17213d; --danger: #f69c8e; --danger-soft: #432d29;
   --supply: #92b6bb; --signal: #e9bb78; --wire: #8c998d; --metal: #737e72;
 }
+:root {
+  --lab-glow: rgba(54,89,217,.16);
+  --lab-grid: rgba(126,137,124,.16);
+  --lab-grid-major: rgba(126,137,124,.22);
+}
+:root[data-theme="dark"] {
+  --lab-glow: rgba(164,182,255,.12);
+  --lab-grid: rgba(140,153,141,.18);
+  --lab-grid-major: rgba(140,153,141,.26);
+}
 * { box-sizing: border-box; }
 html { zoom: 1.15; scroll-behavior: smooth; scrollbar-gutter: stable; }
-body { margin: 0; min-width: 0; background: var(--bg); color: var(--text); font-family: var(--sans); -webkit-font-smoothing: antialiased; }
+body { margin: 0; min-width: 0; background: radial-gradient(circle at 12% 0%, var(--lab-glow), transparent 24%), radial-gradient(circle at 92% 18%, rgba(177,118,28,.08), transparent 26%), linear-gradient(var(--lab-grid-major) 1px, transparent 1px), linear-gradient(90deg, var(--lab-grid-major) 1px, transparent 1px), linear-gradient(var(--lab-grid) 1px, transparent 1px), linear-gradient(90deg, var(--lab-grid) 1px, transparent 1px), var(--bg); background-size: auto, auto, 128px 128px, 128px 128px, 32px 32px, 32px 32px; color: var(--text); font-family: var(--sans); -webkit-font-smoothing: antialiased; }
 body, .workspace, .modal, .lock-stage, .schematic-scroll { transition: background-color .25s, color .25s, border-color .25s; }
 button, input, select { font: inherit; }
 button { color: inherit; }
@@ -25,21 +35,25 @@ button, a, input, select { -webkit-tap-highlight-color: transparent; }
 ::selection { background: var(--accent); color: var(--on-accent); }
 h1, h2, p { margin-top: 0; }
 .app-shell { width: min(1280px, calc(100% - 96px)); margin-inline: auto; }
-.topbar { min-height: 94px; display: flex; align-items: center; justify-content: space-between; gap: 20px; border-bottom: 1px solid var(--line); }
+.topbar { min-height: 94px; display: flex; align-items: center; justify-content: space-between; gap: 20px; border-bottom: 1px solid var(--line); position: relative; }
+.topbar::after { content: "LAB / INSTRUMENT CONTROL"; position: absolute; right: 0; bottom: 7px; color: var(--muted); font: 7px var(--mono); letter-spacing: .16em; opacity: .65; }
 .brand { display: flex; align-items: center; gap: 12px; color: var(--text); text-decoration: none; font-size: 13px; font-weight: 800; letter-spacing: -.02em; }
 .brand-mark { display: grid; place-items: center; width: 32px; height: 36px; color: var(--accent); }
 .brand-mark svg { width: 28px; height: 32px; }
 .brand i { font: 10px var(--mono); color: var(--muted); padding-left: 12px; border-left: 1px solid var(--line); }
+.brand-mark { filter: drop-shadow(0 0 8px var(--lab-glow)); }
 .topbar-actions { display: flex; align-items: center; gap: 8px; }
-.hero { display: grid; grid-template-columns: 1fr 310px; gap: 32px; align-items: end; padding: 56px 0 40px; }
+.hero { display: grid; grid-template-columns: 1fr 310px; gap: 32px; align-items: end; padding: 64px 0 46px; }
 .eyebrow, .panel-kicker { margin: 0; font: 10px/1.6 var(--mono); letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
-.hero h1 { margin: 16px 0 0; font-size: clamp(38px, 5.5vw, 76px); font-weight: 500; line-height: 1.08; letter-spacing: -.065em; }
+.hero h1 { margin: 16px 0 0; font-size: clamp(30px, 4.4vw, 64px); font-weight: 500; line-height: 1.08; letter-spacing: -.065em; text-shadow: 0 12px 34px var(--lab-glow); }
+.hero-title__suffix { color: var(--accent); font-size: .72em; font-weight: 600; letter-spacing: -.04em; white-space: nowrap; }
 .hero h1 span { color: var(--accent); }
 .hero-copy { margin: 0 0 4px; color: var(--muted); font-size: 13px; line-height: 1.85; }
 .hero-meta { display: flex; align-items: center; gap: 8px; margin-top: 18px; font: 9px var(--mono); color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
 .hero-meta i { width: 6px; height: 6px; background: var(--accent); border-radius: 50%; }
+.hero-meta i { box-shadow: 0 0 0 4px var(--accent-soft), 0 0 12px var(--accent); }
 footer { display: flex; justify-content: space-between; gap: 16px; padding: 26px 0 36px; color: var(--muted); font: 9px/1.8 var(--mono); }
 @media (max-width: 1000px) { .app-shell { width: calc(100% - 48px); } .hero { grid-template-columns: 1fr 260px; } }
 @media (max-width: 800px) { .hero { grid-template-columns: 1fr; gap: 22px; padding-block: 38px 30px; } .hero-copy { max-width: 440px; } .hero-meta { margin-top: 12px; } .topbar-actions > .button--ghost { display: none; } }
-@media (max-width: 480px) { .app-shell { width: calc(100% - 32px); } .topbar { min-height: 76px; gap: 8px; } .brand i { display: none; } .brand { gap: 6px; font-size: 12px; } .topbar-actions { gap: 2px; } footer { flex-direction: column; gap: 4px; } }
+@media (max-width: 480px) { .app-shell { width: calc(100% - 32px); } .topbar { min-height: 76px; gap: 8px; } .brand i { display: none; } .brand { gap: 6px; font-size: 12px; } .topbar-actions { gap: 2px; } .hero h1 { font-size: clamp(28px, 8vw, 38px); } footer { flex-direction: column; gap: 4px; } }
 @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } *, *::before, *::after { animation: none !important; transition: none !important; } }

+ 9 - 5
css/circuit.css

@@ -1,11 +1,14 @@
 /* Electronic lock: supply, driver, relay and switched electromagnet. */
 .circuit-panel .panel-heading { margin-bottom: 17px; }
-.circuit-status { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 10px; margin-bottom: 12px; }
+.circuit-panel { position: relative; }
+.circuit-status { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 10px; margin-bottom: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 7px; background: color-mix(in srgb, var(--panel-2) 76%, transparent); box-shadow: inset 0 0 18px rgba(22,127,138,.06); }
 .circuit-status__dot { width: 6px; height: 6px; flex: 0 0 auto; border-radius: 50%; background: var(--muted); }
+.circuit-status__dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--muted) 20%, transparent); }
 .supply-label { margin-left: auto; white-space: nowrap; color: var(--supply); font: 10px var(--mono); }
-.schematic-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; background: var(--panel-2); scrollbar-color: var(--wire) var(--panel-2); }
+.schematic-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; background: radial-gradient(circle at 50% 15%, var(--lab-glow), transparent 42%), var(--panel-2); scrollbar-color: var(--wire) var(--panel-2); box-shadow: inset 0 0 28px rgba(20,28,22,.08); }
+.diagram-toolbar { padding: 6px 8px; border: 1px solid var(--line); border-radius: 7px; background: color-mix(in srgb, var(--panel-2) 70%, transparent); }
 .schematic-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
-.component-tooltip { position: absolute; z-index: 5; right: 18px; bottom: 18px; width: min(360px, calc(100% - 36px)); padding: 16px 40px 15px 16px; border: 1px solid var(--accent); border-radius: 8px; background: var(--panel); box-shadow: 0 12px 28px rgba(0,0,0,.2); animation: tooltip-in .16s ease-out; }
+.component-tooltip { position: relative; width: 100%; margin-top: 12px; padding: 16px 44px 15px 16px; border: 1px solid var(--accent); border-radius: 8px; background: var(--panel); box-shadow: 0 8px 20px rgba(0,0,0,.12); animation: tooltip-in .16s ease-out; }
 .component-tooltip[hidden] { display: none; }
 .component-tooltip__label { display: block; margin-bottom: 5px; color: var(--accent); font: 8px var(--mono); letter-spacing: .09em; }
 .component-tooltip strong { display: block; margin-bottom: 6px; color: var(--text); font: 700 13px/1.35 var(--mono); }
@@ -130,7 +133,7 @@ button:disabled { cursor: not-allowed; }
 .diagram-caption { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; padding: 10px 0 16px; color: var(--muted); font: 9px/1.6 var(--mono); }
 #keypadSignal { color: var(--signal); }
 .thyristor-stages { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 0 0 16px; }
-.thyristor-stages > div { display: grid; grid-template-columns: 1fr auto; gap: 6px; padding: 12px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px; }
+.thyristor-stages > div { display: grid; grid-template-columns: 1fr auto; gap: 6px; padding: 12px; background: linear-gradient(145deg, color-mix(in srgb, var(--panel-2) 88%, var(--accent-soft)), var(--panel-2)); border: 1px solid var(--line); border-radius: 8px; box-shadow: inset 0 1px rgba(255,255,255,.08); }
 .thyristor-stages span { grid-column: 1 / -1; color: var(--muted); font: 9px var(--mono); }
 .thyristor-stages strong { font: 13px var(--mono); }
 .thyristor-stages small { font: 9px/1.8 var(--mono); color: var(--muted); }
@@ -144,7 +147,8 @@ button:disabled { cursor: not-allowed; }
 .node-selector { display: flex; flex-wrap: wrap; gap: 5px; margin: 24px 0 10px; }
 .node-selector button { border-color: var(--line); }
 .node-selector [aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
-.component-detail { padding: 22px; border: 1px solid var(--line); border-radius: 10px; }
+.node-selector [aria-pressed="true"] { box-shadow: inset 0 -2px var(--accent), 0 0 12px var(--lab-glow); }
+.component-detail { padding: 22px; border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--line)); border-radius: 10px; background: linear-gradient(145deg, color-mix(in srgb, var(--panel) 92%, var(--accent-soft)), var(--panel)); }
 .component-detail-disclosure { margin-top: 14px; }
 .component-detail-disclosure > summary { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; padding: 14px 0; border-block: 1px solid var(--line); color: var(--text); cursor: pointer; font: 600 12px var(--sans); list-style: none; }
 .component-detail-disclosure > summary::-webkit-details-marker { display: none; }

+ 11 - 3
css/components.css

@@ -1,17 +1,24 @@
 /* Workbench, controls and supporting dialogs. */
 .workspace { display: grid; grid-template-columns: .85fr 1.15fr; background: var(--panel); border: 1px solid var(--line); border-radius: 18px; overflow: hidden; }
+.workspace { background: color-mix(in srgb, var(--panel) 92%, var(--accent-soft)); box-shadow: 0 24px 60px rgba(11,29,29,.18), inset 0 1px rgba(255,255,255,.28); }
+.workspace::before { display: none; }
+.workspace { position: relative; }
 .workbench-column { min-width: 0; padding: 30px; display: flex; flex-direction: column; gap: 34px; }
+.workbench-column > .panel:first-child { margin-top: 0; }
 .workbench-column + .workbench-column { border-left: 1px solid var(--line); }
 .panel { min-width: 0; }
 .panel + .panel { padding-top: 30px; border-top: 1px solid var(--line); }
 .panel-heading { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; margin-bottom: 22px; }
+.panel-heading h2 { text-wrap: balance; }
 .panel h2 { margin: 6px 0 0; font-size: 20px; font-weight: 600; line-height: 1.35; letter-spacing: -.04em; }
+.panel h2::after { content: ""; display: block; width: 32px; height: 2px; margin-top: 9px; background: var(--accent); opacity: .65; }
 .button, .icon-button, .text-button { border: 0; cursor: pointer; transition: background .2s, color .2s, border-color .2s, transform .2s; }
 .button { min-height: 40px; padding: 11px 16px; border-radius: 8px; font-size: 11px; font-weight: 700; }
-.button--primary { background: var(--accent); color: var(--on-accent); }
+.button--primary { background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 72%, #15203f)); color: var(--on-accent); box-shadow: 0 5px 14px var(--lab-glow); }
 .button--primary:hover:not(:disabled) { filter: brightness(1.08); transform: translateY(-1px); }
-.button--ghost { background: transparent; border: 1px solid var(--line); }
+.button--ghost { background: color-mix(in srgb, var(--panel) 70%, transparent); border: 1px solid var(--line); }
 .button--ghost:hover { background: var(--panel-2); border-color: var(--muted); }
+.button--ghost { letter-spacing: .02em; }
 .icon-button { display: inline-grid; place-items: center; width: 36px; height: 36px; background: transparent; border-radius: 50%; font-size: 18px; color: var(--muted); }
 .icon-button svg { width: 18px; height: 18px; }
 .icon-button:hover, .icon-button.is-active { background: var(--accent-soft); color: var(--accent); }
@@ -19,7 +26,7 @@
 .text-button:hover:not(:disabled) { text-decoration: underline; text-underline-offset: 4px; }
 .button:active:not(:disabled), .icon-button:active { transform: translateY(1px); }
 button:disabled { cursor: not-allowed; }
-.status-pill { padding: 5px 8px; border-radius: 5px; background: var(--panel-2); color: var(--muted); font: 9px var(--mono); }
+.status-pill { padding: 6px 9px; border-radius: 5px; background: var(--panel-2); color: var(--muted); font: 9px var(--mono); letter-spacing: .08em; box-shadow: inset 0 0 0 1px rgba(255,255,255,.06); }
 .status-pill.is-open { background: var(--accent-soft); color: var(--accent); }
 .lock-stage { position: relative; height: 184px; overflow: hidden; border-radius: 10px; border: 1px solid var(--line); background: var(--panel-2); }
 .lock-stage__grid { position: absolute; inset: 0; background-image: radial-gradient(var(--wire) .7px, transparent .7px); background-size: 16px 16px; opacity: .13; }
@@ -40,6 +47,7 @@ button:disabled { cursor: not-allowed; }
 .event-log { margin-top: 18px; }
 .event-log > span { color: var(--muted); font: 8px var(--mono); letter-spacing: .08em; }
 .event-log p { color: var(--muted); margin: 5px 0 0; min-height: 34px; font-size: 11px; line-height: 1.6; }
+.event-log { padding: 12px; border: 1px dashed var(--line); border-radius: 6px; background: color-mix(in srgb, var(--panel-2) 60%, transparent); }
 .explanation { display: flex; gap: 14px; padding: 16px 0; border-block: 1px solid var(--line); }
 .explanation__number { color: var(--accent); font: 20px/1.3 var(--mono); flex-shrink: 0; }
 .explanation p { margin: 0; font-size: 11px; color: var(--muted); line-height: 1.7; }

Разница между файлами не показана из-за своего большого размера
+ 5 - 4
index.html


+ 4 - 3
js/circuit.js

@@ -67,12 +67,13 @@
   document.addEventListener('keydown', e => { if (e.key === 'Escape') document.querySelector('#componentTooltip').hidden = true; });
   let zoom = 100;
   const setZoom = value => { zoom = Math.max(75,Math.min(200,value)); host.style.minWidth = '0'; host.style.width = `${Math.max(host.parentElement.clientWidth,1050)*zoom/100}px`; document.querySelector('#zoomValue').textContent = `${zoom}%`; document.querySelector('#zoomOut').disabled = zoom === 75; document.querySelector('#zoomIn').disabled = zoom === 200; };
-  window.addEventListener('resize', () => setZoom(zoom));
-  setZoom(100);
+  const fitZoom = () => { const available = host.parentElement.clientWidth; const fitted = Math.floor((available / 1050) * 100); setZoom(Math.max(75, Math.min(100, fitted))); };
+  window.addEventListener('resize', fitZoom);
+  fitZoom();
   renderNodeInfo('memory');
   document.querySelector('#zoomIn').onclick = () => setZoom(zoom+25);
   document.querySelector('#zoomOut').onclick = () => setZoom(zoom-25);
-  document.querySelector('#zoomFit').onclick = () => setZoom(100);
+  document.querySelector('#zoomFit').onclick = fitZoom;
   const panel = document.querySelector('.circuit-panel');
   const placeholder = document.createComment('circuit panel home'); panel.before(placeholder);
   const modal = document.querySelector('#circuitModal');

Некоторые файлы не были показаны из-за большого количества измененных файлов