/**
 * Homepage discovery
 * Category shortcuts + age-filter handoff below the hero, then the product
 * rails. Loaded on the front page only, after every component file, so it can
 * tune shared components (.nk-rail-section, .nk-product-rail) for this page
 * without out-specifying them anywhere else.
 */

.nk-home-discovery {
  display: grid;
  gap: var(--nk-space-5);
  padding-block: var(--nk-space-5) var(--nk-section-gap);
}

.nk-home-categories {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--nk-space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nk-home-category {
  display: grid;
  grid-template-rows: auto auto;
  justify-items: center;
  align-content: start;
  gap: var(--nk-space-2);
  min-inline-size: 0;
  min-block-size: var(--nk-touch-target);
  color: var(--nk-text-strong);
  text-decoration: none;
  border: var(--nk-border-width) solid transparent;
  border-radius: var(--nk-radius-lg);
  transition: color var(--nk-transition-base),
    background-color var(--nk-transition-base),
    border-color var(--nk-transition-base),
    box-shadow var(--nk-transition-base),
    transform var(--nk-transition-base);
}

.nk-home-category__media {
  display: grid;
  place-items: center;
  inline-size: calc(var(--nk-space-12) + var(--nk-space-2));
  aspect-ratio: var(--nk-ratio-square);
  overflow: hidden;
  flex: none;
  border-radius: var(--nk-radius-md);
  background-color: var(--nk-surface-sunken);
  box-shadow: var(--nk-shadow-xs);
  transition: transform var(--nk-duration-normal) var(--nk-ease-out),
    box-shadow var(--nk-transition-base);
}

.nk-home-category__media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center;
}

.nk-home-category__label {
  max-inline-size: 100%;
  overflow: hidden;
  font-size: var(--nk-text-xs);
  font-weight: var(--nk-weight-semibold);
  line-height: var(--nk-leading-snug);
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nk-home-category__body {
  display: grid;
  justify-items: center;
}

.nk-home-category__view {
  display: none;
}

.nk-home-category-item--sale {
  display: none;
}

@media (hover: hover) {
  .nk-home-category:hover {
    color: var(--nk-text-accent);
  }
}

@media (hover: hover) {
  .nk-home-category:hover .nk-home-category__media {
    box-shadow: var(--nk-shadow-sm);
    transform: translateY(calc(var(--nk-space-half) * -1));
  }
}

.nk-home-category:focus-visible,
.nk-home-age:focus-visible {
  outline: var(--nk-focus-ring-width) solid var(--nk-focus-ring-color);
  outline-offset: var(--nk-focus-ring-offset);
}

.nk-home-category:active {
  transform: scale(0.98);
}

.nk-home-category[aria-disabled="true"],
.nk-home-age[aria-disabled="true"] {
  border-color: var(--nk-action-disabled-bg);
  background-color: var(--nk-action-disabled-bg);
  color: var(--nk-action-disabled-text);
  cursor: not-allowed;
  pointer-events: none;
}

.nk-home-ages {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--nk-space-1);
}

.nk-home-age {
  display: grid;
  place-items: center;
  min-inline-size: 0;
  min-block-size: var(--nk-touch-target);
  padding-inline: var(--nk-space-half);
  border: var(--nk-border-width) solid var(--nk-border-default);
  border-radius: var(--nk-radius-md);
  background-color: var(--nk-surface-raised);
  color: var(--nk-text-default);
  font-size: var(--nk-text-xs);
  font-weight: var(--nk-weight-semibold);
  line-height: var(--nk-leading-snug);
  text-align: center;
  text-decoration: none;
  transition: color var(--nk-transition-base),
    background-color var(--nk-transition-base),
    border-color var(--nk-transition-base),
    transform var(--nk-transition-base);
}

@media (hover: hover) {
  .nk-home-age:hover {
    border-color: var(--nk-border-accent);
    color: var(--nk-text-accent);
  }
}

.nk-home-age:active {
  transform: scale(0.98);
}

.nk-home-age[aria-current="true"] {
  border-color: var(--nk-action-primary);
  background-color: var(--nk-action-primary);
  color: var(--nk-text-on-accent);
}

.nk-home-age[aria-current="true"]:active {
  border-color: var(--nk-action-primary-hover);
  background-color: var(--nk-action-primary-hover);
  color: var(--nk-text-on-accent);
}
@media (hover: hover) {
  .nk-home-age[aria-current="true"]:hover {
    border-color: var(--nk-action-primary-hover);
    background-color: var(--nk-action-primary-hover);
    color: var(--nk-text-on-accent);
  }
}

.nk-home-age__full { display: none; }

@media (min-width: 768px) {
  .nk-home-discovery {
    gap: var(--nk-space-4);
    padding-block-start: var(--nk-space-6);
  }

  .nk-home-categories {
    gap: var(--nk-grid-gap);
  }

  .nk-home-category {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    padding-inline: var(--nk-space-3);
    padding-block: var(--nk-space-half);
    background-color: var(--nk-surface-raised);
    border-color: var(--nk-border-subtle);
    box-shadow: var(--nk-shadow-sm);
  }

  @media (hover: hover) {
    .nk-home-category:hover {
      border-color: var(--nk-border-accent);
      box-shadow: var(--nk-shadow-md);
      transform: translateY(calc(var(--nk-space-half) * -1));
    }
  }

  .nk-home-category__media {
    inline-size: calc(var(--nk-space-12) + var(--nk-space-2));
    background: none;
    box-shadow: none;
  }

  .nk-home-category__media img {
    transform: scale(1.12);
  }

  @media (hover: hover) {
    .nk-home-category:hover .nk-home-category__media {
      box-shadow: none;
      transform: none;
    }
  }

  .nk-home-category__body {
    justify-items: start;
    align-content: center;
    gap: var(--nk-space-hair);
  }

  .nk-home-category__label {
    font-size: var(--nk-text-base);
    text-align: start;
  }

  .nk-home-category__view {
    display: inline-flex;
    align-items: center;
    gap: var(--nk-space-hair);
    color: var(--nk-text-accent);
    font-size: var(--nk-text-2xs);
    font-weight: var(--nk-weight-medium);
    line-height: var(--nk-leading-snug);
  }

  @media (hover: hover) {
    .nk-home-category:hover .nk-home-category__view {
      text-decoration: underline;
    }
  }

  .nk-home-ages {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
  }

  .nk-home-age {
    min-inline-size: calc(var(--nk-space-20) + var(--nk-space-8));
    padding-inline: var(--nk-space-4);
    font-size: var(--nk-text-base);
  }

  .nk-home-age__full { display: inline; }
  .nk-home-age__compact { display: none; }
}

@media (min-width: 1024px) {
  .nk-home-categories {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--nk-space-3);
  }

  .nk-home-category-item--sale {
    display: block;
  }

  .nk-home-category--sale {
    background-color: var(--nk-surface-accent);
    border-color: var(--nk-border-accent);
  }

  .nk-home-category--sale .nk-home-category__label,
  .nk-home-category--sale .nk-home-category__view {
    color: var(--nk-text-accent);
  }
}

@media (min-width: 1280px) {
  .nk-home-category__media {
    inline-size: var(--nk-space-16);
  }
}

/* =======================================================================
 * HOMEPAGE PRODUCT RAILS — .nk-home-rail
 * The shared .nk-rail-section / .nk-product-rail, told how deep this page's
 * rows are. Only the column count changes; every other value comes from the
 * component.
 * ===================================================================== */

/**
 * Homepage rhythm below the hero.
 *
 * `--nk-section-gap` (40/64/80px) is the distance between *sections of the
 * page*. Discovery is not one — it is a navigation strip attached to the hero,
 * and a full section gap under it read as a hole between the age chips and the
 * first rail. The strip closes on `--nk-space-6`, and the rails carry
 * `--nk-space-8` between one another, which keeps the whole run on the same
 * 4px scale as everything else instead of inventing a homepage-only value.
 */
