/*
Theme Name: Organic
Theme URI: https://templatesjungle.com/
Author: TemplatesJungle
Author URI: https://templatesjungle.com/
Description: Organic is specially designed product packaged for eCommerce store websites.
Version: 1.1
*/

/*--------------------------------------------------------------
This is main CSS file that contains custom style rules used in this template
--------------------------------------------------------------*/
/*--------------------------------------------------------------
/** VARIABLES
--------------------------------------------------------------*/
/* Colour, type and Bootstrap variables now live in css/tokens/ (see
   theme-default.css for the semantic layer and the light/dark contract).
   Do not reintroduce raw values here. */
.btn-primary {
  --bs-btn-color: var(--color-brand-primary-contrast);
  --bs-btn-bg: var(--bs-primary);
  --bs-btn-border-color: transparent;
  --bs-btn-hover-color: var(--color-brand-primary-contrast);
  --bs-btn-hover-bg: var(--color-brand-primary-hover);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-focus-shadow-rgb: var(--color-brand-primary-rgb);
  --bs-btn-active-color: var(--color-brand-primary-contrast);
  --bs-btn-active-bg: var(--bs-primary);
  --bs-btn-active-border-color: transparent;
  --bs-btn-active-shadow: var(--shadow-pressed);
  --bs-btn-disabled-color: var(--color-brand-primary-contrast);
  --bs-btn-disabled-bg: var(--color-border-strong);
  --bs-btn-disabled-border-color: transparent;
}
.btn-outline-primary {
  --bs-btn-color: var(--bs-primary);
  --bs-btn-border-color: var(--bs-primary);
  --bs-btn-hover-color: var(--color-text-inverse);
  --bs-btn-hover-bg: var(--color-accent);
  --bs-btn-hover-border-color: var(--color-accent);
  --bs-btn-focus-shadow-rgb: var(--color-brand-primary-rgb);
  --bs-btn-active-color: var(--color-text-inverse);
  --bs-btn-active-bg: var(--color-accent);
  --bs-btn-active-border-color: var(--color-accent);
  --bs-btn-active-shadow: var(--shadow-pressed);
  --bs-btn-disabled-color: var(--color-warning-subtle);
  --bs-btn-disabled-bg: transparent;
  --bs-btn-disabled-border-color: var(--color-warning-subtle);
  --bs-gradient: none;
}
.btn-outline-light {
  --bs-btn-color: var(--color-text-muted);
  --bs-btn-border-color: var(--color-surface-alt);
  --bs-btn-hover-color: var(--color-text);
  --bs-btn-hover-bg: var(--color-surface-alt);
  --bs-btn-hover-border-color: var(--color-surface-alt);
  --bs-btn-focus-shadow-rgb: var(--color-border-rgb);
  --bs-btn-active-color: var(--color-text);
  --bs-btn-active-bg: var(--color-surface-alt);
  --bs-btn-active-border-color: var(--color-surface-alt);
  --bs-btn-active-shadow: var(--shadow-pressed);
  --bs-btn-disabled-color: var(--color-surface-alt);
  --bs-btn-disabled-bg: transparent;
  --bs-btn-disabled-border-color: var(--color-surface-alt);
  --bs-gradient: none;
}
.btn-warning {
  --bs-btn-color: var(--color-text-muted);
  --bs-btn-bg: var(--color-warning-subtle);
  --bs-btn-border-color: var(--color-warning-subtle);
  --bs-btn-hover-color: var(--color-text-muted);
  --bs-btn-hover-bg: var(--color-warning-subtle-hover);
  --bs-btn-hover-border-color: var(--color-warning-subtle-hover);
  --bs-btn-focus-shadow-rgb: var(--color-warning-rgb);
  --bs-btn-active-color: var(--color-text);
  --bs-btn-active-bg: var(--color-warning-subtle-hover);
  --bs-btn-active-border-color: var(--color-warning-subtle-hover);
  --bs-btn-active-shadow: var(--shadow-pressed);
  --bs-btn-disabled-color: var(--color-text);
  --bs-btn-disabled-bg: var(--color-warning-subtle);
  --bs-btn-disabled-border-color: var(--color-warning-subtle);
}
.btn-success {
  --bs-btn-color: var(--color-text);
  --bs-btn-bg: var(--color-success-subtle);
  --bs-btn-border-color: var(--color-success-subtle);
  --bs-btn-hover-color: var(--color-text);
  --bs-btn-hover-bg: var(--color-success-subtle-hover);
  --bs-btn-hover-border-color: var(--color-success-subtle-hover);
  --bs-btn-focus-shadow-rgb: var(--color-success-rgb);
  --bs-btn-active-color: var(--color-text);
  --bs-btn-active-bg: var(--color-success-subtle-hover);
  --bs-btn-active-border-color: var(--color-success-subtle-hover);
  --bs-btn-active-shadow: var(--shadow-pressed);
  --bs-btn-disabled-color: var(--color-text);
  --bs-btn-disabled-bg: var(--color-success-subtle);
  --bs-btn-disabled-border-color: var(--color-success-subtle);
}
.btn-danger {
  --bs-btn-color: var(--color-text);
  --bs-btn-bg: var(--color-danger-subtle);
  --bs-btn-border-color: var(--color-danger-subtle);
  --bs-btn-hover-color: var(--color-text);
  --bs-btn-hover-bg: var(--color-danger-subtle-hover);
  --bs-btn-hover-border-color: var(--color-danger-subtle-hover);
  --bs-btn-focus-shadow-rgb: var(--color-danger-rgb);
  --bs-btn-active-color: var(--color-text);
  --bs-btn-active-bg: var(--color-danger-subtle-hover);
  --bs-btn-active-border-color: var(--color-danger-subtle-hover);
  --bs-btn-active-shadow: var(--shadow-pressed);
  --bs-btn-disabled-color: var(--color-text);
  --bs-btn-disabled-bg: var(--color-danger-subtle);
  --bs-btn-disabled-border-color: var(--color-danger-subtle);
}
body {
  letter-spacing: 0.03em;
}
h1,h2,h3,h4,h5,h6 {
  font-family: var(--heading-font);
  color: var(--bs-dark);
  font-weight: var(--font-weight-heading);
}
.breadcrumb.text-white {
  --bs-breadcrumb-divider-color: var(--color-text-inverse);
  --bs-breadcrumb-item-active-color: var(--bs-primary);
}
/* The page-header banner is a photo under a scrim, and its <h1> carries
   `text-white` for exactly that reason — but the breadcrumb beneath it did not,
   so it inherited the theme's muted body colour and rendered a mid-grey on the
   scrimmed photo: measured 1.14-1.64:1 in light mode in ALL FOUR themes by
   Micro-prompt 36's contrast sweep. White, matching the heading beside it.
   (`--color-brand-primary-contrast` rather than `--color-text-inverse`, which
   flips to a dark value in dark mode.) */
.page-header .breadcrumb,
.page-header .breadcrumb a,
.page-header .breadcrumb-item,
.page-header .breadcrumb-item.active {
  color: var(--color-brand-primary-contrast);
}
.page-header .breadcrumb {
  --bs-breadcrumb-divider-color: var(--color-brand-primary-contrast);
  --bs-breadcrumb-item-active-color: var(--color-brand-primary-contrast);
}
.dropdown-menu {
  --bs-dropdown-link-active-bg: var(--bs-primary);
}
/* Checkboxes and radios. Bootstrap 5.3.0-alpha3 hardcodes the checked state to
   its own blue and exposes no `--bs-*` variable for it, so the token layer
   could not reach it — blue ticks on a brand-red site, in every theme.
   Re-pointed here rather than in a theme file because it is not theme-specific.
   Found by the Micro-prompt 33 leakage sweep (build log §19.5). */
