/* ═════════════════════════════════════════════════════════════════════════
   WOOCOMMERCE PRODUCT GRID (W-130) — styles

   Scoped to .hzo-product-grid*. Tokens only (no bare hex / px / z-index where a
   token exists). The container marker [data-hzo-pg] already carries an
   aria-busy dim rule in woocommerce.css (loaded on WC pages); these rules add
   the ENGINE card (.hzo-product-card), the responsive grid geometry driven by
   the --hzo-pg-cols* custom properties the PHP sets, the Load-more control, the
   stock pill, and the skeleton loading state.

   Motion: durations/easings are --dur-*/--ease-* tokens only. Reduced-motion
   (PRESERVE-5) — ambient shimmer STOPS, the status spinner SLOWS (never freezes),
   content stays visible. Forced-colors gets an explicit branch.
   ═════════════════════════════════════════════════════════════════════════ */

.hzo-product-grid {
    --hzo-pg-cols: 4;
    --hzo-pg-cols-md: 3;
    --hzo-pg-cols-sm: 2;
    --hzo-pg-gap: var(--space-lg);
    display: block;
}

.hzo-product-grid .hzo-eyebrow,
.hzo-product-grid .hzo-visual-h2 {
    text-align: center;
}

/* ── Grid geometry (container-aware column counts) ─────────────────────────── */
.hzo-product-grid__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--hzo-pg-gap);
    grid-template-columns: repeat(var(--hzo-pg-cols), minmax(0, 1fr));
    margin-top: var(--space-xl);
}
.hzo-product-grid--empty .hzo-empty { margin-top: var(--space-xl); }

/* Heading absent → no top gap eats the section rhythm. */
.hzo-product-grid__list:first-child { margin-top: 0; }

@media (max-width: 1024px) {
    .hzo-product-grid__list { grid-template-columns: repeat(var(--hzo-pg-cols-md), minmax(0, 1fr)); }
}
@media (max-width: 640px) {
    .hzo-product-grid__list {
        grid-template-columns: repeat(var(--hzo-pg-cols-sm), minmax(0, 1fr));
        gap: var(--space-md);
    }
}

/* ── The card ──────────────────────────────────────────────────────────────── */
.hzo-product-card {
    /* Card-integrated add-to-cart: a moderate radius reads more considered than a
       full pill inside a card (per-client themes still override --btn-radius). */
    --btn-radius: var(--radius-1);
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-smd);
    background: var(--card-bg, var(--surface));
    border: var(--border-1) solid var(--card-border, var(--border));
    border-radius: var(--card-radius, var(--radius-2));
    padding: var(--space-smd);
    box-shadow: var(--card-shadow, var(--shadow-sm));
    transition: box-shadow var(--dur-3) var(--ease-out),
                transform var(--dur-3) var(--ease-out),
                border-color var(--dur-3) var(--ease-out);
    text-align: left;
}
/* Decorative lift only — the card is NOT a single click target (it holds a real
   title link AND an add-to-cart control), so no false whole-card affordance
   (PRESERVE-4 / G50). */
.hzo-product-card:hover {
    box-shadow: var(--card-hover-shadow, var(--shadow-lg));
    transform: translateY(-4px);
    border-color: color-mix(in srgb, var(--brand) 22%, var(--border));
}

.hzo-product-card__media {
    display: block;
    position: relative;
    border-radius: var(--radius-1);
    overflow: hidden;
    aspect-ratio: 1 / 1;          /* zero-CLS media box (G51) */
    background: var(--surface-2);
}
.hzo-product-card__media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    margin: 0;
    transition: transform var(--dur-4) var(--ease-out);
}
/* Subtle image zoom on card hover — a touch of life, not a gimmick. */
.hzo-product-card:hover .hzo-product-card__media img { transform: scale(1.05); }

/* Sale flash — a crisp uppercase brand pill at the media corner. */
.hzo-product-card__flash {
    position: absolute;
    top: var(--space-sm);
    left: var(--space-sm);
    z-index: 1;
    padding: 5px 11px;
    background: var(--brand);
    color: var(--text-on-brand, #fff);
    font-size: 0.68rem;
    font-weight: var(--fw-bold, 700);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.3;
    border-radius: var(--radius-pill);
    box-shadow: var(--shadow-sm);
}

.hzo-product-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    flex: 1 1 auto;
}

.hzo-product-card__title {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    font-weight: var(--fw-bold, 700);
    line-height: 1.35;
    color: var(--text-heading);
    margin: 0;
    padding: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;          /* even card heights; long names never blow out the row */
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.hzo-product-card__title a {
    color: inherit;
    text-decoration: none;
    background-image: none; /* a title link is a heading — never let a client content-link highlight ride onto it */
}
.hzo-product-card__title a:hover { color: var(--brand-text, var(--brand)); }

.hzo-product-card__rating { font-size: 0.9rem; margin-top: calc(-1 * var(--space-2xs)); }

/* Price hierarchy: the current price is the loudest thing on the card; a sale
   price takes the brand color, the original strikes through smaller + muted. */
.hzo-product-card__price {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-xs);
    color: var(--text-heading);
    font-size: 1.2rem;
    font-weight: var(--fw-extrabold, 800);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.hzo-product-card__price del {
    color: var(--text-muted);
    font-size: 0.9rem;
    font-weight: var(--fw-medium, 500);
    opacity: 1;
    margin: 0;
}
.hzo-product-card__price ins {
    color: var(--brand-text, var(--brand));
    text-decoration: none;
    font-weight: var(--fw-extrabold, 800);
}

/* ── Stock pill ────────────────────────────────────────────────────────────── */
.hzo-product-card__stock {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    font-size: 0.75rem;
    font-weight: var(--fw-semibold, 600);
    line-height: 1.4;
    border-radius: var(--radius-pill);
}
.hzo-product-card__stock::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: currentColor;
}
.hzo-product-card__stock--in   { color: var(--success-ink); background: var(--success-bg); }
.hzo-product-card__stock--low  { color: var(--warning-ink); background: var(--warning-bg); }
.hzo-product-card__stock--out  { color: var(--error-ink);   background: var(--error-bg); }

