/* ============================================================
   PARINHALL — EXTENSION LAYER
   Components required by templates the approved homepage does
   not cover. Every value resolves to a token that already
   exists in the approved design (--color-*, --space-*,
   --radius-*, --shadow-*) or to a border literal already used
   in one of the two approved files.
   No new colors. No new radii. No new shadows. No new fonts.
   ============================================================ */

/* ---------- 0. Components promoted from the approved design system
   (design/approved-original-design-system.html) ---------- */
.field label{font-size:14px;font-weight:600;color:var(--color-heading);display:block;margin-bottom:6px}
.field textarea,.field select{width:100%;min-height:48px;padding:var(--space-2) var(--space-3);border:1.5px solid #E4DFD6;border-radius:var(--radius-input);background:var(--color-surface);font-family:inherit;font-size:15px;color:var(--color-heading);transition:border-color var(--transition),box-shadow var(--transition)}
.field textarea{min-height:132px;line-height:1.7;resize:vertical}
.field textarea:focus,.field select:focus{border-color:var(--color-secondary);box-shadow:0 0 0 3px var(--color-secondary-tint);outline:none}
.field textarea::placeholder{color:var(--color-muted)}
.field__msg{font-size:12.5px;margin-top:6px;display:block}
.field--error input,.field--error textarea,.field--error select{border-color:var(--color-error)}
.field--error .field__msg{color:var(--color-error)}
.field--success .field__msg{color:var(--color-success)}
.alert{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-3);border-radius:var(--radius-card);font-size:14px;font-weight:500}
.alert svg{width:18px;height:18px;flex-shrink:0;stroke:currentColor}
.alert-success{background:var(--color-mix-tint);color:var(--color-success)}
.alert-error{background:#FBEAEA;color:var(--color-error)}
.alert-info{background:var(--color-secondary-tint);color:var(--color-secondary)}
.chip{display:inline-flex;align-items:center;gap:6px;padding:8px var(--space-3);border:1.5px solid #E4DFD6;border-radius:var(--radius-button);font-size:13.5px;font-weight:600;color:var(--color-body);background:var(--color-surface);cursor:pointer;transition:border-color var(--transition),color var(--transition),background var(--transition)}
.chip:hover,.chip.is-active{border-color:var(--color-primary);color:var(--color-primary);background:var(--color-primary-tint)}
.chip svg{width:13px;height:13px;stroke:currentColor;flex-shrink:0}
.divider{border:none;border-top:1px solid #EDE7DD;margin-block:var(--space-5)}
.price-currency{font-size:12px;color:var(--color-body)}
.badge-limited{background:var(--color-limited-bg);color:var(--color-limited-gold)}
.product-card__media{aspect-ratio:1/1;background:var(--color-primary-tint);position:relative}

/* ---------- 0b. SVG SIZING GUARDS ----------------------------------
   An inline <svg> with a viewBox but no width/height stretches to the
   full width of its container. The approved CSS sizes every icon it
   uses; these rules do the same for the contexts this layer adds, so
   no icon can ever blow up to full width again.                     */
.btn svg{width:17px;height:17px;stroke:currentColor;flex-shrink:0}
.stock-line svg{width:16px;height:16px;stroke:currentColor;flex-shrink:0}
.option-row svg,.summary-row svg,.consent-row svg,.cart-item svg{width:16px;height:16px;stroke:currentColor;flex-shrink:0}

/* ---------- 0c. Body scroll lock while a drawer is open ---------- */
body.has-drawer{overflow:hidden}

/* ---------- 0d. Mobile menu: two-column subcategory lists ----------
   Requested so every subcategory is visible without the list
   overflowing its panel. Layout only — no color, type or spacing
   token is changed.                                                */
.acc-panel .acc-panel ul.acc-sub-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:var(--space-3);row-gap:10px}
.offcanvas{padding-bottom:calc(var(--space-6) + var(--bottom-bar-height))}

/* ---------- 0f. Logo sizing guard ----------------------------------
   The approved CSS sizes the logo with `height`. A plugin, a caching
   layer's image rewriting, or WordPress's own responsive-image handling
   can override that `height` and the logo then renders at its intrinsic
   size — several hundred pixels tall, which collapses the whole header.
   `max-height` caps the rendered height whatever `height` ends up being,
   and `width:auto` keeps the aspect ratio. Same numbers as approved:
   52px, 42px scrolled, 40px on mobile, 54px in the footer.           */
.brand-logo{max-height:52px;width:auto}
.site-header.is-scrolled .brand-logo{max-height:42px}
.footer-brand-logo{max-height:54px;width:auto}

/* ---------- 0g. Mega menu: hover expansion -------------------------
   The DEFAULT column template is written inline on the container by
   PHP, because the number of columns depends on how many product
   categories exist — the approved `repeat(5,1fr) 1.1fr` only holds
   while there are exactly five. With five categories the inline value
   is identical to the approved one.
   Only while a long column is hovered or focused does JS swap the
   track sizes: that column grows, the others shrink by the same total,
   so the container width and every gap stay identical.              */
.mega-menu .container{transition:grid-template-columns .25s ease}
.mega-col--expanded ul{display:grid;grid-template-columns:1fr 1fr;column-gap:var(--space-3);row-gap:10px}
.mega-col--expanded .mega-col-title{color:var(--color-primary)}

/* ---------- 0h. Accessibility utilities ----------------------------
   The approved design never needed these, but real templates do: a skip
   link, and visually-hidden inputs behind the filter switches and colour
   swatches so those controls stay operable by keyboard and screen reader
   while looking exactly as designed.                                  */
.screen-reader-text{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip-link:focus{position:fixed!important;top:var(--space-2);inset-inline-start:var(--space-2);width:auto;height:auto;clip:auto;z-index:2000;background:var(--color-surface);color:var(--color-heading);padding:var(--space-2) var(--space-3);border-radius:var(--radius-input);box-shadow:var(--shadow-lift)}
.filter-swatches label{display:inline-flex;cursor:pointer}
/* .switch-row{cursor:pointer} was here and did nothing — section 3 sets
   the same property on the same selector further down and wins on source
   order. One owner per property. */

/* ---------- 0i. Real images inside .ph-img boxes -------------------
   THE BUG BEHIND "STRETCHED IMAGES".
   `.ph-img` was designed as a placeholder DIV: a fixed aspect-ratio box
   with no image in it. The templates reuse the same class on real <img>
   elements so uploads inherit the approved shape — but an <img> with a
   forced aspect-ratio and no object-fit defaults to `fill`, which
   squashes any photo that is not already that exact shape.

   So it was never the pixel count that broke: an 800px, 640px or 1000px
   square all behaved. A 1200×800 photo in a 1:1 box got squashed, and a
   portrait photo in the 1920:720 hero got crushed flat.

   `cover` crops the overflow instead of distorting, which is what every
   storefront does. Uploads can now be any shape.                      */
img.ph-img{object-fit:cover;display:block}
.hero-slide img.ph-img,.gallery-main img.ph-img{width:100%;height:100%}

/* ---------- 0j. Hero: controls below the frame ---------------------
   Arrows and dots were absolutely positioned over the image. They now
   sit in a row underneath, outside the slider frame, and the caption
   overlay is gone — the image itself is the link.                     */
.hero{overflow:visible}
.hero-frame{position:relative;overflow:hidden;border-radius:var(--radius-card)}
.hero-slide a{display:block;width:100%}
/* Layout lives in section 32 (the dots-above-arrows grid). Only the
   spacing above the row belongs here. */
.hero-controls{margin-top:var(--space-3)}
.hero-controls .hero-arrow{position:static;transform:none;inset:auto;background:var(--color-surface);box-shadow:var(--shadow-soft)}
.hero-controls .hero-arrow:hover{background:var(--color-secondary-tint)}
/* parinhall_icon() emits an <svg> with no width or height — every other
   component sizes it in CSS, but .hero-arrow never got a rule. Inside a
   flex container an SVG with no intrinsic size collapses to nothing, so
   the arrows were rendering as blank white circles. Give them a size and
   a stroke, and a visible edge so a white circle on the cream page
   background is not just a faint shadow. */
/* Size is set in section 32; this is only the colour and weight. */
/* Colour only. stroke-width, the dot gap and the active-dot width are all
   set once in section 23, which is where the control sizing lives; the
   values that used to be repeated here (2.2, 8px, 22px) were overridden
   there and never reached the screen. */
.hero-arrow svg{stroke:var(--color-heading);flex-shrink:0}
/* 1px, not 1.5px. The shorthand here used to say 1.5px and a longhand in
   section 23 said 1px, so the border on screen was never the one this rule
   appeared to set — two owners for one property, and the reader of this
   line had the wrong answer. The longhand is gone; this is the width. */
.hero-controls .hero-arrow{border:1px solid var(--color-control-border)}
.hero-controls .hero-arrow:active{background:var(--color-secondary-tint);transform:scale(.94)}
.hero-controls .hero-dots{position:static;inset:auto;display:flex}
.hero-controls .hero-dot{background:#E4DFD6}
.hero-controls .hero-dot.is-active{background:var(--color-primary);border-radius:var(--radius-button)}
.hero-track{cursor:grab;touch-action:pan-y}
.hero-track.is-dragging{cursor:grabbing}
.hero-track.is-dragging .hero-slide{pointer-events:none}
/* theme.css sets `transform .5s ease`, which starts slowly and finishes
   slowly — on a swipe that reads as the slide hesitating before it moves.
   A decelerating curve leaves at the speed the finger was going and eases
   only into the stop. Shorter, too: half a second is a long time to watch
   a slide travel once you have already flicked it. */
.hero-track{transition:transform .42s cubic-bezier(.22,.61,.36,1)}
.hero-track:focus-visible{outline:2px solid var(--color-secondary);outline-offset:3px}
.hero-slide{-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}
.hero-slide img{pointer-events:none}
@media (prefers-reduced-motion:reduce){
  .hero-track{transition:none}
}

/* Mobile hero uses the portrait image, so the frame changes shape with
   it. A 1920:720 banner on a phone renders a ~146px strip — which is
   what made the homepage look wrong on mobile. */
@media (max-width:768px){
  /* Square only where a portrait file was actually uploaded. Applying
     it to every slide is what squashed the 1920×720 desktop banner on
     phones. A slide with no mobile image keeps its own ratio: a short
     strip is honest, a stretched face is not. */
  .hero-slide--has-mobile img.ph-img,
  .hero-slide--has-mobile .ph-img{aspect-ratio:1/1}
  .hero-slide:not(.hero-slide--has-mobile) img.ph-img{aspect-ratio:1920/720;object-fit:cover}
  /* Arrow size is decided once, in section 32, for every screen — you
     asked for them small on mobile too. Only the spacing changes here. */
  .hero-controls{margin-top:var(--space-4)}
}

/* ---------- 1. Inner-page head & breadcrumb ---------- */
.page-head{background:var(--color-surface);border-bottom:1px solid #EFE9DF;padding:var(--space-4) 0}
.page-head h1{font-size:clamp(20px,3vw,28px)}
.page-head .eyebrow{color:var(--color-secondary);font-weight:700;font-size:13px;margin-bottom:6px}
.page-head .lede{margin-top:var(--space-2);font-size:14.5px;max-width:680px}
.breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-size:12.5px;color:var(--color-muted);margin-bottom:var(--space-2)}
.breadcrumb a{color:var(--color-secondary)}
.breadcrumb a:hover{color:var(--color-primary)}
.breadcrumb svg{width:11px;height:11px;stroke:var(--color-muted);flex-shrink:0}
.result-count{font-size:13.5px;color:var(--color-body)}

/* ---------- 2. Shop / archive layout ---------- */
.shop-layout{display:grid;grid-template-columns:280px 1fr;gap:var(--space-5);align-items:start}
.filter-panel{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4);position:sticky;top:calc(var(--space-4) + 80px)}
.filter-panel__head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);margin-bottom:var(--space-3)}
.filter-panel__head h3{font-size:16px}
.filter-reset{font-size:12.5px;color:var(--color-secondary);font-weight:600}
.filter-close{display:none}
.filter-group{border-top:1px solid #F2EEE6;padding-top:var(--space-3);margin-top:var(--space-3)}
.filter-group:first-of-type{border-top:none;padding-top:0;margin-top:0}
.filter-group__title{font-size:14px;font-weight:700;color:var(--color-heading);display:flex;align-items:center;justify-content:space-between;width:100%;padding:6px 0;text-align:right}
.filter-group__title svg{width:14px;height:14px;stroke:currentColor;flex-shrink:0;transition:transform var(--transition)}
.filter-group__title[aria-expanded="false"] svg{transform:rotate(-90deg)}
.filter-list{display:flex;flex-direction:column;gap:10px;padding-top:var(--space-2)}
.filter-check{display:flex;align-items:center;gap:var(--space-2);font-size:13.5px;color:var(--color-body);cursor:pointer}
.filter-check input{width:18px;height:18px;min-height:0;flex-shrink:0;accent-color:var(--color-primary);padding:0}
.filter-check .fc-count{margin-inline-start:auto;font-size:12px;color:var(--color-muted)}
.filter-swatches{display:flex;flex-wrap:wrap;gap:var(--space-2);padding-top:var(--space-2)}
.filter-swatch{width:26px;height:26px;border-radius:var(--radius-round);border:2px solid #fff;box-shadow:0 0 0 1px #E4DFD6;cursor:pointer;transition:box-shadow var(--transition)}
.filter-swatch.is-active{box-shadow:0 0 0 2px var(--color-primary)}
.price-range{padding-top:var(--space-3)}
.price-range__inputs{display:flex;align-items:center;gap:var(--space-2)}
.price-range__inputs .field{flex:1}
.price-range__inputs input{min-height:40px;font-size:13px;text-align:center;padding:0 var(--space-2)}
.price-range__sep{color:var(--color-muted);font-size:13px}
.price-range__note{font-size:12px;color:var(--color-muted);margin-top:var(--space-2)}
.switch-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;font-size:13.5px;color:var(--color-body);padding:6px 0;cursor:pointer;text-align:right}
.switch{width:42px;height:24px;border-radius:var(--radius-button);background:#E4DFD6;position:relative;flex-shrink:0;transition:background var(--transition)}
.switch::after{content:"";position:absolute;top:3px;inset-inline-end:3px;width:18px;height:18px;border-radius:var(--radius-round);background:var(--color-surface);box-shadow:var(--shadow-soft);transition:transform var(--transition)}
/* .switch.is-on and .switch.is-on::after used to live here. Nothing puts
   that class on the element any more — filter-panel.php says so in its
   own comment, because the class and the :checked state were two owners
   of the same appearance and the switch stuck on after being unchecked.
   The live rules are with the checkbox in section 33. */
.shop-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);flex-wrap:wrap;background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-3);margin-bottom:var(--space-4)}
.shop-toolbar .field{width:auto;min-width:190px}
.shop-toolbar select{min-height:40px;font-size:13.5px}
.filter-open{display:none}
.active-filters{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-bottom:var(--space-4)}
.product-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-4)}
.category-strip{display:flex;gap:var(--space-2);overflow-x:auto;padding-bottom:var(--space-2);margin-bottom:var(--space-4);scrollbar-width:none}
.category-strip::-webkit-scrollbar{display:none}
.category-strip .chip{flex-shrink:0}

