/* Oscilloscope display -- Tektronix 465 inspired * Tan/champagne panel, recessed CRT, teal phosphor * Designed for mcltspice docs hero section */ /* ── Outer chassis ───────────────────────────────────────── */ .scope-frame { --scope-teal: #2dd4bf; --scope-teal-dim: rgba(45, 212, 191, 0.12); --scope-teal-glow: rgba(45, 212, 191, 0.18); --scope-panel: #b5a48a; --scope-panel-light: #c7b89e; --scope-panel-dark: #9e8f78; --scope-crt-bg: #0a0a0a; --scope-label: #3b3428; --scope-knob: #2a2a2d; --scope-knob-ring: #1e1e20; --scope-section-line: rgba(59, 52, 40, 0.25); position: relative; background: /* subtle metallic grain */ url("data:image/svg+xml,%3Csvg width='4' height='4' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='1' height='1' x='0' y='0' fill='rgba(0,0,0,0.03)'/%3E%3Crect width='1' height='1' x='2' y='2' fill='rgba(255,255,255,0.02)'/%3E%3C/svg%3E"), linear-gradient(175deg, var(--scope-panel-light), var(--scope-panel), var(--scope-panel-dark)); border-radius: 6px; padding: 0; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1); max-width: 340px; width: 100%; margin: 0 auto; overflow: hidden; } /* ── Top brand bar ───────────────────────────────────────── */ .scope-brand { display: flex; align-items: baseline; justify-content: space-between; padding: 8px 14px 6px; border-bottom: 1px solid var(--scope-section-line); } .scope-brand-name { font-family: 'Georgia', 'Times New Roman', serif; font-size: 0.65rem; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: var(--scope-label); opacity: 0.75; } .scope-brand-model { font-family: var(--sl-font-mono, ui-monospace, monospace); font-size: 0.55rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--scope-label); opacity: 0.55; } /* ── CRT bay (recessed dark area) ────────────────────────── */ .scope-crt-bay { margin: 10px 12px 0; background: #1a1816; border-radius: 4px; padding: 6px; box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.2); } /* ── CRT screen ──────────────────────────────────────────── */ .scope-screen { position: relative; background: var(--scope-crt-bg); border-radius: 3px; overflow: hidden; aspect-ratio: 1; box-shadow: 0 0 15px var(--scope-teal-glow), inset 0 1px 4px rgba(0, 0, 0, 0.4); } /* ── Canvas ──────────────────────────────────────────────── */ .scope-canvas { display: block; width: 100%; height: 100%; } /* ── Graticule overlay (8x10 grid, like the 465) ─────────── */ .scope-graticule { position: absolute; inset: 0; pointer-events: none; /* 10 horizontal, 8 vertical — classic Tek grid */ background-image: repeating-linear-gradient( 90deg, transparent, transparent calc(12.5% - 0.5px), rgba(45, 212, 191, 0.07) calc(12.5% - 0.5px), rgba(45, 212, 191, 0.07) calc(12.5% + 0.5px), transparent calc(12.5% + 0.5px) ), repeating-linear-gradient( 0deg, transparent, transparent calc(12.5% - 0.5px), rgba(45, 212, 191, 0.07) calc(12.5% - 0.5px), rgba(45, 212, 191, 0.07) calc(12.5% + 0.5px), transparent calc(12.5% + 0.5px) ); } /* Center crosshair tick marks */ .scope-graticule::before, .scope-graticule::after { content: ''; position: absolute; } .scope-graticule::before { /* horizontal center tick */ top: 50%; left: calc(50% - 8px); width: 16px; height: 1px; background: rgba(45, 212, 191, 0.18); } .scope-graticule::after { /* vertical center tick */ left: 50%; top: calc(50% - 8px); width: 1px; height: 16px; background: rgba(45, 212, 191, 0.18); } /* ── Scanline overlay ────────────────────────────────────── */ .scope-scanlines { position: absolute; inset: 0; pointer-events: none; background: repeating-linear-gradient( 0deg, transparent, transparent 2px, rgba(0, 0, 0, 0.04) 2px, rgba(0, 0, 0, 0.04) 4px ); mix-blend-mode: multiply; } /* ── Control panel area ──────────────────────────────────── */ .scope-panel { padding: 8px 12px 6px; border-top: 1px solid var(--scope-section-line); margin-top: 10px; } .scope-controls-row { display: flex; align-items: flex-start; gap: 2px; } /* ── Control section (labeled group) ─────────────────────── */ .scope-section { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 2px; position: relative; } /* Section divider lines */ .scope-section + .scope-section::before { content: ''; position: absolute; left: -1px; top: 0; bottom: 0; width: 1px; background: var(--scope-section-line); } .scope-section-label { font-family: var(--sl-font-mono, ui-monospace, monospace); font-size: 0.45rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--scope-label); opacity: 0.6; line-height: 1; } /* ── Rotary knob ─────────────────────────────────────────── */ .scope-knob { width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 40% 35%, #3a3a3e, var(--scope-knob)); border: 2px solid var(--scope-knob-ring); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.35), inset 0 1px 1px rgba(255, 255, 255, 0.06); position: relative; } /* Knob indicator line */ .scope-knob::after { content: ''; position: absolute; top: 3px; left: 50%; width: 1.5px; height: 7px; background: #d4d0c8; border-radius: 1px; transform: translateX(-50%); } .scope-knob-label { font-family: var(--sl-font-mono, ui-monospace, monospace); font-size: 0.4rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--scope-label); opacity: 0.5; line-height: 1; } /* ── Source knob (interactive) ───────────────────────────── */ /* Uses --knob-rotation custom prop so JS rotation composes with CSS scale */ .scope-source-knob { cursor: pointer; transition: transform 0.15s; transform: rotate(var(--knob-rotation, 0deg)); } .scope-source-knob:hover { transform: rotate(var(--knob-rotation, 0deg)) scale(1.08); } .scope-source-knob:active { transform: rotate(var(--knob-rotation, 0deg)) scale(0.95); } .scope-source-knob:focus-visible { outline: 2px solid var(--scope-teal); outline-offset: 2px; } /* ── Signal name label ──────────────────────────────────── */ .scope-source-name { max-width: 60px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; } /* ── Loading state overlay ──────────────────────────────── */ .scope-screen[data-loading="true"]::after { content: ''; position: absolute; inset: 0; background: rgba(10, 10, 10, 0.7); z-index: 5; animation: scope-loading-pulse 1.2s ease-in-out infinite; } @keyframes scope-loading-pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 0.9; } } /* ── Power toggle ────────────────────────────────────────── */ .scope-toggle { appearance: none; background: var(--scope-knob); border: 2px solid var(--scope-knob-ring); border-radius: 6px; color: #8a8880; font-family: var(--sl-font-mono, ui-monospace, monospace); font-size: 0.55rem; font-weight: 700; letter-spacing: 0.06em; padding: 5px 8px; cursor: pointer; transition: color 0.2s, box-shadow 0.2s; text-transform: uppercase; line-height: 1; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } .scope-toggle:hover { color: #c4c0b8; } .scope-toggle[data-active="true"] { color: var(--scope-teal); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3), 0 0 6px var(--scope-teal-glow); } .scope-toggle:focus-visible { outline: 2px solid var(--scope-teal); outline-offset: 2px; } /* ── Power LED ───────────────────────────────────────────── */ .scope-led { width: 5px; height: 5px; border-radius: 50%; background: #3a3632; border: 1px solid rgba(0, 0, 0, 0.3); transition: background 0.3s, box-shadow 0.3s; } .scope-led[data-on="true"] { background: var(--scope-teal); box-shadow: 0 0 6px var(--scope-teal-glow); } /* ── Attribution bar ─────────────────────────────────────── */ .scope-attribution-bar { padding: 5px 14px 7px; border-top: 1px solid var(--scope-section-line); } .scope-attribution { font-family: var(--sl-font-mono, ui-monospace, monospace); font-size: 0.45rem; color: var(--scope-panel-dark); line-height: 1.4; text-align: center; } .scope-attribution a { color: var(--scope-label); text-decoration: none; transition: color 0.15s; } .scope-attribution a:hover { color: #1a1610; } /* ── Idle state ──────────────────────────────────────────── */ .scope-screen[data-idle="true"] .scope-canvas { opacity: 0.6; } /* ── Reduced motion ──────────────────────────────────────── */ @media (prefers-reduced-motion: reduce) { .scope-scanlines { display: none; } } /* ── Responsive ──────────────────────────────────────────── */ @media (max-width: 50rem) { .scope-frame { max-width: 280px; } .scope-knob { width: 24px; height: 24px; } .scope-knob::after { height: 5px; } } /* ── Skin picker (model name → clickable) ──────────────── */ .scope-brand-right { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; } button.scope-brand-model { appearance: none; background: none; border: none; padding: 0; cursor: pointer; line-height: inherit; transition: opacity 0.15s; } button.scope-brand-model:hover { opacity: 0.85; } button.scope-brand-model:focus-visible { outline: 2px solid var(--scope-teal); outline-offset: 2px; border-radius: 2px; } .scope-brand-sub { font-family: var(--sl-font-mono, ui-monospace, monospace); font-size: 0.4rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--scope-label); opacity: 0.4; } /* ── Tektronix Type 545A skin (1959) ─────────────────────── */ /* Vacuum-tube era: blue-green hammertone, cream silk-screen, Bakelite knobs, deeper CRT recess, ventilation holes */ .scope-skin-545a { --scope-panel: #4a6e64; --scope-panel-light: #5a7e72; --scope-panel-dark: #3a5a50; --scope-label: #e0d8c8; --scope-knob: #1c1814; --scope-knob-ring: #141210; --scope-section-line: rgba(224, 216, 200, 0.15); } /* Hammertone texture — larger dimpled dots, irregular placement */ .scope-skin-545a { background: url("data:image/svg+xml,%3Csvg width='8' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='2' cy='2' r='1.2' fill='rgba(0,0,0,0.06)'/%3E%3Ccircle cx='6' cy='5' r='0.8' fill='rgba(255,255,255,0.04)'/%3E%3Ccircle cx='4' cy='7' r='1' fill='rgba(0,0,0,0.04)'/%3E%3Ccircle cx='7' cy='1' r='0.6' fill='rgba(255,255,255,0.03)'/%3E%3C/svg%3E"), linear-gradient(175deg, var(--scope-panel-light), var(--scope-panel), var(--scope-panel-dark)); } /* Deeper CRT bay recess — tube-era instruments had heavier bezels */ .scope-skin-545a .scope-crt-bay { box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(0, 0, 0, 0.3); } /* Larger Bakelite-era knobs */ .scope-skin-545a .scope-knob { width: 32px; height: 32px; background: radial-gradient(circle at 40% 35%, #2e2218, var(--scope-knob)); } .scope-skin-545a .scope-knob::after { height: 8px; background: #c8b890; } /* Cream-on-green attribution */ .scope-skin-545a .scope-attribution { color: var(--scope-label); opacity: 0.6; } .scope-skin-545a .scope-attribution a { color: var(--scope-label); } .scope-skin-545a .scope-attribution a:hover { color: #fff; } /* ── Ventilation holes (545A only) ──────────────────────── */ .scope-vent-holes { display: none; justify-content: center; gap: 8px; padding: 6px 14px 8px; } .scope-vent-hole { width: 6px; height: 6px; border-radius: 50%; background: radial-gradient(circle, rgba(0, 0, 0, 0.4) 40%, rgba(0, 0, 0, 0.15) 100%); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); } .scope-skin-545a .scope-vent-holes { display: flex; } /* ── 545A responsive overrides ──────────────────────────── */ @media (max-width: 50rem) { .scope-skin-545a .scope-knob { width: 26px; height: 26px; } .scope-skin-545a .scope-knob::after { height: 6px; } .scope-vent-hole { width: 5px; height: 5px; } }