<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Consultation — 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-body { padding-top: 56px; }
/* Query header */
.query-section { padding: var(--space-6) 0 var(--space-4); }
.query-text {
font-family: var(--sans); font-size: var(--text-lg); font-weight: 300;
color: var(--text-primary); line-height: 1.5;
}
.query-property {
display: inline-flex; align-items: center; gap: var(--space-2);
margin-top: var(--space-3);
}
.query-property__check {
width: 16px; height: 16px; border-radius: var(--radius-full);
background: rgba(52, 211, 153, 0.15); border: 1px solid rgba(52, 211, 153, 0.3);
display: flex; align-items: center; justify-content: center;
}
.query-property__check svg { color: var(--signal-green); }
.query-property__addr {
font-family: var(--mono); font-size: var(--text-sm); color: var(--accent);
}
/* AI label */
.ai-label {
display: flex; align-items: center; gap: var(--space-2);
font-family: var(--mono); font-size: var(--text-xs); color: var(--accent);
margin-bottom: var(--space-4);
}
.ai-label__sparkle { font-size: 14px; }
.ai-label__date { color: var(--text-tertiary); }
/* Response card */
.response-card {
background: var(--obsidian-mid);
border: 1px solid var(--glass-border);
border-radius: var(--radius-md);
padding: var(--space-6) var(--space-6);
margin-bottom: var(--space-6);
position: relative;
overflow: hidden;
}
.response-card::before {
content: '';
position: absolute; top: 0; left: 0; right: 0; height: 1px;
background: linear-gradient(90deg, transparent, var(--accent-ring), transparent);
}
/* Review path callout */
.review-path {
padding: var(--space-3) var(--space-4);
border-radius: var(--radius-sm);
margin-bottom: var(--space-5);
border-left: 2px solid;
}
.review-path--inhouse {
background: rgba(251, 191, 36, 0.06);
border-left-color: var(--signal-amber);
}
.review-path--otc {
background: rgba(52, 211, 153, 0.06);
border-left-color: var(--signal-green);
}
.review-path__badge {
display: flex; align-items: baseline; gap: var(--space-3);
margin-bottom: 4px;
}
.review-path__label {
font-family: var(--mono); font-size: var(--text-sm); font-weight: 400;
}
.review-path--inhouse .review-path__label { color: var(--signal-amber); }
.review-path--otc .review-path__label { color: var(--signal-green); }
.review-path__why {
font-family: var(--sans); font-size: var(--text-xs); color: var(--text-tertiary);
}
.review-path__note {
font-family: var(--sans); font-size: var(--text-sm); font-weight: 300;
color: var(--text-secondary); line-height: 1.5;
}
/* Expandable explain */
.review-path__toggle {
background: none; border: none; cursor: pointer;
font-family: var(--mono); font-size: var(--text-xs); color: var(--text-tertiary);
display: inline-flex; align-items: center; gap: 4px;
padding: 0; margin-left: var(--space-3);
transition: color 0.2s;
}
.review-path__toggle:hover { color: var(--accent); }
.review-path__toggle-arrow {
transition: transform 0.3s;
}
.review-path.expanded .review-path__toggle-arrow {
transform: rotate(180deg);
}
.review-path__explain {
max-height: 0; overflow: hidden; opacity: 0;
transition: max-height 0.4s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s, margin 0.3s;
margin-top: 0;
}
.review-path.expanded .review-path__explain {
max-height: 400px; opacity: 1; margin-top: var(--space-3);
}
.review-path__explain p {
font-family: var(--sans); font-size: var(--text-sm); font-weight: 300;
color: var(--text-secondary); line-height: 1.55; margin-bottom: var(--space-3);
}
.review-path__explain strong { font-weight: 400; color: var(--text-primary); }
.review-path__tracks {
display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2);
margin-bottom: var(--space-3);
}
.review-path__track {
padding: var(--space-3);
background: var(--obsidian-mid); border-radius: var(--radius-sm);
border: 1px solid var(--glass-border);
}
.review-path__track-label {
display: block;
font-family: var(--mono); font-size: var(--text-xs); font-weight: 400;
margin-bottom: 4px;
}
.review-path__track-desc {
font-family: var(--sans); font-size: var(--text-xs); font-weight: 300;
color: var(--text-tertiary); line-height: 1.45;
}
.response-headline {
font-family: var(--sans); font-size: var(--text-xl); font-weight: 300;
margin-bottom: var(--space-2);
}
.response-summary {
font-family: var(--sans); font-size: var(--text-base); font-weight: 300;
color: var(--text-primary); line-height: 1.65;
margin-bottom: var(--space-6);
}
/* Detail cards inside response */
.detail-grid {
display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3);
margin-bottom: var(--space-6);
}
.detail-card {
background: var(--glass); border: 1px solid var(--glass-border);
border-radius: var(--radius-sm); padding: var(--space-4);
transition: border-color 0.2s;
}
.detail-card:hover { border-color: var(--glass-hover); }
.detail-card__label {
font-family: var(--mono); font-size: var(--text-xs); font-weight: 400;
letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-tertiary);
margin-bottom: var(--space-2);
}
.detail-card__value {
font-family: var(--mono); font-size: var(--text-lg); font-weight: 300;
color: var(--text-primary); margin-bottom: 2px;
}
.detail-card__note {
font-family: var(--sans); font-size: var(--text-xs); color: var(--text-secondary);
line-height: 1.4;
}
/* Permit checklist */
.permit-checklist { margin-bottom: var(--space-6); }
.permit-checklist__title {
font-family: var(--mono); font-size: var(--text-xs); font-weight: 400;
letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-tertiary);
margin-bottom: var(--space-3);
}
.checklist-item {
display: flex; align-items: flex-start; gap: var(--space-3);
padding: 8px 0;
}
.checklist-item__icon {
width: 18px; height: 18px; border-radius: var(--radius-full); flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
margin-top: 1px;
}
.checklist-item__icon--required {
background: rgba(94, 234, 212, 0.12); border: 1px solid var(--accent-ring);
}
.checklist-item__icon--likely {
background: rgba(251, 191, 36, 0.1); border: 1px solid rgba(251, 191, 36, 0.25);
}
.checklist-item__text {
font-family: var(--sans); font-size: var(--text-sm); color: var(--text-secondary);
line-height: 1.5;
}
.checklist-item__text strong {
font-weight: 400; color: var(--text-primary);
}
.checklist-item__confidence {
font-family: var(--mono); font-size: 10px; color: var(--text-tertiary);
margin-left: auto; flex-shrink: 0; padding-top: 2px;
}
/* Contextual insights */
.insights-section { margin-bottom: var(--space-6); }
.insight-item {
display: flex; align-items: flex-start; gap: var(--space-3);
padding: 10px var(--space-3);
margin: 0 calc(-1 * var(--space-3));
border-radius: var(--radius-sm);
transition: background 0.15s;
cursor: default;
}
.insight-item:hover { background: var(--glass); }
.insight-item__icon {
font-size: 13px; flex-shrink: 0; margin-top: 2px;
color: var(--text-tertiary);
}
.insight-item__text {
font-family: var(--sans); font-size: var(--text-sm); font-weight: 300;
color: var(--text-secondary); line-height: 1.55;
}
.insight-item__text em {
font-style: normal; font-family: var(--mono); color: var(--text-primary);
font-size: var(--text-xs);
}
/* Follow-up questions */
.followup-section { margin-bottom: var(--space-6); }
.followup-item {
display: flex; align-items: center; gap: var(--space-3);
padding: 10px var(--space-4);
margin: 0 calc(-1 * var(--space-4));
border: 1px solid var(--glass-border);
border-radius: var(--radius-sm);
margin-bottom: var(--space-2);
cursor: pointer;
transition: border-color 0.2s, background 0.15s;
}
.followup-item:hover {
border-color: var(--accent-ring); background: var(--accent-glow);
}
.followup-item__text {
font-family: var(--sans); font-size: var(--text-sm); font-weight: 300;
color: var(--text-secondary); flex: 1;
transition: color 0.2s;
}
.followup-item:hover .followup-item__text { color: var(--text-primary); }
.followup-item__arrow {
font-family: var(--mono); font-size: 12px; color: var(--text-tertiary);
opacity: 0; transition: opacity 0.2s, color 0.2s;
}
.followup-item:hover .followup-item__arrow { opacity: 1; color: var(--accent); }
/* Action row */
.action-row {
display: flex; gap: var(--space-3);
padding: var(--space-2) 0 var(--space-6);
}
/* Disclaimer */
.disclaimer {
font-family: var(--sans); font-size: 11px; color: var(--text-ghost);
text-align: center; padding: var(--space-4) 0;
line-height: 1.5;
}
@media (max-width: 768px) {
.detail-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<nav class="nav-float">
<a href="#" class="nav-float__wordmark">sfpermits.ai</a>
<div class="nav-float__links">
<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">
<!-- USER QUERY -->
<div class="query-section reveal">
<div class="query-text">I want to remodel my kitchen at 487 Noe St — remove a bearing wall, relocate the gas line, and add an island with a sink. What permits do I need?</div>
<div class="query-property">
<span class="query-property__check">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><polyline points="20 6 9 17 4 12"/></svg>
</span>
<span class="query-property__addr">487 Noe St · Residential · Noe Valley</span>
</div>
</div>
<!-- AI RESPONSE -->
<div class="reveal reveal-delay-1">
<div class="ai-label">
<span class="ai-label__sparkle">✨</span>
<span>AI Analysis</span>
<span class="ai-label__date">· Based on public records as of Feb 27, 2026</span>
</div>
<div class="response-card">
<!-- LEAD WITH THE ANSWER -->
<p class="response-headline status-text--amber">This will take 4–7 months.</p>
<p class="response-summary">
Bearing wall removal requires <strong>3 permits</strong> and full plan review through <strong>8 city stations</strong>. No shortcut here — but knowing the process saves you from the most common delays.
</p>
<!-- Routing badge — expandable -->
<div class="review-path review-path--inhouse">
<div class="review-path__badge">
<span class="review-path__label">In-house review required</span>
<button class="review-path__toggle" onclick="this.closest('.review-path').classList.toggle('expanded')">
<span class="review-path__toggle-text">Why can't this be faster?</span>
<span class="review-path__toggle-arrow">↓</span>
</button>
</div>
<div class="review-path__explain">
<p>San Francisco has two permit tracks:</p>
<div class="review-path__tracks">
<div class="review-path__track review-path__track--otc">
<span class="review-path__track-label status-text--green">Over-the-counter</span>
<span class="review-path__track-desc">Simple swaps, cosmetic work, no structural changes. Walk in, same-day permit.</span>
</div>
<div class="review-path__track review-path__track--inhouse">
<span class="review-path__track-label status-text--amber">In-house review</span>
<span class="review-path__track-desc">Structural, electrical panels, new plumbing routes, load-bearing changes. Plans reviewed by multiple city departments.</span>
</div>
</div>
<p>Your project involves <strong>removing a bearing wall</strong> — that's structural. The city needs to verify your engineer's calculations won't compromise the building. There's no way around this review, but having your structural letter ready on day one avoids the most common delay.</p>
</div>
</div>
<!-- TIMELINE + FEES -->
<div class="detail-grid">
<div class="detail-card">
<div class="detail-card__label">Est. timeline</div>
<div class="detail-card__value status-text--amber">4–7 months</div>
<div class="detail-card__note">Based on 3,412 similar permits in Noe Valley. PPC station averaging 38 days.</div>
</div>
<div class="detail-card">
<div class="detail-card__label">Est. fees</div>
<div class="detail-card__value">$4,200–$5,800</div>
<div class="detail-card__note">Building permit + plan check + technology surcharge. Assumes $85K construction cost.</div>
</div>
</div>
<!-- PERMIT CHECKLIST -->
<div class="permit-checklist">
<div class="permit-checklist__title">Required permits</div>
<div class="checklist-item">
<span class="checklist-item__icon checklist-item__icon--required">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#5eead4" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>
</span>
<span class="checklist-item__text"><strong>Alterations permit (Form 8)</strong> — covers structural work, wall removal, plumbing relocation</span>
<span class="checklist-item__confidence">high</span>
</div>
<div class="checklist-item">
<span class="checklist-item__icon checklist-item__icon--required">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#5eead4" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>
</span>
<span class="checklist-item__text"><strong>Plumbing permit</strong> — sink relocation and gas line work</span>
<span class="checklist-item__confidence">high</span>
</div>
<div class="checklist-item">
<span class="checklist-item__icon checklist-item__icon--required">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#5eead4" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>
</span>
<span class="checklist-item__text"><strong>Electrical permit</strong> — new circuits for island outlets, possible panel impact</span>
<span class="checklist-item__confidence">high</span>
</div>
<div class="checklist-item">
<span class="checklist-item__icon checklist-item__icon--likely">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2.5"><line x1="12" y1="5" x2="12" y2="12"/><circle cx="12" cy="16" r="0.5" fill="#fbbf24"/></svg>
</span>
<span class="checklist-item__text"><strong>Structural engineer letter</strong> — required for bearing wall removal, must be stamped by licensed SE</span>
<span class="checklist-item__confidence">likely</span>
</div>
</div>
<!-- INSIGHTS -->
<div class="insights-section">
<div class="permit-checklist__title">Things to know</div>
<div class="insight-item">
<span class="insight-item__icon">◆</span>
<span class="insight-item__text">PPC (Plan and Permit Check) is currently the slowest station in Noe Valley, averaging <em>38 days</em>. Your project will route through it.</span>
</div>
<div class="insight-item">
<span class="insight-item__icon">◆</span>
<span class="insight-item__text">Bearing wall removal triggers SFFD review for firewall compliance. This adds <em>12–18 days</em> to the timeline.</span>
</div>
<div class="insight-item">
<span class="insight-item__icon">◆</span>
<span class="insight-item__text">Gas line relocation requires PG&E coordination. Schedule their inspection <em>before</em> filing — backlog is currently 3–4 weeks.</span>
</div>
<div class="insight-item">
<span class="insight-item__icon">◆</span>
<span class="insight-item__text">Similar projects in this block have a <em>34% revision rate</em>. Most revisions are related to inadequate structural calculations.</span>
</div>
</div>
</div><!-- /response-card -->
</div>
<!-- FOLLOW-UP QUESTIONS -->
<section class="followup-section reveal reveal-delay-2">
<div class="section-label">Refine your question</div>
<div class="followup-item">
<span class="followup-item__text">What documents do I need to submit with my application?</span>
<span class="followup-item__arrow">→</span>
</div>
<div class="followup-item">
<span class="followup-item__text">Who are the top contractors for kitchen remodels in Noe Valley?</span>
<span class="followup-item__arrow">→</span>
</div>
<div class="followup-item">
<span class="followup-item__text">What's the revision risk for this type of project?</span>
<span class="followup-item__arrow">→</span>
</div>
</section>
<!-- ACTIONS -->
<div class="action-row reveal reveal-delay-2">
<button class="action-btn">Save to portfolio</button>
<button class="action-btn">Share this analysis</button>
</div>
<!-- DISCLAIMER -->
<div class="disclaimer reveal">
AI-generated from public records. Not legal or professional advice. Consult a licensed architect or permit consultant for your specific project.
</div>
<!-- FRESHNESS -->
<div class="freshness reveal">
<span class="freshness-dot"></span>
Data as of Feb 27, 2026 · Updated nightly
</div>
</div>
</div>
<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));
</script>
</body>
</html>