/* KharidExpress custom-order calculator.
   Layers 1-5 are the approved design system v1.0, unmodified.
   Plugin-specific rules are appended at the end and use tokens only. */


/* ===== tokens.primitives.css ===== */
/* ============================================================================
   KharidExpress DS - LAYER 1: PRIMITIVES
   The ONLY file in this system permitted to contain a raw colour literal.
   Nothing outside tokens.semantic.css may reference these directly.

   Approved at Gate 1: warm-paper ground (from direction 2) with the brand
   orange retained at full strength (from direction 1). Ramps are generated by
   mixing each anchor toward white and toward its own deep shade, so the steps
   are even rather than hand-picked.

   Hex rather than oklch on purpose: these values get pasted into Avada colour
   pickers and WooCommerce option fields.
   ========================================================================== */

:root {
  /* --- orange: the brand mark. 500 is the logo colour, unchanged. --------- */
  --kx-orange-50:  #feeada;
  --kx-orange-100: #fed4b5;
  --kx-orange-200: #fdbe90;
  --kx-orange-300: #fca96a;
  --kx-orange-400: #fc9445;
  --kx-orange-500: #fb7e20;   /* brand. Survivor of #fb7e20/#fb7d1f/#fc9e3a/#ff7a00 */
  --kx-orange-600: #cf6819;   /* the text/border-safe orange (>=3:1 on every ground) */
  --kx-orange-700: #a25112;
  --kx-orange-800: #763a0c;
  --kx-orange-900: #4a2405;

  /* --- navy: one navy. Replaces #0d244c/#0d144c/#17385e/#0a2047. --------- */
  --kx-navy-50:  #e5e7e9;
  --kx-navy-100: #cbced4;
  --kx-navy-200: #b1b6be;
  --kx-navy-300: #979da9;
  --kx-navy-400: #7e8593;
  --kx-navy-500: #646c7e;
  --kx-navy-600: #4a5468;
  --kx-navy-700: #303b53;
  --kx-navy-800: #16233d;   /* headings, CTA fill, hero text */
  --kx-navy-900: #0a0f1b;

  /* --- sand: the warm ground and its neutrals. --------------------------- */
  --kx-sand-50:  #f3f0eb;
  --kx-sand-100: #e7e1d6;
  --kx-sand-200: #dbd2c2;
  --kx-sand-300: #cfc3ae;
  --kx-sand-400: #b6ab98;
  --kx-sand-500: #9e9381;
  --kx-sand-600: #857c6b;   /* strong border (3.60:1 on the raised surface) */
  --kx-sand-700: #6c6455;   /* muted text (5.11:1 worst case) */
  --kx-sand-800: #544c3e;
  --kx-sand-900: #3b3428;

  /* --- ink: body copy. Warm-leaning grey, not pure black. ---------------- */
  --kx-ink-700: #4a5160;
  --kx-ink-900: #14181f;

  /* --- status. Rate up/down doubles as success/danger. ------------------- */
  --kx-green-50:  #dfece5;
  --kx-green-600: #1c7c4a;
  /* Teal, for the "talk to a human" card. Deep enough to carry white text
     (contrast checked against the same worst-case grounds as everything
     else) and clearly distinct from the rate-up green, which means
     something specific in this system. */
  --kx-teal-50:   #dff0ee;
  --kx-teal-600:  #0f7d72;
  --kx-teal-700:  #0a5f57;
  --kx-green-800: #11492c;
  --kx-red-50:    #f4dfdf;
  --kx-red-600:   #b32020;
  --kx-red-800:   #641212;
  --kx-amber-50:  #fdf1dd;
  --kx-amber-600: #9b5f09;

  /* --- paper surfaces ---------------------------------------------------- */
  --kx-paper-0: #ffffff;
  --kx-paper-1: #faf7f2;   /* page canvas */
  --kx-paper-2: #f4efe6;   /* raised / inset band */

  /* --- warm shadow tint, carried over from the site's own good instinct --- */
  --kx-shadow-tint: 91 45 0;
}


/* ===== tokens.semantic.css ===== */
/* ============================================================================
   KharidExpress DS - LAYER 2: SEMANTIC
   References primitives ONLY. Never a hex. This is the single layer a future
   dark mode or a direction change would touch.

   Every foreground/background pair below was solved against the WORST-CASE
   ground it can land on (surface #ffffff, canvas #faf7f2, sunken #f4efe6) -
   not against white alone. Checking against white alone under-reports by ~0.4
   and produced a real miss during Gate 1 review.
   ========================================================================== */

:root {
  /* --- surfaces ---------------------------------------------------------- */
  --kx-color-canvas:         var(--kx-paper-1);
  --kx-color-surface:        var(--kx-paper-0);
  --kx-color-surface-sunken: var(--kx-paper-2);
  --kx-color-surface-ink:    var(--kx-navy-800);

  /* --- lines ------------------------------------------------------------- */
  --kx-color-border:        var(--kx-sand-200);   /* decorative separation */
  --kx-color-border-strong: var(--kx-sand-600);   /* 3.60:1 - real UI boundaries */

  /* --- text: worst-case 6.95 / 5.11 / 13.66 ------------------------------ */
  --kx-color-text:         var(--kx-ink-700);
  --kx-color-text-muted:   var(--kx-sand-700);
  --kx-color-text-strong:  var(--kx-navy-800);
  --kx-color-text-inverse: var(--kx-paper-0);

  /* --- accent (orange) has FOUR roles, not one. Gate 2 review found that a
         single "accent text" colour is not sufficient: at >=3:1 it is legal for
         large text and borders but fails on a 14px label, where AA needs 4.5:1.
         Picking the wrong one is now a contrast bug you can name.

           -accent        FILL only. Large areas. Never text.
           -accent-2      gradient end for the brand hero.
           -accent-on     what sits ON the fill. Navy, 6.04:1. White is 2.59:1
                          and fails - this is the live homepage's current bug.
           -accent-line   borders, rules, icons, text >=24px (or >=18.7px bold).
                          3.25:1 worst case.
           -accent-ink    any text below that size. 4.93:1 worst case.       */
  --kx-color-accent:       var(--kx-orange-500);
  --kx-color-accent-2:     var(--kx-orange-400);
  --kx-color-accent-on:    var(--kx-navy-800);
  --kx-color-accent-line:  var(--kx-orange-600);
  --kx-color-accent-ink:   var(--kx-orange-700);
  --kx-color-accent-wash:  var(--kx-orange-50);
  /* legacy alias - points at the small-text-safe value so existing use is
     correct by default rather than silently failing */
  --kx-color-accent-text:  var(--kx-orange-700);

  /* --- support / "reach a human". Its own role, not the CTA's: the CTA is
         "buy", this is "ask". ------------------------------------------- */
  --kx-color-support:       var(--kx-teal-600);
  --kx-color-support-hover: var(--kx-teal-700);
  --kx-color-support-wash:  var(--kx-teal-50);
  --kx-color-support-on:    var(--kx-paper-0);

  /* --- call to action ---------------------------------------------------- */
  --kx-color-cta:       var(--kx-navy-800);
  --kx-color-cta-hover: var(--kx-navy-900);
  --kx-color-cta-on:    var(--kx-paper-0);         /* 15.65:1 */

  /* --- FX rate semantics. Deliberate: for an importer a RISING lira is bad
         news, so "up" is a direction, not a celebration. Colour is never the
         only signal - an arrow and a sign ship with it. -------------------- */
  --kx-color-rate-up:    var(--kx-green-600);
  --kx-color-rate-down:  var(--kx-red-600);
  --kx-color-rate-flat:  var(--kx-sand-700);
  --kx-color-rate-stale: var(--kx-amber-600);

  /* --- notices ----------------------------------------------------------- */
  --kx-color-success-bg: var(--kx-green-50);
  --kx-color-success-fg: var(--kx-green-600);
  --kx-color-danger-bg:  var(--kx-red-50);
  --kx-color-danger-fg:  var(--kx-red-600);
  --kx-color-warn-bg:    var(--kx-amber-50);
  --kx-color-warn-fg:    var(--kx-amber-600);
  --kx-color-info-bg:    var(--kx-navy-50);
  --kx-color-info-fg:    var(--kx-navy-800);

  /* --- focus: 13.78:1 worst case ---------------------------------------- */
  --kx-color-focus:        var(--kx-navy-800);
  --kx-focus-ring:         3px;
  --kx-focus-ring-offset:  2px;

  /* --- type ---------------------------------------------------------------
     Persian sits larger than Latin at the same nominal size, so body is 17px.
     The weight ladder is the single biggest win: the current site is weight-400
     everywhere and has no hierarchy at all. */
  --kx-font-ui: Vazirmatn, system-ui, -apple-system, "Segoe UI", sans-serif;
  --kx-fs-100: 12px;  --kx-fs-200: 14px;  --kx-fs-300: 15px;
  --kx-fs-400: 17px;  --kx-fs-500: 20px;  --kx-fs-600: 24px;
  --kx-fs-700: 30px;  --kx-fs-800: 38px;  --kx-fs-900: 48px;
  --kx-fw-body: 400;   --kx-fw-medium: 500;
  --kx-fw-strong: 600; --kx-fw-display: 700;
  --kx-lh-body: 1.9;  --kx-lh-tight: 1.45;  --kx-lh-display: 1.3;
  --kx-tracking-fa: 0;   /* letter-spacing breaks Persian joining. Never change. */

  /* --- geometry -----------------------------------------------------------
     20px was the site's most recognisable geometric trait after the orange;
     direction 2 wanted 12. 16 keeps the softness without the bubbliness. */
  --kx-radius-sm:   8px;
  --kx-radius-md:   10px;
  --kx-radius-lg:   16px;
  --kx-radius-pill: 999px;
  --kx-radius-circle: 50%;

  /* --- space: 4px base --------------------------------------------------- */
  --kx-space-1: 4px;   --kx-space-2: 8px;   --kx-space-3: 12px;
  --kx-space-4: 16px;  --kx-space-5: 20px;  --kx-space-6: 24px;
  --kx-space-7: 32px;  --kx-space-8: 40px;  --kx-space-9: 48px;
  --kx-space-10: 64px; --kx-space-11: 80px; --kx-space-12: 96px;
  --kx-gutter: clamp(16px, 4vw, 80px);   /* replaces the ad-hoc 2.5/4/6/8/18vw */

  /* --- elevation: the site is almost shadowless and that reads as calm.
         Kept, with the warm tint the owner's own CSS already used. --------- */
  --kx-shadow-0: none;
  --kx-shadow-1: 0 1px 2px rgb(var(--kx-shadow-tint) / .05);
  --kx-shadow-2: 0 3px 12px rgb(var(--kx-shadow-tint) / .06);
  --kx-shadow-3: 0 10px 30px rgb(var(--kx-shadow-tint) / .08);

  /* --- motion ------------------------------------------------------------ */
  --kx-ease: cubic-bezier(.2, .6, .3, 1);
  --kx-dur-1: 120ms;  --kx-dur-2: 200ms;  --kx-dur-3: 320ms;

  /* --- WCAG 2.2 AA (2.5.8) is 24px; 44 is the design default for a thumb. - */
  --kx-target-min: 44px;
}


/* ===== base.css ===== */
/* ============================================================================
   KharidExpress DS - BASE: reset, typography, RTL, accessibility.
   No colour or size literals - tokens only. Logical properties only.
   ========================================================================== */

@font-face{font-family:Vazirmatn;src:url('fonts/vazirmatn-fa.woff2') format('woff2');
  font-weight:400 700;font-display:swap;unicode-range:U+0600-06FF,U+200C-200D}
@font-face{font-family:Vazirmatn;src:url('fonts/vazirmatn-num.woff2') format('woff2');
  font-weight:400 700;font-display:swap;unicode-range:U+0020,U+0025,U+0028-002F,U+0030-0039,U+003A,U+00D7,U+2013,U+2212}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--kx-color-canvas);
  color:var(--kx-color-text);
  font-family:var(--kx-font-ui);
  font-size:var(--kx-fs-400);
  font-weight:var(--kx-fw-body);
  line-height:var(--kx-lh-body);
  letter-spacing:var(--kx-tracking-fa);
  text-wrap:pretty;
}
h1,h2,h3,h4,h5,h6,p,figure,blockquote{margin:0}
img,svg{max-inline-size:100%;block-size:auto}
button,input,select,textarea{font:inherit;letter-spacing:inherit;color:inherit}
table{border-collapse:collapse;inline-size:100%}

/* Links must be defined even before the system has links, or they render
   browser-default blue the moment someone adds one in the editor. */
a{color:var(--kx-color-cta);text-underline-offset:3px}
a:hover{color:var(--kx-color-accent-ink)}

/* --- typography scale ------------------------------------------------------
   Persian headings need tighter leading than Persian body copy, or a two-line
   title drifts apart. */
.kx-h1,.kx-h2,.kx-h3,.kx-h4{color:var(--kx-color-text-strong);line-height:var(--kx-lh-display);
  font-weight:var(--kx-fw-display)}
