Section 3: Real Business Sections & Components
The four components – testimonial, logo wall, pricing table and FAQ – together, form the complete trust and conversion layer of a professional business website.
Every business website needs to answer the same core questions a potential client is asking: “Can I trust these people? What exactly do I get? What does it cost? And what if I have questions?” These four components answer those questions — in that order.
Testimonials provide social proof from real clients. The Logo Wall signals credibility through brand recognition. The Pricing Table sets clear expectations and nudges toward a recommended plan. And the FAQ removes the last objections before a visitor becomes a lead.
These components are built as self-contained sections inside index.html (the homepage). They can also be reused or referenced from services.html and contact.html — which we’ll do in Section 2. Each component is designed so that removing or reordering it requires changing only a few lines of HTML.
The Testimonials Section
This is a collection of client quotes using semantic <blockquote>, styled avatars, and CSS Grid layout
We’ll create a three-column section of client testimonials, each with a quote, star rating, client name, role, and avatar — all using accessible, semantic HTML.
Client quotes are, by definition, quotations from another person. The semantically correct element for an extended quotation attributed to someone is <blockquote>. Inside it, we use a <p> for the quote text and a <footer> with <cite> for the attribution. This structure is announced correctly by screen readers and recognised by search engines as a quotation.
Add this code inside <main> in index.html, after the “Why Choose Us” section:
<!-- index.html — Testimonials section -->
<section class="testimonials" aria-labelledby="testimonials-heading">
<div class="testimonials-inner">
<div class="section-header">
<h2 id="testimonials-heading">What Our Clients Say</h2>
<p>Real results from real businesses we've had the privilege of working with.</p>
</div>
<div class="testimonials-grid">
<!-- Testimonial 1 -->
<article class="testimonial-card">
<div class="testimonial-stars" aria-label="5 out of 5 stars">
<span aria-hidden="true">★★★★★</span>
</div>
<blockquote>
<p>Kmacims completely transformed our online presence. Within two months of launching our new site, our enquiries doubled. The attention to detail and performance was outstanding.</p>
<footer>
<img
src="images/client-sarah.jpg"
alt="Sarah Okonkwo"
class="testimonial-avatar"
width="48"
height="48"
/>
<div>
<cite class="client-name">Sarah Okonkwo</cite>
<span class="client-role">CEO, BrightPath Consulting</span>
</div>
</footer>
</blockquote>
</article>
<!-- Testimonial 2 -->
<article class="testimonial-card">
<div class="testimonial-stars" aria-label="5 out of 5 stars">
<span aria-hidden="true">★★★★★</span>
</div>
<blockquote>
<p>The team delivered a fast, accessible, and beautiful site — on time and within budget. I especially appreciated how they explained every decision. Truly professional.</p>
<footer>
<img
src="images/client-james.jpg"
alt="James Adetunji"
class="testimonial-avatar"
width="48"
height="48"
/>
<div>
<cite class="client-name">James Adetunji</cite>
<span class="client-role">Founder, Nexus Retail Ltd</span>
</div>
</footer>
</blockquote>
</article>
<!-- Testimonial 3 -->
<article class="testimonial-card">
<div class="testimonial-stars" aria-label="5 out of 5 stars">
<span aria-hidden="true">★★★★★</span>
</div>
<blockquote>
<p>We had worked with two other agencies before. Kmacims is in a different league. They built with clean code, no bloated plugins, and the site loads in under a second.</p>
<footer>
<img
src="images/client-amara.jpg"
alt="Amara Nwosu"
class="testimonial-avatar"
width="48"
height="48"
/>
<div>
<cite class="client-name">Amara Nwosu</cite>
<span class="client-role">Director, Meridian Health Clinic</span>
</div>
</footer>
</blockquote>
</article>
</div><!-- /.testimonials-grid -->
</div><!-- /.testimonials-inner -->
</section>
Before writing the CSS, understand why each element was chosen:
<section aria-labelledby=”testimonials-heading”> — The aria-labelledby attribute connects this section to its heading. Screen readers announce the section name when the user navigates by landmark, so they hear “What Our Clients Say, section” rather than just “section”.
<article> — Each testimonial card is a self-contained piece of content. If you extracted one card and placed it elsewhere, it would still make sense. That’s the definition of an <article>.
<blockquote> — The semantic element for a quotation. Using <p> would be technically valid but semantically wrong — a browser or search engine would have no way to know this text is a quote from another person.
<footer> inside <blockquote> — A <blockquote> can legally contain a <footer>. This is the HTML-spec-recommended way to include attribution for a quote. The <cite> element inside it names the source.
Stars with aria-label + aria-hidden — The star characters (★★★★★) are decorative to visual users but meaningless to screen readers. We put the visible stars inside a <span aria-hidden=”true”> so they are ignored, and put the accessible label on the parent div: aria-label=”5 out of 5 stars”. Screen readers announce the label, sighted users see the stars. Both groups get the right information.
The src paths reference images/client-sarah.jpg, etc. Add real client photos to your images/ folder. If you don’t have photos, we handle the CSS fallback in the next step — the avatar will show a coloured circle with initials.
Styling the Testimonials
Add these rules to css/styles.css:
/* Testimonials Section */
.testimonials {
background: var(--bg-color);
padding-block: 5rem;
}
.testimonials-inner {
max-width: var(--max-width);
margin: 0 auto;
padding-inline: 1rem;
}
/* Shared section header — reused by multiple sections */
.section-header {
text-align: center;
margin-bottom: 3rem;
}
.section-header h2 {
font-size: clamp(1.5rem, 3vw, 2rem);
margin-bottom: 0.65rem;
}
.section-header p {
color: #6b7280;
font-size: 1rem;
max-width: 540px;
margin: 0 auto;
}
/* The responsive grid */
.testimonials-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.75rem;
}
/* Individual card */
.testimonial-card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 1.75rem;
display: flex;
flex-direction: column;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.testimonial-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 35px rgba(0,0,0,0.07);
}
/* Star rating */
.testimonial-stars {
font-size: 1.1rem;
color: #f59e0b;
margin-bottom: 1rem;
letter-spacing: 0.1em;
}
/* The quote itself — remove default browser blockquote margin */
blockquote {
margin: 0;
flex: 1;
display: flex;
flex-direction: column;
}
blockquote p {
font-size: 0.95rem;
color: #374151;
line-height: 1.7;
font-style: italic;
flex: 1;
margin-bottom: 1.5rem;
}
/* Author row inside blockquote footer */
blockquote footer {
display: flex;
align-items: center;
gap: 0.75rem;
margin-top: auto;
background: transparent; /* Override the site-footer background */
padding: 0;
color: inherit;
}
/* Client avatar image */
.testimonial-avatar {
width: 48px;
height: 48px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
background: linear-gradient(135deg, var(--primary-color), #0ea5e9);
}
.client-name {
display: block;
font-style: normal;
font-weight: 700;
font-size: 0.9rem;
color: var(--text-color);
}
.client-role {
font-size: 0.78rem;
color: #9ca3af;
}
In the above styles, setting display: flex; flex-direction: column on both .testimonial-card and blockquote, then flex: 1 on blockquote p, ensures the quote text expands to fill available space. This means the author’s footer always aligns to the card’s bottom, regardless of quote length — a professional detail that requires no JavaScript.
Social Proof — Logo Wall
We’ll create a row of client or partner logos arranged in a responsive grid. Clean, minimal, and visually confident — without needing image editing skills.
The testimonials and logo wall deal with social proof, but they serve distinct psychological roles. Testimonials provide narrative credibility — stories and emotions. The Logo Wall provides institutional credibility — recognition signals. Combining them into one section muddles both messages. Keeping them separate lets each section work at full strength. The Logo Wall typically appears above Testimonials on the page, because name recognition (“they worked with Zenith Bank”) is a faster, lower-friction trust signal than reading a quote.
In a real project, you would use SVG logo files (preferred — they scale perfectly) or PNGs with transparent backgrounds. For this tutorial, we use a text-based fallback that renders elegantly without actual image files. The HTML structure is identical whether you use images or text.
Copy and paste the following HTML code directly above the Testimonials section in index.html file.
<!-- Logo Wall section -->
<section class="logo-wall" aria-labelledby="logos-heading">
<div class="logo-wall-inner">
<p class="logo-wall-label" id="logos-heading">
Trusted by forward-thinking businesses
</p>
<ul class="logo-grid" role="list">
<li>
<a href="#" class="logo-link" aria-label="BrightPath Consulting (client)">
<!-- Replace the span with an <img> when you have the logo file -->
<span class="logo-text" aria-hidden="true">BrightPath</span>
</a>
</li>
<li>
<a href="#" class="logo-link" aria-label="Nexus Retail Ltd (client)">
<span class="logo-text" aria-hidden="true">Nexus Retail</span>
</a>
</li>
<li>
<a href="#" class="logo-link" aria-label="Meridian Health Clinic (client)">
<span class="logo-text" aria-hidden="true">Meridian</span>
</a>
</li>
<li>
<a href="#" class="logo-link" aria-label="Verdant Foods (client)">
<span class="logo-text" aria-hidden="true">Verdant Foods</span>
</a>
</li>
<li>
<a href="#" class="logo-link" aria-label="Crestview Capital (client)">
<span class="logo-text" aria-hidden="true">Crestview</span>
</a>
</li>
<li>
<a href="#" class="logo-link" aria-label="Zephyr Tech (client)">
<span class="logo-text" aria-hidden="true">Zephyr Tech</span>
</a>
</li>
</ul>
</div>
</section>
The <ul role=”list”> – Logo items are an unordered list of brands. The role=”list” attribute is added because Safari with VoiceOver removes list semantics when list-style: none is applied via CSS. This attribute explicitly restores the list role for all screen readers.
Each logo wrapped in <a> — Logos typically link to a case study or the client’s website. Even if you don’t have a URL yet, wrapping in an anchor is correct structure. The aria-label provides screen-reader text since the visible text is hidden with aria-hidden.
Switching to real images — When you have SVG or PNG logos, simply replace <span class=”logo-text” aria-hidden=”true”>BrightPath</span> with <img src=”images/logo-brightpath.svg” alt=”BrightPath Consulting” class=”logo-img” /> and update the CSS accordingly.
Styling the Logo Wall
/* Logo Wall Section Styles */
.logo-wall {
background: #f9fafb;
padding-block: 3rem;
border-top: 1px solid #e5e7eb;
border-bottom: 1px solid #e5e7eb;
}
.logo-wall-inner {
max-width: var(--max-width);
margin: 0 auto;
padding-inline: 1rem;
}
.logo-wall-label {
text-align: center;
font-size: 0.78rem;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: #9ca3af;
margin-bottom: 2rem;
}
.logo-grid {
list-style: none;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 1rem;
align-items: center;
}
.logo-link {
display: flex;
align-items: center;
justify-content: center;
padding: 1.25rem 1rem;
border: 1px solid #e5e7eb;
border-radius: 8px;
background: white;
text-decoration: none;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.logo-link:hover {
border-color: var(--primary-color);
box-shadow: 0 4px 15px rgba(37,99,235,0.08);
}
/*
____________
NOTE:
____________
*/
/* Text placeholder — remove when using real logo images */
.logo-text {
font-weight: 700;
font-size: 0.85rem;
letter-spacing: 0.05em;
text-transform: uppercase;
color: #d1d5db;
transition: color 0.2s ease;
}
.logo-link:hover .logo-text {
color: var(--primary-color);
}
/* NOTE:
/* Real image logos — add when using actual SVG/PNG files */
.logo-img {
height: 32px;
width: auto;
max-width: 120px;
filter: grayscale(100%) opacity(0.5);
transition: filter 0.25s ease;
}
.logo-link:hover .logo-img {
filter: grayscale(0%) opacity(1);
}
Take Note of the following:
The filter: grayscale(100%) opacity(0.5) applied to real logo images is a professional standard. It prevents logos from visually competing with each other through colour conflicts, and creates a clean, unified grey tone. On hover, filter: grayscale(0%) restores full colour — a subtle, delightful interaction that costs nothing in performance.
The Pricing Table
We’ll build a three-column Basic / Pro / Enterprise pricing table where the recommended plan is visually elevated — using CSS only.
Pricing tables look professional only when rows align perfectly across cards — the price amount on one card sits at the same vertical position as the price amount on the others, the feature list items align horizontally, and the CTA buttons sit at the same height. This is hard to achieve without JavaScript when card content lengths vary. CSS Grid Subgrid solves this elegantly.
To create a professional pricing table, add this HTML code in the index.html file after the Services section.
<!— The Pricing Table Section -->
<section class="pricing" aria-labelledby="pricing-heading">
<div class="pricing-inner">
<div class="section-header">
<h2 id="pricing-heading">Simple, Transparent Pricing</h2>
<p>No hidden fees. No long-term lock-ins. Choose the plan that fits your business.</p>
</div>
<div class="pricing-grid">
<!-- BASIC PLAN -->
<article class="pricing-card">
<header class="plan-header">
<h3 class="plan-name">Basic</h3>
<p class="plan-tagline">Perfect for getting started online</p>
</header>
<div class="plan-price">
<span class="price-currency">$</span>
<span class="price-amount">399</span>
<span class="price-period">one-time</span>
</div>
<ul class="plan-features" aria-label="Basic plan features">
<li>5-page website</li>
<li>Mobile responsive design</li>
<li>Contact form</li>
<li>Basic SEO setup</li>
<li class="feature-unavailable">E-commerce</li>
<li class="feature-unavailable">Priority support</li>
</ul>
<a href="contact.html" class="plan-cta">Get Started</a>
</article>
<!-- ── PRO PLAN (RECOMMENDED) ── -->
<article class="pricing-card pricing-card--featured">
<header class="plan-header">
<div class="recommended-badge">Most Popular</div>
<h3 class="plan-name">Pro</h3>
<p class="plan-tagline">The complete business website</p>
</header>
<div class="plan-price">
<span class="price-currency">$</span>
<span class="price-amount">799</span>
<span class="price-period">one-time</span>
</div>
<ul class="plan-features" aria-label="Pro plan features">
<li>Up to 10 pages</li>
<li>Mobile responsive design</li>
<li>Advanced contact forms</li>
<li>Full SEO optimisation</li>
<li>Blog / news section</li>
<li class="feature-unavailable">Priority support</li>
</ul>
<a href="contact.html" class="plan-cta plan-cta--primary">Get Started</a>
</article>
<!-- ── ENTERPRISE PLAN ── -->
<article class="pricing-card">
<header class="plan-header">
<h3 class="plan-name">Enterprise</h3>
<p class="plan-tagline">Custom solutions at scale</p>
</header>
<div class="plan-price">
<span class="price-amount">Custom</span>
<span class="price-period">let's talk</span>
</div>
<ul class="plan-features" aria-label="Enterprise plan features">
<li>Unlimited pages</li>
<li>Mobile responsive design</li>
<li>Custom integrations</li>
<li>Advanced SEO strategy</li>
<li>E-commerce</li>
<li>Priority support</li>
</ul>
<a href="contact.html" class="plan-cta">Contact Us</a>
</article>
</div><!-- /.pricing-grid -->
</div><!-- /.pricing-inner -->
</section>
The parent .pricing-grid defines the row tracks. Each .pricing-card spans all rows and opts into the parent’s row tracks with grid-row: subgrid. Every direct child of the card then automatically lands on the same parent row track as its counterpart in neighbouring cards — perfect alignment with pure CSS.
pricing-card–featured — Using a BEM modifier class (double-dash) on the Pro card cleanly separates “featured” state from base styling. The modifier adds its own styles on top without duplicating the base card rules.
<header> inside <article> — Each pricing card is a self-contained article with its own header. This is semantically correct and creates clear structure inside the card for both the subgrid alignment and for assistive technologies.
feature-unavailable — Unavailable features use a class rather than being removed. A comparison table where cards have different numbers of rows breaks alignment. By including every feature on every card (some styled as unavailable), rows stay aligned across columns.
Styling the Pricing Table with Subgrid
/* Pricing Table Section Styles */
.pricing {
background: #f9fafb;
padding-block: 5rem;
}
.pricing-inner {
max-width: var(--max-width);
margin: 0 auto;
padding-inline: 1rem;
}
/* Parent grid — 3 equal columns.
Defines 4 named row tracks that cards will subgrid onto:
[header] [price] [features] [cta] */
.pricing-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto auto 1fr auto;
gap: 0 1.5rem;
align-items: start;
}
/* Each card spans all 4 row tracks and subgrids into them */
.pricing-card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 2rem 1.75rem;
grid-row: 1 / -1; /* Span all rows */
display: grid;
grid-template-rows: subgrid; /* Inherit parent row tracks */
gap: 0;
transition: box-shadow 0.2s ease;
}
.pricing-card:hover {
box-shadow: 0 8px 30px rgba(0,0,0,0.07);
}
/* Featured / recommended card */
.pricing-card--featured {
border-color: var(--primary-color);
border-width: 2px;
box-shadow: 0 8px 30px rgba(37,99,235,0.1);
position: relative;
}
/* "Most Popular" badge — positioned above the card */
.recommended-badge {
position: absolute;
top: -14px;
left: 50%;
transform: translateX(-50%);
background: var(--primary-color);
color: white;
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
padding: 0.25rem 0.9rem;
border-radius: 999px;
white-space: nowrap;
}
/* Plan header row */
.plan-header {
margin-bottom: 1.5rem;
padding-top: 0.25rem; /* Breathing room below the badge */
}
.plan-name {
font-size: 1.25rem;
font-weight: 800;
color: var(--text-color);
margin-bottom: 0.25rem;
}
.plan-tagline {
font-size: 0.85rem;
color: #6b7280;
}
/* Price row */
.plan-price {
display: flex;
align-items: baseline;
gap: 0.25rem;
margin-bottom: 1.75rem;
}
.price-currency {
font-size: 1.25rem;
font-weight: 700;
color: var(--text-color);
}
.price-amount {
font-size: 2.5rem;
font-weight: 800;
line-height: 1;
color: var(--text-color);
}
.price-period {
font-size: 0.8rem;
color: #9ca3af;
align-self: flex-end;
padding-bottom: 0.35rem;
}
/* Features list row */
.plan-features {
list-style: none;
margin-bottom: 2rem;
}
.plan-features li {
font-size: 0.9rem;
color: #374151;
padding: 0.55rem 0;
border-bottom: 1px solid #f3f4f6;
display: flex;
align-items: center;
gap: 0.6rem;
}
.plan-features li::before {
content: "✓";
color: #22c55e;
font-weight: 700;
font-size: 0.85rem;
flex-shrink: 0;
}
/* Unavailable features */
.feature-unavailable {
color: #d1d5db !important;
text-decoration: line-through;
}
.feature-unavailable::before {
content: "✕" !important;
color: #d1d5db !important;
}
/* CTA button row */
.plan-cta {
display: block;
text-align: center;
padding: 0.8rem 1.5rem;
border-radius: 8px;
font-weight: 600;
font-size: 0.9rem;
text-decoration: none;
border: 2px solid var(--primary-color);
color: var(--primary-color);
background: transparent;
transition: background 0.2s ease, color 0.2s ease;
align-self: end;
}
.plan-cta:hover {
background: var(--primary-color);
color: white;
}
/* Primary CTA (featured card) — filled by default */
.plan-cta--primary {
background: var(--primary-color);
color: white;
}
.plan-cta--primary:hover {
background: #1d4ed8;
border-color: #1d4ed8;
}
/* Responsive: stack on mobile */
@media (max-width: 640px) {
.pricing-grid {
grid-template-columns: 1fr;
grid-template-rows: auto;
gap: 1.5rem;
}
.pricing-card {
grid-row: auto;
display: block;
}
}
CSS Subgrid (grid-template-rows: subgrid) is supported in all modern browsers as of 2023 — Chrome 117+, Firefox 71+, Safari 16+. For older browsers, the mobile stack fallback (display: block) kicks in via the @media query. The pricing table degrades gracefully without subgrid — cards simply won’t have row-aligned content on very old browsers, but the content remains fully readable.
The FAQ Section
This section builds an expandable FAQ accordion where each question/answer pair opens and closes on click — using only native HTML elements. No JavaScript. No ARIA hacks required.
A decade ago, accordion FAQs required JavaScript event listeners, ARIA aria-expanded attributes, and careful keyboard management. Today, the <details> element does all of this natively — at zero cost in code or performance.
The <details> element is a disclosure widget: content inside it is hidden by default and revealed when the element is in the open state. The <summary> element is its visible, clickable heading. The browser handles toggling, keyboard interaction (Enter and Space activate it), and focus management automatically. Screen readers announce it as an expandable button. This is the correct, native, lowest-cost implementation.
Search engines, including Google, now index content inside <details> elements. FAQ content structured with <details> is also a strong candidate for FAQ rich results in Google Search — provided you add the FAQ Schema.org structured data markup. The semantic foundation is correct from day one.
Add this code into the main section in index.html before the footer section.
<!-- FAQ section HTML -->
<section class="faq" aria-labelledby="faq-heading">
<div class="faq-inner">
<div class="section-header">
<h2 id="faq-heading">Frequently Asked Questions</h2>
<p>Answers to the most common questions about working with us.</p>
</div>
<div class="faq-list">
<details class="faq-item">
<summary class="faq-question">
How long does it take to build a website?
</summary>
<div class="faq-answer">
<p>Most projects are completed within 3–4 weeks from the point of receiving your content and sign-off on the design direction. Larger enterprise projects may take 6–8 weeks. We provide a clear project timeline at the start of every engagement.</p>
</div>
</details>
<details class="faq-item">
<summary class="faq-question">
Do I need to provide the written content?
</summary>
<div class="faq-answer">
<p>We recommend that clients provide their own copy, as you know your business best. However, we offer copywriting as an add-on service and can work with your existing brochures, social content, or talking points to produce polished, SEO-ready text.</p>
</div>
</details>
<details class="faq-item">
<summary class="faq-question">
Will my website work on mobile phones and tablets?
</summary>
<div class="faq-answer">
<p>Absolutely. Every website we build is fully responsive by default — it adapts its layout for any screen size, from a small smartphone to a large desktop monitor. We test across iOS Safari, Android Chrome, and all major desktop browsers before delivery.</p>
</div>
</details>
<details class="faq-item">
<summary class="faq-question">
Can I update the website myself after it's built?
</summary>
<div class="faq-answer">
<p>Yes. For clients who prefer self-management, we can integrate a headless CMS so you can update text, images, and blog posts without touching code. We also offer an affordable monthly maintenance plan if you'd prefer to leave updates to us.</p>
</div>
</details>
<details class="faq-item">
<summary class="faq-question">
What do you need from me to get started?
</summary>
<div class="faq-answer">
<p>To begin, we need a completed brief (we provide a simple questionnaire), your brand assets (logo files, colours, preferred fonts if you have them), and a 50% deposit. From there, we handle everything — sitemap, wireframes, design, build, and launch.</p>
</div>
</details>
</div><!-- /.faq-list -->
</div><!-- /.faq-inner -->
</section>
No open attribute on any <details> — By default, <details> elements are closed. Add open (e.g. <details class=”faq-item” open>) to any item you want pre-expanded on page load — typically the first FAQ, as a visual hint that these items are interactive.
The <div class=”faq-answer”> wrapper — We wrap the answer content in a div rather than putting it directly inside <details>. This gives us a reliable CSS target for padding and animation. Styling directly on <details> or its text nodes is inconsistent across browsers.
Paragraph tags inside the answer — Always use <p> tags inside .faq-answer. This ensures correct spacing if you ever have multi-paragraph answers, and maintains semantic structure for screen readers.
Styling the FAQ
/* FAQ Section */
.faq {
background: var(--bg-color);
padding-block: 5rem;
}
.faq-inner {
max-width: 720px; /* Narrower than the max-width — better reading width */
margin: 0 auto;
padding-inline: 1rem;
}
.faq-list {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
/* Each Q&A pair */
.faq-item {
border: 1px solid #e5e7eb;
border-radius: 10px;
overflow: hidden;
transition: border-color 0.2s ease;
}
.faq-item[open] {
border-color: var(--primary-color);
}
/* The clickable question bar */
.faq-question {
padding: 1.1rem 1.5rem;
cursor: pointer;
font-weight: 600;
font-size: 0.97rem;
color: var(--text-color);
list-style: none; /* Remove default triangle in Firefox */
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
background: white;
transition: color 0.2s ease, background 0.2s ease;
user-select: none;
}
/* Remove the default disclosure triangle in WebKit/Blink */
.faq-question::-webkit-details-marker {
display: none;
}
.faq-question:hover {
color: var(--primary-color);
background: #f9fafb;
}
/* The +/− icon — created with CSS, no extra HTML element */
.faq-question::after {
content: "+";
font-size: 1.4rem;
font-weight: 300;
color: var(--primary-color);
flex-shrink: 0;
line-height: 1;
transition: transform 0.25s ease;
}
/* When open: change + to − */
.faq-item[open] .faq-question::after {
content: "−";
}
/* Question turns blue when item is open */
.faq-item[open] .faq-question {
color: var(--primary-color);
border-bottom: 1px solid #e5e7eb;
}
/* The answer panel */
.faq-answer {
padding: 1.25rem 1.5rem;
background: #f9fafb;
}
.faq-answer p {
font-size: 0.93rem;
color: #4b5563;
line-height: 1.7;
margin: 0;
}
.faq-answer p + p {
margin-top: 0.75rem;
}
The native <details> element does not support CSS height or max-height transitions cleanly — the browser removes the element from the layout instantly on close, cutting off any animation.