.form-check-input:checked {
  background-color: var(--input-border-focus);
  border-color: var(--input-border-focus);
}
/* `.text-light`. Bootstrap 5.3 resolves it through the `--bs-light-rgb` triple,
   and the token layer repurposes that as a DARK surface tint in dark mode —
   which is right for `.bg-light` and wrong for `.text-light`. All
   14 uses in this template sit on a brand-coloured surface (the home promo
   cards, the banner titles, the olive CTA strip), so in dark mode that text
   rendered dark-on-red: measured 3.5:1 against a 4.5:1 requirement. Found by
   Micro-prompt 35's contrast audit; it affected every theme, not just glass.
   Restored to the brand contrast, which is white in all four themes. */
[data-mode="dark"] .text-light {
  color: var(--color-brand-primary-contrast) !important;
}
.nav-pills .nav-link {
  --bs-nav-pills-link-active-color: var(--color-text);
  --bs-nav-pills-link-active-bg: var(--color-surface-alt);
}
.pagination {
  --bs-pagination-active-bg: var(--bs-primary);
  --bs-pagination-active-border-color: var(--bs-primary);
}
.container, .container-fluid, .container-lg, .container-md, .container-sm, .container-xl, .container-xxl {
  --bs-gutter-x: 3rem;
}
/*----------------------------------------------*/
/* 6. SITE STRUCTURE */
/*----------------------------------------------*/
/* 6.1 Header
--------------------------------------------------------------*/
/* Preloader */
.preloader-wrapper {
  width: 100%;
  height: 100vh;
  margin: 0 auto;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 111;
  background: var(--color-surface);
}

.preloader-wrapper .preloader {
  margin: 20% auto 0;
  transform: translateZ(0);
}

.preloader:before,
.preloader:after {
  content: '';
  position: absolute;
  top: 0;
}

.preloader:before,
.preloader:after,
.preloader {
  border-radius: 50%;
  width: 2em;
  height: 2em;
  animation: animation 1.2s infinite ease-in-out;
}

.preloader {
  animation-delay: -0.16s;
}

.preloader:before {
  left: -3.5em;
  animation-delay: -0.32s;
}

.preloader:after {
  left: 3.5em;
}

@keyframes animation {
  0%,
  80%,
  100% {
    box-shadow: 0 2em 0 -1em var(--bs-primary);
  }
  40% {
    box-shadow: 0 2em 0 0 var(--bs-primary);
  }
}

/* *** Start editing below this line *** */
/* .container-fluid {
  max-width: 1600px;
}
*/
@media (min-width: 1400px) {
  .container-lg {
      max-width: 1600px;
  }
} 

.banner-blocks {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-template-rows: repeat(2, 1fr);
  grid-gap: 2rem;
}
.block-1 { grid-area: 1 / 1 / 3 / 8; }
.block-2 { grid-area: 1 / 8 / 2 / 13; }
.block-3 { grid-area: 2 / 8 / 3 / 13; }

@media screen and (max-width:1140px) {
  .banner-blocks {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(4, 1fr);
  }
  .block-1 { grid-area: 1 / 1 / 3 / 2; }
  .block-2 { grid-area: 3 / 1 / 4 / 2; }
  .block-3 { grid-area: 4 / 1 / 5 / 2; }
  
}

/* Swiper carousel */
.swiper-prev,
.swiper-next {
  width: 38px;
  height: 38px;
  line-height: 38px;
  background: var(--color-surface-alt);
  color: var(--color-text);
  padding: 0;
  text-align: center;
  border-radius: var(--carousel-control-radius);
  --bs-btn-border-color: transparent;
  --bs-btn-active-bg: var(--color-accent-hover);
  --bs-btn-active-border-color: transparent;
  --bs-btn-hover-bg: var(--bs-primary);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-disabled-color: var(--color-border-strong);
  --bs-btn-disabled-bg: var(--color-surface-alt);
  --bs-btn-disabled-border-color: var(--color-surface-alt)
}
.swiper-prev:hover,
.swiper-next:hover {
  background: var(--bs-primary);
}

/* category carousel — Micro-prompt 30.
   The previous `.category-item` / `.category-title` rules were DEAD: the render
   function (js/components/category-card.js) never emitted those classes, so they
   matched nothing. Replaced by the tile styling below, which targets the markup
   the renderer actually produces. */
.zm-cat-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: 0;
  text-decoration: none;
  text-align: center;
}

.zm-cat-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--category-tile-size);
  height: var(--category-tile-size);
  padding: var(--category-tile-pad);
  border-radius: var(--category-tile-radius);
  background-color: var(--category-tile-bg);
  overflow: hidden;
  transition: background-color var(--dur-fast) var(--ease-base);
}

.zm-cat-card:hover .zm-cat-tile,
.zm-cat-card:focus-visible .zm-cat-tile {
  background-color: var(--category-tile-bg-hover);
}

.zm-cat-tile img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.zm-cat-glyph {
  color: var(--category-glyph-color);
}

/* The name sits BELOW the tile, per the reference — not inside it. */
.zm-cat-name {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--category-name-color);
  transition: color var(--dur-fast) var(--ease-base);
}

.zm-cat-card:hover .zm-cat-name,
.zm-cat-card:focus-visible .zm-cat-name {
  color: var(--category-name-hover);
}

/* Skeleton tiles reuse the same box so the loading state has the same shape. */
.zm-cat-card.zm-skeleton .zm-cat-tile {
  background-color: var(--category-tile-bg);
}

/* brand carousel */
.brand-carousel .brand-item {
  background: var(--color-surface);
  border: 1px solid var(--color-surface-sunken);
  box-shadow: var(--shadow-md);
  border-radius: var(--card-radius);
  padding: 16px;
}
.brand-carousel .brand-item img {
  width: 100%;
  border-radius: var(--radius-md);
}
.brand-carousel .brand-item .brand-details {
  margin-left: 15px;
}
.brand-carousel .brand-item .brand-title {
  margin: 0;
}

/* product tabs */
.product-tabs .nav-tabs {
  justify-content: flex-end;
  border: none;
  
  --bs-nav-link-hover-color: var(--color-text);
  --bs-nav-link-color: var(--color-text-muted);
  --bs-nav-tabs-link-border-color: var(--color-surface);
  --bs-nav-tabs-link-hover-border-color: transparent;
  --bs-nav-tabs-link-active-border-color: var(--color-surface);
}
.product-tabs .nav-tabs .nav-link.active, 
.product-tabs .nav-tabs .nav-item.show .nav-link {
  /* border: none; */
  border-bottom: 3px solid var(--bs-primary);
}

/* products-carousel */
.products-carousel .swiper, .products-carousel .swiper-container {
  overflow: visible;
}

/* product-grid */
input[type=number]::-webkit-inner-spin-button, 
input[type=number]::-webkit-outer-spin-button {  
   opacity: 1;
}
.product-item .button-area .quantity {
  padding: 0.5rem;
}
.product-item .button-area {
  display: none;
  position: absolute;
  text-align: center;
  background: var(--color-surface);
  width: 100%;
  left: 0;
  bottom: -55px;
  z-index: 1;
  box-shadow: var(--shadow-lg);
  /* transition: box-shadow 0.3s ease-out; */
}
.product-item {
  position: relative;
  padding: 16px;
  background: var(--card-bg);
  border: var(--card-border-width) solid var(--card-border);
  border-radius: var(--card-radius);
  margin-bottom: 30px;
  box-shadow: 0px 0px 22px var(--overlay-transparent);
  /* transition: box-shadow 0.3s ease-out, margin 0.3s ease-out; */
}
.product-item:hover .button-area {
  display: block;
}
.product-item:hover {
  /* z-index: 1; */
  /* margin-bottom: -50px; */
  /* max-height: 500px; */
  box-shadow: var(--shadow-lg);
}
.product-item figure {
  text-align: center;
}
.product-item figure img {
  max-height: 210px;
  height: auto;
}
.product-item .product-qty {
  width: 85px;
}
.product-item .btn-link {
  text-decoration: none;
}
.product-item #quantity {
  height: auto;
  width: 28px;
  text-align: center;
  border: none;
  margin: 0;
  padding: 0;
}
.product-item .btn-number {
  width: 26px;
  height: 26px;
  line-height: 1;
  text-align: center;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  padding: 0;
}

/* cart */
.cart .product-qty {
  min-width: 130px;
}