/* ---------- 3. Pagination ---------- */
.pagination{display:flex;justify-content:center;align-items:center;gap:var(--space-2);margin-top:var(--space-6);flex-wrap:wrap}
.page-num{min-width:44px;height:44px;padding:0 var(--space-2);border-radius:var(--radius-input);background:var(--color-surface);box-shadow:var(--shadow-soft);display:inline-flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;color:var(--color-heading);transition:background var(--transition),color var(--transition)}
.page-num:hover{background:var(--color-secondary-tint);color:var(--color-secondary)}
.page-num.is-current{background:var(--color-primary);color:#fff}
.page-num.is-disabled{opacity:.4;pointer-events:none}
.page-num svg{width:16px;height:16px;stroke:currentColor;flex-shrink:0}
.page-dots{color:var(--color-muted);padding:0 4px}

/* ---------- 4. Single product ---------- */
.product-single{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-6);align-items:start}
.product-gallery{position:sticky;top:calc(var(--space-4) + 80px)}
/* position, overflow and the badge z-index are set in section 42, where
   the fixed-ratio media boxes are defined. Repeating them here just meant
   two rules had to be kept in step by hand. */
.gallery-main{border-radius:var(--radius-card);box-shadow:var(--shadow-soft)}
.gallery-main .ph-img{border-radius:0}
.gallery-badges{position:absolute;top:var(--space-3);inset-inline-start:var(--space-3);display:flex;flex-direction:column;gap:6px}
.gallery-thumbs{display:grid;grid-template-columns:repeat(5,1fr);gap:var(--space-2);margin-top:var(--space-2)}
.gallery-thumb{border-radius:var(--radius-input);box-shadow:var(--shadow-soft);border:2px solid transparent;transition:border-color var(--transition);cursor:pointer}
.gallery-thumb .ph-img{border-radius:0}
.gallery-thumb.is-active{border-color:var(--color-primary)}
.product-summary h1{font-size:clamp(20px,2.6vw,26px);margin-bottom:var(--space-2)}
.product-brandline{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;font-size:13px;color:var(--color-muted);margin-bottom:var(--space-3)}
.product-brandline a{color:var(--color-secondary);font-weight:600}
.stars{display:inline-flex;gap:2px;align-items:center}
.stars svg{width:15px;height:15px;stroke:var(--color-limited-gold);fill:var(--color-limited-gold);flex-shrink:0}
.stars svg.is-empty{fill:none;stroke:var(--color-muted)}
.product-price-box{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4);margin-bottom:var(--space-4)}
.product-price-box .price-current{font-size:24px}
.save-note{font-size:13px;color:var(--color-success);font-weight:600;margin-top:6px}
.attr-group{margin-bottom:var(--space-4)}
.attr-group__label{font-size:13.5px;font-weight:700;color:var(--color-heading);margin-bottom:var(--space-2);display:flex;gap:6px;align-items:center}
.attr-group__label span{color:var(--color-body);font-weight:500}
.attr-options{display:flex;flex-wrap:wrap;gap:var(--space-2)}
.attr-option{min-height:44px;padding:0 var(--space-3);border:1.5px solid #E4DFD6;border-radius:var(--radius-input);background:var(--color-surface);font-size:13.5px;font-weight:600;color:var(--color-heading);display:inline-flex;align-items:center;gap:8px;cursor:pointer;transition:border-color var(--transition),color var(--transition)}
.attr-option:hover{border-color:var(--color-primary)}
.attr-option.is-active{border-color:var(--color-primary);color:var(--color-primary);background:var(--color-primary-tint)}
.attr-option.is-disabled{opacity:.45;pointer-events:none;text-decoration:line-through}
.attr-option .swatch-dot{width:18px;height:18px}
.buy-row{display:flex;gap:var(--space-2);align-items:stretch;margin-bottom:var(--space-3);flex-wrap:wrap}
.qty{display:inline-flex;align-items:center;border:1.5px solid #E4DFD6;border-radius:var(--radius-input);background:var(--color-surface);height:48px;flex-shrink:0}
.qty button{width:42px;height:100%;display:flex;align-items:center;justify-content:center;color:var(--color-heading);font-size:18px;font-weight:700}
.qty button:hover{color:var(--color-primary)}
.qty input{width:46px;height:100%;min-height:0;border:none;text-align:center;font-weight:700;color:var(--color-heading);background:transparent;padding:0}
.buy-row .btn-primary{flex:1;min-width:180px}
.buy-row .icon-btn{border:1.5px solid #E4DFD6;width:48px;height:48px;border-radius:var(--radius-input)}
/* Stock line: a short inline status row, icon sized to the text. */
.stock-line{display:inline-flex;align-items:center;gap:8px;font-size:13.5px;font-weight:600;margin-bottom:var(--space-3)}
.product-usp{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-2);margin-top:var(--space-4)}
.usp-item{display:flex;align-items:center;gap:10px;background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-3);font-size:13px;color:var(--color-body)}
.usp-item svg{width:20px;height:20px;stroke:var(--color-secondary);flex-shrink:0}
.product-tabs{margin-top:var(--space-7)}
.tab-nav{display:flex;gap:var(--space-2);border-bottom:1px solid #EDE7DD;margin-bottom:var(--space-4);overflow-x:auto;scrollbar-width:none}
.tab-nav::-webkit-scrollbar{display:none}
.tab-btn{padding:var(--space-3) var(--space-4);font-weight:700;font-size:14.5px;color:var(--color-body);border-bottom:2px solid transparent;white-space:nowrap;transition:color var(--transition),border-color var(--transition)}
.tab-btn.is-active{color:var(--color-primary);border-bottom-color:var(--color-primary)}
.tab-panel{display:none}
.tab-panel.is-active{display:block}
.spec-table{width:100%;border-collapse:collapse;font-size:14px;background:var(--color-surface);border-radius:var(--radius-card);overflow:hidden;box-shadow:var(--shadow-soft)}
.spec-table th{background:var(--color-secondary-tint);color:var(--color-heading);padding:12px var(--space-3);text-align:right;font-weight:700;width:34%}
.spec-table td{padding:12px var(--space-3);border-top:1px solid #EDE7DD;color:var(--color-body)}
.review-item{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4);margin-bottom:var(--space-3)}
.review-head{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;margin-bottom:var(--space-2)}
.review-head strong{font-size:14px;color:var(--color-heading)}
.review-date{font-size:12px;color:var(--color-muted);margin-inline-start:auto}

/* ---------- 5. Cart ---------- */
.cart-layout{display:grid;grid-template-columns:1fr 360px;gap:var(--space-5);align-items:start}
.cart-list{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-3)}
.cart-item{display:grid;grid-template-columns:96px 1fr auto;gap:var(--space-3);align-items:center;padding:var(--space-3) 0;border-bottom:1px solid #F2EEE6}
.cart-item:last-child{border-bottom:none}
.cart-item .ph-img{width:96px;height:96px;border-radius:var(--radius-input)}
.cart-item__title{font-size:14.5px;font-weight:600;color:var(--color-heading);margin-bottom:4px}
.cart-item__variant{font-size:12.5px;color:var(--color-muted);display:flex;gap:var(--space-2);flex-wrap:wrap;margin-bottom:var(--space-2)}
.cart-item__actions{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}
.cart-item__remove{font-size:12.5px;color:var(--color-error);font-weight:600}
.cart-item__price{text-align:left;white-space:nowrap}
.cart-summary{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4);position:sticky;top:calc(var(--space-4) + 80px)}
.cart-summary h3{font-size:16px;margin-bottom:var(--space-3)}
.summary-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);font-size:14px;padding:10px 0;border-bottom:1px solid #F2EEE6}
.summary-row:last-of-type{border-bottom:none}
.summary-row--total{font-size:16px;font-weight:700;color:var(--color-heading);border-top:1px solid #EDE7DD;margin-top:var(--space-2);padding-top:var(--space-3)}
.summary-row .discount{color:var(--color-success);font-weight:600}
.coupon-row{display:flex;gap:var(--space-2);margin:var(--space-3) 0}
.coupon-row .field{flex:1}
.ship-progress{background:var(--color-mix-tint);border-radius:var(--radius-card);padding:var(--space-3);font-size:13px;color:var(--color-body);margin-bottom:var(--space-3)}
.ship-progress__bar{height:6px;border-radius:var(--radius-button);background:#E4DFD6;margin-top:var(--space-2);overflow:hidden}
.ship-progress__fill{height:100%;background:var(--color-success);border-radius:var(--radius-button)}

/* ---------- 6. Checkout ---------- */
.checkout-layout{display:grid;grid-template-columns:1fr 360px;gap:var(--space-5);align-items:start}
.checkout-block{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4);margin-bottom:var(--space-4)}
.checkout-block__head{display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-4)}
.step-num{width:28px;height:28px;border-radius:var(--radius-round);background:var(--color-primary);color:#fff;font-size:13px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.checkout-block__head h3{font-size:16px}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)}
.form-grid .field--full{grid-column:1/-1}
.option-row{display:flex;align-items:flex-start;gap:var(--space-3);border:1.5px solid #E4DFD6;border-radius:var(--radius-card);padding:var(--space-3);cursor:pointer;transition:border-color var(--transition),background var(--transition);margin-bottom:var(--space-2)}
.option-row:hover{border-color:var(--color-secondary)}
.option-row.is-active{border-color:var(--color-primary);background:var(--color-primary-tint)}
.option-row.is-disabled{opacity:.5;pointer-events:none}
.option-row input[type="radio"]{width:18px;height:18px;min-height:0;margin-top:3px;accent-color:var(--color-primary);flex-shrink:0;padding:0}
.option-row__body{flex:1}
.option-row__title{font-size:14px;font-weight:700;color:var(--color-heading);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.option-row__desc{font-size:12.5px;color:var(--color-body);margin-top:4px;display:block}
.option-row__price{font-size:13.5px;font-weight:700;color:var(--color-primary);white-space:nowrap}
.mini-cart-item{display:flex;align-items:center;gap:var(--space-2);padding:10px 0;border-bottom:1px solid #F2EEE6;font-size:13px}
.mini-cart-item .ph-img{width:44px;height:44px;border-radius:var(--radius-input);flex-shrink:0}
.mini-cart-item__title{flex:1;color:var(--color-heading)}
.mini-cart-item__qty{color:var(--color-muted);font-size:12px}

/* ---------- 7. Empty state ---------- */
.empty-state{text-align:center;padding:var(--space-7) var(--space-4);background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft)}
.empty-state svg{width:54px;height:54px;stroke:var(--color-muted);margin:0 auto var(--space-3)}
.empty-state h3{font-size:18px;margin-bottom:var(--space-2)}
.empty-state p{font-size:14px;margin-bottom:var(--space-4);max-width:420px;margin-inline:auto}

/* ---------- 8. Long-form text blocks ---------- */
.prose{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-5)}
.prose h2{font-size:20px;margin:var(--space-5) 0 var(--space-3)}
.prose h2:first-child{margin-top:0}
.prose h3{font-size:16px;margin:var(--space-4) 0 var(--space-2)}
.prose p{margin-bottom:var(--space-3);font-size:15px}
.prose ul{margin:0 0 var(--space-3);display:flex;flex-direction:column;gap:8px}
.prose ul li{position:relative;padding-inline-start:18px;font-size:15px}
.prose ul li::before{content:"";position:absolute;inset-inline-start:0;top:11px;width:7px;height:7px;border-radius:var(--radius-round);background:var(--color-primary)}
.prose a{color:var(--color-secondary);font-weight:600}

/* ---------- 9. Responsive — same breakpoints as the approved design ---------- */
@media (max-width:1024px){
  /* Columns are wide enough here that a long list can simply run in
     two columns permanently — no expansion needed, gaps stay equal. */
  .mega-col--long ul{display:grid;grid-template-columns:1fr 1fr;column-gap:var(--space-3);row-gap:10px}
  .shop-layout{grid-template-columns:1fr}
  /* Filter drawer uses the SAME geometry as the approved off-canvas
     menu: anchored to the right edge and pushed off-screen with a
     positive translateX. Anchoring it to the logical end edge in an
     RTL document put it on the left, where translateX(100%) pushed it
     INTO view — that was the panel stuck at the side of the shop page. */
  .filter-panel{position:fixed;top:0;bottom:0;right:0;width:min(360px,88%);z-index:700;border-radius:0;overflow-y:auto;transform:translateX(100%);transition:transform var(--transition);box-shadow:var(--shadow-lift);padding-bottom:calc(var(--space-6) + var(--bottom-bar-height))}
  .filter-panel.is-open{transform:translateX(0)}
  .filter-close{display:flex}
  .filter-open{display:inline-flex}
  .product-grid{grid-template-columns:repeat(3,1fr)}
  .cart-layout,.checkout-layout{grid-template-columns:1fr}
  .cart-summary,.product-gallery{position:static}
  .product-single{gap:var(--space-5)}
}
@media (max-width:768px){
  .product-single{grid-template-columns:1fr}
  .product-grid{grid-template-columns:repeat(2,1fr);gap:var(--space-3)}
  .gallery-thumbs{grid-template-columns:repeat(4,1fr)}
  .form-grid{grid-template-columns:1fr}
  .cart-item{grid-template-columns:72px 1fr;row-gap:var(--space-2)}
  .cart-item .ph-img{width:72px;height:72px}
  .cart-item__price{grid-column:2;text-align:right}
  .product-usp{grid-template-columns:1fr}
  .page-head{padding:var(--space-3) 0}
  .prose{padding:var(--space-4)}
  .shop-toolbar{gap:var(--space-2)}
  .shop-toolbar .field{flex:1;min-width:0}
}
@media (max-width:480px){
  /* Two side by side on phones, not one. */
  .product-grid{grid-template-columns:repeat(2,1fr);gap:var(--space-2)}
  .page-num{min-width:40px;height:40px}
  .acc-panel .acc-panel ul.acc-sub-grid{column-gap:var(--space-2)}
}

/* ---------- 10. Homepage product rows: two cards visible on phones ---
   The approved CSS sized cards at 68% / 74% / 82% of the viewport, so
   roughly one showed at a time. Approved change: show two.           */
/* Card widths at every breakpoint are set once, in section 42, which
   pairs each flex-basis with min-width:0. The min-width values that used
   to be here fought that pairing and lost — but only because section 42
   comes later in the file, which is not a thing worth relying on. */
@media (max-width:480px){
  /* font-size is not set here. The ≤768px block later in the file sets
     the same 13px at equal specificity and wins inside this range too, so
     two declarations only ever gave one answer. min-height is this
     block's own. */
  .product-card__title{min-height:40px}
}

/* ---------- 11. Mega menu: two rows once there are more than six -----
   Nine columns across 1280px leaves ~107px each, too narrow for the
   Persian titles. Past six categories PHP switches the grid to two
   balanced rows and the limited panel spans both.                     */
.mega-col--limited.is-spanning{grid-row:1 / -1}
@media (max-width:1024px){
  /* Three columns here, so the row span would misplace the panel. */
  .mega-col--limited.is-spanning{grid-row:auto}
}

/* ---------- 12. Category grid column count comes from PHP -----------
   Set inline on .category-grid so any number of categories lays out in
   balanced rows instead of leaving a ragged tail.                     */
/* The responsive column counts used to be restated here as well. Section
   39 sets the same property on the same selector with the same
   !important, so these never applied — and having two places claim to
   own the breakpoint is how one of them ends up silently stale. */

/* ---------- 13. Restored token and contrast corrections -------------
   theme.css is frozen, so these land here. Loaded after theme.css, so
   a :root here overrides the one there without touching that file.

   --color-muted was dropped when theme.css was extracted from the
   approved page. It is not a new colour: the approved design system
   (design/approved-original-design-system.html) defines it as #B4ACA2,
   and theme.css line 39 already uses that exact literal for the input
   placeholder. Without the token, thirteen declarations in
   this file were invalid and their text fell back to --color-body.

   --color-success and --color-error are darkened just enough to clear
   WCAG AA 4.5:1 on the tinted backgrounds they sit on. Same hues.

   --color-primary is untouched, deliberately. White on #E2734A is
   3.10:1 and the price on a cream card is 2.87:1; both are below AA
   and both are an accepted exception, recorded in HANDOFF.md. The
   brand orange does not move.                                        */
:root{
  --color-muted:#B4ACA2;
  --color-success:#217750;
  --color-error:#C13636;
  --color-control-border:#9C9382;
}

/* WCAG 1.4.11 asks for 3:1 on the boundary of anything the user
   operates. #E4DFD6 sits at 1.33:1 on white. Applied to controls only
   — dividers, the progress track, the hero dots and the swatch ring
   are decorative and keep the softer border.                         */
.field input,
.field textarea,
.field select,
.chip,
.attr-option,
.qty,
.buy-row .icon-btn,
.option-row,
.btn-outline{border-color:var(--color-control-border)}

/* ============================================================
   BATCH 5 — magazine, contact, legal pages, FAQ, tracking,
   search and 404.

   None of these were wireframed in Phase 1, so every value below
   resolves to a token that already exists in the approved design.
   No new colours, radii, shadows or fonts.
   ============================================================ */

/* ---------- 14. Single magazine post ---------- */
.post-single{max-width:820px;margin-inline:auto}
.post-single__meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);font-size:13px;color:var(--color-muted);margin-bottom:var(--space-4)}
.post-single__meta span{display:inline-flex;align-items:center;gap:6px}
.post-single__meta svg{width:14px;height:14px;stroke:var(--color-muted);flex-shrink:0}
.post-single__hero{margin-bottom:var(--space-4)}
.post-single__hero img{width:100%;border-radius:var(--radius-card)}
.post-single__hero figcaption{margin-top:var(--space-2);font-size:12.5px;color:var(--color-muted);text-align:center}
.post-single__body p{line-height:2}
.post-single__body img{border-radius:var(--radius-card);margin-block:var(--space-3)}
.post-single__body blockquote{border-inline-start:3px solid var(--color-primary);padding-inline-start:var(--space-3);margin-block:var(--space-4);color:var(--color-heading);font-weight:500}
.post-single__tags{margin-top:var(--space-4)}
.post-single__share{display:flex;align-items:center;gap:var(--space-2);margin-top:var(--space-4);font-size:13.5px;color:var(--color-body)}
.post-single__share .icon-btn{width:40px;height:40px;border:1.5px solid var(--color-control-border);border-radius:var(--radius-input)}
.post-single__share .icon-btn svg{width:17px;height:17px}
.post-single__share .icon-btn.is-copied{border-color:var(--color-success);color:var(--color-success)}

