/* TECH ZONE
   A parts catalogue. Hairlines instead of shadows, hard corners instead of
   pills, monospace for anything a person has to match against a part in their
   hand. One stylesheet serves Arabic and English: every directional value uses
   a logical property, so nothing needs mirroring by hand. */

:root {
  --paper: #fbfbfa;
  --surface: #ffffff;
  --ink: #16141c;
  --ink-2: #2a2733;
  --muted: #6e6a7c;
  --rule: #e3e1e8;
  /* 3.03:1 against the page, which is what WCAG asks of a control's edge.
     The old #c9c6d2 looked nicer and was only 1.6:1, which is invisible to
     plenty of people. */
  --rule-strong: #938fa3;

  --violet: #6d28d9;
  --violet-press: #5b21b6;
  --violet-tint: #f4f1fe;
  --violet-edge: #d9cdfb;

  --ok: #15803d;
  --warn: #b45309;
  --gone: #6e6a7c;

  /* Rounded, on his instruction: "a little bit rounded ... for modern design".
     Controls get --radius, panels get --radius-lg. Still not pills. */
  --radius: 8px;
  --radius-sm: 6px;
  --radius-lg: 14px;
  --lift: 0 1px 2px rgba(22, 20, 28, .06), 0 8px 24px rgba(22, 20, 28, .07);

  --sans: "Plus Jakarta Sans", "Segoe UI", sans-serif;
  --arabic: "Cairo", "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", monospace;

  --wrap: 1280px;
  --gutter: 16px;
}

:root[dir="rtl"] { --sans: "IBM Plex Sans Arabic", "Segoe UI", sans-serif; }

*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  font-synthesis-weight: none;
}

/* On a short page the footer used to stop halfway and leave a band of page
   background under it. main takes the slack instead. */
main { flex: 1 0 auto; }
.foot { flex: none; }

:lang(ar) { font-family: var(--arabic); }

h1, h2, h3, h4 {
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0;
}
:root[dir="rtl"] h1, :root[dir="rtl"] h2,
:root[dir="rtl"] h3, :root[dir="rtl"] h4 { letter-spacing: 0; }

h1 { font-size: 34px; }
h2 { font-size: 22px; }
h3 { font-size: 17px; }

p { margin: 0 0 1em; }

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* height:auto keeps a width/height attribute from fixing the rendered height
   and stretching a photo whose real ratio differs. The media boxes below
   reserve their space with aspect-ratio, so nothing shifts as images load. */
img { max-width: 100%; height: auto; display: block; }

/* Numbers and codes always read unambiguously. Words never get the code
   font: the currency and the stock label are words. */
.code, .num, input[inputmode="numeric"], .mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  direction: ltr;
  unicode-bidi: isolate;
}

/* Prices are read, not matched against a part in your hand, so they get the
   body face. Tabular figures keep a column of them lined up. */
.price {
  font-family: var(--sans);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  direction: ltr;
  unicode-bidi: isolate;
  letter-spacing: -0.01em;
}
:root[dir="rtl"] .price { font-family: var(--arabic); }
.cur {
  font-family: var(--sans);
  font-weight: 500;
  font-size: .8em;
  color: var(--muted);
  margin-inline-start: 5px;
}
:root[dir="rtl"] .cur { font-family: var(--arabic); }

:focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 2px;
  border-radius: 1px;
}

.skip {
  position: absolute;
  inset-inline-start: -9999px;
  top: 0;
  background: var(--violet);
  color: #fff;
  padding: 10px 16px;
  z-index: 100;
}
.skip:focus { inset-inline-start: 0; }

.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
@media (min-width: 768px) { :root { --gutter: 32px; } }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Catalogue text can be either language. `plaintext` resolves each paragraph's
   direction from its own first strong character, so an English product name in
   an Arabic page keeps its full stop at the end instead of throwing it to the
   far side. It leaves `direction` alone, so text-align still follows the page
   and the column stays visually flush. Use it on anything the shop typed. */
.bidi { unicode-bidi: plaintext; }
/* plaintext resolves text-align against the paragraph's own direction,
   which would leave an English title flush left inside an otherwise
   right-aligned Arabic column. Pin the alignment back to the page so
   the column stays on one edge. */
:root[dir="rtl"] .bidi { text-align: right; }
:root[dir="ltr"] .bidi { text-align: left; }

/* ---------------------------------------------------------------- header */