/* floating image */
.image-float {
  margin-top: -140px;
  margin-bottom: -140px;
}
@media screen and (max-width:991px) {
  .image-float {
    margin: 0;
  }
}
 /* post item */
.post-item .post-meta {
  font-size: 0.8rem;
  line-height: 1;
}
.post-item .post-meta svg {
  margin-right: 5px;
}

@media screen and (max-width: 991px) {
  /* offcanvas menu */
  .offcanvas-body .nav-item {
    font-weight: 700;
    border-bottom: 1px solid var(--color-border-strong);
  }
  .offcanvas-body .filter-categories {
    width: 100%;
    margin-bottom: 20px !important;
    border: 1px solid var(--color-border-strong) !important;
    padding: 14px;
    border-radius: var(--radius-md);
  }
  /* dropdown-menu */
  .dropdown-menu {
    padding: 0;
    border: none;
    line-height: 1.4;
    font-size: 0.9em;
  }
  .dropdown-menu a {
    padding-left: 0;
  }
  .dropdown-toggle::after {
    position: absolute;
    right: 0;
    top: 21px;
  }
}

/* single product */
/* product-thumbnail-slider */
.product-thumbnail-slider {
  height: 740px;
}
@media screen and (max-width:992px) {
  .product-thumbnail-slider {
    margin-top: 20px;
    height: auto;
  }
}
@media screen and (min-width:992px) {
  .product-thumbnail-slider {
    height: 420px;
  }
}
@media screen and (min-width:1200px) {
  .product-thumbnail-slider {
    height: 540px;
  }
}
@media screen and (min-width:1400px) {
  .product-thumbnail-slider {
    height: 740px;
  }
}

/* bootstrap extended */
.border-dashed {
  border-bottom: 1px dashed var(--color-border-strong);
}
.ls-1 {
  letter-spacing: -0.04em;
}
.button-area .btn-cart {
  text-wrap: nowrap;
  height: 3.3em;
  line-height: 2em;
  width: 100%;
}
.fs-7 {
  font-size: 0.8rem!important;
}

/* button */
.btn-link {
  display: inline-block;
  font-size: 0.875rem;
  font-weight: bold;
  font-family: var(--bs-body-font-family);
  letter-spacing: 0.0875rem;
  text-transform: uppercase;
  text-decoration: none;
}

a.btn-link,
a.btn-link:after {
  transition: all .5s;
}

a.btn-link {
  position: relative;
}

a.btn-link:before,
a.btn-link:after {
  content: '';
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0;
  background-color: var(--bs-dark);
  height: 2px;
}

[data-bs-theme=dark] a.btn-link:after {
  background-color: var(--color-text);
}

a.btn-link:before {
  background-color: var(--overlay-white-20);
  width: 100%;
}

a.btn-link.is-checked:after,
a.btn-link:hover:after {
  width: 100%;
}

a.btn-link.text-white:after {
  background-color: var(--color-text-inverse);
}

a.btn-link.text-light:after {
  background-color: var(--color-text-inverse);
}

.navbar .megamenu{ padding: 1rem; }
/* ============ desktop view ============ */
@media all and (min-width: 992px) {
	
	.navbar .has-megamenu{position:static!important;}
	.navbar .megamenu{left:0; right:0; width:100%; margin-top:0;  }
	
}	
/* ============ desktop view .end// ============ */


/* ============ mobile view ============ */
@media(max-width: 991px){
	.navbar.fixed-top .navbar-collapse, .navbar.sticky-top .navbar-collapse{
		overflow-y: auto;
	    max-height: 90vh;
	    margin-top:10px;
	}
}
/* ============ mobile view .end// ============ */

/*--------------------------------------------------------------
 Zan Market — async catalogue states (loading / empty / error).
 Rendered by js/catalog-init.js. Reuses the card radius (--card-radius),
 body text colour (--color-text-muted) and spacing; no new design system.
--------------------------------------------------------------*/
.zm-skeleton-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  width: 100%;
}
.zm-skeleton-row > * {
  flex: 1 1 0;
  min-width: 0;
}
.zm-skeleton {
  position: relative;
  overflow: hidden;
}
.zm-skeleton .zm-skeleton-img {
  height: 180px;
  background: var(--color-surface-alt);
  border-radius: var(--card-radius);
  margin-bottom: 14px;
}
.zm-skeleton .zm-skeleton-circle {
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: var(--color-surface-alt);
  margin: 0 auto;
}
.zm-skeleton .zm-line {
  height: 12px;
  background: var(--color-surface-alt);
  border-radius: var(--radius-sm);
  margin: 8px auto;
}
.zm-skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--overlay-white-65), transparent);
  animation: zm-shimmer 1.3s infinite;
}
@keyframes zm-shimmer {
  100% { transform: translateX(100%); }
}
.zm-section-note {
  width: 100%;
  padding: 2.5rem 1rem;
  color: var(--color-text-muted);
}

/*--------------------------------------------------------------
 Zan Market — header search panel + sponsored tag.
--------------------------------------------------------------*/
.search-bar {
  position: relative;
}
.zm-autocomplete {
  left: 0;
  right: 0;
  top: 100%;
  margin-top: 4px;
  max-height: 320px;
  overflow-y: auto;
}
.zm-sponsored {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  letter-spacing: 0;
  text-transform: none;
}
/*--------------------------------------------------------------
 Zan Market — toast notifications (js/components/toast.js) and
 cart line widgets. Built from the template's own tokens (radius,
 shadow, Bootstrap alert colours) rather than a new pattern.
--------------------------------------------------------------*/
.zm-toast-container {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 1080;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: min(360px, calc(100vw - 2rem));
}
.zm-toast {
  border-radius: var(--toast-radius);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.zm-toast-out {
  opacity: 0;
  transform: translateY(6px);
}
.product-qty .input-number {
  -moz-appearance: textfield;
}
.product-qty .input-number::-webkit-outer-spin-button,
.product-qty .input-number::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/*--------------------------------------------------------------
 Zan Market — mobile app chrome (Micro-prompt 28).

 Header app bar, search pill and bottom navigation, to match the ZAN
 Shopping reference. Every value comes from css/tokens/ (Micro-prompt 27)
 — there are no raw colours in this block, by design.

 Two arrangements from one DOM: below `lg` the header is the app bar plus a
 full-width search pill; at `lg` and up the original brand | search | nav |
 icons row returns. Nothing here duplicates markup or ids.
--------------------------------------------------------------*/

/* ---- header shell ------------------------------------------------------ */
.zm-header {
  background-color: var(--header-bg);
}

.zm-header-inner {
  display: block;
}

.zm-appbar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  background-color: var(--appbar-bg);
  color: var(--appbar-text);
}

.zm-appbar-menu {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--appbar-text);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-base);
}

.zm-appbar-menu:hover,
.zm-appbar-menu:focus-visible {
  background-color: var(--bnav-active-bg);
}

/* NOTE: .zm-appbar-menu is unused since the app bar dropped its hamburger to
   match the reference (Micro-prompt 28). Kept deliberately so re-adding the
   offcanvas trigger is a one-line markup change rather than a re-style. */

/* ---- brand lockup ------------------------------------------------------ */
.zm-brand {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
  color: var(--appbar-text);
}

.zm-brand-mark {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
}

.zm-brand-mark svg {
  color: var(--appbar-text);
}

.zm-brand-z {
  position: absolute;
  top: 52%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1;
  color: var(--appbar-bg);
}

.zm-brand-words {
  display: inline-flex;
  flex-direction: column;
  line-height: 1;
}

.zm-brand-name {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.zm-brand-sub {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* ---- tagline (hidden on the narrowest phones) --------------------------- */
.zm-appbar-rule {
  flex: 0 0 auto;
  width: 1px;
  height: 34px;
  background-color: var(--appbar-rule);
}

.zm-tagline {
  flex: 1 1 auto;
  margin: 0;
  min-width: 0;
  font-size: 0.8rem;
  line-height: 1.25;
  color: var(--appbar-text);
}

@media (max-width: 359.98px) {
  .zm-appbar-rule,
  .zm-tagline {
    display: none;
  }
}

/* ---- app bar actions + count badges ------------------------------------ */
.zm-appbar-actions {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-left: auto;
}

.zm-icon-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  color: var(--appbar-text);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-base);
}

