/* ══════════════════════════════════════════════════════════════════════
   zl-season-picks.css — «مختارات زل لهذا الموسم»
   Immersive editorial cards: the photo IS the card. Text sits over a soft
   dark gradient at the bottom — no white panel, no serial numbers, no boxes.
   Isolated under .zsp-* / #zlSeasonPicks. Logical props → RTL & LTR.
   Desktop 4-up · tablet 2-up · mobile snap-slider (1 + peek).
   ══════════════════════════════════════════════════════════════════════ */
#zlSeasonPicks {
  --zsp-sea:#004F6C; --zsp-deep:#0E2F3D; --zsp-cyan:#00ABC7;
  --zsp-gold:#E6B563; --zsp-brown:#996230; --zsp-sand:#F6F2E9;
  --zsp-font:var(--zl-font,var(--font-arabic,'IBM Plex Sans Arabic','Tajawal',sans-serif));
  --zsp-ease:cubic-bezier(.22,.61,.36,1);
}
/* Curved lip rising into the hero — the arc from the approved mockup. The sand
   panel carries its own curve, so the hero above needs no change and no overlap
   hack: ::before is the same sand colour, sits just above the section, and its
   top corners round outward so the hero ends on a soft arc instead of a hard
   horizontal cut. Sized in vw so the curve keeps its proportion on every width. */
.zsp-sec {
  background:var(--zsp-sand); padding:clamp(50px,6.4vw,94px) 0;
  font-family:var(--zsp-font); position:relative;
}
/* THE curve — one implementation.
   A border-radius ellipse must span exactly the viewport width, so its slope
   turns VERTICAL at the two screen edges — the arc met the corners as steep
   horns and read as a bump, not as the mockup's wide sweep. Drawn as a radial
   gradient instead: the ellipse is wider than the screen (58% radius per side),
   so the rise is gentle everywhere — and a background can never overflow its
   box, so the extra width costs no horizontal scroll and no clipping tricks.
   Sand inside the ellipse, the hero's own video above it, nothing else. */
.zsp-sec::before {
  content:""; position:absolute;
  left:0; right:0;
  bottom:calc(100% - 1px);              /* 1px overlap kills the sub-pixel seam */
  height:clamp(34px,7.5vw,52px);
  background:radial-gradient(58% 100% at 50% 100%,
    var(--zsp-sand) 99%, rgba(246,242,233,0) 100%);
  pointer-events:none;
}
.zsp-sec[hidden] { display:none; }
.zsp-wrap { max-width:1400px; margin:0 auto; padding-inline:clamp(16px,3.6vw,34px); }

/* ── Head: centered title + a small ZL diamond divider ───────────────── */
/* عناوين الأقسام من اليمين لا الوسط (طلب المالكة 2026-08-09). `start` تحترم
   الاتجاه: يمين في العربية، يسار في الإنجليزية — بلا قاعدة منفصلة لكل لغة. */
.zsp-head { text-align:start; margin-bottom:clamp(22px,2.4vw,34px); }
.zsp-title { margin:0; color:var(--zsp-deep); font-size:clamp(1.7rem,3.4vw,2.7rem); font-weight:800;
  line-height:1.2; letter-spacing:-.012em; }
.zsp-title .zsp-hl { color:var(--zsp-gold); }
/* (title divider deleted 2026-08-07 — owner: no decorations under headings) */

/* ── Grid ────────────────────────────────────────────────────────────── */
.zsp-track { display:grid; grid-template-columns:repeat(4,1fr); gap:clamp(14px,1.6vw,24px); align-items:stretch; }
.zsp-dots { display:none; }

/* ── Card: the photo IS the card ─────────────────────────────────────── */
.zsp-card { position:relative; display:block; aspect-ratio:4/5; border-radius:22px; overflow:hidden;
  text-decoration:none; background:var(--zsp-deep); isolation:isolate;
  box-shadow:0 10px 26px -16px rgba(14,47,61,.42);
  transition:transform .34s var(--zsp-ease), box-shadow .34s var(--zsp-ease); }
.zsp-card:hover { transform:translateY(-8px); box-shadow:0 28px 52px -20px rgba(14,47,61,.55); }
.zsp-card:focus-visible { outline:3px solid var(--zsp-gold); outline-offset:3px; }

