← back to Ventura Corridor
public/trademarks.html
101 lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Trademarks · The Corridor</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<style>
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;1,400;1,500&family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@200;300;400&display=swap');
:root{--paper:#faf6ee;--ink:#1a1815;--ink-mute:#6e6356;--metal:#8a6d3b;--metal-glow:#b89968;--accent:#6a3a1a;--rule:#d8cdb8}
*{box-sizing:border-box}
html,body{margin:0;background:var(--paper);color:var(--ink);font-family:'Inter',sans-serif;font-weight:300;line-height:1.55}
header{text-align:center;padding:60px 24px 32px;border-bottom:1px solid var(--rule)}
header .kicker{font-size:9px;letter-spacing:.4em;text-transform:uppercase;color:var(--metal);font-weight:500}
header h1{font-family:'Cormorant Garamond',serif;font-style:italic;font-weight:500;font-size:64px;margin:8px 0 0;color:var(--ink);letter-spacing:-0.02em}
header h1 em{color:var(--metal);font-style:normal}
header .deck{font-family:'Cormorant Garamond',serif;font-style:italic;font-size:18px;color:var(--ink-mute);margin-top:12px;max-width:560px;margin-left:auto;margin-right:auto}
.searchbar{padding:32px 24px 8px;text-align:center}
.searchbar input{font-family:'Cormorant Garamond',serif;font-size:28px;font-style:italic;background:transparent;border:none;border-bottom:1px solid var(--rule);color:var(--ink);padding:14px 12px;min-width:520px;max-width:92vw;outline:none;text-align:center}
.searchbar input:focus{border-bottom-color:var(--metal)}
.searchbar .examples{font-size:11px;letter-spacing:.18em;color:var(--ink-mute);margin-top:14px}
.searchbar .examples b{color:var(--metal);font-family:'JetBrains Mono',monospace;font-weight:400;background:rgba(184,153,104,0.08);padding:2px 8px;margin:0 3px;cursor:pointer}
.count{text-align:center;font-size:10px;letter-spacing:.28em;text-transform:uppercase;color:var(--ink-mute);margin:6px 0 0}
main{max-width:860px;margin:0 auto;padding:20px 24px 90px}
.tm{display:grid;grid-template-columns:1fr auto;gap:6px 18px;padding:18px 0;border-bottom:1px solid var(--rule)}
.tm:hover{background:rgba(184,153,104,0.04);padding-left:8px;padding-right:8px}
.tm .mark{font-family:'Cormorant Garamond',serif;font-style:italic;font-size:24px;color:var(--ink);line-height:1.15}
.tm .owner{font-size:12px;color:var(--ink-mute);letter-spacing:.03em;margin-top:2px}
.tm .owner b{color:var(--metal);font-style:normal;font-weight:500}
.tm .gs{grid-column:1/2;font-size:12px;color:var(--ink-mute);margin-top:6px;max-width:620px}
.tm .side{grid-column:2/3;grid-row:1/3;text-align:right;min-width:150px}
.tm .status{display:inline-block;font-size:9px;letter-spacing:.2em;text-transform:uppercase;color:var(--metal-glow);border:1px solid var(--rule);padding:3px 8px;font-weight:500}
.tm .cls{display:block;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--metal);margin-top:8px;letter-spacing:.05em}
.tm .filed{display:block;font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ink-mute);margin-top:4px;letter-spacing:.05em}
.empty{text-align:center;padding:80px 24px;color:var(--ink-mute);font-style:italic;font-family:'Cormorant Garamond',serif;font-size:22px}
.toolbar{position:fixed;top:14px;right:14px;display:flex;gap:6px;z-index:100}
.toolbar a{font-size:9px;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-mute);background:var(--paper);padding:5px 10px;border:1px solid var(--rule);text-decoration:none}
.toolbar a:hover{color:var(--metal);border-color:var(--metal)}
</style>
</head>
<body>
<div class="toolbar">
<a href="/find.html">Business finder</a>
<a href="/">← Corridor</a>
</div>
<header>
<div class="kicker">The Corridor · trademark registry</div>
<h1>Who owns the <em>mark</em>?</h1>
<div class="deck">Search the USPTO trademark full-text record by word mark or by owner. Surface the IP footprint behind any business or brand on the boulevard.</div>
</header>
<div class="searchbar">
<input id="q" type="search" autofocus oninput="onSearch()" placeholder="a word mark, or a company / owner name">
<div class="examples">try
<b onclick="qy('APPLE')">APPLE</b>
<b onclick="qy('cider')">cider</b>
<b onclick="qy('ventures llc')">ventures llc</b>
<b onclick="qy('coffee')">coffee</b>
</div>
<div class="count" id="count"></div>
</div>
<main id="results"></main>
<script>
function escHtml(s){return String(s ?? '').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));}
function titleCase(s){return String(s ?? '').toLowerCase().replace(/\b\w/g,c=>c.toUpperCase());}
function qy(s){document.getElementById('q').value=s;onSearch();}
let _t;
function onSearch(){clearTimeout(_t);_t=setTimeout(go,200);}
async function go(){
const q=document.getElementById('q').value.trim();
const countEl=document.getElementById('count');
if(q.length<2){document.getElementById('results').innerHTML='';countEl.textContent='';return;}
let data;
try{ data=await fetch('/api/trademarks?q='+encodeURIComponent(q)).then(r=>r.json()); }
catch(e){ document.getElementById('results').innerHTML=`<div class="empty">Lookup failed.</div>`; return; }
const rows=data.rows||[];
countEl.textContent = rows.length ? `${data.count}${rows.length>=100?'+':''} match${rows.length===1?'':'es'}` : '';
document.getElementById('results').innerHTML = rows.length===0
? `<div class="empty">No trademarks match “${escHtml(q)}”.</div>`
: rows.map(r=>{
const owner = titleCase(r.owner_name||'');
const loc = [r.owner_city&&titleCase(r.owner_city), r.owner_state].filter(Boolean).join(', ');
const filed = r.filing_date ? String(r.filing_date).replace(/^(\d{4})(\d{2})(\d{2})$/,'$1-$2-$3') : '';
const reg = r.registration_number ? ` · Reg ${escHtml(r.registration_number)}` : '';
return `<div class="tm">
<div>
<div class="mark">${escHtml(r.mark||'—')}</div>
<div class="owner"><b>${escHtml(owner||'—')}</b>${loc?' · '+escHtml(loc):''}${reg}</div>
</div>
<div class="side">
<span class="status">${escHtml(r.status_label||'—')}</span>
${r.primary_class?`<span class="cls">Int'l class ${escHtml(r.primary_class)}</span>`:''}
${filed?`<span class="filed">filed ${escHtml(filed)}</span>`:''}
</div>
${r.goods_services?`<div class="gs">${escHtml(String(r.goods_services).slice(0,220))}${r.goods_services.length>220?'…':''}</div>`:''}
</div>`;
}).join('');
}
</script>
</body>
</html>