.nk-home-discovery {
  padding-block-end: var(--nk-space-6);
}

.nk-home-rail {
  padding-block-end: var(--nk-space-8);
}

/* Discovery and the rail above already carry that spacing, so the section
   starts flush rather than adding the component's own top margin to it. */
.nk-home-rail .nk-rail-section {
  margin-block-start: 0;
}

/* «پرفروش‌ترین کالاها» is a section of the page like the rails around it, and
   carries the same rhythm — the component's own top margin is theirs, not the
   homepage's. */
.nk-home-bestsellers {
  padding-block-end: var(--nk-space-8);
}

.nk-home-bestsellers .nk-bestsellers-section {
  margin-block-start: 0;
}

/**
 * Two cards on a phone, with the third breaking the edge of the screen — the
 * sliver is what says the row scrolls, and it costs less than an arrow. Held
 * to 768px rather than widening at 480: a 3-up card on a 480px screen puts the
 * product photograph below the size at which a parent can judge a garment.
 *
 * **42%, not the component's 46%**, at the shop owner's request: the homepage
 * rails were reading as two big cards rather than a row that continues. At
 * 360px that is a 138px card instead of 151px — still two across, with a wider
 * sliver of the third doing the work the arrows do on desktop. The product
 * page's own rails keep the component default; this is a homepage judgement
 * about a page that already carries a lot above the fold.
 */
.nk-home-rail .nk-product-rail { grid-auto-columns: 42%; }

@media (min-width: 480px) and (max-width: 767px) {
  .nk-home-rail .nk-product-rail { grid-auto-columns: 42%; }
}

@media (min-width: 768px) {
  .nk-home-rail .nk-product-rail { grid-auto-columns: 30%; }

  /* One step up on a wider screen, the way --nk-gutter and --nk-grid-gap do. */
  .nk-home-discovery { padding-block-end: var(--nk-space-8); }
  .nk-home-rail { padding-block-end: var(--nk-space-10); }
}

/* Six up from the desktop line, exactly — the gaps are subtracted rather than
   approximated with a percentage, so the sixth card ends on the container edge
   instead of a pixel or two past it. */
@media (min-width: 1024px) {
  .nk-home-rail .nk-product-rail {
    grid-auto-columns: calc((100% - (5 * var(--nk-grid-gap))) / 6);
  }
}

/* =======================================================================
 * FREE SHIPPING BAND — .nk-promo--ship
 *
 * The commerce component's promo shell (`.nk-promo`, commerce.css) with a
 * homepage-only skin: a patterned band with a clay object at each side. The
 * variant lives here, not in commerce.css, because it renders on exactly one
 * page and commerce.css is on every route in the store — a homepage banner is
 * not worth 40 lines in the checkout's stylesheet.
 *
 * The ground is a flat pastel with a seamless 120px tile over it
 * (assets/images/patterns/confetti.svg, built by tools/build-pattern.py). It
 * replaced a two-stop gradient, which at this width was a band that simply
 * looked unevenly lit. The pattern is what layout.md's "never a shadow on a
 * flat pastel block" is about: the surface is no longer flat, so the lift
 * reads as depth. The objects are photographic clay renders and bring their
 * own shading — they carry no plate and no --nk-shadow-clay, which would give
 * them a second light source.
 * ===================================================================== */

.nk-home-ship {
  padding-block-end: var(--nk-space-8);
}

.nk-promo--ship {
  /* The object, sized once and stepped up at each breakpoint, so nothing
     downstream has to repeat the number. */
  --nk-ship-object: calc(var(--nk-space-16) + var(--nk-space-2)); /* 72px */

  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--nk-space-4);
  padding: var(--nk-space-5) var(--nk-space-4);
  background-color: var(--nk-pastel-sky);
  /* The tile is drawn for this ground and this ground only — its marks are
     white and navy-200 at low alpha. On any other surface, rebuild it. */
  background-image: url("../../images/patterns/confetti.svg");
  background-repeat: repeat;
  /* Half the authored tile: at 120px the marks read as confetti, at 60 they
     read as texture, which is what a band behind a sentence should be. */
  background-size: 120px 120px;
  /* Shadow, no border — layout.md: a raised block gets one or the other. The
     inset hairline is the band's own top edge catching the light. */
  box-shadow:
    var(--nk-shadow-lg),
    inset 0 var(--nk-space-hair) 0 var(--nk-white);
}

/* One decorative object per side. `--lead` is at the inline start, so in RTL
   the tote sits on the right and the bow on the left. */
.nk-promo__object {
  display: block;
  inline-size: var(--nk-ship-object);
  flex: none;
}

.nk-promo__object img {
  inline-size: 100%;
  block-size: auto;
  /* The renders are square and transparent; this keeps a stray non-square
     source from stretching rather than being letterboxed. */
  aspect-ratio: var(--nk-ratio-square);
  object-fit: contain;
}

.nk-promo__object--trail {
  /* Hidden on a phone: two objects around a two-line Persian sentence at 360px
     leave the sentence about 190px, and the promise is what matters.
     Decoration is the first thing to go, never the copy. */
  display: none;
}

.nk-promo--ship .nk-promo__body {
  display: grid;
  gap: var(--nk-space-1);
  min-inline-size: 0;
}

.nk-promo--ship .nk-promo__title {
  font-size: var(--nk-text-lg);
  font-weight: var(--nk-weight-bold);
  line-height: var(--nk-leading-snug);
}

.nk-promo__amount {
  color: var(--nk-text-accent);
  white-space: nowrap;
}

.nk-promo--ship .nk-promo__text {
  font-size: var(--nk-text-sm);
}

@media (min-width: 480px) {
  .nk-promo--ship {
    --nk-ship-object: var(--nk-space-20); /* 80px */
  }

  .nk-promo--ship .nk-promo__title { font-size: var(--nk-text-xl); }
  .nk-promo--ship .nk-promo__text { font-size: var(--nk-text-base); }
}

@media (min-width: 768px) {
  .nk-home-ship { padding-block-end: var(--nk-space-10); }

  .nk-promo--ship {
    --nk-ship-object: calc(var(--nk-space-20) + var(--nk-space-4)); /* 96px */

    grid-template-columns: auto minmax(0, 1fr) auto;
    padding: var(--nk-space-6) var(--nk-space-8);
    gap: var(--nk-space-6);
  }

  /* Both objects present, so the copy sits centred between them rather than
     drifting to one side of a very wide band. */
  .nk-promo--ship .nk-promo__body { justify-items: center; text-align: center; }
  .nk-promo__object--trail { display: block; }
  .nk-promo--ship .nk-promo__title { font-size: var(--nk-text-2xl); }

  /* A few degrees off axis, once there is room for it: a render sitting
     perfectly upright reads as a pasted-in icon, and this is meant to be an
     object resting on the band. Both tilt away from the copy, so the eye is
     pushed back to the sentence. Not on a phone, where the object is small and
     the tilt only costs it width. */
  .nk-promo__object--lead { transform: rotate(-5deg); }
  .nk-promo__object--trail { transform: rotate(5deg); }
}

@media (min-width: 1024px) {
  .nk-promo--ship {
    --nk-ship-object: calc(var(--nk-space-24) + var(--nk-space-2)); /* 104px */

    padding-block: var(--nk-space-6);
  }
}

