/* ============================================================
   ARABNA — Design System  (V.02.5)
   Two themes from one set of symbols. Every colour in the app is a
   **role** (`--surface`, `--text`), never a raw value: the symbol says
   what a colour is for, and the theme decides what it is.

   Dark is the app's own look, lifted one step from the near-black it
   started at. Light is warm ivory rather than white — and never
   burgundy, which swallows the gold the whole brand is built on.

   The only things that change between the two are the navies. Gold,
   ivory, green and red keep their values on purpose; if one of them
   moves, a symbol has been wired to the wrong place.
   ============================================================ */

:root {
  color-scheme: light dark;

  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 26px;

  --header-h: 92px;
  --nav-h: 78px;

  /* Installed to the home screen the app owns the whole screen, clock and
     battery row included, so it has to reserve that strip itself. In the
     browser this resolves to 0px and nothing moves. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);

  --ease: cubic-bezier(0.22, 0.8, 0.3, 1);

  /* The saturated ad cards are the same in both themes — white text on a
     strong colour works either way, and an advertiser's artwork should
     not change under the reader. These five keep them literal-free
     without making them theme-dependent. */
  --ad-ink:   #14213d;
  --ad-cta:   rgba(255,255,255,0.94);
  --ad-badge: rgba(0,0,0,0.32);
  --ad-line:  rgba(255,255,255,0.16);
  --ad-sheen: rgba(255,255,255,0.10);
  --knob:     #FFFDF8;

  /* The previews in Settings show each theme as it really is, so their
     colours belong to no theme and never move. */
  --prev-d-bg: #0E1829;  --prev-d-bar: #263764;  --prev-d-gold: #E4C77E;
  --prev-l-bg: #DFEEF8;  --prev-l-bar: #F3F9FD;  --prev-l-gold: #7A5D28;
}

/* ---------------- dark: the default ---------------- */
:root,
:root[data-theme="dark"] {
  --bg:          #0E1829;
  --bar:         #131F39;
  --surface:     #1C2A50;
  --surface-2:   #263764;
  --text:        #F3F1EC;
  --text-2:      #D6D4CE;
  --muted:       #8B93AC;
  --gold:        #C6A15B;
  --gold-bright: #E4C77E;
  --on-gold:     #1a1206;
  --green:       #8FD0AE;
  --green-bg:    rgba(78,139,107,0.16);
  --green-line:  rgba(78,139,107,0.45);
  --danger:      #C4595C;
  --danger-ink:  #E79A9C;
  --danger-bg:   rgba(196,89,92,0.10);
  --danger-line: rgba(196,89,92,0.45);
  --blue:        #2F86D9;
  --on-blue:     #FFFDF8;

  --line:        rgba(198,161,91,0.16);
  --line-soft:   rgba(255,255,255,0.07);
  --overlay:     rgba(9,14,26,0.80);
  --input-bg:    rgba(255,255,255,0.05);
  --skeleton:    rgba(255,255,255,0.06);

  --wash-1:      rgba(255,255,255,0.03);
  --wash-2:      rgba(255,255,255,0.05);
  --wash-3:      rgba(255,255,255,0.09);
  --wash-4:      rgba(255,255,255,0.18);

  --gold-wash-1: rgba(198,161,91,0.08);
  --gold-wash-2: rgba(198,161,91,0.14);
  --gold-wash-3: rgba(198,161,91,0.35);
  --gold-wash-4: rgba(198,161,91,0.55);

  --shadow-1:    0 2px 10px rgba(0,0,0,0.35);
  --shadow-2:    0 10px 30px rgba(0,0,0,0.45);
  --shadow-frame: 0 40px 90px rgba(0,0,0,0.6);
  --glow:        rgba(198,161,91,0.10);
  --gold-glow:   rgba(228,199,126,0.45);
  --img-scrim:   rgba(0,0,0,0.32);
}

/* ---------------- light: warm ivory ---------------- */
:root[data-theme="light"] {
  /* SKY. And the correction that had to come first: `--bg` never shows on
     a phone at all — it is the space around the frame on a desktop. What
     fills a phone screen is `--bar`, with main and the header transparent
     over it. So the values that matter here are `--bar` and `--surface`,
     not `--bg`.

     And the card is LIGHTER than the page, deliberately: today they are
     one colour separated only by a border line, while the dark theme
     already does the opposite (page #0E1829, card #1C2A50). This makes
     the two themes siblings in structure and not only in colour. */
  --bg:          #CFE4F2;        /* around the frame, on a desktop only */
  --bar:         #DFEEF8;        /* the page — what fills a phone */
  --surface:     #F3F9FD;        /* the cards — lighter, so they lift off it */
  --surface-2:   #E9F3FB;
  --text:        #0C1424;
  --text-2:      #1E2942;
  --muted:       #454B5C;        /* was #5C6376 — the dim text was the pale one */
  --gold:        #7A5D28;
  --gold-bright: #5A4418;        /* measured: 4.17 on a gold wash over ivory */
  --on-gold:     #FFFDF8;
  --green:       #1F5C3D;        /* measured: 4.42 on its own pill */
  --green-bg:    rgba(38,106,72,0.13);
  --green-line:  rgba(38,106,72,0.40);
  --danger:      #B02A2E;
  --danger-ink:  #B02A2E;
  --danger-bg:   rgba(176,42,46,0.09);
  --danger-line: rgba(176,42,46,0.35);
  --blue:        #1B5FA8;
  --on-blue:     #FFFDF8;

  --line:        rgba(122,93,40,0.26);
  --line-soft:   rgba(19,30,51,0.11);
  --overlay:     rgba(19,30,51,0.45);
  --input-bg:    rgba(19,30,51,0.04);
  --skeleton:    rgba(19,30,51,0.06);

  /* white washes become navy washes, or every border and divider in the
     app disappears into the ivory */
  --wash-1:      rgba(19,30,51,0.03);
  --wash-2:      rgba(19,30,51,0.05);
  --wash-3:      rgba(19,30,51,0.09);
  --wash-4:      rgba(19,30,51,0.18);

  --gold-wash-1: rgba(122,93,40,0.08);
  --gold-wash-2: rgba(122,93,40,0.14);
  --gold-wash-3: rgba(122,93,40,0.35);
  --gold-wash-4: rgba(122,93,40,0.55);

  --shadow-1:    0 2px 10px rgba(19,30,51,0.08);
  --shadow-2:    0 10px 30px rgba(19,30,51,0.14);
  --shadow-frame: 0 40px 90px rgba(19,30,51,0.18);
  --glow:        rgba(122,93,40,0.10);
  --gold-glow:   rgba(122,93,40,0.35);
  --img-scrim:   rgba(19,30,51,0.32);
}

/* Before any script runs — and for anyone who never opens the settings —
   the device's own preference decides. The explicit attributes above
   still win, because they are set on the element itself. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]):not([data-theme="light"]) {
    /* the same values as the explicit light block — this copy exists so
       the FIRST PAINT is right before any script runs, and if the two
       drift an «auto» reader gets a different theme from a light one */
    --bg:          #CFE4F2;
    --bar:         #DFEEF8;
    --surface:     #F3F9FD;
    --surface-2:   #E9F3FB;
    --text:        #0C1424;
    --text-2:      #1E2942;
    --muted:       #454B5C;
    --gold:        #7A5D28;
    --gold-bright: #5A4418;
    --on-gold:     #FFFDF8;
    --green:       #1F5C3D;
    --green-bg:    rgba(38,106,72,0.13);
    --green-line:  rgba(38,106,72,0.40);
    --danger:      #B02A2E;
    --danger-ink:  #B02A2E;
    --danger-bg:   rgba(176,42,46,0.09);
    --danger-line: rgba(176,42,46,0.35);
    --blue:        #1B5FA8;
    --line:        rgba(122,93,40,0.26);
    --line-soft:   rgba(19,30,51,0.11);
    --overlay:     rgba(19,30,51,0.45);
    --input-bg:    rgba(19,30,51,0.04);
    --skeleton:    rgba(19,30,51,0.06);
    --wash-1:      rgba(19,30,51,0.03);
    --wash-2:      rgba(19,30,51,0.05);
    --wash-3:      rgba(19,30,51,0.09);
    --wash-4:      rgba(19,30,51,0.18);
    --gold-wash-1: rgba(122,93,40,0.08);
    --gold-wash-2: rgba(122,93,40,0.14);
    --gold-wash-3: rgba(122,93,40,0.35);
    --gold-wash-4: rgba(122,93,40,0.55);
    --shadow-1:    0 2px 10px rgba(19,30,51,0.08);
    --shadow-2:    0 10px 30px rgba(19,30,51,0.14);
    --shadow-frame: 0 40px 90px rgba(19,30,51,0.18);
    --glow:        rgba(122,93,40,0.10);
    --gold-glow:   rgba(122,93,40,0.35);
    --img-scrim:   rgba(19,30,51,0.32);
  }
}

/* The switch is instant, but not jarring: only the large surfaces fade,
   and nothing fades at all for somebody who asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  html, body, .app-header, .bottom-nav, .app-main, .card, .list-row,
  .sheet-panel, .drawer-panel {
    transition: background-color .25s var(--ease), color .25s var(--ease),
                border-color .25s var(--ease);
  }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* The base every font-size in this file is a multiple of — 106.25% is
   17px at a stock browser, and it is written as a PERCENTAGE and not as
   `17px` on purpose.

   A percentage on the root resolves against the reader's own default font
   size, so somebody who enlarged the text on their phone gets 106.25% of
   THEIR number. An absolute `17px` would have overridden them — which is
   the very fault this batch set out to fix, reintroduced one line lower
   down. It also keeps the file's own rule true: no font-size in this
   stylesheet is written in px, the base included.

   17 and not 18: 18 turns the commonest size, 12.5px, into 14px — a 12%
   jump that changes the look of the whole app at once, and nobody could
   say afterwards which half of the change they were reacting to. 17 is a
   step that can be judged, and it is one number to raise again.

   Only `html` carries it. Putting it on `body` as well would compound —
   body would take 106.25% of the root's 17px — which px never did. */
html { font-size: 106.25%; }
/* TWO TYPEFACES, AND WHERE EACH ONE STOPS. IBM Plex stays the reading
   face; Noto Kufi is for what a reader picks out of a screen — the screen
   title, a shop's name, a prayer and its time, a section head.
   NOT the category labels (.78125rem) and NOT the bottom bar (.71875rem):
   at those sizes a face with character is a burden, not a feature.

   And every size below is in `rem` and not px, because the root here is
   106.25% — SEVENTEEN pixels, not sixteen — and `applyFontScale()` writes
   it too. A px number would be 6.25% wrong and would break for the first
   reader who enlarges the type from Settings. */
:root { --font-display: 'Noto Kufi Arabic', 'IBM Plex Sans Arabic', sans-serif; }


/* ⚠️ `hidden` COMES FROM THE BROWSER'S DEFAULT SHEET, AT THE WEAKEST
   PRIORITY — so any class rule that writes `display` cancels it. The
   attribute is set correctly in the code and nothing happens on screen.

   Measured on the published 0.7.6, on all ten screens walked: `#installBar`
   carried `hidden`, `hidden === true`, `innerHTML.length === 0` — and was
   drawn 374 × 22 at y=736, with `elementFromPoint` in its middle returning
   the bar itself. ⚠️ A 22px strip straight above the bottom bar, taking
   every touch that lands on it and doing nothing with them: in the
   directory it sits over the last visible row, so the reader taps a shop
   and it does not open.

   ⚠️ AND IT HAD HAPPENED BEFORE. `.search-clear[hidden] { display: none }`
   was a local patch for this same class — «`display: grid` beats the
   `hidden` attribute, so the empty-field ✕ was showing anyway». It is
   deleted with this rule going in: the same rule written twice is the
   `esc()` fault, and the second copy is the one nobody updates.

   ⚠️ `!important` IS DELIBERATE AND IS NOT REMOVED. Without it the very
   class rule that caused this wins again. This is the one place in the
   file that earns it: a rule saying «this element is not there» must not
   be beaten by anything. And it is general on purpose — whatever is
   hidden with `hidden` tomorrow is covered with no new line. */
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'IBM Plex Sans Arabic', system-ui, -apple-system, 'Segoe UI', Tahoma, sans-serif;
  line-height: 1.6;
  overscroll-behavior-y: none;
}

body {
  min-height: 100dvh;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(1200px 700px at 50% -10%, var(--gold-wash-2), transparent 60%),
    var(--bg);
}

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; padding: 0; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
ul { margin: 0; padding: 0; list-style: none; }

/* ---------- device frame ---------- */
.phone {
  position: relative;
  width: 100%;
  max-width: 460px;
  height: 100dvh;
  max-height: 100dvh;
  background: var(--bar);
  display: flex; flex-direction: column;
  overflow: hidden;
}
@media (min-width: 900px) {
  .phone {
    height: min(920px, 96dvh);
    border-radius: 34px;
    border: 1px solid var(--gold-wash-3);
    box-shadow: var(--shadow-frame), 0 0 0 10px var(--wash-1);
  }
}

/* ---------- header ---------- */
.app-header {
  flex: 0 0 auto;
  height: calc(var(--header-h) + var(--safe-top));
  padding: var(--safe-top) 14px 0;
  /* space-between, because the logo is out of the flow: without it the two
     corner buttons collapse against each other at the start of the row. */
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: linear-gradient(180deg, var(--surface), var(--bar));
  border-bottom: 1px solid var(--line);
  position: relative; z-index: 20;
}
/* The logo is pinned to the true centre of the header, not flowed between the
   buttons — so it sits in exactly the same place in Arabic and in English
   however many icons each side happens to have. */
.app-header .h-logo {
  position: absolute;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  inset-block-start: calc(var(--safe-top) + var(--header-h) / 2);
  /* THE MARK ALONE, at the bar's full height. The name is unreadable at
     this size whatever the arrangement (see LOGO in ui.js), so the bar
     shows the mark and the name lives where there is room for it. Same two
     numbers as before — 65 and 54 — and at a ratio of 1.015 it takes 66px
     of width where the lockup took 80, so the mark is 48% bigger AND the
     header got narrower, not wider. */
  margin-block-start: -32px;           /* half of the 65px height */
  height: 65px; width: auto;
  pointer-events: none;
}
/* RTL mirrors translateX, so the centring stays true in both directions */
[dir="rtl"] .app-header .h-logo { transform: translateX(50%); }
.app-header .h-title { flex: 1; text-align: center; font-weight: 700; font-size: 1.2375rem; font-family: var(--font-display); }

/* Installed, the reserved strip is added on top of the header, so the header
   itself shrinks: 72 + 59 = 131px is close to a native app bar, while
   92 + 59 = 151px would be far too tall. Browser sizes are unchanged. */
@media (display-mode: standalone) {
  :root { --header-h: 72px; }
  .app-header .h-logo { height: 54px; margin-block-start: -27px; }
}


.icon-btn {
  width: 44px; height: 44px; flex: 0 0 44px;
  display: grid; place-items: center;
  border-radius: 12px;
  color: var(--text);
  background: var(--wash-2);
  border: 1px solid var(--line-soft);
  transition: background .18s var(--ease), transform .12s var(--ease);
  position: relative;
}
.icon-btn:active { transform: scale(0.93); background: var(--line); }
.icon-btn .dot {
  position: absolute; inset-block-start: 7px; inset-inline-end: 8px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--gold-bright); border: 2px solid var(--surface);
}
.lang-pill {
  height: 34px; padding: 0 11px;
  display: grid; place-items: center;
  border-radius: 999px;
  font-weight: 700; font-size: .75rem; letter-spacing: .5px;
  color: var(--gold-bright);
  background: var(--gold-wash-2);
  border: 1px solid var(--line);
}

