/* ============================================================================
   Mazraatak — Design System            (branch: redesign/marketplace-ui)
   Loaded AFTER app.generated.css. Unlayered :root beats Tailwind's
   @layer theme, so every override below wins without !important.

   THE LEVER: Tailwind v4 utilities compile to var(--color-*) / var(--font-*).
   Re-tinting those variables re-skins markup we never touch — including the
   admin console, which hardcodes slate+blue and the brand has never reached.

   RULES THIS FILE ENFORCES
     1. One control rail: 36 / 44 / 52px. Nothing else is interactive-sized.
     2. Flat fills. No gradient CTAs, no coloured glows.
     3. One focus ring: 3px at 2px offset, everywhere.
     4. Gold means "verified" and nothing else.
     5. Arabic never asks for a weight the font does not ship (El Messiri
        stops at 700), so 800/900 are capped rather than synthesised.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   1. PALETTE
   --------------------------------------------------------------------------- */
:root {
  /* --- brand: deep forest green (600 = primary). Unchanged — client approved. */
  --color-emerald-50:  #eef6f0;  --color-green-50:  #eef6f0;
  --color-emerald-100: #d4e9db;  --color-green-100: #d4e9db;
  --color-emerald-200: #a8d2b5;  --color-green-200: #a8d2b5;
  --color-emerald-300: #72b587;  --color-green-300: #72b587;
  --color-emerald-400: #40965a;  --color-green-400: #40965a;
  --color-emerald-500: #2a8446;  --color-green-500: #2a8446;
  --color-emerald-600: #1e7a3c;  --color-green-600: #1e7a3c;
  --color-emerald-700: #155c2c;  --color-green-700: #155c2c;
  --color-emerald-800: #114a25;  --color-green-800: #114a25;
  --color-emerald-900: #0d3a1e;  --color-green-900: #0d3a1e;
  --color-emerald-950: #06240f;  --color-green-950: #06240f;

  /* teal folded into the same green so emerald→teal gradients read as green */
  --color-teal-50:  #eaf5ef;  --color-teal-100: #cde7d7; --color-teal-200: #9fd0b3;
  --color-teal-300: #5faa7f;  --color-teal-400: #2f8b50; --color-teal-500: #227a44;
  --color-teal-600: #155c2c;  --color-teal-700: #114a25; --color-teal-800: #0e3d20;
  --color-teal-900: #0a2f19;

  /* --- neutrals: warm agrarian ramp, hue ~120 at 4–8% saturation.
     Replaces stock Tailwind gray AND slate in one move (~3,250 utilities),
     which is what finally pulls the admin console onto the brand. */
  --color-gray-50:  #f7f9f6;  --color-slate-50:  #f7f9f6;
  --color-gray-100: #eef2ee;  --color-slate-100: #eef2ee;
  --color-gray-200: #dde4de;  --color-slate-200: #dde4de;
  --color-gray-300: #c5d0c7;  --color-slate-300: #c5d0c7;
  --color-gray-400: #9aa89d;  --color-slate-400: #9aa89d;
  --color-gray-500: #77877a;  --color-slate-500: #77877a;
  --color-gray-600: #5b6a5e;  --color-slate-600: #5b6a5e;
  --color-gray-700: #3c4940;  --color-slate-700: #3c4940;
  --color-gray-800: #26302a;  --color-slate-800: #26302a;
  --color-gray-900: #161e19;  --color-slate-900: #161e19;
  --color-gray-950: #0c1410;  --color-slate-950: #0c1410;
  /* zinc/neutral/stone appear occasionally; keep them on the same ramp */
  --color-zinc-100: #eef2ee; --color-zinc-200: #dde4de; --color-zinc-400: #9aa89d;
  --color-zinc-600: #5b6a5e; --color-zinc-700: #3c4940; --color-zinc-800: #26302a;
  --color-zinc-900: #161e19;
  --color-neutral-100: #eef2ee; --color-neutral-200: #dde4de; --color-neutral-400: #9aa89d;
  --color-neutral-600: #5b6a5e; --color-neutral-700: #3c4940; --color-neutral-800: #26302a;
  --color-neutral-900: #161e19;

  /* --- gold: the ONE scarce accent. amber/yellow (180 stock uses) land here. */
  --color-amber-50:  #fef7e8;  --color-yellow-50:  #fef7e8;
  --color-amber-100: #fdecc8;  --color-yellow-100: #fdecc8;
  --color-amber-200: #fbd88d;  --color-yellow-200: #fbd88d;
  --color-amber-300: #f9c052;  --color-yellow-300: #f9c052;
  --color-amber-400: #f6ae32;  --color-yellow-400: #f6ae32;
  --color-amber-500: #f4a11f;  --color-yellow-500: #f4a11f;
  --color-amber-600: #d98814;  --color-yellow-600: #d98814;
  --color-amber-700: #b06810;  --color-yellow-700: #b06810;
  --color-amber-800: #8a5211;  --color-yellow-800: #8a5211;
  --color-amber-900: #714312;  --color-yellow-900: #714312;
  --color-amber-950: #422309;  --color-yellow-950: #422309;

  /* --- El Messiri ships 400–700. Capping these stops the browser from
     synthesising 800/900 by smearing the outline — the single loudest
     "cheap Arabic build" tell. Fixes every font-extrabold / font-black
     in the markup without editing one .razor file. */
  --font-weight-extrabold: 700;
  --font-weight-black: 700;

  /* --- brand tokens */
  --mz-primary:   #1e7a3c;
  --mz-primary-d: #155c2c;
  --mz-primary-l: #eef6f0;
  --mz-gold:      #f4a11f;
  --mz-gold-d:    #b06810;
  --mz-gold-tint: #fef7e8;

  /* brand as TEXT needs more contrast than brand as a FILL */
  --mz-brand-txt: #1a6d36;

  --mz-ink:     #161e19;
  --mz-ink-2:   #3c4940;
  --mz-muted:   #5b6a5e;
  --mz-line:    #dde4de;
  --mz-line-soft: #eef2ee;
  --mz-surface: #ffffff;
  --mz-sunken:  #eef2ee;
  --mz-page-bg: #f7f9f6;

  /* --- semantic: a closed set. Nothing else may imply status. */
  --mz-success: #1e7a3c;  --mz-success-txt: #1a6d36;
  --mz-warning: #f4a11f;  --mz-warning-txt: #8a5211;
  --mz-danger:  #c2453d;  --mz-danger-txt:  #a83a33;
  --mz-info:    #2563cc;  --mz-info-txt:    #2563cc;

  /* --- the control rail. Every interactive control snaps to one of these. */
  --mz-h-sm: 36px;
  --mz-h-md: 44px;   /* default; clears the WCAG 2.5.5 target */
  --mz-h-lg: 52px;

  /* --- radii: mapped, never arbitrary */
  --mz-r-field: 10px;
  --mz-r-btn:   12px;
  --mz-r-card:  16px;
  --mz-r-sheet: 24px;
  --mz-r-pill:  999px;

  /* --- exactly three elevations */
  --mz-shadow-sm: 0 1px 2px rgba(12,20,16,.06);
  --mz-shadow:    0 4px 12px -2px rgba(12,20,16,.10);
  --mz-shadow-lg: 0 18px 40px -12px rgba(12,20,16,.22);

  /* --- one focus ring */
  --mz-ring: 0 0 0 3px color-mix(in srgb, var(--color-emerald-600) 35%, transparent);

  /* --- z ladder */
  --mz-z-sticky: 100;
  --mz-z-drawer: 800;
  --mz-z-modal: 1000;
  --mz-z-toast: 1200;

  --mz-disabled-bg: #dde4de;
  --mz-disabled-fg: #9aa89d;
}

.dark {
  --mz-ink:     #e8efe9;
  --mz-ink-2:   #b9c6bc;
  --mz-muted:   #8b9a8e;
  --mz-line:    #2a352d;
  --mz-line-soft: #1d2620;
  --mz-surface: #1a221c;
  --mz-sunken:  #111a15;
  --mz-page-bg: #0c1410;

  --mz-brand-txt:   #5cc47a;
  --mz-success-txt: #5cc47a;
  --mz-warning-txt: #f0bd63;
  --mz-danger-txt:  #e8837c;
  --mz-info-txt:    #6f9ff0;

  --mz-disabled-bg: #222c25;
  --mz-disabled-fg: #5d6b60;

  --mz-shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --mz-shadow:    0 4px 12px -2px rgba(0,0,0,.5);
  --mz-shadow-lg: 0 22px 48px -14px rgba(0,0,0,.65);
}

/* ---------------------------------------------------------------------------
   2. BASE
   --------------------------------------------------------------------------- */
