/*
 * V3 "Ivory & Navy" - product detail page rules
 * Gallery, purchase panel, LNPL box, reservation notice, modals,
 * state-reference gallery. Loaded only on /product/{slug}, on top of core.css.
 */

/* ============================================================
   PRODUCT DETAIL - page-specific rules (new for this page)
   ============================================================ */
.v3-pdp-top { padding-top: 32px; }
/* .v3-banner-slot's own top margin (core.css, 48px - meant to separate it
   from a product rail above it on the homepage) stacks with this
   container's own 32px padding-top here, since the banner is the very
   first thing on the page. Zero it out for this one placement only. */
.v3-pdp-top > .v3-banner-slot:first-child { margin-top: 0; }
/* Same double-margin issue as the top banner, different cause: the
   preceding section (Recommended Products, or Product Description when
   there are no recs) already ends with its own 72px padding-bottom
   (.v3-section), so this banner's own 48px margin-top just stacks an
   oversized gap on top of that. */
.v3-pdp-bottom-banner .v3-banner-slot { margin-top: 0; }

/* Product Description is trusted admin HTML (see product/show.php) and
   sometimes embeds a fixed-width YouTube <iframe> - constrain it to the
   column or it overflows the viewport horizontally on mobile. */
.v3-pdp-desc-body iframe { max-width: 100%; height: auto; aspect-ratio: 16 / 9; }
.v3-pdp-breadcrumb {
    font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
    color: var(--ink-soft); margin: 24px 0 8px;
}
.v3-pdp-breadcrumb a { color: var(--ink-soft); text-decoration: none; }
.v3-pdp-breadcrumb a:hover { color: var(--accent); }
.v3-pdp-breadcrumb .v3-pdp-current { color: var(--ink); }
.v3-pdp-breadcrumb .v3-pdp-sep { margin: 0 6px; opacity: .5; }

/* two-column layout: gallery / purchase panel */
.v3-pdp-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: start; margin: 28px 0 64px; }

/* -------- gallery (left column) -------- */
.v3-pdp-gallery-main { position: relative; max-width: 480px; margin: 0 auto; }
.v3-pdp-main-case { padding: 34px; }
.v3-pdp-arrow {
    /* Solid plate fill, not transparent - a circle that picks up
       whatever background is behind it (page vs plate) can't stay
       readable against both at once; a solid backdrop always reads
       the same regardless of what it overlaps. */
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 40px; height: 40px; border-radius: 999px;
    background: var(--plate); border: 1px solid var(--line); color: var(--ink);
    display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 2;
    box-shadow: 0 8px 20px var(--shadow);
    transition: border-color .2s ease, color .2s ease;
}
.v3-pdp-arrow:hover { border-color: var(--accent); color: var(--accent); }
.v3-pdp-arrow-prev { left: -18px; }
.v3-pdp-arrow-next { right: -18px; }
.v3-pdp-thumbs { display: flex; gap: 12px; margin-top: 20px; flex-wrap: wrap; justify-content: center; max-width: 480px; margin-left: auto; margin-right: auto; }
.v3-pdp-thumb { background: none; border: 0; padding: 0; cursor: pointer; width: 76px; flex: none; }
/* box-shadow ring, not a real `border` - a transparent border on this
   border-radius + gradient-background box antialiases into a faint seam
   at the edge (worst along the flat bottom edge), visible even at 0/not
   selected. Same fix as .v3-card-plate's hover ring in core.css. */
.v3-pdp-thumb .v3-card-plate { padding: 6px; box-shadow: inset 0 0 0 2px transparent; transition: box-shadow .2s ease; }
/* Selection ring is navy (--accent), not gold - "this is the one you're
   looking at" is a structural UI state, not a money signal, same role
   split the rest of this page's palette follows. */
.v3-pdp-thumb.is-current .v3-card-plate { box-shadow: inset 0 0 0 2px var(--accent); }
/* Legacy product.php's .slider-smaller treatment (css.css:3445-3467): every
   non-selected thumb fades to .7 opacity, and hovering one previews it at
   full opacity + the same accent border the selected thumb already gets -
   ported here so a shopper can tell at a glance which thumb they're about
   to click, not just which one is currently active. */
