/* ============================================================
   Attendly — auth.css : الدخول وإنشاء حساب المؤسسة
   ============================================================ */

.auth{min-height:100vh;min-height:100dvh;display:grid;grid-template-columns:1.05fr .95fr}

/* ---------- الجانب التعريفي ---------- */
.auth-side{
  background:var(--grad-hero);
  color:#e6efff;padding:40px 46px;position:relative;overflow:hidden;
  display:flex;flex-direction:column;
}
.auth-side::before{
  content:"";position:absolute;width:520px;height:520px;border-radius:50%;
  background:radial-gradient(circle,rgba(59,130,246,.32),transparent 68%);
  top:-190px;inset-inline-end:-160px;
}
.auth-side::after{
  content:"";position:absolute;width:380px;height:380px;border-radius:50%;
  background:radial-gradient(circle,rgba(34,211,238,.2),transparent 70%);
  bottom:-150px;inset-inline-start:-110px;
}
.auth-side > *{position:relative;z-index:1}
.auth-side .logo-name{color:#fff}
.auth-side .logo-sub{color:var(--brand-300);opacity:1}

.hero-mini{margin-top:auto;margin-bottom:auto;padding:30px 0}
.hero-mini h2{font-size:34px;font-weight:900;line-height:1.32;letter-spacing:-1px;color:#fff}
.hero-mini h2 em{font-style:normal;
  background:linear-gradient(120deg,var(--cyan-300),var(--brand-300));
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
}
.hero-mini p{margin-top:14px;font-size:15.5px;color:#b9cff0;max-width:420px;line-height:1.85}

.hero-points{display:flex;flex-direction:column;gap:14px;margin-top:28px}
.hero-point{display:flex;align-items:flex-start;gap:13px}
.hero-point .ic{
  width:40px;height:40px;border-radius:12px;flex:none;display:grid;place-items:center;
  background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.16);color:var(--cyan-300);
}
.hero-point b{display:block;font-size:14.5px;color:#fff}
.hero-point span{font-size:13px;color:#9fbbe4}

.auth-stats{display:flex;gap:28px;padding-top:24px;border-top:1px solid rgba(255,255,255,.14);flex-wrap:wrap}
.auth-stats div b{display:block;font-size:23px;font-weight:900;color:#fff;letter-spacing:-.5px}
.auth-stats div span{font-size:12px;color:#8fb0dd}

/* ---------- الجانب النموذجي ---------- */
.auth-main{
  /* ⚠ position:relative ضرورية: .auth-top تحت عندها position:absolute،
     وبلا مرجع موضَّع كتتحسب من الشاشة نفسها عوض من هاد العمود.

     النتيجة اللي كانت: فوضع العرض، شريط «البيانات محلية» كياخد
     أول 27px، و.auth-top كتبقى على top:16 من **الشاشة** — يعني
     الأزرار كتدخل تحت الشريط.
     قسناها فـdev/probe-overlap.html: تداخل 215×11px. */
  position:relative;
  display:flex;align-items:center;justify-content:center;padding:38px 26px;
  background:var(--bg);overflow-y:auto;
}
.auth-card{width:100%;max-width:452px}
.auth-card h1{font-size:27px;margin-bottom:6px}
.auth-card .lead{color:var(--text-mute);font-size:14.5px;margin-bottom:24px}

.auth-top{
  position:absolute;top:16px;inset-inline-end:18px;z-index:20;
  display:flex;align-items:center;gap:9px;
}

/* minmax(0,1fr) وماشي 1fr: مع 1fr الخانة ما كتقدرش تصغر أقل من عرض
   أطول كلمة داخلها. بالعربية «الحارس العام» قصيرة فما بان والو، ولكن
   بالفرنسية «Surveillant général» كانت كتوسّع الشبكة وكتفيض برّا الشاشة. */
.role-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px;margin-bottom:22px}
.role-opt{
  border:1.5px solid var(--line);border-radius:var(--r);padding:12px 8px;text-align:center;
  cursor:pointer;transition:var(--transition);background:var(--surface);
}
.role-opt:hover{border-color:var(--brand-300);transform:translateY(-2px)}
.role-opt .ic{
  width:34px;height:34px;margin:0 auto 7px;border-radius:11px;display:grid;place-items:center;
  background:var(--bg-soft);color:var(--text-soft);transition:var(--transition);
}
.role-opt b{
  font-size:12.5px;font-weight:700;display:block;color:var(--text-soft);line-height:1.35;
  overflow-wrap:break-word;hyphens:auto;
}
.role-opt.on{border-color:var(--brand-500);background:var(--brand-50);box-shadow:0 0 0 3px var(--ring)}
.role-opt.on .ic{background:var(--grad-brand);color:#fff}
.role-opt.on b{color:var(--brand-700)}
[data-theme="dark"] .role-opt.on b{color:var(--brand-300)}

/* ============================================================
   ⚠⚠ `right` فيزيائية، لا `inset-inline-end` — وهذا ليس تراجعاً
      عن الخصائص المنطقية، بل تصحيحٌ لتعارضٍ بينها.

   حقل كلمة السرّ عليه `dir="ltr"` صراحةً (وهو صواب: الحروف
   تُكتب من اليسار، ويهمّ ذلك عند إظهارها). أمّا الزرّ فأخٌ له
   داخل `.pw-wrap`، ويرث اتّجاه **الصفحة** — وهي `rtl` بالعربية.

   فكانت الخاصيّتان المنطقيّتان تُحلّان إلى جهتين متقابلتين:

       الحقل  → `padding-inline-end` = padding-right  (لأنّه ltr)
       الزرّ   → `inset-inline-end`   = left           (لأنّه rtl)

   أي أنّ الفراغ محجوز على اليمين والزرّ موضوع على اليسار —
   فوق أوّل حرف من كلمة السرّ بالضبط. وهذا ما يظهر في الشاشة:
   العين والنقاط فوق بعضهما.

   ⚠ والعطب في العربية وحدها. الفرنسية والإنجليزية سليمتان،
     لأنّ اتّجاه الصفحة يوافق اتّجاه الحقل — ولهذا مرّ من كلّ
     الفحوص: كلّها كانت تعمل بالإنجليزية.

   ⚠ والحلّ الفيزيائي صحيح في الاتّجاهين معاً، لأنّ الحقل
     `ltr` دائماً: نهاية النصّ على اليمين مهما كانت لغة الصفحة،
     فمكان العين هو اليمين دائماً.
   ============================================================ */
.pw-wrap{position:relative}
.pw-wrap .input{padding-right:44px;padding-left:14px}
.pw-toggle{
  position:absolute;right:6px;left:auto;top:50%;transform:translateY(-50%);
  width:34px;height:34px;border:none;background:transparent;cursor:pointer;
  color:var(--text-mute);display:grid;place-items:center;border-radius:9px;
}
.pw-toggle:hover{background:var(--bg-soft);color:var(--text)}
/* زر إظهار كلمة السر كيتنقر فكل دخول — 34px صغيرة بزاف على الإبهام */
@media (pointer:coarse){ .pw-toggle{width:44px;height:44px} }

.auth-err{
  background:var(--rose-100);color:var(--rose-700);padding:11px 15px;border-radius:var(--r);
  font-size:13.5px;font-weight:700;margin-bottom:14px;display:flex;align-items:center;gap:9px;
}

/* مدخل الوضع التجريبي — يظهر خارج الوضع التجريبي وحده.
   ⚠ `btn-ghost` لا `btn-primary`: زرّ الدخول فوقه هو الفعل
     الأساسي في هذه الصفحة، ومنافسته بزرّ ممتلئ يجعل مستخدماً
     حقيقياً ينقر «تجربة» ويجد نفسه في معطيات وهمية. */
.demo-enter{margin-top:20px;display:grid;gap:8px}
/* ⚠⚠ لازمة، وليست احتياطاً: قاعدة المتصفّح `[hidden]{display:none}`
   منتقٍ سماتٍ بوزن (0,1,0)، و`.demo-enter` صنفٌ بنفس الوزن يأتي
   بعدها في الترتيب — فيغلبها. أي أنّ `display:grid` وحده **يُبطل
   السمة `hidden`**.

   وأثرها كان مرئياً للمستخدم: داخل الوضع التجريبي يضع الكود
   `enter.hidden = true` ولا يضع نصّاً، فيبقى الزرّ ظاهراً
   **فارغاً** — حبّة بيضاء بلا كلمة أسفل صفحة الدخول.

   ⚠ وكل قاعدة تضع `display` على عنصر قد يحمل `hidden` تحتاج
     هذا السطر. `display:none` في السمة ليس تلقائياً متى لمستَ
     `display` بصنف. */
.demo-enter[hidden]{display:none}
.demo-enter .tiny{text-align:center;line-height:1.6;margin:0}

.demo-box{
  margin-top:22px;border:1px dashed var(--line-strong);border-radius:var(--r);
  padding:14px 16px;background:var(--surface-2);
}
.demo-box .row-between{cursor:pointer}
.demo-box h4{font-size:13.5px;color:var(--text-soft)}
/* ⚠ اللائحة ولّات مشتقّة من البيانات: 9 أساتذة، تلميذ لكل قسم…
   بلا سقف كتطوّل الصفحة وكيتخبّى زر الدخول تحت. */
.demo-list{display:grid;gap:7px;margin-top:12px;max-height:280px;overflow-y:auto;
  overscroll-behavior:contain;padding-inline-end:4px}
.demo-row{
  display:flex;align-items:center;gap:10px;padding:8px 11px;border-radius:11px;
  background:var(--surface);border:1px solid var(--line);cursor:pointer;transition:var(--transition);
}
.demo-row:hover{border-color:var(--brand-400);box-shadow:var(--shadow-sm)}
.demo-row .meta{flex:1;min-width:0}
.demo-row b{display:block;font-size:13px}
.demo-row code{font-size:11.5px;color:var(--text-mute);font-family:"Courier New",monospace;direction:ltr}

.auth-foot{margin-top:22px;text-align:center;font-size:12.5px;color:var(--text-mute)}
.auth-switch{
  margin-top:18px;text-align:center;font-size:14px;color:var(--text-soft);
  padding-top:18px;border-top:1px solid var(--line);
}
.auth-switch a{font-weight:800}

/* ---------- خطوات التسجيل ---------- */
.stepper{display:flex;align-items:center;gap:8px;margin-bottom:26px}
.stepper .st{display:flex;align-items:center;gap:9px;flex:1}
.stepper .bub{
  width:32px;height:32px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:var(--bg-soft);color:var(--text-mute);font-weight:900;font-size:13px;
  transition:var(--transition);border:2px solid transparent;
}
.stepper .st.on .bub{background:var(--grad-brand);color:#fff;box-shadow:var(--shadow-brand)}
.stepper .st.done .bub{background:var(--green-600);color:#fff}
.stepper .lb{font-size:12.5px;font-weight:700;color:var(--text-mute);white-space:nowrap}
.stepper .st.on .lb{color:var(--brand-700)}
[data-theme="dark"] .stepper .st.on .lb{color:var(--brand-300)}
.stepper .line{height:2px;background:var(--line);flex:1;min-width:12px;border-radius:2px}
.stepper .st.done + .line{background:var(--green-500)}

.sum-row{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:11px 14px;border-radius:var(--r);background:var(--surface-2);
  border:1px solid var(--line);margin-bottom:8px;font-size:14px;
}
.sum-row .k{color:var(--text-mute);font-size:13px;font-weight:700}
.sum-row .v{font-weight:800;text-align:end;word-break:break-word}

.check-row{
  display:flex;align-items:flex-start;gap:10px;font-size:13.5px;color:var(--text-soft);
  line-height:1.7;cursor:pointer;margin-bottom:18px;
}
.check-row input{margin-top:3px;flex:none}

.done-hero{text-align:center;padding:14px 0 4px}
.done-hero .ic{
  width:74px;height:74px;border-radius:50%;margin:0 auto 16px;display:grid;place-items:center;
  background:var(--green-100);color:var(--green-600);
}
.done-hero h2{font-size:24px;margin-bottom:8px}

@media(max-width:940px){
  .auth{grid-template-columns:1fr}
  .auth-side{padding:24px 22px;min-height:auto}
  .hero-mini{padding:18px 0}
  .hero-mini h2{font-size:25px}
  .hero-mini p{font-size:14.5px}
  .hero-points,.auth-stats{display:none}

  /* .auth-main هي flex أفقية. منين كان .auth-top كيولّي position:static
     كان كيتحوّل لعنصر flex بجنب البطاقة عوض فوقها — والبطاقة عندها
     width:100% — فالمجموع كيفوت عرض الشاشة وكلشي كيتقطع من الجنب.
     الحل: نقلب الاتجاه لعمودي على الشاشات الصغيرة. */
  .auth-main{
    flex-direction:column;align-items:stretch;justify-content:flex-start;
    padding:20px 16px;
  }
  .auth-top{position:static;justify-content:flex-end;margin-bottom:12px}
  .auth-card{margin-inline:auto}
}

/* هواتف ضيّقة: خانتان للبوابات، والخطوات بالأرقام فقط */
@media(max-width:400px){
  .auth-main{padding:16px 12px}
  .role-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .auth-card h1{font-size:23px}
}

/* «Établissement · Compte directeur · Confirmation» مع white-space:nowrap
   كانت كتفيض هي الأخرى فصفحة التسجيل. على الصغير: الأرقام كافية. */
@media(max-width:560px){
  .stepper .lb{display:none}
  .stepper .st{flex:none}
  .stepper .line{min-width:8px}
}

/* نفس علة `.shell`: ارتفاع الشاشة كامل + حشو الشريط = تمرير زائد */
html.has-demo .auth{
  min-height:calc(100vh - var(--demo-h,0px));
  min-height:calc(100dvh - var(--demo-h,0px));
}

/* ============================================================
   وضع التطبيق — صفحة الدخول

   ⚠ ما تصلحه: التطبيق المثبَّت كان يفتح على صفحة بيع. عمود
     تعريفي بعنوان تسويقي وأرقام و«ليس لديك حساب؟ أنشئ مؤسسة»
     و«جرّب النموذج» — كلّه صحيح في المتصفّح لزائر وصل من رابط،
     وكلّه خطأ لأستاذ فتح أيقونة على شاشته للمرّة المئة هذا
     الشهر. هو لن ينشئ مؤسسة، ولا يحتاج أن يُقنَع.

     شاشة دخول التطبيق: شعار، حقلان، زرّ. لا أكثر.

   ⚠ الصنف تضعه theme.js في <head> قبل الرسم — لا في آخر
     الصفحة: التخطيط يجب ألّا يُرسم مرّة ثمّ يقفز.

   ⚠ لسان المتصفّح لا يتأثّر بشيء ممّا هنا.
   ============================================================ */
html.app-mode .auth{grid-template-columns:1fr}
html.app-mode .auth-side{display:none}

/* الترويسة والذيل التسويقيان: لا مكان لهما في تطبيق مثبَّت */
html.app-mode .auth-switch,
html.app-mode .auth-foot .foot-text{display:none}

/* ⚠ الشعار رابطٌ إلى `index.html`، وتلك الصفحة صارت تنسحب إلى
   `app.html` داخل التطبيق المثبَّت (انظر رأس index.html). فالنقر
   عليه هناك رحلةُ ذهاب وإياب تنتهي حيث بدأت — وميضٌ بلا سبب.

   ⚠ بالتنسيق لا بالجافاسكربت: الصنف `app-mode` يضعه theme.js على
     `<html>` قبل وجود `<body>`، فيسري هذا من **أوّل رسم**. أمّا
     نزع `href` داخل `render()` فيتأخّر إلى أوّل دورة رسم، ولا
     يعمل إن لم تُستدعَ تلك الدورة أصلاً. */
html.app-mode .auth-side .logo{pointer-events:none;cursor:default}

/* ⚠ ويبقى رقم البناء وحده. كان الذيل كلّه يُخفى، والرقم فيه —
   أي أنّه يغيب عن **التطبيق المثبَّت** وهو المكان الذي وُضع
   من أجله: هناك لا شريط عنوان ولا Ctrl+Shift+R، فالسؤال «أيّ
   نسخة أشغّل؟» لا جواب له سواه. */
html.app-mode .auth-foot{margin-top:16px}

/* ⚠⚠ `.demo-box` كان في اللائحة أعلاه — أي أنّ لائحة الحسابات
   التجريبية كانت تُخفى في التطبيق المثبَّت.

   والتصنيف خاطئ: هي ليست «تسويقاً» بل **الباب الوحيد** في
   الوضع التجريبي. والتطبيق المثبَّت هو المكان الذي تشتدّ فيه
   الحاجة إليها: `start_url` يفتح على `app.html`، ولا يمرّ
   بصفحة الهبوط، فلا طريق آخر إطلاقاً.

   وأثرها كان: زرّ «تجربة التطبيق» يقود إلى `?demo=1`، ثمّ
   لا شيء — لائحة موجودة في الـDOM وغير مرئية. طريق مسدود
   بعد خطوة واحدة.

   ⚠ ولا خطر على مؤسسة حقيقية: `renderDemo()` تضع
     `style.display='none'` سطريّاً خارج الوضع التجريبي،
     والسطريّ يغلب الصنف. فالمؤسسة المؤدية لا ترى شيئاً. */

html.app-mode .auth-main{
  padding:26px 22px;
  /* الحقول تُلمس بالإبهام في الأسفل، والشعار في الأعلى:
     توسيط رأسيّ على شاشة طويلة يترك الحقول في المنتصف بعيدة
     عن الإبهام وعن الأعلى معاً. */
  align-items:flex-start;
  padding-top:calc(30px + env(safe-area-inset-top));
  padding-bottom:calc(26px + env(safe-area-inset-bottom));
}
html.app-mode .auth-card{max-width:420px;margin:0 auto}

/* شعار التطبيق فوق النموذج — يحلّ محلّ العمود المحذوف.
   يُحقن من auth.js، ويبقى مخفيّاً في المتصفّح. */
.app-brand{display:none}
html.app-mode .app-brand{
  display:flex;flex-direction:column;align-items:center;gap:10px;
  margin-bottom:26px;text-align:center;
}
html.app-mode .app-brand .logo-mark{
  width:66px;height:66px;border-radius:20px;
  background:var(--grad-brand);color:#fff;
  display:grid;place-items:center;box-shadow:var(--shadow-brand);
}
html.app-mode .app-brand .logo-mark svg{width:34px;height:34px}
html.app-mode .app-brand b{font-size:23px;font-weight:900;letter-spacing:-.6px}
html.app-mode .app-brand span{font-size:13px;color:var(--text-mute)}

/* العنوان الطويل («ادخل إلى فضاء مؤسستك») يزاحم الشعار فوقه */
html.app-mode .auth-card h1{font-size:21px;text-align:center}
html.app-mode .auth-card .lead{text-align:center;margin-bottom:20px}

/* مبدّل اللغة يبقى: أوّل ما قد يحتاجه ولي أمر لا يقرأ العربية.
   والمظهر يتبع النظام هنا — لا داعي لزرّ في شاشة دخول. */
html.app-mode .auth-top{top:calc(12px + env(safe-area-inset-top))}

/* ============================================================
   وضع التطبيق — ضبط الارتفاع واصطفاف الأدوار

   ⚠ مشكلتان ظهرتا في التجربة على نافذة التطبيق (~665px ارتفاعاً):

   1. الأدوار خمسة في شبكة من ثلاثة أعمدة، فالصفّ الثاني فيه
      اثنان ملتصقان بحافة البداية ومكانان فارغان بعدهما. يبدو
      كأنّ شيئاً نقص أو انكسر.
      grid لا يوسّط صفّاً ناقصاً؛ flex يفعل.

   2. زرّ الدخول كان **تحت حافّة الشاشة**. شاشة دخول لا يُرى
      فيها زرّ الدخول هي أسوأ ما يمكن أن يبدأ به تطبيق —
      والمستخدم لا يعرف أنّ عليه التمرير لأنّ الشاشة تبدو
      مكتملة.

      لم نحذف شيئاً: قلّصنا الشعار والفراغات وحشو بطاقات
      الأدوار. المجموع ~75px، وهو ما يكفي لدخول الزرّ في
      الشاشة على أصغر نافذة.

   ⚠ التمرير يبقى ممكناً (`.auth-main` عندها overflow-y:auto):
     هذا ضبطٌ للحالة الشائعة، لا رهان على ارتفاع بعينه.
   ============================================================ */

/* 1 · اصطفاف الأدوار */
html.app-mode .role-grid{
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:8px;margin-bottom:15px;
}
html.app-mode .role-opt{
  /* الأساس ثلث الصفّ، والحدّان يمنعان بطاقة تمتدّ وحدها في
     صفّها الأخير أو تنكمش تحت عرض كلمة «Surveillant». */
  flex:1 1 calc(33.333% - 6px);
  min-width:97px;max-width:158px;
  padding:9px 6px;
}
html.app-mode .role-opt .ic{width:30px;height:30px;margin-bottom:5px}
html.app-mode .role-opt b{font-size:12px}

/* 2 · استرجاع الارتفاع */
html.app-mode .app-brand{gap:7px;margin-bottom:16px}
html.app-mode .app-brand .logo-mark{width:52px;height:52px;border-radius:16px}
html.app-mode .app-brand .logo-mark svg{width:27px;height:27px}
html.app-mode .app-brand b{font-size:20px}
html.app-mode .app-brand span{font-size:12.5px}

html.app-mode .auth-card h1{font-size:19px;margin-bottom:3px}
html.app-mode .auth-card .lead{font-size:13px;margin-bottom:15px}
html.app-mode .field{margin-bottom:10px}

/* ============================================================
   التفعيل برمز مطبوع
   ============================================================ */
.auth-activate{
  margin-top:16px;padding-top:15px;border-top:1px solid var(--line);
  text-align:center;font-size:13.5px;color:var(--text-mute);
}
.auth-activate a{font-weight:700}
/* في التطبيق المثبَّت يبقى هذا الرابط (بخلاف «أنشئ مؤسسة»):
   هو الطريق الوحيد لتلميذ يفتح التطبيق أوّل مرّة. */
html.app-mode .auth-activate{margin-top:14px;padding-top:13px}

/* ============================================================
   مقياس قوّة كلمة السرّ

   ⚠ مساعدة بصرية لا حارس: الحارس في الخادم (app.password_ok).
     مقياس في JS يُتخطّى بنداء مباشر على الـRPC، ولذلك لا يُعتمد
     عليه — لكنّه يمنع الحالة الشائعة: مستخدم يكتب «12345678»
     ويكتشف الرفض بعد أن يملأ النموذج كلّه.
   ============================================================ */
.pw-meter{display:flex;gap:4px;margin-top:7px}
.pw-meter i{
  flex:1;height:4px;border-radius:99px;background:var(--line);
  transition:background var(--transition);
}
.pw-meter.s1 i:nth-child(1){background:var(--rose-500)}
.pw-meter.s2 i:nth-child(-n+2){background:var(--gold-500)}
.pw-meter.s3 i:nth-child(-n+3){background:var(--brand-500)}
.pw-meter.s4 i{background:var(--green-500)}

/* رقم البناء في ذيل صفحة الدخول — يفصل «لم أرفع» عن «رُفع
   وعامل الخدمة يخدم القديم» في نظرة واحدة. */
.build-tag{
  font-family:ui-monospace,Consolas,monospace;font-size:11.5px;
  margin-inline-start:8px;
  padding:1px 6px;border-radius:6px;background:var(--surface-2);
  border:1px solid var(--line);color:var(--text-soft);
}

/* تلميح تحت الحقل — يتبع الدور المختار (auth.js: paintIdentField) */
.field-hint{
  font-size:12px;color:var(--text-mute);line-height:1.6;margin-top:-2px;
}
.field-hint[hidden]{display:none}

/* ⚠⚠ الأدوار خمسة، والشبكة لا تملأ صفّاً ناقصاً مهما فعلت:
   ثلاثة أعمدة تعطي 3+2 وتترك خانةً فارغة، وجرّبتُ
   `auto-fit/minmax` فأعطى أربعة أعمدة و**زاد الأمر سوءاً**:
   4+1، دورٌ وحيد في آخر الصفّ.

   العلّة أنّ عناصر الشبكة لا تتمدّد لتملأ صفّاً ناقصاً — أمّا
   عناصر flex فتفعل. فبـ`flex:1 1 33%` يأخذ الصفّ الأوّل ثلاثة،
   ويتمدّد الاثنان الباقيان إلى النصف لكلٍّ منهما. لا فجوة في
   أيّ عرض، ولا حاجة إلى استثناء لكلّ مقاس.

   ⚠ ولا تُحوَّل إلى `grid` مرّة أخرى عند إضافة دور سادس: ستّة
     تبدو سليمة في ثلاثة أعمدة، ثمّ يعود العطب مع السابع. */
.role-grid{display:flex;flex-wrap:wrap}
.role-grid > *{flex:1 1 calc(33.333% - 6px);min-width:96px}