.topbar {
  background: var(--ink);
  color: #fff;
  position: sticky;
  top: 0;
  z-index: 50;
  transition: background-color .2s ease;
}
/* Scrolled state: you should just about see the page moving behind it. */
.topbar.is-stuck {
  background: rgba(22, 20, 28, .78);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .08), 0 10px 30px rgba(22, 20, 28, .18);
}
/* Without backdrop-filter, translucency would wreck the contrast. Stay solid. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar.is-stuck { background: rgba(22, 20, 28, .97); }
}

.topbar__row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-block: 12px;
}

.brand { display: flex; align-items: center; gap: 10px; flex: none; }
.brand:hover { text-decoration: none; }
.brand img { width: 40px; height: 40px; border-radius: 2px; }
.brand__name {
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 0.01em;
  line-height: 1;
  white-space: nowrap;
}
.brand__name span { color: #b38cf7; }

/* search is the widest thing on the page, because it is the product */
.search { position: relative; flex: 1 1 auto; min-width: 0; }
/* One control, one edge. It used to read as a box inside a box: the field
   drew a border and the button sat against it leaving a seam. */
.search__field {
  display: flex;
  align-items: center;
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: var(--radius);
  overflow: hidden;
}
.search__field:focus-within {
  border-color: var(--violet);
  box-shadow: 0 0 0 3px var(--violet-tint);
}
.search__field svg { flex: none; margin-inline: 12px 0; color: var(--muted); }
.search__field input[type="search"] {
  flex: 1;
  min-width: 0;
  border: 0;
  border-radius: 0;
  background: none;
  padding: 12px 14px;
  min-height: 0;
  font: inherit;
  font-size: 14px;
  color: var(--ink);
}
.search__field input[type="search"]::placeholder { color: var(--muted); }
.search__field input[type="search"]:focus,
.search__field input[type="search"]:focus-visible {
  outline: none;
  border: 0;
  box-shadow: none;
}
.search__go {
  flex: none;
  border: 0;
  background: var(--violet);
  color: #fff;
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  padding: 12px 20px;
  cursor: pointer;
  align-self: stretch;
}
.search__go:hover { background: var(--violet-press); }

.suggest {
  position: absolute;
  inset-inline: 0;
  top: calc(100% + 6px);
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  box-shadow: var(--lift);
  z-index: 40;
  overflow: hidden;
}
.suggest[hidden] { display: none; }
.suggest a {
  display: grid;
  grid-template-columns: 40px 1fr;
  gap: 12px;
  align-items: center;
  padding: 11px 14px;
  border-block-end: 1px solid var(--rule);
  color: var(--ink);
}
.suggest__ph {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--paper);
  border: 1px dashed var(--rule-strong);
}
.suggest a:last-child { border-block-end: 0; }
.suggest a:hover, .suggest a.is-active {
  background: var(--violet-tint);
  text-decoration: none;
}
.suggest img { width: 40px; height: 40px; object-fit: contain; }
.suggest__name { font-size: 14px; min-width: 0; }
.suggest__sku { font-size: 11px; color: var(--muted); }
.suggest__price { font-size: 14px; font-weight: 500; }
.suggest__empty { padding: 14px 12px; color: var(--muted); font-size: 14px; }

.topbar__actions { display: flex; align-items: center; gap: 8px; flex: none; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 12px;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: var(--radius);
  color: #fff;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
}
.chip:hover { background: rgba(255, 255, 255, .1); text-decoration: none; }
.chip--cart { border-color: rgba(255, 255, 255, .4); }
.chip__count {
  font-family: var(--mono);
  font-size: 12px;
  background: var(--violet);
  padding: 1px 6px;
  border-radius: 2px;
}

/* On a phone the three header pieces cannot share one row, so the search
   drops to a line of its own rather than pushing the page sideways. */
@media (max-width: 767px) {
  .topbar__row { flex-wrap: wrap; row-gap: 10px; padding-block: 10px; }
  .search { order: 3; flex: 1 0 100%; }
  .topbar__actions { margin-inline-start: auto; }
  .brand img { width: 34px; height: 34px; }
  .brand__name { font-size: 15px; }
  .chip { padding: 8px 10px; font-size: 12px; }
  .search__go { padding: 11px 14px; }
  .nav a { padding: 11px 12px; }

  /* The header no longer rearranges itself on scroll. It used to collapse
     three rows into one, and swapping the layout mid-scroll read as a jump.
     It just scrolls away now, and .minibar slides down in its place. */
  .topbar { position: static; }
}

/* Phone only. One element, one transform, so the entrance is a slide rather
   than a relayout. */
.minibar { display: none; }
@media (max-width: 767px) {
  .minibar {
    display: flex;
    align-items: center;
    gap: 8px;
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    z-index: 60;
    padding: 9px var(--gutter);
    background: rgba(22, 20, 28, .82);
    backdrop-filter: blur(16px) saturate(140%);
    -webkit-backdrop-filter: blur(16px) saturate(140%);
    box-shadow: 0 6px 24px rgba(22, 20, 28, .26);
    transform: translateY(-104%);
    transition: transform .28s cubic-bezier(.4, 0, .2, 1);
    will-change: transform;
  }
  .minibar.is-on { transform: translateY(0); }
  .minibar .search { flex: 1 1 auto; min-width: 0; }
  .minibar .chip--cart { flex: none; padding: 10px 11px; }
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .minibar { background: rgba(22, 20, 28, .97); }
  }
  @media (prefers-reduced-motion: reduce) {
    .minibar { transition: none; }
  }
}

