style: run oxfmt repo-wide
First full pass of the pnpm fmt toolchain: markdown table alignment, TOML array wrapping, CSS/HTML expansion in the enclosure concept page. No content changes; mermaid blocks untouched.
This commit is contained in:
@@ -1,255 +1,671 @@
|
||||
<title>Typoena — Enclosure Concept</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#E7E1D0; --sheet:#F2EDE0; --ink:#26231D; --ink-soft:#5b564c;
|
||||
--acc:#3C6152; --acc-l:#6E9483; --dim:#B0553B; --hair:#B9B09A;
|
||||
--screen:#F7F4EA;
|
||||
--serif:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,"Times New Roman",serif;
|
||||
--mono:"SFMono-Regular",ui-monospace,Menlo,Consolas,"Courier New",monospace;
|
||||
:root {
|
||||
--paper: #e7e1d0;
|
||||
--sheet: #f2ede0;
|
||||
--ink: #26231d;
|
||||
--ink-soft: #5b564c;
|
||||
--acc: #3c6152;
|
||||
--acc-l: #6e9483;
|
||||
--dim: #b0553b;
|
||||
--hair: #b9b09a;
|
||||
--screen: #f7f4ea;
|
||||
--serif:
|
||||
'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia,
|
||||
'Times New Roman', serif;
|
||||
--mono:
|
||||
'SFMono-Regular', ui-monospace, Menlo, Consolas, 'Courier New', monospace;
|
||||
}
|
||||
*{box-sizing:border-box;}
|
||||
body{margin:0;}
|
||||
.wrap{
|
||||
background:
|
||||
radial-gradient(120% 120% at 50% 0%, #ECE7D8 0%, var(--paper) 60%);
|
||||
min-height:100%;
|
||||
padding:clamp(16px,3vw,44px);
|
||||
color:var(--ink);
|
||||
font-family:var(--serif);
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.sheet{
|
||||
max-width:1180px;margin:0 auto;background:var(--sheet);
|
||||
border:1.5px solid var(--ink);
|
||||
box-shadow:0 1px 0 var(--ink),0 22px 50px -28px rgba(38,35,29,.55);
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
.wrap {
|
||||
background: radial-gradient(
|
||||
120% 120% at 50% 0%,
|
||||
#ece7d8 0%,
|
||||
var(--paper) 60%
|
||||
);
|
||||
min-height: 100%;
|
||||
padding: clamp(16px, 3vw, 44px);
|
||||
color: var(--ink);
|
||||
font-family: var(--serif);
|
||||
}
|
||||
.sheet {
|
||||
max-width: 1180px;
|
||||
margin: 0 auto;
|
||||
background: var(--sheet);
|
||||
border: 1.5px solid var(--ink);
|
||||
box-shadow:
|
||||
0 1px 0 var(--ink),
|
||||
0 22px 50px -28px rgba(38, 35, 29, 0.55);
|
||||
}
|
||||
/* titleblock */
|
||||
.titleblock{
|
||||
display:grid;grid-template-columns:1.7fr .8fr .8fr .9fr;
|
||||
border-bottom:1.5px solid var(--ink);
|
||||
.titleblock {
|
||||
display: grid;
|
||||
grid-template-columns: 1.7fr 0.8fr 0.8fr 0.9fr;
|
||||
border-bottom: 1.5px solid var(--ink);
|
||||
}
|
||||
.tb {
|
||||
padding: 12px 16px;
|
||||
border-right: 1px solid var(--ink);
|
||||
}
|
||||
.tb:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
.tb .k {
|
||||
font-family: var(--mono);
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.tb .v {
|
||||
font-family: var(--mono);
|
||||
font-size: 14px;
|
||||
margin-top: 3px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.tb-title .name {
|
||||
font-family: var(--serif);
|
||||
font-size: clamp(22px, 3.4vw, 34px);
|
||||
line-height: 1.02;
|
||||
letter-spacing: -0.01em;
|
||||
font-weight: 600;
|
||||
text-wrap: balance;
|
||||
}
|
||||
.tb-title .sub {
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.16em;
|
||||
text-transform: uppercase;
|
||||
color: var(--acc);
|
||||
margin-top: 6px;
|
||||
}
|
||||
.tb{padding:12px 16px;border-right:1px solid var(--ink);}
|
||||
.tb:last-child{border-right:0;}
|
||||
.tb .k{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-soft);}
|
||||
.tb .v{font-family:var(--mono);font-size:14px;margin-top:3px;font-variant-numeric:tabular-nums;}
|
||||
.tb-title .name{font-family:var(--serif);font-size:clamp(22px,3.4vw,34px);line-height:1.02;letter-spacing:-.01em;font-weight:600;text-wrap:balance;}
|
||||
.tb-title .sub{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--acc);margin-top:6px;}
|
||||
/* intro */
|
||||
.intro{padding:18px 22px 6px;border-bottom:1px solid var(--hair);}
|
||||
.intro p{margin:0 auto;max-width:70ch;font-size:16px;line-height:1.5;color:#3a362e;}
|
||||
.intro .lead{font-style:italic;color:var(--acc);}
|
||||
/* view panels */
|
||||
.views{display:grid;grid-template-columns:1fr;gap:0;}
|
||||
.panel{padding:14px 18px 18px;border-bottom:1px solid var(--hair);}
|
||||
.panel h2{
|
||||
font-family:var(--mono);font-size:11px;letter-spacing:.2em;text-transform:uppercase;
|
||||
color:var(--ink);margin:0 0 2px;display:flex;justify-content:space-between;align-items:baseline;
|
||||
.intro {
|
||||
padding: 18px 22px 6px;
|
||||
border-bottom: 1px solid var(--hair);
|
||||
}
|
||||
.intro p {
|
||||
margin: 0 auto;
|
||||
max-width: 70ch;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #3a362e;
|
||||
}
|
||||
.intro .lead {
|
||||
font-style: italic;
|
||||
color: var(--acc);
|
||||
}
|
||||
/* view panels */
|
||||
.views {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0;
|
||||
}
|
||||
.panel {
|
||||
padding: 14px 18px 18px;
|
||||
border-bottom: 1px solid var(--hair);
|
||||
}
|
||||
.panel h2 {
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ink);
|
||||
margin: 0 0 2px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
}
|
||||
.panel h2 .tag {
|
||||
color: var(--dim);
|
||||
}
|
||||
.panel .cap {
|
||||
font-family: var(--serif);
|
||||
font-style: italic;
|
||||
color: var(--ink-soft);
|
||||
font-size: 13px;
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
.lower {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.lower .panel:first-child {
|
||||
border-right: 1px solid var(--hair);
|
||||
}
|
||||
svg {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
svg text {
|
||||
font-family: var(--mono);
|
||||
}
|
||||
.panel h2 .tag{color:var(--dim);}
|
||||
.panel .cap{font-family:var(--serif);font-style:italic;color:var(--ink-soft);font-size:13px;margin:0 0 8px;}
|
||||
.lower{display:grid;grid-template-columns:1fr 1fr;}
|
||||
.lower .panel:first-child{border-right:1px solid var(--hair);}
|
||||
svg{width:100%;height:auto;display:block;}
|
||||
svg text{font-family:var(--mono);}
|
||||
/* notes */
|
||||
.notes{padding:18px 22px 24px;display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:18px 26px;}
|
||||
.note h3{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;margin:0 0 6px;color:var(--acc);display:flex;gap:8px;align-items:baseline;}
|
||||
.note h3 .n{color:var(--dim);font-variant-numeric:tabular-nums;}
|
||||
.note p{margin:0;font-size:14px;line-height:1.45;color:#3a362e;}
|
||||
.note p b{color:var(--ink);font-weight:600;}
|
||||
.foot{border-top:1.5px solid var(--ink);padding:10px 18px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px;
|
||||
font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-soft);}
|
||||
.legend{display:flex;gap:16px;flex-wrap:wrap;align-items:center;font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--ink-soft);margin-top:6px;}
|
||||
.legend span{display:inline-flex;gap:6px;align-items:center;}
|
||||
.sw{width:14px;height:10px;border:1px solid var(--ink);display:inline-block;}
|
||||
@media (max-width:720px){
|
||||
.titleblock{grid-template-columns:1fr 1fr;}
|
||||
.tb-title{grid-column:1/-1;border-right:0;border-bottom:1px solid var(--ink);}
|
||||
.lower{grid-template-columns:1fr;}
|
||||
.lower .panel:first-child{border-right:0;}
|
||||
.notes {
|
||||
padding: 18px 22px 24px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
|
||||
gap: 18px 26px;
|
||||
}
|
||||
.note h3 {
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.16em;
|
||||
text-transform: uppercase;
|
||||
margin: 0 0 6px;
|
||||
color: var(--acc);
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: baseline;
|
||||
}
|
||||
.note h3 .n {
|
||||
color: var(--dim);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.note p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.45;
|
||||
color: #3a362e;
|
||||
}
|
||||
.note p b {
|
||||
color: var(--ink);
|
||||
font-weight: 600;
|
||||
}
|
||||
.foot {
|
||||
border-top: 1.5px solid var(--ink);
|
||||
padding: 10px 18px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
font-family: var(--mono);
|
||||
font-size: 10.5px;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.legend {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
font-family: var(--mono);
|
||||
font-size: 10.5px;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--ink-soft);
|
||||
margin-top: 6px;
|
||||
}
|
||||
.legend span {
|
||||
display: inline-flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
}
|
||||
.sw {
|
||||
width: 14px;
|
||||
height: 10px;
|
||||
border: 1px solid var(--ink);
|
||||
display: inline-block;
|
||||
}
|
||||
@media (max-width: 720px) {
|
||||
.titleblock {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.tb-title {
|
||||
grid-column: 1/-1;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid var(--ink);
|
||||
}
|
||||
.lower {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lower .panel:first-child {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="wrap">
|
||||
<div class="sheet">
|
||||
|
||||
<div class="titleblock">
|
||||
<div class="tb tb-title">
|
||||
<div class="name">Typoena</div>
|
||||
<div class="sub">Enclosure concept · typewriter body</div>
|
||||
</div>
|
||||
<div class="tb"><div class="k">Panel</div><div class="v">GDEY0579T93</div><div class="k" style="margin-top:8px">Board</div><div class="v">ESP32-S3</div></div>
|
||||
<div class="tb"><div class="k">Units</div><div class="v">mm</div><div class="k" style="margin-top:8px">Scale</div><div class="v">to-fit</div></div>
|
||||
<div class="tb"><div class="k">Rev</div><div class="v">v0 · concept</div><div class="k" style="margin-top:8px">Date</div><div class="v">2026-07-11</div></div>
|
||||
<div class="tb">
|
||||
<div class="k">Panel</div>
|
||||
<div class="v">GDEY0579T93</div>
|
||||
<div class="k" style="margin-top: 8px">Board</div>
|
||||
<div class="v">ESP32-S3</div>
|
||||
</div>
|
||||
<div class="tb">
|
||||
<div class="k">Units</div>
|
||||
<div class="v">mm</div>
|
||||
<div class="k" style="margin-top: 8px">Scale</div>
|
||||
<div class="v">to-fit</div>
|
||||
</div>
|
||||
<div class="tb">
|
||||
<div class="k">Rev</div>
|
||||
<div class="v">v0 · concept</div>
|
||||
<div class="k" style="margin-top: 8px">Date</div>
|
||||
<div class="v">2026-07-11</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="intro">
|
||||
<p><span class="lead">The screen is the sheet of paper.</span> A shallow sage wedge with a reclined deck; the e-paper strip sits where a typewriter's page would be, a decorative platen roller and two knobs ride the back edge, and the keyboard you bring rests in front. Every dimension below is from the real datasheets — this is the shape to react to before I cut the parametric model.</p>
|
||||
<p>
|
||||
<span class="lead">The screen is the sheet of paper.</span> A shallow
|
||||
sage wedge with a reclined deck; the e-paper strip sits where a
|
||||
typewriter's page would be, a decorative platen roller and two knobs
|
||||
ride the back edge, and the keyboard you bring rests in front. Every
|
||||
dimension below is from the real datasheets — this is the shape to react
|
||||
to before I cut the parametric model.
|
||||
</p>
|
||||
<div class="legend">
|
||||
<span><i class="sw" style="background:var(--acc)"></i>body</span>
|
||||
<span><i class="sw" style="background:var(--acc-l)"></i>platen / deck / feet</span>
|
||||
<span><i class="sw" style="background:var(--screen)"></i>e-paper</span>
|
||||
<span><i class="sw" style="background:var(--dim);border-color:var(--dim)"></i>dimensions</span>
|
||||
<span><i class="sw" style="background: var(--acc)"></i>body</span>
|
||||
<span
|
||||
><i class="sw" style="background: var(--acc-l)"></i>platen / deck /
|
||||
feet</span
|
||||
>
|
||||
<span><i class="sw" style="background: var(--screen)"></i>e-paper</span>
|
||||
<span
|
||||
><i
|
||||
class="sw"
|
||||
style="background: var(--dim); border-color: var(--dim)"
|
||||
></i
|
||||
>dimensions</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="views">
|
||||
<div class="panel">
|
||||
<h2>Side profile <span class="tag">— the silhouette</span></h2>
|
||||
<p class="cap">The money view: shallow deck reclined ~18°, platen & knob at the back, ports on the tail, your keyboard ghosted in front.</p>
|
||||
<svg id="v-side" viewBox="-82 -96 200 118" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Side profile of the enclosure"></svg>
|
||||
<p class="cap">
|
||||
The money view: shallow deck reclined ~18°, platen & knob at the
|
||||
back, ports on the tail, your keyboard ghosted in front.
|
||||
</p>
|
||||
<svg
|
||||
id="v-side"
|
||||
viewBox="-82 -96 200 118"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
role="img"
|
||||
aria-label="Side profile of the enclosure"
|
||||
></svg>
|
||||
</div>
|
||||
<div class="lower">
|
||||
<div class="panel">
|
||||
<h2>Front elevation <span class="tag">— width</span></h2>
|
||||
<p class="cap">Letterbox screen across the deck; knobs poke past the sides.</p>
|
||||
<svg id="v-front" viewBox="-34 -96 244 118" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Front elevation"></svg>
|
||||
<p class="cap">
|
||||
Letterbox screen across the deck; knobs poke past the sides.
|
||||
</p>
|
||||
<svg
|
||||
id="v-front"
|
||||
viewBox="-34 -96 244 118"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
role="img"
|
||||
aria-label="Front elevation"
|
||||
></svg>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<h2>Top plan <span class="tag">— deck layout</span></h2>
|
||||
<p class="cap">Screen forward, platen band aft, ports along the back edge.</p>
|
||||
<svg id="v-top" viewBox="-34 -120 244 136" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Top plan view"></svg>
|
||||
<p class="cap">
|
||||
Screen forward, platen band aft, ports along the back edge.
|
||||
</p>
|
||||
<svg
|
||||
id="v-top"
|
||||
viewBox="-34 -120 244 136"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
role="img"
|
||||
aria-label="Top plan view"
|
||||
></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="notes">
|
||||
<div class="note"><h3><span class="n">01</span> Cheap-ish body</h3><p>You picked the higher-material form, but it stays a <b>shell</b>: ~2.4 mm walls, open bottom, a screwed baseplate. Hollow inside, no infill spent on a solid block.</p></div>
|
||||
<div class="note"><h3><span class="n">02</span> Color does the work</h3><p>Print the body in <b>matte sage</b>, platen & knobs in cream or black. Two-tone via a filament change reads unmistakably "typewriter" for free.</p></div>
|
||||
<div class="note"><h3><span class="n">03</span> Decorative cues</h3><p>Platen roller + two knobs are <b>cosmetic</b> (your call) — printed separately, no wiring, no GPIO. Round feet finish the machined look.</p></div>
|
||||
<div class="note"><h3><span class="n">04</span> Fragile glass</h3><p>The 1 mm panel drops into a rebate behind a bezel lip that overlaps ~6 mm; the FPC folds back to the DESPI-C579 breakout in the cavity.</p></div>
|
||||
<div class="note"><h3><span class="n">05</span> The one tunable</h3><p><b>Deck angle</b> is the ergonomics dial. 18° is typewriter-shallow; 28–35° reads better seated. Say the word and I'll steepen it.</p></div>
|
||||
<div class="note"><h3><span class="n">06</span> Optional lid</h3><p>Your docs say "hinged lid" — a cover latching over the deck echoes a portable typewriter's case and guards the glass in a bag. Toggled off by default.</p></div>
|
||||
<div class="note">
|
||||
<h3><span class="n">01</span> Cheap-ish body</h3>
|
||||
<p>
|
||||
You picked the higher-material form, but it stays a <b>shell</b>:
|
||||
~2.4 mm walls, open bottom, a screwed baseplate. Hollow inside,
|
||||
no infill spent on a solid block.
|
||||
</p>
|
||||
</div>
|
||||
<div class="note">
|
||||
<h3><span class="n">02</span> Color does the work</h3>
|
||||
<p>
|
||||
Print the body in <b>matte sage</b>, platen & knobs in cream or
|
||||
black. Two-tone via a filament change reads unmistakably "typewriter"
|
||||
for free.
|
||||
</p>
|
||||
</div>
|
||||
<div class="note">
|
||||
<h3><span class="n">03</span> Decorative cues</h3>
|
||||
<p>
|
||||
Platen roller + two knobs are <b>cosmetic</b> (your call) — printed
|
||||
separately, no wiring, no GPIO. Round feet finish the machined look.
|
||||
</p>
|
||||
</div>
|
||||
<div class="note">
|
||||
<h3><span class="n">04</span> Fragile glass</h3>
|
||||
<p>
|
||||
The 1 mm panel drops into a rebate behind a bezel lip that
|
||||
overlaps ~6 mm; the FPC folds back to the DESPI-C579 breakout in
|
||||
the cavity.
|
||||
</p>
|
||||
</div>
|
||||
<div class="note">
|
||||
<h3><span class="n">05</span> The one tunable</h3>
|
||||
<p>
|
||||
<b>Deck angle</b> is the ergonomics dial. 18° is typewriter-shallow;
|
||||
28–35° reads better seated. Say the word and I'll steepen it.
|
||||
</p>
|
||||
</div>
|
||||
<div class="note">
|
||||
<h3><span class="n">06</span> Optional lid</h3>
|
||||
<p>
|
||||
Your docs say "hinged lid" — a cover latching over the deck echoes a
|
||||
portable typewriter's case and guards the glass in a bag. Toggled off
|
||||
by default.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="foot">
|
||||
<span>Typoena · writing appliance</span>
|
||||
<span>Screen 150.9 × 56.9 × 1.0 · active 139.0 × 47.7 · pitch 0.1755</span>
|
||||
<span
|
||||
>Screen 150.9 × 56.9 × 1.0 · active 139.0 × 47.7 · pitch 0.1755</span
|
||||
>
|
||||
<span>Orthographic · third-angle · not for manufacture</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
// ---- parameters (mm) ----
|
||||
var W=176, D=104, Hf=24, Hb=58; // body: width, depth, front/back height
|
||||
var SW=151, SH=57, AW=139.0, AH=47.74; // screen glass + active area
|
||||
var sx0=(W-SW)/2, sx1=(W+SW)/2; // screen x extents
|
||||
var sy0=8, sy1=8+54; // screen y extents on deck (57 along slope ~ 54 in plan)
|
||||
var Py=92, Pr=11, Kr=14; // platen y-centre, roller radius, knob radius
|
||||
function zTop(y){ return Hf + (Hb-Hf)*y/D; }
|
||||
var Pz=zTop(Py)+Pr; // platen centre height (sits on deck)
|
||||
var footR=6;
|
||||
;(function () {
|
||||
// ---- parameters (mm) ----
|
||||
var W = 176,
|
||||
D = 104,
|
||||
Hf = 24,
|
||||
Hb = 58 // body: width, depth, front/back height
|
||||
var SW = 151,
|
||||
SH = 57,
|
||||
AW = 139.0,
|
||||
AH = 47.74 // screen glass + active area
|
||||
var sx0 = (W - SW) / 2,
|
||||
sx1 = (W + SW) / 2 // screen x extents
|
||||
var sy0 = 8,
|
||||
sy1 = 8 + 54 // screen y extents on deck (57 along slope ~ 54 in plan)
|
||||
var Py = 92,
|
||||
Pr = 11,
|
||||
Kr = 14 // platen y-centre, roller radius, knob radius
|
||||
function zTop(y) {
|
||||
return Hf + ((Hb - Hf) * y) / D
|
||||
}
|
||||
var Pz = zTop(Py) + Pr // platen centre height (sits on deck)
|
||||
var footR = 6
|
||||
|
||||
// ---- palette ----
|
||||
var INK="#26231D", PAPER="#F7F4EA", ACC="#3C6152", ACCL="#6E9483",
|
||||
DIM="#B0553B", HAIR="#B9B09A", GHOST="#8f8a7c";
|
||||
var MONO="'SFMono-Regular',ui-monospace,Menlo,Consolas,'Courier New',monospace";
|
||||
// ---- palette ----
|
||||
var INK = '#26231D',
|
||||
PAPER = '#F7F4EA',
|
||||
ACC = '#3C6152',
|
||||
ACCL = '#6E9483',
|
||||
DIM = '#B0553B',
|
||||
HAIR = '#B9B09A',
|
||||
GHOST = '#8f8a7c'
|
||||
var MONO =
|
||||
"'SFMono-Regular',ui-monospace,Menlo,Consolas,'Courier New',monospace"
|
||||
|
||||
// ---- primitives (model coords; +b is up, drawn as svg y=-b) ----
|
||||
function poly(pts,fill,stroke,sw){var p=pts.map(function(q){return q[0]+","+(-q[1]);}).join(" ");
|
||||
return '<polygon points="'+p+'" fill="'+fill+'" stroke="'+stroke+'" stroke-width="'+sw+'" stroke-linejoin="round"/>';}
|
||||
function rect(a,b,w,h,fill,stroke,sw,rx,dash){
|
||||
return '<rect x="'+a+'" y="'+(-(b+h))+'" width="'+w+'" height="'+h+'" rx="'+(rx||0)+'" fill="'+fill+'" stroke="'+stroke+'" stroke-width="'+sw+'"'+(dash?' stroke-dasharray="'+dash+'"':'')+'/>';}
|
||||
function circ(a,b,r,fill,stroke,sw){return '<circle cx="'+a+'" cy="'+(-b)+'" r="'+r+'" fill="'+fill+'" stroke="'+stroke+'" stroke-width="'+sw+'"/>';}
|
||||
function line(a1,b1,a2,b2,stroke,sw,dash){
|
||||
return '<line x1="'+a1+'" y1="'+(-b1)+'" x2="'+a2+'" y2="'+(-b2)+'" stroke="'+stroke+'" stroke-width="'+sw+'" stroke-linecap="round"'+(dash?' stroke-dasharray="'+dash+'"':'')+'/>';}
|
||||
function txt(a,b,s,o){o=o||{};var fs=o.fs||3.4,fill=o.fill||INK,anc=o.anchor||"middle",
|
||||
rot=o.rot?' transform="rotate('+o.rot+' '+a+' '+(-b)+')"':'',ls=o.ls!=null?o.ls:0.2;
|
||||
return '<text x="'+a+'" y="'+(-b)+'" font-size="'+fs+'" fill="'+fill+'" text-anchor="'+anc+'" letter-spacing="'+ls+'"'+rot+' font-family="'+MONO+'">'+s+'</text>';}
|
||||
// ---- primitives (model coords; +b is up, drawn as svg y=-b) ----
|
||||
function poly(pts, fill, stroke, sw) {
|
||||
var p = pts
|
||||
.map(function (q) {
|
||||
return q[0] + ',' + -q[1]
|
||||
})
|
||||
.join(' ')
|
||||
return (
|
||||
'<polygon points="' +
|
||||
p +
|
||||
'" fill="' +
|
||||
fill +
|
||||
'" stroke="' +
|
||||
stroke +
|
||||
'" stroke-width="' +
|
||||
sw +
|
||||
'" stroke-linejoin="round"/>'
|
||||
)
|
||||
}
|
||||
function rect(a, b, w, h, fill, stroke, sw, rx, dash) {
|
||||
return (
|
||||
'<rect x="' +
|
||||
a +
|
||||
'" y="' +
|
||||
-(b + h) +
|
||||
'" width="' +
|
||||
w +
|
||||
'" height="' +
|
||||
h +
|
||||
'" rx="' +
|
||||
(rx || 0) +
|
||||
'" fill="' +
|
||||
fill +
|
||||
'" stroke="' +
|
||||
stroke +
|
||||
'" stroke-width="' +
|
||||
sw +
|
||||
'"' +
|
||||
(dash ? ' stroke-dasharray="' + dash + '"' : '') +
|
||||
'/>'
|
||||
)
|
||||
}
|
||||
function circ(a, b, r, fill, stroke, sw) {
|
||||
return (
|
||||
'<circle cx="' +
|
||||
a +
|
||||
'" cy="' +
|
||||
-b +
|
||||
'" r="' +
|
||||
r +
|
||||
'" fill="' +
|
||||
fill +
|
||||
'" stroke="' +
|
||||
stroke +
|
||||
'" stroke-width="' +
|
||||
sw +
|
||||
'"/>'
|
||||
)
|
||||
}
|
||||
function line(a1, b1, a2, b2, stroke, sw, dash) {
|
||||
return (
|
||||
'<line x1="' +
|
||||
a1 +
|
||||
'" y1="' +
|
||||
-b1 +
|
||||
'" x2="' +
|
||||
a2 +
|
||||
'" y2="' +
|
||||
-b2 +
|
||||
'" stroke="' +
|
||||
stroke +
|
||||
'" stroke-width="' +
|
||||
sw +
|
||||
'" stroke-linecap="round"' +
|
||||
(dash ? ' stroke-dasharray="' + dash + '"' : '') +
|
||||
'/>'
|
||||
)
|
||||
}
|
||||
function txt(a, b, s, o) {
|
||||
o = o || {}
|
||||
var fs = o.fs || 3.4,
|
||||
fill = o.fill || INK,
|
||||
anc = o.anchor || 'middle',
|
||||
rot = o.rot
|
||||
? ' transform="rotate(' + o.rot + ' ' + a + ' ' + -b + ')"'
|
||||
: '',
|
||||
ls = o.ls != null ? o.ls : 0.2
|
||||
return (
|
||||
'<text x="' +
|
||||
a +
|
||||
'" y="' +
|
||||
-b +
|
||||
'" font-size="' +
|
||||
fs +
|
||||
'" fill="' +
|
||||
fill +
|
||||
'" text-anchor="' +
|
||||
anc +
|
||||
'" letter-spacing="' +
|
||||
ls +
|
||||
'"' +
|
||||
rot +
|
||||
' font-family="' +
|
||||
MONO +
|
||||
'">' +
|
||||
s +
|
||||
'</text>'
|
||||
)
|
||||
}
|
||||
|
||||
// dimension helpers (oxide red)
|
||||
function hdim(a1,a2,b,label,below){var t=1.6,s="";
|
||||
s+=line(a1,b,a2,b,DIM,0.3);
|
||||
s+=line(a1-t,b-t,a1+t,b+t,DIM,0.3);
|
||||
s+=line(a2-t,b-t,a2+t,b+t,DIM,0.3);
|
||||
s+=txt((a1+a2)/2, b+(below?-4.2:2.4), label, {fs:3.2,fill:DIM});
|
||||
return s;}
|
||||
function vdim(b1,b2,a,label,right){var t=1.6,s="";
|
||||
s+=line(a,b1,a,b2,DIM,0.3);
|
||||
s+=line(a-t,b1-t,a+t,b1+t,DIM,0.3);
|
||||
s+=line(a-t,b2-t,a+t,b2+t,DIM,0.3);
|
||||
s+=txt(a+(right?3.2:-3.2),(b1+b2)/2,label,{fs:3.2,fill:DIM,rot:-90});
|
||||
return s;}
|
||||
function screenlines(x0,y0,x1,y1,n){var s="",i,y;for(i=1;i<=n;i++){y=y0+(y1-y0)*i/(n+1);
|
||||
s+=line(x0+2,y,x1-2,y,HAIR,0.3);}return s;}
|
||||
// dimension helpers (oxide red)
|
||||
function hdim(a1, a2, b, label, below) {
|
||||
var t = 1.6,
|
||||
s = ''
|
||||
s += line(a1, b, a2, b, DIM, 0.3)
|
||||
s += line(a1 - t, b - t, a1 + t, b + t, DIM, 0.3)
|
||||
s += line(a2 - t, b - t, a2 + t, b + t, DIM, 0.3)
|
||||
s += txt((a1 + a2) / 2, b + (below ? -4.2 : 2.4), label, {
|
||||
fs: 3.2,
|
||||
fill: DIM,
|
||||
})
|
||||
return s
|
||||
}
|
||||
function vdim(b1, b2, a, label, right) {
|
||||
var t = 1.6,
|
||||
s = ''
|
||||
s += line(a, b1, a, b2, DIM, 0.3)
|
||||
s += line(a - t, b1 - t, a + t, b1 + t, DIM, 0.3)
|
||||
s += line(a - t, b2 - t, a + t, b2 + t, DIM, 0.3)
|
||||
s += txt(a + (right ? 3.2 : -3.2), (b1 + b2) / 2, label, {
|
||||
fs: 3.2,
|
||||
fill: DIM,
|
||||
rot: -90,
|
||||
})
|
||||
return s
|
||||
}
|
||||
function screenlines(x0, y0, x1, y1, n) {
|
||||
var s = '',
|
||||
i,
|
||||
y
|
||||
for (i = 1; i <= n; i++) {
|
||||
y = y0 + ((y1 - y0) * i) / (n + 1)
|
||||
s += line(x0 + 2, y, x1 - 2, y, HAIR, 0.3)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ---- SIDE (a=depth Y, b=height Z) ----
|
||||
(function(){var s="";
|
||||
s+=line(-66,0,110,0,HAIR,0.4); // ground
|
||||
s+=rect(-58,0,50,12,"rgba(60,97,82,.06)",GHOST,0.4,2,"2 1.6"); // keyboard ghost
|
||||
s+=txt(-33,-4,"BYO KEYBOARD",{fs:2.9,fill:GHOST});
|
||||
s+=poly([[0,0],[D,0],[D,Hb],[0,Hf]],ACC,INK,0.7); // wedge
|
||||
s+=txt(30,37,"DECK ≈18°",{fs:3.1,fill:PAPER});
|
||||
// screen strip on slope
|
||||
s+=line(sy0,zTop(sy0),sy1,zTop(sy1),INK,3.9);
|
||||
s+=line(sy0,zTop(sy0),sy1,zTop(sy1),PAPER,3.1);
|
||||
// platen roller + knob
|
||||
s+=circ(Py,Pz,Pr,ACCL,INK,0.5);
|
||||
s+=circ(Py,Pz,Kr,ACCL,INK,0.6);
|
||||
s+=circ(Py,Pz,2.4,ACC,INK,0.4);
|
||||
s+=txt(Py,Pz+Kr+3,"PLATEN Ø22",{fs:3,fill:DIM});
|
||||
// ports on back face
|
||||
s+=rect(D-6,9,6,4,PAPER,INK,0.4,.6);
|
||||
s+=rect(D-6,15,6,4,PAPER,INK,0.4,.6);
|
||||
s+=rect(D-6,21,7,3,PAPER,INK,0.4,.6);
|
||||
s+=line(D,16,D+8,16,DIM,0.3);
|
||||
s+=txt(D+9,16,"USB-C ×2 + µSD",{fs:2.9,fill:INK,anchor:"start"});
|
||||
// feet
|
||||
s+=rect(6,-5,12,5,ACCL,INK,0.4,1);
|
||||
s+=rect(D-18,-5,12,5,ACCL,INK,0.4,1);
|
||||
// dims
|
||||
s+=hdim(0,D,-9,"104 depth",true);
|
||||
s+=vdim(0,Hf,-4,"24");
|
||||
s+=vdim(0,Hb,D+4,"58",true);
|
||||
document.getElementById("v-side").innerHTML=s;
|
||||
})();
|
||||
// ---- SIDE (a=depth Y, b=height Z) ----
|
||||
;(function () {
|
||||
var s = ''
|
||||
s += line(-66, 0, 110, 0, HAIR, 0.4) // ground
|
||||
s += rect(-58, 0, 50, 12, 'rgba(60,97,82,.06)', GHOST, 0.4, 2, '2 1.6') // keyboard ghost
|
||||
s += txt(-33, -4, 'BYO KEYBOARD', { fs: 2.9, fill: GHOST })
|
||||
s += poly(
|
||||
[
|
||||
[0, 0],
|
||||
[D, 0],
|
||||
[D, Hb],
|
||||
[0, Hf],
|
||||
],
|
||||
ACC,
|
||||
INK,
|
||||
0.7,
|
||||
) // wedge
|
||||
s += txt(30, 37, 'DECK ≈18°', { fs: 3.1, fill: PAPER })
|
||||
// screen strip on slope
|
||||
s += line(sy0, zTop(sy0), sy1, zTop(sy1), INK, 3.9)
|
||||
s += line(sy0, zTop(sy0), sy1, zTop(sy1), PAPER, 3.1)
|
||||
// platen roller + knob
|
||||
s += circ(Py, Pz, Pr, ACCL, INK, 0.5)
|
||||
s += circ(Py, Pz, Kr, ACCL, INK, 0.6)
|
||||
s += circ(Py, Pz, 2.4, ACC, INK, 0.4)
|
||||
s += txt(Py, Pz + Kr + 3, 'PLATEN Ø22', { fs: 3, fill: DIM })
|
||||
// ports on back face
|
||||
s += rect(D - 6, 9, 6, 4, PAPER, INK, 0.4, 0.6)
|
||||
s += rect(D - 6, 15, 6, 4, PAPER, INK, 0.4, 0.6)
|
||||
s += rect(D - 6, 21, 7, 3, PAPER, INK, 0.4, 0.6)
|
||||
s += line(D, 16, D + 8, 16, DIM, 0.3)
|
||||
s += txt(D + 9, 16, 'USB-C ×2 + µSD', {
|
||||
fs: 2.9,
|
||||
fill: INK,
|
||||
anchor: 'start',
|
||||
})
|
||||
// feet
|
||||
s += rect(6, -5, 12, 5, ACCL, INK, 0.4, 1)
|
||||
s += rect(D - 18, -5, 12, 5, ACCL, INK, 0.4, 1)
|
||||
// dims
|
||||
s += hdim(0, D, -9, '104 depth', true)
|
||||
s += vdim(0, Hf, -4, '24')
|
||||
s += vdim(0, Hb, D + 4, '58', true)
|
||||
document.getElementById('v-side').innerHTML = s
|
||||
})()
|
||||
|
||||
// ---- FRONT (a=width X, b=height Z) ----
|
||||
(function(){var s="";
|
||||
s+=line(-14,0,W+14,0,HAIR,0.4);
|
||||
s+=rect(0,0,W,Hf,ACC,INK,0.7,2); // front face
|
||||
s+=rect(0,Hf,W,Hb-Hf,ACCL,INK,0.5); // deck sliver behind
|
||||
// screen (foreshortened band)
|
||||
s+=rect(sx0,27,SW,18,PAPER,INK,0.5,1);
|
||||
s+=screenlines(sx0,27,sx1,45,4);
|
||||
// platen bar + knobs
|
||||
s+=rect(2,Pz-4,W-4,8,ACCL,INK,0.5,4);
|
||||
s+=circ(-2,Pz,Kr,ACCL,INK,0.6); s+=circ(-2,Pz,2.4,ACC,INK,0.4);
|
||||
s+=circ(W+2,Pz,Kr,ACCL,INK,0.6); s+=circ(W+2,Pz,2.4,ACC,INK,0.4);
|
||||
// feet
|
||||
s+=rect(8,-5,14,5,ACCL,INK,0.4,1);
|
||||
s+=rect(W-22,-5,14,5,ACCL,INK,0.4,1);
|
||||
// dims
|
||||
s+=hdim(0,W,-9,"176 width",true);
|
||||
s+=hdim(-16,W+16,Pz+Kr+2,"≈208 across knobs");
|
||||
s+=hdim(sx0,sx1,20,"151 glass · 139 active");
|
||||
document.getElementById("v-front").innerHTML=s;
|
||||
})();
|
||||
// ---- FRONT (a=width X, b=height Z) ----
|
||||
;(function () {
|
||||
var s = ''
|
||||
s += line(-14, 0, W + 14, 0, HAIR, 0.4)
|
||||
s += rect(0, 0, W, Hf, ACC, INK, 0.7, 2) // front face
|
||||
s += rect(0, Hf, W, Hb - Hf, ACCL, INK, 0.5) // deck sliver behind
|
||||
// screen (foreshortened band)
|
||||
s += rect(sx0, 27, SW, 18, PAPER, INK, 0.5, 1)
|
||||
s += screenlines(sx0, 27, sx1, 45, 4)
|
||||
// platen bar + knobs
|
||||
s += rect(2, Pz - 4, W - 4, 8, ACCL, INK, 0.5, 4)
|
||||
s += circ(-2, Pz, Kr, ACCL, INK, 0.6)
|
||||
s += circ(-2, Pz, 2.4, ACC, INK, 0.4)
|
||||
s += circ(W + 2, Pz, Kr, ACCL, INK, 0.6)
|
||||
s += circ(W + 2, Pz, 2.4, ACC, INK, 0.4)
|
||||
// feet
|
||||
s += rect(8, -5, 14, 5, ACCL, INK, 0.4, 1)
|
||||
s += rect(W - 22, -5, 14, 5, ACCL, INK, 0.4, 1)
|
||||
// dims
|
||||
s += hdim(0, W, -9, '176 width', true)
|
||||
s += hdim(-16, W + 16, Pz + Kr + 2, '≈208 across knobs')
|
||||
s += hdim(sx0, sx1, 20, '151 glass · 139 active')
|
||||
document.getElementById('v-front').innerHTML = s
|
||||
})()
|
||||
|
||||
// ---- TOP (a=width X, b=depth Y; front y=0 at bottom) ----
|
||||
(function(){var s="";
|
||||
s+=rect(0,0,W,D,"rgba(60,97,82,.10)",INK,0.7,4); // body outline
|
||||
// screen
|
||||
s+=rect(sx0,sy0,SW,sy1-sy0,PAPER,INK,0.5,1);
|
||||
s+=screenlines(sx0,sy0,sx1,sy1,5);
|
||||
s+=txt(W/2,(sy0+sy1)/2,"e-paper",{fs:3.4,fill:ACC});
|
||||
s+=txt(W/2,sy0-4,"active 139.0 × 47.74",{fs:2.8,fill:INK});
|
||||
// platen band + knobs
|
||||
s+=rect(2,Py-6,W-4,12,ACCL,INK,0.5,4);
|
||||
s+=circ(-6,Py,Kr,ACCL,INK,0.6); s+=circ(-6,Py,2.4,ACC,INK,0.4);
|
||||
s+=circ(W+6,Py,Kr,ACCL,INK,0.6); s+=circ(W+6,Py,2.4,ACC,INK,0.4);
|
||||
s+=txt(W/2,Py,"platen (decorative)",{fs:2.9,fill:INK});
|
||||
// ports along back edge (y=D)
|
||||
s+=rect(60,D-2,7,4,PAPER,INK,0.4,.6);
|
||||
s+=rect(72,D-2,7,4,PAPER,INK,0.4,.6);
|
||||
s+=rect(86,D-2,8,3,PAPER,INK,0.4,.6);
|
||||
s+=txt(W/2,D+4,"USB-C ×2 · microSD",{fs:2.8,fill:DIM});
|
||||
// dims
|
||||
s+=hdim(0,W,-6,"176",true);
|
||||
s+=vdim(0,D,W+8,"104 deep",true);
|
||||
document.getElementById("v-top").innerHTML=s;
|
||||
})();
|
||||
})();
|
||||
// ---- TOP (a=width X, b=depth Y; front y=0 at bottom) ----
|
||||
;(function () {
|
||||
var s = ''
|
||||
s += rect(0, 0, W, D, 'rgba(60,97,82,.10)', INK, 0.7, 4) // body outline
|
||||
// screen
|
||||
s += rect(sx0, sy0, SW, sy1 - sy0, PAPER, INK, 0.5, 1)
|
||||
s += screenlines(sx0, sy0, sx1, sy1, 5)
|
||||
s += txt(W / 2, (sy0 + sy1) / 2, 'e-paper', { fs: 3.4, fill: ACC })
|
||||
s += txt(W / 2, sy0 - 4, 'active 139.0 × 47.74', { fs: 2.8, fill: INK })
|
||||
// platen band + knobs
|
||||
s += rect(2, Py - 6, W - 4, 12, ACCL, INK, 0.5, 4)
|
||||
s += circ(-6, Py, Kr, ACCL, INK, 0.6)
|
||||
s += circ(-6, Py, 2.4, ACC, INK, 0.4)
|
||||
s += circ(W + 6, Py, Kr, ACCL, INK, 0.6)
|
||||
s += circ(W + 6, Py, 2.4, ACC, INK, 0.4)
|
||||
s += txt(W / 2, Py, 'platen (decorative)', { fs: 2.9, fill: INK })
|
||||
// ports along back edge (y=D)
|
||||
s += rect(60, D - 2, 7, 4, PAPER, INK, 0.4, 0.6)
|
||||
s += rect(72, D - 2, 7, 4, PAPER, INK, 0.4, 0.6)
|
||||
s += rect(86, D - 2, 8, 3, PAPER, INK, 0.4, 0.6)
|
||||
s += txt(W / 2, D + 4, 'USB-C ×2 · microSD', { fs: 2.8, fill: DIM })
|
||||
// dims
|
||||
s += hdim(0, W, -6, '176', true)
|
||||
s += vdim(0, D, W + 8, '104 deep', true)
|
||||
document.getElementById('v-top').innerHTML = s
|
||||
})()
|
||||
})()
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user