/* =======================================================================
 * BRANDS — .nk-brand-rail / .nk-brand-card
 * «برندها», rendered by nk_home_brands(). A row of compact logo cards, each
 * one a link to that brand's own WooCommerce archive.
 *
 * Homepage-scoped, like .nk-promo--ship above and for the same reason: it
 * renders on exactly one page today, and commerce.css is loaded on every route
 * in the store including the checkout. If a second template ever wants a brand
 * row, this block moves to commerce.css in that change — not before.
 *
 * The overflow is the same native scroll-snap track the product rails use:
 * `overflow-x: auto` plus `scroll-snap-type`, which is the whole mechanism.
 * Touch gets the platform's own gesture, a keyboard reaches every card because
 * every card is a link, and it all works with JavaScript off. `data-nk-rail` in
 * the markup opts into initRails() for the mouse pointer-drag only — there are
 * no arrows here: a logo is recognised, not paged through.
 * ===================================================================== */

.nk-home-brands {
  padding-block-end: var(--nk-space-8);
}

/* The rails above carry the rhythm between sections; the component's own top
   margin would add to it. Same treatment as .nk-home-bestsellers. */
.nk-brand-rail-section {
  margin-block-start: 0;
}

/*
 * One heading size for the whole run of sections.
 *
 * The two rails head themselves with `.nk-rail-section__title` (`--nk-text-xl`);
 * «پرفروش‌ترین کالاها» and «برندها» use the shared SectionTitle, whose default is
 * a page-level 24px growing to 28px at 768. Stacked one after another they read
 * as two levels of heading on a page that only has one — the sections are peers,
 * so they get the rail's size. The component keeps its own default everywhere
 * else; this is the homepage tuning a shared component, which is what this
 * stylesheet is for.
 */
.nk-home-bestsellers .nk-section-title__text,
.nk-home-brands .nk-section-title__text {
  font-size: var(--nk-text-xl);
}

.nk-home-bestsellers .nk-section-title__sub,
.nk-home-brands .nk-section-title__sub {
  font-size: var(--nk-text-sm);
}

/* The progress bar is the row's only "there is more" cue, so it sits close
   enough to the track to read as part of it. */
.nk-brand-rail-section .nk-rail-progress {
  margin-block-start: var(--nk-space-2);
}

/*
 * Three cards to a phone with the fourth breaking the edge — the sliver is the
 * only affordance the row needs, exactly as on the product rails.
 *
 * Two classes, not one: `ul[class], ol[class]` in base.css is (0,1,1) and zeroes
 * margin and padding, so a single-class rule would lose its bleed. See
 * .claude/rules/css.md.
 */
.nk-brand-rail-section .nk-brand-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 30%;
  gap: var(--nk-space-3);
  overflow-x: auto;

  /*
   * `proximity`, not `mandatory`.
   *
   * A row of logos is browsed, not paged: with `mandatory` every release was
   * yanked to the nearest card — "you let go and it moves on its own" — and a
   * flick that ended between two cards was overruled. `proximity` tidies up a
   * release that is already almost aligned and leaves every other one alone.
   * `initRails()` reads this: it only forces an alignment on a mandatory track.
   */
  scroll-snap-type: x proximity;

  /* Bleed to the screen edge, exactly as .nk-product-rail does. */
  padding-inline: var(--nk-gutter);
  margin-inline: calc(var(--nk-gutter) * -1);

  /*
   * The snapport has to be inset by the same gutter the track is padded with.
   * Without this the first card's snap position sits one gutter inside the
   * scrollport, so the browser scrolls the row **on load** to satisfy it: the
   * track opened already nudged off its start edge, with the first logo cropped
   * against the right edge in RTL. Measured at 1280: a 32px offset before
   * anything had been touched.
   */
  scroll-padding-inline: var(--nk-gutter);

  /*
   * Room above and below for the cards' shadow and their 2px hover lift.
   * `overflow-x: auto` computes `overflow-y` to `auto` as well, so the track
   * clips vertically no matter what the y value says — a lifted card was being
   * cut off along its top edge. Padding is the only way to give it room, and
   * 16px is `--nk-shadow-md`'s 20px blur minus its 6px downward offset, so the
   * soft edge lands inside the box at both ends.
   */
  padding-block: var(--nk-space-4);

  scrollbar-width: none;
  overscroll-behavior-x: contain;
  list-style: none;
}
.nk-brand-rail::-webkit-scrollbar { display: none; }
.nk-brand-rail > * { scroll-snap-align: start; }

/* ui.js suspends the snap for a mouse drag; the cursor says the row can be
   pulled and text must not start selecting mid-drag. Touch never reaches this. */
.nk-brand-rail.is-dragging { cursor: grabbing; user-select: none; scroll-snap-type: none; }

@media (min-width: 480px) { .nk-brand-rail-section .nk-brand-rail { grid-auto-columns: 24%; } }
@media (min-width: 768px) {
  .nk-home-brands { padding-block-end: var(--nk-space-10); }
  .nk-brand-rail-section .nk-brand-rail { grid-auto-columns: 18%; gap: var(--nk-space-3); }
}

/*
 * Eight across the container exactly — the gaps are subtracted rather than
 * approximated, so the eighth card ends on the container edge and the ninth is
 * the one that says there is more.
 *
 * Six was the first pass and the cards came out 183px wide holding a 96px
 * wordmark: a logo chip blown up to the size of a product card. A brand row is
 * a strip of marks a parent recognises in passing, not a grid of destinations,
 * so on desktop the card gets smaller as the screen gets larger, not bigger.
 */
@media (min-width: 1024px) {
  .nk-brand-rail-section .nk-brand-rail {
    grid-auto-columns: calc((100% - (7 * var(--nk-space-3))) / 8);
  }
}

/*
 * The card. Compact by intent: a logo, a name, nothing else. No product count —
 * a number beside a wordmark reads as a price at a glance, and the ranking is
 * already expressed by the order.
 *
 * **White card, and the depth comes from the shadow.** A cream card with a
 * white plate inside it was tried and reads as two boxes rather than one
 * object; the logos are flattened onto white by `build-brand-logos.py`, so
 * white is also the only ground that cannot print a rectangle around them. The
 * card sits *on* the cream page instead of being cut out of it: a resting
 * shadow, a hairline, and a deeper shadow with a 2px lift under the pointer.
 */
.nk-brand-card {
  /* One number for the logo row, so the box and the image inside it can never
     disagree about how tall a logo is. */
  --nk-brand-logo: var(--nk-space-12); /* 48px */

  display: grid;
  gap: var(--nk-space-2);
  justify-items: center;
  align-content: center;
  padding: var(--nk-space-3) var(--nk-space-2);
  background-color: var(--nk-surface-raised);
  border: var(--nk-border-hairline);
  border-radius: var(--nk-radius-lg);
  box-shadow: var(--nk-shadow-xs);
  text-decoration: none;
  block-size: 100%;
  transition:
    transform var(--nk-transition-base),
    border-color var(--nk-transition-base),
    box-shadow var(--nk-transition-base);
}

@media (hover: hover) {
  .nk-brand-card:hover { border-color: var(--nk-border-default); box-shadow: var(--nk-shadow-md); }
}
.nk-brand-card:focus-visible {
  outline: var(--nk-focus-ring-width) solid var(--nk-focus-ring-color);
  outline-offset: var(--nk-focus-ring-offset);
}
.nk-brand-card:active { border-color: var(--nk-border-strong); }

/*
 * The same 2px lift the product and category cards use — `motion.css` owns that
 * rule for the global components, and this one is homepage-scoped, so it carries
 * its own copy including the reduced-motion reset. Deliberately no more than
 * that: the tell of a cheap storefront is UI that bounces.
 */
@media (hover: hover) {
  .nk-brand-card:hover { transform: translateY(-2px); }
}
.nk-brand-card:active { transform: scale(0.99); }

