/* ============================================================
   pages.css — الصفحات المبنيّة في الخادم
   Styles for the server-rendered pages that Django added: the person
   permalink, the change log, the permission notice, plus the handful
   of controls the tree pages didn't already have.

   يعتمد كلياً على متغيّرات base.css فلا ألوان جديدة هنا.
   Built entirely on the base.css tokens — no new colours introduced.
   ============================================================ */

.page {
  max-width: 760px;
  margin-inline: auto;
  /* وحواشي الأمان هنا كذلك: أعلى الصفحة تحت النتوء، وأسفلُها تحت خطّ
     الإيماء — و`env` صفرٌ حيث لا نتوء.
     Safe-area insets here too; `env` is zero where there is no notch. */
  padding: calc(20px + env(safe-area-inset-top, 0px))
           calc(16px + env(safe-area-inset-right, 0px))
           calc(64px + env(safe-area-inset-bottom, 0px))
           calc(16px + env(safe-area-inset-left, 0px));
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.page__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.page__title {
  font-family: var(--font-head);
  font-size: 1.15rem;
  font-weight: 700;
  margin: 0;
}

.page__card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: 24px 20px;
}

.page__lead {
  color: var(--text-muted);
  font-size: .88rem;
  line-height: 1.8;
  margin: 0 0 14px;
}

.page__notice {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: 32px 24px;
  text-align: center;
  line-height: 1.9;
}

.page__notice h1 {
  font-family: var(--font-head);
  font-size: 1.2rem;
  margin: 12px 0;
}

.page__notice p { color: var(--text-muted); font-size: .92rem; margin: 0 0 16px; }

.page__code {
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  font-size: .82rem;
  overflow-x: auto;
  text-align: left;
}

.page__actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  margin-block-start: 18px;
}

/* الاسم الحالي في نهاية سلسلة النسب / the person themselves, closing the chain */
.lineage__self { font-weight: 700; color: var(--g, var(--accent)); }

/* روابط الأبناء في الصفحة المستقلة تأخذ شكل الأزرار نفسه */
.sons__item { text-decoration: none; color: inherit; }

/* ---------- سجلّ التعديلات / the change log table ---------- */
.log {
  width: 100%;
  border-collapse: collapse;
  font-size: .84rem;
}

.log th,
.log td {
  padding: 9px 10px;
  border-block-end: 1px solid var(--border);
  text-align: start;
  vertical-align: middle;
}

.log th {
  font-weight: 700;
  color: var(--text-muted);
  font-size: .78rem;
  white-space: nowrap;
}

.log tbody tr:hover { background: var(--surface-2); }

.log__when { color: var(--text-faint); white-space: nowrap; font-size: .78rem; }

/* ---------- مختصر سجلّ الدخول ---------- */

/* أعمدةُ العدّ تُقرأ بالمقارنة لا بالقراءة: أرقامٌ متساوية العرض
   موسّطةٌ في أعمدةٍ متساوية يفصلها خطّ، فيُرى الفرق بين يومٍ ويوم قبل
   أن يُقرأ. وخطّ الجدول أكبر قليلاً من خطّ السجلّ وأشدُّ سواداً: هذا
   مجملٌ يُنظر إليه، وذاك تفصيلٌ يُقرأ عند الحاجة.

   Counting columns are compared, not read: tabular figures centred in
   equal columns parted by a rule, so the difference between two days is
   seen before it is read. The type is a little larger and darker than
   the log's: this is a whole to be looked at, that is a detail to be
   read when wanted. */
.log--tally { font-size: .92rem; }
.log--tally th,
.log--tally td { text-align: center; color: var(--text); }
.log--tally th { font-size: .88rem; color: var(--text); }

/* خطٌّ بين عمودٍ وعمود — على كلّ خليّةٍ إلا الأولى، فيقع بينها لا حولها */
.log--tally th:not(:first-child),
.log--tally td:not(:first-child) {
  border-inline-start: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
  width: 13%;
}
.log--tally td:not(:first-child) { font-weight: 600; }

/* والتاريخ يُوسَّط مع رأسه، ولا يبقى باهتاً كتواريخ السجلّ */
.log--tally .log__when { color: var(--text); text-align: center; font-size: .92rem; }

/* ---------- رؤوسُ الأيّام والمحرّرين في سجلّ التعديلات ---------- */

/* لونان لا لونٌ واحد: رأسُ اليوم بلون الموقع، ورأسُ المحرّر بلون
   الإضافة — ولو تشابها لعادت الصفحة كتلةً واحدة تُقرأ سطراً سطراً.
   وخطٌّ فوق كلّ يومٍ يقطع ما قبله: الفاصل بين يومٍ ويوم يُرى قبل أن
   يُقرأ التاريخ.

   Two colours, not one: the day's head in the site's colour and the
   editor's in the colour of an addition — alike, they would collapse
   back into one block read line by line. A rule above each day cuts it
   from the one before, so the parting is seen before the date is read. */
.log__day > th {
  padding: 12px 10px;
  border-block-start: 3px solid var(--accent);
  border-block-end: 1px solid color-mix(in oklab, var(--accent) 30%, var(--border));
  background: color-mix(in oklab, var(--accent) 15%, var(--surface));
  color: var(--accent-strong);
  font-size: .86rem;
  white-space: normal;
}
/* وأوّلُ يومٍ في الصفحة لا يُقطع عمّا قبله — لا شيء قبله */
.log tbody:first-of-type .log__day > th { border-block-start: 0; }

.log__day-name { font-weight: 700; }
.log__day-date { margin-inline-start: 10px; }
.log__day-count {
  margin-inline-start: 8px;
  color: color-mix(in oklab, var(--accent-strong) 70%, var(--text-muted));
  font-weight: 400;
}

.log__by > th {
  padding: 8px 10px;
  padding-inline-start: 22px;   /* مُزاحٌ عن رأس اليوم فيُقرأ تحته لا بجانبه */
  border-block-end: 1px solid color-mix(in oklab, var(--success) 25%, var(--border));
  background: color-mix(in oklab, var(--success) 11%, var(--surface));
  color: var(--text);
  font-size: .82rem;
  white-space: normal;
}
.log__by-who { font-weight: 700; }
.log__by-count { margin-inline-start: 8px; color: var(--text-muted); font-weight: 400; }

/* وسطورُ المجموعة مُزاحةٌ قليلاً تحت رأسها */
.log--grouped tbody tr:not(.log__day):not(.log__by) td:first-child {
  padding-inline-start: 22px;
}

.log__action { font-size: .74rem; }
.log__action--create { color: var(--success); border-color: color-mix(in oklab, var(--success) 40%, var(--border)); }
.log__action--delete { color: var(--danger);  border-color: color-mix(in oklab, var(--danger) 40%, var(--border)); }
/* الدخول والخروج بلونين: التقرير يُقرأ بالنظر لا بقراءة كل كلمة، ولونان
   يفرزان العمود قبل أن يُقرأ.
   Two colours for in and out: a report is scanned, not read word by word,
   and two colours sort the column before it is read. */
.log__action--login  { color: var(--success); border-color: color-mix(in oklab, var(--success) 40%, var(--border)); }
.log__action--logout { color: var(--text-muted); }

.log__detail { color: var(--text-faint); }

/* اسم لم يعد له صفحة — محذوف من الشجرة */
.log__gone { color: var(--text-faint); text-decoration: line-through; }

.log__chip {
  display: inline-block;
  background: var(--surface-sunk);
  border-radius: var(--r-sm);
  padding: 1px 6px;
  margin-inline-end: 4px;
  font-size: .74rem;
}

/* الجدول ينزلق أفقياً على الجوال بدل أن يمدّ الصفحة */
@media (max-width: 620px) {
  .page__card { overflow-x: auto; }
  .log { min-width: 520px; }
}