/* ---------- main scroll area ---------- */
.app-main {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  padding-bottom: calc(var(--nav-h) + 18px);
  scrollbar-width: none;
}
.app-main::-webkit-scrollbar { display: none; }
.screen { animation: fade .28s var(--ease); }
@keyframes fade { from { opacity: 0; transform: translateY(8px);} to { opacity:1; transform:none;} }

.pad { padding-inline: 14px; }
.section { margin-top: 28px; }
.section-head {
  display: flex; align-items: center; justify-content: space-between;
  padding-inline: 14px; margin-bottom: 10px;
}
.section-title { font-weight: 700; font-size: 1.2375rem; font-family: var(--font-display); }
.section-title small { display:block; font-weight: 400; font-size: .8125rem; color: var(--muted); margin-top: 2px; }
.link-gold { color: var(--gold-bright); font-size: .84375rem; font-weight: 700; display:flex; align-items:center; gap:3px; }

/* ---------- bottom nav ---------- */
.bottom-nav {
  position: absolute; inset-inline: 0; inset-block-end: 0;
  height: var(--nav-h);
  display: grid; grid-template-columns: repeat(5, 1fr);
  align-items: center;
  background: var(--bar);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  z-index: 30;
  padding-bottom: env(safe-area-inset-bottom);
}
.nav-item {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  color: var(--muted); font-size: .71875rem; font-weight: 600;
  transition: color .18s var(--ease);
}
.nav-item.active { color: var(--gold-bright); }
.nav-item.active svg { filter: drop-shadow(0 0 6px var(--gold-glow)); }
.nav-item:active { transform: scale(0.94); }
.nav-post {
  width: 48px; height: 48px; border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(145deg, var(--gold-bright), var(--gold));
  color: var(--on-gold);
  box-shadow: 0 6px 18px var(--gold-wash-3);
  margin-top: -12px;
}
/* the centre button carries a name like every other tab: the question
   "what does this do" should be answered before it is pressed */
.nav-add { gap: 2px; }
.nav-add > span:last-child { color: var(--gold-bright); }

/* what "+" can make */
.add-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 13px 12px; margin-block-end: 8px;
  border-radius: var(--r-md); text-align: start;
  background: var(--surface); border: 1px solid var(--line-soft);
  color: var(--text);
}
.add-row .a-ico {
  flex: 0 0 42px; width: 42px; height: 42px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--gold-wash-2); color: var(--gold-bright);
}
.add-row .a-txt { flex: 1 1 auto; min-width: 0; }
.add-row .a-txt b { display: block; font-size: .9375rem; }
.add-row .a-txt span { display: block; font-size: .78125rem; color: var(--muted); margin-block-start: 2px; }
.add-row .chev { color: var(--muted); flex: 0 0 auto; }
.add-row.secondary { background: transparent; border-style: dashed; }
.add-row.secondary .a-ico { width: 34px; height: 34px; flex: 0 0 34px; border-radius: 10px; }

/* ---------- buttons ---------- */
/* ⚠️ `height: auto` + `min-height`, and this is the CLASS not one button.
   A fixed height does not grow when the label wraps, so a two-line label
   spills out of its box TOP AND BOTTOM at once — `align-items: center`
   splits the overflow across both sides. Measured on `.btn-sm` at 177px
   wide: the box stayed 40px with the text outside it, and 92px once the
   height was free.
   ⚠️ THE ENGLISH SCREEN IS WHY IT HID: «Edit profile» is short and fits,
   «تعديل الملف الشخصي» is longer and falls out — so shortening the word
   would have hidden the fault until the next long one.
   ⚠️ AND `align-items` IS NOT TOUCHED: centring a single line is correct,
   and the fault was in the fixed height, never in the centring. The
   vertical padding keeps the shape of a one-line button unchanged. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: auto; min-height: 52px; padding: 14px 20px;
  border-radius: var(--r-md);
  font-weight: 700; font-size: .96875rem;
  transition: transform .12s var(--ease), opacity .18s var(--ease);
}
.btn:active { transform: scale(0.975); }
.btn:disabled { opacity: .45; pointer-events: none; }
.btn-gold { background: linear-gradient(145deg, var(--gold-bright), var(--gold)); color: var(--on-gold); box-shadow: 0 6px 18px var(--gold-wash-3); }
.btn-ghost { background: var(--wash-2); border: 1px solid var(--line); color: var(--text); }
.btn-outline-gold { background: transparent; border: 1px solid var(--gold); color: var(--gold-bright); }
/* the quiet third choice — "back" beside two real answers */
.btn-plain { background: transparent; border: 0; color: var(--muted); box-shadow: none; }
.btn-danger { background: var(--danger-bg); border: 1px solid var(--danger-line); color: var(--danger-ink); }
.btn-block { width: 100%; }
.btn-sm { height: auto; min-height: 40px; padding: 10px 15px; font-size: .84375rem; border-radius: 10px; }

/* ---------- inputs ---------- */
.field { margin-bottom: 14px; }
.label { display: block; font-size: .84375rem; font-weight: 700; color: var(--muted); margin-bottom: 6px; }
.input, .select, .textarea {
  width: 100%;
  height: 54px;
  padding: 0 16px;
  background: var(--input-bg);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  color: var(--text);
  outline: none;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.textarea { height: auto; min-height: 110px; padding: 12px 14px; resize: vertical; line-height: 1.6; }
.input:focus, .select:focus, .textarea:focus { border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-wash-2); }
.input::placeholder, .textarea::placeholder { color: var(--muted); }
.input-err { border-color: var(--danger-line) !important; }
.hint { font-size: .78125rem; color: var(--muted); margin-top: 6px; }
.err-msg { font-size: .8125rem; color: var(--danger-ink); margin-top: 6px; display: flex; gap: 5px; align-items: flex-start; }
.ok-msg { font-size: .8125rem; color: var(--green); margin-top: 6px; }

.otp-row { display: flex; gap: 8px; direction: ltr; justify-content: center; margin: 6px 0 4px; }
.otp-box {
  width: 46px; height: 58px; text-align: center;
  font-size: 1.25rem; font-weight: 700;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: 12px; color: var(--text); outline: none;
}
.otp-box:focus { border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-wash-2); }

/* ---------- search + location ---------- */
.search-wrap { padding: 12px 14px 0; }
.search-bar {
  display: flex; align-items: center; gap: 11px;
  height: 52px; padding: 0 16px;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
}
.search-bar input {
  flex: 1; background: none; border: none; outline: none;
  /* `min-width: auto` is every flex item's default and means "never shrink
     below your own content". The placeholder here is a long sentence, so
     the input refused to shrink and spilled out of the bar it sits in —
     over the location chip beside it. The parent shrank as told; the child
     walked out of it. Hidden under the rounded corner at 14px today, and
     the first enlargement of the base font puts one word on top of another. */
  min-width: 0; width: 100%;
}
.loc-bar {
  margin-top: 9px;
  display: flex; align-items: center; gap: 8px;
  font-size: .78125rem; color: var(--muted);
}
.loc-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 38px; padding: 0 14px;
  background: var(--gold-wash-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--gold-bright); font-weight: 700; font-size: .84375rem;
}
/* No location yet. The chip is an invitation, not a statement: a dashed
   edge says "this is empty and you can fill it", where the solid one said
   "this is where you are" about a city we had guessed. */
.loc-chip.unset {
  background: transparent;
  border-style: dashed;
  border-color: var(--gold-wash-4);
}
.radius-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 38px; padding: 0 14px;
  background: var(--wash-2);
  border: 1px solid var(--line-soft);
  border-radius: 999px; font-size: .84375rem; font-weight: 700; color: var(--text);
}

/* ---------- chips row ---------- */
.hscroll {
  display: flex; gap: 11px; align-items: flex-start;
  overflow-x: auto; scrollbar-width: none;
  padding-inline: 14px;
  scroll-snap-type: x proximity;
}
.hscroll::-webkit-scrollbar { display: none; }
.chip {
  flex: 0 0 auto;
  height: 40px; padding: 0 16px;
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 999px;
  background: var(--wash-2);
  border: 1px solid var(--line-soft);
  font-size: .84375rem; font-weight: 700; color: var(--muted);
  transition: all .18s var(--ease);
  white-space: nowrap;
}
.chip.active { background: linear-gradient(145deg, var(--gold-bright), var(--gold)); color: var(--on-gold); border-color: transparent; }
.chip:active { transform: scale(0.96); }

/* ---------- category circles ---------- */
.cat-item { flex: 0 0 auto; width: 66px; text-align: center; scroll-snap-align: start;
  display: flex; flex-direction: column; align-items: center; }
/* ONE SHAPE, drawn one way. The all-categories grid already used a
   rounded square and the home strip a full circle — the same thing drawn
   twice on two screens — so the job was not a new shape but agreeing on
   one. 18px at 52–56, 13px at 44.

   ⚠️ `--h` IS WRITTEN ON THE ELEMENT ITSELF (`style="--h:6"`), never on a
   parent. `var()` inside a custom property is substituted AT THE ELEMENT
   THAT DECLARES IT, not the one that uses it — so putting these rules on
   an ancestor resolves them with no hue and they come out EMPTY, leaving
   a tile with no background and no border. */
.cat-tile {
  width: 56px; height: 56px; margin: 0 auto 7px;
  border-radius: 18px;
  position: relative; overflow: hidden;
  display: grid; place-items: center;
  background: hsl(var(--h) 62% 58% / .18);
  border: 1px solid hsl(var(--h) 60% 62% / .34);
  color: hsl(var(--h) 66% 72%);
  transition: transform .16s var(--ease), box-shadow .16s var(--ease);
}
.cat-tile svg { stroke-width: 1.75; position: relative; z-index: 1; }
/* the khatam — drawn in the page, never a file to fetch */
.cat-pat { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .5; pointer-events: none; }
/* A thin dark stroke dissolves on a light ground while a light stroke on a
   dark ground shows, at almost identical numbers — which is why the weight
   differs between the themes and not only the colour. */
:root[data-theme="light"] .cat-tile {
  background: hsl(var(--h) 58% 45% / .24);
  border-color: hsl(var(--h) 52% 40% / .42);
  color: hsl(var(--h) 66% 24%);
}
:root[data-theme="light"] .cat-tile svg { stroke-width: 2.15; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .cat-tile {
    background: hsl(var(--h) 58% 45% / .24);
    border-color: hsl(var(--h) 52% 40% / .42);
    color: hsl(var(--h) 66% 24%);
  }
  :root:not([data-theme="dark"]) .cat-tile svg { stroke-width: 2.15; }
}
.cat-item:active .cat-tile { transform: scale(0.93); box-shadow: 0 0 0 3px var(--gold-wash-3); }
.cat-item.active .cat-tile { background: linear-gradient(150deg, var(--gold-bright), var(--gold)); color: var(--on-gold); }
/* the door to the rest — a tile in shape, dashed so it reads as a door
   rather than as one more category */
.cat-tile.more { background: none; border-style: dashed; border-color: var(--line);
  color: var(--muted); }
.cat-label { font-size: .78125rem; color: var(--muted); font-weight: 600; line-height: 1.3; display: block; }
.cat-item.active .cat-label { color: var(--gold-bright); }

/* ---------- primary ad slider ---------- */
.slider { position: relative; padding: 14px 14px 0; }
.slider-track { position: relative; height: 176px; border-radius: var(--r-lg); overflow: hidden; }
.slide {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; justify-content: center;
  padding: 16px 18px;
  /* The advertiser's own colour does not follow the theme, so the text on
     top of it must not either. Inheriting --text put dark navy on dark
     maroon in the light theme: measured 1.04, invisible. A fixed ground
     takes fixed ink. */
  color: var(--ad-cta);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  opacity: 0; transform: scale(0.98);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
  pointer-events: none;
  overflow: hidden;
}
.slide.active { opacity: 1; transform: none; pointer-events: auto; }
.slide::after {
  content: ''; position: absolute; inset-block: -40%; inset-inline-end: -18%;
  width: 62%; border-radius: 50%;
  background: radial-gradient(circle, var(--ad-sheen), transparent 65%);
}
.slide-badge {
  align-self: flex-start;
  font-size: .71875rem; font-weight: 700; letter-spacing: .4px;
  padding: 3px 9px; border-radius: 999px;
  background: var(--ad-badge); color: var(--ad-cta);
  border: 1px solid var(--ad-line);
  margin-bottom: 8px;
}
.slide-title { font-size: 1.4375rem; font-weight: 700; line-height: 1.25; }
.slide-sub { font-size: .875rem; opacity: .88; margin-top: 3px; }
.slide-cta {
  align-self: flex-start; margin-top: 12px;
  height: 40px; padding: 0 18px; border-radius: 999px;
  background: var(--ad-cta); color: var(--ad-ink);
  font-weight: 700; font-size: .875rem;
  display: inline-flex; align-items: center; gap: 6px;
  position: relative; z-index: 2;
}
.slide-icon { position: absolute; inset-block-start: 50%; inset-inline-end: 18px; transform: translateY(-50%); opacity: .30; z-index: 1; }
.slide-house {
  /* …and the house slide is the exception that proves it: its ground is
     ours and does follow the theme, so its ink has to follow too. */
  background: linear-gradient(140deg, var(--surface-2), var(--bar));
  color: var(--text);
  border: 1px dashed var(--gold-wash-4) !important;
  align-items: center; text-align: center; justify-content: center;
}
.slide-house .slide-title { color: var(--gold-bright); }
.slider-dots { display: flex; gap: 5px; justify-content: center; margin-top: 10px; }
.dot-i { width: 6px; height: 6px; border-radius: 999px; background: var(--wash-4); transition: all .3s var(--ease); }
.dot-i.active { width: 18px; background: var(--gold-bright); }

/* ---------- mini ad banner ---------- */
/* A button is shrink-to-fit by default, so this banner used to be as wide
   as whatever text happened to be in it — and it changes text every seven
   seconds, so it visibly jumped. Fixed box, ellipsis inside: the size is
   the product, and it stays small on purpose to justify the price gap
   against the slider above it. */