/* The section opts OUT of the site-wide image fade (img.zl-fx sets opacity:0 and
   waits for a resized variant that may not exist — that is what left these cards
   grey). Higher specificity than the global rule, so no !important is needed. */
#zlSeasonPicks .zsp-img, #zlSeasonPicks .zsp-img.zl-fx { opacity:1; }
.zsp-img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:center;
  display:block; background:#123c4c;
  /* keep the photo lively under the tint — never washed out */
  filter:saturate(1.06) contrast(1.02);
  transition:transform .85s var(--zsp-ease); }
.zsp-card:hover .zsp-img { transform:scale(1.06); }
/* last-resort branded cover — a ZL gradient, never an empty grey box */
.zsp-card.zsp-noimg { background:linear-gradient(150deg,#0E2F3D 0%,#004F6C 52%,#996230 100%); }

/* soft dark gradient — strong only where the text sits, plus a whisper-light
   tint over the rest so the four covers read as one family */
.zsp-veil { position:absolute; inset:0; pointer-events:none; z-index:1;
  background:linear-gradient(to top,
    rgba(6,26,34,.92) 0%, rgba(6,26,34,.79) 14%, rgba(6,26,34,.47) 30%,
    rgba(6,26,34,.20) 44%, rgba(6,26,34,.11) 56%, rgba(6,26,34,.09) 82%, rgba(6,26,34,.20) 100%); }

/* Frosted reading zone: a VERY light blur that lives only behind the text and
   fades out before the middle of the photo — the scene stays sharp and legible
   up top, the copy gets a calm premium bed at the bottom. Degrades to the plain
   gradient where backdrop-filter isn't supported. */
.zsp-card::after { content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  -webkit-backdrop-filter:blur(9px) saturate(1.05);
  backdrop-filter:blur(9px) saturate(1.05);
  -webkit-mask-image:linear-gradient(to top,#000 0%,#000 28%,rgba(0,0,0,.55) 44%,rgba(0,0,0,.18) 56%,transparent 66%);
  mask-image:linear-gradient(to top,#000 0%,#000 28%,rgba(0,0,0,.55) 44%,rgba(0,0,0,.18) 56%,transparent 66%); }

/* optional category badge — only rendered when the data really has one */
.zsp-badge { position:absolute; top:15px; inset-inline-end:15px; z-index:3;
  display:inline-flex; align-items:center; gap:6px; padding:7px 13px; border-radius:100px;
  background:rgba(11,36,46,.58); border:1px solid rgba(255,255,255,.22);
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  color:#fff; font-size:.74rem; font-weight:700; letter-spacing:.01em; }

/* ── Content over the photo — every card starts at the same visual line ── */
.zsp-content { position:absolute; inset-inline:0; bottom:0; z-index:2; display:flex; flex-direction:column;
  justify-content:flex-end; min-height:52%;              /* fixed block → aligned starts across cards */
  padding:clamp(16px,1.4vw,20px); color:#fff; }
/* title: one short display name, 1–2 lines, no ellipsis surgery */
.zsp-name { margin:0 0 5px; font-size:clamp(1.14rem,1.25vw,1.36rem); font-weight:800; line-height:1.34;
  text-shadow:0 2px 14px rgba(4,20,27,.5); min-height:1.34em;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
/* region · duration — a single quiet line with one icon */
.zsp-meta { display:flex; align-items:center; gap:6px; margin-bottom:6px;
  font-size:.79rem; font-weight:600; color:rgba(255,255,255,.84); white-space:nowrap; overflow:hidden; }
.zsp-meta svg { width:13px; height:13px; color:rgba(255,255,255,.60); flex:0 0 auto; }
.zsp-meta b { font-weight:600; }
.zsp-meta em { font-style:normal; opacity:.55; margin-inline:2px; }
/* host — one quiet line: who accompanies you, or whose place you stay at.
   Sits between the meta line and the price. The portrait is optional and only
   appears when the record carries a real one. */
.zsp-host { display:flex; align-items:center; gap:7px; margin-bottom:8px;
  font-size:.79rem; color:rgba(255,255,255,.86); min-width:0; }
.zsp-host-av { width:22px; height:22px; border-radius:50%; object-fit:cover; flex:0 0 auto;
  border:1px solid rgba(255,255,255,.45); background:rgba(255,255,255,.12); }
.zsp-host-t { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0;
  font-weight:500; }
.zsp-host-t b { font-weight:700; color:#fff; }

/* price — readable, never shrunk */
.zsp-price { font-size:.95rem; font-weight:800; color:#fff; margin-bottom:12px; letter-spacing:.01em; }
.zsp-price small { font-size:.72rem; font-weight:600; color:rgba(255,255,255,.72); margin-inline-end:4px; }

/* CTA — quiet gold link with a moving arrow */
.zsp-go { display:inline-flex; align-items:center; gap:8px; align-self:flex-start;
  color:var(--zl-gold,#E6B563); font-size:.87rem; font-weight:800; padding-bottom:3px;
  border-bottom:1px solid rgba(230,181,99,.38); transition:gap .28s var(--zsp-ease), border-color .28s, color .28s; }
.zsp-go svg { width:16px; height:16px; transition:transform .28s var(--zsp-ease); }
.zsp-card:hover .zsp-go { gap:12px; border-bottom-color:var(--zsp-gold); }
.zsp-card:hover .zsp-go svg { transform:translateX(-4px); }
html:not([dir="rtl"]) .zsp-card:hover .zsp-go svg { transform:translateX(4px); }

/* one honest inclusion, as a light outlined pill (never a green box) */
/* margin sits BELOW now: the chip moved up from after the CTA to between the
   host line and the price, so the old margin-top would have doubled the gap the
   host line already leaves. */
.zsp-inc { display:inline-block; align-self:flex-start; margin:0 0 10px;
  padding:5px 11px; border-radius:100px; border:1px solid rgba(255,255,255,.26);
  background:rgba(255,255,255,.08);
  color:rgba(255,255,255,.88); font-size:.73rem; font-weight:600; letter-spacing:.01em; }

/* ── Section CTA ─────────────────────────────────────────────────────── */
.zsp-cta-wrap { text-align:center; margin-top:clamp(20px,2.2vw,30px); }
.zsp-all { display:inline-flex; align-items:center; gap:9px; background:var(--zsp-deep); color:#fff;
  font-family:inherit; font-size:.93rem; font-weight:700; padding:13px 28px; border:1px solid rgba(230,181,99,.55);
  border-radius:100px; cursor:pointer; box-shadow:0 12px 26px -16px rgba(14,47,61,.8);
  transition:background .28s var(--zsp-ease), border-color .28s, transform .28s var(--zsp-ease); }
.zsp-all svg { width:17px; height:17px; color:var(--zsp-gold); transition:transform .28s var(--zsp-ease); }
.zsp-all:hover { background:#123c4c; border-color:var(--zsp-gold); transform:translateY(-2px); }
.zsp-all:hover svg { transform:translateX(-4px); }
html:not([dir="rtl"]) .zsp-all:hover svg { transform:translateX(4px); }
.zsp-all:focus-visible { outline:2px solid var(--zsp-gold); outline-offset:3px; }

/* ── Skeletons (identical footprint → no layout shift) ───────────────── */
.zsp-sk { position:relative; aspect-ratio:4/5; border-radius:22px; overflow:hidden; background:#e6dcc9; }
.zsp-sk::after { content:""; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent); animation:zspShim 1.35s infinite; }
@keyframes zspShim { to { transform:translateX(100%); } }

/* ── Responsive ──────────────────────────────────────────────────────── */
@media (max-width:1080px) {
  .zsp-track { grid-template-columns:repeat(2,1fr); gap:clamp(16px,2.4vw,22px); }
  .zsp-card, .zsp-sk { aspect-ratio:5/6; }
  .zsp-name { font-size:1.24rem; }
}
/* ── Mobile: one clear card, centered, with a visible peek of the next ──
   The track breaks out of the 16px section padding and re-applies it inside,
   so cards never touch the screen edge yet a slice of the neighbour shows.
   scroll-snap-align:center + scroll-padding lets EVERY card (first & last
   included) settle in the middle. */
@media (max-width:660px) {
  /* NO backdrop-filter on phones — this is the fix for three symptoms at once:
     the blur over the photo, the covers reading as grey, and the shake on swipe.
     .zsp-card::after frosts the card with blur(9px) and relies on a mask-image to
     confine that frost to the lower third. iOS applies the mask unreliably, so the
     blur spread across the WHOLE card and fogged the photograph — and because the
     element is inset:0 on a layer the deck translates every frame, the compositor
     had to re-sample, re-blur and re-mask the backdrop on each one. That is the
     jitter. The .zsp-veil gradient underneath already carries all the text
     contrast the copy needs, so removing the frost costs legibility nothing.
     Desktop keeps it: there the card never moves and the mask behaves. */
  .zsp-card::after { -webkit-backdrop-filter:none; backdrop-filter:none;
    -webkit-mask-image:none; mask-image:none; background:none; }
  .zsp-badge { -webkit-backdrop-filter:none; backdrop-filter:none;
    background:rgba(11,36,46,.72); }
  /* one promoted layer per card is enough; blur+mask+will-change together were
     pushing iOS past its compositing budget */
  .zsp-card, .zsp-sk { will-change:transform; }

  .zsp-sec { padding:clamp(38px,9vw,56px) 0; }
  .zsp-wrap { padding-inline:16px; }
  /* DECK GEOMETRY — one variable drives it. The side padding is derived from the
     card width, so a snapped card sits dead-centre and its neighbours peek by
     exactly (gutter - gap) on each side. At 390px: card 308px, peek ~29px. */
  /* DECK STAGE — not a scroll container.
     The old rules made this an overflow-x:auto scroll-snap row, and the browser's
     snapping then fought the script's scrollLeft corrections; that disagreement
     was the shake. The track is now a plain positioned stage: every card is
     absolutely centred on it, and js translates each one away from centre. So
     "centred" is the card's resting position by construction — nothing measures
     it, nothing corrects it afterwards.
     NOTE: no transform / opacity / transition is declared for .zsp-card here.
     js is the single owner of all three on this breakpoint; a competing
     declaration is exactly what produced the fight before. */
  .zsp-track {
    --zsp-cw: 79%;                                  /* spec: 78–82% of the viewport */
    --zsp-gap: 12px;                                /* spec: 12–14px               */
    display:block; grid-template-columns:none;
    position:relative; overflow:hidden;
    height:clamp(440px,70vh,560px);
    padding:0; margin-inline:0;
    touch-action:pan-y;                             /* horizontal gesture is ours, vertical stays the page's */
    -webkit-user-select:none; user-select:none;
  }
  /* every card starts dead-centre; js moves it from there */
  /* Centred by auto margins between left:0 and right:0 — not by
     left:50% + a negative margin. A percentage margin resolves against the
     CONTAINING BLOCK's width, not the element's, so that pairing left a constant
     ~26px offset. Auto margins split the leftover space exactly, in LTR and RTL
     alike, with no arithmetic to get wrong. */
  .zsp-card, .zsp-sk {
    position:absolute; top:0; left:0; right:0;
    width:var(--zsp-cw); max-width:400px;
    margin-inline:auto;
    height:100%; aspect-ratio:auto; border-radius:20px;
    will-change:transform, opacity;
    transform-origin:center;
    box-shadow:0 18px 36px -18px rgba(14,47,61,.55);
  }
  .zsp-sk:nth-child(n+2) { opacity:0; }             /* one skeleton on the stage, not four stacked */
  .zsp-card > * { pointer-events:none; }            /* the card itself takes the gesture */
  .zsp-card .zsp-cta, .zsp-card .zsp-feat { pointer-events:auto; }
  /* a touch more breathing room inside the card on phones */
  .zsp-content { min-height:52%; padding:18px; }
  .zsp-name { font-size:1.22rem; }
  .zsp-dots { display:flex; gap:7px; justify-content:center; margin-top:14px; }
  .zsp-dot { width:7px; height:7px; border-radius:50%; background:rgba(14,47,61,.20); transition:all .25s; }
  .zsp-dot.on { width:22px; border-radius:4px; background:var(--zsp-gold); }
  .zsp-cta-wrap { margin-top:20px; }
  .zsp-all { padding:14px 34px; font-size:.95rem; }      /* standalone button, not a full-width bar */
}
@media (max-width:380px) { .zsp-card, .zsp-sk { width:86vw; } }

@media (prefers-reduced-motion:reduce) {
  .zsp-card, .zsp-img, .zsp-go, .zsp-go svg, .zsp-all, .zsp-all svg { transition:none !important; }
  /* No transform here. js owns the card's transform on this breakpoint, so the
     hover lift is cancelled by simply not declaring one — a `transform:none`
     counter-rule would be a second declaration on the property we just made
     single-owner. The inner image keeps its own (js never touches it). */
  .zsp-card:hover .zsp-img { transform:none; }
  .zsp-sk::after { animation:none; }
}
