Refine team imagery UX: keep headshots only in roster, add accessible bio toggle cards, and document updates
This commit is contained in:
parent
ea0ca8ae6f
commit
780f4f7855
4 changed files with 147 additions and 61 deletions
92
PROJECT.md
92
PROJECT.md
|
|
@ -4,73 +4,57 @@
|
||||||
- Stack: Node/Express + EJS templates + global CSS/JS.
|
- Stack: Node/Express + EJS templates + global CSS/JS.
|
||||||
- Brand/entity: **AutoTQ** / Golden Hour Medical, Inc.
|
- Brand/entity: **AutoTQ** / Golden Hour Medical, Inc.
|
||||||
- Content source remains `site.config.js` for factual data (team, literature, testimonials, news, contact).
|
- Content source remains `site.config.js` for factual data (team, literature, testimonials, news, contact).
|
||||||
- This update focused on a stronger visual hierarchy, mixed section layouts, and reduced repetitive card patterns.
|
- This revision focused on UX/content-structure consistency for people imagery and team bio presentation.
|
||||||
|
|
||||||
## 2) Updated file structure notes (files changed in this pass)
|
## 2) Updated file structure notes (files changed in this pass)
|
||||||
- `views/layout.ejs`
|
|
||||||
- `views/index.ejs`
|
|
||||||
- `views/about-autotq.ejs`
|
|
||||||
- `views/company.ejs`
|
- `views/company.ejs`
|
||||||
- `views/research.ejs`
|
|
||||||
- `views/literature.ejs`
|
|
||||||
- `views/testimonials.ejs`
|
|
||||||
- `views/news.ejs`
|
|
||||||
- `public/css/style.css`
|
- `public/css/style.css`
|
||||||
|
- `public/js/main.js`
|
||||||
- `PROJECT.md`
|
- `PROJECT.md`
|
||||||
|
|
||||||
## 3) Navigation/routes
|
## 3) Navigation/routes
|
||||||
- Primary nav: `/`, `/about-autotq`, `/company`, `/research`, `/literature`, `/news`, `/testimonials`, `/contact`.
|
- Primary nav remains: `/`, `/about-autotq`, `/company`, `/research`, `/literature`, `/news`, `/testimonials`, `/contact`.
|
||||||
- **Removed Company Gallery references** from page structure and nav rendering behavior.
|
- Team profile links from the Company roster continue to use slug routes (e.g., `/<member.slug>`).
|
||||||
|
|
||||||
## 4) Design system (refresh)
|
## 4) Design system notes (this revision)
|
||||||
- Updated primary red toward requested tone: `--brand-red: #d12020`.
|
- Reinforced visual logic: profile/headshot treatment is now isolated to the team roster cards.
|
||||||
- Complementary palette introduced with dark neutrals for contrast bands:
|
- Narrative sections (Company mission and Operating mission) continue using neutral/non-profile supporting media (`company4`, `company5`).
|
||||||
- `--dark: #111315`
|
- Added dedicated team-roster card styles and a clear CTA hierarchy for bio reveal (`Read bio` button + collapsible panel).
|
||||||
- `--dark-soft: #1e2124`
|
|
||||||
- white/light-gray surfaces for cleaner reading sections.
|
|
||||||
- Larger red/dark surface usage in hero, strip bands, and CTA moments while keeping body sections clean.
|
|
||||||
|
|
||||||
## 5) Component patterns now used
|
## 5) Component patterns now used
|
||||||
- Alternating split sections (`.split`, `.split-reverse`) for left/right rhythm.
|
- Existing split sections and capability cards retained for company narrative blocks.
|
||||||
- Media-first blocks (`.media-band`, `.media-stack`, `.video-grid`).
|
- New team-specific component set:
|
||||||
- Quote strip and quote row formats (`.quote-strip`, `.quote-row`) replacing repetitive equal cards.
|
- `.team-roster` (2-column responsive grid)
|
||||||
- Context list and research/doc rows (`.context-list`, `.research-item`, `.doc-row`).
|
- `.team-person-card` (headshot + person details)
|
||||||
- News rows with left accent instead of repeated large cards.
|
- `.btn-team-bio` (bio reveal control)
|
||||||
|
- `.team-bio-panel` (collapsible bio region)
|
||||||
|
- Bio reveal behavior is managed by progressive JS and keeps native button keyboard behavior.
|
||||||
|
|
||||||
## 6) Content/layout updates by page
|
## 6) Content/layout updates by page
|
||||||
- **Home (`index.ejs`)**: kept mixed-layout structure; replaced research-adjacent image with product visual and tightened internal anchor linking.
|
- **Company (`company.ejs`)**
|
||||||
- **About (`about-autotq.ejs`)**: redesigned with high-contrast statistic showcase (`2`, `92%`, `100%`) and alternating split sections.
|
- Kept non-team sections free of employee portraits in mission/operating mission blocks.
|
||||||
- **Company (`company.ejs`)**: moved away from headshot-heavy cards to capability cards + clean people list rows.
|
- Reworked “Leadership and specialists” into a true roster with each person’s headshot, name, role, and a `Read bio` button.
|
||||||
- **Research (`research.ejs`)**: added `#sources` anchor and expanded source-adjacent internal CTA links.
|
- Added collapsible bio panel per person instead of displaying long bios inline by default.
|
||||||
- **News (`news.ejs`)**: added `#press-links` anchor and split CTA band to drive research/literature discovery.
|
- **Audit pass completed (no edits required):**
|
||||||
- **Literature (`literature.ejs`)**: improved heading hierarchy with section-level H2 and document-level H3 rows; added implementation CTA split section.
|
- `views/literature.ejs`
|
||||||
- **Testimonials (`testimonials.ejs`)**: kept quote-row format and added balanced contextual section with supporting links.
|
- `views/testimonials.ejs`
|
||||||
|
- `views/about-autotq.ejs`
|
||||||
|
- `views/research.ejs`
|
||||||
|
- `views/index.ejs`
|
||||||
|
- These pages were verified to use non-employee support visuals in narrative sections.
|
||||||
|
|
||||||
## 7) Media inventory used in redesign
|
## 7) JS behavior updates
|
||||||
Reused existing configured assets (from `config.assets.images`) across pages:
|
- `public/js/main.js` now includes a scoped team bio accordion behavior:
|
||||||
- `hero`, `product`
|
- Uses `.team-bio-toggle` buttons with `aria-expanded` + `aria-controls`.
|
||||||
- `company1`–`company7`
|
- Toggles `hidden` state on associated `.team-bio-panel`.
|
||||||
- no new external assets introduced in this pass
|
- Keeps one bio open at a time within the company roster for cleaner scanning.
|
||||||
|
- Button labels switch between **Read bio** / **Hide bio**.
|
||||||
|
|
||||||
Added provided YouTube embeds:
|
## 8) Accessibility/UX notes
|
||||||
- `z7VjjfdjIhU`
|
- Team bio interaction is button-based and keyboard accessible by default.
|
||||||
- `l2ocd5el0Yc`
|
- ARIA state and controlled-region linkage are implemented per card.
|
||||||
- `4PnhBm5WIg0`
|
- Visual hierarchy now clearly separates abstract/company claims from individual people content.
|
||||||
- `rI2n9TlMYIU`
|
|
||||||
|
|
||||||
## 8) SEO and UX pass (this revision)
|
|
||||||
- Added global per-page metadata defaults in `views/layout.ejs`:
|
|
||||||
- unique `<title>` + meta description mapping by `pageName`
|
|
||||||
- canonical URLs
|
|
||||||
- Open Graph + Twitter card defaults
|
|
||||||
- Improved internal linking and anchors:
|
|
||||||
- Home evidence CTA links to `/research#sources`
|
|
||||||
- News press list has `#press-links`
|
|
||||||
- Research source section has `id="sources"`
|
|
||||||
- Replaced homepage research-adjacent visual with product imagery (`config.assets.images.product`) to avoid profile-style mismatch.
|
|
||||||
- Updated logo presentation in header/footer via transparent styling (removed white box treatment).
|
|
||||||
- Added shared UI consistency styles for new patterns: `.stats-showcase`, `.capability-grid`, `.people-list`, `.person-row`.
|
|
||||||
|
|
||||||
## 9) Known TODOs
|
## 9) Known TODOs
|
||||||
- If route-level rendering does not pass expected `pageName` values on some pages, map those names in server routes so metadata mapping applies exactly.
|
- Optional next pass: animate panel expansion/collapse while preserving reduced-motion preferences.
|
||||||
- Optional next pass: expand structured data (`JSON-LD`) for organization and article/news items.
|
- Optional next pass: consolidate legacy unused classes (`.people-list`, `.person-row`, `.team-grid`, `.team-card`) if no longer referenced elsewhere.
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,54 @@ p { margin: 0 0 1rem; color: var(--text); }
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: .9rem 1rem;
|
padding: .9rem 1rem;
|
||||||
}
|
}
|
||||||
|
.team-roster {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.team-person-card {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 150px 1fr;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: start;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.team-person-card img {
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.team-person-content {
|
||||||
|
display: grid;
|
||||||
|
gap: .6rem;
|
||||||
|
}
|
||||||
|
.team-role {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--muted);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.btn-team-bio {
|
||||||
|
width: fit-content;
|
||||||
|
background: #fff;
|
||||||
|
color: var(--brand-red);
|
||||||
|
border-color: #f1cdcd;
|
||||||
|
}
|
||||||
|
.btn-team-bio:hover {
|
||||||
|
background: #fff5f5;
|
||||||
|
}
|
||||||
|
.team-bio-panel {
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
padding-top: .75rem;
|
||||||
|
}
|
||||||
|
.team-bio-panel p {
|
||||||
|
margin-bottom: .65rem;
|
||||||
|
}
|
||||||
.doc-row h3 { margin-bottom: .3rem; }
|
.doc-row h3 { margin-bottom: .3rem; }
|
||||||
.brand-footer img { filter: none; }
|
.brand-footer img { filter: none; }
|
||||||
.quote-row {
|
.quote-row {
|
||||||
|
|
@ -330,7 +378,7 @@ select:focus-visible {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 980px) {
|
@media (max-width: 980px) {
|
||||||
.hero-grid, .split, .video-grid, .news-testimonials, .footer-grid, .form-grid, .team-grid, .team-card, .quote-row, .stats-showcase, .capability-grid { grid-template-columns: 1fr; }
|
.hero-grid, .split, .video-grid, .news-testimonials, .footer-grid, .form-grid, .team-grid, .team-card, .quote-row, .stats-showcase, .capability-grid, .team-roster, .team-person-card { grid-template-columns: 1fr; }
|
||||||
.person-row { flex-direction: column; }
|
.person-row { flex-direction: column; }
|
||||||
.split-reverse .split-copy,
|
.split-reverse .split-copy,
|
||||||
.split-reverse .split-media { order: initial; }
|
.split-reverse .split-media { order: initial; }
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,44 @@
|
||||||
reveals.forEach((el) => el.classList.add('is-visible'));
|
reveals.forEach((el) => el.classList.add('is-visible'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const teamBioToggles = document.querySelectorAll('.team-bio-toggle');
|
||||||
|
if (teamBioToggles.length) {
|
||||||
|
const closeBioPanel = (button) => {
|
||||||
|
const panelId = button.getAttribute('aria-controls');
|
||||||
|
const panel = panelId ? document.getElementById(panelId) : null;
|
||||||
|
if (!panel) return;
|
||||||
|
|
||||||
|
button.setAttribute('aria-expanded', 'false');
|
||||||
|
button.textContent = 'Read bio';
|
||||||
|
panel.hidden = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
teamBioToggles.forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const panelId = button.getAttribute('aria-controls');
|
||||||
|
const panel = panelId ? document.getElementById(panelId) : null;
|
||||||
|
if (!panel) return;
|
||||||
|
|
||||||
|
const isExpanded = button.getAttribute('aria-expanded') === 'true';
|
||||||
|
const roster = button.closest('[data-team-roster]');
|
||||||
|
|
||||||
|
if (roster) {
|
||||||
|
roster.querySelectorAll('.team-bio-toggle[aria-expanded="true"]').forEach((openBtn) => {
|
||||||
|
if (openBtn !== button) closeBioPanel(openBtn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isExpanded) {
|
||||||
|
closeBioPanel(button);
|
||||||
|
} else {
|
||||||
|
button.setAttribute('aria-expanded', 'true');
|
||||||
|
button.textContent = 'Hide bio';
|
||||||
|
panel.hidden = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const contactForm = document.getElementById('contactForm');
|
const contactForm = document.getElementById('contactForm');
|
||||||
const status = document.getElementById('formStatus');
|
const status = document.getElementById('formStatus');
|
||||||
const endpoint = 'https://api.corben.world/forms/af90392e-9399-4778-9b80-9eed83580f1d/submit';
|
const endpoint = 'https://api.corben.world/forms/af90392e-9399-4778-9b80-9eed83580f1d/submit';
|
||||||
|
|
|
||||||
|
|
@ -44,14 +44,30 @@
|
||||||
<section class="section section-alt">
|
<section class="section section-alt">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Leadership and specialists</h2>
|
<h2>Leadership and specialists</h2>
|
||||||
<div class="people-list">
|
<div class="team-roster" data-team-roster>
|
||||||
<% (config.team || []).forEach(member => { %>
|
<% (config.team || []).forEach((member, index) => {
|
||||||
<article class="person-row reveal" data-reveal>
|
const bioId = `team-bio-${index}`;
|
||||||
<div>
|
const imageSrc = config?.assets?.images?.[member.image];
|
||||||
|
%>
|
||||||
|
<article class="team-person-card reveal" data-reveal>
|
||||||
|
<% if (imageSrc) { %>
|
||||||
|
<img src="<%= imageSrc %>" alt="<%= member.name %> headshot" loading="lazy" />
|
||||||
|
<% } %>
|
||||||
|
<div class="team-person-content">
|
||||||
<h3><%= member.name %></h3>
|
<h3><%= member.name %></h3>
|
||||||
<p><%= member.role %></p>
|
<p class="team-role"><%= member.role %></p>
|
||||||
|
<button
|
||||||
|
class="btn btn-team-bio team-bio-toggle"
|
||||||
|
type="button"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="<%= bioId %>">
|
||||||
|
Read bio
|
||||||
|
</button>
|
||||||
|
<div class="team-bio-panel" id="<%= bioId %>" hidden>
|
||||||
|
<p><%= member.bio %></p>
|
||||||
|
<a class="text-link" href="/<%= member.slug %>">View full profile →</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="text-link" href="/<%= member.slug %>">View profile →</a>
|
|
||||||
</article>
|
</article>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue