/* =========================================================================
   FRONT-END PASS  (2026-08-18, Pavel's device review)

   Eight items photographed off his phone. Every number below was measured in a
   real browser at 390x844 BEFORE the change - the before/after sits in each
   block. Loaded LAST, after chrome-ux.css, so it wins on equal specificity.
   The !important that is here is aimed at TeeSpace's generated style.css,
   which states most of this with !important already.
   ========================================================================= */


/* -------------------------------------------------------------------------
   1.  CARD IMAGE ZOOM                                          (Pavel item 2)

   MEASURED ACROSS 12 REAL PRODUCTS, not copied off imaginatio and not eyeballed.
   Print bounding box as a fraction of the mockup frame:

       width   0.281 - 0.439   mean 0.390
       height  0.398 - 0.466   mean 0.431
       centre  y 0.491 - 0.538 mean 0.511

   THE PREMISE THIS STARTED FROM WAS HALF WRONG, so do not re-derive it from
   the brief. MoshTee's print is NOT wider than imaginatio's - 39% against 40%,
   the same shirt at the same distance. It is TALLER (43% against 37%) and it
   sits LOWER (centre 51% against 42%). Height and position are what differ, so
   the origin is what has to move; the scale barely does.

   1.55 with origin center 51%: the visible window is 64.5% of the frame
   centred on the print, and the tallest print measured (0.466 tall, centred at
   0.538, so spanning 0.305-0.771) sits inside 0.187-0.833 with 11.8pp of air
   above and 6.2pp below. Nothing clips. The print lands at 60% of the card
   width against imaginatio's 64% - fractionally gentler, which is what was
   asked for, and still 2.2x the size it rendered at this morning.

   Inheriting imaginatio's origin of 35% would have cropped the bottom off the
   artwork on all 83 cards. That is the number that mattered, not the scale.

   BEFORE: transform none, .product-thumbnail overflow visible. No zoom existed
   at all - the print rendered ~77px wide inside a 188px card, which is exactly
   why the lettering was unreadable in the grid.

   Desktop mouse hovers back out to 1.0 so the whole shirt stays checkable.
   Touch keeps the static zoom; there is no hover there to reveal anything.
   ------------------------------------------------------------------------- */
.product-thumbnail{ overflow:hidden; }
.product-thumbnail a{ display:block; }
.product-thumbnail img{
  transform:scale(1.55); /* desktop 1.55 (Pavel 2026-09-17: 1.2 was for phones only; phones get NO zoom via the media rule below) */
  transform-origin:center 51%;
}
@media (hover:hover) and (pointer:fine){
  .product-thumbnail img{ transition:transform .4s ease; }
  .product-thumbnail:hover img{ transform:scale(1); transform-origin:center 51%; }
}
/* Phones: NO zoom (Pavel 2026-09-16, after Shimmy). The whole tee on the pale
   flat-lay ground is what makes a 2-up phone grid read as T-shirts. Desktop keeps
   1.2 at rest. hover:none catches touch phones; max-width catches narrow windows. */
@media (hover:none), (max-width:767px){
  .product-thumbnail img{ transform:none; }
}


/* -------------------------------------------------------------------------
   2.  ONE GUTTER, BOTH PAGES                                   (Pavel item 2)

   Home and shop render IDENTICAL markup - .products.layout-grid, .grid-item -
   and looked different because TeeSpace's flex gutter rules are scoped to
   WooCommerce archive body classes, and the homepage is a plain page.

   MEASURED at 390px BEFORE:
     shop  grid margin 18px -8px 0, item padding 8px  -> 16px between cards
     home  grid margin 0,           item padding 0    -> cards TOUCHING
   which is precisely what Pavel photographed.

   Replaced with an explicit CSS grid so the gutter is stated once and can
   never again depend on which template the loop was called from. Same shape
   as imaginatio's own .layout-grid override.
   ------------------------------------------------------------------------- */
.products.layout-grid{
  display:grid !important;
  grid-template-columns:repeat(4,minmax(0,1fr)) !important;
  gap:28px 24px !important;
  margin:18px 0 0 !important;
}
.products.layout-grid .grid-item{
  width:auto !important;
  max-width:none !important;
  min-width:0 !important;
  padding:0 !important;
  margin:0 !important;
  float:none !important;
}
@media (max-width:991px){
  .products.layout-grid{ grid-template-columns:repeat(3,minmax(0,1fr)) !important; }
}
@media (max-width:640px){
  .products.layout-grid{
    grid-template-columns:repeat(2,minmax(0,1fr)) !important;
    gap:22px 16px !important;
  }
}


/* -------------------------------------------------------------------------
   3.  CARD TITLE IS ONE LINE                     (Pavel item 7, 2026-08-19)

   SUPERSEDES the two-line block that stood here, INCLUDING its instruction not
   to "improve" this to line-clamp:1. That instruction was sound advice built on
   a wrong measurement: it claimed a 2-up card gives "about 12 readable
   characters". It does not. Measured with the real font off the real card
   (canvas measureText, bold 16px Plus Jakarta Sans, 172px text box at a 390px
   viewport) the ceiling is ~20-21 characters, and 55 of 83 card titles ALREADY
   fitted one line before anything was renamed.

   The remaining 28 are shortened on the CARD ONLY - mt_short_title_map() in
   inc/shop-loop.php. The database keeps the full title, so the Meta feed, the
   PDP H1 and <title> are untouched.

   Reserving a second line is what produced the dead space Pavel photographed:
   a one-line title such as "Axolotl Drummer" rendered inside a 44.8px box, so
   every short card carried a full empty line above its price. Measured live
   before this change: title margin 20px top, min-height 44.8px, 10px to the
   price. This block reclaims ~32px per card.

   line-clamp stays at 1 rather than being dropped, as the safety net: if
   MyDesigns re-pushes a long title with no map entry, the card ellipsises
   instead of growing a second line and making the row ragged again.
   ------------------------------------------------------------------------- */
.woocommerce ul.products li.product .woocommerce-loop-product__title,
.woocommerce-page ul.products li.product .woocommerce-loop-product__title,
.products.layout-grid .woocommerce-loop-product__title{
  display:-webkit-box !important;
  -webkit-line-clamp:1 !important;
  -webkit-box-orient:vertical !important;
  overflow:hidden !important;
  min-height:1.4em;
  margin-top:10px !important;
  margin-bottom:4px !important;
}


/* -------------------------------------------------------------------------
   4.  NO HOVER ICONS ON A CARD                                 (Pavel item 4)

   TeeSpace's .product-actions overlay - the round bag + magnifier Pavel
   photographed. On a phone there is no hover, so a tap surfaces them and eats
   the tap that was meant to open the product. imaginatio kills the same node
   with the same one-liner.

   Removed in CSS rather than by unhooking, deliberately: that markup also
   carries the screen-reader "Select options" text whose id is referenced from
   elsewhere in the card.
   ------------------------------------------------------------------------- */
