.pdp-breadcrumb { max-width: var(--content-max-width); margin: 0 auto; padding: 36px 48px 24px; font-size: 12.5px; color: var(--color-text-grey-dim); }
.pdp-breadcrumb a:hover { color: var(--color-gold-accent); }
.pdp-breadcrumb .current { color: var(--color-beige-light); }
@media (max-width: 639px) { .pdp-breadcrumb { padding: 20px 20px 16px; } }

.pdp-main { max-width: var(--content-max-width); margin: 0 auto; padding: 0 48px 80px; display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: start; }
@media (max-width: 979px) { .pdp-main { grid-template-columns: 1fr; } }
@media (max-width: 639px) { .pdp-main { padding: 0 20px 56px; gap: 32px; } }

/* Real bug found and fixed (2026-08-31, user-reported live: "so much
   white space", then confirmed "all the pictures will be same size" --
   every real product photo here is a fixed 1536x1024, i.e. a real 3:2
   frame). A fixed-height box with a fluid (roughly 1.3-1.4:1) width was
   never going to match that 3:2 photo, so object-fit: contain was
   ALWAYS letterboxing -- reducing the img's own padding (below) could
   only ever shrink one layer of the white space, not the structural
   mismatch underneath it. Matching the box's own aspect-ratio to the
   real photo aspect means contain has nothing left to letterbox: the
   image fills the box exactly, and only the small deliberate padding
   remains. Replaces the old fixed height (520px desktop / capped on
   mobile) -- aspect-ratio drives the height at every width now, so no
   separate mobile override is needed either. */
.pdp-gallery__main { position: relative; border-radius: var(--radius-category-card); overflow: hidden; aspect-ratio: 3/2; background: var(--color-beige-light); }
/* object-fit: contain, not cover -- this is the page where a shopper
   decides whether to buy the physical object; the complete product
   (edges, hardware, corners, full silhouette) must stay visible, never
   zoomed past the frame. Real neutral studio backdrop + padding instead
   of the dark panel background, matching .product-card__media. */
.pdp-gallery__main img { width: 100%; height: 100%; object-fit: contain; padding: clamp(8px, 2%, 16px); box-sizing: border-box; }

/* Real gap found in the mobile motion audit (2026-08-21), Phase 19:
   switching thumbnails/swiping just snapped the main <img>'s src
   instantly, no transition at all. showMedia() (product-detail.js) now
   toggles .is-loading around the src swap -- opacity fades out, the new
   image loads, then fades back in. Kept deliberately short (--motion-
   fast) so it reads as "instant but smooth", never a wait. */
.pdp-gallery__main img[data-gallery-main] { transition: opacity var(--motion-fast) var(--ease-premium), transform var(--motion-normal) var(--ease-premium); }
.pdp-gallery__main img[data-gallery-main].is-loading { opacity: 0; }

/* Phase 19: video/360 should also "transition smoothly" when switched
   to, not just snap into view (display:none -> block). One shared
   one-shot fade, applied by showMedia() to whichever element just
   became visible. Deliberately not applied to the 3D <model-viewer> --
   Phase 19 explicitly says "3D: do not animate unnecessarily", and
   model-viewer already has its own load transition. */
@keyframes pdp-media-fade-in { from { opacity: 0; } to { opacity: 1; } }
.pdp-media-fade-in { animation: pdp-media-fade-in var(--motion-normal) var(--ease-premium); }

/* Phase 20: tap-to-zoom on the main product image only (video has its
   own controls, 360/3D already have their own drag/orbit interactions
   that a zoom gesture here would fight with -- see product-detail.js's
   click handler, which only wires this up for the "image" media type).
   transform-origin is set per-tap by JS to zoom toward where the user
   actually tapped, not always dead-center. Capped at 1.8x -- "not
   beyond useful detail" per the spec, still well within the padded
   .pdp-gallery__main box so nothing crops at the container edge. */
.pdp-gallery__main.is-zoomable img[data-gallery-main] { cursor: zoom-in; }
.pdp-gallery__main.is-zoomed img[data-gallery-main] { cursor: zoom-out; transform: scale(1.8); }
/* Real bug fix: the <video> element (product_detail.html) had no sizing
   CSS at all -- only `hidden` was toggled by JS, so an unstyled <video>
   renders at its own native pixel dimensions (e.g. 1920x1080), not
   contained to this box. .pdp-gallery__main's own overflow:hidden would
   have clipped it, but uncontrolled/zoomed, not a real "contain"
   presentation. object-fit:contain preserves the video's real aspect
   ratio -- never crops or stretches product-focused footage. */
