The issue: My product page doesn’t assign the correct images to the color swatches/variants.
This is the code:
{% assign product_has_only_default_variant = product.has_only_default_variant %}
{% assign variant_images = product.images | where: 'attached_to_variant?', true | map: 'src' %}
{% assign first_3d_model = product.media | where: 'media_type', 'model' | first %}
<div class="product-detail-section" data-product-id="{{ product.id }}" data-section-id="{{ section.id }}">
<div class="product-detail-wrapper">
<div class="product-media-column">
<div class="product-media-gallery">
{% if product.media.size > 0 %}
<div class="product-images product-main-images">
{% for media in product.media %}
{% case media.media_type %}
{% when 'image' %}
{% assign associated_variant = false %}
{% for variant in product.variants %}
{% if variant.featured_image and variant.featured_image.id == media.id %}
{% assign associated_variant = variant %}
{% break %}
{% endif %}
{% endfor %}
<img
src="{{ media | img_url: '800x800', crop: 'center' }}"
alt="{{ media.alt | escape }}"
class="product-image {% if forloop.first %}active{% endif %}"
data-index="{{ forloop.index0 }}"
data-media-id="{{ media.id }}"
{% if associated_variant %}data-variant-id="{{ associated_variant.id }}"{% endif %}
loading="{% if forloop.first %}eager{% else %}lazy{% endif %}">
{% when 'model' %}
<div class="product-model {% if forloop.first %}active{% endif %}" data-index="{{ forloop.index0 }}" data-media-id="{{ media.id }}">
{{ media | model_viewer_tag }}
</div>
{% when 'video' %}
<div class="product-video {% if forloop.first %}active{% endif %}" data-index="{{ forloop.index0 }}" data-media-id="{{ media.id }}">
{{ media | video_tag: controls: true, autoplay: false }}
</div>
{% endcase %}
{% endfor %}
</div>
{% if product.media.size > 1 %}
<div class="product-thumbnails">
{% for media in product.media %}
{% assign associated_variant = false %}
{% for variant in product.variants %}
{% if media.variant_ids contains variant.id %}
{% assign associated_variant = variant %}
{% break %}
{% endif %}
{% endfor %}
<button
class="thumbnail-button {% if forloop.first %}active{% endif %}"
data-index="{{ forloop.index0 }}"
data-media-id="{{ media.id }}"
{% if associated_variant %}data-variant-id="{{ associated_variant.id }}"{% endif %}
aria-label="Go to image {{ forloop.index }}"
>
<img
src="{{ media | img_url: '100x100', crop: 'center' }}"
alt="{{ media.alt | escape }}"
loading="lazy"
>
</button>
{% endfor %}
</div>
{% endif %}
{% else %}
<div class="product-no-image">
<div class="no-image-placeholder">NO IMAGE</div>
</div>
{% endif %}
</div>
</div>
<div class="product-info-column">
<div class="product-info-wrapper">
{% if product.tags contains 'Best Seller' %}
<div class="product-badge">Best Seller</div>
{% endif %}
<h1 class="product-title">{{ product.title }}</h1>
<div class="product-price">
{%- render 'price',
product: product,
use_variant: true,
show_badges: true
-%}
</div>
{% if product.metafields.reviews.rating %}
<div class="product-reviews">
<div class="star-rating">
{% assign rating = product.metafields.reviews.rating.value | round %}
{% for i in (1..5) %}
{% if i <= rating %}
<span class="star filled">★</span>
{% else %}
<span class="star">★</span>
{% endif %}
{% endfor %}
</div>
<a href="#reviews" class="review-count">{{ product.metafields.reviews.count }}</a>
</div>
{% endif %}
{% unless product_has_only_default_variant %}
<div class="product-variants">
{% for option in product.options_with_values %}
{% if option.name == 'Color' or option.name == 'Colour' %}
<div class="variant-option">
<h3 class="option-name">
{{ option.name }}: <span class="selected-color-name"></span>
</h3>
<div class="color-options">
{% assign unique_values = option.values | uniq %}
{% for value in unique_values %}
{% assign color_code = value | handleize %}
{% assign has_image = false %}
{% assign variant_id = "" %}
{% assign media_id = "" %}
{% for variant in product.variants %}
{% if variant.options[forloop.parentloop.index0] == value %}
{% assign variant_id = variant.id %}
{% for media in product.media %}
{% if media.variant_ids contains variant.id %}
{% assign has_image = true %}
{% assign media_id = media.id %}
{% break %}
{% endif %}
{% endfor %}
{% break %}
{% endif %}
{% endfor %}
<button
class="color-option {% if forloop.first %}active{% endif %}"
data-color="{{ color_code }}"
data-option-position="{{ option.position }}"
data-value="{{ value | escape }}"
data-variant-id="{{ variant_id }}"
{% if has_image %}data-media-id="{{ media_id }}"{% endif %}
style="background-color: {{ value | downcase | replace: ' ', '' | split: '/' | last | default: color_code }};"
title="{{ value }}"
{% if forloop.first %}aria-pressed="true"{% else %}aria-pressed="false"{% endif %}>
</button>
{% endfor %}
</div>
</div>
{% else %}
<div class="variant-option">
<h3 class="option-name">{{ option.name }}</h3>
<div class="size-options">
{% for value in option.values %}
<button
class="size-option {% if forloop.first %}active{% endif %}"
data-option-position="{{ option.position }}"
data-value="{{ value | escape }}"
{% if forloop.first %}aria-pressed="true"{% else %}aria-pressed="false"{% endif %}
>
{{ value }}
</button>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
{% endunless %}
<div class="product-actions">
<button
type="button"
class="add-to-cart-button"
data-product-id="{{ product.id }}"
data-variant-id="{{ product.selected_or_first_available_variant.id }}"
{% if product.available == false %}disabled{% endif %}
>
{% if product.available %}
ADD TO BAG
{% else %}
SOLD OUT
{% endif %}
</button>
</div>
<div class="product-accordions">
<details class="product-accordion">
<summary>
<h3>DESCRIPTION</h3>
<span class="accordion-icon">+</span>
</summary>
<div class="accordion-content">
{{ product.description }}
</div>
</details>
<details class="product-accordion">
<summary>
<h3>FREE SHIPPING & RETURNS</h3>
<span class="accordion-icon">+</span>
</summary>
<div class="accordion-content">
<p>Free standard shipping on all orders.</p>
<p>Free returns within 30 days. See our <a href="/pages/returns">return policy</a> for more information.</p>
</div>
</details>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const productSection = document.querySelector('.product-detail-section');
if (!productSection) return;
const productId = productSection.dataset.productId;
const mainImages = Array.from(productSection.querySelectorAll('.product-main-images .product-image, .product-main-images .product-video, .product-main-images .product-model'));
const thumbnailButtons = Array.from(productSection.querySelectorAll('.thumbnail-button'));
const colorOptions = Array.from(productSection.querySelectorAll('.color-option'));
const sizeOptions = Array.from(productSection.querySelectorAll('.size-option'));
const addToCartButton = productSection.querySelector('.add-to-cart-button');
const selectedColorNameSpan = productSection.querySelector('.selected-color-name'); // Added selector
const colorInfo = colorOptions.map((option, index) => {
return {
element: option,
value: option.getAttribute('data-value') || option.getAttribute('title') || `Color ${index + 1}`,
variantId: option.getAttribute('data-variant-id') || null,
mediaId: option.getAttribute('data-media-id') || null,
index: index
};
});
let allVariantData = [];
let currentIndex = 0;
const getProductHandle = () => {
const path = window.location.pathname;
const pathParts = path.split('/');
let handle = '';
for (let i = 0; i < pathParts.length; i++) {
if (pathParts[i] === 'products' && i + 1 < pathParts.length) {
handle = pathParts[i + 1].split('?')[0];
break;
}
}
return handle;
};
const fetchProductData = async () => {
const handle = getProductHandle();
if (!handle) return null;
try {
const response = await fetch(`/products/${handle}.js`);
if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
return await response.json();
} catch (error) {
console.error('Error getting product data:', error);
return null;
}
};
const buildVariantDataList = (productData) => {
if (!productData || !productData.variants || productData.variants.length === 0) return [];
let colorOptionPosition = -1;
if (productData.options && Array.isArray(productData.options)) {
colorOptionPosition = productData.options.findIndex(opt =>
opt.name.toLowerCase() === 'color' || opt.name.toLowerCase() === 'colour'
);
}
const useDirectMapping = productData.variants.length === colorOptions.length;
const variantMediaMap = {};
if (productData.media && Array.isArray(productData.media)) {
productData.media.forEach(media => {
if (media.id && media.variant_ids && Array.isArray(media.variant_ids)) {
media.variant_ids.forEach(variantId => {
variantMediaMap[variantId] = String(media.id);
});
}
});
}
const variants = [];
productData.variants.forEach((variant, variantIndex) => {
let colorValue = '';
if (colorOptionPosition !== -1) {
const optionKey = `option${colorOptionPosition + 1}`;
colorValue = variant[optionKey] || '';
} else {
const colorData = useDirectMapping && variantIndex < colorInfo.length ? colorInfo[variantIndex] : null;
colorValue = colorData ? colorData.value : '';
}
let variantImage = variant.featured_image || null;
let mediaId = variantImage ? String(variantImage.id) : variantMediaMap[variant.id] || null;
if (!mediaId && useDirectMapping && variantIndex < colorInfo.length && colorInfo[variantIndex].mediaId) {
mediaId = colorInfo[variantIndex].mediaId;
}
let imageElement = null;
if (mediaId) {
imageElement = mainImages.find(img => img.getAttribute('data-media-id') === mediaId);
}
if (!imageElement && useDirectMapping && variantIndex < mainImages.length) {
imageElement = mainImages[variantIndex];
}
let colorElement = null;
for (const color of colorOptions) {
if (color.getAttribute('data-variant-id') === String(variant.id)) {
colorElement = color;
break;
}
}
if (!colorElement && useDirectMapping && variantIndex < colorOptions.length) {
colorElement = colorOptions[variantIndex];
}
variants.push({
id: String(variant.id),
colorValue: colorValue,
colorElement: colorElement,
mediaId: mediaId,
imageElement: imageElement,
imageIndex: imageElement ? mainImages.indexOf(imageElement) : -1,
price: variant.price,
available: variant.available,
variantIndex: variantIndex
});
if (colorElement) {
colorElement.setAttribute('data-variant-id', String(variant.id));
if (mediaId) {
colorElement.setAttribute('data-media-id', mediaId);
}
// Ensure title attribute reflects the actual color value from variant
if (colorValue) {
colorElement.setAttribute('title', colorValue);
if (!colorElement.hasAttribute('data-value')) {
colorElement.setAttribute('data-value', colorValue);
}
}
}
});
return variants;
};
function updateDisplay(variantIndex) {
if (variantIndex < 0 || variantIndex >= allVariantData.length) return;
currentIndex = variantIndex;
const variant = allVariantData[currentIndex];
colorOptions.forEach(btn => {
btn.classList.remove('active');
btn.setAttribute('aria-pressed', 'false');
});
if (variant.colorElement) {
variant.colorElement.classList.add('active');
variant.colorElement.setAttribute('aria-pressed', 'true');
}
mainImages.forEach(img => img.classList.remove('active'));
let imageIndex = -1;
if (variant.imageElement) {
variant.imageElement.classList.add('active');
imageIndex = mainImages.indexOf(variant.imageElement);
} else if (variant.mediaId) {
for (let i = 0; i < mainImages.length; i++) {
if (mainImages[i].getAttribute('data-media-id') === variant.mediaId) {
mainImages[i].classList.add('active');
imageIndex = i;
break;
}
}
}
if (imageIndex === -1 && variant.variantIndex < mainImages.length) {
imageIndex = variant.variantIndex; // Fallback to index if lengths match
}
if (imageIndex === -1 && mainImages.length > 0) {
imageIndex = 0; // Fallback to first image
}
if (imageIndex !== -1 && imageIndex < mainImages.length) {
mainImages[imageIndex].classList.add('active');
}
thumbnailButtons.forEach(btn => btn.classList.remove('active'));
if (imageIndex >= 0 && imageIndex < thumbnailButtons.length) {
thumbnailButtons[imageIndex].classList.add('active');
}
// Update selected color name display
if (selectedColorNameSpan) {
selectedColorNameSpan.textContent = variant.colorValue || '';
}
if (addToCartButton) {
addToCartButton.setAttribute('data-variant-id', variant.id);
addToCartButton.disabled = !variant.available;
addToCartButton.textContent = variant.available ? 'ADD TO BAG' : 'SOLD OUT';
}
// Trigger price update (assumes a 'price' snippet handles this via events or direct update)
const priceElement = productSection.querySelector('.product-price');
if (priceElement) {
const event = new CustomEvent('variant:changed', {
bubbles: true,
detail: { variant: variant }
});
priceElement.dispatchEvent(event);
// If the price snippet doesn't listen for events, you might need direct manipulation here
// e.g., update price based on variant.price
}
}
function updateCartState() {
fetch('/cart.js')
.then(response => response.json())
.then(cart => {
const event = new CustomEvent('cart:updated', {
bubbles: true,
detail: cart
});
document.dispatchEvent(event);
const cartTotalElements = document.querySelectorAll('#cart-total');
cartTotalElements.forEach(element => {
element.textContent = `$ ${(cart.total_price / 100).toFixed(2)}`;
});
const cartCountElements = document.querySelectorAll('.cart-count, .cart-quantity, .cart-item-count, .js-cart-count');
cartCountElements.forEach(element => {
element.textContent = cart.item_count;
if (cart.item_count > 0 && element.classList.contains('hidden')) {
element.classList.remove('hidden');
} else if (cart.item_count === 0 && !element.classList.contains('hidden')) {
element.classList.add('hidden'); // Hide if empty
}
});
// Update section rendering for cart total if needed
fetch('/?sections=cart-total')
.then(response => response.text())
.then(sectionsText => {
try {
const sectionsJson = JSON.parse(sectionsText);
const cartTotalHtml = sectionsJson['cart-total'];
if (cartTotalHtml) {
const parser = new DOMParser();
const doc = parser.parseFromString(cartTotalHtml, 'text/html');
const newCartTotalContent = doc.querySelector('#cart-total')?.innerHTML;
if (newCartTotalContent) {
document.querySelectorAll('#cart-total').forEach(el => {
el.innerHTML = newCartTotalContent;
});
}
}
} catch(e) {
console.warn("Could not parse cart-total section response");
}
})
.catch(error => console.error('Error updating cart total section:', error));
})
.catch(error => console.error('Error updating cart information:', error));
}
function setupColorButtons() {
colorOptions.forEach((btn, index) => {
btn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
const variantId = btn.getAttribute('data-variant-id');
const colorValue = btn.getAttribute('data-value') || btn.getAttribute('title');
let targetIndex = -1;
if (variantId) {
targetIndex = allVariantData.findIndex(v => v.id === variantId);
}
if (targetIndex === -1) {
targetIndex = allVariantData.findIndex(v => v.colorElement === btn);
}
if (targetIndex === -1 && allVariantData.length === colorOptions.length) {
targetIndex = index;
}
if (targetIndex !== -1) {
updateDisplay(targetIndex);
}
});
});
}
function setupThumbnails() {
thumbnailButtons.forEach((btn, index) => {
btn.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (index >= mainImages.length) return;
const mediaId = mainImages[index].getAttribute('data-media-id');
let targetIndex = -1;
if (mediaId) {
targetIndex = allVariantData.findIndex(v => v.mediaId === mediaId);
}
if (targetIndex === -1) {
targetIndex = allVariantData.findIndex(v => v.imageElement === mainImages[index]);
}
if (targetIndex === -1 && allVariantData.length === mainImages.length) {
targetIndex = index;
}
if (targetIndex !== -1) {
updateDisplay(targetIndex);
} else {
mainImages.forEach(img => img.classList.remove('active'));
mainImages[index].classList.add('active');
thumbnailButtons.forEach(button => button.classList.remove('active'));
btn.classList.add('active');
}
});
});
}
function setupAddToCartButton() {
if (!addToCartButton) return;
addToCartButton.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (this.disabled || this.classList.contains('adding')) return;
const variantId = this.getAttribute('data-variant-id');
if (!variantId) return;
this.classList.add('adding');
const originalText = this.textContent;
this.textContent = 'Adding...';
const formData = { 'items': [{ 'id': variantId, 'quantity': 1 }] };
fetch('/cart/add.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
})
.then(response => {
if (!response.ok) {
return response.json().then(data => {
throw { status: response.status, message: data.description || 'Error' };
});
}
return response.json();
})
.then(data => {
this.textContent = 'Added!';
updateCartState();
setTimeout(() => {
this.classList.remove('adding');
this.textContent = originalText;
}, 1500);
})
.catch(error => {
this.classList.remove('adding');
this.textContent = error.message || 'Error';
setTimeout(() => {
this.textContent = originalText;
// Re-evaluate button state based on current variant availability
const currentVariant = allVariantData[currentIndex];
if(currentVariant) {
this.disabled = !currentVariant.available;
this.textContent = currentVariant.available ? 'ADD TO BAG' : 'SOLD OUT';
} else {
this.textContent = 'ADD TO BAG'; // Default fallback
this.disabled = false;
}
}, 2000);
});
});
}
async function init() {
try {
const productData = await fetchProductData();
if (!productData) return;
allVariantData = buildVariantDataList(productData);
if (allVariantData.length === 0) return;
setupColorButtons();
setupThumbnails();
setupAddToCartButton();
// Initialize display with the first available variant or just the first one
let initialIndex = allVariantData.findIndex(v => v.available);
if (initialIndex === -1) initialIndex = 0; // Fallback to the first variant if none are available
if(allVariantData.length > 0) {
updateDisplay(initialIndex);
}
} catch (error) {
console.error('Error during initialization:', error);
}
}
init();
const accordions = productSection.querySelectorAll('.product-accordion');
accordions.forEach(accordion => {
const summary = accordion.querySelector('summary');
if (summary) {
summary.addEventListener('click', (e) => {
// Only prevent default if we're managing the open state manually
// e.preventDefault(); // Might not be needed with <details> default behavior
const currentlyOpen = accordion.hasAttribute('open');
// Close others only if we are opening this one
if (!currentlyOpen) {
accordions.forEach(acc => {
if (acc !== accordion && acc.hasAttribute('open')) {
acc.removeAttribute('open');
// Update icon if needed
const otherIcon = acc.querySelector('.accordion-icon');
if (otherIcon) otherIcon.textContent = '+';
}
});
}
// Toggle current accordion (browser might do this automatically, check if needed)
// accordion.toggleAttribute('open'); // Only if preventing default
// Update icon for the clicked accordion
const icon = summary.querySelector('.accordion-icon');
if (icon) {
// Check state *after* potential toggle
icon.textContent = accordion.hasAttribute('open') ? '-' : '+';
}
});
// Set initial icon state for pre-opened accordions
const icon = summary.querySelector('.accordion-icon');
if (icon) {
icon.textContent = accordion.hasAttribute('open') ? '-' : '+';
}
}
});
});
</script>
<style>
.product-price,
.sold-out-badge,
.product-badge,
.option-name,
.accordion-content {
font-family: "NHaasGroteskTXPro";
}
.product-accordion summary h3{
font-family: "SweetSansProBold";
font-size: 12px;
}
.product-detail-section {
max-width: 1350px;
margin: 0 auto 50px;
padding: 0 20px;
}
.product-detail-wrapper {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 40px;
align-items: start;
}
/* Media Column Styles */
.product-media-column {
position: relative;
grid-column: 1 / 7;
}
/* Info Column Styles */
.product-info-column {
padding-top: 20px;
grid-column: 8 / 13; /* Usando 13 para asegurar que llegue hasta el final (12 inclusive) */
}
.product-images {
position: relative;
padding-bottom: 100%;
overflow: hidden;
background: #f7f7f7;
}
.product-image,
.product-video,
.product-model {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0;
transition: opacity 0.3s;
pointer-events: none;
}
.product-image.active,
.product-video.active,
.product-model.active {
opacity: 1;
pointer-events: auto;
}
.no-image-placeholder {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #f8f8f8;
color: #999;
font-size: 12px;
font-weight: bold;
}
.product-thumbnails {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.thumbnail-button {
width: 70px;
height: 70px;
padding: 0;
border: 1px solid #e8e8e8;
background: none;
cursor: pointer;
overflow: hidden;
}
.thumbnail-button.active {
border-color: #000;
}
.thumbnail-button img {
width: 100%;
height: 100%;
object-fit: cover;
}
.product-badge {
font-size: 12px;
margin-bottom: 10px;
color: #616161;
}
.product-title {
font-size: 24px;
font-weight: 400;
margin-bottom: 0px;
line-height: 1.4;
letter-spacing: 0.75px;
text-transform: uppercase;
font-family: "SweetSansProRegular";
}
.product-price {
font-size: 16px;
color: #000;
margin-bottom: 15px;
letter-spacing: 0.75px;
}
/* Reviews */
.product-reviews {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.star-rating {
display: flex;
}
.star {
color: #d8d8d8;
font-size: 16px;
}
.star.filled {
color: #000;
}
.review-count {
margin-left: 5px;
color: #616161;
text-decoration: underline;
}
/* Variant Selectors */
.product-variants {
margin-bottom: 20px;
}
.variant-option {
margin-bottom: 20px;
display: flex;
gap: 5rem;
}
.option-name {
font-size: 12px;
margin-bottom: 10px;
font-weight: 400;
min-width: 50px;
}
.color-options {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
}
.color-option {
width: 24px;
height: 24px;
border-radius: 50%;
border: 2px solid #8d8d8d;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
padding: 0;
background-clip: content-box;
}
.color-option[style*="background-color: white"] {
border-color: #ccc;
}
.color-option:hover {
transform: scale(1.1);
}
.color-option.active {
box-shadow: 0 0 0 1px white, 0 0 0 2px #000;
}
.size-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.size-option {
min-width: 40px;
height: 40px;
padding: 0 15px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #e8e8e8;
background: white;
cursor: pointer;
font-size: 12px;
transition: all 0.2s;
}
.size-option:hover {
border-color: #999;
}
.size-option.active {
border-color: #000;
background: #000;
color: white;
}
/* Add to Cart */
.product-actions {
margin-bottom: 30px;
}
.add-to-cart-button {
width: 100%;
padding: 12px;
cursor: pointer;
transition: all 0.3s;
font-weight: 400;
text-align: center;
background-color: #000;
color: #fff;
border: 1px solid #000;
font-family: "SweetSansProBold";
}
.add-to-cart-button:hover:not([disabled]) {
background-color: #333;
}
.add-to-cart-button[disabled] {
background-color: #f8f8f8;
border-color: #e8e8e8;
color: #999;
cursor: not-allowed;
}
/* Accordions */
.product-accordions {
border-top: 1px solid #e8e8e8;
}
.product-accordion {
border-bottom: 1px solid #e8e8e8;
}
.product-accordion summary {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 0;
cursor: pointer;
list-style: none;
}
.product-accordion summary h3 {
font-size: 12px;
font-weight: 400;
margin: 0;
}
.product-accordion .accordion-icon {
font-size: 16px;
transition: transform 0.3s;
}
.product-accordion[open] .accordion-icon {
transform: rotate(45deg);
}
.accordion-content {
padding: 0 0 20px 0;
font-size: 12px;
line-height: 1.6;
}
/* Responsive */
@media (max-width: 991px) {
.product-detail-wrapper {
gap: 30px;
}
.product-media-column {
grid-column: 1 / 7;
}
.product-info-column {
grid-column: 7 / 13;
}
}
@media (max-width: 767px) {
.product-detail-wrapper {
grid-template-columns: 1fr;
}
.product-media-column,
.product-info-column {
grid-column: 1 / -1;
}
.product-media-column {
margin-bottom: 20px;
}
}
</style>