.product-actions,
.woocommerce ul.products li.product .product-actions,
.products.layout-grid .product-actions{ display:none !important; }


/* -------------------------------------------------------------------------
   5.  THE COLOUR ROW IS HIDDEN, NOT DELETED                    (Pavel item 5)

   `color` is a LOCAL (non-taxonomy) product attribute holding exactly one
   option, Black, on all 83 products. Deleting it is not a display change - it
   rewrites 498 variations, MyDesigns re-adds it on the next push, and the Meta
   catalogue's content_ids ARE the variation ids, so regenerating them desyncs
   the feed that was finished on 18 Aug.

   The <select id="color"> therefore stays in the DOM and stays a real part of
   the variation form; only its row is hidden. inc/product-page.php preselects
   Black so the form resolves to a variation on page load.

   :has() is the selector because the row carries no distinguishing class - the
   theme already relies on :has() for .haru-active-filters. If a browser
   without it ever shows up the row simply reappears WITH Black preselected,
   which is strictly better than today's nothing-selected state.
   ------------------------------------------------------------------------- */
.woocommerce div.product form.cart table.variations tr:has(#color){
  display:none !important;
}

/* One attribute row left means WooCommerce's "Clear" link is offering to clear
   a single preselected size. It stays in the DOM for the variation JS and goes
   quiet visually. */
.woocommerce div.product form.cart .reset_variations{ visibility:hidden; }


/* -------------------------------------------------------------------------
   6.  PDP GALLERY IS ARROWS, NOT A THUMBNAIL RAIL (Pavel item 1, 2026-08-19)

   REVERSES the 08-19 decision to bring the rail back as the swipe affordance.
   Pavel photographed the rail with a red X over it and drew an arrow on the
   photo instead.

   The arrows already existed and were already styled - TeeSpace prints
   .slick-prev / .slick-next inside #product-images and chrome-ux.css block 11
   paints them BONE on 55% ink. They were invisible for one reason: the parent
   reveals them on :hover of the gallery, and on a phone there is no hover, so
   they could never appear. Measured live before this change: both arrows in the
   DOM at 26x48, opacity 0, visibility hidden.

   The behaviour Pavel asked for is what slick already does. The gallery is
   built with infinite:false, so on slide 1 only "next" is live and on slide 2
   only "prev" is - forward to the ghost mannequin, back to the flat lay. The
   disabled one is removed entirely rather than dimmed to .35, because a greyed
   arrow on a two-image gallery reads as broken.

   RAIL IS COLLAPSED, NOT REMOVED FROM THE DOM. #product-images is initialised
   with asNavFor:".slider-nav"; deleting the rail breaks slick's pairing and
   takes the main slider down with it. height:0 rather than display:none
   because slick measures container width.

   The glyph is inline SVG, not the parent's :before. That :before is a
   private-use codepoint in the `phosphor` icon font - if that font fails to
   load or an optimiser subsets it away, the control renders as an empty box
   and nothing is logged anywhere.

   No JS is needed to stop an arrow tap opening the lightbox: the arrows are
   direct children of #product-images, siblings of .slick-list, so a click on
   one never lands inside the .product-image-lightbox anchor.
   ------------------------------------------------------------------------- */
.single-product .product-thumbnails-wrap{
  height:0 !important;
  overflow:hidden !important;
  margin-top:0 !important;
  padding:0 !important;
  visibility:hidden !important;
}

.single-product #product-images{ position:relative; }

.single-product #product-images .slick-prev.slick-arrow,
.single-product #product-images .slick-next.slick-arrow{
  opacity:1 !important;
  visibility:visible !important;
  width:44px !important;
  height:44px !important;
  top:50% !important;
  transform:translateY(-50%) !important;
  border-radius:50% !important;
  background-color:rgba(10,10,10,.55) !important;
  background-repeat:no-repeat !important;
  background-position:center !important;
  background-size:22px 22px !important;
  border:1px solid var(--mt-hairline-strong,#2E2E2E) !important;
  z-index:9 !important;
  cursor:pointer;
  transition:background-color .2s ease, border-color .2s ease;
}
.single-product #product-images .slick-prev.slick-arrow{
  left:10px !important; right:auto !important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23EDE8DF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 4l-8 8 8 8'/%3E%3C/svg%3E") !important;
}
.single-product #product-images .slick-next.slick-arrow{
  right:10px !important; left:auto !important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23EDE8DF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 4l8 8-8 8'/%3E%3C/svg%3E") !important;
}
/* Kill the phosphor glyph. The button keeps its "Previous"/"Next" text node for
   screen readers; the parent already sets font-size:0 on it. */
.single-product #product-images .slick-prev.slick-arrow:before,
.single-product #product-images .slick-next.slick-arrow:before{
  content:none !important;
}
.single-product #product-images .slick-prev.slick-arrow:hover,
.single-product #product-images .slick-next.slick-arrow:hover{
  background-color:rgba(10,10,10,.8) !important;
  border-color:var(--mt-bone,#EDE8DF) !important;
}
.single-product #product-images .slick-arrow.slick-disabled{
  opacity:0 !important;
  pointer-events:none !important;
}


/* -------------------------------------------------------------------------
   7.  BUNDLE LADDER STRIP                                      (Pavel item 6)

   Sits directly above Add to Cart, same position as imaginatio's. The rung
   text is printed by mu-plugins/mt-bundle-offer.php - the thing that actually
   delivers the rungs - so the strip cannot advertise something the cart does
   not honour.
   ------------------------------------------------------------------------- */
