/* ═══════════════════════════════════════════════════════════════════
   Product detail page — the conversion surface.

   MOBILE FIRST. Everything outside a media query is the phone layout;
   every @media is min-width. Below 768 the gallery and the decision
   column stack and the buy controls sit within a thumb's reach; above
   it they sit side by side and nothing else changes (CLAUDE.md §9.1).

   Three rules did most of the shaping:

   §9.9  The top of a phone screen is the most expensive space on the
         site. Image → title → price → stock → Add to cart, and nothing
         decorative in front of them. Support, specifications, the long
         description and the related rail all come after.

   §9.10 Never list everything. The description, a long specification
         table and the related grid each clip with max-height — never
         display:none, never [hidden] — behind a real button that names
         what it reveals, so the text stays in the DOM and indexable.

   §9.11 No text of ours on a product photograph. The "tap to zoom" hint
         and the image counter used to be a pill floating on the picture;
         they now sit in their own row beneath it, where there is a
         contrast ratio we actually control.
   ═══════════════════════════════════════════════════════════════════ */

.pdp{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--sp-5);
  padding-block:var(--sp-4) var(--sp-6)}

/* ── Gallery ────────────────────────────────────────────────────── */
.pdp-gallery{min-width:0}
.pdp-main{aspect-ratio:1/1;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-lg);overflow:hidden;display:flex;align-items:center;
  justify-content:center}
.pdp-main img{width:100%;height:100%;object-fit:contain}
.pdp-main .ph{width:38%;height:38%;color:var(--ink-3);stroke-width:1.2}

/* §9.11 — beneath the photograph, in our own chrome, never on it. */
.pdp-viewrow{display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp-3);margin-top:var(--sp-2);flex-wrap:wrap}
.pdp-hint{display:inline-flex;align-items:center;gap:var(--sp-2);
  font-size:.875rem;font-weight:600;color:var(--ink-3)}
.pdp-hint .ico{width:1.55em;height:1.55em}     /* §9.3 — 22px beside 14px meta */
.pdp-count{font-size:.875rem;font-weight:600;color:var(--ink-3);
  font-variant-numeric:tabular-nums}

/* §9.4 — more than one image means a contained scrollable strip. */
.pdp-thumbs{display:flex;gap:var(--sp-2);margin-top:var(--sp-3);
  overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;
  scrollbar-width:none;padding-bottom:2px}
.pdp-thumbs::-webkit-scrollbar{display:none}
.pdp-thumbs button{width:76px;height:76px;flex:0 0 auto;border:2px solid var(--line);
  border-radius:var(--r-sm);overflow:hidden;background:var(--surface);padding:2px}
.pdp-thumbs button[aria-current="true"]{border-color:var(--brand)}
.pdp-thumbs img{width:100%;height:100%;object-fit:contain}

/* ── The decision column ────────────────────────────────────────── */
.pdp-info{min-width:0;display:flex;flex-direction:column;gap:var(--sp-3)}
.pdp-info h1{font-size:1.5rem;font-weight:800}
.pdp-sku{font-size:.875rem;color:var(--ink-3);font-variant-numeric:tabular-nums;
  margin-top:calc(var(--sp-2) * -1)}
.pdp-price{display:flex;align-items:baseline;gap:var(--sp-3);flex-wrap:wrap}
.pdp-price .now{font-size:1.875rem;font-weight:900;color:var(--ink);
  font-variant-numeric:tabular-nums}
.pdp-price .was{font-size:1.0625rem;color:var(--ink-3);text-decoration:line-through;
  font-variant-numeric:tabular-nums}
.pdp-info .card-stock{font-size:1rem}
.pdp-info .card-stock .ico{width:1.4em;height:1.4em}
/* TONE.md §3.1 — the seller's own opening line, cut to one fact. */
.pdp-short{font-size:1rem;line-height:1.6;color:var(--ink-2);max-width:65ch}