body {
  font-family: "El Messiri", "Inter", -apple-system,
    BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background-color: var(--mz-page-bg);
  color: var(--mz-ink);
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* Arabic is a connected script: it needs more leading than Latin, and
   tracking/uppercase would sever the joins. */
body, p, li, td, th, label, input, textarea, select, button { letter-spacing: 0; }
p, li { line-height: 1.75; }

::selection { background: color-mix(in srgb, var(--color-emerald-600) 22%, transparent); }

@media (pointer: fine) {
  * { scrollbar-width: thin; scrollbar-color: #bfe0c8 transparent; }
  *::-webkit-scrollbar { width: 10px; height: 10px; }
  *::-webkit-scrollbar-thumb { background: #cfe7d6; border-radius: 999px; border: 3px solid transparent; background-clip: content-box; }
  .dark *::-webkit-scrollbar-thumb { background: #2a3a30; border: 3px solid transparent; background-clip: content-box; }
}

.no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.no-scrollbar::-webkit-scrollbar { display: none; }

/* Blazor's fatal-error bar (index.html). Blazor sets display:block on it. */
#blazor-error-ui {
  display: none; position: fixed; inset-inline: 0; bottom: 0; z-index: var(--mz-z-toast);
  padding: .875rem 1.25rem; background: var(--mz-danger); color: #fff;
  font-size: .9375rem; text-align: center; box-shadow: 0 -4px 16px -6px rgba(0,0,0,.4);
}
#blazor-error-ui a { color: #fff; font-weight: 700; text-decoration: underline; margin-inline-start: .75rem; }
#blazor-error-ui .dismiss { float: inline-end; cursor: pointer; text-decoration: none; font-size: 1.25rem; line-height: 1; }

.mz-animate-fade-in { animation: mz-fade-in .4s ease-out both; }
@keyframes mz-fade-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* Grid and flex children default to min-width:auto, so one nowrap token can
   widen a track and push the page sideways. */
.mz-shell, .mz-section { min-width: 0; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* In-page anchors must clear the sticky header instead of hiding under it. */
html { scroll-padding-block-start: 88px; }

/* ---------------------------------------------------------------------------
   3. COMPONENT LAYER
   Kept in @layer components so per-element Tailwind utilities still win
   where a call site genuinely needs a tweak.
   --------------------------------------------------------------------------- */
@layer components {

  /* ==== Shell + section rhythm ========================================== */
  .mz-shell { width: 100%; max-width: 1280px; margin-inline: auto; padding-inline: 1rem; }
  @media (min-width: 640px) { .mz-shell { padding-inline: 1.5rem; } }
  @media (min-width: 1024px) { .mz-shell { padding-inline: 2rem; } }
  .mz-shell-wide { max-width: none; }
  .mz-section { display: block; margin-block: 2rem; }
  @media (min-width: 1024px) { .mz-section { margin-block: 3rem; } }

  /* ==== Page header ===================================================== */
  .mz-page-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between;
    gap: 1rem; margin-bottom: 1.5rem; }
  .mz-page-header h1 { font-size: 1.5rem; font-weight: 700; color: var(--mz-ink); line-height: 1.25; letter-spacing: -.01em; }
  .mz-page-header .mz-page-sub { color: var(--mz-muted); font-size: .9rem; margin-top: .25rem; }
  .mz-page-actions { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }

  /* ==== Buttons ========================================================= */
  .mz-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
    height: var(--mz-h-md); padding-inline: 1.25rem;
    font-family: inherit; font-weight: 600; font-size: .95rem; line-height: 1;
    white-space: nowrap; cursor: pointer; text-decoration: none;
    border-radius: var(--mz-r-btn); border: 1.5px solid transparent;
    transition: background-color .12s ease, border-color .12s ease, color .12s ease, transform .06s ease;
  }
  .mz-btn:active { transform: translateY(1px); }
  .mz-btn:focus-visible { outline: none; box-shadow: var(--mz-ring); }
  .mz-btn:disabled, .mz-btn[disabled], .mz-btn.is-disabled {
    background: var(--mz-disabled-bg); color: var(--mz-disabled-fg);
    border-color: transparent; cursor: not-allowed; transform: none;
  }
  .mz-btn-sm { height: var(--mz-h-sm); padding-inline: .75rem; font-size: .875rem; }
  .mz-btn-lg { height: var(--mz-h-lg); padding-inline: 1.625rem; font-size: 1rem; font-weight: 700; }
  .mz-btn-block { width: 100%; }

  /* flat fills — a gradient CTA with a coloured glow is the loudest AI tell */
  .mz-btn-primary { background: var(--mz-primary); color: #fff; }
  .mz-btn-primary:hover:not(:disabled) { background: var(--mz-primary-d); }

  .mz-btn-outline, .mz-btn-secondary {
    background: var(--mz-surface); color: var(--mz-brand-txt);
    border-color: color-mix(in srgb, var(--mz-primary) 32%, transparent);
  }
  .mz-btn-outline:hover:not(:disabled), .mz-btn-secondary:hover:not(:disabled) {
    background: color-mix(in srgb, var(--mz-primary) 7%, transparent);
    border-color: color-mix(in srgb, var(--mz-primary) 55%, transparent);
  }
  .dark .mz-btn-outline, .dark .mz-btn-secondary { background: transparent; }

  .mz-btn-ghost { background: transparent; color: var(--mz-ink-2); }
  .mz-btn-ghost:hover:not(:disabled) { background: color-mix(in srgb, var(--mz-ink) 7%, transparent); color: var(--mz-ink); }

  .mz-btn-link { background: none; border: 0; height: auto; padding: 0; color: var(--mz-brand-txt);
    text-decoration: underline; text-underline-offset: 3px; font-weight: 600; }

  /* destructive is a TONE on a variant, not a sixth variant */
  .mz-btn-danger { background: transparent; color: var(--mz-danger-txt);
    border-color: color-mix(in srgb, var(--mz-danger) 38%, transparent); }
  .mz-btn-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--mz-danger) 8%, transparent); }
  .mz-btn-danger-solid { background: var(--mz-danger); color: #fff; }
  .mz-btn-danger-solid:hover:not(:disabled) { background: #a83a33; }

  /* gold is reserved for verification, not for CTAs */
  .mz-btn-gold { background: var(--mz-gold); color: #3a2400; }
  .mz-btn-gold:hover:not(:disabled) { background: #e0940f; }

  .mz-btn-icon { width: var(--mz-h-md); height: var(--mz-h-md); padding: 0; border-radius: var(--mz-r-field);
    background: transparent; color: var(--mz-ink-2); }
  .mz-btn-icon:hover:not(:disabled) { background: color-mix(in srgb, var(--mz-ink) 8%, transparent); }
  .mz-btn-icon-sm { width: var(--mz-h-sm); height: var(--mz-h-sm); }

  /* .mz-spin used to be defined only as `.mz-btn .mz-spin`, so the 28 call sites that
     use it outside a button - the global loading overlay, page loaders, card loaders -
     got no radius, no animation and no box model. Tailwind's preflight sets
     border-style: solid on every element, so the inline border-width those call sites
     pass still painted a border: the spinner rendered as a static green SQUARE.
     inline-block matters too - a bare <span> is inline, so width/height were ignored
     outside the button's flex context. */
  .mz-spin { display: inline-block; box-sizing: border-box; width: 16px; height: 16px;
    border: 2px solid currentColor; border-top-color: transparent;
    border-radius: 50%; animation: mz-spin .7s linear infinite; opacity: .9; }
  .mz-btn .mz-spin { width: 16px; height: 16px; }
  @keyframes mz-spin { to { transform: rotate(360deg); } }
  /* Still turns, just calmly - a frozen spinner reads as a hung page. */
  @media (prefers-reduced-motion: reduce) { .mz-spin { animation-duration: 1.8s; } }

  /* ==== Fields ========================================================== */
  .mz-field { display: flex; flex-direction: column; gap: .375rem; min-width: 0; }
  .mz-label { font-size: .875rem; font-weight: 600; color: var(--mz-ink); }
  .mz-label .mz-req { color: var(--mz-danger-txt); margin-inline-start: .15rem; }
  .mz-hint { font-size: .8125rem; color: var(--mz-muted); line-height: 1.5; }
  /* error sits ABOVE the control so the mobile keyboard can never hide it */
  .mz-field-error { font-size: .8125rem; font-weight: 600; color: var(--mz-danger-txt);
    display: flex; align-items: center; gap: .375rem; }
  .mz-field.is-invalid { border-inline-start: 4px solid var(--mz-danger); padding-inline-start: .75rem; }

  .mz-input, .mz-select, .mz-textarea {
    width: 100%; min-width: 0; font-family: inherit;
    font-size: 1rem;                 /* 16px floor: below this iOS force-zooms */
    height: var(--mz-h-md); padding-inline: .875rem;
    color: var(--mz-ink); background: var(--mz-surface);
    border: 1.5px solid var(--mz-line); border-radius: var(--mz-r-field);
    text-align: start;
    transition: border-color .12s ease, box-shadow .12s ease;
  }
  .mz-textarea { height: auto; min-height: 96px; padding-block: .625rem; line-height: 1.7; resize: vertical; }
  .mz-input::placeholder, .mz-textarea::placeholder { color: var(--mz-muted); }
  .mz-input:focus, .mz-select:focus, .mz-textarea:focus {
    outline: none; border-color: var(--color-emerald-500); box-shadow: var(--mz-ring);
  }
  .mz-input:disabled, .mz-select:disabled, .mz-textarea:disabled {
    background: var(--mz-sunken); color: var(--mz-muted); cursor: not-allowed;
  }
  .is-invalid .mz-input, .is-invalid .mz-select, .is-invalid .mz-textarea,
  .mz-input.is-invalid, .mz-select.is-invalid { border-color: var(--mz-danger); }

  .mz-select { appearance: none; padding-inline-end: 2.25rem;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235b6a5e' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-size: 18px; background-position: right .75rem center; }
  [dir="rtl"] .mz-select { background-position: left .75rem center; }
  .dark .mz-select { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b9a8e' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }

  /* leading/trailing affix — currency, unit, search icon */
  .mz-input-group { display: flex; align-items: stretch; min-width: 0; }
  .mz-input-group .mz-input { border-start-end-radius: 0; border-end-end-radius: 0; }
  .mz-input-affix { display: inline-flex; align-items: center; padding-inline: .75rem;
    background: var(--mz-sunken); border: 1.5px solid var(--mz-line); border-inline-start: 0;
    border-start-end-radius: var(--mz-r-field); border-end-end-radius: var(--mz-r-field);
    color: var(--mz-muted); font-size: .875rem; font-weight: 600; white-space: nowrap; }

  .mz-checkbox, .mz-radio { width: 18px; height: 18px; accent-color: var(--mz-primary); cursor: pointer; flex: none; }
  .mz-check-row { display: flex; align-items: center; gap: .625rem; min-height: var(--mz-h-md);
    cursor: pointer; font-size: .9375rem; color: var(--mz-ink); }

  /* selectable bordered card — plan picker, consultation type, payment method */
  .mz-radio-card { display: flex; align-items: flex-start; gap: .75rem; padding: 1rem; cursor: pointer;
    background: var(--mz-surface); border: 1.5px solid var(--mz-line); border-radius: var(--mz-r-card);
    transition: border-color .12s ease, background-color .12s ease; }
  .mz-radio-card:hover { border-color: color-mix(in srgb, var(--mz-primary) 40%, transparent); }
  .mz-radio-card.is-selected { border-color: var(--mz-primary);
    background: color-mix(in srgb, var(--mz-primary) 6%, transparent); }

  /* 2–5 exclusive options; below 5 a <select> makes people open it just to peek */
  .mz-segmented { display: inline-flex; padding: 3px; gap: 2px; background: var(--mz-sunken);
    border: 1px solid var(--mz-line); border-radius: var(--mz-r-field); }
  .mz-segmented button { flex: 1; height: var(--mz-h-sm); padding-inline: .875rem; border: 0; cursor: pointer;
    background: transparent; color: var(--mz-ink-2); font-family: inherit; font-size: .875rem; font-weight: 600;
    border-radius: 8px; white-space: nowrap; }
  .mz-segmented button[aria-checked="true"], .mz-segmented button.is-active {
    background: var(--mz-surface); color: var(--mz-ink); box-shadow: var(--mz-shadow-sm); }

  /* ==== Surfaces ======================================================== */
  .mz-card { background: var(--mz-surface); border: 1px solid var(--mz-line);
    border-radius: var(--mz-r-card); box-shadow: var(--mz-shadow-sm); }
  .mz-card-pad { padding: 1rem; }
  .mz-card-pad-lg { padding: 1.5rem; }
  .mz-card-hover { transition: transform .16s ease, box-shadow .2s ease, border-color .2s ease; }
  .mz-card-hover:hover { transform: translateY(-2px); box-shadow: var(--mz-shadow);
    border-color: color-mix(in srgb, var(--mz-primary) 30%, transparent); }

  /* ==== Status: a closed set of five. Always icon + text. ================ */
  .mz-status { display: inline-flex; align-items: center; gap: .3125rem; height: 22px; padding-inline: .5rem;
    border-radius: 6px; font-size: .75rem; font-weight: 700; white-space: nowrap; }
  .mz-status i, .mz-status svg { font-size: .75rem; width: 12px; height: 12px; flex: none; }
  .mz-status-success { color: var(--mz-success-txt); background: color-mix(in srgb, var(--mz-success) 12%, transparent); }
  .mz-status-warning { color: var(--mz-warning-txt); background: color-mix(in srgb, var(--mz-warning) 20%, transparent); }
  .mz-status-danger  { color: var(--mz-danger-txt);  background: color-mix(in srgb, var(--mz-danger) 12%, transparent); }
  .mz-status-info    { color: var(--mz-info-txt);    background: color-mix(in srgb, var(--mz-info) 12%, transparent); }
  .mz-status-neutral { color: var(--mz-muted);       background: color-mix(in srgb, var(--mz-ink) 8%, transparent); }

  /* verification tiers — the one job gold is spent on */
  .mz-tier { display: inline-flex; align-items: center; gap: .25rem; padding: .125rem .375rem;
    border-radius: 5px; font-size: .6875rem; font-weight: 700; white-space: nowrap; }
  .mz-tier-basic { color: var(--mz-muted); border: 1px solid var(--mz-line); }
  .mz-tier-verified { color: var(--mz-warning-txt); background: color-mix(in srgb, var(--mz-gold) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--mz-gold) 45%, transparent); }

  /* ==== Sign-in prompt (gated action) =================================== */
  /* Deliberately not an alert: nothing has gone wrong, we are asking for an
     action. Stacks so it stays readable inside a narrow sidebar column. */
  .mz-signin-prompt { display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: .625rem; padding: 1.125rem 1rem; border-radius: var(--mz-r-field);
    background: color-mix(in srgb, var(--mz-primary) 6%, transparent);
    border: 1px solid color-mix(in srgb, var(--mz-primary) 18%, transparent); }
  .mz-signin-ic { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
    background: color-mix(in srgb, var(--mz-primary) 12%, transparent); color: var(--mz-brand-txt); font-size: .95rem; }
  .mz-signin-text { font-size: .9375rem; line-height: 1.6; color: var(--mz-ink-2); text-wrap: balance; margin: 0; }

  /* ==== Alerts ========================================================== */
  .mz-alert { display: flex; gap: .75rem; padding: .875rem 1rem; border-radius: var(--mz-r-field);
    border: 1px solid var(--mz-line); border-inline-start-width: 3px; background: var(--mz-surface);
    font-size: .9375rem; line-height: 1.6; color: var(--mz-ink-2); }
  /* Without these the message is an auto-width flex child: inside any narrow
     column it collapses to min-content and breaks one word per line. */
  .mz-alert > i, .mz-alert > svg { flex: none; margin-top: .15rem; }
  .mz-alert > div, .mz-alert > p { flex: 1 1 auto; min-width: 0; }
  .mz-alert-info    { border-inline-start-color: var(--mz-info); }
  .mz-alert-success { border-inline-start-color: var(--mz-success); }
  .mz-alert-warning { border-inline-start-color: var(--mz-warning); }
  .mz-alert-danger  { border-inline-start-color: var(--mz-danger); }

  /* ==== Price: bidi-isolated, tabular, three decimals (1000 baisa) ======= */
  .mz-price { display: inline-flex; align-items: baseline; gap: .3rem; }
  .mz-price .mz-price-val { font-size: 1.25rem; font-weight: 700; color: var(--mz-brand-txt);
    font-variant-numeric: tabular-nums; letter-spacing: -.01em; unicode-bidi: isolate; }
  .mz-price .mz-price-cur { font-size: .875rem; font-weight: 600; color: var(--mz-brand-txt); }
  .mz-price .mz-price-unit { font-size: .875rem; font-weight: 400; color: var(--mz-muted); }
  .mz-price-lg .mz-price-val { font-size: 1.75rem; }
  .mz-price-sm .mz-price-val { font-size: 1rem; }
  .mz-price-was { font-size: .875rem; color: var(--mz-muted); text-decoration: line-through; }
  /* anything that must not be reordered by the bidi algorithm */
  .mz-ltr { unicode-bidi: isolate; direction: ltr; font-variant-numeric: tabular-nums; }

  /* ==== Empty states: two modes, never one ============================== */
  .mz-empty { display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: .5rem; padding: 2rem 1.25rem; }
  .mz-empty-ic { width: 56px; height: 56px; border-radius: var(--mz-r-card); display: grid; place-items: center;
    background: color-mix(in srgb, var(--mz-primary) 12%, transparent); color: var(--mz-brand-txt); font-size: 1.5rem; }
  .mz-empty h3, .mz-empty-title { font-size: 1.25rem; font-weight: 700; color: var(--mz-ink); }
  .mz-empty p, .mz-empty-body { font-size: .9375rem; color: var(--mz-muted); max-width: 34ch; line-height: 1.6; }
  .mz-empty-actions { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: center; margin-top: .5rem; }

  /* ==== Skeletons: shape-matched, never a spinner ======================== */
  .mz-skel { background: var(--mz-sunken); border-radius: 6px; position: relative; overflow: hidden; }
  .mz-skel::after { content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--mz-ink) 7%, transparent), transparent);
    transform: translateX(-100%); animation: mz-shim 1.5s linear infinite; }
  @keyframes mz-shim { to { transform: translateX(100%); } }
  .mz-skel-text { height: 12px; }
  .mz-skel-title { height: 18px; width: 60%; }
  .mz-skel-media { aspect-ratio: 4 / 5; border-radius: var(--mz-r-card); }
  .mz-skel-avatar { width: 40px; height: 40px; border-radius: 999px; }

  /* ==== Overlays ======================================================== */
  .mz-modal-backdrop { position: fixed; inset: 0; z-index: var(--mz-z-modal);
    background: rgba(12,20,16,.55); backdrop-filter: blur(2px);
    display: flex; align-items: center; justify-content: center; padding: 1rem; }
  .mz-modal { width: 100%; max-width: 560px; max-height: 90vh; display: flex; flex-direction: column;
    background: var(--mz-surface); border-radius: var(--mz-r-card); box-shadow: var(--mz-shadow-lg); overflow: hidden; }
  .mz-modal-sm { max-width: 420px; }
  .mz-modal-lg { max-width: 720px; }
  .mz-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    min-height: 56px; padding: .75rem 1rem .75rem 1.25rem; border-bottom: 1px solid var(--mz-line); }
  .mz-modal-head h2, .mz-modal-title { font-size: 1.125rem; font-weight: 700; color: var(--mz-ink); }
  .mz-modal-body { padding: 1.25rem; overflow-y: auto; flex: 1; }
  .mz-modal-foot { display: flex; align-items: center; justify-content: flex-end; gap: .5rem;
    padding: 1rem 1.25rem; border-top: 1px solid var(--mz-line); background: var(--mz-surface); }
  /* below sm it becomes a bottom sheet */
  @media (max-width: 639px) {
    .mz-modal-backdrop { align-items: flex-end; padding: 0; }
    .mz-modal { max-width: none; max-height: 88vh;
      border-radius: var(--mz-r-sheet) var(--mz-r-sheet) 0 0;
      padding-bottom: env(safe-area-inset-bottom); }
  }

  /* sticky bottom action bar — every page that can end in a transaction */
  .mz-actionbar { position: fixed; inset-inline: 0; bottom: 0; z-index: var(--mz-z-sticky);
    display: flex; align-items: center; gap: .75rem; padding: .75rem 1rem;
    padding-bottom: calc(.75rem + env(safe-area-inset-bottom));
    background: var(--mz-surface); border-top: 1px solid var(--mz-line); box-shadow: 0 -4px 16px -6px rgba(12,20,16,.16); }

  /* ==== Toasts ========================================================== */
  /* Stack, not a single slot. Positioned with logical properties so it sits
     top-inline-end in both directions with no per-direction stylesheet. */
  .mz-toast-stack { position: fixed; inset-block-start: 1rem; inset-inline-end: 1rem;
    z-index: var(--mz-z-toast); display: flex; flex-direction: column; gap: .5rem;
    width: min(24rem, calc(100vw - 2rem)); pointer-events: none; }
  .mz-toast { pointer-events: auto; display: flex; align-items: flex-start; gap: .75rem;
    padding: .875rem 1rem; border-radius: var(--mz-r-field);
    background: var(--mz-surface); border: 1px solid var(--mz-line);
    border-inline-start-width: 3px; box-shadow: var(--mz-shadow-lg);
    animation: mz-toast-in .22s ease-out both; }
  @keyframes mz-toast-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
  .mz-toast-ic { font-size: 1.05rem; line-height: 1.4; flex: none; }
  .mz-toast-body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: .125rem; }
  .mz-toast-title { font-size: .875rem; font-weight: 700; color: var(--mz-ink); }
  .mz-toast-msg { font-size: .875rem; line-height: 1.6; color: var(--mz-ink-2); white-space: pre-line; overflow-wrap: anywhere; }
  .mz-toast-x { flex: none; width: 28px; height: 28px; border: 0; background: none; cursor: pointer;
    color: var(--mz-muted); border-radius: 6px; }
  .mz-toast-x:hover { background: color-mix(in srgb, var(--mz-ink) 8%, transparent); color: var(--mz-ink); }
  .mz-toast-success { border-inline-start-color: var(--mz-success); }
  .mz-toast-success .mz-toast-ic { color: var(--mz-success-txt); }
  .mz-toast-warning { border-inline-start-color: var(--mz-warning); }
  .mz-toast-warning .mz-toast-ic { color: var(--mz-warning-txt); }
  .mz-toast-danger  { border-inline-start-color: var(--mz-danger); }
  .mz-toast-danger .mz-toast-ic { color: var(--mz-danger-txt); }
  .mz-toast-info    { border-inline-start-color: var(--mz-info); }
  .mz-toast-info .mz-toast-ic { color: var(--mz-info-txt); }

  /* ==== Tables ========================================================== */
  .mz-table-card { background: var(--mz-surface); border: 1px solid var(--mz-line);
    border-radius: var(--mz-r-card); overflow-x: auto; max-width: 100%; }
  .mz-table { width: 100%; border-collapse: collapse; }
  .mz-table thead th { position: sticky; top: 0; z-index: 1;
    text-align: start; font-size: .75rem; font-weight: 600; letter-spacing: 0;
    color: var(--mz-muted); height: 40px; padding-inline: .875rem; white-space: nowrap;
    background: var(--mz-sunken); border-bottom: 1px solid var(--mz-line); }
  .mz-table tbody td { height: 48px; padding-inline: .875rem; font-size: .875rem;
    color: var(--mz-ink-2); border-bottom: 1px solid var(--mz-line-soft); }
  .mz-table tbody tr:last-child td { border-bottom: 0; }
  .mz-table tbody tr:hover { background: color-mix(in srgb, var(--mz-primary) 5%, transparent); }
  .mz-table .mz-td-strong { color: var(--mz-ink); font-weight: 600; }
  /* money and counts line up; dates and IDs are read as strings and stay at start */
  .mz-table .mz-num { text-align: end; font-variant-numeric: tabular-nums; color: var(--mz-ink); unicode-bidi: isolate; }
  .mz-table-compact tbody td { height: 40px; }

  /* ==== Pager =========================================================== */
  .mz-pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: .75rem; padding-block: 1rem; }
  .mz-pager-count { font-size: .875rem; color: var(--mz-muted); font-variant-numeric: tabular-nums; }
  .mz-pager-nav { display: flex; align-items: center; gap: .25rem; }
  .mz-pager-nav button { min-width: 40px; height: 40px; padding-inline: .5rem; border-radius: var(--mz-r-field);
    border: 1px solid var(--mz-line); background: var(--mz-surface); color: var(--mz-ink-2);
    font-family: inherit; font-weight: 600; font-size: .875rem; cursor: pointer; font-variant-numeric: tabular-nums; }
  .mz-pager-nav button:hover:not(:disabled) { border-color: color-mix(in srgb, var(--mz-primary) 40%, transparent); }
  .mz-pager-nav button[aria-current="page"] { background: var(--mz-primary); border-color: var(--mz-primary); color: #fff; }
  .mz-pager-nav button:disabled { opacity: .45; cursor: not-allowed; }

  /* ==== Filter chips ==================================================== */
  .mz-filters-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
  .mz-filter-chip { display: inline-flex; align-items: center; gap: .375rem; height: 32px; padding-inline: .75rem;
    border-radius: var(--mz-r-pill); background: color-mix(in srgb, var(--mz-primary) 10%, transparent);
    color: var(--mz-brand-txt); border: 1px solid color-mix(in srgb, var(--mz-primary) 25%, transparent);
    font-size: .8125rem; font-weight: 600; white-space: nowrap; }
  .mz-filter-chip button { display: inline-grid; place-items: center; width: 16px; height: 16px;
    border: 0; background: none; color: inherit; cursor: pointer; opacity: .7; }
  .mz-filter-chip button:hover { opacity: 1; }

  /* ==== Horizontal rail ================================================= */
  /* No mask-image. A `linear-gradient(90deg, transparent, ...)` fade is
     PHYSICAL, so under RTL it fades the inline-START edge — which is exactly
     where the active "all categories" chip sits, clipping it. Padding keeps
     focus rings and active borders off the container edge instead. */
  .mz-rail { display: flex; gap: .5rem; overflow-x: auto; overflow-y: hidden;
    padding-block: .25rem; padding-inline: 2px;
    scroll-snap-type: x proximity; scroll-padding-inline: 2px;
    scrollbar-width: none; -ms-overflow-style: none; overscroll-behavior-x: contain; }
  .mz-rail::-webkit-scrollbar { display: none; }
  .mz-rail > * { flex: none; scroll-snap-align: start; }

  /* ==== Chips / pills (navigation + selection) ========================== */
  .mz-chip { display: inline-flex; align-items: center; gap: .4rem; height: var(--mz-h-sm); padding-inline: .875rem;
    border-radius: var(--mz-r-pill); background: var(--mz-surface); border: 1.5px solid var(--mz-line);
    color: var(--mz-ink-2); font-weight: 600; font-size: .875rem; white-space: nowrap; cursor: pointer;
    transition: all .15s ease; text-decoration: none; }
  .mz-chip:hover { border-color: color-mix(in srgb, var(--mz-primary) 40%, transparent); color: var(--mz-brand-txt); }
  .mz-chip-active { background: var(--mz-primary); border-color: var(--mz-primary); color: #fff; }
  .mz-chip-active:hover { background: var(--mz-primary-d); color: #fff; }
  .dark .mz-chip { background: transparent; }

  /* ==== Badges ========================================================== */
  .mz-badge { display: inline-flex; align-items: center; gap: .3rem; padding: .2rem .6rem; border-radius: 6px;
    font-size: .72rem; font-weight: 700;
    background: color-mix(in srgb, var(--mz-primary) 12%, transparent); color: var(--mz-brand-txt); }
  .mz-badge-offer { background: color-mix(in srgb, var(--mz-gold) 22%, transparent); color: var(--mz-warning-txt); }
  .mz-badge-new { background: color-mix(in srgb, var(--mz-info) 12%, transparent); color: var(--mz-info-txt); }

  /* ==== Section header ================================================== */
  .mz-section-title { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; }
  .mz-section-title h2 { font-size: 1.25rem; font-weight: 700; color: var(--mz-ink); display: flex; align-items: center; gap: .6rem; }
  .mz-section-title h2::before { content: ""; width: 4px; height: 1.15rem; border-radius: 999px; background: var(--mz-primary); }
  .mz-section-title-plain h2::before { display: none; }
  .mz-section-more { color: var(--mz-brand-txt); font-weight: 600; font-size: .9rem; text-decoration: none; white-space: nowrap; }

  /* ==== Search ========================================================== */
  .mz-search { display: flex; align-items: center; width: 100%; background: var(--mz-surface);
    border: 1.5px solid var(--mz-line); border-radius: var(--mz-r-pill);
    padding: .25rem .25rem .25rem .875rem; transition: border-color .18s ease, box-shadow .18s ease; }
  .mz-search:focus-within { border-color: var(--color-emerald-500); box-shadow: var(--mz-ring); }
  .mz-search .mz-search-ic { color: var(--mz-muted); font-size: 1rem; flex: none; }
  .mz-search input { flex: 1 1 auto; min-width: 0; border: none; outline: none; background: transparent;
    color: var(--mz-ink); font-size: 1rem; padding: .625rem .7rem; font-family: inherit; }
  .mz-search input::placeholder { color: var(--mz-muted); }
  .mz-search-btn { flex: none; display: inline-flex; align-items: center; gap: .4rem; border: none; cursor: pointer;
    height: var(--mz-h-sm); background: var(--mz-primary); color: #fff; font-weight: 600; padding-inline: 1.125rem;
    border-radius: var(--mz-r-pill); font-family: inherit; transition: background-color .15s ease; }
  .mz-search-btn:hover { background: var(--mz-primary-d); }
  .mz-search-scope { flex: none; display: inline-flex; align-items: center; gap: .35rem; color: var(--mz-ink-2);
    font-weight: 600; font-size: .9rem; padding: 0 .9rem; border-inline-end: 1px solid var(--mz-line);
    cursor: pointer; background: transparent; }
  .dark .mz-search { background: var(--mz-sunken); }

  /* ==== Avatar / seller identity ======================================== */
  .mz-avatar { display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 999px;
    background: var(--mz-primary); color: #fff; font-weight: 700; flex: none; overflow: hidden; }
  .mz-avatar img { width: 100%; height: 100%; object-fit: cover; }
  .mz-avatar-sm { width: 24px; height: 24px; font-size: .6875rem; }
  .mz-avatar-lg { width: 56px; height: 56px; font-size: 1.25rem; }
  .mz-identity { display: flex; align-items: center; gap: .5rem; min-width: 0; font-size: .8125rem; color: var(--mz-ink-2); }
  .mz-identity-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ==== Media =========================================================== */
  .mz-media { position: relative; overflow: hidden; background: var(--mz-sunken); }
  .mz-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
  /* one locked ratio stops user-uploaded photos from producing ragged rows */
  .mz-media-4x5 { aspect-ratio: 4 / 5; }
  .mz-media-4x3 { aspect-ratio: 4 / 3; }
  .mz-media-count { position: absolute; inset-block-end: .5rem; inset-inline-start: .5rem;
    background: rgba(12,20,16,.72); color: #fff; font-size: .6875rem; font-weight: 600;
    padding: .125rem .375rem; border-radius: 5px; font-variant-numeric: tabular-nums; unicode-bidi: isolate; }

  /* ==== Gallery ========================================================= */
  /* `cover` is right for grid cards (uniform rows) but wrong for the detail
     hero: it crops user-uploaded machinery and produce, removing the evidence
     the buyer is judging. Scoped `contain` on a neutral plate instead. */
  .mz-media-fit img { object-fit: contain; }
  .mz-gallery-frame { background: var(--mz-sunken); }
  .mz-gallery-frame:focus-visible { outline: none; box-shadow: var(--mz-ring); }

  .mz-gallery-nav { position: absolute; inset-block-start: 50%; transform: translateY(-50%);
    width: 44px; height: 44px; display: grid; place-items: center; z-index: 3; cursor: pointer;
    border: 1px solid var(--mz-line); border-radius: 999px;
    background: color-mix(in srgb, var(--mz-surface) 90%, transparent);
    color: var(--mz-ink); font-size: .95rem; box-shadow: var(--mz-shadow-sm);
    transition: background-color .15s ease, transform .15s ease; }
  .mz-gallery-nav:hover { background: var(--mz-surface); }
  .mz-gallery-nav:active { transform: translateY(-50%) scale(.94); }
  .mz-gallery-nav:focus-visible { outline: none; box-shadow: var(--mz-ring); }
  /* Logical insets: "previous" is always at the inline-start edge in both directions. */
  .mz-gallery-prev { inset-inline-start: .75rem; }
  .mz-gallery-next { inset-inline-end: .75rem; }

  .mz-gallery-thumb { position: relative; flex: none; width: 88px; aspect-ratio: 4 / 3; padding: 0;
    cursor: pointer; overflow: hidden; background: var(--mz-sunken);
    border: 2px solid var(--mz-line); border-radius: var(--mz-r-field);
    transition: border-color .15s ease, opacity .15s ease; opacity: .78; }
  .mz-gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .mz-gallery-thumb:hover { opacity: 1; border-color: color-mix(in srgb, var(--mz-primary) 45%, transparent); }
  .mz-gallery-thumb.is-active { opacity: 1; border-color: var(--mz-primary); }
  .mz-gallery-thumb:focus-visible { outline: none; box-shadow: var(--mz-ring); }

  /* ==== Product card ==================================================== */
  .mz-product-card { display: flex; flex-direction: column; background: var(--mz-surface); border: 1px solid var(--mz-line);
    border-radius: var(--mz-r-card); overflow: hidden; box-shadow: var(--mz-shadow-sm); text-decoration: none;
    transition: transform .16s ease, box-shadow .2s ease, border-color .2s ease; height: 100%; }
  .mz-product-card:hover { transform: translateY(-2px); box-shadow: var(--mz-shadow);
    border-color: color-mix(in srgb, var(--mz-primary) 30%, transparent); }
  .mz-pc-media { position: relative; aspect-ratio: 4 / 5; background: var(--mz-sunken); overflow: hidden; }
  .mz-pc-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .3s ease; }
  .mz-product-card:hover .mz-pc-media img { transform: scale(1.03); }
  .mz-pc-heart { position: absolute; inset-block-start: .5rem; inset-inline-start: .5rem;
    width: var(--mz-h-sm); height: var(--mz-h-sm); border-radius: var(--mz-r-field);
    background: color-mix(in srgb, var(--mz-surface) 92%, transparent); color: var(--mz-ink-2);
    border: 1px solid var(--mz-line); cursor: pointer; display: inline-flex; align-items: center;
    justify-content: center; z-index: 2; transition: color .15s ease; }
  .mz-pc-heart:hover { color: var(--mz-danger); }
  .mz-pc-heart[aria-pressed="true"] { color: var(--mz-danger); }
  .mz-pc-toptag { position: absolute; inset-block-start: .5rem; inset-inline-end: .5rem; z-index: 2; }
  .mz-pc-body { padding: .75rem .8125rem .8125rem; display: flex; flex-direction: column; gap: .4375rem; flex: 1; }
  .mz-pc-title { font-weight: 600; color: var(--mz-ink); font-size: .9375rem; line-height: 1.4;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .mz-pc-attrs { font-size: .78125rem; color: var(--mz-muted); display: flex; gap: .375rem; flex-wrap: wrap; }
  .mz-pc-meta { display: inline-flex; align-items: center; gap: .3rem; color: var(--mz-muted); font-size: .78125rem; min-width: 0; }
  .mz-pc-meta span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mz-pc-foot { display: flex; align-items: center; gap: .5rem; padding-top: .5rem; margin-top: auto;
    border-top: 1px solid var(--mz-line-soft); }

  /* harvest freshness — the purchase criterion for produce */
  .mz-fresh { display: flex; flex-direction: column; gap: .25rem; }
  .mz-fresh-bars { display: flex; gap: 3px; }
  .mz-fresh-bars span { display: block; height: 4px; flex: 1; border-radius: 2px; background: var(--mz-line); }
  .mz-fresh-bars span.on { background: var(--color-emerald-500); }
  .mz-fresh-bars span.warn { background: var(--mz-gold); }
  .mz-fresh-lbl { font-size: .75rem; color: var(--mz-ink-2); font-weight: 600; }

  /* ==== Category tile =================================================== */
  .mz-cat-tile { display: flex; align-items: stretch; gap: .8rem; padding: 1rem; border-radius: var(--mz-r-card);
    background: var(--mz-surface); border: 1px solid var(--mz-line); box-shadow: var(--mz-shadow-sm); text-decoration: none;
    transition: transform .16s ease, box-shadow .2s ease, border-color .2s ease; min-height: 92px; }
  .mz-cat-tile:hover { transform: translateY(-2px); box-shadow: var(--mz-shadow);
    border-color: color-mix(in srgb, var(--mz-primary) 30%, transparent); }
  .mz-cat-ic { width: 54px; height: 54px; border-radius: 14px; flex: none; display: inline-flex; align-items: center; justify-content: center; }
  .mz-cat-body { display: flex; flex-direction: column; justify-content: center; gap: .15rem; min-width: 0; }
  .mz-cat-title { font-weight: 700; color: var(--mz-ink); font-size: 1rem; line-height: 1.2; }
  .mz-cat-sub { color: var(--mz-muted); font-size: .8rem; line-height: 1.3; }

  /* ==== Stat card ======================================================= */
  .mz-stat { position: relative; display: flex; flex-direction: column; gap: .5rem; padding: 1.1rem 1.25rem;
    min-width: 0; border-radius: var(--mz-r-card); background: var(--mz-surface); border: 1px solid var(--mz-line);
    box-shadow: var(--mz-shadow-sm); overflow: hidden; transition: border-color .18s ease, box-shadow .2s ease; }
  .mz-stat:hover { border-color: color-mix(in srgb, var(--mz-primary) 30%, transparent); box-shadow: var(--mz-shadow); }
  .mz-stat::before { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; width: 3px; background: var(--mz-primary); }
  .mz-stat-head { display: flex; align-items: center; gap: .5rem; color: var(--mz-muted); font-size: .82rem; font-weight: 600; min-width: 0; }
  .mz-stat-head span { min-width: 0; overflow-wrap: anywhere; }
  .mz-stat-head i { color: var(--mz-brand-txt); font-size: .95rem; width: 1.15rem; text-align: center; }
  .mz-stat-val { font-size: 1.75rem; font-weight: 700; color: var(--mz-ink); line-height: 1;
    letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
  .mz-stat-sub { color: var(--mz-muted); font-size: .78rem; line-height: 1.35; }
  .mz-stat-ic { width: 40px; height: 40px; border-radius: 11px; flex: none; display: inline-flex; align-items: center;
    justify-content: center; font-size: 1rem; background: color-mix(in srgb, var(--mz-primary) 10%, transparent); color: var(--mz-brand-txt); }
  .mz-stat-lbl { color: var(--mz-muted); font-size: .85rem; font-weight: 600; }

  /* ==== Sidebar link ==================================================== */
  .mz-side-link { position: relative; display: flex; align-items: center; gap: .75rem; padding: .625rem .875rem;
    border-radius: var(--mz-r-field); color: var(--mz-ink-2); font-weight: 600; font-size: .9375rem;
    text-decoration: none; transition: background .15s ease, color .15s ease; }
  .mz-side-link:hover { background: color-mix(in srgb, var(--mz-primary) 8%, transparent); color: var(--mz-brand-txt); }
  .mz-side-link.active, .mz-side-link-active { background: color-mix(in srgb, var(--mz-primary) 10%, transparent); color: var(--mz-brand-txt); }
  .mz-side-link.active::before, .mz-side-link-active::before { content: ""; position: absolute; inset-inline-start: -.25rem;
    inset-block: .35rem; width: 3px; border-radius: 999px; background: var(--mz-primary); }
  .mz-side-group { font-size: .6875rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: var(--mz-muted); padding: .75rem .875rem .375rem; }

  /* ==== Top nav ========================================================= */
  .mz-nav-badge { position: absolute; inset-block-start: -2px; inset-inline-start: -2px; min-width: 18px; height: 18px;
    padding: 0 4px; border-radius: 999px; background: var(--mz-danger); color: #fff; font-size: .66rem; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 0 0 2px var(--mz-surface);
    font-variant-numeric: tabular-nums; }
  .mz-topnav-link { display: inline-flex; align-items: center; gap: .45rem; height: var(--mz-h-sm); padding-inline: .875rem;
    border-radius: var(--mz-r-field); font-weight: 600; font-size: .9375rem; color: var(--mz-ink-2);
    white-space: nowrap; text-decoration: none; transition: all .15s ease; }
  .mz-topnav-link:hover { background: color-mix(in srgb, var(--mz-primary) 8%, transparent); color: var(--mz-brand-txt); }
  .mz-topnav-link.active { color: var(--mz-brand-txt); box-shadow: inset 0 -2px 0 var(--mz-primary); border-radius: 0; }

  /* ==== Header ==========================================================
     Sizes come from the 2025-26 marketplace benchmark: a dense action row that
     CONDENSES (never hides) on desktop, over a taxonomy rail that carries real
     categories. Opaque — the translucent blurred bar over a listing grid is
     glassmorphism and costs a compositing layer on every scroll frame. */
  .mz-header { position: sticky; inset-block-start: 0; z-index: 60;
    background: var(--mz-surface);
    box-shadow: 0 1px 0 color-mix(in srgb, var(--mz-ink) 8%, transparent);
    transition: box-shadow .15s cubic-bezier(.2,0,0,1); }
  .mz-header.is-stuck { box-shadow: 0 1px 2px rgba(16,24,40,.06), 0 6px 16px -8px rgba(16,24,40,.16); }

  /* Published so anything that has to sit under the header (sticky sub-bars,
     full-height wrappers) can track it instead of hardcoding the old 64px. */
  :root { --mz-hdr-h: 56px; }
  @media (min-width: 768px)  { :root { --mz-hdr-h: 64px; } }
  @media (min-width: 1280px) { :root { --mz-hdr-h: 72px; } }

  .mz-header-in { max-inline-size: 1280px; margin-inline: auto; padding-inline: 1rem;
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
    column-gap: 1rem; block-size: var(--mz-hdr-h); transition: block-size .2s cubic-bezier(.2,0,0,1); }
  @media (min-width: 768px)  { .mz-header-in { padding-inline: 1.5rem; column-gap: 1.5rem; } }
  @media (min-width: 1280px) { .mz-header-in { padding-inline: 2rem; } }
  @media (min-width: 768px)  { .mz-header.is-stuck .mz-header-in { block-size: 56px; } }

  .mz-brand { display: inline-flex; align-items: center; gap: .625rem; text-decoration: none; flex: none; }
  .mz-brand svg { width: 32px; height: 32px; transition: width .2s cubic-bezier(.2,0,0,1), height .2s cubic-bezier(.2,0,0,1); }
  .mz-header.is-stuck .mz-brand svg { width: 28px; height: 28px; }
  .mz-brand b { font-size: 1.25rem; font-weight: 700; line-height: 1.4; color: var(--mz-ink); letter-spacing: 0; }

  /* Search. Radius 12 and a flush rectangular submit — a 999px pill with an
     inset circular coloured icon button is the strongest template tell there is,
     and no high-volume marketplace ships one. */
  .mz-hsearch { display: flex; align-items: center; block-size: 44px; inline-size: 100%;
    max-inline-size: 640px; padding: 4px; padding-inline-start: .75rem;
    background: var(--mz-surface); border: 1px solid color-mix(in srgb, var(--mz-ink) 14%, transparent);
    border-radius: 12px; transition: border-color .15s ease, box-shadow .15s cubic-bezier(.2,0,0,1), block-size .2s cubic-bezier(.2,0,0,1); }
  .dark .mz-hsearch { background: var(--mz-sunken); }
  .mz-header.is-stuck .mz-hsearch { block-size: 38px; }
  .mz-hsearch:focus-within { border-color: var(--color-emerald-500);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-emerald-500) 22%, transparent); }
  .mz-hsearch-scope { flex: none; display: inline-flex; align-items: center; gap: .375rem;
    block-size: 36px; padding-inline: .75rem; border: 0; background: transparent; cursor: pointer;
    font-family: inherit; font-size: .875rem; font-weight: 500; color: var(--mz-ink-2);
    border-inline-end: 1px solid color-mix(in srgb, var(--mz-ink) 12%, transparent); }
  .mz-hsearch-ic { flex: none; color: var(--mz-muted); font-size: 1rem; margin-inline-start: .5rem; }
  .mz-hsearch input { flex: 1 1 auto; min-inline-size: 0; border: 0; outline: none; background: transparent;
    font-family: inherit; font-size: .9375rem; line-height: 1.5; color: var(--mz-ink); padding-inline: .5rem; }
  .mz-hsearch input::placeholder { color: var(--mz-muted); }
  .mz-hsearch-go { flex: none; block-size: 36px; min-inline-size: 36px; padding-inline: 1rem;
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    border: 0; border-radius: 8px; cursor: pointer; font-family: inherit;
    font-size: .9375rem; font-weight: 600; background: var(--mz-primary); color: #fff;
    transition: background-color .15s ease; }
  .mz-hsearch-go:hover { background: var(--color-emerald-500); }
  .mz-hsearch-go:focus-visible { outline: none; box-shadow: var(--mz-ring); }

  .mz-header-actions { display: flex; align-items: center; gap: .25rem; flex: none; }
  .mz-header-actions .mz-btn-icon { width: 40px; height: 40px; border-radius: 10px; }
  .mz-header-cta { margin-inline-start: .5rem; }

  /* Taxonomy rail. Real categories, no icons on the labels, current scope marked. */
  .mz-header-rail { border-block-start: 1px solid color-mix(in srgb, var(--mz-ink) 7%, transparent);
    background: var(--mz-surface);
    display: grid; grid-template-rows: 1fr; transition: grid-template-rows .18s cubic-bezier(.2,0,0,1), opacity .12s linear; }
  .mz-header.is-stuck .mz-header-rail { grid-template-rows: 0fr; opacity: 0; pointer-events: none; }
  /* Clip ONLY while collapsing. The 1fr->0fr row animation needs overflow:hidden,
     but an unconditional clip also cuts off the categories dropdown, whose panel is
     absolutely positioned below the 44px rail — the trigger stayed alive while
     nothing appeared. Clipping only in the stuck state keeps the animation and lets
     the panel escape at rest, when it is the only time it can be open anyway. */
  .mz-header-rail > div { overflow: visible; }
  .mz-header.is-stuck .mz-header-rail > div { overflow: hidden; }
  .mz-header-rail nav { max-inline-size: 1280px; margin-inline: auto; padding-inline: 1.5rem;
    display: flex; align-items: center; gap: .25rem; block-size: 44px; }
  @media (min-width: 1280px) { .mz-header-rail nav { padding-inline: 2rem; } }
  .mz-rail-link { display: inline-flex; align-items: center; block-size: 44px; padding-inline: .75rem;
    font-size: .9375rem; font-weight: 500; line-height: 1.4; color: var(--mz-ink-2);
    text-decoration: none; white-space: nowrap; border-radius: 0; }
  .mz-rail-link:hover { color: var(--mz-ink); }
  .mz-rail-link.active { color: var(--mz-brand-txt); font-weight: 600; box-shadow: inset 0 -2px 0 var(--mz-primary); }

  /* Anchors must clear the stuck header. */
  .mz-nav-badge { direction: ltr; unicode-bidi: isolate; }

  /* ==== Category rail (replaces the 4x2 tile grid) ======================
     Airbnb's production pattern: one monochrome icon size, a 12/600 label, a
     hidden scrollbar and a half-cut item as the swipe affordance. Height drops
     from ~380px to 76px, which is what lifts listings above the fold. */
  .mz-catrail { display: flex; gap: 2rem; overflow-x: auto; scroll-snap-type: x proximity;
    scroll-padding-inline-start: 1rem; padding-inline: 1rem; scrollbar-width: none;
    border-block-end: 1px solid var(--mz-line);
    -webkit-mask-image: linear-gradient(to left, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
    mask-image: linear-gradient(to left, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%); }
  .mz-catrail::-webkit-scrollbar { display: none; }
  .mz-catrail-item { flex: 0 0 auto; scroll-snap-align: start; display: flex; flex-direction: column;
    align-items: center; gap: .5rem; padding-block: .625rem; min-inline-size: 72px;
    text-decoration: none; color: var(--mz-ink-2); opacity: .65;
    transition: opacity .15s ease, box-shadow .15s ease; }
  .mz-catrail-item:hover, .mz-catrail-item.active { opacity: 1; color: var(--mz-ink);
    box-shadow: inset 0 -2px 0 var(--mz-primary); }
  .mz-catrail-item:focus-visible { outline: none; box-shadow: var(--mz-ring); border-radius: 8px; }
  /* One rule for BOTH the drawn SVGs and admin-uploaded icon images, so a rail
     containing a mix of the two never shows two different sizes. */
  .mz-catrail-item svg, .mz-catrail-ic { width: 28px; height: 28px; flex: none; display: block; }
  .mz-catrail-item span { font-size: .75rem; font-weight: 600; line-height: 1rem; white-space: nowrap; }
  @media (max-width: 767px) {
    .mz-catrail-item svg, .mz-catrail-ic { width: 24px; height: 24px; }
    .mz-catrail { gap: 1.5rem; }
  }

  /* ==== Hero bento ======================================================
     `grid-column: span N` with auto-placement, NOT grid-template-areas: under
     direction:rtl a named-area string silently mirrors, so visually-authored
     layouts flip. Spans follow direction correctly with no RTL special-casing. */
  .mz-hero { display: grid; grid-template-columns: repeat(12, 1fr); grid-auto-rows: 150px;
    gap: 1.25rem; }
  .mz-hero-a { grid-column: span 12; grid-row: span 2; }
  .mz-hero-b, .mz-hero-c { grid-column: span 12; grid-row: span 1; }
  @media (min-width: 768px) {
    .mz-hero { grid-template-columns: repeat(6, 1fr); grid-auto-rows: 140px; }
    .mz-hero-a { grid-column: span 6; grid-row: span 2; }
    .mz-hero-b, .mz-hero-c { grid-column: span 3; }
  }
  @media (min-width: 1024px) {
    .mz-hero { grid-template-columns: repeat(12, 1fr); grid-auto-rows: 150px; }
    .mz-hero-a { grid-column: span 7; grid-row: span 2; }
    .mz-hero-b, .mz-hero-c { grid-column: span 5; grid-row: span 1; }
  }
  .mz-hero-card { position: relative; overflow: hidden; border-radius: 20px;
    display: flex; flex-direction: column; justify-content: flex-end;
    padding: 1.25rem 1.375rem; text-decoration: none; isolation: isolate;
    background: var(--mz-sunken); border: 1px solid var(--mz-line);
    transition: transform .2s cubic-bezier(.2,0,0,1), box-shadow .2s cubic-bezier(.2,0,0,1); }
  .mz-hero-card:hover { transform: translateY(-2px); box-shadow: var(--mz-shadow); }
  .mz-hero-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
  /* Scrim, not a flat tint: text stays legible over any photograph. */
  .mz-hero-card::after { content: ""; position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(to top, rgba(8,20,12,.82) 0%, rgba(8,20,12,.45) 42%, rgba(8,20,12,.06) 100%); }
  .mz-hero-card.is-brand { background: var(--mz-primary); border-color: transparent; }
  .mz-hero-card.is-brand::after { background: linear-gradient(105deg, var(--mz-primary-d), transparent 70%); }

  /* Tinted cards for the two secondary tiles. A stock placeholder photo behind a
     dark scrim reads as a broken image, which is worse than no image at all —
     these carry their own colour and a large, quiet watermark glyph instead, so
     they look deliberate until real photography exists. */
  .mz-hero-card.is-tint { border-color: transparent; }
  .mz-hero-card.is-tint::after { background: none; }
  .mz-hero-card.is-tint .mz-hero-eyebrow { color: rgba(255,255,255,.78); }
  .mz-hero-tint-deep { background: linear-gradient(140deg, #17512a 0%, #1e7a3c 100%); }
  .mz-hero-tint-warm { background: linear-gradient(140deg, #2a5d38 0%, #3f7d4b 100%); }
  .mz-hero-mark { position: absolute; inset-block-start: 50%; inset-inline-end: -8px;
    transform: translateY(-50%); width: 132px; height: 132px; z-index: -1;
    color: #fff; opacity: .12; pointer-events: none; }
  .mz-hero-mark-lg { width: 210px; height: 210px; inset-inline-end: auto; inset-inline-start: 2rem; opacity: .10; }
  @media (max-width: 767px) { .mz-hero-mark { width: 104px; height: 104px; } .mz-hero-mark-lg { width: 140px; height: 140px; } }
  .mz-hero-eyebrow { font-size: .75rem; font-weight: 700; color: rgba(255,255,255,.82); margin-bottom: .375rem; }
  .mz-hero-title { font-size: 1.375rem; font-weight: 700; line-height: 1.25; color: #fff; text-wrap: balance; }
  .mz-hero-a .mz-hero-title { font-size: 1.75rem; }
  .mz-hero-sub { font-size: .875rem; line-height: 1.5; color: rgba(255,255,255,.86); margin-top: .375rem; }
  .mz-hero-cta { align-self: flex-start; margin-top: .875rem; display: inline-flex; align-items: center; gap: .5rem;
    height: 40px; padding-inline: 1.125rem; border-radius: 10px; background: #fff; color: var(--mz-primary-d);
    font-weight: 700; font-size: .9375rem; text-decoration: none; }

  /* ==== Advertiser marquee ============================================== */
  /* direction:ltr must be on the CLIPPING CONTAINER, not only on the track.
     A `width:max-content` track inside an RTL parent is anchored by its RIGHT
     edge, so translating it left pulls it away from that edge and opens a gap
     that grows exactly as far as it has travelled — the strip leaves to the
     left and never comes back from the right. With the container in ltr the
     track is anchored left, and translating left feeds chips in from the right. */
  .mz-mq { direction: ltr; position: relative; overflow: hidden; padding-block: .5rem;
    /* Fixed px, not %: a 6% fade is 77px on a 1280 container but 38px on a 640
       one, so the softness changed with the breakpoint. */
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%); }
  @media (max-width: 767px) {
    .mz-mq { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%);
             mask-image: linear-gradient(to right, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%); }
  }
  /* direction:ltr on the GEOMETRY only. In a dir=rtl flex row the main-axis
     start is the right edge, so the track overflows leftward and a negative
     translate drains the strip instead of feeding it. */
  .mz-mq-vp { display: flex; column-gap: 1rem; width: max-content; direction: ltr; will-change: transform; }
  .mz-mq-set { display: flex; column-gap: 1rem; flex: 0 0 auto; margin: 0; padding: 0; list-style: none; direction: ltr; }
  .mz-mq-chip { display: inline-flex; align-items: center; gap: .75rem; height: 64px; padding-inline: 1.25rem;
    border-radius: 16px; background: transparent; border: 1px solid transparent; text-decoration: none;
    transition: background-color .18s cubic-bezier(.2,0,0,1), border-color .18s cubic-bezier(.2,0,0,1); }
  .mz-mq-chip:hover, .mz-mq-chip:focus-visible { background: var(--mz-sunken); border-color: var(--mz-line); }
  .mz-mq-chip:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--mz-surface), 0 0 0 4px var(--mz-primary); }
  /* ONE hue for every advertiser. Eight different brand colours here is the
     rainbow-tile pattern the client already rejected. */
  .mz-mq-mark { width: 40px; height: 40px; border-radius: 8px; flex: none; display: inline-flex;
    align-items: center; justify-content: center; background: var(--mz-sunken);
    color: var(--mz-ink); opacity: .70; font-weight: 700; font-size: 1rem; }
  .mz-mq-name { font-size: .9375rem; font-weight: 600; line-height: 1.4; color: var(--mz-ink);
    white-space: nowrap; direction: rtl; unicode-bidi: isolate; }
  .mz-mq-toggle { position: absolute; inset-inline-end: 0; inset-block-start: 50%; transform: translateY(-50%);
    width: 32px; height: 32px; z-index: 2; display: grid; place-items: center; cursor: pointer;
    border: 1px solid var(--mz-line); border-radius: 999px; background: var(--mz-surface);
    color: var(--mz-muted); font-size: .7rem; }
  .mz-mq-toggle:focus-visible { outline: none; box-shadow: var(--mz-ring); }
  @media (max-width: 767px) {
    .mz-mq-chip { height: 56px; padding-inline: 1rem; }
    .mz-mq-mark { width: 34px; height: 34px; }
  }
  /* NOTE: there is deliberately no `prefers-reduced-motion` override here.
     An earlier version set `transform: none !important` on the track, which
     both froze the strip AND would now silently beat the JS that drives it.
     The scroll continues under reduced motion at a lower speed, and the pause
     button is the accessibility escape hatch (WCAG 2.2.2 asks for a mechanism
     to pause auto-moving content, not for the content to be motionless). */

  /* ==== Promo (Home — approved, kept) ==================================== */

  .mz-promo { position: relative; overflow: hidden; border-radius: var(--mz-r-card);
    background: linear-gradient(105deg, var(--color-emerald-700), var(--color-emerald-500) 70%);
    color: #fff; box-shadow: var(--mz-shadow); }
  .mz-promo-in { position: relative; z-index: 1; padding: 1.4rem 1.6rem; }
  .mz-promo-cta { display: inline-flex; align-items: center; gap: .5rem; height: var(--mz-h-md); margin-top: .9rem;
    background: #fff; color: var(--mz-primary-d); font-weight: 700; padding-inline: 1.25rem;
    border-radius: var(--mz-r-pill); text-decoration: none; transition: transform .15s ease; }
  .mz-promo-cta:hover { transform: translateY(-1px); }

  /* ==== Pre-launch gate ================================================== */
  /* Temporary. Remove together with <SiteGate> in App.razor at launch. */

  .mz-gate { position: fixed; inset: 0; z-index: var(--mz-z-modal, 60);
    display: grid; place-items: center; padding: 1.25rem;
    background: linear-gradient(160deg, var(--color-emerald-50), var(--color-gray-50)); }
  .mz-gate-card { width: 100%; max-width: 26rem; text-align: center; }
  .mz-gate-mark { display: grid; place-items: center; width: 4.25rem; height: 4.25rem;
    margin: 0 auto .9rem; border-radius: var(--mz-r-pill);
    background: var(--color-emerald-50); color: var(--mz-primary-d); }
  .mz-gate-title { font-size: 1.5rem; font-weight: 700; color: var(--color-gray-900); margin-bottom: .35rem; }
  .mz-gate-sub { font-size: .9375rem; color: var(--color-gray-600); margin-bottom: 1.35rem; line-height: 1.7; }
  .mz-gate-btn { width: 100%; margin-top: .9rem; justify-content: center; }

  @media (prefers-color-scheme: dark) {
    .mz-gate { background: var(--color-gray-900); }
    .mz-gate-title { color: #fff; }
    .mz-gate-sub { color: var(--color-gray-300); }
    .mz-gate-mark { background: var(--color-gray-800); color: var(--color-emerald-300); }
  }
}