/* «الأساس» base stylesheet — logical properties throughout so the same
   rules lay out correctly in RTL and LTR without a mirrored sheet. */

*, *::before, *::after { box-sizing: border-box; }

.asas-shell {
  /* Radios and checkboxes are the browser's to paint, and its default blue
     is the one colour on the page the theme did not choose. */
  accent-color: var(--asas-accent);
  background: var(--asas-bg);
  color: var(--asas-fg);
  font-family: var(--asas-font-body);
  /* The theme states its own leading rather than inheriting the platform's.
     It never did, so every line in the store sat on the 1.5 the storefront's
     global stylesheet sets for a Latin stack — and Arabic does not fit in it.
     At 16px that is a 24px line box for glyphs that measure 25: the ascenders
     of the Arabic-Indic digits came off flat, so every PRICE in the checkout
     summary read as cropped. Measured on baytna at 375px: `scrollHeight` 25
     against `clientHeight` 24 on every row, clearing at 1.6 and above.

     1.7, which is what جُرأة measured as the comfortable Arabic line and what
     Dawn's 1.8 is for Latin. Headings set their own 1.2 below and are
     unaffected. */
  line-height: 1.7;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.asas-main { flex: 1 0 auto; }

.asas-container {
  max-inline-size: var(--asas-page-width);
  margin-inline: auto;
  padding-inline: calc(var(--asas-space) * 1.25);
}

.asas-section { padding-block: calc(var(--asas-space) * 2.5); }
[data-asas-layout="compact"] .asas-section { padding-block: calc(var(--asas-space) * 1.5); }
[data-asas-layout="spacious"] .asas-section { padding-block: calc(var(--asas-space) * 4); }

h1, h2, h3, h4 {
  font-family: var(--asas-font-heading);
  line-height: 1.2;
  margin-block: 0 calc(var(--asas-space) * 0.75);
}
h1 { font-size: calc(2rem * var(--asas-heading-scale) / 100); }
h2 { font-size: calc(1.5rem * var(--asas-heading-scale) / 100); }
h3 { font-size: calc(1.15rem * var(--asas-heading-scale) / 100); }
p { margin-block: 0 var(--asas-space); }
img { max-inline-size: 100%; block-size: auto; }

a { color: inherit; }
:focus-visible { outline: 2px solid var(--asas-accent); outline-offset: 2px; }

.asas-skip {
  position: absolute;
  inset-inline-start: -9999px;
  background: var(--asas-bg);
  color: var(--asas-fg);
  padding: var(--asas-space);
  z-index: 100;
}
.asas-skip:focus { inset-inline-start: var(--asas-space); inset-block-start: var(--asas-space); }

/* Buttons ---------------------------------------------------------- */
.asas-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5ch;
  padding: 0.7em 1.4em;
  border: 1px solid transparent;
  border-radius: var(--asas-button-radius);
  background: var(--asas-accent);
  color: var(--asas-accent-contrast);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: opacity 120ms ease;
}
.asas-btn:hover { opacity: 0.9; }
.asas-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.asas-btn--outline { background: transparent; color: var(--asas-fg); border-color: var(--asas-border); }
.asas-btn--full { inline-size: 100%; }

/* Announcement ----------------------------------------------------- */
.asas-announcement {
  background: var(--asas-ann-bg, var(--asas-accent));
  color: var(--asas-ann-fg, var(--asas-accent-contrast));
  font-size: 0.875rem;
}
.asas-announcement__inner {
  display: flex; align-items: center; justify-content: center; gap: var(--asas-space);
  min-block-size: 2.5rem; padding-block: 0.4rem; text-align: center;
}
.asas-announcement__track { display: flex; gap: 3rem; white-space: nowrap; }
.asas-announcement[data-mode="ticker"] { overflow: hidden; }
.asas-announcement[data-mode="ticker"] .asas-announcement__track {
  animation: asas-ticker var(--asas-ticker-duration, 20s) linear infinite;
}
.asas-announcement[data-mode="ticker"]:hover .asas-announcement__track { animation-play-state: paused; }
@keyframes asas-ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
[dir="rtl"] .asas-announcement[data-mode="ticker"] .asas-announcement__track {
  animation-name: asas-ticker-rtl;
}
@keyframes asas-ticker-rtl { from { transform: translateX(0); } to { transform: translateX(50%); } }
@media (prefers-reduced-motion: reduce) {
  .asas-announcement[data-mode="ticker"] .asas-announcement__track { animation: none; }
}

/* Header ----------------------------------------------------------- */
/* The merchant's colours, when they set them; the theme's otherwise. */
.asas-header {
  border-block-end: 1px solid var(--asas-border);
  background: var(--asas-header-bg, var(--asas-bg));
  color: var(--asas-header-fg, inherit);
}
.asas-header[data-separator="false"] { border-block-end-color: transparent; }
.asas-header[data-sticky="true"] { position: sticky; inset-block-start: 0; z-index: 20; }

/*
 * Behaviour on scroll. The PLATFORM decides when each state applies — the same
 * rule in every store — and stamps the header; this is only what the states
 * look like here.
 */
.asas-header[data-o-sticky-header] { transition: transform 180ms ease, padding-block 180ms ease; }
.asas-header[data-o-header-hidden] { transform: translateY(-100%); }
.asas-header[data-o-sticky-header="shrink"][data-o-header-shrunk] .asas-header__inner {
  padding-block: calc(var(--asas-header-pt, 12px) * 0.5) calc(var(--asas-header-pb, 12px) * 0.5);
}
.asas-header[data-o-sticky-header="shrink"][data-o-header-shrunk] .asas-header__logo img {
  max-inline-size: calc(var(--asas-logo-w, 160px) * 0.75);
}
@media (prefers-reduced-motion: reduce) {
  .asas-header[data-o-sticky-header] { transition: none; }
}

/* The language switcher, in this theme's own vocabulary: a real form control
   in the same rounded capsule as every other control on the page. One control
   at any width, and the phone's native picker on a phone. */
.asas-lang { display: inline-flex; align-items: center; }
.asas-lang__select {
  appearance: none;
  min-block-size: 32px;
  padding-inline: 0.6rem 1.5rem;
  border: 1px solid color-mix(in srgb, var(--asas-fg) 14%, transparent);
  border-radius: var(--asas-button-radius);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.8rem;
  line-height: 1;
  cursor: pointer;
  /* The caret is drawn rather than fetched: an inline chevron on the
     trailing edge, which flips with the writing mode. */
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  background-position: right 0.6rem center, right calc(0.6rem + 4px) center;
}
:dir(rtl) .asas-lang__select {
  padding-inline: 1.5rem 0.6rem;
  background-position: left calc(0.6rem + 4px) center, left 0.6rem center;
}
.asas-lang__select:focus-visible { outline: 2px solid var(--asas-accent); outline-offset: 2px; }
.asas-lang__select option { color: CanvasText; background: Canvas; }
/* On a phone the control is in the MENU, not the row.

   A phone's header row is the logo and four 44px targets; the select is
   another 105px of a 335px line, and with it there the row measured 398px of
   content in a 375px viewport — every store on this theme scrolled sideways,
   on the theme's own defaults, because `available_languages` is the
   platform's six locales on every store there is. Dawn puts the same control
   in the menu rather than the row; the drawer opens from this same header, so
   it is no further away.

   The same markup renders in both places and exactly one is ever shown —
   including the `<noscript>` links, which are the whole control when the
   script is not running. */
@media (max-width: 47.99rem) {
  .asas-header__actions > .asas-lang,
  .asas-header__actions > noscript { display: none; }
}
/* `menu_style: drawer` keeps the drawer open to desktop widths, where the row
   is showing its own control — so this one goes rather than doubling it. */
@media (min-width: 48rem) {
  .asas-drawer__lang { display: none; }
}
.asas-drawer__lang {
  border-block-start: 1px solid var(--asas-border);
  margin-block-start: 0.5rem;
  padding-block-start: calc(var(--asas-space) * 0.75);
}
.asas-drawer__lang .asas-lang { display: flex; }
.asas-drawer__lang .asas-lang__select { inline-size: 100%; min-block-size: 2.75rem; }
/* Without JavaScript the select cannot navigate, so the plain link is what
   is shown instead — never both. */
.asas-lang__plain a { font-size: 0.8rem; font-weight: 600; text-decoration: underline; }

/* The basket as a word, when the merchant prefers words to glyphs. */
.asas-cart__word { font-size: 0.9rem; font-weight: 600; }
.asas-cart[data-cart-style="text"] { gap: 0.35rem; inline-size: auto; padding-inline: 0.5rem; }

/*
 * The menu as the merchant chose it: links in the row, one wide panel, or
 * nothing but the button. `drawer` keeps the hamburger at every width — the
 * row below already shows it under the breakpoint.
 */
/*
 * `drawer` keeps the hamburger and its panel at EVERY width — both are hidden
 * above the breakpoint by the rules further down, which is right when the row
 * of links is doing the work and wrong when the merchant asked for a menu
 * button instead.
 */
.asas-header[data-menu-style="drawer"] .asas-nav { display: none; }
.asas-header[data-menu-style="drawer"] .asas-drawer-details { display: block; }
.asas-header[data-menu-style="drawer"] .asas-drawer,
.asas-header[data-menu-style="drawer"] .asas-drawer-scrim { display: block; }
.asas-header[data-menu-style="meganav"] .asas-nav__sub {
  inset-inline: 0; inline-size: 100%;
  display: none; grid-template-columns: repeat(auto-fit, minmax(min(10rem, 100%), 1fr));
  gap: 0.25rem 1rem;
}
.asas-header[data-menu-style="meganav"] .asas-nav__item:hover > .asas-nav__sub,
.asas-header[data-menu-style="meganav"] .asas-nav__item:focus-within > .asas-nav__sub { display: grid; }
/* Below the breakpoint the nav is hidden, which leaves a three-column grid
   holding two children: the logo takes the first column and the controls
   auto-flow into the `1fr`, stranding an empty third column at the end. The
   row reads as pushed to one side with a hole beside it. A phone has two
   things in this row, so it gets a row; the grid starts where the nav does. */
.asas-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--asas-space);
  padding-block: var(--asas-header-pt, 12px) var(--asas-header-pb, 12px);
}
@media (min-width: 48rem) {
  .asas-header__inner {
    display: grid;
    grid-template-columns: auto 1fr auto;
  }
}
/* Dawn's four logo positions: two that share the row with the menu, and two
   that give the mark a row of its own above it. */
.asas-header[data-logo="middle-center"] .asas-header__inner { grid-template-columns: 1fr auto 1fr; }
@media (min-width: 48rem) {
  .asas-header[data-logo="top-left"] .asas-header__inner,
  .asas-header[data-logo="top-center"] .asas-header__inner {
    grid-template-columns: 1fr auto;
    grid-template-areas: "logo actions" "nav nav";
    row-gap: 0.5rem;
  }
  .asas-header[data-logo="top-center"] .asas-header__inner { justify-items: center; }
  .asas-header[data-logo="top-center"] .asas-header__logo { justify-self: center; grid-column: 1 / -1; }
  .asas-header[data-logo="top-center"] .asas-header__actions { justify-self: end; }
}
/* The wordmark is a link, so it takes the same 24px floor as every other
   control.

   It yields before the page does. `flex: none` plus the default `min-width:
   auto` made the mark the one thing in the row that could not give, so a
   120px logo — the theme's own mobile default — or a store name longer than
   the ~119px left beside four 44px controls pushed the whole page sideways
   instead. Shrinking a mark is a smaller loss than a storefront that scrolls
   horizontally, and the name below ellipsises rather than clipping mid-word. */
.asas-header__logo {
  align-items: center;
  display: inline-flex;
  flex: 0 1 auto;
  font-size: 1.15rem;
  font-weight: 700;
  min-block-size: 44px;
  min-inline-size: 0;
  text-decoration: none;
}
.asas-header__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The merchant sets the width; the height follows, capped so a tall logo
   cannot make the header a band. Two widths, because a logo sized for a desk
   takes half a phone's screen. */
.asas-header__logo img {
  /* Height-driven, not `auto` + a max. An SVG uploaded without width/height
     attributes has NO intrinsic size, and `block-size:auto;inline-size:auto`
     then resolves to 0x0 — the logo vanishes with no error anywhere. Merchants
     export sizeless SVGs constantly, so the theme gives it a height and lets
     the width follow. */
  block-size: 44px;
  inline-size: auto;
  max-block-size: 44px;
  /* Capped by the merchant's width AND by the box the row could spare, or a
     shrunken logo link would simply be overflowed by its own image. */
  max-inline-size: min(var(--asas-logo-w-m, 120px), 100%);
  object-fit: contain;
}
@media (min-width: 48rem) {
  .asas-header__logo img { max-inline-size: min(var(--asas-logo-w, 160px), 100%); }
}
.asas-nav { display: none; }
.asas-nav__list { display: flex; flex-wrap: wrap; gap: calc(var(--asas-space) * 1.25); list-style: none; margin: 0; padding: 0; }
.asas-nav__link { text-decoration: none; padding-block: 0.4rem; display: inline-block; }
.asas-nav__link[aria-current="page"] { border-block-end: 2px solid var(--asas-accent); }
.asas-nav__item { position: relative; }
.asas-nav__sub {
  position: absolute; inset-block-start: 100%; inset-inline-start: 0;
  background: var(--asas-bg); border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius); padding: var(--asas-space);
  list-style: none; margin: 0; min-inline-size: 12rem;
  display: none; z-index: 30;
}
.asas-nav__item:hover > .asas-nav__sub,
.asas-nav__item:focus-within > .asas-nav__sub { display: block; }
/*
 * The header row must be able to shrink. A flex item's `min-width` defaults to
 * `auto`, which refuses to go below the item's own content — so the search
 * field's 8rem floor plus the cart link and the menu button held this row at
 * 417px on a 375px phone and pushed the WHOLE PAGE sideways by 79px. Every
 * store on this theme scrolled horizontally on mobile.
 */
/* One row, always. It used to wrap, and on a phone that meant the search
   field on one line, the basket on the next and the menu on a third. */
