DIY — Board Product Page
A complete open-hardware board product page for the fictional CIRCUITO Nano R3, built with vanilla HTML, CSS and JavaScript. It pairs an SVG render gallery with hover magnification and a thumbnail strip against a sticky buy box with variant pricing, a quantity stepper, live stock state and an amber add-to-cart flow. Below sit four tabbed panels — overview, a grouped technical spec table, a labelled pinout diagram and a downloads list — plus an accessories carousel and a copyable getting-started snippet.
MCP
Code
:root{
--teal:#00979d;
--teal-d:#007b80;
--teal-l:#4fc3c7;
--ink:#1a2b34;
--ink-2:#3d5561;
--muted:#6b7d87;
--amber:#f5a623;
--amber-d:#d78c10;
--mist:#eef6f6;
--mist-2:#f7fbfb;
--white:#ffffff;
--bg:#ffffff;
--line:rgba(26,43,52,.12);
--line-2:rgba(26,43,52,.22);
--ok:#2f9e6f;
--warn:#d98a2b;
--danger:#d4503e;
--r-sm:6px; --r-md:12px; --r-lg:18px;
--sh-1:0 1px 2px rgba(26,43,52,.06), 0 4px 14px rgba(26,43,52,.06);
--sh-2:0 10px 34px rgba(0,123,128,.14);
--mono:"JetBrains Mono", ui-monospace, monospace;
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
margin:0;
font-family:Inter, system-ui, sans-serif;
line-height:1.5;
color:var(--ink);
background:var(--bg);
-webkit-font-smoothing:antialiased;
}
img,svg{max-width:100%}
h1,h2,h3{margin:0;line-height:1.2;letter-spacing:-.02em}
p{margin:0}
button{font:inherit;color:inherit;cursor:pointer}
a{color:inherit}
.mono{font-family:var(--mono);font-variant-ligatures:none}
.wrap{width:min(1180px,100% - 40px);margin-inline:auto}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
:focus-visible{outline:3px solid var(--teal);outline-offset:2px;border-radius:4px}
.skip{position:absolute;left:-9999px;top:8px;background:var(--ink);color:#fff;padding:10px 16px;border-radius:var(--r-sm);z-index:60}
.skip:focus{left:16px}
/* ---------- top bar ---------- */
.topbar{position:sticky;top:0;z-index:40;background:rgba(255,255,255,.9);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topbar-in{display:flex;align-items:center;gap:24px;min-height:66px}
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--teal-d)}
.brand-mark{width:30px;height:30px}
.brand-name{font-weight:800;letter-spacing:.16em;font-size:15px;color:var(--ink)}
.topnav{display:flex;gap:22px;margin-left:12px}
.topnav a{text-decoration:none;font-size:14px;font-weight:500;color:var(--ink-2);padding:6px 0;border-bottom:2px solid transparent;transition:color .16s,border-color .16s}
.topnav a:hover{color:var(--teal-d);border-color:var(--teal)}
.topbar-actions{margin-left:auto;display:flex;align-items:center;gap:14px}
.pill{font-size:11.5px;font-weight:600;padding:5px 11px;border-radius:999px;letter-spacing:.02em}
.pill-ok{background:var(--mist);color:var(--teal-d);border:1px solid rgba(0,151,157,.22)}
.icon-btn{position:relative;background:var(--white);border:1px solid var(--line);border-radius:var(--r-sm);width:40px;height:40px;display:grid;place-items:center;color:var(--ink);transition:border-color .16s,transform .16s}
.icon-btn:hover{border-color:var(--teal);transform:translateY(-1px)}
.icon-btn svg{width:20px;height:20px;fill:currentColor}
.cart-count{position:absolute;top:-6px;right:-6px;min-width:20px;height:20px;padding:0 5px;border-radius:999px;background:var(--amber);color:#3a2600;font-size:11px;font-weight:700;display:grid;place-items:center;font-family:var(--mono)}
.cart-count.bump{animation:bump .4s ease}
@keyframes bump{50%{transform:scale(1.35)}}
/* ---------- breadcrumbs ---------- */
.crumbs{padding:22px 0 6px}
.crumbs ol{list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;font-size:13px;color:var(--muted)}
.crumbs li+li::before{content:"/";margin-right:8px;color:var(--line-2)}
.crumbs a{text-decoration:none}
.crumbs a:hover{color:var(--teal-d)}
/* ---------- hero ---------- */
.hero{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:56px;padding:22px 0 64px;align-items:start}
.gallery{position:sticky;top:92px}
.stage{
position:relative;overflow:hidden;border-radius:var(--r-lg);
background:
radial-gradient(120% 90% at 50% 0%, #ffffff 0%, var(--mist) 62%, #e2eff0 100%);
border:1px solid var(--line);
aspect-ratio:16/11;display:grid;place-items:center;
}
.stage-badge{position:absolute;left:16px;top:16px;font-size:11px;letter-spacing:.12em;color:var(--teal-d);background:rgba(255,255,255,.82);border:1px solid rgba(0,151,157,.22);padding:4px 9px;border-radius:999px;z-index:2}
.shot{position:absolute;inset:0;display:grid;place-items:center;opacity:0;transform:scale(.985);transition:opacity .32s ease, transform .32s ease;pointer-events:none;padding:22px}
.shot.is-active{opacity:1;transform:none;pointer-events:auto}
.board-svg{width:100%;height:auto;filter:drop-shadow(0 18px 26px rgba(0,90,94,.18));transition:transform .18s ease}
.chip-t{font-family:var(--mono);font-size:17px;font-weight:700;fill:#eaf6f6;letter-spacing:.12em}
.chip-s{font-family:var(--mono);font-size:10px;fill:#8fb6bd;letter-spacing:.16em}
.silk{font-family:var(--mono);font-size:11px;fill:#d8f3f4;letter-spacing:.18em}
.stage[data-mag="1"] .shot.is-active .board-svg{transform:scale(1.55)}
.magnifier-hint{position:absolute;right:14px;bottom:12px;font-size:11px;color:var(--muted);background:rgba(255,255,255,.8);padding:4px 9px;border-radius:999px;border:1px solid var(--line);transition:opacity .2s;z-index:2}
.stage[data-mag="1"] .magnifier-hint{opacity:0}
.thumbs{display:flex;gap:12px;margin-top:14px}
.thumb{flex:1;background:var(--white);border:1px solid var(--line);border-radius:var(--r-md);padding:10px;display:grid;gap:8px;justify-items:center;transition:border-color .16s, box-shadow .16s, transform .16s}
.thumb span.mono{font-size:11px;letter-spacing:.1em;color:var(--muted);text-transform:uppercase}
.thumb:hover{border-color:var(--teal-l);transform:translateY(-2px)}
.thumb.is-active{border-color:var(--teal);box-shadow:0 0 0 3px rgba(0,151,157,.14)}
.thumb.is-active span.mono{color:var(--teal-d)}
.thumb-art{width:100%;height:44px;border-radius:var(--r-sm);position:relative;overflow:hidden}
.thumb-top{background:linear-gradient(180deg,#00a8ae,#00787d)}
.thumb-top::after{content:"";position:absolute;inset:35% 30%;background:#1a2b34;border-radius:3px}
.thumb-bottom{background:linear-gradient(180deg,#00676b,#00494c)}
.thumb-bottom::after{content:"";position:absolute;left:8%;right:8%;top:22%;height:5px;background:#e6c67a;box-shadow:0 20px 0 #e6c67a}
.thumb-headers{background:linear-gradient(180deg,#00a8ae,#00787d)}
.thumb-headers::after{content:"";position:absolute;left:6%;right:6%;top:12%;height:7px;background:#1a2b34;box-shadow:0 24px 0 #1a2b34}
/* ---------- buy box ---------- */
.eyebrow{font-size:11.5px;letter-spacing:.18em;color:var(--teal-d);text-transform:uppercase;font-weight:600}
.buy h1{font-size:clamp(30px,4vw,44px);font-weight:800;margin:8px 0 12px}
.lede{color:var(--ink-2);font-size:16px;max-width:52ch}
.chips{list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin:20px 0 0;padding:0}
.chip{font-size:11.5px;letter-spacing:.04em;background:var(--mist);border:1px solid rgba(0,151,157,.18);color:var(--ink-2);padding:6px 10px;border-radius:999px}
.chip b{color:var(--teal-d);margin-right:6px;letter-spacing:.1em}
.price-row{display:flex;align-items:baseline;gap:12px;margin:26px 0 4px}
.price{font-size:34px;font-weight:800;letter-spacing:-.03em;font-family:var(--mono)}
.price-note{font-size:12px;color:var(--muted)}
.variants{border:0;margin:20px 0 0;padding:0;display:grid;gap:10px}
.variants legend{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);padding:0 0 10px}
.variant{display:flex;align-items:center;gap:14px;border:1px solid var(--line);border-radius:var(--r-md);padding:14px 16px;cursor:pointer;background:var(--white);transition:border-color .16s, background .16s, box-shadow .16s}
.variant:hover{border-color:var(--teal-l);background:var(--mist-2)}
.variant input{appearance:none;width:18px;height:18px;border-radius:50%;border:2px solid var(--line-2);flex:none;transition:border-color .16s, box-shadow .16s}
.variant input:checked{border-color:var(--teal);box-shadow:inset 0 0 0 4px var(--teal)}
.variant:has(input:checked){border-color:var(--teal);background:var(--mist);box-shadow:0 0 0 3px rgba(0,151,157,.12)}
.variant-in{display:grid;gap:2px}
.variant-name{font-weight:600;font-size:15px}
.variant-sub{font-size:11.5px;color:var(--muted)}
.variant-price{margin-left:auto;font-weight:600;font-size:14px}
.qty-row{display:flex;align-items:center;gap:18px;margin:22px 0 0;flex-wrap:wrap}
.stepper{display:flex;align-items:center;border:1px solid var(--line-2);border-radius:var(--r-sm);overflow:hidden;background:var(--white)}
.stepper button{width:42px;height:46px;border:0;background:transparent;font-size:20px;color:var(--ink-2);transition:background .14s}
.stepper button:hover{background:var(--mist)}
.stepper input{width:52px;height:46px;border:0;border-inline:1px solid var(--line);text-align:center;font-size:15px;font-weight:600;background:transparent;color:var(--ink)}
.stepper input:focus{outline:none;background:var(--mist-2)}
.stock{display:flex;align-items:center;gap:8px;font-size:13.5px;color:var(--ink-2)}
.dot{width:9px;height:9px;border-radius:50%;background:var(--ok);box-shadow:0 0 0 4px rgba(47,158,111,.16)}
.stock[data-level="low"] .dot{background:var(--warn);box-shadow:0 0 0 4px rgba(217,138,43,.18)}
.cta{
margin-top:20px;width:100%;border:0;border-radius:var(--r-md);
background:linear-gradient(180deg,var(--amber),var(--amber-d));
color:#3a2600;font-weight:700;font-size:16px;padding:17px 22px;
display:flex;align-items:center;justify-content:center;gap:14px;
box-shadow:0 8px 20px rgba(245,166,35,.34);
transition:transform .14s, box-shadow .14s, filter .14s;
}
.cta:hover{transform:translateY(-2px);box-shadow:0 12px 26px rgba(245,166,35,.42)}
.cta:active{transform:translateY(0) scale(.99);filter:saturate(1.1)}
.cta-total{background:rgba(58,38,0,.14);padding:3px 10px;border-radius:999px;font-size:13.5px}
.assurances{list-style:none;margin:22px 0 0;padding:0;display:grid;gap:9px;font-size:13.5px;color:var(--ink-2)}
.assurances li{display:flex;gap:10px;align-items:center}
.assurances span{color:var(--teal);font-size:15px;width:18px;text-align:center}
/* ---------- tabs ---------- */
.tabs-section{border-top:1px solid var(--line);padding-top:8px}
.tabbar{display:flex;gap:4px;overflow-x:auto;border-bottom:1px solid var(--line);margin-bottom:34px;scrollbar-width:thin}
.tab{background:none;border:0;padding:16px 20px;font-size:15px;font-weight:600;color:var(--muted);border-bottom:3px solid transparent;white-space:nowrap;transition:color .16s, border-color .16s}
.tab:hover{color:var(--ink)}
.tab.is-active{color:var(--teal-d);border-color:var(--teal)}
.panel{animation:fade .28s ease}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.ov-grid{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);gap:52px;padding-bottom:56px}
.prose h2{font-size:26px;margin-bottom:16px}
.prose p{color:var(--ink-2);margin-bottom:14px;max-width:60ch}
.feature-list{list-style:none;margin:0;padding:0;display:grid;gap:2px;background:var(--line);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden}
.feature-list li{background:var(--white);padding:16px 18px;display:grid;gap:4px;transition:background .16s}
.feature-list li:hover{background:var(--mist)}
.feature-list b{font-size:14.5px}
.feature-list span{font-size:13px;color:var(--muted)}
.spec{width:100%;border-collapse:collapse;margin-bottom:56px;font-size:14px}
.spec th,.spec td{text-align:left;padding:12px 16px;border-bottom:1px solid var(--line)}
.spec tr.grp th{background:var(--ink);color:#eaf6f6;font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;font-family:var(--mono);padding:10px 16px;border:0}
.spec tbody tr:not(.grp):hover{background:var(--mist-2)}
.spec th[scope="row"]{font-weight:500;color:var(--ink-2);width:46%}
.spec td{color:var(--ink);font-size:13px}
.pin-wrap{padding-bottom:56px}
.pinout{width:100%;background:var(--mist);border:1px solid var(--line);border-radius:var(--r-lg);padding:12px}
.pin text{font-family:var(--mono);font-size:11px;fill:var(--ink);letter-spacing:.06em}
.pin rect{transition:transform .16s, filter .16s}
.pin:hover rect{filter:brightness(1.12)}
.p-pwr rect{fill:#d4503e}
.p-gnd rect{fill:#1a2b34}
.p-dig rect{fill:#00979d}
.p-ana rect{fill:#f5a623}
.p-com rect{fill:#6b4fc7}
.pin-lbl{font-size:10px;fill:var(--muted);letter-spacing:.1em}
.pin-note{font-size:11px;fill:var(--muted);letter-spacing:.08em}
.legend{list-style:none;display:flex;flex-wrap:wrap;gap:20px;margin:18px 0 0;padding:0;font-size:13px;color:var(--ink-2)}
.legend li{display:flex;align-items:center;gap:8px}
.sw{width:14px;height:14px;border-radius:4px;display:inline-block}
.sw-pwr{background:#d4503e}.sw-gnd{background:#1a2b34}.sw-dig{background:#00979d}.sw-ana{background:#f5a623}.sw-com{background:#6b4fc7}
.docs{list-style:none;margin:0 0 56px;padding:0;display:grid;gap:10px}
.docs li{display:flex;align-items:center;gap:16px;border:1px solid var(--line);border-radius:var(--r-md);padding:14px 16px;background:var(--white);transition:border-color .16s, box-shadow .16s, transform .16s}
.docs li:hover{border-color:var(--teal-l);box-shadow:var(--sh-1);transform:translateY(-1px)}
.doc-ico{flex:none;width:46px;height:46px;border-radius:var(--r-sm);background:var(--mist);color:var(--teal-d);display:grid;place-items:center;font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.06em;border:1px solid rgba(0,151,157,.2)}
.doc-txt{display:grid;gap:2px;min-width:0}
.doc-txt b{font-size:14.5px}
.doc-txt span{font-size:12.5px;color:var(--muted)}
.size{margin-left:auto;font-size:11.5px;color:var(--ink-2);background:var(--mist);border:1px solid var(--line);padding:4px 9px;border-radius:999px;white-space:nowrap}
.dl{background:var(--white);border:1px solid var(--teal);color:var(--teal-d);font-weight:600;font-size:13.5px;padding:9px 16px;border-radius:var(--r-sm);transition:background .16s,color .16s}
.dl:hover{background:var(--teal);color:#fff}
/* ---------- accessories ---------- */
.acc{padding:16px 0 64px;border-top:1px solid var(--line)}
.acc-head{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:34px 0 20px}
.acc-head h2{font-size:24px}
.acc-nav{display:flex;gap:8px}
.acc-nav button{width:40px;height:40px;border-radius:50%;border:1px solid var(--line-2);background:var(--white);font-size:20px;line-height:1;color:var(--ink-2);transition:background .16s,border-color .16s}
.acc-nav button:hover{background:var(--mist);border-color:var(--teal)}
.rail{display:flex;gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:10px;scroll-behavior:smooth}
.rail::-webkit-scrollbar{height:8px}
.rail::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:999px}
.card{flex:0 0 232px;scroll-snap-align:start;border:1px solid var(--line);border-radius:var(--r-md);padding:14px;background:var(--white);display:grid;gap:6px;transition:transform .18s, box-shadow .18s, border-color .18s}
.card:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:var(--teal-l)}
.card h3{font-size:15px}
.card p{font-size:11.5px;color:var(--muted);letter-spacing:.04em}
.card-price{font-weight:700;font-size:15px;color:var(--teal-d)}
.card-art{height:112px;border-radius:var(--r-sm);position:relative;overflow:hidden;background:var(--mist)}
.art-1{background:repeating-linear-gradient(90deg,#1a2b34 0 8px,#eef6f6 8px 18px),linear-gradient(#eef6f6,#eef6f6);background-size:100% 26px,100% 100%;background-repeat:no-repeat;background-position:0 44px,0 0}
.art-2{background:radial-gradient(circle at 30% 40%,#00979d 0 16px,transparent 17px),radial-gradient(circle at 68% 62%,#f5a623 0 18px,transparent 19px),var(--mist)}
.art-3{background:linear-gradient(135deg,var(--mist) 0 46%,#1a2b34 46% 54%,var(--mist) 54%)}
.art-4{background:repeating-linear-gradient(0deg,#fff 0 6px,#dfeef0 6px 12px),repeating-linear-gradient(90deg,#fff 0 6px,#dfeef0 6px 12px)}
.art-5{background:linear-gradient(#1a2b34,#0d171d);position:relative}
.art-5::after{content:"128×64";position:absolute;inset:26% 18%;border:1px solid var(--teal-l);color:var(--teal-l);font-family:var(--mono);font-size:11px;display:grid;place-items:center;border-radius:3px}
.art-6{background:linear-gradient(160deg,#c9d6da,#8fa3ab)}
/* ---------- getting started ---------- */
.start{padding:0 0 72px}
.start-head{margin-bottom:26px}
.start-head h2{font-size:28px;margin-top:8px}
.steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin-bottom:24px}
.step{border:1px solid var(--line);border-left:3px solid var(--teal);border-radius:var(--r-md);padding:20px;background:var(--mist-2);display:grid;gap:8px;align-content:start;transition:transform .18s, box-shadow .18s}
.step:hover{transform:translateY(-3px);box-shadow:var(--sh-1)}
.num{font-size:12px;letter-spacing:.18em;color:var(--teal-d);font-weight:700}
.step h3{font-size:17px}
.step p{font-size:14px;color:var(--ink-2)}
.code{border-radius:var(--r-md);overflow:hidden;border:1px solid rgba(26,43,52,.5);background:#0f2027}
.code-bar{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:#1a2b34;color:#cfe6e8;font-size:12px;letter-spacing:.08em}
.copy{background:transparent;border:1px solid rgba(207,230,232,.34);color:#cfe6e8;font-size:12px;font-weight:600;padding:5px 12px;border-radius:var(--r-sm);transition:background .16s,border-color .16s}
.copy:hover{background:rgba(207,230,232,.14);border-color:var(--teal-l)}
.copy.done{background:var(--ok);border-color:var(--ok);color:#fff}
.code pre{margin:0;padding:18px;overflow-x:auto;color:#d7ecee;font-size:13px;line-height:1.7}
/* ---------- footer ---------- */
.foot{border-top:1px solid var(--line);background:var(--mist-2)}
.foot-in{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;padding:22px 0;font-size:12px;color:var(--muted)}
/* ---------- toasts ---------- */
.toasts{position:fixed;right:20px;bottom:20px;display:grid;gap:10px;z-index:80}
.toast{background:var(--ink);color:#eaf6f6;padding:12px 16px;border-radius:var(--r-md);font-size:13.5px;box-shadow:0 12px 30px rgba(26,43,52,.3);border-left:3px solid var(--amber);animation:slide .3s ease;max-width:320px}
.toast.out{animation:slideout .3s ease forwards}
@keyframes slide{from{opacity:0;transform:translateX(24px)}to{opacity:1;transform:none}}
@keyframes slideout{to{opacity:0;transform:translateX(24px)}}
@media (prefers-reduced-motion:reduce){
*{animation-duration:.01ms !important;transition-duration:.01ms !important}
.rail{scroll-behavior:auto}
}
@media (max-width:960px){
.hero{grid-template-columns:1fr;gap:36px}
.gallery{position:static}
.ov-grid{grid-template-columns:1fr;gap:32px}
.steps{grid-template-columns:1fr}
.topnav{display:none}
}
@media (max-width:520px){
.wrap{width:min(1180px,100% - 28px)}
.topbar-in{min-height:58px;gap:12px}
.pill{display:none}
.buy h1{font-size:28px}
.price{font-size:28px}
.chips{gap:6px}
.chip{font-size:10.5px;padding:5px 8px}
.variant{padding:12px;gap:10px}
.variant-price{font-size:13px}
.qty-row{gap:12px}
.stock{font-size:12.5px}
.tab{padding:13px 14px;font-size:14px}
.spec th,.spec td{padding:10px 12px;font-size:12.5px}
.spec th[scope="row"]{width:50%}
.docs li{flex-wrap:wrap;gap:10px}
.doc-txt{flex:1 1 60%}
.dl{flex:1 1 100%}
.size{margin-left:0}
.card{flex-basis:200px}
.toasts{left:14px;right:14px;bottom:14px}
.toast{max-width:none}
.foot-in{font-size:11px}
}(function () {
"use strict";
var $ = function (s, r) { return (r || document).querySelector(s); };
var $$ = function (s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); };
/* ---------------- toast ---------------- */
var toastHost = $("#toasts");
function toast(msg, ms) {
var el = document.createElement("div");
el.className = "toast";
el.textContent = msg;
toastHost.appendChild(el);
setTimeout(function () {
el.classList.add("out");
setTimeout(function () { el.remove(); }, 320);
}, ms || 2600);
}
/* ---------------- gallery ---------------- */
var stage = $("#stage");
var shots = $$(".shot");
var thumbs = $$(".thumb");
function showShot(name) {
shots.forEach(function (s) { s.classList.toggle("is-active", s.dataset.shot === name); });
thumbs.forEach(function (t) {
var on = t.dataset.shot === name;
t.classList.toggle("is-active", on);
t.setAttribute("aria-selected", on ? "true" : "false");
});
}
thumbs.forEach(function (t, i) {
t.addEventListener("click", function () { showShot(t.dataset.shot); });
t.addEventListener("keydown", function (e) {
var d = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
if (!d) return;
e.preventDefault();
var next = thumbs[(i + d + thumbs.length) % thumbs.length];
next.focus();
showShot(next.dataset.shot);
});
});
/* magnifier: translate origin with pointer */
stage.addEventListener("pointermove", function (e) {
var r = stage.getBoundingClientRect();
var x = ((e.clientX - r.left) / r.width) * 100;
var y = ((e.clientY - r.top) / r.height) * 100;
var art = $(".shot.is-active .board-svg");
if (art) art.style.transformOrigin = x + "% " + y + "%";
stage.dataset.mag = "1";
});
stage.addEventListener("pointerleave", function () { stage.dataset.mag = "0"; });
stage.addEventListener("blur", function () { stage.dataset.mag = "0"; });
/* ---------------- buy box ---------------- */
var priceEl = $("#price");
var priceNote = $("#priceNote");
var ctaTotal = $("#ctaTotal");
var qtyEl = $("#qty");
var stockEl = $("#stock");
var stockText = $("#stockText");
var money = function (n) { return "$" + n.toFixed(2); };
function currentVariant() { return $('input[name="variant"]:checked'); }
function qty() { return Math.max(1, Math.min(99, parseInt(qtyEl.value, 10) || 1)); }
function render() {
var v = currentVariant();
var unitPrice = parseFloat(v.dataset.price);
var units = parseInt(v.dataset.unit, 10);
var q = qty();
qtyEl.value = String(q);
priceEl.textContent = money(unitPrice);
priceNote.textContent = units > 1
? "excl. VAT · " + money(unitPrice / units) + " per board"
: "excl. VAT · unit " + money(unitPrice);
ctaTotal.textContent = money(unitPrice * q);
if (v.dataset.stock === "low") {
stockEl.dataset.level = "low";
stockText.textContent = "Low stock — 9 trays left";
} else {
stockEl.dataset.level = "in";
stockText.textContent = "In stock — ships in 24 h";
}
}
$$('input[name="variant"]').forEach(function (r) {
r.addEventListener("change", function () {
render();
var name = r.closest(".variant").querySelector(".variant-name").textContent;
toast("Variant set to " + name.toLowerCase() + ".");
});
});
$("#qtyMinus").addEventListener("click", function () { qtyEl.value = String(qty() - 1); render(); });
$("#qtyPlus").addEventListener("click", function () { qtyEl.value = String(qty() + 1); render(); });
qtyEl.addEventListener("input", function () { qtyEl.value = qtyEl.value.replace(/[^0-9]/g, ""); });
qtyEl.addEventListener("change", render);
qtyEl.addEventListener("keydown", function (e) {
if (e.key === "ArrowUp") { e.preventDefault(); qtyEl.value = String(qty() + 1); render(); }
if (e.key === "ArrowDown") { e.preventDefault(); qtyEl.value = String(qty() - 1); render(); }
});
var cartCount = $("#cartCount");
var cart = 0;
$("#addBtn").addEventListener("click", function () {
var v = currentVariant();
var boards = qty() * parseInt(v.dataset.unit, 10);
cart += boards;
cartCount.textContent = String(cart);
cartCount.classList.remove("bump");
void cartCount.offsetWidth;
cartCount.classList.add("bump");
toast("Added " + boards + " × Circuito Nano R3 — " + ctaTotal.textContent + " in cart.");
});
$("#cartBtn").addEventListener("click", function () {
toast(cart === 0 ? "Your cart is empty." : "Cart: " + cart + " board" + (cart === 1 ? "" : "s") + " ready for checkout.");
});
render();
/* ---------------- tabs ---------------- */
var tabs = $$(".tab");
function activate(btn) {
tabs.forEach(function (t) {
var on = t === btn;
t.classList.toggle("is-active", on);
t.setAttribute("aria-selected", on ? "true" : "false");
var p = document.getElementById(t.dataset.panel);
p.hidden = !on;
p.classList.toggle("is-active", on);
});
}
tabs.forEach(function (t, i) {
t.addEventListener("click", function () { activate(t); });
t.addEventListener("keydown", function (e) {
var d = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
if (!d) return;
e.preventDefault();
var n = tabs[(i + d + tabs.length) % tabs.length];
n.focus(); activate(n);
});
});
$$('a[href^="#tab-"]').forEach(function (a) {
a.addEventListener("click", function () {
var btn = document.getElementById(a.getAttribute("href").slice(1));
if (btn) activate(btn);
});
});
/* ---------------- downloads ---------------- */
$$(".dl").forEach(function (b) {
b.addEventListener("click", function () {
var size = b.parentElement.querySelector(".size").textContent;
b.disabled = true;
b.textContent = "Preparing…";
setTimeout(function () {
b.disabled = false;
b.textContent = "Download";
toast("Started download: " + b.dataset.file + " (" + size + ")");
}, 620);
});
});
/* ---------------- accessories carousel ---------------- */
var rail = $("#rail");
function step() {
var card = rail.querySelector(".card");
return card ? card.getBoundingClientRect().width + 16 : 240;
}
$("#accNext").addEventListener("click", function () { rail.scrollBy({ left: step() * 2, behavior: "smooth" }); });
$("#accPrev").addEventListener("click", function () { rail.scrollBy({ left: -step() * 2, behavior: "smooth" }); });
rail.addEventListener("keydown", function (e) {
if (e.key === "ArrowRight") { e.preventDefault(); rail.scrollBy({ left: step(), behavior: "smooth" }); }
if (e.key === "ArrowLeft") { e.preventDefault(); rail.scrollBy({ left: -step(), behavior: "smooth" }); }
});
$$(".card").forEach(function (c) {
c.addEventListener("click", function () {
toast(c.querySelector("h3").textContent + " — " + c.querySelector(".card-price").textContent);
});
});
/* ---------------- copy snippet ---------------- */
var copyBtn = $("#copyBtn");
copyBtn.addEventListener("click", function () {
var code = $(".code pre code").textContent;
var done = function () {
copyBtn.textContent = "Copied";
copyBtn.classList.add("done");
toast("blink.ino copied to clipboard.");
setTimeout(function () { copyBtn.textContent = "Copy"; copyBtn.classList.remove("done"); }, 1800);
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(code).then(done).catch(fallback);
} else { fallback(); }
function fallback() {
var ta = document.createElement("textarea");
ta.value = code; ta.style.position = "fixed"; ta.style.opacity = "0";
document.body.appendChild(ta); ta.select();
try { document.execCommand("copy"); done(); } catch (err) { toast("Copy failed — select the code manually."); }
ta.remove();
}
});
/* ---------------- reveal on scroll ---------------- */
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
en.target.style.transition = "opacity .5s ease, transform .5s ease";
en.target.style.opacity = "1";
en.target.style.transform = "none";
io.unobserve(en.target);
}
});
}, { threshold: .16 });
$$(".step, .card, .feature-list li").forEach(function (el, i) {
el.style.opacity = "0";
el.style.transform = "translateY(14px)";
el.style.transitionDelay = (i % 6) * 45 + "ms";
io.observe(el);
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Circuito Nano R3 — CIRCUITO Store</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<header class="topbar">
<div class="wrap topbar-in">
<a class="brand" href="#main" aria-label="CIRCUITO home">
<svg class="brand-mark" viewBox="0 0 40 40" aria-hidden="true">
<circle cx="20" cy="20" r="18" fill="none" stroke="currentColor" stroke-width="3"/>
<path d="M11 20h4.5a3.5 3.5 0 1 1 0 .01M29 20h-4.5a3.5 3.5 0 1 0 0 .01" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"/>
<path d="M8 20h3M29 20h3" stroke="currentColor" stroke-width="3" stroke-linecap="round"/>
</svg>
<span class="brand-name">CIRCUITO</span>
</a>
<nav class="topnav" aria-label="Main">
<a href="#main">Boards</a>
<a href="#accessories">Accessories</a>
<a href="#tab-docs-btn">Documentation</a>
<a href="#start">Learn</a>
</nav>
<div class="topbar-actions">
<span class="pill pill-ok" role="status">Open hardware · CERN-OHL-S</span>
<button class="icon-btn" id="cartBtn" aria-label="Open cart">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 4h2.2l2.3 11h9.6l2.2-8H7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><circle cx="9.5" cy="19" r="1.6"/><circle cx="17" cy="19" r="1.6"/></svg>
<span class="cart-count" id="cartCount">0</span>
</button>
</div>
</div>
</header>
<main id="main">
<div class="wrap">
<nav class="crumbs" aria-label="Breadcrumb">
<ol>
<li><a href="#main">Store</a></li>
<li><a href="#main">Boards</a></li>
<li><a href="#main">Nano family</a></li>
<li aria-current="page">Circuito Nano R3</li>
</ol>
</nav>
<section class="hero">
<!-- GALLERY -->
<div class="gallery">
<div class="stage" id="stage" tabindex="0" aria-label="Board render, hover to magnify">
<div class="stage-badge mono">RENDER · 1:1</div>
<div class="shot is-active" data-shot="top" role="img" aria-label="Top view of the Circuito Nano R3 board">
<svg viewBox="0 0 420 260" class="board-svg">
<defs>
<linearGradient id="pcbTop" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#00a8ae"/><stop offset="1" stop-color="#00787d"/>
</linearGradient>
<linearGradient id="metal" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#e9eef0"/><stop offset="1" stop-color="#b3c0c5"/>
</linearGradient>
</defs>
<rect x="40" y="46" width="340" height="168" rx="10" fill="url(#pcbTop)"/>
<rect x="40" y="46" width="340" height="168" rx="10" fill="none" stroke="#005a5e" stroke-width="2"/>
<g fill="none" stroke="#7fe3e6" stroke-opacity=".45" stroke-width="1.5">
<path d="M70 84h90l16 16h60"/><path d="M70 104h60l14-14h120"/>
<path d="M92 180h150l18-18h64"/><path d="M70 160h48l20 20h130"/>
</g>
<rect x="150" y="98" width="120" height="64" rx="6" fill="#1a2b34"/>
<rect x="150" y="98" width="120" height="64" rx="6" fill="none" stroke="#0d171d" stroke-width="2"/>
<circle cx="162" cy="110" r="4" fill="#3d5561"/>
<text x="210" y="126" text-anchor="middle" class="chip-t">CRQ32</text>
<text x="210" y="146" text-anchor="middle" class="chip-s">NANO-R3</text>
<g fill="#12323a">
<rect x="52" y="58" width="316" height="12" rx="3"/>
<rect x="52" y="190" width="316" height="12" rx="3"/>
</g>
<g fill="url(#metal)">
<rect x="36" y="104" width="26" height="52" rx="4"/>
</g>
<rect x="300" y="100" width="34" height="24" rx="4" fill="#c9d6da"/>
<rect x="300" y="136" width="34" height="24" rx="4" fill="#f5a623"/>
<g fill="#0d171d">
<circle cx="60" cy="176" r="4"/><circle cx="76" cy="176" r="4"/>
<circle cx="92" cy="176" r="4"/>
</g>
<g class="leds"><circle cx="286" cy="80" r="5" fill="#f5a623"/><circle cx="302" cy="80" r="5" fill="#2f9e6f"/></g>
<text x="80" y="208" class="silk">CIRCUITO NANO R3</text>
</svg>
</div>
<div class="shot" data-shot="bottom" role="img" aria-label="Bottom view of the board showing solder pads">
<svg viewBox="0 0 420 260" class="board-svg">
<rect x="40" y="46" width="340" height="168" rx="10" fill="#00676b"/>
<rect x="40" y="46" width="340" height="168" rx="10" fill="none" stroke="#00494c" stroke-width="2"/>
<g fill="#e6c67a">
<rect x="52" y="58" width="316" height="12" rx="3"/>
<rect x="52" y="190" width="316" height="12" rx="3"/>
</g>
<g fill="none" stroke="#9ff0f2" stroke-opacity=".35" stroke-width="1.4">
<path d="M60 96h120l24 24h150"/><path d="M60 140h90l30-24h180"/>
</g>
<rect x="150" y="104" width="120" height="52" rx="6" fill="none" stroke="#9ff0f2" stroke-opacity=".5" stroke-width="1.6" stroke-dasharray="5 4"/>
<text x="210" y="136" text-anchor="middle" class="silk">SOLDER SIDE</text>
<text x="210" y="182" text-anchor="middle" class="chip-s">SN 0xC4-19A · REV 3.2</text>
</svg>
</div>
<div class="shot" data-shot="headers" role="img" aria-label="Board with pre-soldered pin headers">
<svg viewBox="0 0 420 260" class="board-svg">
<rect x="40" y="56" width="340" height="150" rx="10" fill="url(#pcbTop)"/>
<rect x="40" y="56" width="340" height="150" rx="10" fill="none" stroke="#005a5e" stroke-width="2"/>
<rect x="150" y="104" width="120" height="56" rx="6" fill="#1a2b34"/>
<text x="210" y="138" text-anchor="middle" class="chip-t">CRQ32</text>
<g id="hdrTop">
<rect x="52" y="40" width="316" height="18" rx="3" fill="#1a2b34"/>
</g>
<g id="hdrBot">
<rect x="52" y="204" width="316" height="18" rx="3" fill="#1a2b34"/>
</g>
<g fill="#e6c67a" class="pins">
<rect x="58" y="30" width="6" height="12" rx="1"/><rect x="80" y="30" width="6" height="12" rx="1"/>
<rect x="102" y="30" width="6" height="12" rx="1"/><rect x="124" y="30" width="6" height="12" rx="1"/>
<rect x="146" y="30" width="6" height="12" rx="1"/><rect x="168" y="30" width="6" height="12" rx="1"/>
<rect x="190" y="30" width="6" height="12" rx="1"/><rect x="212" y="30" width="6" height="12" rx="1"/>
<rect x="234" y="30" width="6" height="12" rx="1"/><rect x="256" y="30" width="6" height="12" rx="1"/>
<rect x="278" y="30" width="6" height="12" rx="1"/><rect x="300" y="30" width="6" height="12" rx="1"/>
<rect x="322" y="30" width="6" height="12" rx="1"/><rect x="344" y="30" width="6" height="12" rx="1"/>
<rect x="58" y="222" width="6" height="12" rx="1"/><rect x="80" y="222" width="6" height="12" rx="1"/>
<rect x="102" y="222" width="6" height="12" rx="1"/><rect x="124" y="222" width="6" height="12" rx="1"/>
<rect x="146" y="222" width="6" height="12" rx="1"/><rect x="168" y="222" width="6" height="12" rx="1"/>
<rect x="190" y="222" width="6" height="12" rx="1"/><rect x="212" y="222" width="6" height="12" rx="1"/>
<rect x="234" y="222" width="6" height="12" rx="1"/><rect x="256" y="222" width="6" height="12" rx="1"/>
<rect x="278" y="222" width="6" height="12" rx="1"/><rect x="300" y="222" width="6" height="12" rx="1"/>
<rect x="322" y="222" width="6" height="12" rx="1"/><rect x="344" y="222" width="6" height="12" rx="1"/>
</g>
<text x="210" y="186" text-anchor="middle" class="silk">HEADERS PRE-SOLDERED</text>
</svg>
</div>
<span class="magnifier-hint mono" id="magHint">⌖ hover to magnify</span>
</div>
<div class="thumbs" role="tablist" aria-label="Board views">
<button class="thumb is-active" role="tab" aria-selected="true" data-shot="top">
<span class="thumb-art thumb-top" aria-hidden="true"></span>
<span class="mono">Top</span>
</button>
<button class="thumb" role="tab" aria-selected="false" data-shot="bottom">
<span class="thumb-art thumb-bottom" aria-hidden="true"></span>
<span class="mono">Bottom</span>
</button>
<button class="thumb" role="tab" aria-selected="false" data-shot="headers">
<span class="thumb-art thumb-headers" aria-hidden="true"></span>
<span class="mono">Headers</span>
</button>
</div>
</div>
<!-- BUY BOX -->
<div class="buy">
<p class="eyebrow mono">NANO FAMILY · SKU CRQ-N3-100</p>
<h1>Circuito Nano R3</h1>
<p class="lede">A 45 × 18 mm open-hardware board with a 32-bit core, USB-C, and 22 addressable I/O pins — small enough for a breadboard, fast enough for real signal work.</p>
<ul class="chips" aria-label="Quick specifications">
<li class="chip mono"><b>CLOCK</b> 64 MHz</li>
<li class="chip mono"><b>FLASH</b> 512 KB</li>
<li class="chip mono"><b>SRAM</b> 128 KB</li>
<li class="chip mono"><b>GPIO</b> 22</li>
<li class="chip mono"><b>VOP</b> 3.3 V</li>
</ul>
<div class="price-row">
<span class="price" id="price">$24.90</span>
<span class="price-note mono" id="priceNote">excl. VAT · unit $24.90</span>
</div>
<fieldset class="variants">
<legend>Variant</legend>
<label class="variant">
<input type="radio" name="variant" value="headers" data-price="24.90" data-unit="1" data-stock="in" checked />
<span class="variant-in">
<span class="variant-name">With headers</span>
<span class="variant-sub mono">pre-soldered · breadboard ready</span>
</span>
<span class="variant-price mono">$24.90</span>
</label>
<label class="variant">
<input type="radio" name="variant" value="bare" data-price="21.50" data-unit="1" data-stock="in" />
<span class="variant-in">
<span class="variant-name">Without headers</span>
<span class="variant-sub mono">castellated edges · reflow friendly</span>
</span>
<span class="variant-price mono">$21.50</span>
</label>
<label class="variant">
<input type="radio" name="variant" value="bulk" data-price="104.00" data-unit="5" data-stock="low" />
<span class="variant-in">
<span class="variant-name">Bulk 5-pack</span>
<span class="variant-sub mono">antistatic tray · save 16%</span>
</span>
<span class="variant-price mono">$104.00</span>
</label>
</fieldset>
<div class="qty-row">
<div class="stepper" role="group" aria-label="Quantity">
<button id="qtyMinus" aria-label="Decrease quantity">−</button>
<input id="qty" class="mono" type="text" inputmode="numeric" value="1" aria-label="Quantity" />
<button id="qtyPlus" aria-label="Increase quantity">+</button>
</div>
<p class="stock" id="stock"><span class="dot"></span><span id="stockText">In stock — ships in 24 h</span></p>
</div>
<button class="cta" id="addBtn">
<span>Add to cart</span>
<span class="cta-total mono" id="ctaTotal">$24.90</span>
</button>
<ul class="assurances">
<li><span aria-hidden="true">↺</span> 30-day returns on unopened trays</li>
<li><span aria-hidden="true">⛨</span> 24-month hardware warranty</li>
<li><span aria-hidden="true">⌁</span> Schematics & STEP files published openly</li>
</ul>
</div>
</section>
<!-- TABS -->
<section class="tabs-section" aria-label="Product details">
<div class="tabbar" role="tablist" aria-label="Product detail sections">
<button class="tab is-active" role="tab" id="tab-ov-btn" aria-selected="true" aria-controls="panel-ov" data-panel="panel-ov">Overview</button>
<button class="tab" role="tab" id="tab-spec-btn" aria-selected="false" aria-controls="panel-spec" data-panel="panel-spec">Tech specs</button>
<button class="tab" role="tab" id="tab-pin-btn" aria-selected="false" aria-controls="panel-pin" data-panel="panel-pin">Pinout</button>
<button class="tab" role="tab" id="tab-docs-btn" aria-selected="false" aria-controls="panel-docs" data-panel="panel-docs">Docs & downloads</button>
</div>
<div class="panel is-active" id="panel-ov" role="tabpanel" aria-labelledby="tab-ov-btn">
<div class="ov-grid">
<div class="prose">
<h2>Small board, full-size peripherals</h2>
<p>The Nano R3 keeps the 45 × 18 mm footprint of the family but swaps the 8-bit core for a 64 MHz 32-bit part with a hardware floating-point unit. That means PID loops, FFT windows, and sensor fusion run on-device instead of being shipped off to a host.</p>
<p>Power arrives over USB-C or the VIN pin (5–12 V), and an on-board buck regulator holds 3.3 V at up to 800 mA — enough headroom for a display, a radio, and a handful of sensors on the same rail. Every I/O pin is 5 V tolerant through series protection, so legacy shields keep working.</p>
<p>The board is published under CERN-OHL-S: schematics, Gerbers, and the bill of materials sit in the same public repository as the firmware bootloader.</p>
</div>
<ul class="feature-list">
<li><b>USB-C with native device stack</b><span>Serial, MIDI, and HID enumerate without a bridge chip.</span></li>
<li><b>Castellated edges</b><span>Reflow the whole module onto a carrier PCB as a drop-in SoM.</span></li>
<li><b>12-bit ADC ×8, 12-bit DAC ×1</b><span>200 ksps sampling with an internal 1.024 V reference.</span></li>
<li><b>Hardware crypto block</b><span>AES-128, SHA-256, and a true random number generator.</span></li>
<li><b>Drag-and-drop bootloader</b><span>Double-tap reset to mount a mass-storage drive and copy a UF2 file.</span></li>
</ul>
</div>
</div>
<div class="panel" id="panel-spec" role="tabpanel" aria-labelledby="tab-spec-btn" hidden>
<table class="spec">
<caption class="sr-only">Full technical specifications for the Circuito Nano R3</caption>
<tbody>
<tr class="grp"><th colspan="2" scope="colgroup">Processing</th></tr>
<tr><th scope="row">Microcontroller</th><td class="mono">CRQ32-M4F (Cortex-class 32-bit)</td></tr>
<tr><th scope="row">Clock speed</th><td class="mono">64 MHz (48 MHz USB domain)</td></tr>
<tr><th scope="row">Floating point</th><td class="mono">Single-precision FPU</td></tr>
<tr><th scope="row">Flash memory</th><td class="mono">512 KB (16 KB reserved for bootloader)</td></tr>
<tr><th scope="row">SRAM</th><td class="mono">128 KB</td></tr>
<tr><th scope="row">EEPROM emulation</th><td class="mono">4 KB (flash-backed)</td></tr>
<tr class="grp"><th colspan="2" scope="colgroup">Power</th></tr>
<tr><th scope="row">Operating voltage</th><td class="mono">3.3 V</td></tr>
<tr><th scope="row">Input voltage (VIN)</th><td class="mono">5 – 12 V</td></tr>
<tr><th scope="row">Regulator output</th><td class="mono">3.3 V @ 800 mA (buck)</td></tr>
<tr><th scope="row">DC current per I/O</th><td class="mono">15 mA (25 mA sink on PA08)</td></tr>
<tr><th scope="row">Deep-sleep current</th><td class="mono">14 µA typical</td></tr>
<tr class="grp"><th colspan="2" scope="colgroup">Input / output</th></tr>
<tr><th scope="row">Digital I/O pins</th><td class="mono">22 (all interrupt capable)</td></tr>
<tr><th scope="row">PWM channels</th><td class="mono">12 (16-bit)</td></tr>
<tr><th scope="row">Analog inputs</th><td class="mono">8 × 12-bit, 200 ksps</td></tr>
<tr><th scope="row">Analog output</th><td class="mono">1 × 12-bit DAC</td></tr>
<tr><th scope="row">Interfaces</th><td class="mono">2 × UART, 2 × I²C, 1 × SPI, 1 × I²S</td></tr>
<tr><th scope="row">Connector</th><td class="mono">USB-C, device + host-detect</td></tr>
<tr class="grp"><th colspan="2" scope="colgroup">Physical</th></tr>
<tr><th scope="row">Dimensions</th><td class="mono">45.0 × 18.0 mm</td></tr>
<tr><th scope="row">Weight</th><td class="mono">6 g (with headers 8 g)</td></tr>
<tr><th scope="row">Mounting</th><td class="mono">2 × Ø2.2 mm, 40.0 mm pitch</td></tr>
<tr><th scope="row">Operating temperature</th><td class="mono">−20 °C to +70 °C</td></tr>
<tr><th scope="row">Hardware licence</th><td class="mono">CERN-OHL-S v2</td></tr>
</tbody>
</table>
</div>
<div class="panel" id="panel-pin" role="tabpanel" aria-labelledby="tab-pin-btn" hidden>
<div class="pin-wrap">
<svg viewBox="0 0 720 330" class="pinout" role="img" aria-label="Pinout diagram of the Circuito Nano R3">
<rect x="150" y="105" width="420" height="120" rx="10" fill="#00979d"/>
<rect x="150" y="105" width="420" height="120" rx="10" fill="none" stroke="#005a5e" stroke-width="2"/>
<rect x="290" y="135" width="140" height="60" rx="6" fill="#1a2b34"/>
<text x="360" y="172" text-anchor="middle" class="chip-t">CRQ32</text>
<rect x="130" y="145" width="24" height="40" rx="4" fill="#c9d6da"/>
<text x="142" y="132" text-anchor="middle" class="pin-lbl mono">USB-C</text>
<g class="pinrow" data-side="top">
<g class="pin p-pwr"><rect x="170" y="95" width="46" height="20" rx="4"/><text x="193" y="86" text-anchor="middle">3V3</text></g>
<g class="pin p-gnd"><rect x="230" y="95" width="46" height="20" rx="4"/><text x="253" y="86" text-anchor="middle">GND</text></g>
<g class="pin p-ana"><rect x="290" y="95" width="46" height="20" rx="4"/><text x="313" y="86" text-anchor="middle">A0</text></g>
<g class="pin p-ana"><rect x="350" y="95" width="46" height="20" rx="4"/><text x="373" y="86" text-anchor="middle">A1</text></g>
<g class="pin p-dig"><rect x="410" y="95" width="46" height="20" rx="4"/><text x="433" y="86" text-anchor="middle">D2</text></g>
<g class="pin p-com"><rect x="470" y="95" width="46" height="20" rx="4"/><text x="493" y="86" text-anchor="middle">SDA</text></g>
<g class="pin p-com"><rect x="530" y="95" width="46" height="20" rx="4"/><text x="553" y="86" text-anchor="middle">SCL</text></g>
</g>
<g class="pinrow" data-side="bottom">
<g class="pin p-pwr"><rect x="170" y="215" width="46" height="20" rx="4"/><text x="193" y="252" text-anchor="middle">VIN</text></g>
<g class="pin p-gnd"><rect x="230" y="215" width="46" height="20" rx="4"/><text x="253" y="252" text-anchor="middle">GND</text></g>
<g class="pin p-dig"><rect x="290" y="215" width="46" height="20" rx="4"/><text x="313" y="252" text-anchor="middle">D5~</text></g>
<g class="pin p-dig"><rect x="350" y="215" width="46" height="20" rx="4"/><text x="373" y="252" text-anchor="middle">D6~</text></g>
<g class="pin p-com"><rect x="410" y="215" width="46" height="20" rx="4"/><text x="433" y="252" text-anchor="middle">TX0</text></g>
<g class="pin p-com"><rect x="470" y="215" width="46" height="20" rx="4"/><text x="493" y="252" text-anchor="middle">RX0</text></g>
<g class="pin p-ana"><rect x="530" y="215" width="46" height="20" rx="4"/><text x="553" y="252" text-anchor="middle">DAC</text></g>
</g>
<text x="360" y="300" text-anchor="middle" class="pin-note mono">Full 22-pin map in the datasheet · rev 3.2</text>
</svg>
<ul class="legend">
<li><i class="sw sw-pwr"></i>Power rails</li>
<li><i class="sw sw-gnd"></i>Ground</li>
<li><i class="sw sw-dig"></i>Digital / PWM</li>
<li><i class="sw sw-ana"></i>Analog</li>
<li><i class="sw sw-com"></i>Communication</li>
</ul>
</div>
</div>
<div class="panel" id="panel-docs" role="tabpanel" aria-labelledby="tab-docs-btn" hidden>
<ul class="docs">
<li>
<span class="doc-ico" aria-hidden="true">PDF</span>
<span class="doc-txt"><b>Nano R3 datasheet</b><span>Electrical characteristics, timing, absolute maximums — rev 3.2</span></span>
<span class="size mono">4.1 MB</span>
<button class="dl" data-file="circuito-nano-r3-datasheet.pdf">Download</button>
</li>
<li>
<span class="doc-ico" aria-hidden="true">SCH</span>
<span class="doc-txt"><b>Schematic & Gerbers</b><span>Full board files, BOM and pick-and-place, CERN-OHL-S v2</span></span>
<span class="size mono">2.7 MB</span>
<button class="dl" data-file="nano-r3-schematic-gerbers.zip">Download</button>
</li>
<li>
<span class="doc-ico" aria-hidden="true">3D</span>
<span class="doc-txt"><b>STEP model</b><span>Mechanical model for enclosure design, includes header variant</span></span>
<span class="size mono">11.3 MB</span>
<button class="dl" data-file="nano-r3.step">Download</button>
</li>
<li>
<span class="doc-ico" aria-hidden="true">LIB</span>
<span class="doc-txt"><b>Core library v3.2.1</b><span>Board support package, bootloader binary and examples</span></span>
<span class="size mono">860 KB</span>
<button class="dl" data-file="circuito-core-3.2.1.tar.gz">Download</button>
</li>
</ul>
</div>
</section>
<!-- ACCESSORIES -->
<section class="acc" id="accessories" aria-labelledby="accH">
<div class="acc-head">
<h2 id="accH">Compatible accessories</h2>
<div class="acc-nav">
<button id="accPrev" aria-label="Previous accessories">‹</button>
<button id="accNext" aria-label="Next accessories">›</button>
</div>
</div>
<div class="rail" id="rail" tabindex="0" aria-label="Accessories carousel">
<article class="card"><div class="card-art art-1" aria-hidden="true"></div><h3>Nano Screw Terminal Base</h3><p class="mono">CRQ-A-110 · 22 poles</p><span class="card-price mono">$12.40</span></article>
<article class="card"><div class="card-art art-2" aria-hidden="true"></div><h3>Grove Sensor Starter Set</h3><p class="mono">CRQ-A-204 · 8 modules</p><span class="card-price mono">$38.00</span></article>
<article class="card"><div class="card-art art-3" aria-hidden="true"></div><h3>USB-C Data Cable 1 m</h3><p class="mono">CRQ-A-031 · shielded</p><span class="card-price mono">$6.90</span></article>
<article class="card"><div class="card-art art-4" aria-hidden="true"></div><h3>Half-size Breadboard</h3><p class="mono">CRQ-A-055 · 400 tie points</p><span class="card-price mono">$5.50</span></article>
<article class="card"><div class="card-art art-5" aria-hidden="true"></div><h3>OLED 128×64 Display</h3><p class="mono">CRQ-A-312 · I²C</p><span class="card-price mono">$14.20</span></article>
<article class="card"><div class="card-art art-6" aria-hidden="true"></div><h3>Machined Enclosure Kit</h3><p class="mono">CRQ-A-401 · anodised</p><span class="card-price mono">$27.00</span></article>
</div>
</section>
<!-- GETTING STARTED -->
<section class="start" id="start" aria-labelledby="startH">
<div class="start-head">
<p class="eyebrow mono">GETTING STARTED</p>
<h2 id="startH">From box to blinking LED in three steps</h2>
</div>
<div class="steps">
<article class="step"><span class="num mono">01</span><h3>Install the core</h3><p>Add the CIRCUITO board index in your IDE preferences, then install <b>Circuito Nano Core</b> from the boards manager.</p></article>
<article class="step"><span class="num mono">02</span><h3>Connect over USB-C</h3><p>Plug the board in. The amber power LED lights immediately; the port appears as <span class="mono">CIRCUITO Nano R3</span>.</p></article>
<article class="step"><span class="num mono">03</span><h3>Upload the sketch</h3><p>Paste the snippet, hit upload, and the green user LED on pin 13 starts its one-second cycle.</p></article>
</div>
<div class="code">
<div class="code-bar">
<span class="mono">blink.ino</span>
<button class="copy" id="copyBtn">Copy</button>
</div>
<pre class="mono"><code>void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
Serial.println("nano r3 alive");
}</code></pre>
</div>
</section>
</div>
</main>
<footer class="foot">
<div class="wrap foot-in">
<span class="mono">CIRCUITO · fictional open-hardware platform</span>
<span class="mono">Illustrative UI demo — no real products are sold.</span>
</div>
</footer>
<div class="toasts" id="toasts" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Board Product Page
A single-product page for a fictional development board. The top half is a two-column split: on the left an SVG render stage that swaps between top view, solder side and a pre-soldered header variant via a thumbnail strip, with a pointer-tracked magnifier that scales the artwork around the cursor. On the right, the buy box carries the price, three variants (with headers, without headers, bulk 5-pack), a quantity stepper, a stock indicator that turns amber for the low-stock tray, and an add-to-cart button that reports the running total in a toast.
Quick-spec chips in monospace sit directly under the title — clock, flash, SRAM, GPIO count and operating voltage — so the numbers that decide a purchase are readable before any scrolling. The lower half is a four-tab region: an overview with prose and a hoverable feature list, a full technical spec table with grouped section headers, a pinout diagram with colour-coded pin classes and a legend, and a downloads list where each row shows a file-size chip and simulates preparing the file before firing a toast.
The page closes with a horizontal accessories carousel (scroll-snapped, arrow-driven, keyboard navigable) and a getting-started band of three numbered steps next to a dark code panel with a working copy button that falls back to execCommand when the async clipboard is unavailable.
How this look is built
The layout is written in the spirit of open-hardware store board pages, but the mechanics are modern: CSS grid handles both the hero split and the three-step band, position: sticky keeps the gallery in view while the long spec table scrolls, and :has(input:checked) styles the whole variant row from the radio inside it — no JavaScript class bookkeeping for selection state. The magnifier is a single transform: scale() with a transform-origin written from pointer coordinates, which stays GPU-composited instead of the old background-position sprite trick. All product imagery is inline SVG plus layered gradients, so the page ships zero image requests; an IntersectionObserver reveals cards and steps once, and a prefers-reduced-motion block disables the whole motion layer.
Illustrative UI only — always follow real safety guidance when working with tools, electronics, or repairs.