/* ---------- الحسابات / accounts ---------- */

/* صندوق الرقم المولَّد: بارزٌ عمداً — يُقرأ مرّةً واحدة ثم لا يُقرأ.
   The one-time password card: deliberately loud — read now or never. */
.fresh {
  border: 1px solid color-mix(in oklab, var(--accent) 45%, var(--border));
  background: color-mix(in oklab, var(--accent) 8%, var(--surface));
}
.fresh__pair {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 14px;
  margin: 10px 0 16px;
  align-items: center;
}
.fresh__pair dt { color: var(--text-muted); font-size: .82rem; }
.fresh__pair dd {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: .04em;
  user-select: all;              /* ضغطةٌ واحدة تحدّده كلّه */
}
.fresh__fallback {
  inline-size: 100%;
  min-block-size: 6.5rem;
  margin-block-start: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font: inherit;
}
.page--narrow { max-width: 520px; }

.card__title {
  font-family: var(--font-head);
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 6px;
}

/* النماذج الطويلة في عمودين على الشاشات الواسعة */
.form--grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 0 16px; }
.form--grid > button { grid-column: 1 / -1; justify-self: start; }

.field__error { color: var(--danger); font-size: .78rem; }

.form__error {
  background: var(--danger-soft);
  border: 1px solid color-mix(in oklab, var(--danger) 40%, var(--border));
  color: var(--danger);
  border-radius: var(--r-sm);
  padding: 8px 12px;
  font-size: .84rem;
  margin-block-end: 12px;
}

/* رسائل النجاح والخطأ بعد كل إجراء */
.flash { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.flash__item {
  border-radius: var(--r-md);
  padding: 10px 14px;
  font-size: .88rem;
  border: 1px solid;
}

.flash__item--success { background: var(--success-soft); border-color: color-mix(in oklab, var(--success) 40%, var(--border)); color: var(--success); }
.flash__item--error   { background: var(--danger-soft);  border-color: color-mix(in oklab, var(--danger) 40%, var(--border));  color: var(--danger); }
.flash__item--info    { background: var(--surface-2);    border-color: var(--border); color: var(--text-muted); }

/* شرط كلمة المرور ونداء تغييرها — في صفحة تغييرها حيث يُقرآن.
   The rule and the demand, where the password is actually changed. */
.pw-required {
  margin: 0 0 12px;
  padding: 11px 14px;
  border: 1px solid var(--danger);
  border-radius: var(--r-md);
  background: var(--danger-soft);
  color: var(--danger);
  font-weight: 600;
  font-size: .9rem;
  line-height: 1.8;
}
.pw-rule {
  margin: 0 0 16px;
  padding: 9px 12px;
  border-radius: var(--r-md);
  background: var(--surface-sunk);
  color: var(--text-muted);
  font-size: .88rem;
  line-height: 1.8;
}

.accounts td { vertical-align: top; }
/* اسم الحساب زرّ التعديل — يبدو كاسمٍ حتى يُقترب منه.
   The name is the edit control; it looks like a name until approached. */
.accounts__open {
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  border-block-end: 1px dashed var(--border-strong);
}
.accounts__open:hover { color: var(--accent-strong); border-block-end-color: var(--accent); }

/* «تحديث» و«إلغاء» في سطر / the two buttons share a line */
.form__actions { display: flex; gap: 10px; align-items: center; }
/* سطرٌ واحد: قائمةٌ وزرّها بجانبها، وتلتفّ على الجوّال */
.form--row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.form--row .input { flex: 1 1 240px; min-inline-size: 0; }
.accounts__full { color: var(--text-faint); font-size: .78rem; }

/* أزرارُ التقارير الثلاثة: صفٌّ فوق البطاقة يلتفّ على الجوّال، والمفتوح
   منها مميّزٌ بـ`btn--on`.
   The three report buttons: a row above the card that wraps on a phone,
   with the open one marked by `btn--on`. */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-block-end: 14px;
}
.accounts__none { color: var(--text-faint); }
.accounts__on  { color: var(--success); font-weight: 600; font-size: .8rem; }
.accounts__off { color: var(--danger);  font-weight: 600; font-size: .8rem; }

/* سطرُ المطويّ: صندوقٌ واسمُه يُضغطان معاً — الوسمُ يلفّ الصندوق فيصير
   النصُّ كلُّه هدفاً، وسطرٌ رفيعٌ لا يزاحم عنوان القائمة فوقه.
   The label wraps the box so the whole line is the target. */
.accounts__folded { margin-block: .4rem 0; font-size: .85rem; }
.accounts__folded label {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  cursor: pointer;
}

/* سطرٌ تحت شارة الدور: القائمة والزرّ معاً فلا ينزل أحدهما وحده.
   ولا تحمل `inline-form`: تلك تفرض `display: inline` وتأتي بعدها في
   هذا الملف فتغلبها، فينزل الزرّ سطراً تحت القائمة.
   A line under the role chip. It deliberately does not carry
   `inline-form`: that rule forces `display: inline` and comes later in
   this file, which drops the button onto its own line. */
.accounts__role {
  display: flex;
  gap: 6px;
  align-items: center;
  margin: 6px 0 0;
}
.accounts__select {
  inline-size: auto;
  min-inline-size: 96px;
  padding: 4px 8px;
  font-size: .8rem;
}

/* لون لكل دور، ليُقرأ الجدول بلمحة */
.role--admin     { color: var(--danger);  border-color: color-mix(in oklab, var(--danger) 40%, var(--border)); }
.role--supervisor { color: var(--danger); border-color: color-mix(in oklab, var(--danger) 25%, var(--border)); }
.role--assistant { color: var(--accent);  border-color: color-mix(in oklab, var(--accent) 45%, var(--border)); }
.role--user      { color: var(--text-muted); }
.chip--self      { background: var(--surface-sunk); color: var(--text-muted); }
/* حسابٌ بلا اسمٍ في الشجرة: تنبيهٌ لا خطأ — يُرى ولا يصرخ.
   An account with no name in the tree: a notice, not an alarm. */
.chip--loose     { background: color-mix(in oklab, var(--danger) 12%, var(--surface)); color: var(--danger); }

.inline-form { display: inline; margin: 0; }

.assign {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--surface-sunk);
  border-radius: var(--r-sm);
  padding: 2px 4px 2px 8px;
  margin: 0 0 4px 4px;
  font-size: .8rem;
}

.assign__x {
  border: none;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
  font-size: .8rem;
  padding: 0 2px;
  line-height: 1;
}
.assign__x:hover { color: var(--danger); }

/* نموذج كلمة المرور مطويّ داخل الجدول حتى لا يزدحم */
.pw summary { display: inline-block; list-style: none; cursor: pointer; }
.pw summary::-webkit-details-marker { display: none; }
.pw__form { display: flex; flex-direction: column; gap: 6px; margin-block-start: 8px; min-width: 170px; }

/* ---------- عناصر تحكّم إضافية / small controls ---------- */
.check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: .88rem;
  cursor: pointer;
  line-height: 1.6;
}

.check input { inline-size: 18px; block-size: 18px; accent-color: var(--accent); cursor: pointer; }

/* زر الخروج داخل الشريط العلوي / logout sits inline in the top bar */
.logout-form { display: inline-flex; margin: 0; }

/* ---------- عين إظهار كلمة المرور / show-password toggle ---------- */
.pw-field { position: relative; display: block; }

/* مساحة للزر حتى لا يمرّ النصّ تحته */
.pw-field .input { padding-inline-end: 40px; }

.pw-eye {
  position: absolute;
  inset-inline-end: 5px;
  inset-block-start: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 30px;
  block-size: 30px;
  padding: 0;
  border: none;
  background: none;
  border-radius: var(--r-sm);
  color: var(--text-faint);
  cursor: pointer;
}

