feat(binary): add full binary simulator with unsigned and two’s complement modes

- Introduce new Binary Simulator page with adjustable bit width (4–16 bits)
- Support unsigned and two’s complement representations with live conversion
- Add left/right shift operations and custom binary/denary input
- Implement accessible bulb-and-switch UI with MD3-inspired styling
- Add seven-segment display font assets for realistic number output
- Establish shared base layout, styles, and tooling for future simulators

Signed-off-by: Alexander Lyall <alex@adcm.uk>
This commit is contained in:
2025-12-14 16:57:31 +00:00
parent 7a694bf400
commit 50829688e3
113 changed files with 6769 additions and 6663 deletions

137
public/css/tools/binary.css Normal file
View File

@@ -0,0 +1,137 @@
/* ---------- DSEG7 font ---------- */
/* Put your font file here:
public/fonts/DSEG7Classic-Regular.woff2
*/
@font-face {
font-family: "DSEG7ClassicRegular";
src: url("/fonts/DSEG7Classic-Regular.woff2") format("woff2");
font-display: swap;
}
/* ---------- Layout ---------- */
.tool-shell {
min-height: 100vh;
display: grid;
place-items: center;
padding: 1rem;
background: #0b0f14;
color: #e7eaf0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
}
.tool-card {
width: min(1100px, 100%);
background: #111824;
border: 1px solid rgba(255,255,255,0.08);
border-radius: 18px;
padding: 1rem;
}
.tool-header h1 { margin: 0 0 .25rem 0; font-size: 1.4rem; }
.tool-header p { margin: 0 0 1rem 0; opacity: .85; }
.display-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: .75rem;
margin-bottom: .75rem;
}
.display-box {
background: #0b0f14;
border: 1px solid rgba(255,255,255,0.08);
border-radius: 14px;
padding: .75rem;
}
.display-label { font-size: .9rem; opacity: .8; margin-bottom: .25rem; }
.sevenseg {
font-family: "DSEG7ClassicRegular", monospace;
font-size: clamp(2rem, 4vw, 3.2rem);
letter-spacing: 0.08em;
line-height: 1.1;
}
/* Buttons under denary/binary (your request) */
.actions {
display: flex;
flex-wrap: wrap;
gap: .5rem;
margin-bottom: 1rem;
}
/* ---------- Simple MD3-ish buttons ---------- */
.md3-btn {
border: 1px solid rgba(255,255,255,0.16);
background: rgba(255,255,255,0.06);
color: #e7eaf0;
padding: .6rem .9rem;
border-radius: 999px;
cursor: pointer;
font-weight: 600;
}
.md3-btn:hover { background: rgba(255,255,255,0.10); }
.md3-btn--tonal { background: rgba(255,255,255,0.10); }
/* ---------- Switches row ---------- */
.switch-row {
display: grid;
grid-template-columns: repeat(8, minmax(90px, 1fr));
gap: .75rem;
}
.switch-col {
display: grid;
justify-items: center;
gap: .35rem;
}
.bit-label { opacity: .85; font-weight: 600; }
/* ---------- “Light switch” rocker ---------- */
.rocker {
position: relative;
width: 70px;
height: 46px;
display: inline-block;
user-select: none;
}
.rocker input {
opacity: 0;
width: 0;
height: 0;
}
.rocker-body {
position: absolute;
inset: 0;
border-radius: 12px;
background: #1a2331;
border: 1px solid rgba(255,255,255,0.14);
box-shadow: inset 0 0 0 2px rgba(0,0,0,0.35);
}
/* the “toggle” */
.rocker-body::after {
content: "";
position: absolute;
left: 6px;
top: 6px;
width: 58px;
height: 18px;
border-radius: 10px;
background: rgba(255,255,255,0.20);
transition: transform 180ms ease, background 180ms ease;
}
/* ON position */
.rocker input:checked + .rocker-body::after {
transform: translateY(16px);
background: rgba(255,255,255,0.55);
}
@media (max-width: 900px) {
.switch-row { grid-template-columns: repeat(4, minmax(90px, 1fr)); }
}