@media (prefers-reduced-motion: reduce) {
  .nk-brand-card:hover,
  .nk-brand-card:active { transform: none; }
}

/* No disabled state: the card is a link to a brand archive, and a brand with
   nothing in stock is not rendered at all rather than shown greyed out. */

/*
 * A fixed logo *height*, not an aspect ratio. The artwork arrives at wildly
 * different proportions — a wide wordmark, a stacked lockup — and it is equal
 * optical height that makes eight logos read as one set. The width is whatever
 * `contain` gives them inside the plate.
 */
.nk-brand-card__media {
  display: grid;
  place-items: center;
  inline-size: 100%;
  min-block-size: var(--nk-brand-logo);
}

/*
 * The height is stated on the **image**, in a length, and `object-fit: contain`
 * letterboxes the artwork inside it. Two obvious ways to write this are both
 * wrong, and both were measured in Chrome rather than guessed:
 *
 *   - `block-size: auto` with `max-block-size: 100%` — the intrinsic 600×400
 *     gives the img an aspect ratio, the width cap settles it at the card's
 *     width, and the height that ratio implies (104px) simply ignored the cap.
 *   - `block-size: 100%` against a box with a definite height — the percentage
 *     never resolved either; the img stayed at its aspect-ratio height and
 *     printed the wordmark over the brand's name.
 *
 * A length has no containing block to resolve against and cannot do either.
 *
 * Two classes: `.woocommerce-page img { height: auto }` is (0,1,1), and this row
 * renders inside our own chrome today but must not break if the section is ever
 * dropped onto a commerce route. See .claude/rules/css.md.
 */
.nk-brand-card__media .nk-brand-card__img {
  inline-size: 100%;
  block-size: var(--nk-brand-logo);
  object-fit: contain;
}

/*
 * No artwork: the brand's wordmark set in the display face, muted, on the same
 * surface the card already has. A missing logo should look like a quiet
 * typographic card, never like a failed image or a generic grey placeholder.
 */
.nk-brand-card__fallback {
  font-family: var(--nk-font-display);
  font-size: var(--nk-text-base);
  font-weight: var(--nk-weight-bold);
  line-height: var(--nk-leading-tight);
  color: var(--nk-text-muted);
  text-align: center;
  /* Two words of a long label wrap rather than pushing the card wider. */
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/*
 * The last item in the row: a text link with an arrow, not a card.
 *
 * It sits in a full-width grid track like everything else — the track keeps the
 * row's rhythm — but paints nothing of its own, so it reads as the row ending
 * rather than as one more brand. Deliberately not a filled button either: the
 * homepage's one `--primary` action belongs to the hero.
 */
.nk-brand-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--nk-space-1);
  block-size: 100%;
  min-block-size: var(--nk-touch-target);
  padding-inline: var(--nk-space-2);
  color: var(--nk-text-accent);
  font-size: var(--nk-text-sm);
  font-weight: var(--nk-weight-semibold);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--nk-transition-base);
}

@media (hover: hover) {
  .nk-brand-more:hover { color: var(--nk-action-primary-hover); text-decoration: underline; }
}
.nk-brand-more:active { color: var(--nk-action-primary-active); }
.nk-brand-more:focus-visible {
  outline: var(--nk-focus-ring-width) solid var(--nk-focus-ring-color);
  outline-offset: var(--nk-focus-ring-offset);
  border-radius: var(--nk-radius-sm);
}

@media (hover: hover) {
  /* A nudge toward where the arrow points. `translate` is physical, and that is
     deliberate here: the site is `fa_IR` and RTL-only, so "forward" is negative
     X. If an LTR locale ever ships, this flips. */
  .nk-brand-more:hover .nk-icon { translate: calc(var(--nk-space-1) * -1) 0; }
}
.nk-brand-more .nk-icon { transition: translate var(--nk-transition-base); }

@media (prefers-reduced-motion: reduce) {
  .nk-brand-more:hover .nk-icon { translate: none; }
}

/* Always present, artwork or not — a logo alone is a guess for anyone who does
   not already know the mark, and it is the only text the link carries. */