.pw-eye:hover { color: var(--text); background: var(--surface-sunk); }
.pw-eye svg { inline-size: 19px; block-size: 19px; }


/* شارات سجلّ الدخول — الفاشلة وحدها تلفت النظر */
.log__action--login  { border-color: color-mix(in oklab, var(--success, var(--gen-1)) 45%, var(--border)); color: var(--gen-1); }
.log__action--logout { color: var(--text-muted); }
.log__action--failed { border-color: color-mix(in oklab, var(--danger, var(--gen-2)) 55%, var(--border)); color: var(--gen-2); font-weight: 700; }


/* ---------- أبواب القبيلة في الصفحة الرئيسية ---------- */
.home__head {
  text-align: center;
  /* فسحةٌ عن حافّة الصفحة — أوّل شاشةٍ بعد الدخول لا تبدأ ملتصقةً بالحافّة */
  padding-block: 44px 8px;
}
.home__title { font-size: 1.55rem; line-height: 1.4; }
/* الدعاء تحت الاسم: لوحٌ أبيض وحبرٌ أسود، بلا حدٍّ مرسوم.
   يُحيط بالنصّ وحده لا بعرض الصفحة (`inline-block`)، ويُوسَّط بما حوله.
   واللونان مثبَّتان لا مأخوذان من متغيّرات السمة: طُلب أبيضُ وأسود،
   فيبقيان كذلك في الوضعين — والليليُّ يقرؤه لوحاً ناصعاً على أرضٍ داكنة.

   The prayer under the name: a white plate with black ink, no border and
   no rounding. It hugs the text rather than the page's width and is
   centred by its surroundings. The two colours are fixed rather than
   taken from the theme's tokens — white and black were asked for, and
   they stay so in both themes. */
.home__lead {
  display: inline-block;
  /* ويُنزَّل عن الاسم قليلاً: لوحٌ ملتصقٌ بما فوقه يُقرأ ذيلاً للعنوان
     لا سطراً قائماً بنفسه.
     Dropped a little below the name: a plate touching what is above it
     reads as the heading's tail rather than a line of its own. */
  margin-block-start: 26px;
  padding: 10px 18px;
  background: #fff;
  color: #000;
  border: 0;
  /* واستدارةُ الأبواب تحته (`--r-lg` نفسها في `.door`): لوحٌ حادُّ
     الزوايا فوق بطاقاتٍ مستديرة يُقرأ غريباً عنها، والصفحة واحدة.
     The doors' own rounding below it — a sharp-cornered plate above
     rounded cards reads as a stranger to them, and the page is one. */
  border-radius: var(--r-lg);
  font-size: .95rem;
}

/* سطر الإدارة — بخطّ SF Article Bold وحبرٍ أسود.
   كان أزرقَ غامقاً، فطُلب الأسود؛ والخطُّ مشترًى بترخيصٍ لصاحب الموقع
   ويُستعمل في هذا السطر وحده. وإعلانتُه في قالب الرئيسية لا في ملفّ
   ساكن: الملفّ يُخدم من القاعدة برابطٍ يحمل بصمة (انظر `SiteFont`).
   The administration line: SF Article Bold in black ink. It was deep
   blue; black was asked for. The face is licensed to the site's owner
   and used on this line alone; its `@font-face` sits in the home page's
   template because the file is served from the database under a stamped
   URL that a static stylesheet cannot know.
   The stewards' line: deep blue and a touch larger, so it carries across
   a sand-coloured page where the turquoise faded into it. */
.home__stewards {
  margin: 26px 0 0;
  text-align: center;
  /* لا `var(--font-head)` بعده: خطُّ الموقع يبتلع باء «البرمجة» فتُقرأ
     «الرمجة»، فالاحتياطيُّ خطُّ النظام لا هو (انظر `--font-article`).
     Not `--font-head` behind it: the site face swallows the bā' of
     «البرمجة», so the fallback is the system face instead. */
  font-family: var(--font-article);
  font-size: 1.14rem;
  font-weight: 700;
  line-height: 1.9;
  color: #000;
}

/* العنوان في سطرٍ والأسماء في الذي يليه، وكلُّ صفةٍ مع صاحبها لا تنقطع
   عنه عند طرف السطر.
   The heading on one line and the names on the next, each role kept whole
   with its name rather than broken at the edge of the line. */
.home__stewards-head,
.home__stewards-roles { display: block; }
.home__stewards-roles { font-size: .96em; }
.home__stewards-roles span { display: inline-block; white-space: nowrap; }

.home__foot {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  /* الفسحة صغرت لأن سطر المشرفين صار فوقها ويحمل فسحته */
  margin-block-start: 14px;
  padding-block-start: 20px;
  border-block-start: 1px solid var(--border);
}

.doors {
  display: grid;
  /* عمودان على الحاسب وعمودٌ على الجوّال — بلا استعلام وسائط:
     `auto-fit` مع `minmax` تتكفّل، فلا رقمَ شاشةٍ يُخمَّن. */
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
}

.door {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 14px;
  align-items: center;
  padding: 20px 18px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  color: inherit;
  transition: transform .15s, box-shadow .15s, border-color .15s;
}
.door:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: var(--shadow-md);
}
.door:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.door__icon {
  grid-row: 1 / 3;
  font-size: 1.9rem;
  line-height: 1;
}
.door__title { font-family: var(--font-head); font-size: 1.15rem; font-weight: 700; }

/* رقمُ الجديد على الباب: عند طرفه، خارجَ مجرى العنوان فلا يزيحه.
   The unseen count, at the door's far end, out of the title's flow. */
.door { position: relative; }
.door__count {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: 16px;
  transform: translateY(-50%);
  min-inline-size: 1.7em;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: .85rem;
  font-weight: 700;
  line-height: 1.5;
  text-align: center;
}

/* ---------- صفحة اللويبات: عنوانٌ كبير وأبوابٌ موسّطة ---------- */

/* العنوان ثلاثةُ أضعاف عنوان الصفحات (١٫١٥ريم): صفحةٌ ليس فيها إلا
   اسمٌ وأبواب، فيؤخذ للاسم حجمُه.
   Three times the pages' heading: this page holds a name and a row of
   doors, so the name is given its size. */
.trees__title {
  text-align: center;
  font-size: 3.45rem;
  line-height: 1.15;
  margin-block: 4px 20px;
}

/* والأبواب هنا اسمٌ وحده بلا رمز، فعمودٌ واحد موسَّط لا عمودان —
   ولولا ذلك لبقي الاسم لاصقاً بحافّة البطاقة حيث كان الرمز.
   The doors here carry a name and no icon, so one centred column: with
   two, the name would keep the edge the icon used to leave it. */
.doors--trees .door {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
}
.doors--trees .door__title { font-size: 1.3rem; }


/* ---------- فهرس الأجيال ---------- */
.gen-index__lead { margin-block-end: 20px; }

/* الخطّ المستقيم بين كل جيلٍ والذي يليه */
.gen-index__rule {
  margin-block: 22px;
  border: 0;
  border-block-start: 1px solid var(--border-strong);
}

.gen-index__generation { margin-block: 4px; }

/* عنوان الجيل في وسط الصفحة لا على حافّتها: الأسماء تحته تُرصّ عمودين
   أو ثلاثة، فالعنوان على الحافّة يصير عنواناً للعمود الأوّل وحده. وفي
   الوسط يعلو الأعمدة كلّها فيُقرأ فاصلاً بين جيلٍ وجيل.
   The generation heading is centred, not on the edge: the names below it
   run in two or three columns, and a heading on the edge reads as the
   first column's. Centred, it sits above them all and reads as the break
   between one generation and the next. */
.gen-index__title {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 0 0 12px;
  font-size: 1.05rem;
  color: var(--g, var(--accent-strong));
}
.gen-index__count {
  padding: 1px 9px;
  border-radius: 999px;
  background: var(--surface-sunk);
  color: var(--text-muted);
  font-size: .78rem;
  font-weight: 700;
}