.kx-h1{font-size:var(--kx-fs-800)}
.kx-h2{font-size:var(--kx-fs-700)}
.kx-h3{font-size:var(--kx-fs-600)}
.kx-h4{font-size:var(--kx-fs-500);font-weight:var(--kx-fw-strong);line-height:var(--kx-lh-tight)}
.kx-lead{font-size:var(--kx-fs-500);line-height:var(--kx-lh-body)}
.kx-body{font-size:var(--kx-fs-400)}
.kx-small{font-size:var(--kx-fs-300)}
.kx-caption{font-size:var(--kx-fs-200);color:var(--kx-color-text-muted)}
.kx-muted{color:var(--kx-color-text-muted)}
.kx-strong{font-weight:var(--kx-fw-strong)}

/* --- RTL --------------------------------------------------------------------
   Root hook is .rtl on <html>, matching Avada's own convention, so the same
   selectors keep working once this lands in the theme.

   LTR islands use unicode-bidi:isolate, never a bare direction:ltr. A bare
   direction change is what breaks the current site's read-more links: it
   reorders surrounding content instead of isolating the run. And it must never
   go on a LAYOUT CONTAINER - on a grid or flex parent it reverses the order the
   tracks are placed in, which silently mirrored the colour-ramp labels during
   Gate 2 review. Isolate the run, never the box. */
.kx-ltr{direction:ltr;unicode-bidi:isolate;text-align:start}
.kx-num{direction:ltr;unicode-bidi:isolate;font-variant-numeric:tabular-nums}

/* User-pasted foreign product titles: <bdi> is the correct primitive. */
bdi{unicode-bidi:isolate}

/* Icon mirroring is a two-set rule, not a blanket flip.
   MIRROR: chevrons, arrows, back/forward, timeline progress.
   NEVER:  clock, check, cross, magnifier, external-link, logos, product art. */
.rtl .kx-i-flip{transform:scaleX(-1)}