.mini-ad {
  box-sizing: border-box;
  margin: 16px 14px 0;
  width: -webkit-fill-available;
  width: stretch;
  display: flex; align-items: center; gap: 12px;
  height: 62px; min-height: 62px; max-height: 62px;
  padding: 0 14px;
  border-radius: var(--r-md);
  background: linear-gradient(90deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line-soft);
  overflow: hidden; text-align: start;
}
.mini-ad .m-ico { width: 38px; height: 38px; border-radius: 8px; display: grid; place-items: center; background: var(--gold-wash-2); color: var(--gold-bright); flex: 0 0 38px; }
/* the text column is the only thing allowed to give way */
.mini-ad .m-body { flex: 1 1 auto; min-width: 0; }
.mini-ad .m-name,
.mini-ad .m-tag { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini-ad .m-name { font-size: .90625rem; font-weight: 700; }
.mini-ad .m-tag { font-size: .78125rem; color: var(--muted); }
/* The dots live BELOW the box, never inside it: the 62px box is fixed and
   its smallness is what the price difference rests on. They are smaller
   than the main slider's for the same reason. */
.mini-dots {
  display: flex; gap: 4px; justify-content: center;
  margin: 7px 14px 0; min-height: 5px;
}
.mini-dots .dot-i { width: 5px; height: 5px; }
.mini-dots .dot-i.active { width: 13px; }
.ad-label {
  margin-inline-start: auto; flex: 0 0 auto;
  font-size: .6875rem; font-weight: 700; letter-spacing: .4px;
  color: var(--muted); border: 1px solid var(--line-soft);
  padding: 2px 6px; border-radius: 5px;
}

/* ---------- cards ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: transform .14s var(--ease), border-color .18s var(--ease);
}
.card:active { transform: scale(0.985); }

.feat-card { flex: 0 0 auto; width: 205px; scroll-snap-align: start; }
.feat-cover {
  height: 110px; position: relative;
  display: grid; place-items: center;
  background: linear-gradient(140deg, var(--surface-2), var(--surface));
  color: var(--gold-bright);
}
.feat-body { padding: 12px 13px 14px; }
.feat-name { font-size: .9375rem; font-weight: 700; line-height: 1.3; }
.feat-meta { font-size: .78125rem; color: var(--muted); margin-top: 3px; display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }

.badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .71875rem; font-weight: 700;
  padding: 4px 9px; border-radius: 7px;
}
.badge-verified { background: var(--gold-wash-1); color: var(--gold-bright); border: 1px solid var(--line); }
.badge-free { background: var(--green-bg); color: var(--green); border: 1px solid var(--green-line); }
.badge-boost { background: linear-gradient(145deg, var(--gold-bright), var(--gold)); color: var(--on-gold); }
.badge-sponsored { background: var(--line-soft); color: var(--text-2); border: 1px solid var(--line-soft); }
.badge-cat { background: var(--surface-2); color: var(--gold-bright); border: 1px solid var(--line); }

.stars { display: inline-flex; align-items: center; gap: 2px; color: var(--gold-bright); font-size: .78125rem; font-weight: 700; }

/* ---------- directory list rows ---------- */
.list-row {
  display: flex; gap: 13px; padding: 15px;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  margin-bottom: 10px;
  align-items: flex-start;
  transition: transform .14s var(--ease);
}
.list-row.premium { border-color: var(--gold-wash-4); background: linear-gradient(140deg, var(--surface-2), var(--surface)); }
.list-row:active { transform: scale(0.99); }
/* ⚠️ `.list-row` is a <div> everywhere else, so it fills its parent. In the
   account hub it is a BUTTON — correctly, because it is an action — and a
   flex button sizes to its CONTENT, so six rows came out at six widths
   (222 · 158 · 164 · 157 · 163 · 168 inside a 390 parent). The fault is in
   the style, not in the tag: the button stays a button, for the screen
   reader and for the keyboard pass. And this covers every
   `button.list-row` written from here on, not the six that exist today. */
button.list-row { width: 100%; }
.row-ico {
  width: 54px; height: 54px; flex: 0 0 54px;
  border-radius: 12px; display: grid; place-items: center;
  background: var(--gold-wash-2); color: var(--gold-bright);
  border: 1px solid var(--line);
}
.row-main { flex: 1; min-width: 0; }
.row-title { font-size: 1.1rem; font-weight: 700; font-family: var(--font-display); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.row-sub { font-size: .78125rem; color: var(--muted); margin-top: 2px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* ⚠️ `wrap`, because these buttons were CUT and not scrolled to: measured
   at 390px in English, the last two ran to 397 while the page's own
   scrollWidth stayed 390 — so the part past the edge could not be reached
   at all. A row somebody chooses from must not run off the edge; the
   magazine's chips answered it the same way. */
.row-actions { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
.mini-btn {
  height: 38px; padding: 0 13px; border-radius: 10px;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .78125rem; font-weight: 700;
  background: var(--wash-2); border: 1px solid var(--line-soft); color: var(--text);
}
.mini-btn.gold { background: var(--gold-wash-2); border-color: var(--line); color: var(--gold-bright); }
.mini-btn:active { transform: scale(0.95); }

/* ---------- upgrade banner ---------- */
.upsell {
  margin: 14px; padding: 14px;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--line), var(--surface-2));
  border: 1px solid var(--line);
  display: flex; align-items: center; gap: 12px;
}
.upsell-txt { flex: 1; }
.upsell-txt b { display: block; font-size: .9375rem; }
.upsell-txt span { font-size: .78125rem; color: var(--muted); }

/* ---------- classifieds grid ---------- */
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; padding: 0 14px; }
.cl-card { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-md); overflow: hidden; }
.cl-card.boosted { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold-wash-3), 0 6px 20px var(--gold-wash-2); }
.cl-img { height: 128px; display: grid; place-items: center; background: linear-gradient(140deg, var(--surface-2), var(--surface)); color: var(--muted); position: relative; }
.cl-body { padding: 11px 12px 13px; }
.cl-price { color: var(--gold-bright); font-weight: 700; font-size: 1.03125rem; }
.cl-title { font-size: .84375rem; font-weight: 600; line-height: 1.35; margin-top: 2px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cl-meta { font-size: .71875rem; color: var(--muted); margin-top: 5px; display: flex; align-items: center; justify-content: space-between; gap: 4px; }

/* ---------- magazine ---------- */
.story-card { flex: 0 0 auto; width: 215px; scroll-snap-align: start; }
.story-cover { height: 116px; display: grid; place-items: center; background: linear-gradient(140deg, var(--surface-2), var(--surface)); color: var(--gold-bright); position: relative; }
.mag-card { display: flex; gap: 13px; padding: 13px; margin-bottom: 11px; }
.mag-thumb { width: 108px; height: 92px; flex: 0 0 108px; border-radius: 10px; display: grid; place-items: center; background: linear-gradient(140deg, var(--surface-2), var(--surface)); color: var(--gold-bright); }
.mag-title { font-size: .9375rem; font-weight: 700; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mag-ex { font-size: .78125rem; color: var(--muted); margin-top: 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.mag-meta { font-size: .71875rem; color: var(--muted); margin-top: 6px; display: flex; gap: 8px; align-items: center; }

.article-hero { height: 190px; display: grid; place-items: center; background: linear-gradient(140deg, var(--surface-2), var(--surface)); color: var(--gold-bright); position: relative; }
.article-body { padding: 16px 16px 30px; }
.article-body h1 { font-size: 1.4375rem; line-height: 1.4; margin: 10px 0 6px; }
.article-body p { font-size: .96875rem; line-height: 1.95; color: var(--text-2); margin: 0 0 15px; }

/* ---------- detail page ---------- */
.detail-hero {
  height: 168px; position: relative;
  display: grid; place-items: center;
  background: linear-gradient(150deg, var(--surface-2), var(--bar));
  border-bottom: 1px solid var(--line);
}
.back-btn {
  position: absolute; inset-block-start: 12px; inset-inline-start: 12px;
  width: 38px; height: 38px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--bar); border: 1px solid var(--line-soft);
  backdrop-filter: blur(8px); z-index: 5;
}
.detail-body { padding: 16px 14px 26px; }
.detail-title { font-size: 1.375rem; font-weight: 700; }
.info-row { display: flex; gap: 12px; align-items: flex-start; padding: 14px 0; border-bottom: 1px solid var(--line-soft); }
.info-row .i-ico { color: var(--gold-bright); flex: 0 0 20px; margin-top: 2px; }
.info-row .i-txt b { display: block; font-size: .9375rem; font-weight: 700; }
.info-row .i-txt span { font-size: .78125rem; color: var(--muted); }
.action-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin: 14px 0; }

.locked {
  position: relative; border-radius: var(--r-md);
  border: 1px dashed var(--gold-wash-4);
  background: var(--surface-2);
  padding: 20px 16px; text-align: center;
}
.locked .lk-ico { color: var(--gold); margin-bottom: 8px; }
.locked b { display: block; font-size: .875rem; margin-bottom: 4px; }
.locked span { font-size: .75rem; color: var(--muted); display: block; margin-bottom: 12px; }

.photo-strip { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
.photo-strip::-webkit-scrollbar { display: none; }
.photo-tile { flex: 0 0 120px; height: 94px; border-radius: 10px; display: grid; place-items: center; background: linear-gradient(140deg, var(--surface-2), var(--surface)); color: var(--muted); border: 1px solid var(--line-soft); }

.review { padding: 12px 0; border-bottom: 1px solid var(--line-soft); }
.review-head { display: flex; align-items: center; gap: 8px; }
.avatar { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; background: var(--gold-wash-2); color: var(--gold-bright); font-weight: 700; font-size: .75rem; }
.review p { margin: 8px 0 0; font-size: .875rem; color: var(--text-2); }

/* ---------- drawer ---------- */
.drawer-root { position: fixed; inset: 0; z-index: 100; pointer-events: none; }
.drawer-root.open { pointer-events: auto; }
.drawer-scrim { position: absolute; inset: 0; background: var(--overlay); opacity: 0; transition: opacity .3s var(--ease); backdrop-filter: blur(2px); }
.drawer-root.open .drawer-scrim { opacity: 1; }
.drawer-panel {
  position: absolute; inset-block: 0; inset-inline-start: 0;
  padding-block-start: var(--safe-top);
  width: min(360px, 86%);
  background: linear-gradient(180deg, var(--surface), var(--bar));
  border-inline-end: 1px solid var(--line);
  transform: translateX(var(--drawer-off, -100%));
  transition: transform .32s var(--ease);
  display: flex; flex-direction: column;
  overflow-y: auto; scrollbar-width: none;
}
html[dir="rtl"] .drawer-panel { --drawer-off: 100%; }
.drawer-root.open .drawer-panel { transform: translateX(0); }
.drawer-head { padding: 20px 18px 16px; border-bottom: 1px solid var(--line-soft); text-align: center; }
/* 64 and not 46: at 46 the stacked lockup put the two names under a mark
   too small to read them. The width is never written — the file is
   1173x955, ratio 1.23, so 64 takes 79px and the image keeps its own
   proportions. Nothing crops it: no overflow, no object-fit, and the head
   is an ordinary block, so the extra height pushes what is below and cuts
   nothing above. */
.drawer-head img { height: 64px; margin: 0 auto 10px; }
.drawer-user { font-size: .78125rem; color: var(--muted); }
.dr-item {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px; width: 100%;
  font-size: .9375rem; font-weight: 600; text-align: start;
}
.dr-item svg { color: color-mix(in srgb, var(--text) 55%, transparent); flex: 0 0 20px; }
.dr-item:active { background: var(--wash-2); }
/* The single accent in the drawer: "advertise with us" is the revenue row. */
.dr-accent svg { color: var(--gold); }
.dr-version {
  margin-block-start: auto;
  padding: 16px 18px calc(18px + var(--safe-bottom, 0px));
  border-block-start: 1px solid var(--line-soft);
  text-align: center; color: var(--muted); font-size: .6875rem;
}
.dr-group-label { padding: 16px 18px 6px; font-size: .75rem; font-weight: 700; letter-spacing: .6px; color: var(--muted); }

/* ---------- bottom sheet / modal ---------- */
.sheet-root { position: fixed; inset: 0; z-index: 120; pointer-events: none; display: flex; align-items: flex-end; justify-content: center; }
.sheet-root.open { pointer-events: auto; }
.sheet-scrim { position: absolute; inset: 0; background: var(--overlay); opacity: 0; transition: opacity .28s var(--ease); }
.sheet-root.open .sheet-scrim { opacity: 1; }
/* A flex column: the body scrolls, the footer sits beside it and is
   therefore always on screen — sticky pinned to a container taller than
   the viewport, which put the last filter group under the apply button. */
.sheet-panel {
  position: relative;
  display: flex; flex-direction: column;
  width: 100%; max-width: 460px;
  max-height: 88dvh;
  background: linear-gradient(180deg, var(--surface), var(--bar));
  border-top-left-radius: var(--r-xl); border-top-right-radius: var(--r-xl);
  border: 1px solid var(--line); border-bottom: none;
  padding: 8px 16px calc(22px + env(safe-area-inset-bottom));
  transform: translateY(100%);
  transition: transform .34s var(--ease);
}
.sheet-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; scrollbar-width: none;
  padding-block-end: 10px;
}
.sheet-body::-webkit-scrollbar { display: none; }
.sheet-root.open .sheet-panel { transform: translateY(0); }
.sheet-panel::-webkit-scrollbar { display: none; }
.sheet-grip { width: 42px; height: 4px; border-radius: 999px; background: var(--wash-4); margin: 6px auto 14px; }
.sheet-title { font-size: 1.1875rem; font-weight: 700; margin-bottom: 4px; }
.sheet-sub { font-size: .84375rem; color: var(--muted); margin-bottom: 16px; }

/* ---------- a long review does not eat the screen ----------
   Two lines, then «اقرأ المزيد». `-webkit-line-clamp` is the clamp the
   project already uses (`.list-row.premium .row-title`), so no second
   truncation idiom is invented. */
.rv-text.clamped {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.rv-more {
  background: none; border: 0; padding: 4px 0 0;
  font-size: .8125rem; font-weight: 700; color: var(--gold-bright);
  text-decoration: underline;
}

/* the update prompt's own button — the one toast, extended, not a second
   component to keep in sync */
.toast-act {
  margin-inline-start: 10px; padding: 4px 12px;
  border-radius: 999px; border: 0;
  background: var(--gold); color: var(--on-gold);
  font-size: .8125rem; font-weight: 700;
}

/* ---------- the greeting card ----------
   Its own root, not `#sheet`: `render()` empties the sheet on every
   navigation, so a card opened from the boot sequence would be wiped
   before it was seen. And it is CENTRED, not a bottom sheet — a
   greeting is read, not chosen from.
   ⚠️ No ornament, no ribbon, no medal. A frame, type and white space —
   and whoever wants to add something to it later is adding it to a
   design chosen for having none of that. */
.greet-root { position: fixed; inset: 0; z-index: 190; pointer-events: none; display: flex; align-items: center; justify-content: center; padding: 20px; }
.greet-root.open { pointer-events: auto; }
.greet-scrim { position: absolute; inset: 0; background: var(--overlay); opacity: 0; transition: opacity .28s var(--ease); }
.greet-root.open .greet-scrim { opacity: 1; }
/* ---- «أضِفه إلى شاشتك» — one line, once, and it never covers the page ----
   ⚠️ Every colour is a token and the ground is `--surface`, which follows
   the theme, so the ink follows it too. `--muted` is deliberately NOT
   used here: it is banned on tinted grounds by measurement, and this
   strip sits on the card colour. */
.install-bar {
  position: absolute; inset-inline: 8px;
  inset-block-end: calc(var(--nav-h) + 8px);
  z-index: 120;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--gold-wash-3);
  border-radius: 16px;
  box-shadow: var(--shadow-2);
}
.install-bar .ib-ico { flex: 0 0 auto; color: var(--gold); display: flex; }
.install-bar .ib-txt {
  flex: 1 1 auto; min-width: 0;
  font-size: .8125rem; line-height: 1.35; color: var(--text);
}
.install-bar .ib-go {
  flex: 0 0 auto; padding: 7px 12px; border-radius: 999px;
  background: var(--gold); color: var(--on-gold);
  font-size: .8125rem; font-weight: 700; border: 0;
}
/* ⚠️ 44px of touch, and the glyph is smaller than the box it lives in:
   a close button somebody misses is a strip they cannot get rid of. */
.install-bar .ib-x {
  flex: 0 0 auto; width: 32px; height: 32px; border: 0; background: none;
  color: var(--text-2); display: flex; align-items: center; justify-content: center;
}
.inst-steps { counter-reset: instep; }
.inst-step { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; }
.inst-step .is-n {
  flex: 0 0 26px; height: 26px; border-radius: 999px;
  background: var(--gold-wash-2); color: var(--gold-bright);
  display: flex; align-items: center; justify-content: center;
  font-size: .8125rem; font-weight: 700;
}
.inst-step .is-t { flex: 1 1 auto; font-size: .9375rem; line-height: 1.5; color: var(--text); }

.greet-card {
  position: relative;
  width: 16.2rem; max-width: 100%;
  background: var(--surface);
  border: 1px solid var(--gold-wash-3);
  border-radius: 22px;
  box-shadow: var(--shadow-2);
  opacity: 0; transform: scale(.94);
  transition: opacity .28s var(--ease), transform .28s var(--ease);
}
.greet-root.open .greet-card { opacity: 1; transform: scale(1); }
.greet-frame {
  margin: .5rem;
  border: 1px solid var(--gold-wash-3);
  border-radius: 16px;
  padding: 20px 16px 16px;
  text-align: center;
}
/* the mark is a file and takes its own width from its ratio */
.greet-logo { height: 15px; width: auto; display: block; margin: 0 auto 16px; }
/* ⚠️ 1.41875rem AND .7875rem, NOT 1.42 AND .79 — and this is a debt from
   V.07.0, named rather than quietly corrected. `v28 · 2.3` asserts that
   every rem in this file maps back to an exact one-decimal px, which is
   what made the V.03.5 px→rem migration provable; these two came straight
   out of the design table as rem and broke it. 22.7/16 and 12.6/16 keep
   the invariant, and the rendered difference is 0.02px. */
.greet-title { font-family: var(--font-display); font-size: 1.41875rem; font-weight: 600; line-height: 1.55; margin-bottom: 10px; }
.greet-body { font-size: .7875rem; line-height: 1.85; color: var(--text-2); margin-bottom: 18px; }
.greet-cta { margin-bottom: 8px; }
@media (prefers-reduced-motion: reduce) {
  .greet-card, .greet-scrim { transition: none; }
}

/* ---------- toast ---------- */
.toast-root { position: fixed; inset-block-start: calc(var(--safe-top) + 14px); inset-inline: 0; z-index: 200; display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; }
.toast {
  max-width: 90%; padding: 13px 18px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 999px; font-size: .875rem; font-weight: 600;
  box-shadow: var(--shadow-2);
  display: flex; align-items: center; gap: 8px;
  animation: toastIn .28s var(--ease);
}
.toast.ok { border-color: var(--green-line); }
.toast.err { border-color: var(--danger-line); }
.toast svg { flex: 0 0 16px; }
@keyframes toastIn { from { opacity: 0; transform: translateY(-14px);} to { opacity:1; transform:none;} }

/* ---------- empty state ---------- */
.empty { padding: 46px 26px; text-align: center; }
.empty-ico {
  width: 74px; height: 74px; margin: 0 auto 14px;
  border-radius: 50%; display: grid; place-items: center;
  background: var(--gold-wash-1); border: 1px solid var(--line);
  color: var(--gold);
}
.empty b { display: block; font-size: 1.0625rem; margin-bottom: 6px; }
.empty span { font-size: .84375rem; color: var(--muted); display: block; max-width: 250px; margin: 0 auto 16px; }

/* ---------- misc ---------- */
.tabs { display: flex; gap: 6px; padding: 12px 14px 0; }
/* The admin bar carries eight tabs and stopped fitting in 390px. It wraps
   onto a second line rather than scrolling sideways — the same answer the
   magazine's chips got, and the same rule: a row somebody chooses from
   must not run off the edge. It applies to the panel too. */
#aTabs { flex-wrap: wrap; }
#aTabs .tab { flex: 1 1 auto; min-width: calc(25% - 5px); padding-inline: 8px; font-size: .8125rem; }
.tab {
  flex: 1; height: 46px; border-radius: var(--r-md);
  display: grid; place-items: center;
  font-size: .90625rem; font-weight: 700; color: var(--muted);
  background: var(--wash-2); border: 1px solid var(--line-soft);
}
.tab.active { background: var(--gold-wash-2); color: var(--gold-bright); border-color: var(--line); }

.list-note {
  margin: 14px 14px 0; padding: 13px 14px;
  font-size: .78125rem; color: var(--muted);
  background: var(--wash-1);
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  display: flex; gap: 8px; align-items: flex-start;
}
.list-note svg { flex: 0 0 15px; color: var(--gold); margin-top: 1px; }

.price-card {
  padding: 16px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-soft);
  margin-bottom: 10px; display: flex; gap: 12px; align-items: flex-start;
  text-align: start; width: 100%;
}
.price-card.selected,
.ad-card.selected > .price-card { border-color: var(--gold); background: linear-gradient(140deg, var(--gold-wash-2), var(--surface)); }
.price-radio { width: 20px; height: 20px; flex: 0 0 20px; border-radius: 50%; border: 2px solid var(--muted); margin-top: 2px; display: grid; place-items: center; }
.price-card.selected .price-radio,
.ad-card.selected .price-radio { border-color: var(--gold-bright); }
.price-card.selected .price-radio::after,
.ad-card.selected .price-radio::after { content: ''; width: 10px; height: 10px; border-radius: 50%; background: var(--gold-bright); }
.price-name { font-size: .96875rem; font-weight: 700; }
.price-desc { font-size: .78125rem; color: var(--muted); margin-top: 3px; }
.price-amt { margin-inline-start: auto; color: var(--gold-bright); font-weight: 700; font-size: 1.03125rem; white-space: nowrap; }