.nk-brand-card__name {
  inline-size: 100%;
  font-size: var(--nk-text-xs);
  font-weight: var(--nk-weight-medium);
  line-height: var(--nk-leading-snug);
  color: var(--nk-text-default);
  text-align: center;
  /* One line at every width — it is what keeps the cards the same height. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/*
 * One step up on a tablet, and no further. The logo grew to 64px at 768 and
 * stayed there while the card kept getting wider, which is how a compact chip
 * turns into a poster; 56px with the smaller desktop card holds the row at the
 * size a mark is read at.
 */
@media (min-width: 768px) {
  .nk-brand-card {
    --nk-brand-logo: calc(var(--nk-space-12) + var(--nk-space-2)); /* 56px */

    padding: var(--nk-space-3);
  }
  .nk-brand-card__fallback { font-size: var(--nk-text-base); }
  .nk-brand-card__name { font-size: var(--nk-text-sm); }
}

/* =======================================================================
 * SEASONAL BANNERS — .nk-home-banners
 * The band between «برندها» and the club, rendered by nk_home_banners().
 *
 * Homepage-scoped, like .nk-promo--ship and .nk-brand-rail above and for the
 * same reason: it renders on exactly one page today.
 *
 * The component is almost nothing, and deliberately: each banner is a finished
 * studio composition with its own headline and its own button painted into the
 * pixels, so everything this file does is give the picture a box of the right
 * shape, round its corners and make the whole of it pressable. Anything drawn
 * on top of, or around, that artwork competes with a design that is already
 * complete.
 *
 * 16:9 at every width, one file. The band shipped with an art-directed square
 * crop below 768px and the shop owner asked for the wide frame on the phone as
 * well — so there is no ratio swap, no <picture> and nothing here that has to
 * stay in step with a media query in PHP. If a second crop ever comes back,
 * that agreement comes back with it.
 * ===================================================================== */

.nk-home-banners {
  padding-block-end: var(--nk-space-8);
}

/* A list with a class, so it needs two classes to beat base.css's
   `ul[class] { margin: 0; padding: 0 }` reset — see .claude/rules/css.md. */
.nk-home-banners .nk-home-banners__list {
  display: grid;
  gap: var(--nk-space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nk-home-banner,
.nk-home-banners .nk-home-banner {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: var(--nk-radius-xl);
  /* Reserved before the picture decodes, so the club below it never jumps.
     One ratio at every width — the artwork is the wide campaign frame on a
     phone too, at the shop owner's instruction. */
  aspect-ratio: var(--nk-ratio-banner);
  background-color: var(--nk-surface-sunken);
  color: inherit;
  text-decoration: none;
}

.nk-home-banner__img,
.nk-home-banner .nk-home-banner__img {
  /* Two classes: `.woocommerce-page img { height: auto }` would collapse this
     to intrinsic height if the band ever renders on a commerce route. */
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
  transition: filter var(--nk-transition-base);
}

/*
 * Hover does nothing to the frame — no ring, no border, no coral edge.
 *
 * This is the second time that has been asked for on this artwork, so it is
 * written down rather than left to taste: these compositions carry their own
 * button, and an outline appearing around the whole picture on hover reads as
 * a rendering fault rather than as an affordance. The cursor is the
 * affordance; the acknowledgement is a whisper of brightness on the picture.
 */
@media (hover: hover) {
  a.nk-home-banner:hover .nk-home-banner__img {
    filter: brightness(1.04);
  }
}

a.nk-home-banner:active .nk-home-banner__img {
  filter: brightness(0.97);
}

/* Focus is the one state that does draw a ring, and it is never optional. It
   sits inside the banner's own clip so a rounded corner cannot crop it. */
a.nk-home-banner:focus-visible {
  outline: var(--nk-focus-ring-width) solid var(--nk-focus-ring-color);
  outline-offset: calc(-1 * (var(--nk-focus-ring-width) + var(--nk-focus-ring-offset)));
}

/* ≥768 — two banners across. Below it they stack, because a 16:9 banner at
   360px is already only 184px tall and two side by side would be unreadable. */
@media (min-width: 768px) {
  .nk-home-banners .nk-home-banners__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--nk-space-6);
  }
}

/* =======================================================================
 * CUSTOMER CLUB — .nk-club
 * «باشگاه مشتریان», rendered by nk_home_club().
 *
 * The approved composition is a cream membership panel with one navy artwork
 * stage. It uses two real layouts rather than compressing desktop onto a phone:
 *   <1024 — a narrow vertical card: artwork, overlapping badge, copy, benefits,
 *            stacked phone field and CTA.
 *   ≥1024 — a 55/45 split: content at the RTL inline start (right), membership
 *            artwork at the physical left, and the form joined into one capsule.
 *
 * The existing data attributes, server-rendered states and REST enhancement are
 * unchanged; this block owns presentation only.
 * ===================================================================== */

.nk-club {
  padding-block-end: var(--nk-section-gap);
}

.nk-club {
  /* Narrow-composition geometry. The ≥1024 block has its own, much larger set;
     these are the two values the single-column layout is actually tuned by. */
  --nk-club-panel-max: calc(var(--nk-container-narrow) / 2);
  --nk-club-stage-h: calc(var(--nk-space-24) * 2.3);  /* a floor, not the height */
  --nk-club-mcard-width: 78%;
  --nk-club-mcard-max: 19rem;
  --nk-club-mcard-y: 10px;     /* nudged below centre, at the shop owner's eye */
  --nk-club-mcard-pad-start: var(--nk-space-6);
  --nk-club-mcard-pad-end: var(--nk-space-10);
}

.nk-club__panel {
  position: relative;
  overflow: hidden;
  inline-size: 100%;
  max-inline-size: var(--nk-club-panel-max);
  margin-inline: auto;
  background-color: var(--nk-surface-raised);
  border: var(--nk-border-width) solid var(--nk-border-subtle);
  border-radius: var(--nk-radius-2xl);
  box-shadow: var(--nk-shadow-xl);
}

/* -------- illustration stage -------- */

/* The card is an in-flow grid item here rather than an absolutely positioned
   one, so the **stage takes its height from the card** instead of being told a
   number that only happens to fit at one width. Told a number, it was 250px at
   768 while the card wanted 312, and the difference was clipped off by the
   curved bottom edge. `--nk-club-stage-h` survives as a floor for the case
   where the card is small. Everything else in here — halo, sparks, the star —
   is absolutely positioned and so is unaffected by the grid.

   The bottom padding is larger than the top on purpose: the stage's bottom
   corners curve away (`50% 26%`), so a card centred in the *box* has its lower
   corners eaten by the arc. The extra bottom padding centres it in what is
   actually visible. */
.nk-club__visual {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  padding-block: var(--nk-club-mcard-pad-start) var(--nk-club-mcard-pad-end);
  min-block-size: var(--nk-club-stage-h);
  overflow: hidden;
  background-color: var(--nk-surface-inverse);
  border-end-start-radius: 50% 26%;
  border-end-end-radius: 50% 26%;
}

.nk-club__halo {
  position: absolute;
  z-index: -1;
  inset-block-start: calc(var(--nk-space-20) * -1.4);
  inset-inline-start: calc(var(--nk-space-12) * -1);
  inline-size: 130%;
  aspect-ratio: var(--nk-ratio-square);
  background-image: var(--nk-glow-accent);
  border-radius: var(--nk-radius-circle);
  pointer-events: none;
}

.nk-club__spark {
  position: absolute;
  inline-size: var(--nk-space-4);
  aspect-ratio: var(--nk-ratio-square);
  background-color: currentColor;
  clip-path: polygon(50% 0, 61% 35%, 100% 50%, 64% 62%, 50% 100%, 38% 64%, 0 50%, 35% 38%);
  pointer-events: none;
}

.nk-club__spark--coral {
  inset-block-start: var(--nk-space-8);
  inset-inline-start: var(--nk-space-8);
  color: var(--nk-action-primary);
  transform: rotate(10deg) scale(1.3);
}

.nk-club__spark--navy {
  display: none;
  color: var(--nk-navy-800);
}

.nk-club__membership-scene {
  position: relative;
  z-index: var(--nk-z-raised);
  inline-size: var(--nk-club-mcard-width);
  /* Capped, or a 768px panel gives the card a 468px width and a 312px-tall
     navy slab above the copy. A tablet gets a bigger card, not a giant one. */
  max-inline-size: var(--nk-club-mcard-max);
  transform: translateY(var(--nk-club-mcard-y));
  pointer-events: none;
}

.nk-club__membership-scene .nk-club__membership {
  display: block;
  inline-size: 100%;
  block-size: auto;
}

.nk-club__desktop-decor,
.nk-club__body-decor {
  display: none;
}

.nk-club__art {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.nk-club__art img {
  position: absolute;
  block-size: auto;
  filter: drop-shadow(var(--nk-shadow-md));
}

.nk-club__art .nk-club__star {
  inline-size: 13%;
  inset-inline-end: var(--nk-space-8);
  inset-block-start: var(--nk-space-6);
  transform: rotate(12deg);
}

/* -------- copy and benefits -------- */

.nk-club__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--nk-space-3);
  padding: var(--nk-space-4) var(--nk-space-5) var(--nk-space-5);
  color: var(--nk-text-default);
  text-align: center;
}

.nk-club__eyebrow {
  position: relative;
  z-index: var(--nk-z-raised);
  display: inline-flex;
  align-items: center;
  gap: var(--nk-space-2);
  margin: calc(var(--nk-space-10) * -1) 0 0;
  padding: var(--nk-space-2) var(--nk-space-4);
  background-color: var(--nk-surface-inverse);
  border: var(--nk-border-width) solid var(--nk-border-inverse);
  border-radius: var(--nk-radius-pill);
  box-shadow: var(--nk-shadow-md);
  color: var(--nk-text-inverse);
  font-size: var(--nk-text-sm);
  font-weight: var(--nk-weight-semibold);
}

.nk-club__eyebrow .nk-icon {
  color: var(--nk-text-accent-inverse);
}

.nk-club__eyebrow-icon--desktop {
  display: none;
}

.nk-club__eyebrow-desktop,
.nk-club__title-desktop {
  display: none;
}

.nk-club__title {
  margin: var(--nk-space-1) 0 0;
  color: var(--nk-text-strong);
  font-family: var(--nk-font-display);
  font-size: var(--nk-text-3xl);
  font-weight: var(--nk-weight-bold);
  line-height: var(--nk-leading-tight);
}

.nk-club__text {
  max-inline-size: 31ch;
  margin: 0;
  color: var(--nk-text-muted);
  font-size: var(--nk-text-base);
  line-height: var(--nk-leading-normal);
}

.nk-club__body .nk-club__perks {
  display: grid;
  gap: var(--nk-space-2);
  inline-size: 100%;
  margin: var(--nk-space-1) 0 0;
  padding: 0;
  list-style: none;
}

.nk-club__perk {
  display: flex;
  align-items: center;
  gap: var(--nk-space-3);
  min-block-size: var(--nk-touch-target-lg);
  padding: var(--nk-space-2) var(--nk-space-4);
  background-color: var(--nk-surface-sunken);
  border: var(--nk-border-width) solid transparent;
  border-radius: var(--nk-radius-lg);
  box-shadow: var(--nk-shadow-xs);
  color: var(--nk-text-default);
  font-size: var(--nk-text-base);
  font-weight: var(--nk-weight-medium);
  line-height: var(--nk-leading-snug);
  text-align: start;
}