.nav {
  display: flex;
  align-items: center;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: none;
}
.nav::-webkit-scrollbar { display: none; }
.nav a {
  padding: 12px 14px;
  font-size: 14px;
  font-weight: 500;
  color: rgba(255, 255, 255, .78);
  white-space: nowrap;
  border-block-end: 2px solid transparent;
}
.nav a:hover { color: #fff; text-decoration: none; }
.nav a.is-on { color: #fff; border-block-end-color: var(--violet); }

/* ------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 18px;
  border-radius: var(--radius);
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 500;
  font-size: 14px;
  cursor: pointer;
  text-align: center;
}
.btn:hover { border-color: var(--ink); text-decoration: none; }
.btn--primary {
  background: var(--violet);
  border-color: var(--violet);
  color: #fff;
}
.btn--primary:hover { background: var(--violet-press); border-color: var(--violet-press); }
.btn--wide { width: 100%; }
.btn--sm { min-height: 36px; font-size: 13px; padding: 0 14px; }
/* The multiplication sign sits above the centre of its own line box in most
   faces, so the button looked off no matter how the box was aligned. The
   cross is drawn instead, which puts it dead centre whatever the font does. */
.btn--icon {
  position: relative;
  width: 40px;
  min-width: 40px;
  padding: 0;
  font-size: 0;
  color: var(--muted);
}
.btn--icon::before,
.btn--icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 13px;
  height: 1.5px;
  border-radius: 1px;
  background: currentColor;
}
.btn--icon::before { transform: translate(-50%, -50%) rotate(45deg); }
.btn--icon::after { transform: translate(-50%, -50%) rotate(-45deg); }
.btn--icon:hover { color: #b3261e; border-color: #b3261e; }
.btn.is-added { border-color: var(--ok); color: var(--ok); }
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  pointer-events: none;
}
/* Was WhatsApp green. He asked why a foreign brand colour was on his site,
   which was a fair question, so these use the shop's accent now. */
.btn--wa { background: var(--violet); border-color: var(--violet); color: #fff; }
.btn--wa:hover { background: var(--violet-press); border-color: var(--violet-press); }

/* ------------------------------------------------------------- sections */

.section { padding-block: 40px; }
.section__head {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-block-end: 20px;
}
/* the rule runs out from the title instead of a fine print label above it */
.section__head::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}
.section__head .more { flex: none; font-size: 14px; color: var(--violet); }

/* --------------------------------------------------------- product grid */

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  border: 1px solid var(--rule);
  border-inline-end: 0;
  border-block-end: 0;
  background: var(--surface);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
@media (min-width: 640px) { .grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1040px) { .grid { grid-template-columns: repeat(4, 1fr); } }

/* A row of two related parts should not leave the lattice hanging open, so a
   short grid narrows to the number of items it actually has. */
.grid--n1 { grid-template-columns: 1fr; max-width: 330px; }
@media (min-width: 640px) {
  .grid--n2 { grid-template-columns: repeat(2, 1fr); max-width: 660px; }
}
@media (min-width: 1040px) {
  .grid--n2 { max-width: 660px; }
  .grid--n3 { grid-template-columns: repeat(3, 1fr); max-width: 990px; }
}

.cell {
  border-inline-end: 1px solid var(--rule);
  border-block-end: 1px solid var(--rule);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
  background: var(--surface);
}
.cell:hover { background: var(--violet-tint); }
.cell__media {
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  background: var(--surface);
  padding: 6px;
}
.cell__media img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  mix-blend-mode: multiply;
}
.cell__media--empty {
  border: 1px dashed var(--rule-strong);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
}
.cell__sku { font-size: 11px; color: var(--muted); }
.cell__name {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.35;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cell__name a::after { content: ""; position: absolute; inset: 0; }
.cell__foot { margin-block-start: auto; display: grid; gap: 8px; }
.cell__prices { display: flex; align-items: baseline; gap: 12px; }
.cell__prices .price { font-size: 16px; font-weight: 700; }
/* The old price used to sit at almost the same size as the live one, so a
   pair like "250 230" read as one number. It is now clearly the quieter of
   the two. */
.price--old {
  font-size: 12px;
  font-weight: 400;
  color: var(--muted);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  letter-spacing: 0;
  opacity: .75;
}
.price--old .cur { display: none; }
.cell .btn { position: relative; z-index: 1; }

/* the one place a pill is right, because it reads as a status */
.stock {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
}

.stock--in { color: var(--ok); }
.stock--low { color: var(--warn); }
/* Out of stock is a stop, not a shrug. Grey read as ordinary small print
   next to the price and people missed it. */
.stock--out { color: #b3261e; font-weight: 600; }

/* --------------------------------------------------------------- shop */

.shop { display: grid; gap: 24px; padding-block: 24px; }
@media (min-width: 900px) { .shop { grid-template-columns: 240px 1fr; } }

.rail { align-self: start; }
@media (min-width: 900px) { .rail { position: sticky; top: 16px; } }

/* On a phone the filter rail was a slab you had to scroll past, and putting
   it under the grid meant you could only filter after browsing. It is a sheet
   now, opened from a button that sits above the products. */
.toolbar__filters { display: none; }
.rail__head { display: none; }
.rail__scrim { display: none; }

@media (max-width: 899px) {
  .shop__main { order: 1; }
  .toolbar__filters { display: inline-flex; gap: 7px; }

  .rail {
    order: 2;
    position: fixed;
    inset-block: 0;
    inset-inline: 0;
    z-index: 80;
    background: var(--surface);
    padding: 0 var(--gutter) calc(20px + env(safe-area-inset-bottom));
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateY(100%);
    visibility: hidden;
    transition: transform .3s cubic-bezier(.4, 0, .2, 1), visibility .3s;
  }
  .rail.is-open { transform: translateY(0); visibility: visible; }

  .rail__head {
    display: flex;
    align-items: center;
    gap: 12px;
    position: sticky;
    top: 0;
    z-index: 1;
    padding-block: 16px 12px;
    background: var(--surface);
    border-block-end: 1px solid var(--rule);
  }
  .rail__head h2 { font-size: 18px; flex: 1; }

  .rail__cats { max-height: none; }
  .rail__done { margin-block-start: 18px; }

  .rail__scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 79;
    background: rgba(22, 20, 28, .45);
    opacity: 0;
    visibility: hidden;
    transition: opacity .3s, visibility .3s;
  }
  .rail__scrim.is-open { opacity: 1; visibility: visible; }

  @media (prefers-reduced-motion: reduce) {
    .rail, .rail__scrim { transition: none; }
  }
}
@media (min-width: 900px) {
  .rail__done { display: none; }
}
.rail__group { border-block-end: 1px solid var(--rule); padding-block: 14px; }
.rail__group:first-child { padding-block-start: 0; }
.rail h3 { font-size: 14px; margin-block-end: 10px; }
.rail label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  padding-block: 4px;
  cursor: pointer;
}
.rail__cats { max-height: 320px; overflow-y: auto; display: grid; gap: 2px; }
.rail__cats a {
  font-size: 14px;
  padding: 4px 8px;
  border-radius: 2px;
  color: var(--muted);
}
.rail__cats a:hover { background: var(--violet-tint); color: var(--ink); text-decoration: none; }
.rail__cats a.is-on { background: var(--violet-tint); color: var(--violet); font-weight: 500; }
.rail__cats .sub { padding-inline-start: 20px; }