/*
   أعمدةٌ لا سطرٌ واحد: الأسماء قصيرة والشاشة عريضة، فسردها عموداً
   واحداً يجعل الجيل الواحد شاشتين. و`columns` يوزّعها بلا حسابٍ لعددها.
   Columns rather than one long list: the names are short and the screen
   is wide, so a single column would make one generation two screensful.
*/
.gen-index__names {
  list-style: none;
  margin: 0;
  padding: 0;
  /* أعمدةٌ لا سطرٌ واحد: الأسماء قصيرة والشاشة عريضة، فسردها عموداً
     واحداً يجعل الجيل الواحد شاشتين. والعرض الأدنى ٢٤٠ بكسلاً يكفي
     «فلان بن فلان بن فلان»، وعلى الجوّال يصير عموداً واحداً وحده.
     Columns rather than one long list; the 240px floor fits a triple name,
     and a phone collapses to a single column on its own. */
  /* العرض وحده بلا عدد: يملأ المتصفّح ما وسعه — عمودان أو ثلاثة على
     الشاشة، وواحدٌ على الجوّال — بلا عددٍ مفروض يقاوم الانكماش. الأسماء
     قصيرة والشاشة عريضة، فسردها عموداً واحداً يجعل الجيل شاشتين.
     Column width with no count: the browser fits as many as it can and
     falls to one on a phone, with no imposed count resisting the shrink.
     ٢٤٠ بكسلاً تسع «فلان بن فلان بن فلان». */
  columns: 240px;
  column-gap: 26px;
}
.gen-index__names li { break-inside: avoid; margin-block-end: 3px; }

/* والاسم الخماسيّ أطول من الثلاثيّ بمقدار أبٍ وجدّ، فعمودُه أوسع —
   وإلّا انكسر الاسم الواحد سطرين وضاع «بن» في طرف العمود.
   A five-name lineage is two names longer than a triple, so its column is
   wider; otherwise one name breaks over two lines. */
.gen-index__names--long { column-width: 320px; }

/* سطرا صفحة الأسماء في المنتصف وبحبر النصّ: صفحةٌ عمودُها الأسماء
   وهي موسّطةٌ في عمودين، فسطرٌ مزاحٌ إلى الحافّة باهتُ اللون يُقرأ
   حاشيةً لا عنواناً لما تحته.

   وسوادُ الموقع `var(--text)` لا `#000`: الصفحة تقلب ألوانها مع الوضع
   الليلي، ولو ثُبّت أسود لصار غير مقروء فيه.

   The page's two notes are centred and set in the text's own ink: the
   names are centred in their columns, so a faint line pushed to the edge
   reads as a margin note rather than as the heading it is. The black is
   the site's `var(--text)`, not `#000`, so it turns with the night
   theme. */
.names__note { text-align: center; color: var(--text); }

/* سطرُ الجهاز والعنوان تحت الاسم في تقارير الدخول — أصغر من الاسم
   وأخفُّ حبراً، فيُقرأ تابعاً له لا سطراً ثانياً بإزائه.
   The device-and-address line under the name: smaller and lighter, read
   as the name's tail rather than as a second line beside it. */
.report__mark { font-size: .74rem; margin-block-start: 2px; }

/* دلالةُ التثبيت: سطرٌ فوق البلاطات، يُقرأ ثمّ يُغلق فلا يعود */
.install {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  margin-block-end: 14px;
  border: 1px solid color-mix(in oklab, var(--accent) 35%, var(--border));
  border-radius: var(--r-lg);
  background: color-mix(in oklab, var(--accent) 8%, var(--surface));
  font-size: .86rem;
}
.install__mark { font-size: 1.3rem; }
.install__say { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.install__say span { color: var(--text-muted); line-height: 1.6; }

/* ---------- «لوحتي»: شاشةُ التطبيق ---------- */

/* شبكةٌ تملأ ما وجدت: عمودٌ على الشاشة المطويّة (نحو ٤١٢ بكسلاً)،
   وثلاثةٌ على المفتوحة (نحو ٨٨٤) — بلا عرضٍ مكتوبٍ لجهازٍ بعينه، فما
   يُكتب لجهازٍ يسقط عند غيره.
   A grid that fills what it finds: one column on a folded screen, three
   on an unfolded one, with no device's width written into it. */
.console {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  margin-block-end: 16px;
}

/* والبلاطة كبيرةٌ تُضغط بالإبهام: الإصبع لا يصيب رابطاً في سطر */
.console__tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-block-size: 74px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  color: var(--text);
  text-decoration: none;
  font-family: var(--font-head);
  font-size: 1.02rem;
  font-weight: 700;
  transition: transform .12s, box-shadow .12s, border-color .12s;
}
.console__tile:hover,
.console__tile:focus-visible {
  transform: translateY(-2px);
  border-color: color-mix(in oklab, var(--accent) 45%, var(--border));
  box-shadow: var(--shadow-md);
}
.console__tile:active { transform: translateY(0); }

.console__mark {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  block-size: 44px;
  border-radius: 50%;
  background: color-mix(in oklab, var(--accent) 12%, var(--surface-sunk));
  font-size: 1.35rem;
}
.console__name { flex: 1; }

/* عدّادُ ما ينتظر عملاً — على البلاطة لا داخل الصفحة */
.console__count {
  flex: none;
  min-inline-size: 28px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: .82rem;
  text-align: center;
}

.console__form { margin-block-end: 8px; }

/* ---------- صورةُ البطاقة مكبَّرة ---------- */

/* الصورة في البطاقة زرٌّ بلا هيئةِ زرّ: هي نفسها ما يُضغط، فلا يُزاد
   عليها إطارٌ ولا حشو — وإنّما مؤشّرٌ يقول إنّها تُكبَّر.
   The photo is the button: nothing is drawn around it, only a cursor
   that says it opens. */
.hero__zoom {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  line-height: 0;
}

.lightbox {
  padding: 0;
  border: 0;
  background: transparent;
  max-inline-size: 100vw;
  max-block-size: 100vh;
  overflow: visible;
}
.lightbox::backdrop { background: rgb(0 0 0 / .82); }

/* بأبعادها لا فوقها: `max-*` تُنقص ولا تزيد، و`auto` تمنع التمديد —
   فالصورة تُعرض بدقّتها التي رُفعت بها (٢٤٠٠ بكسلاً على الحدّ الأطول)
   أو أصغر إن ضاقت الشاشة، ولا تُمطّ فتتشوّه.
   Its own size and no larger: `max-*` only shrinks and `auto` refuses to
   stretch, so the picture shows at the resolution it was stored with —
   2400px on its longest edge — or smaller on a narrow screen, never
   blown up. */
.lightbox__photo {
  display: block;
  inline-size: auto;
  block-size: auto;
  max-inline-size: 96vw;
  max-block-size: 92vh;
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
}

.lightbox__close {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 8px;
  width: 36px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  border: 0;
  border-radius: 50%;
  background: rgb(0 0 0 / .55);
  color: #fff;
  font-size: 1rem;
  cursor: pointer;
}
.lightbox__close:hover { background: rgb(0 0 0 / .75); }

/* أزرارُ الشجرة في شريط الصفحة — كما في لوحة الإدارة */
.bar__trees {
  display: flex;
  align-items: center;
  gap: 6px;
  /* شريطٌ يُسحب لا صفٌّ يفيض: سبعُ شجراتٍ لا تسع الشاشة الخارجية للجهاز
     المطويّ (نحو ٤١٢ بكسلاً)، فكانت تخرج من الحافّتين ويُقصّ أوّلها
     وآخرها. والسحبُ يبقيها كلَّها في متناول الإبهام، ويجرّها القارئ كما
     يجرّ أي شريطِ خياراتٍ على جوّاله.
     A strip that is dragged rather than a row that spills: seven trees do
     not fit the fold's cover screen (about 412px), so the first and last
     were being cut off. Dragging keeps every one of them within a thumb's
     reach. */
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  /* ولا شريط تمرير يأكل من ارتفاع الشريط العلويّ */
  scrollbar-width: none;
}
.bar__trees::-webkit-scrollbar { display: none; }
.bar__trees > * { flex: none; scroll-snap-align: center; }