/* ---------- 15. Previous / next, reused by 404 and the legal pages ---------- */
.post-nav{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3);max-width:820px;margin-inline:auto}
.post-nav__item{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-3) var(--space-4);display:flex;flex-direction:column;gap:4px;transition:box-shadow var(--transition),transform var(--transition)}
.post-nav__item:hover{box-shadow:var(--shadow-lift);transform:translateY(-2px)}
.post-nav__item span{font-size:12.5px;color:var(--color-muted)}
.post-nav__item strong{font-size:14.5px;color:var(--color-heading);line-height:1.7}
.post-nav__item--prev{text-align:end}

/* ---------- 16. Comments ---------- */
.post-comments{max-width:820px;margin:var(--space-6) auto 0}
.post-comments__title{font-size:18px;margin-bottom:var(--space-3)}
.comment-list{list-style:none;display:flex;flex-direction:column;gap:var(--space-3);margin-bottom:var(--space-5)}
.comment-list .children{list-style:none;margin-top:var(--space-3);padding-inline-start:var(--space-4);display:flex;flex-direction:column;gap:var(--space-3)}
.comment-body{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4)}
.comment-body .avatar{border-radius:var(--radius-round);flex-shrink:0}
.comment-meta{display:flex;align-items:center;gap:10px;margin-bottom:var(--space-2)}
.comment-author{font-weight:600;font-size:14px;color:var(--color-heading)}
.comment-metadata{font-size:12px;color:var(--color-muted)}
.comment-content p{font-size:14.5px;line-height:1.9;color:var(--color-body)}
.comment-reply-link{font-size:13px;font-weight:600;color:var(--color-secondary)}
.comment-form{margin-top:var(--space-3)}
.comment-form .form-submit{grid-column:1/-1}
.comment-awaiting-moderation{display:block;font-size:12.5px;color:var(--color-muted);margin-top:6px}

/* ---------- 17. Contact ---------- */
.contact-layout{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:var(--space-4);align-items:start}
.contact-details{display:flex;flex-direction:column;gap:var(--space-3)}
.contact-details li{display:flex;align-items:flex-start;gap:10px;font-size:14px;color:var(--color-body)}
.contact-details svg{width:16px;height:16px;stroke:var(--color-secondary);flex-shrink:0;margin-top:3px}
.contact-channels{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-2)}
.contact-channels .usp-item{transition:box-shadow var(--transition)}
.contact-channels .usp-item:hover{box-shadow:var(--shadow-lift)}
/* The honeypot. Off-screen rather than display:none — a bot that reads
   CSS skips hidden fields, and a screen reader never reaches it because
   the wrapper carries aria-hidden. */
/* The honeypot was `left:-9999px`. In an LTR page that is harmless —
   overflow past the left edge is unreachable. This document is RTL, where
   the scroll origin is the right edge, so leftward overflow is exactly
   what the scrollbar exposes: the contact page gained ten thousand pixels
   of empty horizontal scroll. Clip it in place instead, the same way
   .screen-reader-text does, so it occupies no space in any direction. */
.parinhall-hp{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- 18. Legal pages: terms, return policy ---------- */
.legal-layout{display:grid;grid-template-columns:minmax(0,240px) minmax(0,1fr);gap:var(--space-4);align-items:start}
.legal-toc{position:sticky;top:var(--space-4);background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4)}
.legal-toc__title{font-size:13px;font-weight:700;color:var(--color-heading);margin-bottom:var(--space-2)}
.legal-toc ul{display:flex;flex-direction:column;gap:10px}
.legal-toc a{font-size:13.5px;color:var(--color-body)}
.legal-toc a:hover{color:var(--color-secondary)}
.legal-updated{margin-top:var(--space-5);padding-top:var(--space-3);border-top:1px solid #EDE7DD;font-size:12.5px;color:var(--color-muted)}
.return-steps{list-style:none;display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-3)}
.return-step{display:flex;gap:var(--space-3);background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4)}
.return-step strong{display:block;font-size:14.5px;color:var(--color-heading);margin-bottom:6px}
.return-step p{font-size:13px;color:var(--color-body);line-height:1.9}

/* ---------- 19. FAQ ---------- */
.faq-group{margin-bottom:var(--space-5)}
.faq-group__title{font-size:18px;color:var(--color-heading);margin-bottom:var(--space-3)}
.faq-list{list-style:none;display:flex;flex-direction:column;gap:var(--space-2)}
.faq-item{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);overflow:hidden}
.faq-q{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);text-align:start;font-weight:600;font-size:14.5px;color:var(--color-heading);line-height:1.8}
.faq-q:hover{color:var(--color-secondary)}
.faq-a__inner{padding:0 var(--space-4) var(--space-4)}
.faq-a__inner p{font-size:14px;line-height:2;color:var(--color-body);margin-bottom:var(--space-2)}
.faq-a__inner p:last-child{margin-bottom:0}
.faq-a__inner a{color:var(--color-secondary);font-weight:600}

/* ---------- 20. Order tracking ---------- */
.track-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-4);max-width:820px;margin-inline:auto}
.track-result__title{font-size:15px;color:var(--color-heading);margin:var(--space-4) 0 var(--space-2)}
.track-result .spec-table td{line-height:1.9}

/* ---------- 21. Search results and 404 ---------- */
.search-page-form{display:flex;gap:var(--space-2);align-items:flex-start;max-width:560px}
.search-page-form .field{flex:1;margin:0}
.empty-state .search-page-form{margin-inline:auto;margin-top:var(--space-4)}

/* ---------- 21b. Nothing may widen the page ----------
   The honeypot above was one way an RTL page grows a horizontal
   scrollbar. The other is client-authored content: a pasted tracking
   URL, a long SKU, a table copied out of Excel, an image dropped in at
   full size. None of those can be caught in review, so the areas that
   accept editor input defend themselves.

   The drawers (.offcanvas, .filter-panel) park off-screen with
   position:fixed, which does not contribute to scrollable overflow —
   they are fine and are deliberately left alone. */
.prose,
.faq-a__inner,
.post-single__body,
.comment-content,
.spec-table td{overflow-wrap:break-word;word-break:break-word}

.prose img,
.faq-a__inner img,
.post-single__body img{max-width:100%;height:auto}

.prose table,
.faq-a__inner table,
.post-single__body table{display:block;max-width:100%;overflow-x:auto}

.prose pre,
.post-single__body pre{max-width:100%;overflow-x:auto;white-space:pre-wrap}

/* ---------- 21c. Generic page ----------
   page.php was missing entirely, so ordinary pages fell to index.php and
   rendered as magazine cards. These are the few styles that file needs. */
.page-hero{margin-bottom:var(--space-4)}
.page-hero img{width:100%;border-radius:var(--radius-card)}

/* ============================================================
   BATCH 6 — my account, product reviews, payment box, and the
   slider controls at a sensible size.
   ============================================================ */

/* ---------- 23. Slider controls, smaller ----------
   44px circles with a 20px chevron dominated the space under the hero.
   These are secondary controls — the dots and the swipe are the primary
   way through. 34px keeps a comfortable target without shouting. */
/* Sizing and layout for these now live together in section 32, so that
   one place decides how big the controls are and where they sit. Leaving
   a 34px rule here and a 28px rule there is how a component ends up with
   three answers to the same question. */
/* border-width was set here as well as in the shorthand in section 0j.
   Folded into that shorthand, which is where a reader looks for it. */
.hero-arrow svg{stroke-width:2}
.hero-controls .hero-dots{gap:6px}
.hero-controls .hero-dot{width:7px;height:7px}
.hero-controls .hero-dot.is-active{width:18px}

/* ---------- 24. My Account ----------
   The templates were written against these class names and the styles
   were never added, so the page rendered as a bare vertical list of
   links with the icons stacked above them. */
