[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/enhancedEcommerceEvents.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import updateEcommerce from './updateEcommerce'
import {
  PixelMessage,
  ProductOrder,
  Impression,
  CartItem,
} from '../typings/events'
import { AnalyticsEcommerceProduct } from '../typings/gtm'
import {
  purchase,
  selectItem,
  selectPromotion,
  viewItem,
  viewItemList,
  viewPromotion,
  addToCart,
  removeFromCart,
  addPaymentInfo,
  beginCheckout,
  addShippingInfo,
  viewCart,
  search,
  login,
  refund,
  addToWishlist,
  signUp,
  share,
} from './gaEvents'
import {
  getCategory,
  getSeller,
  getProductNameWithoutVariant,
  getPurchaseObjectData,
} from './utils'
import {
  customDimensionSkuAvailability,
  productViewSkuReference,
} from './customDimensions'

export async function sendEnhancedEcommerceEvents(e: PixelMessage) {
  switch (e.data.eventName) {
    case 'vtex:productView': {
      const {
        productId,
        productReference,
        selectedSku,
        productName,
        brand,
        categories,
      } = e.data.product

      const productAvailableQuantity = getSeller(selectedSku.sellers)
        .commertialOffer.AvailableQuantity

      const isAvailable = customDimensionSkuAvailability(
        productAvailableQuantity
      )

      // Product summary list title. Ex: 'List of products'
      const list = e.data.list ? { actionField: { list: e.data.list } } : {}

      let price

      try {
        price = getSeller(selectedSku.sellers).commertialOffer.Price
      } catch {
        price = undefined
      }

      const data = {
        ecommerce: {
          detail: {
            ...list,
            products: [
              {
                brand,
                category: getCategory(categories),
                id: productId,
                variant: selectedSku.itemId,
                name: productName,
                dimension1: productReference ?? '',
                dimension2: productViewSkuReference(e.data.product) ?? '',
                dimension3: selectedSku.name,
                dimension4: isAvailable,
                price,
              },
            ],
          },
        },
        event: 'productDetail',
      }

      viewItem(e.data)
      updateEcommerce('productDetail', data)

      return
    }

    case 'vtex:productClick': {
      const { product, position } = e.data
      const {
        productName,
        brand,
        categories,
        sku,
        productId,
        productReference,
      } = product

      // Product summary list title. Ex: 'List of products'
      const list = e.data.list ? { actionField: { list: e.data.list } } : {}

      let price

      try {
        price = getSeller(sku?.sellers ?? product.items[0].sellers)
          .commertialOffer.Price
      } catch {
        price = undefined
      }

      const data = {
        event: 'productClick',
        ecommerce: {
          click: {
            ...list,
            products: [
              {
                brand,
                category: getCategory(categories),
                id: productId,
                variant: sku.itemId,
                name: productName,
                dimension1: productReference ?? '',
                dimension2: sku.referenceId?.Value ?? '',
                dimension3: sku.name,
                price,
                position,
              },
            ],
          },
        },
      }

      selectItem(e.data)
      updateEcommerce('productClick', data)

      return
    }

    case 'vtex:addToCart': {
      const { items } = e.data

      const data = {
        ecommerce: {
          add: {
            products: items.map(item => ({
              brand: item.brand,
              category: item.category,
              id: item.productId,
              variant: item.skuId,
              name: item.name, // Product name
              price:
                item.priceIsInt === true
                  ? `${item.price / 100}`
                  : `${item.price}`,
              quantity: item.quantity,
              dimension1: item.productRefId ?? '',
              dimension2: item.referenceId ?? '', // SKU reference id
              dimension3: item.variant, // SKU name (variant)
            })),
          },
          currencyCode: e.data.currency,
        },
        event: 'addToCart',
      }

      addToCart(e.data)
      updateEcommerce('addToCart', data)

      return
    }

    case 'vtex:removeFromCart': {
      const { items } = e.data

      const data = {
        ecommerce: {
          currencyCode: e.data.currency,
          remove: {
            products: items.map(item => ({
              brand: item.brand,
              category: item.category,
              id: item.productId,
              variant: item.skuId,
              name: item.name, // Product name
              price:
                item.priceIsInt === true
                  ? `${item.price / 100}`
                  : `${item.price}`,
              quantity: item.quantity,
              dimension1: item.productRefId ?? '',
              dimension2: item.referenceId ?? '', // SKU reference id
              dimension3: item.variant, // SKU name (variant)
            })),
          },
        },
        event: 'removeFromCart',
      }

      removeFromCart(e.data)
      updateEcommerce('removeFromCart', data)

      return
    }

    case 'vtex:orderPlaced': {
      const order = e.data

      const ecommerce = {
        purchase: {
          actionField: getPurchaseObjectData(order),
          products: order.transactionProducts.map((product: ProductOrder) =>
            getProductObjectData(product)
          ),
        },
      }

      const data = {
        // @ts-ignore
        event: 'orderPlaced',
        ...order,
        // The name ecommerceV2 was introduced as a fix, so it is possible that some clients
        // were using this as it was called before (ecommerce). For that reason,
        // it will also be sent as ecommerce to the dataLayer.
        ecommerce,
        // This variable is called ecommerceV2 so it matches the variable name present on the checkout
        // This way, users can have one single tag for checkout and orderPlaced events
        ecommerceV2: {
          ecommerce,
        },
      }

      purchase(order)
      updateEcommerce('orderPlaced', data)

      return
    }

    case 'vtex:productImpression': {
      const { currency, list, impressions } = e.data

      const parsedImpressions = (impressions || []).map(
        getProductImpressionObjectData(list)
      )

      const data = {
        event: 'productImpression',
        ecommerce: {
          currencyCode: currency,
          impressions: parsedImpressions,
        },
      }

      viewItemList(e.data)
      updateEcommerce('productImpression', data)

      return
    }

    case 'vtex:cartLoaded': {
      const { orderForm } = e.data

      const data = {
        event: 'checkout',
        ecommerce: {
          checkout: {
            actionField: {
              step: 1,
            },
            products: orderForm.items.map(getCheckoutProductObjectData),
          },
        },
      }

      updateEcommerce('checkout', data)

      break
    }

    case 'vtex:promoView': {
      const { promotions } = e.data

      const data = {
        event: 'promoView',
        ecommerce: {
          promoView: {
            promotions,
          },
        },
      }

      viewPromotion(e.data)
      updateEcommerce('promoView', data)

      break
    }

    case 'vtex:promotionClick': {
      const { promotions } = e.data

      const data = {
        event: 'promotionClick',
        ecommerce: {
          promoClick: {
            promotions,
          },
        },
      }

      selectPromotion(e.data)
      updateEcommerce('promotionClick', data)

      break
    }

    case 'vtex:addPaymentInfo': {
      addPaymentInfo(e.data)

      break
    }

    case 'vtex:beginCheckout': {
      beginCheckout(e.data)

      break
    }

    case 'vtex:addShippingInfo': {
      addShippingInfo(e.data)

      break
    }

    case 'vtex:viewCart': {
      viewCart(e.data)

      break
    }

    case 'vtex:login': {
      login(e.data)

      break
    }

    case 'vtex:signUp': {
      signUp(e.data)

      break
    }

    case 'vtex:refund': {
      refund(e.data)

      break
    }

    case 'vtex:addToWishlist': {
      addToWishlist(e.data)

      break
    }

    case 'vtex:search': {
      search(e.data)

      break
    }

    case 'vtex:share': {
      share(e.data)

      break
    }

    default: {
      break
    }
  }
}

function getProductObjectData(product: ProductOrder) {
  const productName = getProductNameWithoutVariant(
    product.name,
    product.skuName
  )

  return {
    brand: product.brand,
    category: product.categoryTree?.join('/'),
    id: product.id, // Product id
    variant: product.sku, // SKU id
    name: productName, // Product name
    price: product.price,
    quantity: product.quantity,
    dimension1: product.productRefId ?? '',
    dimension2: product.skuRefId ?? '',
    dimension3: product.skuName, // SKU name (only variant)
  }
}

function getProductImpressionObjectData(list: string) {
  return ({ product, position }: Impression) => ({
    brand: product.brand,
    category: getCategory(product.categories),
    id: product.productId, // Product id
    variant: product.sku.itemId, // SKU id
    list,
    name: product.productName,
    position,
    price: `${product.sku.seller.commertialOffer.Price}`,
    dimension1: product.productReference ?? '',
    dimension2: product.sku.referenceId?.Value ?? '',
    dimension3: product.sku.name, // SKU name (variation only)
  })
}

function getCheckoutProductObjectData(
  item: CartItem
): AnalyticsEcommerceProduct {
  const productName = getProductNameWithoutVariant(item.name, item.skuName)

  return {
    id: item.productId, // Product id
    variant: item.id, // SKU id
    name: productName, // Product name without variant
    category: Object.keys(item.productCategories ?? {}).reduce(
      (categories, category) =>
        categories ? `${categories}/${category}` : category,
      ''
    ),
    brand: item.additionalInfo?.brandName ?? '',
    price: item.sellingPrice / 100,
    quantity: item.quantity,
    dimension1: item.productRefId ?? '',
    dimension2: item.referenceId ?? '', // SKU reference id
    dimension3: item.skuName,
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/legacyEvents.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import push from './push'
import { PixelMessage, SearchPageInfoData } from '../typings/events'

export async function sendLegacyEvents(e: PixelMessage) {
  switch (e.data.eventName) {
    case 'vtex:pageInfo': {
      const { eventType } = e.data

      switch (eventType) {
        case 'homeView': {
          push({
            event: 'homeView',
          })
          break
        }

        case 'categoryView': {
          const data = e.data as SearchPageInfoData

          push({
            event: 'categoryView',
            departmentId: data.department?.id,
            departmentName: data.department?.name,
            categoryId: data.category?.id,
            categoryName: data.category?.name,
          })
          break
        }

        case 'departmentView': {
          const data = e.data as SearchPageInfoData

          push({
            event: 'departmentView',
            departmentId: data.department?.id,
            departmentName: data.department?.name,
          })
          break
        }

        case 'emptySearchView':

        // eslint-disable-next-line no-fallthrough
        case 'internalSiteSearchView': {
          const data = e.data as SearchPageInfoData

          push({
            event: 'internalSiteSearchView',
            siteSearchTerm: data.search?.term,
            siteSearchForm: window.location.href,
            siteSearchCategory: data.search?.category?.id,
            siteSearchResults: data.search?.results,
          })

          break
        }

        case 'productView': {
          push({
            event: 'productView',
          })
          break
        }

        default: {
          push({
            event: 'otherView',
          })
          break
        }
      }

      break
    }

    default: {
      break
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/utils.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  CartItem,
  Impression,
  Order,
  ProductOrder,
  Seller,
} from '../typings/events'
import { customDimensions } from './customDimensions'

export function getSeller(sellers: Seller[]) {
  const defaultSeller = sellers.find(seller => seller.sellerDefault)

  if (!defaultSeller) {
    return sellers[0]
  }

  return defaultSeller
}

export function getPrice(seller: Seller) {
  let price

  try {
    price = seller.commertialOffer.Price
  } catch {
    price = undefined
  }

  return price
}

function formatCategoriesHierarchy(
  categories: { [key: string]: string },
  value: string,
  index: number
) {
  const categoryHierarchyNumber = index + 1
  const isFirstCategory = categoryHierarchyNumber === 1
  const key = `item_category${isFirstCategory ? '' : categoryHierarchyNumber}`

  categories[key] = value
}

export function getCategoriesWithHierarchy(categoriesArray: string[]) {
  if (!categoriesArray || !categoriesArray.length) return

  const categoryString = getCategory(categoriesArray)
  const categories = splitIntoCategories(categoryString)

  if (!categories || !categoryString) return {}

  const categoriesFormatted: { [key: string]: string } = {}

  if (!categories || !categories.length) {
    formatCategoriesHierarchy(categoriesFormatted, categoryString, 0)
  } else {
    categories.forEach((category, index) => {
      formatCategoriesHierarchy(categoriesFormatted, category, index)
    })
  }

  return categoriesFormatted
}

function getCategoriesHierarchyByKey(
  categories: Record<string, string> | null,
  keysArray?: string[]
) {
  if (!keysArray || !keysArray.length || !categories) return []
  const categoriesFormatted: string[] = []
  const categoriesHierarchyFormatted = {}

  keysArray.forEach(key => {
    if (key) categoriesFormatted.push(categories[key])
  })

  categoriesFormatted.forEach((category, index) => {
    formatCategoriesHierarchy(categoriesHierarchyFormatted, category, index)
  })

  return categoriesHierarchyFormatted
}

export function getQuantity(seller: Seller) {
  const isAvailable = seller.commertialOffer.AvailableQuantity > 0

  return isAvailable ? 1 : 0
}

export function getImpressions(impressions: Impression[]) {
  if (!impressions || !impressions.length) return []

  const formattedImpressions = impressions.map(impression => {
    const { product, position } = impression
    const {
      productName,
      productId,
      productReference,
      sku,
      brand,
      categories,
    } = product

    const { itemId, seller, referenceId, name } = sku

    const price = getPrice(seller)
    const discount = getDiscount(seller)
    const quantity = getQuantity(seller)

    const categoriesHierarchy = getCategoriesWithHierarchy(categories)

    return {
      item_id: productId,
      item_name: productName,
      item_variant: itemId,
      item_brand: brand,
      index: position,
      discount,
      price,
      quantity,
      ...categoriesHierarchy,
      ...customDimensions({
        productReference,
        skuReference: referenceId?.Value,
        skuName: name,
        quantity,
      }),
    }
  })

  return formattedImpressions
}

export function getDiscount(seller: Seller) {
  if (!seller.commertialOffer.PriceWithoutDiscount) return 0

  const { commertialOffer } = seller
  const { Price, PriceWithoutDiscount } = commertialOffer

  if (PriceWithoutDiscount <= Price) return 0

  let price

  try {
    price = PriceWithoutDiscount - Price
  } catch {
    price = 0
  }

  return price
}

export function getCategory(rawCategories: string[]) {
  if (!rawCategories || !rawCategories.length) {
    return
  }

  return removeStartAndEndSlash(rawCategories[0])
}

// Transform this: "/Apparel & Accessories/Clothing/Tops/"
// To this: "Apparel & Accessories/Clothing/Tops"
function removeStartAndEndSlash(category?: string) {
  return category?.replace(/^\/|\/$/g, '')
}

function splitIntoCategories(category?: string) {
  if (!category) return

  const splitted = category.split('/')

  return splitted
}

export function getPurchaseObjectData(order: Order) {
  return {
    affiliation: order.transactionAffiliation,
    coupon: order.coupon ? order.coupon : null,
    id: order.orderGroup,
    revenue: order.transactionTotal,
    shipping: order.transactionShipping,
    tax: order.transactionTax,
  }
}

export function getProductNameWithoutVariant(
  productNameWithVariant: string,
  variant: string
) {
  const indexOfVariant = productNameWithVariant.lastIndexOf(variant)

  if (indexOfVariant === -1 || indexOfVariant === 0) {
    return productNameWithVariant
  }

  return productNameWithVariant.substring(0, indexOfVariant - 1) // Removes the variant and the whitespace
}

function formatPurchaseProduct(product: ProductOrder) {
  const {
    name,
    skuName,
    id,
    brand,
    sku,
    price,
    quantity,
    categoryTree,
    productRefId,
    skuRefId,
  } = product

  const productName = getProductNameWithoutVariant(name, skuName)

  const item = {
    item_id: id,
    item_name: productName,
    item_brand: brand,
    item_variant: sku,
    price,
    quantity,
    ...getCategoriesWithHierarchy([categoryTree.join('/')]),
    ...customDimensions({
      productReference: productRefId,
      skuReference: skuRefId,
      skuName,
      quantity,
    }),
  }

  return item
}

export function formatCartItemsAndValue(
  cartItems: CartItem[],
  options?: {
    dividePrice: boolean
  }
) {
  let totalValue = 0.0

  if (!cartItems.length) return { items: [], totalValue }

  const items = cartItems.map((item: CartItem) => {
    const productName = getProductNameWithoutVariant(item.name, item.skuName)

    const shouldFormatPrice = item.priceIsInt ?? options?.dividePrice

    const formattedPrice = shouldFormatPrice ? item.price / 100 : item.price

    const itemBrand = item.brand ? item.brand : item.additionalInfo?.brandName

    const categoryIds = splitIntoCategories(item.productCategoryIds)
    const formattedCategories = item.category
      ? getCategoriesWithHierarchy([item.category])
      : getCategoriesHierarchyByKey(item.productCategories, categoryIds)

    totalValue += formattedPrice * item.quantity

    return {
      item_id: item.productId,
      item_brand: itemBrand,
      item_name: productName,
      item_variant: item.skuId,
      quantity: item.quantity,
      price: formattedPrice,
      ...formattedCategories,
      ...customDimensions({
        productReference: item.productRefId,
        skuReference: item.referenceId,
        skuName: item.variant,
        quantity: item.quantity,
      }),
    }
  })

  return { items, totalValue }
}

export function getPurchaseItems(orderProducts: ProductOrder[]) {
  return orderProducts.map(formatPurchaseProduct)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/extraEvents.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import push from './push'
import { PixelMessage } from '../typings/events'

async function emailToHash(email:string) {
  const msgUint8 = new TextEncoder().encode(email);
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
  return hashHex;
}

export async function sendExtraEvents(e: PixelMessage) {

  switch (e.data.eventName) {
    case 'vtex:pageView': {
      push({
        event: 'pageView',
        location: e.data.pageUrl,
        page: e.data.pageUrl.replace(e.origin, ''),
        referrer: e.data.referrer,
        ...(e.data.pageTitle && {
          title: e.data.pageTitle,
        }),
      })

      return
    }

    case 'vtex:userData': {
      const { data } = e

      if (!data.isAuthenticated) {
        return
      }

      const emailHash = data.email ? await emailToHash(data.email) : undefined

      push({
        event: 'userData',
        userId: data.id,
        emailHash: emailHash
      })

      break
    }

    default: {
      break
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/gaEvents.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  AddToCartData,
  RemoveFromCartData,
  PromoViewData,
  OrderPlacedData,
  AddPaymentInfoData,
  ProductClickData,
  ProductViewData,
  ProductImpressionData,
  BeginCheckoutData,
  AddShippingInfoData,
  ViewCartData,
  SearchData,
  LoginData,
  RefundData,
  AddToWishlistData,
  SignUpData,
  ShareData,
  PromotionClickData,
} from '../typings/events'
import updateEcommerce from './updateEcommerce'
import {
  getPrice,
  getSeller,
  getCategoriesWithHierarchy,
  getQuantity,
  getImpressions,
  getDiscount,
  getPurchaseObjectData,
  getPurchaseItems,
  formatCartItemsAndValue,
} from './utils'
import { customDimensions, productViewSkuReference } from './customDimensions'
import shouldSendGA4Events from './utils/shouldSendGA4Events'

export function viewItem(eventData: ProductViewData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'view_item'

  const { currency, product, list } = eventData

  const {
    selectedSku,
    productName,
    productId,
    productReference,
    categories,
    brand,
  } = product

  const { itemId: variant } = selectedSku

  const seller = getSeller(selectedSku.sellers)
  const value = getPrice(seller)
  const categoriesHierarchy = getCategoriesWithHierarchy(categories)
  const discount = getDiscount(seller)
  const quantity = getQuantity(seller)

  const item = {
    item_id: productId,
    item_name: productName,
    item_list_name: list,
    item_brand: brand,
    item_variant: variant,
    discount,
    quantity,
    price: value,
    ...categoriesHierarchy,
    ...customDimensions({
      productReference,
      skuReference: productViewSkuReference(product),
      skuName: selectedSku.name,
      quantity,
    }),
  }

  const data = {
    currency,
    value,
    items: [item],
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function viewItemList(eventData: ProductImpressionData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'view_item_list'

  const { list, impressions } = eventData

  const items = getImpressions(impressions)

  const data = {
    item_list_name: list,
    items,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function selectItem(eventData: ProductClickData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'select_item'

  const { product, list, position } = eventData

  const {
    sku,
    productName,
    productId,
    productReference,
    categories,
    brand,
  } = product

  const { itemId: variant, referenceId, name } = sku

  const seller = getSeller(sku.sellers)
  const price = getPrice(seller)
  const categoriesHierarchy = getCategoriesWithHierarchy(categories)
  const discount = getDiscount(seller)
  const quantity = getQuantity(seller)

  const item = {
    item_id: productId,
    item_name: productName,
    item_list_name: list,
    item_brand: brand,
    item_variant: variant,
    index: position,
    price,
    quantity,
    discount,
    ...categoriesHierarchy,
    ...customDimensions({
      productReference,
      skuReference: referenceId?.Value,
      skuName: name,
      quantity,
    }),
  }

  const data = {
    item_list_name: list,
    items: [item],
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function selectPromotion(eventData: PromotionClickData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'select_promotion'
  const [promotion] = eventData.promotions

  const data = {
    creative_name: promotion.creative,
    creative_slot: promotion.position,
    promotion_id: promotion.id,
    promotion_name: promotion.name,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function viewPromotion(eventData: PromoViewData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'view_promotion'

  const {
    promotions: [{ creative, position, id, name, products }],
  } = eventData

  let items: Array<{ item_id: string; item_name: string }> = []

  if (products?.length) {
    items = products.map(product => ({
      item_id: product.productId,
      item_name: product.productName,
    }))
  }

  const data = {
    creative_name: creative,
    creative_slot: position,
    promotion_id: id,
    promotion_name: name,
    items,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function addToCart(eventData: AddToCartData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'add_to_cart'

  const { items: eventDataItems, currency } = eventData

  const { items, totalValue } = formatCartItemsAndValue(eventDataItems)

  const data = {
    items,
    currency,
    value: totalValue,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function removeFromCart(eventData: RemoveFromCartData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'remove_from_cart'

  const { items: eventDataItems, currency } = eventData

  const { items, totalValue } = formatCartItemsAndValue(eventDataItems)

  const data = {
    items,
    currency,
    value: totalValue,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function purchase(eventData: OrderPlacedData) {
  if (!shouldSendGA4Events()) return

  const eventName = 'purchase'

  const { id, revenue, tax, shipping, coupon } = getPurchaseObjectData(
    eventData
  )

  const { transactionProducts, currency } = eventData

  const items = getPurchaseItems(transactionProducts)

  const data = {
    transaction_id: id,
    value: revenue,
    tax,
    shipping,
    coupon,
    items,
    currency,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function addPaymentInfo(eventData: AddPaymentInfoData) {
  const eventName = 'add_payment_info'

  const { currency, payment, items: eventDataItems } = eventData
  const { value, group } = payment

  const { items } = formatCartItemsAndValue(eventDataItems)

  const formattedValue = value / 100

  const data = {
    currency,
    value: formattedValue,
    payment_type: group,
    items,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function beginCheckout(eventData: BeginCheckoutData) {
  const eventName = 'begin_checkout'

  const { currency, items: eventDataItems } = eventData

  const { items, totalValue } = formatCartItemsAndValue(eventDataItems)

  const data = {
    currency,
    value: totalValue,
    items,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function addShippingInfo(eventData: AddShippingInfoData) {
  const eventName = 'add_shipping_info'

  const { currency, items: eventDataItems, shippingTier, value } = eventData

  const { items } = formatCartItemsAndValue(eventDataItems)

  const data = {
    currency,
    value,
    items,
    shipping_tier: shippingTier,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function viewCart(eventData: ViewCartData) {
  const eventName = 'view_cart'

  const { currency, items: eventDataItems } = eventData

  const { items, totalValue } = formatCartItemsAndValue(eventDataItems, {
    dividePrice: true,
  })

  const data = {
    currency,
    value: totalValue,
    items,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function addToWishlist(eventData: AddToWishlistData) {
  const eventName = 'add_to_wishlist'

  const { currency, items, list } = eventData

  const { product } = items

  const {
    sku,
    productName,
    productId,
    categories,
    brand,
    productReference,
  } = product

  const variant = sku ? sku.itemId : items.selectedItem.itemId

  const seller = getSeller(sku ? sku.sellers : items.selectedItem.sellers)
  const value = getPrice(seller)
  const categoriesHierarchy = getCategoriesWithHierarchy(categories)
  const discount = getDiscount(seller)
  const quantity = getQuantity(seller)

  const item = {
    item_id: productId,
    item_name: productName,
    item_list_name: list,
    item_brand: brand,
    item_variant: variant,
    discount,
    quantity,
    price: value,
    ...categoriesHierarchy,
    ...customDimensions({
      productReference,
      skuReference: sku ? sku.referenceId.Value : items.selectedItem.referenceId,
      skuName: sku ? sku.name : items.selectedItem.name,
      quantity,
    }),
  }

  const data = {
    currency,
    value,
    items: [item],
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function refund(eventData: RefundData) {
  const eventName = 'refund'

  const { currency } = eventData

  const {
    tax,
    shipping,
    value,
    transactionId,
    items: orderItems,
  } = eventData.order

  const items = getPurchaseItems(orderItems)

  const data = {
    transaction_id: transactionId,
    value,
    tax,
    shipping,
    items,
    currency,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function login(eventData: LoginData) {
  const eventName = 'login'

  const { method } = eventData

  const data = {
    method,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function signUp(eventData: SignUpData) {
  const eventName = 'sign_up'

  const { method } = eventData

  const data = {
    method,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function search(eventData: SearchData) {
  const eventName = 'search'

  const { term } = eventData

  const data = {
    search_term: term,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

export function share(eventData: ShareData) {
  const eventName = 'share'

  const { method, contentType, itemId } = eventData

  const data = {
    method,
    content_type: contentType,
    item_id: itemId,
  }

  updateEcommerce(eventName, { ecommerce: data })
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/customDimensions.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ProductViewData, ProductViewReferenceId } from '../typings/events'

type CustomDimensionSkuAvailability = 'available' | 'unavailable'

interface CustomDimensions {
  /** Product reference */
  dimension1: string
  /** SKU reference */
  dimension2: string
  /** SKU name */
  dimension3: string
  /** SKU availability */
  dimension4: CustomDimensionSkuAvailability
}

interface CustomDimensionParams {
  productReference?: string
  skuReference?: string
  skuName?: string
  quantity: number
}

export function customDimensions(
  params: CustomDimensionParams
): CustomDimensions {
  return {
    dimension1: params.productReference ?? '',
    dimension2: params.skuReference ?? '',
    dimension3: params.skuName ?? '',
    dimension4: customDimensionSkuAvailability(params.quantity),
  }
}

export function customDimensionSkuAvailability(
  quantity: number
): CustomDimensionSkuAvailability {
  return quantity ? 'available' : 'unavailable'
}

export function productViewSkuReference(
  product: ProductViewData['product']
): string {
  const defaultReference = { Value: '' }

  // The `vtex:productView` is the only event where the
  // `product.selectedSku.referenceId` is different between its type and actual
  // data. Type `Item` (for `selectedSku`) specifies `referenceId` as a single
  // `{ Key: string; Value: string }` object type. However, in this event,
  // `referenceId` comes as an array of that object.
  //
  // This type conversion is needed because vtex.store does not normalize the
  // SKU Reference ID. Doing that there could possibly break some apps or
  // stores, so it's better doing it here.
  const skuReferenceId = (
    ((product.selectedSku
      .referenceId as unknown) as ProductViewReferenceId)?.[0] ??
    defaultReference
  ).Value

  return skuReferenceId ?? ''
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/utils/shouldSendGA4Events.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
export default function shouldSendGA4Events() {
  return Boolean(window?.__gtm__?.sendGA4Events)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/analytics/utils.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
// Almost all of the logic of expiration and campaign invalidation is based on this official GA article https://support.google.com/analytics/answer/2731565

export interface AnalyticsData {
  location: string
  referrer: string
  expires: number
}

export interface AnalyticsDataWithOrigin extends AnalyticsData {
  origin: 'storage' | 'fresh'
}

export const UTM_SOURCE_PARAM = 'utm_source'
export const UTM_MEDIUM_PARAM = 'utm_medium'

// All of these parameters trigger a new session storage of the url
// This list was inspired by Simo Ahava's list used on his cookie implementation of this feature
// https://www.simoahava.com/analytics/persist-campaign-data-landing-page/#setup-the-persist-campaign-data-tag
export const analyticsURLParams = [
  UTM_SOURCE_PARAM,
  UTM_MEDIUM_PARAM,
  'utm_campaign',
  'gclid',
  'utm_term',
  'utm_content',
  'utm_id',
] as const

export function shouldInvalidateCurrentCampaign(
  location: Location,
  referrer: string,
  storageReferrer: string
) {
  const referrerURL = referrer ? new URL(referrer) : null

  // if user comes from a referring website
  if (
    referrerURL &&
    referrer !== storageReferrer &&
    referrerURL.host !== location.host
  ) {
    return true
  }

  // the slice removes the initial "?" character
  const individualLocationParams = location.search.slice(1).split('&')

  return individualLocationParams.some(locationParam => {
    return analyticsURLParams.some(campaignParam =>
      locationParam.startsWith(`${campaignParam}=`)
    )
  })
}

const STORAGE_KEY_ANALYTICS_DATA = 'analytics:session'

export function getAnalyticsFromStorage(): AnalyticsData | null {
  let analyticsData = null

  try {
    const rawAnalyticsData = window.localStorage.getItem(
      STORAGE_KEY_ANALYTICS_DATA
    )

    analyticsData = rawAnalyticsData ? JSON.parse(rawAnalyticsData) : null
  } catch (e) {
    console.error(
      'Error while fetching original browser location from localStorage storage'
    )
  }

  return analyticsData
}

export async function saveAnalyticsOnStorage(analyticsData: AnalyticsData) {
  try {
    window.localStorage.setItem(
      STORAGE_KEY_ANALYTICS_DATA,
      JSON.stringify(analyticsData)
    )
  } catch (e) {
    console.error(
      'Error while saving original browser location on localStorage storage'
    )
  }
}

export function currentDateInSeconds() {
  return Math.floor(Date.now() / 1000)
}

export const THIRTY_MIN_IN_SECONDS = 30 * 60

export function isStorageExpired(expiresIn: number, now: number) {
  return now - expiresIn > 0
}

export function renewExpirationDate() {
  return currentDateInSeconds() + THIRTY_MIN_IN_SECONDS
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of google-tag-manager/react/modules/analytics/index.ts from the google-tag-manager VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  AnalyticsData,
  AnalyticsDataWithOrigin,
  currentDateInSeconds,
  getAnalyticsFromStorage,
  isStorageExpired,
  renewExpirationDate,
  saveAnalyticsOnStorage,
  shouldInvalidateCurrentCampaign,
} from './utils'

export function createOrGetAnalyticsData(): AnalyticsDataWithOrigin {
  let analyticsData = getAnalyticsData()
  let origin: AnalyticsDataWithOrigin['origin'] = 'storage'

  if (!analyticsData) {
    analyticsData = createAnalyticsData()
    origin = 'fresh'
  }

  saveAnalyticsOnStorage(analyticsData)

  return { ...analyticsData, origin }
}

function getAnalyticsData(): AnalyticsData | null {
  const analyticsFromStorage = getAnalyticsFromStorage()

  if (
    !analyticsFromStorage ||
    isStorageExpired(analyticsFromStorage.expires, currentDateInSeconds()) ||
    shouldInvalidateCurrentCampaign(
      window.location,
      document.referrer,
      analyticsFromStorage.referrer
    )
  ) {
    return null
  }

  return {
    ...analyticsFromStorage,
    expires: renewExpirationDate(),
  }
}

function createAnalyticsData(): AnalyticsData {
  return {
    location: window.location.href,
    referrer: document.referrer,
    expires: renewExpirationDate(),
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/checkout-ui-custom/checkout6-custom.js from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```javascript
// WARNING: THE USAGE OF CUSTOM SCRIPTS IS NOT SUPPORTED. VTEX IS NOT LIABLE FOR ANY DAMAGES THIS MAY CAUSE. THIS MAY BREAK YOUR STORE AND STOP SALES. IN CASE OF ERRORS, PLEASE DELETE THE CONTENT OF THIS SCRIPT.
(function () {})();

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/checkout-ui-custom/checkout-confirmation-custom.js from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```javascript
// WARNING: THE USAGE OF CUSTOM SCRIPTS IS NOT SUPPORTED. VTEX IS NOT LIABLE FOR ANY DAMAGES THIS MAY CAUSE.
// THIS MAY BREAK YOUR STORE AND STOP SALES. IN CASE OF ERRORS, PLEASE DELETE THE CONTENT OF THIS SCRIPT.

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/checkout-ui-custom/checkout5-custom.js from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```javascript
// WARNING: THE USAGE OF CUSTOM SCRIPTS IS NOT SUPPORTED. VTEX IS NOT LIABLE FOR ANY DAMAGES THIS MAY CAUSE. THIS MAY BREAK YOUR STORE AND STOP SALES. IN CASE OF ERRORS, PLEASE DELETE THE CONTENT OF THIS SCRIPT.

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/docs/README.md from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```markdown
# B2C Store Theme

<!-- @import "[TOC]" {cmd="toc" depthFrom=2 depthTo=6 orderedList=false} -->

<!-- code_chunk_output -->

- [Prerequisites](#prerequisites)
  - [Toolbelt](#toolbelt)
  - [Edition](#edition)
- [Setup](#setup)
  - [Peer Dependencies](#peer-dependencies)
  - [Search](#search)
  - [Reviews and Ratings](#reviews-and-ratings)

<!-- /code_chunk_output -->

## Prerequisites

### Toolbelt

Follow this [Developer Docs Guide](https://developers.vtex.com/vtex-developer-docs/docs/vtex-io-documentation-2-basicsetuptodevelopinvtexio) to setup **Toolbelt** and have access to CLI commands.

### Edition

Follow the steps required to setup `vtex.edition-store@3.x` detailed in this [Developer Docs Guide](https://developers.vtex.com/vtex-developer-docs/docs/vtex-io-documentation-2-prerequesites#implementing-the-correct-edition-app)

## Setup

### Peer Dependencies

Install theme peer dependencies and accept all terms of use/service:

```sh
vtex install \
    vtex.wish-list@1.x \
    vtex.reviews-and-ratings@2.x \
    vtex.location-availability@0.x \
    vtex.shopper-location@0.x \
    vtex.wordpress-integration@2.x
```

### Search

Follow the steps detailed in the section [Implementing the VTEX Intelligent Search](https://developers.vtex.com/vtex-developer-docs/docs/vtex-io-documentation-2-prerequesites#implementing-the-vtex-intelligent-search) of the Prerequisites for Store Framework development guide.

Go to: **STORE SETUP** → **Search** → **Integration settings** (`https://{{account}}.myvtex.com/admin/search/integration-settings`) and click "Start Integration"

![Screen Shot 2021-02-18 at 08.31.00](/assets/Screen%20Shot%202021-02-18%20at%2008.31.00.png)

Wait until all the steps are completed.

![Screen Shot 2021-02-18 at 08.32.31](/assets/Screen%20Shot%202021-02-18%20at%2008.32.31.png)

### Reviews and Ratings

Go to **PRODUCTS** → **Catalog** → **Reviews** (`https://{{account}}.myvtex.com/admin/reviews-ratings/pending`);

Click "Reviews Settings →" in the top right conrner.

![Screen Shot 2021-02-25 at 10.12.49](/assets/Screen%20Shot%202021-02-25%20at%2010.12.49.png)

Check "Display stars in product-rating-summary if there are no reviews"

Uncheck "Display total reviews number on product-rating-summary block"

Click "Save"

![Screen Shot 2021-02-18 at 10.15.38](/assets/Screen%20Shot%202021-02-18%20at%2010.15.38.png)

You should see a toast message saing: "Your data was submitted successfully."

![Screen Shot 2021-02-18 at 10.21.00](/assets/Screen%20Shot%202021-02-18%20at%2010.21.00.png)

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/store/interfaces.json from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store.search.product-comparison": {
    "around": ["comparison-context-wrapper"]
  },
  "store.custom.product-comparison": {
    "around": ["comparison-context-wrapper"]
  },
  "search-result-layout.desktop.product-comparison": {
    "allowed": ["product-comparison-drawer"]
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/store/routes.json from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store.custom#product-comparison-list": {
    "path": "/product-comparison"
  },
  "store.custom.product-comparison#deals": {
    "path": "/deals"
  },
  "store.custom.product-comparison#releases": {
    "path": "/releases"
  },
  "store.custom.product-comparison#top-sales": {
    "path": "/top-sales"
  },
  "store.custom.product-comparison#popular": {
    "path": "/popular"
  },
  "store.custom.product-comparison#trending": {
    "path": "/trending"
  },
  "store.custom#customer-services": {
    "path": "/services"
  },
  "store.custom#gift-cards": {
    "path": "/gift-cards"
  },
  "store.custom#company": {
    "path": "/company"
  },
  "store.custom#careers": {
    "path": "/careers"
  },
  "store.custom#sell": {
    "path": "/sell"
  },
  "store.custom#investors": {
    "path": "/investors"
  },
  "store.custom#advertise": {
    "path": "/advertise"
  },
  "store.custom#locations": {
    "path": "/locations"
  },
  "store.custom#accessibility": {
    "path": "/accessibility"
  },
  "store.custom#contact": {
    "path": "/contact"
  },
  "store.custom#help-center": {
    "path": "/help-center"
  },
  "store.custom#pickup": {
    "path": "/pickup"
  },
  "store.custom#recalls": {
    "path": "/recalls"
  },
  "store.custom#returns": {
    "path": "/returns"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/store/plugins.json from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "my-account-pages > my-account-page": "my-account-page.wishlist-page",
  "my-account-menu > my-account-link": "my-account-link.wishlist-link"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.store-link.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.link--popularLink,
.link--trending-link {
  text-decoration: none;
}

.label--popularLink,
.label--trending-link {
  color: #0067c7;
  font-size: 14px;
  line-height: 24px;
  font-weight: bold;
}

.label--popularLink::after,
.label--trending-link::after {
  content: url("assets/icons/chevronBlue.svg");
  margin-left: 8px;
  top: 1px;
  position: relative;
}

.link--networkLink {
  width: 32px;
  height: 32px;
  background: rgba(255, 255, 255, 0.16);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.link--shopByLink {
  width: 100%;
  text-decoration: none;
}

.link--shopByLink:hover :global(.vtex-rich-text-0-x-paragraph--shopByCategory) {
  color: #0067c7;
}

.link--shopByLink:hover .childrenContainer {
  border: 1px solid #0067c7;
}

.childrenContainer--shopByLink {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-flow: column nowrap;
  max-width: 216px;
  height: 196px;
  background: #f3f9ff;
  border-radius: 4px;
  transition: all 0.3s ease;
  border: 1px solid transparent;
}

.childrenContainer--linkCategorySlider {
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
}

.link--linkCategorySlider {
  text-decoration: none;
}

.link--blogLink {
  display: block;
  max-width: 100px;
  width: 100%;
  height: 32px;
  font-size: 14px;
  line-height: 32px;
  text-align: center;
  color: #0067c7;
  background: #f3f9ff;
  text-decoration: none;
}

.childrenContainer--linkMail,
.childrenContainer--linkCall {
  display: flex;
  align-items: center;
  margin: 0;
  height: 48px;
  padding: 0px 20px;
  border-radius: 4px;
  max-width: 280px;
  width: 100%;
}

.childrenContainer--linkCall {
  background-color: var(--fresh-blue-dark);
}

.childrenContainer--linkMail {
  border: 1px solid var(--bg-header);
}

.link--linkCall,
.link--linkMail {
  text-transform: uppercase;
  color: #fff;
  font-size: 14px;
  line-height: 24px;
  font-weight: 700;
  text-decoration: none;
}

.link--linkCall :global(.vtex-store-components-3-x-imageElement),
.link--linkMail :global(.vtex-store-components-3-x-imageElement) {
  margin-right: 12px;
}

.link--linkCall {
  display: block;
  margin-bottom: 12px;
}

.link--quickLink {
  text-decoration: none;
  position: relative;
}

.link--quickLink::after {
  content: url("assets/icons/nav-arrow-right.svg");
  display: block;
  position: absolute;
  color: #717786;
  right: 0;
  top: 50%;
  transform: translate(-50%, -50%);
}

.link--quickOrderButton {
  text-decoration: none;
  padding: 24px;
  background: #f2f5f9;
  border: 1px solid #dee7ef;
  display: block;
  margin-bottom: 8px;
  border-radius: 4px;
  position: relative;
}

.link--quickOrderButton::after {
  content: url("assets/icons/nav-arrow-right-blue.svg");
  display: block;
  position: absolute;
  color: #717786;
  right: 12px;
  top: 50%;
  transform: translate(-50%, -50%);
}

.link--orderQuote {
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #fff;
  height: 100%;
  font-weight: 500;
  font-size: 14px;
  line-height: 20px;
}

@media (max-width: 64rem) {
  .childrenContainer--accountLink :global(.vtex-store-icons-0-x-profileIcon) {
    width: 20px;
    height: 20px;
  }

  .link--footerLink {
    color: #fff;
    font-size: 16px;
    line-height: 48px;
    font-weight: 500;
    text-decoration: none;
  }

  .link--networkLink {
    width: 32px;
    height: 32px;
    background: rgba(255, 255, 255, 0.16);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.product-comparison.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.drawerContainer {
  z-index: 6;
}

.productSelectorContainer {
  opacity: 0;
  transition: all 0.3s ease;
}

.productSelectorContainer :global(.vtex-checkbox__line-container) {
  justify-content: center;
}

.productSelectorContainer :global(.vtex-checkbox__label) {
  width: auto;
}

.productSelectorContainer :global(.vtex-checkbox__inner-container) {
  width: 20px;
  height: 20px;
  border-width: 1px;
}

.productSelectorContainer :global(.vtex-checkbox__container),
.productSelectorContainer :global(.vtex-checkbox__input) {
  width: 20px;
  height: 20px;
}

.imageElement--paymentImage {
  margin: 0px auto;
}
.showDifferencesContainer :global(.vtex-checkbox__inner-container),
.productSelectorContainer :global(.vtex-checkbox__inner-container) {
  border-color: #a3afbc;
}

.productSelectorContainer :global(.vtex-checkbox__box-wrapper) {
  width: 20px;
  height: 20px;
}

.productSelectorContainer :global(.vtex__icon-check) {
  width: 16px;
  height: 16px;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.search.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.tileList .tileListList {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 12px;
  padding: 0px 24px;
  margin: 0;
}

.tileListTitle {
  display: none;
  opacity: 0;
}

.biggy-autocomplete {
  padding-top: 0;
}

.tileList,
.itemList--suggestion {
  padding-top: 24px;
}

.itemListTitle {
  font-size: 20px;
  line-height: 24px;
  font-weight: 500;
  color: #000;
  text-transform: initial;
}

@media (max-width: 64rem) {
  .biggy-autocomplete {
    padding: 0;
  }

  .tileList .tileListList {
    grid-template-columns: 1fr;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.product-price.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.sellingPrice--desktop {
  font-size: 24px;
  font-weight: normal;
  line-height: 32px;
  color: #000000;
}

.sellingPrice .sellingPriceValue--desktop {
  display: none;
}

.sellingPriceWithTax--desktop {
  font-size: 28px;
  font-weight: bold;
}

.listPrice--desktop {
  font-size: 16px;
  line-height: 20px;
  text-decoration-line: line-through;
  color: #717786;
}

.savings--desktop {
  font-size: 14px;
  line-height: 20px;
  color: #717786;
}

.savingsValue--desktop {
  color: #468a2e;
  font-weight: 500;
}

.savings--savingSummary {
  display: block;
  background: #e5f1e1;
  color: #468a2e;
  text-transform: uppercase;
  font-size: 12px;
  line-height: 18px;
  font-weight: 500;
  padding: 0px 8px;
  border-radius: 10px;
}

.savings--savingPercentage {
  display: block;
  background: var(--fresh-orange);
  color: #fff;
  text-transform: uppercase;
  font-size: 12px;
  line-height: 18px;
  font-weight: 700;
  padding: 0px 8px;
  border-radius: 10px;
}

.savings--savingPercent {
  margin-left: 4px;
  color: #468a2e;
  font-weight: 500;
}

@media (max-width: 64rem) {
  .savings--savingPercent {
    color: #000;
  }

  .currencyContainer--sticky {
    font-size: 20px;
    line-height: 28px;
    color: #000;
    font-weight: bold;
  }
}

/* Seller Name */

.sellerNameContainer--default {
  font-size: 0.875rem;
  color: var(--black-medium);
  margin-bottom: 0.5rem;
}

.sellerName--default {
  color: var(--black-dark);
  font-weight: 500;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.product-customizer.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.textInputValue {
  margin-top: 8px !important;
}

.textInputValue :global(.vtex-input-prefix__group) {
  border: none;
}

.textInputValue :global(.vtex-styleguide-9-x-input) {
  background: #ffffff;
  border: 1px solid #a3afbc;
  box-sizing: border-box;
  border-radius: 4px;
  padding: 0 20px;
}

.textInputValue :global(.vtex-input__label) {
  display: none;
}

.textInputValue::after {
  display: inline-block;
  color: #717786;
  content: "Max. of 20 characters";
  font-size: 12px;
  margin-top: 8px;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.store.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
:global(.vtex-store__template),
:global(.vtex-modal-layout-0-x-container),
:global(.vtex-minicart-2-x-drawer),
:global(.vtex-telemarketing-2-x-portalContainer),
:global(.vtex-login-2-x-portalContainer) {
  --black-dark: #000000;
  --fresh-blue: #0067c7;
  --fresh-blue-dark: #0067c7;
  --fresh-blue-lightest: #f3f9ff;
  --fresh-orange: #ff5f00;
  --fresh-darkest: #003364;
  --green-dark: #468a2e;
  --black-medium: #717786;
  --bg-header: var(--fresh-blue-lightest);
  --blue-medium: #597298;
  --b2b-blue-darkest: #1b3255;
  --lines-dark: #bdc9d6;
  --lines-darker: #a3afbc;
  --lines-light: #dee7ef;
  --serious-blue-dark: #214d8e;
  --serious-black: #142032;
  --serious-orange: #ff7d30;
  --base: #fff;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.quickorder.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
@media (max-width: 64rem) {
  .categoryButtonAdd {
    padding: 0;
  }

  .categoryButtonAdd :global(.vtex-button) {
    width: 100%;
    height: 48px;
    background: var(--serious-orange);
    border-radius: 4px;
    display: block;
    line-height: 48px;
    border: none;
    margin: 16px 0px 24px;
  }

  .categoryContainer .textContainer :not(:global(.vtex-fake)) {
    margin: 0;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.orderquote.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.containerCreate,
.containerList,
.containerView {
  max-width: 1440px;
  width: 100%;
  padding: 0px;
  margin: 0px auto;
}

.buttonSave :global(.vtex-button),
.createButton :global(.vtex-button),
.buttonUse :global(.vtex-button) {
  background: var(--serious-blue-dark);
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.minicart.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.drawer {
  z-index: 999;
}

.minicartIconContainer {
  color: var(--black-dark);
}

.closeIconContainer::before {
  content: "My cart";
  font-size: 24px;
  line-height: 32px;
  color: var(--black-dark);
  font-weight: 500;
}

.closeIconButton {
  margin-left: auto;
  padding: 12px 0px;
}

.closeIconContainer {
  background: var(--fresh-blue-lightest);
  align-items: center;
  padding: 0px 24px;
}

.minicartTitle {
  display: none;
  opacity: 0;
}

.openIconContainer {
  padding: 0;
}

.openIconContainer :global(.vtex-button) {
  border: none;
  border-radius: 0;
  outline: none;
}

.minicartQuantityBadge {
  background-color: var(--fresh-orange);
  font-weight: 700;
}

.minicartCheckoutButton {
  padding: 12px 16px 16px;
  margin: 0;
}

.minicartCheckoutButton :global(.vtex-button) {
  height: 52px;
  background: var(--fresh-orange);
  border-radius: 4px;
  border: none;
  font-weight: 700;
  font-size: 18px;
  line-height: 28px;
  outline: none;
}

@media (max-width: 64rem) {
  .openIconContainer {
    padding: 0;
  }

  .drawer {
    width: 100% !important;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.sku-list.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.skuContentWrapper {
  cursor: pointer;
  border-radius: 0;
  border-width: 0.0625rem;
  margin: 0 -0.5rem -0.0625rem;
  padding: 0.5rem 1rem;
}

.skuContentWrapper:focus {
  outline: none;
}

.skuContentWrapper:first-child {
  margin-top: -0.5rem;
  border-top-left-radius: 0.25rem;
  border-top-right-radius: 0.25rem;
}

.skuContentWrapper:last-child {
  margin-bottom: -0.5rem;
  border-bottom-left-radius: 0.25rem;
  border-bottom-right-radius: 0.25rem;
}

.itemHighlight,
.priceContainer,
.inventoryContainer,
.highlightContent {
  padding: 0;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.rich-text.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
/* BEGIN - Header */
.container--HeaderStripeText {
  margin-right: 24px;
}

.container--HeaderStripeText .link {
  color: #fff;
  font-weight: 500;
  font-size: 14px;
  line-height: 20px;
  text-decoration: none;
}

.headingLevel2--menuTitle {
  font-size: 20px;
  line-height: 24px;
  font-weight: 500;
  color: #000;
  margin: 0;
  margin-bottom: 24px;
}

.container--menuTitle {
  margin-top: 38px;
  padding-top: 38px;
  border-top: 1px solid #dee7ef;
}

.headingLevel2--quickTitle {
  font-size: 20px;
  line-height: 28px;
  color: #000;
  font-weight: 500;
  margin: 0;
  margin-bottom: 4px;
  display: flex;
  align-items: center;
}

.headingLevel2--quickTitle::before {
  content: url("assets/icons/quickOrderIcon.svg");
  display: block;
  margin-right: 10px;
  width: 22px;
  height: 22px;
}

.paragraph--quickText {
  font-size: 14px;
  line-height: 20px;
  margin: 0;
  color: #717786;
}

/* END - Header */
/* BEGIN - Generic */

.headingLevel3--sectionTitle,
.headingLevel3--shopByCategoryTitle {
  font-size: 24px;
  font-weight: 500;
  line-height: 32px;
  color: #000000;
  margin: 0;
  margin-bottom: 16px;
}

.wrapper--alsoView,
.wrapper--sectionTitle {
  width: 100%;
}

.headingLevel3--alsoView,
.headingLevel3--sectionTitle {
  padding-bottom: 16px;
  border-bottom: 1px solid #e9eff5;
}

.headingLevel3--alsoView {
  font-size: 24px;
  font-weight: 500;
  line-height: 32px;
  color: #000000;
  margin: 0;
  margin-bottom: 16px;
  margin-top: 32px;
}

/* END - Generic */
/* BEGIN - ShopByCategory */

.wrapper--shopByCategory {
  width: 100%;
  height: 100%;
}

.paragraph--shopByCategory {
  margin: 0;
  height: 100%;
}

.link--shopByCategory {
  display: flex;
  flex-flow: column;
  align-items: center;
  text-decoration: none;
  height: 100%;
  justify-content: center;
}

.image--shopByCategory {
  display: block;
  margin-bottom: 24px;
}

.strong--shopByCategory {
  font-size: 18px;
  line-height: 24px;
  color: #000;
  font-weight: 400;
}

/* END - ShopByCategory */
/* BEGIN - QuickViewTrigger */

.container--quickviewTrigger .image {
  display: block;
  width: 20px;
}

/* END - QuickViewTrigger */
/* BEGIN - BannerThird */

.headingLevel4--bannerTitle {
  margin: 0;
  margin-bottom: 12px;
  font-size: 20px;
  line-height: 28px;
  font-weight: 500;
  color: #000;
}

.paragraph--bannerDesc {
  max-width: 388px;
  width: 100%;
  margin: 0px auto 16px;
  color: #717786;
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
}

.container--bannerTitle,
.container--bannerDesc,
.container--bannerLink {
  display: flex;
  align-items: center;
  justify-content: center;
}

.paragraph--bannerLink {
  margin: 0;
}

.link--bannerLink {
  width: 244px;
  height: 48px;
  background-color: #0067c7;
  border-radius: 4px;
  color: #fff;
  font-size: 14px;
  line-height: 48px;
  font-weight: 700;
  display: block;
  text-decoration: none;
}

/* END - BannerThird */
/* BEGIN - Benefits Bar */

.wrapper--benefitsItem .paragraph {
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
  margin: 0;
  color: #717786;
  font-size: 14px;
  line-height: 20px;
}

.wrapper--benefitsItem .image {
  object-fit: contain;
  display: block;
  margin-bottom: 24px;
  width: 34px;
  height: 26px;
}

.wrapper--benefitsItem .strong {
  font-size: 18px;
  line-height: 24px;
  color: #000;
  font-weight: 500;
  display: block;
  margin: 0;
  margin-bottom: 8px;
}
/* END - Benefits Bar */
/* BEGIN - Footer */

.paragraph--footerStripe {
  font-size: 12px;
  line-height: 18px;
  color: rgba(225, 239, 255, 0.5);
  margin: 0;
  padding: 32px 0px;
}

.paragraph--footerTitle {
  margin: 0;
  color: #e1efff;
  margin-bottom: 16px;
  font-size: 18px;
  line-height: 24px;
  font-weight: 500;
}

.paragraph--mailTo,
.paragraph--callTo {
  text-transform: uppercase;
  color: #fff;
  font-size: 14px;
  line-height: 24px;
  font-weight: 700;
  text-decoration: none;
  margin: 0;
}

.paragraph--footerText {
  margin: 0;
  color: #e1efff;
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  text-align: left;
}

.paragraph--footerRights {
  font-size: 14px;
  line-height: 24px;
  color: #fff;
}

.paragraph--followTitle {
  margin: 0;
  margin-bottom: 16px;
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.5);
}

/* END - Footer */
/* BEGIN - Trending Shelf */

.heading--trending-title {
  font-size: 24px;
  line-height: 32px;
  color: #000;
  margin: 0;
}

/* END - Trending Shelf */
/* BEGIN - Popular Shelf */

.headingLevel3--popularTitle {
  font-size: 24px;
  line-height: 32px;
  color: #000;
  font-weight: 500;
  margin: 0;
  margin-bottom: 16px;
}

/* END - Popular Shelf */
/* BEGIN - QuickOrder */

.headingLevel3--titleQuickorder {
  margin-left: 0.5rem;
}

/* END - QuickOrder */
/* BEGIN - Search Page */

.paragraph--SEOText {
  font-size: 14px;
  line-height: 18px;
  color: #717786;
  margin: 0;
  margin-bottom: 24px;
}

.paragraph--textCategorySlider {
  font-size: 14px;
  line-height: 20px;
  color: #717786;
  margin: 0;
}

.paragraph--blogSEO {
  max-height: 400px;
  overflow: auto scroll;
  padding: 0;
  margin: 0;
  font-size: 14px;
  line-height: 20px;
  color: #717786;
}

.heading--blogTitle {
  font-size: 16px;
  line-height: 20px;
  font-weight: 500;
  margin: 0;
  margin-bottom: 8px;
  color: #000;
}

.paragraph--blogDescription {
  font-size: 14px;
  line-height: 18px;
  color: #717786;
  margin: 0;
  margin-bottom: 24px;
}

/* END - Search Page */

@media (max-width: 64rem) {
  .paragraph--blogSEO {
    width: 100%;
    max-width: 100%;
    margin: 0;
    padding: 0;
    max-height: initial;
    margin-bottom: 40px;
  }

  .headingLevel3--blogSecondarySEO {
    font-size: 18px;
    line-height: 28px;
    color: #000;
    margin: 0;
    margin-bottom: 40px;
  }

  .wrapper--shopByCategoryTitle {
    margin: 0px auto;
  }

  .headingLevel3--sectionTitle {
    border: none;
    padding: 0;
    margin: 0;
  }

  .link--sectionLink {
    text-decoration: none;
    font-size: 14px;
    line-height: 24px;
    color: var(--fresh-blue);
    display: flex;
    align-items: center;
  }

  .link--sectionLink::after {
    content: url("assets/icons/chevronRight.svg");
    display: block;
    margin-left: 8px;
    height: 21px;
  }

  .headingLevel4--bannerTitle {
    max-width: 250px;
    width: 100%;
    margin: 0px auto 12px;
    font-size: 20px;
    line-height: 28px;
    font-weight: 500;
  }

  .paragraph--bannerDesc {
    font-size: 14px;
    line-height: 20px;
  }

  .link--bannerLink {
    height: 40px;
    line-height: 40px;
  }

  .headingLevel3--titleWithBorder {
    font-size: 24px;
    line-height: 32px;
    font-weight: 500;
    color: #000;
    margin: 0;
    margin-bottom: 16px;
    padding-bottom: 16px;
    border-bottom: 1px solid #e9eff5;
    text-align: center;
  }

  .wrapper--titleWithBorder {
    width: 100%;
  }

  .paragraph--benefitsItem {
    text-align: center;
    font-size: 12px;
    line-height: 16px;
  }

  .strong--benefitsItem {
    font-size: 16px;
    line-height: 24px;
  }

  .container--paymentLabel {
    justify-content: center;
  }

  .paragraph--paymentLabel {
    margin: 0;
    font-size: 12px;
    line-height: 16px;
    margin-bottom: 12px;
    color: rgba(255, 255, 255, 0.5);
  }

  .paragraph--footerStripe {
    text-align: center;
    padding: 0px;
    margin-bottom: 24px;
  }

  .container--copyright {
    justify-content: center;
  }

  .paragraph--copyright {
    margin: 0;
    margin-bottom: 8px;
    font-size: 12px;
    line-height: 16px;
    font-weight: 500;
    color: #fff;
  }

  .link--HeaderStripeText {
    white-space: nowrap;
  }

  .paragraph--HeaderStripeText,
  .container--HeaderStripeText {
    margin: 0;
  }

  .paragraph--SEOText {
    font-size: 12px;
    line-height: 16px;
  }

  .headingLevel2--quickOrderButtonTitle {
    font-size: 16px;
    line-height: 24px;
    color: #000;
    margin: 0;
    margin-bottom: 4px;
  }

  .paragraph--quickOrderButtonText {
    font-size: 14px;
    line-height: 18px;
    color: #717786;
    margin: 0;
    max-width: 240px;
  }

  .wrapper--quickOrderTitlePageMobile {
    width: 100%;
  }

  .headingLevel1--quickOrderTitlePageMobile {
    font-size: 24px;
    line-height: 32px;
    margin: 0;
    color: #000;
    padding-bottom: 16px;
    margin-bottom: 24px;
    border-bottom: 1px solid #e9eff5;
  }
}

.paragraph--disclosure-trigger-heading {
  color: #000000;
  font-weight: 500;
  font-size: 20px;
  line-height: 24px;
  margin: 0;
  padding: 0;
}

.paragraph--skuList {
  margin: 0;
  line-height: 1.5;
}

.paragraph--modal-trigger-shipping-availability {
  cursor: pointer;
}

.paragraph--modal-trigger-shipping-availability:hover {
  text-decoration: underline;
}

/* Reset Spacing */

.container--reset-spacing,
.container--reset-spacing :not(:global(.vtex-fake)) {
  margin: 0;
  padding: 0;
}

.container--black-medium {
  color: var(--black-medium);
}

.container--fw5 {
  font-weight: 500;
}

.container--newsletter-title,
.wrapper--newsletter-title {
  width: 100%;
}

.container--newsletter-title .heading {
  color: #fff;
  font-size: 2rem;
  font-weight: 500;
  line-height: 1.25;
  margin-right: auto;
}

@media (max-width: 64rem) {
  .container--newsletter-title .heading {
    font-size: 1.25rem;
    line-height: 1.4;
    margin-bottom: 0.75rem;
    text-align: center;
  }
}

.paragraph--form-section-title {
  margin: 0;
  margin-bottom: 0.5rem;
}

.paragraph--product-price-message,
.paragraph--product-summary-price-message {
  text-align: center;
  color: var(--black-medium);
  font-weight: 500;
  margin: 0;
  padding: 0;
}

.paragraph--product-summary-price-message {
  font-size: 0.75rem;
  line-height: 1.5;
}

.container--product-price-message,
.container--product-summary-price-message {
  border: 1px solid var(--lines-dark);
  border-radius: 0.25rem;
  padding: 1rem;
}

.container--product-summary-price-message {
  margin-bottom: 0.5rem;
  padding: 0.5rem;
}

.wrapper--product-price-message,
.wrapper--product-summary-price-message {
  width: 100%;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.store-icons.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.caretIcon--fresh-blue {
  color: var(--fresh-blue);
}

.caretIcon--lines-darker {
  color: var(--lines-darker);
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.login.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.container :global(.vtex-button) {
  border: 1px solid var(--fresh-blue-dark);
  border-radius: 4px;
  min-height: 3rem;
}

.container :global(.vtex-button__label) {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

.label {
  display: block;
  color: var(--fresh-blue);
  text-transform: initial;
  font-size: 16px;
  line-height: 24px;
  padding-left: 0;
}

.profile {
  color: inherit;
}

.sendButton :global(.vtex-button) {
  background: #214d8e;
  border: none;
}

@media (max-width: 64rem) {
  .profile {
    display: block;
  }

  .label {
    font-size: 14px;
    line-height: 32px;
    font-weight: 500;
  }
}

.buttonLink :global(.vtex-button) {
  border-color: var(--fresh-blue-dark);
  min-height: 2rem;
}

.buttonLink :global(.vtex-button__label) {
  padding-left: 1.25rem;
  padding-right: 1rem;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.product-summary.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.container--summaryComplete {
  position: relative;
  max-width: 240px;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 20px;
  transition: all 0.3s ease;
}

.containerNormal--minimumSummary {
  padding: 0 0.5rem;
}

.container--summaryComplete:hover {
  border-color: #dee7ef;
}

.container--summaryComplete:hover
  :global(.vtex-product-comparison-0-x-productSelectorContainer),
.container--summaryComplete:hover .buyButtonContainer,
.container--summaryComplete:hover
  :global(.vtex-flex-layout-0-x-flexRow--product-summary-buy-button),
.container--summaryComplete:hover
  :global(.vtex-wish-list-1-x-wishlistIconContainer),
.container--summaryComplete:hover
  :global(.vtex-modal-layout-0-x-triggerContainer) {
  opacity: 1;
}

.container--summaryComplete
  :global(.vtex-store-components-3-x-installmentsPrice) {
  display: none;
}

.container--summaryComplete .buyButton :global(.vtex-button),
.container--summaryComplete
  :global(.vtex-flex-layout-0-x-flexRow--product-summary-buy-button)
  :global(.vtex-button) {
  border: none;
  background-color: var(--fresh-orange);
  height: 48px;
  border-radius: 4px;
}

.priceContainer {
  align-items: flex-start;
}

.nameWrapper,
.price_sellingPriceContainer,
.price_listPriceContainer {
  text-align: left;
  padding-bottom: 0;
  margin-bottom: 4px;
}

.price_sellingPriceLabel,
.element--minimumSummary .price_listPriceContainer,
.element--minimumSummary .price_installmentContainer {
  display: none;
  overflow: 0;
  visibility: hidden;
}

.container--summaryComplete .price_listPrice,
.container--summaryComplete .price_sellingPrice {
  padding: 0;
}

.container--summaryComplete .productBrandContainer {
  font-size: 14px;
  color: #0067c7;
  font-weight: 500;
  line-height: 20px;
  text-align: left;
}

.container--summaryComplete .nameContainer {
  padding: 0;
}

.container--summaryComplete .productNameContainer {
  text-align: left;
  font-size: 16px;
  line-height: 22px;
  color: #000;
  width: 100%;
  margin-bottom: 16px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.container--summaryComplete .buyButtonContainer,
.container--summaryComplete
  :global(.vtex-flex-layout-0-x-flexRow--product-summary-buy-button) {
  margin-top: auto;
  margin-bottom: 16px;
  padding: 0;
}

.container--summaryComplete .image {
  margin-bottom: 16px;
  width: 196px;
  height: 196px;
  object-fit: contain;
}

.element--summaryComplete {
  padding: 0;
}

.element--summaryComplete .priceContainer {
  align-items: flex-start;
  padding: 0;
}

.element--summaryComplete .buyButtonContainer,
.element--summaryComplete
  :global(.vtex-flex-layout-0-x-flexRow--product-summary-buy-button) {
  opacity: 0;
  transition: all 0.3s ease;
}

.element--summaryComplete .productPriceClass {
  flex-flow: column-reverse;
}

.element--summaryComplete .listPriceLabel,
.element--summaryComplete .sellingPriceLabel {
  display: none;
}

.element--summaryComplete .listPriceValue .currencyContainer {
  font-size: 12px;
  line-height: 16px;
  font-weight: 400;
  color: #717786;
}

.currencyCode {
  margin-right: 4px;
}

/* BEGIN - Trending Shelg */

.column--summaryCol {
  flex-flow: column nowrap;
  align-items: flex-start;
}

.element--trendingSummary
  :global(.vtex-reviews-and-ratings-1-x-inlineContainer) {
  margin: 0;
}

.element--trendingSummary :global(.vtex-flex-layout-0-x-flexRowContent) {
  align-items: center;
}

.element--trendingSummary .imageStackContainer {
  margin-right: 24px;
}

.container--trendingSummary {
  max-width: 100% !important;
  width: 100%;
  background: #fff;
  border-radius: 8px;
  padding: 16px 24px;
  border: 1px solid transparent;
  transition: all 0.3s ease;
}

.container--trendingSummary:hover {
  border: 1px solid var(--fresh-blue);
  box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.1);
}

.element--trendingSummary {
  justify-content: center;
  padding: 0;
}

.element--trendingSummary .price_installmentContainer,
.element--trendingSummary .listPriceContainer {
  display: none;
}

.element--trendingSummary .image {
  width: 96px !important;
  height: 96px;
  object-fit: cover;
}

.element--trendingSummary .nameContainer {
  padding: 0;
  margin-bottom: 8px;
}

.element--trendingSummary .productBrand {
  font-weight: 700;
  text-align: left;
  color: #000;
  font-size: 16px;
  line-height: 22px;
}

.element--trendingSummary .price_sellingPrice,
.element--trendingSummary .price_sellingPriceContainer,
.element--trendingSummary .priceContainer {
  padding: 0;
}

/* END - Trending Shelg */
/* BEGIN - Popular Shelf */

.container--minimumSummary .image {
  width: 192px;
  height: 192px;
  object-fit: contain;
}

/* END - Popular Shelf */

.column--drawer-summary-col2 {
  align-items: flex-start;
}

.element--comparison-page-summary .buyButton :global(.vtex-button),
.element--comparison-page-summary
  :global(.vtex-flex-layout-0-x-flexRow--product-summary-buy-button)
  :global(.vtex-button) {
  border: none;
  height: 48px;
  background: var(--fresh-orange);
}

.element--comparison-page-summary .sellingPrice,
.element--comparison-page-summary .buyButtonContainer,
.element--comparison-page-summary
  :global(.vtex-flex-layout-0-x-flexRow--product-summary-buy-button) {
  padding: 0;
}

/* BEGIN - Search Bar Summary */

.element--summarySearch .imageContainer {
  margin-bottom: 8px;
  width: auto;
  margin-right: auto;
  margin-left: initial;
}

.element--summarySearch .productBrandContainer {
  text-align: left;
}

.element--summarySearch .productBrandContainer .productBrandName {
  font-size: 14px;
  color: #0067c7;
  font-weight: 500;
  line-height: 20px;
  margin-bottom: 4px;
}

.element--summarySearch .nameContainer {
  padding: 0;
  justify-content: flex-start;
}

.element--summarySearch .nameContainer .productBrand {
  font-size: 12px;
  line-height: 18px;
  color: #000;
}

/* END - Search Bar Summary */

@media (max-width: 64rem) {
  .container--summaryComplete {
    padding: 8px;
  }

  .container--summaryComplete {
    min-width: 144px !important;
    max-width: 100% !important;
  }

  .element--minimumSummary
    :global(.vtex-reviews-and-ratings-1-x-inlineContainer) {
    margin: 0;
  }

  .element--minimumSummary .priceContainer {
    align-items: flex-start;
  }

  .element--summaryComplete .price_sellingPrice {
    font-size: 20px;
    color: #000;
    line-height: 24px;
    font-weight: 500;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.location-availability.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.shippingHeader--desktop {
  display: none;
  font-size: 16px;
  font-weight: 500;
  color: black;
}

.shippingListItem--desktop {
  display: none;
}

.shippingListItem--desktop:first-child {
  display: block;
}

.shippingListEmptyMessage,
.shippingDeliveryName--desktop,
.shippingListItem--desktop {
  font-size: 14px;
  color: black;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.modal-layout.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.triggerContainer--quickviewTrigger {
  background: #f3f9fe;
  position: absolute;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  top: 76px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: all 0.3s ease;
  outline: none;
}

.paper--quickviewContainer {
  padding: 32px;
  overflow: visible;
}

.paper--quickviewContainer
  :global(.vtex-store-components-3-x-carouselGaleryThumbs) {
  display: none;
  opacity: 0;
  visibility: hidden;
}

.paper--quickviewContainer
  :global(.vtex-store-components-3-x-productImagesContainer),
.paper--quickviewContainer
  :global(.vtex-store-components-3-x-carouselContainer) {
  width: auto;
}

.paper--quickviewContainer
  :global(.vtex-store-components-3-x-carouselGaleryCursor) {
  margin-left: initial !important;
  width: initial !important;
}

.paper--quickviewContainer
  :global(.vtex-store-components-3-x-productImagesContainer--desktop)::after {
  content: none;
}

.paper--quickviewContainer :global(.vtex-flex-layout-0-x-flexCol--right-col) {
  margin-right: 24px;
}

.paper--quickviewContainer .closeButton {
  width: 32px;
  height: 32px !important;
  display: block;
  position: absolute;
  top: -12px;
  right: -12px;
  min-height: initial;
  border-radius: 50%;
  background: #dee7ef;
  border: none;
  outline: none;
}

.paper--quickviewContainer .closeButtonLabel {
  display: none;
}

.paper--quickviewContainer .closeButton::before {
  content: url("assets/icons/closeQuickviewIcon.svg");
  display: block;
}

/* Shipping Availability */

.headerContainer--shipping-availability {
  align-items: center;
  border-bottom: 1px solid var(--lines-light);
  position: relative;
  padding: 0.5rem 1rem;
}

.closeButtonContainer--shipping-availability {
  align-items: center;
  background-color: var(--lines-light);
  border-radius: 999px;
  display: flex;
  height: 2rem;
  justify-content: center;
  top: 1rem;
  right: 1rem;
  width: 2rem;
}

@media (min-width: 64rem) {
  .paper--shipping-availability {
    overflow: visible;
  }
  .headerContainer--shipping-availability {
    border: none;
    height: 0;
    padding: 0;
  }
  .headerContent--shipping-availability {
    display: none;
  }
  .closeButtonContainer--shipping-availability {
    position: absolute;
    top: 0;
    right: 0;
    transform: translate(50%, -50%);
  }
}

.closeButton--shipping-availability {
  padding: 0;
  font-style: 0;
  line-height: 0;
}

.closeIcon--shipping-availability {
  height: 1.25rem;
  width: 1.25rem;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.sticky-layout.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.container--headerMobile {
  background: var(--bg-header);
  z-index: 999;
}

.wrapper--box--stuck .container--box {
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  margin-left: 354px;
  z-index: 997;
}

.container--sticky-buy {
  background: #fff;
  padding: 8px 0px;
}

.wrapper--sticky-buy {
  height: 0 !important;
  z-index: 999;
}

.container--sticky-buy :global(.vtex-button) {
  height: 48px;
  background: var(--serious-orange);
  border: none;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.store-components.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.container {
  max-width: 1440px;
  width: 100%;
  padding: 0px 32px;
  margin: 0px auto;
}

.logoLink {
  display: block;
  transform: none !important;
}

.logoImage {
  display: block;
  height: 28px;
  width: auto;
}

.searchBarContainer :global(.vtex-input-prefix__group) {
  height: 48px;
}

.imageElement--vtexLogo {
  max-width: 67px;
  object-fit: contain;
  margin-right: 16px;
}

.newsletter {
  max-width: 100%;
  margin: 0;
  height: 104px;
  display: flex;
  align-items: center;
  background: var(--bg-header);
}

.newsletter .container {
  padding: 0px 32px;
}

.productImageTag--sellersPage--main {
  max-width: 168px;
}

.newsletter .form {
  display: flex;
  align-items: center;
  max-width: 100%;
}

.newsletter .form .label {
  font-size: 32px;
  line-height: 40px;
  font-weight: 500;
  margin-right: auto;
  color: #fff;
}

.newsletter .inputGroup {
  max-width: 680px;
  width: 100%;
  padding: 0;
  position: relative;
}

.newsletter :global(.vtex-input-prefix__group) {
  height: initial;
  border: none;
}

.newsletter :global(.vtex-styleguide-9-x-input) {
  height: 56px;
  background: #fff;
  font-size: 20px;
  line-height: 24px;
  color: var(--black-medium);
}

.newsletter :global(.vtex-styleguide-9-x-input)::placeholder {
  color: var(--black-medium);
  font-size: 20px;
  line-height: 24px;
}

.newsletter .buttonContainer {
  position: absolute;
  right: 24px;
  top: 8px;
}

.newsletter .buttonContainer :global(.vtex-button) {
  color: var(--fresh-blue);
  font-size: 16px;
  line-height: 24px;
  font-weight: bold;
  outline: none;
  border: none;
  background: none;
}

.newsletter .buttonContainer :global(.vtex-button__label) {
  padding: 0;
}

.imageElement--bannerThird {
  margin-bottom: 24px;
}

.logoContainer {
  display: block;
  padding: 0;
}

.imageElement--quickviewTrigger {
  width: 20px;
  height: 14px;
  object-fit: contain;
}

.searchBarContainer {
  width: 100%;
  max-width: 856px;
}

.searchBarContainer :global(.vtex-styleguide-9-x-input) {
  max-width: 100%;
  width: 100%;
}

.searchBarContainer :global(.vtex-input__suffix) {
  border-radius: 0px;
}

.imageElement--paymentImage {
  width: 100%;
  object-fit: contain;
  max-height: 18px;
}

.imageElement--networkImage {
  display: block;
}

.imageElement--shoByImage {
  width: 80px;
  height: auto;
  object-fit: contain;
  max-height: 80px;
  max-width: 80px;
  margin-bottom: 16px;
}

.imageElement--imageCategorySlider {
  border: 1px solid #dee7ef;
  padding: 16px;
  border-radius: 50%;
  margin-bottom: 12px;
}

.imageElement--blogImage {
  display: block;
  margin-bottom: 16px;
}

.imageElement--benefitImage {
  margin: 0px auto 24px;
  width: 32px;
  height: 34px;
  object-fit: contain;
}

.userAddressContainer {
  height: 100%;
  background: none;
  padding: 0;
  margin-right: 60px;
}

.userAddressContainer .container {
  padding: 0;
}

@media (max-width: 64rem) {
  .imageElement--blogImage {
    width: 100%;
  }

  .container {
    padding: 0px 16px;
  }

  .imageElement--homeSlider {
    max-height: 384px !important;
    object-fit: cover;
  }

  .newsletter {
    height: 136px;
  }

  .newsletter .container {
    padding: 0;
  }

  .newsletter .form {
    flex-flow: column nowrap;
  }

  .newsletter .form .label {
    font-size: 20px;
    line-height: 28px;
    margin-bottom: 12px;
    width: 100%;
    text-align: center;
  }

  .newsletter .buttonContainer :global(.vtex-button) {
    font-size: 14px;
  }

  .newsletter :global(.vtex-styleguide-9-x-input)::placeholder,
  .newsletter :global(.vtex-styleguide-9-x-input) {
    font-size: 18px;
    line-height: 20px;
  }

  .imageElement--paymentImage {
    margin: 0px auto;
  }

  .searchBarInnerContainer--searchMobile :global(.vtex-input-prefix__group) {
    border: none;
  }

  .searchBarInnerContainer--searchMobile :global(.vtex-styleguide-9-x-input) {
    max-width: 100%;
  }

  .searchIcon--searchMobile {
    display: none;
  }

  .searchBarIcon--searchMobile:not(.searchBarIcon--searchMobile--clear) {
    background: url("assets/icons/searchMobile.svg");
    width: 18px;
    height: 18px;
    display: block;
    background-repeat: no-repeat;
    background-size: contain;
  }

  .imageElement--singleBanner {
    width: 100%;
    object-fit: cover;
  }

  .logoLink {
    display: flex !important;
    align-items: center;
  }

  .logoImage {
    display: block;
    width: 123px;
    height: 24px;
  }

  .suffixWrapper--searchMobile {
    align-items: center;
  }

  .searchBarContainer {
    padding: 0;
  }

  .imageElement--networkImage {
    display: block;
  }

  .resultsList--searchMobile {
    height: 100%;
    max-height: 100%;
    padding: 0px 16px;
  }

  .resultsItem--searchMobile {
    color: #717786;
  }

  .resultsItemName--searchMobile,
  .searchTerm--searchMobile {
    color: #000 !important;
  }

  .productImagesContainer--sellersPage {
    height: 106px !important;
    overflow: hidden;
    width: 106px !important;
    margin-right: 24px;
  }

  .productImageTag--sellersPage--main {
    max-height: 106px;
    object-fit: contain;
  }
}

/* Product Images */

.productImagesContainer--desktop,
.carouselContainer--desktop {
  width: 564px;
}

.carouselGaleryThumbs--desktop {
  max-width: 100px;
}

.productImagesThumb--desktop,
.productImagesThumb--desktop :not(:global(.vtex-fake)) {
  border-radius: 4px;
  overflow: hidden;
}

.productImagesThumbActive--desktop .carouselThumbBorder--desktop {
  border: 1px solid #0067c7;
}

.carouselContainer--desktop .carouselGaleryCursor,
.productImagesGallerySwiperContainer--desktop,
.productImagesGallerySlide--desktop,
.productImage--desktop,
.productImageTag--desktop {
  height: 448px !important;
  width: 448px !important;
}

.carouselContainer--desktop .carouselGaleryCursor {
  margin-left: 100px;
  width: 464px !important;
}

.productImagesContainer--desktop {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.productImagesContainer--desktop::after {
  display: block;
  color: #717786;
  content: "Roll over image to zoom in";
  padding-top: 20px;
  padding-left: 116px;
  font-size: 12px;
  line-height: 16px;
  text-align: center;
}

.productImageTag--desktop--zoom {
  display: none;
}

/* Product Brand */

.productBrandContainer {
  font-size: 14px;
  line-height: 16px;
  color: #0067c7;
}

/* Product Name */

.productNameContainer--product-page {
  color: var(--serious-black);
  font-size: 24px;
  font-weight: 500;
  line-height: 28px;
}

.productNameContainer--minicart {
  color: var(--black-dark);
  font-size: 14px;
  line-height: 18px;
}

/* Sku Selector */

.skuSelectorContainer--desktop .skuSelectorSubcontainer {
  margin-bottom: 20px;
}

.skuSelectorContainer--desktop .skuSelectorNameContainer {
  margin: 0;
}

.skuSelectorContainer--desktop .skuSelectorName,
.skuSelectorContainer--desktop .skuSelectorNameSeparator,
.skuSelectorContainer--desktop .skuSelectorSelectorImageValue {
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  color: #717786;
}

.skuSelectorContainer--desktop .skuSelectorSelectorImageValue {
  color: #000000;
}

.skuSelectorContainer--desktop .skuSelectorTextContainer {
  margin-bottom: 8px;
}

.skuSelectorContainer--desktop .skuSelectorOptionsList {
  margin: 0;
}

.skuSelectorContainer--desktop .skuSelectorItem.skuSelectorItemImage {
  height: 48px;
  width: 48px;
}

.skuSelectorContainer--desktop .skuSelectorItem {
  height: 40px;
}

/* Round SKU Selector */

.skuSelectorContainer--color-round .frameAround {
  border: 1px solid #bdc9d6;
  bottom: 0;
  left: 0;
  right: 0;
  top: 0;
}

.skuSelectorContainer--color-round .skuSelectorItem--selected .frameAround {
  box-shadow: 0 0 0 4px #f3f9ff;
  border-color: #0067c7;
}

.skuSelectorContainer--color-round .skuSelectorInternalBox {
  border: none;
}

.skuSelectorContainer--color-round
  .skuSelectorSubcontainer--cor
  .skuSelectorOptionsList
  :not(:global(.vtex-fake)) {
  border-radius: 9999px;
}

.productImagesContainer--fake-summary {
  pointer-events: none !important;
}

.productImagesContainer--fake-summary :not(:global(.vtex-fake)) {
  display: block;
  float: left;
  overflow: hidden;
  width: 100%;
  height: 100%;
}

.productImagesContainer--fake-summary,
.productImageTag--fake-summary {
  height: 96px !important;
  overflow: hidden;
  width: 96px !important;
}

.productImagesGallerySwiperContainer--fake-summary .swiper-pagination,
.swiperCaret--fake-summary,
.carouselGaleryThumbs--fake-summary {
  display: none !important;
}

.carouselContainer--fake-summary .carouselGaleryCursor {
  padding: 0;
  margin: 0;
  width: 100%;
}

.productNameContainer--fake-summary {
  font-size: 14px;
  line-height: 16px;
}

.productSKUAttributesContainer--inline {
  color: #717786;
  font-size: 14px;
  line-height: 16px;
}

.attributeLine--inline,
.attributeName--inline {
  color: inherit;
  display: inline;
  font-weight: inherit;
  font-size: inherit;
  margin: 0;
  padding: 0;
}

.attributeName--inline::after {
  content: " ";
}

.attributeLine--inline::after {
  content: ", ";
}

.attributeLine--inline:last-child::after {
  content: "";
}

/* Product Description */

@media (min-width: 64rem) {
  .productDescriptionContainer--desktop {
    max-width: 300px;
  }
}

.productDescriptionText {
  font-size: 14px;
  line-height: 1.25;
  color: var(--black-medium);
}

.productDescriptionTitle {
  display: none;
}

.productDescriptionTitle--desktop {
  display: block;
  font-weight: 500;
  font-size: 24px;
  line-height: 32px;
  color: var(--black-dark);
  margin-bottom: 24px;
}

/* Product Images Gallery */

.productImagesGallerySwiperContainer--gallery {
  margin: 0;
  padding: 0;
}

@media (min-width: 64rem) {
  .productImagesGallerySwiperContainer--gallery {
    height: 464px;
    width: 664px;
  }
}

.carouselGaleryThumbs--gallery {
  display: none;
}

.productImagesGallerySlide--gallery {
  margin: 0;
  margin-bottom: 16px;
}

@media (min-width: 64rem) {
  .productImagesGallerySlide--gallery {
    height: 224px;
    width: 50% !important;
    max-width: 324px;
  }
}

.productImagesGallerySwiperContainer--gallery :not(:global(.vtex-fake)) {
  flex-wrap: wrap;
  justify-content: space-between;
  transform: translate3d(0, 0px, 0px) !important; /* Disables swiping */
}

.productImageTag--gallery {
  border-radius: 4px;
}

/* Dots Around */

.productImagesGallerySlide--dots-around {
  padding-bottom: 32px;
}

.productImagesContainer--dots-around .swiper-pagination {
  bottom: 0;
}

.productImagesContainer--dots-around .swiperBullet {
  background-color: var(--lines-dark);
  opacity: 1;
}

.productImagesContainer--dots-around .swiperBullet--active {
  background-color: var(--serious-blue-dark);
}

/* Shipping Simulator */

.shippingContainer
  :not(:global(.vtex-address-form__postalCode)):not(:global(.vtex-input)):not(:global(.vtex-input-prefix__group)):not(:global(.vtex-address-form-4-x-input)):not(:global(.vtex-button)):not(:global(.vtex-button__label)) {
  display: none;
}

.shippingContainer {
  display: flex;
}

@media (min-width: 40rem) {
  .shippingContainer {
    width: 18rem;
  }
}

.shippingContainer :global(.vtex-address-form__postalCode),
.shippingContainer :global(.vtex-button) {
  flex: 1 1 auto;
}

.shippingContainer :global(.vtex-address-form__postalCode) {
  width: 100%;
}

.shippingContainer :global(.vtex-input-prefix__group) {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: none;
  border-width: 0.0625rem;
  height: 2.75rem;
}

.shippingContainer :global(.vtex-address-form-4-x-input) {
  color: var(--black-dark);
}

.shippingContainer :global(.vtex-button) {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-left: none;
  color: var(--fresh-blue-dark);
  width: auto;
}

.shippingContainer :global(.vtex-button):focus {
  outline: none;
}

.shippingContainer :global(.vtex-button):disabled {
  color: var(--lines-light);
}

.shippingContainer :global(.vtex-input-prefix__group),
.shippingContainer :global(.vtex-button) {
  border-width: 0.0625rem;
  border-color: var(--lines-light);
  background-color: #fff;
}

.shippingContainer :global(.vtex-button__label) {
  color: inherit;
  font-size: 0;
}

.shippingContainer :global(.vtex-button__label)::before {
  content: "OK";
  font-size: 0.875rem;
}

.shippingTable,
.shippingTableBody,
.shippingTableRow {
  border: none;
}

.shippingTable {
  margin: 0;
  margin-top: 1rem;
  padding: 0;
}

.shippingTableCell {
  padding: 16px;
}

.shippingTableCellDeliveryName {
  background-color: #f3f9ff;
  padding-top: 32px;
  padding-bottom: 32px;
  height: 92px;
  width: 0px;
  padding-left: 0;
  padding-right: 0;
}

.shippingTableCellDeliveryEstimate {
  border-left: none;
}

.shippingTableRow {
  background-color: #fff;
  border: 1px solid #dee7ef;
  border-radius: 0.25rem;
  display: flex;
  align-items: center;
  margin-bottom: 0.5rem;
}

.shippingTableRow:last-child {
  margin-bottom: 0;
}

.shippingTableLabel {
  white-space: pre;
  font-weight: 500;
  color: #000;
  position: relative;
  padding-left: 16px;
}

.shippingTableRadioBtn {
  display: none;
  margin-right: 36px;
  margin-left: 4px;
  top: 8px;
  position: relative;
}

.shippingTableCellDeliveryPrice {
  font-weight: 500;
  padding-left: 0;
  padding-right: 16px;
  text-align: right;
  width: 100%;
}

.shippingTableCellDeliveryEstimate,
.shippingTableCellDeliveryPrice {
  white-space: pre;
}

.shippingTableCellDeliveryEstimate::before,
.shippingTableCellDeliveryPrice::after {
  content: "\a";
  display: block;
}

.shippingNoMessage {
  color: var(--black-medium);
  text-align: center;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.wish-list.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.wishlistIconContainer {
  position: absolute;
  width: 38px;
  height: 38px;
  display: block;
  border-radius: 50%;
  background: #f3f9fe;
  transition: all .3s ease;
  opacity: 0;
  text-align: center;
}

.wishlistIconContainer :global(.vtex-button):hover,
.wishlistIconContainer :global(.vtex-button){
  outline: none;
  background: none;
}

.wishlistIconContainer :global(.vtex-button__label){
  padding: 0;
}

.wishlistIcon.outline {
  background: url("assets/icons/heartIcon.svg");
  background-repeat: no-repeat;
  background-size: contain;
  width: 19px;
  height: 15px;
}

.wishlistIcon.fill {
  background: url("assets/icons/heartFilled.svg");
  background-repeat: no-repeat;
  background-size: contain;
  width: 19px;
  height: 15px;
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2cstoreqa.theme/styles/css/vtex.wordpress-integration.css from the b2cstoreqa.theme VTEX app.

[Assistant]
Here's the implementation:

```css
.categoryBlockTitle,
.categoryBlockLink {
  display: none;
}

.categoryBlockContainer,
.categoryBlockFlex {
  margin: 0;
  padding: 0;
}

.categoryBlockFlex {
  margin-left: -1rem;
  margin-right: -1rem;
}

.categoryBlockFlexItem {
  margin: 0;
  padding-left: 1rem;
  padding-right: 1rem;
  width: 50%;
}

.categoryBlockFlexItem:first-child {
  width: 100%;
}

@media (min-width: 64em) {
  .categoryBlockFlexItem,
  .categoryBlockFlexItem:first-child {
    width: 25%;
  }
}

.categoryBlockFlexItem :global(.vtex-card) {
  box-shadow: none !important;
}

.teaserImage {
  border-radius: 0.25rem;
  height: auto;
  margin-bottom: 1rem;
  width: 100%;
}

.teaserTitle,
.teaserTitleLink,
.teaserBody {
  padding: 0;
  margin: 0;
}

.teaserTitle,
.teaserTitleLink {
  color: #000;
  font-size: 1rem;
  line-height: 1.25;
  font-weight: 500;
  margin-bottom: 8px;
  text-decoration: none;
}

.teaserBody {
  font-size: 0.875rem;
  line-height: 1.2857142857;
  color: #717786;
  margin-bottom: 24px;
}

```