feat(site): original device art + amazing polish pass
Adds original OpenScribe illustrations and elevates the whole site from a plain
scaffold to a polished, animated product site.
What changed:
- assets/img/: original SVG artwork (CC-BY-SA, no third-party photos):
- openscribe-wearable.svg - the wearable recorder with a breathing status LED (SMIL
animation that plays even when embedded via <img>).
- openscribe-kit.svg - the dev/kit build: ESP32-S3 board + I2S mic + microSD + LiPo,
with amber trace connectors.
- favicon.svg - the "12" studio mark; wired as the site icon and header logo.
- index.html: two-column hero with the floating device, a trust strip, a featured
showcase (device image + sync diagram), project cards with device thumbnails, and a
new "why open beats a locked box" comparison table (our own words, no competitor art).
- projects/openscribe.html: device hero, the AI picker in a proper panel, and a new
"two ways to build it" section with product figures (wearable + kit) and descriptions.
- assets/styles.css: full theme refresh - atmospheric background, gradient headings,
hero float, hover lift + shadows, product/figure styles, comparison table, and
scroll-reveal transitions (honours prefers-reduced-motion).
- assets/app.js: IntersectionObserver scroll reveals alongside the provider picker.
- README: documents the artwork and that it is original/publishable.
Why:
- The user asked for product images with descriptions, then to "make it amazing" - this
delivers IP-safe original device imagery and a genuinely polished, animated site.
Notes:
- Still zero dependencies and no build step. Validated: app.js passes node --check, all
SVGs are valid XML, HTML section tags balanced, every local link/asset resolves.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e1bf5a2d7a
commit
71217ce3e1
8 changed files with 448 additions and 107 deletions
13
assets/img/favicon.svg
Normal file
13
assets/img/favicon.svg
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="12 Hobbies Studio">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#f0a35e"/>
|
||||
<stop offset="1" stop-color="#6ec7c0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="4" y="4" width="56" height="56" rx="14" fill="url(#g)"/>
|
||||
<text x="32" y="43" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif"
|
||||
font-size="30" font-weight="800" fill="#0c0e13">12</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 613 B |
69
assets/img/openscribe-kit.svg
Normal file
69
assets/img/openscribe-kit.svg
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
Original illustration of the OpenScribe DIY kit (dev build). 12 Hobbies Studio. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 320" role="img"
|
||||
aria-label="OpenScribe DIY kit - an ESP32-S3 board, an I2S microphone, a microSD card and a LiPo battery, connected">
|
||||
<defs>
|
||||
<linearGradient id="pcb" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#1a2b30"/>
|
||||
<stop offset="1" stop-color="#122024"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="cell" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#2c2436"/>
|
||||
<stop offset="1" stop-color="#201a29"/>
|
||||
</linearGradient>
|
||||
<filter id="s2" x="-30%" y="-30%" width="160%" height="160%">
|
||||
<feDropShadow dx="0" dy="7" stdDeviation="10" flood-color="#000000" flood-opacity="0.4"/>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<style>
|
||||
.lbl { font-family: ui-monospace, monospace; font-size: 11px; fill: #8a97ab; letter-spacing: 1px; }
|
||||
.trace { stroke: #f0a35e; stroke-width: 2; stroke-dasharray: 4 5; fill: none; opacity: 0.8; }
|
||||
.pin { fill: #f0a35e; }
|
||||
</style>
|
||||
|
||||
<!-- connectors (drawn first, behind parts) -->
|
||||
<path class="trace" d="M300 118 C 260 130, 250 150, 230 158"/>
|
||||
<path class="trace" d="M420 190 C 380 190, 360 178, 232 172"/>
|
||||
<path class="trace" d="M300 250 C 270 240, 250 210, 232 196"/>
|
||||
|
||||
<!-- ESP32-S3 board -->
|
||||
<g filter="url(#s2)">
|
||||
<rect x="60" y="112" width="172" height="112" rx="12" fill="url(#pcb)" stroke="#2f6a63" stroke-width="2"/>
|
||||
</g>
|
||||
<rect x="96" y="140" width="60" height="60" rx="6" fill="#0f1a1d" stroke="#2f6a63"/>
|
||||
<text x="126" y="174" text-anchor="middle" class="lbl" fill="#6ec7c0">S3</text>
|
||||
<!-- USB-C notch -->
|
||||
<rect x="52" y="156" width="12" height="24" rx="4" fill="#0f1a1d" stroke="#2f6a63"/>
|
||||
<!-- pin headers -->
|
||||
<g class="pin">
|
||||
<circle cx="80" cy="122" r="2.5"/><circle cx="94" cy="122" r="2.5"/><circle cx="108" cy="122" r="2.5"/>
|
||||
<circle cx="122" cy="122" r="2.5"/><circle cx="136" cy="122" r="2.5"/><circle cx="150" cy="122" r="2.5"/>
|
||||
<circle cx="80" cy="214" r="2.5"/><circle cx="94" cy="214" r="2.5"/><circle cx="108" cy="214" r="2.5"/>
|
||||
<circle cx="122" cy="214" r="2.5"/><circle cx="136" cy="214" r="2.5"/><circle cx="150" cy="214" r="2.5"/>
|
||||
</g>
|
||||
<text x="146" y="242" text-anchor="middle" class="lbl">ESP32-S3</text>
|
||||
|
||||
<!-- I2S mic module -->
|
||||
<g filter="url(#s2)">
|
||||
<rect x="300" y="70" width="96" height="66" rx="10" fill="url(#pcb)" stroke="#2f6a63" stroke-width="2"/>
|
||||
</g>
|
||||
<circle cx="348" cy="103" r="17" fill="#0f1a1d" stroke="#2f6a63"/>
|
||||
<circle cx="348" cy="103" r="8" fill="#1c2f34"/>
|
||||
<text x="348" y="130" text-anchor="middle" class="lbl">I2S MIC</text>
|
||||
|
||||
<!-- microSD -->
|
||||
<g filter="url(#s2)">
|
||||
<path d="M424 150 h52 a6 6 0 0 1 6 6 v70 a6 6 0 0 1 -6 6 h-52 a6 6 0 0 1 -6 -6 v-58 l10 -12 a6 6 0 0 1 4 -2 z"
|
||||
fill="#20242f" stroke="#39445a" stroke-width="2"/>
|
||||
</g>
|
||||
<text x="450" y="196" text-anchor="middle" class="lbl">microSD</text>
|
||||
|
||||
<!-- LiPo -->
|
||||
<g filter="url(#s2)">
|
||||
<rect x="252" y="212" width="150" height="72" rx="12" fill="url(#cell)" stroke="#43364f" stroke-width="2"/>
|
||||
</g>
|
||||
<rect x="252" y="212" width="150" height="20" rx="12" fill="#ffffff" opacity="0.05"/>
|
||||
<text x="327" y="255" text-anchor="middle" class="lbl" fill="#c9a0e0">LiPo 3.7V</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
58
assets/img/openscribe-wearable.svg
Normal file
58
assets/img/openscribe-wearable.svg
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
Original illustration of the OpenScribe wearable recorder. 12 Hobbies Studio. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 360" role="img"
|
||||
aria-label="OpenScribe wearable recorder - a small vertical capsule with a record button, status LED and microphone grille">
|
||||
<defs>
|
||||
<linearGradient id="body" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#2b3345"/>
|
||||
<stop offset="1" stop-color="#171b26"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="btn" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#f6b774"/>
|
||||
<stop offset="1" stop-color="#e2894e"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
|
||||
<stop offset="0" stop-color="#6ec7c0" stop-opacity="0.9"/>
|
||||
<stop offset="1" stop-color="#6ec7c0" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<filter id="soft" x="-30%" y="-30%" width="160%" height="160%">
|
||||
<feDropShadow dx="0" dy="10" stdDeviation="14" flood-color="#000000" flood-opacity="0.45"/>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- lanyard loop -->
|
||||
<path d="M160 20 a20 20 0 0 1 20 20 v6 h-10 v-6 a10 10 0 0 0 -20 0 v6 h-10 v-6 a20 20 0 0 1 20 -20 z"
|
||||
fill="#3a465c" stroke="#2c3444"/>
|
||||
<rect x="150" y="40" width="20" height="10" rx="3" fill="#20242f"/>
|
||||
|
||||
<!-- body -->
|
||||
<g filter="url(#soft)">
|
||||
<rect x="108" y="46" width="104" height="286" rx="52" fill="url(#body)" stroke="#39445a" stroke-width="2"/>
|
||||
</g>
|
||||
<!-- left highlight -->
|
||||
<rect x="120" y="60" width="16" height="256" rx="8" fill="#ffffff" opacity="0.06"/>
|
||||
|
||||
<!-- microphone grille -->
|
||||
<g fill="#5b6a80" opacity="0.9">
|
||||
<circle cx="146" cy="96" r="4"/><circle cx="160" cy="90" r="4"/><circle cx="174" cy="96" r="4"/>
|
||||
<circle cx="146" cy="112" r="4"/><circle cx="160" cy="106" r="4"/><circle cx="174" cy="112" r="4"/>
|
||||
</g>
|
||||
|
||||
<!-- status LED (breathing, as if recording) -->
|
||||
<circle cx="160" cy="150" r="22" fill="url(#glow)">
|
||||
<animate attributeName="opacity" values="0.35;1;0.35" dur="2.6s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle cx="160" cy="150" r="6" fill="#8fe4dd">
|
||||
<animate attributeName="r" values="5;7.5;5" dur="2.6s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
|
||||
<!-- engraved wordmark -->
|
||||
<text x="160" y="205" text-anchor="middle" font-family="ui-monospace, monospace"
|
||||
font-size="13" letter-spacing="2" fill="#8a97ab">OPENSCRIBE</text>
|
||||
|
||||
<!-- record button -->
|
||||
<circle cx="160" cy="268" r="30" fill="#12151d" stroke="#39445a" stroke-width="2"/>
|
||||
<circle cx="160" cy="268" r="22" fill="url(#btn)"/>
|
||||
<circle cx="160" cy="268" r="9" fill="#12151d" opacity="0.35"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
Loading…
Add table
Add a link
Reference in a new issue