/* ── Add-to-cart control (engine .hzo-btn inherits its state visuals from
   buttons.css: .is-loading spinner / .is-added check — do NOT redefine them). ── */
.hzo-product-card__add {
    margin-top: auto;              /* pin to card bottom regardless of body height */
    align-self: stretch;
    justify-content: center;
    min-height: 44px;              /* substantial, comfortable tap (§11.2) */
    font-weight: var(--fw-bold, 700);
    letter-spacing: 0.01em;
}

/* ── Load-more control ─────────────────────────────────────────────────────── */
.hzo-product-grid__foot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    margin-top: var(--space-xl);
}
.hzo-product-grid__more {
    position: relative;
    min-height: 44px;
    min-width: 220px;
    justify-content: center;
}
.hzo-product-grid__more-spinner {
    display: none;
    width: 1em;
    height: 1em;
    margin-left: var(--space-sm);
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: var(--radius-full);
    animation: hzo-pg-spin var(--dur-4) linear infinite;
}
.hzo-product-grid__more.is-loading .hzo-product-grid__more-spinner { display: inline-block; }
.hzo-product-grid__more[aria-disabled="true"] { pointer-events: none; opacity: 0.7; }

.hzo-product-grid__error {
    margin: 0;
    color: var(--error-ink);
    font-size: 0.9rem;
    font-weight: var(--fw-semibold, 600);
}

@keyframes hzo-pg-spin { to { transform: rotate(360deg); } }

/* ── Skeleton loading state (G47 — a visible cue that works on FIRST load, not
   an opacity dim). Shimmer is AMBIENT motion → stops under reduced-motion. ──── */
.hzo-product-card--skeleton {
    pointer-events: none;
    gap: var(--space-sm);
}
.hzo-product-card--skeleton:hover { transform: none; box-shadow: var(--card-shadow, var(--shadow-sm)); }
.hzo-skel {
    display: block;
    border-radius: var(--radius-input);
    background: linear-gradient(
        100deg,
        var(--surface-2) 30%,
        var(--border) 50%,
        var(--surface-2) 70%
    );
    background-size: 200% 100%;
    animation: hzo-pg-shimmer var(--dur-4) var(--ease-standard) infinite;
}
.hzo-skel.hzo-product-card__media { aspect-ratio: 1 / 1; }
.hzo-skel--line { height: 0.9rem; border-radius: var(--radius-pill); }
.hzo-skel--short { width: 55%; }

@keyframes hzo-pg-shimmer {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

/* ── Reduced motion (PRESERVE-5): ambient shimmer + hover lift stop; the status
   spinner SLOWS but keeps moving; content stays fully visible. ─────────────── */
@media (prefers-reduced-motion: reduce) {
    .hzo-product-card,
    .hzo-product-card:hover { transition: none; transform: none; }
    .hzo-skel { animation: none; background: var(--surface-2); }
    .hzo-product-grid__more-spinner { animation-duration: 1.5s; }
}

/* ── Forced-colors / High Contrast (§12.2): the skeleton conveys nothing and the
   spinner border must remain visible; stock pills fall back to system colors. ─ */
@media (forced-colors: active) {
    .hzo-skel { background: Canvas; border: var(--border-1) solid CanvasText; animation: none; }
    .hzo-product-grid__more-spinner { border-color: CanvasText; border-top-color: transparent; }
    .hzo-product-card__stock { border: var(--border-1) solid CanvasText; }
    .hzo-product-card__flash { border: var(--border-1) solid CanvasText; }
}

/* ── Print (§12.1): drop the interactive chrome; keep the catalog readable. ─── */
@media print {
    .hzo-product-grid__foot,
    .hzo-product-card__add,
    .hzo-product-card--skeleton { display: none !important; }
    .hzo-product-card { box-shadow: none; break-inside: avoid; }
}

/* ─── Static block-pattern grids (merge graft from Track-1/2) ────────────────
   blocks/product-card.html renders cards DIRECTLY inside .hzo-product-grid with
   a --cols-N modifier and no __list child, so for that markup the grid must
   live on the element itself. The [hzo_product_grid] widget above never emits a
   --cols-N class (it drives columns via inline --hzo-pg-cols on __list), so
   these rules cannot collide with it — the two layouts stay independent.
   Base is auto-fill so mobile stays fluid; counts lock in at >=768px. */
.hzo-product-grid--cols-2,
.hzo-product-grid--cols-3,
.hzo-product-grid--cols-4 {
    display: grid;
    gap: var(--product-grid-gap, var(--space-lg));
    grid-template-columns: repeat(auto-fill, minmax(var(--product-grid-min, 240px), 1fr));
}

@media (min-width: 768px) {
    .hzo-product-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
    .hzo-product-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
    .hzo-product-grid--cols-4 { grid-template-columns: repeat(4, 1fr); }
}