/* ---------- سطورُ الأسماء: رقمٌ ولونان ---------- */

/* لونان يتناوبان على السطور، والشريط يغطّي السطر كلَّه لا ما تحت الحروف:
   مئتا اسمٍ متشابهةِ الطول في عمودين تُقرأ فيها العينُ سطراً مكان سطر،
   والتناوب يمسك موضعها.

   Two colours taking turns, each band covering the whole line rather
   than just the letters: in two columns of look-alike names the eye
   slips a line, and the alternation holds its place. */
.names__list li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-block-end: 0;          /* شريطٌ يلي شريطاً بلا فرجة */
  padding: 2px 8px;
  border-radius: var(--r-sm);
}
.names__list li.is-band { background: var(--surface-sunk); }

/* والرقم ترتيبُ الاسم في الهجاء: أرقامٌ متساوية العرض مصفوفةٌ على طرفها،
   وحبرُها أخفُّ من حبر الاسم فلا تزاحمه.
   Equal-width figures aligned on their end, in a lighter ink than the
   name so they do not compete with it. */
.names__num {
  flex: none;
  min-inline-size: 2.4em;
  text-align: end;
  color: var(--text-muted);
  /* أصغرُ من الاسم دائماً: لمّا صغُر الاسم إلى ٨٢. تساوى الرقمُ معه
     فقرآ سطراً واحداً، والرقم تابعٌ لا قرين.
     Always smaller than the name: when the name came down to .82 the two
     matched and read as one line; the ordinal follows the name. */
  font-size: .76rem;
  font-variant-numeric: tabular-nums;
}

/* واسمُ هذه الصفحة أصغر من اسم صفحة الأجيال: ٨٢. لا ٩٢.
   قِيس ذلك ولم يُخترَ ذوقاً — في عمودٍ عرضُه ٣٥٠ بكسلاً تقريباً: الاسم
   الخماسيّ يسع سطراً عند ٩٢.، والسداسيّ لا يسعه حتى ينزل إلى ٨٢.
   فنزل. وما فوق ذلك — سباعيٌّ أو سداسيٌّ بلقب — لا يسع سطراً عند أيّ
   قياسٍ يُقرأ (جُرّب حتى ٧٢.)، وعلّتُه أنّ الصفحة ٧٦٠ بكسلاً وفيها
   عمودان: لا يجتمع عمودان وسبعةُ أسماءٍ في سطر إلا بصفحةٍ أعرض.
   وصفحةُ الأجيال تبقى على ٩٢. — أسماؤها ثلاثيّة وأربعُها أقصر.

   Measured, not guessed: in a ~350px column a five-name lineage fits at
   .92 and a six-name one only from .82 down, so .82 it is. Longer than
   that — seven names, or six with a laqab — fits at no readable size
   (tried down to .72): the page is 760px and holds two columns, and two
   columns plus seven names do not share a line. The generations index
   keeps .92; its names are shorter. */
.names__list .gen-index__name { font-size: .82rem; }

/* والاسم بحبر النصّ في كل حال — ولو زاره القارئ من قبل: لا يُترك للون
   المتصفّح الافتراضيّ للروابط المزارة.
   The name keeps the text's ink even after it has been visited, rather
   than falling to the browser's default for visited links. */
.names__list .gen-index__name,
.names__list .gen-index__name:visited {
  flex: 1;
  color: var(--text);
}

/* والأسماء تُملأ سطورُها من الحافّة إلى الحافّة: خماسيّاتٌ متقاربة
   الطول، فتساوي أطرافُها يجعل العمود كتلةً تُقرأ لا حافّةً مسنّنة.
   The lines are filled edge to edge: five-name lineages run to similar
   lengths, and squaring their ends turns the column into a block that
   reads rather than a ragged edge. */
.gen-index__names--long .gen-index__name {
  text-align: justify;
  text-align-last: justify;
}

.gen-index__name {
  display: block;
  padding: 5px 8px;
  border-radius: var(--r-sm);
  color: var(--text);
  text-decoration: none;
  font-size: .92rem;
  line-height: 1.6;
}
.gen-index__name:hover,
.gen-index__name:focus-visible {
  background: var(--surface-sunk);
  color: var(--accent-strong);
}


/* ---------- معلوماتي ---------- */
.me__who { font-weight: 700; color: var(--text); margin-block-end: 18px; }

.me__photo {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-block-end: 18px;
}
.me__frame {
  flex: none;
  inline-size: 96px;
  block-size: 96px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-sunk);
  box-shadow: 0 0 0 3px var(--g, var(--accent));
}
.me__img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
.me__blank { display: block; inline-size: 100%; block-size: 100%; }
.me__photo-actions { display: flex; flex-direction: column; gap: 6px; align-items: start; }
/* اللصيقة زرٌّ لأن حقل الملفّ نفسه لا يُنسَّق — والمؤشّر يقول إنها تُضغط.
   The label is the button because a file input cannot be styled. */
.me__photo-actions label { cursor: pointer; }

/* ---------- صور القبيلة / the album ----------

   صفحةٌ أوسع من أخواتها: البقيّة نصٌّ يُقرأ في سطرٍ قصير فحُدّت بسبعمئةٍ
   وستّين، وهذه صورٌ تُنظر — والعين تكسب من العرض ما يخسره السطر.
   Wider than its sisters: they are text, and text is read in a short
   measure; this is photographs, and the eye gains from width what a line
   of prose loses. */
.page--wide { max-width: 1080px; }

/* البلاطة تتبع الشاشة لا رقماً مكتوباً: `clamp` تجعلها أربعين بالمئة من
   عرض الجوّال — فبلاطتان لا واحدة — ولا تدعها تتجاوز ٢١٦ على الحاسب،
   فلا تصير أربع صورٍ عملاقة.
   The tile follows the screen: 40% of a phone's width, so two fit rather
   than one, and never past 216px on a desktop. */
.album {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(9rem, 40vw, 13.5rem), 1fr));
  gap: 14px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.album__link {
  display: block;
  text-decoration: none;
  border-radius: var(--r-lg);
}
.album__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* الإطار الناعم: حاشيةٌ من ورق الصفحة حول الصورة، وحلقةٌ رفيعة بلون
   الجيل، وظلٌّ يرفعها عن السطح. لا خطّ حادّ ولا زاوية قائمة — النعومة
   من الحاشية والاستدارة والظلّ مجتمعةً، لا من حدٍّ يُثخَّن.

   A mat of the page's own paper around the picture, a hairline ring in
   the generation's colour, and a shadow that lifts it off the surface.
   The softness comes from mat, radius and shadow together — not from
   thickening a border. */
.album__frame {
  --mat: 6px;
  position: relative;
  margin: 0;
  padding: var(--mat);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow:
    0 0 0 1px color-mix(in oklab, var(--g, var(--accent)) 26%, transparent),
    var(--shadow-md);
  transition: box-shadow .2s, transform .2s;
}

.album__link:hover .album__frame,
.album__link:focus-visible .album__frame {
  transform: translateY(-2px);
  box-shadow:
    0 0 0 2px color-mix(in oklab, var(--g, var(--accent)) 45%, transparent),
    var(--shadow-lg);
}

