/* TactaBlue PDP v28 styles — extracted from tactablue-pdp-v28.html and scoped under .tb-pdp-v28. Do not load globally. */

/* ==========================================================================
   1. TOKENS
   Single source of truth. Same palette/type as the v10 homepage system.
   ========================================================================== */
.tb-pdp-v28{
  --navy:#0A5098;
  --navy-d:#083E77;
  --navy-ink:#0C1E33;
  --ink:#16202B;
  --body:#3A4653;
  --muted:#626E7A;
  --paper:#FFFFFF;
  --mist:#F4F7FA;
  --mist2:#EAF1F8;
  --line:#DCE4EC;
  --line-2:#CFE0F1;
  --accent:#E7A33C;
  --accent-d:#D08F2C;
  --good:#217B48;
  --good-bg:#EFF8F2;
  --warn-bg:#FFF7E7;
  --warn-ink:#654915;
  --disp:'Oswald', system-ui, sans-serif;
  --text:'Roboto', system-ui, sans-serif;
  --shadow:0 10px 28px rgba(10,44,82,.07);
  --shadow-lg:0 16px 44px rgba(10,44,82,.14);
  --gut:22px;
  --maxw:1560px;
}

/* ==========================================================================
   2. RESET + BASE
   ========================================================================== */
.tb-pdp-v28 *{box-sizing:border-box}
.tb-pdp-v28{scroll-behavior:smooth;scroll-padding-top:24px}
.tb-pdp-v28{margin:0;font-family:var(--text);color:var(--body);background:#fff;line-height:1.55;-webkit-font-smoothing:antialiased}
.tb-pdp-v28 a{color:inherit;text-decoration:none}
.tb-pdp-v28 img{display:block;max-width:100%}
.tb-pdp-v28 button,.tb-pdp-v28 input,.tb-pdp-v28 select,.tb-pdp-v28 textarea{font:inherit}
.tb-pdp-v28 :focus-visible{outline:3px solid var(--accent);outline-offset:2px}
.tb-pdp-v28 .tb-wrap{max-width:var(--maxw);margin:0 auto;padding:0 28px}
.tb-pdp-v28 .tb-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.tb-pdp-v28 h1,.tb-pdp-v28 h2,.tb-pdp-v28 h3,.tb-pdp-v28 h4{font-family:var(--disp);color:var(--navy-ink);font-weight:700;line-height:1.1;margin:0}

/* ==========================================================================
   3. SHIP BAR  (parity #1)
   ========================================================================== */
.tb-pdp-v28 .tb-shipbar{position:relative;overflow:hidden;background:var(--navy);color:#fff;font-size:14px;font-weight:500;text-align:center}
.tb-pdp-v28 .tb-shipbar .tb-wrap{padding:9px 24px;display:flex;gap:10px;align-items:center;justify-content:center}
.tb-pdp-v28 .tb-shipbar b{color:var(--accent)}
.tb-pdp-v28 .tb-shipbar__shine{position:absolute;top:0;left:-40%;width:40%;height:100%;pointer-events:none;
  background:linear-gradient(100deg,transparent 0%,rgba(255,255,255,.22) 50%,transparent 100%);
  animation:tbShine 6s ease-in-out infinite}
@keyframes tbShine{0%{left:-40%}55%,100%{left:120%}}
@media(prefers-reduced-motion:reduce){.tb-pdp-v28 .tb-shipbar__shine{animation:none;display:none}}

/* ==========================================================================
   4. HEADER + NAV  (parity #2, #3)
   ========================================================================== */
.tb-pdp-v28 .tb-hdr{background:linear-gradient(180deg,#fff,#F7FAFD);border-bottom:1px solid var(--line)}
.tb-pdp-v28 .tb-hdr .tb-wrap{min-height:96px;display:grid;grid-template-columns:250px minmax(300px,1fr) 158px;gap:28px;align-items:center}
/* Brand mark. The data URI keeps this file standalone; in the theme, swap it
   for <img src="/wp-content/uploads/tactablue-logo.png" width="630" height="133">
   and ship the two PNGs alongside this file. */
.tb-pdp-v28 .tb-logo{display:block;line-height:0}
.tb-pdp-v28 .tb-logo img{width:100%;max-width:238px;height:auto}
.tb-pdp-v28 .tb-search{position:relative;display:flex;height:48px;border:1px solid var(--line);background:#fff}
.tb-pdp-v28 .tb-search input{flex:1;min-width:0;border:0;padding:0 14px;background:transparent}
.tb-pdp-v28 .tb-search button{border:0;background:var(--navy);color:#fff;padding:0 24px;font-weight:700;cursor:pointer}
.tb-pdp-v28 .tb-search button:hover{background:var(--navy-d)}
.tb-pdp-v28 .tb-suggest{position:absolute;top:100%;left:0;right:0;background:#fff;border:1px solid var(--line);border-top:0;box-shadow:var(--shadow-lg);z-index:40;display:none}
.tb-pdp-v28 .tb-suggest.is-open{display:block}
.tb-pdp-v28 .tb-suggest a{display:flex;gap:10px;align-items:center;padding:10px 14px;font-size:14px;border-bottom:1px solid var(--mist)}
.tb-pdp-v28 .tb-suggest a:hover{background:var(--mist)}
.tb-pdp-v28 .tb-hicons{display:flex;justify-content:flex-end;gap:8px}
.tb-pdp-v28 .tb-hicons a{position:relative;width:42px;height:42px;display:grid;place-items:center;border:1px solid var(--line);border-radius:50%;background:#fff}
.tb-pdp-v28 .tb-hicons a:hover{border-color:var(--navy);color:var(--navy)}
.tb-pdp-v28 .tb-hcount{position:absolute;top:-4px;right:-4px;min-width:19px;height:19px;padding:0 5px;border-radius:10px;background:var(--accent);color:var(--navy-ink);font-size:11px;font-weight:700;display:grid;place-items:center}

.tb-pdp-v28 .tb-nav{position:relative;background:#fff;border-bottom:1px solid var(--line);box-shadow:0 2px 8px rgba(10,44,82,.035)}
.tb-pdp-v28 .tb-nav .tb-wrap{display:flex;gap:26px;align-items:center;flex-wrap:wrap;padding:12px 28px;font-size:14px}
.tb-pdp-v28 .tb-nav a:hover{color:var(--navy)}
.tb-pdp-v28 .tb-nav:after{content:"";display:block;height:2px;background:linear-gradient(90deg,transparent,rgba(10,80,152,.18) 18%,rgba(231,163,60,.35) 50%,rgba(10,80,152,.18) 82%,transparent)}
.tb-pdp-v28 .tb-dd{position:relative}
.tb-pdp-v28 .tb-dd__trigger{font-family:var(--disp);text-transform:uppercase;letter-spacing:.03em;color:var(--navy);font-weight:700;background:#F2F7FC;border:1px solid var(--line-2);padding:7px 12px;cursor:pointer;display:flex;gap:8px;align-items:center}
.tb-pdp-v28 .tb-dd__list{position:absolute;top:calc(100% + 10px);left:0;width:290px;background:#fff;border:1px solid var(--line);box-shadow:var(--shadow-lg);padding:6px;z-index:50;display:none}
.tb-pdp-v28 .tb-dd.is-open .tb-dd__list{display:block}
.tb-pdp-v28 .tb-dd__item{display:flex;justify-content:space-between;align-items:center;padding:9px 12px;font-size:14px}
.tb-pdp-v28 .tb-dd__item:hover{background:var(--mist2);color:var(--navy)}

/* ==========================================================================
   5. PDP SHELL + BREADCRUMB  (parity #4)
   ========================================================================== */
.tb-pdp-v28{background:linear-gradient(180deg,#fff 0%,#F7FAFD 100%);padding:22px 0 0}/* no bottom padding: the full-bleed newsletter (last section) must butt the footer, no white strip */
.tb-pdp-v28 .tb-crumb{list-style:none;margin:0 0 18px;padding:0;display:flex;gap:8px;flex-wrap:wrap;font-size:13px;color:var(--muted)}
.tb-pdp-v28 .tb-crumb li:not(:last-child):after{content:"/";margin-left:8px;color:#AAB6C2}
.tb-pdp-v28 .tb-crumb a:hover{color:var(--navy)}
/* Title spans the full page width. The two columns below it therefore start at
   the same y, and because they stretch, they finish at the same y too. */
.tb-pdp-v28 .tb-grid{display:grid;grid-template-columns:minmax(620px,63%) minmax(400px,37%);gap:var(--gut);align-items:start}/* start, not stretch: don't stretch the GALLERY card to match a taller buy box (variable products add variation-form height) — avoids empty space below the thumbnails. The right column opts back into stretch on the next line. */
.tb-pdp-v28 .tb-col{display:flex;flex-direction:column;gap:18px}
/* Right column opts back IN to stretch, so its bottom card finishes level with the
   gallery. Scoped to the right column on purpose: `align-items:stretch` on the grid
   would also stretch the gallery and reintroduce the dead space above. When the buy
   column is naturally the taller of the two (variable products) the row height is
   already its own height, so this is a no-op and nothing regresses. */
.tb-pdp-v28 .tb-grid > .tb-col:not(.tb-col--left){align-self:stretch}
.tb-pdp-v28 .tb-col--left{min-width:0;position:sticky;top:16px;align-self:start}/* sticky gallery: when the buy column is taller (e.g. variable products), the gallery follows the scroll instead of leaving dead space below the thumbnails. Collapses on mobile where .tb-col becomes display:contents. */
.tb-pdp-v28 .tb-col--left .tb-gal{flex:1;display:flex;flex-direction:column}
/* Right column: the BUY box grows to fill remaining height and its blocks
   space out evenly, so the column bottom lines up with the gallery on the
   left while the features card keeps its natural (compact) height. */
.tb-pdp-v28 .tb-col:not(.tb-col--left) .tb-buy{flex:1;display:flex;flex-direction:column;justify-content:space-between;gap:14px}
.tb-pdp-v28 .tb-col:not(.tb-col--left) .tb-buy > *{margin-top:0;margin-bottom:0}
.tb-pdp-v28 .tb-col:not(.tb-col--left) .tb-buy > .tb-stock{align-self:flex-start}
.tb-pdp-v28 .tb-card{border:1px solid var(--line);background:#fff;box-shadow:var(--shadow)}

/* ==========================================================================
   6. TITLE CARD  (parity #5, #6, #7, #8)
   ========================================================================== */
.tb-pdp-v28 .tb-title{position:relative;padding:25px 26px 18px;margin-bottom:18px;overflow:hidden;
  background:linear-gradient(180deg,#F7FBFF 0%,#fff 62%)}
.tb-pdp-v28 .tb-title:before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:var(--navy)}
.tb-pdp-v28 .tb-title:after{content:"";position:absolute;top:-40px;right:-40px;width:220px;height:220px;pointer-events:none;
  background:radial-gradient(circle,rgba(10,80,152,.06) 0%,transparent 68%)}
.tb-pdp-v28 .tb-title__top{position:relative;min-width:0}

/* The H1 owns the full page width and is locked to a two-line band, so the
   card is the same height for a 40-character title and a 140-character one.
   --h1 is set by the FITH1 script; the clamp is the ceiling, not the answer. */
.tb-pdp-v28 .tb-title h1{
  font-family:var(--disp);
  font-size:var(--h1, clamp(28px,2.7vw,42px));
  line-height:1.18;
  letter-spacing:-.01em;
  margin:8px 0 4px;
  padding-bottom:2px;
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
}
.tb-pdp-v28 .tb-eyebrow{font-family:var(--disp);font-size:13px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--navy);display:inline-flex;align-items:center;gap:9px}
.tb-pdp-v28 .tb-eyebrow:before{content:"";width:20px;height:2px;background:var(--accent)}
.tb-pdp-v28 .tb-review{display:flex;gap:10px 14px;flex-wrap:wrap;align-items:center;font-size:14px;color:var(--muted);margin-bottom:0}
.tb-pdp-v28 .tb-stars{color:#D6DEE7;letter-spacing:2px;font-size:15px}
.tb-pdp-v28 .tb-stars[data-rating]{color:var(--accent)}
.tb-pdp-v28 .tb-review a{color:var(--navy);font-weight:800}
/* One continuous identity strip: review status | brand · MFR# · UPC | share.
   Every item is the same object type separated by hairline rules, so nothing
   reads as a floating box bolted into the middle of the row. */
.tb-pdp-v28 .tb-metarow{position:relative;display:flex;justify-content:flex-start;align-items:center;gap:12px 0;flex-wrap:wrap;
  margin-top:16px;padding-top:16px}
.tb-pdp-v28 .tb-metarow:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:var(--line)}
.tb-pdp-v28 .tb-share-btn{margin-left:auto}
.tb-pdp-v28 .tb-review{padding-right:22px}
.tb-pdp-v28 .tb-meta{border-left:1px solid var(--line);padding-left:22px}
.tb-pdp-v28 .tb-meta{display:flex;align-items:center;flex-wrap:wrap;font-size:13.5px;color:#5B6876}
.tb-pdp-v28 .tb-meta > *{display:inline-flex;align-items:baseline;gap:7px;padding:0 18px;border-left:1px solid var(--line)}
.tb-pdp-v28 .tb-meta > *:first-child{padding-left:0;border-left:0}
.tb-pdp-v28 .tb-meta .k{font-size:11px;letter-spacing:.09em;text-transform:uppercase;font-weight:800;color:var(--muted)}
.tb-pdp-v28 .tb-meta b{color:var(--ink);font-weight:700}
.tb-pdp-v28 .tb-meta__brand a:not(.tb-meta__shop){font-family:var(--disp);font-size:20px;line-height:1;letter-spacing:.01em;color:var(--navy-ink)}
.tb-pdp-v28 .tb-meta__brand a:not(.tb-meta__shop):hover{color:var(--navy)}
.tb-pdp-v28 .tb-meta__shop{font-family:var(--text);font-weight:800;color:var(--navy);white-space:nowrap;font-size:13px;align-self:center}
.tb-pdp-v28 .tb-meta__shop:hover{text-decoration:underline}
.tb-pdp-v28 .tb-meta b{color:var(--ink)}
.tb-pdp-v28 .tb-share-btn{display:inline-flex;gap:8px;align-items:center;background:#fff;border:1px solid var(--line);color:var(--navy);font-weight:700;padding:7px 13px;cursor:pointer;font-size:13.5px}
.tb-pdp-v28 .tb-share-btn:hover{border-color:var(--navy);background:var(--mist)}
.tb-pdp-v28 .tb-share-btn.is-copied{border-color:var(--good);color:var(--good)}

/* ==========================================================================
   7. GALLERY  (parity #9, #10)
   ========================================================================== */
.tb-pdp-v28 .tb-gal{padding:14px}
/* White stage, not mist. mix-blend-mode:multiply was crushing the whites and
   greys out of product shots — removing it is the single biggest clarity win.
   The stage grows to match the buy-box column, capped so it never gets absurd. */
.tb-pdp-v28 .tb-gal__stage{position:relative;flex:1;min-height:560px;max-height:900px;
  background:#fff;border:1px solid var(--line);
  background-image:radial-gradient(circle at 50% 42%, #fff 0%, #F6F9FC 78%);
  display:grid;place-items:center;overflow:hidden;cursor:zoom-in;padding:26px}
.tb-pdp-v28 .tb-gal__stage img{width:100%;height:100%;object-fit:contain;transition:opacity .18s;
  filter:contrast(1.04) saturate(1.05);image-rendering:auto}
.tb-pdp-v28 .tb-gal__nav{position:absolute;top:50%;transform:translateY(-50%);width:42px;height:42px;border:1px solid var(--line);background:rgba(255,255,255,.94);color:var(--navy-ink);display:grid;place-items:center;cursor:pointer;font-size:18px;z-index:2}
.tb-pdp-v28 .tb-gal__nav:hover{background:#fff;border-color:var(--navy);color:var(--navy)}
.tb-pdp-v28 .tb-gal__nav--prev{left:12px}
.tb-pdp-v28 .tb-gal__nav--next{right:12px}
.tb-pdp-v28 .tb-gal__flags{position:absolute;top:12px;left:12px;display:flex;flex-direction:column;gap:6px;z-index:2}
.tb-pdp-v28 .tb-flag{font-family:var(--disp);font-size:12px;letter-spacing:.08em;text-transform:uppercase;padding:5px 9px;font-weight:600}
.tb-pdp-v28 .tb-flag--accent{background:var(--accent);color:var(--navy-ink)}
.tb-pdp-v28 .tb-flag--good{background:var(--good);color:#fff}
.tb-pdp-v28 .tb-gal__hint{font-size:12px;color:var(--muted);text-align:center;margin:10px 0 13px}
.tb-pdp-v28 .tb-gal__thumbs{display:grid;grid-template-columns:repeat(6,1fr);gap:10px}
.tb-pdp-v28 .tb-thumb{aspect-ratio:1/1;border:1px solid var(--line);background:#fff;padding:7px;cursor:pointer}
.tb-pdp-v28 .tb-thumb img{width:100%;height:100%;object-fit:contain}
.tb-pdp-v28 .tb-thumb:hover{border-color:var(--navy)}

/* Expand to full resolution */
.tb-pdp-v28 .tb-gal__expand{position:absolute;bottom:12px;right:12px;z-index:2;display:flex;gap:7px;align-items:center;
  border:1px solid var(--line);background:rgba(255,255,255,.95);color:var(--navy-ink);
  font-size:12.5px;font-weight:700;padding:7px 11px;cursor:pointer}
.tb-pdp-v28 .tb-gal__expand:hover{border-color:var(--navy);color:var(--navy)}
.tb-pdp-v28 .tb-lb{position:fixed;inset:0;z-index:200;background:rgba(8,20,32,.94);display:none;place-items:center;padding:32px}
.tb-pdp-v28 .tb-lb.is-open{display:grid}
.tb-pdp-v28 .tb-lb img{max-width:100%;max-height:88vh;width:auto;height:auto;object-fit:contain}
.tb-pdp-v28 .tb-lb__close{position:absolute;top:18px;right:22px;border:1px solid rgba(255,255,255,.3);background:transparent;color:#fff;font-size:26px;line-height:1;width:42px;height:42px;cursor:pointer}
.tb-pdp-v28 .tb-lb__close:hover{background:rgba(255,255,255,.12)}
.tb-pdp-v28 .tb-lb__nav{position:absolute;top:50%;transform:translateY(-50%);width:52px;height:52px;border:1px solid rgba(255,255,255,.3);background:transparent;color:#fff;font-size:26px;cursor:pointer}
.tb-pdp-v28 .tb-lb__nav:hover{background:rgba(255,255,255,.12)}
.tb-pdp-v28 .tb-lb__nav--prev{left:22px}
.tb-pdp-v28 .tb-lb__nav--next{right:22px}
.tb-pdp-v28 .tb-lb__count{position:absolute;bottom:22px;left:50%;transform:translateX(-50%);color:#A9C2DC;font-size:13px;letter-spacing:.08em}
.tb-pdp-v28 .tb-thumb.is-active{outline:2px solid var(--accent);border-color:var(--navy)}

/* ==========================================================================
   8. BUY BOX  (parity #14–#25)
   ========================================================================== */
.tb-pdp-v28 .tb-buy{padding:16px}
.tb-pdp-v28 .tb-stock{display:inline-flex;gap:9px;align-items:center;font-size:16px;font-weight:800;color:var(--good);
  margin-bottom:10px;background:var(--good-bg);border:1px solid #CBE7D6;border-radius:999px;padding:7px 15px}
.tb-pdp-v28 .tb-stock .dot{width:10px;height:10px;border-radius:50%;background:currentColor;box-shadow:0 0 0 4px rgba(35,131,77,.14)}
.tb-pdp-v28 .tb-stock small{color:#3E7A57;font-weight:600;font-size:13.5px}
.tb-pdp-v28 .tb-stock .low{color:var(--accent-d)}
/* Out of stock = red, backorder = amber (client 2026-10-16: out of stock must not be green). */
.tb-pdp-v28 .tb-stock.tb-stock--out{color:#B42318;background:#FEF3F2;border-color:#F7C9C5}
.tb-pdp-v28 .tb-stock.tb-stock--out .dot{box-shadow:0 0 0 4px rgba(180,35,24,.14)}
.tb-pdp-v28 .tb-stock.tb-stock--out small{color:#912018}
.tb-pdp-v28 .tb-stock.tb-stock--backorder{color:#93590B;background:#FFF8EB;border-color:#F5DDB0}
.tb-pdp-v28 .tb-stock.tb-stock--backorder .dot{box-shadow:0 0 0 4px rgba(147,89,11,.14)}
.tb-pdp-v28 .tb-stock.tb-stock--backorder small{color:#7A4A09}

.tb-pdp-v28 .tb-pricerow{display:grid;grid-template-columns:minmax(150px,1fr) minmax(230px,1.05fr);gap:12px;align-items:stretch;margin-bottom:13px}
.tb-pdp-v28 .tb-pricebox{position:relative;display:flex;flex-direction:column;justify-content:center;
  background:linear-gradient(180deg,#FDFBF4 0%,#fff 100%);
  border:1px solid #F0E1C2;padding:14px 16px 14px 19px}
.tb-pdp-v28 .tb-pricebox:before{content:"";position:absolute;top:0;bottom:0;left:0;width:4px;background:var(--accent)}
.tb-pdp-v28 .tb-price{font-family:var(--disp);font-size:clamp(34px,3.2vw,48px);line-height:1;color:var(--navy-ink);font-weight:700}
.tb-pdp-v28 .tb-price__was{font-size:20px;color:var(--muted);text-decoration:line-through;margin-left:10px;font-weight:500}
.tb-pdp-v28 .tb-price__save{display:inline-block;margin-top:7px;background:var(--accent);color:var(--navy-ink);font-size:12px;font-weight:800;padding:3px 8px;text-transform:uppercase;letter-spacing:.06em}
.tb-pdp-v28 .tb-price__note{font-size:12.5px;color:var(--muted);margin:6px 0 0}

/* delivery panel (parity #26, #27, #28) */
.tb-pdp-v28 .tb-deliv{display:flex;flex-direction:column;justify-content:center;border:1px solid var(--line-2);background:#F8FBFF;padding:12px 14px;min-height:112px}
.tb-pdp-v28 .tb-deliv__row{display:flex;gap:10px;align-items:flex-start}
.tb-pdp-v28 .tb-deliv__ico{flex:none;color:var(--navy)}
.tb-pdp-v28 .tb-deliv__lab{font-size:11px;letter-spacing:.1em;text-transform:uppercase;font-weight:800;color:var(--muted);display:block}
.tb-pdp-v28 .tb-deliv__date{font-family:var(--disp);font-size:26px;line-height:1.05;color:var(--navy-ink);display:block}
.tb-pdp-v28 .tb-deliv__sub{font-size:12.5px;color:#516273;margin-top:4px}
.tb-pdp-v28 .tb-deliv__sub b{color:var(--navy-ink)}
.tb-pdp-v28 .tb-deliv__cut{font-size:12.5px;color:var(--warn-ink);background:var(--warn-bg);border:1px solid #F0D5A8;padding:5px 8px;margin-top:8px}
.tb-pdp-v28 .tb-deliv__count{font-weight:800}
.tb-pdp-v28 .tb-deliv__intl{display:none;gap:10px;align-items:flex-start}
.tb-pdp-v28 .tb-deliv__intl a{color:var(--navy);font-weight:700;text-decoration:underline}

/* tier picker (parity #16, #17) */
.tb-pdp-v28 .tb-tier{border:1px solid var(--line);margin-bottom:12px}
.tb-pdp-v28 .tb-tier__head{background:#F7FAFD;border-bottom:1px solid var(--line);padding:11px 12px}
.tb-pdp-v28 .tb-tier__head b{display:block;font-family:var(--disp);font-size:17px;letter-spacing:.04em;text-transform:uppercase;color:var(--navy-ink)}
.tb-pdp-v28 .tb-tier__head small{color:var(--muted);font-size:12px}
/* `stretch`, not `center`: the two boxes are a matched pair, so they share the row's height and
   line up top AND bottom rather than only through their centres. */
.tb-pdp-v28 .tb-tier__body{display:grid;grid-template-columns:1fr 165px;gap:10px;align-items:stretch;padding:11px}

/* 🔴 `margin:0` is load-bearing — client-reported, 2026-08-06: "the dropdown doesnt sit in the
   center as needed straight with the 'selected' section".
   `css/style.css:247` sets `select{margin-bottom:1.5rem}` (0,0,1), which this rule never reset.
   With the grid centring each item's MARGIN box, that 24px pushed the visible control 12px
   higher than the Selected panel beside it — measured exactly -12px (_qa-tools/v28_tier.js).

   The arrow is load-bearing too, and it is the SAME trap in reverse. `css/style.css` sets
   `select{appearance:none}` and supplies its own arrow via `background-image`; the `background:#fff`
   SHORTHAND here wiped that image out, so the control had `appearance:none` with no replacement —
   measured `background-image: NONE`. A dropdown with no affordance whatsoever, which is exactly
   what the client saw. Declared as `background-color` + an explicit chevron so neither can wipe
   the other. Chevron is --accent-d (#D08F2C) so it reads as interactive against the navy text —
   the client asked for "a down arrow with a slight different color". */
.tb-pdp-v28 .tb-tier__select{
  min-height:46px;height:auto;margin:0;width:100%;
  border:1px solid var(--line);background-color:#fff;font-weight:700;
  padding:0 38px 0 12px;
  -webkit-appearance:none;-moz-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9' fill='none'%3E%3Cpath d='M1 1L7 7L13 1' stroke='%23D08F2C' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;background-size:14px 9px;
  cursor:pointer;
}
.tb-pdp-v28 .tb-tier__select:hover{border-color:var(--accent-d)}
/* Business-only tiers a regular customer can see but not pick, and the quote row (2026-10-16). */
.tb-pdp-v28 .tb-tier__select option.is-locked,.tb-pdp-v28 .tb-tier__select option.is-quote{color:#8A96A3}
.tb-pdp-v28 .tb-tier__select:focus-visible{outline:2px solid var(--navy);outline-offset:-2px}
.tb-pdp-v28 .tb-tier__out{border:1px solid var(--line);background:#FBFDFF;padding:10px 12px;min-height:46px;display:flex;align-items:center;justify-content:center;text-align:center;font-size:13px;color:#516273}
.tb-pdp-v28 .tb-tier__out b{color:var(--navy);font-size:15px}
.tb-pdp-v28 .tb-tier__biz{border-top:1px solid var(--line);background:var(--warn-bg);padding:11px 12px;font-size:12.8px;color:var(--warn-ink)}
.tb-pdp-v28 .tb-tier__biz b{display:block;color:#4B350F}
.tb-pdp-v28 .tb-tier__biz a{color:var(--navy);font-weight:800}

/* cart form (parity #18–#22) */
.tb-pdp-v28 .tb-cartrow{display:grid;grid-template-columns:112px 1fr;gap:9px}
.tb-pdp-v28 .tb-qty{position:relative;display:flex;height:54px;border:1px solid var(--line);background:#fff}
.tb-pdp-v28 .tb-qty input{width:100%;border:0;padding:0 34px 0 14px;font-weight:700;text-align:left;-moz-appearance:textfield}
.tb-pdp-v28 .tb-qty input::-webkit-outer-spin-button,.tb-pdp-v28 .tb-qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.tb-pdp-v28 .tb-qty__spin{position:absolute;top:0;right:0;width:30px;height:100%;display:flex;flex-direction:column;border-left:1px solid var(--line)}
.tb-pdp-v28 .tb-qty__spin button{flex:1;border:0;background:var(--mist2);color:var(--navy-ink);cursor:pointer;font-size:12px;line-height:1}
.tb-pdp-v28 .tb-qty__spin button:first-child{border-bottom:1px solid var(--line)}
.tb-pdp-v28 .tb-qty__spin button:hover{background:var(--mist)}
.tb-pdp-v28 .tb-btn{position:relative;display:flex;gap:9px;align-items:center;justify-content:center;min-height:54px;border:1px solid transparent;padding:0 18px;font-weight:800;cursor:pointer;transition:background .16s,color .16s}
.tb-pdp-v28 .tb-btn--accent{background:var(--accent);color:var(--navy-ink)}
.tb-pdp-v28 .tb-btn--accent:hover{background:var(--accent-d)}
.tb-pdp-v28 .tb-btn--navy{background:var(--navy);color:#fff}
.tb-pdp-v28 .tb-btn--navy:hover{background:var(--navy-d)}
.tb-pdp-v28 .tb-btn--outline{background:#fff;color:var(--navy);border-color:var(--line);font-weight:700}
.tb-pdp-v28 .tb-btn--outline:hover{border-color:var(--navy);background:var(--mist)}
.tb-pdp-v28 .tb-btn[disabled]{opacity:.5;cursor:not-allowed}
.tb-pdp-v28 .tb-atc__check{display:none}
.tb-pdp-v28 .tb-atc.is-added{background:var(--good);color:#fff}
.tb-pdp-v28 .tb-atc.is-added .tb-atc__ico,.tb-pdp-v28 .tb-atc.is-added .tb-atc__text{display:none}
.tb-pdp-v28 .tb-atc.is-added .tb-atc__check{display:inline-flex;gap:8px;align-items:center}
.tb-pdp-v28 .tb-actions{display:grid;grid-template-columns:1fr 56px 56px;gap:10px;margin-top:10px}
/* ===== Variable/grouped products: skin Woo's native variation form to match the v28 buy box.
   (v28 falls back to woocommerce_template_single_add_to_cart() for non-simple types; without this
   the native form shows WooCommerce's default purple button + unstyled qty/price.) ===== */
.tb-pdp-v28 .tb-varcart .variations{width:100%;border:0;margin:0 0 4px;background:none}
.tb-pdp-v28 .tb-varcart .variations th,.tb-pdp-v28 .tb-varcart .variations td{border:0;padding:2px 0;background:none;vertical-align:middle}
.tb-pdp-v28 .tb-varcart .variations .label label{font-family:var(--disp);font-weight:600;font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:var(--muted)}
.tb-pdp-v28 .tb-varcart .variations select{width:100%;height:48px;border:1px solid var(--line);background:#fff;padding:0 12px;font-size:15px;font-family:var(--text)}
.tb-pdp-v28 .tb-varcart .reset_variations{display:inline-block;margin:2px 0 8px;font-size:13px;color:var(--navy)}
.tb-pdp-v28 .tb-varcart .woocommerce-variation-price{font-family:var(--disp);font-size:22px;color:var(--navy-ink);margin:8px 0 2px}
.tb-pdp-v28 .tb-varcart .woocommerce-variation-price .price{color:var(--navy-ink)}
.tb-pdp-v28 .tb-varcart .woocommerce-variation-availability{color:var(--muted);font-size:14px;margin-bottom:4px}
.tb-pdp-v28 .tb-varcart .woocommerce-variation-add-to-cart{display:grid;grid-template-columns:112px 1fr;gap:9px;align-items:stretch;margin-top:8px}
.tb-pdp-v28 .tb-varcart .quantity{position:relative;display:flex;height:54px;border:1px solid var(--line);background:#fff;float:none;margin:0}
.tb-pdp-v28 .tb-varcart .quantity input{width:100%;border:0;padding:0 12px;font-weight:700;text-align:left;-moz-appearance:textfield;background:none}
.tb-pdp-v28 .tb-varcart .quantity input::-webkit-outer-spin-button,.tb-pdp-v28 .tb-varcart .quantity input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.tb-pdp-v28 .tb-varcart .single_add_to_cart_button.button.alt{display:flex;align-items:center;justify-content:center;width:100%;min-height:54px;margin:0;border:1px solid transparent;border-radius:0;padding:0 18px;font-family:var(--text);font-weight:800;font-size:15px;letter-spacing:0;text-transform:none;background:var(--accent);color:var(--navy-ink);text-shadow:none;box-shadow:none}
.tb-pdp-v28 .tb-varcart .single_add_to_cart_button.button.alt:hover{background:var(--accent-d);color:var(--navy-ink)}
.tb-pdp-v28 .tb-varcart .single_add_to_cart_button.disabled,.tb-pdp-v28 .tb-varcart .single_add_to_cart_button:disabled{opacity:.5;cursor:not-allowed}
.tb-pdp-v28 .tb-btn--icon{padding:0;width:100%}
.tb-pdp-v28 .tb-btn--icon svg{width:19px;height:19px}
.tb-pdp-v28 .tb-wishlist .tb-wishlist__heart{font-size:20px;line-height:1}
.tb-pdp-v28 .tb-wishlist.is-on{border-color:var(--accent);color:var(--accent-d);background:var(--warn-bg)}

/* Wishlist, PLUGIN variant (tb_v28_wishlist_control -> [jvm_add_to_wishlist]).
   style.css carries a theme-wide `.jvm_add_to_wishlist:not(.tb-moved){display:none!important}`
   because the LEGACY product template relocates the button with jQuery into
   `.tb-product-actions` and tags it `.tb-moved` (functions.php). V28 has no such container and
   prints the shortcode straight into `.tb-actions`, so it was never tagged and never revealed —
   which left the 56px slot in `.tb-actions` (1fr 56px 56px) rendering as an empty gap next to
   Buy now. Un-hide it here and match the compare control beside it. The !important is required
   only to out-rank that legacy rule. */
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin{display:block;min-width:0}
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin .jvm_add_to_wishlist{
  display:flex!important;align-items:center;justify-content:center;
  width:100%;height:100%;min-height:54px;margin:0;padding:0;
  background:#fff;color:var(--navy);border:1px solid var(--line);border-radius:0;
  box-shadow:none;transition:background .16s,color .16s,border-color .16s}
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin .jvm_add_to_wishlist:hover{border-color:var(--navy);background:var(--mist)}
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin .jvm_add_to_wishlist_heart{font-size:19px;line-height:1}
/* icon-only, to match the compare button: the plugin ships both label spans inline */
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin .jvm_add_to_wishlist_text_add,
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin .jvm_add_to_wishlist_text_remove,
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin .jvm_add_to_wishlist_text_already_in{display:none}
/* already-saved state */
.tb-pdp-v28 .tb-actions .tb-wishlist--plugin .jvm_add_to_wishlist.in_wishlist{border-color:var(--accent);color:var(--accent-d);background:var(--warn-bg)}

/* trust (parity #25) — compact icon strip for a clean, uncrowded look */
.tb-pdp-v28 .tb-trust{display:flex;margin-top:14px;border:1px solid var(--line);background:#FBFDFF}
.tb-pdp-v28 .tb-trust-item{flex:1;position:relative;display:flex;flex-direction:column;align-items:center;gap:6px;
  text-align:center;padding:12px 6px}
.tb-pdp-v28 .tb-trust-item + .tb-trust-item:before{content:"";position:absolute;left:0;top:20%;height:60%;width:1px;background:var(--line)}
.tb-pdp-v28 .tb-trust-ico{flex:none;color:var(--navy);display:grid;place-items:center}
.tb-pdp-v28 .tb-trust-ico svg{width:21px;height:21px}
.tb-pdp-v28 .tb-trust-txt strong{display:block;font-size:11.5px;font-weight:700;color:var(--navy-ink);line-height:1.2}
.tb-pdp-v28 .tb-trust-txt small{display:none}

/* fitment note (shown directly above Add to Cart) — soft, generic, one line */
.tb-pdp-v28 .tb-fitnote{display:flex;gap:8px;align-items:flex-start;color:var(--muted);
  font-size:12.5px;line-height:1.45;padding:2px 2px 0}
.tb-pdp-v28 .tb-fitnote__ico{flex:none;color:var(--navy);opacity:.7;margin-top:1px}
.tb-pdp-v28 .tb-fitnote a{color:var(--navy);font-weight:700}

/* ==========================================================================
   9. FEATURES CARD  (parity #11)
   ========================================================================== */
.tb-pdp-v28 .tb-featcard{padding:16px}
.tb-pdp-v28 .tb-featcard h2,.tb-pdp-v28 .tb-sec h2{font-size:24px;margin-bottom:14px}
.tb-pdp-v28 .tb-features{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.tb-pdp-v28 .tb-features li{display:flex;gap:10px;align-items:flex-start;font-size:15px;color:var(--ink)}
.tb-pdp-v28 .tb-check{flex:none;width:21px;height:21px;margin-top:2px;border-radius:50%;background:var(--navy);color:#fff;display:grid;place-items:center;font-size:12px}

/* ==========================================================================
   10. CONTENT SECTIONS  (parity #12, #13, #29)
   ========================================================================== */
.tb-pdp-v28 .tb-content{padding:26px 0 10px;background:#fff}
.tb-pdp-v28 .tb-two{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.tb-pdp-v28 .tb-two--single{grid-template-columns:minmax(0,1fr)}/* only one of highlights|description present → full width, no empty half */
.tb-pdp-v28 .tb-sec{border:1px solid var(--line);background:#fff;box-shadow:var(--shadow);padding:24px;margin-bottom:20px}
.tb-pdp-v28 .tb-sec--mist{background:var(--mist)}
.tb-pdp-v28 .tb-sec p{margin:0 0 14px;color:#33465A}
.tb-pdp-v28 .tb-sec p:last-child{margin-bottom:0}
.tb-pdp-v28 .tb-highlights{list-style:none;margin:0;padding:0;display:grid;gap:11px}
.tb-pdp-v28 .tb-highlights li{position:relative;padding-left:26px;font-size:15px;color:#33465A}
.tb-pdp-v28 .tb-highlights li:before{content:"";position:absolute;left:0;top:9px;width:12px;height:2px;background:var(--accent)}
.tb-pdp-v28 .tb-hl-first{color:var(--navy-ink);font-weight:700}
/* Fixed-height content clamp + auto "View more" (highlights / description).
   Both columns share --clamp-h so the collapsed state is always even; the
   button + fade appear only when a product's content overflows the box. */
.tb-pdp-v28 .tb-two{--clamp-h:300px}
.tb-pdp-v28 .tb-clamp{position:relative;overflow:hidden;max-height:var(--clamp-h);transition:max-height .32s ease}
.tb-pdp-v28 .tb-sec.is-open .tb-clamp{max-height:var(--clamp-open,2400px)}
.tb-pdp-v28 .tb-sec.is-clampable:not(.is-open) .tb-clamp::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:60px;pointer-events:none;
  background:linear-gradient(to bottom,rgba(255,255,255,0),#fff)}
.tb-pdp-v28 .tb-more{display:none;margin-top:15px;align-items:center;gap:6px;background:none;border:0;padding:0;
  cursor:pointer;font-family:var(--disp);font-weight:600;font-size:13px;letter-spacing:.05em;
  text-transform:uppercase;color:var(--navy)}
.tb-pdp-v28 .tb-sec.is-clampable .tb-more{display:inline-flex}
.tb-pdp-v28 .tb-more:hover{text-decoration:underline}
.tb-pdp-v28 .tb-more svg{width:12px;height:12px;transition:transform .22s ease}
.tb-pdp-v28 .tb-sec.is-open .tb-more svg{transform:rotate(180deg)}
.tb-pdp-v28 .tb-specnote{font-size:13px;color:var(--muted);margin:-4px 0 16px}
.tb-pdp-v28 .tb-specgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
.tb-pdp-v28 .tb-spec{border:1px solid var(--line);background:#FBFCFE;padding:12px;overflow-wrap:anywhere}
.tb-pdp-v28 .tb-spec dt{font-size:12px;letter-spacing:.04em;text-transform:uppercase;font-weight:800;color:var(--muted);margin:0 0 5px}
.tb-pdp-v28 .tb-spec dd{margin:0;font-size:14.5px;font-weight:600;color:var(--ink)}
.tb-pdp-v28 .tb-tags{display:flex;flex-wrap:wrap;gap:9px}
.tb-pdp-v28 .tb-tag{background:var(--mist2);border:1px solid var(--line-2);color:var(--navy);font-size:13px;font-weight:700;padding:8px 11px}
.tb-pdp-v28 .tb-tag:hover{background:var(--navy);color:#fff;border-color:var(--navy)}

/* ==========================================================================
   11. COMPARISON  (parity #30)
   ========================================================================== */
.tb-pdp-v28 .tb-comp{background:var(--mist);padding:48px 0}
.tb-pdp-v28 .tb-comp__head{text-align:center;max-width:720px;margin:0 auto 26px}
.tb-pdp-v28 .tb-comp__head h2{font-size:32px}
.tb-pdp-v28 .tb-comp__head p{color:var(--muted);margin-top:8px}
.tb-pdp-v28 .tb-comp__scroll{overflow-x:auto;background:#fff;border:1px solid var(--line);box-shadow:var(--shadow)}
.tb-pdp-v28 .tb-comptable{width:100%;border-collapse:collapse;min-width:860px}
.tb-pdp-v28 .tb-comptable th,.tb-pdp-v28 .tb-comptable td{border-bottom:1px solid var(--line);padding:14px;text-align:center;font-size:14px;vertical-align:middle}
.tb-pdp-v28 .tb-comptable thead th{background:#FBFDFF;vertical-align:top}
.tb-pdp-v28 .tb-comptable .rowlbl{text-align:left;font-weight:700;color:var(--navy-ink);background:#FBFDFF;width:190px;position:sticky;left:0;z-index:2}
/* scroll-shadow on the pinned label column so it reads as fixed while the rest scrolls */
.tb-pdp-v28 .tb-comptable .rowlbl::after{content:"";position:absolute;top:0;right:0;bottom:-1px;width:8px;pointer-events:none;box-shadow:inset 8px 0 8px -8px rgba(16,42,67,.18)}
.tb-pdp-v28 .tb-comptable thead .rowlbl{z-index:3}
.tb-pdp-v28 .tb-comptable .colhi{background:#F3F8FE;box-shadow:inset 0 0 0 2px var(--navy)}
.tb-pdp-v28 .tb-comp__img{height:110px;margin:0 auto 10px}
.tb-pdp-v28 .tb-comp__img img{height:100%;width:auto;margin:0 auto;object-fit:contain}
.tb-pdp-v28 .tb-comp__t{font-family:var(--text);font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.35;display:block;min-height:56px}
.tb-pdp-v28 .tb-comp__you{display:inline-block;background:var(--navy);color:#fff;font-family:var(--disp);font-size:11px;letter-spacing:.1em;text-transform:uppercase;padding:3px 8px;margin-bottom:8px}
.tb-pdp-v28 .tb-comp__price{font-family:var(--disp);font-size:22px;color:var(--navy-ink)}

/* ==========================================================================
   12. RAILS + OFFERS  (parity #33, #34)
   ========================================================================== */
.tb-pdp-v28 .tb-rail{padding:44px 0;background:#fff}
.tb-pdp-v28 .tb-rail__head{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;margin-bottom:20px}
.tb-pdp-v28 .tb-rail__head h2{font-size:28px}
.tb-pdp-v28 .tb-rail__head a{color:var(--navy);font-weight:800;white-space:nowrap}
.tb-pdp-v28 .tb-relgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.tb-pdp-v28 .tb-relc{display:flex;flex-direction:column;border:1px solid var(--line);background:#fff;padding:14px;gap:10px;transition:box-shadow .18s,transform .18s}
.tb-pdp-v28 .tb-relc:hover{box-shadow:var(--shadow-lg);transform:translateY(-2px)}
.tb-pdp-v28 .tb-relc__img{height:150px;background:var(--mist);display:grid;place-items:center;position:relative}
.tb-pdp-v28 .tb-relc__img img{max-height:150px;max-width:100%;width:auto;height:auto;object-fit:contain;filter:contrast(1.03)}
.tb-pdp-v28 .tb-relc__ph{display:none;flex-direction:column;align-items:center;gap:4px;
  font-family:var(--disp);font-size:12px;letter-spacing:.06em;text-transform:uppercase;
  font-weight:600;color:var(--muted);text-align:center;line-height:1.25}
.tb-pdp-v28 .tb-relc__ph svg{width:26px;height:26px;opacity:.45}
.tb-pdp-v28 .tb-relc__img.is-empty img{display:none}
.tb-pdp-v28 .tb-relc__img.is-empty .tb-relc__ph{display:flex}
.tb-pdp-v28 .tb-relc__heart{position:absolute;top:8px;right:8px;width:32px;height:32px;border:1px solid var(--line);background:#fff;border-radius:50%;display:grid;place-items:center;cursor:pointer;color:var(--muted)}
.tb-pdp-v28 .tb-relc__heart:hover,.tb-pdp-v28 .tb-relc__heart.is-on{color:var(--accent-d);border-color:var(--accent)}
.tb-pdp-v28 .tb-relc__cat{font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);font-weight:700}
.tb-pdp-v28 .tb-relc__t{font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.35;min-height:56px}
.tb-pdp-v28 .tb-relc__t:hover{color:var(--navy)}
.tb-pdp-v28 .tb-relc__foot{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:auto}
.tb-pdp-v28 .tb-relc__price{font-family:var(--disp);font-size:21px;color:var(--navy-ink)}
.tb-pdp-v28 .tb-relc__add{border:1px solid var(--navy);background:#fff;color:var(--navy);font-weight:800;padding:8px 14px;cursor:pointer;font-size:13px}
.tb-pdp-v28 .tb-relc__add:hover{background:var(--navy);color:#fff}
.tb-pdp-v28 .tb-relc__add.is-added{background:var(--good);border-color:var(--good);color:#fff}

.tb-pdp-v28 .tb-offers{display:block;background:var(--navy-ink);padding:48px 0}/* display:block defends against home-v10.css unscoped .tb-offers{display:grid} leaking in via the reused v10 header/footer stylesheet */
.tb-pdp-v28 .tb-offers__head{text-align:center;max-width:700px;margin:0 auto 26px;color:#A9C2DC}
.tb-pdp-v28 .tb-offers__head h2{color:#fff;font-size:32px}
/* css/style.css `p{color:var(--Text,#71757d)}` (0,0,1) beats INHERITANCE — an inherited
   value loses to any declaration at all — so this <p> rendered grey #71757d on the dark
   panel instead of the intended #A9C2DC. That is 3.63:1, an AA failure, and it was never
   the design. Re-inherit rather than restate the colour, so the parent stays the one
   source of truth. */
.tb-pdp-v28 .tb-offers__head p{color:inherit}
.tb-pdp-v28 .tb-offers__grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.tb-pdp-v28 .tb-offer{display:flex;gap:16px;align-items:flex-start;background:#12283F;border:1px solid #1E3B58;padding:22px}
.tb-pdp-v28 .tb-offer__ico{flex:none;width:52px;height:52px;display:grid;place-items:center;background:var(--accent);color:var(--navy-ink)}
.tb-pdp-v28 .tb-offer h6{margin:0;font-family:var(--disp);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);font-weight:600}
.tb-pdp-v28 .tb-offer h3{color:#fff;font-size:24px;margin:4px 0 8px}
.tb-pdp-v28 .tb-offer p{color:#A9C2DC;font-size:14px;margin:0 0 14px}
.tb-pdp-v28 .tb-offer a{display:inline-block;background:var(--accent);color:var(--navy-ink);font-weight:800;padding:11px 20px}
.tb-pdp-v28 .tb-offer a:hover{background:var(--accent-d)}

/* ==========================================================================
   13. REVIEWS  (parity #31, #32)
   ========================================================================== */
.tb-pdp-v28 .tb-reviews{background:var(--mist);padding:48px 0}
.tb-pdp-v28 .tb-reviews h2{font-size:32px;margin-bottom:8px}
.tb-pdp-v28 .tb-rev-empty{border:1px dashed var(--line);background:#fff;padding:26px;text-align:center;color:var(--muted);margin-bottom:20px}
.tb-pdp-v28 .tb-rev-empty b{display:block;color:var(--navy-ink);font-family:var(--disp);font-size:20px;margin-bottom:4px}
.tb-pdp-v28 .tb-revform{border:1px solid var(--line);background:#fff;padding:24px;max-width:760px}
.tb-pdp-v28 .tb-field{margin-bottom:16px}
.tb-pdp-v28 .tb-field label{display:block;font-weight:700;color:var(--navy-ink);font-size:14px;margin-bottom:6px}
.tb-pdp-v28 .tb-field .req{color:#B4321F}
.tb-pdp-v28 .tb-field input[type=text],.tb-pdp-v28 .tb-field input[type=email],.tb-pdp-v28 .tb-field textarea{width:100%;border:1px solid var(--line);padding:11px 13px;background:#fff}
.tb-pdp-v28 .tb-field textarea{min-height:130px;resize:vertical}
/* WooCommerce's single-product.js finds `select#rating` at runtime and injects its OWN star
   widget (`p.stars`) next to it — which is why the duplicate never appears in the server HTML
   but is visible on screen. Two rows of stars, and no way to tell which is clickable.

   Hidden rather than left visible-but-inert: these are real <a> elements, so a visually-hidden
   treatment would leave focusable stars a keyboard user could tab into but not see. Removing
   them from the layout is the accessible choice.

   Submission is unaffected. WooCommerce reads the rating from `select#rating`, not from these
   stars — they only write into it, and `#tb-ratepick` already does the same. Verified by
   submitting a review after the change. */
.tb-pdp-v28 .tb-revform p.stars{display:none!important}

.tb-pdp-v28 .tb-ratepick{display:flex;gap:4px}
.tb-pdp-v28 .tb-ratepick button{border:0;background:none;font-size:28px;line-height:1;color:#D6DEE7;cursor:pointer;padding:0 2px}
.tb-pdp-v28 .tb-ratepick button.is-on{color:var(--accent)}
.tb-pdp-v28 .tb-drop{border:2px dashed var(--line-2);background:var(--mist);padding:26px;text-align:center;color:var(--muted);cursor:pointer}
.tb-pdp-v28 .tb-drop.is-over{border-color:var(--navy);background:var(--mist2);color:var(--navy)}
.tb-pdp-v28 .tb-drop b{display:block;color:var(--navy-ink)}
.tb-pdp-v28 .tb-droplist{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.tb-pdp-v28 .tb-droplist span{font-size:12px;background:var(--mist2);border:1px solid var(--line-2);padding:5px 9px}

/* ==========================================================================
   14. NEWSLETTER  (parity #35)
   ========================================================================== */
.tb-pdp-v28 .tb-nl{background:var(--navy);color:#fff;padding:40px 0}
.tb-pdp-v28 .tb-nl__inner{display:grid;grid-template-columns:1fr 440px;gap:24px;align-items:center}
.tb-pdp-v28 .tb-nl h2{color:#fff;font-size:28px}
.tb-pdp-v28 .tb-nl p{color:#C9DCF0;margin:6px 0 0;font-size:14.5px}
.tb-pdp-v28 .tb-nl form{display:flex;gap:10px}
.tb-pdp-v28 .tb-nl input{flex:1;min-width:0;border:1px solid transparent;padding:14px;background:#fff}
.tb-pdp-v28 .tb-nl button{background:var(--accent);color:var(--navy-ink);border:0;padding:0 24px;font-weight:800;cursor:pointer}
.tb-pdp-v28 .tb-nl button:hover{background:var(--accent-d)}
.tb-pdp-v28 .tb-nl small{display:block;color:#ADC7E2;font-size:12px;margin-top:8px}
.tb-pdp-v28 .tb-nl-overlay{position:fixed;inset:0;background:rgba(8,24,40,.7);display:none;place-items:center;z-index:120;padding:20px}
.tb-pdp-v28 .tb-nl-overlay.is-open{display:grid}
.tb-pdp-v28 .tb-nl-modal{position:relative;width:min(520px,100%);background:var(--navy-ink);color:#fff;border:1px solid #1E3B58;padding:34px}
.tb-pdp-v28 .tb-nl-modal h3{color:#fff;font-size:26px}
.tb-pdp-v28 .tb-nl-modal p{color:#A9C2DC;font-size:14px;margin:8px 0 18px}
.tb-pdp-v28 .tb-nl-close{position:absolute;top:10px;right:12px;border:0;background:none;color:#A9C2DC;font-size:26px;line-height:1;cursor:pointer}
.tb-pdp-v28 .tb-nl-close:hover{color:#fff}
.tb-pdp-v28 .tb-nl-fine{color:#7E9AB6;font-size:11.5px;margin-top:12px}

/* ==========================================================================
   15. STICKY CTA  (parity #36)
   ========================================================================== */
/* The bar sits over the page, so the page has to end ABOVE it.
   Measured at 390x844: the footer's "Privacy Policy" and "Terms & Conditions" links
   landed at y=808–823 while the bar's top edge was at 777 — and at maximum scroll there
   is nowhere further to scroll, so those links were permanently unclickable on mobile.
   The client's requirement is explicit: "Sticky Add to Cart must not cover content, chat,
   consent controls or form buttons."
   env(safe-area-inset-bottom) covers the second requirement in the same breath — on an
   iPhone with a home indicator the bar would otherwise sit underneath it. The fallback 0px
   keeps this valid on browsers with no env() support. */
.tb-pdp-v28 .tb-sticky{position:fixed;left:0;right:0;bottom:0;z-index:100;background:#fff;border-top:1px solid var(--line);box-shadow:0 -8px 24px rgba(10,44,82,.13);
  padding:10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  display:grid;grid-template-columns:minmax(0,1fr) 140px 150px 150px;gap:12px;align-items:center;
  transform:translateY(110%);transition:transform .22s ease;visibility:hidden}
.tb-pdp-v28 .tb-sticky.is-visible{transform:translateY(0);visibility:visible}
/* Reserve the bar's height at the very end of the document.
   It has to go on the FOOTER, not on .tb-pdp-v28: measured, the footer is a SIBLING of
   the product wrapper (a → li → ul → nav → .tb-wrap → footer.tb-foot → .tb-home → body),
   so padding the wrapper moves nothing that was actually trapped.
   :has() scopes it to pages that really carry the bar — it is already used in this
   codebase (category-v2.css), so it is safe here. */
/* NOT scoped to a breakpoint. The bar is visible at EVERY width - measured 390 through
   1920 - and the first version of this fix assumed it was mobile-only. At 1920 the footer
   columns go wide, the footer gets short, and its last row lands right in the bar's strip:
   "Privacy Policy" and "Terms & Conditions" were covered on desktop exactly as they were
   on mobile. Reserved unconditionally wherever the bar exists. */
body:has(.tb-pdp-v28 .tb-sticky) .tb-foot{
  padding-bottom:calc(84px + env(safe-area-inset-bottom, 0px));
}
.tb-pdp-v28 .tb-sticky__t{font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.3;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.tb-pdp-v28 .tb-sticky__p{font-family:var(--disp);font-size:26px;color:var(--navy-ink);text-align:right}
.tb-pdp-v28 .tb-sticky .tb-btn{min-height:46px}
@media(prefers-reduced-motion:reduce){.tb-pdp-v28 .tb-sticky{transition:none}}

/* ==========================================================================
   16. FOOTER  (parity #37)
   ========================================================================== */
.tb-pdp-v28 .tb-foot{background:var(--navy-ink);color:#A9C2DC;padding:48px 0 0;font-size:14px}
.tb-pdp-v28 .tb-foot__cols{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:26px;padding-bottom:34px}
.tb-pdp-v28 .tb-foot h4{color:#fff;font-size:15px;letter-spacing:.08em;text-transform:uppercase;margin-bottom:12px}
.tb-pdp-v28 .tb-foot ul{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.tb-pdp-v28 .tb-foot a:hover{color:#fff}
.tb-pdp-v28 .tb-flogo{display:block;line-height:0}
.tb-pdp-v28 .tb-flogo img{width:100%;max-width:224px;height:auto}
.tb-pdp-v28 .tb-foot__bot{border-top:1px solid #1E3B58;padding:16px 0;display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;font-size:13px}
.tb-pdp-v28 .tb-fbadges{display:flex;gap:8px;flex-wrap:wrap}
.tb-pdp-v28 .tb-fbadges span{border:1px solid #1E3B58;padding:5px 10px;font-size:12px}

/* ==========================================================================
   17. RESPONSIVE
   ========================================================================== */
@media(max-width:1250px){
  /* Stack to one column and flatten both columns so their cards become direct
     children we can reorder: gallery first (right after the title), then the
     price/stock/Add-to-Cart buy box, then features. */
  /* align-items:stretch is REQUIRED here and must not be dropped.
     The two-column rule above sets `align-items:start`, which is right while this is a
     GRID (it stops the gallery card stretching to match a taller buy box). The moment it
     becomes a column FLEX container the cross axis turns horizontal, so `start` stops the
     children filling the width — and the buy box collapsed to its content width. Measured:
     at 1100/950/768px the gallery ran 1044/894/712px wide while the price, quantity and
     Add-to-Cart box sat pinned at 475px with dead space beside it, across the entire
     tablet range the client asked about (768/820/834/1024). */
  .tb-pdp-v28 .tb-grid{display:flex;flex-direction:column;gap:var(--gut);align-items:stretch}
  .tb-pdp-v28 .tb-col{display:contents}
  .tb-pdp-v28 .tb-col--left .tb-gal{order:1}
  .tb-pdp-v28 .tb-buy{order:2}
  .tb-pdp-v28 .tb-col:not(.tb-col--left) .tb-buy{flex:none}
  .tb-pdp-v28 .tb-featcard{order:3}
  .tb-pdp-v28 .tb-gal__stage{min-height:500px;max-height:none}
  .tb-pdp-v28 .tb-pricerow,.tb-pdp-v28 .tb-tier__body{grid-template-columns:1fr}
  .tb-pdp-v28 .tb-specgrid{grid-template-columns:repeat(3,minmax(0,1fr))}
  .tb-pdp-v28 .tb-relgrid{grid-template-columns:repeat(3,1fr)}
}
@media(max-width:960px){
  .tb-pdp-v28 .tb-hdr .tb-wrap{grid-template-columns:1fr auto;grid-template-areas:"brand icons" "search search";gap:12px;padding-top:14px;padding-bottom:14px;min-height:0}
  .tb-pdp-v28 .tb-logo{grid-area:brand}.tb-pdp-v28 .tb-search{grid-area:search}.tb-pdp-v28 .tb-hicons{grid-area:icons}
  .tb-pdp-v28 .tb-nav{display:none}
  .tb-pdp-v28 .tb-gal__stage{min-height:400px;padding:18px}
  .tb-pdp-v28 .tb-two,.tb-pdp-v28 .tb-relgrid,.tb-pdp-v28 .tb-offers__grid,.tb-pdp-v28 .tb-nl__inner{grid-template-columns:minmax(0,1fr)}
  .tb-pdp-v28 .tb-foot__cols{grid-template-columns:1fr 1fr}
  /* Left pad clears the bottom-left accessibility widget, same reason as the checkout bar
     in tb-checkout.css: the widget is fixed to that corner and is not ours to move, and it
     was sitting on the left edge of Add to Cart — taps there hit the widget, not the
     button. This is the primary purchase control, so it gets the clearance rather than the
     widget. */
  /* Price STAYS with the purchase action. Hiding it left the bar showing a bare "Add to cart"
     with no idea what it costs — the customer has scrolled past the buy box by definition, so
     the sticky bar is the only price on screen. The title goes instead: it is the page they
     are already on, and it was the widest element. */
  .tb-pdp-v28 .tb-sticky{grid-template-columns:auto minmax(0,1fr);padding:10px 12px 10px 72px;gap:12px}
  .tb-pdp-v28 .tb-sticky__t{display:none}
  .tb-pdp-v28 .tb-sticky__p{display:block;font-size:20px;text-align:left;white-space:nowrap}
  .tb-pdp-v28 .tb-sticky .tb-btn{min-width:0;padding:0 10px;white-space:nowrap}
}
@media(max-width:620px){
  .tb-pdp-v28 .tb-wrap{padding:0 16px}
  .tb-pdp-v28{padding-bottom:0}
  /* One primary CTA on small phones — avoids the two buttons overflowing 100vw. The price
     keeps its column: "Add to cart" with no price is not a purchase control, it is a guess. */
  .tb-pdp-v28 .tb-sticky{grid-template-columns:auto minmax(0,1fr);max-width:100vw;overflow:hidden}
  .tb-pdp-v28 #tb-sticky-buy{display:none}
  .tb-pdp-v28 .tb-sticky__p{font-size:18px}
  .tb-pdp-v28 .tb-meta{gap:6px 0}
  .tb-pdp-v28 .tb-meta > *{padding:0 12px}
  .tb-pdp-v28 .tb-gal__stage{min-height:320px;padding:12px}
  .tb-pdp-v28 .tb-gal__thumbs{grid-template-columns:repeat(4,1fr)}
  .tb-pdp-v28 .tb-specgrid,.tb-pdp-v28 .tb-cartrow{grid-template-columns:1fr}
  .tb-pdp-v28 .tb-trust{grid-template-columns:1fr}
  .tb-pdp-v28 .tb-sec{padding:18px}
  .tb-pdp-v28 .tb-metarow{flex-direction:column;align-items:flex-start}
  .tb-pdp-v28 .tb-review{padding-right:0}
  .tb-pdp-v28 .tb-meta{border-left:0;padding-left:0}
  .tb-pdp-v28 .tb-rail__head{flex-wrap:wrap;align-items:flex-start}
  .tb-pdp-v28 .tb-rail__head a{white-space:normal}
  /* Scale the large 28–32px display section headings down on phones */
  .tb-pdp-v28 .tb-comp__head h2,
  .tb-pdp-v28 .tb-offers__head h2,
  .tb-pdp-v28 .tb-reviews h2,
  .tb-pdp-v28 .tb-nl h2,
  .tb-pdp-v28 .tb-rail__head h2{font-size:22px}
  .tb-pdp-v28 .tb-featcard h2,.tb-pdp-v28 .tb-sec h2{font-size:20px}
  .tb-pdp-v28 .tb-comp__head p,.tb-pdp-v28 .tb-offers__head p{font-size:14px}
  /* Comparison table: pinned label column narrower + tighter cells on phones (still scrolls) */
  .tb-pdp-v28 .tb-comptable{min-width:560px}
  .tb-pdp-v28 .tb-comptable .rowlbl{width:132px}
  .tb-pdp-v28 .tb-comptable th,.tb-pdp-v28 .tb-comptable td{padding:10px 9px;font-size:13px}
  .tb-pdp-v28 .tb-comp__t{font-size:12.5px;min-height:44px}
  .tb-pdp-v28 .tb-comp__price{font-size:19px}
  .tb-pdp-v28 .tb-comp__img{height:78px}
}

/* ══════════════════════════════════════════════════════════════════════════════
   CLIENT FINAL DESIGN PASS — mobile/tablet first-load hierarchy
   ═════════════════════════════════════════════════════════════════════════════
   Reported: on phone and tablet the page does not open like a commerce PDP. The title card
   (eyebrow, H1, rating, brand, MFR#, UPC, Share) filled the entire first viewport, so the
   shopper landed on text and had to scroll to reach the product image, with price and Add to
   cart further down again. The H1 was also clamped to two lines, hiding size / finish / part
   number — the very identifiers a buyer is checking.

   These blocks come LAST in the file deliberately: they override the stacked rules set at
   1250px and 960px, and media queries add no specificity, so source order is what decides.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ── PHONE ─────────────────────────────────────────────────────────────────── */
@media(max-width:767px){

  /* Flatten the title card so its two halves become siblings of the grid and can be ordered
     around it. `display:contents` drops the card's own background and rules, so both halves
     get them back below — the page should still look like two cards, just with the gallery
     between them. */
  .tb-pdp-v28 .tb-wrap--head{display:flex;flex-direction:column}
  .tb-pdp-v28 .tb-wrap--head > *{order:5}
  .tb-pdp-v28 .tb-crumb{order:1}
  .tb-pdp-v28 .tb-title{display:contents}
  .tb-pdp-v28 .tb-title__top{order:2}
  .tb-pdp-v28 .tb-grid{order:3}
  .tb-pdp-v28 .tb-metarow{order:4}

  /* Title: full width, no card chrome of its own — the H1 is the first thing read, and it
     should not sit in a box that costs vertical space before the image. */
  .tb-pdp-v28 .tb-title__top{padding:2px 0 12px;margin:0}

  /* THE H1 IS NO LONGER TRUNCATED. Two lines is not enough for titles that carry the calibre,
     length, finish and part number, and those are exactly what a buyer is confirming. */
  .tb-pdp-v28 .tb-title h1{
    display:block;-webkit-line-clamp:none;-webkit-box-orient:horizontal;overflow:visible;
    font-size:21px;line-height:1.25;
  }

  /* Secondary metadata now sits under the buy box, presented as its own card. */
  .tb-pdp-v28 .tb-metarow{
    margin-top:16px;padding:14px 16px;background:#fff;border:1px solid var(--line);
    flex-direction:column;align-items:flex-start;gap:10px;
  }
  .tb-pdp-v28 .tb-metarow:before{display:none}

  /* The gallery is the first thing below the title, so it must not eat the whole viewport
     either — the buy box needs to be one short swipe away, not two. */
  .tb-pdp-v28 .tb-gal__stage{min-height:260px;max-height:44vh}
}

/* ── TABLET ────────────────────────────────────────────────────────────────── */
@media(min-width:768px) and (max-width:1024px){

  /* A real tablet layout. This range was inheriting the phone stack, so an 834px iPad showed a
     full-width square image with the price pushed below the fold — on a screen with ample room
     to put them side by side. Two columns restores "see it and buy it" without scrolling.

     `display:contents` from the 1250px block has to be undone here or the columns collapse. */
  .tb-pdp-v28 .tb-grid{
    display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
    gap:20px;align-items:start;
  }
  .tb-pdp-v28 .tb-col{display:flex;flex-direction:column;gap:14px}
  .tb-pdp-v28 .tb-col--left{position:static;min-width:0}
  .tb-pdp-v28 .tb-col--left .tb-gal{order:0}
  .tb-pdp-v28 .tb-buy{order:0}
  .tb-pdp-v28 .tb-featcard{order:0}

  /* Squarer, shorter stage so both columns start level and the buy box is fully visible. */
  .tb-pdp-v28 .tb-gal__stage{min-height:300px;max-height:360px;padding:16px}
  .tb-pdp-v28 .tb-gal__thumbs{grid-template-columns:repeat(5,1fr)}

  /* Three lines here, not two — tablet has the width, and truncating identifiers is the
     complaint being fixed. */
  .tb-pdp-v28 .tb-title h1{-webkit-line-clamp:3;font-size:26px}

  .tb-pdp-v28 .tb-pricerow{grid-template-columns:1fr}
  .tb-pdp-v28 .tb-relgrid{grid-template-columns:repeat(3,1fr)}
}

/* ── PHONE: put the purchase controls next to the price ────────────────────── */
@media(max-width:767px){
  /* "Price and Add to cart must be reachable with one short swipe."
     In DOM order the buy box runs: stock, price, quantity-discount panel, business banner,
     fit note, THEN the quantity + Add to cart row. Measured on a 390x844 phone that put Add
     to cart 1,696px down — roughly two full swipes below the price at 1,002px.

     Reordered so the purchase row follows the price directly. The tier panel, business
     prompt, fit note and trust strip are all things a shopper reads AFTER deciding to buy,
     so they lose nothing by sitting below the button. Nothing is hidden and desktop is
     untouched. */
  .tb-pdp-v28 .tb-buy{display:flex;flex-direction:column}
  .tb-pdp-v28 .tb-buy > .tb-stock{order:1}
  .tb-pdp-v28 .tb-buy > .tb-pricerow{order:2}
  .tb-pdp-v28 .tb-buy > #tb-cartform,
  .tb-pdp-v28 .tb-buy > .tb-varcart,
  .tb-pdp-v28 .tb-buy > .tb-actions{order:3}
  .tb-pdp-v28 .tb-buy > .tb-tier{order:4}
  .tb-pdp-v28 .tb-buy > .tb-fitnote{order:5}
  .tb-pdp-v28 .tb-buy > .tb-trust{order:6}
}

/* ── The floating badge that overlaps the purchase bar ─────────────────────── */
/*
 * It is NOT an accessibility widget, which is why it could not be found: it is CookieYes'
 * "revisit consent" button (.cky-btn-revisit-wrapper, 45x45, fixed bottom-left, z-index
 * 999999). It is injected only AFTER a visitor accepts cookies, so it is invisible to any
 * fresh session — including every automated check run against this site until now.
 *
 * Because it outranks everything on the page it sat on top of the sticky purchase bar. The
 * theme already reserved 72px of left padding on that bar below 960px, but the badge is fixed
 * at ALL widths, so on desktop it covered the bar's title and price — which is what the
 * client's desktop screenshot shows.
 *
 * Lifting it clear of the bar is better than padding around it: the badge stays reachable, the
 * bar keeps its full width, and it works at every breakpoint instead of one. `:has()` is
 * already relied on a few rules above for the footer padding, so this adds no new requirement.
 */
body:has(.tb-pdp-v28 .tb-sticky.is-visible) .cky-btn-revisit-wrapper{
  bottom:84px!important;
}
@media(prefers-reduced-motion:no-preference){
  .cky-btn-revisit-wrapper{transition:bottom .2s ease}
}

/* Between 621 and 960px the bar had three items (price, Add to cart, Buy now) in a
   two-column grid, so they wrapped onto two rows and it stood 125px tall — nearly double
   the 67px it takes at every other width, eating the bottom of the screen and pushing the
   floating badge into it. Three columns puts them back on one row. */
@media(min-width:621px) and (max-width:960px){
  .tb-pdp-v28 .tb-sticky{grid-template-columns:auto minmax(0,1fr) minmax(0,1fr)}
}

/* ── Product metadata card: structured layout for tablet and phone ─────────── */
/*
 * Desktop keeps the horizontal pill row it was designed with — nothing below changes it.
 *
 * On narrower screens that row wrapped into something scattered: the rating, brand, MFR#, UPC
 * and Share button all broke onto their own lines at different alignments, with the Share
 * button stranded on the right. Nothing lined up, so nothing was quick to read — and these are
 * exactly the values a buyer cross-checks against a part they already own.
 *
 * Restructured as a key/value list: label left, value right, one hairline between each. Same
 * information, same markup, but scannable — and the part numbers get tabular figures so digits
 * align down the column.
 */
/* The small-screen duplicate of "Shop all" is desktop-hidden; the in-brand one is authoritative
   there. Exactly one is ever displayed. */
.tb-pdp-v28 .tb-meta__shop--sm{display:none}
/* Invisible to the desktop layout — the row above behaves exactly as it always did. */
.tb-pdp-v28 .tb-metarow__ids{display:contents}

@media(max-width:1024px){

  /* THREE EVEN ROWS:
       1  rating          — stars, verdict, call to action
       2  identifiers     — Brand | MFR# | UPC, as equal columns
       3  actions         — Share | Shop all
     Rows 2 and 3 live in .tb-metarow__ids so they can be moved as one unit on phone, where the
     rating goes up under the title and these stay below the buy box. Six columns so row 2
     divides into thirds and row 3 into halves — both landing on the same grid, which is what
     makes the block read as even rather than assembled. */
  .tb-pdp-v28 .tb-metarow{
    display:block;padding:0;gap:0;background:#fff;border:1px solid var(--line);
  }
  .tb-pdp-v28 .tb-metarow:before{display:none}
  .tb-pdp-v28 .tb-metarow__ids{display:grid;grid-template-columns:repeat(6,1fr)}

  /* ── ROW 1 ──
     ONE LINE, always. It was wrapping at 390px, dropping "Be the first to review" onto a second
     line and giving the row an unbalanced two-line block for what is a single short statement.
     nowrap plus smaller type keeps stars, verdict and call to action on one row; the verdict is
     the only part allowed to shrink, since the stars are fixed and truncating the link would
     make it unreadable. */
  .tb-pdp-v28 .tb-review{
    display:flex;align-items:center;flex-wrap:nowrap;gap:7px;
    margin:0;padding:9px 13px;border-bottom:1px solid var(--line-soft);font-size:12px;
  }
  .tb-pdp-v28 .tb-review .tb-stars{font-size:12px;flex:none;letter-spacing:.5px}
  .tb-pdp-v28 .tb-review strong{
    font-weight:700;color:var(--ink);font-size:12px;
    min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  .tb-pdp-v28 .tb-review a{
    margin-left:auto;white-space:nowrap;font-weight:700;font-size:12px;flex:none;
  }

  /* ── ROW 2 ──
     grid-auto-flow:column with equal auto-columns means the cells stay even whether there are
     three of them or two — a product with no brand simply divides in half instead of leaving a
     hole, which explicit spans would not survive. */
  .tb-pdp-v28 .tb-meta{
    grid-column:1/-1;display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
    align-items:stretch;border-bottom:1px solid var(--line-soft);font-size:13px;
  }
  .tb-pdp-v28 .tb-meta > *{
    display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:3px;
    padding:9px 12px;border-left:1px solid var(--line-soft);border-bottom:0;min-width:0;
  }
  .tb-pdp-v28 .tb-meta > *:first-child{border-left:0}

  .tb-pdp-v28 .tb-meta .k{
    font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
    font-weight:700;line-height:1.2;
  }
  /* Tabular figures so part numbers line up; break-all because a 12-digit barcode cannot wrap
     on its own and would otherwise widen its column and unbalance the row. */
  .tb-pdp-v28 .tb-meta b,
  .tb-pdp-v28 .tb-meta__brand a[data-woo="brand"]{
    font-size:13px;font-weight:800;color:var(--navy-ink);line-height:1.25;
    font-variant-numeric:tabular-nums;word-break:break-all;text-align:left;
  }
  /* On this layout the brand's own "Shop all" moves to row 3. */
  .tb-pdp-v28 .tb-meta__brand{display:flex}
  .tb-pdp-v28 .tb-meta__brand .tb-meta__shop{display:none}

  /* ── ROW 3 ── */
  .tb-pdp-v28 .tb-share-btn{
    grid-column:1/4;display:flex;justify-content:center;align-items:center;gap:8px;
    margin:0;padding:11px 12px;border:0;border-radius:0;background:#FBFDFF;
    font-size:13px;font-weight:800;
  }
  .tb-pdp-v28 .tb-meta__shop--sm{
    grid-column:4/7;display:flex;justify-content:center;align-items:center;
    padding:11px 12px;background:#FBFDFF;border-left:1px solid var(--line-soft);
    font-size:13px;font-weight:800;white-space:nowrap;
  }
  /* No brand means no second action — Share takes the whole row rather than half of it. */
  .tb-pdp-v28 .tb-share-btn:last-child{grid-column:1/-1}
}

/* ── Quantity discount belongs ABOVE the buy button ────────────────────────── */
/*
 * An earlier pass moved the whole tier panel below Add to cart to bring the button within one
 * swipe. That was the wrong trade: the tier selector is what tells a customer 5 or 10 units are
 * cheaper AND sets the quantity, so putting it after the button means they add one unit and
 * never see it. It cost a sale to save a scroll.
 *
 * It goes back above the button, but compacted so the button stays reachable. `display:contents`
 * on .tb-tier lets its three parts be ordered independently, so the business-account prompt —
 * which is not part of choosing a quantity — can sit below the button while the selector stays
 * above it. Measured savings: the "Selected: $x/unit" line (46px) duplicates what the dropdown
 * already reads, the instructional subtitle (24px) explains a dropdown, and the business banner
 * (82px) moves down.
 */
@media(max-width:767px){
  .tb-pdp-v28 .tb-buy > .tb-tier{display:contents}

  .tb-pdp-v28 .tb-tier__head{order:3;padding:0;margin:2px 0 0;border:0;background:none}
  .tb-pdp-v28 .tb-tier__head small{display:none}
  .tb-pdp-v28 .tb-tier__body{order:4;grid-template-columns:1fr;padding:0;border:0;background:none;gap:0}
  .tb-pdp-v28 .tb-tier__out{display:none}

  .tb-pdp-v28 .tb-buy > #tb-cartform,
  .tb-pdp-v28 .tb-buy > .tb-varcart,
  .tb-pdp-v28 .tb-buy > .tb-actions{order:5}

  .tb-pdp-v28 .tb-tier__biz{order:6;margin-top:2px}
  .tb-pdp-v28 .tb-buy > .tb-fitnote{order:7}
  .tb-pdp-v28 .tb-buy > .tb-trust{order:8}

  /* The dropdown label was being cut off ("… — $152.02/u…") on longer prices. Full width and a
     slightly smaller face gives it the room; the select is the only control on its row now. */
  .tb-pdp-v28 .tb-tier__select{width:100%;font-size:14px;padding-right:34px}
}

/* ── Metadata sits directly under the buy box ──────────────────────────────── */
/*
 * It was landing AFTER the "Why customers choose this item" card — stranded between two content
 * sections rather than attached to the product. The features card lives inside .tb-grid while
 * the metadata lives outside it, so ordering the grid as a single unit could only ever place the
 * metadata before or after ALL of it.
 *
 * Flattening the grid as well makes the gallery, buy box and features card siblings of the
 * metadata, so all four can be sequenced properly: title, gallery, buy box, identifiers,
 * features. That is the order the brief asked for — identifiers "below the gallery or buy box".
 * The grid's own gap goes with it, so the wrapper carries the spacing instead.
 */
@media(max-width:767px){
  .tb-pdp-v28 .tb-wrap--head{gap:18px}
  .tb-pdp-v28 .tb-grid{display:contents}

  /* ONLY the rating goes up under the title — "No reviews yet / Be the first to review" is
     about the product itself and belongs with its name. The identifiers and their actions stay
     below the buy box, where they were.
     .tb-metarow becomes display:contents so its two halves can be ordered independently; each
     then carries its own card chrome, since the wrapper that provided it is no longer laid out. */
  .tb-pdp-v28 .tb-metarow{display:contents}

  .tb-pdp-v28 .tb-review{
    order:3;background:#fff;border:1px solid var(--line);border-bottom:1px solid var(--line);
    padding:9px 13px;
  }
  .tb-pdp-v28 .tb-col--left .tb-gal{order:4}
  .tb-pdp-v28 .tb-col:not(.tb-col--left) .tb-buy{order:5}
  .tb-pdp-v28 .tb-metarow__ids{order:6;background:#fff;border:1px solid var(--line)}
  .tb-pdp-v28 .tb-featcard{order:7}
}

/* ── Reclaiming the space the identifiers now occupy above the gallery ─────── */
/*
 * Moving the identifier block above the gallery costs 133px before the buy box, so the same
 * amount is taken back from things that were not earning it.
 *
 * The gallery hint ("Click the image to open it full size…") is the biggest single saving at
 * ~100px, and it is instruction rather than content: on a touch screen tapping an image to
 * enlarge it needs no caption, and "additional supplier images appear when available" describes
 * our data pipeline, not the product. It stays on desktop where the space is free.
 *
 * The delivery estimate keeps its content but loses padding it did not need at this width.
 */
@media(max-width:767px){
  .tb-pdp-v28 .tb-gal__hint{display:none}
  .tb-pdp-v28 .tb-deliv{padding:10px 12px;min-height:0}
  .tb-pdp-v28 .tb-deliv__row{gap:8px}
  .tb-pdp-v28 .tb-pricebox{min-height:0;padding:12px 14px}
  .tb-pdp-v28 .tb-gal__stage{max-height:40vh}
}

/* =====================================================================
 * COMPARISON TABLE — centre the viewed product on desktop.
 *
 * The markup puts it first so it cannot be scrolled off-screen on narrow viewports (see the long
 * note in inc/product-v28.php). Above 1024px the table does not scroll, so the columns are
 * reordered visually into rival · YOU'RE VIEWING · rival.
 *
 * A table cannot reorder its columns, so the rows become flex containers here — and only here.
 * The table, thead and tbody are switched to block first: leaving them as table boxes around
 * non-table rows makes the browser generate anonymous table wrappers, which is where this
 * technique usually goes wrong.
 *
 * Cells then re-create what the table model was giving us for free: stretch to the row height,
 * so the highlight ring still spans the full cell, with the content centred inside. Header cells
 * keep align-items:stretch on purpose — the image and title are block-level and centred by
 * text-align, and shrink-wrapping them would change where the product name wraps.
 * ===================================================================== */
@media(min-width:1025px){
  .tb-pdp-v28 .tb-comptable--center,
  .tb-pdp-v28 .tb-comptable--center thead,
  .tb-pdp-v28 .tb-comptable--center tbody{display:block}
  .tb-pdp-v28 .tb-comptable--center tr{display:flex;align-items:stretch}

  .tb-pdp-v28 .tb-comptable--center .rowlbl{flex:0 0 190px}
  .tb-pdp-v28 .tb-comptable--center th:not(.rowlbl),
  .tb-pdp-v28 .tb-comptable--center td:not(.rowlbl){flex:1 1 0;min-width:0}

  .tb-pdp-v28 .tb-comptable--center tbody td{display:flex;align-items:center;justify-content:center}
  .tb-pdp-v28 .tb-comptable--center tbody .rowlbl{justify-content:flex-start}
  .tb-pdp-v28 .tb-comptable--center thead th{display:flex;flex-direction:column;align-items:stretch}
  /* The badge is an inline-block pill; becoming a flex item blockifies it, which would stretch it
     into a full-width bar. Shrink it back to its own width so it reads exactly as it did. */
  .tb-pdp-v28 .tb-comptable--center .tb-comp__you{align-self:center}

  /* Cell 1 is the attribute label (order 0), cell 2 the viewed product, cells 3 and 4 the rivals. */
  .tb-pdp-v28 .tb-comptable--center tr > :nth-child(3){order:1}
  .tb-pdp-v28 .tb-comptable--center tr > :nth-child(2){order:2}
  .tb-pdp-v28 .tb-comptable--center tr > :nth-child(4){order:3}
}