.nk-club__perk .nk-icon {
  flex: 0 0 auto;
  inline-size: var(--nk-icon-md);
  block-size: var(--nk-icon-md);
  margin-inline: calc((var(--nk-space-8) - var(--nk-icon-md)) / 2);
  color: var(--nk-action-primary);
}

/* -------- form -------- */

.nk-club__form,
.nk-club__field {
  inline-size: 100%;
}

.nk-club__field {
  display: flex;
  flex-direction: column;
}

.nk-club__form {
  margin-block-start: var(--nk-space-1);
}

.nk-club__capsule {
  position: relative;
  display: grid;
  gap: var(--nk-space-3);
}

.nk-club__capsule-icon {
  position: absolute;
  z-index: var(--nk-z-raised);
  display: grid;
  place-items: center;
  inline-size: var(--nk-space-8);
  aspect-ratio: var(--nk-ratio-square);
  inset-block-start: var(--nk-space-3);
  inset-inline-start: var(--nk-space-3);
  color: var(--nk-action-primary);
  pointer-events: none;
}

.nk-club__capsule .nk-club__input {
  inline-size: 100%;
  min-block-size: calc(var(--nk-touch-target-lg) + var(--nk-space-2));
  padding-block: var(--nk-space-3);
  padding-inline-start: var(--nk-space-4);
  padding-inline-end: var(--nk-space-12);
  background-color: var(--nk-surface-raised);
  border: var(--nk-border-width) solid var(--nk-border-default);
  border-radius: var(--nk-radius-lg);
  box-shadow: var(--nk-shadow-inset);
  color: var(--nk-text-strong);
  font-family: var(--nk-font-numeric);
  font-size: var(--nk-text-md);
  text-align: start;
  transition: border-color var(--nk-transition-base), box-shadow var(--nk-transition-base);
}

.nk-club__capsule .nk-club__input::placeholder {
  color: var(--nk-text-subtle);
  opacity: 1;
}

@media (hover: hover) {
  .nk-club__capsule .nk-club__input:hover {
    border-color: var(--nk-border-strong);
  }
}

.nk-club__capsule .nk-club__input:focus-visible {
  border-color: var(--nk-border-accent);
  outline: var(--nk-focus-ring-width) solid var(--nk-focus-ring-color);
  outline-offset: var(--nk-focus-ring-offset);
}

.nk-club__capsule .nk-club__input:active {
  border-color: var(--nk-border-accent);
}

.nk-club__capsule .nk-club__input:disabled {
  background-color: var(--nk-action-disabled-bg);
  border-color: var(--nk-border-default);
  color: var(--nk-action-disabled-text);
  cursor: not-allowed;
}

.nk-club__capsule .nk-club__input[aria-invalid="true"] {
  border-color: var(--nk-status-danger);
}

.nk-club__capsule .nk-club__input:disabled[aria-invalid="true"] {
  border-color: var(--nk-border-default);
}

/* Deliberately shorter than the field it sits beside — one touch target tall,
   not the field's typing-comfort height. The shop owner read the full-height
   slab as shouting; 48px is still the preferred primary-action target. */
.nk-club__capsule .nk-btn {
  inline-size: 100%;
  min-block-size: var(--nk-touch-target-lg);
  padding: var(--nk-space-2) var(--nk-space-5);
  border-radius: var(--nk-radius-lg);
  box-shadow: var(--nk-shadow-accent);
  font-size: var(--nk-text-base);
  font-weight: var(--nk-weight-bold);
  white-space: nowrap;
  transition: background-color var(--nk-transition-base), border-color var(--nk-transition-base), box-shadow var(--nk-transition-base), transform var(--nk-transition-base);
}

@media (hover: hover) {
  .nk-club__capsule .nk-btn:hover:not(:disabled) {
    box-shadow: var(--nk-shadow-lg);
    transform: translateY(calc(var(--nk-space-half) * -1));
  }
}

.nk-club__capsule .nk-btn:active:not(:disabled) {
  box-shadow: var(--nk-shadow-sm);
  transform: translateY(0);
}

.nk-club__capsule .nk-btn:disabled {
  background-color: var(--nk-action-disabled-bg);
  border-color: var(--nk-action-disabled-bg);
  box-shadow: none;
  color: var(--nk-action-disabled-text);
  cursor: not-allowed;
  transform: none;
}

.nk-club__capsule .nk-btn[aria-busy="true"]::after {
  content: "";
  inline-size: var(--nk-icon-sm);
  block-size: var(--nk-icon-sm);
  border: var(--nk-border-width-thick) solid var(--nk-coral-300);
  border-block-start-color: var(--nk-text-on-accent);
  border-radius: var(--nk-radius-circle);
  animation: nk-spin var(--nk-duration-slow) linear infinite;
}

.nk-club__capsule .nk-btn[aria-busy="true"]:disabled {
  background-color: var(--nk-action-primary);
  color: var(--nk-text-on-accent);
  opacity: 0.8;
  cursor: progress;
}

.nk-club__help {
  order: 2;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: var(--nk-space-2);
  margin: var(--nk-space-3) 0 0;
  color: var(--nk-text-subtle);
  font-size: var(--nk-text-xs);
  line-height: var(--nk-leading-normal);
}

.nk-club__help .nk-icon {
  flex: 0 0 auto;
  margin-block-start: var(--nk-space-1);
}

.nk-club__error {
  order: 1;
  align-items: flex-start;
  padding: var(--nk-space-2) var(--nk-space-3);
  background-color: var(--nk-status-danger-bg);
  border-radius: var(--nk-radius-sm);
  color: var(--nk-status-danger-text);
  text-align: start;
}

.nk-club__error .nk-icon {
  flex: none;
  margin-block-start: var(--nk-space-half);
}

/* -------- success / duplicate result -------- */

.nk-club__result {
  display: grid;
  justify-items: start;
  gap: var(--nk-space-1);
  inline-size: 100%;
  margin-block-start: var(--nk-space-1);
  padding: var(--nk-space-4) var(--nk-space-5);
  background-color: var(--nk-surface-sunken);
  border: var(--nk-border-width) solid var(--nk-border-subtle);
  border-radius: var(--nk-radius-xl);
  color: var(--nk-text-default);
  text-align: start;
}

.nk-club__result:focus,
.nk-club__result:focus-visible {
  outline: none;
}

.nk-club__result-mark {
  color: var(--nk-action-primary);
  line-height: var(--nk-leading-none);
}

.nk-club__result-title {
  margin: 0;
  color: var(--nk-text-strong);
  font-family: var(--nk-font-display);
  font-size: var(--nk-text-lg);
  font-weight: var(--nk-weight-bold);
}

.nk-club__result-text {
  margin: 0;
  color: var(--nk-text-muted);
  font-size: var(--nk-text-base);
  line-height: var(--nk-leading-normal);
}

/* =======================================================================
 * ≥768 — the tablet pass over the narrow composition.
 *
 * A tablet is not a big phone here and it is not a small desktop either. The
 * panel used to stay capped at `--nk-container-narrow / 2` — 384px — all the
 * way to 1024, so a 768 or 900px screen showed a phone-width card marooned in
 * the middle of it. What a tablet actually has is *inline room*, so this block
 * spends it and nothing else: a wider panel, the three benefits as one row
 * instead of three stacked bars, and the field and button joined into one
 * capsule.
 *
 * Everything here is width-driven, so it deliberately stays in force at 1024
 * and above; the 1024 block below is only the two-column composition. Moving
 * these rules down out of it is why the desktop capsule is not restated there.
 * ===================================================================== */

