# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project context

Shopify theme for **Milano1881** (client: We Are Pendulum PTE LTD, Singapore).
Store: `milano1881.myshopify.com` — plan **Shopify** (not Plus), currency **SGD**, single market **Singapore**, timezone +08. **The store is not live yet** (no custom domain connected; primary domain is still the `.myshopify.com` one), but shipping zones already cover the EU, UK, CH, NO, US, AU, JP…

The current engagement is **tracking & marketing setup** (GA4, GSC, GTM, Google Ads, Merchant Center, Meta, consent). The task list with per-task DoD lives in `docs/requierments/todo.md`. Note: `docs/` is in `.gitignore`, so that file is untracked — read it, don't assume it's in git history.

## Commands

There is **no build system**: no `package.json`, no bundler, no tests, no linter config. `assets/*.min.js` and `assets/style.css` are committed build artifacts whose sources are not in this repo.

Shopify CLI 4.7.0 is installed, but the theme is **not yet connected** (no `.shopify/` dir, no store link):

```bash
shopify theme dev --store milano1881.myshopify.com   # local preview + hot reload
shopify theme check                                   # Liquid/theme linting
shopify theme pull --store … --theme <id>             # pull live changes made in the editor
shopify theme push --unpublished                      # push as a new unpublished theme (never push over live)
```

Since merchandisers edit sections in the theme editor, `config/settings_data.json` and the `templates/*.json` drift on the live store — **pull before working**, and prefer pushing to an unpublished duplicate.

## Architecture

Custom theme built by the "360Shop" agency — **not a Dawn derivative**. It mixes Online Store 2.0 JSON templates with a large amount of hand-rolled Liquid and one monolithic minified JS bundle.

### Alternate `.liquid` templates are AJAX render endpoints

Templates such as `cart.json.liquid`, `product.card.liquid`, `collection.product-list.liquid` start with `{% layout none %}` and exist only to be fetched by JS via `?view=<suffix>`:

| URL | Template | Renders |
| --- | --- | --- |
| `/cart?view=json` | `cart.json.liquid` | header cart drawer (`snippets/header-cart.liquid`) |
| `/cart?view=jsonpage` | `cart.jsonpage.liquid` | cart page section |
| `/products/x?view=card` | `product.card.liquid` | product card |
| `/collections/x?view=product-list` | `collection.product-list.liquid` | paginated product grid |
| `?view=quick-buy`, `?view=flash`, `?view=more`, `?view=top-section`, `?view=image-only`, `?view=card-wishlist` | … | partials for the same pattern |

Changing markup in the corresponding snippet changes what the AJAX call returns — check both the full-page and the `?view=` path.

### JavaScript

`assets/vendor.min.js` (~465 KB, 25 lines) bundles **Vue 3 + Swiper + axios + the theme's own `$360` namespace** — minified, no sourcemap, no source in the repo. Treat it as read-only. Add new behaviour in a new asset file or inline in Liquid; do not try to refactor or re-minify it.

- `$360.*` — global app object (`showHeaderCart`, `hideHeaderCart`, `updateHeaderCartCount`, `updateCartPage`, `lazyLoadInstance`…), called directly from inline `onclick` handlers in Liquid.
- `$360Shop` — per-request config object emitted by `snippets/360shop-script.liquid` in `<head>`: money formats, `shop.metafields.global`, and `vSettings` (per-variant `shipping` metafields driving `datepicker.js` for delivery/pickup date rules on product and cart pages).
- Cart is fully AJAX (`axios` → `/cart.js`, then `/cart?view=json`); `/cart/add` is the only form POST (`snippets/product-variants.liquid`).
- Other vendored libs: `tippy.min.js` + `popper.min.js` (tooltips), `datepicker.js`.

### CSS

One 360 KB atomic/utility `style.css` (also a build artifact — do not hand-edit for section-specific needs). Utility classes carry breakpoint prefixes:

- no prefix = mobile-first base, `t-` = ≥600px, `d-` = ≥1024px, `hd-` = ≥1440px
- grid: `col-12`, `col-t-6`, `col-d-4`, `col-hd-7`
- vertical rhythm: `sp-{no|sm|md|lg}` plus `spt-…-half` / `spb-…-half`

Section-specific styling is done with a **scoped `<style>` block at the top of the section**, keyed on a generated id.

### Section conventions

Sections follow a consistent preamble — match it when adding one:

```liquid
{% liquid
  assign section_name = 'Media + Text'
  assign el_id = section_name | handle | append: '-' | append: section.id
  assign padding_class = 'sp-' | append: section.settings.padding
%}
<style>#{{ el_id }} { … }</style>
<section id="{{ el_id }}" class="{{ padding_class }}"> … </section>
{% schema %} … {% endschema %}
```

Every section schema starts with the same "Section Padding" header block (`padding` select + `top_half_padding` / `bottom_half_padding` checkboxes).

### Global design system sections

`layout/theme.liquid` renders five settings-driven sections at the top of `<body>` that emit the site's CSS custom properties and typographic scale: `typography-header`, `typography-body`, `colors`, `buttons`, `links`. Typography and colours are **section-generated CSS**, not `settings.css` — change them there, not in `style.css`.

### Other layout facts

- `theme.liquid` special-cases `/policies/` pages and Shopify `challenge` pages with dedicated wrappers.
- `snippets/json-ld.liquid` holds all structured data (Organization / Product / Breadcrumb) — the SEO-relevant surface for Merchant Center and GSC.
- The theme setting `settings.script` injects raw code at the very end of `<body>` and is the theme's **only** built-in script injection point.
- Wishlist is **Swym** (`snippets/swym-custom.liquid`, `templates/page.wishlist.json`, `product.card-wishlist.liquid`), driven by the `swym:cart-loaded` custom event dispatched from `$360`.
- i18n: `locales/en.default.json` only — English-only store.
- `templates/product.bundle.json` + `sections/bundle-info.liquid` implement product bundles; `templates/product.e-gift-card.json` a digital gift card flow.

## Tracking work — constraints that matter

- **No tracking code exists in the theme today**: no GTM container, no `dataLayer`, no `gtag`, no Meta pixel anywhere in `layout/`, `sections/`, `snippets/`.
- Installed publications are **Online Store, Point of Sale, Shop** only — the **Google & YouTube** and **Facebook & Instagram** sales channels are *not* installed, so the "native" path in the todo is not started.
- Plan is Shopify, not Plus → `checkout.liquid` and Additional Scripts are unavailable/deprecated. Checkout and thank-you page tracking **must** go through Settings → Customer events → **Custom pixel** (Web Pixels API, sandboxed — no access to `window` of the page, no direct `dataLayer` push).
- The cart is AJAX, so `add_to_cart` / cart-drawer events cannot be tied to page loads; hook the `$360` cart flow or use the Web Pixel `cart` events.
- Never enable the native Google/Meta channel *and* an equivalent GTM tag for the same event — the todo's core architectural decision (T1) is precisely about picking one source of truth.

## Git conventions

Per the global rules: `main` = production (no direct commits), `dev` = integration, `feature/…` / `fix/…` branches off `dev`, Conventional Commits. This repo currently only has `main` with a single initial commit — create `dev` before starting feature work.