.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding-block-end: 14px;
  border-block-end: 1px solid var(--rule);
  margin-block-end: 0;
}
.toolbar__count { font-size: 14px; color: var(--muted); }
.toolbar__count b { color: var(--ink); font-family: var(--mono); font-weight: 500; }
.toolbar .spacer { flex: 1; }

.field {
  display: grid;
  gap: 6px;
}
.field > label { font-size: 13px; font-weight: 500; }
.field .hint { font-size: 12px; color: var(--muted); }
.field .err { font-size: 12px; color: #b3261e; }
input[type="text"], input[type="tel"], input[type="email"],
input[type="number"], input[type="search"], input[type="password"],
select, textarea {
  width: 100%;
  font: inherit;
  font-size: 14px;
  padding: 10px 14px;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  min-height: 44px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none;
  border-color: var(--violet);
  box-shadow: 0 0 0 3px var(--violet-tint);
}
textarea { min-height: 110px; resize: vertical; line-height: 1.5; }
select { appearance: none; padding-inline-end: 38px; cursor: pointer; }

/* The browser's number spinners are two tiny grey arrows nobody can hit.
   The cart and the quantity boxes draw their own controls instead. */
input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.select {
  position: relative;
  display: inline-block;
}
.select::after {
  content: "";
  position: absolute;
  inset-inline-end: 14px;
  top: 50%;
  width: 9px;
  height: 9px;
  /* physical, not logical. A chevron pointing down means the same thing in
     both directions, but border-inline-end flips to the left in Arabic and
     swings the arrow round to point sideways. */
  border-right: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
  transition: transform .15s ease;
}
.select:hover::after { transform: translateY(-45%) rotate(45deg); }
.has-error input, .has-error select, .has-error textarea { border-color: #b3261e; }

.pager { display: flex; gap: 6px; justify-content: center; padding-block: 28px; }
.pager a, .pager span {
  min-width: 40px;
  min-height: 40px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: 13px;
  background: var(--surface);
}
.pager .is-on { background: var(--violet); border-color: var(--violet); color: #fff; }

.empty {
  border: 1px solid var(--rule);
  background: var(--surface);
  padding: 48px 24px;
  text-align: center;
  border-radius: var(--radius-lg);
}
.empty h2 { margin-block-end: 8px; }
.empty p { color: var(--muted); max-width: 46ch; margin-inline: auto; }

/* ------------------------------------------------------------- product */

.product { display: grid; gap: 28px; padding-block: 28px; }
@media (min-width: 900px) { .product { grid-template-columns: 1.1fr 1fr; gap: 48px; } }

.gallery__main {
  border: 1px solid var(--rule);
  background: var(--surface);
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  padding: 24px;
}
.gallery__main img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  mix-blend-mode: multiply;
}
.gallery__strip { display: flex; gap: 8px; margin-block-start: 8px; flex-wrap: wrap; }
.gallery__strip button {
  width: 64px; height: 64px;
  border: 1px solid var(--rule);
  background: var(--surface);
  padding: 4px;
  cursor: pointer;
  border-radius: var(--radius);
}
.gallery__strip button[aria-current="true"] { border-color: var(--violet); }
.gallery__strip img { width: 100%; height: 100%; object-fit: contain; }

.crumbs { font-size: 13px; color: var(--muted); padding-block: 14px; }
.crumbs a:hover { color: var(--ink); }
.crumbs span { margin-inline: 6px; }

.product__title { font-size: 26px; margin-block-end: 10px; }
.product__meta { display: flex; gap: 16px; flex-wrap: wrap; align-items: center; font-size: 13px; color: var(--muted); }
.product__price { font-size: 27px; font-weight: 700; }
.product__buy {
  border: 1px solid var(--rule);
  background: var(--surface);
  padding: 16px;
  display: grid;
  gap: 12px;
  margin-block: 20px;
}
.qty {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}
.qty button {
  width: 42px;
  border: 0;
  background: var(--surface);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  color: var(--ink);
  transition: background-color .12s ease, color .12s ease;
}
.qty button:hover { background: var(--violet); color: #fff; }
/* It used to scale down on press, which exposed the white behind it and
   looked like the button was coming apart. Darken instead. */
.qty button:active { background: var(--violet-press); color: #fff; }
.qty input {
  width: 54px;
  border: 0;
  border-inline: 1px solid var(--rule-strong);
  text-align: center;
  min-height: 42px;
  border-radius: 0;
  font-weight: 600;
}
.qty input:focus-visible { box-shadow: none; border-color: var(--rule-strong); }

/* the cart's copy, a size down */
.qty--sm button { width: 34px; font-size: 17px; }
.qty--sm input { width: 44px; min-height: 34px; font-size: 14px; }

/* Adding something no longer throws you into the cart. This says it worked
   and offers the cart if you want it, otherwise it gets out of the way. */
.toastbar {
  position: fixed;
  inset-block-end: 22px;
  inset-inline: 0;
  margin-inline: auto;
  width: max-content;
  max-width: calc(100% - 32px);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 14px 12px 18px;
  background: var(--ink);
  color: #fff;
  border-radius: var(--radius-lg);
  box-shadow: 0 10px 40px rgba(22, 20, 28, .32);
  font-size: 14px;
  animation: toast-in .22s ease-out;
}
:root[dir="rtl"] .toastbar { padding: 12px 18px 12px 14px; }
.toastbar__msg { font-weight: 500; }
.toastbar__go {
  background: var(--violet);
  color: #fff;
  padding: 8px 14px;
  border-radius: var(--radius);
  font-weight: 600;
  white-space: nowrap;
}
.toastbar__go:hover { background: var(--violet-press); text-decoration: none; }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .toastbar { animation: none; } }

.foot__by { color: rgba(255, 255, 255, .45); margin-inline-start: 10px; }
/* His name sits at the same weight as the words around it, not brighter. */
.foot__by .code { color: inherit; }
.buy-row { display: flex; gap: 10px; align-items: stretch; }
.buy-row .btn { flex: 1; }

.specs { width: 100%; border-collapse: collapse; font-size: 14px; }
.specs th, .specs td {
  text-align: start;
  padding: 9px 12px;
  border-block-end: 1px solid var(--rule);
  vertical-align: top;
}
.specs th { font-weight: 500; color: var(--muted); width: 42%; }
.specs td { font-family: var(--mono); font-size: 13px; }

.prose { font-size: 15px; }
.prose h2 { font-size: 19px; margin-block: 24px 10px; }
.prose h3 { font-size: 16px; margin-block: 20px 8px; }
.prose ul, .prose ol { padding-inline-start: 22px; margin-block: 0 1em; }
.prose li { margin-block-end: 6px; }
.prose a { color: var(--violet); text-decoration: underline; }

.panel {
  border: 1px solid var(--rule);
  background: var(--surface);
  padding: 22px;
  border-radius: var(--radius-lg);
}
.panel--tint { background: var(--violet-tint); border-color: var(--violet-edge); }

/* ----------------------------------------------------- cart and checkout */

.lines { width: 100%; border-collapse: collapse; }
.lines th {
  text-align: start;
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  padding: 10px 12px;
  border-block-end: 1px solid var(--rule-strong);
}
.lines td {
  padding: 14px 12px;
  border-block-end: 1px solid var(--rule);
  vertical-align: middle;
}
/* The total and the remove button used to sit on different lines. */
/* Fixed widths, otherwise going from 9 to 18 EGP widens the total column
   and the whole quantity stepper slides sideways as you click it. */
/* .price forces direction:ltr, which makes text-align:start resolve to left
   even on an Arabic page. That left the unit price hanging under the wrong
   edge of the product name. This line follows the page instead, with the
   number itself still resolved left to right. */
.lines__unit {
  direction: inherit;
  unicode-bidi: plaintext;
  text-align: start;
}

.lines__qty { width: 128px; }
.lines__total {
  width: 110px;
  text-align: end;
  white-space: nowrap;
  font-size: 14px;
}
.lines__rm { width: 58px; text-align: end; }
.lines .thumb { width: 64px; height: 64px; object-fit: contain; mix-blend-mode: multiply; }
.lines__name { font-weight: 500; font-size: 14px; }
.lines__sku { font-size: 11px; color: var(--muted); }
/* The summary lines carried the part code as well as the count. The count is
   the part anyone actually needs to check, so the code goes. */
.lines__count {
  font-size: 12px;
  color: var(--muted);
  direction: inherit;
  unicode-bidi: plaintext;
  text-align: start;
}
.lines__thumb { width: 80px; }

/* Five columns do not fit on a phone, and the photo is the one that earns
   its place least in a list you already chose from. */
@media (max-width: 639px) {
  .lines__thumb { display: none; }
  .lines th, .lines td { padding: 10px 6px; }
}

.totals { display: grid; gap: 10px; }
.totals__row { display: flex; justify-content: space-between; gap: 16px; font-size: 14px; }
.totals__row--grand {
  border-block-start: 1px solid var(--rule-strong);
  padding-block-start: 10px;
  font-size: 18px;
  font-weight: 600;
}
.free { color: var(--ok); font-weight: 500; }

.checkout { display: grid; gap: 24px; padding-block: 24px; }
@media (min-width: 900px) { .checkout { grid-template-columns: 1.4fr 1fr; gap: 40px; align-items: start; } }
.form-grid { display: grid; gap: 16px; }
@media (min-width: 560px) { .form-grid--2 { grid-template-columns: 1fr 1fr; } }
.consent {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}
.consent input { margin-block-start: 3px; flex: none; width: 18px; height: 18px; }

.notice {
  border: 1px solid var(--rule-strong);
  border-inline-start: 3px solid var(--violet);
  background: var(--surface);
  padding: 14px 16px;
  font-size: 14px;
  border-radius: var(--radius);
}
.notice--bad { border-inline-start-color: #b3261e; }
.notice--good { border-inline-start-color: var(--ok); }

/* A tracking rail, the way a delivery app shows it: numbered stops joined by
   a line that fills in behind you. */
.steps {
  display: flex;
  counter-reset: s;
  margin: 0;
  padding: 0;
  list-style: none;
}
.steps li {
  flex: 1;
  position: relative;
  padding-block-start: 38px;
  text-align: center;
  font-size: 12px;
  line-height: 1.35;
  color: var(--muted);
}
.steps li::before {
  counter-increment: s;
  content: counter(s);
  position: absolute;
  top: 0;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 12px;
  background: var(--surface);
  border: 2px solid var(--rule-strong);
  border-radius: 50%;
  color: var(--muted);
  z-index: 1;
}
:root[dir="rtl"] .steps li::before { transform: translateX(50%); }
/* the road to the next stop */
.steps li::after {
  content: "";
  position: absolute;
  top: 13px;
  inset-inline-start: 50%;
  width: 100%;
  height: 2px;
  background: var(--rule-strong);
}
.steps li:last-child::after { display: none; }

.steps li.is-done { color: var(--ink); }
.steps li.is-done::before {
  background: var(--ok);
  border-color: var(--ok);
  color: #fff;
}
.steps li.is-done::after { background: var(--ok); }
.steps li.is-now { color: var(--ink); font-weight: 600; }
.steps li.is-now::before {
  background: var(--violet);
  border-color: var(--violet);
  color: #fff;
  box-shadow: 0 0 0 4px var(--violet-tint);
}

/* Five stops will not fit across a phone, so it stands up instead. */
@media (max-width: 559px) {
  .steps { display: grid; gap: 0; }
  .steps li {
    text-align: start;
    padding-block: 0 18px;
    padding-inline-start: 42px;
    min-height: 34px;
  }
  .steps li::before { inset-inline-start: 0; transform: none; }
  :root[dir="rtl"] .steps li::before { transform: none; }
  .steps li::after {
    top: 28px;
    inset-inline-start: 13px;
    width: 2px;
    height: 100%;
  }
}

/* ---------------------------------------------------------- categories */

.dir { columns: 1; column-gap: 24px; padding-block: 24px; }
@media (min-width: 700px) { .dir { columns: 2; } }
@media (min-width: 1040px) { .dir { columns: 3; } }
.dir__block { break-inside: avoid; margin-block-end: 24px; }
.dir__block h2 {
  font-size: 15px;
  padding-block-end: 8px;
  border-block-end: 1px solid var(--rule-strong);
  margin-block-end: 8px;
}
.dir__block h2 .n { font-family: var(--mono); font-size: 12px; color: var(--muted); font-weight: 400; }
.dir__block ul { list-style: none; margin: 0; padding: 0; }
.dir__block li a {
  display: block;
  padding: 5px 0;
  font-size: 14px;
  color: var(--muted);
}
.dir__block li a:hover { color: var(--violet); text-decoration: none; }

/* Borders on the cells, not a gap showing a coloured backdrop. An incomplete
   last row then just ends, instead of leaving a grey block. */
.tiles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
@media (min-width: 640px) { .tiles { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1040px) { .tiles { grid-template-columns: repeat(4, 1fr); } }
/* One line, one weight, vertically centred. The old version stacked a big
   name over a tiny number and nothing lined up. */
.tile {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 18px 20px;
  min-height: 68px;
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
}
.tile:hover {
  background: var(--violet-tint);
  border-color: var(--violet-edge);
  text-decoration: none;
}
.tile__name { flex: 1; min-width: 0; }
.tile__go {
  flex: none;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--rule-strong);
  border-top: 2px solid var(--rule-strong);
  transform: rotate(45deg);
  transition: border-color .15s ease, transform .15s ease;
}
:root[dir="rtl"] .tile__go { transform: rotate(-135deg); }
.tile:hover .tile__go { transform: rotate(45deg) translate(2px, -2px); }
:root[dir="rtl"] .tile:hover .tile__go { transform: rotate(-135deg) translate(2px, -2px); }
.tile:hover .tile__go { border-color: var(--violet); }

/* ------------------------------------------------------------ services */

.svc { display: grid; gap: 12px; }
@media (min-width: 760px) { .svc { grid-template-columns: repeat(2, 1fr); } }
.svc__item {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 24px;
  display: grid;
  gap: 10px;
  align-content: start;
}
.svc__item:hover { border-color: var(--violet-edge); }
.svc__item h3 { font-size: 17px; }
.svc__item p { color: var(--muted); font-size: 14px; margin: 0; }
.svc__price { font-size: 13px; color: var(--muted); }

/* -------------------------------------------------------------- footer */

.foot { background: var(--ink); color: rgba(255, 255, 255, .72); margin-block-start: 56px; }
.foot__cols { display: grid; gap: 28px; padding-block: 40px; }
@media (min-width: 700px) { .foot__cols { grid-template-columns: 1.4fr repeat(3, 1fr); } }
.foot h3 { color: #fff; font-size: 14px; margin-block-end: 12px; }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.foot a { font-size: 14px; }
.foot a:hover { color: #fff; }
.foot__legal {
  border-block-start: 1px solid rgba(255, 255, 255, .12);
  padding-block: 18px;
  font-size: 12px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  justify-content: center;
  text-align: center;
}
.foot__biz { font-family: var(--mono); font-size: 11px; line-height: 1.7; }
.foot__note {
  display: block;
  font-size: 11px;
  color: rgba(255, 255, 255, .45);
  margin-block-start: 2px;
}

/* --------------------------------------------------------------- home */

.hero {
  border-block-end: 1px solid var(--rule);
  background: var(--surface);
  padding-block: 44px 36px;
}
/* The heading names what is sold, for anyone arriving from a search that
   might have landed them anywhere. It is not the loudest thing on the page
   any more; the search box is. */
.hero h1 { font-size: 28px; max-width: 20ch; }
@media (min-width: 760px) { .hero h1 { font-size: 36px; } }
.hero p { color: var(--muted); max-width: 56ch; margin-block: 10px 0; }

.hero__search { margin-block-start: 20px; max-width: 680px; flex: none; }
.hero__search .search__field {
  border-color: var(--rule-strong);
  border-radius: var(--radius-lg);
}
.hero__search input[type="search"] { padding: 16px 14px; font-size: 16px; }
.hero__search .search__field svg { margin-inline-start: 16px; }
.hero__search .search__go { padding-inline: 22px; align-self: stretch; }
/* the panel has to clear a taller field than the header's */
.hero__search .suggest { inset-block-start: calc(100% + 6px); }
/* Real part numbers people type, so they are links worth the size of a
   target. They used to be 12px grey text that read as a caption. */
.hero__quick { display: flex; gap: 10px; flex-wrap: wrap; margin-block-start: 22px; }
.hero__quick a {
  font-family: var(--mono);
  font-size: 14px;
  padding: 9px 16px;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-2);
}
.hero__quick a:hover {
  border-color: var(--violet);
  background: var(--violet-tint);
  color: var(--violet);
  text-decoration: none;
}

/* ------------------------------------------------------------- utility */

.stack { display: grid; gap: 16px; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }

@media (prefers-reduced-motion: no-preference) {
  .cell, .tile, .btn, .chip { transition: background-color .12s ease, border-color .12s ease; }
}

@media print {
  .topbar, .foot, .rail, .btn { display: none; }
  body { background: #fff; }
}

/* ------------------------------------------------------- the dropdown

   A native <select> is styled only until you click it. The list that opens
   belongs to the operating system, so it arrives with its own font, its own
   blue highlight and square corners, and it makes the page look like two
   different sites. select.js draws the open state instead, and these are the
   styles for it. The closed button reuses the input shape so a dropdown and
   a text field still sit level next to each other. */

.sel { position: relative; display: inline-block; width: 100%; }
/* the arrow on .select is drawn over the native control; here the button
   owns it, so the wrapper's own chevron steps aside */
.sel.select::after { display: none; }

.sel__btn {
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  padding-inline-end: 38px;
  font: inherit;
  font-size: 14px;
  text-align: start;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  cursor: pointer;
  display: flex;
  align-items: center;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.sel__btn::after {
  content: "";
  position: absolute;
  inset-inline-end: 14px;
  top: 50%;
  width: 9px;
  height: 9px;
  /* physical: down is down in both directions, see .select::after */
  border-right: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: translateY(-70%) rotate(45deg);
  transition: transform .15s ease;
  pointer-events: none;
}
.sel__btn:hover { border-color: var(--ink-2); }
.sel__btn:focus-visible {
  outline: none;
  border-color: var(--violet);
  box-shadow: 0 0 0 3px var(--violet-tint);
}
.sel.is-open .sel__btn {
  border-color: var(--violet);
  box-shadow: 0 0 0 3px var(--violet-tint);
}
.sel.is-open .sel__btn::after { transform: translateY(-25%) rotate(225deg); }

.sel__value {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sel__value.is-placeholder { color: var(--muted); }

.sel__list {
  position: absolute;
  z-index: 60;
  /* The list is its own white panel wherever it opens. Inheriting colour
     meant that inside the dark bulk bar every option came out white text on
     a white panel, which is to say invisible. */
  color: var(--ink);
  inset-inline: 0;
  top: calc(100% + 6px);
  max-height: 280px;
  overflow-y: auto;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--lift);
}
/* near the bottom of a short sheet, open upwards instead */
.sel--up .sel__list { top: auto; bottom: calc(100% + 6px); }

.sel__opt {
  color: var(--ink);
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
}
.sel__opt:hover { background: var(--violet-tint); }
.sel__opt.is-on { background: var(--violet-tint); font-weight: 600; }
/* the tick, so the chosen row reads without relying on colour alone */
.sel__opt.is-on::after {
  content: "";
  margin-inline-start: auto;
  width: 5px;
  height: 9px;
  border-right: 2px solid var(--violet);
  border-bottom: 2px solid var(--violet);
  transform: rotate(45deg);
  flex: none;
}
.sel__opt[aria-disabled="true"] {
  color: var(--muted);
  cursor: default;
  background: none;
}

/* ------------------------------------------------- admin order controls */

/* Names the stop it moves the order to, with a chevron after it, instead of
   a bare arrow you have to hover to understand. */
.btn--step {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.btn--step svg { flex: none; opacity: .7; transition: transform .15s ease; }
.btn--step:hover svg { transform: translateX(2px); opacity: 1; }
:root[dir="rtl"] .btn--step svg { transform: scaleX(-1); }
:root[dir="rtl"] .btn--step:hover svg { transform: scaleX(-1) translateX(2px); }