/* البايتات كما رُفعت، والمتصفّح ينزّلها إلى مقاس البلاطة — فتبقى حادّة
   على الشاشات عالية الكثافة. و`cover` مع مركزٍ مرفوع قليلاً: الوجوه في
   أعلى الصورة غالباً، والقصّ من الوسط يقطع الجباه.
   The uploaded bytes, downscaled by the browser to the tile — sharp on a
   dense screen. `cover` with the centre raised, since faces sit in the
   upper part and a centred crop cuts foreheads. */
.album__photo {
  display: block;
  inline-size: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: 50% 32%;
  border-radius: var(--r-md);
  background: var(--surface-sunk);
}

/* الاسم على الصورة لا تحتها. والتدرّج تحته لأن الخلفيات تختلف: أبيضُ
   على صورةٍ فاتحة لا يُقرأ. ويظلم أسفلها وحده فيبقى الوجه على حاله.
   The name on the picture. The gradient because backgrounds differ —
   white on a pale one cannot be read — and it darkens only the foot, so
   the face is left alone. */
.album__name {
  position: absolute;
  inset-inline: var(--mat);
  inset-block-end: var(--mat);
  /* الحشو السفليّ يرفع الاسم عن حافّة الإطار، والعلويّ يمدّ التدرّج
     فوقه فلا يبدأ عند الحرف فجأةً. وقُلّم العلويّ حين صار الاسم خماسيّاً:
     سطرانِ يعطيان التدرّجَ مداه، فلو بقي الحشو على سعته لعلا على الصدر.
     The lower padding lifts the name off the frame's edge, the upper one
     lets the gradient start above the letters rather than at them — and it
     was trimmed when the name went to five parts: two lines give the
     gradient its run-up, and the old padding would have climbed the chest. */
  padding: 22px 10px 13px;
  border-end-start-radius: var(--r-md);
  border-end-end-radius: var(--r-md);
  background: linear-gradient(
    to top,
    rgb(0 0 0 / .78),
    rgb(0 0 0 / .48) 48%,
    rgb(0 0 0 / 0)
  );
  color: #fff;
  font-family: var(--font-head);
  /* المقاس على حاله والسطران مقبولان: الاسم الخماسيّ لا يُصغَّر ليُحشر
     في سطر — يُقرأ من بعيد أهمّ من أن يقف في سطرٍ واحد. و`balance` يقسم
     السطرين نصفين فلا يبقى في الثاني كلمةٌ وحيدة.
     The size stands and two lines are welcome: a five-part name is not
     shrunk to be squeezed into one. `balance` splits the two lines evenly
     so the second is never left with a lone word. */
  font-size: .9rem;
  font-weight: 700;
  line-height: 1.4;
  text-align: center;
  text-wrap: balance;
  text-shadow: 0 1px 3px rgb(0 0 0 / .6);
}

/* ---------- أسر الجماعة: الأب وأبناؤه ---------- */

/* دائرةُ الحرف لمن لا صورة له. وتأخذ مقاس البلاطة ونسبتَها فلا يختلّ
   الصفّ، وحرفُها كبيرٌ باهتٌ لا يُقرأ اسماً — هو علامةُ موضعٍ ينتظر
   صورة، لا اسمٌ يُغني عنها.
   A lettered tile for whoever has no picture: it takes the tile's own
   size and ratio so the row stays even, and its letter is large and
   faint — a place waiting for a photograph, not a name standing in. */
.album__photo--blank {
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: 100%;
  aspect-ratio: 3 / 4;
  border-radius: var(--r-md);
  background: var(--surface-sunk);
  color: color-mix(in oklab, var(--g, var(--accent)) 55%, transparent);
  font-family: var(--font-display, inherit);
  font-size: 3rem;
  line-height: 1;
  user-select: none;
}

/* شريطُ الآباء: طريقُ الصعود، يلتفّ على الشاشات الضيّقة ولا يُقصّ —
   من قُصّ عليه أعلى النسب فقد الطريق إلى الجدّ.
   The fathers' bar wraps rather than scrolling out of reach. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-block-end: 12px;
}

/* بطاقةُ الأب: صورتُه إلى جانب اسمه ونسبه — أكبر من بلاطات أبنائه
   ليُقرأ الصفُّ «هذا الرجل، وهؤلاء بنوه» بنظرةٍ واحدة.
   The father's card: larger than his sons' tiles, so the page reads
   "this man, and these are his sons" at a glance. */
.family__head {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.family__photo {
  inline-size: 96px;
  aspect-ratio: 1;
  object-fit: cover;
  object-position: 50% 32%;
  border-radius: 50%;
  background: var(--surface-sunk);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--g, var(--accent)) 45%, transparent);
  flex: none;
}
.family__photo--blank {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.2rem;
  color: color-mix(in oklab, var(--g, var(--accent)) 60%, transparent);
  user-select: none;
}
.family__say { min-width: 0; flex: 1; }
.family__name { margin: 0; font-size: 1.15rem; }
.family__lineage { margin: .2rem 0 0; color: var(--text-muted); font-size: .9rem; }
.family__meta { margin: .35rem 0 0; font-size: .82rem; color: var(--text-faint); }

/* ---------- الألبوم الخاص: صورةٌ وتحتها كلام ---------- */

/* بلاطاته أوسع من بلاطات صور القبيلة: تلك وجهٌ واحد يُعرف من مربّعٍ
   صغير، وهذه مجالسُ ومناسبات — والوجوه فيها تصغر حتى لا تُعرف إن ضاقت
   البلاطة. فبلاطةٌ واحدة على الجوّال وثلاثٌ على الحاسب.
   Wider tiles than the tribe's album: that one is a single face, legible
   in a small square, while these are gatherings whose faces shrink past
   knowing if the tile is narrow. One per phone screen, three on a desktop. */
.album--told {
  grid-template-columns: repeat(auto-fill, minmax(clamp(15rem, 88vw, 20rem), 1fr));
}

/* الصورة كاملةً بلا قصّ: صور القبيلة وجوهٌ تُقصّ إلى مربّعٍ واحدٍ فتصطفّ،
   وهذه مناسباتٌ — من قُصَّ طرفُها ذهب نصفُ الحاضرين، ومن صوّر بجوّاله
   طولاً رأى صورته مبتورةً من أعلاها وأسفلها. فلا نسبة مفروضة: كلّ صورةٍ
   على نسبتها، والبلاطة تطول بطولها. والحدّ الأعلى لئلّا تبتلع صورةٌ
   طويلةٌ الشاشة كلَّها.

   The whole picture, uncropped. The tribe's album crops faces to one
   square so they line up in a grid; these are occasions, and a trimmed
   edge takes half the gathering with it — a phone-held portrait loses its
   top and bottom. So no ratio is imposed: every picture keeps its own and
   the tile grows to fit, with a ceiling so one tall photograph cannot
   swallow the screen. */
.album__photo--whole {
  aspect-ratio: auto;
  block-size: auto;
  max-block-size: 78vh;
  object-fit: contain;
}

/* التفاصيل تحت الصورة داخل الإطار: أسطرٌ تُقرأ، ولو كُتبت على الصورة
   لحجبت ما تشرحه. ولا تُقصّ بالنقاط — من كتب ثلاثة أسطرٍ أرادها تُقرأ.
   The words under the picture, inside the mat: lines to be read, which
   written across the frame would cover what they describe. Never
   ellipsised — whoever wrote three lines meant them to be read. */
.album__told {
  padding: 10px 4px 2px;
  color: var(--text);
  font-size: .84rem;
  line-height: 1.75;
  white-space: pre-line;
  overflow-wrap: anywhere;
}

/* ذيلُ البلاطة: من رفعها ومتى، والحذف عند طرفه — خارج الإطار فلا
   يزاحم الصورة ولا يُضغط سهواً.
   The tile's foot: who put it up and when, with the delete at its far
   end — outside the mat, so it neither crowds the picture nor is pressed
   by accident. */