.zm-icon-btn:hover,
.zm-icon-btn:focus-visible {
  background-color: var(--bnav-active-bg);
  color: var(--appbar-text);
}

.zm-count {
  position: absolute;
  top: 0;
  right: 0;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  border-radius: var(--count-badge-radius);
  background-color: var(--count-badge-bg);
  color: var(--count-badge-text);
  box-shadow: 0 0 0 2px var(--count-badge-ring);
}

/* ---- search pill ------------------------------------------------------- */
.zm-search-row {
  padding-bottom: var(--space-3);
}

.zm-search-pill {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-4);
  border-radius: var(--search-pill-radius);
  background-color: var(--search-pill-bg);
  box-shadow: var(--search-pill-shadow);
}

.zm-search-lead {
  flex: 0 0 auto;
  display: inline-flex;
  color: var(--search-pill-icon);
}

.zm-search-cat {
  flex: 0 0 auto;
  min-width: 130px;
  border-right: 1px solid var(--color-border);
}

.zm-search-cat .form-select {
  color: var(--search-pill-text);
}

.zm-search-form {
  flex: 1 1 auto;
  min-width: 0;
}

.zm-search-form .form-control {
  color: var(--search-pill-text);
  box-shadow: none;
  /* Bootstrap's .form-control carries its own height and padding; the pill
     supplies the box, so the input must not add a second one. */
  height: auto;
  padding-top: 0;
  padding-bottom: 0;
  line-height: 1.5;
  background-color: transparent;
}

.zm-search-form .form-control::placeholder {
  color: var(--search-pill-placeholder);
}

/* ---- desktop arrangement (unchanged behaviour, restored at lg) ---------- */
@media (min-width: 992px) {
  .zm-header-inner {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    padding: var(--space-4) 0;
    border-bottom: 1px solid var(--header-border);
  }

  .zm-desktop-brand {
    flex: 0 0 auto;
  }

  .zm-search-row {
    flex: 1 1 300px;
    max-width: 520px;
    padding-bottom: 0;
  }

  .zm-search-pill {
    background-color: var(--color-surface-alt);
    box-shadow: none;
  }

  .zm-desktop-nav {
    flex: 1 1 auto;
  }

  .zm-desktop-icons {
    flex: 0 0 auto;
    margin-left: auto;
  }
}

/*--------------------------------------------------------------
 Zan Market — mobile bottom navigation (Micro-prompt 28).
 New shared chrome: partials/bottom-nav.html, injected on every page by
 js/partials.js. Hidden from `lg` up, where the top nav stays primary.
--------------------------------------------------------------*/
.zm-bnav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--bnav-z);
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  padding: var(--space-1) var(--space-1) calc(var(--space-1) + env(safe-area-inset-bottom, 0px));
  background-color: var(--bnav-bg);
  border-top: 1px solid var(--bnav-border);
}

.zm-bnav-item {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: var(--space-2) 1px;
  border-radius: var(--bnav-active-radius);
  color: var(--bnav-text);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-base);
}

.zm-bnav-item:hover,
.zm-bnav-item:focus-visible {
  color: var(--bnav-text);
}

.zm-bnav-item.is-active {
  background-color: var(--bnav-active-bg);
  color: var(--bnav-active-text);
}

.zm-bnav-icon {
  position: relative;
  display: inline-flex;
}

.zm-bnav-icon .zm-count {
  top: -6px;
  right: -8px;
}

.zm-bnav-label {
  /* 9.6px, not 11px: "Categories" is a longer word than any label in the
     reference mockup and must not truncate at a 360px viewport (it needs
     ~56px and the item only offers ~57px). Verified at 360px, 390px, 414px. */
  font-size: 0.6rem;
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* Keep the fixed bar clear of page content and of the toast stack. */
@media (max-width: 991.98px) {
  body {
    padding-bottom: 72px;
  }

  .zm-toast-container {
    bottom: 84px;
  }
}

/*--------------------------------------------------------------
 Zan Market — product card, "Bidhaa Maarufu" layout (Micro-prompt 31).

 One shared renderProductCard, so this styling lands on every surface at once:
 home grid + carousels, category, search, shop and the account wishlist.
 Tokens only; no raw colours.

 Slots below the image (badge, struck-through price, rating) render only when
 the data supplies them — see the component's header comment.
--------------------------------------------------------------*/
.zm-pcard {
  display: flex;
  flex-direction: column;
  padding: var(--pcard-padding);
  background: var(--pcard-bg);
  border: var(--card-border-width) solid var(--pcard-border);
  border-radius: var(--pcard-radius);
  box-shadow: var(--pcard-shadow);
  transition: box-shadow var(--dur-base) var(--ease-base);
}

.zm-pcard:hover {
  box-shadow: var(--pcard-shadow-hover);
}

/* ---- media: badge top-left, wishlist top-right -------------------------- */
.zm-pcard-media {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  border-radius: var(--pcard-media-radius);
  background: var(--pcard-media-bg);
  overflow: hidden;
}

.zm-pcard-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.zm-pcard-link img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.zm-pcard-placeholder {
  color: var(--pcard-placeholder);
}

.zm-pcard-badge {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  padding: var(--badge-padding-y) var(--badge-padding-x);
  font-size: var(--badge-font-size);
  font-weight: var(--badge-font-weight);
  line-height: 1.5;
  border-radius: var(--pcard-badge-radius);
  background: var(--pcard-badge-bg);
  color: var(--pcard-badge-text);
}

.zm-pcard-chip {
  position: absolute;
  bottom: var(--space-2);
  left: var(--space-2);
  padding: 2px var(--space-2);
  font-size: 0.7rem;
  border-radius: var(--badge-radius);
  background: var(--color-brand-secondary);
  color: var(--color-brand-secondary-contrast);
}

.zm-pcard-sponsored {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  padding: 2px var(--space-2);
  font-size: 0.7rem;
  border-radius: var(--badge-radius);
  background: var(--color-surface-inverse);
  /* Was `var(--color-surface)`. Correct only while surfaces are opaque — under
     liquid glass (Micro-prompt 35) the label would turn translucent and the
     "Sponsored" tag would fade into its own dark chip. The text colour of an
     inverse-surface chip is the inverse text colour. Identical in every theme
     shipped before this one. */
  color: var(--color-text-inverse);
}

.zm-pcard-fav {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--pcard-fav-bg);
  color: var(--pcard-fav-icon);
  box-shadow: var(--pcard-fav-shadow);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-base), transform var(--dur-fast) var(--ease-base);
}

.zm-pcard-fav:hover,
.zm-pcard-fav.active {
  color: var(--pcard-fav-icon-active);
}

/* ---- body --------------------------------------------------------------- */
.zm-pcard-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-top: var(--pcard-gap);
}

.zm-pcard-title {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.3;
}

.zm-pcard-title a {
  display: -webkit-box;
  -webkit-line-clamp: var(--pcard-title-lines);
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--pcard-title);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-base);
}

.zm-pcard-title a:hover {
  color: var(--pcard-title-hover);
}

.zm-pcard-seller {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  text-decoration: none;
}

.zm-pcard-seller:hover {
  color: var(--pcard-title-hover);
}

.zm-pcard-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-2);
}

.zm-pcard-figures {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.zm-pcard-prices {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.zm-pcard-now {
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.1;
  color: var(--pcard-price);
}

.zm-pcard-was {
  font-size: 0.8rem;
  color: var(--pcard-was);
}

.zm-pcard-rating {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.8rem;
  line-height: 1.2;
  color: var(--pcard-rating);
}

.zm-pcard-score {
  font-weight: 600;
}

/* ---- circular add-to-cart button ---------------------------------------- */
.zm-pcard-cart {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--pcard-cart-size);
  height: var(--pcard-cart-size);
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--pcard-cart-bg);
  color: var(--pcard-cart-text);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-base);
}