/* ── Quantity + Add to cart ─────────────────────────────────────── */
/* GRID, not flex. On a phone the stepper and Add to cart share row 1
   and Buy now takes the whole of row 2 — three controls do not fit on a
   360px line. From 1024px the two buttons sit side by side in row 1,
   which is the first width at which the info column can carry both:
   "Add to cart" with its icon needs ~150px before the label starts to
   clip, and at 900px the column is 376px wide, all of it. */
.pdp-buy{display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:var(--sp-2);align-items:stretch}
.pdp-buy .stepper{grid-column:1;grid-row:1}
.pdp-buy .pdp-add{grid-column:2;grid-row:1;min-width:0}
.pdp-buy .pdp-now{grid-column:1 / -1;grid-row:2;min-width:0;justify-content:center}
.stepper{display:flex;align-items:stretch;flex:0 0 auto;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface);
  overflow:hidden}
.stepper .step{width:var(--tap);min-height:var(--tap);display:flex;
  align-items:center;justify-content:center;color:var(--ink-2)}
.stepper .step:hover{background:var(--surface-2);color:var(--ink)}
.stepper .step .ico{width:22px;height:22px}   /* §9.3 — icon alone in a 44px target */
/* UI_UX §5 — text + inputmode, never type="number". */
.qty-in{width:48px;min-width:0;border:0;border-inline:1px solid var(--line);
  background:var(--surface);color:var(--ink);text-align:center;
  font-family:inherit;font-size:1rem;font-weight:700;font-variant-numeric:tabular-nums}
.qty-in:focus{outline:none;background:var(--brand-xlight)}

/* ── Support — the honest trust signal (§9.7, TONE §5) ──────────── */
/* Full width, below the gallery/info block — it used to live inside
   .pdp-info, so on desktop it hung off the bottom of the right column
   and aligned with nothing: the image ended and the panel kept going.
   Out here it starts and ends on the page's own gutters like every
   other section. */
.pdp-support{background:var(--brand-xlight);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:var(--sp-4);display:flex;flex-direction:column;
  gap:var(--sp-3);margin-bottom:var(--sp-6)}
.pdp-support-note{font-size:var(--fs-pair-sub);line-height:var(--lh-pair-sub);
  color:var(--ink-2);margin-top:calc(var(--sp-2) * -1)}
.pdp-trust{display:flex;flex-direction:column;gap:var(--sp-3);
  border-top:1px solid var(--line);padding-top:var(--sp-3)}
/* align-items:center, not flex-start. The glyph labels the whole pair,
   and a 26px icon hung off the TOP of a two-line block lines up with
   nothing — it overhangs the heading's line box and reads as floating.
   It sits on the block's centre line instead. */
.pdp-trust li{display:flex;align-items:center;gap:var(--sp-3);
  font-size:1rem;color:var(--ink-2)}
.pdp-trust .ico{width:1.6em;height:1.6em;flex:0 0 auto;color:var(--brand-ink)}  /* §9.3 — 26px */
/* The pair: the promise, then the sentence that qualifies it. Both were
   16px, which is not a hierarchy. */
.pdp-trust b{display:block;color:var(--ink);font-weight:700;
  font-size:var(--fs-pair-head);line-height:1.3}
.pdp-trust .d{display:block;font-size:var(--fs-pair-sub);
  line-height:var(--lh-pair-sub)}

/* ── Sections ───────────────────────────────────────────────────── */
.pdp-sec{padding-top:var(--sp-6)}
.pdp-sec h2{font-size:1.25rem;font-weight:800;margin-bottom:var(--sp-3)}

/* ── Disclosure (§9.10) ──────────────────────────────────────────
   A max-height clip, never display:none and never [hidden]: the text
   stays in the DOM for assistive tech and for a crawler. The control is
   a real button, 44px tall, 16px label, and it names what it reveals. */
