← back to Wallco Ai
wall-calc pin hardening: positive guard + unit tag + 90d TTL
33807f22dd673f8221c4918060f73aabfa8740df · 2026-05-12 16:06:01 -0700 · SteveStudio2
Files touched
Diff
commit 33807f22dd673f8221c4918060f73aabfa8740df
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Tue May 12 16:06:01 2026 -0700
wall-calc pin hardening: positive guard + unit tag + 90d TTL
---
server.js | 35 ++++++++++++++++++++++++-----------
1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/server.js b/server.js
index 4aa3534..613a9d2 100644
--- a/server.js
+++ b/server.js
@@ -4421,15 +4421,28 @@ ${htmlHeader('/designs')}
var pinLabel = document.getElementById('wc-pin-label');
var pinClear = document.getElementById('wc-pin-clear');
// Hydrate priority: pinned defaults beat the most-recent working values.
+ // Guards: w/h must be positive finite numbers; pin expires after 90 days
+ // so a stale 2024 pin doesn't haunt the 2026 catalog. Unit-tagged so a
+ // future inches/cm variant can drop mismatched pins on load.
var pinned = null, recent = null;
try { pinned = JSON.parse(localStorage.getItem('wallco-wall-calc-pin') || 'null'); } catch(e){}
try { recent = JSON.parse(localStorage.getItem('wallco-wall-calc') || 'null'); } catch(e){}
- var prev = (pinned && isFinite(pinned.w) && isFinite(pinned.h)) ? pinned : recent;
+ var PIN_TTL_MS = 90*86400*1000;
+ function pinValid(p){
+ return !!(p && isFinite(p.w) && isFinite(p.h) && p.w > 0 && p.h > 0
+ && (!p.unit || p.unit === 'ft')
+ && (!p.t || (Date.now() - p.t) < PIN_TTL_MS));
+ }
+ if (pinned && !pinValid(pinned)) {
+ try { localStorage.removeItem('wallco-wall-calc-pin'); } catch(e){}
+ pinned = null;
+ }
+ var prev = pinValid(pinned) ? pinned : recent;
if (prev && isFinite(prev.w) && prev.w > 0) wEl.value = prev.w;
if (prev && isFinite(prev.h) && prev.h > 0) hEl.value = prev.h;
if (prev && wallDetails && !wallDetails.open) wallDetails.open = true;
function renderPinUI(){
- if (pinned && isFinite(pinned.w) && isFinite(pinned.h)) {
+ if (pinValid(pinned)) {
pinLink.style.display = 'none';
pinStatus.style.display = 'inline-flex';
pinLabel.textContent = 'Pinned ' + pinned.w + '×' + pinned.h + ' ft';
@@ -4445,7 +4458,7 @@ ${htmlHeader('/designs')}
pinLink.addEventListener('click', function(){
var w = parseFloat(wEl.value), h = parseFloat(hEl.value);
if (!isFinite(w) || !isFinite(h) || w<=0 || h<=0) return;
- pinned = { w: w, h: h, pinned: true, t: Date.now() };
+ pinned = { w: w, h: h, unit: 'ft', pinned: true, t: Date.now() };
try { localStorage.setItem('wallco-wall-calc-pin', JSON.stringify(pinned)); } catch(e){}
renderPinUI();
});
@@ -8552,27 +8565,27 @@ app.get('/studio', (_req, res) => {
})}
<body>
${htmlHeader('')}
-<main style="padding:24px 28px;max-width:1500px;margin:0 auto">
- <h1 style="font-family:'Cormorant Garamond',serif;font-weight:300;font-size:30px;margin:0 0 6px">Designer Studio</h1>
- <p style="color:#666;margin:0 0 22px">Pick artists, styles, elements, or upload your own. Add up to 6 sources to the board → Compose generates a new pattern.</p>
+<main style="padding:88px 28px 24px;max-width:1500px;margin:0 auto">
+ <h1 class="studio-display-title" style="font-family:'Cormorant Garamond',serif;font-weight:400;font-size:clamp(30px,6.4vw,48px);letter-spacing:-0.01em;margin:6px 0 4px;line-height:1.05">Designer Studio</h1>
+ <p style="color:#666;margin:0 0 22px;font-size:14px">Pick artists, styles, elements, or upload your own. Add up to 6 sources to the board → Compose generates a new pattern.</p>
- <!-- Top: 3-column reference panels -->
- <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:22px">
+ <!-- Top: 3-column reference panels — auto-stacks below ~640px so chips never clip mid-word on mobile -->
+ <div class="studio-3col" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:14px;margin-bottom:22px">
<!-- Artists -->
- <div style="padding:14px;border:1px solid #ddd;border-radius:8px;background:#fafafa;max-height:320px;overflow-y:auto">
+ <div style="padding:14px;border:1px solid #ddd;border-radius:8px;background:#fafafa;max-height:320px;overflow-y:auto;min-width:0;overflow-wrap:anywhere">
<h3 style="margin:0 0 8px;font-size:14px">Famous Artists</h3>
<div id="artists-list" style="font-size:12px"></div>
</div>
<!-- Styles -->
- <div style="padding:14px;border:1px solid #ddd;border-radius:8px;background:#fafafa;max-height:320px;overflow-y:auto">
+ <div style="padding:14px;border:1px solid #ddd;border-radius:8px;background:#fafafa;max-height:320px;overflow-y:auto;min-width:0;overflow-wrap:anywhere">
<h3 style="margin:0 0 8px;font-size:14px">Styles</h3>
<div id="styles-list" style="font-size:12px"></div>
</div>
<!-- Elements -->
- <div style="padding:14px;border:1px solid #ddd;border-radius:8px;background:#fafafa;max-height:320px;overflow-y:auto">
+ <div style="padding:14px;border:1px solid #ddd;border-radius:8px;background:#fafafa;max-height:320px;overflow-y:auto;min-width:0;overflow-wrap:anywhere">
<h3 style="margin:0 0 8px;font-size:14px">Elements <span style="font-size:10px;color:#999;font-weight:400">(animals, monograms, …)</span></h3>
<div id="elements-list" style="font-size:12px"></div>
</div>
← 57b8702 gitignore: keep data/generated_pre_seamless_backup/ local-on
·
back to Wallco Ai
·
studio: P1 mobile + display-weight title (from graphic-desig 2750b1e →