@media (min-width: 768px) {
  .nk-club {
    --nk-club-panel-max: 34rem;
  }

  .nk-club__body {
    gap: var(--nk-space-4);
    padding: var(--nk-space-5) var(--nk-space-8) var(--nk-space-8);
  }

  .nk-club__body .nk-club__perks {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--nk-space-3);
  }

  .nk-club__perk {
    justify-content: center;
    min-block-size: calc(var(--nk-touch-target-lg) + var(--nk-space-2));
    padding: var(--nk-space-2) var(--nk-space-3);
    font-size: var(--nk-text-sm);
    text-align: center;
  }

  .nk-club__perk .nk-icon {
    margin-inline: 0;
  }

  .nk-club__capsule {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--nk-space-2);
    padding: var(--nk-space-1);
    background-color: var(--nk-surface-raised);
    border: var(--nk-border-width) solid var(--nk-border-default);
    border-radius: var(--nk-radius-lg);
    box-shadow: var(--nk-shadow-md);
    transition: border-color var(--nk-transition-base), box-shadow var(--nk-transition-base);
  }

  /* The ring is on the capsule, not the input: the capsule is what a sighted
     keyboard user perceives as the control, and both would draw ring-in-ring. */
  .nk-club__capsule:focus-within {
    border-color: var(--nk-border-accent);
    outline: var(--nk-focus-ring-width) solid var(--nk-focus-ring-color);
    outline-offset: var(--nk-focus-ring-offset);
  }

  .nk-club__capsule-icon {
    inset-block-start: 50%;
    inset-inline-start: var(--nk-space-4);
    transform: translateY(-50%);
  }

  .nk-club__capsule .nk-club__input {
    flex: 1 1 auto;
    min-inline-size: 0;
    min-block-size: var(--nk-touch-target-lg);
    padding-inline-start: var(--nk-space-4);
    padding-inline-end: var(--nk-space-12);
    background-color: transparent;
    border-color: transparent;
    border-radius: var(--nk-radius-md);
    box-shadow: none;
  }

  .nk-club__capsule .nk-club__input:focus-visible,
  .nk-club__capsule .nk-club__input:active,
  .nk-club__capsule .nk-club__input[aria-invalid="true"] {
    border-color: transparent;
    outline: none;
  }
  @media (hover: hover) {
    .nk-club__capsule .nk-club__input:hover {
      border-color: transparent;
      outline: none;
    }
  }

  .nk-club__capsule .nk-btn {
    flex: 0 0 auto;
    inline-size: auto;
    min-inline-size: calc(var(--nk-space-24) * 1.35);
    padding-inline: var(--nk-space-5);
    border-radius: var(--nk-radius-md);
  }

  .nk-club__result {
    margin-block-start: 0;
  }
}

/* =======================================================================
 * ≥1024 — approved desktop composition.
 * ===================================================================== */