.zm-pcard-cart:hover:not(:disabled) {
  background: var(--pcard-cart-bg-hover);
}

/* Out of stock (real `in_stock`) and the in-flight state the handler sets. */
.zm-pcard-cart:disabled,
.zm-pcard-cart.disabled {
  background: var(--pcard-cart-bg-disabled);
  color: var(--pcard-cart-text-disabled);
  cursor: not-allowed;
}

/* Micro-interaction (Micro-prompt 31): a brief press-pulse confirming the tap.
   Pure CSS — the delegated handler in cart-widget.js is untouched, and the
   Prompt 22 toast still fires. */
@keyframes zm-cart-pop {
  0% { transform: scale(1); }
  45% { transform: scale(0.85); }
  100% { transform: scale(1); }
}

.zm-pcard-cart:active:not(:disabled) {
  /* longhands, not the shorthand: a shorthand containing var() is deferred by
     the parser, so `animationName` cannot be read back off the rule. */
  animation-name: zm-cart-pop;
  animation-duration: 320ms;
  animation-timing-function: var(--ease-base);
}

/* The quantity stepper stays (it is existing cart wiring) but is kept compact
   so it does not dominate the reference's arrangement. */
.zm-pcard-qty {
  width: 100px;
  margin-top: var(--space-1);
}

/*--------------------------------------------------------------
 Zan Market — 2-column mobile product grid (Micro-prompt 31).

 The reference's "Bidhaa Maarufu" is a 2-up grid on a phone. The grid system is
 Bootstrap's own `row-cols-*`, so this only re-points the narrow breakpoints —
 the desktop columns are unchanged.
--------------------------------------------------------------*/
@media (max-width: 575.98px) {
  .product-grid.row-cols-1 {
    --bs-gutter-x: var(--space-3);
    --bs-gutter-y: var(--space-3);
  }

  .zm-pcard-now {
    font-size: 0.98rem;
  }

  .zm-pcard-was {
    font-size: 0.74rem;
  }

  .zm-pcard-title {
    font-size: 0.86rem;
  }
}
/*--------------------------------------------------------------
 Zan Market — section header (Micro-prompt 30).

 Rendered by js/components/section-header.js so the categories block here and
 the popular-products block in Micro-prompt 31 share one implementation.
 Tokens only.
--------------------------------------------------------------*/
.zm-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--section-header-gap);
  margin-bottom: var(--section-header-margin);
}

.zm-section-header-lead {
  display: flex;
  align-items: center;
  gap: var(--section-header-gap);
  min-width: 0;
}

.zm-section-header-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--section-header-icon);
}

.zm-section-header-title {
  margin: 0;
  font-size: 1.45rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--section-header-title);
}

.zm-section-header-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex: 0 0 auto;
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--section-header-link);
  transition: color var(--dur-fast) var(--ease-base);
}

.zm-section-header-link:hover,
.zm-section-header-link:focus-visible {
  color: var(--section-header-link-hover);
}

/* Carousel arrows: right-aligned under the header. Hidden below `lg`, where the
   row scrolls by touch instead (see the mobile block at the end of this file). */
.zm-cat-arrows {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

/*--------------------------------------------------------------
 Zan Market — category row: native scroll on mobile (Micro-prompt 30).

 `js/script.js:80` owns `.category-carousel` with `slidesPerView` 2/3/5/8 and is
 deliberately UNCHANGED, so below `lg` the reference's edge-to-edge scroll row is
 produced in CSS instead:

   - the wrapper becomes a real scroll container (`overflow-x: auto`) with
     `scroll-snap-type: x mandatory`;
   - Swiper's inline `transform: translate3d(...)` on the wrapper and its inline
     `width`/`margin-right` on the slides are neutralised with `!important`
     (a stylesheet `!important` beats a non-important inline style);
   - `touch-action: pan-x` is re-asserted, because Swiper sets `pan-y` to keep
     horizontal gestures for itself — without this the browser would refuse the
     native horizontal pan.

 At `lg` and up none of this applies: the element is an ordinary Swiper again and
 the arrows drive it.
--------------------------------------------------------------*/
@media (max-width: 991.98px) {
  .zm-cat-arrows {
    display: none;
  }

  .category-carousel .swiper-wrapper {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    transform: none !important;
    transition: none !important;
    padding: 0 var(--space-4) var(--space-3);
    scrollbar-width: none;
  }

  .category-carousel .swiper-wrapper::-webkit-scrollbar {
    display: none;
  }

  .category-carousel .swiper-slide {
    flex: 0 0 auto;
    width: auto !important;
    margin-right: var(--space-4) !important;
    scroll-snap-align: start;
  }

  .zm-cat-tile {
    width: var(--category-tile-size-mobile);
    height: var(--category-tile-size-mobile);
  }

  .zm-cat-name {
    font-size: 0.8rem;
  }
}
/*--------------------------------------------------------------
 Zan Market — hero promo card (Micro-prompt 29).

 Restyle of the existing hero into the reference's rounded brand-red card:
 copy on the left, lifestyle art on the right, gold pill CTA, dot pagination.
 The carousel itself is the template's own `main-swiper` config
 (js/script.js:26) — untouched. Tokens only; no raw colours.

 `black` appears once, inside a mask-image gradient: that is a mask alpha, not
 a painted colour, and CSS masks take no custom property.
--------------------------------------------------------------*/
.zm-hero {
  padding: var(--space-5) 0 var(--space-3);
}

.zm-hero-swiper {
  border-radius: var(--hero-radius);
}

.zm-hero-card {
  position: relative;
  display: flex;
  align-items: center;
  min-height: var(--hero-min-height);
  padding: var(--hero-padding);
  padding-bottom: calc(var(--hero-padding) + var(--space-5));
  border-radius: var(--hero-radius);
  overflow: hidden;
  background-image: linear-gradient(135deg, var(--hero-bg-from) 0%, var(--hero-bg-to) 100%);
}

/* ---- lifestyle art -----------------------------------------------------
   The banner art spans the whole card — its own composition already puts the
   subject on the right — and a brand-red gradient is laid over the left where
   the copy sits. Cropping it into a narrow right-hand panel zoomed it into an
   unreadable close-up (first attempt), so the art stays full-bleed and the
   gradient does the separating. */
.zm-hero-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: right center;
}

/* Must be ::after, not ::before: ::before is the card's FIRST child, so the
   absolutely-positioned <img> sibling would paint over it. ::after comes last
   and therefore sits above the art, with .zm-hero-copy (z-index 1) above both. */
.zm-hero-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--hero-fade-image);
}

/* ---- copy -------------------------------------------------------------- */
.zm-hero-copy {
  position: relative;
  z-index: 1;
  max-width: 62%;
  color: var(--hero-text);
}

.zm-hero-welcome {
  margin: 0 0 var(--space-1);
  font-size: 0.95rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--hero-welcome-text);
}

.zm-hero-title {
  margin: 0 0 var(--space-2);
  font-size: 2rem;
  font-weight: var(--font-weight-heading);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--hero-text);
}

.zm-hero-subtext {
  margin: 0 0 var(--space-4);
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--hero-welcome-text);
}

/* ---- CTAs -------------------------------------------------------------- */
.zm-hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.zm-hero-cta,
.zm-hero-ghost {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  border-radius: var(--hero-cta-radius);
  transition: background-color var(--dur-fast) var(--ease-base);
}

.zm-hero-cta {
  background-color: var(--hero-cta-bg);
  color: var(--hero-cta-text);
}

.zm-hero-cta:hover,
.zm-hero-cta:focus-visible {
  background-color: var(--hero-cta-bg-hover);
  color: var(--hero-cta-text);
}

/* The reference shows one CTA; the template's second link is kept as a ghost
   button rather than dropped, so no content or destination is lost. */
.zm-hero-ghost {
  background-color: transparent;
  color: var(--hero-ghost-text);
  box-shadow: inset 0 0 0 1px var(--hero-ghost-border);
}

.zm-hero-ghost:hover,
.zm-hero-ghost:focus-visible {
  background-color: var(--hero-ghost-bg-hover);
  color: var(--hero-ghost-text);
}