.steps { display: flex; align-items: center; gap: 6px; padding: 12px 14px 0; }
.step-dot { flex: 1; height: 4px; border-radius: 999px; background: var(--wash-3); }
.step-dot.done { background: var(--gold); }

.stat-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; padding: 0 14px; }
.stat { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-md); padding: 12px 10px; text-align: center; width: 100%; }
button.stat:active { border-color: var(--gold); background: var(--gold-wash-1); }
.stat b { display: block; font-size: 1.375rem; color: var(--gold-bright); }
.stat span { font-size: .71875rem; color: var(--muted); }

.switch { width: 44px; height: 26px; border-radius: 999px; background: var(--wash-3); position: relative; transition: background .22s var(--ease); flex: 0 0 44px; }
.switch::after { content: ''; position: absolute; inset-block-start: 3px; inset-inline-start: 3px; width: 20px; height: 20px; border-radius: 50%; background: var(--knob); transition: transform .22s var(--ease); }
.switch.on { background: var(--gold); }
html[dir="ltr"] .switch.on::after { transform: translateX(18px); }
html[dir="rtl"] .switch.on::after { transform: translateX(-18px); }

.setting-row { display: flex; align-items: center; gap: 12px; padding: 16px 14px; border-bottom: 1px solid var(--line-soft); }
.setting-row .s-txt { flex: 1; }
.setting-row .s-txt b { display: block; font-size: .9375rem; font-weight: 600; }
.setting-row .s-txt span { font-size: .78125rem; color: var(--muted); }

.legal-body { padding: 16px 16px 30px; }
.legal-body h2 { font-size: 1.03125rem; margin: 18px 0 6px; color: var(--gold-bright); }
.legal-body p, .legal-body li { font-size: .90625rem; color: var(--text-2); line-height: 1.95; }
.legal-body li { margin-inline-start: 18px; list-style: disc; }

.notif-row { display: flex; gap: 13px; padding: 16px 14px; border-bottom: 1px solid var(--line-soft); }
.notif-row.unread { background: var(--gold-wash-1); }
.notif-ico { width: 42px; height: 42px; flex: 0 0 42px; border-radius: 10px; display: grid; place-items: center; background: var(--gold-wash-2); color: var(--gold-bright); }
.notif-txt b { display: block; font-size: .90625rem; }
.notif-txt span { font-size: .78125rem; color: var(--muted); }

.spinner {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--wash-4); border-top-color: var(--text);
  animation: spin .7s linear infinite;
}
.spinner.sm { width: 14px; height: 14px; border-width: 2px; flex: 0 0 14px; }
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton { background: linear-gradient(90deg, var(--skeleton), var(--wash-3), var(--skeleton)); background-size: 200% 100%; animation: sk 1.2s infinite; border-radius: 8px; }
@keyframes sk { to { background-position: -200% 0; } }

.center-col { display: flex; flex-direction: column; align-items: center; text-align: center; }
.mt-8 { margin-top: 8px; } .mt-12 { margin-top: 12px; } .mt-16 { margin-top: 16px; } .mt-20 { margin-top: 20px; }
.muted { color: var(--muted); }
.fs-12 { font-size: .8125rem; } .fs-13 { font-size: .875rem; }
.gold { color: var(--gold-bright); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* Latin-script content inside RTL layout (phones, addresses, emails) */
.ltr { direction: ltr; unicode-bidi: isolate; text-align: start; display: inline-block; }
.cl-price, .price-amt, .stat b { direction: ltr; unicode-bidi: isolate; text-align: start; }
.price-card > span:nth-child(2) { flex: 1; min-width: 0; }
.price-name, .price-desc { display: block; }
.cat-label { min-height: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
input[inputmode="tel"], input[type="email"], input[inputmode="decimal"], #zipIn { direction: ltr; text-align: start; }

/* ============================================================
   V.02 additions — categories grid, photo uploads, messages,
   listing status. Same tokens as everything above.
   ============================================================ */

/* ---------- categories screen ---------- */
.cat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  padding: 0 14px;
}
.cat-cell {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 16px 8px;
  border-radius: var(--r-md);
  background: linear-gradient(150deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line-soft);
  color: var(--text);
  min-height: 104px;
  transition: transform .12s var(--ease), border-color .18s var(--ease);
}
.cat-cell:active { transform: scale(0.96); border-color: var(--gold-wash-4); }
.cat-cell .cc-ico svg { stroke-width: 1.75; position: relative; z-index: 1; }
:root[data-theme="light"] .cat-cell .cc-ico {
  background: hsl(var(--h) 58% 45% / .24);
  border-color: hsl(var(--h) 52% 40% / .42);
  color: hsl(var(--h) 66% 24%);
}
:root[data-theme="light"] .cat-cell .cc-ico svg { stroke-width: 2.15; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .cat-cell .cc-ico {
    background: hsl(var(--h) 58% 45% / .24);
    border-color: hsl(var(--h) 52% 40% / .42);
    color: hsl(var(--h) 66% 24%);
  }
  :root:not([data-theme="dark"]) .cat-cell .cc-ico svg { stroke-width: 2.15; }
}
.cat-cell .cc-ico {
  width: 44px; height: 44px; border-radius: 13px;
  position: relative; overflow: hidden;
  display: grid; place-items: center;
  background: hsl(var(--h) 62% 58% / .18); color: hsl(var(--h) 66% 72%);
  border: 1px solid hsl(var(--h) 60% 62% / .34);
}
/* A marketplace section is not a place — it is a listing that passes. So it
   keeps the hue (the subject) and loses the fill and the khatam (the
   section): filled = a place in the directory, outlined = a listing.
   The border is `currentColor`, so it can never drift from the icon —
   measured worst case 4.72 dark and 5.57 light, both over 3.
   The width is left at the 1px above ON PURPOSE: a border-width of 1.5px is
   floored to 1px by the browser, so writing 1.5 would say one thing and
   render another.
   Repeated under each theme because the theme blocks above are (0,4,0) and
   would otherwise paint the fill back over this one. */
.cat-cell .cc-ico.mk { background: none; border-color: currentColor; }
:root[data-theme="light"] .cat-cell .cc-ico.mk { background: none; border-color: currentColor; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .cat-cell .cc-ico.mk { background: none; border-color: currentColor; }
}
/* Light mode only: the outline carries ALL the colour here — there is no
   fill to carry it — and ink at 24% reads black on a near-white ground.
   Measured: 24% = 5.57 contrast but no colour; 32% = 3.37, over the 3:1
   bar that non-text graphics answer to, and the hue reads.
   The border stays `currentColor`, so it follows the new ink by itself and
   can never drift from it — that is what writing it that way in 220 buys. */
:root[data-theme="light"] .cat-cell .cc-ico.mk { color: hsl(var(--h) 70% 32%); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .cat-cell .cc-ico.mk { color: hsl(var(--h) 70% 32%); }
}
.cat-cell .cc-label { font-size: .8125rem; line-height: 1.35; text-align: center; }
.cat-cell .cc-count { font-size: .6875rem; color: var(--muted); }

/* ---------- photo upload ---------- */
.ph-thumb {
  position: relative; flex: 0 0 96px; height: 96px;
  border-radius: 10px; overflow: hidden;
  border: 1px solid var(--line-soft);
  background: var(--surface-2);
}
.ph-thumb img { width: 100%; height: 100%; object-fit: cover; }
.ph-thumb .ph-x {
  position: absolute; inset-block-start: 4px; inset-inline-end: 4px;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--overlay); color: var(--danger-ink);
  border: 1px solid var(--line);
}
.ph-thumb .ph-main {
  position: absolute; inset-block-end: 0; inset-inline: 0;
  font-size: .65625rem; text-align: center; padding: 3px 2px;
  background: var(--overlay); color: var(--muted);
}
.ph-thumb.is-main { border-color: var(--gold); }
.ph-thumb.is-main .ph-main { background: linear-gradient(145deg, var(--gold-bright), var(--gold)); color: var(--on-gold); font-weight: 700; }

/* listing photo gallery */
.cl-gallery { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding: 0 14px; }
.cl-gallery::-webkit-scrollbar { display: none; }
.cl-gallery img { flex: 0 0 78%; height: 210px; object-fit: cover; border-radius: var(--r-md); border: 1px solid var(--line-soft); }
.cl-img img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- status pill ---------- */
.badge-pending { color: var(--gold-bright); background: var(--gold-wash-2); border-color: var(--gold-wash-4); }

/* ---------- messages ---------- */
.msg-list { display: flex; flex-direction: column; gap: 10px; padding: 14px; }
.msg {
  max-width: 78%; padding: 10px 13px; border-radius: 16px;
  font-size: .875rem; line-height: 1.55; white-space: pre-wrap; word-break: break-word;
}
.msg.me { align-self: flex-end; background: linear-gradient(145deg, var(--gold-bright), var(--gold)); color: var(--on-gold); border-end-end-radius: 5px; }
.msg.them { align-self: flex-start; background: var(--surface-2); border: 1px solid var(--line-soft); border-end-start-radius: 5px; }
.msg-when { font-size: .6875rem; opacity: .7; margin-top: 3px; }
.msg-bar { display: flex; gap: 8px; padding: 0 14px 14px; align-items: flex-end; }
.msg-bar .textarea { min-height: 48px; }

/* ---------- events ---------- */
.ev-card { display: block; overflow: hidden; margin-bottom: 12px; padding: 0; }
.ev-card.featured { border-color: var(--gold-wash-4); box-shadow: 0 0 0 1px var(--gold-wash-3); }
.ev-cover {
  position: relative; height: 132px;
  display: grid; place-items: center;
  background: linear-gradient(150deg, var(--surface-2), var(--surface));
  color: var(--gold-bright);
}
.ev-cover img { width: 100%; height: 100%; object-fit: cover; }
.ev-body { padding: 12px 14px 14px; }
.ev-when { font-size: .78125rem; font-weight: 700; color: var(--gold-bright); display: flex; align-items: center; gap: 5px; }
.ev-title { font-weight: 700; font-size: .96875rem; line-height: 1.45; margin: 5px 0 4px; }
.ev-meta { font-size: .78125rem; color: var(--muted); display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.ev-hero {
  position: relative; height: 200px;
  display: grid; place-items: center;
  background: linear-gradient(150deg, var(--surface-2), var(--surface));
  color: var(--gold-bright);
}
.ev-hero img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- password show / hide ---------- */
.pass-wrap { position: relative; }
.pass-wrap .input { padding-inline-end: 52px; }
.pass-eye {
  position: absolute; inset-inline-end: 6px; inset-block-start: 50%;
  transform: translateY(-50%);
  width: 42px; height: 42px; border-radius: 10px;
  display: grid; place-items: center;
  color: var(--muted);
}
.pass-eye.on, .pass-eye:active { color: var(--gold-bright); background: var(--gold-wash-2); }

/* ---------- verified (blue) badge ---------- */
.badge-check {
  display: inline-grid; place-items: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--blue); color: var(--on-blue);
  margin-inline-start: 5px; vertical-align: middle;
}
.ok-inline { color: var(--green); display: inline-flex; align-items: center; gap: 3px; }