.pdp-clip{position:relative}
.pdp-clip.is-clipped{overflow:hidden}
.pdp-clip.is-clipped::after{content:'';position:absolute;inset-inline:0;bottom:0;
  height:var(--sp-8);pointer-events:none;
  background:linear-gradient(180deg,transparent,var(--bg))}
.pdp-desc-clip.is-clipped{max-height:15em}
/* Four rows plus a slice of the fifth: the cut is the affordance. */
.pdp-spec-clip.is-clipped{max-height:calc(var(--tap) * 4 + var(--sp-3))}

.pdp-more{display:inline-flex;align-items:center;gap:var(--sp-2);
  min-height:var(--tap);margin-top:var(--sp-2);padding-inline:0;
  font-size:1rem;font-weight:700;color:var(--brand-ink);
  text-decoration:underline;text-underline-offset:4px}
.pdp-more .ico{width:22px;height:22px;transform:rotate(90deg);transition:transform .15s ease}
.pdp-more[aria-expanded="true"] .ico{transform:rotate(-90deg)}
.pdp-more:hover{color:var(--ink)}


/* Recommendation rails (Similar, Frequently bought together, Customers
   also viewed) are home-page rails — public/js/rail.js, styled in
   home.css: four, then "Show more …" in fours, at every width. */

/* ── Specifications table ───────────────────────────────────────── */
.pdp-specs{width:100%;border-collapse:collapse;table-layout:fixed}
.pdp-specs tr{height:var(--tap);border-bottom:1px solid var(--line-soft)}
.pdp-specs th,.pdp-specs td{padding:var(--sp-2) var(--sp-3);text-align:left;
  font-size:1rem;overflow-wrap:anywhere}
.pdp-specs th{width:46%;color:var(--ink-3);font-weight:600}
.pdp-specs td{color:var(--ink);font-weight:700;font-variant-numeric:tabular-nums}

/* ── Description — the shop's own WooCommerce HTML ──────────────── */
.pdp-desc{font-size:1rem;line-height:1.75;color:var(--ink-2);max-width:70ch}
.pdp-desc h2,.pdp-desc h3{font-size:1.125rem;margin:var(--sp-5) 0 var(--sp-2)}
.pdp-desc p{margin-bottom:var(--sp-3)}
.pdp-desc ul{list-style:disc;padding-left:var(--sp-5);margin-bottom:var(--sp-3)}
.pdp-desc li{margin-bottom:var(--sp-1)}
.pdp-desc img{border-radius:var(--r);margin-block:var(--sp-3)}
.pdp-desc table{width:100%;border-collapse:collapse;font-size:.9375rem}
.pdp-desc td,.pdp-desc th{border:1px solid var(--line);padding:var(--sp-2);text-align:left}

.pdp-social{padding-top:var(--sp-6)}
.pdp-social-h{font-size:1.25rem;font-weight:800;margin-bottom:var(--sp-3)}

/* ── Sticky buy bar ─────────────────────────────────────────────────
   Up only once the real Add to cart has scrolled off the top. It clears
   the fixed tab bar by sitting exactly --tabbar-h above the floor, and
   it clears the WhatsApp FAB by lifting it: the bar is exactly
   `--tap + --sp-4` tall (44px of control, 8px of padding either side),
   so the offset below is arithmetic rather than a guess.

   visibility (not display:none) keeps it out of the tab order while
   parked — it is a duplicated control, not content, so §9.10's
   max-height rule does not apply to it. */
.pdp-bar{position:fixed;left:0;right:0;z-index:var(--z-sticky);
  /* The extra 1px is the tab bar's own top border. Without it the bar's
     bottom edge lands ON that hairline — measurably covering it, and
     visually stacking two rules into one thick one. */
  bottom:calc(var(--tabbar-h) + 1px + env(safe-area-inset-bottom,0px));
  background:var(--surface);border-top:1px solid var(--line);
  box-shadow:var(--shadow-lg);
  visibility:hidden;transform:translateY(100%);transition:transform .2s ease,visibility .2s}