.account-layout{display:grid;grid-template-columns:minmax(0,260px) minmax(0,1fr);gap:var(--space-4);align-items:start}
.account-side{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4);position:sticky;top:var(--space-4)}
.account-user{display:flex;align-items:center;gap:12px;padding-bottom:var(--space-3);margin-bottom:var(--space-3);border-bottom:1px solid #EDE7DD}
.account-avatar{flex:0 0 44px;width:44px;height:44px;aspect-ratio:1;border-radius:var(--radius-round);background:var(--color-secondary-tint);display:grid;place-items:center;line-height:0}
.account-avatar svg{width:20px;height:20px;stroke:var(--color-secondary)}
.account-user strong{display:block;font-size:14.5px;color:var(--color-heading)}
.account-user span{font-size:12.5px;color:var(--color-muted);direction:ltr;display:inline-block}
.account-nav{display:flex;flex-direction:column;gap:2px}
.account-nav a{display:flex;align-items:center;gap:10px;padding:11px var(--space-3);border-radius:var(--radius-input);font-size:14px;font-weight:500;color:var(--color-body);transition:background var(--transition),color var(--transition)}
.account-nav a svg{width:17px;height:17px;stroke:currentColor;flex-shrink:0}
.account-nav a:hover{background:var(--color-bg);color:var(--color-heading)}
.account-nav a.is-active{background:var(--color-secondary-tint);color:var(--color-secondary);font-weight:600}
.account-nav a.is-logout{margin-top:var(--space-2);border-top:1px solid #EDE7DD;padding-top:var(--space-3);border-radius:0;color:var(--color-error)}
.account-nav a.is-logout:hover{background:#FBEAEA;color:var(--color-error)}
.woocommerce-MyAccount-content{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-5);min-width:0}
.woocommerce-MyAccount-content h2,
.woocommerce-MyAccount-content h3{font-size:17px;color:var(--color-heading);margin-bottom:var(--space-3)}
.woocommerce-MyAccount-content p{font-size:14.5px;line-height:1.9}
/* .button has to be excluded here as well as .btn. WooCommerce renders
   نمایش as <a class="button">, and this selector outranked the button
   rule below — so an orange button was getting blue link text. */
.woocommerce-MyAccount-content a:not(.btn):not(.button){color:var(--color-secondary);font-weight:600}
.woocommerce-MyAccount-content a.button,
.woocommerce-MyAccount-content a.button:hover,
.woocommerce-message a.button,
.woocommerce-info a.button,
.woocommerce-error a.button{color:#fff}
.woocommerce-MyAccount-content .woocommerce-Address{margin-bottom:var(--space-4)}
.woocommerce-MyAccount-content address{font-style:normal;font-size:14px;line-height:2;color:var(--color-body)}

/* WooCommerce prints its account tables with its own classes. */
.woocommerce-MyAccount-content table{width:100%;border-collapse:collapse;font-size:13.5px}
.woocommerce-MyAccount-content table th{text-align:start;padding:12px var(--space-2);background:var(--color-bg);color:var(--color-heading);font-weight:700;white-space:nowrap}
.woocommerce-MyAccount-content table td{padding:12px var(--space-2);border-top:1px solid #EDE7DD;color:var(--color-body)}
.woocommerce-MyAccount-content table .btn,
.woocommerce-MyAccount-content table .button{white-space:nowrap}

/* ---------- 25. Product reviews ----------
   WooCommerce's own stylesheet is dequeued, and its star glyphs come
   from a webfont that goes with it. These rebuild the rating display and
   the rating input out of a plain character, so nothing depends on that
   font being present. */
#reviews .commentlist{list-style:none;display:flex;flex-direction:column;gap:var(--space-3);margin-bottom:var(--space-5)}
#reviews .commentlist li{background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-4)}
#reviews .comment_container{display:flex;gap:var(--space-3);align-items:flex-start}
#reviews .comment_container img.avatar{width:40px;height:40px;border-radius:var(--radius-round);flex-shrink:0}
#reviews .comment-text{flex:1;min-width:0}
#reviews .woocommerce-review__author{font-weight:600;font-size:14px;color:var(--color-heading)}
#reviews .woocommerce-review__dash{display:none}
#reviews .woocommerce-review__published-date{font-size:12.5px;color:var(--color-muted);display:block;margin-top:2px}
#reviews .description{margin-top:var(--space-2)}
#reviews .description p{font-size:14.5px;line-height:1.9;color:var(--color-body)}

/* Read-only rating: grey stars underneath, gold stars clipped to width. */
.star-rating{position:relative;display:inline-block;width:5.4em;height:1.2em;overflow:hidden;font-size:14px;line-height:1.2;letter-spacing:.08em;direction:ltr;font-family:inherit}
.star-rating::before{content:"★★★★★";position:absolute;inset-inline-start:0;top:0;color:#E4DFD6}
.star-rating span{position:absolute;inset-inline-start:0;top:0;overflow:hidden;padding-top:1.2em;white-space:nowrap}
.star-rating span::before{content:"★★★★★";position:absolute;inset-inline-start:0;top:0;color:var(--color-limited-gold)}

/* Rating input: WooCommerce renders five links whose text is
   "1 of 5 stars" and so on, and relies on its own CSS to turn them into
   stars. Without that CSS the words printed literally across the form,
   which is what the screenshot showed. */
#review_form .comment-form-rating{margin-bottom:var(--space-3)}
#review_form .comment-form-rating label{display:block;font-size:14px;font-weight:600;color:var(--color-heading);margin-bottom:6px}
#review_form p.stars{display:inline-flex;flex-direction:row-reverse;gap:4px;direction:ltr}
#review_form p.stars a{width:26px;height:26px;text-indent:0;font-size:0;position:relative;display:inline-block}
#review_form p.stars a::before{content:"★";position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:24px;line-height:1;color:#E4DFD6;transition:color var(--transition)}
#review_form p.stars a:hover::before,
#review_form p.stars a:hover ~ a::before,
#review_form p.stars.selected a.active::before,
#review_form p.stars.selected a.active ~ a::before{color:var(--color-limited-gold)}
#review_form .comment-form-comment label,
#review_form .comment-form-author label,
#review_form .comment-form-email label{display:block;font-size:14px;font-weight:600;color:var(--color-heading);margin-bottom:6px}
#review_form textarea,
#review_form input[type="text"],
#review_form input[type="email"]{width:100%;min-height:48px;padding:var(--space-2) var(--space-3);border:1.5px solid var(--color-control-border);border-radius:var(--radius-input);background:var(--color-surface);font-family:inherit;font-size:15px;color:var(--color-heading)}
#review_form textarea{min-height:120px;line-height:1.8;resize:vertical}
#review_form textarea:focus,
#review_form input:focus{border-color:var(--color-secondary);box-shadow:0 0 0 3px var(--color-secondary-tint);outline:none}
#review_form .form-submit input[type="submit"],
#review_form .form-submit .submit{display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:0 var(--space-5);border-radius:var(--radius-button);font-weight:600;font-size:15px;background:var(--color-primary);color:#fff;border:0;cursor:pointer;transition:background var(--transition)}
#review_form .form-submit input[type="submit"]:hover{background:var(--color-primary-dark)}
#reviews #comments > h2,
#review_form_wrapper .comment-reply-title{font-size:17px;color:var(--color-heading);margin-bottom:var(--space-3);display:block}
#reviews .woocommerce-noreviews{font-size:14.5px;color:var(--color-body)}

/* ---------- 26. Checkout payment box ----------
   The gateway list arrived with its full description paragraph and a
   privacy blurb, which buried the one thing that matters: the shopper is
   paying by ZarinPal. Keep the gateway, its logo and the terms line;
   drop the prose. */
.woocommerce-checkout-payment ul.payment_methods{list-style:none;display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--space-3)}
.woocommerce-checkout-payment ul.payment_methods li{border:1.5px solid var(--color-control-border);border-radius:var(--radius-card);padding:var(--space-3)}
.woocommerce-checkout-payment ul.payment_methods li label{display:flex;align-items:center;gap:10px;font-weight:600;font-size:14.5px;color:var(--color-heading);cursor:pointer}
.woocommerce-checkout-payment ul.payment_methods li img{max-height:24px;width:auto;margin-inline-start:auto}
.woocommerce-checkout-payment .payment_box{margin-top:var(--space-2);padding:var(--space-3);background:var(--color-secondary-tint);border-radius:var(--radius-input);font-size:13px;color:var(--color-body)}
.woocommerce-checkout-payment .payment_box p:empty{display:none}
.woocommerce-checkout-payment .woocommerce-privacy-policy-text{display:none}
.woocommerce-terms-and-conditions-wrapper{margin-block:var(--space-3);font-size:13.5px}
.woocommerce-terms-and-conditions-wrapper label{display:flex;gap:8px;align-items:flex-start}
/* Full button styling lives in section 45; setting width here as well
   left two owners for one property with the same value. */

.summary-note{font-size:12px;color:var(--color-muted);margin-top:var(--space-2);line-height:1.8}

/* ============================================================
   BATCH 7 — purchase progress, cart table, mega-menu cards,
   and the slider controls rearranged.
   ============================================================ */

/* ---------- 27. Purchase progress strip ---------- */
.checkout-steps{list-style:none;display:flex;align-items:flex-start;justify-content:center;gap:0;margin-bottom:var(--space-5)}
.checkout-step{display:flex;flex-direction:column;align-items:center;gap:8px;position:relative;flex:1;max-width:180px;text-align:center}
/* The connector is drawn by the step, not between steps, so the count of
   steps can change without the line needing to know. */
.checkout-step::before{content:"";position:absolute;top:26px;inset-inline-end:50%;width:100%;height:2px;background:#EDE7DD}
.checkout-step:last-child::before{display:none}
.checkout-step.is-done::before,
.checkout-step.is-current::before{background:var(--color-mix-tint)}
.checkout-step__icon{width:52px;height:52px;border-radius:var(--radius-card);background:var(--color-surface);border:1.5px solid #EDE7DD;display:flex;align-items:center;justify-content:center;position:relative;z-index:1;transition:background var(--transition),border-color var(--transition)}
.checkout-step__icon svg{width:22px;height:22px;stroke:var(--color-muted)}
.checkout-step__label{font-size:13px;color:var(--color-muted);font-weight:500}
.checkout-step.is-done .checkout-step__icon{background:var(--color-mix-tint);border-color:var(--color-mix-tint)}
.checkout-step.is-done .checkout-step__icon svg{stroke:var(--color-mix)}
.checkout-step.is-done .checkout-step__label{color:var(--color-body)}
.checkout-step.is-current .checkout-step__icon{background:var(--color-mix-tint);border-color:var(--color-mix)}
.checkout-step.is-current .checkout-step__icon svg{stroke:var(--color-mix)}
.checkout-step.is-current .checkout-step__label{color:var(--color-heading);font-weight:700}

/* ---------- 28. Stage heading + back link ----------
   align-items, justify-content and gap are NOT set here. Section 45
   stacks this row into a column and answers all three; declaring them
   twice left the earlier values dead and only source order deciding,
   which is the pattern that has cost this project several bug rounds.
   One owner per property. */
.cart-head-row{display:flex;margin-bottom:var(--space-3)}
.cart-head-row__title{font-size:16px;color:var(--color-heading)}
.step-back{display:inline-flex;align-items:center;gap:4px;font-size:13.5px;font-weight:600;color:var(--color-secondary);text-decoration:underline;text-underline-offset:3px}
.step-back svg{width:13px;height:13px;stroke:currentColor}
.step-back:hover{color:var(--color-mix)}

/* ---------- 29. Cart column headings ----------
   Desktop only. The rows underneath stay the approved cards; these line
   up with them rather than turning the cart into a real <table>, so the
   mobile layout is untouched. */
/* The .cart-columns rules that stood here are gone with the markup they
   styled — see woocommerce/cart/cart.php. They laid out four table
   headings above a layout that renders as cards at every width, so on
   screen they were a stray «قیمت واحد / تعداد / قیمت کل» floating over
   the summary box with nothing beneath them. */

/* Minus turns into a delete control at the minimum. Both glyphs are in
   the markup and CSS swaps them, so the icon is our real SVG rather than
   an emoji whose shape depends on the operating system. */
.qty .qty-trash{display:none}
.qty .qty-trash svg{width:15px;height:15px;stroke:currentColor}
.qty button.is-remove{color:var(--color-error)}
.qty button.is-remove .qty-minus{display:none}
.qty button.is-remove .qty-trash{display:inline-flex;align-items:center;justify-content:center}

.summary-saving{color:var(--color-success);font-weight:600}
.summary-saving span:last-child{font-weight:700}

/* ---------- 30. Order received ---------- */
.order-done{text-align:center;background:var(--color-surface);border-radius:var(--radius-card);box-shadow:var(--shadow-soft);padding:var(--space-6) var(--space-4)}
.order-done__mark{width:64px;height:64px;border-radius:var(--radius-round);background:var(--color-mix-tint);display:flex;align-items:center;justify-content:center;margin:0 auto var(--space-3)}
.order-done__mark svg{width:28px;height:28px;stroke:var(--color-success)}
.order-done h2{font-size:20px;color:var(--color-heading);margin-bottom:var(--space-2)}
.order-done p{font-size:14.5px;color:var(--color-body);max-width:460px;margin-inline:auto}

/* ---------- 31. Mega menu as cards ----------
   Each category becomes a card in our own surface style, all top-aligned
   so a tall list no longer stretches its neighbours. The child list still
   opens on hover, as before — only the container changed.
   لیمیتد ادیشن keeps its dark gold card and stays open. */
.mega-menu .container{align-items:start}
.mega-col{background:var(--color-bg);border:1px solid #EFE9DF;border-radius:var(--radius-card);padding:var(--space-3) var(--space-4);align-self:start;transition:background var(--transition),border-color var(--transition),box-shadow var(--transition)}
.mega-col:hover,
.mega-col:focus-within{background:var(--color-surface);border-color:var(--color-control-border);box-shadow:var(--shadow-soft)}
.mega-col .mega-col-title{margin-bottom:0;transition:margin-bottom var(--transition)}
.mega-col:hover .mega-col-title,
.mega-col:focus-within .mega-col-title{margin-bottom:var(--space-2)}
/* The limited card was already distinct; keep it that way and keep it open. */
.mega-col--limited,
.mega-col--limited:hover{background:var(--color-limited-bg);border-color:var(--color-limited-bg)}
.mega-col--limited .mega-col-title,
.mega-col--limited:hover .mega-col-title{margin-bottom:var(--space-2)}

/* ---------- 32. Slider controls: dots above, arrows below ----------
   A flex column would stack the two arrows on top of each other, so this
   is a two-row grid: dots span the full width, the arrows sit side by
   side beneath them. */
/* column-gap is set once, just below section 34 — the arrows sit together
   as one control, not at opposite ends of a var(--space-5) gap. */
/* Back to two columns in 2.9.4. The third was the autoplay pause button,
   which the client asked to remove — it read as a media player parked in
   the middle of a shop. */
.hero-controls{display:grid;grid-template-columns:auto auto;grid-template-areas:"dots dots" "prev next";justify-content:center;align-items:center;row-gap:var(--space-2)}
.hero-controls .hero-dots{grid-area:dots;justify-self:center}
.hero-controls .hero-arrow--prev{grid-area:prev}
.hero-controls .hero-arrow--next{grid-area:next}
.hero-controls .hero-arrow{width:28px;height:28px}
.hero-arrow svg{width:12px;height:12px}

/* ---------- 33. Cart icon in the mobile header ----------
   theme.css hides the cart, wishlist and account icons under 768px and
   leaves only the magnifier. The basket is the one a shopper reaches for
   mid-purchase, so it comes back and sits beside the search. */
@media (max-width:768px){
  .header-icons .icon-btn--cart{display:flex}
}

/* ---------- 36. Mobile: smaller cards ----------
   The category tiles and the product cards were sized so roughly one and
   a half filled the screen — a lot of scrolling to see six categories.
   Shorter tiles and narrower cards put two of each in view at once. */
@media (max-width:768px){
  /* .hero padding-inline is set in section 34, .category-grid gap in
     section 39 — both below this point, so both won anyway. Restating
     them here only made it look like this block decided them. */
  /* Card widths are decided once, in section 42. Nine rules across two
     files were setting this, which is how the layout kept surprising us. */
  .product-card__title{font-size:13px;line-height:1.7}
  .product-card__body{padding:var(--space-2)}
  .price-current{font-size:15px}
}
@media (max-width:480px){
  /* .category-card span's font-size used to be set here too. The
     top-level rule in section 39 is later in the file at the same
     specificity, so this never applied; the ≤768px block below is the one
     that answers small screens. */

}
@media (max-width:360px){

}

@media (max-width:600px){
  /* The My Account single-column rule used to live here. It never took
     effect: the two-column rules it answers are in section 35 below, later
     in the file at the same specificity, so they won at every width and the
     edit-account and address forms stayed two 150px columns on a phone.
     Moved to sit directly after what it overrides. */
  .checkout-steps{gap:0}
  .checkout-step__icon{width:44px;height:44px}
  .checkout-step__icon svg{width:18px;height:18px}
  .checkout-step__label{font-size:11.5px}
  .checkout-step::before{top:22px}
  /* .cart-head-row's stacking used to be repeated here. Section 45 sets
     the same three properties at the top level, further down the file, so
     this copy never reached the screen at any width. */
}

/* ============================================================
   BATCH 8 — hero width, account forms, mobile card sizes.
   ============================================================ */

/* ---------- 34. Hero: contained on desktop ----------
   The slider sat edge to edge while every other section on the page
   stops at --container-max. On a wide monitor that made the banner the
   only thing breaking the page's left and right margin, and the arrows
   ended up marooned in the middle of all that width. */
/* Back to the container width. The extra 120px read as "stretched"
   rather than "prominent" on a wide monitor, and it broke the vertical
   line every other section on the page sits against. Same margin from
   both edges as everything else — that is the ceiling. */
.hero{max-width:var(--container-max);margin-inline:auto;padding-inline:var(--space-4)}
/* This rule sits after the mobile block above, and a later rule with the
   same specificity wins even against one inside a media query — so the
   phone was getting the desktop's 16px side padding. Restated here,
   below, where it actually takes effect. On a phone the banner should
   run the full width of the screen and no further. */
@media (max-width:768px){
  .hero{max-width:100%;padding-inline:0}
  .hero-frame{border-radius:0}
}

/* Arrows sit together as one control, not at opposite ends of a gap. */
.hero-controls{column-gap:6px}

/* ---------- 35. My Account forms ----------
   WooCommerce prints the edit-account and address forms with its own
   markup and no theme classes, so without these the fields rendered as
   bare browser inputs with the labels crushed against them. */
.woocommerce-MyAccount-content form{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)}
.woocommerce-MyAccount-content form .form-row,
.woocommerce-MyAccount-content form p{margin:0;min-width:0}
.woocommerce-MyAccount-content form .form-row-wide,
.woocommerce-MyAccount-content form fieldset,
.woocommerce-MyAccount-content form .clear,
.woocommerce-MyAccount-content form .woocommerce-form-row--wide,
.woocommerce-MyAccount-content form p:last-of-type{grid-column:1/-1}

.woocommerce-MyAccount-content form label{display:block;font-size:13.5px;font-weight:600;color:var(--color-heading);margin-bottom:6px}
.woocommerce-MyAccount-content form label .required{color:var(--color-error);text-decoration:none}
.woocommerce-MyAccount-content form input[type="text"],
.woocommerce-MyAccount-content form input[type="email"],
.woocommerce-MyAccount-content form input[type="tel"],
.woocommerce-MyAccount-content form input[type="password"],
.woocommerce-MyAccount-content form input[type="number"],
.woocommerce-MyAccount-content form select,
.woocommerce-MyAccount-content form textarea{width:100%;min-height:48px;padding:var(--space-2) var(--space-3);border:1.5px solid var(--color-control-border);border-radius:var(--radius-input);background:var(--color-surface);font-family:inherit;font-size:15px;color:var(--color-heading);transition:border-color var(--transition),box-shadow var(--transition)}
.woocommerce-MyAccount-content form textarea{min-height:110px;line-height:1.8;resize:vertical}
.woocommerce-MyAccount-content form input:focus,
.woocommerce-MyAccount-content form select:focus,
.woocommerce-MyAccount-content form textarea:focus{border-color:var(--color-secondary);box-shadow:0 0 0 3px var(--color-secondary-tint);outline:none}
.woocommerce-MyAccount-content form span.description,
.woocommerce-MyAccount-content form em{display:block;font-size:12px;color:var(--color-muted);margin-top:6px;font-style:normal;line-height:1.7}

/* The password fieldset ships with a browser default border. */
.woocommerce-MyAccount-content form fieldset{border:1px solid #EDE7DD;border-radius:var(--radius-card);padding:var(--space-4);margin-top:var(--space-2)}
.woocommerce-MyAccount-content form fieldset legend{font-size:14px;font-weight:700;color:var(--color-heading);padding:0 8px}
.woocommerce-MyAccount-content form fieldset .form-row{margin-bottom:var(--space-3)}
.woocommerce-MyAccount-content form fieldset .form-row:last-child{margin-bottom:0}

/* WooCommerce's submit is a bare <button class="button">. */
.woocommerce-MyAccount-content form button[type="submit"],
.woocommerce-MyAccount-content .button{display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:0 var(--space-5);border:0;border-radius:var(--radius-button);background:var(--color-primary);color:#fff;font-family:inherit;font-weight:600;font-size:15px;cursor:pointer;transition:background var(--transition)}
.woocommerce-MyAccount-content form button[type="submit"]:hover,
.woocommerce-MyAccount-content .button:hover{background:var(--color-primary-dark)}
.woocommerce-MyAccount-content .woocommerce-Addresses{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)}
.woocommerce-MyAccount-content .woocommerce-Address{background:var(--color-bg);border-radius:var(--radius-card);padding:var(--space-4)}
.woocommerce-MyAccount-content .woocommerce-Address-title{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);margin-bottom:var(--space-2)}
.woocommerce-MyAccount-content .woocommerce-Address-title h2,
.woocommerce-MyAccount-content .woocommerce-Address-title h3{margin:0;font-size:15px}
.woocommerce-MyAccount-content .woocommerce-Address-title .edit{font-size:13px;font-weight:600;color:var(--color-secondary)}

/* One column on a phone. This is the same declaration that used to sit in
   the ≤600px block of section 28, where it could never win — both grids it
   answers are declared above at equal specificity. Kept here, immediately
   after them, so the file reads in the order the cascade resolves. */
@media (max-width:600px){
  .woocommerce-MyAccount-content form,
  .woocommerce-MyAccount-content .woocommerce-Addresses{grid-template-columns:1fr}
}

/* ============================================================
   BATCH 9 — WooCommerce notices, mega-menu columns, card sizes.
   ============================================================ */

/* ---------- 37. WooCommerce notices ----------
   WooCommerce's own stylesheet is dequeued, and its notices went with
   it — «به سبد شما افزوده شد» was rendering as a full-bleed bar with a
   hairline border and no colour, no icon, no card. These are the same
   three states as .alert, applied to WooCommerce's class names, sitting
   in the page container instead of spanning the whole viewport. */
.woocommerce-notices-wrapper:empty{display:none}
.woocommerce-message,
.woocommerce-error,
.woocommerce-info,
.wc-block-components-notice-banner{
  display:flex;align-items:flex-start;gap:var(--space-2);
  max-width:var(--container-max);margin:var(--space-3) auto;
  padding:var(--space-3) var(--space-4);
  border:0;border-radius:var(--radius-card);
  font-size:14px;font-weight:500;line-height:1.9;
  list-style:none;box-shadow:var(--shadow-soft)
}
.woocommerce-message{background:var(--color-mix-tint);color:var(--color-success)}
.woocommerce-info,
.wc-block-components-notice-banner{background:var(--color-secondary-tint);color:var(--color-secondary)}
/* gap is 6px here rather than the banners' var(--space-2): an error list
   stacks its lines, and the shared rule's gap was written for a row. One
   owner still — the shared rule sets it for the four banners, this one
   narrows it for the error, and there is no third opinion. */
.woocommerce-error{background:#FBEAEA;color:var(--color-error);flex-direction:column;gap:6px}
.woocommerce-error li{list-style:none}

/* The inline link WooCommerce puts in the message — «مشاهده سبد خرید». */
.woocommerce-message .button,
.woocommerce-info .button,
.woocommerce-error .button{
  margin-inline-start:auto;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  min-height:38px;padding:0 var(--space-4);
  border-radius:var(--radius-button);
  background:var(--color-primary);color:#fff;
  font-size:13.5px;font-weight:600;border:0
}
.woocommerce-message .button:hover{background:var(--color-primary-dark)}
/* Inside a page that already has its own container, do not add another. */
.container .woocommerce-message,
.container .woocommerce-error,
.container .woocommerce-info{margin-inline:0;max-width:none}

/* ---------- 38. Mega menu: limited on the left, 10 per column ---------- */
/* -2/-1 is the last track. In an RTL grid the last track is the leftmost
   column, which is where محصولات ویژه belongs. Auto-placement was putting
   it in the first track — the right edge — because the spanning rule made
   it hunt for the first column with free rows. */
.mega-menu .container .mega-col--limited{grid-column:-2 / -1}
/* grid-row for .is-spanning is set once, in section 11, alongside the
   1024px rule that cancels it. Keeping the pair together is the point. */

/* Ten items fill a column, then a second one starts. --mega-rows comes
   from PHP so the break happens where the template counted it.
   display:grid is required — theme.css sets this list to flex, and a
   flex container ignores grid-auto-flow and grid-template-rows entirely,
   so without it none of the rest of this rule would do anything. */
.mega-col ul{display:grid;grid-template-columns:repeat(var(--mega-cols,1),minmax(0,1fr));column-gap:var(--space-4);row-gap:10px;align-content:start}
.mega-col--two:hover,
.mega-col--two:focus-within{z-index:2}
.mega-col--two:hover ul,
.mega-col--two:focus-within ul{max-height:520px}
.mega-more{color:var(--color-primary)!important;font-weight:700}

/* ---------- 39. Category cards, shorter ----------
   1:1.1 made every tile taller than it was wide, so eight categories
   filled the screen twice over. Landscape reads as a tile, not a poster. */
/* Four to a row, with room to breathe.

   auto-fill was the wrong tool: it packs in as many tiles as will fit,
   so the count changed with the window and the last row was left ragged.
   A fixed four is predictable and lines the rows up under each other.

   The column count is written inline on .category-grid by PHP and an
   inline style beats a stylesheet rule, so this needs !important — the
   same override the responsive block below already uses. */
/* Ratio moved to .category-card .card-media in section 42 — one owner. */
.category-card span{padding:10px var(--space-2);font-size:13px}

@media (min-width:1025px){
  .category-grid{grid-template-columns:repeat(4,minmax(0,1fr))!important;gap:var(--space-4)}
}
/* iPad and small laptops: three across, still with real spacing. */
@media (min-width:769px) and (max-width:1024px){
  .category-grid{grid-template-columns:repeat(3,minmax(0,1fr))!important;gap:var(--space-3)}
}
@media (max-width:768px){
  .category-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:var(--space-3)}
  .category-card span{padding:8px var(--space-2);font-size:12.5px}
}

/* ---------- 39b. Filter toggles ----------
   Two faults, feeding each other.

   The checkbox was hidden with .screen-reader-text, which positions it
   absolutely and clips it to a 1px box. A native checkbox is a replaced
   element and does not always honour `clip`, so it escaped its clip
   rectangle and drew itself as a stray blue tick at the top of the
   panel — visible in the shop sidebar.

   And the switch had two owners: clicking the <label> flips the checkbox
   natively, while pages.js also toggled .is-on. Two sources of truth for
   one control, so a click could set the checkbox on and the class off,
   and the toggle appeared dead even though the filter had applied.

   Now the checkbox is hidden without clip, and the switch reads its
   state straight from :checked. One source of truth, no script. */
.switch-row input[type="checkbox"]{
  position:absolute;opacity:0;width:1px;height:1px;
  margin:0;padding:0;border:0;pointer-events:none;appearance:none;-webkit-appearance:none
}
.switch-row input[type="checkbox"]:checked ~ .switch{background:var(--color-secondary)}
/* +18px, not −18px. translateX is a physical direction — it does not
   flip with `direction: rtl` the way inset-inline-* does. The knob parks
   at inset-inline-end:3px, which in a right-to-left page is the LEFT
   edge of the 42px pill, so translating it by −18px pushed it further
   left and straight out of the track: switch on, knob gone. It has to
   travel right, towards inline-start, to land on the far side. */
.switch-row input[type="checkbox"]:checked ~ .switch::after{transform:translateX(18px)}
.switch-row input[type="checkbox"]:focus-visible ~ .switch{outline:2px solid var(--color-secondary);outline-offset:2px}

/* Colour swatches, same pattern. theme.css styles .filter-swatch.is-active
   with a ring; that class is no longer printed, so the ring is restated
   here off :checked. */
.swatch-label{display:inline-flex;cursor:pointer;position:relative}
.swatch-label input[type="checkbox"]{
  position:absolute;opacity:0;width:1px;height:1px;
  margin:0;padding:0;border:0;pointer-events:none;appearance:none;-webkit-appearance:none
}
.swatch-label input[type="checkbox"]:checked ~ .filter-swatch{box-shadow:0 0 0 2px var(--color-secondary)}
.swatch-label input[type="checkbox"]:focus-visible ~ .filter-swatch{outline:2px solid var(--color-secondary);outline-offset:3px}

/* The avatar was drawing as an ellipse: it sits in a flex row and a bare
   width/height can still be stretched by the row's sizing. A flex basis
   plus aspect-ratio pins it square whatever the row does.

   The glyph also sat high inside it. An inline <svg> keeps its baseline,
   and the descender space below the baseline pushed the artwork up. grid
   with place-items:center ignores baselines entirely, and line-height:0
   removes the strut that caused it. */
/* .account-avatar is defined once, in the My Account section above. */
.account-avatar svg{display:block}

/* ---------- 39c. Space under the hero ----------
   .section carries 64px of top padding, which is right between two
   content sections but too much directly under the slider — the dots and
   arrows already add their own space, so the gap read as a hole. Only
   the section immediately after the hero is tightened. */
.hero + .section{padding-top:var(--space-4)}
@media (max-width:768px){
  .hero + .section{padding-top:var(--space-3)}
}

/* ---------- 39d. Product request ---------- */
.product-request{padding-bottom:var(--space-7)}
.request-card{
  display:grid;grid-template-columns:minmax(0,0.9fr) minmax(0,1.1fr);gap:var(--space-5);
  background:var(--color-surface);border-radius:var(--radius-card);
  box-shadow:var(--shadow-soft);padding:var(--space-5);align-items:start
}
.request-card__icon{
  width:48px;height:48px;border-radius:var(--radius-card);
  background:var(--color-secondary-tint);display:grid;place-items:center;
  margin-bottom:var(--space-3)
}
.request-card__icon svg{width:22px;height:22px;stroke:var(--color-secondary);display:block}
.request-card__intro h2{font-size:20px;color:var(--color-heading);margin-bottom:var(--space-2);line-height:1.8}
.request-card__intro p{font-size:14.5px;color:var(--color-body);line-height:2}
.request-card__call{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin-top:var(--space-3);padding-top:var(--space-3);
  border-top:1px solid #EDE7DD;font-size:13.5px
}
.request-card__call svg{width:15px;height:15px;stroke:var(--color-secondary);flex-shrink:0}
.request-card__call a{color:var(--color-secondary);font-weight:700}
.request-card__form .field__msg{display:block;margin-top:var(--space-2);color:var(--color-muted)}
.request-card__form .btn{width:100%}

@media (max-width:900px){
  .request-card{grid-template-columns:1fr;gap:var(--space-4);padding:var(--space-4)}
}

/* ---------- 39e. Trust badges ----------
   theme.css gives the slot a dashed box and a fixed 90×90. That frame is
   a placeholder telling the client where to paste the code — once a real
   badge is in, the box is just a cage around someone else's logo. The
   dashed version stays for empty slots so the hint is still there. */
.trust-badge-slot.has-badge{
  width:auto;height:auto;min-width:0;
  background:none;border:0;padding:0
}
/* No max-width here. ZarinPal's own snippet sets `#zarinpal img{width:80px}`
   and Enamad's does the same — whichever number you put in that code is
   the one that should win. Capping it from the theme as well meant two
   rules deciding one size, and a badge scaled twice is a badge that
   looks soft. The slot just holds them; their code sizes them. */
/* No width cap here. The badge snippet sets its own size (ZarinPal's
   sets width:80px) and a cap in the theme would silently override the
   client's own code. Only stop it overflowing. */
.trust-badge-slot.has-badge img{max-width:100%;height:auto;display:block}

/* ---------- Badge hit area: one rule, one answer ----------

   Three versions of this rule had accumulated here across separate
   edits, plus two different values for .trust-badges gap. Only the last
   of each was doing anything; the rest were dead weight that made the
   real behaviour impossible to read. Consolidated.

   The problem being solved: a 60px logo is a 60px target. ZarinPal's
   markup wraps it in a bare inline <a>, and theme.css sets
   img{display:block} — a block image inside an inline anchor leaves the
   anchor generating a short inline box that does not even wrap its own
   picture, so the hit area ended up smaller than the logo and worked
   only near the centre.

   Making the anchor a flex box fixes the containment. Padding then
   extends the target outward, and the matching negative margin pulls the
   layout back — the target grows to 92px, the design does not move a
   pixel. Padding goes on the anchor, never the image: theme.css sets
   box-sizing:border-box globally, so padding on the <img> would eat into
   its 60px and shrink the logo instead.

   Applies to Enamad as well — same <a><img> shape, same problem, and
   neither pasted snippet needs touching. */
.trust-badge-slot.has-badge a{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;
  padding:16px;margin:-16px;
  border-radius:var(--radius-input);
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:background var(--transition)
}
.trust-badge-slot.has-badge a:hover{background:rgba(255,255,255,.08)}
.trust-badge-slot.has-badge a:focus-visible{
  background:rgba(255,255,255,.12);
  outline:2px solid var(--color-limited-gold);outline-offset:0
}

/* A badge code that puts the handler on the <img> with no anchor around
   it. content-box lets the padding grow the target outward rather than
   shrinking the artwork. */
.trust-badge-slot.has-badge > img{
  box-sizing:content-box;padding:16px;margin:-16px;
  cursor:pointer;border-radius:var(--radius-input)
}
.trust-badge-slot.has-badge > img:hover{background:rgba(255,255,255,.08)}

/* The negative margins would let two adjacent targets meet, so the row
   gap has to cover them. This is the only .trust-badges gap in the file. */
.trust-badges{align-items:center;flex-wrap:wrap;gap:calc(var(--space-4) + 32px)}

/* ---------- 40. Address book ---------- */
.address-intro{font-size:14px;color:var(--color-body);margin-bottom:var(--space-4)}
.address-book{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--space-3)}
.address-card{background:var(--color-bg);border:1px solid #EDE7DD;border-radius:var(--radius-card);padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-3)}
.address-card.is-empty{border-style:dashed;border-color:var(--color-control-border)}
.address-card__head{display:flex;align-items:flex-start;gap:10px}
.address-card__icon{width:36px;height:36px;border-radius:var(--radius-round);background:var(--color-secondary-tint);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.address-card__icon svg{width:16px;height:16px;stroke:var(--color-secondary)}
.address-card h3{font-size:15px;color:var(--color-heading);margin:0}
.address-card__hint{font-size:12px;color:var(--color-muted);margin-top:3px;line-height:1.7}
.address-card address{font-style:normal;font-size:14px;line-height:2;color:var(--color-body);margin:0}
.address-card__empty{font-size:13.5px;color:var(--color-muted);margin:0}
.address-card .btn{align-self:flex-start;margin-top:auto}
.address-card .btn svg{width:15px;height:15px}

/* ---------- 41b. Nothing scrolls sideways, on any screen ----------
   Two separate causes were at work.

   First, theme.css only swaps the desktop nav for the hamburger below
   768px. Between 769 and 1024 the full nav — eight Persian items plus
   four icons plus the logo — was still rendering and simply did not fit,
   so an iPad got a horizontal scrollbar and a header cut off at the
   edge. The switch happens at 1024 now: a tablet gets the same header a
   phone gets, which fits by construction.

   Second, a belt-and-braces clip. overflow-x:clip, not hidden — hidden
   turns the element into a scroll container and silently kills
   position:sticky, which the account sidebar and the legal contents list
   both rely on. clip does not. */
html{overflow-x:clip}
body{overflow-x:clip;max-width:100%}

@media (max-width:1024px){
  /* The top bar stays, but only the middle message.
     theme.css hides the whole strip below 1024px, and this file repeated
     the same declaration — two owners saying the same thing, which is
     how it stopped being obvious that the bar was gone at all. It is one
     owner now, and it keeps the one line worth the space: the membership
     offer. The two free-shipping thresholds are the ones a shopper meets
     again in the cart, where the numbers actually mean something; on a
     phone they cost three lines of screen to say it early. */
  /* max-height has to clear two lines, because theme.css animates this
     strip closed on scroll by driving max-height to 0 — a value too
     small to fit the text would clip it permanently rather than only
     while scrolled. Two lines at 11.5px/1.45 is about 34px of text plus
     10px of padding; 56px leaves room without letting a long message
     grow without limit. */
  .header-top{display:block;font-size:11.5px;padding:5px 0;max-height:56px}
  .header-top .container{display:block;padding-inline:var(--space-3)}
  .header-top .ht-right,
  .header-top .ht-left{display:none}
  /* Wraps rather than truncates. The current message runs to about 58
     characters, which cannot fit one 390px line at any size a person
     would want to read, and clipping it costs «هدیه بگیرید» — the half
     that says what the shopper gets. Two lines, then clamp. */
  .header-top .ht-center{
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
    text-align:center;font-weight:600;line-height:1.45;overflow:hidden
  }
  .main-nav{display:none}
  .header-icons .icon-btn--account,
  .header-icons .icon-btn--wishlist{display:none}
  .header-icons .icon-btn--cart{display:flex}
  .header-main .container{position:relative;gap:var(--space-2);padding:0 var(--space-3)}
  .hamburger{display:flex;order:1;z-index:2}
  .brand{order:2;position:absolute;left:50%;transform:translateX(-50%)}
  .header-icons{order:3;margin-inline-start:auto;z-index:2}
  .header-main{padding:10px 0}
}

/* ---------- 41c. Real photos in fixed-ratio boxes ----------
   One uploaded image made the whole site look broken, and the cause is a
   single missing declaration.

   WordPress prints width="1000" height="1000" on every image it renders.
   theme.css line 4 says `img{max-width:100%}` and stops there — so the
   browser shrank the width to fit the card and kept the height at
   1000px. A square photo therefore rendered as a tall column, dragging
   the product row, the category grid and the shop listing out of shape
   around it. The placeholders looked right because they are <div>s with
   no height attribute to honour.

   `height:auto` is the standard companion to `max-width:100%`. With it,
   the aspect-ratio already on .ph-img decides the shape and object-fit
   crops the photo to fill rather than squashing it.

   The hero is deliberately untouched — .hero-slide img.ph-img sets its
   own height and is more specific, so the slider keeps the behaviour you
   already signed off. */
img{height:auto}

/* ---------- 42. Media boxes: the actual root fix ----------
   Setting height:auto and an aspect-ratio on the <img> itself was still
   the wrong shape of solution. The image remained *in the document
   flow*, so its intrinsic dimensions still had a say in how tall its
   parent grew, and any rule that failed to apply — a more specific
   selector somewhere, an attribute the browser preferred — put a
   thousand-pixel photo back into the layout.

   The reliable pattern is to take the image out of the flow entirely.
   .card-media is a fixed-ratio box; the image inside is absolutely
   positioned to fill it. An absolutely positioned element contributes
   nothing to its parent's size, so the card's height is decided by the
   ratio and by nothing else. Upload a panorama, a portrait, a 5000px
   scan — the grid does not move.

   object-fit:cover crops to fill rather than squashing, and
   object-position:center takes the crop from the middle. */
.card-media{position:relative;display:block;overflow:hidden;background:var(--color-bg)}
.card-media > .ph-img,
.card-media > img,
.card-media > picture{position:absolute;inset:0;width:100%;height:100%;margin:0;border-radius:0;aspect-ratio:auto;object-fit:cover;object-position:center}
.card-media > picture img{width:100%;height:100%;object-fit:cover}

/* The ratio each context wants. One place, one answer. */
.product-card__link.card-media{aspect-ratio:1/1}
.category-card .card-media{aspect-ratio:1/0.66}
.post-card .card-media{aspect-ratio:16/10}

/* The gallery frames get the same treatment — they had no ratio at all,
   so `height:100%` on the image was resolving against an auto-height
   parent, which is no constraint whatsoever. */
.gallery-main,
.gallery-thumb{position:relative;overflow:hidden;aspect-ratio:1/1}
.gallery-main > .ph-img,
.gallery-main > img,
.gallery-thumb > .ph-img,
.gallery-thumb > img{position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto;object-fit:cover;border-radius:0}
.gallery-badges{z-index:3}

@media (max-width:768px){
  .category-card .card-media{aspect-ratio:1/0.62}
}

/* ============================================================
   42. LAYOUT CANNOT BE BROKEN BY AN IMAGE — the root fix
   ============================================================

   Last version I fixed the wrong half of this. `height:auto` stopped a
   photo being stretched, but it did not stop a photo making its
   container wider than the layout allows. That is what was still
   breaking the phone.

   The mechanism, because it is worth knowing — it catches everyone once:

   Grid and flex children have `min-width: auto` by default, not zero.
   "Auto" means *do not shrink below my content*. An image is content,
   and a 1000px image is 1000px of it. So the card refuses to be 200px
   wide, the flex item grows to 1000px, the row overflows, and the page
   looks broken. Placeholders never triggered it because a <div> has no
   intrinsic width to defend.

   There is a second half. A flex item sized only with `min-width: 52%`
   has no *definite* width — min-width is a floor, not a size. So
   `width: 100%` on the image inside has nothing to resolve against, the
   browser falls back to the image's intrinsic width, and that feeds
   straight back into the flex item. `flex: 0 0 52%` gives a definite
   basis and the circle is broken.

   Both fixes below. After this, an image of any dimensions can be
   uploaded and the layout holds. */

/* 1. Nothing that holds an image may refuse to shrink. */
.product-grid > *,
.product-carousel > *,
.category-grid > *,
.magazine-grid > *,
.cart-layout > *,
.shop-layout > *,
.checkout-layout > *,
.account-layout > *,
.contact-layout > *,
.legal-layout > *,
.address-book > *,
.request-card > *,
.gallery-thumbs > *{min-width:0;min-height:0}

/* 2. Carousel cards get a definite width, not just a floor. One rule per
      breakpoint, in one place, so there is a single answer to "how wide
      is a card". */
@media (max-width:1024px){
  .product-carousel .product-card{flex:0 0 calc(33.333% - var(--space-3));min-width:0}
}
@media (max-width:768px){
  .product-carousel .product-card{flex:0 0 calc(46% - var(--space-3));min-width:0}
}
@media (max-width:480px){
  .product-carousel .product-card{flex:0 0 calc(52% - var(--space-3));min-width:0}
}
@media (max-width:360px){
  .product-carousel .product-card{flex:0 0 calc(58% - 6px);min-width:0}
}

/* 3. The image itself: fills the box its container defines, never sets
      the box. object-fit crops; it never distorts. */
.product-card img,
.category-card img,
.post-card img,
.gallery-main img,
.gallery-thumb img{width:100%;height:auto;max-width:100%;object-fit:cover;object-position:center}

/* Cart thumbnails already have a fixed box from .cart-item .ph-img, so
   they only need the crop — setting width here would fight that rule. */
.mini-cart-item img,
.cart-item img{object-fit:cover;object-position:center;max-width:100%}

/* Anything that can be wider than its box, told not to be.

   .container is deliberately NOT in this list. It carries
   max-width:var(--container-max) from theme.css, and putting
   max-width:100% on it here overrode that — every section on the site
   stretched to the full width of the monitor. The guard is for content
   that has no width of its own, not for the layout wrapper that does. */
img,video,iframe,table,pre{max-width:100%}

/* ---------- 41. Tablet: the 769–1024 gap ----------
   Every layout below jumped straight from the desktop rule to the phone
   rule, so an iPad got the desktop grid squeezed into 800px. These give
   that range its own answer. */
@media (min-width:769px) and (max-width:1024px){
  .contact-layout,
  .legal-layout,
  .account-layout{grid-template-columns:minmax(0,220px) minmax(0,1fr)}
  .return-steps{grid-template-columns:1fr 1fr}
  .address-book{grid-template-columns:1fr}
  .woocommerce-MyAccount-content form{grid-template-columns:1fr 1fr}
  .woocommerce-MyAccount-content .woocommerce-Addresses{grid-template-columns:1fr}

  .checkout-step__icon{width:48px;height:48px}
  .hero{padding-inline:var(--space-3)}
}

/* ---------- 22. Batch 5 responsive ---------- */
@media (max-width:900px){
  .contact-layout,
  .legal-layout,
  .account-layout{grid-template-columns:1fr}
  .legal-toc,
  .account-side{position:static}
  .return-steps{grid-template-columns:1fr}
  /* Wrapped pills of different widths left a ragged four-row block that
     pushed the actual page off the first screen. A two-column grid gives
     every item the same footprint, so it reads as one tidy panel. */
  .account-side{padding:var(--space-3)}
  .account-nav{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .account-nav a{
    padding:12px 10px;border:1px solid var(--color-control-border);
    border-radius:var(--radius-input);font-size:12.5px;font-weight:600;
    justify-content:flex-start;gap:8px;min-height:46px;line-height:1.4
  }
  .account-nav a svg{width:16px;height:16px}
  .account-nav a.is-active{border-color:var(--color-secondary)}
  .account-nav a.is-logout{grid-column:1/-1;margin-top:2px;border-top:1px solid var(--color-control-border);padding-top:12px;border-radius:var(--radius-input);justify-content:center}
  .account-user{padding-bottom:var(--space-2);margin-bottom:var(--space-3)}

  .woocommerce-MyAccount-content{padding:var(--space-3)}
  /* Order tables are five columns of Persian text in 360px. Scrolling a
     table sideways on a phone is how a row gets missed, so each row
     becomes its own stacked card with the header as a label. */
  .woocommerce-MyAccount-content table thead{display:none}
  .woocommerce-MyAccount-content table,
  .woocommerce-MyAccount-content table tbody,
  .woocommerce-MyAccount-content table tr{display:block;width:100%}
  /* td is given display:flex just below — listing it here too set a value
     that never survived to the next rule. */
  .woocommerce-MyAccount-content table td{width:100%}
  .woocommerce-MyAccount-content table tr{
    background:var(--color-bg);border-radius:var(--radius-card);
    padding:var(--space-3);margin-bottom:var(--space-2)
  }
  .woocommerce-MyAccount-content table td{
    display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);
    border:0;padding:5px 0;text-align:start
  }
  .woocommerce-MyAccount-content table td::before{
    content:attr(data-title);font-weight:700;color:var(--color-heading);
    font-size:12.5px;flex-shrink:0
  }
  .woocommerce-MyAccount-content table td.woocommerce-orders-table__cell-order-actions{
    justify-content:stretch;padding-top:var(--space-2)
  }
  .woocommerce-MyAccount-content table td.woocommerce-orders-table__cell-order-actions::before{display:none}
  .woocommerce-MyAccount-content table td .button{width:100%}
}
@media (max-width:600px){
  .post-nav{grid-template-columns:1fr}
  .post-nav__item--prev{text-align:start}
  .contact-channels{grid-template-columns:1fr}
  .search-page-form{flex-direction:column}
  .search-page-form .btn{width:100%}
}

.checkout-gateway-note{font-size:12.5px;color:var(--color-muted);text-align:center;line-height:1.9}

/* ---------- 43. Sign-in card and account dashboard ------------------
   FOUND BY REBUILDING THE DESIGN REFERENCE.

   Every class below was already in the templates and had no rule
   anywhere. woocommerce/myaccount/form-login.php has been emitting
   .auth-card since Batch 4 (and, until 2.9.3, the code-field classes
   that went out with the theme's own sign-in card), and
   myaccount/dashboard.php has been emitting .account-card, .stat-grid
   and .data-table — none of them styled. The sidebar beside them was
   styled, which is why nobody noticed: the page looked half-finished
   rather than obviously broken.

   The consequence was not cosmetic. OTP is the only way a customer
   signs in to this shop, and the six code boxes were rendering as six
   full-width inputs stacked down the page. That is the front door.

   How this was missed: verify.py checks that every function a template
   calls exists, and phpcheck.py checks that every file parses. Neither
   has any idea whether a class the markup uses has a rule. Nothing was
   broken in a way a scanner could see. It took writing an honest mockup
   — one that had to use the real class names — to surface it.

   Values below are tokens that already exist. No new colours, no new
   radii, no new shadows.                                             */

/* --- Sign-in --------------------------------------------------- */
.auth-wrap{max-width:460px;margin-inline:auto}
.auth-card{background:var(--color-surface);border-radius:var(--radius-card);
  box-shadow:var(--shadow-soft);padding:var(--space-5)}
.auth-card__head{margin-bottom:var(--space-3)}
.auth-card__head h2{font-size:20px;margin-bottom:4px}
.auth-card .body-text{font-size:14px;line-height:1.9;margin-bottom:var(--space-4)}
.auth-card .field{margin-bottom:var(--space-3)}
.input-text{width:100%;min-height:48px;padding:var(--space-2) var(--space-3);
  border:1.5px solid var(--color-control-border);border-radius:var(--radius-input);
  background:var(--color-surface);font-family:inherit;font-size:15px;
  color:var(--color-heading);transition:border-color var(--transition),box-shadow var(--transition)}
.input-text:focus{border-color:var(--color-secondary);
  box-shadow:0 0 0 3px var(--color-secondary-tint);outline:none}
.consent-row{display:flex;align-items:flex-start;gap:10px;font-size:13px;
  line-height:1.9;color:var(--color-body);margin-bottom:var(--space-4);cursor:pointer}
.consent-row input{width:18px;height:18px;flex-shrink:0;margin-top:3px;accent-color:var(--color-secondary)}

/* The six-box code field, its countdown row and its phone override used to
   sit here. They dressed the theme's own sign-in card, which was deleted in
   2.9.3 — the PARINHALL SMS plugin owns sign-in and ships its own
   stylesheet for it, on its own phs- classes. Nothing in the theme or the
   plugin emits .otp-inputs, .otp-digit, .auth-meta or .auth-timer any more,
   so the rules went with the markup. .consent-row and .auth-resend below
   stay: form-login.php still emits both. */
.auth-resend,.auth-alt button{font:inherit;font-size:13px;font-weight:600;cursor:pointer;
  background:none;border:0;color:var(--color-secondary);padding:0}
.auth-resend:hover,.auth-alt button:hover{color:var(--color-heading)}
.auth-alt{text-align:center;font-size:13px}

/* --- Account dashboard ------------------------------------------ */
.account-card{background:var(--color-surface);border-radius:var(--radius-card);
  box-shadow:var(--shadow-soft);padding:var(--space-4);margin-bottom:var(--space-4)}
.account-card:last-child{margin-bottom:0}
.account-card__head{display:flex;align-items:center;justify-content:space-between;
  gap:var(--space-3);flex-wrap:wrap;margin-bottom:var(--space-3)}
.account-card__head h2{font-size:17px;margin:0}
.account-card .body-text{font-size:14px;line-height:1.9;margin:0}

.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:var(--space-3)}
.stat-box{background:var(--color-bg);border-radius:var(--radius-input);
  padding:var(--space-3);text-align:center}
.stat-box strong{display:block;font-size:24px;font-weight:700;color:var(--color-heading);line-height:1.3}
.stat-box span{font-size:12.5px;color:var(--color-body)}

/* A table on a phone is the classic overflow: it cannot wrap, so it
   pushes the page sideways. Scrolling the table instead of the document
   is the fix — see section 41b, which is what this pairs with. */
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
.data-table{width:100%;border-collapse:collapse;font-size:13.5px;min-width:460px}
.data-table th,.data-table td{padding:12px var(--space-2);text-align:right;
  border-bottom:1px solid #EDE7DD;vertical-align:middle}
.data-table th{font-size:12.5px;font-weight:700;color:var(--color-muted);
  white-space:nowrap;border-bottom-width:1.5px}
.data-table tr:last-child td{border-bottom:0}
.data-table td.num{direction:ltr;text-align:right;font-weight:600;color:var(--color-heading)}
.data-table .badge{white-space:nowrap}

/* The chosen variation, printed beside its attribute label. */
.attr-group__value{font-weight:400;color:var(--color-body);font-size:13px}

@media (max-width:480px){
  .auth-card{padding:var(--space-4)}
}

/* The order-summary sentence on My Account → a single order.

   WooCommerce marks the order number, date and status with <mark>, and
   normally its own stylesheet neutralises the element. inc/enqueue.php
   dequeues woocommerce-general, -layout and -smallscreen, so nothing was
   left to do it: three words rendered on the browser's default bright
   yellow, in the middle of a cream RTL page. Same defect class as the one
   section 43 above was written to fix, in a template added after it. */
.order-intro{font-size:15px;line-height:2;color:var(--color-body);margin-bottom:var(--space-4)}
.order-intro mark{background:none;color:var(--color-heading);font-weight:700;padding:0}
.order-intro .order-status{color:var(--color-secondary)}

/* ---------- 44. Compare table, and anchors under the sticky header --
   Two more gaps from the same sweep as section 43.

   .contact-aside and .faq-a were also on the list of classes with no
   rules, and were deliberately left alone: .contact-layout already
   places the aside, and .acc-panel already animates the FAQ answer.
   They are semantic hooks, not missing styles. Adding rules "to be
   safe" is how a stylesheet grows a second owner for a property.

   These two are different — they are genuinely absent.               */

/* --- The compare page -------------------------------------------
   page-compare.php has emitted these four classes since Batch 4 with
   nothing styling them, so the comparison rendered as a browser
   default table: no borders, no padding, and — because a table cannot
   wrap — four columns of product pushing the page sideways on a phone. */
.compare-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;
  background:var(--color-surface);border-radius:var(--radius-card);
  box-shadow:var(--shadow-soft);padding:var(--space-3)}
.compare-table{width:100%;border-collapse:collapse;font-size:13.5px;min-width:620px}
.compare-table th,.compare-table td{padding:var(--space-3) var(--space-2);
  border-bottom:1px solid #EDE7DD;vertical-align:middle;text-align:center}
.compare-table th{width:132px;text-align:start;font-size:12.5px;font-weight:700;
  color:var(--color-muted);white-space:nowrap;background:var(--color-bg)}
.compare-table tr:last-child th,.compare-table tr:last-child td{border-bottom:0}
.compare-head-cell{min-width:170px;text-align:center}
.compare-head-cell > a{display:block;max-width:130px;margin:0 auto var(--space-2)}
.compare-head-cell .product-card__title{margin-bottom:8px;min-height:0}
.compare-remove{font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;
  background:none;border:0;color:var(--color-error);padding:4px}
.compare-remove:hover{text-decoration:underline}

/* --- Anchors and the sticky header -------------------------------
   html has scroll-behavior:smooth and .site-header is position:sticky,
   and nothing was reserving room for it. So every in-page link landed
   its target underneath the header: the قوانین table of contents
   scrolled each heading out of sight, and «۲۴ دیدگاه» on a product
   page jumped past the reviews tab.

   scroll-margin-top is the property built for exactly this. The header
   is 52px of logo plus padding, and the top bar collapses on scroll —
   96px clears it in both states without leaving an obvious gap. */
:where([id]){scroll-margin-top:96px}
@media (max-width:768px){:where([id]){scroll-margin-top:76px}}

/* ---------- 45. Screenshot QA: navigation, trust, cart and checkout -- */

/* The limited-edition card uses the brand orange button on a dark panel.
   Its label must retain enough contrast in every link state. */
.mega-col--limited a.btn,
.mega-col--limited a.btn:visited,
.mega-col--limited a.btn:hover,
.mega-col--limited a.btn:focus-visible{color:#fff}

/* Badge sizing, and the one place that decides it.
   ------------------------------------------------
   This rule used to read `width:80px!important;height:80px!important;
   object-fit:contain`, which is what was blurring the ZarinPal seal.

   The artwork the issuers actually serve, measured from the live page:

     ZarinPal  cdn.zarinpal.com/badges/trustLogo/1.png    60 × 85
     Enamad    trustseal.enamad.ir/logo.aspx             125 × 136

   Forcing ZarinPal's 60px-wide source into an 80px box enlarged it by a
   third, and there is no detail there to enlarge into — 60×85 is the
   only file that CDN serves. `!important` also meant the number in the
   client's own snippet was ignored, so changing it from 80px to 60px
   there appeared to do nothing at all. Both halves of the complaint,
   one declaration.

   Height is the controlling dimension now, at 60px: below both native
   heights, so neither badge is ever scaled up, and a shared baseline
   makes two logos of different proportions sit as a pair. ZarinPal
   draws 42×60, Enamad 55×60 — both downscales, which stay sharp.
   width:auto keeps each aspect ratio, so object-fit has nothing left to
   correct.

   One owner, both axes, and this is where !important earns its place.

   Leaving width to the badge snippet looked like the polite choice and
   was the wrong one. ZarinPal's code carries `#zarinpal img{width:60px}`,
   which is an ID selector and beats anything this file can say with
   classes — so the snippet set the width, this rule set the height, and
   the seal came out 60×60: a 60×85 logo squashed square. Two owners of
   one shape is exactly the failure this codebase keeps warning about,
   and an aspect ratio cannot be co-owned. The theme takes both numbers
   or neither.

   76px, not 60: below both native heights, so still a downscale on each
   — ZarinPal draws 54×76, Enamad 70×76 — and enough bigger that the
   Enamad seal reads at a glance again.

   The client can now delete the <style> line from the Customizer field;
   it no longer does anything either way. */
.trust-badge-slot--badge_1.has-badge img,
.trust-badge-slot--badge_2.has-badge img{
  height:76px!important;
  width:auto!important;
  max-width:100%!important;
  object-fit:contain;
  display:block
}

/* The menu used to stay in normal flex flow while invisible. That made
   the fixed FAB as wide and tall as every hidden label, covering the
   trust badges on mobile. Absolute positioning reduces the closed hit
   area to the visible button; inert in main.js provides the DOM-side
   click and keyboard guard. */
/* position:fixed used to be restated here. theme.css:241 already says it,
   and repeating a frozen file's rule makes it unclear which one owns the
   property — the copy can only ever agree or lie. */
.support-fab-menu{
  position:absolute;inset-inline-start:0;bottom:calc(100% + 8px);
  margin:0;opacity:0;visibility:hidden;pointer-events:none;
  /* right, not left. The menu is anchored with inset-inline-start, which
     in RTL is the right edge — so it grew out of the corner opposite the
     one it is pinned to. Only about a pixel at scale(.98), but it is the
     exact class of mistake this stylesheet has been hunting: a physical
     value sitting next to a logical one. transform-origin has no logical
     keyword, so the value is written for the direction the site is in. */
  transform:translateY(12px) scale(.98);transform-origin:bottom right;
  transition:opacity .32s ease,transform .32s ease,visibility 0s linear .32s
}
.support-fab.is-open .support-fab-menu{
  opacity:1;visibility:visible;pointer-events:auto;transform:translateY(0) scale(1);
  transition:opacity .32s ease,transform .32s ease,visibility 0s
}
.support-fab-link{
  transition:opacity .32s ease,transform .32s ease,visibility 0s linear .32s
}
.support-fab.is-open .support-fab-link{
  transition:opacity .32s ease,transform .32s ease,visibility 0s
}

/* Native checkboxes must never paint over the custom shop switches. */
.switch-row{position:relative}
.switch-row input[type="checkbox"]{
  inset:0 auto auto 0;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap
}

/* The back action and page title form one right-aligned stage label. */
.cart-head-row{
  direction:rtl;flex-direction:column;align-items:flex-start;
  justify-content:flex-start;gap:6px
}
.cart-head-row .step-back{order:-1}
.cart-head-row .cart-head-row__title{order:0}

/* Step 2 reads in delivery order: name, region, street, then identifiers.
   Hidden country fields are removed from grid layout entirely. */
.checkout-address-grid .screen-reader-text,
.checkout-address-grid input[type="hidden"]{display:none}
.checkout-block .form-grid > .field{min-width:0;margin:0}
.checkout-block .form-grid > .field label{line-height:1.7}

/* Shipping choices are moved here after every WooCommerce AJAX refresh. */
#parinhall-shipping-methods{min-height:62px}
#parinhall-shipping-methods ul#shipping_method,
#parinhall-shipping-methods ul.woocommerce-shipping-methods{
  display:grid;gap:var(--space-2);list-style:none;margin:0
}
#parinhall-shipping-methods li{
  display:flex;align-items:flex-start;gap:10px;padding:var(--space-3);
  border:1.5px solid var(--color-control-border);border-radius:var(--radius-card);
  background:var(--color-surface)
}
#parinhall-shipping-methods input[type="radio"]{
  width:18px;height:18px;min-height:0;margin-top:3px;flex-shrink:0;
  accent-color:var(--color-primary)
}
#parinhall-shipping-methods label{font-size:14px;font-weight:600;cursor:pointer}
.shipping-methods-empty{
  padding:var(--space-3);border:1px dashed var(--color-control-border);
  border-radius:var(--radius-input);color:var(--color-muted);
  font-size:13px;line-height:1.8;text-align:center
}

/* Show one clean ZarinPal gateway card above the legal acceptance and
   submit button. It is information, not a duplicated payment section. */
.checkout-payment-title{
  margin:var(--space-4) 0 var(--space-2);padding-top:var(--space-3);
  border-top:1px solid #EDE7DD;font-size:15px;color:var(--color-heading)
}
.woocommerce-checkout-payment.has-single-gateway ul.payment_methods{margin-bottom:var(--space-3)}
.woocommerce-checkout-payment.has-single-gateway ul.payment_methods > li{
  border-color:var(--color-secondary);background:var(--color-secondary-tint);
  padding:var(--space-3)
}
.woocommerce-checkout-payment.has-single-gateway ul.payment_methods > li > input{
  width:18px;height:18px;min-height:0;margin-inline-end:8px;
  accent-color:var(--color-secondary)
}
.woocommerce-checkout-payment.has-single-gateway ul.payment_methods > li > label{
  display:inline-flex;max-width:calc(100% - 32px);vertical-align:middle
}
.woocommerce-checkout-payment.has-single-gateway .payment_box{
  margin-top:var(--space-3);background:rgba(255,255,255,.72);line-height:1.8
}
.woocommerce-checkout-payment .woocommerce-terms-and-conditions-wrapper{
  margin:var(--space-3) 0;padding:var(--space-3);
  border:1px solid #EDE7DD;border-radius:var(--radius-input);
  background:var(--color-bg);font-size:13.5px;line-height:1.9
}
.woocommerce-checkout-payment .woocommerce-terms-and-conditions-wrapper label{
  display:flex;align-items:flex-start;gap:10px;margin:0;cursor:pointer
}
.woocommerce-checkout-payment .woocommerce-terms-and-conditions-wrapper input[type="checkbox"]{
  width:18px;height:18px;min-height:0;margin-top:4px;flex-shrink:0;
  accent-color:var(--color-primary)
}
.woocommerce-checkout-payment .woocommerce-terms-and-conditions-wrapper a{
  color:var(--color-secondary);font-weight:700;text-decoration:underline;
  text-underline-offset:3px
}
.woocommerce-checkout-payment .form-row.place-order{margin:0;padding:0}
.woocommerce-checkout-payment #place_order{
  display:flex;align-items:center;justify-content:center;width:100%;
  min-height:52px;padding:0 var(--space-4);border:0;
  border-radius:var(--radius-button);background:var(--color-primary);
  color:#fff;font-family:inherit;font-size:16px;font-weight:700;
  cursor:pointer;transition:background var(--transition),transform var(--transition)
}
.woocommerce-checkout-payment #place_order:hover{background:var(--color-primary-dark)}
.woocommerce-checkout-payment #place_order:active{transform:translateY(1px)}
.woocommerce-checkout-payment #place_order:disabled{opacity:.55;cursor:not-allowed}
.woocommerce-checkout-payment .blockUI.blockOverlay{border-radius:var(--radius-card)}
.checkout-gateway-note{margin-top:var(--space-3)}

@media (max-width:600px){
  /* Give the coupon field most of the row and keep the maintenance action
     deliberately compact. All WooCommerce names and hooks stay intact. */
  .coupon-row{
    display:grid;grid-template-columns:minmax(0,1fr) auto auto;
    align-items:center;gap:8px
  }
  .coupon-row .field{min-width:0}
  .coupon-row .field input{min-width:0}
  .coupon-row button[name="apply_coupon"]{padding-inline:14px}
  .coupon-row button[name="update_cart"]{
    min-height:40px;padding-inline:9px;font-size:11.5px;white-space:nowrap
  }

  .checkout-block{padding:var(--space-3)}
  .checkout-block .form-grid{grid-template-columns:1fr}
  .checkout-block .form-grid .field--full{grid-column:auto}
  .woocommerce-checkout-payment #place_order{min-height:54px}

  .support-fab-menu{bottom:calc(100% + 6px)}
}

@media (max-width:360px){
  .coupon-row{grid-template-columns:minmax(0,1fr) auto}
  .coupon-row button[name="update_cart"]{
    grid-column:1/-1;justify-self:start
  }
}

/* ============ TRANSPARENT COLOUR SWATCH ============ */
/* «بی رنگ» is transparency, not a colour. Every flat hex either sits next
   to سفید or turns grey and misdescribes the product, so the term carries
   a flag instead and the swatch is drawn as a checkerboard. Both tones are
   existing tokens: --color-surface for the light squares, --color-muted —
   the same neutral an unset term already falls back to — for the dark. The
   PHP omits the inline `background` on these, because that shorthand would
   reset background-image and the pattern would vanish silently. */
.filter-swatch--transparent,
.swatch-dot--transparent{
  background-color:var(--color-surface);
  background-image:
    linear-gradient(45deg,var(--color-muted) 25%,transparent 25%,transparent 75%,var(--color-muted) 75%),
    linear-gradient(45deg,var(--color-muted) 25%,transparent 25%,transparent 75%,var(--color-muted) 75%)
}
.filter-swatch--transparent{background-size:8px 8px;background-position:0 0,4px 4px}
.swatch-dot--transparent{background-size:6px 6px;background-position:0 0,3px 3px}

/* ============ SHORT DESCRIPTION ============ */
/* Not in the approved single-product design. Added because the field was
   being filled in the admin and rendered nowhere at all. Deliberately not
   a .prose card: that class carries a surface, a shadow and space-5 of
   padding, and a second card stacked above the price box would read as a
   heavier element than the price itself. This is plain text in the
   summary column — but the list styling is copied from .prose to the
   pixel (15px, 7px dot, top:11px, --color-primary), so a bulleted short
   description and a bulleted full description look like one voice. */
.product-shortdesc{margin-bottom:var(--space-4);font-size:15px;color:var(--color-body)}
.product-shortdesc>:last-child{margin-bottom:0}
.product-shortdesc p{margin-bottom:var(--space-2);font-size:15px}
.product-shortdesc ul{margin:0 0 var(--space-2);display:flex;flex-direction:column;gap:8px}
.product-shortdesc ul li{position:relative;padding-inline-start:18px;font-size:15px}
.product-shortdesc ul li::before{content:"";position:absolute;inset-inline-start:0;top:11px;width:7px;height:7px;border-radius:var(--radius-round);background:var(--color-primary)}
.product-shortdesc a{color:var(--color-secondary);font-weight:600}
.product-shortdesc strong{color:var(--color-heading)}

/* ============ PRODUCT IMAGE LIGHTBOX ============ */
/* The gallery had no zoom at all — clicking a photo did nothing, and
   there was not one anchor around an image on the whole page. Cosmetics
   is bought on texture and finish, so a 640px thumbnail is not enough to
   decide on a shade.

   Sizes, radii and the round white control chip all reuse what the design
   already established for .hero-arrow and .product-card__fav, so the
   overlay does not introduce a new visual language. The scrim is the same
   hue as .search-overlay and .offcanvas-scrim — rgba(14,56,47,·) — taken
   to .82 rather than .45 because those two dim a page you are still meant
   to read, and this one has to let a photograph carry the screen. */
.gallery-zoom{position:absolute;bottom:var(--space-3);inset-inline-end:var(--space-3);width:40px;height:40px;border-radius:var(--radius-round);background:rgba(255,255,255,.9);box-shadow:var(--shadow-soft);display:flex;align-items:center;justify-content:center;color:var(--color-heading);z-index:3;cursor:pointer;transition:background var(--transition)}
.gallery-zoom:hover{background:#fff}
.gallery-zoom svg{width:20px;height:20px}
.gallery-main img{cursor:zoom-in}

/* z-index 800 clears everything the design places: offcanvas 700, search
   overlay 600, mobile bottom bar 500, header 400. */
.lightbox{position:fixed;inset:0;z-index:800;display:flex;align-items:center;justify-content:center;padding:var(--space-5);background:rgba(14,56,47,.82);opacity:0;visibility:hidden;transition:opacity var(--transition),visibility var(--transition)}
.lightbox.is-open{opacity:1;visibility:visible}
.lightbox__figure{margin:0;display:flex;flex-direction:column;align-items:center;gap:var(--space-3);max-width:100%}
.lightbox__figure img{display:block;width:auto;height:auto;max-width:min(920px,100%);max-height:78vh;border-radius:var(--radius-card);box-shadow:var(--shadow-lift);background:var(--color-surface)}
.lightbox__count{font-size:13px;color:#fff;opacity:.9}
.lightbox__close,
.lightbox__nav{position:absolute;width:44px;height:44px;border-radius:var(--radius-round);background:rgba(255,255,255,.9);display:flex;align-items:center;justify-content:center;color:var(--color-heading);cursor:pointer;transition:background var(--transition)}
.lightbox__close:hover,
.lightbox__nav:hover{background:#fff}
.lightbox__close{top:var(--space-4);inset-inline-end:var(--space-4)}
.lightbox__nav{top:50%;transform:translateY(-50%)}
.lightbox__nav--prev{inset-inline-start:var(--space-4)}
.lightbox__nav--next{inset-inline-end:var(--space-4)}
.lightbox__close svg,
.lightbox__nav svg{width:20px;height:20px}

/* On a phone the side arrows sit on top of the photo, which is the one
   thing the overlay exists to show. Drop them to the bottom edge instead
   and let the image have the full width. */
@media (max-width:480px){
  .lightbox{padding:var(--space-3)}
  .lightbox__figure img{max-height:68vh}
  /* The two properties trade places against the desktop rules above, and
     that is not a typo. Up there the offset is small, so
     `inset-inline-start:16px` pins the button to the start edge — the
     right, in a right-to-left page — which is where «قبلی» belongs. Here
     the offset crosses the halfway mark, and `inset-inline-start:calc(50%
     + …)` sets the button's start edge 50% in from the start, landing it
     on the far side of centre. Measured at 390px: it put «قبلی» left of
     centre and «بعدی» right of it, the wrong way round for RTL. */
  .lightbox__nav{top:auto;bottom:var(--space-4);transform:none}
  .lightbox__nav--prev{inset-inline-start:auto;inset-inline-end:calc(50% + var(--space-2))}
  .lightbox__nav--next{inset-inline-end:auto;inset-inline-start:calc(50% + var(--space-2))}
}

@media (prefers-reduced-motion:reduce){
  .lightbox{transition:none}
}

/* The WordPress admin bar is position:fixed at z-index 99999 and no
   overlay outranks it, so for a signed-in administrator the close button
   at top:16px was sitting underneath it — invisible and unclickable.
   Shoppers never see the bar, so this only moves the button for the
   people who have one. 32px is the bar's desktop height, 46px its height
   below 783px, matching WordPress's own breakpoint. */
body.admin-bar .lightbox__close{top:calc(var(--space-4) + 32px)}
@media (max-width:782px){
  body.admin-bar .lightbox__close{top:calc(var(--space-4) + 46px)}
}

/* The «+۱» that stands in for colours the card has no room to draw. Not
   a fifth dot: a dot implies a colour you can see, and this one is
   standing in for the ones you cannot. Sized and coloured like the
   .fc-count numerals in the filter panel so it reads as a count. */
.swatch-more{
  align-self:center;
  font-size:12px;
  font-weight:600;
  line-height:1;
  color:var(--color-muted);
  margin-inline-start:2px;
  direction:rtl
}

/* ============ "ADDED TO BASKET" DIALOG ============ */
/* The green notice bar this replaces sat above the fold and was scrolled
   past. It reported what had happened without helping with the only
   decision that follows — keep looking, or go and pay.

   Same overlay language as the product lightbox: the scrim hue the design
   already uses for .search-overlay and .offcanvas-scrim, a round white
   close chip, and the tokens that build every other card. The backdrop
   blur is the one addition, and it earns its place here — the page behind
   is a grid of other products, and blurring it is what stops the eye
   wandering back to them mid-decision. */
.cart-modal{
  position:fixed;inset:0;z-index:810;
  display:flex;align-items:center;justify-content:center;padding:var(--space-4);
  background:rgba(14,56,47,.55);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  opacity:0;visibility:hidden;
  transition:opacity var(--transition),visibility var(--transition)
}
.cart-modal.is-open{opacity:1;visibility:visible}

.cart-modal__panel{
  position:relative;
  background:var(--color-surface);
  border-radius:var(--radius-card);
  box-shadow:var(--shadow-lift);
  padding:var(--space-6) var(--space-5) var(--space-5);
  width:min(420px,100%);
  text-align:center;
  transform:translateY(8px);
  transition:transform var(--transition)
}
.cart-modal.is-open .cart-modal__panel{transform:translateY(0)}

.cart-modal__close{
  position:absolute;top:var(--space-3);inset-inline-end:var(--space-3);
  width:34px;height:34px;border-radius:var(--radius-round);
  display:flex;align-items:center;justify-content:center;
  color:var(--color-body);background:transparent;cursor:pointer;
  transition:background var(--transition)
}
.cart-modal__close:hover{background:var(--color-bg)}
.cart-modal__close svg{width:18px;height:18px}

.cart-modal__tick{
  display:flex;align-items:center;justify-content:center;
  width:52px;height:52px;margin:0 auto var(--space-3);
  border-radius:var(--radius-round);
  background:var(--color-mix-tint);color:var(--color-success)
}
.cart-modal__tick svg{width:26px;height:26px}

.cart-modal__title{font-size:17px;font-weight:800;color:var(--color-heading);margin:0 0 6px}
.cart-modal__name{font-size:14px;color:var(--color-muted);margin:0 0 var(--space-5);min-height:1.2em}

/* One column, not two side by side. The two choices are not equal — one
   continues the visit and one ends it — and stacking them lets the
   primary keep full width on a phone without a second breakpoint. */
.cart-modal__actions{display:flex;flex-direction:column;gap:var(--space-2)}
.cart-modal__actions .btn{width:100%}

@media (prefers-reduced-motion:reduce){
  .cart-modal,.cart-modal__panel{transition:none}
}

/* The typed city fallback, hidden until «شهر من در فهرست نیست» is picked.
   Also hidden without JavaScript — the class ships on the field from PHP —
   which is correct: with no script the province cannot change either, so
   the server-rendered list is the only list, and an empty extra box would
   just be one more thing to ignore. */
/* .city-other.is-hidden was here. The generic .is-hidden at the end of
   this file does the same job for every block that hides itself, so the
   scoped copy was a second owner of one declaration. */

/* ============ WISHLIST + COMPARE ON THE CARD ============ */
/* theme.css positions .product-card__fav in the corner and gives its icon
   a stroke. It never gave it an "on" state — the script has always added
   .is-active and nothing rendered it, so the heart looked identical
   whether or not the product was saved. That is the whole feature: a
   shopper cannot see what is on their list. Filling the icon says it in
   the one place they are looking. */
.product-card__fav.is-active svg,
.product-card__compare.is-active svg{
  fill:var(--color-primary);
  stroke:var(--color-primary)
}
.product-card__compare.is-active svg{fill:none;stroke-width:2.6}

/* The two controls stack in the corner theme.css reserved for one. The
   wrapper takes over positioning so the frozen rule for .product-card__fav
   keeps sizing and colouring the button and stops deciding where it sits —
   one owner for the box, another for the look. */
.product-card__tools{
  position:absolute;top:var(--space-2);inset-inline-end:var(--space-2);
  z-index:2;display:flex;flex-direction:column;gap:6px
}
.product-card__tools .product-card__fav{position:static;top:auto;inset-inline-end:auto}
.product-card__compare{
  width:36px;height:36px;border-radius:var(--radius-round);
  background:rgba(255,255,255,.9);display:flex;align-items:center;justify-content:center;
  cursor:pointer;transition:background var(--transition)
}
.product-card__compare svg{width:16px;height:16px;stroke:var(--color-heading)}
.product-card__fav:hover,
.product-card__compare:hover{background:#fff}

/* A card leaving the wishlist or compare grid, rather than sitting there
   looking saved when it is not. */
.product-card.is-leaving{
  opacity:0;transform:scale(.96);
  transition:opacity .25s ease,transform .25s ease;
  pointer-events:none
}
@media (prefers-reduced-motion:reduce){
  .product-card.is-leaving{transition:none}
}

/* ============ COMPARE TOAST ============ */
/* Adding to compare used to do nothing a shopper could see except tint an
   icon, and the compare page had no route to it from anywhere on the
   site. The toast is the route: it confirms the add, counts what is in
   there, and hands over the link — then gets out of the way. */
.compare-toast{
  position:fixed;z-index:760;
  inset-inline-start:var(--space-4);
  bottom:calc(var(--space-4) + var(--bottom-bar-height));
  display:flex;align-items:center;gap:var(--space-3);
  background:var(--color-surface);color:var(--color-heading);
  border-radius:var(--radius-card);box-shadow:var(--shadow-lift);
  padding:var(--space-3) var(--space-4);
  font-size:14px;font-weight:600;
  opacity:0;visibility:hidden;transform:translateY(10px);
  transition:opacity var(--transition),visibility var(--transition),transform var(--transition)
}
.compare-toast.is-open{opacity:1;visibility:visible;transform:translateY(0)}
.compare-toast a{color:var(--color-primary);font-weight:800;white-space:nowrap}
.compare-toast__count{color:var(--color-muted);font-weight:400}
@media (max-width:480px){
  .compare-toast{inset-inline:var(--space-3);justify-content:space-between}
}
@media (prefers-reduced-motion:reduce){
  .compare-toast{transition:none}
}

/* Utility. Used by the wishlist grid, the compare table and the typed
   city fallback, all of which ship a block that JavaScript reveals or
   hides in place rather than fetching a fresh page for. */
.is-hidden{display:none}

/* ============ THE BUY ROW'S OWN WISHLIST BUTTON ============ */
/* The button beside «افزودن به سبد خرید» carries .product-card__fav to
   borrow its icon colour — and inherited `position:absolute` with it.
   theme.css positions that class for a card overlay, pinned to the top
   corner, so on the product page the heart was torn out of the buy row
   and parked against the nearest positioned ancestor. Measured: the row
   sits at (190, 50) and the heart rendered at (8, 8), which is why the
   product page has only ever shown one icon next to the cart button.

   Same fix as the card: the row owns where the button sits, theme.css
   keeps owning how it looks. */
.buy-row .product-card__fav{
  position:static;top:auto;inset-inline-end:auto
}

/* And the "on" state, for both buttons in the row. These are .icon-btn
   here rather than the card classes — giving them the card classes would
   drag a 36px box into a row that sizes its controls at 48px, which is
   the two-owners problem again. Scoping the fill to .buy-row says the
   same thing without moving the boundary. */
.buy-row .icon-btn.is-active svg{stroke:var(--color-primary);fill:var(--color-primary)}
.buy-row .icon-btn[data-compare-id].is-active svg{fill:none;stroke-width:2.6}
