diff --git a/assets/css/shop/components.css b/assets/css/shop/components.css
index 57a94d0..1873b4c 100644
--- a/assets/css/shop/components.css
+++ b/assets/css/shop/components.css
@@ -1,11 +1,327 @@
-/* Component styles — extracted from inline styles in later phases.
+/* Component styles — extracted from inline styles in product.ex, layout.ex, etc.
Each component gets its own section. */
@layer components {
- /* Phase 2: product cards, grid, badges, hero, categories */
- /* Phase 2: PDP, variant selector, gallery, accordion */
- /* Phase 3: layout components (header, footer, nav, search) */
- /* Phase 3: cart components (drawer, items, summary) */
- /* Phase 4: content components (contact, reviews, newsletter) */
- /* Phase 4: page templates (checkout success, etc.) */
+ /* ── Shared heading treatment ──
+ font-family + weight + tracking + colour used across
+ hero titles, section headings, collection headers, PDP, etc. */
+
+ .t-heading {
+ font-family: var(--t-font-heading);
+ font-weight: var(--t-heading-weight);
+ letter-spacing: var(--t-heading-tracking);
+ color: var(--t-text-primary);
+ }
+
+ /* ── Product card ── */
+
+ .product-card {
+ background-color: var(--t-surface-raised);
+ border-radius: var(--t-radius-card);
+
+ &[data-variant="default"],
+ &[data-variant="compact"] {
+ border: 1px solid var(--t-border-default);
+ }
+
+ &[data-variant="minimal"] {
+ border: 1px solid var(--t-border-subtle);
+ }
+
+ &[data-variant="default"],
+ &[data-variant="featured"] {
+ cursor: pointer;
+ }
+
+ &[data-clickable] {
+ position: relative;
+ }
+
+ & .stretched-link {
+ color: inherit;
+ text-decoration: none;
+ }
+ }
+
+ .product-card-image-wrap {
+ z-index: 1;
+ }
+
+ .product-card-placeholder {
+ color: var(--t-text-tertiary);
+ }
+
+ .product-card-category {
+ color: var(--t-text-tertiary);
+ text-decoration: none;
+ position: relative;
+ z-index: 1;
+ }
+
+ .product-card-title {
+ color: var(--t-text-primary);
+ }
+
+ .product-card[data-variant="default"] .product-card-title,
+ .product-card[data-variant="compact"] .product-card-title {
+ font-family: var(--t-font-heading);
+ }
+
+ .product-card-delivery {
+ color: var(--t-text-tertiary);
+ }
+
+ /* ── Product prices (shared between cards and PDP) ── */
+
+ .product-price--sale {
+ color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
+ }
+
+ .product-price--compare {
+ color: var(--t-text-tertiary);
+ }
+
+ .product-price--regular {
+ color: var(--t-text-primary);
+ }
+
+ .product-price--secondary {
+ color: var(--t-text-secondary);
+ }
+
+ .sale-badge {
+ background-color: var(--t-sale-color);
+ }
+
+ /* ── Hero section ── */
+
+ .hero-section {
+ padding: var(--space-2xl) var(--space-lg);
+
+ &[data-background="base"] {
+ background-color: var(--t-surface-base);
+ }
+
+ &[data-background="sunken"] {
+ background-color: var(--t-surface-sunken);
+ }
+ }
+
+ .hero-section--page {
+ padding-top: var(--space-2xl);
+ }
+
+ .hero-pre-title {
+ font-family: var(--t-font-heading);
+ font-weight: var(--t-heading-weight);
+ color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
+ }
+
+ .hero-description {
+ color: var(--t-text-secondary);
+ line-height: 1.6;
+ }
+
+ /* ── Category nav ── */
+
+ .category-nav-section {
+ padding: var(--space-xl) var(--space-lg);
+ background-color: var(--t-surface-base);
+ }
+
+ .category-card {
+ text-decoration: none;
+ cursor: pointer;
+ }
+
+ .category-name {
+ font-family: var(--t-font-body);
+ color: var(--t-text-primary);
+ }
+
+ /* ── Featured products section ── */
+
+ .featured-section {
+ padding: var(--space-xl) var(--space-lg);
+ background-color: var(--t-surface-sunken);
+ }
+
+ .outline-button {
+ background-color: transparent;
+ color: var(--t-text-primary);
+ border: 1px solid var(--t-text-primary);
+ border-radius: var(--t-radius-button);
+ cursor: pointer;
+ text-decoration: none;
+ }
+
+ /* ── Image + text section ── */
+
+ .image-text-section {
+ padding: var(--space-2xl) var(--space-lg);
+ background-color: var(--t-surface-base);
+ }
+
+ .image-text-image {
+ border-radius: var(--t-radius-image);
+ }
+
+ .image-text-body {
+ color: var(--t-text-secondary);
+ line-height: 1.7;
+ }
+
+ .accent-link {
+ color: var(--t-accent-text, hsl(var(--t-accent-h) var(--t-accent-s) 38%));
+ text-decoration: none;
+ cursor: pointer;
+ }
+
+ /* ── Collection header ── */
+
+ .collection-header-wrap {
+ background-color: var(--t-surface-raised);
+ border-color: var(--t-border-default);
+ }
+
+ .collection-header-meta {
+ color: var(--t-text-secondary);
+ }
+
+ /* ── Breadcrumb ── */
+
+ .breadcrumb {
+ color: var(--t-text-secondary);
+
+ & [aria-current="page"] {
+ color: var(--t-text-primary);
+ }
+ }
+
+ /* ── Related products ── */
+
+ .related-section {
+ border-top: 1px solid var(--t-border-default);
+ }
+
+ /* ── PDP gallery ── */
+
+ .pdp-gallery-frame {
+ border-radius: var(--t-radius-image);
+ overflow: hidden;
+ }
+
+ .pdp-thumbnail {
+ border-radius: var(--t-radius-image);
+ }
+
+ /* ── Variant selector ── */
+
+ .variant-label {
+ color: var(--t-text-primary);
+ }
+
+ .variant-label-value {
+ color: var(--t-text-secondary);
+ font-weight: normal;
+ }
+
+ .color-swatch {
+ border-color: var(--t-border-default);
+
+ &[aria-pressed="true"] {
+ border-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
+ --tw-ring-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
+ }
+ }
+
+ .size-btn {
+ border: 2px solid var(--t-border-default);
+ border-radius: var(--t-radius-button);
+ color: var(--t-text-primary);
+ background: transparent;
+
+ &[aria-pressed="true"] {
+ border-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
+ background: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l) / 0.1);
+ }
+ }
+
+ /* ── Quantity selector ── */
+
+ .qty-label {
+ color: var(--t-text-primary);
+ }
+
+ .qty-group {
+ border: 2px solid var(--t-border-default);
+ border-radius: var(--t-radius-input);
+ }
+
+ .qty-btn {
+ color: var(--t-text-primary);
+ }
+
+ .qty-display {
+ border-color: var(--t-border-default);
+ color: var(--t-text-primary);
+ }
+
+ .stock-in {
+ color: var(--t-text-tertiary);
+ }
+
+ .stock-out {
+ color: var(--t-sale-color);
+ }
+
+ /* ── Add to cart ── */
+
+ .atc-wrap {
+ background-color: var(--t-surface-base);
+ border-color: var(--t-border-subtle);
+ }
+
+ .atc-btn {
+ background-color: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
+ color: var(--t-text-inverse);
+ border-radius: var(--t-radius-button);
+ border: none;
+ cursor: pointer;
+
+ &:disabled {
+ background-color: var(--t-border-default);
+ cursor: not-allowed;
+ }
+ }
+
+ /* ── Accordion ── */
+
+ .accordion-summary {
+ color: var(--t-text-primary);
+ }
+
+ .accordion-body {
+ color: var(--t-text-secondary);
+ }
+
+ /* ── Product details ── */
+
+ .details-wrap {
+ border-top: 1px solid var(--t-border-subtle);
+ border-bottom: 1px solid var(--t-border-subtle);
+ border-color: var(--t-border-subtle);
+ }
+
+ .details-table-row {
+ border-bottom: 1px solid var(--t-border-subtle);
+ }
+
+ .details-th {
+ color: var(--t-text-primary);
+ }
+
+ .details-subheading {
+ color: var(--t-text-primary);
+ }
}
diff --git a/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex b/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex
index 2bf5f11..7ba53e6 100644
--- a/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex
+++ b/lib/simpleshop_theme_web/components/layouts/shop_root.html.heex
@@ -19,6 +19,10 @@
) do %>
<% end %>
+
+