@media (min-width: 1024px) {
  /* ------------------------------------------------------------------
   * The desktop composition's geometry, in one block.
   *
   * These are **component-local custom properties, not design tokens** —
   * they belong here and never in `tokens.css`. The composition is one
   * bespoke arrangement of one artwork and every value is a share of
   * something else inside it, so there is nothing here for a second
   * component to reuse. What they buy is that the arrangement can be
   * tuned in one place and read back as numbers: `club-tuner.html` at
   * the theme root binds a control to each one.
   *
   * Anything positioned against the ticket's *drawn* corners is measured
   * off the artwork's alpha channel, never guessed — the accent block
   * further down carries the one-liner that reads them back.
   * ------------------------------------------------------------------ */
  .nk-club {
    /* the navy ground */
    --nk-club-navy-width: 81%;   /* share of the artwork column */
    --nk-club-navy-arc-x: 38%;   /* horizontal half of the arc radius — taste */
    --nk-club-navy-arc-y: 50%;   /* vertical half — must stay 50%, see below */

    /* the ticket */
    --nk-club-card-width: 81%;   /* share of the artwork column */
    --nk-club-card-x: 8.5%;        /* from the column's outer edge */
    --nk-club-card-y: 0%;        /* off centre, as a share of the card's own height */

    /* the accent box. Starts identical to the card on purpose — the coral pair
       is pinned to the ticket's drawn corners, so by default the accents travel
       with it. It is a *separate* set of three rather than the card's own so the
       card can still be moved on its own; make them differ only deliberately. */
    --nk-club-decor-width: 85%;
    --nk-club-decor-x: 4%;
    --nk-club-decor-y: 0%;

    /* accents, as shares of the card */
    --nk-club-rays-size: 16.2%;
    --nk-club-rays-x: 9.8%;
    --nk-club-rays-y: -6.8%;
    --nk-club-burst-size: 12%;
    --nk-club-burst-x: 1.7%;
    --nk-club-burst-y: -16.7%;
    --nk-club-heart-size: 11%;
    --nk-club-heart-x: 36.8%;
    --nk-club-heart-y: -17.4%;

    /* the copy side — the pair of marks above the eyebrow, then the staggered
       indents that give the column its ragged inline-start edge.

       Three of these are raw px rather than a spacing token: 92, 50 and 100 sit
       between steps of the 4px scale. They are kept as tuned rather than
       snapped, for the same reason the percentages above are not tokens — this
       is the placement of one piece of artwork in one bespoke composition, not
       a spacing rhythm anything else can reuse. Snapping them to 96/48/96 is a
       visible nudge to something that was set by eye. */
    --nk-club-cburst-size: var(--nk-space-10);
    --nk-club-cburst-x: 92px;
    --nk-club-cburst-y: var(--nk-space-5);
    --nk-club-cstar-size: 28px;
    --nk-club-cstar-x: 50px;
    --nk-club-cstar-y: var(--nk-space-16);
    --nk-club-eyebrow-x: 100px;
    --nk-club-title-x: var(--nk-space-1);
    --nk-club-text-x: var(--nk-space-5);

    /* the panel */
    --nk-club-panel-min-h: calc(var(--nk-space-24) * 5);
    --nk-club-body-pad-block: var(--nk-space-8);
    --nk-club-body-pad-start: var(--nk-space-10);
    --nk-club-body-pad-end: var(--nk-space-12);
  }

  .nk-club__panel {
    display: grid;
    grid-template-columns: minmax(0, 55%) minmax(0, 45%);
    /* The panel is a band, not a hero. It was 6× and the copy floated in the
       middle of it with nothing to do; the artwork column sets the real floor. */
    min-block-size: var(--nk-club-panel-min-h);
    max-inline-size: none;
    border: 0;
    border-radius: var(--nk-radius-xl);
    box-shadow: var(--nk-shadow-lg);
  }

  .nk-club__visual {
    grid-column: 2;
    grid-row: 1;
    display: block;
    padding-block: 0;
    min-block-size: 100%;
    overflow: visible;
    background-color: transparent;
    border-radius: 0;
  }

  /* A full-height navy block anchored to the panel's outer edge, reaching about
     four fifths of the way across the artwork column, with its **inner edge an
     ellipse arc**. Three shapes were tried before it and each failure is worth
     keeping: a cropped oversized ellipse read as a curved-edge column, a circle
     contained inside the column turned the section into a card-on-a-dot, and a
     straight edge with a chamfered corner read as a folded sheet. What the
     composition is about is the ticket *leaving* a solid ground, so the ground
     stays solid and full-height and only the edge it is left across is shaped.

     The arc is two corner radii, not a `clip-path`: `border-radius` has logical
     longhands and a polygon does not. Both inline-start corners take a vertical
     radius of exactly 50% so the two arcs meet at mid-height with no straight
     segment between them — anything less and the "ellipse" has a flat middle.
     The panel's own `border-radius` + `overflow: hidden` round the two outer
     corners, so the block states nothing for them. */
  .nk-club__visual::before {
    content: "";
    position: absolute;
    z-index: var(--nk-z-base);
    inset-block: 0;
    inset-inline-end: 0;
    inset-inline-start: auto;
    inline-size: var(--nk-club-navy-width);
    background-color: var(--nk-surface-inverse);
    border-start-start-radius: var(--nk-club-navy-arc-x) var(--nk-club-navy-arc-y);
    border-end-start-radius: var(--nk-club-navy-arc-x) var(--nk-club-navy-arc-y);
    pointer-events: none;
  }

  .nk-club__halo,
  .nk-club__spark,
  .nk-club__art {
    display: none;
  }

  /* Started inside the navy block and reaching past its arc, so the ticket's
     inner end lands on the cream — it overhangs the artwork column itself,
     which is why `.nk-club__visual` is `overflow: visible` here. The copy
     column's own asymmetric padding is what keeps it clear of the text. */
  .nk-club__membership-scene {
    position: absolute;
    z-index: var(--nk-z-raised);
    position: absolute;
    inset-block-start: 50%;
    inset-inline-end: var(--nk-club-card-x);
    inset-inline-start: auto;
    display: block;
    inline-size: var(--nk-club-card-width);
    max-inline-size: none;
    aspect-ratio: 3 / 2;
    transform: translateY(calc(-50% + var(--nk-club-card-y)));
    pointer-events: none;
  }

  /* Boxed onto the card, not onto the column: the coral pair is pinned to the
     ticket's own corners, so every offset here is a share of the *card* and the
     pair travels with it when the card is resized. The one accent that belongs
     to the ground rather than to the card overrides the box back.

     It takes its own `--nk-club-decor-*` triple rather than reading the card's.
     They start equal, so the default behaviour is unchanged — but sharing one
     triple meant the card could not be nudged without dragging every accent
     along with it, and there was no way to say "move the ticket, leave the
     marks". Two sets that happen to match is the cheaper thing to undo. */
  .nk-club__desktop-decor {
    position: absolute;
    z-index: var(--nk-z-raised);
    inset-block-start: 50%;
    inset-inline-end: var(--nk-club-decor-x);
    inset-inline-start: auto;
    inline-size: var(--nk-club-decor-width);
    aspect-ratio: 3 / 2;
    display: block;
    transform: translateY(calc(-50% + var(--nk-club-decor-y)));
    pointer-events: none;
  }

  .nk-club__desktop-decor img,
  .nk-club__body-decor img {
    position: absolute;
    display: block;
    block-size: auto;
  }

  /* The coral pair marks the ticket's two outer corners — one each, never both
     at one end — and each is *centred on its corner point*, half on the card
     and half off. Guessing the offsets put both of them floating in open navy
     near a corner rather than on one, which reads as spilled rather than
     placed. The numbers come from the artwork's alpha channel instead: the
     ticket is rotated ~8° inside a 3:2 box, so its corners are at (2.3%, 19.5%)
     and (7.7%, 95.8%) of that box, **not** at its corners. Re-measure if
     `membership.webp` is ever rebuilt at a different rotation:

       ys, xs = np.nonzero(np.array(img)[:, :, 3] > 230)
       xs[np.argmax(-xs - ys)], ys[np.argmax(-xs - ys)]   # and the three siblings

     Percentages are shares of the card, and `block-size: auto` means each
     image's own ratio converts its width into the block-axis half it needs
     centring by. */
  .nk-club__desktop-decor .nk-club__accent-rays {
    inset-block-start: var(--nk-club-rays-y);
    inset-inline-end: var(--nk-club-rays-x);
    inline-size: var(--nk-club-rays-size);
    transform: rotate(-8deg);
  }

  .nk-club__desktop-decor .nk-club__accent-burst {
    inset-inline-end: var(--nk-club-burst-x);
    inset-block-end: var(--nk-club-burst-y);
    inline-size: var(--nk-club-burst-size);
    transform: rotate(-8deg);
  }

  /* Placed by *ground*, not by the card: the white clay heart disappears on
     cream, so it is pinned below the card onto the navy and takes its offsets
     from the column, not from the decor box. Re-check it whenever the navy
     block's width or its arc moves. */
  .nk-club__desktop-decor .nk-club__accent-heart {
    inset-block-start: auto;
    inset-block-end: var(--nk-club-heart-y);
    inset-inline-start: auto;
    inset-inline-end: var(--nk-club-heart-x);
    inline-size: var(--nk-club-heart-size);
    transform: rotate(-10deg);
  }

  /* Removed rather than re-placed. Losing the chamfer lost the one patch of
     cream inside this column, and the copy side already carries a navy star
     (`.nk-club__body-decor`) — two of the same mark, one of them homeless. */
  .nk-club__desktop-decor .nk-club__accent-star {
    display: none;
  }

  .nk-club__body {
    position: relative;
    grid-column: 1;
    grid-row: 1;
    align-items: flex-start;
    justify-content: center;
    gap: var(--nk-space-3);
    /* Asymmetric on purpose: the inline-end side is the one the ticket
       overhangs into, so it carries the clearance the other side does not
       need. Shrinking the card instead would undo the overhang. */
    padding-block: var(--nk-club-body-pad-block);
    padding-inline: var(--nk-club-body-pad-start) var(--nk-club-body-pad-end);
    text-align: start;
  }

  .nk-club__body-decor {
    position: absolute;
    z-index: var(--nk-z-base);
    inset: 0;
    display: block;
    overflow: hidden;
    border-start-end-radius: var(--nk-radius-xl);
    border-end-end-radius: var(--nk-radius-xl);
    pointer-events: none;
  }

  .nk-club__body > :not(.nk-club__body-decor) {
    position: relative;
    z-index: var(--nk-z-raised);
  }

  /* The copy side's own pair, above the eyebrow. Lengths rather than shares of
     the body: they hang off the panel's top corner, which does not move when
     the column gets wider, so a percentage would drift them across the copy. */
  .nk-club__body-decor .nk-club__accent-burst {
    inset-block-start: var(--nk-club-cburst-y);
    inset-inline-start: var(--nk-club-cburst-x);
    inline-size: var(--nk-club-cburst-size);
    transform: rotate(8deg);
  }

  .nk-club__body-decor .nk-club__accent-star {
    inset-block-start: var(--nk-club-cstar-y);
    inset-inline-start: var(--nk-club-cstar-x);
    inset-inline-end: auto;
    inline-size: var(--nk-club-cstar-size);
    transform: rotate(-8deg);
  }

  .nk-club__eyebrow {
    margin: 0;
    margin-inline-start: var(--nk-club-eyebrow-x);
    box-shadow: none;
  }

  .nk-club__eyebrow-mobile,
  .nk-club__title-mobile {
    display: none;
  }

  .nk-club__eyebrow-desktop,
  .nk-club__title-desktop {
    display: inline;
  }

  .nk-club__eyebrow-icon--mobile {
    display: none;
  }

  .nk-club__eyebrow-icon--desktop {
    display: block;
  }

  .nk-club__title {
    margin-inline-start: var(--nk-club-title-x);
    font-size: var(--nk-text-5xl);
  }

  .nk-club__text {
    max-inline-size: 48ch;
    margin-inline-start: var(--nk-club-text-x);
    font-size: var(--nk-text-lg);
  }

  .nk-club__help {
    justify-content: flex-start;
    margin-inline-start: var(--nk-space-4);
    font-size: var(--nk-text-sm);
  }

}

@media (min-width: 1280px) {
  .nk-club {
    --nk-club-body-pad-block: var(--nk-space-10);
    --nk-club-body-pad-start: var(--nk-space-12);
    --nk-club-body-pad-end: var(--nk-space-16);
  }
}