/* ---- pagination dots (the reference's small circular style) ------------- */
.zm-hero-dots {
  bottom: var(--space-4) !important;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.zm-hero-dots .swiper-pagination-bullet {
  width: var(--hero-dot-size);
  height: var(--hero-dot-size);
  margin: 0 !important;
  border-radius: var(--radius-pill);
  background-color: var(--hero-dot-bg);
  opacity: 1;
  transition: width var(--dur-base) var(--ease-base), background-color var(--dur-base) var(--ease-base);
}

.zm-hero-dots .swiper-pagination-bullet-active {
  width: var(--hero-dot-active-width);
  background-color: var(--hero-dot-active-bg);
}

/* ---- the stats that used to sit inside the hero ------------------------- */
.zm-hero-stats {
  padding: var(--space-5) 0 0;
}

.zm-hero-stats p {
  color: var(--color-text);
}

.zm-hero-stats .text-uppercase {
  color: var(--color-text-muted);
}

/* ---- mobile: crop the art behind the copy, keep the card feel ----------- */
@media (max-width: 767.98px) {
  .zm-hero-card {
    min-height: 210px;
    padding: var(--space-5);
    padding-bottom: calc(var(--space-5) + var(--space-5));
  }

  .zm-hero-copy {
    max-width: 68%;
  }

  .zm-hero-title {
    font-size: 1.5rem;
  }

  .zm-hero-welcome,
  .zm-hero-subtext {
    font-size: 0.8rem;
  }

  .zm-hero-art {
    /* Stays full-bleed; only the focal point shifts so the subject is not
       cropped out of a narrow card. */
    object-position: 72% center;
  }

  /* The copy needs a wider share on a narrow card, and the gradient under it
     has to reach further so the text never sits on the photo. */
  .zm-hero-card::after {
    background-image: var(--hero-fade-image-mobile);
  }

  .zm-hero-actions {
    gap: var(--space-2);
  }

  .zm-hero-cta,
  .zm-hero-ghost {
    padding: var(--space-2) var(--space-4);
    font-size: 0.8rem;
  }
}

/* ==========================================================================
   Theme + colour mode (Micro-prompt 32)
   --------------------------------------------------------------------------
   Two controls share this section:
     .zm-mode-btn     the header quick toggle (app bar + desktop arrangements)
     .zm-appearance   the full theme/mode picker in Account -> Settings, built
                      by js/theme/theme-engine.js

   Every value below resolves to a token in css/tokens/*. No raw colour, radius
   or shadow is declared here — the acceptance grep in the build log §13.9
   covers this file. The sun/moon swap is pure CSS keyed on <html data-mode>,
   so no script ever touches the icon.
   ========================================================================== */

/* ---- header quick toggle ------------------------------------------------ */
.zm-mode-dd {
  display: inline-flex;
  align-items: center;
}

.zm-mode-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 0;
  background: none;
  border-radius: var(--radius-sm);
  color: var(--icon-color);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-base),
              color var(--dur-fast) var(--ease-base);
}

.zm-mode-btn:hover,
.zm-mode-btn:focus-visible {
  background-color: var(--dropdown-item-hover-bg);
  color: var(--icon-color-hover);
}

/* The app bar sits on the brand band, so it needs the on-brand text colour and
   hover fill rather than the page-level icon tokens. */
.zm-mode-btn--appbar {
  color: var(--appbar-text);
}

.zm-mode-btn--appbar:hover,
.zm-mode-btn--appbar:focus-visible {
  background-color: var(--bnav-active-bg);
  color: var(--appbar-text);
}

.zm-mode-ico {
  display: inline-flex;
}

/* The moon is the dark-mode icon: hidden until dark is in effect. */
.zm-mode-ico-moon {
  display: none;
}

:root[data-mode="dark"] .zm-mode-ico-sun {
  display: none;
}

:root[data-mode="dark"] .zm-mode-ico-moon {
  display: inline-flex;
}

/* ---- the mode dropdown -------------------------------------------------- */
.zm-mode-menu {
  min-width: 11rem;
}

.zm-mode-menu .dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--dropdown-text);
}

.zm-mode-menu .dropdown-item.active,
.zm-mode-menu .dropdown-item[aria-checked="true"] {
  background-color: var(--dropdown-item-hover-bg);
  color: var(--dropdown-item-hover-text);
  font-weight: 600;
}

/* A leading rule on the active row — a plain box, so no colour literal and no
   glyph font is involved. */
.zm-mode-menu .dropdown-item::before {
  content: "";
  flex: 0 0 auto;
  width: 3px;
  height: 1em;
  border-radius: var(--radius-pill);
  background-color: transparent;
}

.zm-mode-menu .dropdown-item[aria-checked="true"]::before {
  background-color: var(--color-brand-primary);
}

/* ---- Account -> Settings picker ---------------------------------------- */
.zm-theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3);
}

.zm-theme-opt {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-base),
              border-color var(--dur-fast) var(--ease-base);
}

.zm-theme-opt:hover {
  background-color: var(--color-surface-alt);
}

.zm-theme-opt[aria-checked="true"] {
  border-color: var(--color-brand-primary);
  box-shadow: inset 0 0 0 1px var(--color-brand-primary);
}

.zm-theme-swatch {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface-alt);
}

/* All four themes have token files now (`default` Prompts 27-31,
   `neo-brutalism` Prompt 33, `material3` Prompt 34, `liquid-glass` Prompt 35),
   so every swatch shows a real preview and none keeps the dashed placeholder.
   Each preview deliberately uses tokens that are STABLE ACROSS THEMES — the
   shape must show its own theme whichever theme is currently active (§20.6). */
.zm-theme-opt[data-zm-theme-swatch="default"] .zm-theme-swatch {
  border-style: solid;
  border-color: var(--color-brand-primary);
  background-image: linear-gradient(
    135deg,
    var(--color-brand-primary) 0 50%,
    var(--color-accent) 50% 100%
  );
}

/* The brutalist preview: square, flat brand red, hard ink rule.
   `--radius-none` is 0 in all three themes, so the squareness is stable; the
   rule uses `--bs-border-width` (1px default, 2px neo, 1px M3 — never 0) rather
   than `--card-border-width`, which material3 sets to 0 and which would
   therefore strip this preview's outline while M3 is the active theme. */
.zm-theme-opt[data-zm-theme-swatch="neo-brutalism"] .zm-theme-swatch {
  border-style: solid;
  border-width: var(--bs-border-width);
  border-color: var(--color-text);
  border-radius: var(--radius-none);
  background-color: var(--color-brand-primary);
}

/* The Material 3 preview: a circle (M3's signature FAB shape), brand red over
   the primary-container tone, with an elevation shadow. A proportional 50%
   rather than `--radius-pill`, because neo-brutalism sets that token to 0 and
   would square this preview off — the same drift, in the other direction. */
.zm-theme-opt[data-zm-theme-swatch="material3"] .zm-theme-swatch {
  border-style: solid;
  border-color: var(--color-brand-primary-subtle);
  border-radius: 50%;
  background-color: var(--color-brand-primary);
  background-image: linear-gradient(
    135deg,
    var(--color-brand-primary) 0 52%,
    var(--color-brand-primary-subtle) 52% 100%
  );
  box-shadow: var(--shadow-xs);
}

/* The liquid-glass preview: a soft squircle with a white hairline. The edge is
   `--color-text-inverse`, which is white in all four themes — `--color-border`
   would turn it ink-black while neo-brutalism is active. The 30% is a
   proportional radius, not a scale step, so the shape is theme-invariant; the
   same reasoning as the 50% above. */
.zm-theme-opt[data-zm-theme-swatch="liquid-glass"] .zm-theme-swatch {
  border-style: solid;
  border-color: var(--color-text-inverse);
  border-radius: 30%;
  background-color: var(--color-brand-primary);
  background-image: linear-gradient(
    135deg,
    var(--color-brand-primary) 0 45%,
    var(--color-brand-primary-subtle) 45% 100%
  );
  box-shadow: var(--shadow-xs);
}

