2121
2222{% with carousel_id='_testimonials_cards_carousel' total=testimonials|length %}
2323{% comment %}
24- Per-state rules generated from the testimonials loop so the rule count
25- scales with the actual data. Each radio's id is unique, so we target it
26- directly instead of using :nth-of-type. Covers: track translation,
27- per-state prev/next nav visibility, active dot highlight, per-state CTA
28- visibility, and focus ring on the active nav button.
24+ Per-state rules emitted from the testimonials loop so the rule count
25+ scales with the data. Each radio's id is unique, so we target it directly
26+ rather than using :nth-of-type.
2927{% endcomment %}
3028< style >
3129 {% for testimonial in testimonials %}
32- /* When this slide's radio is the :checked one, shift the slide track
33- horizontally so this slide lands in view. forloop.counter0 maps
34- slide 1 -> 0%, slide 2 -> -100%, slide 3 -> -200%, and so on. */
30+ /* Shift the track to bring this slide into view (-N00% per zero-indexed slide). */
3531 # {{ carousel_id }}- {{ for loop.counter }}: checked ~ .cards-carousel__track .testimonial-card__list {
3632 transform : translateX (- {{ forloop .counter0 }}00%);
3733 }
38- /* When this slide is active, reveal its matching prev/next nav block
39- inside the card header. All nav blocks are display:none by default
40- (see .testimonial-card__nav in testimonial-card.css). */
34+ /* Reveal this slide's nav block (others are display:none in testimonial-card.css). */
4135 # {{ carousel_id }}- {{ for loop.counter }}: checked ~ .card__header .testimonial-card__nav-- {{ forloop .counter }} {
4236 display : inline-flex;
4337 }
44- /* When this slide is active, bring the matching pagination dot to
45- full opacity. Inactive dots remain at the base dimmed opacity */
38+ /* Highlight the active dot; inactive dots stay dimmed via the base rule. */
4639 # {{ carousel_id }}- {{ forloop .counter }}: checked ~ .testimonial-card__dots .testimonial-card__dot : nth-child ({{ forloop .counter }}) {
4740 opacity : 1 ;
4841 }
49- /* When this slide is active, show its matching Read-more CTA. All
50- CTAs are display:none by default (see .testimonial-card__cta). */
42+ /* Show this slide's CTA (others are display:none). */
5143 # {{ carousel_id }}- {{ forloop .counter }}: checked ~ .testimonial-card__cta-- {{ forloop .counter }} {
5244 display : flex;
5345 }
54- /* When this slide is active, restore visibility on its list-item so
55- its quote-link and user-profile links re-enter the keyboard tab
56- order. Inactive slides stay visibility:hidden via the base rule. */
46+ /* Restore the active slide's visibility so its tab targets re-enter the tab order. */
5747 # {{ carousel_id }}- {{ forloop .counter }}: checked ~ .cards-carousel__track .testimonial-card__list .testimonial-card__list-item : nth-child ({{ forloop .counter }}) {
5848 visibility : visible;
5949 transition-delay : 0s ;
6050 }
61- /* The radios are visually hidden, so when the user keyboard-focuses
62- one (Tab + arrow keys), surface a visible focus ring on the
63- matching prev/next nav wrapper in the card header. */
51+ /* Mirror the hidden radio's focus onto the visible nav wrapper. */
6452 # {{ carousel_id }}- {{ forloop .counter }}: focus-visible ~ .card__header .testimonial-card__nav-- {{ forloop .counter }} {
6553 outline : 2px solid var (--color-stroke-link-accent );
6654 }
6755 {% endfor %}
6856</ style >
6957
7058< section class ="card testimonial-card " id ="{{ carousel_id }} " role ="region " aria-labelledby ="{{ carousel_id }}-heading ">
71- {% comment %}
72- Hidden radios drive carousel state without JS. Sibling selectors on
73- `.testimonial-card__radio:nth-of-type(N):checked` translate the track,
74- highlight the active dot, and reveal the matching prev/next nav block.
75- {% endcomment %}
59+ {% comment %} Hidden radios drive all carousel state via the per-state rules above. {% endcomment %}
7660 {% for testimonial in testimonials %}
7761 < input type ="radio "
7862 name ="{{ carousel_id }}-state "
8670 < div class ="card__header ">
8771 < h2 id ="{{ carousel_id }}-heading " class ="card__title "> {{ heading }}</ h2 >
8872
89- {% comment %}
90- Per-state prev/next: one block per testimonial; CSS shows only the
91- block matching the currently-checked radio. Wraps cyclically.
92- {% endcomment %}
73+ {% comment %} One nav block per slide; prev/next wrap cyclically (first ↔ last). {% endcomment %}
9374 {% for testimonial in testimonials %}
9475 < div class ="carousel-buttons testimonial-card__nav testimonial-card__nav--{{ forloop.counter }} " role ="group " aria-label ="Carousel navigation ">
9576 {% if forloop.first %}
@@ -110,7 +91,7 @@ <h2 id="{{ carousel_id }}-heading" class="card__title">{{ heading }}</h2>
11091 {% endfor %}
11192 </ div >
11293
113- < hr class ="card__hr " aria-hidden ="True " />
94+ < hr class ="card__hr " aria-hidden ="true " />
11495
11596 {% if total > 1 %}
11697 < div class ="testimonial-card__dots " aria-label ="Testimonial pagination ">
@@ -146,13 +127,9 @@ <h2 id="{{ carousel_id }}-heading" class="card__title">{{ heading }}</h2>
146127 </ section >
147128 </ div>
148129
149- < hr class ="card__hr " aria-hidden ="True " />
130+ < hr class ="card__hr " aria-hidden ="true " />
150131
151- {% comment %}
152- Per-state "Read more" CTA: one button per testimonial, sits below the
153- divider at the bottom of the card. CSS shows only the one matching the
154- active radio. Targets the same modal slug as the quote-bubble link.
155- {% endcomment %}
132+ {% comment %} One CTA per slide; targets the same modal slug as the quote-bubble link. {% endcomment %}
156133 {% for testimonial in testimonials %}
157134 {% if testimonial.slug %}
158135 < a href ="#{{ testimonial.slug }} "
@@ -164,11 +141,7 @@ <h2 id="{{ carousel_id }}-heading" class="card__title">{{ heading }}</h2>
164141 {% endfor %}
165142</ section>
166143
167- {% comment %}
168- Bundle the matching Content Modals as a sibling of the card. Each
169- testimonial that carries `content` gets a modal rendered here,
170- so clicking its quote bubble opens the modal via :target.
171- {% endcomment %}
144+ {% comment %} Modals rendered as siblings of the card so :target wires up the quote-bubble links. {% endcomment %}
172145{% if testimonials.0.content %}
173146 {% include "v3/includes/_content_modal_group.html" with items=testimonials only %}
174147{% endif %}
0 commit comments