<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>487 Noe St — sfpermits.ai</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="obsidian-tokens.css">
<style>
/* Page-specific layout */
.page-body { padding-top: 56px; }
.property-header {
padding: var(--space-6) 0 var(--space-4);
}
.property-address {
font-family: var(--mono); font-size: var(--text-xl); font-weight: 300;
margin-bottom: var(--space-2);
}
.property-address .accent { color: var(--accent); }
.property-meta {
display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
}
/* Intel panel — the summary cards */
.intel-grid {
display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--space-3);
margin-bottom: var(--space-4);
}
.intel-card {
padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm);
background: var(--glass); border: 1px solid var(--glass-border);
transition: border-color 0.3s, background 0.3s, transform 0.2s;
cursor: pointer;
}
.intel-card:hover {
border-color: var(--glass-hover);
background: var(--obsidian-light);
transform: translateY(-1px);
}
.intel-card--primary {
background: var(--accent-glow);
border-color: var(--accent-ring);
}
.intel-card--primary:hover {
background: rgba(94, 234, 212, 0.12);
}
.intel-card--danger:hover {
border-color: rgba(248, 113, 113, 0.25);
}
.intel-card__top {
display: flex; align-items: baseline; justify-content: space-between;
margin-bottom: 2px;
}
.intel-card__number {
font-family: var(--mono); font-size: 22px;
font-weight: 300; line-height: 1;
}
.intel-card__arrow {
font-family: var(--mono); font-size: 12px; color: var(--text-tertiary);
opacity: 0; transition: opacity 0.2s, color 0.2s;
}
.intel-card:hover .intel-card__arrow {
opacity: 1; color: var(--accent);
}
.intel-card__label {
font-family: var(--sans); font-size: var(--text-sm); color: var(--text-secondary);
}
.intel-card__detail {
font-family: var(--mono); font-size: var(--text-xs); color: var(--text-tertiary);
margin-top: 2px;
}
/* Actions needed */
.actions-section { margin-bottom: var(--space-6); }
.action-item {
display: flex; align-items: center; gap: var(--space-3);
padding: 10px var(--space-4);
border-radius: var(--radius-sm);
transition: background 0.15s;
cursor: pointer;
}
.action-item:hover { background: var(--glass); }
.action-item__icon {
width: 6px; height: 6px; border-radius: var(--radius-full); flex-shrink: 0;
}
.action-item__text {
font-family: var(--sans); font-size: var(--text-base); color: var(--text-secondary);
flex: 1;
}
.action-item__text strong {
color: var(--text-primary); font-weight: 400;
}
.action-item__cta {
font-family: var(--mono); font-size: var(--text-xs); color: var(--text-tertiary);
opacity: 0; transition: opacity 0.2s;
}
.action-item:hover .action-item__cta { opacity: 1; color: var(--accent); }
/* Permit list */
.permit-list { margin-bottom: var(--space-6); }
.permit-item {
display: grid; grid-template-columns: 1fr auto; gap: var(--space-4);
align-items: start;
padding: 12px var(--space-3);
margin: 0 calc(-1 * var(--space-3));
border-bottom: 1px solid var(--glass-border);
border-radius: var(--radius-sm);
transition: background 0.15s;
cursor: pointer;
}
.permit-item:hover { background: var(--glass); }
.permit-item:first-child { padding-top: 12px; }
.permit-item__number {
font-family: var(--mono); font-size: var(--text-sm); font-weight: 300;
color: var(--text-primary); margin-bottom: 2px;
}
.permit-item__desc {
font-family: var(--sans); font-size: var(--text-sm); font-weight: 300;
color: var(--text-secondary); line-height: 1.5;
}
.permit-item__status {
text-align: right;
}
.permit-item__status-text {
font-family: var(--mono); font-size: var(--text-xs);
display: flex; align-items: center; gap: var(--space-2);
justify-content: flex-end;
}
.permit-item__date {
font-family: var(--mono); font-size: var(--text-xs); color: var(--text-tertiary);
margin-top: 2px; text-align: right;
}
/* Routing progress section */
.routing-section { margin-bottom: var(--space-8); }
.station-row {
display: flex; align-items: center; gap: var(--space-4);
padding: 10px 0;
border-bottom: 1px solid var(--glass-border);
}
.station-row:last-child { border-bottom: none; }
.station-name {
font-family: var(--mono); font-size: var(--text-sm); font-weight: 400;
color: var(--text-secondary); width: 100px; flex-shrink: 0;
}
.station-bar { flex: 1; }
.station-result {
font-family: var(--mono); font-size: var(--text-xs);
width: 80px; text-align: right; flex-shrink: 0;
}
/* Entity section */
.entity-row {
display: flex; align-items: center; justify-content: space-between;
padding: 10px var(--space-3);
margin: 0 calc(-1 * var(--space-3));
border-bottom: 1px solid var(--glass-border);
border-radius: var(--radius-sm);
transition: background 0.15s;
cursor: pointer;
}
.entity-row:hover { background: var(--glass); }
.entity-row:last-child { border-bottom: none; }
.entity-name {
font-family: var(--sans); font-size: var(--text-base); color: var(--text-primary);
}
.entity-role {
font-family: var(--mono); font-size: var(--text-xs); color: var(--text-tertiary);
margin-top: 2px;
}
.entity-permits {
font-family: var(--mono); font-size: var(--text-sm); color: var(--text-secondary);
}
/* CTA row */
.cta-row {
display: flex; gap: var(--space-6); justify-content: center;
padding: var(--space-4) 0 var(--space-6);
}
/* Show more */
.show-more {
text-align: center; padding: var(--space-4) 0;
}
</style>
</head>
<body>
<!-- NAV -->
<nav class="nav-float">
<a href="#" class="nav-float__wordmark">sfpermits.ai</a>
<div class="nav-float__links">
<div class="search-bar" style="width: 240px;">
<input type="text" class="search-input" placeholder="Search" value="487 Noe St" style="padding: 8px 14px; font-size: 12px;">
<svg class="search-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
</div>
<a href="#" class="nav-float__link">Methodology</a>
<div class="nav-float__avatar">TB</div>
</div>
</nav>
<div class="page-body">
<div class="obs-container">
<!-- PROPERTY HEADER -->
<header class="property-header reveal">
<h1 class="property-address"><span class="accent">487 Noe St</span></h1>
<div class="property-meta">
<span class="chip">Residential</span>
<span class="chip">Noe Valley</span>
<span class="chip">Block 3582 / Lot 035</span>
</div>
</header>
<!-- INTEL PANEL -->
<div class="intel-grid reveal reveal-delay-1">
<div class="intel-card intel-card--primary">
<div class="intel-card__top">
<span class="intel-card__number status-text--green">3</span>
<span class="intel-card__arrow">→</span>
</div>
<div class="intel-card__label">Active permits</div>
<div class="intel-card__detail">2 in review · 1 issued</div>
</div>
<div class="intel-card intel-card--danger">
<div class="intel-card__top">
<span class="intel-card__number status-text--red">2</span>
<span class="intel-card__arrow">→</span>
</div>
<div class="intel-card__label">Open complaints</div>
<div class="intel-card__detail">1 building · 1 noise</div>
</div>
<div class="intel-card">
<div class="intel-card__top">
<span class="intel-card__number">4</span>
<span class="intel-card__arrow">→</span>
</div>
<div class="intel-card__label">Businesses</div>
<div class="intel-card__detail">2 active · 2 closed</div>
</div>
</div>
<!-- ACTIONS NEEDED -->
<section class="actions-section reveal reveal-delay-2">
<div class="section-label">Needs attention</div>
<div class="action-item">
<span class="action-item__icon" style="background: var(--signal-amber);"></span>
<span class="action-item__text"><strong>PPC stalled 12 days</strong> on permit 202401015832 — kitchen remodel</span>
<span class="action-item__cta">→</span>
</div>
<div class="action-item">
<span class="action-item__icon" style="background: var(--signal-red);"></span>
<span class="action-item__text"><strong>Open complaint</strong> — building code violation reported Nov 2025</span>
<span class="action-item__cta">→</span>
</div>
<div class="action-item">
<span class="action-item__icon" style="background: var(--signal-blue);"></span>
<span class="action-item__text"><strong>BLDG approved today</strong> on permit 202401028741 — bathroom renovation</span>
<span class="action-item__cta">→</span>
</div>
</section>
<!-- CTA ROW -->
<div class="cta-row reveal reveal-delay-2">
<a href="#" class="ghost-cta">Ask AI about this property →</a>
<a href="#" class="ghost-cta">Full property report →</a>
</div>
<hr class="divider">
<!-- ACTIVE PERMITS -->
<section class="permit-list reveal reveal-delay-2" style="padding-top: var(--space-8);">
<div class="section-label">Active permits</div>
<div class="permit-item">
<div>
<div class="permit-item__number">202401015832</div>
<div class="permit-item__desc">Kitchen remodel — remove bearing wall, relocate plumbing, new electrical panel</div>
</div>
<div class="permit-item__status">
<div class="permit-item__status-text status-text--amber">
<span class="status-dot status-dot--amber"></span>PPC pending
</div>
<div class="permit-item__date">Filed Jan 15, 2024</div>
</div>
</div>
<div class="permit-item">
<div>
<div class="permit-item__number">202401028741</div>
<div class="permit-item__desc">Bathroom renovation — new fixtures, waterproofing, tile work</div>
</div>
<div class="permit-item__status">
<div class="permit-item__status-text status-text--green">
<span class="status-dot status-dot--green"></span>BLDG approved
</div>
<div class="permit-item__date">Filed Feb 3, 2024</div>
</div>
</div>
<div class="permit-item">
<div>
<div class="permit-item__number">202312089923</div>
<div class="permit-item__desc">Electrical panel upgrade — 100A to 200A service</div>
</div>
<div class="permit-item__status">
<div class="permit-item__status-text status-text--green">
<span class="status-dot status-dot--green"></span>Issued
</div>
<div class="permit-item__date">Filed Dec 8, 2023</div>
</div>
</div>
<div class="show-more">
<a href="#" class="ghost-cta">Show all 7 permits →</a>
</div>
</section>
<hr class="divider">
<!-- ROUTING PROGRESS -->
<section class="routing-section reveal reveal-delay-3" style="padding-top: var(--space-8);">
<div class="section-label">Routing progress · 202401015832</div>
<div class="glass-card" style="padding: var(--space-5) var(--space-6);">
<div style="margin-bottom: var(--space-4);">
<div class="progress-label">
<span>Plan review</span>
<span>5 / 8 stations</span>
</div>
<div class="progress-track">
<div class="progress-fill" style="width: 62%"></div>
</div>
</div>
<div class="station-row">
<span class="station-name">BLDG</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 100%"></div></div>
</div>
<span class="station-result status-text--green">Approved</span>
</div>
<div class="station-row">
<span class="station-name">SFFD</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 100%"></div></div>
</div>
<span class="station-result status-text--green">Approved</span>
</div>
<div class="station-row">
<span class="station-name">ELEC</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 100%"></div></div>
</div>
<span class="station-result status-text--green">Approved</span>
</div>
<div class="station-row">
<span class="station-name">PLMB</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 100%"></div></div>
</div>
<span class="station-result status-text--green">Approved</span>
</div>
<div class="station-row">
<span class="station-name">MECH-E</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 100%"></div></div>
</div>
<span class="station-result status-text--green">Approved</span>
</div>
<div class="station-row">
<span class="station-name">PPC</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 30%"></div></div>
</div>
<span class="station-result status-text--amber">12 days</span>
</div>
<div class="station-row">
<span class="station-name">CP-ZOC</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 0%"></div></div>
</div>
<span class="station-result" style="color: var(--text-tertiary);">Pending</span>
</div>
<div class="station-row">
<span class="station-name">DPH</span>
<div class="station-bar">
<div class="progress-track"><div class="progress-fill" style="width: 0%"></div></div>
</div>
<span class="station-result" style="color: var(--text-tertiary);">Pending</span>
</div>
</div>
</section>
<hr class="divider" style="margin-top: var(--space-8);">
<!-- ENTITY NETWORK -->
<section class="reveal" style="padding: var(--space-8) 0;">
<div class="section-label">Project team</div>
<div class="entity-row">
<div>
<div class="entity-name">Smith & Associates</div>
<div class="entity-role">Architect</div>
</div>
<div class="entity-permits">47 permits</div>
</div>
<div class="entity-row">
<div>
<div class="entity-name">Bay Area Builders Inc</div>
<div class="entity-role">General contractor</div>
</div>
<div class="entity-permits">132 permits</div>
</div>
<div class="entity-row">
<div>
<div class="entity-name">Pacific Electrical Co</div>
<div class="entity-role">Electrical contractor</div>
</div>
<div class="entity-permits">89 permits</div>
</div>
<div class="show-more">
<a href="#" class="ghost-cta">View entity network →</a>
</div>
</section>
<!-- FRESHNESS -->
<div class="freshness reveal">
<span class="freshness-dot"></span>
Data as of Feb 27, 2026 · Updated nightly
</div>
</div>
</div>
<!-- SCROLL REVEAL OBSERVER -->
<script>
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.15, rootMargin: '0px 0px -40px 0px' });
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
// Animate progress fills after reveal
setTimeout(() => {
document.querySelectorAll('.progress-fill').forEach(el => {
el.style.width = el.style.width; // trigger reflow
});
}, 500);
</script>
</body>
</html>