/* --- accessibility --------------------------------------------------------- */
:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline:var(--kx-focus-ring) solid var(--kx-color-focus);
  outline-offset:var(--kx-focus-ring-offset);
  border-radius:var(--kx-radius-sm);
}
.kx-sr{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.kx-sr-focus:not(:focus):not(:focus-within){position:absolute;inline-size:1px;
  block-size:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* Visibility is never driven by the `hidden` attribute in this system: the
   Claude Design dc runtime strips valueless boolean attributes when it compiles
   a template, so `hidden` in the source is absent from the rendered DOM.
   Components default to hidden in CSS and are revealed by a state class. */
.kx-is-hidden{display:none}

/* Visible end-state is the BASE style; animation only ever plays FROM hidden,
   so print, PDF export and reduced-motion show content, never a stuck
   opacity:0. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important}
}


/* ===== components.css ===== */
/* ============================================================================
   KharidExpress DS - COMPONENTS (v1 primitives)
   Tokens only. Logical properties only. Every interactive element clears the
   44px target default and carries a visible :focus-visible ring from base.css.
   ========================================================================== */

/* --- surface ---------------------------------------------------------------*/
.kx-card{background:var(--kx-color-surface);border:1px solid var(--kx-color-border);
  border-radius:var(--kx-radius-lg);box-shadow:var(--kx-shadow-1);
  padding-block:var(--kx-space-6);padding-inline:var(--kx-space-6)}
.kx-card--flat{box-shadow:var(--kx-shadow-0)}
.kx-card--sunken{background:var(--kx-color-surface-sunken);border-color:transparent}

/* --- button ----------------------------------------------------------------*/
.kx-btn{display:inline-flex;align-items:center;justify-content:center;
  gap:var(--kx-space-2);min-block-size:var(--kx-target-min);
  padding-block:var(--kx-space-3);padding-inline:var(--kx-space-6);
  border:1px solid transparent;border-radius:var(--kx-radius-pill);
  font-weight:var(--kx-fw-strong);cursor:pointer;text-decoration:none;
  transition:background-color var(--kx-dur-2) var(--kx-ease),
             border-color var(--kx-dur-2) var(--kx-ease)}
/* Every hover/focus rule below repeats its OWN colour, even where it looks
   unchanged from the base rule. Reason: a generic `a:hover{color:accent-ink}`
   rule (below, meant for plain body-copy links) has higher specificity
   (0,1,1) than a single class like `.kx-btn--cta` (0,1,0) for the COLOR
   property specifically. Background correctly came from this file's own
   hover rule; text colour silently fell through to that generic rule instead
   - white button text turned orange-on-navy and orange-on-orange, both
   unreadable, on the plugin's own primary action buttons. `!important` is
   used here (and nowhere else in this file) because these are the checkout
   path's core conversion controls: they must never be silently reskinned by
   this file's own cascade or by a surrounding theme's anchor styles. */
.kx-btn--cta{background:var(--kx-color-cta) !important;color:var(--kx-color-cta-on) !important}
.kx-btn--cta:hover,.kx-btn--cta:focus-visible{background:var(--kx-color-cta-hover) !important;color:var(--kx-color-cta-on) !important}
/* accent fill takes NAVY text, never white: white on #fb7e20 is 2.59:1 */
.kx-btn--accent{background:var(--kx-color-accent) !important;color:var(--kx-color-accent-on) !important}
.kx-btn--accent:hover,.kx-btn--accent:focus-visible{background:var(--kx-color-accent-2) !important;color:var(--kx-color-accent-on) !important}
.kx-btn--ghost{background:transparent !important;color:var(--kx-color-text-strong) !important;
  border-color:var(--kx-color-border-strong)}
.kx-btn--ghost:hover,.kx-btn--ghost:focus-visible{background:var(--kx-color-surface-sunken) !important;color:var(--kx-color-text-strong) !important}
.kx-btn--link{background:transparent;color:var(--kx-color-accent-ink);
  padding-inline:var(--kx-space-2);border-radius:var(--kx-radius-sm);
  text-decoration:underline}
.kx-btn[disabled],.kx-btn[aria-disabled="true"]{opacity:.5;cursor:not-allowed}
/* Loading state announces itself; the spinner is decorative only. */
.kx-btn[data-kx-loading] .kx-btn__label{opacity:.7}
.kx-btn__icon{display:flex;flex:0 0 auto}
/* The submit button sets aria-busy while its request is in flight; the icon
   steps aside for the spinner rather than the two competing for attention. */
.kx-btn[aria-busy="true"] .kx-btn__icon{display:none}
.kx-spin{inline-size:1em;block-size:1em;border:2px solid currentColor;
  border-block-start-color:transparent;border-radius:var(--kx-radius-circle);
  animation:kx-spin 700ms linear infinite}
@keyframes kx-spin{to{transform:rotate(360deg)}}

/* --- fields ----------------------------------------------------------------*/
.kx-field{display:block;margin-block-end:var(--kx-space-5)}
.kx-label{display:block;font-size:var(--kx-fs-300);font-weight:var(--kx-fw-medium);
  color:var(--kx-color-text-strong);margin-block-end:var(--kx-space-2)}
.kx-req{color:var(--kx-color-danger-fg);margin-inline-start:var(--kx-space-1)}
.kx-input,.kx-select,.kx-textarea{display:block;inline-size:100%;
  min-block-size:var(--kx-target-min);background:var(--kx-color-surface);
  color:var(--kx-color-text);border:1px solid var(--kx-color-border-strong);
  border-radius:var(--kx-radius-md);
  padding-block:var(--kx-space-3);padding-inline:var(--kx-space-4)}
.kx-textarea{min-block-size:calc(var(--kx-target-min) * 2)}
.kx-input::placeholder,.kx-textarea::placeholder{color:var(--kx-color-text-muted)}
.kx-input:hover,.kx-select:hover{border-color:var(--kx-color-text-muted)}
/* Native select kept for accessibility + select2/WooCommerce compatibility;
   only the arrow is ours, positioned with a logical inset so RTL is free. */
.kx-select{appearance:none;padding-inline-end:var(--kx-space-9);
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-size:6px 6px,6px 6px;background-repeat:no-repeat;
  background-position:right var(--kx-space-4) center, right calc(var(--kx-space-4) + 6px) center}
.rtl .kx-select{background-position:left var(--kx-space-4) center, left calc(var(--kx-space-4) + 6px) center}
.kx-help{display:block;font-size:var(--kx-fs-200);color:var(--kx-color-text-muted);
  margin-block-start:var(--kx-space-2)}
.kx-input[aria-invalid="true"],.kx-select[aria-invalid="true"],.kx-textarea[aria-invalid="true"]{
  border-color:var(--kx-color-danger-fg);border-width:2px}
/* Error defaults to HIDDEN and is revealed by a state class. The dc runtime
   strips valueless boolean attributes, so `hidden` written in a template never
   reaches the DOM and cannot drive visibility. A state class behaves the same
   under the runtime, in the exported static HTML, and in WordPress.
   Error is never colour alone: icon + text + aria-describedby. */
.kx-error{display:none;align-items:center;gap:var(--kx-space-2);
  font-size:var(--kx-fs-200);color:var(--kx-color-danger-fg);
  font-weight:var(--kx-fw-medium);margin-block-start:var(--kx-space-2)}
.kx-error.kx-error--on{display:flex}
.kx-row2{display:grid;grid-template-columns:1fr 1fr;gap:var(--kx-space-5)}
@media (max-width:520px){.kx-row2{grid-template-columns:1fr}}

/* Checkbox is 24px: WCAG 2.2 AA (2.5.8) minimum target, not 20. */
.kx-check{display:flex;align-items:flex-start;gap:var(--kx-space-3);
  min-block-size:var(--kx-target-min);cursor:pointer}
.kx-check input{inline-size:24px;block-size:24px;margin-block-start:2px;flex:0 0 auto;
  accent-color:var(--kx-color-cta)}

/* --- price + figures -------------------------------------------------------*/
.kx-price{display:inline-flex;align-items:baseline;gap:var(--kx-space-2);
  direction:ltr;unicode-bidi:isolate;font-variant-numeric:tabular-nums;
  color:var(--kx-color-text-strong);font-weight:var(--kx-fw-display);
  font-size:var(--kx-fs-700);line-height:var(--kx-lh-tight)}
.kx-price__unit{font-size:var(--kx-fs-300);font-weight:var(--kx-fw-medium);
  color:var(--kx-color-text-muted)}
/* a large price qualifies as large text, so the -line orange is legal here */
.kx-price--accent{color:var(--kx-color-accent-line)}
.kx-price--sm{font-size:var(--kx-fs-500);color:var(--kx-color-text-strong)}

/* --- badge / chip ----------------------------------------------------------*/
.kx-chip{display:inline-flex;align-items:center;gap:var(--kx-space-2);
  padding-block:var(--kx-space-2);padding-inline:var(--kx-space-3);
  border:1px solid var(--kx-color-border);border-radius:var(--kx-radius-pill);
  background:var(--kx-color-surface);color:var(--kx-color-text-strong);
  font-size:var(--kx-fs-200);font-weight:var(--kx-fw-medium)}
.kx-chip--sale{background:var(--kx-color-accent);color:var(--kx-color-accent-on);
  border-color:transparent;font-weight:var(--kx-fw-strong)}
.kx-chip--ink{background:var(--kx-color-surface-ink);color:var(--kx-color-text-inverse);
  border-color:transparent}

/* Rate delta. The arrow carries the meaning; colour only reinforces it. */
.kx-delta{display:inline-flex;align-items:center;gap:var(--kx-space-1);
  direction:ltr;unicode-bidi:isolate;font-variant-numeric:tabular-nums;
  font-weight:var(--kx-fw-medium)}
.kx-delta--up{color:var(--kx-color-rate-up)}
.kx-delta--down{color:var(--kx-color-rate-down)}
.kx-delta--flat{color:var(--kx-color-rate-flat)}
.kx-delta--stale{color:var(--kx-color-rate-stale)}

/* --- alert -----------------------------------------------------------------*/
.kx-alert{display:flex;gap:var(--kx-space-3);
  padding-block:var(--kx-space-4);padding-inline:var(--kx-space-5);
  border-radius:var(--kx-radius-md);border-inline-start:4px solid currentColor;
  font-size:var(--kx-fs-300)}
.kx-alert__body{color:var(--kx-color-text)}
.kx-alert__title{display:block;font-weight:var(--kx-fw-strong);
  color:inherit;margin-block-end:var(--kx-space-1)}
.kx-alert--info{background:var(--kx-color-info-bg);color:var(--kx-color-info-fg)}
.kx-alert--success{background:var(--kx-color-success-bg);color:var(--kx-color-success-fg)}
.kx-alert--warn{background:var(--kx-color-warn-bg);color:var(--kx-color-warn-fg)}
.kx-alert--danger{background:var(--kx-color-danger-bg);color:var(--kx-color-danger-fg)}

/* --- table -----------------------------------------------------------------*/
.kx-table{font-size:var(--kx-fs-300)}
.kx-table th,.kx-table td{text-align:start;padding-block:var(--kx-space-3);
  padding-inline:var(--kx-space-4);border-block-end:1px solid var(--kx-color-border)}
.kx-table th{font-weight:var(--kx-fw-strong);color:var(--kx-color-text-strong);
  font-size:var(--kx-fs-200)}
.kx-table td.kx-n{direction:ltr;unicode-bidi:isolate;font-variant-numeric:tabular-nums}
.kx-table tbody tr:hover{background:var(--kx-color-surface-sunken)}

/* --- skeleton (rate widget is async) ---------------------------------------*/
.kx-skel{background:var(--kx-color-surface-sunken);border-radius:var(--kx-radius-sm);
  color:transparent;position:relative;overflow:hidden}
@media (prefers-reduced-motion: no-preference){
  .kx-skel::after{content:"";position:absolute;inset:0;
    background:linear-gradient(90deg,transparent,rgb(255 255 255 / .55),transparent);
    animation:kx-shim 1.4s infinite}
  @keyframes kx-shim{to{transform:translateX(100%)}}
}
.rtl .kx-skel::after{animation-direction:reverse}

/* --- hero ------------------------------------------------------------------
   The orange hero is reserved for the homepage and the brand landing pages.
   Everywhere else uses --quiet. Approved at Gate 1. */
.kx-hero{padding-block:var(--kx-space-9);padding-inline:var(--kx-space-7);
  border-radius:var(--kx-radius-lg)}
.kx-hero--brand{background:linear-gradient(135deg,var(--kx-color-accent),var(--kx-color-accent-2));
  color:var(--kx-color-accent-on)}
.kx-hero--quiet{background:var(--kx-color-surface-sunken);color:var(--kx-color-text-strong)}
.kx-hero--ink{background:var(--kx-color-surface-ink);color:var(--kx-color-text-inverse)}
.kx-hero .kx-h1,.kx-hero .kx-h2{color:inherit}
.kx-hero__actions{display:flex;flex-wrap:wrap;gap:var(--kx-space-3);
  margin-block-start:var(--kx-space-6)}
.kx-hero--brand .kx-btn--ghost,.kx-hero--ink .kx-btn--ghost{color:inherit;border-color:currentColor}

/* --- layout helpers --------------------------------------------------------*/
.kx-stack > * + *{margin-block-start:var(--kx-space-4)}
.kx-cluster{display:flex;flex-wrap:wrap;gap:var(--kx-space-3);align-items:center}
.kx-split{display:flex;justify-content:space-between;align-items:baseline;gap:var(--kx-space-4)}


/* ===== business.css ===== */
/* ============================================================================
   KharidExpress DS - business surfaces.
   The components that only exist because of THIS business: buying abroad in a
   foreign currency, billing freight by weight, and quoting against a rate that
   moves. Tokens only, logical properties only.
   ========================================================================== */

/* --- live FX rate ----------------------------------------------------------
   Three states matter, not one: fresh, stale, and unavailable. A quote built on
   a stale rate is the single most expensive failure in this business, so
   staleness is a first-class visual state rather than a footnote. */
.kx-rate{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--kx-space-3);
  padding-block:var(--kx-space-4);padding-inline:var(--kx-space-5);
  background:var(--kx-color-surface);border:1px solid var(--kx-color-border);
  border-radius:var(--kx-radius-md)}
.kx-rate__label{font-size:var(--kx-fs-200);color:var(--kx-color-text-muted)}
.kx-rate__value{direction:ltr;unicode-bidi:isolate;font-variant-numeric:tabular-nums;
  font-size:var(--kx-fs-600);font-weight:var(--kx-fw-display);
  color:var(--kx-color-text-strong);line-height:1.2}
.kx-rate__unit{font-size:var(--kx-fs-200);color:var(--kx-color-text-muted)}
.kx-rate__meta{margin-inline-start:auto;font-size:var(--kx-fs-200);
  color:var(--kx-color-text-muted)}
.kx-rate--stale{border-color:var(--kx-color-rate-stale);
  background:var(--kx-color-warn-bg)}
.kx-rate--stale .kx-rate__meta{color:var(--kx-color-rate-stale);
  font-weight:var(--kx-fw-strong)}

/* --- calculator ------------------------------------------------------------
   The result panel is a sunken surface so it reads as an output, not another
   input. It is also a live region: the total changes as you type. */
.kx-calc__out{margin-block-start:var(--kx-space-6);
  background:var(--kx-color-surface-sunken);border-radius:var(--kx-radius-md);
  padding-block:var(--kx-space-5);padding-inline:var(--kx-space-5)}
.kx-calc__total{display:flex;justify-content:space-between;align-items:baseline;
  gap:var(--kx-space-4);margin-block-start:var(--kx-space-4);
  padding-block-start:var(--kx-space-4);
  border-block-start:1px solid var(--kx-color-border-strong)}
.kx-calc__total .kx-price{font-size:var(--kx-fs-800)}

/* --- cost breakdown --------------------------------------------------------*/
.kx-break{display:grid;gap:var(--kx-space-2)}
.kx-break__row{display:grid;grid-template-columns:1fr auto;gap:var(--kx-space-4);
  align-items:baseline;font-size:var(--kx-fs-300)}
.kx-break__row dt{color:var(--kx-color-text);margin:0}
.kx-break__row dd{margin:0;direction:ltr;unicode-bidi:isolate;
  font-variant-numeric:tabular-nums;color:var(--kx-color-text-strong);
  font-weight:var(--kx-fw-medium)}
.kx-break__note{font-size:var(--kx-fs-200);color:var(--kx-color-text-muted)}

/* --- rate-change comparison ------------------------------------------------
   Shown when the rate on the proforma no longer matches today's. Two figures
   side by side, because "the price changed" is not actionable but
   "1,450 then, 1,505 now" is. */
.kx-ratediff{display:grid;grid-template-columns:1fr auto 1fr;gap:var(--kx-space-4);
  align-items:center;margin-block-start:var(--kx-space-4);
  padding-block:var(--kx-space-4);padding-inline:var(--kx-space-4);
  background:var(--kx-color-surface);border-radius:var(--kx-radius-sm)}
.kx-ratediff__cell{text-align:center}
.kx-ratediff__k{display:block;font-size:var(--kx-fs-200);
  color:var(--kx-color-text-muted);margin-block-end:var(--kx-space-1)}
.kx-ratediff__v{direction:ltr;unicode-bidi:isolate;font-variant-numeric:tabular-nums;
  font-size:var(--kx-fs-500);font-weight:var(--kx-fw-display);
  color:var(--kx-color-text-strong)}
.kx-ratediff__arrow{color:var(--kx-color-text-muted);font-size:var(--kx-fs-500)}

/* --- process timeline ------------------------------------------------------
   Numbered steps threaded on ONE continuous connector: a ::before track plus
   a ::after fill whose length is --kx-progress (0..1), set live by
   kx-order.js as the reader scrolls - forward fills it, scrolling back
   rewinds it. The default is 1, so with no JS (or reduced motion, where the
   script never arms) the timeline simply renders finished. Steps the fill
   has passed carry .is-done; until then, .kx-steps--live (JS-armed only)
   dims them.

   Vertical below 900px, horizontal from 900px up. Horizontal track geometry
   assumes gap:0 with the breathing room as per-item padding: the end offsets
   are 100%/(2n) - a column-centre - and a real gap would break that math.
   All logical properties, so RTL runs the line right-to-left for free.

   The vertical tail below the LAST circle is painted over by that li's
   ::after in the band's own background - the section sits in a PLAIN band
   (the marquee above it is the sunken one; the alternation is what separates
   them), so the eraser must be --kx-color-surface. */
.kx-steps{--kx-progress:1;--kx-steps-n:6;
  list-style:none;margin:0;padding:0;display:grid;gap:var(--kx-space-6);
  position:relative}
.kx-steps::before{content:"";position:absolute;inset-block-start:20px;
  inset-block-end:0;inset-inline-start:19px;inline-size:2px;
  background:var(--kx-color-border)}
.kx-steps::after{content:"";position:absolute;inset-block-start:20px;
  inset-inline-start:19px;inline-size:2px;
  block-size:calc((100% - 20px) * var(--kx-progress, 1));
  background:var(--kx-color-support);
  transition:block-size .2s ease-out,inline-size .2s ease-out}
.kx-step{display:grid;grid-template-columns:auto 1fr;gap:var(--kx-space-4);
  align-items:start;position:relative}
/* z-index lifts the eraser above the ol's ::after fill, which as a later
   sibling in paint order would otherwise draw its tail over it. */
.kx-step:last-child::after{content:"";position:absolute;
  inset-block-start:40px;inset-block-end:0;
  inset-inline-start:19px;inline-size:2px;z-index:1;
  background:var(--kx-color-surface)}
.kx-step__n{inline-size:40px;block-size:40px;border-radius:var(--kx-radius-circle);
  background:var(--kx-color-support);color:var(--kx-color-support-on);
  display:grid;place-items:center;font-weight:var(--kx-fw-display);
  font-variant-numeric:tabular-nums;flex:0 0 auto;z-index:1;
  transition:background-color .35s ease-out,color .35s ease-out,
    box-shadow .35s ease-out}
/* Not-yet-reached steps, only once the script is driving the fill. */
.kx-steps--live .kx-step:not(.is-done) .kx-step__n{
  background:var(--kx-color-surface-sunken);color:var(--kx-color-text-muted);
  box-shadow:inset 0 0 0 2px var(--kx-color-border)}
/* font-size is stated, not inherited: these titles are <h3> for the document
   outline, and a UA h3 size would blow up a step label. */
.kx-step__t{font-size:var(--kx-fs-400);font-weight:var(--kx-fw-strong);
  color:var(--kx-color-text-strong);margin-block-end:var(--kx-space-1)}
.kx-step__d{font-size:var(--kx-fs-300);color:var(--kx-color-text)}
@media (max-width: 520px){
  .kx-steps{gap:var(--kx-space-4)}
  .kx-step{gap:var(--kx-space-3)}
}
@media (min-width: 900px){
  .kx-steps{grid-template-columns:none;grid-auto-flow:column;
    grid-auto-columns:1fr;gap:0}
  .kx-step{grid-template-columns:1fr;justify-items:center;text-align:center;
    gap:var(--kx-space-3);padding-inline:var(--kx-space-2)}
  .kx-steps::before{inset-block-start:20px;inset-block-end:auto;
    block-size:2px;inline-size:auto;
    inset-inline-start:calc(100% / (var(--kx-steps-n, 6) * 2));
    inset-inline-end:calc(100% / (var(--kx-steps-n, 6) * 2))}
  .kx-steps::after{inset-block-start:20px;block-size:2px;
    inset-inline-start:calc(100% / (var(--kx-steps-n, 6) * 2));
    inline-size:calc((100% - 100% / var(--kx-steps-n, 6)) * var(--kx-progress, 1))}
  .kx-step:last-child::after{content:none}
}

/* --- trust strip -----------------------------------------------------------*/
.kx-trust{display:flex;flex-wrap:wrap;gap:var(--kx-space-4);align-items:center;
  padding-block:var(--kx-space-5);padding-inline:var(--kx-space-5);
  background:var(--kx-color-surface-sunken);border-radius:var(--kx-radius-md)}
.kx-trust__item{display:flex;align-items:center;gap:var(--kx-space-2);
  font-size:var(--kx-fs-200);color:var(--kx-color-text-strong);
  font-weight:var(--kx-fw-medium)}
.kx-trust__mark{inline-size:36px;block-size:36px;border-radius:var(--kx-radius-sm);
  background:var(--kx-color-surface);border:1px solid var(--kx-color-border);
  display:grid;place-items:center;font-size:var(--kx-fs-100);
  color:var(--kx-color-text-muted)}

/* --- FAQ -------------------------------------------------------------------
   Native <details>/<summary>: keyboard and screen-reader behaviour for free,
   and it still works with JavaScript disabled. */
.kx-faq{display:grid;gap:var(--kx-space-2)}
.kx-faq details{border:1px solid var(--kx-color-border);
  border-radius:var(--kx-radius-md);background:var(--kx-color-surface)}
.kx-faq summary{cursor:pointer;list-style:none;
  min-block-size:var(--kx-target-min);display:flex;align-items:center;
  justify-content:space-between;gap:var(--kx-space-4);
  padding-block:var(--kx-space-4);padding-inline:var(--kx-space-5);
  font-weight:var(--kx-fw-strong);color:var(--kx-color-text-strong)}
.kx-faq summary::-webkit-details-marker{display:none}
.kx-faq summary::after{content:"+";font-size:var(--kx-fs-500);
  color:var(--kx-color-accent-ink);line-height:1}
.kx-faq details[open] summary::after{content:"\2212"}
.kx-faq__a{padding-block:0 var(--kx-space-5);padding-inline:var(--kx-space-5);
  font-size:var(--kx-fs-300)}

/* --- size table ------------------------------------------------------------*/
.kx-sizes{overflow-x:auto}
.kx-sizes table{min-inline-size:520px}
.kx-sizes th[scope="row"]{font-weight:var(--kx-fw-strong);
  background:var(--kx-color-surface-sunken)}


/* ===== commerce.css ===== */
/* ============================================================================
   KharidExpress DS - commerce + ordering surfaces.
   Tokens only, logical properties only.
   ========================================================================== */

/* --- product card ----------------------------------------------------------
   The current shop puts product art on a peach tint. Kept, because it reads as
   deliberate rather than as a missing background. */
.kx-prod{display:flex;flex-direction:column;background:var(--kx-color-surface);
  border:1px solid var(--kx-color-border);border-radius:var(--kx-radius-lg);
  overflow:hidden;block-size:100%}
.kx-prod__media{position:relative;aspect-ratio:1/1;
  background:var(--kx-color-accent-wash);display:grid;place-items:center;
  color:var(--kx-color-text-muted);font-size:var(--kx-fs-200)}
.kx-prod__flag{position:absolute;inset-block-start:var(--kx-space-3);
  inset-inline-start:var(--kx-space-3)}
.kx-prod__body{padding-block:var(--kx-space-4) var(--kx-space-5);
  padding-inline:var(--kx-space-5);display:flex;flex-direction:column;
  gap:var(--kx-space-2);flex:1}
.kx-prod__t{font-weight:var(--kx-fw-strong);color:var(--kx-color-text-strong);
  font-size:var(--kx-fs-300);line-height:var(--kx-lh-tight)}
.kx-prod__src{font-size:var(--kx-fs-200);color:var(--kx-color-text-muted)}
.kx-prod__foot{margin-block-start:auto;padding-block-start:var(--kx-space-3);
  display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--kx-space-3)}
