berrypod/assets/css/shop/components.css
jamey 2af2d782d5 extract product.ex inline styles to CSS component classes (Phase 2)
Move ~80 inline style= attributes from product.ex into ~40 CSS classes
in @layer components. Only genuinely dynamic values (hex colours,
background-image URLs) remain as inline styles. Pre-declare CSS layer
order in shop_root.html.heex so reset < components in the cascade.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 00:13:03 +00:00

328 lines
6.7 KiB
CSS

/* Component styles — extracted from inline styles in product.ex, layout.ex, etc.
Each component gets its own section. */
@layer components {
/* ── 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);
}
}