DIY — 3D Print Service Landing
A polished landing page for a fictional print-on-demand farm, built around a live instant-quote engine. Pick a material, layer height, infill, quantity and rush option and every line of the price breakdown recalculates and flashes in place, alongside an estimated ship date. An isometric SVG printer animates its nozzle while the part grows layer by layer, capability stat cards hold the specs, a job gallery shows finished work with material and finish chips, and an eight-tile farm status band ticks live progress bars.
MCP
Code
:root{
--bg:#f6f8fb;
--bg-2:#eef2f8;
--white:#ffffff;
--ink:#1f2733;
--ink-2:#3a4553;
--muted:#6c7787;
--orange:#ff7a1a;
--orange-d:#e56506;
--orange-soft:#fff0e2;
--teal:#0fb5ba;
--teal-soft:#e2f8f8;
--violet:#8b7cf6;
--violet-soft:#efecff;
--line:rgba(31,39,51,.12);
--line-2:rgba(31,39,51,.22);
--ok:#12a46b;
--warn:#d98a2b;
--danger:#d4503e;
--r-sm:6px; --r-md:12px; --r-lg:18px;
--sh-1:0 1px 2px rgba(31,39,51,.06), 0 4px 14px rgba(31,39,51,.05);
--sh-2:0 2px 6px rgba(31,39,51,.07), 0 18px 44px rgba(31,39,51,.09);
--mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
margin:0;
font-family:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;
font-size:16px;line-height:1.5;color:var(--ink);
background:var(--bg);
-webkit-font-smoothing:antialiased;
}
h1,h2,h3{margin:0;line-height:1.12;letter-spacing:-.022em;font-weight:800}
p{margin:0}
img,svg{max-width:100%}
.mono{font-family:var(--mono);font-variant-ligatures:none}
.wrap{max-width:1180px;margin:0 auto;padding:0 24px}
.skip{position:absolute;left:-999px;top:8px;background:var(--ink);color:#fff;padding:10px 16px;border-radius:var(--r-sm);z-index:99}
.skip:focus{left:12px}
:focus-visible{outline:2.5px solid var(--orange);outline-offset:2px;border-radius:4px}
/* ---------- buttons ---------- */
.btn{
font:inherit;font-weight:650;cursor:pointer;border:1px solid transparent;
border-radius:var(--r-md);padding:12px 20px;
transition:transform .12s ease, box-shadow .18s ease, background .18s ease, border-color .18s ease;
}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--orange);color:#fff;box-shadow:0 2px 0 var(--orange-d),0 10px 22px rgba(255,122,26,.28)}
.btn-primary:hover{background:#ff8b36}
.btn-ghost{background:var(--white);color:var(--ink);border-color:var(--line-2);box-shadow:var(--sh-1)}
.btn-ghost:hover{border-color:var(--ink-2)}
.btn-sm{padding:9px 15px;font-size:14px}
.btn-lg{padding:15px 30px;font-size:17px}
.btn-block{display:block;width:100%}
.pill{
display:inline-flex;align-items:center;gap:8px;
font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
padding:6px 12px;border-radius:999px;border:1px solid var(--line);background:var(--white);color:var(--ink-2);
}
.dot{width:7px;height:7px;border-radius:50%;background:var(--ok);box-shadow:0 0 0 3px rgba(18,164,107,.18);animation:pulse 2.4s ease-in-out infinite}
@keyframes pulse{50%{box-shadow:0 0 0 6px rgba(18,164,107,0)}}
/* ---------- nav ---------- */
.nav{position:sticky;top:0;z-index:40;background:rgba(246,248,251,.86);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
.nav-in{display:flex;align-items:center;gap:24px;height:66px}
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--ink)}
.brand-mark{width:28px;height:28px;color:var(--orange)}
.brand-txt{font-weight:800;letter-spacing:-.02em;display:flex;flex-direction:column;line-height:1.05}
.brand-txt em{font-style:normal;font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;color:var(--muted);font-weight:600}
.nav-links{display:flex;gap:22px;margin-left:auto}
.nav-links a{color:var(--ink-2);text-decoration:none;font-size:14.5px;font-weight:550;padding:6px 0;border-bottom:2px solid transparent}
.nav-links a:hover{color:var(--ink);border-bottom-color:var(--orange)}
.nav-cta{display:flex;align-items:center;gap:12px;margin-left:auto}
.nav-links + .nav-cta{margin-left:0}
/* ---------- hero ---------- */
.hero{
position:relative;padding:76px 0 84px;overflow:hidden;
background:
radial-gradient(680px 320px at 88% 6%, rgba(15,181,186,.10), transparent 70%),
radial-gradient(560px 300px at 4% 100%, rgba(255,122,26,.10), transparent 70%),
linear-gradient(180deg,var(--bg) 0%, var(--bg-2) 100%);
}
.hero::before{
content:"";position:absolute;inset:0;pointer-events:none;
background-image:
linear-gradient(to right, rgba(31,39,51,.045) 1px, transparent 1px),
linear-gradient(to bottom, rgba(31,39,51,.045) 1px, transparent 1px);
background-size:32px 32px;
-webkit-mask-image:radial-gradient(circle at 50% 30%, #000, transparent 78%);
mask-image:radial-gradient(circle at 50% 30%, #000, transparent 78%);
}
.hero-in{position:relative;display:grid;grid-template-columns:1.05fr .95fr;gap:56px;align-items:center}
.eyebrow{display:inline-flex;align-items:center;gap:9px;font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2);background:var(--white);border:1px solid var(--line);padding:7px 14px;border-radius:999px;box-shadow:var(--sh-1)}
.hero h1{font-size:clamp(34px,5.1vw,60px);margin:20px 0 18px}
.hl{
background:linear-gradient(100deg,var(--orange),#ff9d54 55%,var(--teal));
-webkit-background-clip:text;background-clip:text;color:transparent;
}
.lede{font-size:17.5px;color:var(--ink-2);max-width:52ch}
.hero-actions{display:flex;gap:12px;margin:28px 0 34px;flex-wrap:wrap}
.hero-trust{list-style:none;display:flex;gap:36px;margin:0;padding:26px 0 0;border-top:1px dashed var(--line-2);flex-wrap:wrap}
.hero-trust strong{display:block;font-size:21px;font-weight:700;color:var(--ink)}
.hero-trust span{font-size:12.5px;color:var(--muted)}
.art-frame{
position:relative;background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);
box-shadow:var(--sh-2);padding:16px;
background-image:linear-gradient(180deg,#fff,#f9fbfd);
}
.art-frame::after{
content:"";position:absolute;inset:12px;border-radius:14px;pointer-events:none;
background:repeating-linear-gradient(180deg, rgba(31,39,51,.028) 0 1px, transparent 1px 7px);
}
.printer{display:block;width:100%;height:auto}
.gantry{animation:gantry 4.6s ease-in-out infinite}
@keyframes gantry{0%,100%{transform:translateY(0)}50%{transform:translateY(-26px)}}
.nozzle{animation:noz 1.9s ease-in-out infinite}
@keyframes noz{0%,100%{transform:translateX(-34px)}50%{transform:translateX(34px)}}
.drip{animation:drip 1.1s linear infinite}
@keyframes drip{0%{opacity:0;transform:translateY(0)}25%{opacity:1}100%{opacity:0;transform:translateY(24px)}}
.part .layer{opacity:0;transform-origin:210px 262px;animation:grow 7s ease-in-out infinite}
.part .layer:nth-child(1){animation-delay:0s}
.part .layer:nth-child(2){animation-delay:.55s}
.part .layer:nth-child(3){animation-delay:1.1s}
.part .layer:nth-child(4){animation-delay:1.65s}
.part .layer:nth-child(5){animation-delay:2.2s}
.part .layer:nth-child(6){animation-delay:2.75s}
@keyframes grow{0%{opacity:0;transform:scale(.8)}8%{opacity:1;transform:scale(1)}82%{opacity:1;transform:scale(1)}92%,100%{opacity:0;transform:scale(1)}}
.glow{animation:glowp 3s ease-in-out infinite}
@keyframes glowp{50%{opacity:.45}}
.art-hud{
position:absolute;right:22px;bottom:22px;display:grid;gap:5px;
background:rgba(31,39,51,.92);color:#e6ecf4;padding:10px 13px;border-radius:var(--r-sm);font-size:11px;letter-spacing:.04em;
}
.hud-row b{color:var(--teal);font-weight:700;margin-right:8px}
/* ---------- section heads ---------- */
section{padding:78px 0}
.kicker{display:block;font-size:11.5px;letter-spacing:.14em;color:var(--orange);font-weight:700;margin-bottom:12px}
.sec-head{max-width:60ch;margin-bottom:34px}
.sec-head h2{font-size:clamp(26px,3.4vw,38px)}
.sec-head p{margin-top:12px;color:var(--ink-2);font-size:16.5px}
.sec-head-row{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;max-width:none}
.card{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-1)}
/* ---------- quote ---------- */
.quote{background:var(--white);border-block:1px solid var(--line)}
.quote-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:26px;align-items:start}
.qform{padding:24px;display:grid;gap:18px;background:linear-gradient(180deg,#fdfeff,#f7fafc)}
.drop{
display:flex;align-items:center;gap:16px;padding:20px;cursor:pointer;
border:2px dashed var(--line-2);border-radius:var(--r-md);background:var(--bg);color:var(--ink);
transition:border-color .18s, background .18s, transform .12s;
}
.drop:hover,.drop.hot{border-color:var(--orange);background:var(--orange-soft)}
.drop:active{transform:scale(.995)}
.drop-ico{width:42px;height:42px;color:var(--orange);flex:none}
.drop strong{display:block;font-size:15px}
.drop span{font-size:12px;color:var(--muted)}
.field{display:grid;gap:7px}
.lbl{font-size:12.5px;font-weight:650;color:var(--ink-2);letter-spacing:.01em}
.lbl-flex{display:flex;justify-content:space-between;align-items:baseline}
.lbl-flex b{color:var(--orange);font-size:14px}
.hint{font-size:11px;color:var(--muted)}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
input[type=text],select{
font:inherit;width:100%;padding:11px 13px;border:1px solid var(--line-2);border-radius:var(--r-sm);
background:var(--white);color:var(--ink);transition:border-color .16s, box-shadow .16s;
}
input[type=text]{font-family:var(--mono);font-size:13.5px}
select{appearance:none;
background-image:linear-gradient(45deg,transparent 50%,var(--ink-2) 50%),linear-gradient(135deg,var(--ink-2) 50%,transparent 50%);
background-position:calc(100% - 17px) 51%, calc(100% - 12px) 51%;
background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:34px;cursor:pointer;
}
input[type=text]:focus,select:focus{border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,122,26,.16);outline:none}
input[type=range]{
-webkit-appearance:none;appearance:none;width:100%;height:24px;background:transparent;cursor:pointer;
}
input[type=range]::-webkit-slider-runnable-track{height:6px;border-radius:999px;background:linear-gradient(90deg,var(--orange) var(--pct,20%),var(--bg-2) var(--pct,20%))}
input[type=range]::-moz-range-track{height:6px;border-radius:999px;background:var(--bg-2)}
input[type=range]::-moz-range-progress{height:6px;border-radius:999px;background:var(--orange)}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:19px;height:19px;margin-top:-6.5px;border-radius:50%;background:var(--white);border:2.5px solid var(--orange);box-shadow:0 2px 6px rgba(31,39,51,.22)}
input[type=range]::-moz-range-thumb{width:19px;height:19px;border-radius:50%;background:var(--white);border:2.5px solid var(--orange)}
.stepper{display:flex;align-items:center;border:1px solid var(--line-2);border-radius:var(--r-sm);overflow:hidden;background:var(--white)}
.step{font:inherit;font-size:19px;line-height:1;width:44px;height:44px;border:0;background:var(--bg);color:var(--ink);cursor:pointer;transition:background .15s}
.step:hover{background:var(--orange-soft);color:var(--orange-d)}
.stepper input{border:0;text-align:center;border-radius:0;flex:1}
.stepper input:focus{box-shadow:none}
.toggle{
display:flex;align-items:center;gap:12px;width:100%;height:44px;padding:0 14px;cursor:pointer;
border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--white);font:inherit;font-size:13px;color:var(--ink-2);
transition:border-color .18s,background .18s;
}
.toggle .knob{position:relative;flex:none;width:38px;height:21px;border-radius:999px;background:var(--bg-2);transition:background .2s}
.toggle .knob::after{content:"";position:absolute;top:3px;left:3px;width:15px;height:15px;border-radius:50%;background:var(--white);box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .2s ease}
.toggle[aria-checked=true]{border-color:var(--orange);background:var(--orange-soft);color:var(--orange-d)}
.toggle[aria-checked=true] .knob{background:var(--orange)}
.toggle[aria-checked=true] .knob::after{transform:translateX(17px)}
.toggle-txt em{font-style:normal;font-family:var(--mono);font-weight:700}
.qout{padding:24px;position:sticky;top:86px}
.qout-head{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;padding-bottom:18px;border-bottom:1px solid var(--line)}
.qout-head h3{font-size:17px;font-family:var(--mono);font-weight:700;word-break:break-all}
.chip{display:inline-block;font-size:11px;padding:5px 10px;border-radius:999px;font-weight:600;letter-spacing:.03em;white-space:nowrap}
.chip-mat{background:var(--teal-soft);color:#0a7d81;border:1px solid rgba(15,181,186,.3)}
.break{margin:0;padding:16px 0 4px;display:grid;gap:2px}
.brow{display:flex;justify-content:space-between;align-items:baseline;gap:14px;padding:10px 10px;border-radius:var(--r-sm);transition:background .3s}
.brow dt{color:var(--ink-2);font-size:14px}
.brow dd{margin:0;font-weight:600;font-size:14.5px}
.brow .sub{display:block;font-size:11px;color:var(--muted);margin-top:2px}
.brow.flash{background:var(--orange-soft)}
.brow-total{margin-top:8px;padding-top:16px;border-top:2px solid var(--ink);border-radius:0}
.brow-total dt{font-weight:700;color:var(--ink);font-size:15px}
.brow-total dd{font-size:26px;font-weight:700;letter-spacing:-.02em}
.ship{display:flex;align-items:center;gap:12px;margin:16px 0;padding:14px;border-radius:var(--r-md);background:var(--violet-soft);color:#4b3ec4}
.ship svg{width:26px;height:26px;flex:none}
.ship-l{display:block;font-size:11.5px;font-family:var(--mono);letter-spacing:.05em;text-transform:uppercase;opacity:.8}
.ship strong{font-size:15.5px}
.fine{margin-top:12px;font-size:11.5px;color:var(--muted);text-align:center}
/* ---------- stats ---------- */
.caps{background:var(--bg-2)}
.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.stat{background:var(--white);border:1px solid var(--line);border-radius:var(--r-md);padding:22px;box-shadow:var(--sh-1);position:relative;overflow:hidden;transition:transform .18s,box-shadow .18s}
.stat::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(180deg,var(--orange),var(--teal))}
.stat:hover{transform:translateY(-3px);box-shadow:var(--sh-2)}
.stat-l{font-size:10.5px;letter-spacing:.13em;color:var(--muted);display:block;margin-bottom:10px}
.stat strong{display:block;font-size:24px;font-weight:700;letter-spacing:-.02em}
.stat-s{font-size:12.5px;color:var(--muted);display:block;margin-top:6px}
/* ---------- gallery ---------- */
.g-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.g-card{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-1);transition:transform .2s,box-shadow .2s,border-color .2s}
.g-card:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:var(--line-2)}
.g-art{height:172px;display:grid;place-items:center;position:relative;
background-image:repeating-linear-gradient(180deg,rgba(255,255,255,.10) 0 1px,transparent 1px 6px);
}
.g-art svg{width:120px;height:120px;filter:drop-shadow(0 10px 18px rgba(31,39,51,.28))}
.g-body{padding:16px 18px 18px}
.g-body h3{font-size:15.5px;margin-bottom:6px}
.g-body p{font-size:13px;color:var(--muted)}
.g-chips{display:flex;flex-wrap:wrap;gap:7px;margin-top:12px}
.chip-s{font-family:var(--mono);font-size:10.5px;padding:4px 9px;border-radius:999px;background:var(--bg-2);color:var(--ink-2);border:1px solid var(--line)}
.chip-s.a{background:var(--orange-soft);color:var(--orange-d);border-color:rgba(255,122,26,.3)}
.chip-s.b{background:var(--violet-soft);color:#5a4bd4;border-color:rgba(139,124,246,.3)}
/* ---------- farm ---------- */
.farm{background:var(--ink);color:#e8edf4;
background-image:radial-gradient(600px 300px at 12% 0%, rgba(15,181,186,.14), transparent 65%),radial-gradient(600px 300px at 90% 100%, rgba(255,122,26,.12), transparent 65%);
}
.farm .sec-head h2{color:#fff}
.farm .pill{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.16);color:#cfd8e4}
.p-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.p-tile{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);border-radius:var(--r-md);padding:16px;transition:background .2s,border-color .2s}
.p-tile:hover{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.24)}
.p-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}
.p-id{font-family:var(--mono);font-size:13px;font-weight:700;letter-spacing:.04em}
.p-state{font-family:var(--mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;padding:3px 8px;border-radius:999px;display:inline-flex;align-items:center;gap:6px}
.p-state i{width:6px;height:6px;border-radius:50%;background:currentColor}
.s-printing{background:rgba(18,164,107,.16);color:#4bdca0}
.s-idle{background:rgba(207,216,228,.12);color:#b6c2d1}
.s-maint{background:rgba(217,138,43,.18);color:#f2bb6c}
.p-job{font-size:12px;color:#9dabbd;margin-bottom:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.p-bar{height:6px;border-radius:999px;background:rgba(255,255,255,.12);overflow:hidden}
.p-fill{height:100%;border-radius:999px;background:linear-gradient(90deg,var(--orange),#ffb066);transition:width .8s ease}
.p-tile.maint .p-fill{background:linear-gradient(90deg,var(--warn),#f2c98a)}
.p-tile.idle .p-fill{background:rgba(255,255,255,.22)}
.p-meta{display:flex;justify-content:space-between;font-family:var(--mono);font-size:10.5px;color:#8fa0b4;margin-top:8px}
/* ---------- faq ---------- */
.acc{display:grid;gap:10px}
.acc-item{background:var(--white);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;box-shadow:var(--sh-1)}
.acc-q{width:100%;display:flex;justify-content:space-between;align-items:center;gap:16px;text-align:left;
font:inherit;font-weight:650;font-size:15.5px;color:var(--ink);background:none;border:0;padding:18px 20px;cursor:pointer}
.acc-q:hover{background:var(--bg)}
.chev{flex:none;width:11px;height:11px;border-right:2.2px solid var(--muted);border-bottom:2.2px solid var(--muted);transform:rotate(45deg);transition:transform .25s ease;margin-top:-4px}
.acc-q[aria-expanded=true]{color:var(--orange-d)}
.acc-q[aria-expanded=true] .chev{transform:rotate(-135deg);margin-top:3px;border-color:var(--orange)}
.acc-a{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s ease}
.acc-a > p{overflow:hidden;padding:0 20px;color:var(--ink-2);font-size:14.5px;min-height:0}
.acc-item.open .acc-a{grid-template-rows:1fr}
.acc-item.open .acc-a > p{padding-bottom:20px}
/* ---------- cta / foot ---------- */
.cta{background:var(--bg-2);border-top:1px solid var(--line)}
.cta-in{display:flex;align-items:center;justify-content:space-between;gap:26px;flex-wrap:wrap}
.cta h2{font-size:clamp(24px,3vw,34px)}
.cta p{color:var(--ink-2);margin-top:10px}
.foot{padding:24px 0;background:var(--ink);color:#96a3b4}
.foot-in{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;font-size:11px;letter-spacing:.07em}
/* ---------- toast ---------- */
.toast{
position:fixed;left:50%;bottom:26px;transform:translate(-50%,20px);
background:var(--ink);color:#fff;padding:13px 20px;border-radius:var(--r-md);
font-size:14px;box-shadow:var(--sh-2);opacity:0;pointer-events:none;transition:opacity .22s,transform .22s;z-index:80;max-width:90vw;text-align:center;
}
.toast.show{opacity:1;transform:translate(-50%,0)}
/* ---------- responsive ---------- */
@media (max-width:1000px){
.hero-in{grid-template-columns:1fr;gap:40px}
.quote-grid{grid-template-columns:1fr}
.qout{position:static}
.stat-grid{grid-template-columns:repeat(2,1fr)}
.g-grid{grid-template-columns:repeat(2,1fr)}
.p-grid{grid-template-columns:repeat(2,1fr)}
.nav-links{display:none}
}
@media (max-width:520px){
.wrap{padding:0 16px}
section{padding:52px 0}
.hero{padding:48px 0 56px}
.hero-trust{gap:22px}
.row2{grid-template-columns:1fr}
.stat-grid,.g-grid,.p-grid{grid-template-columns:1fr}
.nav-in{height:60px;gap:12px}
.nav-cta .pill{display:none}
.sec-head-row{flex-direction:column;align-items:flex-start}
.qform,.qout{padding:18px}
.brow-total dd{font-size:22px}
.cta-in{flex-direction:column;align-items:flex-start}
.btn-lg{width:100%}
.art-hud{right:12px;bottom:12px;font-size:10px}
}
@media (prefers-reduced-motion:reduce){
html{scroll-behavior:auto}
*,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
.part .layer{opacity:1}
.drip{opacity:0}
}/* Layerworks Print Farm — instant quote, gallery, live farm, accordion. Vanilla JS. */
(function () {
"use strict";
var reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
var $ = function (s, r) { return (r || document).querySelector(s); };
var $$ = function (s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); };
/* ---------------- toast ---------------- */
var toastEl = $("#toast"), toastT;
function toast(msg) {
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastT);
toastT = setTimeout(function () { toastEl.classList.remove("show"); }, 2600);
}
/* ---------------- smooth scroll buttons ---------------- */
$$("[data-scroll]").forEach(function (b) {
b.addEventListener("click", function () {
var t = $(b.getAttribute("data-scroll"));
if (t) t.scrollIntoView({ behavior: reduced ? "auto" : "smooth", block: "start" });
});
});
/* ---------------- instant quote ---------------- */
var fname = $("#fname"), material = $("#material"), layer = $("#layer"),
infill = $("#infill"), infillOut = $("#infillOut"), qty = $("#qty"),
rush = $("#rush"), drop = $("#drop"), dropSub = $("#dropSub");
var SAMPLES = [
{ n: "bracket_v4_rev-c.stl", g: 86, h: 5.4 },
{ n: "planetary_gear_set.3mf", g: 142, h: 9.1 },
{ n: "drone_arm_left.step", g: 61, h: 4.2 },
{ n: "enclosure_lid_v2.stl", g: 208, h: 12.6 },
{ n: "cable_grommet_x8.3mf", g: 34, h: 2.3 }
];
var sampleIx = 0;
var base = SAMPLES[0];
var MACHINE_RATE = 3.0; // $/h
var SETUP = 8.0; // flat
var RUSH_PCT = 0.35;
var last = {};
function money(n) {
return "$" + n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function clampQty(v) {
v = parseInt(String(v).replace(/[^\d]/g, ""), 10);
if (isNaN(v) || v < 1) v = 1;
if (v > 2500) v = 2500;
return v;
}
function flash(key) {
var row = $('.brow[data-row="' + key + '"]');
if (!row || reduced) return;
row.classList.remove("flash");
void row.offsetWidth;
row.classList.add("flash");
setTimeout(function () { row.classList.remove("flash"); }, 620);
}
function shipDate(days) {
var d = new Date(2026, 6, 30); // fixed demo "today": Thu Jul 30, 2026
var added = 0;
while (added < days) {
d.setDate(d.getDate() + 1);
if (d.getDay() !== 0) added++; // farm runs Mon–Sat
}
return d.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" });
}
function recalc(changedRows) {
var mOpt = material.options[material.selectedIndex];
var rate = parseFloat(mOpt.dataset.rate); // $/g
var lOpt = layer.options[layer.selectedIndex];
var mult = parseFloat(lOpt.dataset.mult); // time multiplier
var inf = parseInt(infill.value, 10);
var n = clampQty(qty.value);
var isRush = rush.getAttribute("aria-checked") === "true";
var infFactor = 0.62 + (inf / 100) * 0.9;
var grams = base.g * infFactor;
var hours = base.h * mult * (0.75 + (inf / 100) * 0.55);
var cMat = grams * rate * n;
var cTime = hours * MACHINE_RATE * n;
var cSetup = SETUP + (n > 10 ? (n - 10) * 0.22 : 0);
var sub = cMat + cTime + cSetup;
var cRush = isRush ? sub * RUSH_PCT : 0;
var total = sub + cRush;
$("#outName").textContent = fname.value || "untitled.stl";
$("#outMat").textContent = mOpt.dataset.name;
$("#gramsOut").textContent = (grams * n).toFixed(0) + " g total";
$("#hoursOut").textContent = (hours * n).toFixed(1) + " h · " + lOpt.value + " mm";
$("#cMat").textContent = money(cMat);
$("#cTime").textContent = money(cTime);
$("#cSetup").textContent = money(cSetup);
$("#cRush").textContent = isRush ? money(cRush) : "—";
$("#cTotal").textContent = money(total);
$("#unitOut").textContent = money(total / n) + " / unit";
var days = isRush ? 2 : 3 + (n > 25 ? 2 : 0) + (mult > 1.4 ? 1 : 0);
$("#shipDate").textContent = shipDate(days);
infillOut.textContent = inf + "%";
infill.style.setProperty("--pct", ((inf - 10) / 80 * 100).toFixed(1) + "%");
(changedRows || ["mat", "time", "setup", "rush"]).forEach(flash);
last = { total: total, n: n, mat: mOpt.dataset.name };
}
["change", "input"].forEach(function (ev) {
material.addEventListener(ev, function () { recalc(["mat", "time"]); });
layer.addEventListener(ev, function () { recalc(["time"]); });
infill.addEventListener(ev, function () { recalc(["mat", "time"]); });
fname.addEventListener(ev, function () { recalc([]); });
});
$$(".step").forEach(function (b) {
b.addEventListener("click", function () {
qty.value = clampQty(clampQty(qty.value) + parseInt(b.dataset.qty, 10));
recalc(["mat", "time", "setup"]);
});
});
qty.addEventListener("input", function () { recalc(["mat", "time", "setup"]); });
qty.addEventListener("blur", function () { qty.value = clampQty(qty.value); recalc([]); });
rush.addEventListener("click", function () {
var on = rush.getAttribute("aria-checked") === "true";
rush.setAttribute("aria-checked", String(!on));
recalc(["rush"]);
toast(!on ? "Rush enabled — 48-hour guarantee." : "Rush removed — standard queue.");
});
function pickSample() {
sampleIx = (sampleIx + 1) % SAMPLES.length;
base = SAMPLES[sampleIx];
fname.value = base.n;
dropSub.textContent = "loaded · " + base.g + " g raw · mesh OK";
drop.classList.add("hot");
setTimeout(function () { drop.classList.remove("hot"); }, 500);
recalc(["mat", "time"]);
toast("Analyzed " + base.n + " — watertight mesh, no repairs needed.");
}
drop.addEventListener("click", pickSample);
drop.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); pickSample(); }
});
["dragover", "dragenter"].forEach(function (ev) {
drop.addEventListener(ev, function (e) { e.preventDefault(); drop.classList.add("hot"); });
});
["dragleave", "drop"].forEach(function (ev) {
drop.addEventListener(ev, function (e) { e.preventDefault(); drop.classList.remove("hot"); });
});
drop.addEventListener("drop", pickSample);
$("#order").addEventListener("click", function () {
$("#quoteId").textContent = String(4100 + Math.floor(Math.random() * 899));
toast("Slot reserved — " + last.n + " × " + last.mat + " for " + money(last.total) + ".");
});
recalc([]);
/* ---------------- gallery ---------------- */
var JOBS = [
{ t: "Harvester sensor mount", c: "Bramble Agritech", d: "42 units, jig-drilled inserts", bg: "linear-gradient(150deg,#22303f,#141c26)", col: "#ff9a4d", chips: ["PETG", "Bead blasted", "0.20 mm"], k: "gear" },
{ t: "Anemometer housing", c: "North Reach Labs", d: "Weather-sealed, 6 mating parts", bg: "linear-gradient(150deg,#123840,#0b2026)", col: "#3fd6da", chips: ["Nylon PA12", "Vapor smoothed", "0.12 mm"], k: "cube" },
{ t: "Miniature terrain set", c: "Hollowpine Games", d: "310 pieces, 0.06 mm detail", bg: "linear-gradient(150deg,#2a2440,#171327)", col: "#a99bff", chips: ["Resin 8K", "Primed grey", "0.06 mm"], k: "cone" },
{ t: "Prosthetic grip sleeve", c: "Kestrel Mobility", d: "Shore 95A, 3 sizes", bg: "linear-gradient(150deg,#3a2418,#1e120b)", col: "#ff7a1a", chips: ["TPU 95A", "As printed", "0.24 mm"], k: "torus" },
{ t: "Espresso tamper jig", c: "Ironhorse Coffee", d: "Shop fixture, daily use", bg: "linear-gradient(150deg,#1e2a35,#121820)", col: "#ffc27a", chips: ["PLA Matte", "Sanded 400", "0.20 mm"], k: "cube" },
{ t: "Cable routing spine", c: "Meridian Studio", d: "Wall run, 118 links", bg: "linear-gradient(150deg,#13303a,#0a1a20)", col: "#0fb5ba", chips: ["PETG", "As printed", "0.28 mm"], k: "torus" }
];
var SHAPES = {
cube: '<path d="M60 14 106 40v52L60 118 14 92V40Z" fill="COL" opacity=".92"/><path d="M14 40 60 66l46-26M60 66v52" fill="none" stroke="rgba(0,0,0,.35)" stroke-width="2"/>',
gear: '<circle cx="60" cy="66" r="34" fill="COL"/><circle cx="60" cy="66" r="13" fill="rgba(0,0,0,.42)"/><g fill="COL"><rect x="53" y="18" width="14" height="16" rx="3"/><rect x="53" y="98" width="14" height="16" rx="3"/><rect x="12" y="59" width="16" height="14" rx="3"/><rect x="92" y="59" width="16" height="14" rx="3"/></g>',
cone: '<path d="M60 16 96 106H24Z" fill="COL"/><ellipse cx="60" cy="106" rx="36" ry="11" fill="rgba(0,0,0,.32)"/>',
torus: '<circle cx="60" cy="66" r="36" fill="none" stroke="COL" stroke-width="17"/><ellipse cx="60" cy="66" rx="36" ry="12" fill="none" stroke="rgba(0,0,0,.25)" stroke-width="3"/>'
};
$("#gGrid").innerHTML = JOBS.map(function (j) {
var art = SHAPES[j.k].replace(/COL/g, j.col);
return '<article class="g-card">' +
'<div class="g-art" style="background:' + j.bg + '">' +
'<svg viewBox="0 0 120 132" aria-label="' + j.t + ' render">' + art + '</svg></div>' +
'<div class="g-body"><h3>' + j.t + '</h3><p>' + j.c + " · " + j.d + '</p>' +
'<div class="g-chips">' +
'<span class="chip-s a">' + j.chips[0] + '</span>' +
'<span class="chip-s b">' + j.chips[1] + '</span>' +
'<span class="chip-s">' + j.chips[2] + '</span>' +
'</div></div></article>';
}).join("");
/* ---------------- farm status ---------------- */
var PRINTERS = [
{ id: "LW-01", job: "bracket_v4_rev-c ×42", st: "printing", p: 68 },
{ id: "LW-02", job: "anemometer_shell", st: "printing", p: 31 },
{ id: "LW-03", job: "queue empty", st: "idle", p: 0 },
{ id: "LW-04", job: "terrain_set_batch_9", st: "printing", p: 84 },
{ id: "LW-05", job: "nozzle swap 0.6 mm", st: "maint", p: 45 },
{ id: "LW-06", job: "grip_sleeve_M ×18", st: "printing", p: 12 },
{ id: "LW-07", job: "cable_spine_links", st: "printing", p: 57 },
{ id: "LW-08", job: "tamper_jig_rev2", st: "printing", p: 93 }
];
var LABEL = { printing: "printing", idle: "idle", maint: "maintenance" };
var CLS = { printing: "s-printing", idle: "s-idle", maint: "s-maint" };
var pGrid = $("#pGrid");
function renderFarm() {
pGrid.innerHTML = PRINTERS.map(function (p) {
var eta = p.st === "printing"
? "ETA " + Math.max(1, Math.round((100 - p.p) * 0.14)) + " h"
: (p.st === "maint" ? "tech on site" : "ready");
return '<article class="p-tile ' + p.st + '">' +
'<div class="p-top"><span class="p-id">' + p.id + '</span>' +
'<span class="p-state ' + CLS[p.st] + '"><i></i>' + LABEL[p.st] + '</span></div>' +
'<p class="p-job">' + p.job + '</p>' +
'<div class="p-bar" role="progressbar" aria-valuenow="' + p.p + '" aria-valuemin="0" aria-valuemax="100" aria-label="' + p.id + ' progress">' +
'<span class="p-fill" style="width:' + p.p + '%"></span></div>' +
'<div class="p-meta"><span>' + p.p + "%</span><span>" + eta + '</span></div></article>';
}).join("");
}
renderFarm();
if (!reduced) {
setInterval(function () {
PRINTERS.forEach(function (p) {
if (p.st !== "printing") return;
p.p += Math.random() * 3;
if (p.p >= 100) { p.p = 0; p.job = "job " + (1200 + Math.floor(Math.random() * 799)) + " starting"; }
});
PRINTERS.forEach(function (p) { p.p = Math.round(p.p); });
renderFarm();
}, 3000);
var artLayer = $("#artLayer"), lv = 147;
setInterval(function () {
lv = lv >= 312 ? 1 : lv + 1;
artLayer.textContent = lv;
}, 900);
}
/* ---------------- accordion ---------------- */
$$("#acc .acc-q").forEach(function (q) {
if (q.getAttribute("aria-expanded") === "true") q.parentElement.classList.add("open");
q.addEventListener("click", function () {
var open = q.getAttribute("aria-expanded") === "true";
$$("#acc .acc-q").forEach(function (o) {
o.setAttribute("aria-expanded", "false");
o.parentElement.classList.remove("open");
});
if (!open) { q.setAttribute("aria-expanded", "true"); q.parentElement.classList.add("open"); }
});
});
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Layerworks Print Farm — Instant 3D Printing Quotes</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="#quote">Skip to instant quote</a>
<header class="nav">
<div class="wrap nav-in">
<a class="brand" href="#top">
<svg class="brand-mark" viewBox="0 0 32 32" aria-hidden="true">
<path d="M16 3 29 10.5v11L16 29 3 21.5v-11L16 3Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M3 10.5 16 18l13-7.5M16 18v11" fill="none" stroke="currentColor" stroke-width="1.6" opacity=".55"/>
</svg>
<span class="brand-txt">Layerworks<em>Print Farm</em></span>
</a>
<nav class="nav-links" aria-label="Primary">
<a href="#quote">Instant quote</a>
<a href="#caps">Capabilities</a>
<a href="#gallery">Recent jobs</a>
<a href="#farm">Farm status</a>
<a href="#faq">FAQ</a>
</nav>
<div class="nav-cta">
<span class="pill pill-live"><i class="dot"></i> 6 / 8 printers running</span>
<button class="btn btn-primary btn-sm" data-scroll="#quote" type="button">Get a quote</button>
</div>
</div>
</header>
<main id="top">
<!-- HERO -->
<section class="hero">
<div class="wrap hero-in">
<div class="hero-copy">
<span class="eyebrow"><i class="dot"></i> FDM & SLA · Ships from Bend, Oregon</span>
<h1>Upload a part today.<br /><span class="hl">Hold it Thursday.</span></h1>
<p class="lede">Layerworks is a 24-hour print farm for makers, prototypers and small hardware teams. Eight calibrated machines, five materials, and a quote engine that prices your part before you finish reading this sentence.</p>
<div class="hero-actions">
<button class="btn btn-primary" data-scroll="#quote" type="button">Price my part</button>
<button class="btn btn-ghost" data-scroll="#gallery" type="button">See recent jobs</button>
</div>
<ul class="hero-trust">
<li><strong class="mono">±0.15 mm</strong><span>typical tolerance</span></li>
<li><strong class="mono">18 h</strong><span>median turnaround</span></li>
<li><strong class="mono">4,120</strong><span>parts shipped</span></li>
</ul>
</div>
<div class="hero-art" aria-hidden="true">
<div class="art-frame">
<svg viewBox="0 0 420 380" class="printer" role="img">
<defs>
<linearGradient id="bedG" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#2b3644"/><stop offset="1" stop-color="#161d27"/>
</linearGradient>
<linearGradient id="partG" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#ff9a4d"/><stop offset="1" stop-color="#ff6a05"/>
</linearGradient>
<linearGradient id="frameG" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#cfd8e4"/><stop offset="1" stop-color="#9aa8bb"/>
</linearGradient>
</defs>
<!-- rear frame -->
<path d="M60 90 210 20 360 90 210 160Z" fill="none" stroke="rgba(31,39,51,.18)" stroke-width="1.5" stroke-dasharray="4 5"/>
<g stroke="url(#frameG)" stroke-width="7" stroke-linecap="round" fill="none">
<path d="M60 90v170"/><path d="M360 90v170"/>
</g>
<path d="M60 90 210 20 360 90" fill="none" stroke="url(#frameG)" stroke-width="7" stroke-linejoin="round" stroke-linecap="round"/>
<!-- gantry + nozzle -->
<g class="gantry">
<path d="M60 150 210 80 360 150" fill="none" stroke="#b9c4d3" stroke-width="5" stroke-linejoin="round"/>
<g class="nozzle">
<rect x="196" y="96" width="28" height="24" rx="4" fill="#39424f"/>
<path d="M203 120h14l-7 13Z" fill="var(--orange)"/>
<circle class="drip" cx="210" cy="140" r="3.4" fill="var(--orange)"/>
</g>
</g>
<!-- bed -->
<path d="M70 262 210 194 350 262 210 330Z" fill="url(#bedG)"/>
<path d="M70 262 210 194 350 262 210 330Z" fill="none" stroke="rgba(255,255,255,.14)" stroke-width="2"/>
<g stroke="rgba(15,181,186,.35)" stroke-width="1">
<path d="M105 262 245 194M140 262 280 194M175 262 315 194M245 330 105 262M280 330 140 262M315 330 175 262"/>
</g>
<!-- growing part -->
<g class="part">
<g class="layer"><path d="M160 254 210 230 260 254 210 278Z" fill="url(#partG)"/></g>
<g class="layer"><path d="M162 240 210 217 258 240 210 263Z" fill="url(#partG)"/></g>
<g class="layer"><path d="M166 227 210 206 254 227 210 248Z" fill="url(#partG)"/></g>
<g class="layer"><path d="M170 215 210 196 250 215 210 234Z" fill="url(#partG)"/></g>
<g class="layer"><path d="M176 204 210 188 244 204 210 220Z" fill="url(#partG)"/></g>
<g class="layer"><path d="M182 194 210 181 238 194 210 207Z" fill="url(#partG)"/></g>
</g>
<ellipse class="glow" cx="210" cy="262" rx="72" ry="30" fill="rgba(255,122,26,.18)"/>
</svg>
<div class="art-hud mono">
<span class="hud-row"><b>NOZZLE</b> 215 °C</span>
<span class="hud-row"><b>BED</b> 60 °C</span>
<span class="hud-row"><b>LAYER</b> <span id="artLayer">147</span>/312</span>
</div>
</div>
</div>
</div>
</section>
<!-- QUOTE -->
<section id="quote" class="quote">
<div class="wrap quote-in">
<div class="sec-head">
<span class="kicker mono">01 — INSTANT QUOTE</span>
<h2>Price recalculates as you tweak.</h2>
<p>No sales call, no waiting on a PDF. Change any input and the breakdown updates instantly with a firm price and ship date.</p>
</div>
<div class="quote-grid">
<form class="card qform" id="qform" novalidate>
<div class="drop" id="drop" tabindex="0" role="button" aria-label="Choose a model file">
<svg viewBox="0 0 48 48" aria-hidden="true" class="drop-ico">
<path d="M24 8 40 17v14L24 40 8 31V17L24 8Z" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linejoin="round"/>
<path d="M8 17l16 9 16-9M24 26v14" fill="none" stroke="currentColor" stroke-width="1.6" opacity=".5"/>
</svg>
<div>
<strong>Drop an STL / 3MF / STEP</strong>
<span class="mono" id="dropSub">or click to pick a sample part</span>
</div>
</div>
<label class="field">
<span class="lbl">File name</span>
<input id="fname" type="text" value="bracket_v4_rev-c.stl" spellcheck="false" />
</label>
<div class="row2">
<label class="field">
<span class="lbl">Material</span>
<select id="material">
<option value="pla" data-rate="0.042" data-name="PLA Matte">PLA — matte, everyday</option>
<option value="petg" data-rate="0.058" data-name="PETG">PETG — tough, outdoor</option>
<option value="tpu" data-rate="0.091" data-name="TPU 95A">TPU 95A — flexible</option>
<option value="resin" data-rate="0.130" data-name="Resin 8K">Resin 8K — fine detail</option>
<option value="nylon" data-rate="0.155" data-name="Nylon PA12">Nylon PA12 — engineering</option>
</select>
</label>
<label class="field">
<span class="lbl">Layer height</span>
<select id="layer">
<option value="0.30" data-mult="0.72">0.30 mm — draft</option>
<option value="0.20" data-mult="1" selected>0.20 mm — standard</option>
<option value="0.12" data-mult="1.45">0.12 mm — fine</option>
<option value="0.06" data-mult="2.3">0.06 mm — ultra</option>
</select>
</label>
</div>
<div class="field">
<span class="lbl lbl-flex">Infill <b class="mono" id="infillOut">25%</b></span>
<input id="infill" type="range" min="10" max="90" step="5" value="25" aria-describedby="infillHint" />
<span class="hint mono" id="infillHint">10% cosmetic · 25% typical · 60%+ load bearing</span>
</div>
<div class="row2">
<div class="field">
<span class="lbl">Quantity</span>
<div class="stepper">
<button type="button" class="step" data-qty="-1" aria-label="Decrease quantity">−</button>
<input id="qty" class="mono" type="text" inputmode="numeric" value="4" aria-label="Quantity" />
<button type="button" class="step" data-qty="1" aria-label="Increase quantity">+</button>
</div>
</div>
<div class="field">
<span class="lbl">Rush service</span>
<button type="button" class="toggle" id="rush" role="switch" aria-checked="false">
<span class="knob"></span>
<span class="toggle-txt">48-hour rush <em>+35%</em></span>
</button>
</div>
</div>
</form>
<aside class="card qout" aria-live="polite">
<header class="qout-head">
<div>
<span class="kicker mono">ESTIMATE</span>
<h3 id="outName">bracket_v4_rev-c.stl</h3>
</div>
<span class="chip chip-mat mono" id="outMat">PLA Matte</span>
</header>
<dl class="break">
<div class="brow" data-row="mat"><dt>Material <span class="mono sub" id="gramsOut">86 g</span></dt><dd class="mono" id="cMat">$3.61</dd></div>
<div class="brow" data-row="time"><dt>Machine time <span class="mono sub" id="hoursOut">5.4 h</span></dt><dd class="mono" id="cTime">$16.20</dd></div>
<div class="brow" data-row="setup"><dt>Setup & post-processing</dt><dd class="mono" id="cSetup">$8.00</dd></div>
<div class="brow" data-row="rush"><dt>Rush surcharge</dt><dd class="mono" id="cRush">—</dd></div>
<div class="brow brow-total"><dt>Total <span class="mono sub" id="unitOut">$6.95 / unit</span></dt><dd class="mono" id="cTotal">$27.81</dd></div>
</dl>
<div class="ship">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 8h11v9H3zM14 11h4l3 3v3h-7z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/><circle cx="7" cy="18" r="1.8" fill="currentColor"/><circle cx="17.5" cy="18" r="1.8" fill="currentColor"/></svg>
<div><span class="ship-l">Estimated ship date</span><strong id="shipDate">Thursday, Aug 6</strong></div>
</div>
<button class="btn btn-primary btn-block" id="order" type="button">Reserve this slot</button>
<p class="fine">Price locked for 24 h. Quote LW-<span class="mono" id="quoteId">4192</span> · fictional demo data.</p>
</aside>
</div>
</div>
</section>
<!-- CAPABILITIES -->
<section id="caps" class="caps">
<div class="wrap">
<div class="sec-head"><span class="kicker mono">02 — CAPABILITIES</span><h2>What fits on the bed.</h2></div>
<div class="stat-grid">
<div class="stat"><span class="stat-l mono">BUILD VOLUME</span><strong class="mono">350 × 350 × 400</strong><span class="stat-s">millimetres, FDM bay</span></div>
<div class="stat"><span class="stat-l mono">TOLERANCE</span><strong class="mono">±0.15 mm</strong><span class="stat-s">±0.05 mm on resin</span></div>
<div class="stat"><span class="stat-l mono">MATERIALS</span><strong class="mono">5 × 22</strong><span class="stat-s">families × colorways</span></div>
<div class="stat"><span class="stat-l mono">MAX QUANTITY</span><strong class="mono">2,500</strong><span class="stat-s">units per production run</span></div>
</div>
</div>
</section>
<!-- GALLERY -->
<section id="gallery" class="gallery">
<div class="wrap">
<div class="sec-head"><span class="kicker mono">03 — RECENT JOBS</span><h2>Shipped last week.</h2></div>
<div class="g-grid" id="gGrid"></div>
</div>
</section>
<!-- FARM -->
<section id="farm" class="farm">
<div class="wrap">
<div class="sec-head sec-head-row">
<div><span class="kicker mono">04 — FARM STATUS</span><h2>Live from the floor.</h2></div>
<span class="pill pill-live"><i class="dot"></i> polling every 3 s</span>
</div>
<div class="p-grid" id="pGrid"></div>
</div>
</section>
<!-- FAQ -->
<section id="faq" class="faq">
<div class="wrap faq-in">
<div class="sec-head"><span class="kicker mono">05 — TURNAROUND & SHIPPING</span><h2>The practical answers.</h2></div>
<div class="acc" id="acc">
<div class="acc-item">
<button class="acc-q" type="button" aria-expanded="true"><span>How fast is standard turnaround?</span><i class="chev"></i></button>
<div class="acc-a"><p>Standard queue is 3–5 business days from file approval. Median across the last 500 jobs was 18 hours of machine time plus one business day of finishing and QC. Rush moves you to the front of the queue with a 48-hour guarantee.</p></div>
</div>
<div class="acc-item">
<button class="acc-q" type="button" aria-expanded="false"><span>Do you check my file before printing?</span><i class="chev"></i></button>
<div class="acc-a"><p>Every upload runs through automated mesh repair (non-manifold edges, flipped normals, self-intersections). If a part needs geometry changes we email a marked-up render within four hours and pause the clock until you approve.</p></div>
</div>
<div class="acc-item">
<button class="acc-q" type="button" aria-expanded="false"><span>Which materials ship same-week?</span><i class="chev"></i></button>
<div class="acc-a"><p>PLA, PETG and Resin 8K are stocked in all 22 colorways and ship same week. TPU 95A and Nylon PA12 run in batched cycles on Tuesdays and Fridays — order by Monday noon to make that week's batch.</p></div>
</div>
<div class="acc-item">
<button class="acc-q" type="button" aria-expanded="false"><span>How do you pack and ship?</span><i class="chev"></i></button>
<div class="acc-a"><p>Parts are bagged individually, nested in recycled kraft fill and boxed. Domestic ground is flat $7.40, two-day is $18.60, and orders over $250 ship free. International goes DDU via a consolidator out of Portland, typically 6–9 days.</p></div>
</div>
<div class="acc-item">
<button class="acc-q" type="button" aria-expanded="false"><span>What if a part arrives wrong?</span><i class="chev"></i></button>
<div class="acc-a"><p>Send a photo within 14 days. If the part is outside our stated tolerance or has a visible layer defect we reprint at no cost, on rush, and pay return shipping. Roughly 1.8% of jobs get reprinted — we publish that number every quarter.</p></div>
</div>
</div>
</div>
</section>
<section class="cta">
<div class="wrap cta-in">
<div>
<h2>Your part is 40 seconds from a price.</h2>
<p>Drop a file, pick a material, reserve a slot. That's the whole process.</p>
</div>
<button class="btn btn-primary btn-lg" data-scroll="#quote" type="button">Start a quote</button>
</div>
</section>
</main>
<footer class="foot">
<div class="wrap foot-in">
<span class="mono">LAYERWORKS PRINT FARM · BEND, OR · FICTIONAL DEMO</span>
<span class="mono">MON–SAT 07:00–22:00 PT</span>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>3D Print Service Landing
Layerworks Print Farm is a fictional 24-hour print-on-demand shop, and the page is built the way a real one would want to sell: no contact form, no “request a quote” dead end. The hero splits copy and CTA against an isometric SVG printer whose gantry rises, whose nozzle sweeps left to right, and whose part stacks itself one orange layer at a time on a loop, with a small mono HUD reading nozzle temperature, bed temperature and current layer.
The centerpiece is the instant-quote card. A drop zone accepts a drag-and-drop gesture or a click to cycle through sample parts, each with its own raw mass and base machine time. Material, layer height, infill percentage, quantity and a rush switch all feed one pricing function: material cost scales with grams and per-gram rate, machine time scales with layer-height multiplier and infill, setup adds a flat fee plus a per-unit charge above ten units, and rush adds 35% on top of the subtotal. Every affected row flashes as it updates, and the ship date walks forward over a Monday-to-Saturday production calendar.
Below the quote, mono stat cards state build volume, tolerance, material count and maximum run size. A gallery of six shipped jobs renders each part as a CSS-lit SVG solid over a layer-line texture with material and finish chips. The farm status band draws eight printer tiles on a dark industrial panel, cycling their progress bars every three seconds and rolling a finished machine straight into its next job. A turnaround and shipping accordion closes the page with the practical answers.
How this look is built
The layer-line and blueprint textures are pure CSS: repeating-linear-gradient for the print striations and two crossed linear-gradient layers with background-size: 32px 32px for the hero grid, faded out with a radial mask-image so it never fights the copy — much cheaper than a tiled PNG and it stays crisp at any DPI. The range slider’s filled track is a gradient whose stop is driven by a --pct custom property that JS writes on input, so no extra element is needed. The accordion animates height with the grid-template-rows: 0fr → 1fr trick, which gets real transitions on auto-height content that max-height hacks only approximate. The printer animation is SVG groups with staggered animation-delay, so it composites on transform and opacity only; both it and the three-second farm polling are disabled under prefers-reduced-motion, which is the thing to watch — a looping animation plus a repainting grid is the one combination on this page that can cost battery on low-end devices.
Illustrative UI only — always follow real safety guidance when working with tools, electronics, or repairs.