.asas-header { position: relative; }

.asas-header__actions {
  display: flex; align-items: center; gap: 0.5rem;
  flex-wrap: nowrap; min-inline-size: 0;
}
/* Which item gives when the row is too narrow. Below the breakpoint the row
   holds nothing but 44px touch targets — none of them can shrink — so a row
   allowed to shrink just overflows its own box and takes the page with it:
   with `min-inline-size: 0` here, a long store name grew the logo to 212px
   and pushed the page 81px sideways while the controls spilled out of their
   box. The controls hold their size and the mark yields, which is the only
   pair of the two that has anywhere to go.

   Above the breakpoint the row also holds the search field, which is meant to
   flex — so the shrinkable row is right there and stays. */
@media (max-width: 47.99rem) {
  .asas-header__actions { flex: none; min-inline-size: auto; }
}
/* The field below the breakpoint, the link above it — never both.

   Scoped through the row rather than written bare: `.asas-icon-btn`, which the
   link also carries, sets `display: inline-flex` LATER in this file at equal
   specificity, and a media query adds none. So the desktop rule lost and both
   shipped — measured on a 1280px screen, a 234.6px search field with a
   redundant 44px magnifier sitting beside it. */
.asas-search { display: none; }
/* Revealed by the icon: the platform sets `data-o-search-open` on the root.
   The field drops out of the header as a band, the way the menu panel does —
   it does NOT take a line inside the row.

   It used to try: `flex-basis: 100%` and `order: 9` were written against
   `.asas-search`, which is not the row's flex item — `<o-search-form>` wraps
   it and is. So neither declaration ever applied. The host box took a line of
   its own, the four icons wrapped underneath it, and the logo — centred by
   `.asas-header__inner` against a block that was now 156px tall — came to
   rest below both. Measured on a 375px phone: 189px of header where 77px had
   been, with the field above the icons and the wordmark stranded under them.

   As a band the row is untouched, and the field is as wide as the header
   instead of as wide as whatever was left beside the logo (252px of 375). */
@media (max-width: 47.99rem) {
  [data-o-search-open] o-search-form[data-o-search-host] {
    background: var(--asas-header-bg, var(--asas-bg));
    border-block-end: 1px solid var(--asas-border);
    inset-block-start: 100%;
    inset-inline: 0;
    padding: calc(var(--asas-space) * 0.5) calc(var(--asas-space) * 1.25);
    position: absolute;
    z-index: 40;
  }
  [data-o-search-open] .asas-search { display: flex; max-inline-size: none; }
}
.asas-header__actions .asas-search-link { display: inline-flex; }
@media (min-width: 48rem) {
  .asas-header__actions { gap: 0.75rem; }
  .asas-search { display: flex; }
  .asas-header__actions .asas-search-link { display: none; }
}
.asas-search { gap: 0.25rem; flex: 1 1 10rem; min-inline-size: 0; max-inline-size: 22rem; }
.asas-search input {
  border: 1px solid var(--asas-border); border-radius: var(--asas-button-radius);
  padding: 0.5em 0.8em; font: inherit; background: var(--asas-bg); color: var(--asas-fg);
  inline-size: 100%; min-inline-size: 0;
}
/* Every chrome control is the same 44×44 target — the size a thumb needs
   (WCAG 2.5.5) and the size that keeps the row optically even. */
.asas-icon-btn {
  align-items: center;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--asas-button-radius);
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  justify-content: center;
  min-block-size: 2.75rem;
  min-inline-size: 2.75rem;
  padding: 0;
  position: relative;
  text-decoration: none;
}
.asas-icon-btn:hover { border-color: var(--asas-border); }
.asas-icon-btn::-webkit-details-marker { display: none; }
.asas-icon-btn::marker { content: ""; }
.asas-icon { display: block; }

.asas-cart__count {
  align-items: center;
  background: var(--asas-accent);
  border-radius: 999px;
  color: var(--asas-accent-fg);
  display: inline-flex;
  font-size: 0.6875rem;
  font-weight: 700;
  inset-block-start: 0.35rem;
  inset-inline-end: 0.3rem;
  justify-content: center;
  line-height: 1;
  min-inline-size: 1.05rem;
  padding: 0.15rem 0.25rem;
  position: absolute;
}
/* An empty basket needs no badge. */
.asas-cart { position: relative; }
.asas-cart__count[data-o-cart-empty="true"] { display: none; }

/* The panel drops out of the header rather than pushing it taller. */
.asas-drawer {
  background: var(--asas-bg);
  border-block: 1px solid var(--asas-border);
  inset-block-start: 100%;
  inset-inline: 0;
  padding-block: var(--asas-space);
  position: absolute;
  z-index: 30;
}
.asas-drawer-details > .asas-menu-toggle { list-style: none; }
.asas-drawer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
@media (min-width: 62rem) {
  /* The categories get their OWN row rather than a share of the middle column.
   Measured with the store's eight links: seven on one line at y=56 and two
   more at y=114.8, wrapping inside a column sized by what was left over
   between the logo and the controls. A row of its own is wide enough for all
   of them and reads as a deliberate band instead of an overflow.

   Not a sideways scroller: these items carry `.asas-nav__sub` dropdowns, and
   a scroll container clips its own absolutely-positioned descendants. */
.asas-nav { display: block; grid-column: 1 / -1; grid-row: 2; }
.asas-header__logo { grid-column: 1; grid-row: 1; }
.asas-header__actions { grid-column: 3; grid-row: 1; }
.asas-header[data-logo="middle-center"] .asas-header__logo { grid-column: 2; }
.asas-nav__list { justify-content: flex-start; }
  /* The whole disclosure goes, not only its parts: leaving the <details>
     behind left an empty box in the header at desktop widths. */
  .asas-drawer-details { display: none; }
}