.mt-bundle-promo{
  display:flex;
  flex-direction:column;
  gap:6px;
  margin:0 0 16px;
  padding:12px 14px;
  border:1px solid var(--mt-hairline-strong,#2C2C2C);
  background:var(--mt-ink-raised,#141414);
}
.mt-bundle-lead{ display:flex; flex-direction:column; gap:5px; }
.mt-bundle-rung{
  display:block;
  font-size:13px;
  line-height:1.35;
  color:var(--mt-bone,#EDE8DF);
}
.mt-bundle-rung strong{
  font-weight:800;
  letter-spacing:.06em;
  text-transform:uppercase;
}
.mt-bundle-sub{
  font-size:11.5px;
  color:var(--mt-steel-text,#8A8A8A);
  letter-spacing:.02em;
}


/* -------------------------------------------------------------------------
   8.  CART DRAWER GOES STRAIGHT TO CHECKOUT                    (Pavel item 8)

   VIEW CART is unhooked in PHP (inc/commerce-ux.php), not hidden here - a
   hidden link is still a tab stop and still announced by a screen reader.
   What is left is one full-width CHECKOUT button, same as imaginatio.

   /cart/ itself stays alive on purpose: WooCommerce redirects an empty
   checkout to it, coupon errors render on it, and the header cart icon keeps
   it as its no-JS href.
   ------------------------------------------------------------------------- */
.mt-cart .haru-cart-wrap.cart-side .cart-total .buttons{
  display:flex !important;
  flex-direction:column !important;
  gap:10px !important;
}
.mt-cart .haru-cart-wrap.cart-side .cart-total .buttons .button{
  width:100% !important;
}


/* -------------------------------------------------------------------------
   9.  DRAWER REWARD BAR                                        (Pavel item 6)

   Rendered through the WPC Free Shipping Bar filter, which is the one pipeline
   proven to reach the mini-cart fragment. Colours are stated inline in the PHP
   as well, because LiteSpeed UCSS strips selectors it cannot find in static
   HTML and this markup only exists inside an AJAX fragment.
   ------------------------------------------------------------------------- */
.mt-reward-bar{ padding:4px 0 2px; }
.mt-reward-msg{
  font-size:12px;
  line-height:1.4;
  color:var(--mt-bone,#EDE8DF);
  text-align:center;
}
.mt-reward-track{
  position:relative;
  height:4px;
  background:var(--mt-hairline-strong,#2C2C2C);
  margin:0 24px;
}
.mt-reward-fill{
  position:absolute;
  left:0; top:0; bottom:0;
  background:var(--mt-blood,#A3121F);
}
.mt-reward-node{
  position:absolute;
  top:50%;
  width:26px; height:26px;
  margin:-13px 0 0 -13px;
  border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--mt-ink-raised,#141414);
  border:1px solid var(--mt-hairline-strong,#2C2C2C);
  color:var(--mt-steel-text,#8A8A8A);
}
.mt-reward-node.is-hit{
  background:var(--mt-blood,#A3121F);
  border-color:var(--mt-blood,#A3121F);
  color:var(--mt-bone,#EDE8DF);
}
.mt-reward-label{
  position:absolute;
  top:20px;
  width:56px;
  margin-left:-28px;
  text-align:center;
  font-size:9.5px;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--mt-steel-text,#8A8A8A);
}
.mt-reward-label.is-hit{ color:var(--mt-bone,#EDE8DF); }


/* -------------------------------------------------------------------------
   10. MYSTERY-TEE CAPTURE, BLOCK CHECKOUT ONLY                (Pavel item 6)

   This store runs WooCommerce's BLOCK cart and BLOCK checkout (pages are
   wp:woocommerce/cart and wp:woocommerce/checkout), so none of the classic
   checkout hooks fire and the capture fields are registered through the
   Additional Checkout Fields API instead - see mu-plugins/mt-bundle-offer.php.

   That API has no conditional visibility: a registered field renders for every
   shopper, so a one-tee buyer would be asked to steer a mystery tee they have
   not earned. Both fields are therefore registered always and gated here on a
   body class the plugin computes from the real cart.

   Safe because /checkout/ is never page-cached - LiteSpeed excludes cart and
   checkout - so the class is always computed for the visitor in front of it.
   If that exclusion is ever removed these fields start lying about the tier;
   move the gate into PHP at that point rather than patching this.
   ------------------------------------------------------------------------- */
/* SELECT fields do NOT get the address-form__<id> class that TEXT fields get.
   WooCommerce Blocks wraps a select in .wc-block-components-select-input-<id>
   instead - discovered 2026-08-23 by reading the rendered checkout DOM. Every
   rule below that targeted .wc-block-components-address-form__mt-mystery-size
   had therefore matched NOTHING since the field shipped, including the red
   ambiguous-size label. Verify this class in the DOM after any Woo update. */
.wc-block-components-select-input-mt-mystery-size,
.wc-block-components-address-form__mt-custom-brief{ display:none !important; }
/* The size question shows in BOTH gift tiers - a 4-tee custom order has the
   same mixed-size problem a 3-tee one does. 2026-08-23. */
body.mt-tier-mystery .wc-block-components-select-input-mt-mystery-size,
body.mt-tier-custom  .wc-block-components-select-input-mt-mystery-size{ display:block !important; }
/* When we had to guess, say so where the shopper is looking. */
body.mt-size-ambiguous .wc-block-components-select-input-mt-mystery-size label{ color:#A3121F !important; }

/* The 3-tee tier asks ONE question and it is the size. The old
   mt/mystery-steer text box ("Colour or size") sat directly above the size
   dropdown, so it asked the size twice, and its colour half was unanswerable -
   the mystery product has a single colourway. Field deregistered in
   mu-plugins/mt-bundle-offer.php 2026-08-23; there is nothing left to reveal.
   The 4-tee custom tier is untouched. */
body.mt-tier-custom  .wc-block-components-address-form__mt-custom-brief{ display:block !important; }

/* Nothing to ask a one or two tee buyer, so the whole block goes rather than
   leaving an "Additional information" heading standing over an empty box. */
body.mt-tier-none .wp-block-woocommerce-checkout-additional-information-block,
body.mt-tier-none .wc-block-checkout__additional-information{ display:none !important; }

/* -------------------------------------------------------------------------
   11.  HOME GRID MATCHES THE SHOP GRID                       (Pavel item 2)

   Same gutter, same card size. Measured at 390px after block 2 landed: the two
   grids finally shared a 16px gap but the home cards were still 152px against
   the shop's 174px, because THE DROP band adds its own 20px page padding on top
   of the wrapper's 15px while the shop archive only has the wrapper's.

   Pulled out by exactly that 20px on phones so the home grid starts at x=15,
   the same as /shop/. Nothing can overflow: the band is full bleed and the pull
   lands on the wrapper edge, not past it.

   Mobile only. On desktop the band's padding is doing real work.
   ------------------------------------------------------------------------- */
@media (max-width:640px){
  .mt-home-products .products.layout-grid{
    margin-left:-20px !important;
    margin-right:-20px !important;
  }
}


/* -------------------------------------------------------------------------
   13. HEADER CART ICON WAS 8.5px HIGH             (Pavel item 3, 2026-08-19)

   Pavel reported "search is lower than the cart". It is the other way round and
   fixing the search would have made it worse. Measured ink centres of the four
   header controls at 390x844, off a screenshot rather than a rect:

       hamburger  y=74.5      logo  y=74.5
       search     y=73.5      cart  y=66.0

   The cart glyph was also 8.5px LEFT of its button centre (glyph cx 346.5 in a
   button centred on 355). Both offsets have one cause: TeeSpace's style.css
   carries `.haru-cart .haru-cart-opener > a{display:inline-block}` at (0,3,1),
   which outranks the child's `.mt-icon-btn{display:inline-flex}` at (0,1,0). So
   align-items and justify-content on that anchor did nothing and its 21px SVG
   parked itself top-left as an inline box on the text baseline.

   Search was already correct - .mt-search-toggle computes to flex and centres
   its glyph exactly. Nothing about it is touched here.

   NOTE FOR NEXT TIME: the 08-19 pass recorded "all four measure a vertical
   centre of exactly y=75" and called the header correctly aligned. That reading
   was of the 38px BUTTON boxes, which really are all centred. The glyphs inside
   them were not. Measuring the wrapper cannot detect a mis-centred child.
   ------------------------------------------------------------------------- */
.mt-header-icons .haru-cart .haru-cart-wrap .haru-cart-opener > a{
  display:inline-flex !important;
  align-items:center !important;
  justify-content:center !important;
  width:38px;
  height:38px;
  line-height:1 !important;
}
.mt-header-icons .haru-cart .haru-cart-opener > a > svg{
  display:block;
  flex:0 0 auto;
}
/* The count badge is absolutely positioned off the anchor, so it must not be
   allowed to participate in the flex centring above. */
.mt-header-icons .mt-cart-count{
  position:absolute;
  top:-2px;
  right:-2px;
}


/* -------------------------------------------------------------------------
   14. HEADER LIVE SEARCH RESULTS                  (Pavel item 4, 2026-08-19)

   Dropdown rendered by inc/live-search.php into the existing .mt-search-panel.
   Ported from imaginatio, which answers with product thumbnails as you type
   instead of reloading the page.
   ------------------------------------------------------------------------- */
.mt-search-results{
  margin-top:10px;
  border-top:1px solid var(--mt-hairline,#232323);
  max-height:60vh;
  overflow-y:auto;
}
.mt-search-results[hidden]{ display:none !important; }
.mt-search-results ul{ list-style:none; margin:0; padding:0; }
.mt-search-results li{ border-bottom:1px solid var(--mt-hairline,#232323); }
.mt-search-results li a{
  display:flex;
  align-items:center;
  gap:12px;
  padding:10px 2px;
  color:var(--mt-bone,#EDE8DF);
  text-decoration:none;
}
.mt-search-results li a:hover{ color:var(--mt-blood,#A3121F); }
.mt-search-results .mt-sr-thumb{
  flex:0 0 48px;
  width:48px;
  height:48px;
  overflow:hidden;
  background:var(--mt-ink-sunk,#141414);
}
.mt-search-results .mt-sr-thumb img{
  width:100%; height:100%; display:block; object-fit:cover;
}
.mt-search-results .mt-sr-text{ min-width:0; }
.mt-search-results .mt-sr-title{
  display:block;
  font-weight:700;
  font-size:14px;
  line-height:1.3;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.mt-search-results .mt-sr-price{
  display:block;
  font-size:13px;
  color:var(--mt-steel,#6E6E6E);
}
.mt-search-results .mt-sr-price del{ display:none; }
.mt-search-all{
  display:block;
  padding:12px 2px 4px;
  font-size:13px;
  font-weight:800;
  letter-spacing:.06em;
  text-transform:uppercase;
  color:var(--mt-bone,#EDE8DF);
  text-decoration:none;
}
.mt-search-all:hover{ color:var(--mt-blood,#A3121F); }
.mt-search-empty{
  padding:14px 2px;
  color:var(--mt-steel,#6E6E6E);
  font-size:14px;
}


/* -------------------------------------------------------------------------
   15. MINICART SUGGESTIONS                        (Pavel item 5, 2026-08-19)

   Rendered by inc/minicart-suggestions.php inside the drawer, on the same
   WooCommerce hook as the bundle reward bar, so it arrives with the cart
   fragment and never needs its own request.
   ------------------------------------------------------------------------- */
.mt-mc-suggestions{
  margin:16px 0 4px;
  padding-top:14px;
  border-top:1px solid var(--mt-hairline,#232323);
}
.mt-mc-suggestions[data-empty="1"]{ display:none; }
.mt-mc-sugg-title{
  margin:0 0 10px;
  font-size:12px;
  font-weight:800;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--mt-steel,#6E6E6E);
}
.mt-mc-sugg-track{
  display:flex;
  gap:10px;
  overflow-x:auto;
  overflow-y:hidden;
  scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;
  padding-bottom:6px;
}
.mt-mc-sugg-card{
  flex:0 0 96px;
  width:96px;
  scroll-snap-align:start;
  color:var(--mt-bone,#EDE8DF);
  text-decoration:none;
}
.mt-mc-sugg-card:hover .mt-mc-sugg-name{ color:var(--mt-blood,#A3121F); }
.mt-mc-sugg-img{
  display:block;
  width:96px;
  height:96px;
  overflow:hidden;
  background:var(--mt-ink-sunk,#141414);
  border:1px solid var(--mt-hairline,#232323);
}
.mt-mc-sugg-img img{ width:100%; height:100%; display:block; object-fit:cover; }
.mt-mc-sugg-name{
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
  margin-top:6px;
  font-size:12px;
  font-weight:700;
  line-height:1.25;
}
.mt-mc-sugg-price{
  display:block;
  margin-top:2px;
  font-size:12px;
  color:var(--mt-steel,#6E6E6E);
}
.mt-mc-sugg-price del{ display:none; }


/* -------------------------------------------------------------------------
   16. PDP ZOOM CONTROL                           (Pavel item 1, 2026-08-19b)

   NOTHING WAS BUILT HERE. The control already existed and WE hid it.
   TeeSpace renders, inside .single-product-image:

       <div class="product-images-actions">
         <div class="product-gallery-enlarge product-gallery-btn">
           <a href="javascript:;"><span>Click to enlarge</span></a>

   and every gallery slide is already wrapped in
   <a class="product-image-lightbox" data-fancybox="product-gallery">. Clicking
   the control opens fancybox 3.5.7 with both photographs, a close button, a
   zoom button and arrows. It was invisible because sections.css block 7 said
   `display:none !important` with the note "the gallery is a single image now" -
   true when it was written on 08-08, false since 08-19, when the ghost mannequin
   came back into the gallery. That block is now a tombstone; this is the styling.

   WHY THE GLYPH IS INK AND SITS TOP-RIGHT
   The MyDesigns mockup template is pixel-identical across products (same finding
   as the 08-18 featured-image sort): sampling a 14% corner box on 8 random
   products returns EXACTLY TL=168 TR=179 BL=123 BR=84 mean luminance on all 8.
   So an INK glyph beats a BONE one in either top corner, and bottom-left (123)
   is mostly black shirt where an ink glyph would vanish.

   IT SHIPPED TOP-LEFT FIRST AND THAT WAS WRONG. TL=168 is a true average and a
   useless one: the yellow plush chick in its studded collar sits exactly there,
   so the magnifier landed ON the chick's collar and read as part of the prop.
   Caught by screenshotting it in WebKit, not by any number. A luminance average
   over a box says nothing about what is IN the box - the same lesson as
   "measuring is not seeing". TR is the brightest corner AND clean stone with the
   shirt shoulder well below the icon, checked by cropping it and looking.

   WHAT THE PARENT DOES THAT PAVEL ASKED TO STOP
   .product-gallery-btn > a is a WHITE PILL (background #fff, border-radius 30px,
   box-shadow), and `> a:hover > span` animates max-width 0 -> 220px, so hovering
   inflates the pill and reveals the words "Click to enlarge". That is the
   "background changes on hover" in his note. The <span> is not deleted - it is
   moved to a screen-reader-only box, so the control keeps an accessible name.
   ------------------------------------------------------------------------- */
.single-product .single-product-image .product-images-actions{
  display:block !important;
  position:absolute !important;
  top:0 !important;
  right:0 !important;
  left:auto !important;
  bottom:auto !important;
  padding:10px !important;
  z-index:10 !important;
}
.single-product .single-product-image .product-gallery-enlarge,
.single-product .single-product-image .product-gallery-btn{
  display:block !important;
}

/* The magnifier is an inline SVG data URI, NOT the parent's :before glyph.
   That glyph is U+E92F in the `phosphor` icon font - a private-use codepoint
   that renders as an empty box and logs nothing at all if the font fails. Same
   call already on record for the gallery arrows (2026-08-19). */
.single-product .single-product-image .product-gallery-btn > a{
  display:block !important;
  width:34px !important;
  height:34px !important;
  padding:0 !important;
  background-color:transparent !important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230A0A0A' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='6.5'/%3E%3Cpath d='M15.8 15.8L20 20'/%3E%3Cpath d='M8.5 11h5M11 8.5v5'/%3E%3C/svg%3E") !important;
  background-repeat:no-repeat !important;
  background-position:center !important;
  background-size:24px 24px !important;
  border-radius:0 !important;
  box-shadow:none !important;
  transition:none !important;
}
.single-product .single-product-image .product-gallery-btn > a:before{ content:none !important; }

/* No hover state at all - Pavel's third clause. Stated for hover AND focus so a
   keyboard tab does not do what a mouse is barred from doing. */
.single-product .single-product-image .product-gallery-btn > a:hover,
.single-product .single-product-image .product-gallery-btn > a:focus{
  background-color:transparent !important;
  box-shadow:none !important;
  transform:none !important;
}

/* "Click to enlarge" becomes the accessible name and stops being a pill that
   inflates on hover. max-width is restated on :hover because the parent's
   animation targets exactly that property. */
.single-product .single-product-image .product-gallery-btn > a > span,
.single-product .single-product-image .product-gallery-btn > a:hover > span{
  position:absolute !important;
  width:1px !important;
  height:1px !important;
  max-width:1px !important;
  padding:0 !important;
  margin:-1px !important;
  overflow:hidden !important;
  clip:rect(0 0 0 0) !important;
  white-space:nowrap !important;
  border:0 !important;
}


/* -------------------------------------------------------------------------
   17. THE SIZE VALUE IS PRINTED ONCE, NOT TWICE  (Pavel item 2, 2026-08-19b)

   Three writers put the selected value in that row. TeeSpace hardcodes
   <span class="selected-value"> in variable.php and fills it from
   assets/js/index.js; the swatch plugin injects <span class="cfvsw-selected-label">
   INSIDE the <label>. sections.css block 4 hid the plugin's copy and KEPT the
   theme's, on this reasoning: "a colour circle does not name itself, so
   COLOR : DARK CHOCOLATE is worth showing".

   THAT REASONING EXPIRED ON 2026-08-19. The colour row is display:none now
   (single-option attribute, hidden not deleted because deleting it rewrites 498
   variations and the Meta catalogue is keyed on variation ids). Size is the only
   row left, and a size swatch DOES name itself - the swatch literally reads
   "3XL". So the label repeat is pure duplication. Measured before: label "Size"
   at x=15 w=35, then a second visible "L" at x=60 w=23.7, then the swatch row
   below with L already highlighted.

   IF A SECOND COLOURWAY EVER SHIPS, re-enable this for the colour row only.
   ------------------------------------------------------------------------- */
.single-product .variations td.label .selected-value{
  display:none !important;
}


/* -------------------------------------------------------------------------
   18. THE QUANTITY NUMBER WAS INVISIBLE, NOT DIM (Pavel item 3, 2026-08-19b)

   body.dark-mode is on. The parent has a dark-mode block (style.css 17440-17448)
   that repaints .quantity to #333 and the +/- buttons to #ababab - and never
   touches the number, which stays at the hardcoded `color:#000` from
   style.css:16561. Measured live: box rgb(51,51,51), buttons rgb(171,171,171),
   input rgb(0,0,0).

       #000    on #333  =  1.66:1   <- what shipped
       #ababab on #333  =  5.50:1
       #EDE8DF on #333  = 10.36:1   <- this

   WCAG minimum for body text is 4.5:1. It was not hard to read, it was gone.
   Bone rather than #ababab because the number is the value the shopper chose;
   the buttons that change it are secondary and stay at 5.5:1.
   ------------------------------------------------------------------------- */
.single-product form.cart .quantity .input-text[type="number"],
.single-product form.cart .quantity input[type="number"]{
  color:var(--mt-bone,#EDE8DF) !important;
}


/* -------------------------------------------------------------------------
   19. SEARCH OVERLAYS THE HEADER                 (Pavel item 5, 2026-08-19b)

   Before: .mt-search-panel was position:static and a sibling of
   .mt-header-inner, so opening it grew .mt-header from 69px to 150px and pushed
   #product-images from y=129.8 to y=210.8. The page jumped 81px under the
   shopper's thumb. Now it is absolutely positioned over the header row itself,
   Grizzly's shape: announce bar stays, the search field takes the logo row, the
   close X sits where the cart icon was, and nothing below moves by one pixel.

   inset:0 resolves against .mt-header's PADDING box, which is 68px - the header
   is 69px because it carries a 1px bottom border. Verified first that
   .mt-header is position:relative with overflow:visible and that #haru-main is
   overflow:visible too, so the results list can hang below the header without
   being clipped.

   THE SUBMIT BUTTON'S LABEL WAS 10px BELOW ITS OWN CENTRE, and that is what
   Pavel photographed. Measured in real WebKit on an iPhone 15 viewport: button
   y 126..174 (centre 150.0), label ink rows 155..165 (centre 160.0), gap above
   29px against gap below 9px. Cause: line-height:48px inherited onto a
   display:block button with padding:10px - the 48px line box overflows a 28px
   content box and starts at the padding edge, so the text lands at 10+24=34px
   from the top of a 48px button. Predicted 10px from the arithmetic, measured
   10.0px. THIS IS THE THIRD TIME this theme has done it: the cart drawer buttons
   on 08-18 (line-height:44px on VIEW CART only) and the header cart glyph on
   08-19. Rule: centre with flex, never with line-height.

   The wide "SEARCH" word becomes a magnifier icon button, which is what the
   Grizzly reference Pavel supplied actually has. It is still type="submit"
   inside the real <form>, so the no-JS fallback is unchanged. Arithmetic at
   393px: 16 + field + 8 + 40 + 8 + 40 + 16 leaves the field 265px, against
   188px if the word had stayed.
   ------------------------------------------------------------------------- */
.mt-header .mt-search-panel{
  position:absolute !important;
  inset:0 !important;
  height:auto !important;
  z-index:60 !important;
  display:flex !important;
  align-items:center !important;
  gap:8px;
  padding:0 var(--mt-space-4,16px) !important;
  background:var(--mt-ink,#0A0A0A) !important;
  border-top:0 !important;
}
.mt-header .mt-search-panel[hidden]{ display:none !important; }

.mt-header .mt-search-panel form{
  flex:1 1 auto;
  min-width:0;
  max-width:none !important;
  margin:0;
  display:flex !important;
  align-items:center !important;
  gap:8px;
}
.mt-header .mt-search-panel input[type="search"]{
  flex:1 1 auto;
  min-width:0;
  height:40px;
  padding:0 12px !important;
  line-height:normal;
}

/* Both chrome buttons in this row: 40x40, flex-centred, transparent, and no
   hover background - chrome-ux.css block 1 already states that rule for the
   header icons and this row is the header. */
.mt-header .mt-search-panel button[type="submit"],
.mt-header .mt-search-close{
  flex:0 0 40px;
  width:40px !important;
  height:40px !important;
  padding:0 !important;
  display:inline-flex !important;
  align-items:center !important;
  justify-content:center !important;
  line-height:1 !important;
  background:transparent !important;
  border:0 !important;
  border-radius:0 !important;
  color:var(--mt-bone,#EDE8DF) !important;
  cursor:pointer;
}
.mt-header .mt-search-panel button[type="submit"]:hover,
.mt-header .mt-search-close:hover{
  background:transparent !important;
  color:var(--mt-blood,#A3121F) !important;
}
.mt-header .mt-search-panel button[type="submit"] svg,
.mt-header .mt-search-close svg{
  width:22px;
  height:22px;
  display:block;
}

/* Results hang BELOW the header rather than inside it. top:100% is the bottom
   of the absolutely-positioned panel, which is the bottom of the header row.
   The cap keeps the list inside the viewport on a phone with the keyboard up. */
.mt-header .mt-search-panel .mt-search-results{
  position:absolute;
  top:100%;
  left:0;
  right:0;
  z-index:60;
  margin-top:0;
  padding:0 var(--mt-space-4,16px);
  background:var(--mt-ink-raised,#141414);
  border-top:1px solid var(--mt-hairline,#232323);
  border-bottom:1px solid var(--mt-hairline,#232323);
  max-height:calc(100vh - 190px);
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
}


/* -------------------------------------------------------------------------
   20. PDP ZOOM VIEWER                            (Pavel item 1, 2026-08-19c)

   Replaces fancybox for the gallery. Behaviour and the reasoning for not simply
   configuring fancybox are in inc/product-page.php -> mt_zoom_viewer_js().

   This is a SCROLL CONTAINER, not a zoom widget - the same shape Shopify Dawn
   uses on thegrizzlyco.com, measured there before building: their modal holds
   the image at its natural 1100px inside a 393px viewport and scrolls to centre.
   Panning is therefore native scrolling, which on iOS means momentum and rubber
   banding for free, and no touch handlers to fight the browser.

   The image WIDTH is set in JS, not here, because it is computed from the
   viewport and the print geometry (viewport / 0.390). Nothing in this block may
   set a width on .mt-zoom__img.

   `overscroll-behavior: contain` is the one line that stops a pan reaching the
   end of the image and starting to scroll the PAGE behind it.
   ------------------------------------------------------------------------- */
.mt-zoom{
  position:fixed;
  inset:0;
  z-index:99999;
  background:var(--mt-ink,#0A0A0A);
  overflow:auto;
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
}
.mt-zoom[hidden]{ display:none !important; }

.mt-zoom__img{
  display:block;
  max-width:none;   /* the theme sets img{max-width:100%}; that would undo the zoom */
  height:auto;
}

/* Fixed, not absolute: the container scrolls under it, so an absolutely
   positioned button would slide off the top the moment you panned down.

   background AND color carry !important, and that is not defensive habit - it
   shipped without them and rendered as a solid BLOOD disc with no X on it.
   TeeSpace's GENERATED style.css paints every <button>, background and colour
   alike, with !important; the svg strokes `currentColor`, so the glyph inherited
   blood too and drew blood-on-blood. Measured: background rgb(163,18,31),
   color rgb(163,18,31), stroke rgb(163,18,31). The search close button written
   earlier the same day already had these and rendered correctly - this one
   simply did not copy them. Never edit style.css to fix this; it is generated
   and any edit is lost on a theme update. */
.mt-zoom__close{
  position:fixed;
  top:12px;
  right:12px;
  width:44px;
  height:44px;
  padding:0;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  line-height:1;
  border:0 !important;
  border-radius:50% !important;
  background:rgba(10,10,10,.55) !important;
  color:var(--mt-bone,#EDE8DF) !important;
  cursor:pointer;
  z-index:1;
}
.mt-zoom__close:hover,
.mt-zoom__close:focus{
  background:rgba(10,10,10,.75) !important;
  color:var(--mt-bone,#EDE8DF) !important;
}
.mt-zoom__close svg{
  width:22px;
  height:22px;
  display:block;
  stroke:currentColor;
}

/* -------------------------------------------------------------------------
   24. THE FREE-TEE BRIEF IS A GIFT PANEL, NOT A FOOTNOTE     (Pavel, 22 Aug)

   The capture field was rendering inside WooCommerce's stock "Additional order
   information" step, BELOW the payment block, two thirds of the way down the
   page - and Woo Blocks uses a floating label, so with an empty input there was
   no visible text at all explaining what the box was for. A shopper who has
   just earned a free tee never saw the one question that decides what we print.

   Two changes, and only this one is CSS. The other is the block order on the
   checkout page itself: `woocommerce/checkout-additional-information-block` now
   sits directly ABOVE `woocommerce/checkout-payment-block` (backup of the old
   page content is in option `moshtee_backup_20260822_checkout_page`). That puts
   it in the same relative position imaginatio has it - immediately before
   Payment options - which is what Pavel asked for.

   The heading text is replaced per tier with CSS `content` rather than by JS.
   The step title is rendered by React and rewriting its text node is reverted on
   the next re-render; a stylesheet is not. `font-size:0` on the h2 kills the
   stock string without removing the element, so the screen-reader `<legend>`
   still announces the step.

   Everything here is scoped to a tier body class, so a one or two tee cart is
   untouched - that cart still hides the whole block (rule 10 above).
   ------------------------------------------------------------------------- */

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block {
  background: #141414;
  border: 2px dashed var(--mt-blood, #A3121F);
  border-radius: 3px;
  padding: 20px 18px 22px !important;
  margin: 28px 0 !important;
}

/* Kill the stock "Additional order information" without removing the node. */
body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__title,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__title {
  font-size: 0 !important;
  line-height: 0 !important;
  margin: 0 !important;
}

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__title::after,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__title::after {
  display: block;
  font-family: inherit;
  font-size: 17px;
  line-height: 1.25;
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--mt-bone, #EDE8DF);
  margin: 0 0 6px;
}

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__title::after {
  content: "Your FREE Mystery Tee";
}

body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__title::after {
  content: "Your FREE Custom Tee - made only for you";
}

/* The explanation the floating label can never carry. */
body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__heading-container::after,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__heading-container::after {
  display: block;
  font-size: 13.5px;
  line-height: 1.5;
  color: #b8b1a4;
  margin: 0 0 14px;
}

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__heading-container::after {
  content: "Black tee, and the design is our surprise. Just set the size below.";
}

body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__heading-container::after {
  content: "A one-off tee designed for you. Give us a name, a genre or an in-joke. Leave it blank and we will surprise you.";
}

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__heading,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__heading {
  margin: 0 !important;
}

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__content,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-checkout-step__content {
  margin: 0 !important;
}

/* The input itself has to read as fillable on INK. */
body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-text-input input,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-text-input input {
  background: #0A0A0A !important;
  border: 1px solid #4a4a4a !important;
  color: var(--mt-bone, #EDE8DF) !important;
  border-radius: 2px !important;
}

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-text-input input:focus,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-text-input input:focus {
  border-color: var(--mt-bone, #EDE8DF) !important;
  outline: none !important;
}

body.mt-tier-mystery .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-text-input label,
body.mt-tier-custom .wp-block-woocommerce-checkout-additional-information-block .wc-block-components-text-input label {
  color: #9d968a !important;
}

/* -------------------------------------------------------------------------
 26. NO OMNISEND POPUP ON THE CHECKOUT                        (Pavel 2026-08-23)

 The 10%-off popup was firing on /checkout/, over a customer who is already
 buying, offering a code the 2+ tee cart refuses anyway. On a 393px phone it
 covered the whole FREE TEE panel - it had to be deleted from the DOM before
 that panel could even be screenshotted.

 #omnisend-forms-wrapper holds the fixed-position modal AND its overlay
 (verified by Node.contains on the live checkout). #omnisend-subscribe-block
 - the pre-ticked "Email me with news and offers" box that made the first real
 customer reachable - is a SEPARATE node outside this wrapper and is NOT
 touched. Do not widen this to [id*=omnisend].

 Hiding, not unloading: omnisend-front-script.js also carries the abandoned
 cart and checkout tracking that three live email automations run on, so the
 snippet must keep loading. The proper fix is Omnisend's own display rules -
 exclude /checkout/ there and the popup never renders or counts an
 impression. This rule is the belt.
 ------------------------------------------------------------------------- */
body.woocommerce-checkout #omnisend-forms-wrapper{ display:none !important; }
/* ---------------------------------------------------------------------------
   27. CART DRAWER: THE LINE ITEMS OWN THE FLEXIBLE REGION  (Pavel 2026-08-24)

   Measured at 393x659 on 23 Aug: the item list rendered clientHeight 115
   against scrollHeight 299. A two-tee cart showed ONE item, itself clipped
   part-way through its REMOVE link, under a $63.98 subtotal - the second tee
   was not below the fold, it was outside the scroll box entirely.

   THE REAL TREE, dumped live rather than assumed:

     .cart_list_wrap            flex column, 590px on a 659px viewport
       .cart_list_content       display:BLOCK   <- the wrapper that matters
         ul.cart_list           the line items
       .cart-total              247px: total + reward bar + CHECKOUT

   The flexible region is .cart_list_content, NOT ul.cart_list. A first pass
   here declared `.cart_list_wrap > * { flex:0 0 auto }` and put the grow on the
   ul; that pinned .cart_list_content to content height, and because it is
   display:block the flex declaration on its child ul did nothing at all. The
   list went 115px -> 30px. Measured, caught, rewritten.

   .cart-total is left at content height on purpose: it carries the subtotal,
   the ladder progress and the CHECKOUT button, none of which may ever be
   pushed off-screen to win room for line items.

   min-height:0 is load-bearing in both rules - a flex item defaults to
   min-height:auto and refuses to shrink below content height, which would move
   the overflow back up to the panel and give the drawer two scrollbars.

   max-height:none overrides style.css:45633 (max-height:350px), a desktop
   dropdown number that has no business capping a full-height drawer.
   --------------------------------------------------------------------------- */
.haru-cart .haru-cart-wrap.cart-side .cart_list_wrap > .cart_list_content{
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.haru-cart .haru-cart-wrap.cart-side .cart_list_wrap > .cart_list_content > .cart_list{
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
}
.haru-cart .haru-cart-wrap.cart-side .cart_list_wrap > .cart-total{
  flex: 0 0 auto;
}

/* Short viewports: the upsell yields, never the line item.

   Measured 2026-08-24 at 393x659 with ONE tee in the cart: the item list got
   132px for 156px of content, so the single line item was clipped through its
   REMOVE link again - this time by the suggestion strip (208px), which renders
   inside .cart-total and so inherits its flex:0 0 auto.

   Arithmetic: header 69 + subtotal/ladder/checkout 247 + suggestions 208 +
   one full row 156 = 680. Under ~700px of viewport there is no arrangement
   that shows a complete line item and a three-card upsell at once.

   A two-tee cart never reaches this rule - mt_minicart_suggestions() has
   already returned by then. This covers the one-tee case only. At 393x852,
   the real iPhone 15, the strip stays and the list measures 325/325. */
@media screen and (max-height: 700px){
  .haru-cart .haru-cart-wrap.cart-side .mt-mc-suggestions{
    display: none;
  }
}


/* --- BLOCK 28 (2026-08-25) - WooCommerce Blocks notices on a dark checkout ---

   Pavel: "when coupon added strange table appears, remove it".

   Measured live in WebKit iPhone 15 after applying MOSH666XWVKZ:
     .wc-block-components-notice-banner.is-info  bg rgb(244,248,255) / text rgb(47,47,47)
     .wc-block-components-notice-banner__content bg rgb(246,250,252)
     .wc-block-components-notice-banner__dismiss bg rgb(163,18,31)  <- BLOOD square

   Two separate faults. The banner ships Woo's stock LIGHT palette, which on a
   #0A0A0A checkout reads as a white panel pasted over the page. And the 16x16
   dismiss button is painted BLOOD by TeeSpace's generated CSS, which colours
   every <button> - the same trap as the 07 Aug search close button and the
   19 Aug lightbox close. Its glyph strokes currentColor, so it renders as a
   solid red square with no visible X.

   THE SUCCESS TOAST IS HIDDEN, THE FAILURE ONES ARE NOT. 'Coupon applied' is
   pure duplication - the order summary already shows the coupon chip and a
   Discount line the moment it lands. But a coupon that is expired, used up or
   misspelled reports ONLY through this snackbar, so hiding is-error/is-warning
   would make a failed code look like nothing happened. Those are restyled to
   the dark palette instead.

   Scoped to the snackbar list so inline validation banners inside the checkout
   form are untouched. The fixed containers are already pointer-events:none
   (verified), so nothing here affects tapping. */

.wc-block-components-notice-snackbar-list .wc-block-components-notice-snackbar.is-info{
  display: none;
}

.wc-block-components-notice-snackbar-list .wc-block-components-notice-banner{
  background: #141414;
  color: #EDE8DF;
  border: 1px solid rgba(237,232,223,.22);
  border-radius: 2px;
}

.wc-block-components-notice-snackbar-list .wc-block-components-notice-banner__content{
  background: transparent;
  color: #EDE8DF;
}

.wc-block-components-notice-snackbar-list .wc-block-components-notice-banner.is-error{
  border-color: #A3121F;
}

.wc-block-components-notice-snackbar-list .wc-block-components-notice-banner__dismiss{
  background: transparent !important;
  color: #EDE8DF !important;
  border: 0 !important;
  box-shadow: none !important;
  min-width: 0;
  padding: 0;
}

.wc-block-components-notice-snackbar-list .wc-block-components-notice-banner__dismiss svg{
  fill: currentColor;
}

/* --- BLOCK 28b (2026-08-25) - a failed coupon must LOOK failed ---

   Coupon errors do NOT use the snackbar. They render inline as
   .wc-block-components-validation-error inside .wc-block-components-totals-coupon__content.
   Measured: the wrapper DIV carries color rgb(204,24,24), but the <p> inside is
   repainted BONE by the dark-mode cascade, so 'Coupon X cannot be applied' reads
   in ordinary body colour and looks like a normal sentence, not a rejection.

   BLOOD #A3121F is NOT used here - it measures 2.28:1 on #0A0A0A (the 17 Aug
   finding that moved the I LIKE METAL middle line off red). #F08A8A is a lifted
   red that clears 7:1 on ink while still reading unmistakably as an error. */

.wc-block-components-totals-coupon__content .wc-block-components-validation-error,
.wc-block-components-totals-coupon__content .wc-block-components-validation-error p,
.wc-block-components-totals-coupon__content .wc-block-components-validation-error span{
  color: #F08A8A;
}


/* =========================================================================
   MT-BLOCK-QTY-OFF - PDP quantity stepper removed          (2026-09-16)

   Shimmy Morris, live store review: "you don't need this plus one, plus two,
   I would just have a big add to cart button." Pavel's call: PRODUCT PAGE
   ONLY. The cart drawer and checkout keep their +/- so two of the same
   design is still one tap away. display:none still submits the hidden
   input, so every add is quantity 1. The button already carries
   flex:1 1 auto (sections.css block 18), so it takes the freed width.
   !important is required, not lazy: variation JS writes an INLINE
   style="display:block" onto .quantity every time a variation resolves,
   and an inline style beats any selector (measured 2026-09-16).
   Revert: delete this block.
   ========================================================================= */
body.single-product .single-product-top form.cart .woocommerce-variation-add-to-cart .quantity{
  display:none !important;
}


/* =========================================================================
   MT-BLOCK-VIEWCART-OFF - no 'View cart' link after add to cart  (2026-09-17)

   The AJAX single add-to-cart triggers added_to_cart with the button, and
   WooCommerce's add-to-cart.js then appends a.added_to_cart.wc-forward beside
   it, which squeezed ADD TO CART narrower. The drawer already opens; the link
   is redundant. Pavel: remove it.
   ========================================================================= */
a.added_to_cart.wc-forward{ display:none !important; }


/* =========================================================================
   MT-BLOCK-PRIMARY-HOVER - red button text stays BONE on hover   (2026-09-17)

   The generated parent style.css paints `a:hover` and
   `body.dark-mode a:hover` BLOOD with !important (0,2,2). On a BLOOD button
   that is red text on red - the label vanished (Shop all, View all).
   (0,3,2) + !important wins without touching any other link.
   ========================================================================= */
body a.mt-btn.mt-btn--primary:hover,
body a.mt-btn.mt-btn--primary:focus,
body a.mt-btn.mt-btn--primary:active,
/* Halloween drop CTA (inc/seasonal-drop.php): iOS keeps :hover after a tap, so
   the label went BLOOD on the darker blood-hover fill - Pavel's iPhone, 17 Sep. */
body a.mt-drop-cta.mt-drop-cta:hover,
body a.mt-drop-cta.mt-drop-cta:focus,
body a.mt-drop-cta.mt-drop-cta:active{ color:#EDE8DF !important; }


/* =========================================================================
   MT-BLOCK-CHECKOUT-HEADER - no cart or search icon on checkout   (2026-09-17)

   Pavel's call. On /checkout/ the cart icon had nowhere useful to go (its href
   resolves to checkout itself, /cart/ is never linked) and search only pulls
   a buyer out of the funnel. visibility, not display: the header is a 3-column
   grid and the logo must not move. Thank-you page keeps both.
   ========================================================================= */
body.woocommerce-checkout:not(.woocommerce-order-received) .mt-header-icons .mt-search-toggle,
body.woocommerce-checkout:not(.woocommerce-order-received) .mt-header-icons .mt-cart{
  visibility:hidden !important;
  pointer-events:none !important;
}


/* =========================================================================
   ORDER-PAY / THANK-YOU / VIEW-ORDER - prices were black on ink   (2026-09-21)

   Pavel caught it on the failed-order pay page (#1436). Parent style.css
   paints `.amount bdi{color:#000}` (0,1,1); these pages render the stock
   classic shop_table, which none of the PDP/drawer price repairs cover.
   ========================================================================= */
body.woocommerce-order-pay .amount bdi,
body.woocommerce-order-pay .amount .woocommerce-Price-currencySymbol,
body.woocommerce-order-received .amount bdi,
body.woocommerce-order-received .amount .woocommerce-Price-currencySymbol,
body.woocommerce-view-order .amount bdi,
body.woocommerce-view-order .amount .woocommerce-Price-currencySymbol{
  color:var(--mt-bone) !important;
}