.v3-pdp-thumb:not(.is-current) { opacity: .7; transition: opacity .2s ease; }
.v3-pdp-thumb:not(.is-current):hover { opacity: 1; }
.v3-pdp-thumb:not(.is-current):hover .v3-card-plate { box-shadow: inset 0 0 0 2px var(--accent); }
/* Kill the ambient floating-card shadow (.v3-card-plate::after, tuned for
   full-size catalog cards) here - at 76px it reads as a flat stray line
   under the thumbnail rather than a soft shadow, especially with no border
   to visually anchor it on the non-current ones. Selection is already
   communicated by the accent ring above, so the thumbnail doesn't need it. */
.v3-pdp-thumb .v3-card-plate::after { display: none; }

/* Video item in the gallery - the product's own first photo doubles as
   the poster (mirrors legacy productvideo.class.php's outputLinkHTML(),
   which paints the same $pic as a background behind a play glyph). */
.v3-pdp-thumb-play {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    background: rgba(27, 31, 46, .45); border-radius: 8px; color: #fff; font-size: 15px; pointer-events: none;
}
.v3-pdp-main-case { position: relative; cursor: zoom-in; }
.v3-pdp-main-case img.is-hidden,
.v3-pdp-main-case video.is-hidden { display: none; }
.v3-pdp-main-case video { width: 100%; height: auto; display: block; border-radius: 4px; background: #000; }
/* Magnify-on-hover overlay (#pdp-zoom, product.js) - sized to match
   .v3-pdp-main-case exactly, including its padding, same as legacy's
   .slider-main > * / #sec-zoom (css.css:3397-3403). overflow:hidden lives
   here, not on .v3-pdp-main-case (== .v3-card-plate): that class's ::after
   ambient shadow extends past its own box (core.css) and would get
   clipped if the card itself carried overflow:hidden. */
.v3-pdp-zoom {
    position: absolute; inset: 0; overflow: hidden; opacity: 0;
    transition: opacity .15s ease; pointer-events: none; z-index: 3;
}
.v3-pdp-zoom.is-active { opacity: 1; }
.v3-pdp-zoom img { position: absolute; top: 0; left: 0; max-width: none; display: block; }

/* -------- purchase panel (right column) -------- */
.v3-pdp-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); margin: 0 0 8px; }
.v3-pdp-title { font-size: 36px; line-height: 1.2; color: var(--ink); margin: 8px 0 18px; }
.v3-pdp-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
.v3-pdp-badge {
    display: inline-flex; align-items: center; font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    border: 1px solid var(--line); color: var(--ink-soft); padding: 5px 11px; border-radius: 999px;
}
.v3-pdp-badge.is-up { border-color: var(--up); color: var(--up); }
/* Shipping badges are filled (not just outlined) so they stand out from the
   packaging/condition pills next to them. */
