Refine team imagery UX: keep headshots only in roster, add accessible bio toggle cards, and document updates

This commit is contained in:
gator 2026-03-11 01:46:29 +00:00
parent ea0ca8ae6f
commit 780f4f7855
4 changed files with 147 additions and 61 deletions

View file

@ -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 persons 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.

View file

@ -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; }

View file

@ -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';

View file

@ -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>