.zm-theme-name {
  font-size: 0.9375rem;
  font-weight: 600;
}

.zm-mode-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.zm-mode-opt {
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background-color: var(--color-surface);
  color: var(--color-text);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-base),
              border-color var(--dur-fast) var(--ease-base),
              color var(--dur-fast) var(--ease-base);
}

.zm-mode-opt:hover {
  background-color: var(--color-surface-alt);
}

.zm-mode-opt[aria-checked="true"] {
  background-color: var(--color-brand-primary);
  border-color: var(--color-brand-primary);
  color: var(--color-brand-primary-contrast);
}

.zm-appearance-note {
  margin: var(--space-4) 0 0;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background-color: var(--color-warning-subtle);
  color: var(--color-text);
  font-size: 0.875rem;
}

/* ==========================================================================
   Glass surfaces (Micro-prompt 35)
   --------------------------------------------------------------------------
   The one place `--surface-blur` is consumed. It is `none` in every theme but
   liquid-glass, so this whole group is inert elsewhere and no other theme pays
   for it.

   Why a grouped rule rather than an edit to each component: the token-layer
   discipline forbids a theme file from naming a selector (§18.9 / §19.5), and
   `backdrop-filter` cannot be expressed as a token *value* that applies itself.
   A single seam here — component CSS consuming a layer-3 token — is the same
   indirection every other themed property uses.

   These are exactly the surfaces that read as "glass" once the theme makes
   their background colours translucent: the app bar, the header shell, the
   bottom nav, product cards, category tiles, menus, drawers, the hero and the
   toast.

   NOTE `backdrop-filter` makes an element a containing block for
   `position: fixed` descendants and creates a stacking context. The offcanvas
   drawers are direct children of <body> (not nested inside any of these), and
   Bootstrap's dropdown menus are `position: absolute`, so neither is affected —
   verified in the build log §21.6. */
.zm-header,
.zm-appbar,
.zm-bnav,
.zm-pcard,
.product-item,
.zm-cat-tile,
.zm-hero-card,
.zm-toast,
.dropdown-menu,
.offcanvas {
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
}

/* ==========================================================================
   Auth entry screen — login.html / register.html
   --------------------------------------------------------------------------
   A full-viewport two-column entry screen per the reference design: a quiet
   form panel on the left, a saturated photographic brand panel on the right.

   These two pages deliberately render NO header, footer or bottom nav — the
   screen owns the whole viewport — which is why this shell is authored in the
   page rather than in partials/header.html.

   Every colour resolves to a token in css/tokens/ (see the `auth shell` group
   in tokens/components.css), so all four themes and both colour modes apply.
   ========================================================================== */

.zm-auth {
  display: grid;
  grid-template-columns: 1fr;          /* mobile: the form owns the viewport */
  min-height: 100vh;
  min-height: 100dvh;
  background-color: var(--auth-panel-bg);
  color: var(--auth-panel-text);
}

/* The reference splits 452:468 — very slightly in favour of the brand panel.
   From `lg` up the split is pinned to the viewport, so a tall form (register
   has five fields) scrolls inside its own panel instead of dragging the brand
   panel off-screen. */
@media (min-width: 992px) {
  .zm-auth {
    grid-template-columns: 1fr 1.04fr;
    height: 100vh;
    height: 100dvh;
  }
}

/* ---- left: form panel ---------------------------------------------------- */
.zm-auth-panel {
  display: flex;
  flex-direction: column;
  padding: var(--auth-gutter);
  padding-bottom: calc(var(--auth-gutter) + env(safe-area-inset-bottom, 0px));
}

.zm-auth-bar {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-3);
}

.zm-auth-back {
  justify-self: start;
  font-size: 0.8125rem;
  color: var(--auth-muted);
  text-decoration: none;
}
.zm-auth-back:hover { color: var(--auth-panel-text); }

.zm-auth-wordmark {
  grid-column: 2;
  font-family: var(--auth-display-font);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--auth-panel-text);
  text-decoration: none;
  white-space: nowrap;
}

.zm-auth-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  max-width: var(--auth-form-width);
  margin-inline: auto;
  padding-block: var(--space-3);
}

.zm-auth-title {
  margin: 0 0 var(--space-4);
  font-family: var(--auth-display-font);
  font-size: clamp(2rem, 1.4rem + 2.2vw, 2.75rem);
  font-weight: 700;
  line-height: 1.05;
  color: var(--auth-panel-text);
}

/* ---- fields: filled and borderless, as in the reference ------------------
   The reference names each field inside the control as a placeholder and shows
   no label. The <label> stays in the DOM for screen readers and for the
   label/for-id association; only its box is hidden. */
.zm-auth .form-label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.zm-auth .form-control {
  height: var(--auth-field-height);
  padding-inline: var(--space-4);
  background-color: var(--auth-field-bg);
  border: 1px solid transparent;
  border-radius: var(--auth-field-radius);
  color: var(--auth-field-text);
  font-size: 0.9375rem;
}

.zm-auth .form-control::placeholder { color: var(--auth-field-placeholder); }

.zm-auth .form-control:focus {
  background-color: var(--auth-field-bg);
  border-color: var(--input-border-focus);
  color: var(--auth-field-text);
  box-shadow: none;
}

/* Bootstrap's tick/cross icon is drawn for a bordered field; in a filled one it
   collides with the text. The message below the field still carries it. */
.zm-auth .form-control.is-invalid { background-image: none; }

.zm-auth .invalid-feedback { font-size: 0.8125rem; }

.zm-auth .form-text { font-size: 0.75rem; color: var(--auth-muted); }

/* ---- password reveal (the eye in the reference) -------------------------- */
.zm-auth-field { position: relative; }

.zm-auth-reveal {
  position: absolute;
  top: 50%;
  right: var(--space-3);
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 0;
  background: none;
  border-radius: var(--radius-sm);
  color: var(--auth-field-placeholder);
  cursor: pointer;
}
.zm-auth-reveal:hover,
.zm-auth-reveal:focus-visible { color: var(--auth-panel-text); }
.zm-auth-reveal[aria-pressed="true"] { color: var(--color-brand-primary-text); }

/* The icon swap is pure CSS keyed on aria-pressed — the same trick the header's
   light/dark toggle uses, so no script touches the glyph. */
.zm-auth-reveal .zm-auth-reveal-off { display: none; }
.zm-auth-reveal[aria-pressed="true"] .zm-auth-reveal-on { display: none; }
.zm-auth-reveal[aria-pressed="true"] .zm-auth-reveal-off { display: inline-flex; }

/* ---- actions ------------------------------------------------------------- */
.zm-auth-forgot {
  display: block;
  margin: calc(var(--space-3) * -1) 0 var(--space-5);
  text-align: right;
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--auth-panel-text);
  text-decoration: none;
}
.zm-auth-forgot:hover { color: var(--color-brand-primary-text); text-decoration: underline; }

.zm-auth-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--auth-field-height);
  padding: var(--space-3) var(--space-5);
  border: var(--card-border-width) solid transparent;
  border-radius: var(--auth-cta-radius);
  background-color: var(--auth-cta-bg);
  color: var(--auth-cta-text);
  font-size: 0.9375rem;
  font-weight: 700;
  transition: background-color var(--dur-fast) var(--ease-base);
}
.zm-auth-cta:hover,
.zm-auth-cta:focus-visible { background-color: var(--auth-cta-bg-hover); color: var(--auth-cta-text); }
.zm-auth-cta:disabled { opacity: 0.6; }

.zm-auth-or {
  display: block;
  margin: var(--space-2) 0;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--auth-muted);
}

.zm-auth-social {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--auth-field-height);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--auth-social-border);
  border-radius: var(--auth-cta-radius);
  background-color: var(--auth-social-bg);
  color: var(--auth-social-text);
  font-size: 0.9375rem;
  font-weight: 700;
  transition: background-color var(--dur-fast) var(--ease-base);
}
.zm-auth-social + .zm-auth-social { margin-top: var(--space-3); }
.zm-auth-social:hover,
.zm-auth-social:focus-visible { background-color: var(--auth-social-bg-hover); color: var(--auth-social-text); }
/* The Google button disables itself while the ~200 KB Identity Services SDK
   loads on first click. Without this it looked identical but ignored clicks —
   which reads as "broken", not "loading". */