/* ---------- admin: reject reason ---------- */
.reject-box { margin-top: 8px; }
.reject-box .input { height: 44px; font-size: .84375rem; }

/* ============================================================
   V.01.4 — interface simplification
   ============================================================ */

/* header: a spacer opposite the menu button keeps the logo truly centred */
.app-header .h-spacer { width: 44px; height: 44px; flex: 0 0 44px; }
/* The flip sits where the spacer was, same 44px, so nothing moves. Neutral
   on purpose: the gold accent belongs to «أعلن معنا» alone. */
.app-header #hTheme { color: var(--muted); }

/* categories strip: five circles must fit a 390px screen without clipping */
#cats { gap: 6px; }
/* one line each, and the city name is Latin inside an Arabic sentence, so
   it is isolated the way every other place name in the app is */
.home-intro { padding: 2px 14px 10px; }
.home-headline { font-family: var(--font-display); font-size: 1.2375rem; font-weight: 700;
  color: var(--text); margin: 0; line-height: 1.35; unicode-bidi: plaintext; }
.home-subline { font-size: .84375rem; color: var(--muted); margin: 4px 0 0; line-height: 1.5; }

/* six across, ten between, and it fits 390 exactly: 6×52 + 5×10 = 362 */
.cat-row { display: flex; gap: 10px; padding: 0 14px; }
.cat-row .cat-item { flex: 1 1 0; min-width: 0; width: auto; }
.cat-row .cat-tile { width: 52px; height: 52px; }
.cat-tile.more { display: grid; place-items: center; font-weight: 700; font-size: .9375rem; }

/* one-row search: field takes the space, city chip stays compact */
.search-row { display: flex; gap: 8px; align-items: center; padding: 12px 14px 0; }
.search-row .search-bar { flex: 1 1 auto; min-width: 0; margin: 0; }
.search-row .loc-chip { flex: 0 0 auto; max-width: 46%; overflow: hidden; }
.search-row .loc-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filter-btn {
  flex: 0 0 auto; position: relative;
  height: 46px; width: 46px; border-radius: 12px;
  display: grid; place-items: center;
  color: var(--text);
  background: var(--wash-2);
  border: 1px solid var(--line);
}
.filter-btn.on { color: var(--gold-bright); border-color: var(--gold); }
.filter-btn .f-count {
  position: absolute; inset-block-start: -5px; inset-inline-end: -5px;
  min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: 9px; display: grid; place-items: center;
  font-size: .6875rem; font-weight: 700;
  background: linear-gradient(145deg, var(--gold-bright), var(--gold));
  color: var(--on-gold);
}
.info-dot {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-grid; place-items: center;
  color: var(--muted); border: 1px solid var(--line-soft);
  vertical-align: middle; margin-inline-start: 6px;
}
.info-dot:active { color: var(--gold-bright); border-color: var(--gold); }

/* ---------- drawer: collapsible groups ---------- */
.dr-badge {
  margin-inline-start: auto;
  min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: 11px; display: grid; place-items: center;
  font-size: .75rem; font-weight: 700;
  background: linear-gradient(145deg, var(--gold-bright), var(--gold));
  color: var(--on-gold);
}
/* One hairline between blocks — never one under every row, which is the
   clearest tell of an old design. */
.drawer-panel > .dr-item,
.drawer-panel > .dr-group { border-block-end: 1px solid var(--line-soft); }
.dr-head { width: 100%; font-weight: 700; }
/* ⚠️ THE ARROW IS GONE FROM THE MARKUP, and its rules go with it. Moving
   it to the end of the row was `345`'s answer to its displacing the
   label; taking it out of both heads is Rai's. Hiding it with a rule here
   would have been two sources of truth, and LEAVING its rules behind is
   the same debt as a dead export: read six months from now they say a
   fold indicator exists. `grep grp-arrow js/` returns nothing. */
/* An open head is marked by a faint ground and the turned arrow, not by
   turning gold — the accent is spent elsewhere. */
.dr-group.open .dr-head { background: var(--wash-1); }
.dr-group.open .dr-head svg { color: color-mix(in srgb, var(--text) 75%, transparent); }
/* One grid child only: with several children the extra rows fall into
   implicit auto tracks and the group never actually collapses. */
.dr-sub {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .2s var(--ease);
}
.dr-group.open .dr-sub { grid-template-rows: 1fr; }
.dr-sub-inner {
  overflow: hidden; min-height: 0; position: relative;
  visibility: hidden; transition: visibility .2s var(--ease);
}
.dr-group.open .dr-sub-inner { visibility: visible; }
/* The vertical rule does the work a row of separators used to do: it shows
   at a glance which items belong to the open group. */
/* a leaf with nothing behind it yet: it says so and does not navigate */
.dr-item.dr-soon { opacity: .55; }
/* ---------- sign-up: errors under the field, strength before the fail ---------- */
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.field-err { font-size: .75rem; color: var(--danger); margin-top: 5px; min-height: 0; }
.field-err:empty { display: none; }
.link-inline { background: none; border: 0; padding: 0; font: inherit; text-decoration: underline; }
.pw-meter {
  height: 4px; border-radius: 999px; background: var(--wash-2);
  margin: 8px 0 0; overflow: hidden; position: relative;
}
.pw-meter > span { display: block; height: 100%; width: 0; transition: width .2s var(--ease), background .2s var(--ease); }
.pw-meter.s1 > span { width: 33%; background: var(--danger); }
.pw-meter.s2 > span { width: 66%; background: var(--gold); }
.pw-meter.s3 > span { width: 100%; background: var(--green); }
.pw-meter::after {
  content: attr(data-label);
  position: absolute; inset-block-start: 8px; inset-inline-end: 0;
  font-size: .71875rem; color: var(--muted);
}
.pw-meter { margin-bottom: 18px; }

/* ---------- add-business: one box per attribute group ---------- */
.req { color: var(--danger); font-weight: 700; }
.attr-box { border: 1px solid var(--line-soft); border-radius: var(--r-md); margin-bottom: 10px; }
.attr-head {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 13px 14px; background: none; border: 0; text-align: start;
  font-size: .875rem; font-weight: 700; color: var(--text);
}
.attr-head > span:first-child { flex: 1 1 auto; }
.attr-count {
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px;
  display: inline-grid; place-items: center;
  font-size: .75rem; font-weight: 700;
  background: var(--gold-wash-2); color: var(--gold-bright);
}
.attr-count:empty { display: none; }
.attr-head .attr-arrow { flex: 0 0 18px; color: var(--muted); transition: transform .2s var(--ease); }
.attr-box.open .attr-head .attr-arrow { transform: rotate(180deg); }
.attr-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .2s var(--ease); }
.attr-box.open .attr-body { grid-template-rows: 1fr; }
.attr-body-inner {
  overflow: hidden; visibility: hidden;
  display: flex; flex-wrap: wrap; gap: 7px;
  padding: 0 14px;
}
.attr-box.open .attr-body-inner { visibility: visible; padding-bottom: 13px; }
/* what has been chosen, readable with the box shut */
.attr-chosen {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 0 14px 12px;
}

/* ---------- the sponsored rows under a section slider ---------- */
.spon-block { margin: 12px 14px 0; display: grid; gap: 8px; }
/* marked, not disguised: the tint says paid before the badge is read */
.spon-block .list-row.spon { background: var(--gold-wash-1); border-color: var(--gold-wash-3); }
.spon-block .list-row.spon .row-title { display: flex; align-items: center; gap: 7px; }
.spon-block .badge-sponsored { flex: 0 0 auto; }

/* ---- offers (V.03.2) ----
   The gold wash marks it as the subscriber's own space without competing
   with the badge: every colour here is a token, so both themes follow. */
.offer-card {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 13px 14px; margin-top: 8px;
  background: var(--gold-wash-1);
  border: 1px solid var(--gold-wash-3);
  border-radius: var(--r-md);
}
.offer-card.pending, .offer-card.rejected {
  background: var(--wash-1); border-color: var(--line-soft);
}
.offer-main { flex: 1 1 auto; min-width: 0; }
.offer-text { font-size: .90625rem; font-weight: 600; color: var(--text); line-height: 1.45; }
.offer-price { font-size: .9375rem; font-weight: 700; color: var(--gold-bright); margin-top: 4px; }
.offer-meta {
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
  font-size: .75rem; color: var(--muted); margin-top: 6px;
}
.offer-meta svg { flex: 0 0 15px; }
.offer-flag {
  padding: 2px 8px; border-radius: 999px;
  background: var(--wash-2); color: var(--text-2); font-weight: 600;
}
/* --danger is the fill colour; --danger-ink is the one measured to be read
   on a surface. On the rejected card --danger came out at 3.55 in dark. */
.offer-why { font-size: .78125rem; color: var(--danger-ink); margin-top: 6px; }

/* the shop that has not subscribed sees the door, not a blank heading */
.offer-lock {
  display: flex; gap: 12px; align-items: center; width: 100%;
  margin-top: 20px; padding: 14px;
  background: var(--gold-wash-1); border: 1px solid var(--gold-wash-3);
  border-radius: var(--r-md); text-align: start; cursor: pointer;
}
.offer-lock-ico { flex: 0 0 auto; color: var(--gold-bright); display: flex; }
.offer-lock div { flex: 1 1 auto; min-width: 0; }
.offer-lock b { display: block; font-size: .875rem; color: var(--text); }
.offer-lock span { display: block; font-size: .78125rem; color: var(--muted); margin-top: 3px; }

/* the home strip — a card wide enough to read, never a full-width block */
.offer-strip { display: flex; gap: 10px; overflow-x: auto; padding: 2px 14px 4px; }
.offer-tile {
  flex: 0 0 78%; max-width: 300px; text-align: start;
  padding: 13px 14px; border-radius: var(--r-md);
  background: var(--gold-wash-1); border: 1px solid var(--gold-wash-3);
}
.offer-tile .offer-shop {
  display: flex; gap: 6px; align-items: center;
  font-size: .78125rem; color: var(--muted); margin-bottom: 6px;
}
.offer-tile .offer-shop b { color: var(--gold-bright); font-weight: 600; }

/* the «عنده عرض» mark on a directory row */
.badge-offer {
  display: inline-flex; gap: 4px; align-items: center; flex: 0 0 auto;
  padding: 2px 7px; border-radius: 999px;
  background: var(--gold-wash-2); color: var(--gold-bright);
  font-size: .6875rem; font-weight: 700;
}

/* ---- the directions sheet (V.03.4) ---- */
.pick-row {
  display: flex; gap: 11px; align-items: center; width: 100%;
  padding: 13px 14px; margin-bottom: 8px; text-align: start;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--r-md); font-size: .875rem; color: var(--text);
}
.pick-row.active { border-color: var(--gold-wash-3); background: var(--gold-wash-1); }
.pick-dot {
  flex: 0 0 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--line); position: relative;
}
.pick-row.active .pick-dot { border-color: var(--gold-bright); }
.pick-row.active .pick-dot::after {
  content: ''; position: absolute; inset: 3px;
  border-radius: 50%; background: var(--gold-bright);
}

/* ---- the receipt (V.03.4) ----
   Printable in one page: @media print drops everything but the paper. */
.rc {
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--r-md); padding: 16px;
}
.rc-head { border-block-end: 1px solid var(--line-soft); padding-block-end: 11px; margin-block-end: 11px; }
.rc-head b { font-size: .9375rem; color: var(--text); }
.rc-no { font-size: .8125rem; font-weight: 700; color: var(--gold-bright); margin-top: 4px; letter-spacing: .5px; }
.rc-row {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 6px 0; font-size: .8125rem; align-items: baseline;
}
.rc-row > span { color: var(--muted); flex: 0 0 auto; }
.rc-row > b { color: var(--text); font-weight: 600; text-align: end; }
.rc-total {
  border-block-start: 1px solid var(--line-soft);
  margin-block-start: 6px; padding-block-start: 10px; font-size: .9375rem;
}
.rc-total > b { color: var(--gold-bright); }
.rc-note { font-size: .75rem; color: var(--muted); margin-top: 8px; line-height: 1.5; }
.rc-issuer { border-block-start: 1px solid var(--line-soft); padding-block-start: 9px; margin-top: 11px; }

@media print {
  .app-header, .nav-bar, .action-grid, .btn, .hint, .toast-root { display: none !important; }
  .rc { border: 0; padding: 0; background: none; }
}

/* ---- the live password checklist (V.03.4) ---- */
.pw-hint { font-size: .75rem; color: var(--muted); margin-top: 6px; }
.pw-hint.bad { color: var(--danger-ink); }
.pw-reqs { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 5px; }
.pw-reqs li {
  display: flex; gap: 8px; align-items: center;
  font-size: .78125rem; color: var(--muted);
}
.pw-dot {
  flex: 0 0 16px; height: 16px; border-radius: 50%;
  border: 1.5px solid var(--line); display: flex;
  align-items: center; justify-content: center;
  color: transparent;
}
/* met: a tick and the green, never a hidden row — a list that shrinks
   under your fingers is a list that dances */
.pw-reqs li.ok { color: var(--green); }
.pw-reqs li.ok .pw-dot { border-color: var(--green); background: var(--green); color: var(--on-gold); }

/* ---- «آخر ما عُدِّل» (V.03.3) ---- */
.log-row {
  padding: 11px 13px; margin-top: 8px;
  background: var(--wash-1); border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
}
.log-head { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.log-head b { font-size: .84375rem; color: var(--text); }
.log-head span { font-size: .71875rem; color: var(--muted); flex: 0 0 auto; }
.log-field { font-size: .75rem; color: var(--gold-bright); margin-top: 3px; font-weight: 600; }
.log-diff { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 5px; font-size: .75rem; }
.log-from { color: var(--muted); text-decoration: line-through; }
.log-to { color: var(--text-2); }

/* the panel editing somebody else's shop says so, at the top */
.admin-as {
  display: flex; gap: 8px; align-items: center;
  margin: 0 0 14px; padding: 11px 13px;
  background: var(--gold-wash-1); border: 1px solid var(--gold-wash-3);
  border-radius: var(--r-md);
  font-size: .78125rem; color: var(--text);
}
.admin-as svg { flex: 0 0 auto; color: var(--gold-bright); }

/* ---- ramadan (V.03.2) ----
   One line and two buttons, under the prayer bar and above the search
   row. Every colour is a token, so both themes follow it. */
.rm-bar {
  margin: 8px 14px 0; padding: 11px 13px;
  background: var(--gold-wash-1); border: 1px solid var(--gold-wash-3);
  border-radius: var(--r-md);
}
.rm-line { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; font-size: .84375rem; }
.rm-line svg { flex: 0 0 auto; color: var(--gold-bright); }
.rm-name { font-weight: 700; color: var(--text); }
.rm-at { font-weight: 700; color: var(--gold-bright); }
.rm-left { color: var(--muted); font-size: .78125rem; }
.rm-btns { display: flex; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
.rm-btns .mini-btn { flex: 1 1 auto; justify-content: center; }

/* ---- the newcomer's guide (V.03.2) ---- */
.nc-card {
  display: flex; gap: 12px; align-items: center; width: 100%;
  padding: 14px; margin-top: 4px; text-align: start;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--r-md); cursor: pointer;
}
.nc-card-ico {
  flex: 0 0 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--gold-wash-2); color: var(--gold-bright);
}
.nc-card-txt { flex: 1 1 auto; min-width: 0; }
.nc-card-txt b { display: block; font-size: .90625rem; color: var(--text); }
.nc-card-txt span { display: block; font-size: .78125rem; color: var(--muted); margin-top: 3px; }
.nc-head { display: flex; gap: 9px; align-items: center; }
.nc-head svg { flex: 0 0 auto; color: var(--gold-bright); }