.v3-pdp-badge.is-free-ship { border-color: var(--up); background: var(--up); color: #fff; }
.v3-pdp-badge.is-no-ship { border-color: var(--down); background: var(--down); color: #fff; }

/* padding, not the <p>'s own margin (removed above) - this is what actually
   made the price "stand out" before; rebuilt deliberately here on the
   wrapper instead, so it can't throw off .v3-pdp-price-row's internal
   badge/digit alignment the way the <p>'s margin did. */
.v3-pdp-price-block { padding: 24px 0; margin-bottom: 8px; }
/* align-items:flex-start, not baseline - baseline aligned any badge here
   (Live Pricing today, whatever else lands in this row later) to the big
   price digits' text baseline, which reads as pinned to the bottom of the
   row instead of sitting level with its top. */
.v3-pdp-price-row { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
/* margin:0 - this is a <p>, and nothing else here resets paragraph margins
   (core.css only zeroes h1/h2/h3); the browser's default ~1em top margin
   (34px at this font-size) was the real reason .v3-pdp-price-row's
   align-items:flex-start still left the badge sitting well above the
   visible price digits instead of level with them. */
.v3-pdp-price { font-family: Manrope, sans-serif; font-weight: 800; font-variant-numeric: lining-nums tabular-nums; font-size: 34px; line-height: 1; color: var(--gold); margin: 0; }
/* .v3-strike is shared markup with the listing card (product_card.php), but
   core.css only scopes it under .v3-card-price - it never matched here, so
   the promo original price silently rendered unstyled (no strikethrough) on
   the PDP. em-sized (not the card's fixed 12.5px) so it scales with the
   34px/28px desktop/mobile price via .v3-pdp-price's own font-size. */
.v3-pdp-price .v3-strike { font-size: .5em; font-weight: 600; color: var(--ink-soft); text-decoration: line-through; margin-left: 6px; }
.v3-pdp-status-line { font-size: 15px; color: var(--ink-soft); margin: 10px 0 0; }
.v3-pdp-status-line.is-closed { color: var(--down); }
.v3-pdp-status-line.is-out { color: var(--down); }
.v3-pdp-status-line.is-up { color: var(--up); }
.v3-pdp-status-line i { margin-right: 6px; }

/* Lock Now, Pay Later + Reservation notice - navy-bordered sub-card, no
   fill beyond the panel tint; the deposit/locked-price FIGURE inside is
   gold (money), the frame around it is navy (structure), same split as
   everywhere else on the page. */
.v3-pdp-lnpl { border: 1px solid var(--accent); border-radius: 14px; padding: 16px 18px; margin: 22px 0; background: var(--panel); }
.v3-pdp-lnpl-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--accent); margin: 0 0 10px; }
.v3-pdp-lnpl-copy { color: var(--ink); font-size: 14px; line-height: 1.65; margin: 0 0 4px; }
.v3-pdp-lnpl-deposit { font-family: Manrope, sans-serif; font-weight: 800; font-variant-numeric: lining-nums tabular-nums; font-size: 22px; color: var(--gold); margin: 10px 0 0; }

.v3-pdp-reserve { border: 1px solid var(--accent); border-radius: 14px; padding: 14px 16px; margin: 22px 0; display: flex; gap: 12px; align-items: flex-start; background: var(--panel); }
.v3-pdp-reserve i { color: var(--accent); font-size: 18px; margin-top: 2px; flex: none; }
.v3-pdp-reserve p { margin: 0; color: var(--ink); font-size: 14px; line-height: 1.65; }

/* quantity stepper + CTA row, scaled up for the single primary action */
.v3-pdp-buy-row { display: flex; align-items: stretch; gap: 16px; margin-top: 26px; flex-wrap: wrap; }
.v3-pdp-qty { display: inline-flex; align-items: stretch; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; flex: none; }
.v3-pdp-qty button {
    background: var(--accent); color: var(--accent-text); border: 0; width: 40px;
    font-size: 16px; font-weight: 700; cursor: pointer; transition: filter .2s ease;
}
.v3-pdp-qty button:hover { filter: brightness(.82); }
/* aria-disabled, not disabled: the click must still fire so the stepper can say why
   it stopped (max/min message in #pdp-qty-msg). */
.v3-pdp-qty button.is-limit { opacity: .4; cursor: not-allowed; }
.v3-pdp-qty button.is-limit:hover { filter: none; }
/* Both lines below keep their space when idle (visibility, not display/hidden, and a min-height
   sized to the message's wrapped height) so toggling qty 1 <-> 2+ or hitting a limit never
   shifts the stepper/CTA under the customer's finger. */
/* Tighter than a regular status line: this row is reserved even at qty 1, so keep the idle gap small. */
.v3-pdp-unit-line { margin-top: 4px; font-size: 14px; line-height: 20px; }
.v3-pdp-unit-line.is-idle { visibility: hidden; }
.v3-pdp-buy-row .v3-field-error,
.v3-pdp-buy-row .v3-field-error:empty { order: 99; flex: 0 0 100%; margin: -8px 0 0; font-size: 13px; line-height: 18px; min-height: 18px; }
@media (max-width: 520px) {
    .v3-pdp-buy-row .v3-field-error,
    .v3-pdp-buy-row .v3-field-error:empty { min-height: 36px; }
}
.v3-pdp-qty-rule { margin: 0 0 12px; }
.v3-pdp-qty input {
    width: 52px; text-align: center; border: 0; border-left: 1px solid var(--line); border-right: 1px solid var(--line);
    background: var(--plate); color: var(--ink); font-family: Manrope, sans-serif; font-size: 15px;
}
.v3-pdp-buy-row .v3-card-cta { width: auto; flex: 1 1 200px; height: 48px; font-size: 16px; padding: 0 28px; }

.v3-pdp-share {
    margin-top: 18px; display: inline-flex; align-items: center; gap: 8px; color: var(--ink-soft);
    font-size: 13px; background: none; border: 0; cursor: pointer; text-decoration: none; padding: 0;
}
.v3-pdp-share:hover { color: var(--accent); }

/* -------- product description -------- */
.v3-pdp-desc-body { font-size: 16px; line-height: 1.7; color: var(--ink); max-width: 900px; }
.v3-pdp-desc-body p { margin: 0 0 20px; }
.v3-pdp-desc-body ul { margin: 16px 0 0; padding-left: 22px; }
.v3-pdp-desc-body li { margin-bottom: 12px; }

/* -------- state gallery (reference) -------- */
.v3-pdp-state-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.v3-pdp-state-card { border: 1px solid var(--line); border-radius: 14px; padding: 22px; background: var(--plate); }
.v3-pdp-state-card h3 { font-size: 16px; color: var(--ink); margin: 0 0 12px; line-height: 1.35; }
.v3-pdp-state-caption { font-size: 11px; font-style: italic; color: var(--ink-soft); margin: 0 0 10px; }
.v3-pdp-state-card .v3-pdp-qty { transform: scale(.9); transform-origin: left center; }
.v3-pdp-state-card .v3-pdp-buy-row { margin-top: 14px; gap: 10px; }
.v3-pdp-state-card .v3-card-cta { height: 36px; font-size: 13px; padding: 0 16px; }
.v3-pdp-state-card .v3-pdp-reserve, .v3-pdp-state-card .v3-pdp-lnpl { margin: 12px 0 0; }

/* -------- modals reference -------- */
.v3-pdp-modal-triggers { display: flex; flex-wrap: wrap; gap: 10px; }
.v3-pdp-modal-trigger-btn {
    font-family: Manrope, sans-serif; font-size: 13px; color: var(--ink); background: transparent;
    border: 1px solid var(--line); border-radius: 8px; padding: 8px 14px; display: inline-flex;
    align-items: center; gap: 8px; cursor: pointer; transition: border-color .2s ease, color .2s ease;
}
.v3-pdp-modal-trigger-btn:hover { border-color: var(--accent); color: var(--accent); }
.v3-pdp-modal-backdrop {
    position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 200;
    display: flex; align-items: center; justify-content: center; padding: 20px;
}
.v3-pdp-modal-backdrop.is-hidden { display: none; }
.v3-pdp-modal {
    background: var(--plate); border: 1px solid var(--line); border-top: 2px solid var(--accent);
    border-radius: 14px; padding: 26px; max-width: 420px; width: 100%; position: relative;
    box-shadow: 0 24px 48px var(--shadow);
}
.v3-pdp-modal h3 { display: flex; align-items: center; gap: 8px; font-size: 21px; color: var(--accent); margin: 0 0 14px; }
/* Draw-in checkmark ahead of "Item Added to Cart" - a plain show/hide toggle
   (.v3-pdp-modal-backdrop.is-hidden <-> flex, product.css above) rather than
   a re-render, so no JS replay trick is needed: an `animation` on an element
   restarts on its own once its ancestor goes from display:none back to
   displayed, which is exactly what opening this modal already does. Circle
   dasharray = its own circumference (2*pi*24 ~= 151); check dasharray = the
   drawn path's own length (~9.9 + ~22.6 ~= 33), each just long enough that
   stroke-dashoffset can travel it from full-length (hidden) to 0 (fully drawn). */
.v3-pdp-modal-tick { display: inline-flex; flex: none; position: relative; }
.v3-pdp-modal-tick svg { width: 24px; height: 24px; overflow: visible; }
.v3-pdp-modal-tick-circle {
    stroke: var(--up); stroke-width: 3;
    stroke-dasharray: 151; stroke-dashoffset: 151;
    animation: v3-pdp-tick-draw .75s ease-out forwards;
}
.v3-pdp-modal-tick-check {
    stroke: var(--up); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round;
    stroke-dasharray: 33; stroke-dashoffset: 33;
    animation: v3-pdp-tick-draw .25s .4s ease-out forwards;
}
@keyframes v3-pdp-tick-draw { to { stroke-dashoffset: 0; } }
/* Expanding ring "success ping" - see core.css's copy of this rule for the
   fuller comment. */
.v3-pdp-modal-tick::after {
    content: ""; position: absolute; inset: 0; border-radius: 50%;
    border: 2px solid var(--up); opacity: 0;
    animation: v3-pdp-tick-pulse .8s ease-out .55s both;
}
@keyframes v3-pdp-tick-pulse {
    0%   { transform: scale(1); opacity: .7; }
    100% { transform: scale(2.6); opacity: 0; }
}
/* Two-stage "Item Added to Cart" reveal - see core.css's copy of this rule
   for the fuller comment. */
.v3-pdp-modal-intro {
    position: absolute; inset: 0; z-index: 5; border-radius: inherit;
    display: flex; align-items: center; justify-content: center;
    background: var(--plate); pointer-events: none;
    animation: v3-pdp-modal-intro-out 1.9s ease forwards;
}
.v3-pdp-modal-intro .v3-pdp-modal-tick svg { width: 72px; height: 72px; }
@keyframes v3-pdp-modal-intro-out {
    0%, 78% { opacity: 1; visibility: visible; }
    100%    { opacity: 0; visibility: hidden; }
}
.v3-pdp-modal-content {
    opacity: 0; pointer-events: none;
    animation: v3-pdp-modal-content-in .5s ease 1.55s forwards;
}
@keyframes v3-pdp-modal-content-in { to { opacity: 1; pointer-events: auto; } }
.v3-pdp-modal p { color: var(--ink); font-size: 14.5px; line-height: 1.65; margin: 0 0 16px; }
.v3-pdp-modal label { display: block; font-size: 12px; color: var(--ink-soft); margin-bottom: 6px; }
.v3-pdp-modal input[type="email"], .v3-pdp-modal input[type="text"] {
    width: 100%; padding: 10px 12px; background: var(--panel); border: 1px solid var(--line);
    color: var(--ink); border-radius: 8px; margin-bottom: 10px; font-family: Manrope, sans-serif; font-size: 14px;
}
.v3-pdp-modal .v3-form-error { display: block; color: var(--down); font-size: 12.5px; margin: -4px 0 12px; min-height: 1em; }
.v3-pdp-modal .v3-form-result { font-size: 13.5px; margin: 0 0 16px; }
.v3-pdp-modal-actions { display: flex; gap: 10px; flex-wrap: wrap; }
/* Standardized on the full-width stacked button treatment every other
   .v3-pdp-modal-* consumer already has (core.css/cart.css/order.css never
   narrowed these) - dropped the auto-width/side-by-side override so PDP's
   modals (added-to-cart, contact, market-closed) match. */
.v3-pdp-modal-close {
    /* z-index above .v3-pdp-modal-intro's 5px - see core.css's copy of that
       rule for the fuller comment. */
    position: absolute; top: 10px; right: 10px; z-index: 6; background: none; border: 0; color: var(--ink-soft);
    font-size: 20px; line-height: 1; cursor: pointer; padding: 6px;
}
.v3-pdp-modal-close:hover { color: var(--accent); }

@media (max-width: 900px) {
    .v3-pdp-layout { grid-template-columns: 1fr; gap: 36px; }
    .v3-pdp-state-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
    .v3-pdp-title { font-size: 28px; }
    .v3-pdp-price { font-size: 28px; }
    .v3-pdp-state-grid { grid-template-columns: 1fr; }
    .v3-pdp-main-case { padding: 22px; }
    /* On mobile the arrows sit right on the photo (no plate margin to
       float in), and real product photography here has a watermark
       logo dead-center-left and a distributor seal near the bottom
       right - vertical-center collides with the logo. Lower the
       arrows into the gap between the two. */
    .v3-pdp-arrow { top: 60%; }
    .v3-pdp-arrow-prev { left: 4px; }
    .v3-pdp-arrow-next { right: 4px; }
}