.album__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 4px 0;
  color: var(--text-muted);
  font-size: .74rem;
}
.album__when { margin-inline-start: 6px; opacity: .8; }

/* ملصقةُ اختيار الصورة واسمُ ما اختير في سطرٍ واحد */
.album__pick {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* بطاقةُ الألبوم في «معلوماتي»: فاصلٌ عمّا فوقها فلا تُقرأ ذيلاً للنموذج */
.me__album { margin-block-start: 16px; }

@media (prefers-reduced-motion: reduce) {
  .album__frame { transition: none; }
  .album__link:hover .album__frame,
  .album__link:focus-visible .album__frame { transform: none; }
}


/* ============================================================
   أخبار الجماعة — ما أُرسل إلى الأجهزة، يُقرأ بعد حين

   بطاقاتٌ في عمودٍ واحد لا جدول: صفحةُ المرسِل جدولٌ لأنّ فيها عمودَ
   «كم جهازاً بلغه» وهو شأنُه وحده. وهذه تُقرأ على جوّالٍ في يدٍ واحدة،
   فالخبرُ فيها فقرةٌ تُقرأ لا صفٌّ تمسحه العين.

   Cards in one column, not a table: the sender's page is a table because
   it carries a "how many devices" column, which is his business alone.
   ============================================================ */
.news {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.news__item {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.news__mark {
  font-size: 1.5rem;
  line-height: 1.2;
  flex: 0 0 auto;
}

/* و`260px` أساسٌ لا مقاس: يطلبه النصُّ فينكسر الصفُّ دونه فينزل
   الزرّان، ويشرحُ فوقه على السعة. و`min-width: 0` تُلزم السطر الطويل
   بالكسر داخل المرن.
   A basis, not a width: the text asks for it, the row breaks rather
   than starve it, and the actions drop below. */
.news__say { flex: 1 1 260px; min-width: 0; }

/*
 * `.news` وإخوتُها بقيت لقائمة «طلباتُ نشرٍ» في صفحة الإرسال وحدها —
 * صفحةُ الأخبار صارت صفوفاً (`.rows`) وحُذفت بطاقاتُها.
 *
 * وسقط معها التوسيطُ الذي كان لها: كان العنوانُ وسطرُ التوقيع
 * موسَّطين في البطاقة، وكان ذلك يقع سهواً على قائمة الطلبات أيضاً —
 * وهي قائمةُ عملٍ يمسحها المراجعُ بعينه، والتوسيطُ يُبطئ مسحَها.
 *
 * These stayed for the pending-requests list on the sending page alone.
 * The centring that came with the card fell with it: it had been landing
 * on that work list too, where a swept eye wants a fixed left edge.
 */
.news__title {
  font-family: var(--font-head);
  font-size: 1.02rem;

}

.news__body {
  margin: 4px 0 0;
  line-height: 1.85;
  /* نصُّ الخبر يكتبه المرسِل، وقد يأتي بكلمةٍ لا فراغ فيها */
  overflow-wrap: anywhere;
}

.news__by {
  margin: 8px 0 0;
  color: var(--text-muted);
  font-size: .82rem;

}


/* ما عولج من طلبات النشر: يبقى ولا يُزاحم ما ينتظر
   Handled requests stay, without crowding what still waits. */
.news__item--done { opacity: .62; }
.news__item--done .news__title { font-weight: 600; }

.news__done {
  flex: 0 0 auto;
  align-self: center;
  color: var(--text-muted);
  font-size: .82rem;
  white-space: nowrap;
}

/* وزرُّ الحذف بمحاذاة «أُرسلت» نفسها: الصفُّ يبدأ من أعلاه، فلو تُرك
   الزرُّ على أصل الصفّ علا السطرَ الذي يخصّه.
   The delete button sits on the "أُرسلت" line: the row aligns to its
   top, which would otherwise float the button above its own text. */
.news__item--done .inline-form { flex: 0 0 auto; align-self: center; }


/* ------------------------------------------------------------
   صورةُ الخبر

   بعرضٍ كامل وارتفاعٍ محدود: الصور تأتي بأبعادٍ شتّى — لقطةُ شاشةٍ
   طويلة وصورةُ حفلٍ عريضة — ولو تُركت على طبيعتها لدفعت ما بعدها من
   الأخبار خارج الشاشة. و`object-fit: cover` تملأ الإطار بلا تشويه،
   والضغطةُ تفتحها كاملةً في لسانٍ آخر لمن أراد.

   Full width, bounded height: pictures arrive in every shape, and a
   tall screenshot left to itself would push the next item off the
   screen. A press opens the whole of it in a new tab.
   ------------------------------------------------------------ */


/* وفي صفحة التعديل تُرى كاملةً لا مقصوصة: المقصودُ أن يعرف ما يُبدّله */
.news__shot-edit {
  display: block;
  max-width: 100%;
  max-height: 260px;
  width: auto;
  border-radius: var(--radius);
  margin-block: 6px;
}


/* ------------------------------------------------------------
   منتقي صورةِ الخبر — نتائجُ بحثٍ بوجوهها

   والوجهُ صغيرٌ إلى جانب الاسم لا بطاقةٌ كبيرة: المقصودُ تأكيدُ أنّ
   الرجل هو هو قبل الإرسال، لا تصفّحُ الألبوم. واثنتا عشرة نتيجةً
   تُقرأ في شاشةٍ واحدة.

   A small face beside the name, not a card: it confirms the right man
   before sending rather than inviting a browse.
   ------------------------------------------------------------ */
.pick__list {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  max-height: 280px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.pick__one {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
}

.pick__one:hover,
.pick__one:focus-visible { background: var(--surface-sunk); }

.pick__one img {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
}

.pick__none {
  padding: 10px;
  color: var(--text-muted);
  font-size: .88rem;
}

.pick__chosen {
  margin: 8px 0 4px;
  color: var(--text-muted);
  font-size: .88rem;
}


/* صفحاتُ الأخبار: زرّان وموضعٌ بينهما، في وسط السطر */
.news__pages {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-block-start: 16px;
}

.news__where { color: var(--text-muted); font-size: .85rem; }


/* ============================================================
   الشكل الثاني: صفوف — صورةٌ مربّعةٌ صغيرة إلى جانب سطرين

   يُقرأ الخبرُ كلُّه في سطرين، ويُرى ثلاثةُ أخبارٍ في شاشةٍ واحدة بدل
   واحد. و«يُرى» هو المقصود: من فتح الصفحة يمسح ما جدّ بعينه ثمّ يقف
   عند ما يعنيه — والبطاقةُ الكبيرة تُحسن عرضَ الخبر الواحد وتُسيء
   عرضَ العشرة.

   Three items to a screen instead of one: the reader sweeps what is new
   and stops at what concerns him. A big card shows one item well and ten
   items badly.
   ============================================================ */
.rows {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
}

/*
 * سطران في الصفّ: العنوانُ فوق على عرضه كلِّه، ثمّ الصورةُ والنصّ.
 *
 * «اجعل أعلى الصورة في مستوى النصّ». وكانت تبدأ عند العنوان فتعلوه،
 * فيبقى إلى جانبها سطرٌ قصيرٌ ثمّ فراغ. وبهذا يُقرأ العنوانُ في سطرٍ
 * واحد بدل سطرين، ويُسند النصُّ إلى الوجه.
 *
 * Two lines: the headline across the top, then the picture and the body.
 * It used to start level with the headline and rise above it, leaving a
 * short line beside it and then emptiness.
 */
.rows__one {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px 12px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

/* العنوانُ يأخذ ما بقي من سطره، فتنزل الأزرارُ إلى جانبه لا تحته */
.rows__one .rows__title { flex: 1 1 auto; }

/* والسطر الثاني على عرض الصفّ: صورةٌ ونصٌّ يبدآن معاً */
.rows__line {
  flex: 1 1 100%;
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

/* الصورةُ مربّعةٌ مقصوصةٌ من أعلاها: صورةُ الوجه طوليّة، وقصُّها من
   الوسط يقطع الرأس. والكاملةُ على بُعد ضغطة. */
.rows__shot {
  flex: 0 0 auto;
  display: block;
  width: 72px;
  height: 72px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-sunk);
}

.rows__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  display: block;
}

/* ومن لا صورة لخبره يقوم رمزُه مقامها، فلا يختلّ الصفّ */
.rows__mark {
  flex: 0 0 auto;
  width: 72px;
  height: 72px;
  display: grid;
  place-items: center;
  font-size: 1.8rem;
  border-radius: 10px;
  background: var(--surface-sunk);
}

.rows__say { flex: 1 1 200px; min-width: 0; }

.rows__title { font-family: var(--font-head); font-size: .98rem; }

.rows__body {
  margin: 3px 0 0;
  line-height: 1.7;
  font-size: .9rem;
  overflow-wrap: anywhere;
}

.rows__by {
  margin: 5px 0 0;
  color: var(--text-muted);
  font-size: .78rem;
}

.rows__acts {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-inline-start: auto;
}



/* زرُّ «أريد نشر خبر» في آخر الشريط — هامشٌ تلقائيٌّ على أوّله يدفعه
   إلى طرفه المقابل. و`inline-start` لا `left`: الصفحةُ عربيّةٌ اليوم
   وقد تُقرأ يوماً بغيرها، والمنطقيُّ يتبع اتّجاه الكتابة.
   An auto margin on its start edge pushes it to the bar's far end;
   logical, not left-handed, so it follows the writing direction. */
.news__ask { margin-inline-start: auto; }

/* ---------- مناسبات وحفلات ---------- */

/* المجلّداتُ أعرضُ من بلاطات الوجوه وبنسبةٍ أفقيّة: الغلافُ صورةُ مجلس
   لا وجهٌ واحد. والعنوانُ على الغلاف كأسماء صور الجماعة.
   Folders are wider and landscape: a cover is a gathering, not a face. */
.occasions {
  grid-template-columns: repeat(auto-fill, minmax(clamp(15rem, 88vw, 19rem), 1fr));
}
.occasions__cover {
  aspect-ratio: 4 / 3;
  object-position: 50% 40%;
}
.occasions__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 8px 4px 0;
  color: var(--text-muted);
  font-size: .8rem;
}
.occasions__new { margin: 0 0 12px; font-size: 1.05rem; }

.occasion__draft p { margin: 0 0 10px; }
.occasion__caption {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 4px 0;
}
.occasion__caption .textarea { min-height: 0; }
.occasion__caption .btn { align-self: flex-start; }
.occasion__asked {
  margin: 22px 0 8px;
  text-align: center;
  color: var(--text-muted);
}

/* الصورةُ زرٌّ يكبّرها — بلا حشوٍ ولا خلفيّةٍ ولا حدّ */
.occasion__view {
  display: block;
  inline-size: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}
.occasion__view:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.occasion__box {
  inline-size: 100vw;
  max-inline-size: 100vw;
  block-size: 100dvh;
  max-block-size: 100dvh;
  margin: 0;
  padding: 16px;
  border: 0;
  background: transparent;
  color: #fff;
}
.occasion__box[open] {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.occasion__box::backdrop { background: rgb(0 0 0 / .88); }
.occasion__big {
  max-inline-size: 100%;
  max-block-size: calc(100dvh - 110px);
  object-fit: contain;
  border-radius: var(--r-md);
}
.occasion__big-caption {
  margin: 0;
  max-inline-size: 60ch;
  text-align: center;
  white-space: pre-line;
  line-height: 1.7;
}
.occasion__close,
.occasion__step {
  position: fixed;
  border: 0;
  border-radius: 50%;
  inline-size: 44px;
  block-size: 44px;
  background: rgb(255 255 255 / .16);
  color: #fff;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}
.occasion__close { inset-block-start: 14px; inset-inline-end: 14px; font-size: 1.1rem; }
.occasion__step { inset-block-start: 50%; transform: translateY(-50%); }
/* في صفحةٍ من اليمين إلى اليسار: التاليةُ إلى اليسار */
.occasion__step--next { inset-inline-end: 10px; }
.occasion__step--prev { inset-inline-start: 10px; }

/* مربّعُ الإفلات: حدٌّ متقطّعٌ يُقرأ «هنا تُفلت»، ويضيء ما دام شيءٌ فوقه.
   The drop box: a dashed edge reads "drop here", and lights while hovered. */
.occasion__drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 26px 16px;
  border: 2px dashed var(--border);
  border-radius: var(--r-lg);
  background: var(--surface-sunk);
  text-align: center;
  transition: border-color .15s, background .15s;
}
.occasion__drop p { margin: 0; }
.occasion__drop-say { font-family: var(--font-head); font-weight: 700; font-size: 1.05rem; }
.occasion__drop--over {
  border-color: var(--accent);
  background: color-mix(in oklab, var(--accent) 10%, var(--surface));
}
.occasion__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-block-start: 12px;
}
.occasion__bar [data-upload-status] { flex: 1 1 14rem; }

/* القائمةُ قبل الرفع: مصغّراتٌ تُحذف بضغطة، في صندوقٍ يُمرَّر فلا تدفع
   ثلاثمئةُ صورةٍ الصفحةَ كلَّها. A scrolling tray of thumbnails. */
.occasion__queue {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 8px;
  max-block-size: 52vh;
  overflow-y: auto;
  margin: 12px 0 0;
  padding: 4px;
  list-style: none;
}
.occasion__queued {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface-sunk);
}
.occasion__queued img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}
.occasion__queued--going { opacity: .45; }
.occasion__queued--bad { outline: 2px solid var(--danger); }
.occasion__queued-note {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  padding: 2px 4px;
  background: rgb(0 0 0 / .62);
  color: #fff;
  font-size: .68rem;
  line-height: 1.4;
  text-align: center;
}
.occasion__queued-note:empty { display: none; }
.occasion__queued-x {
  position: absolute;
  inset-block-start: 4px;
  inset-inline-end: 4px;
  inline-size: 26px;
  block-size: 26px;
  border: 0;
  border-radius: 50%;
  background: rgb(0 0 0 / .6);
  color: #fff;
  font-size: .8rem;
  line-height: 1;
  cursor: pointer;
}

/* شريطُ الحذف الجماعيّ: يلزم أعلى الشاشة والمجلّدُ يُمرَّر.
   The bulk bar sticks to the top while the folder scrolls. */
.occasion__bulk {
  position: sticky;
  inset-block-start: 8px;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-block-end: 12px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: color-mix(in oklab, var(--surface) 94%, transparent);
  box-shadow: var(--shadow-md);
  backdrop-filter: blur(6px);
}
.occasion__bulk-say { flex: 1 1 16rem; font-size: .85rem; color: var(--text-muted); }

/* مربّعُ التحديد على زاوية الصورة، والمحدَّدةُ تُطوَّق بلون الخطر */
.album__cell { position: relative; }
.occasion__pick {
  position: absolute;
  z-index: 2;
  inset-block-start: 12px;
  inset-inline-start: 12px;
  display: grid;
  place-items: center;
  inline-size: 34px;
  block-size: 34px;
  border-radius: 8px;
  background: rgb(255 255 255 / .9);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}
.occasion__pick input { inline-size: 20px; block-size: 20px; margin: 0; cursor: pointer; }
.album__cell:has([data-pick]:checked) .album__frame {
  box-shadow: 0 0 0 3px var(--danger), var(--shadow-md);
}

/* بين شبكة العرضيّات وشبكة الطوليّات فسحةُ صفّ */
.occasion__group + .occasion__group { margin-block-start: 22px; }