/* Product grid ----------------------------------------------------- */
.asas-grid { display: grid; gap: calc(var(--asas-space) * 1.25); grid-template-columns: repeat(2, minmax(0, 1fr)); list-style: none; margin: 0; padding: 0; }
@media (min-width: 48rem) { .asas-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 62rem) { .asas-grid[data-columns="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 62rem) { .asas-grid[data-columns="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 62rem) { .asas-grid[data-columns="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.asas-card { position: relative; display: flex; flex-direction: column; gap: 0.5rem; min-inline-size: 0; }
/* The badge was printed BELOW the price, at the end of the card, where it
   read as another line of text. It belongs on the photograph, which is where
   a shopper scanning a grid is already looking. */
.asas-card > .asas-badge {
  position: absolute;
  inset-block-start: 0.6rem;
  inset-inline-start: 0.6rem;
  z-index: 1;
}
/* Something has to happen when the pointer lands on a card, or the grid reads
   as a printed page rather than a set of things that can be opened. */
.asas-card__media { transition: transform 200ms ease, box-shadow 200ms ease; }
.asas-card:hover .asas-card__media {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--asas-fg) 12%, transparent);
}
.asas-card:hover .asas-card__media img { transform: scale(1.03); }
.asas-card__media img { transition: transform 400ms ease; }
@media (prefers-reduced-motion: reduce) {
  .asas-card__media, .asas-card__media img { transition: none; }
  .asas-card:hover .asas-card__media { transform: none; }
  .asas-card:hover .asas-card__media img { transform: none; }
}
.asas-card__media {
  display: block; border-radius: var(--asas-radius); overflow: hidden;
  background: color-mix(in srgb, var(--asas-border) 40%, transparent);
}
.asas-card__media img { inline-size: 100%; display: block; object-fit: cover; }
.asas-card__media[data-ratio="square"] img { aspect-ratio: 1 / 1; }
.asas-card__media[data-ratio="portrait"] img { aspect-ratio: 3 / 4; }
/* 24px is the floor a thumb needs (WCAG 2.5.8 AA). Every standalone link in
   this theme — card titles, footer columns, the drawer, the collection list —
   gets it from its line box, so nothing moves on the page. */
.asas-card__title { font-weight: 600; text-decoration: none; font-size: 0.98rem; display: inline-block; min-block-size: 24px; }
.asas-card__meta { color: var(--asas-muted); font-size: 0.85rem; }
.asas-price { display: flex; gap: 0.5ch; align-items: baseline; flex-wrap: wrap; }
.asas-price__compare { text-decoration: line-through; color: var(--asas-muted); font-size: 0.9em; }
.asas-price__current { font-weight: 700; }
.asas-price--on-sale .asas-price__current { color: var(--asas-sale); }
.asas-badge {
  display: inline-block; background: var(--asas-sale); color: #fff;
  border-radius: 999px; padding: 0.15em 0.6em; font-size: 0.75rem; font-weight: 700;
}
.asas-badge--muted { background: var(--asas-muted); }

/* Collection toolbar + filters ------------------------------------- */
.asas-toolbar {
  display: flex; flex-wrap: wrap; gap: var(--asas-space);
  align-items: end; justify-content: space-between;
  padding-block-end: var(--asas-space);
  border-block-end: 1px solid var(--asas-border);
  margin-block-end: calc(var(--asas-space) * 1.5);
}
.asas-field { display: grid; gap: 0.25rem; font-size: 0.9rem; }
.asas-field select, .asas-field input {
  border: 1px solid var(--asas-border); border-radius: var(--asas-button-radius);
  padding: 0.45em 0.7em; font: inherit; background: var(--asas-bg); color: var(--asas-fg);
}
.asas-filters { display: flex; flex-wrap: wrap; gap: var(--asas-space); align-items: end; }
.asas-checkbox { display: inline-flex; gap: 0.4ch; align-items: center; }

/* «الأساس» filters the way it does everything else: in pills. The controls
   were browser defaults — the one place in the theme where nothing was
   decided — and they read identically to every other theme's. Price is one
   rounded shell holding both numbers, stock is a pill that fills when it is
   on, and the sort carries the theme's own chevron. */
.asas-filters__prices {
  display: flex;
  align-items: stretch;
  gap: 0;
  border: 1px solid var(--asas-border);
  border-radius: 999px;
  background: var(--asas-bg);
  padding-inline: 0.35rem;
}
.asas-filters__prices .asas-field,
.asas-filters .asas-field:has(select) {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0;
}
.asas-filters__prices .asas-field > span,
.asas-filters .asas-field:has(select) > span {
  font-size: 0.75rem;
  color: var(--asas-muted);
  padding-inline: 0.75rem 0.25rem;
  white-space: nowrap;
}
.asas-filters .asas-field:has(select) {
  border: 1px solid var(--asas-border);
  border-radius: 999px;
  background: var(--asas-bg);
}
.asas-filters .asas-field:has(select:focus-visible) { outline: 2px solid var(--asas-accent); outline-offset: 2px; }
.asas-filters select[name="sort_by"]:focus-visible { outline: none; }
.asas-filters__prices input {
  border: 0;
  border-radius: 0;
  background: transparent;
  inline-size: 5.5rem;
  min-block-size: 2.6rem;
  padding-inline: 0.25rem 0.75rem;
}
.asas-filters__prices input:focus-visible { outline: 2px solid var(--asas-accent); outline-offset: -2px; border-radius: 999px; }
.asas-filters__prices .asas-field + .asas-field { border-inline-start: 1px solid var(--asas-border); }

/* The stock filter is a pill the shopper switches on, not a checkbox with a
   caption beside it. The input stays exactly where the platform reads it. */
.asas-filters .asas-checkbox {
  gap: 0.55rem;
  border: 1px solid var(--asas-border);
  border-radius: 999px;
  padding-inline: 0.75rem 1rem;
  min-block-size: 2.75rem;
  cursor: pointer;
  user-select: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.asas-filters .asas-checkbox input {
  appearance: none;
  margin: 0;
  inline-size: 1.1rem;
  block-size: 1.1rem;
  border: 2px solid currentColor;
  border-radius: 999px;
  flex: none;
  display: grid;
  place-content: center;
}
.asas-filters .asas-checkbox input::after {
  content: "";
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: 999px;
  background: currentColor;
  transform: scale(0);
  transition: transform 0.15s ease;
}
.asas-filters .asas-checkbox input:checked::after { transform: scale(1); }
.asas-filters .asas-checkbox:has(input:checked) {
  background: var(--asas-accent);
  border-color: transparent;
  color: var(--asas-accent-contrast);
}
.asas-filters .asas-checkbox:has(input:focus-visible) { outline: 2px solid var(--asas-accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .asas-filters .asas-checkbox,
  .asas-filters .asas-checkbox input::after { transition: none; }
}

/* The sort keeps the pill geometry. Its chevron is an element placed with
   `inset-inline-end` rather than a background image, because
   `background-position` has no logical form and would point at the wrong
   edge in RTL. */
.asas-select-shell {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.asas-select-shell__arrow {
  position: absolute;
  inset-inline-end: 0.85rem;
  pointer-events: none;
  line-height: 0;
  color: var(--asas-muted);
}
.asas-filters select[name="sort_by"] {
  appearance: none;
  border: 0;
  background: transparent;
  border-radius: 999px;
  min-block-size: 2.65rem;
  padding-inline: 0.25rem 2.5rem;
}
.asas-filters .asas-btn { border-radius: 999px; min-block-size: 2.75rem; }
@media (max-width: 40rem) {
  .asas-filters { inline-size: 100%; }
  .asas-filters__prices { inline-size: 100%; }
  .asas-filters__prices input { inline-size: 100%; }
  .asas-filters select[name="sort_by"] { flex: 1 1 10rem; }
}

/* Pagination ------------------------------------------------------- */
.asas-pagination { display: flex; gap: 0.4rem; justify-content: center; list-style: none; padding: 0; margin-block-start: calc(var(--asas-space) * 2); flex-wrap: wrap; }
.asas-pagination a, .asas-pagination span {
  display: inline-block; min-inline-size: 2.25rem; text-align: center;
  padding: 0.4em 0.6em; border: 1px solid var(--asas-border);
  border-radius: var(--asas-button-radius); text-decoration: none;
}
.asas-pagination [aria-current="page"] { background: var(--asas-accent); color: var(--asas-accent-contrast); border-color: var(--asas-accent); }

/* Product page ----------------------------------------------------- */
.asas-product { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--asas-space) * 2); }
@media (min-width: 48rem) { .asas-product { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: start; } }
.asas-gallery { display: grid; gap: var(--asas-space); }
.asas-gallery[data-ratio="square"] { --asas-plate: 1 / 1; }
.asas-gallery[data-ratio="portrait"] { --asas-plate: 3 / 4; }
.asas-gallery[data-ratio="natural"] { --asas-plate: auto; }
/* A product photo is not a page: uncapped it grew to the full column and a
   shopper scrolled a screen of one picture before reaching the price. It fits
   inside the fold, whole — `contain`, so nothing is cropped.

   Square, to Shopify's own 2048×2048 recommendation, so this theme's plates
   agree with the other three and with the cards on the collection page. */
/* The stage: every photograph side by side, snapping. A swipe moves it, and
   so does a thumb — the thumbs are anchors to the slides, so the gallery
   works with no JavaScript and with the keyboard. */
.asas-gallery__stage {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  max-inline-size: min(100%, 34rem);
  border-radius: var(--asas-radius);
  scrollbar-width: none;
}
.asas-gallery__stage::-webkit-scrollbar { display: none; }
.asas-gallery__stage:focus-visible { outline: 2px solid var(--asas-accent); outline-offset: 3px; }
.asas-gallery__slide {
  scroll-snap-align: center;
  /* The crop the cards use, so a merchant who chose portrait does not get a
     square plate above a grid of portrait cards. Square is the fallback. */
  aspect-ratio: var(--asas-plate, 1 / 1);
  background: color-mix(in srgb, var(--asas-border) 25%, transparent);
  border-radius: var(--asas-radius);
}
.asas-gallery__slide img {
  inline-size: 100%;
  block-size: 100%;
  /* A product photo is not a page: `contain` so nothing is cropped. */
  object-fit: contain;
  display: block;
}
.asas-gallery__thumbs { display: flex; gap: 0.5rem; flex-wrap: wrap; list-style: none; padding: 0; margin: 0; }
.asas-gallery__thumb {
  display: block;
  border-radius: calc(var(--asas-radius) / 1.5);
  /* A 72px plate is under the 44px floor only in one axis; the target itself
     is 72×72, so it already clears it. */
}
.asas-gallery__thumb img {
  inline-size: 72px; block-size: 72px; object-fit: cover;
  border-radius: calc(var(--asas-radius) / 1.5);
  border: 1px solid var(--asas-border);
  display: block;
}
.asas-gallery__thumb:hover img,
.asas-gallery__thumb:focus-visible img { border-color: var(--asas-accent); }
@media (prefers-reduced-motion: reduce) {
  .asas-gallery__stage { scroll-behavior: auto; }
}
/* 6.4px between a variant's name and the 40px chips under it — the label read
   as belonging to nothing in particular. */
/* The name of the option and the values under it were 12px apart, the same
   step this theme uses between lines of text — so «اللون» read as a caption
   on the chips instead of a question above them. And one group ran into the
   next at a single space. */
.asas-option {
  display: grid;
  gap: calc(var(--asas-space) * 0.75);
  margin-block-end: calc(var(--asas-space) * 1.75);
}
/* A `<legend>` is the fieldset's CAPTION, not a child in its formatting
   context, so `gap` never reaches it: the option's name sat hard against its
   own values at 0px while the grid claimed a 12px row gap. The space has to
   be a margin on the legend itself — which is how nabd and waqar already do
   it. */
.asas-option > legend,
.asas-option__label {
  font-weight: 600;
  padding: 0;
  margin-block-end: calc(var(--asas-space) * 0.6);
}
.asas-option__values { display: flex; gap: calc(var(--asas-space) * 0.75); flex-wrap: wrap; }
.asas-option__value input { position: absolute; opacity: 0; pointer-events: none; }
.asas-option__value span {
  display: inline-block; border: 1px solid var(--asas-border);
  border-radius: var(--asas-button-radius); padding: 0.4em 0.9em; cursor: pointer;
}
.asas-option__value input:checked + span { border-color: var(--asas-accent); box-shadow: inset 0 0 0 1px var(--asas-accent); }
/* A colour swatch carries the value as its background, so an INSET ring
   paints over the very thing being chosen. Outside it goes. */
.asas-option__value input:checked + .asas-swatch {
  box-shadow: 0 0 0 2px var(--asas-bg, #fff), 0 0 0 4px var(--asas-accent);
}
.asas-option__value input:focus-visible + span { outline: 2px solid var(--asas-accent); outline-offset: 2px; }
.asas-swatch { inline-size: 2rem; block-size: 2rem; border-radius: 999px; padding: 0 !important; }
/* Asas is the plainest of the four and its stepper stays plain: two round keys
   with the numeral floating between them and no shell at all — the same soft
   geometry as its swatches, which are the only other circles in the theme. */
.asas-qty { display: grid; gap: 0.35rem; justify-items: start; margin-block-end: var(--asas-space); }
.asas-qty__label { font-size: 0.9rem; color: var(--asas-muted); }
.asas-stepper { display: inline-flex; align-items: center; gap: 0.35rem; }
.asas-stepper__key {
  display: grid; place-items: center;
  inline-size: 2.5rem; block-size: 2.5rem; padding: 0;
  border: 1px solid var(--asas-border); border-radius: 999px;
  background: var(--asas-bg); color: var(--asas-fg); cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
}
.asas-stepper__key:hover:not(:disabled) {
  background: var(--asas-accent); border-color: var(--asas-accent); color: #fff;
}
.asas-stepper__key:disabled { opacity: 0.35; cursor: default; }
.asas-stepper__value {
  inline-size: 3.25rem; min-block-size: 2.5rem;
  border: 0; background: none; color: var(--asas-fg);
  font: inherit; font-weight: 600; text-align: center;
  font-variant-numeric: tabular-nums;
}
.asas-stepper__value::-webkit-outer-spin-button,
.asas-stepper__value::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.asas-stepper__value { -moz-appearance: textfield; appearance: textfield; }
@media (prefers-reduced-motion: reduce) {
  .asas-stepper__key { transition: none; }
}
[data-o-product-form][data-o-available="false"] .asas-instock { display: none; }
[data-o-product-form][data-o-available="true"] .asas-soldout { display: none; }

/* Editorial sections ----------------------------------------------- */
/* A merchant who has not chosen a photograph yet got 1160x460 of flat grey —
   measured on this store — which reads as a page that failed to load rather
   than a store that has not finished setting up. The empty case is COMPOSED:
   the theme's own accent, at low strength, laid over a fine diagonal rule.
   The moment an image is set, `.asas-hero__media` covers all of it. */
.asas-hero {
  position: relative;
  display: grid;
  align-items: center;
  min-block-size: var(--asas-hero-height, 420px);
  border-radius: var(--asas-radius);
  overflow: hidden;
  background-color: color-mix(in srgb, var(--asas-accent) 7%, var(--asas-bg));
  background-image:
    radial-gradient(120% 90% at 85% 10%,
      color-mix(in srgb, var(--asas-accent) 16%, transparent) 0%, transparent 60%),
    repeating-linear-gradient(135deg,
      color-mix(in srgb, var(--asas-accent) 6%, transparent) 0 1px,
      transparent 1px 14px);
}
/* With a photograph in it the ground is never seen, and a pattern behind a
   transparent PNG would show through it. */
.asas-hero:has(.asas-hero__media) { background-image: none; }
.asas-hero__media { position: absolute; inset: 0; }
.asas-hero__media img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.asas-hero__content { position: relative; padding: calc(var(--asas-space) * 2); max-inline-size: 34rem; }
.asas-hero[data-align="center"] { justify-items: center; text-align: center; }
.asas-hero[data-align="end"] { justify-items: end; text-align: end; }
/* The clip fills the media box the way the still does. The still sits on top
   and is hidden, so it is what shows if the video never plays — a codec the
   browser refuses, a file that 404s, or a visitor who asked for less motion. */
.asas-hero__video { position: absolute; inset: 0; inline-size: 100%; block-size: 100%;
  object-fit: cover; }
.asas-hero__still { position: absolute; inset: 0; inline-size: 100%; block-size: 100%;
  object-fit: cover; opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .asas-hero__video { display: none; }
  .asas-hero__still { opacity: 1; }
}
.asas-hero__overlay { position: absolute; inset: 0; background: rgba(0,0,0,var(--asas-hero-overlay, 0.25)); }
/* The eyebrow is `.asas-card__meta`, which paints itself `--asas-muted` — a
   token picked for a product card on the store's own background. Over a hero
   it overrode the colour the section was told to use, so a merchant who set
   light text for a dark overlay still got clay grey, at 2:1 against the
   photograph. Here it takes the hero's colour and steps back with opacity,
   which reads on a dark overlay and a light one alike. */
.asas-hero__content .asas-card__meta { color: inherit; opacity: 0.82; }

.asas-media-text { display: grid; gap: calc(var(--asas-space) * 1.5); align-items: center; }
@media (min-width: 48rem) { .asas-media-text { grid-template-columns: 1fr 1fr; } }
/* Until the merchant adds a picture there is nothing to put beside the text,
   and a blank half column reads as a section that failed rather than one
   waiting. The plate carries a soft ground so the slot is legible in the
   editor, and the layout goes to one column so the page never shows a void. */
.asas-media-text__media:empty { display: none; }
@media (min-width: 48rem) {
  .asas-media-text:has(.asas-media-text__media:empty) { grid-template-columns: 1fr; }
}
.asas-media-text[data-media="end"] .asas-media-text__media { order: 2; }
.asas-media-text__media img { inline-size: 100%; border-radius: var(--asas-radius); display: block; }
/* An image-grid tile with no picture yet: a plate rather than a collapsed
   nothing, so the shipped section reads as four slots to fill. */
.asas-card__media:empty {
  display: block;
  aspect-ratio: 1 / 1;
  background: color-mix(in srgb, var(--asas-border) 30%, transparent);
  border-radius: var(--asas-radius);
}

.asas-quotes { display: grid; gap: var(--asas-space); }
@media (min-width: 48rem) { .asas-quotes { grid-template-columns: repeat(3, minmax(0,1fr)); } }
/* A review was a bordered box with the quote in body copy and the name under
   it in grey — three identical rectangles that said «text» before they said
   «somebody bought this and came back to say so». The quote is now set at
   reading size against a mark, the rating is drawn as stars rather than
   printed as «★ 5/5», and the name sits on a rule beneath it. */
.asas-quote {
  position: relative;
  display: grid;
  gap: 0.75rem;
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  padding: calc(var(--asas-space) * 1.5) calc(var(--asas-space) * 1.25) calc(var(--asas-space) * 1.25);
  background: var(--asas-bg);
}
/* The quotation mark is decoration, so it is drawn and hidden from the tree. */
.asas-quote::before {
  content: "”";
  position: absolute;
  inset-block-start: -0.15em;
  inset-inline-start: calc(var(--asas-space) * 1.1);
  font-size: 3.4rem;
  line-height: 1;
  color: color-mix(in srgb, var(--asas-accent) 26%, transparent);
  pointer-events: none;
}
.asas-quote blockquote {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.65;
}
.asas-quote__author {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  color: var(--asas-muted);
  font-size: 0.9rem;
  padding-block-start: 0.75rem;
  border-block-start: 1px solid var(--asas-border);
}
.asas-quote__stars { color: var(--asas-accent); letter-spacing: 0.08em; white-space: nowrap; }
/* The browser's own blockquote carries 40px of margin on each side. Inside a
   three-column card at 768px that left the quotation a 25-pixel column and cut
   the words. The card provides the inset; the quote provides none. */
.asas-quote blockquote { margin: 0 0 0.5rem; }
.asas-quote__author { color: var(--asas-muted); font-size: 0.9rem; }

.asas-faq { display: grid; gap: 0.5rem; max-inline-size: 46rem; margin-inline: auto; }
/* The Q&A was small type in small boxes — a section a shopper scrolled past.
   The question is the size of a question now, the marker is a drawn sign that
   turns when the answer opens, and the whole row is the target. */
.asas-faq { gap: 0.6rem; }
.asas-faq details {
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  padding: calc(var(--asas-space) * 0.9) var(--asas-space);
  background: var(--asas-bg);
  transition: border-color 160ms ease;
}
.asas-faq details[open] { border-color: color-mix(in srgb, var(--asas-accent) 45%, var(--asas-border)); }
.asas-faq summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1.5;
  min-block-size: 2.75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
}
.asas-faq summary::-webkit-details-marker { display: none; }
/* A plus that becomes a minus — drawn, so it needs no glyph and no string. */
.asas-faq summary::after {
  content: "";
  flex: none;
  inline-size: 0.75rem;
  block-size: 0.75rem;
  background:
    linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat,
    linear-gradient(currentColor, currentColor) center / 2px 100% no-repeat;
  transition: transform 200ms ease, opacity 200ms ease;
  color: var(--asas-accent);
}
.asas-faq details[open] summary::after {
  background: linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat;
  transform: rotate(180deg);
}
.asas-faq .asas-rte { padding-block-start: 0.6rem; color: var(--asas-muted); }
@media (prefers-reduced-motion: reduce) {
  .asas-faq details, .asas-faq summary::after { transition: none; }
}

.asas-newsletter { text-align: center; max-inline-size: 34rem; margin-inline: auto; }
.asas-newsletter form { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }
.asas-newsletter input { flex: 1 1 14rem; border: 1px solid var(--asas-border); border-radius: var(--asas-button-radius); padding: 0.6em 0.9em; font: inherit; }

.asas-form { display: grid; gap: var(--asas-space); max-inline-size: 34rem; }
.asas-form label { display: grid; gap: 0.3rem; font-size: 0.9rem; }
.asas-form input, .asas-form textarea {
  border: 1px solid var(--asas-border); border-radius: var(--asas-button-radius);
  padding: 0.6em 0.9em; font: inherit; background: var(--asas-bg); color: var(--asas-fg);
}

/* `overflow-wrap: break-word` breaks a long token onto the next LINE but, by
   spec (CSS Text 3 §5.5), it does not change the element's min-content size —
   only `anywhere` does. A spaceless URL in a product description therefore kept
   a 355.7px minimum, an `auto` grid track grew to fit it, and the whole buy
   column was pushed to left:-52.9 on a 375px screen with the shell clipping it:
   the price, the buttons and the description were all sliced off. Measured on
   /ar/product/gate-long-content. */
.asas-rte { overflow-wrap: anywhere; }
.asas-rte h2, .asas-rte h3 { margin-block-start: calc(var(--asas-space) * 1.5); }
.asas-rte img { border-radius: var(--asas-radius); }

/* Footer ----------------------------------------------------------- */
/* The footer was a hairline and four naked columns of links — structurally
   fine and visually nothing, so the page just stopped. A ground of its own
   separates it from the last section, the column headings are set apart from
   the links beneath them, and a link answers the pointer. */
.asas-footer {
  border-block-start: 1px solid var(--asas-border);
  margin-block-start: calc(var(--asas-space) * 3);
  background: color-mix(in srgb, var(--asas-border) 16%, transparent);
}
.asas-footer h3 {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asas-fg);
  margin-block: 0 0.85rem;
}
.asas-footer__list a:hover { color: var(--asas-fg); text-decoration: underline; text-underline-offset: 3px; }
.asas-footer .asas-rte { color: var(--asas-muted); font-size: 0.9rem; }
.asas-footer__cols { display: grid; gap: calc(var(--asas-space) * 1.5); padding-block: calc(var(--asas-space) * 2); }
@media (min-width: 48rem) { .asas-footer__cols { grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr)); } }
.asas-footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.asas-footer__list a,
.asas-drawer__list a,
.asas-list a { display: inline-block; min-block-size: 24px; }
.asas-footer__list a { text-decoration: none; color: var(--asas-muted); }
.asas-footer__bottom { border-block-start: 1px solid var(--asas-border); padding-block: var(--asas-space); color: var(--asas-muted); font-size: 0.85rem; text-align: center; }

