berrypod/assets/css/theme-layer2-attributes.css
jamey 67a26eb6b4
All checks were successful
deploy / deploy (push) Successful in 1m26s
add contextual prompts for skipped setup steps
Disable checkout when Stripe isn't connected (cart drawer, cart page,
and early guard in checkout controller to prevent orphaned orders).
Show amber warning on order detail when email isn't configured.
Fix pre-existing missing vertical spacing between page blocks.

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

732 lines
15 KiB
CSS

/* ========================================
LAYER 2: THEME TOKENS (Shared Styles)
========================================
This file contains .themed styles used by both shop and theme editor.
The .preview-frame CSS variable switching rules are in app.css (admin only).
Shop pages get CSS variables inline from CSSGenerator.
======================================== */
.themed {
/* Font size scale */
font-size: calc(16px * var(--t-font-size-scale, 1));
/* Heading Weight Override */
& h1, & h2, & h3, & h4, & h5, & h6 {
font-weight: var(--t-heading-weight-override, var(--t-heading-weight, 600)) !important;
}
/* Type Scale Utility Classes */
& .t-caption { font-size: var(--t-text-caption); }
& .t-small { font-size: var(--t-text-small); }
& .t-base { font-size: var(--t-text-base); }
& .t-large { font-size: var(--t-text-large); }
& .t-xl { font-size: var(--t-text-xl); }
& .t-2xl { font-size: var(--t-text-2xl); }
& .t-heading-sm { font-size: var(--t-heading-sm); }
& .t-heading-md { font-size: var(--t-heading-md); }
& .t-heading-lg { font-size: var(--t-heading-lg); }
& .t-heading-xl { font-size: var(--t-heading-xl); }
& .t-heading-display { font-size: var(--t-heading-display); }
/* Override Tailwind text-* classes */
& .text-xs { font-size: var(--t-text-caption) !important; }
& .text-sm { font-size: var(--t-text-small) !important; }
& .text-base { font-size: var(--t-text-base) !important; }
& .text-lg { font-size: var(--t-text-large) !important; }
& .text-xl { font-size: var(--t-text-xl) !important; }
& .text-2xl { font-size: var(--t-text-2xl) !important; }
& .text-3xl { font-size: var(--t-heading-lg) !important; }
& .text-4xl { font-size: var(--t-heading-xl) !important; }
& .text-5xl, & .text-6xl, & .text-7xl, & .text-8xl, & .text-9xl {
font-size: var(--t-heading-display) !important;
}
/* Header Layout */
&[data-header="standard"] .shop-header {
justify-content: space-between;
}
&[data-header="centered"] {
& .shop-header {
flex-wrap: wrap;
justify-content: center;
gap: 0.5rem 1.5rem;
padding-top: 1.5rem;
padding-bottom: 1.5rem;
}
& .shop-logo {
width: 100%;
justify-content: center;
text-align: center;
}
& .shop-nav {
justify-content: center;
}
}
&[data-header="left"] {
& .shop-header {
justify-content: flex-start;
gap: 2rem;
}
& .shop-cart {
margin-left: auto;
}
}
&[data-sticky="true"] .shop-header {
position: sticky;
top: 0;
z-index: 50;
}
/* Layout Width */
&[data-layout="contained"] :is(.max-w-7xl, .page-container, .collection-header-inner) {
max-width: var(--t-layout-max-width, 1100px);
}
&[data-layout="wide"] :is(.max-w-7xl, .page-container, .collection-header-inner) {
max-width: var(--t-layout-max-width, 1400px);
}
&[data-layout="full"] :is(.max-w-7xl, .page-container, .collection-header-inner) {
max-width: var(--t-layout-max-width, 100%);
padding-left: 2rem;
padding-right: 2rem;
}
/* Card Shadow */
&[data-shadow="none"] {
& .product-card,
& .category-card {
box-shadow: none;
}
}
&[data-shadow="sm"] {
& .product-card,
& .category-card {
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
}
&[data-shadow="md"] {
& .product-card,
& .category-card {
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
}
}
&[data-shadow="lg"] {
& .product-card,
& .category-card {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
}
}
/* Product Grid */
& .product-grid {
gap: var(--space-lg, 1.5rem);
}
&[data-density="spacious"] .product-grid {
gap: calc(var(--space-lg, 1.5rem) * 1.25);
}
&[data-density="compact"] .product-grid {
gap: calc(var(--space-lg, 1.5rem) * 0.75);
}
/* Product Card Padding */
& .product-card > div:last-child {
padding: var(--space-md, 1rem);
text-align: var(--t-product-text-align, left);
}
&[data-density="spacious"] .product-card > div:last-child {
padding: calc(var(--space-md, 1rem) * 1.25);
}
&[data-density="compact"] .product-card > div:last-child {
padding: calc(var(--space-md, 1rem) * 0.75);
}
/* Button Style Variants */
&[data-button-style="outline"] {
& .themed-button,
& .atc-btn,
& .cart-drawer-checkout {
background-color: transparent !important;
color: var(--t-accent) !important;
border: 2px solid var(--t-accent) !important;
}
}
&[data-button-style="soft"] {
& .themed-button,
& .atc-btn,
& .cart-drawer-checkout {
background-color: color-mix(in oklch, var(--t-accent) 12%, var(--t-surface-base)) !important;
color: color-mix(in oklch, var(--t-accent) 80%, black) !important;
border: 2px solid transparent !important;
}
}
/* Image Aspect Ratio */
& .product-card .product-card-image-wrap {
aspect-ratio: var(--t-image-aspect-ratio, 1 / 1);
}
/* Link Hover */
& a:not([class*="btn"]):not([class*="button"]):not(.product-card):not(.nav-link):hover {
color: var(--t-secondary-accent, var(--t-text-primary));
}
/* Product Card Hover */
& .product-card:hover {
border-color: var(--t-secondary-accent, var(--t-border-default)) !important;
}
/* Button Hover */
& button:hover,
& [role="button"]:hover {
filter: brightness(0.95);
}
/* Nav Link Hover */
& .nav-link:hover,
& nav a:hover {
color: var(--t-secondary-accent, var(--t-text-primary));
}
/* Filter Pills */
& .filter-pills-container {
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}
& .filter-pill {
flex-shrink: 0;
padding: 0.5rem 1rem;
font-size: var(--t-text-small);
font-weight: 500;
border-radius: var(--t-radius-button);
border: 1px solid var(--t-border-default);
background-color: var(--t-surface-base);
color: var(--t-text-secondary);
cursor: pointer;
transition: all 0.15s ease;
white-space: nowrap;
&:hover {
background-color: var(--t-surface-sunken);
color: var(--t-text-primary);
}
}
& .filter-pill-active {
background-color: var(--t-accent);
color: var(--t-text-inverse);
border-color: transparent;
&:hover {
background-color: var(--t-accent-hover);
color: var(--t-text-inverse);
}
}
/* Themed Form Controls */
& .themed-input {
background-color: var(--t-surface-base);
color: var(--t-text-primary);
border: 1px solid var(--t-border-input, var(--t-border-default));
border-radius: var(--t-radius-input);
padding: 0.5rem 0.75rem;
&:focus {
outline: none;
border-color: var(--t-accent);
}
&::placeholder {
color: var(--t-text-tertiary);
}
}
& .themed-select {
background-color: var(--t-surface-raised);
color: var(--t-text-primary);
border: 1px solid var(--t-border-input, var(--t-border-default));
border-radius: var(--t-radius-input);
padding: 0.375rem 0.75rem;
font-size: var(--t-text-small);
font-family: var(--t-font-body);
&:focus {
outline: none;
border-color: var(--t-accent);
}
}
& .themed-button {
background-color: var(--t-accent);
color: var(--t-text-inverse);
border-radius: var(--t-radius-button);
border: none;
cursor: pointer;
padding: 0.75rem 1.5rem;
font-weight: 600;
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
& .themed-button-outline {
background-color: transparent;
color: var(--t-text-primary);
border: 1px solid var(--t-border-default);
border-radius: var(--t-radius-button);
cursor: pointer;
padding: 0.75rem 1.5rem;
font-weight: 600;
}
& .themed-card {
background-color: var(--t-surface-raised);
border: 1px solid var(--t-border-default);
border-radius: var(--t-radius-card);
}
}
/* Shop nav display - handled by components.css (hidden on mobile, flex on md+) */
/* =============================================
STANDALONE COMPONENTS (Context-independent)
============================================= */
/* Product Badges */
.product-badge {
position: absolute;
top: 0.5rem;
left: 0.5rem;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.025em;
border-radius: var(--t-radius-sm, 4px);
z-index: 10;
}
.badge-sale {
background-color: var(--t-sale-color, #dc2626);
color: #ffffff;
}
.badge-new {
background-color: var(--t-accent);
color: var(--t-text-inverse);
}
.badge-sold-out {
background-color: var(--t-text-tertiary, #737373);
color: #ffffff;
}
/* Product Card Images — mobile: swipe, desktop: hover crossfade */
.product-card-image-wrap {
position: relative;
}
/* Mobile default: horizontal scroll-snap for swiping between images */
.product-image-scroll {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
height: 100%;
&::-webkit-scrollbar {
display: none;
}
}
.product-image-scroll > img,
.product-image-scroll > picture {
flex: 0 0 100%;
width: 100%;
height: 100%;
scroll-snap-align: start;
}
/* Dot indicators for swipeable images (mobile only) */
.product-image-dots {
position: absolute;
bottom: 0.5rem;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 0.375rem;
z-index: 5;
}
.product-image-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.42);
border: none;
padding: 0;
transition: all 0.2s ease;
}
.product-image-dot-active {
width: 8px;
height: 8px;
background: rgba(255, 255, 255, 0.95);
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.42);
}
/* Desktop: hover crossfade instead of scroll */
@media (hover: hover) {
.product-image-scroll {
display: contents;
}
.product-image-dots {
display: none;
}
.product-image-hover {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.3s ease;
}
.product-card:hover .product-image-hover {
opacity: 1;
}
.product-card:hover .product-image-primary:has(+ .product-image-hover) {
opacity: 0;
}
}
/* Social Links */
.social-link:hover {
background-color: var(--t-surface-sunken);
color: var(--t-secondary-accent, var(--t-text-primary));
}
/* Header Icon Buttons */
.header-icon-btn:hover {
background-color: var(--t-surface-sunken);
color: var(--t-secondary-accent, var(--t-text-primary));
}
/* Search Modal Animation */
.search-modal {
opacity: 1;
transition: opacity 0.2s ease;
}
.search-modal-content {
transform: translateY(0);
transition: transform 0.2s ease;
}
/* Breadcrumb */
.breadcrumb {
margin-bottom: 1rem;
font-size: 0.875em;
& ol {
display: flex;
flex-wrap: wrap;
align-items: center;
list-style: none;
margin: 0;
padding: 0;
}
& li + li::before {
content: "\203A";
padding-inline: 0.375em;
}
& li[aria-current="page"] {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 20ch;
}
}
@media (min-width: 640px) {
.breadcrumb {
margin-bottom: 2rem;
& li[aria-current="page"] {
max-width: none;
}
}
}
/* PDP Gallery — mobile: swipe + dots, desktop: carousel + thumbs */
.pdp-gallery-carousel,
.pdp-gallery-single {
aspect-ratio: 1 / 1;
background-color: #e5e7eb;
overflow: hidden;
}
.pdp-gallery-single {
position: relative;
}
.pdp-gallery-carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}
.pdp-carousel-img {
flex: 0 0 100%;
width: 100%;
height: 100%;
object-fit: cover;
scroll-snap-align: start;
}
/* Desktop-only: lightbox click target + nav arrows (hidden on mobile) */
.pdp-lightbox-click,
.pdp-nav {
display: none;
}
.pdp-gallery-thumbs {
display: none;
}
@media (hover: hover) {
.pdp-lightbox-click {
display: block;
position: absolute;
inset: 0;
z-index: 1;
cursor: zoom-in;
}
.pdp-nav {
display: flex;
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 2;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
border-radius: 9999px;
background: rgba(255, 255, 255, 0.9);
color: #374151;
border: none;
cursor: pointer;
opacity: 0;
transition: opacity 0.15s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
& svg {
width: 1.25rem;
height: 1.25rem;
}
}
.pdp-nav-prev {
left: 0.75rem;
}
.pdp-nav-next {
right: 0.75rem;
}
/* Show arrows on gallery hover */
.pdp-gallery:hover .pdp-nav {
opacity: 1;
}
.pdp-nav:hover {
background: rgba(255, 255, 255, 1);
}
.pdp-gallery-single {
cursor: zoom-in;
}
.pdp-gallery-thumbs {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
margin-top: 1rem;
}
}
/* Lightbox */
.lightbox {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
border: none;
padding: 0;
margin: 0;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
&::backdrop {
background: rgba(0, 0, 0, 0.95);
}
&:not([open]) {
display: none;
}
}
.lightbox-content {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.lightbox-close {
position: absolute;
top: var(--space-md, 1rem);
right: var(--space-md, 1rem);
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.05);
border: none;
border-radius: 50%;
color: white;
cursor: pointer;
transition: background 0.15s ease;
z-index: 1;
&:hover {
background: rgba(255, 255, 255, 0.1);
}
& svg {
width: 24px;
height: 24px;
}
}
.lightbox-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.1);
border: none;
border-radius: 50%;
color: white;
cursor: pointer;
transition: background 0.15s ease;
&:hover {
background: rgba(255, 255, 255, 0.2);
}
& svg {
width: 24px;
height: 24px;
}
}
.lightbox-prev {
left: var(--space-md, 1rem);
}
.lightbox-next {
right: var(--space-md, 1rem);
}
.lightbox-image-container {
max-width: 90vw;
max-height: 75vh;
display: flex;
align-items: center;
justify-content: center;
}
.lightbox-image {
max-width: 100%;
max-height: 75vh;
object-fit: contain;
border-radius: var(--t-radius-image, 8px);
}
.lightbox-figure {
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-md, 1rem);
}
.lightbox-caption {
color: rgba(255, 255, 255, 0.8);
font-family: var(--t-font-body);
font-size: 0.875rem;
text-align: center;
max-width: 600px;
line-height: 1.5;
}
.lightbox-counter {
position: absolute;
bottom: var(--space-md, 1rem);
left: 50%;
transform: translateX(-50%);
color: rgba(255, 255, 255, 0.7);
font-size: 0.875rem;
font-family: var(--t-font-body);
}