/* the heart and the share side by side at the top of a detail page */
.top-actions { display: flex; gap: 8px; flex: 0 0 auto; }
/* a listing's own photo in the row icon, in place of the category glyph */
.row-ico.shot { padding: 0; overflow: hidden; }
.row-ico.shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- admin: the two-bar comparison ---------- */
.cmp-bars {
  display: flex; gap: 26px; justify-content: center; align-items: flex-end;
  padding: 12px 0 4px;
}
.cmp-col { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.cmp-bar { width: 46px; border-radius: 6px 6px 0 0; display: block; }
.cmp-bar.a { background: var(--gold); }
.cmp-bar.b { background: var(--blue); }
.cmp-col b { font-size: 1.0625rem; }
.cmp-col > span:last-child { font-size: .75rem; color: var(--muted); text-align: center; }

/* ---------- help: the questions, folded ---------- */
.faq { margin-top: 10px; }
.faq-item { border-block-end: 1px solid var(--line-soft); }
.faq-item:first-child { border-block-start: 1px solid var(--line-soft); }
.faq-head {
  width: 100%; display: flex; align-items: center; gap: 12px;
  padding: 15px 2px; text-align: start;
  font-size: .90625rem; font-weight: 700; color: var(--text);
  background: none; border: 0;
}
.faq-head span { flex: 1 1 auto; }
.faq-head .faq-arrow { flex: 0 0 19px; color: var(--muted); transition: transform .2s var(--ease); }
.faq-item.open .faq-head .faq-arrow { transform: rotate(180deg); }
/* one grid child only, or the rows fall into implicit tracks and the
   panel never actually collapses — the same trap the drawer hit */
.faq-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .2s var(--ease); }
.faq-item.open .faq-body { grid-template-rows: 1fr; }
.faq-body-inner { overflow: hidden; visibility: hidden; }
.faq-item.open .faq-body-inner { visibility: visible; }
.faq-body-inner p {
  margin: 0 0 15px; font-size: .875rem; line-height: 1.9; color: var(--text-2);
}

/* a soon-tag on a normal button, not just a drawer row */
.btn .soon-tag {
  margin-inline-start: 8px;
  font-size: .6875rem; font-weight: 700;
  padding: 2px 8px; border-radius: 999px;
  background: var(--wash-2); color: var(--muted);
  border: 1px solid var(--line-soft);
}
.dr-item.dr-soon .soon-tag {
  margin-inline-start: auto;
  font-size: .6875rem; font-weight: 700;
  padding: 2px 8px; border-radius: 999px;
  background: var(--wash-2); color: var(--muted);
  border: 1px solid var(--line-soft);
}

.dr-sub-inner::before {
  content: ""; position: absolute; inset-block: 6px;
  inset-inline-start: 26px; width: 2px; border-radius: 2px;
  background: linear-gradient(180deg, var(--gold), var(--gold-wash-2));
}
.dr-sub .dr-item {
  padding-inline-start: 40px;
  font-size: .8625rem; font-weight: 500;
  color: color-mix(in srgb, var(--text) 72%, transparent);
}
.dr-sub .dr-item svg { width: 18px; height: 18px; flex: 0 0 18px; color: color-mix(in srgb, var(--text) 42%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .dr-sub, .dr-sub-inner { transition: none; }
}

/* ---------- drawer: the visitor's invite card ----------
   A visitor sees one invitation instead of a list of account tools that
   would only bounce every tap into a sign-up screen. */
.dr-invite {
  margin: 14px; padding: 16px 15px;
  border-radius: var(--r-md);
  background: linear-gradient(140deg, var(--gold-wash-2), var(--surface));
  border: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 6px; text-align: start;
}
.dr-invite b { font-size: .9375rem; }
.dr-invite > span { font-size: .78125rem; color: var(--muted); line-height: 1.55; }
.dr-invite .btn { margin-top: 6px; width: 100%; }
#drLang .lang-pill {
  background: var(--line-soft);
  color: color-mix(in srgb, var(--text) 80%, transparent);
  border-color: transparent;
}
.dr-invite-link {
  font-size: .78125rem; color: var(--gold-bright); font-weight: 600;
  text-align: center; padding: 6px 0 0; width: 100%;
}

/* ---------- commercial prices behind a free account ---------- */
.price-gate {
  margin-top: 14px; padding: 16px 15px;
  border-radius: var(--r-md);
  background: linear-gradient(140deg, var(--gold-wash-2), var(--surface));
  border: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 12px;
}
.price-gate > span {
  display: flex; align-items: center; gap: 8px;
  font-size: .8125rem; color: var(--muted);
}
.price-gate svg { color: var(--gold); flex: 0 0 16px; }

/* ---------- advertise: a package that opens where it stands ---------- */
.ad-card { margin-bottom: 10px; }
.ad-card .price-card { margin-bottom: 0; }
.ad-card.selected .price-card { border-radius: var(--r-md) var(--r-md) 0 0; }
.ad-more {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .2s var(--ease);
  background: var(--surface);
  border-inline: 1px solid var(--line);
  border-block-end: 1px solid var(--line);
  border-radius: 0 0 var(--r-md) var(--r-md);
}
.ad-card.selected .ad-more {
  grid-template-rows: 1fr;
  border-color: var(--gold);
  background: linear-gradient(140deg, var(--gold-wash-2), var(--surface));
}
.ad-card:not(.selected) .ad-more { border-color: transparent; }
.ad-more-inner {
  overflow: hidden; min-height: 0;
  visibility: hidden; transition: visibility .2s var(--ease);
}
.ad-card.selected .ad-more-inner { visibility: visible; padding: 0 14px 14px; }

.ad-points { list-style: none; margin: 12px 0 0; padding: 0; }
.ad-points li {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: .78125rem; color: var(--muted); line-height: 1.6;
  margin-bottom: 6px;
}
.ad-points svg { color: var(--gold); flex: 0 0 14px; margin-top: 3px; }

/* the phone wireframe: plain rectangles, no images, no libraries */
.ad-preview { display: flex; gap: 14px; align-items: center; padding-top: 14px; }
.ph {
  flex: 0 0 82px; height: 140px; padding: 5px;
  border: 2px solid var(--line); border-radius: 12px;
  background: var(--bar);
  display: flex; flex-direction: column; gap: 4px;
}
.ph-row { display: block; border-radius: 3px; background: var(--line-soft); }
.ph-bar { height: 10px; background: var(--wash-3); }
.ph-line { height: 6px; width: 55%; background: var(--wash-4); }
.ph-cats { display: flex; gap: 3px; background: none; }
.ph-cats i { flex: 1; height: 9px; border-radius: 50%; background: var(--wash-3); }
.ph-nav { margin-top: auto; height: 11px; border-radius: 3px; background: var(--wash-3); }
.ph-ad {
  background: linear-gradient(140deg, var(--gold-bright), var(--gold));
  box-shadow: 0 0 0 2px var(--gold-wash-3);
}
.ad-preview-key { display: flex; flex-direction: column; gap: 5px; align-items: flex-start; }
.ad-here {
  font-size: .71875rem; font-weight: 700; color: var(--on-gold);
  background: linear-gradient(145deg, var(--gold-bright), var(--gold));
  padding: 4px 10px; border-radius: 999px;
}
.ad-where { font-size: .75rem; color: var(--muted); line-height: 1.5; }

.ad-gate-note {
  margin-top: 8px; text-align: center;
  font-size: .71875rem; color: var(--muted); line-height: 1.5;
}

.ad-guide-link {
  width: 100%; margin-top: 4px; padding: 13px 6px;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  font-size: .84375rem; font-weight: 600; color: var(--gold-bright);
}
.ad-guide-link svg { color: var(--gold); }

.guide-row {
  width: 100%; display: flex; align-items: center; gap: 12px;
  padding: 13px 4px; text-align: start;
  border-bottom: 1px solid var(--line-soft);
}
.guide-row .g-ico { color: var(--gold); flex: 0 0 22px; }
.guide-row .g-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.guide-row .g-txt b { font-size: .875rem; }
.guide-row .g-txt span { font-size: .75rem; color: var(--gold-bright); }
.guide-row .chev { color: var(--muted); }
.guide-row:active { background: var(--gold-wash-1); }

@media (prefers-reduced-motion: reduce) {
  .ad-more, .ad-more-inner { transition: none; }
}

/* ============================================================
   V.01.8 — hours, attributes, duplicates
   ============================================================ */

/* the open / closed pill, on the card and on the detail page */
.open-pill {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .71875rem; font-weight: 700;
  padding: 3px 8px; border-radius: 7px;
  white-space: nowrap;
}
.open-pill svg { flex: 0 0 12px; }
.open-pill.open   { background: var(--green-bg);  color: var(--green); border: 1px solid var(--green-line); }
/* a quiet warning, not an alarm — they are still open */
.open-pill.soon   { background: var(--gold-wash-1);  color: var(--gold-bright); border: 1px solid var(--line); }
.open-pill.closed { background: var(--wash-2); color: var(--text-2); border: 1px solid var(--line-soft); }

/* the week table on a business page */
.hours-block { border-block-end: 1px solid var(--line-soft); padding: 14px 0; }
.hours-head { display: flex; align-items: center; gap: 12px; }
.hours-head .i-ico { color: var(--gold-bright); flex: 0 0 20px; }
.hours-head b { font-size: .9375rem; }
.hours-head .open-pill { margin-inline-start: auto; }
.hours-week { margin-block-start: 10px; padding-inline-start: 32px; }
.hours-row {
  display: flex; justify-content: space-between; gap: 10px;
  font-size: .8125rem; padding: 4px 0; color: var(--muted);
}
.hours-row.today {
  color: var(--text); font-weight: 700;
}
.hours-row.today span:first-child::before {
  content: ''; display: inline-block;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--gold-bright); margin-inline-end: 6px; vertical-align: middle;
}

/* prayer / mass times */
.worship-block { padding-block-start: 4px; }
.wor-head {
  display: flex; align-items: center; gap: 7px;
  font-size: .875rem; font-weight: 700; color: var(--gold-bright);
  padding: 14px 0 8px;
}
.wor-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; padding-block-end: 12px; }
.wor-cell {
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: 10px; padding: 8px 4px; text-align: center;
}
.wor-cell b { display: block; font-size: .71875rem; font-weight: 700; }
.wor-cell span { font-size: .71875rem; color: var(--gold-bright); }

/* ============================================================
   PRAYER TIMES
   The bar is one line and must stay one line: it sits above the
   fold on Home, and a second line costs the whole app a band of
   screen for something that is read in a glance.
   ============================================================ */
.pr-bar {
  display: flex; align-items: center; gap: 8px;
  width: calc(100% - 32px); margin: 10px 16px 0;
  min-height: 44px; padding: 0 12px;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: 12px; color: var(--text);
  font-size: .84375rem; text-align: start;
}
.pr-bar > svg { flex: 0 0 auto; color: var(--gold); }
.pr-bar-name { font-weight: 700; white-space: nowrap; }
.pr-bar-at { font-weight: 700; color: var(--gold-bright); white-space: nowrap; }
.pr-bar-left {
  color: var(--muted); margin-inline-start: auto;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pr-bar.unset { border-style: dashed; color: var(--muted); }

.pr-next {
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: 16px; padding: 18px 16px; text-align: center;
}
.pr-next-label { font-size: .78125rem; color: var(--muted); }
.pr-next-name { font-size: 1.5125rem; font-weight: 700; font-family: var(--font-display); margin-block-start: 4px; }
.pr-next-at { font-size: 2.0625rem; font-weight: 700; font-family: var(--font-display); color: var(--gold-bright); line-height: 1.2; }
.pr-next-left { font-size: .84375rem; color: var(--text-2); margin-block-start: 4px; }

.pr-list { margin-block-start: 14px; border: 1px solid var(--line-soft); border-radius: 14px; overflow: hidden; }
.pr-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 14px; background: var(--surface);
  border-block-end: 1px solid var(--line-soft);
}
.pr-row:last-child { border-block-end: 0; }
.pr-row-name { font-family: var(--font-display); font-weight: 600; display: flex; align-items: center; gap: 8px; }
.pr-row-at { font-family: var(--font-display); font-weight: 700; color: var(--gold-bright); }
/* sunrise is not a prayer. It is printed among them because it is what a
   fasting person is actually asking about, and greyed so it is not one. */
.pr-row.sun .pr-row-name, .pr-row.sun .pr-row-at { color: var(--muted); font-weight: 600; }
.pr-row.next { background: var(--wash-2); }
.pr-group { font-size: .6875rem; color: var(--muted); font-weight: 500; }

.wor-fix {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .78125rem; font-weight: 600; color: var(--muted);
  background: none; border: 0; padding: 8px 0;
}

/* the attribute pills under a description */
.attr-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-block-start: 12px; }
.attr-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .75rem; font-weight: 600;
  padding: 5px 10px; border-radius: 999px;
  background: var(--wash-2);
  border: 1px solid var(--line-soft);
  color: var(--text-2);
}
.attr-chip svg { color: var(--gold); flex: 0 0 14px; }

/* multi-select attribute pickers: the filter sheet and the add form */
.attr-pick { display: flex; flex-wrap: wrap; gap: 8px; }
.attr-pick .chip { height: 38px; }
.attr-group { margin-block-end: 14px; }
.attr-group-label { font-size: .78125rem; font-weight: 700; color: var(--muted); margin-block-end: 7px; }

/* seven-day hours editor */
.hrs-grid { display: flex; flex-direction: column; gap: 7px; }
.hrs-row { display: flex; align-items: center; gap: 7px; }
.hrs-day { flex: 0 0 40%; display: flex; align-items: center; gap: 7px; font-size: .84375rem; }
.hrs-day input { width: 17px; height: 17px; accent-color: var(--gold); flex: 0 0 17px; }
.hrs-t { height: 40px; padding: 0 8px; font-size: .8125rem; flex: 1; min-width: 0; direction: ltr; }
.hrs-dash { color: var(--muted); }
.hrs-row:has(input[type="checkbox"]:not(:checked)) .hrs-t,
.hrs-row:has(input[type="checkbox"]:not(:checked)) .hrs-dash { opacity: .35; pointer-events: none; }

/* the duplicate warning */
.delta { font-size: .71875rem; font-weight: 700; margin-inline-start: 5px; }
.delta.up { color: var(--green); }
.delta.down { color: var(--danger-ink); }

/* ---------- the picker row and its drop-down (V.02.4) ---------- */
/* One row, and it never scrolls sideways. The two pickers share whatever
   width is left after the filter button, which keeps its own size so it
   is always in the same place under the reader's thumb. */
