Interior — Team
An editorial team page for an interior design studio: portrait-led designer cards pairing warm imagery with name, role, specialty badge and a short bio. Filter the roster by discipline, toggle a compact list view, and open a quiet detail panel that slides in with each designer's philosophy, projects and contact. Muted clay-and-sage palette, thin rules, Cormorant Garamond headings and generous whitespace give it a print-magazine calm.
MCP
Code
:root {
--bg: #f6f2ec;
--paper: #fbf9f5;
--ink: #2c2620;
--ink-2: #5a5147;
--muted: #8a8175;
--clay: #b08968;
--clay-d: #8c6a4f;
--walnut: #5c4433;
--sage: #9caf88;
--line: rgba(44, 38, 32, 0.12);
--white: #fff;
--r-sm: 4px;
--r-md: 8px;
--r-lg: 14px;
--shadow: 0 18px 46px -22px rgba(44, 38, 32, 0.4);
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
background: var(--bg);
color: var(--ink);
font-family: "Inter", system-ui, sans-serif;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.page {
max-width: 1080px;
margin: 0 auto;
padding: 40px 28px 64px;
}
/* ---------- Masthead ---------- */
.masthead__top {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 16px;
padding-bottom: 18px;
border-bottom: 1px solid var(--line);
flex-wrap: wrap;
}
.wordmark {
font-family: "Cormorant Garamond", serif;
font-size: 1.5rem;
font-weight: 600;
letter-spacing: 0.02em;
color: var(--walnut);
}
.wordmark__tag {
font-size: 0.72rem;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--muted);
}
.masthead__lead {
display: grid;
grid-template-columns: 1.15fr 1fr;
gap: 24px 48px;
align-items: end;
padding: 40px 0 8px;
}
.masthead__title {
font-family: "Cormorant Garamond", serif;
font-weight: 500;
font-size: clamp(2.4rem, 6vw, 3.6rem);
line-height: 1.05;
margin: 0;
color: var(--ink);
}
.masthead__mission {
margin: 0;
color: var(--ink-2);
font-size: 0.95rem;
max-width: 42ch;
}
/* ---------- Controls ---------- */
.controls {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin: 34px 0 26px;
padding: 14px 0;
border-top: 1px solid var(--line);
border-bottom: 1px solid var(--line);
flex-wrap: wrap;
}
.filters { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
font: inherit;
font-size: 0.82rem;
letter-spacing: 0.01em;
color: var(--ink-2);
background: transparent;
border: 1px solid var(--line);
border-radius: 999px;
padding: 7px 15px;
cursor: pointer;
transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.12s ease;
}
.pill:hover { border-color: var(--clay); color: var(--walnut); }
.pill:active { transform: translateY(1px); }
.pill.is-active {
background: var(--walnut);
border-color: var(--walnut);
color: var(--paper);
}
.controls__right { display: flex; align-items: center; gap: 16px; }
.count {
margin: 0;
font-size: 0.78rem;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--muted);
}
.count #countNum { color: var(--walnut); font-weight: 600; }
.viewtoggle {
display: inline-flex;
border: 1px solid var(--line);
border-radius: var(--r-md);
overflow: hidden;
}
.viewtoggle__btn {
display: grid;
place-items: center;
width: 34px;
height: 30px;
border: 0;
background: var(--paper);
color: var(--muted);
cursor: pointer;
transition: background 0.16s ease, color 0.16s ease;
}
.viewtoggle__btn svg rect { fill: currentColor; }
.viewtoggle__btn + .viewtoggle__btn { border-left: 1px solid var(--line); }
.viewtoggle__btn:hover { color: var(--walnut); }
.viewtoggle__btn.is-active { background: var(--clay); color: var(--white); }
/* ---------- Roster ---------- */
.roster {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 34px 28px;
}
.card {
display: flex;
flex-direction: column;
cursor: pointer;
background: none;
border: 0;
padding: 0;
text-align: left;
font: inherit;
color: inherit;
border-radius: var(--r-md);
transition: transform 0.2s ease;
}
.card:focus-visible {
outline: 2px solid var(--clay);
outline-offset: 6px;
}
.card__figure {
position: relative;
aspect-ratio: 4 / 5;
border-radius: var(--r-md);
overflow: hidden;
background: linear-gradient(135deg, #e7ddd0, #d8c7b4);
}
.card__figure img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
filter: saturate(0.92) contrast(1.02);
transition: transform 0.5s ease, filter 0.4s ease;
}
.card:hover .card__figure img { transform: scale(1.045); filter: saturate(1) contrast(1.04); }
.card__figure::after {
content: "";
position: absolute;
inset: 0;
box-shadow: inset 0 0 0 1px rgba(44, 38, 32, 0.08);
border-radius: var(--r-md);
pointer-events: none;
}
.card__body { padding-top: 14px; }
.card__rule {
height: 1px;
width: 28px;
background: var(--clay);
margin: 0 0 12px;
transition: width 0.28s ease;
}
.card:hover .card__rule { width: 56px; }
.card__name {
font-family: "Cormorant Garamond", serif;
font-size: 1.5rem;
font-weight: 600;
margin: 0 0 2px;
color: var(--ink);
line-height: 1.1;
}
.card__role {
font-size: 0.72rem;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--muted);
margin: 0 0 10px;
}
.badge {
display: inline-block;
font-size: 0.68rem;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--clay-d);
background: rgba(176, 137, 104, 0.12);
border: 1px solid rgba(176, 137, 104, 0.28);
padding: 3px 9px;
border-radius: 999px;
}
.badge[data-disc="styling"] { color: #7d8a5e; background: rgba(156, 175, 136, 0.16); border-color: rgba(156, 175, 136, 0.38); }
.badge[data-disc="lighting"] { color: var(--walnut); background: rgba(92, 68, 51, 0.1); border-color: rgba(92, 68, 51, 0.24); }
.card__bio {
margin: 12px 0 0;
color: var(--ink-2);
font-size: 0.88rem;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ---------- List view ---------- */
.roster.is-list { grid-template-columns: 1fr; gap: 0; }
.roster.is-list .card {
flex-direction: row;
align-items: center;
gap: 20px;
padding: 18px 6px;
border-bottom: 1px solid var(--line);
border-radius: 0;
}
.roster.is-list .card:focus-visible { outline-offset: 2px; }
.roster.is-list .card__figure {
width: 66px;
min-width: 66px;
aspect-ratio: 1 / 1;
border-radius: 50%;
}
.roster.is-list .card__body { padding-top: 0; flex: 1; display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 6px 20px; }
.roster.is-list .card__rule { display: none; }
.roster.is-list .card__name { font-size: 1.28rem; grid-row: 1; }
.roster.is-list .card__role { margin: 0; grid-row: 2; grid-column: 1; }
.roster.is-list .card__bio { display: none; }
.roster.is-list .badge { grid-row: 1 / span 2; grid-column: 2; justify-self: end; }
.empty {
text-align: center;
color: var(--muted);
font-style: italic;
padding: 48px 0;
font-family: "Cormorant Garamond", serif;
font-size: 1.3rem;
}
/* ---------- Colophon ---------- */
.colophon {
display: flex;
justify-content: space-between;
gap: 16px;
margin-top: 52px;
padding-top: 20px;
border-top: 1px solid var(--line);
font-size: 0.76rem;
letter-spacing: 0.06em;
color: var(--muted);
flex-wrap: wrap;
}
/* ---------- Panel ---------- */
.panel {
position: fixed;
inset: 0;
z-index: 40;
visibility: hidden;
pointer-events: none;
}
.panel.is-open { visibility: visible; pointer-events: auto; }
.panel__backdrop {
position: absolute;
inset: 0;
background: rgba(44, 38, 32, 0.34);
opacity: 0;
transition: opacity 0.32s ease;
backdrop-filter: blur(1px);
}
.panel.is-open .panel__backdrop { opacity: 1; }
.panel__sheet {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: min(440px, 92vw);
background: var(--paper);
box-shadow: var(--shadow);
transform: translateX(102%);
transition: transform 0.36s cubic-bezier(0.22, 1, 0.36, 1);
overflow-y: auto;
display: flex;
flex-direction: column;
}
.panel.is-open .panel__sheet { transform: translateX(0); }
.panel__sheet:focus { outline: none; }
.panel__close {
position: absolute;
top: 16px;
right: 16px;
z-index: 2;
width: 38px;
height: 38px;
display: grid;
place-items: center;
border-radius: 50%;
border: 1px solid var(--line);
background: rgba(251, 249, 245, 0.86);
color: var(--ink);
cursor: pointer;
transition: background 0.16s ease, transform 0.14s ease;
}
.panel__close:hover { background: var(--white); }
.panel__close:active { transform: scale(0.94); }
.panel__portrait {
height: 300px;
background-size: cover;
background-position: center;
background-color: #d8c7b4;
}
.panel__body { padding: 26px 30px 36px; }
.panel__role {
font-size: 0.72rem;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--muted);
}
.panel__name {
font-family: "Cormorant Garamond", serif;
font-weight: 600;
font-size: 2.1rem;
line-height: 1.05;
margin: 4px 0 12px;
color: var(--ink);
}
.panel__bio {
margin: 18px 0 0;
color: var(--ink-2);
font-size: 0.94rem;
}
.panel__meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px 20px;
margin: 24px 0;
padding: 18px 0;
border-top: 1px solid var(--line);
border-bottom: 1px solid var(--line);
}
.panel__meta dt {
font-size: 0.68rem;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 3px;
}
.panel__meta dd { margin: 0; font-size: 0.92rem; color: var(--ink); font-weight: 500; }
.panel__subhead {
font-family: "Cormorant Garamond", serif;
font-weight: 600;
font-size: 1.2rem;
margin: 0 0 10px;
color: var(--walnut);
}
.panel__projects { list-style: none; margin: 0 0 26px; padding: 0; }
.panel__projects li {
display: flex;
justify-content: space-between;
gap: 14px;
padding: 9px 0;
border-bottom: 1px dotted var(--line);
font-size: 0.9rem;
}
.panel__projects li span:last-child { color: var(--muted); font-variant-numeric: tabular-nums; }
.emailbtn {
display: inline-flex;
align-items: center;
gap: 9px;
font: inherit;
font-size: 0.86rem;
font-weight: 500;
color: var(--paper);
background: var(--clay);
border: 0;
border-radius: var(--r-md);
padding: 11px 18px;
cursor: pointer;
transition: background 0.18s ease, transform 0.14s ease;
}
.emailbtn:hover { background: var(--clay-d); }
.emailbtn:active { transform: translateY(1px); }
/* focus visibility */
button:focus-visible,
.card:focus-visible { outline: 2px solid var(--clay); outline-offset: 3px; }
.emailbtn:focus-visible, .panel__close:focus-visible { outline-offset: 3px; }
/* ---------- Toast ---------- */
.toast {
position: fixed;
left: 50%;
bottom: 28px;
transform: translate(-50%, 20px);
background: var(--walnut);
color: var(--paper);
font-size: 0.84rem;
letter-spacing: 0.02em;
padding: 11px 20px;
border-radius: 999px;
box-shadow: var(--shadow);
opacity: 0;
pointer-events: none;
transition: opacity 0.24s ease, transform 0.24s ease;
z-index: 60;
}
.toast.is-show { opacity: 1; transform: translate(-50%, 0); }
/* ---------- Responsive ---------- */
@media (max-width: 860px) {
.roster { grid-template-columns: repeat(2, 1fr); }
.masthead__lead { grid-template-columns: 1fr; gap: 18px; }
}
@media (max-width: 520px) {
.page { padding: 28px 18px 48px; }
.roster { grid-template-columns: 1fr; gap: 30px; }
.controls { flex-direction: column; align-items: stretch; }
.controls__right { justify-content: space-between; }
.filters { overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; }
.pill { white-space: nowrap; }
.roster.is-list .card__body { grid-template-columns: 1fr; }
.roster.is-list .badge { grid-row: 3; grid-column: 1; justify-self: start; margin-top: 4px; }
.masthead__title { font-size: 2.3rem; }
.colophon { flex-direction: column; gap: 6px; }
}
@media (prefers-reduced-motion: reduce) {
* { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}/* Marlowe & Fen — Studio Team page */
(function () {
"use strict";
var U = "https://images.unsplash.com/";
var q = "?auto=format&fit=crop&w=640&q=80";
var TEAM = [
{
id: "elodie-marlowe",
name: "Elodie Marlowe",
role: "Founding Partner",
disc: "residential",
discLabel: "Residential",
city: "Lisboa",
years: "14 years",
email: "[email protected]",
img: "photo-1544005313-94ddf0286df2",
bio: "Elodie founded the studio on a belief that a home should feel inevitable — as if the rooms had always been that way.",
full: "Elodie leads the residential practice with a preference for lime plaster, aged oak and light that moves through a room across the day. She trained as a cabinetmaker before turning to interiors, and it shows in the joinery-first way she approaches every plan.",
projects: [["Casa Alfama", "2024"], ["The Belgrave House", "2022"], ["Quinta do Lago Villa", "2021"]]
},
{
id: "tomas-fen",
name: "Tomás Fen",
role: "Founding Partner",
disc: "commercial",
discLabel: "Commercial",
city: "London",
years: "14 years",
email: "[email protected]",
img: "photo-1500648767791-00dcc994a43e",
bio: "Tomás shapes the studio's hospitality and workplace work, translating warmth into spaces that hold hundreds of people a day.",
full: "Tomás thinks in circulation and acoustics as much as finishes. His commercial interiors — restaurants, members' clubs, studios — carry the same quiet materiality as the studio's homes, only built to take a decade of daily use.",
projects: [["Larder & Vine, Soho", "2025"], ["Foundry Members Club", "2023"], ["Praça Coworking", "2022"]]
},
{
id: "naomi-okafor",
name: "Naomi Okafor",
role: "Senior Designer",
disc: "residential",
discLabel: "Residential",
city: "London",
years: "8 years",
email: "[email protected]",
img: "photo-1573497019940-1c28c88b4f3e",
bio: "Naomi is drawn to colour drawn from the landscape — clay, ochre, moss — layered until a room feels sun-warmed.",
full: "Naomi runs the studio's most ambitious family homes, balancing heirloom pieces with commissioned craft. She keeps a running archive of pigment swatches gathered on site walks, and most of the studio's palettes begin on her desk.",
projects: [["Hampstead Terrace", "2024"], ["Ericeira Beach House", "2023"], ["The Reader's Flat", "2021"]]
},
{
id: "arch-delgado",
name: "Arch Delgado",
role: "Lighting Designer",
disc: "lighting",
discLabel: "Lighting",
city: "Lisboa",
years: "6 years",
email: "[email protected]",
img: "photo-1507003211169-0a1dd7228f2d",
bio: "Arch treats light as a material — never fixtures for their own sake, only the glow they leave on plaster and stone.",
full: "Arch designs the layered lighting schemes that give the studio's rooms their evening character. He builds every scheme around a single low, warm anchor and works outward, so no room ever reads as merely switched on.",
projects: [["Casa Alfama", "2024"], ["Foundry Members Club", "2023"], ["Atelier Lumen", "2022"]]
},
{
id: "wren-castellan",
name: "Wren Castellan",
role: "Stylist & Set Designer",
disc: "styling",
discLabel: "Styling",
city: "London",
years: "5 years",
email: "[email protected]",
img: "photo-1487412720507-e7ab37603c6f",
bio: "Wren dresses the finished rooms — the books, the ceramics, the single branch — that make a space read as lived-in.",
full: "Wren stages every project for its final photography and, more importantly, for the first evening the client moves in. She sources from small makers and flea markets, keeping a props library the whole studio borrows from.",
projects: [["The Belgrave House", "2022"], ["Larder & Vine, Soho", "2025"], ["Hampstead Terrace", "2024"]]
},
{
id: "mateo-rivas",
name: "Mateo Rivas",
role: "Project Designer",
disc: "commercial",
discLabel: "Commercial",
city: "Lisboa",
years: "4 years",
email: "[email protected]",
img: "photo-1506794778202-cad84cf45f1d",
bio: "Mateo keeps the workshops honest — the detail drawings, the site visits, the joints that never make the magazines.",
full: "Mateo carries the studio's commercial projects from concept into built reality, coordinating fabricators and trades. His measured drawings are quietly famous in the studio for anticipating problems months before they arrive on site.",
projects: [["Praça Coworking", "2022"], ["Atelier Lumen", "2022"], ["Foundry Members Club", "2023"]]
}
];
var roster = document.getElementById("roster");
var emptyEl = document.getElementById("empty");
var countNum = document.getElementById("countNum");
var toastEl = document.getElementById("toast");
var toastTimer;
var state = { filter: "all", view: "grid" };
function toast(msg) {
toastEl.textContent = msg;
toastEl.classList.add("is-show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-show");
}, 2200);
}
function imgUrl(id) { return U + id + q; }
function render() {
var list = TEAM.filter(function (p) {
return state.filter === "all" || p.disc === state.filter;
});
roster.innerHTML = "";
list.forEach(function (p) {
var li = document.createElement("li");
var btn = document.createElement("button");
btn.className = "card";
btn.type = "button";
btn.dataset.id = p.id;
btn.setAttribute("aria-label", "View profile of " + p.name + ", " + p.role);
btn.innerHTML =
'<span class="card__figure"><img src="' + imgUrl(p.img) + '" alt="Portrait of ' + p.name + '" loading="lazy" /></span>' +
'<span class="card__body">' +
'<span class="card__rule" aria-hidden="true"></span>' +
'<span class="card__name">' + p.name + '</span>' +
'<span class="card__role">' + p.role + '</span>' +
'<span class="badge" data-disc="' + p.disc + '">' + p.discLabel + '</span>' +
'<span class="card__bio">' + p.bio + '</span>' +
'</span>';
btn.addEventListener("click", function () { openPanel(p.id); });
li.appendChild(btn);
roster.appendChild(li);
});
countNum.textContent = list.length;
emptyEl.hidden = list.length !== 0;
roster.hidden = list.length === 0;
}
/* ---- Filters ---- */
var pills = document.querySelectorAll(".pill");
pills.forEach(function (pill) {
pill.addEventListener("click", function () {
pills.forEach(function (p) {
p.classList.remove("is-active");
p.setAttribute("aria-pressed", "false");
});
pill.classList.add("is-active");
pill.setAttribute("aria-pressed", "true");
state.filter = pill.dataset.filter;
render();
});
});
/* ---- View toggle ---- */
var viewBtns = document.querySelectorAll(".viewtoggle__btn");
viewBtns.forEach(function (b) {
b.addEventListener("click", function () {
viewBtns.forEach(function (x) {
x.classList.remove("is-active");
x.setAttribute("aria-pressed", "false");
});
b.classList.add("is-active");
b.setAttribute("aria-pressed", "true");
state.view = b.dataset.view;
roster.classList.toggle("is-list", state.view === "list");
});
});
/* ---- Detail panel ---- */
var panel = document.getElementById("panel");
var sheet = panel.querySelector(".panel__sheet");
var lastFocused = null;
var current = null;
function openPanel(id) {
var p = TEAM.find(function (x) { return x.id === id; });
if (!p) return;
current = p;
lastFocused = document.activeElement;
document.getElementById("panelPortrait").style.backgroundImage =
"url(" + imgUrl(p.img) + ")";
document.getElementById("panelRole").textContent = p.role;
document.getElementById("panelName").textContent = p.name;
var badge = document.getElementById("panelBadge");
badge.textContent = p.discLabel;
badge.setAttribute("data-disc", p.disc);
document.getElementById("panelBio").textContent = p.full;
document.getElementById("panelYears").textContent = p.years;
document.getElementById("panelCity").textContent = p.city;
document.getElementById("emailLabel").textContent = p.email;
var pl = document.getElementById("panelProjects");
pl.innerHTML = "";
p.projects.forEach(function (pr) {
var li = document.createElement("li");
li.innerHTML = "<span>" + pr[0] + "</span><span>" + pr[1] + "</span>";
pl.appendChild(li);
});
panel.classList.add("is-open");
panel.setAttribute("aria-hidden", "false");
document.body.style.overflow = "hidden";
setTimeout(function () { sheet.focus(); }, 40);
}
function closePanel() {
if (!panel.classList.contains("is-open")) return;
panel.classList.remove("is-open");
panel.setAttribute("aria-hidden", "true");
document.body.style.overflow = "";
current = null;
if (lastFocused && lastFocused.focus) lastFocused.focus();
}
panel.querySelectorAll("[data-close]").forEach(function (el) {
el.addEventListener("click", closePanel);
});
document.addEventListener("keydown", function (e) {
if (e.key === "Escape") closePanel();
});
/* ---- Copy email ---- */
document.getElementById("emailBtn").addEventListener("click", function () {
if (!current) return;
var email = current.email;
var done = function () { toast("Copied " + email); };
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(email).then(done).catch(function () {
fallbackCopy(email); done();
});
} else {
fallbackCopy(email); done();
}
});
function fallbackCopy(text) {
var ta = document.createElement("textarea");
ta.value = text;
ta.style.position = "fixed";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.select();
try { document.execCommand("copy"); } catch (e) { /* no-op */ }
document.body.removeChild(ta);
}
render();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Marlowe & Fen — Studio Team</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=Cormorant+Garamond:wght@400;500;600&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="page">
<header class="masthead">
<div class="masthead__top">
<span class="wordmark">Marlowe & Fen</span>
<span class="wordmark__tag">Interior Studio · Est. 2011</span>
</div>
<div class="masthead__lead">
<h1 class="masthead__title">The people behind the rooms</h1>
<p class="masthead__mission">
A twelve-strong studio of designers, stylists and lighting specialists working
between London and Lisbon. We compose spaces that age gently — warm, quiet and
made to be lived in.
</p>
</div>
</header>
<section class="controls" aria-label="Team filters">
<div class="filters" role="group" aria-label="Filter by discipline">
<button class="pill is-active" data-filter="all" aria-pressed="true">All</button>
<button class="pill" data-filter="residential" aria-pressed="false">Residential</button>
<button class="pill" data-filter="commercial" aria-pressed="false">Commercial</button>
<button class="pill" data-filter="styling" aria-pressed="false">Styling</button>
<button class="pill" data-filter="lighting" aria-pressed="false">Lighting</button>
</div>
<div class="controls__right">
<p class="count" aria-live="polite"><span id="countNum">6</span> designers</p>
<div class="viewtoggle" role="group" aria-label="Change layout">
<button class="viewtoggle__btn is-active" data-view="grid" aria-pressed="true" title="Grid view" aria-label="Grid view">
<svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true"><rect x="2" y="2" width="7" height="7" rx="1"/><rect x="11" y="2" width="7" height="7" rx="1"/><rect x="2" y="11" width="7" height="7" rx="1"/><rect x="11" y="11" width="7" height="7" rx="1"/></svg>
</button>
<button class="viewtoggle__btn" data-view="list" aria-pressed="false" title="List view" aria-label="List view">
<svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true"><rect x="2" y="3" width="16" height="2.4" rx="1"/><rect x="2" y="9" width="16" height="2.4" rx="1"/><rect x="2" y="15" width="16" height="2.4" rx="1"/></svg>
</button>
</div>
</div>
</section>
<main>
<ul class="roster" id="roster" aria-label="Studio designers"></ul>
<p class="empty" id="empty" hidden>No designers in this discipline yet.</p>
</main>
<footer class="colophon">
<span>Marlowe & Fen — 14 Rua das Flores, Lisboa</span>
<span>[email protected]</span>
</footer>
</div>
<!-- Detail panel -->
<div class="panel" id="panel" aria-hidden="true">
<div class="panel__backdrop" data-close></div>
<aside class="panel__sheet" role="dialog" aria-modal="true" aria-labelledby="panelName" tabindex="-1">
<button class="panel__close" data-close aria-label="Close designer detail">
<svg viewBox="0 0 20 20" width="18" height="18" aria-hidden="true"><path d="M5 5l10 10M15 5L5 15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
</button>
<div class="panel__portrait" id="panelPortrait"></div>
<div class="panel__body">
<span class="panel__role" id="panelRole"></span>
<h2 class="panel__name" id="panelName"></h2>
<span class="badge" id="panelBadge"></span>
<p class="panel__bio" id="panelBio"></p>
<dl class="panel__meta">
<div><dt>With the studio</dt><dd id="panelYears"></dd></div>
<div><dt>Based in</dt><dd id="panelCity"></dd></div>
</dl>
<h3 class="panel__subhead">Signature projects</h3>
<ul class="panel__projects" id="panelProjects"></ul>
<button class="emailbtn" id="emailBtn">
<svg viewBox="0 0 20 20" width="15" height="15" aria-hidden="true"><path d="M2.5 5h15v10h-15z" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M2.5 5l7.5 5.5L17.5 5" fill="none" stroke="currentColor" stroke-width="1.4"/></svg>
<span id="emailLabel"></span>
</button>
</div>
</aside>
</div>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>A calm, print-inspired team page for the fictional Marlowe & Fen interior studio. The masthead sets an editorial tone with a Cormorant Garamond title, a short mission line and a discipline filter rendered as thin pill controls. Below it, a responsive grid of designer cards leads with a portrait, then layers name, role, a specialty badge and a two-line bio, each card lifting gently on hover with a hairline that draws the eye down the column.
The filter bar re-flows the roster by discipline — Residential, Commercial, Styling, Lighting — with a live count, and a view toggle collapses the grid into a compact list of rows for skimming. Selecting any card slides in a quiet detail panel from the right holding the designer’s fuller bio, signature projects, years with the studio and a copy-to-clipboard email, dismissible by button, backdrop or the Escape key.
Every control is keyboard-usable with visible focus, the panel traps nothing the user can’t escape, and a small toast confirms copied addresses. The whole page holds AA contrast on its warm paper background and reflows to a single column below 520px.