.asas-empty { text-align: center; padding-block: calc(var(--asas-space) * 3); color: var(--asas-muted); }
.asas-visually-hidden {
  position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Form status: the platform sets data-o-state on the form; only the matching
   message is shown, and nothing at all before a submit. */
.asas-form-status span { display: none; }
.asas-form-status span[data-state="error"] { color: var(--asas-sale); }
[data-o-state="sent"] .asas-form-status span[data-state="sent"],
[data-o-form][data-o-state="sent"] ~ .asas-form-status span[data-state="sent"] { display: inline; }
[data-o-state="error"] .asas-form-status span[data-state="error"],
[data-o-form][data-o-state="error"] ~ .asas-form-status span[data-state="error"] { display: inline; }
[data-o-state="sending"] button[type="submit"] { opacity: 0.6; pointer-events: none; }

/* ------------------------------------------------------------- cart lines */
.asas-lines { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; }
.asas-line {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: 0.85rem;
  padding: 0.9rem 0;
  border-top: 1px solid var(--asas-border);
}
.asas-line:last-child { border-bottom: 1px solid var(--asas-border); }
.asas-line__media img { inline-size: 100%; block-size: auto; border-radius: var(--asas-radius); }
.asas-line__body { display: grid; gap: 0.2rem; align-content: start; }
.asas-line__title { font-weight: 600; text-decoration: none; color: inherit; }
.asas-line__title:hover { text-decoration: underline; }
.asas-line__side {
  grid-column: 2;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem 0.9rem;
}
.asas-step { display: inline-flex; align-items: center; border: 1px solid var(--asas-border); border-radius: var(--asas-radius); }
.asas-step__btn {
  min-inline-size: 44px; min-block-size: 44px;
  background: none; border: 0; color: inherit; cursor: pointer; font: inherit;
}
.asas-step__btn:hover { background: var(--asas-bg); }
.asas-step__value { min-inline-size: 2.5ch; text-align: center; font-variant-numeric: tabular-nums; }
.asas-line__remove {
  margin-inline-start: auto;
  background: none; border: 0; padding: 0;
  color: var(--asas-muted); cursor: pointer; font: inherit;
  min-block-size: 44px; text-decoration: underline;
}
.asas-line__remove:hover { color: var(--asas-fg); }

/* The rows come from the server once the browser has reported the basket, so
 * until they arrive the list reserves their height from `--o-cart-lines` — the
 * count the platform publishes as soon as it reads the basket. Without it the
 * summary below is pushed down the moment the rows land. */
.asas-lines:empty { min-block-size: calc(var(--o-cart-lines, 0) * 6.5rem); }

/* The drawer's version of the same row: a narrower plate and tighter rhythm,
   because the panel is 24rem wide rather than a page column. Everything else
   — the stepper, the remove, the offer notes — is the row the cart page uses,
   so the two never drift. */
.asas-lines--compact { margin-block-start: 0; max-block-size: 46vh; overflow-y: auto; }
.asas-line--compact { grid-template-columns: 3.5rem minmax(0, 1fr); gap: 0.7rem; padding: 0.7rem 0; }
.asas-line--compact .asas-line__title { font-size: 0.95rem; }
.asas-line--compact .asas-line__side { gap: 0.5rem; flex-wrap: wrap; }
.asas-line--compact .asas-line__remove { font-size: 0.8rem; }
.asas-drawer-cart__filled { display: grid; gap: 0.75rem; align-content: start; }

/* --------------------------------------------------------- offers + inputs */
/* ── The quantity ladder: BUNDLE CARDS ─────────────────────────────────────
   The pattern a shopper has met on every bundle picker: a card per rung, a
   check on the leading edge, the price and the saving ranged to the other,
   and the merchant's own qualifier as a ribbon. This theme's idea is that a
   shopper recognises it — the other three invent, this one does not. */
.asas-offers { list-style: none; margin: 0.75rem 0; padding: 0; display: grid; gap: 0.6rem; }
.asas-offer {
  position: relative;
  inline-size: 100%;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
  text-align: start;
  padding: 0.85rem 0.9rem;
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
/* The check: a ring until it is chosen, then filled with its own tick. */
.asas-offer__check {
  inline-size: 1.25rem;
  block-size: 1.25rem;
  border: 2px solid var(--asas-border);
  border-radius: 999px;
  display: grid;
  place-items: center;
}
.asas-offer__check::after {
  content: "";
  inline-size: 0.6rem;
  block-size: 0.32rem;
  border-inline-start: 2px solid var(--asas-bg, #fff);
  border-block-end: 2px solid var(--asas-bg, #fff);
  transform: rotate(-45deg) translate(1px, -1px);
  opacity: 0;
}
.asas-offer__body { display: grid; gap: 0.15rem; min-inline-size: 0; }
.asas-offer__name { font-weight: 600; }
.asas-offer__meta { font-size: 0.85rem; color: var(--asas-muted, inherit); opacity: 0.75; }
.asas-offer__note { font-size: 0.85rem; opacity: 0.65; }
.asas-offer__right { display: grid; justify-items: end; gap: 0.2rem; text-align: end; }
.asas-offer__price { font-weight: 700; white-space: nowrap; }
/* The saving, as the rounded pill this theme uses everywhere else. */
.asas-offer__save {
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.15em 0.6em;
  border-radius: 999px;
  background: color-mix(in srgb, var(--asas-accent) 14%, transparent);
  color: var(--asas-accent);
  white-space: nowrap;
}
/* The merchant's «الأكثر طلبًا», ribboned over the card's edge. */
.asas-offer__ribbon {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0.9rem;
  transform: translateY(-50%);
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.15em 0.6em;
  border-radius: 999px;
  background: var(--asas-accent);
  color: #fff;
}

.asas-offer:hover { border-color: var(--asas-accent); }
.asas-offer[data-o-selected="true"] {
  border-color: var(--asas-accent);
  box-shadow: 0 0 0 1px var(--asas-accent);
  background: color-mix(in srgb, var(--asas-accent) 6%, transparent);
}
.asas-offer[data-o-selected="true"] .asas-offer__check {
  background: var(--asas-accent);
  border-color: var(--asas-accent);
}
.asas-offer[data-o-selected="true"] .asas-offer__check::after { opacity: 1; }
.asas-customs { display: grid; gap: 0.6rem; margin-block: 0.75rem; }
.asas-custom { display: grid; gap: 0.25rem; }
.asas-custom input { padding: 0.55rem 0.7rem; border: 1px solid var(--asas-border); border-radius: var(--asas-radius); }
.asas-customs [data-o-invalid="true"] { border-color: var(--asas-sale); }
.asas-customs__error { display: none; margin: 0; color: var(--asas-sale); font-size: 0.85rem; }
[data-o-invalid="true"] .asas-customs__error { display: block; }

/* Buyer reviews, page width — the buy column is too narrow for prose. */
.asas-reviews {
  display: grid;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}

.asas-reviews__summary { margin: 0 0 1rem; color: var(--asas-muted); }

.asas-review {
  border-block-start: 1px solid var(--asas-border);
  display: grid;
  gap: 0.25rem;
  padding-block: 1rem;
}

.asas-review:last-child { border-block-end: 1px solid var(--asas-border); }
.asas-review p { margin: 0; }
.asas-review__stars { color: var(--asas-accent); letter-spacing: 0.08em; }
.asas-review__title { font-weight: 600; }
.asas-review__by { color: var(--asas-muted); font-size: 0.875rem; }

@media (min-width: 60rem) {
  .asas-reviews { grid-template-columns: 1fr 1fr; column-gap: 2rem; }
  .asas-reviews .asas-review:nth-last-child(2):nth-child(even) {
    border-block-end: 1px solid var(--asas-border);
  }
}

/* The merchant's offer clock: `dir="ltr"` on the clock keeps its fields in
   time order under RTL, and tabular figures stop the width jumping. */
.asas-countdown {
  align-items: baseline;
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  display: flex;
  gap: 0.5rem;
  justify-content: space-between;
  margin-block: 0.75rem;
  padding: 0.5rem 0.75rem;
}

.asas-countdown__clock {
  font-feature-settings: "tnum" 1;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* ------------------------------------------------------------------ */
/* The theme's own checkout form (Phase 29D)                           */
/* ------------------------------------------------------------------ */

.asas-checkout-form { display: grid; gap: var(--asas-space); }
.asas-checkout-form[hidden] { display: none; }
.asas-checkout-form[data-compact="true"] { gap: 1rem; }

/* The details block is the one that goes on and on: every field the full
   width of the column and stacked, which is what made the checkout read as
   enormous — measured 574.4px per field over 1938.8px of body. Two columns
   where there is room, and only what genuinely needs the width spans both.

   `auto-fit` rather than a fixed count, because the field list is the
   MERCHANT's: a store with three fields must not get a hole where the fourth
   would have been, and one with twelve must not get twelve rows. */
.asas-checkout-block {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: 0.8rem calc(var(--asas-space) * 2.5);
  align-items: start;
}
.asas-checkout-block > h2 { grid-column: 1 / -1; }
/* These four are the block's own full-width parts, not fields: they span
   every column rather than sitting in one. They must NOT share the
   `display: none` below — chained onto it they hid the payment picker,
   the coupon, the order lines and the totals outright. */
.asas-checkout-block > .asas-pay,
.asas-checkout-block > .asas-coupon,
.asas-checkout-block > .asas-total,
.asas-checkout-block > .asas-colines,
.asas-checkout-block > p { grid-column: 1 / -1; }
/* A hidden row must not hold a column open. */
.asas-checkout-block > [data-o-checkout-row][hidden] { display: none; }
.asas-checkout-block h2 { font-size: 1.05rem; margin: 0; }

.asas-checkout-empty { display: grid; gap: 1rem; justify-items: start; padding-block: 2.5rem; }
.asas-checkout-empty[hidden] { display: none; }
.asas-empty__title { font-size: 1.2rem; font-weight: 600; margin: 0; }

.asas-field { display: grid; gap: 0.3rem; }
.asas-field[hidden] { display: none; }
.asas-field__label { font-size: 0.9rem; }
.asas-field__error { color: var(--asas-sale); font-size: 0.85rem; margin: 0; }
.asas-field__error[hidden] { display: none; }
.asas-field[data-o-invalid="true"] .asas-input { border-color: var(--asas-sale); }

.asas-input {
  background: var(--asas-bg);
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  color: var(--asas-fg);
  font: inherit;
  padding: 0.6rem 0.75rem;
  inline-size: 100%;
}

.asas-pay { display: grid; gap: 0.5rem; list-style: none; margin: 0; padding: 0; }
.asas-pay__item[hidden] { display: none; }

.asas-pay__label {
  align-items: center;
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  cursor: pointer;
  display: flex;
  gap: 0.7rem;
  padding: 0.75rem 0.9rem;
}

.asas-pay__item[data-o-selected="true"] .asas-pay__label {
  border-color: var(--asas-accent);
  box-shadow: inset 0 0 0 1px var(--asas-accent);
}

.asas-pay__body { display: grid; gap: 0.1rem; }
.asas-pay__name { font-weight: 600; }
.asas-pay__note { color: var(--asas-muted); font-size: 0.85rem; margin: 0; }

.asas-coupon { display: flex; gap: 0.5rem; }
.asas-coupon .asas-input { flex: 1; }
.asas-coupon__ok { color: var(--asas-accent); margin: 0; }
.asas-coupon__ok[hidden] { display: none; }

/* An editable line in the checkout breakdown.
   The stepper is the basket's own — same control, same hooks — with a field
   between the buttons, so a shopper who wants eight of something types eight
   rather than pressing «+» seven times. */
/* Sized to itself. `.asas-coline__body` is a grid, so an `inline-flex`
   stepper stretched the whole column and the row grew a band of empty
   capsule either side of the number. */
.asas-coline__step { justify-self: start; margin-block-start: 0.4rem; }
.asas-step__field {
  appearance: textfield;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  font-variant-numeric: tabular-nums;
  inline-size: 2.5rem;
  min-inline-size: 0;
  text-align: center;
}
.asas-step__field::-webkit-outer-spin-button,
.asas-step__field::-webkit-inner-spin-button { appearance: none; margin: 0; }
.asas-step__field:focus-visible { outline: 2px solid var(--asas-accent); outline-offset: 1px; }

/* The merchant's quantity ladder, on the line it belongs to.
   It lived on the product page and nowhere else, so «خد ٣ ووفّر» never reached
   the one screen where the shopper is deciding what to spend. «الأساس» states
   an offer plainly and does not sell it twice: one row per rung, the rung
   already taken marked, and the merchant's own words when they wrote any. */
/* A ROW OF ITS OWN, spanning the whole line. Inside the body column the
   ladder had 193px of a 335px row to work in, so a rung carrying the
   merchant's own words — «٣ برطمانات بـ ٦٧٥ ج.م» — was wider than its column
   and pushed the checkout 44px sideways on a phone. */
.asas-coline__offers {
  display: grid;
  gap: 0.3rem;
  grid-column: 1 / -1;
  margin-block-start: 0.5rem;
  min-inline-size: 0;
}
.asas-coline__body { min-inline-size: 0; }
.asas-coline__offers:has([data-o-line-offers][hidden]) { display: none; }
.asas-coline__offers-label {
  color: var(--asas-muted);
  font-size: 0.75rem;
  font-weight: 700;
}
/* CHIPS, not a list. A basket of three products with four rungs each is
   twelve controls; stacked, that is a checkout the shopper has to scroll past
   to reach the fields. Each rung is one line of text in a capsule and the row
   wraps, so the ladder costs a line or two rather than a screen. */
.asas-rungs { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.asas-rungs[hidden] { display: none; }
.asas-rung {
  align-items: baseline;
  background: none;
  border: 1px solid var(--asas-border);
  border-radius: 999px;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  font-size: 0.78rem;
  gap: 0.35rem;
  padding: 0.3rem 0.7rem;
  /* The chip may take a second line on a narrow phone; a FIGURE never breaks
     across one — «٤٥ ج.م» split over two lines is not a price. */
  white-space: normal;
}
.asas-rung > * { white-space: nowrap; }
.asas-rung:hover { border-color: var(--asas-accent); }
.asas-rung[data-o-selected="true"] {
  background: color-mix(in srgb, var(--asas-accent) 8%, transparent);
  border-color: var(--asas-accent);
  font-weight: 700;
}
/* A figure never breaks across lines; the merchant's own WORDS may, or a
   long rung name would be wider than the row it sits in. */
.asas-rung__name { font-weight: 700; white-space: normal; }
.asas-rung__name[hidden] { display: none; }
/* The merchant's own words win; «اجعلها ٣» is only the fallback. */
.asas-rung[data-o-offer-titled="true"] .asas-rung__set { display: none; }
.asas-rung[data-o-offer-titled="true"] .asas-rung__price { display: none; }
.asas-rung__price { font-variant-numeric: tabular-nums; font-weight: 700; }
.asas-rung__save,
.asas-rung__ship { color: var(--asas-success); }
/* The saving is the reason to press it; free delivery is a badge, not a
   sentence, and both go if the rung is the one already taken. */
.asas-rung__ship[hidden] { display: none; }
.asas-rung[data-o-selected="true"] .asas-rung__save,
.asas-rung[data-o-selected="true"] .asas-rung__ship { display: none; }

/* The checkout the merchant sells this product with, on the product page.
   It used to be a bare `<div>` with no rule of its own anywhere in this
   sheet: the first labelled field opened immediately under «اشترِ الآن»,
   flush against it, with nothing to say that everything below was a form for
   buying THIS. Room above it, a hairline to separate it from the buying
   controls, and a heading. */
.asas-inline-checkout {
  border-block-start: 1px solid var(--asas-border);
  margin-block-start: calc(var(--asas-space) * 2);
  padding-block-start: calc(var(--asas-space) * 1.5);
}
.asas-inline-checkout__title {
  font-size: 1.15rem;
  margin-block: 0 var(--asas-space);
}

.asas-total { display: grid; gap: 0.35rem; margin: 0; }
.asas-total__row { display: flex; gap: 1rem; justify-content: space-between; }
.asas-total__row[hidden] { display: none; }
.asas-total dt, .asas-total dd { margin: 0; }
.asas-total dd { font-variant-numeric: tabular-nums; }

.asas-total__row--sum {
  border-block-start: 1px solid var(--asas-border);
  font-size: 1.1rem;
  font-weight: 600;
  padding-block-start: 0.45rem;
}

.asas-money { font-variant-numeric: tabular-nums; font-weight: 600; }

.asas-freeship {
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  display: grid;
  gap: 0.45rem;
  padding: 0.75rem 0.9rem;
}
.asas-freeship[hidden] { display: none; }
.asas-freeship__line { margin: 0; }
.asas-freeship__line [hidden] { display: none; }
.asas-freeship__track { background: var(--asas-border); block-size: 0.3rem; border-radius: 999px; overflow: hidden; }

.asas-freeship__fill {
  background: var(--asas-accent);
  block-size: 100%;
  display: block;
  inline-size: var(--o-progress, 0%);
  transition: inline-size 0.3s ease;
}

.asas-offerbars { display: grid; gap: 0.35rem; list-style: none; margin: 0; padding: 0; }
.asas-offerbars[hidden] { display: none; }
.asas-offerbar { display: grid; gap: 0.1rem; }
.asas-offerbar__gap { color: var(--asas-muted); font-size: 0.85rem; }
.asas-offerbar__gap [hidden] { display: none; }

.asas-checkout-errors {
  border: 1px solid var(--asas-sale);
  border-radius: var(--asas-radius);
  padding: 0.7rem 0.9rem;
}
.asas-checkout-errors[hidden] { display: none; }
.asas-checkout-errors p { margin: 0; }

[data-o-checkout-submit] [hidden] { display: none; }

/* A merchant pastes a table from a document and it is wider than the column.
   Letting it scroll inside its own box keeps the page intact; the platform
   then gives that box keyboard access (theme/elements/richText.ts), because
   no Liquid can put tabindex on markup that arrives as a string. */
.asas-rte table {
  display: block;
  max-inline-size: 100%;
  overflow-x: auto;
}

.asas-rte img {
  block-size: auto;
  max-inline-size: 100%;
}

.asas-rte blockquote {
  border-inline-start: 3px solid var(--asas-border);
  margin-inline: 0;
  padding-inline-start: var(--asas-space);
}

.asas-rte pre {
  max-inline-size: 100%;
  overflow-x: auto;
}

/* An order's head row: its number on one side, its status on the other. */
.asas-order__row {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: space-between;
}

/* ------------------------------------------------- the content-width floor */

/* Merchant HTML may not set the width of the page.

   Every box takes its minimum width from its contents, and that minimum
   travels: ONE unbreakable line — a <pre> from a datasheet, a wide pasted
   table — becomes the minimum width of the grid track it sits in, then of
   the section, then of the layout. The store does not scroll sideways, so
   the damage is silent: a page drawn at 1180px and cropped to the phone,
   with the title cut off at both edges and the buy panel half off-screen.

   Size containment on the WIDE CHILD cuts the chain at its source: the
   block takes its inline size from its container instead of its contents,
   and the content that does not fit overflows inside it — where these are
   already scroll containers (above) and the platform makes them
   keyboard-reachable.

   On the child, not on the wrapper: a prose wrapper is often a flex item,
   and a flex item whose size is contained resolves its auto basis to ZERO
   and disappears — measured, on this theme's collection header.

   Keyed on the platform's own attribute rather than a theme class, so it
   covers every surface carrying merchant HTML — a description, a page, a
   FAQ answer, a collection blurb — including any added later. */
[data-o-rte] :where(pre, table) {
  contain: inline-size;
}
/* Suggestions swipe on a phone: six related products are one gesture instead
   of three rows of scrolling. The grid returns as soon as there is room to
   show them together. Marked on the list itself so the catalogue grid — which
   a shopper reads top to bottom — keeps its columns. */
@media (max-width: 47.99rem) {
  .asas-grid[data-asas-rail] {
    grid-auto-columns: min(70vw, 15rem);
    /* A sideways scroller takes its width FROM its container; without size
       containment its own content sets the container's minimum width and the
       scroller stops being a scroller — the row just makes the page wider. */
    contain: inline-size;
    grid-auto-flow: column;
    grid-template-columns: none;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    padding-block-end: 0.5rem;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
  }
  .asas-grid[data-asas-rail] > * { scroll-snap-align: start; }
}

/* ------------------------------------------- merchant lists and rhythm */

/* The store's own reset strips list markers — right for a nav, wrong for a
   merchant's prose, where a numbered list of steps that renders as five
   unnumbered lines has lost its meaning. Restored here, in the theme, so
   the prose does not depend on what the page around it happens to reset. */
.asas-rte :where(ul) { list-style: disc; }
.asas-rte :where(ol) { list-style: decimal; }
.asas-rte :where(ul, ol) :where(ul) { list-style: circle; }
.asas-rte :where(li) { list-style: inherit; }

/* Rhythm at ANY depth. Merchant HTML arrives wrapped — an editor emits a
   <div> around the body often enough that a rule for DIRECT children alone
   silently stops applying, and the heading after a list ends up glued to it.
   Measured on the product description: `margin-block-start: 0px` on every
   nested heading. */
.asas-rte
  :is(p, ul, ol, dl, h1, h2, h3, h4, h5, h6, blockquote, pre, table, figure, hr)
  + :is(p, ul, ol, dl, h1, h2, h3, h4, h5, h6, blockquote, pre, table, figure, hr) {
  margin-block-start: 1em;
}

/* A heading opens a new idea; it wants more air above it than a paragraph. */
.asas-rte :is(p, ul, ol, blockquote, pre, table, figure) + :is(h2, h3, h4) {
  margin-block-start: 1.6em;
}

/* The add worked — say so for a moment (`data-o-added` comes from the
   platform, which also clears it). */
[data-o-add-to-cart][data-o-added="true"] {
  background: var(--asas-success);
  border-color: var(--asas-success);
  color: #fff;
}

[data-o-add-to-cart][data-o-added="true"]::after { content: " ✓"; }

.asas-buy-error { display: none; margin: 0.5rem 0 0; color: var(--asas-sale, #b42318); font-size: 0.9rem; font-weight: 600; }
[data-o-add-to-cart][data-o-error="customization"] ~ .asas-buy-error--custom,
[data-o-add-to-cart][data-o-error="true"] ~ .asas-buy-error--failed { display: block; }

/* The merchant's free-delivery promotion — plain, like the rest of «الأساس». */
.asas-freeship {
  border: 1px solid var(--asas-border); border-radius: var(--asas-radius);
  margin-block-end: var(--asas-space); padding: calc(var(--asas-space) * 0.75);
}
.asas-freeship[data-reached="true"] { border-color: var(--asas-success); }
.asas-freeship__line { margin: 0 0 0.5rem; font-weight: 600; }
.asas-freeship__bar {
  appearance: none; block-size: 6px; border: 0; border-radius: 999px;
  display: block; inline-size: 100%;
  background: color-mix(in srgb, var(--asas-border) 60%, transparent);
}
.asas-freeship__bar::-webkit-progress-bar { background: color-mix(in srgb, var(--asas-border) 60%, transparent); border-radius: 999px; }
.asas-freeship__bar::-webkit-progress-value { background: var(--asas-accent); border-radius: 999px; }
.asas-freeship__bar::-moz-progress-bar { background: var(--asas-accent); border-radius: 999px; }
.asas-freeship__prompt { margin: 0.75rem 0 0.5rem; font-size: 0.9rem; }
/* The shelf under the bar. Its images were `inline-size: 100%` with
   `block-size: auto`, so each took a full grid column at whatever aspect the
   merchant's file happened to be — three suggestions, three different heights,
   the row ragged. A fixed square thumbnail beside its name is the same row
   every time, whatever the photograph. */

.asas-line__offer { display: block; font-size: 0.85rem; font-weight: 600; margin-block-start: 0.25rem; }
.asas-line__offer[data-state="applied"] { color: var(--asas-muted, #6b7280); }
.asas-line__offer[data-state="next"] { color: var(--asas-accent); }
.asas-line__offer[data-state="next"]::before { content: "→ "; }

/* File pickers ----------------------------------------------------- */
/* The native control cannot be themed — its own button, its own wording, in
   the browser's language — so the input is hidden (still focusable, still what
   the label opens) and the theme draws the row. The platform writes the chosen
   name into `[data-o-file-name]` and sets `data-o-has-file` on the wrapper. */
.asas-file {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  padding: 0.5rem;
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
}
.asas-file__input {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* The one control that opens a phone's camera roll gets a thumb-sized box. */
.asas-file__pick { flex: none; padding: 0.5em 1em; min-block-size: 44px; }
.asas-file__icon { inline-size: 1rem; block-size: 1rem; fill: none; stroke: currentColor; stroke-width: 2; }
/* The ring goes on what the eye sees, not on the input hidden behind it. */
.asas-file__input:focus-visible + .asas-file__pick { outline: 2px solid var(--asas-fg); outline-offset: 2px; }
/* A phone filename is long and unbreakable: one line, an ellipsis, the rest
   of the row's width. */
.asas-file__name {
  flex: 1 1 8rem;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--asas-muted);
  font-size: 0.9rem;
}
.asas-file[data-o-has-file="true"] .asas-file__name { color: var(--asas-fg); font-weight: 600; }
.asas-file__clear {
  display: none;
  flex: none;
  align-items: center;
  justify-content: center;
  min-inline-size: 2.25rem;
  min-block-size: 2.25rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--asas-muted);
  cursor: pointer;
}
.asas-file[data-o-has-file="true"] .asas-file__clear { display: inline-flex; }
.asas-file__clear:hover { color: var(--asas-fg); }
.asas-file__clear:focus-visible { outline: 2px solid var(--asas-fg); outline-offset: 2px; }

/* Two lines, then an ellipsis: a long product name was taking four lines of a
   card and pushing the price and the button out of the first screen. */
.asas-card__title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* ------------------------------------------------------ search suggestions */

/* A custom element is inline until told otherwise, and an inline box is not a
   containing block for the panel hanging off it. */
o-search-form { display: block; position: relative; }

.asas-suggest-panel {
  background: var(--asas-bg);
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  inset-block-start: calc(100% + 0.4rem);
  inset-inline: 0;
  max-block-size: min(60vh, 26rem);
  overflow-y: auto;
  position: absolute;
  z-index: 60;
}

.asas-suggest-panel[hidden] { display: none; }

.asas-suggest__label {
  color: var(--asas-muted);
  font-size: 0.82rem;
  font-weight: 700;
  margin: 0;
  padding: calc(var(--asas-space) * 0.75) var(--asas-space) calc(var(--asas-space) * 0.4);
}

.asas-suggest__list { display: grid; list-style: none; margin: 0; padding: 0; }

.asas-suggest__row {
  align-items: center;
  color: var(--asas-fg);
  display: grid;
  gap: calc(var(--asas-space) * 0.75);
  grid-template-columns: auto minmax(0, 1fr);
  padding: calc(var(--asas-space) * 0.5) var(--asas-space);
  text-decoration: none;
}

/* Pointer and keyboard share ONE highlight. */
.asas-suggest__row:hover,
.asas-suggest__row[data-o-active="true"] {
  background: color-mix(in srgb, var(--asas-accent) 10%, transparent);
}

.asas-suggest__media {
  aspect-ratio: 1;
  background: color-mix(in srgb, var(--asas-border) 45%, transparent);
  border-radius: var(--asas-radius);
  display: block;
  inline-size: 3rem;
  overflow: hidden;
}

.asas-suggest__media img { block-size: 100%; inline-size: 100%; object-fit: cover; }

.asas-suggest__text { display: grid; gap: 0.15rem; min-inline-size: 0; }

/* One line per suggestion. */
.asas-suggest__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.asas-suggest__price { font-size: 0.9rem; font-weight: 700; }

.asas-suggest__was {
  color: var(--asas-muted);
  font-weight: 400;
  margin-inline-start: 0.4rem;
}

.asas-suggest__all {
  border-block-start: 1px solid var(--asas-border);
  display: block;
  font-size: 0.9rem;
  font-weight: 700;
  padding: calc(var(--asas-space) * 0.75) var(--asas-space);
  text-align: center;
}

.asas-suggest__empty { color: var(--asas-muted); margin: 0; padding: var(--asas-space); }

/* ------------------------------------------------- the merchant's WhatsApp */

/* The anchor is empty until the merchant switches WhatsApp on, and an empty
   list item under the address looks like a broken link. */
.asas-footer__whatsapp:has(> o-whatsapp:empty) { display: none; }

/* Placed here, the button stops being a floating circle over the page and
   becomes a row on this list — so it takes the list's size and colour rather
   than the platform's green. */
.asas-footer__whatsapp {
  --o-whatsapp-size: auto;
  --o-whatsapp-icon: 1.1rem;
  --o-whatsapp-radius: var(--asas-button-radius);
  --o-whatsapp-bg: transparent;
  --o-whatsapp-bg-hover: transparent;
  --o-whatsapp-fg: var(--asas-muted);
  --o-whatsapp-border: 0 solid transparent;
  --o-whatsapp-shadow: none;
  --o-whatsapp-gap: 0.45rem;
  --o-whatsapp-padding: 0;
}

/* The list's links are 24px tall for the touch floor (WCAG 2.5.8); the button
   sitting among them keeps that. */
.asas-footer__whatsapp [data-o-element="whatsapp"] {
  min-block-size: 24px;
  justify-content: flex-start;
}

.asas-footer__whatsapp [data-o-element="whatsapp"]:hover {
  color: var(--asas-fg);
}

/* ── The order, line by line, and the way out of a free-delivery gap ────────
   «الأساس» stays soft and rounded, the same geometry as its cards. */
.asas-colines { display: grid; gap: 0.6rem; list-style: none; margin: 0 0 0.6rem; padding: 0; }
.asas-colines[hidden] { display: none; }
.asas-coline {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start; gap: 0.7rem;
  padding: 0.7rem;
  border: 1px solid var(--asas-border); border-radius: var(--asas-radius);
}
.asas-coline__shot { inline-size: 3rem; block-size: 3rem; object-fit: cover; border-radius: calc(var(--asas-radius) / 1.5); background: color-mix(in srgb, var(--asas-border) 35%, transparent);
  aspect-ratio: 1 / 1;
}
.asas-coline__shot[hidden] { display: none; }
.asas-coline__body { display: grid; gap: 0.15rem; min-inline-size: 0; }
.asas-coline__title { font-weight: 600; overflow-wrap: anywhere; }
.asas-coline__detail { font-size: 0.85rem; color: var(--asas-muted); overflow-wrap: anywhere; }
.asas-coline__detail[hidden] { display: none; }
.asas-coline__count { font-size: 0.85rem; color: var(--asas-muted); }
.asas-coline__total { font-weight: 700; white-space: nowrap; }

/* A line with no photograph must not move the money.
   `display: none` takes the image out of the grid, and IMPLICIT placement then
   walks every remaining child one track towards the start — so the line total
   landed in the `minmax(0, 1fr)` track and was squeezed to four pixels wide on
   a phone, with the price cut off inside it. Measured on a 375px viewport.
   Naming the tracks makes the row independent of how many children are there,
   and the two-column spelling drops the empty gap the collapsed track left. */
.asas-coline__shot { grid-column: 1; }
.asas-coline__body { grid-column: 2; }
.asas-coline__total { grid-column: 3; }
.asas-coline:has(.asas-coline__shot[hidden]) { grid-template-columns: minmax(0, 1fr) auto; }
.asas-coline:has(.asas-coline__shot[hidden]) .asas-coline__body { grid-column: 1; }
.asas-coline:has(.asas-coline__shot[hidden]) .asas-coline__total { grid-column: 2; }



/* ── Categories ────────────────────────────────────────────────────────────
   A category tile is not a product card. It was literally the same class:
   image above, title beneath, count beneath that — so the category grid and
   the product grid read as the same thing twice on one page. This one is
   full-bleed with the name on a scrim over it, which is also the only place
   in «الأساس» where type sits on a photograph. */
.asas-cat { position: relative; min-inline-size: 0; }
.asas-cat__link {
  display: block; position: relative;
  border-radius: var(--asas-radius);
  overflow: hidden;
  color: #fff; text-decoration: none;
  background: color-mix(in srgb, var(--asas-accent) 22%, var(--asas-bg));
}
.asas-cat__media { display: block; aspect-ratio: 1 / 1; }
.asas-cat__media img {
  inline-size: 100%; block-size: 100%; object-fit: cover; display: block;
  transition: transform 400ms ease;
}
/* The scrim is what makes the name readable over ANY photograph — a light
   product shot and a dark one both take the same white type. */
.asas-cat__label {
  position: absolute; inset-inline: 0; inset-block-end: 0;
  display: grid; gap: 0.15rem;
  padding: 1.6rem 0.9rem 0.8rem;
  background: linear-gradient(to top,
    color-mix(in srgb, #000 68%, transparent) 0%,
    color-mix(in srgb, #000 34%, transparent) 55%,
    transparent 100%);
}
.asas-cat__title { font-weight: 700; font-size: 1rem; line-height: 1.25; overflow-wrap: anywhere; }
.asas-cat__count { font-size: 0.8rem; opacity: 0.85; }
.asas-cat__link:hover .asas-cat__media img { transform: scale(1.05); }
.asas-cat__link:focus-visible { outline: 2px solid var(--asas-accent); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .asas-cat__media img { transition: none; }
  .asas-cat__link:hover .asas-cat__media img { transform: none; }
}

/* ── The cart's own summary ────────────────────────────────────────────────
   There wasn't one. The whole of it was a muted meta line under the title —
   «٣ — ١٬١٣٠٫٠٠ ج.م.» at 0.85rem in grey — so the one number a shopper came
   to this page for was the smallest thing on it. A panel now, beside the
   lines where there is room and beneath them on a phone, with the checkout
   inside it because that is the next thing to do. */
.asas-cart-page { display: grid; gap: calc(var(--asas-space) * 1.5); align-items: start; }
@media (min-width: 60rem) {
  .asas-cart-page { grid-template-columns: minmax(0, 1fr) 20rem; }
}
.asas-cart-page__summary {
  display: grid; gap: 0.65rem;
  padding: calc(var(--asas-space) * 1.1);
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  background: color-mix(in srgb, var(--asas-border) 14%, transparent);
}
@media (min-width: 60rem) {
  .asas-cart-page__summary { position: sticky; inset-block-start: var(--asas-space); }
}
.asas-cart-page__summary h2 { font-size: 1.05rem; margin: 0; }
.asas-cart-page__row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin: 0; }
.asas-cart-page__row dt { color: var(--asas-muted); font-size: 0.9rem; margin: 0; }
.asas-cart-page__row dd { margin: 0; font-variant-numeric: tabular-nums; }
.asas-cart-page__row--sum {
  padding-block-start: 0.65rem;
  border-block-start: 1px solid var(--asas-border);
  font-size: 1.15rem; font-weight: 700;
}
.asas-cart-page__note { margin: 0; font-size: 0.8rem; color: var(--asas-muted); }
.asas-cart-page__summary .asas-btn { inline-size: 100%; justify-content: center; min-block-size: 2.75rem; }
/* Nothing to total, nothing to check out. */
.asas-cart-page:has([data-o-cart-empty="true"]) .asas-cart-page__summary .asas-btn { display: none; }

/* ── Media with no photograph ──────────────────────────────────────────────
   A merchant part-way through setting up has categories and products with no
   image yet, and a flat grey square reads as a picture that failed to load.
   The same composed ground the hero uses, so an unfinished catalogue looks
   deliberate rather than broken. `:has()` is the test — the box is empty of
   an `<img>`, not merely showing one that has not decoded. */
.asas-card__media:not(:has(img)),
.asas-cat__media:not(:has(img)),
.asas-cat__link:not(:has(img)) {
  background-color: color-mix(in srgb, var(--asas-accent) 7%, var(--asas-bg));
  background-image:
    radial-gradient(110% 80% at 80% 15%,
      color-mix(in srgb, var(--asas-accent) 14%, transparent) 0%, transparent 62%),
    repeating-linear-gradient(135deg,
      color-mix(in srgb, var(--asas-accent) 7%, transparent) 0 1px,
      transparent 1px 12px);
}
/* The product card's box has no intrinsic height without an image inside it. */
.asas-card__media:not(:has(img)) { aspect-ratio: 1 / 1; }

/* The store's own details on the contact page — a form asks the shopper to
   write; these say it can also be phoned, mailed or visited. */
.asas-contact-details {
  list-style: none; margin: 0 0 var(--asas-space); padding: var(--asas-space);
  display: grid; gap: 0.5rem;
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  background: color-mix(in srgb, var(--asas-border) 14%, transparent);
}
.asas-contact-details li { min-block-size: 24px; display: flex; align-items: center; }
.asas-contact-details a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
.asas-contact-details a:hover { color: var(--asas-accent); text-decoration: underline; }

/* ── The cart drawer ───────────────────────────────────────────────────────
   Hidden below the layout breakpoint, which is this theme's way of saying
   «a phone goes to the cart page». The platform reads that decision off the
   computed style before it swallows the basket click, so the same control is
   a drawer here and a link there. */
.asas-drawer-cart { display: none; }
@media (min-width: 48rem) {
  .asas-drawer-cart { display: block; }
  /* Out of the way until the platform opens it. `visibility` rather than
     `display` so the panel can transition in — and DELAYED by the slide's own
     length on the way out, or the panel disappears mid-move and there is no
     closing animation to see. */
  .asas-drawer-cart { visibility: visible; transition: visibility 0s; }
  .asas-drawer-cart:not([data-o-open]) {
    visibility: hidden;
    pointer-events: none;
    transition: visibility 0s linear 260ms;
  }
}
.asas-drawer-cart__backdrop {
  position: fixed; inset: 0; z-index: 60;
  background: color-mix(in srgb, #000 45%, transparent);
  opacity: 0; transition: opacity 220ms ease;
}
.asas-drawer-cart[data-o-open] .asas-drawer-cart__backdrop { opacity: 1; }
.asas-drawer-cart__panel {
  position: fixed;
  inset-block: 0;
  inset-inline-end: 0;
  z-index: 61;
  inline-size: min(24rem, 92vw);
  display: flex;
  flex-direction: column;
  gap: var(--asas-space);
  padding: var(--asas-space);
  background: var(--asas-bg);
  border-inline-start: 1px solid var(--asas-border);
  box-shadow: -12px 0 40px color-mix(in srgb, var(--asas-fg) 14%, transparent);
  /* Off-canvas on the INLINE axis, so it slides from the page's end edge in
     both writing directions. */
  transform: translateX(0);
  transition: transform 260ms cubic-bezier(0.32, 0.72, 0, 1);
}
/* `translate` has no logical axis, so the direction is stated per writing
   mode rather than assumed. */
:dir(rtl) .asas-drawer-cart:not([data-o-open]) .asas-drawer-cart__panel { transform: translateX(-100%); }
:dir(ltr) .asas-drawer-cart:not([data-o-open]) .asas-drawer-cart__panel { transform: translateX(100%); }
.asas-drawer-cart__head { display: flex; align-items: center; justify-content: space-between; gap: var(--asas-space); }
.asas-drawer-cart__head h2 { margin: 0; font-size: 1.05rem; }
.asas-drawer-cart__body { display: grid; gap: 0.75rem; align-content: start; }
.asas-drawer-cart__body .asas-btn { inline-size: 100%; justify-content: center; min-block-size: 2.75rem; }
/* The basket is empty or it is not; both were rendered, and the flag the
   platform sets on the count decides which is seen. */
.asas-drawer-cart__filled { display: none; }
.asas-drawer-cart__body:has([data-o-cart-count]:not([data-o-cart-empty="true"])) .asas-drawer-cart__filled { display: grid; gap: 0.75rem; }
.asas-drawer-cart__body:has([data-o-cart-empty="true"]) .asas-drawer-cart__empty { display: grid; }
/* The line count above both states. It is hidden while the basket is empty —
   «0 عناصر» over an empty-basket illustration says the same thing twice. */
.asas-drawer-cart__count {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  margin: 0;
  color: var(--asas-muted);
  font-size: 0.9rem;
}
.asas-drawer-cart__count b { color: var(--asas-fg); font-variant-numeric: tabular-nums; }
.asas-drawer-cart__body:has([data-o-cart-empty="true"]) .asas-drawer-cart__count { display: none; }
/* The drawer's empty state, in the theme's round vocabulary: the same basket
   mark the cart page uses, centred, with the way out underneath it. */
.asas-drawer-cart__empty {
  justify-items: center;
  text-align: center;
  gap: 0.6rem;
  padding-block: calc(var(--asas-space) * 1.5);
}
.asas-drawer-cart__mark {
  inline-size: 3rem;
  block-size: 3rem;
  color: var(--asas-muted);
}
.asas-drawer-cart__empty-title { margin: 0; font-size: 1.05rem; font-weight: 600; }
.asas-drawer-cart__empty .asas-card__meta { margin: 0; }
.asas-drawer-cart__empty .asas-btn { margin-block-start: 0.4rem; }
.asas-drawer-cart__body:has([data-o-cart-count]:not([data-o-cart-empty="true"])) .asas-drawer-cart__empty { display: none; }
/* The page behind a dialog does not scroll. */
html[data-o-cart-open] { overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  .asas-drawer-cart, .asas-drawer-cart__panel, .asas-drawer-cart__backdrop { transition: none; }
}

/* ── The menu: a side drawer ───────────────────────────────────────────────
   «الأساس» opens its basket from the edge of the screen, so its menu opens
   from the same edge — one theme, one gesture.

   The panel is a SIBLING of the `<details>`, not a child: a `<details>` hides
   its own children outright, so a panel inside it has no closed state to
   animate from and simply appeared. Outside, it is always in the document,
   parked off-canvas, and `[open] ~` slides it in.

   `inset-inline-end` — the same edge the menu button sits on. Anchored to
   `inset-inline-start` it opened from the far side of the screen, away from
   the thumb that asked for it.

   The button does NOT sit above the panel. It was given `z-index: 71` against
   the drawer's 70, so the hamburger floated over its own open menu. */
.asas-drawer,
.asas-drawer-scrim { display: none; }

.asas-drawer {
  position: fixed;
  inset-block: 0;
  inset-inline-end: 0;
  z-index: 70;
  inline-size: min(20rem, 88vw);
  overflow-y: auto;
  border: 0;
  border-inline-start: 1px solid var(--asas-border);
  background: var(--asas-bg);
  box-shadow: -12px 0 40px color-mix(in srgb, var(--asas-fg) 14%, transparent);
  padding: var(--asas-space);
  /* Parked off-canvas on the INLINE axis. `translate` has no logical axis, so
     the direction is stated per writing mode rather than assumed. */
  transition: transform 260ms ease, visibility 260ms;
  visibility: hidden;
}
.asas-drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 69;
  background: color-mix(in srgb, #000 42%, transparent);
  opacity: 0;
  visibility: hidden;
  transition: opacity 220ms ease, visibility 220ms;
}
:dir(rtl) .asas-drawer { transform: translateX(100%); }
:dir(ltr) .asas-drawer { transform: translateX(-100%); }

.asas-drawer-details[open] ~ .asas-drawer {
  transform: translateX(0);
  visibility: visible;
}
.asas-drawer-details[open] ~ .asas-drawer-scrim { opacity: 1; visibility: visible; }

@media (max-width: 47.99rem) {
  .asas-drawer, .asas-drawer-scrim { display: block; }
}
html:has(.asas-drawer-details[open]) { overflow: hidden; }
.asas-drawer__list a { font-size: 1.05rem; padding-block: 0.35rem; }
@media (prefers-reduced-motion: reduce) {
  .asas-drawer, .asas-drawer-scrim { transition: none; }
}
 }


/* ── Header items the merchant composed ────────────────────────────────────
   The store's `main-menu` is built from the category tree and nothing else,
   so a header could previously only ever list categories. These are the other
   kinds of item — a link with an optional glyph, a call to action, one product
   worth pointing at — and «الأساس» draws each in its own register: the link
   like any other nav link, the button filled, the product with its face. */
.asas-nav__link { display: inline-flex; align-items: center; gap: 0.4rem; }
.asas-nav__cta {
  min-block-size: 2.25rem;
  padding-inline: 0.9rem;
  font-size: 0.9rem;
}
.asas-nav__pick img {
  inline-size: 1.5rem;
  block-size: 1.5rem;
  object-fit: cover;
  border-radius: 999px;
  background: color-mix(in srgb, var(--asas-border) 35%, transparent);
}
.asas-drawer__cta { inline-size: 100%; justify-content: center; min-block-size: 2.75rem; margin-block-start: 0.35rem; }

/* A shelf can look different from the shelf above it. The treatment is the
   merchant's store-wide default and a SECTION may state its own — a home page
   where every shelf is identical is one shelf shown four times. */
.asas-card[data-style="framed"] {
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  padding: calc(var(--asas-space) * 0.75);
}
.asas-card[data-style="raised"] {
  border-radius: var(--asas-radius);
  padding: calc(var(--asas-space) * 0.75);
  box-shadow: 0 6px 20px color-mix(in srgb, var(--asas-fg) 10%, transparent);
}

/* A payment method is a choice, not a paragraph: they were full-width rows
   stacked down the page, so four ways to pay took four screens' worth of
   rhythm. They sit as many to a row as fit. */
.asas-pay {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
  gap: var(--asas-space);
}


/* ── The way out of a free-delivery gap: PILLS ─────────────────────────────
   «الأساس» is round and plain, and here the whole pill IS the control — one
   tap adds it, and a quieter link underneath goes to the product for anyone
   who wants to look first. A wrap of pills, not a list and not a grid. */
.asas-copicks {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  list-style: none;
  margin: 0.7rem 0 0;
  padding: 0;
}
.asas-copicks[hidden] { display: none; }
.asas-copick { display: grid; gap: 0.2rem; justify-items: center; }
.asas-copick__add {
  display: flex; align-items: center; gap: 0.5rem;
  min-block-size: 2.75rem;
  padding: 0.3rem 0.9rem 0.3rem 0.3rem;
  border: 1px solid var(--asas-border);
  border-radius: 999px;
  background: var(--asas-bg); color: var(--asas-fg);
  font: inherit; font-size: 0.85rem; cursor: pointer;
  max-inline-size: 15rem;
}
:dir(rtl) .asas-copick__add { padding: 0.3rem 0.3rem 0.3rem 0.9rem; }
.asas-copick__add:hover { border-color: var(--asas-accent); }
.asas-copick__shot {
  inline-size: 2rem; block-size: 2rem; aspect-ratio: 1 / 1; flex: none;
  object-fit: cover; border-radius: 999px;
  background: color-mix(in srgb, var(--asas-border) 35%, transparent);
}
.asas-copick__shot[hidden] { display: none; }
.asas-copick__name {
  min-inline-size: 0;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1;
  overflow: hidden; overflow-wrap: anywhere;
}
.asas-copick__price { font-weight: 700; white-space: nowrap; }
.asas-copick__link { font-size: 0.75rem; color: var(--asas-muted); text-decoration: none; }
.asas-copick__link:hover { color: var(--asas-accent); text-decoration: underline; }

/* «الأساس» keeps a meter and keeps it round — the same geometry as its pills,
   its swatches and its buttons. */
.asas-freeship .asas-freeship__bar { block-size: 0.6rem; border-radius: 999px; overflow: hidden; }
.asas-freeship .asas-freeship__bar::-webkit-progress-bar { border-radius: 999px; }
.asas-freeship .asas-freeship__bar::-webkit-progress-value { border-radius: 999px; }

/* ── Checkout: the familiar two-column ─────────────────────────────────────
   «الأساس» is the plain theme, so it takes the pattern a shopper has seen
   everywhere else: their details on one side, a card holding the order on the
   other, following them down the page. No invention — that IS this theme's
   idea. */
.asas-checkout-main,
.asas-checkout-aside { display: grid; gap: calc(var(--asas-space) * 1.25); align-content: start; min-inline-size: 0; }
@media (min-width: 64rem) {
  .asas-checkout-form:not([data-compact="true"]) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(19rem, 24rem);
    column-gap: calc(var(--asas-space) * 6);
    align-items: start;
  }
  .asas-checkout-form:not([data-compact="true"]) > .asas-checkout-aside {
    position: sticky;
    inset-block-start: var(--asas-space);
    padding: var(--asas-space);
    border: 1px solid var(--asas-border);
    border-radius: var(--asas-radius);
    background: color-mix(in srgb, var(--asas-border) 12%, transparent);
  }
}

/* ── Card DESIGNS ──────────────────────────────────────────────────────────
   `plain`, `framed` and `raised` are a border and a shadow. These are
   different cards. «الأساس» is the plain theme, so its variants are the
   plain ones a shopper meets everywhere — done properly. */

/* PLAIN is a real choice, not the absence of one: a section inside a page
   set to `framed` has to be able to say «not here». */
.asas-card[data-style="plain"] {
  border: 0;
  box-shadow: none;
  padding: 0;
  background: none;
}

/* OVERLAY — the caption on the picture. */
.asas-card[data-style="overlay"] { position: relative; display: block; }
.asas-card[data-style="overlay"] .asas-card__media { display: block; margin: 0; }
.asas-card[data-style="overlay"] .asas-card__title,
.asas-card[data-style="overlay"] .asas-card__meta,
.asas-card[data-style="overlay"] .asas-price {
  position: relative;
  z-index: 2;
  color: #fff;
}
.asas-card[data-style="overlay"]::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 60%;
  z-index: 1;
  border-end-start-radius: var(--asas-radius);
  border-end-end-radius: var(--asas-radius);
  background: linear-gradient(to top, rgb(0 0 0 / 0.75), transparent);
  pointer-events: none;
}
.asas-card[data-style="overlay"] .asas-card__title {
  position: absolute;
  inset-inline: 0.75rem;
  inset-block-end: 2.1rem;
  font-weight: 600;
}
.asas-card[data-style="overlay"] .asas-price {
  position: absolute;
  inset-inline-start: 0.75rem;
  inset-block-end: 0.7rem;
}
.asas-card[data-style="overlay"] { border-radius: var(--asas-radius); overflow: hidden; }

/* COMPACT — the picture beside the words. Made for a rail, a cross-sell, and
   anywhere a column of many products has to stay readable. */
.asas-card[data-style="compact"],
.asas-card[data-style="row"] {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  align-items: center;
  gap: 0.75rem;
}
.asas-card[data-style="compact"] .asas-card__media,
.asas-card[data-style="row"] .asas-card__media {
  inline-size: 76px;
  border-radius: var(--asas-radius);
  overflow: hidden;
}
.asas-card[data-style="compact"] .asas-card__title,
.asas-card[data-style="row"] .asas-card__title { grid-column: 2; font-size: 0.95rem; }
.asas-card[data-style="compact"] .asas-card__meta,
.asas-card[data-style="row"] .asas-card__meta { grid-column: 2; }
.asas-card[data-style="compact"] .asas-price,
.asas-card[data-style="row"] .asas-price { grid-column: 2; }

/* ROW carries a rule as well, so a column of them reads as a list. */
.asas-card[data-style="row"] {
  border-block-end: 1px solid var(--asas-border);
  padding-block-end: 0.6rem;
}

/* A list design has to own the row. Left in the section's column count an
   index reads as a row of index entries rather than a list, so these span
   every track whatever the merchant set the grid to. */
.asas-card[data-style="compact"],
.asas-card[data-style="row"] { grid-column: 1 / -1; }


/* ---- per-unit choices inside a quantity offer -------------------------
   The platform decides how many rows exist and refuses an unfinished set;
   everything visual here is the theme's. */
.asas-slots[hidden] { display: none; }
.asas-slots {
  display: grid;
  gap: var(--o-space-3, 12px);
  margin-block: var(--o-space-4, 16px);
  padding: var(--o-space-4, 16px);
  border: 1px solid var(--o-color-border);
  border-radius: var(--o-radius, 10px);
  background: color-mix(in srgb, var(--o-color-accent) 4%, transparent);
}
.asas-slot {
  display: grid;
  gap: var(--o-space-2, 8px);
  padding: 0;
  margin: 0;
  border: 0;
  border-block-end: 1px solid var(--o-color-border);
  padding-block-end: var(--o-space-3, 12px);
}
.asas-slots > [data-o-offer-slot-index]:last-child .asas-slot {
  border-block-end: 0;
  padding-block-end: 0;
}
.asas-slot__label {
  font-size: .82rem;
  font-weight: 600;
  color: var(--o-color-muted);
  padding: 0;
}
.asas-option--slot .asas-option__name {
  font-size: .78rem;
  color: var(--o-color-muted);
}
/* The platform marks an unfinished row; the theme says what that looks like. */
.asas-slots [data-o-invalid] .asas-slot {
  outline: 2px solid var(--o-color-sale, #b3261e);
  outline-offset: 4px;
  border-radius: var(--o-radius, 10px);
}

/* An image a shopper attaches to a customisation. The platform reads the file
   and parks the data URL on the input; the theme owns everything visible. */
.asas-file--custom { align-items: flex-start; }
.asas-file__preview {
  flex: none;
  inline-size: 56px;
  block-size: 56px;
  object-fit: cover;
  border-radius: var(--asas-radius);
  border: 1px solid var(--asas-border);
}
.asas-file__error { display: none; flex-basis: 100%; font-size: 0.85rem; color: #b42318; }
.asas-file[data-o-file-error="type"] .asas-file__error[data-o-when="type"],
.asas-file[data-o-file-error="size"] .asas-file__error[data-o-when="size"] { display: block; }
.asas-file[data-o-file-error] { border-color: #b42318; }

/* The buy actions are one group, and a group needs air: a solid button and an
   outlined one flush against each other read as a single odd control. */
.asas-buy-actions { display: grid; gap: 0.75rem; }
.asas-buy-actions .asas-buy-error { margin: 0; }

/* الأساس keeps the clock quiet: a hairline row, tabular digits, and a state
   that steps back rather than shouts when the offer is over. */
.asas-countdown[data-o-countdown-state="off"] { display: none; }
.asas-countdown[data-o-countdown-state="ended"] {
  border-style: dashed;
  color: var(--asas-muted);
}
.asas-countdown[data-o-countdown-state="ended"] .asas-countdown__clock {
  opacity: 0.5;
  text-decoration: line-through;
}
/* The last hours are the only ones worth raising a voice for. */
.asas-countdown[data-o-countdown-days-left="0"] { border-color: currentColor; }

/* The banner on a phone.
   The height setting is what the merchant wants on a DESKTOP. Holding a tall
   box on a 375px screen turned a 1600×900 photograph into a 36%-wide slice of
   itself, because `cover` has to crop whichever axis does not fit. On a narrow
   screen the media's own shape wins: the box is at least 16:9 and grows if the
   copy needs more, so nothing is cut off the sides.

   «and grows if the copy needs more» is what `aspect-ratio` alone did NOT do.
   With `min-block-size: 0` the ratio fixed the height outright, and this
   section's `overflow: hidden` — there to clip the photograph to the corner
   radius — then cut off everything that did not fit. Measured on a 375px
   phone with an eyebrow, a heading, a paragraph and a button: 263px of copy
   inside a 188px box, so the last 75px of it, the BUTTON included, was simply
   not on the page. A hero whose call to action is invisible is the worst
   single defect a storefront can ship.

   The ratio is a FLOOR instead, held by a zero-width item sharing the content's
   grid cell: percentage padding resolves against that cell's inline size, so
   the box is 16:9 of its own width — no viewport arithmetic, correct inside
   any container — and the row grows the moment the copy is taller. */
@media (max-width: 47.99rem) {
  .asas-hero { min-block-size: 0; aspect-ratio: auto; }
  /* Both in the SAME cell, both said explicitly. Placing only the spacer left
     the copy to auto-placement, which put it in row 2 — the ratio then added
     its full height ABOVE the text instead of standing under it, and the
     banner grew to 434px for 246px of copy. */
  .asas-hero::before {
    content: "";
    grid-area: 1 / 1;
    inline-size: 0;
    padding-block-start: 56.25%;
  }
  .asas-hero__content { grid-area: 1 / 1; }
}

/* .asas-order — rendered by more than one section, so it belongs to the theme
   rather than to main-account.liquid. A section's own {% stylesheet %} ships only when
   that section is on the page, so these rules were simply absent everywhere
   else the class appeared. */
/* «asas-card» is the PRODUCT card: a flex column with a gap and nothing else —
   no border, no ground, no radius, because a product card's surface is its own
   photograph. The account and the order history borrowed that class and got
   padding around bare text, which is what «unstyled» meant here. A real
   surface of their own. */
.asas-account__card,
.asas-account__edit,
.asas-order {
  padding: var(--asas-space);
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  background: var(--asas-bg);
}
/* An order is a thing you can open; it should say so under the pointer. */
.asas-order { transition: border-color 160ms ease, box-shadow 160ms ease; }
.asas-order:hover {
  border-color: color-mix(in srgb, var(--asas-accent) 45%, var(--asas-border));
  box-shadow: 0 4px 16px color-mix(in srgb, var(--asas-fg) 8%, transparent);
}
/* The history reads as a list of ORDERS rather than a wall of totals: the
   number and its state, then what was in it, then what it cost. */
.asas-order__items {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 0.4rem;
  padding-block: 0.6rem;
  border-block: 1px solid var(--asas-border);
}
.asas-order__items li { display: flex; align-items: center; gap: 0.6rem; min-inline-size: 0; }
.asas-order__items img {
  inline-size: 2.5rem; block-size: 2.5rem; flex: none;
  object-fit: cover; border-radius: calc(var(--asas-radius) / 1.5);
  background: color-mix(in srgb, var(--asas-border) 35%, transparent);
}
.asas-order__items li > span:first-of-type {
  min-inline-size: 0;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1;
  overflow: hidden; overflow-wrap: anywhere;
}
.asas-order__items li > .asas-card__meta { margin-inline-start: auto; white-space: nowrap; }
.asas-order__totals dt { color: var(--asas-muted); }
.asas-order__totals dd { margin: 0; text-align: end; font-variant-numeric: tabular-nums; }
.asas-order { display: grid; gap: 0.4rem; padding: var(--asas-space); }
.asas-order__row { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }

/* .asas-account — rendered by more than one section, so it belongs to the theme
   rather than to main-account.liquid. A section's own {% stylesheet %} ships only when
   that section is on the page, so these rules were simply absent everywhere
   else the class appeared. */
.asas-account { display: grid; gap: calc(var(--asas-space) * 1.5); align-items: start; }
.asas-account__heading { font-size: 1.05rem; margin-block: 0 0.75rem; }
.asas-account__facts { display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 1rem; margin: 0; }
.asas-account__facts dt { color: var(--asas-muted); }
.asas-account__facts dd { margin: 0; }
.asas-account__edit { display: grid; gap: 0.75rem; }
.asas-account__edit .asas-card__meta { margin: 0; }
.asas-account__status { margin: 0; font-weight: 600; }
.asas-account__status[hidden] { display: none; }
.asas-account__status[data-o-state="error"] { color: var(--asas-sale); }
.asas-account__edit[data-o-busy="true"] { opacity: 0.6; pointer-events: none; }

/* An empty basket, and the summary that must not be offered with one.
   The count element carries the platform's flag, so both states are rendered
   server-side and CSS chooses — nothing waits for JavaScript. */
.asas-cart-empty { display: none; }
.asas-cart-page:has([data-o-cart-count][data-o-cart-empty="true"]) { display: none; }
.asas-section:has([data-o-cart-count][data-o-cart-empty="true"]) .asas-cart-empty { display: block; }
.asas-cart-empty__card {
  display: grid;
  justify-items: center;
  gap: 0.75rem;
  text-align: center;
  padding-block: clamp(2rem, 6vw, 3.5rem);
}
.asas-cart-empty__mark { inline-size: 3rem; block-size: 3rem; color: var(--asas-accent); }
.asas-cart-empty__title { margin: 0; }
.asas-cart-empty__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; justify-content: center; }

/* The merchant's exit-intent offer, in الأساس's own clothes. The platform
   owns when it appears and what it says; the theme owns all of how it looks. */
[data-o-element="exit-intent"] {
  position: fixed; inset: 0; z-index: 120;
  display: grid; place-items: center;
  background: color-mix(in srgb, #000 46%, transparent);
  padding: 1rem;
}
[data-o-element="exit-intent"] [data-o-part="dialog"] {
  inline-size: min(26rem, 100%);
  background: var(--asas-bg);
  color: var(--asas-fg);
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  padding: clamp(1.25rem, 4vw, 2rem);
  text-align: center;
  position: relative;
}
[data-o-element="exit-intent"] [data-o-part="close"] {
  position: absolute; inset-block-start: 0.5rem; inset-inline-end: 0.5rem;
  min-inline-size: 44px; min-block-size: 44px;
  border: 0; background: none; color: inherit; cursor: pointer;
}
[data-o-element="exit-intent"] [data-o-part="icon"] { font-size: 2rem; }
[data-o-element="exit-intent"] [data-o-part="title"] { margin: 0.5rem 0; font-size: 1.25rem; }
[data-o-element="exit-intent"] [data-o-part="coupon-code"] {
  display: inline-flex; align-items: center; gap: 0.5rem;
  border: 1px dashed var(--asas-accent); border-radius: var(--asas-radius);
  padding: 0.5rem 0.9rem; margin-block: 0.75rem;
  font-weight: 700; letter-spacing: 0.08em;
}
[data-o-element="exit-intent"] [data-o-part="cta"] {
  inline-size: 100%; min-block-size: 44px; cursor: pointer;
  border: 0; border-radius: var(--asas-button-radius);
  background: var(--asas-accent); color: var(--asas-accent-contrast);
}

/* ------------------------------------------------------------------ */
/* Product card designs                                                */
/* ------------------------------------------------------------------ */
/* The sections have offered these six for a long time and nothing consumed
   the setting: a merchant picked a card style and the page did not change.
   The ancestor carries `data-asas-card`, the card reads it, so a developer can
   put any of them anywhere without touching the card snippet. */

[data-asas-card="plain"] .asas-card { border: 0; padding: 0; background: none; box-shadow: none; }

[data-asas-card="framed"] .asas-card {
  border: 1px solid var(--asas-border);
  border-radius: var(--asas-radius);
  padding: 0.75rem;
}

[data-asas-card="raised"] .asas-card {
  border-radius: var(--asas-radius);
  padding: 0.75rem;
  background: var(--asas-bg);
  box-shadow: 0 1px 2px rgb(0 0 0 / 6%), 0 8px 24px rgb(0 0 0 / 7%);
}

/* Media-dominant, with the type laid over it. */
[data-asas-card="overlay"] .asas-card { position: relative; border-radius: var(--asas-radius); overflow: hidden; }
[data-asas-card="overlay"] .asas-card__media { margin: 0; }
[data-asas-card="overlay"] .asas-card::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(180deg, transparent 45%, rgb(0 0 0 / 64%));
}
[data-asas-card="overlay"] .asas-card__title,
[data-asas-card="overlay"] .asas-card__meta { position: relative; z-index: 1; color: #fff; }
[data-asas-card="overlay"] .asas-card__title { padding-inline: 0.75rem; margin-block-start: -3.2rem; }
[data-asas-card="overlay"] .asas-card__meta { padding: 0 0.75rem 0.75rem; }

/* Tighter type for a dense grid. */
[data-asas-card="compact"] .asas-card { border: 0; padding: 0; }
[data-asas-card="compact"] .asas-card__title { font-size: 0.95rem; line-height: 1.35; }
[data-asas-card="compact"] .asas-card__meta { font-size: 0.85rem; }

/* A horizontal row — for a rail beside copy, or a compact list. */
[data-asas-card="row"] .asas-card {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr);
  gap: 0.75rem;
  align-items: center;
}
[data-asas-card="row"] .asas-card__media { margin: 0; }

/* What the shopper pays now, stated in the block that asks for it. */
.asas-deposit-due {
  align-items: baseline;
  display: flex;
  gap: 0.5rem;
  justify-content: space-between;
  margin: 0.75rem 0 0;
}
.asas-deposit-due__label { color: var(--asas-muted, #5b5b5b); }
.asas-deposit-due__amount { font-size: 1.25rem; font-weight: 700; }
.asas-deposit-rest {
  color: var(--asas-muted, #5b5b5b);
  display: flex;
  gap: 0.35rem;
  margin: 0.15rem 0 0;
  font-size: 0.875rem;
}

/* ---------------------------------------------------------------------------
 * The exit-intent sheet owns its own visibility (Phase 31 fix round).
 *
 * The popup is a PLATFORM element rendered into <body>, and it still carries
 * the legacy `exit-intent-popup-*` class names — so on a package store it was
 * taking `opacity`, `transform`, `animation`, `overflow` and `max-width` from
 * the compiled stylesheet the store also happens to load. A theme must not
 * depend on that sheet: it is retired, it is served from a CDN this repository
 * cannot change, and a theme installed on a store without it would show a
 * sheet stuck at its entrance animation's first frame — a card and its text,
 * invisible.
 *
 * So the visibility is declared, and the entrance is the theme's own.
 * ------------------------------------------------------------------------- */
[data-o-element="exit-intent"] [data-o-part="dialog"] {
  opacity: 1;
  overflow: visible;
  transform: none;
  animation: asas-sheet-in 220ms ease-out both;
}

@keyframes asas-sheet-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  [data-o-element="exit-intent"] [data-o-part="dialog"] { animation: none; }
}

/* ---------------------------------------------------------------------------
 * The sales notification, in الأساس's hand.
 *
 * The platform's defaults are a white card with a grey hairline — close to
 * this theme already, and wrong the moment a merchant re-schemes it. Stated
 * from the theme's own tokens so it follows the store instead.
 *
 * الأساس's card is the plainest of the four: the store's own surface, its own
 * border radius, and the product name carrying the only weight.
 * ------------------------------------------------------------------------- */
[data-o-element="sales-notification"] {
  --o-sales-bg: var(--asas-bg);
  --o-sales-fg: var(--asas-fg);
  --o-sales-border: 1px solid var(--asas-border);
  --o-sales-radius: var(--asas-radius);
  --o-sales-shadow: 0 8px 20px rgb(0 0 0 / 0.10);
  --o-sales-image-radius: var(--asas-radius);
  --o-sales-font: var(--asas-font-body);
}
[data-o-element="sales-notification"] [data-o-part="card"] { color: var(--asas-fg); }
/* The secondary lines take a tone DERIVED from this card's own ink and ground,
   not the theme's muted setting.
 *
 * A merchant may set the muted colour for body copy on a wide, calm page;
 * this card is small, dense and gone in four seconds. Measured on the live
 * demo stores, the merchant-chosen muted came out at 3.87:1 on أساس and
 * 2.88:1 on جُرأة's cream scheme — under AA at 13px. A mix is always the same
 * distance between ink and ground whatever the palette, so the floor holds on
 * every store that installs the theme. The plain declaration first is what a
 * browser without `color-mix` keeps. */
[data-o-element="sales-notification"] [data-o-part="message"],
[data-o-element="sales-notification"] [data-o-part="purchased"],
[data-o-element="sales-notification"] [data-o-part="time"] {
  color: var(--asas-muted);
  color: color-mix(in oklab, var(--asas-fg) 68%, var(--asas-bg));
  opacity: 1;
}
[data-o-element="sales-notification"] [data-o-part="customer"],
[data-o-element="sales-notification"] [data-o-part="location"] {
  color: var(--asas-fg);
  font-weight: 600;
}
[data-o-element="sales-notification"] [data-o-part="product"] {
  color: var(--asas-fg);
  font-family: var(--asas-font-heading);
  font-weight: 600;
}
[data-o-element="sales-notification"] [data-o-part="close"] { color: var(--asas-muted); }