.ctl-row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 14px 0;
}
.ctl {
  flex: 1 1 0; min-width: 0;
  height: 46px; padding: 0 12px;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  color: var(--text);
  text-align: start;
}
.ctl.open { border-color: var(--gold-wash-4); }
.ctl > svg { flex: 0 0 16px; color: var(--muted); transition: transform .16s ease; }
.ctl.open > svg { transform: rotate(180deg); }
/* the value can be long — it truncates, and the row's height never moves */
.ctl-txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.ctl-k { font-size: .65625rem; color: var(--muted); }
.ctl-v {
  font-size: .875rem; font-weight: 700; color: var(--gold-bright);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ctl-row .filter-btn { flex: 0 0 auto; height: 46px; width: 46px; }

/* The panel is in the flow: it pushes the results down rather than
   covering them, so the reader never loses sight of where they were. */
.dd-panel {
  margin: 8px 14px 0;
  background: var(--surface-2);
  border: 1px solid var(--gold-wash-3);
  border-radius: 16px;
  overflow: hidden;
}
.dd-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 14px;
  font-size: .78125rem; color: var(--muted);
  border-block-end: 1px solid var(--line);
}
.dd-total { color: var(--gold); font-weight: 700; }
.dd-scroll { max-height: 45dvh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.dd-row {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px;
  background: none; border: 0;
  color: var(--ink); font-size: .90625rem; text-align: start;
}
.dd-row + .dd-row { border-block-start: 1px solid var(--wash-2); }
.dd-row > svg { flex: 0 0 18px; color: var(--muted); }
.dd-nogap { flex: 0 0 18px; }
.dd-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-row .chip-n { flex: 0 0 auto; }
.dd-tick { flex: 0 0 18px; display: flex; color: var(--gold-bright); }
.dd-row.selected { background: var(--gold-wash-2); }
.dd-row.selected .dd-name { color: var(--gold-bright); font-weight: 700; }
.dd-row:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }

/* the quick attribute chips wrap onto a second line instead of running
   off the edge — same rule: an option you cannot see does not exist */
.chip-wrap {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px 14px 0;
}
.chip-wrap:empty { display: none; }

/* ---------- search and filters (batch four) ---------- */
/* The magnifier used to shrink to ~13px because flex-shrink defaults to 1
   and the row was crowded. It is now on a row of its own and refuses to
   shrink, in gold rather than the body colour. */
.search-row.solo { padding-inline: 14px; }
.search-row.solo .search-bar { flex: 1 1 auto; min-width: 0; }
/* the chip shares the row with the search field: same height so the pair
   reads as one control, never wider than 44% so the field keeps the space,
   and its label truncates instead of wrapping the row onto two lines */
.search-row.solo .loc-chip {
  flex: 0 0 auto; height: 52px; max-width: 44%; min-width: 0;
  border-radius: var(--r-md); padding-inline: 13px;
}
.search-row.solo .loc-chip svg { flex: 0 0 17px; }
.search-row.sub { padding: 8px 14px 0; gap: 8px; }
.search-bar.big {
  /* 38, not 52. At 52 with a 22px lens there were fifteen pixels of air
     above it and fifteen below; at 38 there are eight. (My reservation is
     on the record once — search is the most important thing on the screen
     and 42 was easier — and the decision is Rai's.) */
  height: 38px;
  background: var(--surface-2);
  border: 1px solid var(--gold-wash-3);
}
.search-bar.big > svg { flex: 0 0 22px; width: 22px; height: 22px; color: var(--gold-bright); }
.search-bar.big input { font-size: .9375rem; }
/* The search field is not `.input`, so `.input::placeholder` never reached it
   and it kept the BROWSER's default #757575 — identical in both themes, which
   is the proof it was never styled at all. Measured 4.10 light and 2.51 dark.
   The fade rule below owns `opacity` and says nothing about colour, so the
   colour is added here rather than folded into it.
   Dark takes `--text-2`, not `--muted`: the field's ground is `--surface-2`,
   and «--muted is never put on --surface-2» is the V.02.5 rule, measured 3.79.
   This field was the case the rule had missed, not an exception to it.
   After: 7.74 light and 8.45 dark. */
.search-bar input::placeholder { color: var(--muted); }
[data-theme="dark"] .search-bar input::placeholder { color: var(--text-2); }

/* the fade duration is written FROM `HINT_FADE_MS`, never typed here — one
   value in data.js and no second copy that could drift from it */
.search-bar.big input::placeholder { transition: opacity var(--hint-fade, 250ms) var(--ease); }
.search-bar.big input.hint-out::placeholder { opacity: 0; }
.search-clear {
  flex: 0 0 26px; width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; color: var(--muted);
  background: var(--wash-2); border: 0;
}
.chip-n {
  font-size: .6875rem; font-weight: 700; opacity: .7;
  margin-inline-start: 4px;
}
.chip.chip-grid { flex: 0 0 auto; padding-inline: 12px; }

/* every category at once, no sideways scroll */
.cat-box { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.cat-box-cell {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 12px 6px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-soft);
  color: var(--text);
}
.cat-box-cell.active { border-color: var(--gold); background: var(--gold-wash-2); }
.cat-box-cell .cc-ico { color: var(--gold-bright); }
.cat-box-cell .cc-label { font-size: .75rem; line-height: 1.3; text-align: center; }
.cat-box-cell .cc-count { font-size: .6875rem; color: var(--muted); }

/* what is filtering the list right now, and how to switch each one off */
.pill-row { display: flex; flex-wrap: wrap; gap: 7px; padding: 10px 14px 0; }
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; border-radius: 999px;
  font-size: .78125rem; color: var(--gold-bright);
  background: var(--gold-wash-2); border: 1px solid var(--gold-wash-4);
}
.pill.clear { color: var(--muted); background: transparent; border-color: var(--line); }
.pill.sugg { color: var(--text); }
.sugg-row { display: flex; flex-wrap: wrap; gap: 7px; justify-content: center; margin-top: 10px; }

.near-miss {
  display: flex; align-items: center; gap: 6px;
  margin: 6px 14px 0; font-size: .78125rem; color: var(--gold-bright);
}
.near-miss svg { flex: 0 0 15px; }

/* the sheet's own footer — a sibling of the scrolling body, never inside it */
.sheet-foot {
  flex: 0 0 auto;
  display: flex; gap: 10px; align-items: center;
  margin: 0 -16px calc(-22px - env(safe-area-inset-bottom));
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  background: var(--surface); border-block-start: 1px solid var(--line-soft);
}
.sheet-foot .btn-gold { flex: 1 1 auto; }
.sheet-foot .btn:disabled { opacity: .45; }

/* `input[type=range]` does not follow `direction: rtl` the same way in
   every engine — WebKit on iPhone left the thumb at the far left with the
   track full while the label read "5 miles", the smallest value. So the
   control is pinned to LTR everywhere and mirrored in Arabic, which puts
   the smallest value on the right and cannot disagree with the label. */
.range {
  width: 100%; accent-color: var(--gold); margin: 6px 0 0;
  direction: ltr;
}
[dir="rtl"] .range { transform: scaleX(-1); }

/* the card you came back from */
.list-row.flash { animation: flashRow 1.1s ease-out; }
@keyframes flashRow {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  20%, 60% { box-shadow: 0 0 0 2px var(--gold-wash-4); }
}

/* published contact details — a real address, not a form */
.contact-box {
  width: 100%; padding: 14px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-soft);
}
.cb-title { font-weight: 700; font-size: .9375rem; margin-block-end: 4px; }
.contact-line {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 0; font-size: .875rem; color: var(--text);
  border-block-start: 1px solid var(--line-soft);
}
.contact-line svg { color: var(--gold-bright); flex: 0 0 18px; }

/* seven numbers do not need a charting library */
.spark {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 4px; height: 44px; margin: 12px 2px 4px;
}
.spark-bar {
  flex: 1 1 0; border-radius: 3px 3px 0 0;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold-wash-3));
}

/* how much of a placement is left, said under its price */
.ad-avail {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 0 14px 10px; margin-top: -4px;
  font-size: .75rem; color: var(--muted);
}
.ad-avail svg { flex: 0 0 14px; }
.ad-avail.full { color: var(--gold-bright); }
.ad-avail .link-gold { font-size: .75rem; }

/* monthly / yearly, and the plan switch inside "my subscription" */
.seg {
  display: flex; gap: 6px; padding: 5px;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: 14px;
}
.seg-btn {
  flex: 1 1 0; min-width: 0; padding: 11px 8px;
  border-radius: 10px; font-size: .875rem; font-weight: 600;
  color: var(--muted); background: transparent; border: 0;
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
.seg-btn.active {
  background: linear-gradient(145deg, var(--gold-bright), var(--gold));
  color: var(--on-gold);
}
.seg-tag {
  font-size: .65625rem; font-weight: 700; padding: 1px 6px;
  border-radius: 999px; background: color-mix(in srgb, var(--on-gold) 18%, transparent);
}
.seg-btn:not(.active) .seg-tag { background: var(--line); color: var(--gold-bright); }

/* what the law wants read before any card field */
.consent-box {
  padding: 4px 12px 12px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--gold-wash-3);
}

.consent-text {
  margin: 8px 0; white-space: pre-wrap; word-break: break-word;
  font-family: inherit; font-size: .78125rem; line-height: 1.75; color: var(--text);
}

.sub-hero { text-align: center; padding: 4px 0 14px; }
.sub-status {
  display: inline-block; padding: 3px 12px; border-radius: 999px;
  font-size: .78125rem; font-weight: 600; border: 1px solid;
}
.sub-status.trialing { color: var(--gold-bright); border-color: var(--gold-wash-4); }
.sub-status.active   { color: var(--green); border-color: var(--green-line); }
.sub-status.canceled { color: var(--muted); border-color: var(--line); }
.sub-status.past_due { color: var(--danger-ink); border-color: var(--danger-line); }
.sub-amount { display: block; font-size: 2rem; font-weight: 700; color: var(--text); margin-block-start: 10px; }
.sub-amount span { font-size: .875rem; color: var(--muted); margin-inline-start: 4px; }

/* the one thing that must not reach launch day unnoticed */
.demo-warn {
  display: flex; align-items: center; gap: 8px;
  margin: 10px 14px 0; padding: 9px 12px;
  border-radius: var(--r-sm);
  background: var(--gold-wash-2); border: 1px solid var(--gold-wash-4);
  color: var(--gold-bright); font-size: .8125rem; line-height: 1.5;
}
.demo-warn svg { flex: 0 0 17px; }

/* one item waiting on a human decision, in the admin panel */
.q-card {
  padding: 12px; margin-block-end: 9px;
  border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-soft);
}
.q-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.q-head b { font-size: .90625rem; }
.conf-tag {
  flex: 0 0 auto; padding: 1px 8px; border-radius: 999px;
  font-size: .6875rem; line-height: 1.8; border: 1px solid;
}
.conf-tag.certain { color: var(--danger-ink); border-color: var(--danger-line); }
.conf-tag.likely  { color: var(--gold-bright); border-color: var(--gold-wash-4); }
.conf-tag.weak    { color: var(--muted); border-color: var(--line); }

/* "we found a listing that looks like yours" — the existing page, shown
   in full, because the person has to recognise it to claim it */
.sim-card {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--gold-wash-3);
  margin-block-end: 8px;
}
.sim-ico {
  width: 54px; height: 54px; flex: 0 0 54px;
  border-radius: 14px; display: grid; place-items: center;
  background: var(--gold-wash-2); color: var(--gold-bright);
}
.sim-photo { width: 54px; height: 54px; flex: 0 0 54px; border-radius: 14px; object-fit: cover; }
.sim-main { min-width: 0; }
.sim-main .row-sub { margin-block-start: 2px; }

.dup-warn {
  margin-block-end: 14px; padding: 14px;
  border-radius: var(--r-md);
  background: var(--danger-bg);
  border: 1px solid var(--danger-line);
}
.dup-head { display: flex; align-items: center; gap: 8px; font-size: .90625rem; margin-block-end: 10px; }
.dup-head svg { color: var(--danger-ink); flex: 0 0 18px; }
.dup-row {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 10px; margin-block-end: 8px;
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: 10px;
}
.dup-row .row-ico { width: 38px; height: 38px; flex: 0 0 38px; }
.dup-row .row-title { font-size: .875rem; }

/* ============================================================
   V.01.9 — photos, reviews, ownership, verification, import
   ============================================================ */

/* the gold business badge, deliberately unlike the blue personal one */
.badge-bizverified {
  background: linear-gradient(145deg, var(--gold-bright), var(--gold));
  color: var(--on-gold); border: none;
  margin-inline-start: 6px;
}
.badge-bizverified svg { flex: 0 0 12px; }

/* THE MARK ALONE, for every list. A gold shield the size of the personal
   blue circle, so a name that fitted one line still fits one line — the
   pill with its word measured 60px against 28 and turned every long name
   into two. The shape is the difference from the personal badge, and it
   is deliberately not a coloured circle: colour alone is not a signal. */
/* the state suggestion: a place to press, standing where a result list
   would be. It is a row and not a chip because it is an answer, and the
   reader who typed «TX» is owed one. */
/* THE SHARE MARK ON A PAID PLACEMENT. Small, in the corner, and never
   competing with the advertiser's own call to action: the advertiser is
   paying for the tap that opens them, and this one is for the shop owner
   who wants to send their own ad to their family. */
.ad-share {
  position: absolute; inset-block-start: 8px; inset-inline-start: 8px;
  display: inline-grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--ad-badge); color: var(--ad-cta);
  border: none; padding: 0; cursor: pointer; z-index: 2;
}
.mini-ad .ad-share {
  position: static; flex: 0 0 26px; width: 26px; height: 26px;
  background: transparent; color: var(--muted);
}
.list-row.spon .ad-share {
  position: static; flex: 0 0 30px;
  background: transparent; color: var(--muted);
}

.state-suggest {
  display: flex; align-items: center; gap: 10px;
  margin: 10px 14px 0; width: calc(100% - 28px);
  padding: 11px 13px; border-radius: 14px; text-align: start;
  background: var(--surface); border: 1px solid var(--line); color: var(--text);
  font: inherit; cursor: pointer;
}
.state-suggest svg { flex: 0 0 18px; color: var(--gold-bright); }
.state-suggest > span { display: grid; gap: 2px; min-width: 0; }
.state-suggest b { font-size: .9375rem; }
.state-suggest > span > span { font-size: .8125rem; color: var(--muted); }

.badge-shield {
  display: inline-grid; place-items: center;
  /* THE BOX IS THE GLYPH. An 18px box around a 12px shield spent six
     pixels on nothing, and «مطبخ ومخبز سامي اللبناني» — the longest
     Arabic name in the file — measured 242px of the 263 the row has, so
     those six pixels were the whole difference between one line and two.
     Measured after: 15px of 263 left over. */
  width: 14px; height: 14px;
  color: var(--gold-bright);
  /* ⚠️ NO MARGIN. `.row-title` is a flex row with `gap: 6px`, so a margin
     here is double spacing — and at 242px of the row's 263 for the longest
     Arabic name in the file, those four pixels were the whole difference
     between one line and two. */
  vertical-align: middle; flex: 0 0 14px;
}
/* the mark alone, standing beside a line that already names it. The
   selector is specific enough to beat `.i-txt span`, which is grey. */
.i-txt .badge-bizverified.mark { color: var(--on-gold); padding: 3px 6px; }

/* a real hero photo replaces the category icon when there is one */
.detail-hero.has-photo { padding: 0; }
.hero-img { width: 100%; height: 100%; object-fit: cover; }
.photo-tile.shot { padding: 0; overflow: hidden; position: relative; }
.photo-tile.shot img { width: 100%; height: 100%; object-fit: cover; }
.photo-tile.shot.pending { opacity: .72; }
.shot-flag {
  position: absolute; inset-block-end: 0; inset-inline: 0;
  font-size: .65625rem; text-align: center; padding: 3px 2px;
  background: var(--overlay); color: var(--gold-bright);
}