.kx-grid{display:grid;gap:var(--kx-space-5);
  grid-template-columns:repeat(auto-fill,minmax(220px,1fr))}

/* --- Iranian address -------------------------------------------------------
   Persian WooCommerce turns city into a dependent <select> and forces province
   and city into half-width rows. Those IDs and the form-row-first/last classes
   are load-bearing: its inline footer script targets them directly. This block
   reproduces that structure exactly so the design cannot break the plugin. */
.kx-addr{display:grid;grid-template-columns:1fr 1fr;gap:var(--kx-space-5)}
@media (max-width:560px){.kx-addr{grid-template-columns:1fr}}
.kx-addr__full{grid-column:1 / -1}

/* --- footer ----------------------------------------------------------------*/
.kx-footer{background:var(--kx-color-surface-sunken);
  padding-block:var(--kx-space-10);padding-inline:var(--kx-gutter);
  margin-block-start:var(--kx-space-12)}
.kx-footer__grid{display:grid;gap:var(--kx-space-8);max-inline-size:1060px;
  margin-inline:auto;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.kx-footer h3{font-size:var(--kx-fs-300);font-weight:var(--kx-fw-strong);
  color:var(--kx-color-text-strong);margin-block-end:var(--kx-space-4)}
.kx-footer ul{list-style:none;margin:0;padding:0;display:grid;
  gap:var(--kx-space-2);font-size:var(--kx-fs-300)}
/* A footer nav list is a set of targets, not prose, so WCAG 2.2 2.5.8's
   inline-in-a-sentence exception does not apply. Measured at 23px before this. */
.kx-footer ul a{display:inline-flex;align-items:center;min-block-size:32px}
.kx-footer a{color:var(--kx-color-text);text-decoration:none}
.kx-footer a:hover{color:var(--kx-color-accent-ink);text-decoration:underline}
.kx-social{display:flex;gap:var(--kx-space-3);flex-wrap:wrap}
/* The owner's own CSS commented the orange out of these and went neutral grey.
   That instinct is kept: social chips are quiet, the CTA is not. */
.kx-social a{display:inline-flex;align-items:center;gap:var(--kx-space-2);
  min-block-size:var(--kx-target-min);
  padding-block:var(--kx-space-2);padding-inline:var(--kx-space-4);
  background:var(--kx-color-surface);border:1px solid var(--kx-color-border);
  border-radius:var(--kx-radius-sm);font-size:var(--kx-fs-200);
  color:var(--kx-color-text-strong);text-decoration:none}
.kx-social a:hover{background:var(--kx-color-canvas)}

/* --- brand landing pattern -------------------------------------------------
   The Zara / Trendyol / Bershka pages are ~213k-character near-identical clones
   in the database. This is the same page as composition instead of copy-paste. */
.kx-band{padding-block:var(--kx-space-10);padding-inline:var(--kx-gutter)}
.kx-band--sunken{background:var(--kx-color-surface-sunken)}
.kx-band__in{max-inline-size:1060px;margin-inline:auto}
/* Explicit, even tracks instead of auto-fit: auto-fit at the 1060px band width
   packed 5 features as 4+1 - a lone orphan on its own row. Fixed counts per
   range plus a last-child full-width rule keep every row balanced whatever
   count the merchant configures. In RTL the grid auto-flows right-to-left, so
   the reading order stays logical with no override.

   The cells are the Aceternity "hover effects" treatment ported to tokens:
   a gapless grid ruled by hairline dividers, each cell an icon / title /
   description column; hovering a cell raises a soft surface glow, grows and
   recolours the accent bar beside the title, and nudges the title inward.
   Divider logic must work for ANY row count, so the horizontal rules are
   border-block-START on everything except the (deterministic) first row -
   a border-end scheme would need to know which cells form the last row,
   which CSS cannot express for an arbitrary count. */
.kx-cols{display:grid;gap:0;grid-template-columns:1fr}
/* Rules BETWEEN cells only, never around the group: a border on the outer
   edges would box the section in, which is not what the grid is doing. Each
   cell draws the rule on its own start edge and the first cell of each row
   drops it - so the outer edge is always the one that got dropped, whatever
   the column count or the card count. */
.kx-cols .kx-feature{border-block-start:1px solid var(--kx-color-border)}
.kx-cols .kx-feature:first-child{border-block-start:0}
@media (min-width: 560px) and (max-width: 899px){
  .kx-cols{grid-template-columns:repeat(2, 1fr)}
  .kx-cols .kx-feature:last-child:nth-child(odd){grid-column:1 / -1}
  .kx-cols .kx-feature{border-inline-start:1px solid var(--kx-color-border)}
  .kx-cols .kx-feature:nth-child(2n+1){border-inline-start:0}
  .kx-cols .kx-feature:nth-child(-n+2){border-block-start:0}
}
@media (min-width: 900px){
  .kx-cols{grid-template-columns:repeat(3, 1fr)}
  /* Fill the last row rather than leaving a ruled, empty cell: a lone
     trailing card takes the whole row, and a pair splits it. With the five
     shipped reasons that turns 3 + 2 + hole into 3 + 2 spanning full. */
  .kx-cols .kx-feature:last-child:nth-child(3n+1){grid-column:1 / -1}
  .kx-cols .kx-feature:last-child:nth-child(3n+2){grid-column:span 2}
  .kx-cols .kx-feature{border-inline-start:0;
    border-block-start:1px solid var(--kx-color-border)}
  .kx-cols .kx-feature:nth-child(3n+1){border-inline-start:1px solid var(--kx-color-border)}
  .kx-cols .kx-feature:nth-child(-n+3){border-block-start:0}
}
.kx-feature{position:relative;display:flex;flex-direction:column;
  padding-block:var(--kx-space-7);padding-inline:var(--kx-space-6)}
/* The hover glow: a surface-white wash rising from the cell's foot. */
.kx-feature::before{content:"";position:absolute;inset:0;opacity:0;
  pointer-events:none;transition:opacity .2s ease-out;
  background:linear-gradient(to top, var(--kx-color-surface), transparent)}
.kx-feature:hover::before{opacity:1}
.kx-feature__ic{position:relative;z-index:1;color:var(--kx-color-text-muted);
  margin-block-end:var(--kx-space-4)}
.kx-feature__ic svg{display:block}
.kx-feature__t{position:relative;z-index:1;font-weight:var(--kx-fw-strong);
  font-size:var(--kx-fs-400);color:var(--kx-color-text-strong);
  margin-block-end:var(--kx-space-2)}
/* The accent bar at the cell's inline-start edge, beside the title. */
.kx-feature__t::before{content:"";position:absolute;
  inset-inline-start:calc(-1 * var(--kx-space-6));inset-block-start:50%;
  transform:translateY(-50%);inline-size:4px;block-size:24px;
  border-radius:var(--kx-radius-pill);background:var(--kx-color-border-strong);
  transition:block-size .2s ease-out,background-color .2s ease-out}
.kx-feature:hover .kx-feature__t::before{block-size:34px;
  background:var(--kx-color-accent)}
.kx-feature__t > span{display:inline-block;transition:transform .2s ease-out}
.kx-feature:hover .kx-feature__t > span{transform:translateX(8px)}
.rtl .kx-feature:hover .kx-feature__t > span{transform:translateX(-8px)}
.kx-feature__d{position:relative;z-index:1;font-size:var(--kx-fs-300);
  color:var(--kx-color-text)}

/* ============================================================================
   Plugin-specific layer. Tokens only, logical properties only.
   Nothing here introduces a new visual direction.
   ========================================================================== */

.kx-co{max-inline-size:720px;margin-inline:auto}
/* With the sidebar present the 720px single-column cap starved the form down
   to 400px. The layout variant takes the band's full content width instead:
   1060 - 300 sidebar - 20 gap = a 740px form. */
.kx-co--wide{max-inline-size:1060px}
.kx-co__intro{margin-block-end:var(--kx-space-6);font-size:var(--kx-fs-300);
  line-height:var(--kx-lh-body)}
.kx-co__title{margin-block-end:var(--kx-space-6)}
.kx-co__actions{display:flex;flex-wrap:wrap;gap:var(--kx-space-3);
  margin-block-start:var(--kx-space-6)}
/* The single remaining action carries the whole row now that "پاک کردن" is
   gone; full width reads as the intended primary action rather than a small
   button stranded at one edge. */
.kx-co__actions .kx-btn--cta{inline-size:100%}
.kx-co__deferred{margin-block-start:var(--kx-space-4)}
.kx-co__phone{margin-block-start:var(--kx-space-6);color:var(--kx-color-text-muted)}
.kx-co__phone a{color:var(--kx-color-accent-ink);text-decoration:none}
.kx-co__phone a:hover{text-decoration:underline}

/* --- link preview -----------------------------------------------------------
   Lives at the top of the sidebar now, product-page style: the photo (or the
   brand mark, when the merchant's site refuses a server-side fetch - most of
   them do) is the first thing a returning customer looks for to confirm this
   is the right order, so it leads the card rather than sitting as a strip
   under the URL field.

   Fixed aspect-ratio on the media box so a late-arriving image cannot reflow
   anything below it - the card's block-size is stable from the moment it
   un-hides. */
.kx-side__card--preview{padding:0;overflow:hidden}
.kx-preview__media{position:relative;aspect-ratio:4/3;
  background:var(--kx-color-surface-sunken);
  display:flex;align-items:center;justify-content:center}
.kx-preview__thumb{position:absolute;inset:0;inline-size:100%;block-size:100%;
  object-fit:cover}
.kx-preview__logo{inline-size:72px;block-size:72px;object-fit:contain;
  border-radius:var(--kx-radius-sm)}
/* A photo loaded: the logo steps down to a corner badge identifying the
   store, the same role it plays everywhere else (cart, order, email). */
.kx-preview__thumb:not([hidden]) ~ .kx-preview__logo{
  position:absolute;inset-block-end:var(--kx-space-2);inset-inline-end:var(--kx-space-2);
  inline-size:32px;block-size:32px;padding:4px;
  background:var(--kx-color-surface);border-radius:var(--kx-radius-sm);
  box-shadow:0 1px 3px rgb(var(--kx-shadow-tint) / .25)}
.kx-preview__body{padding:var(--kx-space-3) var(--kx-space-4) var(--kx-space-4);
  display:grid;gap:2px}
.kx-preview__seller{display:flex;align-items:baseline;gap:var(--kx-space-2);margin:0}
.kx-preview__label{font-size:var(--kx-fs-100);color:var(--kx-color-text-muted)}
.kx-preview__domain{font-size:var(--kx-fs-200);font-weight:var(--kx-fw-strong);
  color:var(--kx-color-text-strong)}
.kx-preview__title{font-size:var(--kx-fs-200);color:var(--kx-color-text-muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* --- cart ----------------------------------------------------------------- */
.kx-qty-locked{font-variant-numeric:tabular-nums;direction:ltr;unicode-bidi:isolate;
  display:inline-block;min-inline-size:2ch;text-align:center}

/* The quote block is an output, not an input: give it a sunken ground so it
   never reads as another field. */
.kx-co .kx-calc__out{margin-block-start:var(--kx-space-6)}

/* ---------------------------------------------------------------------------
   Re-quote acceptance
   Shown in cart/checkout when the rate window lapsed and the total moved.
   Checkout stays blocked until the customer presses the accept control, so
   this block must read as a decision, not as a passive notice.
   ------------------------------------------------------------------------ */
.kx-requote {
  border: 1px solid var(--kx-color-border-strong, #857c6b);
  border-inline-start: 4px solid var(--kx-color-accent-line, #cf6819);
  border-radius: var(--kx-radius-lg, 16px);
  background: var(--kx-color-surface-sunken);
  padding: var(--kx-space-5, 20px);
  margin-block-end: var(--kx-space-5, 20px);
}
.kx-requote__lead { margin: 0 0 var(--kx-space-3, 12px); font-weight: 600; }
.kx-requote__list { margin: 0 0 var(--kx-space-4, 16px); padding: 0; list-style: none; }
.kx-requote__list li { display: flex; gap: var(--kx-space-3, 12px); align-items: baseline; }
.kx-requote__was {
  text-decoration: line-through;
  color: var(--kx-color-text-muted);
  direction: ltr;
  unicode-bidi: isolate;
}
.kx-requote__now {
  font-weight: 700;
  color: var(--kx-color-accent-ink, #a25112);
  direction: ltr;
  unicode-bidi: isolate;
}
/* 24px floor, WCAG 2.2 target size. */
.kx-requote__accept { min-block-size: 44px; display: inline-flex; align-items: center; }

/* ---------------------------------------------------------------------------
   Line image
   The merchant photo or brand logo shown wherever WooCommerce would show a
   product thumbnail: cart, checkout, order page, emails, wp-admin.
   ------------------------------------------------------------------------ */
/* No background: each logo already carries its own tile, so a plate behind it
   would draw a ring around every coloured one. */
.kx-line-img {
  inline-size: 64px;
  block-size: 64px;
  object-fit: contain;
  border-radius: 10px;
}
.kx-line-img--inline {
  inline-size: 40px;
  block-size: 40px;
  vertical-align: middle;
  margin-inline-end: 8px;
  border-radius: 8px;
}

/* ---------------------------------------------------------------------------
   Form + sidebar
   The sidebar answers the two questions a first-time buyer has before pasting
   a link: "who do I ask?" and "is this the real price?". It sits beside the
   form on desktop and BELOW it on mobile — the form is the task, the sidebar
   is support, so the form must never be pushed off the first screen.

   The sidebar sits to the READING-START side of the form (the right, in this
   RTL page) - `order` does that visually while the form stays FIRST in the
   DOM, so keyboard/tab order still reaches the form fields before the
   sidebar's links. Reordering the markup instead would have fixed the visual
   but broken that.
   ------------------------------------------------------------------------ */
.kx-co__layout {
  display: grid;
  gap: var(--kx-space-5, 20px);
  align-items: start;
}
@media (min-width: 900px) {
  /* The sidebar sits on the PHYSICAL RIGHT of the form, which on this RTL
     page is the reading-start side.

     A correction for the record, because the previous comment here asserted
     the opposite: grid's explicit track list IS mirrored by direction, per
     spec - in dir="rtl", column 1 is the RIGHTMOST. The earlier "empirical
     proof" that it was not came from a test WordPress that was still an
     English LTR install while production is Persian RTL; the measurement
     was real, the environment was wrong. Verified again after switching the
     rig to fa_IR: the old layout put the sidebar on the LEFT in RTL,
     matching the production screenshot that exposed it.

     So: column 1 (rightmost in RTL) is the 300px sidebar track, column 2
     the form. Explicit placement, not DOM order, decides who goes where -
     the form stays FIRST in the DOM so keyboard tab order still reaches its
     fields before the sidebar's links. */
  .kx-co__layout {
    grid-template-columns: 300px minmax(0, 1fr);
  }
  .kx-co__intro { grid-column: 1 / -1; }
  .kx-side      { grid-column: 1; grid-row: 2; }
  .kx-co__form  { grid-column: 2; grid-row: 2; }
  .kx-co__layout--solo { grid-template-columns: minmax(0, 1fr); }
  .kx-co__layout--solo .kx-co__form { grid-column: 1; }
}

.kx-side {
  display: grid;
  gap: var(--kx-space-4, 16px);
  align-content: start;
}

.kx-side__card {
  border: 1px solid var(--kx-color-border, #d9d1c4);
  border-radius: var(--kx-radius-lg, 16px);
  background: var(--kx-color-surface, #fff);
  padding: var(--kx-space-4, 16px);
}
.kx-side__card p { margin: 0; }

/* The fee note is the single most reassuring line on the page, so it gets the
   accent edge and nothing else competes with it. */
.kx-side__card--fee {
  display: flex;
  gap: var(--kx-space-3, 12px);
  align-items: flex-start;
  background: var(--kx-color-surface-sunken, #f4efe6);
  border-inline-start: 4px solid var(--kx-color-accent-line, #cf6819);
  font-weight: 600;
  line-height: 1.7;
}
.kx-side__icon {
  inline-size: 22px;
  block-size: 22px;
  flex: 0 0 auto;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--kx-color-accent-line, #cf6819);
  color: #fff;
  font-size: 13px;
  line-height: 1;
}
.kx-side__icon svg { display: block; }

/* The call card is the answer to "something went wrong, now what" - the one
   moment on the page where a person wants a HUMAN, not a form field. It gets
   the same accent-edge treatment as the fee card, in navy rather than orange,
   so the two read as a pair: orange = reassurance, navy = action. */
/* Teal, not navy: the CTA is "buy", this card is "ask a human" - two
   different jobs deserve two different colours. teal-600 is used as a FILL
   only (white on it is 5.00:1); teal-700 carries any text role, because
   teal-600 as text on the sunken ground measures 4.37:1 and misses AA. */
.kx-side__card--call {
  border-inline-start: 4px solid var(--kx-color-support, #0f7d72);
}
.kx-side__card-head {
  display: flex;
  align-items: center;
  gap: var(--kx-space-3, 12px);
  margin-block-end: var(--kx-space-3, 12px);
}
.kx-side__card--call .kx-side__icon {
  background: var(--kx-color-support, #0f7d72);
  inline-size: 28px;
  block-size: 28px;
}

.kx-side__lead {
  font-size: var(--kx-fs-200, 14px);
  color: var(--kx-color-text-muted, #736c5f);
  margin-block-end: var(--kx-space-2, 8px) !important;
}
/* Inside the call header the icon+lead sit in a row and the FLEX gap does the
   spacing, not a block margin - a bottom margin here would just add dead
   space under a row, not between the row and what follows. */
.kx-side__card-head .kx-side__lead {
  color: var(--kx-color-text-strong, #16233d);
  font-weight: var(--kx-fw-strong, 700);
  margin: 0 !important;
}
.kx-side__phone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--kx-space-2, 8px);
  min-block-size: 48px;          /* WCAG 2.5.8 target size, +4px over the floor
                                     since this is the card's whole purpose */
  inline-size: 100%;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  border-radius: var(--kx-radius-md, 12px);
  /* !important for the same reason as .kx-btn--cta above: this is a
     click-to-call button, not body copy, and the generic `a:hover{color:
     accent-ink}` rule elsewhere in this file was winning on hover for the
     COLOR property alone (higher specificity than a single class), turning
     white text orange on a navy background - unreadable, on a control a
     worried customer is actively trying to use. */
  background: var(--kx-color-support, #0f7d72) !important;
  color: var(--kx-color-support-on, #fff) !important;
  text-decoration: none;
  direction: ltr;
  unicode-bidi: isolate;
  box-shadow: 0 2px 0 0 rgb(var(--kx-shadow-tint, 91 45 0) / .18);
}
.kx-side__phone:hover,
.kx-side__phone:focus-visible {
  background: var(--kx-color-support-hover, #0a5f57) !important;
  color: var(--kx-color-support-on, #fff) !important;
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgb(var(--kx-shadow-tint, 91 45 0) / .22);
}
.kx-side__phone-icon { display: flex; flex: 0 0 auto; }

/* A quiet pulse draws the eye to the one control on the page a worried
   customer actually needs, without demanding attention from everyone else. */
@media (prefers-reduced-motion: no-preference) {
  .kx-side__card--call .kx-side__icon { animation: kx-call-pulse 2.4s ease-in-out infinite; }
}
@keyframes kx-call-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgb(15 125 114 / .35); }
  50%      { box-shadow: 0 0 0 6px rgb(15 125 114 / 0); }
}

.kx-side__trust {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--kx-space-3, 12px);
}
.kx-side__trust li {
  position: relative;
  padding-inline-start: 26px;
  font-size: var(--kx-fs-200, 14px);
  line-height: 1.75;
  color: var(--kx-color-text, #4a5160);
}
.kx-side__trust li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: .55em;
  inline-size: 14px;
  block-size: 8px;
  border-inline-start: 2px solid var(--kx-color-accent-line, #cf6819);
  border-block-end: 2px solid var(--kx-color-accent-line, #cf6819);
  transform: rotate(-45deg);
}

/* --- delivery: time and freight, per origin ---------------------------------
   One lightweight inner card per country, separated by their own borders
   rather than by whitespace, so the card stays compact while the two origins
   stay unmistakably distinct. Deliberately quieter than the contact card
   above it: a tinted surface and hairline borders, no shadow, and the orange
   appears only at icon size - this is reference information the reader
   consults, not the action the page wants.

   Label and value are a two-column row: the label is small and muted, the
   value carries the weight, so the numbers are what the eye lands on. */
.kx-side__sub {
  margin-block: 2px var(--kx-space-3);
  font-size: var(--kx-fs-200);
  line-height: 1.6;
  color: var(--kx-color-text-muted);
}
.kx-eta {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--kx-space-2);
}
.kx-eta__item {
  padding: var(--kx-space-3);
  border: 1px solid var(--kx-color-border);
  border-radius: var(--kx-radius-md);
  background: var(--kx-color-surface-sunken);
}
.kx-eta__country {
  display: flex;
  align-items: center;
  gap: var(--kx-space-2);
  margin-block-end: var(--kx-space-2);
  font-size: var(--kx-fs-400);
  font-weight: var(--kx-fw-strong);
  color: var(--kx-color-text-strong);
}
/* Flags are geography, not UI: they never mirror, and they keep the same
   proportions the currency chip uses so the two read as the same object. */
.kx-eta__flag {
  display: inline-flex;
  flex: 0 0 auto;
}
.kx-eta__flag svg {
  display: block;
  inline-size: 20px;
  block-size: 14px;
  border-radius: 3px;
}
.kx-eta__facts {
  display: grid;
  gap: 6px;
}
.kx-eta__fact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--kx-space-3);
}
.kx-eta__k {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  font-size: var(--kx-fs-200);
  color: var(--kx-color-text-muted);
}
/* The one spot of orange in this card, at 14px. */
.kx-eta__ic {
  display: inline-flex;
  color: var(--kx-color-accent);
  /* baseline alignment would hang the icon low against the label's x-height */
  align-self: center;
}
.kx-eta__v {
  text-align: end;
  font-size: var(--kx-fs-300);
  font-weight: var(--kx-fw-strong);
  color: var(--kx-color-text-strong);
}
/* The unit rides with the figure but must not compete with it. */
.kx-eta__u {
  display: block;
  font-size: var(--kx-fs-100);
  font-weight: var(--kx-fw-body);
  color: var(--kx-color-text-muted);
}

/* ---------------------------------------------------------------------------
   Ordering guide
   ------------------------------------------------------------------------ */
.kx-terms {
  margin-block-start: var(--kx-space-7, 32px);
  padding-block-start: var(--kx-space-6, 24px);
  border-block-start: 1px solid var(--kx-color-border, #d9d1c4);
}
.kx-terms__title {
  font-size: var(--kx-fs-500, 21px);
  color: var(--kx-color-text-strong, #16233d);
  margin: 0 0 var(--kx-space-4, 16px);
}
.kx-terms__body { max-inline-size: 68ch; }
.kx-terms__body h3 {
  font-size: var(--kx-fs-300, 16px);
  color: var(--kx-color-text-strong, #16233d);
  margin: var(--kx-space-5, 20px) 0 var(--kx-space-2, 8px);
}
.kx-terms__body p { margin: 0 0 var(--kx-space-3, 12px); line-height: 1.85; }
.kx-terms__body ul { margin: 0 0 var(--kx-space-3, 12px); padding-inline-start: 1.2em; }
.kx-terms__body li { margin-block-end: 6px; line-height: 1.85; }

/* ---------------------------------------------------------------------------
   Landing composition
   Every section below is an existing design-system component; only the eyebrow,
   the merchant marquee and the reveal are new. All values come from tokens.
   ------------------------------------------------------------------------ */

.kx-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--kx-space-2, 8px);
  padding: 6px 14px;
  border-radius: var(--kx-radius-pill, 999px);
  background: var(--kx-color-accent-wash, #fdf0e2);
  color: var(--kx-color-accent-ink, #a25112);
  font-size: var(--kx-fs-100, 13px);
  font-weight: var(--kx-fw-strong, 700);
  margin-block-end: var(--kx-space-4, 16px);
}

.kx-hero__lead {
  max-inline-size: 54ch;
  font-size: var(--kx-fs-400, 18px);
  color: var(--kx-color-text-muted, #736c5f);
  line-height: 1.85;
  text-wrap: pretty;
}

.kx-lp__rate { margin-block-start: var(--kx-space-6, 24px); }
.kx-lp__note { margin-block: var(--kx-space-2, 8px) var(--kx-space-5, 20px); }
.kx-lp__h { margin-block-end: var(--kx-space-6, 24px); }

/* --- merchant marquee ---------------------------------------------------- */

.kx-marquee {
  --kx-marquee-dur: 46s;
  /* Pinned LTR on purpose, on an RTL page. In RTL the flex track anchors to
     the container's RIGHT edge and overflows leftward, so translateX(-50%)
     moves the track's coverage AWAY from the window - the strip plays once,
     ends on blank space, and never wraps. The loop's -50% math assumes the
     LTR anchoring (track pinned left, second copy sliding in from the
     right), and a row of logos has no reading order to preserve - the
     aria-hidden duplicate already handles what a screen reader hears. */
  direction: ltr;
  position: relative;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.kx-marquee__track { display: flex; inline-size: max-content; gap: var(--kx-space-4, 16px); }
.kx-marquee__tile {
  flex: 0 0 auto;
  inline-size: 96px;
  block-size: 96px;
  display: grid;
  place-items: center;
  border: 1px solid var(--kx-color-border, #d9d1c4);
  border-radius: var(--kx-radius-md, 12px);
  background: var(--kx-color-surface, #fff);
}
.kx-marquee__tile img { inline-size: 60px; block-size: 60px; object-fit: contain; }

/* The track is duplicated in the markup, so translating exactly -50% lands on
   an identical frame and the loop is seamless. */
@media (prefers-reduced-motion: no-preference) {
  .kx-marquee__track { animation: kx-marquee var(--kx-marquee-dur) linear infinite; }
  .kx-marquee:hover .kx-marquee__track,
  .kx-marquee:focus-within .kx-marquee__track { animation-play-state: paused; }
}
@keyframes kx-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
/* Motion off: no animation, and the duplicate track becomes scrollable rather
   than a second copy the reader has to pass twice. */
@media (prefers-reduced-motion: reduce) {
  .kx-marquee { -webkit-mask-image: none; mask-image: none; overflow-x: auto; }
}

/* --- scroll reveal ------------------------------------------------------- */

/* The visible state is the BASE state: with no JS, no IntersectionObserver, or
   reduced motion, the content is simply there. The hidden start is opt-in and
   only applied once JS has confirmed it can undo it. */
@media (prefers-reduced-motion: no-preference) {
  .kx-js .kx-reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .5s ease-out, transform .5s ease-out;
  }
  .kx-js .kx-reveal.is-in { opacity: 1; transform: none; }

  /* The timeline's own animation is NOT here: its fill is scroll-linked
     (--kx-progress, driven live by kx-order.js and reversible), not a
     one-shot reveal - see the process-timeline block. Only the generic
     container fade above applies to the <ol>. */

  /* Why-us grid: cards fade up in sequence off the observer mark. */
  .kx-js .kx-cols.kx-reveal .kx-feature {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity .45s ease-out, transform .45s ease-out;
    transition-delay: calc(var(--i, 0) * .06s);
  }
  .kx-js .kx-cols.kx-reveal.is-in .kx-feature { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------------
   Full-bleed landing

   Avada (and most themes) wrap page content in a fixed-width container, so the
   bands can only ever be as wide as that container and the page reads as a
   narrow column floating in white space. .kx-band__in keeps the text itself
   at a readable 1060px regardless of how wide the band becomes.

   No CSS rule here on purpose - .kx-lp--bleed is purely a marker class for
   the JS below to select. Two earlier attempts at a CSS-only guess both
   failed for reasons worth recording, because a third attempt WILL be
   tempted to reintroduce one:

     1. margin-inline: calc(50% - 50vw) PLUS an explicit width makes a
        normal-flow block box over-constrained (CSS2.1 10.3.3). The RTL
        tiebreak in that rule says the browser must silently DISCARD the
        specified margin-left and recompute it from the others -
        getComputedStyle reported the value that was set; the rendered
        position ignored it completely.
     2. Dropping the width and keeping only the calc-based margin looked
        right in isolation, but then the JS below cleared its OWN inline
        override to re-measure and read back a position CSS had ALREADY
        partly corrected - and then replaced that correction with a much
        smaller one computed as if starting from zero margin, undoing most
        of what CSS had done.

   Two independent systems computing overlapping corrections is the actual
   defect, not either formula alone. With no CSS margin rule, "cleared" in
   the JS below genuinely means margin: 0, so its measurement is honest and
   its correction is the only one in effect. The band simply stays inside
   its normal container - safe, unremarkable, not broken - until JS runs;
   the same fail-open shape as .kx-reveal above. */

/* ---------------------------------------------------------------------------
   Refinements: motion on buttons, a slimmer hero, currency-aware inputs,
   units on every figure, and a real container for the ordering guide.
   ------------------------------------------------------------------------ */

/* --- button hover/active motion -------------------------------------------
   The colour rules above already pin fill and text (see the specificity note
   there). This adds the FEEL: a small lift on hover, pressed on active, and
   the same treatment on :focus-visible so keyboard users get it too. Gated
   on prefers-reduced-motion like everything else that moves. */
.kx-btn { transition: background-color var(--kx-dur-2) var(--kx-ease),
                      border-color var(--kx-dur-2) var(--kx-ease),
                      transform var(--kx-dur-1, 120ms) var(--kx-ease),
                      box-shadow var(--kx-dur-2) var(--kx-ease); }
@media (prefers-reduced-motion: no-preference) {
  .kx-btn--cta:hover, .kx-btn--cta:focus-visible,
  .kx-btn--accent:hover, .kx-btn--accent:focus-visible {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgb(var(--kx-shadow-tint, 91 45 0) / .24);
  }
  .kx-btn:active { transform: translateY(0); box-shadow: none; }
  .kx-btn--ghost:hover, .kx-btn--ghost:focus-visible { transform: translateY(-1px); }
}
.kx-btn--ghost:hover, .kx-btn--ghost:focus-visible {
  border-color: var(--kx-color-cta, #16233d);
}

/* --- slimmer hero ---------------------------------------------------------
   The hero is an introduction, not the destination - the form below it is.
   Roughly half the vertical weight it carried before. */
.kx-band--slim { padding-block: var(--kx-space-7, 32px); }
.kx-band--slim .kx-h1 { font-size: clamp(24px, 3.4vw, var(--kx-fs-800, 38px)); }
.kx-band--slim .kx-hero__lead { margin-block-start: var(--kx-space-3, 12px); }
.kx-band--slim .kx-hero__actions { margin-block-start: var(--kx-space-5, 20px); }

/* --- currency symbol inside the price field ------------------------------- */
.kx-inputwrap { position: relative; }
/* Padding, not a flex sibling: the symbol must sit ON the field so the value
   and its unit read as one number, and the input keeps its full hit area. */
.kx-input--sym { padding-inline-end: 3.2em; }
.kx-inputwrap__sym {
  position: absolute;
  inset-inline-end: var(--kx-space-3, 12px);
  inset-block-start: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  font-weight: var(--kx-fw-strong, 700);
  color: var(--kx-color-text-muted, #736c5f);
  direction: ltr;
  unicode-bidi: isolate;
}
.kx-inputwrap__sym[hidden] { display: none; }

/* --- units on breakdown figures ------------------------------------------- */
.kx-unit {
  font-size: var(--kx-fs-100);
  color: var(--kx-color-text-muted);
  /* The unit sits BEFORE the figure now, so the gap moved with it. */
  margin-inline-end: 6px;
  font-weight: var(--kx-fw-body);
}

/* --- "what the price includes", stated at the price ----------------------- */
.kx-break__includes {
  display: flex;
  align-items: flex-start;
  gap: var(--kx-space-2, 8px);
  margin-block: var(--kx-space-3, 12px) 0;
  padding: var(--kx-space-3, 12px);
  border-radius: var(--kx-radius-md, 12px);
  background: var(--kx-color-success-bg, #eaf3ed);
  color: var(--kx-color-text, #4a5160);
  font-size: var(--kx-fs-200, 14px);
  line-height: 1.75;
}
.kx-break__includes-icon {
  flex: 0 0 auto;
  display: flex;
  margin-block-start: 3px;
  color: var(--kx-color-success-fg, #1c7c4a);
}

/* --- the ordering guide, as a real card ----------------------------------- */
.kx-terms__body {
  max-inline-size: none;
  background: var(--kx-color-surface, #fff);
  border: 1px solid var(--kx-color-border, #d9d1c4);
  border-radius: var(--kx-radius-lg, 16px);
  padding: var(--kx-space-6, 24px);
}
/* Each numbered clause becomes its own block, so the guide scans as a list of
   things to check rather than one wall of prose. */
.kx-terms__body h3 {
  margin-block: var(--kx-space-6, 24px) var(--kx-space-2, 8px);
  padding-block-end: var(--kx-space-2, 8px);
  border-block-end: 1px solid var(--kx-color-border, #d9d1c4);
}
.kx-terms__body h3:first-child { margin-block-start: 0; }
@media (min-width: 900px) {
  /* Two columns on wide screens: the guide is reference material, and a
     68ch line length across a 1060px band leaves the right half empty. */
  .kx-terms__body { columns: 2; column-gap: var(--kx-space-8, 40px); }
  .kx-terms__body h3 { break-after: avoid; }
  .kx-terms__body ul, .kx-terms__body p { break-inside: avoid; }
}

/* --- preview: the product name, on its own labelled row ------------------- */
.kx-preview__product {
  display: flex;
  align-items: baseline;
  gap: var(--kx-space-2, 8px);
  margin: 4px 0 0;
}
/* The name wraps to at most two lines instead of being cut mid-word: a
   half-shown product name is worse than a slightly taller card. */
.kx-preview__title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
  text-overflow: unset;
  line-height: 1.6;
}

/* --- [hidden] actually hides ------------------------------------------------
   `[hidden]{display:none}` lives in the UA stylesheet, and ANY author `display`
   beats a UA declaration regardless of specificity - origin wins before
   specificity is even consulted. So `.kx-alert{display:flex}` and
   `.kx-break__row{display:grid}` were quietly cancelling the attribute, and
   three elements that JS toggles with `hidden` were permanently visible:
   the empty red form-error bar, the "هزینه فروشنده ۰ تومان" surcharge row, and
   the freight row during a deferred quote. Measured on the RTL rig before the
   fix: display:flex/grid with the attribute present and 29-32px of height.

   Scoped to the plugin's own roots so it cannot reach into the theme, and
   !important because there is no other way to outrank an author display rule
   that may be added later.
   ------------------------------------------------------------------------ */
.kx-co [hidden],
.kx-lp [hidden] { display: none !important; }

/* --- compound row: price(+currency), weight ----------------------------------
   Layout "ب": quantity moved out of this row entirely - it now sits beside
   the "افزودن به سبد خرید" button (see .kx-co__actions further down) - and
   currency moved INSIDE the price field as a chip, so this row is only ever
   two fields. Three field rows became two.

   Still driven by a CONTAINER query, not a viewport one, because the form's
   width is not a function of the viewport. Measured on the rig:

       viewport 899px -> form 812px
       viewport 901px -> form 494px

   The sidebar track appears at 900px and takes 318px with it, so the form is
   narrower at 901 than at 899. A `min-width` breakpoint tuned at either side is
   measuring the wrong number at exactly the width where it matters, and
   .kx-co__layout--solo (a merchant setting) moves the goalposts again. The
   container query asks the only question the row actually cares about.

   Mobile-first, unlike .kx-row2 next door, and for a structural reason rather
   than taste: .kx-row2's unqueried default (1fr 1fr, no floors) can shrink
   forever without breaking. This row has a hard floor on the price side (the
   currency chip plus a few digits), so the default must be the layout that
   cannot break - a browser with no container-query support gets the stacked
   form: correct, just less dense. No @supports needed.
   ------------------------------------------------------------------------ */
.kx-co__form { container: kx-form / inline-size; }

.kx-rowcp {
  display: grid;
  gap: var(--kx-space-5);
  grid-template-columns: minmax(0, 1fr);
}
/* 220px price floor (chip + a few digits) + 20 gap + 150px weight floor = 390,
   +130 slack: generous on purpose, because unlike the old three-column row
   nothing here is fighting for space - two fields easily share 520px. */
@container kx-form (min-width: 520px) {
  .kx-rowcp { grid-template-columns: minmax(220px, 1.25fr) minmax(150px, 1fr); }
}

/* --- compound currency+price field -------------------------------------------
   The currency the customer is thinking in is a property of the price, not a
   separate decision beside it - a payment-form idiom: a chip that reads as
   part of the same control as the amount, not two unrelated fields.

   ACCESSIBILITY / NO-JS CONTRACT: the real <select> is a full-bleed, fully
   OPAQUE-TO-INTERACTION overlay on the chip (position:absolute; inset:0), not
   a decorative dropdown some JS drives. It keeps the native popup, full
   keyboard support (typeahead, arrow keys) and the chip's entire area as its
   hit target. kx-order.js only mirrors the select's OWN state (symbol, flag)
   after the fact - the select is never disabled, never hidden, never a fake.
   With JS off, this degrades to "a select glued to the left of an input",
   which still works completely.
   ------------------------------------------------------------------------ */
.kx-cfield {
  display: flex;
  align-items: stretch;
  min-block-size: var(--kx-target-min);
  background: var(--kx-color-surface);
  border: 1px solid var(--kx-color-border-strong);
  border-radius: var(--kx-radius-md);
}
.kx-cfield:hover { border-color: var(--kx-color-text-muted); }

.kx-cfield__cur {
  position: relative;
  display: flex;
  align-items: center;
  /* flex-shrink:0 is the fix, not the padding: as a default flex item the chip
     was shrinking BELOW its own content width to give room to the price input
     beside it, so the contents overflowed their padding box and the chevron
     ended up flush against the chip's edge with the padding still nominally
     "applied". It now holds its natural width and the input takes the rest.
     The chevron also carries an end margin, because a triangle drawn in
     borders has no optical side bearing the way a glyph does. */
  flex: 0 0 auto;
  gap: var(--kx-space-2);
  padding-inline: var(--kx-space-3);
  background: var(--kx-color-surface-sunken);
  border-inline-end: 1px solid var(--kx-color-border);
  border-start-start-radius: calc(var(--kx-radius-md) - 1px);
  border-end-start-radius: calc(var(--kx-radius-md) - 1px);
  color: var(--kx-color-text-strong);
  font-size: var(--kx-fs-300);
  font-weight: var(--kx-fw-medium);
}
/* The focus ring belongs on the CHIP, because the select itself is invisible -
   a ring on an opacity:0 element would never be seen. :focus-within fires the
   instant native keyboard focus lands on the select underneath. */
.kx-cfield__cur:focus-within {
  outline: var(--kx-focus-ring) solid var(--kx-color-focus);
  outline-offset: 2px;
}
.kx-cfield__flag {
  display: inline-flex;
  flex: 0 0 auto;
}
.kx-cfield__flag svg {
  display: block;
  inline-size: 20px;
  block-size: 14px;
  border-radius: 3px;
  /* A flag with square corners against a rounded chip reads as a mistake;
     3px is enough to soften it without looking like a coin. */
}
/* The currency NAME (لیر / درهم), not the symbol - matches the approved
   reference design exactly: 14px, so the price number stays the visually
   dominant figure and the chip reads as a label beside it, not competing
   text. */
.kx-cfield__name {
  font-size: var(--kx-fs-200);
  white-space: nowrap;
}
/* A CSS-only triangle, not an SVG or webfont glyph - one less request for a
   mark this small, and currentColor keeps it in step with the text beside it
   with no separate color rule to maintain. */
.kx-cfield__chev {
  inline-size: 0;
  block-size: 0;
  border-inline-start: 5px solid transparent;
  border-inline-end: 5px solid transparent;
  border-block-start: 6px solid currentColor;
  opacity: .7;
  flex: 0 0 auto;
  margin-inline-end: 2px;
}
.kx-cfield__select {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  opacity: 0;
  cursor: pointer;
  /* The element is invisible, but its NATIVE POPUP is not, and the browser
     renders that list at the select's own font-size. Inheriting the chip's
     15px produced a cramped little menu; the popup is a reading surface, so
     it gets a reading size. This cannot affect the chip - nothing about an
     opacity:0 box is painted. Width stays pinned to the chip via inset:0, so
     the invisible hit area never creeps over the price input beside it; the
     popup sizes itself to its longest option regardless. */
  font-size: var(--kx-fs-400);
  line-height: 1.8;
  /* No appearance/border/background rules: this element is never seen, only
     interacted with. Nothing here should ever need to match .kx-select. */
}
.kx-cfield__num {
  flex: 1 1 auto;
  min-inline-size: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  /* .kx-input already supplies padding-block/font/line-height; only the
     chrome that would visually double the field's border is removed here. */
}

/* --- "اختیاری" chip on the weight label --------------------------------------
   Tells the customer up front that leaving weight blank is a legitimate
   answer, not a field they forgot - the same fact the باربری row now repeats
   in context once they reach the breakdown.
   ------------------------------------------------------------------------ */
.kx-optchip {
  display: inline-block;
  font-size: var(--kx-fs-100);
  font-weight: var(--kx-fw-medium);
  color: var(--kx-color-support);
  background: var(--kx-color-support-wash);
  border-radius: var(--kx-radius-pill);
  padding: 1px 8px;
  margin-inline-start: var(--kx-space-2);
  vertical-align: middle;
}

/* --- quantity stepper ------------------------------------------------------
   No `direction` declaration anywhere in this block, deliberately. The RTL
   section of this stylesheet forbids a bare direction change on a LAYOUT
   CONTAINER - on a flex or grid parent it reorders the children rather than
   isolating a text run, and that rule exists because it already caused a real
   bug here once. .kx-stepper is a flex container, so it simply mirrors with the
   page: minus on the physical right in RTL, on the left in LTR, from one set of
   rules with no .rtl override. That matches how iOS and Material mirror
   steppers, and it means the plugin does not break if it is ever put on an LTR
   site. The DIGITS are already isolated by .kx-num on the input itself - a leaf,
   which is the correct granularity for an isolate.

   Every side-specific property below is therefore logical, and the corner
   keywords (border-start-start-radius et al) are direction-aware.

   Height is derived, not typed in. The inner input carries .kx-input's own
   padding and line-height, so the control computes to exactly the height of the
   fields beside it - measured 58.3px against the price input's 58.3px, bottoms
   aligned to 0.0px. The buttons stretch to 44 x 56.3, well clear of the 24px
   WCAG 2.2 SC 2.5.8 minimum. Do not replace this with a fixed block-size: the
   whole point is that it stays right if the type scale moves.
   ------------------------------------------------------------------------ */
.kx-stepper {
  display: flex;
  align-items: stretch;
  inline-size: 100%;
  max-inline-size: 176px;          /* narrowed further beside the CTA by
                                       .kx-co__actions .kx-stepper, below */
  min-block-size: var(--kx-target-min);
  background: var(--kx-color-surface);
  border: 1px solid var(--kx-color-border-strong);
  border-radius: var(--kx-radius-md);
}
/* Matches .kx-input:hover, so the control reacts as one field, not three parts. */
.kx-stepper:hover,
.kx-stepper:focus-within { border-color: var(--kx-color-text-muted); }

/* background is STATED, not inherited-transparent: a host theme that styles
   bare <button> (the stock WP themes paint them dark) shows straight through
   `transparent` and the two ends of the control turn into dark blocks. The
   control owns its own surface. */
.kx-stepper__btn {
  flex: 0 0 var(--kx-target-min);
  inline-size: var(--kx-target-min);
  padding: 0;
  border: 0;
  background: var(--kx-color-surface);
  color: var(--kx-color-text-strong);
  display: grid;
  place-items: center;
  cursor: pointer;
}
/* Without display:block the icon sits on the text baseline and the button's
   optical centre lands 2-3px low. */
.kx-stepper__btn svg { display: block; }
/* Theme armour. Stock WP themes ship rules like
   `button:not(:hover):not(:active):not(.has-background)` - specificity (0,3,1),
   which outranks any sane class selector here and paints both ends of the
   control in the theme's primary colour. Scoped + !important is the same
   pattern this file already uses for [hidden]; an escalating specificity war
   against themes we cannot see is not maintainable. */
.kx-co .kx-stepper__btn,
.kx-lp .kx-stepper__btn {
  background: var(--kx-color-surface) !important;
  color: var(--kx-color-text-strong) !important;
}
.kx-co .kx-stepper__btn:hover,
.kx-lp .kx-stepper__btn:hover { background: var(--kx-color-surface-sunken) !important; }
.kx-co .kx-stepper__btn:active,
.kx-lp .kx-stepper__btn:active { background: var(--kx-color-border) !important; }
.kx-stepper__btn:hover { background: var(--kx-color-surface-sunken); }
.kx-stepper__btn:active { background: var(--kx-color-border); }
/* The same treatment the DS already gives a blocked .kx-btn. */
.kx-stepper__btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  background: transparent;
}
/* -1px so the inner corner sits inside the wrapper's border rather than half a
   pixel outside it. overflow:hidden would do the same job and clip the focus
   ring - never do that here. */
.kx-stepper__btn:first-child {
  border-start-start-radius: calc(var(--kx-radius-md) - 1px);
  border-end-start-radius:   calc(var(--kx-radius-md) - 1px);
  border-inline-end: 1px solid var(--kx-color-border);
}
.kx-stepper__btn:last-child {
  border-start-end-radius: calc(var(--kx-radius-md) - 1px);
  border-end-end-radius:   calc(var(--kx-radius-md) - 1px);
  border-inline-start: 1px solid var(--kx-color-border);
}

/* Two classes, so this does not depend on which stylesheet Avada loads last. */
.kx-stepper .kx-stepper__input {
  flex: 1 1 auto;
  min-inline-size: 0;
  inline-size: 100%;
  min-block-size: auto;
  /* Keeps .kx-input's vertical padding so the control ends up exactly as tall
     as the sibling fields. Measured: without this the stepper sat at its 44px
     floor while the price input rendered 58.3px, and the row visibly stepped
     down. The height is a CONSEQUENCE of matching the siblings' box model, not
     a number typed in here - so it stays right if the type scale changes. */
  padding-block: var(--kx-space-3);
  padding-inline: 0;
  /* Pinned, not inherited. .kx-input sets no line-height and picks up 1.9 from
     body, but something else on the page (theme or a WooCommerce stylesheet)
     reaches this input and gives it 1.7 - measured 28.9px against the price
     field's 32.3px, which is exactly the 3.4px by which the stepper sat short
     of its neighbour. Stating it makes the row align regardless of which
     foreign stylesheet loads last. */
  line-height: var(--kx-lh-body);
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--kx-color-text-strong);
  font-weight: var(--kx-fw-medium);
  text-align: center;
  -moz-appearance: textfield;
       appearance: textfield;
}
/* The native spinner is ~13px tall - half the 24px minimum target - and Chrome
   only reveals it on hover, so on touch it does not exist at all. The buttons
   ARE the spinner now; leaving the native one would also park it on top of "+".
   There was no suppression anywhere in this stylesheet before. */
.kx-stepper__input::-webkit-outer-spin-button,
.kx-stepper__input::-webkit-inner-spin-button {
  -webkit-appearance: none;
          appearance: none;
  margin: 0;
}

/* --- quantity stepper beside the CTA, full size ------------------------------
   Product-page style: no longer among the fields above, and no longer inside
   the price breakdown - it sits right where the action it affects happens.
   Same .kx-stepper the field row used to hold (base rules a few blocks up
   still apply, no size override needed - "normal" was the ask, and normal is
   what the base class already is).

   DOM order is [+, input, -], the REVERSE of the in-form stepper's [-, input,
   +]: .kx-stepper is a flex row and mirrors with RTL page direction (see the
   quantity-stepper block above - DOM child 1 renders physically rightmost),
   so putting "+" first is what puts "+" on the right and "-" on the left,
   which is what was asked for here specifically. Two different DOM orders for
   two different contexts, on purpose - not an inconsistency to "fix" later. */
.kx-co__actions {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--kx-space-3);
  align-items: stretch;
}
/* Widening the segmented box did not fix it, because the box WAS the problem:
   one bordered rectangle sliced into thirds by two hairlines put the value in
   a 49px pen between two buttons, and no amount of extra width stops that
   reading as cramped. So the segmentation is gone. The two buttons are now
   free-standing circles - echoing the pill CTA beside them - with the figure
   breathing between them and the group carrying no outer box at all. */
.kx-co__actions .kx-stepper {
  max-inline-size: 190px;
  gap: var(--kx-space-2);
  background: transparent;
  border: 0;
  border-radius: 0;
  align-items: center;
}
/* The base control reacts as one field on hover; this variant has no field to
   react, so the buttons carry their own states instead. */
.kx-co__actions .kx-stepper:hover,
.kx-co__actions .kx-stepper:focus-within { border-color: transparent; }

.kx-co__actions .kx-stepper .kx-stepper__btn,
.kx-co__actions .kx-stepper .kx-stepper__btn:first-child,
.kx-co__actions .kx-stepper .kx-stepper__btn:last-child {
  flex: 0 0 48px;
  inline-size: 48px;
  block-size: 48px;
  /* All four sides, overriding the segmented variant's single divider edge. */
  border: 1px solid var(--kx-color-border-strong);
  border-radius: var(--kx-radius-circle);
  transition: background-color var(--kx-dur-1) var(--kx-ease),
    border-color var(--kx-dur-1) var(--kx-ease);
}
.kx-co__actions .kx-stepper .kx-stepper__btn:hover { border-color: var(--kx-color-text-muted); }
.kx-co__actions .kx-stepper .kx-stepper__btn:focus-visible {
  outline: var(--kx-focus-ring) solid var(--kx-color-focus);
  outline-offset: 2px;
}
/* The pressed state moves the glyph a hair rather than only changing colour -
   on a control you hold down to repeat, that read is what confirms the press. */
.kx-co__actions .kx-stepper .kx-stepper__btn:active svg { transform: scale(.85); }
.kx-co__actions .kx-stepper .kx-stepper__btn svg {
  transition: transform var(--kx-dur-1) var(--kx-ease);
}
.kx-co__actions .kx-stepper .kx-stepper__input {
  font-size: var(--kx-fs-600);
  font-weight: var(--kx-fw-display);
  padding-block: 0;
}
.kx-co__actions .kx-btn { inline-size: 100%; }

/* --- the deferred-weight notice ----------------------------------------------
   Replaces the باربری row while weight is unknown, rather than a short phrase
   swapped inline inside that row - the full sentence (with the merchant's
   configured tariffs) gets its own visual weight here, the same "quiet card
   inside the price box" treatment .kx-break__includes already uses a few
   lines below for "what the price includes". INFO tint rather than that
   block's success-green: this is neutral procedural information ("here is
   what happens next"), not a reassurance, and green would misstate it as
   good news.
   ------------------------------------------------------------------------ */
.kx-break__deferred {
  display: flex;
  align-items: flex-start;
  gap: var(--kx-space-2);
  margin-block: var(--kx-space-3) 0;
  padding: var(--kx-space-3);
  border-radius: var(--kx-radius-md);
  background: var(--kx-color-info-bg);
  color: var(--kx-color-info-fg);
  font-size: var(--kx-fs-200);
  line-height: 1.75;
}
.kx-break__deferred-icon {
  flex: 0 0 auto;
  display: flex;
  margin-block-start: 3px;
  color: var(--kx-color-support);
}

/* --- anchor landing --------------------------------------------------------
   Avada ships a sticky header, so a raw anchor jump parks the form's first
   field underneath it. scroll-margin is the property built for exactly this and
   it is honoured by scrollIntoView as well as by a plain hash jump.
   ------------------------------------------------------------------------ */
#kx-order-form { scroll-margin-block-start: var(--kx-space-9); }

/* --- hero with a picture ---------------------------------------------------
   Only applies when the merchant has actually set one; without .kx-hero--split
   the hero keeps its original single-column layout untouched, which is what an
   upgrade with no image set gets.

   The picture is LAST in the DOM and placed by grid, so keyboard and
   screen-reader users reach the headline and the CTA before a decorative image.

   Grid's explicit track list IS direction-mirrored: in dir="rtl" column 1 is the
   RIGHTMOST, exactly as the .kx-co__layout block above this file records. So the
   TEXT takes column 1 (right, where it already sits today) and the picture takes
   column 2 (left, the empty half). Getting this backwards put the image on the
   right and squeezed the headline - caught by measuring, not by reading.

   Single column below 860px: the headline is the thing that has to survive, and
   at narrow widths a side-by-side split starves it. The image is dropped rather
   than stacked, because it is decoration and stacking it would push the CTA
   below the fold on exactly the devices where that matters most.
   ------------------------------------------------------------------------ */
.kx-hero--split .kx-hero__media { display: none; }

@media (min-width: 860px) {
  .kx-hero--split {
    display: grid;
    /* Column 1 is the RIGHT track in RTL and holds the text, so it gets the
       larger share - the headline is what has to breathe, not the decoration. */
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: var(--kx-space-8);
    align-items: center;
  }
  .kx-hero--split .kx-hero__text  { grid-column: 1; }
  .kx-hero--split .kx-hero__media { display: block; grid-column: 2; }
}

.kx-hero__img {
  display: block;
  inline-size: 100%;
  block-size: auto;
  max-block-size: 340px;
  object-fit: cover;
  border-radius: var(--kx-radius-lg);
}

/* The built-in illustration standing in for an unset picture. It inherits the
   hero's text colour, so it re-themes with the band instead of needing its own
   palette. Sized in ch-independent units and capped, so it never out-shouts
   the headline it sits beside. */
.kx-hero__art {
  display: block;
  inline-size: 100%;
  max-inline-size: 380px;
  block-size: auto;
  margin-inline: auto;
  color: currentColor;
  overflow: visible;
}
/* Flags never mirror, but a route travelling left-to-right does: in RTL the
   parcel should set off from the reading origin (right) toward the doorstep
   on the left, or the picture contradicts the text beside it. */
.rtl .kx-hero__art { transform: scaleX(-1); }

/* --- preview card: card-7 style, glass header on the image ------------------
   Modelled on 21st.dev's "card-7" product card (portrait image, glass header,
   floating badge, view dots, gentle tilt) - ported to vanilla CSS/JS with this
   design system's own tokens, not the original's React/Tailwind.

   CONTRAST IS GUARANTEED BY THE TINT ITSELF, NOT THE BLUR. The header sits on
   an arbitrary merchant photo, so its background alpha has to carry the
   contrast on its own - backdrop-filter softens BUSY photos but does not
   change the blend math for a uniform one, and the worst case tested here is
   a pure-white photo (the common case: most product shots are on white).

   MEASURED by pixel-sampling the rendered card against a forced pure-white
   photo (glyphs hidden so the sample is the true backdrop, not a letter
   stroke): rgb(22 35 61 / .90) over white renders as rgb(45 57 80), and white
   text on that is 11.59:1 - nearly 3x the 4.5:1 AA floor, and better than the
   6.7:1 first estimated by hand before this was actually measured. The
   found-badge sits partly over the header too, which darkens its own backdrop
   further: measured 14.53:1. The @supports fallback below raises the tint
   further for engines with no backdrop-filter at all, since without the blur
   softening a busy photo's texture there is less margin to spare.

   The found-badge stays glass too, matching the header's material, rather
   than the earlier solid white chip - if a future measurement ever puts its
   contrast under AA, the solid chip is the documented fallback to fall back
   to (kept in CHANGELOG, not duplicated here as dead CSS).
   ------------------------------------------------------------------------ */
.kx-side__card--preview {
  padding: 0;
  overflow: hidden;
  /* The tilt transform (kx-order.js) is set inline on THIS element, so its
     transition lives on the base rule rather than a separate one further
     down - one rule, one place to find it. */
  transition: transform .35s ease;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .kx-side__card--preview { transition: none; }
}

.kx-side__card--preview .kx-preview__media {
  position: relative;
  aspect-ratio: 3 / 4;
  background: var(--kx-color-surface-sunken);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* No photo: the logo IS the image, sized against the card so it reads as a
   result rather than a placeholder. */
.kx-side__card--preview .kx-preview__logo {
  inline-size: 52%;
  block-size: auto;
  max-inline-size: 200px;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  border-radius: var(--kx-radius-sm);
}
/* No photo: the logo is centred in the frame, but the header sits across the
   top third - so centring on the true middle would run it under the header.
   Lifting it clear keeps both legible. Scoped via [hidden] to the no-photo
   case, so the corner-badge rule below is untouched. */
.kx-side__card--preview .kx-preview__thumb[hidden] ~ .kx-preview__logo {
  margin-block-start: 20%;
}

/* A photo loaded: it fills the frame and the logo steps down to a small mark
   at the header's inline-end - card-7's own "brand logo inside the header". */
.kx-side__card--preview .kx-preview__thumb:not([hidden]) ~ .kx-preview__logo {
  position: absolute;
  inset-block-start: calc(var(--kx-space-3) + 10px);
  inset-inline-end: calc(var(--kx-space-3) + 10px);
  inline-size: 26px;
  block-size: 26px;
  padding: 3px;
  background: var(--kx-color-surface);
  border-radius: var(--kx-radius-sm);
  z-index: 2;
  box-shadow: 0 1px 4px rgb(var(--kx-shadow-tint) / .35);
}

/* The glass header, pinned to the top of the frame. */
.kx-side__card--preview .kx-preview__body {
  position: absolute;
  inset-block-start: var(--kx-space-3);
  inset-inline: var(--kx-space-3);
  z-index: 1;
  display: grid;
  gap: 2px;
  padding: var(--kx-space-3) var(--kx-space-4);
  border-radius: var(--kx-radius-md);
  border: 1px solid rgb(255 255 255 / .14);
  background: rgb(22 35 61 / .90);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
@supports not (backdrop-filter: blur(1px)) {
  .kx-side__card--preview .kx-preview__body { background: rgb(22 35 61 / .95); }
}
.kx-side__card--preview .kx-preview__seller,
.kx-side__card--preview .kx-preview__product {
  display: flex;
  align-items: baseline;
  gap: var(--kx-space-2);
  margin: 0;
  min-inline-size: 0;
}
.kx-side__card--preview .kx-preview__label {
  font-size: var(--kx-fs-100);
  color: rgb(255 255 255 / .72);
  flex: 0 0 auto;
}
.kx-side__card--preview .kx-preview__domain {
  font-size: var(--kx-fs-200);
  font-weight: var(--kx-fw-medium);
  color: rgb(255 255 255 / .92);
}
.kx-side__card--preview .kx-preview__title {
  font-size: var(--kx-fs-300);
  font-weight: var(--kx-fw-strong);
  color: #fff;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
}

/* The found-badge: card-7's floating price pill, translated to our "we
   recognised your link" confirmation - positioned to overlap the header's
   lower edge, exactly like card-7 overlaps its own price pill on its header. */
.kx-side__card--preview .kx-preview__found {
  position: absolute;
  inset-block-start: calc(var(--kx-space-3) + 60px);
  inset-inline-start: var(--kx-space-4);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 4px 11px;
  border-radius: var(--kx-radius-pill);
  border: 1px solid rgb(255 255 255 / .14);
  background: rgb(22 35 61 / .90);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: #fff;
  font-size: var(--kx-fs-100);
  font-weight: var(--kx-fw-medium);
}
@supports not (backdrop-filter: blur(1px)) {
  .kx-side__card--preview .kx-preview__found { background: rgb(22 35 61 / .95); }
}
.kx-side__card--preview .kx-preview__found-icon { display: inline-flex; flex: 0 0 auto; }

/* A quiet grounding gradient at the bottom - just enough for the dots to read
   against a pale photo, not a text carrier like the earlier full-frame design. */
.kx-side__card--preview .kx-preview__media::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 30%;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(to top, rgb(22 35 61 / .45), transparent);
}

/* --- view dots (photo / logo) -------------------------------------------- */
.kx-preview__dots {
  position: absolute;
  inset-block-end: var(--kx-space-3);
  inset-inline: 0;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: var(--kx-space-2);
}
/* 24x24 hit area (WCAG 2.2 SC 2.5.8) around a 6px visual dot, not a 6px hit
   target - the mark is decorative, the button is not. */
.kx-preview__dot {
  inline-size: 24px;
  block-size: 24px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.kx-preview__dot::before {
  content: '';
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: rgb(255 255 255 / .4);
}
.kx-preview__media[data-view="photo"] .kx-preview__dot[data-kx-view="photo"]::before,
.kx-preview__media[data-view="logo"] .kx-preview__dot[data-kx-view="logo"]::before {
  background: #fff;
}
/* The view NOT currently shown still occupies layout space (no [hidden]) so
   the dots below it never jump; only visibility changes. */
.kx-preview__media[data-view="logo"] .kx-preview__thumb:not([hidden]) { visibility: hidden; }
.kx-preview__media[data-view="logo"] .kx-preview__thumb:not([hidden]) ~ .kx-preview__logo {
  position: absolute;
  inset: 0;
  margin: auto;
  inline-size: 40%;
  max-inline-size: 160px;
  block-size: 40%;
  padding: 0;
  background: transparent;
  box-shadow: none;
  z-index: 1;
}


/* --- unit before the figure -------------------------------------------------
   The unit span is FIRST in the dd, but the dd's children are inline, and DOM
   order is not visual order for inline bidi content: "تومان" is a strong RTL
   run and the digits after it are European Numbers, which the bidi algorithm
   absorbs INTO that run and renders to its left. Measured: markup order
   [تومان][290,000] rendered as "290,000 تومان".

   Making the dd a flex container is what fixes it, because flex lays out BOXES
   in order and `direction` decides that order - which is exactly how .kx-price
   already gets this right for the total. Same mechanism, same result, no
   bidi-control characters needed.
   ------------------------------------------------------------------------ */
.kx-break__row dd {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
}