.pdp-bar.is-on{visibility:visible;transform:none}
.pdp-bar-in{display:flex;align-items:center;gap:var(--sp-2);
  max-width:var(--page);margin-inline:auto;
  padding:var(--sp-2) var(--gutter);min-height:calc(var(--tap) + var(--sp-4))}
.pdp-bar .pdp-add{flex:1 1 auto;min-width:0}
/* The name and price are a redundant echo of the h1 above; there is no
   room for them on a phone and they are not needed there, because the
   customer has just scrolled past both. */
.pdp-bar-id{display:none;flex-direction:column;min-width:0;flex:1 1 auto}
.pdp-bar-id .nm{font-size:.9375rem;font-weight:600;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pdp-bar-id .pr{font-size:1.0625rem;font-weight:800;color:var(--ink);
  font-variant-numeric:tabular-nums}
/* So the last section is never sitting under the bar. */
.pdp-barspace{height:calc(var(--tap) + var(--sp-4))}

body.pdp-bar-on .wa-fab{
  bottom:calc(var(--tabbar-h) + 1px + var(--tap) + var(--sp-4) + var(--sp-3)
    + env(safe-area-inset-bottom,0px));
  transition:bottom .2s ease}


@media (min-width:640px){
  .pdp-bar-id{display:flex}
  .pdp-bar .pdp-add{flex:0 0 auto;min-width:200px}
}

@media (min-width:768px){
  /* Room to read: the clip is about protecting phone space, and there is
     more of it here. */
  .pdp-desc-clip.is-clipped{max-height:22em}
  /* The gallery is CAPPED, not half the page. Two equal columns meant a
     1:1 image grew with the viewport while the info column's content did
     not, so the buy column ended 304px above the image at 1280 and 311px
     at 1440 — half a column of nothing beside the most important controls
     on the page. Capping the image gives the width back to the copy,
     which is what actually needs it. */
  .pdp{grid-template-columns:minmax(0,460px) minmax(0,1fr);gap:var(--sp-8);
    align-items:start;padding-block:var(--sp-5) var(--sp-8)}
  .pdp-info h1{font-size:1.875rem}
  /* NOT a row here. At 844px — a phone held sideways — the ask, the
     note and three promises in one row measured 979px against an 844px
     viewport and panned the page, which golden rule 4 forbids outright.
     The row waits for 900px; see the block below. */
  .pdp-support{padding:var(--sp-5)}
  .pdp-sec h2,.pdp-social-h{font-size:1.5rem}
  /* The tab bar retires at 768, so the bar drops to the floor and the
     FAB only has to clear the bar itself. */
  .pdp-bar{bottom:0}
  .pdp-bar-in{padding-bottom:calc(var(--sp-2) + env(safe-area-inset-bottom,0px))}
  body.pdp-bar-on .wa-fab{
    bottom:calc(var(--tap) + var(--sp-4) + var(--sp-5) + env(safe-area-inset-bottom,0px))}
}

@media (min-width:900px){
  /* One band instead of a tall column: the ask, then the three promises
     laid out beside it. §9.1 — same content, adapted. */
  .pdp-support{flex-direction:row;align-items:center;gap:var(--sp-6)}
  .pdp-support>.btn{flex:0 0 auto;width:auto}
  .pdp-support-note{flex:0 0 auto;margin-top:0;max-width:22ch}
  .pdp-trust{flex:1 1 auto;flex-direction:row;gap:var(--sp-6);
    border-top:0;border-left:1px solid var(--line);
    padding-top:0;padding-left:var(--sp-6)}
  .pdp-trust li{flex:1 1 0;min-width:0}
}

@media (min-width:1024px){
  /* Add to cart and Buy now, side by side. Below this the info column is
     too narrow to carry the stepper and two labelled buttons on one
     line; see the .pdp-buy comment above. */
  .pdp-buy{grid-template-columns:auto minmax(0,1fr) minmax(0,1fr)}
  .pdp-buy .pdp-now{grid-column:3;grid-row:1}
}