/* reviews: an empty state, not a gap */
.rev-empty { text-align: center; padding: 26px 18px; }
.rev-empty-ico {
  width: 60px; height: 60px; margin: 0 auto 10px;
  border-radius: 50%; display: grid; place-items: center;
  background: var(--gold-wash-1); border: 1px solid var(--line);
  color: var(--gold);
}
.rev-empty b { display: block; font-size: .96875rem; margin-bottom: 4px; }
.rev-empty span { font-size: .8125rem; color: var(--muted); }

/* the owner's answer, clearly theirs and clearly attached */
.owner-reply {
  margin: 10px 0 0; padding: 11px 13px;
  border-radius: 10px;
  background: var(--gold-wash-1);
  border-inline-start: 3px solid var(--gold);
}
.owner-reply .or-head {
  display: flex; align-items: center; gap: 6px;
  font-size: .75rem; font-weight: 700; color: var(--gold-bright);
}
.owner-reply p { margin: 5px 0 0; font-size: .84375rem; color: var(--text-2); }
.owner-reply svg { flex: 0 0 14px; }

/* owner controls and the claim invitation */
.owner-box, .claim-box {
  margin: 18px 0 0; padding: 14px;
  border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line);
}
.owner-head { display: flex; align-items: center; gap: 8px; font-size: .90625rem; }
.owner-head svg { color: var(--gold); flex: 0 0 18px; }
.claim-txt b { display: block; font-size: .9375rem; }
.claim-txt span { font-size: .78125rem; color: var(--muted); }

/* suggestions at the very foot of a free page — never sold */
.similar { margin-top: 22px; padding-top: 18px; border-block-start: 1px solid var(--line-soft); }

/* verification: consent is asked before anything is captured */
.privacy-box {
  padding: 14px; border-radius: var(--r-md);
  background: var(--wash-1); border: 1px solid var(--line-soft);
}
.privacy-box .pb-head { display: flex; align-items: center; gap: 8px; font-size: .875rem; }
.privacy-box .pb-head svg { color: var(--gold); flex: 0 0 18px; }
.privacy-box p { margin: 8px 0 0; font-size: .78125rem; color: var(--muted); line-height: 1.7; }
.consent-row {
  display: flex; gap: 11px; align-items: flex-start;
  font-size: .84375rem; line-height: 1.6; cursor: pointer;
}
.consent-row input { width: 20px; height: 20px; flex: 0 0 20px; margin-top: 2px; accent-color: var(--gold); }

/* the import preview: every row accounted for */
.imp-row {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; margin-bottom: 7px;
  border-radius: 10px;
  background: var(--surface); border: 1px solid var(--line-soft);
}
.imp-row.bad { border-color: var(--danger-line); background: var(--danger-bg); }
.imp-row.dup { border-color: var(--gold-wash-4); background: var(--gold-wash-1); }
/* a warning row still imports — it is marked, not refused */
.imp-row.warn { border-color: var(--gold-wash-3); }
.imp-pick { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.imp-pick input { width: 18px; height: 18px; accent-color: var(--gold); }
.imp-line { font-size: .65625rem; color: var(--muted); }
.imp-body { flex: 1; min-width: 0; }
.imp-body b { display: block; font-size: .875rem; }
.imp-why { font-size: .71875rem; margin-top: 3px; line-height: 1.5; }
.imp-why { display: flex; gap: 5px; align-items: flex-start; }
.imp-why svg { flex: 0 0 12px; margin-top: 3px; }
.imp-why.err { color: var(--danger-ink); }
.imp-why.warn { color: var(--gold-bright); }
.imp-why.dup { color: var(--gold-bright); }
/* a public place in the preview: marked, not warned about */
.imp-tag {
  display: inline-block; margin-inline-start: 6px;
  padding: 1px 7px; border-radius: 999px;
  font-size: .6875rem; line-height: 1.7;
  color: var(--gold-bright); border: 1px solid var(--gold-wash-4);
}

/* ---------- "which section am I looking at" ---------- */
.sec-note {
  margin: 12px 14px 0;
  display: flex; align-items: baseline; gap: 8px;
}
.sec-note b { font-size: .90625rem; color: var(--gold-bright); }
.sec-note span { font-size: .75rem; color: var(--muted); }
/* the marketplace rules sit on the note, where the section is named */
.sec-note .info-dot { margin-inline-start: auto; }

/* ---------- notifications: new vs earlier ---------- */
.notif-group-label {
  padding: 14px 16px 6px;
  font-size: .78125rem; font-weight: 700; letter-spacing: .3px;
  color: var(--muted); text-transform: uppercase;
}
.notif-row.unread { position: relative; background: var(--gold-wash-1); }
.notif-row.unread::before {
  content: ''; position: absolute;
  inset-inline-start: 0; inset-block-start: 50%;
  width: 4px; height: 34px; margin-block-start: -17px;
  border-start-end-radius: 3px; border-end-end-radius: 3px;
  background: var(--gold-bright);
}

/* ---------- V.02.5: what used to be written into the JavaScript ----------
   A colour inside a template string cannot be themed, so none live there
   any more. These are the classes those inline styles turned into. */
.ink-danger { color: var(--danger-ink); }
.check-gold { width: 18px; height: 18px; accent-color: var(--gold); }
.tile-ico {
  width: 38px; height: 38px; border-radius: 11px;
  display: grid; place-items: center;
  background: var(--gold-wash-3); color: var(--gold-bright);
}
.tile-ico.lg { width: 40px; height: 40px; border-radius: 12px; background: var(--gold-wash-3); }
.done-mark {
  width: 84px; height: 84px;
  color: var(--green); border-color: var(--green-line); background: var(--green-bg);
}
.flag-pill { color: var(--danger-ink); background: var(--danger-bg); border-color: var(--danger-line); }
.hero-ico { color: var(--muted); }
.cta-center { align-self: center; background: linear-gradient(145deg, var(--gold-bright), var(--gold)); color: var(--on-gold); }

/* ---------- appearance: three ways, each showing itself ---------- */
.theme-pick { display: flex; flex-direction: column; padding: 4px 14px 0; gap: 8px; }
.theme-opt {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-soft);
  color: var(--text); text-align: start;
}
.theme-opt.on { border-color: var(--gold); background: var(--gold-wash-1); }
.tp-prev {
  flex: 0 0 46px; width: 46px; height: 32px; border-radius: 8px;
  border: 1px solid var(--line-soft); overflow: hidden;
  display: flex; flex-direction: column; justify-content: space-between; padding: 3px;
}
.tp-prev i { display: block; height: 6px; border-radius: 2px; }
.tp-prev b { display: block; height: 4px; width: 60%; border-radius: 2px; }
.tp-prev.dark  { background: var(--prev-d-bg); }
.tp-prev.dark i  { background: var(--prev-d-bar); }
.tp-prev.dark b  { background: var(--prev-d-gold); }
.tp-prev.light { background: var(--prev-l-bg); }
.tp-prev.light i { background: var(--prev-l-bar); }
.tp-prev.light b { background: var(--prev-l-gold); }
/* automatic shows both halves, which is exactly what it does */
.tp-prev.auto { background: linear-gradient(90deg, var(--prev-l-bg) 50%, var(--prev-d-bg) 50%); }
.tp-prev.auto i { background: linear-gradient(90deg, var(--prev-l-bar) 50%, var(--prev-d-bar) 50%); }
.tp-prev.auto b { background: linear-gradient(90deg, var(--prev-l-gold) 50%, var(--prev-d-gold) 50%); }
.tp-name { flex: 1 1 auto; font-size: .90625rem; font-weight: 600; }
.theme-opt.on .tp-name { color: var(--gold-bright); }
.tp-tick { flex: 0 0 18px; display: flex; color: var(--gold-bright); }

/* Four across, not four down: the choice is one axis and the A in each
   button already says which is which, so a column would be four rows of
   the same word. The buttons keep a fixed height while the A inside them
   grows, or the row itself would jump as the reader compares. */
.font-pick { display: flex; gap: 8px; padding: 4px 14px 0; }
.font-opt {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  height: 62px; padding: 6px 4px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-soft); color: var(--text);
}
.font-opt.on { border-color: var(--gold); background: var(--gold-wash-1); }
.font-opt .fo-a { font-weight: 700; line-height: 1; }
.font-opt.on .fo-a, .font-opt.on .fo-name { color: var(--gold-bright); }
.fo-name { font-size: .71875rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis;
           white-space: nowrap; max-width: 100%; }
/* A real directory row at the size on offer. Four words named «كبير» tell
   nobody how large large is. */
/* The count sits on the label, not under the field: under it is where the
   error goes, and two things in one place is neither of them. */
/* «تعرف مسجداً ليس هنا؟» — a quiet line and a small button, never a card
   competing with the list above it. */
.suggest-box {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 14px; border-radius: var(--r-md);
  background: var(--surface); border: 1px dashed var(--line-soft);
}
.suggest-txt { flex: 1 1 auto; min-width: 0; font-size: .84375rem; color: var(--text-2); }

/* The one question, asked once, in the strip's own place on Home. */
.pr-ask {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 10px 14px 0; padding: 12px 14px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--line-soft);
}
.pr-ask-txt { flex: 1 1 190px; display: flex; align-items: center; gap: 8px;
              font-size: .84375rem; font-weight: 600; color: var(--text); }
.pr-ask-btns { display: flex; gap: 8px; margin-inline-start: auto; }

/* The feast rows: a name on one side, a date on the other, and the word
   «تقديري» under the date where the date cannot be promised. */
.feast-row { align-items: center; }
.feast-at { margin-inline-start: auto; text-align: end; display: flex; flex-direction: column; gap: 1px; }
/* `plaintext`, NOT `isolate`. The first takes its direction FROM the text,
   the second imposes one on it — and «25 ديسمبر 2026» is Arabic with a
   number in it, so `.ltr` reordered its parts into «25 2026 ديسمبر». One
   class, no condition: the Arabic date reads Arabic and the English one
   reads English. */
.feast-date { unicode-bidi: plaintext; font-size: .84375rem; font-weight: 600; color: var(--text); }
.feast-est { font-size: .6875rem; font-weight: 600; color: var(--muted); }
/* an occasion keeps its place for a week after its day, dimmed and
   labelled «مضت» — still readable, and never mistaken for the next one */
.feast-row.past { opacity: .55; }
.feast-past { color: var(--muted); }
.feast-list .row-title { font-size: .875rem; }

.ch-count {
  float: inline-end; font-size: .71875rem; font-weight: 600; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.ch-count.over { color: var(--gold-bright); }

.font-sample {
  margin: 10px 14px 2px; padding: 12px 14px; border-radius: var(--r-md);
  background: var(--surface-2); color: var(--text);
  font-size: .84375rem; font-weight: 600;
}
.dr-end { margin-inline-start: auto; }
/* the light/dark flip lives in the drawer head, costing no row */
.drawer-head { position: relative; }
/* Neutral on purpose: gold in the drawer is spent on «أعلن معنا», the one
   row that earns money. An accent that marks everything marks nothing. */

/* ---- outside the covered areas ----
   Explains, never blocks: the listings stay right under it. And its
   height never changes, because it names no area — the names are in a
   sheet that opens. */
.outside-box { margin: 12px 0 4px; padding: 13px 14px; border-radius: 14px;
  background: var(--surface); border: 1px solid var(--line); }
.outside-head { display: flex; align-items: center; gap: 8px; color: var(--gold-bright);
  font-size: .9375rem; font-weight: 700; }
.outside-body { margin-block-start: 6px; color: var(--text-2); font-size: .84375rem; line-height: 1.6; }
.outside-btn { margin-block-start: 10px; display: flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--gold-bright); font-size: .875rem; font-weight: 700; font-family: inherit; }

/* ============================================================
   The drawer head's two buttons — V.05.5
   Rai's decision: «حسابي» and sign-out sit UNDER THE NAME, so neither
   depends on the panel not scrolling. They are 50% each of one row, so
   the head grows by one row's height and no more.
   ============================================================ */
.dr-head-acts { display: flex; gap: 8px; margin-top: 12px; }
.dr-act {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 9px 6px; border-radius: var(--r-sm);
  background: var(--wash-2); border: 1px solid var(--line);
  color: var(--text-2); font: inherit; font-size: .825rem; font-weight: 600;
  cursor: pointer;
}
.dr-act:active { background: var(--wash-3); }
.dr-act span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dr-act.ink-danger { color: var(--danger-ink); border-color: var(--danger-line); }

/* the three avatar kinds share one box — V.05.5 */
.av-wrap { display:grid; place-items:center; border-radius:50%; line-height:1; }
.av-wrap svg { width:100%; height:100%; display:block; }
.av-emoji { background: var(--surface-2); }
.av-pick { display:grid; grid-template-columns:repeat(6,1fr); gap:8px; margin-top:8px; }
.av-opt { padding:0; border:2px solid transparent; border-radius:50%; background:none; cursor:pointer; }
.av-opt[aria-pressed="true"] { border-color: var(--gold-bright); }
.av-opt .av-wrap { width:44px; height:44px; }

/* the social row — V.05.6. Every colour is a token, so it flips with the
   theme by itself; 40px clears the touch-target floor. */
.social-row { display:flex; gap:10px; justify-content:center; margin-top:14px;
  padding-top:12px; border-top:1px solid var(--line); }
.soc { width:40px; height:40px; border-radius:12px; display:grid; place-items:center;
  background:var(--surface-2); border:1px solid var(--line); color:var(--text-2); }
.soc:active { background:var(--wash-3); }
.soc-soon { opacity:.42; cursor:default; }
/* the same muted caption size the hints use; centred under the row it explains */
.social-soon { margin-top:6px; text-align:center; font-size:.75rem; color:var(--muted); }

/* ---------- the drawer's coloured tiles ----------
   ⚠️ 30px in a row whose content box is 23px (55 tall, minus 16+16 of
   padding), so a top-level row grows by 8 and a group head — which
   carried only an arrow before — by 10. «اللغة» is the one exception at
   67px: the tile sits inside the room it already had.
   Measured with a group open: a visitor 195 -> 231, a member 112 -> 156.
   ⚠️ AND FOLDED THE DRAWER IS STILL 0, for both roles and both themes.
   That is the rule that actually stands; the overflow above only ever
   appears with a group open, which was true before this too.
   ⚠️ AND THE LEAVES GET NOTHING. There is no rule here turning a tile off
   inside `.dr-sub`, because no leaf is ever given one — a stylesheet that
   undoes what the markup just asked for is two sources of truth. */
.dr-tile {
  width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: 9px; display: grid; place-items: center;
  background: hsl(var(--h) 58% 42%);
}
/* ⚠️ `!important` because `.dr-item svg` sets the muted ink for every glyph
   in the drawer and it is the more specific of the two by element type.
   The tile's whole job is that the glyph stops being drawer-grey. */
.dr-tile svg { color: #fff !important; flex: 0 0 19px; }
/* The one paid row. `--on-gold` is the ink the gold BUTTON already uses,
   so the tile and the button say gold the same way in both themes. */
.dr-tile-gold { background: linear-gradient(145deg, var(--gold-bright), var(--gold)); }
.dr-tile-gold svg { color: var(--on-gold) !important; }
/* the arrow keeps its own size beside a tile */

/* A two-column grid whose children have a minimum width of their own — a
   native date input is the case that forced this — becomes one column on a
   narrow screen instead of being cut at the edge. Opt-in, so no existing
   `.action-grid` (two buttons, which shrink happily) changes at all. */
@media (max-width: 400px) {
  .action-grid.stack-narrow { grid-template-columns: 1fr; }
}