.zm-auth-social:disabled { opacity: 0.55; cursor: progress; }

/* ---- footer of the form -------------------------------------------------- */
.zm-auth-foot {
  margin: var(--space-4) 0 0;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--auth-muted);
}
.zm-auth-foot a {
  font-weight: 700;
  color: var(--auth-panel-text);
  text-decoration: none;
}
.zm-auth-foot a:hover { text-decoration: underline; }

.zm-auth-shop { margin: var(--space-5) 0 0; text-align: center; }
.zm-auth-shop a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.8125rem;
  color: var(--auth-muted);
  text-decoration: none;
}
.zm-auth-shop a:hover { color: var(--auth-panel-text); text-decoration: underline; }
.zm-auth-shop-hint { margin: var(--space-1) 0 0; font-size: 0.6875rem; color: var(--auth-field-placeholder); }

/* ---- right: brand panel -------------------------------------------------- */
.zm-auth-brand {
  position: relative;
  display: none;                        /* mobile: the form has the viewport */
  overflow: hidden;
  isolation: isolate;                   /* keep the blend modes self-contained */
  background-color: var(--auth-brand-bg);
  color: var(--auth-brand-text);
}

@media (min-width: 992px) {
  .zm-auth-brand { display: flex; flex-direction: column; }
}

/* Duotone, as in the reference: the panel is a photograph carried entirely by
   the brand colour. Greyscale removes the source image's own hues (which would
   fight the brand), then the brand colour multiplies over it. */
.zm-auth-brand-art {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 32%;
  filter: grayscale(1) contrast(1.08);
}

.zm-auth-brand::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--auth-brand-bg);
  mix-blend-mode: multiply;
}

/* A scrim top and bottom so the white chrome text keeps its contrast wherever
   the photograph happens to be bright. */
.zm-auth-brand::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: linear-gradient(
    to bottom,
    var(--overlay-black-20) 0,
    transparent 22%,
    transparent 74%,
    var(--overlay-black-20) 100%
  );
}

.zm-auth-brand-inner {
  position: relative;
  z-index: 1;                            /* above the scrim */
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  padding: var(--auth-gutter);
}

.zm-auth-brand-top,
.zm-auth-brand-bottom {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-3);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
}
.zm-auth-brand-top { border-bottom: 1px solid var(--auth-brand-rule); }
.zm-auth-brand-bottom { border-top: 1px solid var(--auth-brand-rule); }

.zm-auth-brand-copy {
  margin: var(--space-6) 0 0;
  max-width: 13em;
  font-family: var(--auth-display-font);
  font-size: clamp(1.125rem, 1rem + 0.6vw, 1.375rem);
  font-weight: 400;
  line-height: 1.35;
}

.zm-auth-brand-caption {
  margin: auto 0 var(--space-5) auto;     /* bottom-right, as in the reference */
  max-width: 11em;
  text-align: right;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--auth-brand-caption);
}

/* ---- short viewports -----------------------------------------------------
   The registration form has five fields, so on a short window the form panel
   scrolls rather than dragging the brand panel off-screen. The scrollbar itself
   is suppressed: a visible track down the middle of a designed entry screen is
   noise, and with the rhythm above the register form clears a ~680px viewport
   anyway — this is a fallback for unusually short windows, not the normal case. */
.zm-auth-panel {
  overflow-y: auto;
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* legacy Edge */
}
.zm-auth-panel::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* Bootstrap's `.mb-3` is `margin-bottom: 1rem !important`, so the override has
   to carry `!important` too. Tighter than 1rem because the five-field register
   form has to clear the viewport without scrolling. */
.zm-auth form > .mb-3 { margin-bottom: var(--space-3) !important; }

/* ==========================================================================
   Legal documents — /terms and /policy
   --------------------------------------------------------------------------
   Rendered by js/legal-page.js from js/content/legal.js. Everything here is
   token-driven; nothing declares a raw colour, radius or shadow.

   Two decisions that shape the whole section:
     - the measure is capped in `ch`, so lines stay readable at any width;
     - the contents list is sticky and follows the reader, which is what makes
       a twenty-section policy navigable instead of a scroll.
   ========================================================================== */

.zm-legal {
  max-width: var(--legal-measure);
  color: var(--legal-text);
  font-size: 1rem;
  line-height: 1.75;
}

/* Anchored sections must clear the sticky header when deep-linked. */
.zm-legal-section { scroll-margin-top: 6rem; }

.zm-legal-updated {
  margin: 0 0 var(--space-5);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--legal-text);
}

.zm-legal-notice {
  margin: 0 0 var(--space-6);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--legal-rule);
  border-left: 3px solid var(--color-warning);
  border-radius: var(--radius-sm);
  background-color: var(--legal-notice-bg);
  color: var(--legal-notice-text);
  font-size: 0.9375rem;
}
.zm-legal-notice p { margin: 0; }

.zm-legal-intro { margin-bottom: var(--space-7); }
.zm-legal-intro p { margin: 0 0 var(--space-4); }

.zm-legal-section {
  padding-top: var(--space-6);
  margin-bottom: var(--space-6);
  border-top: 1px solid var(--legal-rule);
}

.zm-legal-heading {
  margin: 0 0 var(--space-4);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--legal-heading);
}

/* ---- prose --------------------------------------------------------------
   The source documents are plain <p> / <ul> / <li> / <strong> / <a>, so this
   block is the entire typographic contract for them. */
.zm-legal-body p { margin: 0 0 var(--space-4); }
.zm-legal-body p:last-child { margin-bottom: 0; }

.zm-legal-body ul,
.zm-legal-body ol {
  margin: 0 0 var(--space-4);
  padding-left: var(--space-5);
}
.zm-legal-body li { margin-bottom: var(--space-2); }
.zm-legal-body li:last-child { margin-bottom: 0; }

.zm-legal-body strong { color: var(--legal-strong); font-weight: 700; }

.zm-legal-body a {
  color: var(--legal-link);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.zm-legal-body a:hover { color: var(--legal-heading); }

.zm-legal-foot {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--legal-rule);
}
.zm-legal-related { margin: 0; font-size: 0.9375rem; }
.zm-legal-related a { color: var(--legal-link); }

/* ---- contents list ------------------------------------------------------- */
.zm-legal-toc {
  position: sticky;
  top: var(--space-5);
  max-height: calc(100vh - var(--space-8));
  overflow-y: auto;
  padding-right: var(--space-3);
}

.zm-legal-toc-title {
  margin: 0 0 var(--space-3);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--legal-toc-strong);
}

.zm-legal-toc-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-left: 1px solid var(--legal-rule);
}

.zm-legal-toc-link {
  display: flex;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  margin-left: -1px;
  border-left: 2px solid transparent;
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--legal-toc-text);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-base),
              border-color var(--dur-fast) var(--ease-base);
}
.zm-legal-toc-link:hover { color: var(--legal-toc-strong); }

.zm-legal-toc-link.is-active {
  border-left-color: var(--legal-toc-active-text);
  color: var(--legal-toc-active-text);
  font-weight: 700;
}

.zm-legal-toc-num {
  flex: 0 0 auto;
  min-width: 1.25em;
  color: var(--legal-toc-text);
  font-variant-numeric: tabular-nums;
}
.zm-legal-toc-link.is-active .zm-legal-toc-num { color: inherit; }

/* ---- printing ------------------------------------------------------------
   Policy pages get printed and filed. Drop the site chrome, the contents list
   (useless on paper) and the page colouring, and keep the document legible. */
@media print {
  .zm-header,
  .zm-bnav,
  .zm-legal-toc,
  .page-header,
  footer,
  [data-partial] { display: none !important; }

  .zm-legal { max-width: none; color: var(--print-ink); }
  .zm-legal-notice { border-color: var(--print-ink); background: none; }
  .zm-legal-section { break-inside: avoid; }
  a { text-decoration: none; color: var(--print-ink); }
}

