← back to Designer Portfolio Pages
src/views/portfolio.ejs
238 lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title><%= portfolio.title || "Mood Board" %></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=Lora:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap" rel="stylesheet" />
<meta name="robots" content="noindex,nofollow" />
<style>
:root {
--font-heading: 'Lora', serif;
--font-body: -apple-system, system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
--color-bg: #fafaf8;
--color-surface: #fff;
--color-text: #1a1a1a;
--color-muted: #6b6b6b;
--color-border: #e5e2dc;
--color-accent: #3D4246;
--color-accent-light: #f5f3ef;
--radius: 8px;
}
* { box-sizing: border-box; margin: 0; }
body {
font-family: var(--font-body);
background: var(--color-bg);
color: var(--color-text);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
.container { max-width: 1000px; margin: 0 auto; padding: 40px 24px; }
.portfolio-header {
text-align: center;
margin-bottom: 32px;
padding-bottom: 24px;
border-bottom: 1px solid var(--color-border);
}
.portfolio-header h1 {
font-family: var(--font-heading);
font-size: 34px;
font-weight: 600;
letter-spacing: -0.01em;
margin-bottom: 6px;
}
.portfolio-header .byline {
font-size: 14px;
color: var(--color-muted);
}
.portfolio-header .byline strong {
color: var(--color-text);
font-weight: 500;
}
.ai-intro {
font-family: var(--font-heading);
font-size: 16px;
font-style: italic;
line-height: 1.8;
color: #444;
max-width: 680px;
margin: 0 auto;
text-align: center;
padding: 20px 24px;
}
.section-title {
font-family: var(--font-heading);
font-weight: 500;
font-size: 19px;
margin-bottom: 18px;
}
.section-title .count {
font-weight: 400;
color: var(--color-muted);
font-size: 15px;
}
.card {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: 24px;
margin: 20px 0;
}
.mood-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 18px;
}
.mood-item {
border: 1px solid var(--color-border);
border-radius: var(--radius);
overflow: hidden;
background: var(--color-surface);
transition: box-shadow 0.2s ease;
}
.mood-item:hover {
box-shadow: 0 3px 16px rgba(0,0,0,0.06);
}
.mood-item img {
width: 100%;
aspect-ratio: 1 / 1;
object-fit: cover;
display: block;
}
.mood-item-info {
padding: 12px 14px 14px;
}
.mood-item-name {
font-family: var(--font-heading);
font-weight: 500;
font-size: 14px;
line-height: 1.3;
margin-bottom: 4px;
}
.mood-item-tags {
font-size: 11px;
color: var(--color-muted);
letter-spacing: 0.02em;
}
.contact-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px 32px;
}
.contact-grid .field { margin-bottom: 14px; }
.contact-grid dt {
font-size: 11px;
color: var(--color-muted);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 2px;
}
.contact-grid dd { margin: 0; font-size: 14px; }
.contact-grid a { color: var(--color-accent); text-decoration: none; }
.contact-grid a:hover { text-decoration: underline; }
.footer {
margin-top: 32px;
text-align: center;
font-size: 12px;
color: var(--color-muted);
}
.footer code {
background: var(--color-accent-light);
padding: 3px 8px;
border-radius: 4px;
font-size: 11px;
}
@media (max-width: 600px) {
.mood-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.contact-grid { grid-template-columns: 1fr; }
.portfolio-header h1 { font-size: 26px; }
}
</style>
</head>
<body>
<main class="container">
<header class="portfolio-header">
<h1><%= portfolio.title || "Mood Board" %></h1>
<p class="byline">
Curated by <strong><%= portfolio.contact.name %></strong><% if (portfolio.contact.business) { %>, <%= portfolio.contact.business %><% } %>
</p>
</header>
<% if (portfolio.aiIntro) { %>
<section class="card">
<p class="ai-intro"><%= portfolio.aiIntro %></p>
</section>
<% } %>
<section class="card">
<h2 class="section-title">Selected Patterns <span class="count">(<%= portfolio.patterns.length %>)</span></h2>
<div class="mood-grid">
<% portfolio.patterns.forEach(function(p) { %>
<div class="mood-item">
<% if (p.productUrl) { %>
<a href="<%= p.productUrl %>" target="_blank" rel="noopener noreferrer">
<img src="<%= p.imageUrl %>" alt="<%= p.name %>" loading="lazy" />
</a>
<% } else { %>
<img src="<%= p.imageUrl %>" alt="<%= p.name %>" loading="lazy" />
<% } %>
<div class="mood-item-info">
<div class="mood-item-name"><%= p.name %></div>
<% if (p.tags && p.tags.length) { %>
<div class="mood-item-tags"><%= p.tags.slice(0, 5).join(" · ") %></div>
<% } %>
</div>
</div>
<% }) %>
</div>
</section>
<section class="card">
<h2 class="section-title">Contact</h2>
<dl class="contact-grid">
<div class="field">
<dt>Designer</dt>
<dd><strong><%= portfolio.contact.name %></strong></dd>
</div>
<% if (portfolio.contact.business) { %>
<div class="field">
<dt>Business</dt>
<dd><%= portfolio.contact.business %></dd>
</div>
<% } %>
<div class="field">
<dt>Email</dt>
<dd><a href="mailto:<%= portfolio.contact.email %>"><%= portfolio.contact.email %></a></dd>
</div>
<% if (portfolio.contact.phone) { %>
<div class="field">
<dt>Phone</dt>
<dd><%= portfolio.contact.phone %></dd>
</div>
<% } %>
<% if (portfolio.contact.website) { %>
<div class="field">
<dt>Website</dt>
<dd><a href="<%= portfolio.contact.website %>" target="_blank" rel="noopener noreferrer"><%= portfolio.contact.website %></a></dd>
</div>
<% } %>
</dl>
</section>
<footer class="footer">
Share this mood board: <code><%= baseUrl %>/p/<%= portfolio.slug %></code>
</footer>
</main>
</body>
</html>