============================================================ */
/* --- Price block: force save amount onto its own line --- */
.price__badge-sale,
.price-item--sale ~ .price__save,
.price__save {
display: block;
width: 100%;
}
/* --- Price meta: shipping policy / tax notes smaller --- */
.price__shipping-policy-text,
.product__tax-note,
.price__taxes-note {
font-size: 0.75em !important;
opacity: 0.6;
}
/* --- Footer: column heading styles --- */
.footer__heading,
.footer__title,
.footer-block__heading {
color: #f16558 !important;
font-size: 1.6rem !important;
font-weight: 900 !important;
text-transform: uppercase;
letter-spacing: 0.08em;
text-align: center;
}
/* --- Footer: column content centre-aligned --- */
.site-footer .footer__collapsible,
.site-footer .footer__collapsible li,
.site-footer .footer__collapsible a,
.site-footer .footer__collapsible p,
.site-footer .footer__collapsible address {
text-align: center !important;
}
/* --- Footer: back to top button --- */
.back-to-top {
text-align: center;
margin-top: 20px;
padding-bottom: 10px;
}
/* --- Utility buttons: on-brand pill outline style ---
Back to top · Back to collection · Back to blog · View all (header + end-of-grid)
Matches Rainger CTA system: coral border, transparent bg, fills on hover. --- */
.back-to-top .btn,
.return-link,
.section-header__link,
.grid__item.text-center > .btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 38px;
padding: 0 22px;
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
border-radius: 9999px;
border: 1.5px solid #f16558;
background: transparent;
color: #f16558;
text-decoration: none;
cursor: pointer;
transition: background 0.15s, color 0.15s;
box-sizing: border-box;
white-space: nowrap;
}
.back-to-top .btn:hover,
.return-link:hover,
.section-header__link:hover,
.grid__item.text-center > .btn:hover {
background: #f16558;
color: #ffffff;
text-decoration: none;
}
/* --- Mobile: View all at end of grid is full-width (acts as section divider) --- */
@media (max-width: 768px) {
.grid__item.text-center > .btn {
display: flex;
width: 100%;
}
}
/* --- Overflow carousel: prevent flex-wrap from breaking Impulse's horizontal scroll carousel.
Scoped to mobile only — desktop must wrap normally for multi-row grid layouts.
Without this scope, per_row=4 + rows=2 sections with mobile_scrollable:true render
all 8 items in a single non-wrapping desktop row (skinny cards). --- */
@media (max-width: 768px) {
.grid-overflow-wrapper .grid.grid--uniform {
flex-wrap: nowrap;
}
}
/* --- PDP: price block — column layout, each element on its own line ---
DOM order: compare-at → current price → savings → tax note.
We reorder visually via flex order so current price leads. --- */
.product-block--price {
display: flex;
flex-direction: column;
gap: 3px;
}
/* 1. Current price row — dominant anchor.
font-weight: 700 (not 800) so the large size reads as confident without being harsh.
color: var(--colorPrice) aligns with the theme's configured price colour. --- */
.rs-price-row {
order: 1;
display: block;
}
.rs-price-row .product__price {
font-size: 1.75em;
font-weight: 700;
line-height: 1.15;
color: var(--colorPrice);
}
/* 2. Compare-at line — "RRP: $X", quieter, no strikethrough needed with label */
[data-product-price-wrap] {
order: 2;
display: block;
}
.product__price--compare {
display: block;
font-size: 0.82em !important;
color: #aaa !important;
text-decoration: none !important;
font-weight: 400 !important;
line-height: 1.3;
}
.product__price--compare::before {
content: "RRP: ";
font-weight: 600;
font-style: normal;
}
/* 3. Savings line — secondary coral row */
[data-save-price] {
order: 3;
display: block;
font-size: 0.82em;
font-weight: 700;
color: #f16558;
line-height: 1.3;
}
/* 4. Tax / shipping note — market-safe (only outputs if shop.taxes_included or policy exists)
Already rendered via Shopify Liquid conditionals in product-template.liquid — no hardcoded text. */
.product-block--price .product__policies {
order: 4;
font-size: 0.75em;
opacity: 0.6;
margin-top: 2px;
line-height: 1.4;
}
/* --- PDP: SKU — deliberate "SKU: value" label treatment --- */
.product-single__sku {
font-size: 0.82em;
color: #888;
margin-top: 2px;
margin-bottom: 4px;
}
.product-single__sku:not(:empty)::before {
content: "SKU: ";
font-weight: 700;
color: #666;
}
/* --- PDP: store pickup availability — fully centred, deliberate line stacking ---
Layout: column flex so icon sits above the text block, both centred.
Text: centre-aligned throughout.
Line order rendered by Impulse's sections/store-availability.liquid:
→ "Pickup available at Store Name"
→ pick_up_time (e.g. "Usually ready in 1-2 days")
→ link (e.g. "View store info")
splits "Pickup available at" and "Store Name" onto
separate lines without touching the Liquid or Shopify-managed JS. --- */
.store-availability {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
text-align: center !important;
padding: 14px 0 10px;
border-top: 1px solid #e9e9e9;
margin-top: 14px;
}
.store-availability + .store-availability {
border-top: none;
margin-top: 0;
padding-top: 0;
}
/* Icon above text — give it a small bottom gap */
.store-availability .icon {
flex-shrink: 0;
margin-bottom: 8px;
margin-left: 0 !important;
}
.store-availability__info {
flex: 0 1 auto;
margin-left: 0 !important;
text-align: center !important;
}
/* Each child line: block, uniform font size, deliberate gap */
.store-availability__info > div,
.store-availability__info > p {
display: block;
font-size: 0.875em;
line-height: 1.45;
margin-bottom: 4px;
}
.store-availability__info > div:last-child,
.store-availability__info > p:last-child {
margin-bottom: 0;
}
/* Store name inside translation string: force onto its own line */
.store-availability__info > div strong {
display: block;
font-weight: 600;
margin-top: 2px;
}
.store-availability__info a {
color: #f16558;
text-decoration: underline;
font-size: 0.875em;
}
/* --- PDP: Product Description heading --- */
.rs-description-heading {
font-size: 1.15rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 0.08em;
margin-top: 16px;
margin-bottom: 10px;
color: inherit;
}
/* --- PDP: tax/shipping policy split lines ---
Each policy item on its own line (block), not inline text run-on. */
.product__policy-item {
display: block;
line-height: 1.5;
}
/* --- Featured collection: heading as link --- */
.rs-heading-link {
text-decoration: none;
color: inherit;
}
.rs-heading-link:hover {
color: #f16558;
}
/* --- Featured collection: mobile View all (only shows on ≤768px, outside carousel) --- */
.rs-mobile-view-all {
display: none;
padding: 12px 0 4px;
}
@media (max-width: 768px) {
.rs-mobile-view-all {
display: block;
}
}
/* --- Footer: mobile — keep all columns expanded, hide accordion trigger --- */
@media (max-width: 768px) {
.footer__heading,
.footer__title,
.footer-block__heading {
font-size: 1.15rem !important;
}
footer .collapsible-content--small {
height: auto !important;
opacity: 1 !important;
overflow: visible !important;
visibility: visible !important;
}
footer .collapsible-content--small .collapsible-content__inner {
transform: translateY(0) !important;
}
footer .collapsible-trigger-btn {
pointer-events: none !important;
cursor: default !important;
}
footer .collapsible-trigger__icon {
display: none !important;
}
}
/* --- Collection grid: override float layout with flex so rows equalise card heights ---
The Impulse grid uses float:left on .grid__item (theme.css:2689).
Floated elements never stretch to match their neighbours, so margin-top:auto
could not produce row-level alignment. Switching to flex here replaces the
float behaviour; align-items:stretch (flex default) makes every card in a
visual row the same height. Width fraction classes (medium-up--one-quarter
etc.) continue to work unchanged as flex children. --- */
.grid.grid--uniform {
display: flex;
flex-wrap: wrap;
}
/* --- Collection card: flex column + full-chain bottom anchor ---
Title grows to fill available height; price / rating / selector / CTA
form a consistent bottom stack that aligns across every card in a row.
Chain (with corrected nesting):
card → content → image-wrapper (flex col) → image-mask (natural) +
link (flex:1) → meta (flex:1) → title (flex:1) → price → rating → CTA.
NOTE: .grid-product__link is nested inside .grid__item-image-wrapper (block),
NOT a direct child of .grid-product__content. Without making image-wrapper a
flex container, flex:1 on the link has no effect — this was the previous failure. --- */
.grid-product.grid__item {
display: flex;
flex-direction: column;
}
.grid-product.grid__item .grid-product__content {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
/* image-wrapper is the missing flex node — must be flex col for link to grow */
.grid-product.grid__item .grid__item-image-wrapper {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
/* image-mask holds the aspect-ratio image — must not grow */
.grid-product.grid__item .grid-product__image-mask {
flex: 0 0 auto;
}
.grid-product.grid__item .grid-product__link {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.grid-product.grid__item .grid-product__meta {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.grid-product.grid__item .grid-product__title {
flex: 1 1 auto;
}
.grid-product.grid__item .rs-atc-actions {
margin-top: auto;
}
/* --- Collection card: inline ATC actions --- */
.rs-atc-actions {
padding: 0 10px 12px;
display: flex;
flex-direction: column;
gap: 7px;
width: 100%;
box-sizing: border-box;
}
/* Stacked form: dropdown row + button row, each full width */
.rs-atc-stacked,
.js-rs-atc {
display: flex;
flex-direction: column;
gap: 7px;
width: 100%;
}
.rs-atc-select {
width: 100%;
height: 36px;
padding: 0 36px 0 14px;
font-size: 13px;
border: 1px solid #ddd;
border-radius: 9999px;
background-color: #fff;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23666' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 14px center;
appearance: none;
-webkit-appearance: none;
text-align: left;
box-sizing: border-box;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.rs-atc-btn {
width: 100%;
height: 36px;
padding: 0 12px;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.05em;
border-radius: 9999px;
border: 1px solid transparent;
background: #f16558;
color: #ffffff;
cursor: pointer;
white-space: nowrap;
line-height: 36px;
box-sizing: border-box;
transition: opacity 0.15s;
}
.rs-atc-btn:hover { opacity: 0.85; }
.rs-atc-btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* View Product — filled pill, matches Add to cart and Notify Me */
.rs-view-btn {
display: block;
width: 100%;
height: 36px;
padding: 0 12px;
text-align: center;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.05em;
border-radius: 9999px;
border: 1px solid transparent;
background: #f16558;
color: #ffffff;
text-decoration: none;
box-sizing: border-box;
transition: opacity 0.15s;
line-height: 36px;
white-space: nowrap;
}
.rs-view-btn:hover {
opacity: 0.85;
text-decoration: none;
}
/* Notify Me — outline pill: visually distinct from filled Add to Cart so sold-out state is clear */
.rs-notify-btn {
display: block;
width: 100%;
height: 36px;
padding: 0 12px;
text-align: center;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.05em;
border-radius: 9999px;
border: 1.5px solid #f16558;
background: transparent;
color: #f16558;
text-decoration: none;
box-sizing: border-box;
transition: background 0.15s, color 0.15s;
line-height: 33px;
white-space: nowrap;
}
.rs-notify-btn:hover {
background: #f16558;
color: #ffffff;
text-decoration: none;
}
@media (max-width: 768px) {
.rs-atc-actions {
padding: 0 8px 10px;
gap: 6px;
}
.rs-atc-stacked,
.js-rs-atc {
gap: 6px;
}
.rs-atc-select,
.rs-atc-btn,
.rs-view-btn {
font-size: clamp(11px, 3vw, 13px);
height: 34px;
line-height: 34px;
}
.rs-notify-btn {
font-size: clamp(11px, 3vw, 13px);
height: 34px;
line-height: 31px; /* 34 - 2×1.5px border */
}
}
/* --- Collection banner: increase desktop height by ~50% ---
Banner is the Promotional Grid → Advanced block (type="advanced"), NOT the native
collection-header (.collection-hero). collection-header has enable:false in collection.json.
promo-grid.liquid generates responsive min-height from block.settings.height (currently 400):
mobile (<769px): height × 0.6 = 240px ← DO NOT TOUCH
tablet (≥769px): height × 0.8 = 320px ← DO NOT TOUCH
desktop (≥1140px): height × 1.0 = 400px ← INCREASE TO 600px
Override at ≥1140px only so mobile and tablet heights are completely untouched.
block.id == "advanced" → Shopify renders class .flex-grid__item--advanced. --- */
@media only screen and (min-width: 1140px) {
.template-collection .flex-grid__item--advanced {
min-height: 600px !important;
}
}
/* --- Collection page: reduce dead space after product grid / pagination ---
Sources confirmed: .index-section margin-top 75px + .section--divider padding-top 75px = 150px.
Scoped to .template-collection. --- */
.collection-content {
padding-bottom: 0;
}
.collection-content .grid__item--content {
padding-bottom: 8px;
}
.template-collection .index-section {
margin-top: 20px;
}
.template-collection .section--divider {
padding-top: 20px;
}
/* --- Blog/archive page: reduce excess spacing above article grid ---
Sources confirmed: preceding index-section mb=75px + blog page-content pt=75px = 150px.
Scoped to .template-blog only. --- */
.template-blog .index-section {
margin-top: 20px;
margin-bottom: 20px;
}
.template-blog .page-content {
padding-top: 20px;
}
/* --- Guides / blog page: heading hierarchy ---
Rich-text
is the visible page title; enlarge it to match that role.
enlarge-text intro copy is shrunk back to body size to reduce visual dominance.
NOTE: "NEWS" or blog title label in breadcrumbs = Shopify admin blog title → admin-only fix. --- */
.template-blog .theme-block h2 {
font-size: clamp(1.8rem, 4vw, 3rem);
font-weight: 800;
line-height: 1.15;
margin-bottom: 0.4em;
}
.template-blog .enlarge-text {
font-size: 1rem;
}
@media (max-width: 768px) {
.collection-content .grid__item--content {
padding-bottom: 4px;
}
.template-collection .section--divider,
.template-blog .page-content {
padding-top: 15px;
}
}
/* --- Featured-collections overlay tile: proportional font + clean 2-line max ---
Inherited heading font reaches ~35px inside overlay tiles — too large for a
4-column grid. clamp() scales it to tile proportions. max-height enforces the
2-line ceiling without ellipsis so text ends at a word boundary. --- */
.collection-item__title--overlaid > span {
font-size: clamp(15px, 1.8vw, 22px);
font-weight: 700;
line-height: 1.3;
max-height: 2.7em;
overflow: hidden;
word-break: normal;
overflow-wrap: break-word;
}
/* --- Product card: Loox aggregate star rating --- */
.rs-loox-rating {
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
padding: 4px 10px 2px;
}
.rs-stars {
display: flex;
align-items: center;
gap: 1px;
}
.rs-star {
display: block;
flex-shrink: 0;
}
.rs-star--full {
color: #f16558;
}
.rs-star--empty {
color: #ccc;
}
.rs-loox-count {
font-size: 11px;
color: #888;
line-height: 1;
}
/* --- Collection card: price hierarchy ---
Secondary row (compare-at + savings): compact, muted, above current price.
Current price: dominant anchor — last in group, nearest to CTA zone. --- */
.grid-product__price {
display: flex;
flex-direction: column;
gap: 2px;
text-align: center;
}
.rs-price-secondary {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
flex-wrap: wrap;
line-height: 1.2;
}
.rs-price-current {
font-size: 1.1em;
font-weight: 700;
line-height: 1.2;
}
.grid-product__price--original {
font-size: 0.8em !important;
color: #aaa !important;
text-decoration: line-through !important;
font-weight: 400 !important;
line-height: 1.2;
}
.rs-price-save {
font-size: 0.78em;
font-weight: 600;
color: #f16558;
line-height: 1.2;
}
/* Legacy savings span — superseded by rs-price-save */
.grid-product__price--savings {
display: none;
}
/* --- Collection card: mobile secondary image ---
Impulse suppresses secondary image on touch devices at ≤768px (theme.css:9439).
We re-enable it and fade it in when JS adds .rs-touch-active to the card.
- Only cards with 2+ images have .grid-product__secondary-image in the DOM.
- JS uses passive touchstart/touchend — scrolling is never blocked.
- tap-to-PDP works normally (no preventDefault).
- Uses transition (not animation) so fade-out on touchend works cleanly. --- */
@media (max-width: 768px) {
.supports-touch .grid-product__secondary-image {
display: block !important;
opacity: 0;
transition: opacity 0.2s cubic-bezier(0.26, 0.54, 0.32, 1);
}
.supports-touch .grid-product__content.rs-touch-active .grid-product__secondary-image {
opacity: 1;
}
}
/* --- Sold-out collection card: dim tile image so unavailability is visually obvious,
but restore on hover so the card still feels interactive --- */
.grid-product__tag--sold-out ~ .grid__item-image-wrapper {
opacity: 0.72;
transition: opacity 0.2s ease;
}
.grid-product:hover .grid-product__tag--sold-out ~ .grid__item-image-wrapper {
opacity: 0.95;
}
/* ============================================================
BACKORDER CARD STATE — added test/backorder-card-v1
============================================================ */
/* Badge base: corner radius + typography across all badge types */
.grid-product__tag {
border-bottom-left-radius: 8px;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.04em;
}
/* Backorder badge: dark navy background, white text, uppercase for badge feel */
.grid-product__tag--backorder {
background-color: #2B2F3E;
color: #ffffff;
text-transform: uppercase;
}
/* PDP backorder badge: same colour story as the card, larger for ATC context */
.rs-backorder-badge--pdp {
display: inline-block;
background-color: #2B2F3E;
color: #ffffff;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 9px 14px;
border-radius: 6px;
margin-bottom: 14px;
line-height: 1;
}
@media only screen and (min-width: 769px) {
.rs-backorder-badge--pdp {
font-size: 14px;
padding: 10px 16px;
margin-bottom: 16px;
}
}
/* Sold-out badge: light grey background, dark grey text, uppercase for badge consistency */
.grid-product__tag--sold-out {
background-color: #e8e8e8;
color: #444444;
text-transform: uppercase;
}
/* Sale badge: uppercase for badge consistency (text is hardcoded uppercase, this is defensive) */
.grid-product__tag--sale {
text-transform: uppercase;
}
/* Backorder image: always full opacity — not dimmed like sold-out */
.grid-product--backorder .grid__item-image-wrapper {
opacity: 1 !important;
}
/* Bold product titles across all collection cards */
.grid-product__title {
font-weight: 700;
}
/* Rounded corners on product card images */
.grid__item-image-wrapper {
border-radius: 8px;
overflow: hidden;
}
/* PDP backorder note below ATC button */
.backorder-note {
font-size: 0.85em;
color: #666;
margin-top: 8px;
}
/* --- PDP mobile gallery: Flickity dots in normal flow, wrapping ---
Base theme: .flickity-page-dots { position: absolute; bottom: -25px } — with
30-40 product images the dots wrapped onto a second absolute row that overlapped
the content below. An earlier fix forced them onto ONE nowrap line, but that line
is ~640px wide on a 390px phone: it inflated the page's scrollable width and
caused the sideways drift on mobile flick-scrolls (page "goes off to one side").
Fix: take the dots out of absolute positioning entirely. In normal flow they
wrap into centred rows INSIDE the viewport width — content can never overlap,
and the page width can never grow, at any image count. --- */
@media (max-width: 768px) {
.template-product .product__main-photos {
margin-bottom: 30px !important;
overflow: visible !important;
}
.template-product .product__main-photos .flickity-page-dots {
position: static !important;
display: flex !important;
flex-wrap: wrap !important;
justify-content: center !important;
row-gap: 6px !important;
max-width: 100% !important;
padding: 12px 16px 0 !important;
white-space: normal !important;
}
.template-product .product__main-photos .flickity-page-dots .dot {
width: 8px !important;
height: 8px !important;
margin: 0 4px !important;
}
}
/* --- Recommendation / recently-viewed carousels: suppress ATC widget ---
Cards in these carousels are navigational tiles; the full ATC stack (dropdown +
button) is wrong UX in a horizontal scroll context. The whole card links to PDP. --- */
[data-section-type="product-recommendations"] .rs-atc-actions,
[data-section-type="recently-viewed"] .rs-atc-actions {
display: none;
}
/* --- PDP recommendation sections: reduce top spacing and HR weight --- */
.template-product product-recommendations .index-section {
margin-top: 20px;
}
.template-product [data-section-type="recently-viewed"] .index-section--small {
margin-top: 0;
}
.template-product [data-section-type="recently-viewed"] .hr--large {
margin-top: 20px;
margin-bottom: 0;
}
@media (max-width: 768px) {
.template-product product-recommendations .index-section,
.template-product [data-section-type="recently-viewed"] .hr--large {
margin-top: 15px;
}
}
/* --- Page template: reduce excessive top padding (mirrors blog fix) ---
.page-content base: padding-top 40px mobile / 75px desktop.
Standard page sections (Contact, About, etc.) don't need that much breathing
room between the sticky header and the page title. --- */
.template-page .page-content {
padding-top: 20px !important;
}
/* --- Collection pages: reduce collection-content top padding ---
Base theme: padding-top 22.5px mobile / 45px desktop.
Already reduced index-section margin-top to 20px above; align the
collection-content padding to the same compact rhythm. --- */
.template-collection .collection-content {
padding-top: 12px !important;
}
/* --- Homepage: reduce excessive gap between hero and first section below ---
Slideshow uses schema "class": "index-section--hero" (not "index-section"),
so the sibling rule ".index-section + .index-section { margin-top:0 }" does
not fire. The section after the hero keeps the full 75px (desktop) top margin,
creating a large white gap. Scoped to .template-index only — does not affect
collections, pages, or any other template. --- */
.template-index .index-section--hero + .index-section {
margin-top: 20px !important;
}
/* --- Header spacing: standardise top offset to match Guides/News reference (20px desktop / 15px mobile)
Reference: .template-blog .page-content { padding-top: 20px } (15px mobile).
Applied to all remaining templates that still carry the base 40–75px default. --- */
/* Collection header: collection-header.liquid wraps in .page-content.page-content--top
Base: padding-top 75px (desktop). Already-fixed .collection-content covers the grid
area; this covers the breadcrumb / page title strip above it. */
.template-collection .page-content {
padding-top: 20px !important;
}
/* Product pages: main-product.liquid uses .page-content--product
Base: padding-top 55px (desktop) / 0 (mobile).
0 mobile is intentional on stock Impulse (image is full-bleed top),
but a small 15px offset on mobile gives the title breathing room. */
.template-product .page-content--product {
padding-top: 20px !important;
}
/* Standard pages (mobile): desktop already 20px; add matching mobile override */
@media (max-width: 768px) {
.template-collection .page-content {
padding-top: 15px !important;
}
.template-product .page-content--product {
padding-top: 15px !important;
}
.template-page .page-content {
padding-top: 15px !important;
}
}
/* --- EXACT CAUSE OF HEADER-TO-CONTENT GAP ON ALL TEMPLATES ---
sections/apps.liquid renders
when space_around:true.
The popup-group.json apps section has space_around:true, placing this wrapper
between the header-group and on every page.
That wrapper inherits .index-section { margin: 40px 0 / 75px 0 } — producing
the oversized white band above the hero (mobile) and all other first sections.
On the blog, .template-blog .index-section { margin: 20px } already reduced it
to 20px (which the user identified as "correct").
Fix: zero the margin on any .index-section inside the popup-group section group,
globally. Content-section spacing below is unaffected (those are in main-content,
not in .shopify-section-group-popup-group). --- */
.shopify-section-group-popup-group .index-section {
margin: 0 !important;
padding: 0 !important;
}
/* ============================================================
PDP OOS STATE: Back in Stock CTA
Branch: fix/pdp-back-in-stock-cta
Source: AMP Back in Stock app embed (config/settings_data.json)
is active globally and injects its trigger post-load via JS.
============================================================ */
/* --- STEP 1a: Hide disabled SOLD OUT button (confirmed safe) ---
button[data-add-to-cart][disabled] only exists when current_variant.available=false.
In-stock PDPs never have this disabled — selector cannot fire on in-stock state.
Source confirmed: snippets/product-form.liquid lines 32-46. --- */
.template-product button[data-add-to-cart][disabled] {
display: none !important;
}
/* --- STEP 1b: OOS status row — replaces "Shipping Available" sales-point ---
Context: Both the sales_point block (Shipping Available + truck icon) and the
inventory_status block (pulsing dot + stock text) render with the same class
.product-block--sales-point. Differentiator: inventory block contains
[data-product-inventory]; sales_point block does NOT.
On OOS (data-variant-oos="true"):
(i) Hide the sales_point "Shipping Available" row.
:not(:has([data-product-inventory])) targets the sales_point block only.
In-stock: data-variant-oos is "false" → rule never fires.
(ii) Inject "🚫 Out of Stock" into the inventory_status block's
.
On OOS the inventory block's
elements are already hidden via Liquid .hide
class so the
is visually empty. Adding ::before repurposes that block
as the OOS status row — positioned exactly where "Shipping Available" sat.
inventory_status block is block 6 in block_order, sales_point is block 5,
so this sits one slot lower — still above quantity selector and buy_buttons.
Both selectors are scoped to .template-product and [data-variant-oos="true"].
In-stock products: data-variant-oos="false" → both rules dormant.
Confirmed selectors from: snippets/product-inventory.liquid,
snippets/product-template.liquid, templates/product.json. --- */
/* Live OOS signal: ATC's [disabled] attribute IS toggled live by the
theme's variant-change JS. data-variant-oos is Liquid-rendered and
stale after the initial page load, so all OOS-conditional rules
below scope to .template-product:has(button[data-add-to-cart][disabled]). */
/* (i) Hide Shipping Available row on OOS */
.template-product:has(button[data-add-to-cart][disabled])
[data-product-blocks]
.product-block--sales-point:not(:has([data-product-inventory])) {
display: none !important;
}
/* (ii) Inject OOS status row into inventory block */
.template-product:has(button[data-add-to-cart][disabled])
[data-product-blocks]
.product-block--sales-point:has([data-product-inventory])
.sales-points::before {
content: "🚫 Out of Stock";
display: block;
margin-bottom: 10px;
font-size: 0.875em;
font-weight: 600;
color: #999;
letter-spacing: 0.03em;
text-transform: uppercase;
}
/* --- STEP 2: AMP Back in Stock trigger — styled as Rainger CTA button ---
Selector confirmed via DevTools outerHTML: button#BIS_trigger
The AMP app embed (config/settings_data.json, disabled:false) injects this
element post-load via external JS. The app also sets inline styles on the element:
font-size: 1em; width: 100%; margin-top: -10px;
All three are overridden with !important below.
Sizing mirrors the PDP ATC button (.element-button[type="submit"]):
min-height: 50px / padding: 13px 20px / letter-spacing: .3em / fw: 800
Colours and border-radius mirror .rs-atc-btn (collection card CTA):
background: settings.color_button (#f16558) / white text / 9999px pill
NOTE — button text: CSS cannot change rendered text content.
"EMAIL WHEN AVAILABLE" → "NOTIFY ME WHEN AVAILABLE"
must be updated in the AMP app dashboard Caption setting, not via CSS. --- */
.template-product button#BIS_trigger {
display: block !important;
width: 100% !important;
padding: 13px 20px !important;
min-height: 50px !important;
margin-top: 16px !important;
background: #f16558 !important;
color: #ffffff !important;
text-align: center !important;
font-size: 14px !important;
font-weight: 700 !important;
text-transform: uppercase !important;
letter-spacing: 0.08em !important;
line-height: 1.42 !important;
border: none !important;
border-radius: 9999px !important;
text-decoration: none !important;
cursor: pointer !important;
box-sizing: border-box !important;
transition: opacity 0.15s !important;
}
/* --- STEP 2b: Hide BIS_trigger when current variant is in stock ---
Uses the live ATC-disabled signal (see comment above the OOS rules).
When NO disabled ATC button is on the page, the current variant is
in stock → hide the AMP back-in-stock trigger. When the customer
switches to an OOS variant, ATC becomes disabled and BIS_trigger
re-appears automatically (CSS re-evaluates on attribute change). */
.template-product:not(:has(button[data-add-to-cart][disabled])) button#BIS_trigger {
display: none !important;
}
.template-product button#BIS_trigger:hover,
.template-product button#BIS_trigger:focus {
opacity: 0.85 !important;
outline: 2px solid #f16558 !important;
outline-offset: 2px !important;
text-decoration: none !important;
}
/* ── Mobile Filter / Sort — Frosted Glass Pills ────────────────
Scoped to ≤768px: .collection-filter is position:sticky on mobile only.
Two different element types require different treatment:
Filter → button (.btn inside .collection-filter__item--drawer):
backdrop-filter applies directly to the button element.
Sort → bare