.pdp-gallery__main video { width: 100%; height: 100%; object-fit: contain; }
/* Same dark-gradient + gold "AK" monogram fallback used site-wide for
   no-photo states (product cards, category tiles, leather swatches). */
.pdp-gallery__main-placeholder {
  width: 100%; height: 100%;
  background: linear-gradient(160deg, var(--color-charcoal-surface) 0%, var(--color-charcoal-secondary) 100%);
  display: flex; align-items: center; justify-content: center;
}
.pdp-gallery__main-placeholder::before {
  content: "AK";
  font-family: var(--font-serif);
  font-size: 96px;
  color: var(--color-gold-accent);
  opacity: .14;
}
.pdp-gallery__thumbs { display: flex; gap: 12px; margin-top: 14px; flex-wrap: wrap; }
.pdp-gallery__thumb { width: 78px; height: 78px; border-radius: 10px; overflow: hidden; cursor: pointer; border: 2px solid transparent; background: var(--color-beige-light); }
.pdp-gallery__thumb.is-active { border-color: var(--color-gold-accent); }
.pdp-gallery__thumb img { width: 100%; height: 100%; object-fit: contain; padding: 6px; box-sizing: border-box; }

.pdp-title { font-family: var(--font-serif); font-size: 32px; margin: 0 0 12px; font-weight: 600; }
.pdp-rating { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; color: var(--color-text-grey); font-size: 13.5px; }
.pdp-rating--empty { color: var(--color-gold-accent); text-decoration: underline; text-underline-offset: 3px; }
.pdp-rating--empty:hover { color: var(--color-gold-hover); }
.pdp-price { display: flex; align-items: baseline; gap: 12px; margin-bottom: 20px; }
.pdp-price .current { font-size: 26px; color: var(--color-gold-accent); font-weight: 700; }
.pdp-price .old { font-size: 16px; color: #6a6a6a; text-decoration: line-through; }
/* Real feature (2026-08-28), user-requested: "it should also show much
   much percentage descount we are providing" -- the same real
   error/sale tone already used sitewide for LOW STOCK/SOLD OUT, not the
   gold .badge (that's reserved for Best Seller/New Arrival). */
.pdp-price .badge-discount { align-self: center; background: var(--color-error-bg); color: var(--color-error-text); }
.pdp-desc { color: var(--color-text-grey); font-size: 14.5px; line-height: 1.75; margin: 0 0 26px; max-width: 480px; }

/* Real bug fix: found live during the mobile audit -- `flex-wrap: nowrap`
   (the default) plus no mobile override meant a product with many color
   variants (this store has some with 10+) pushed the row past the
   viewport with no wrap and no scroll container, which forced the whole
   page's layout viewport wider than the device -- the identical bug
   class found and fixed on the Custom Order thread-color row this same
   session (see custom-order.css). Confirmed live: window.innerWidth read
   510 instead of 320 on a real 10-variant product before this fix. */
.pdp-swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.pdp-swatch { width: 40px; height: 40px; border-radius: 50%; cursor: pointer; border: 2px solid rgba(255,255,255,.2); }
.pdp-swatch.is-selected { border-color: var(--color-gold-accent); }

.pdp-qty { display: flex; align-items: center; border: 1px solid rgba(255,255,255,.15); border-radius: 8px; }
.pdp-qty button { width: 40px; height: 44px; background: none; border: none; color: var(--color-beige-light); font-size: 16px; cursor: pointer; }
.pdp-qty span, .pdp-qty input { width: 34px; text-align: center; font-size: 14px; background: none; border: none; color: var(--color-beige-light); }

.pdp-actions { display: flex; align-items: center; gap: 20px; margin-bottom: 26px; flex-wrap: wrap; }

/* Real launch discount (2026-09-10) -- same gold-accent treatment as
   the utility bar's version of this offer (nav.css), repeated here
   right above the Add to Cart/Buy Now buttons. */
.pdp-launch-offer { display: flex; gap: 8px; align-items: center; font-size: 13px; color: var(--color-gold-accent); margin-bottom: 18px; }
.pdp-launch-offer strong { letter-spacing: .03em; }

.pdp-trust-mini { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; padding-top: 24px; border-top: 1px solid rgba(255,255,255,.08); }
.pdp-trust-mini > div { display: flex; gap: 10px; align-items: center; font-size: 12.5px; color: var(--color-text-grey); }

.pdp-tabs-section { max-width: var(--content-max-width); margin: 0 auto; padding: 0 48px 80px; }
/* User-reported and confirmed live: .pdp-tabs-section kept the flat
   desktop 48px side padding at every viewport -- .pdp-main and
   .pdp-breadcrumb right above it in this same file already got a
   639px override (48px -> 20px) when this exact bug class was fixed
   there, but this section was missed. Result: the whole tab list (and
   every tab panel's content under it) sat indented ~28px further
   right than the rest of the page, reading as visibly off from the
   product title/gallery above it instead of flush with the same left
   edge. */
@media (max-width: 639px) { .pdp-tabs-section { padding: 0 20px 56px; } }
.pdp-tabs { display: flex; gap: 34px; border-bottom: 1px solid rgba(255,255,255,.1); margin-bottom: 32px; flex-wrap: wrap; }
.pdp-tab { background: none; border: none; cursor: pointer; padding-bottom: 16px; font-size: 12px; font-weight: 700; letter-spacing: .05em; color: var(--color-text-grey-dim); border-bottom: 2px solid transparent; }
.pdp-tab.is-active { color: var(--color-gold-accent); border-bottom-color: var(--color-gold-accent); }
.pdp-tab-panel { display: none; }
.pdp-tab-panel.is-active { display: block; }
/* Real mobile fix: 5 tabs wrapped into an uneven 3-row cluster of
   sub-44px buttons (measured ~34px tall live) -- exactly the "busy,
   cramped" anti-pattern. Restyled into a real full-width vertical list
   on mobile, one row per section, each a real 44px+ touch target,
   active row picked out with a gold accent bar -- the same underlying
   JS (single panel visible at a time, ?tab= deep-linking, the review
   form inside its panel) is untouched, only the tab strip's own layout
   changed. */
@media (max-width: 639px) {
  .pdp-tabs { flex-direction: column; gap: 0; border-bottom: none; margin-bottom: 4px; }
  .pdp-tab {
    text-align: left;
    padding: 15px 4px 15px 16px;
    min-height: 44px;
    border-bottom: 1px solid rgba(255,255,255,.08);
    border-left: 3px solid transparent;
    font-size: 12.5px;
  }
  .pdp-tab.is-active { border-bottom-color: rgba(255,255,255,.08); border-left-color: var(--color-gold-accent); background: rgba(201,162,39,.04); }
  .pdp-tab-panel.is-active { padding: 18px 4px 8px; }
}

.pdp-features { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.pdp-feature-row { display: flex; gap: 10px; align-items: center; font-size: 13.5px; color: var(--color-text-grey); }

.pdp-spec-table { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; max-width: 600px; }
.pdp-spec-table > div { font-size: 13.5px; padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,.08); }
.pdp-spec-table > div:nth-child(odd) { color: var(--color-text-grey-dim); }

.pdp-review { border-bottom: 1px solid rgba(255,255,255,.08); padding-bottom: 18px; margin-bottom: 20px; max-width: 640px; }
.pdp-review .stars { display: flex; gap: 3px; margin-bottom: 8px; color: var(--color-gold-accent); }

.pdp-review-form { max-width: 480px; margin-top: 30px; }
.pdp-review-form .rating-radio { display: flex; gap: 10px; margin-bottom: 16px; }
.pdp-review-form .rating-radio label { cursor: pointer; }

.sticky-action-bar {
  position: fixed; bottom: 0; left: 0; right: 0;
  background: var(--color-charcoal-secondary);
  border-top: 1px solid rgba(255,255,255,.1);
  padding: 14px 48px;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  z-index: 250;
  box-shadow: var(--shadow-sticky-bar);
  transform: translateY(100%);
  transition: transform .25s ease;
}
.sticky-action-bar.is-visible { transform: translateY(0); }
@media (max-width: 639px) { .sticky-action-bar { padding: 14px 20px; } }

/* Real finding from the mobile audit: at narrow phone widths (measured on
   a real 375px viewport) the thumbnail+name+price group and the two
   action buttons genuinely could not both fit -- their combined content
   width (~358px) plus the base 24px gap exceeded the available space even
   after the 639px rule above trims the padding, causing this fixed bar to
   overflow its own 375px box by ~27px. The two buttons are the actual
   call-to-action and can't shrink further without hurting tap targets, so
   the thumbnail (purely decorative here -- the product photo is already
   on the page) and then the product name (redundant with the buttons'
   context) are dropped first, keeping just the price, which real testing
   confirmed comfortably fits alongside both buttons. */
@media (max-width: 639px) {
  .sticky-action-bar { gap: 10px; }
  .sticky-action-bar__thumb { display: none; }
}
@media (max-width: 420px) {
  .sticky-action-bar__name { display: none; }
}
