/* The lobby's stylesheet (index.html), after the shared styles/majlis-v16.css,
   the inserted account sheet, the design's tokens (design/tak/tokens.css) and
   styles/fonts-tak.css. It is the five sheets the page used to load after those,
   in their cascade order, each under its own part heading: the imported design
   (design/tak/components.css, styles/tak.css),
   the Saikal layer (styles/saikal.css), the port's corrections (styles/port.css,
   whose numbered sections keep their numbers here) and the quick-match sheet
   (styles/quick-v2.css). Merged 2026-11-02 with no change on screen: rules that
   need a class or id nothing on this page can produce, and declarations a later
   declaration under the identical selector always overrides, were left out
   (app/client/README.md, "One stylesheet per page"). Edit this file in place. */

/* ==========================================================================
   Part 1: formerly design/tak/components.css
   ========================================================================== */

/* ============================================================
   قالب تَك · components.css — الطبقة المبنيّة (الطاولة، ليلًا)
   Reads AFTER tokens.css on <div dir="rtl" lang="ar" class="tak">.

   THE ONE RULE UNDER EVERY CLASS BELOW:
     GAME UI IS LIT. APP UI IS PRINTED.
   So every pressable body wears FOUR light facts, never three:
     ١ نور داخلي فوق   ٢ ظل داخلي تحت
     ٣ ظل تماس ضيّق    ٤ ظل محيط واسع
   and its border is a GRADIENT (padding-box fill + border-box
   gradient) — never a flat colour. A flat fill plus a hairline
   plus a faint inset, all on one plane, is precisely what reads
   as 2012. That was «basic»: an elevation failure, not a taste
   failure.

   ---- الحزّة: القانون شرطٌ لا عدد ----
   كان هنا مكتوبًا «بيوته الآن **أربعة** … فالتوقيع يتكرّر **سبع**
   مرّات» وبدرجتين «٥٨ و٣٦»، وMOLD تقول «**ثلاثة** مواضع»، وKIT
   تقول «**ستّ**»، والدفتر ما هو في ولا عدّة منها ودرجته ٣٢ لا ٣٦.
   عددٌ في ترويسة هو رقمٌ يعيش في أربعة ملفات، ويبات مؤرّشفًا مع
   أول commit. فالعدد انحذف من هنا ومن MOLD، والقائمة تُقرا من
   الملف نفسه:
     grep -nE '^\s*--nt:[0-9]|clip-path:(path|polygon)\([^)]' design/tak/components.css
   (والـpolygon شرط: أول صياغة لهذا الـgrep كانت ‎--nt:‎ و‎path(‎
    وحدهما، فتسقط منها ظهر الورقة — وهي أكثر بيت يتكرّر على
    الشاشة. وقاعدةٌ تُعِدّ ناقصًا أخطر من عددٍ مضبوط باليد،
    لأنها تُقرا موثوقة. و‎[^)]‎ يستبعد ذكر الاسمين في الشروح.)
   والشرط الباقي شرطان لا يزيغان:
     ١ · الدرجة تُقرا «مقصوصة» أو ما تنحزّ. على سطحٍ درجته بمقاس
         نصف قطره تُقرا خدشًا أو عطبَ رسم. مرفوضة بالقياس على ورقة
         الكرسي (٢١px) مرّتين — §٨٫٥.
     ٢ · القصّ والقناع يمحوان ظلّ العنصر الخارجي **و‎outline‎ه**
         (الرسم: filter ثم clip-path ثم mask). فالجسم المحزوز اللي
         ينضغط ما يملك ظلّه: الشكل على الجسم، والتماس والمحيط
         والوهج وحلقة التركيز على غلافه. والغائر ينجو من القناع
         فيبقى مكانه. مقيسة في §٨ وفي ‎_probe/clipshadow.html‎.

   ONE bloom per screen · ONE idle loop per screen · ONE accent.
   One sun, upper-right, FIXED: every offset is physical px and
   every gradient angle is in deg. NOTHING mirrors under RTL —
   only spacing uses logical properties.
   Never letter-spacing on Arabic. line-height >= 1.35 on every
   control. overflow:hidden is banned on any Arabic container.

   Image slots bound by the app shell:
     --im-weave   نسيج الطاولة (weave-najdi.jpg) — والقاعدة اللي تستعملها
                  تعيش في غلاف المنتج جنب الإعلان، لا هنا: الـurl()
                  جوّا خاصيّة مخصّصة ينحلّ نسبةً لملف الاستعمال.
   ============================================================ */
.tak,.tak *,.tak *::before,.tak *::after{box-sizing:border-box}
/* منع تزييف الأوزان يعيش في tokens.css مع بقيّة قرارات الكسوة —
   بيت واحد لا بيتين. */

/* ============================================================
   ٠ · الأرض — ثلاث طبقات ثابتة. ما يحطّ أحد شيئًا على z 0–2.
   الخامة تعطي الإضاءة، واللوح يعطي الصبغة: مزج luminosity
   يصحّح زيتون الخامة (H104) إلى أخضرنا (H154). لا تستعملها خام.
   ولا طبقة حبيبات: تباين إضاءة النسيج نفسه يكسر التشريط،
   والحبيبات إشارة تعتيق — ممنوعة.
   ============================================================ */
/* ═══ وليش ما فيه ‎background-image‎ هنا · ٢٠٢٦-٠٧-٢٩ · الجولة ١ ═══
   كان هذا السطر ‎background-image:var(--im-weave), …‎ — أي إن القالب
   يستهلك فتحة خامة. وقانون القالب نفسه (‎MOLD.md‎ §الفتحات) يمنعها
   بالحرف، والسطر كان يخالفه من أول يوم: الـ‎url()‎ جوّا خاصيّة
   مخصّصة ينحلّ عند الملف **المستعمِل**، فإعلان الكسوة
   ‎url("../design/assets/weave-najdi-v3.jpg")‎ ينحلّ من ‎design/tak/‎ إلى
   ‎design/assets/…‎ = ٤٠٤. وما بان العطب لأن كل مستهلك حقيقي
   (‎styles/tak.css‎ · ‎parts.html‎ · ‎starter.html‎ · ‎_probe/ground.html‎)
   يعيد كتابة ‎background-image‎ بعده فيغلبه بالتتالي — طبقةٌ كاذبة
   تحت طبقةٍ صادقة. انمسكت بـ‎node _probe/a-url.mjs‎، لا بالعين.
   والقالب الآن يملك كل شي **إلا** الصورة: اللون والمقاس والتكرار
   والمزج. والرابط يجي من البيت اللي يعرف وين الملفّات.
   ولو ما انربطت الفتحة، الأرض تطلع ‎--s-table‎ سادًّا — نقصٌ يُشاف،
   مو ٤٠٤ ما يقول شي. */
.tk-ground{position:fixed;inset:0;z-index:0;pointer-events:none;
  background-color:var(--s-table);
  background-size:var(--weave-tile) var(--weave-tile), cover;
  background-repeat:repeat,no-repeat;
  background-blend-mode:luminosity,normal}
.tk-lamp{position:fixed;inset:0;z-index:1;pointer-events:none;
  mix-blend-mode:screen;background-image:var(--lamp)}
.tk-fall{position:fixed;inset:0;z-index:2;pointer-events:none;
  background-image:var(--falloff)}

/* ============================================================
   ١ · الضغطة — تُلبَس مع أي جسم يُضغط
   الجسم يغطس صوب ظله: المحيط ينشال ويجي بداله داخلي.
   نزول ٨٠ms ease-in، ورجعة ٣٠٠ms بنبضة. اللاتماثل هو الحيلة.
   ============================================================ */
.tkpress{
  transition:
    transform  var(--t-up)   var(--spring),
    box-shadow var(--t-up)   var(--spring),
    background-image var(--t-tint) linear,
    color            var(--t-tint) linear}
.tkpress:active,.tkpress.is-active{
  transform:scale(.96) translateY(2px);
  transition:
    transform  var(--t-down) var(--ease-in),
    box-shadow var(--t-down) var(--ease-in)}

/* ============================================================
   ٢ · الزر الثاني — الأساس. أثاث مقصوص من الطاولة نفسها.
   ============================================================ */
/* ٨٠٠ للأدوات — زين لها وجه ٨٠٠ حقيقي */
.tkb{
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:.5em;
  min-height:50px;padding-block:9px;padding-inline:22px;
  border:1px solid transparent;border-radius:var(--r-btn);
  background-color:transparent;
  background-image:var(--lamp-catch),var(--face-rise),var(--edge);
  background-origin:border-box;background-clip:padding-box,padding-box,border-box;
  box-shadow:var(--rim),var(--sh2);
  color:var(--tx);
  font-family:var(--fu);font-weight:var(--w-control);font-size:1.0625rem;line-height:1.45;
  text-align:center;cursor:pointer;appearance:none;-webkit-appearance:none;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation}
/* فوقه اليد = يطلع درجة. الأثاث ما يتحرّك — الضغطة وحدها تتحرّك */
/* ═══ التحويم خلف ‎@media (hover:hover)‎ ═══════════════════════
   ٢٠٢٦-٠٧-٣١ · الدورة ٣ · الجولة ٢. كانت وجوه التحويم تُشحن بلا
   حارس، وعلى اللمس هذا **عطبٌ مقيس لا ذوق**: المتصفّح يورّث
   ‎:hover‎ لآخر عنصرٍ انلمس ويخلّيه عليه لين تنلمس نقطةٌ ثانية —
   فاللاعب يضغط «أنت والخوي»، والصفحة تنتقل، ويرجع فيلقى الزرّ
   لابسًا وجه التحويم بوهجه الأوسع. حالةٌ ما لها مدخلٌ ولا مخرج
   على جهازٍ ما فيه مؤشّر.
   و‎.is-hover‎ داخل الحارس معها بقصد: هي صنف **لوح الأجزاء**،
   وظيفتها تفرّج وجه التحويم — ووجهٌ ما يوجد على اللمس ما يُفرَّج
   على اللمس. ولا سطر انتكرّر: الإعلانات مكانها، والحارس حولها،
   فما فيه قيمةٌ عاشت في مكانين. */
@media (hover:hover){
.tkb:hover,.tkb.is-hover{background-image:var(--lamp-catch),var(--face-lift),var(--edge);
  box-shadow:var(--rim),var(--sh3)}
}

.tkb:focus-visible,.tkb.is-focus{outline:var(--ring);outline-offset:var(--ring-gap)}
.tkb:focus:not(:focus-visible){outline:none}
/* ---- سلّم الضغطة، ممسوحًا كامله (٢٠٢٦-٠٧-٢٨ · الجولة ٥) ----
   الشرط: الساكن والمضغوط ما يشحنان نفس المحيط، وإلا فالضغطة
   «اختفاء» لا «غطس». المسح:
     .tkb    sh2 (٤ طبقات) → sh1 (٢)         ينزل درجتين ✓
     .tkb-1  sh3 + وهج     → sh1 + وهج غاطس   ينزل درجتين ✓
     .tkb-q  sh1           → sh1              ما ينزل ✗  → sh0
     .tkchip sh1           → sh1              ما ينزل ✗  → sh0
   والموقوف يشحن sh1 كذلك، وهو ليس حالة ضغط: transform:none. */
.tkb:active,.tkb.is-active{box-shadow:var(--sink),var(--sh1)}
/* الموقوف = مُطفأ، مو معتّم. يبطّل يكون جسمًا عليه ضوء */
/* عطب مقيس ومصلَّح (٢٠٢٦-٠٧-٢٨ · الجولة ٣): هذي القاعدة تعلن
   طبقتَي خلفية بينما .tkb فوقها تعلن قصًّا بثلاث قيم. القائمة
   تنقصّ لأول طبقتين (padding-box,padding-box)، فـ--edge-quiet
   ينرسم *تحت* تعبئة سادّة وما يظهر أبدًا، والحلقة الشفّافة تورّي
   اللوح من ورا. أي قاعدة تعيد إعلان background-image بعدد طبقات
   مختلف عن أصلها لازم تعيد إعلان background-clip معها. */
.tkb:disabled,.tkb[aria-disabled="true"]{
  background-image:linear-gradient(196deg,var(--s-panel-lo),var(--s-panel-lo)),var(--edge-quiet);
  background-clip:padding-box,border-box;
  box-shadow:inset 0 1px 0 rgba(var(--lit-rgb),.05),var(--sh1);
  color:var(--tx4);cursor:not-allowed;transform:none}

/* على وجه النحاس الحبر غامق — الفاتح عليه يختفي.
   وكان هنا «٥٫٥٢:١ مقيسة على المركّب». الرقم انشال ٢٠٢٦-٠٧-٢٩:
   السطر السند انحذف من الردهة بحكم صاحب البيت، فما بقي على
   الشاشة جسمٌ يشحن ‎.tkb-1 .sub‎ — والقاعدة باقية للقالب لا
   للردهة. رقمٌ ما له جسمٌ يُقاس عليه اليوم ليس رقمًا يُنشر.
   والقانون اللي فوقه (الغامق على النحاس) قانونٌ، ما هو قياسًا. */
.tkb-1 .sub{color:var(--ink2)}

/* ---- الثانوي المنكمش — يقعد على كلمته، ما يملأ اللوح.
        هذا هو اللي يعطي التفاوت الهندسي: زرّان بعرض كامل ما
        يقدران يختلفان إلا بالارتفاع، فالفرق يبقى في الارتفاع وحده.

        ---- ولا رقم هنا، وهذي **الثالثة** اللي ينشال فيها ----
        ٢٠٢٦-٠٧-٢٩ · الدورة ٣ · الجولة ١.
        كان مكتوبًا هنا ‎#duoButton‎ ٣٠٦×٥٦ و‎#soloButton‎ ١٢٣٫٥٦×٥٠،
        ومنها «الأساسي ٢٫٧٧× مساحةً و١٫١٢× ارتفاعًا» — مقيسةً بيدٍ
        أمينة يوم قيست. وقبلها كان منشورًا ٤٫٤٢× و١٫٦٥×، وانشالا
        لمّا انحذف السطر السند وانكمش الأساسي. ثم **رجع الأساسي
        بطوله** بحكم صاحب البيت («الكبير كان أحسن»)، فصار
        ‎.panel .tkb-1{min-block-size:clamp(56px,56px+12*--g,88px)}‎
        — وسقط الصندوق والنسبة معًا، وبقي النصّ.

        فالدرس مو «انتبه»: النسبة **مشتقّة من صندوقين يتحرّكان**،
        وكل مرّة تُكتب تنتظر حكمًا واحدًا من صاحب البيت يكذّبها.
        و٢٫٧٧ كانت **تحت قانون الـ٣×** نفسه المكتوب في §٣ تحت —
        أي إن هذا التعليق كان ينشر مخالفةً بوصفها وصفًا.

        الرقم يُقرا من الرِّج، ما ينكتب هنا:
          node _probe/a-squint.mjs            (كتلةً ومساحةً، بالحجب)
          _probe/a-rects.html?w=390&h=844     (STABLE=true، ثم الصندوقان)
        والقانون نفسه في ‎MOLD.md‎ قانون ٢، ومنقولٌ عنه في §٣ تحت. ---- */
.tkb-2{display:flex;width:fit-content;margin-inline:auto}   /* flex لا inline-flex، وإلا ما نفع التوسيط */

/* ============================================================
   ٣ · الزر الأساسي — النحاس. وحده يحمل الوهج واللمعة.

   ---- قانون الوزن — يُنقل عنه، ما ينكتب هنا ----
   ٢٠٢٦-٠٧-٢٩.
   نصّه الوحيد في ‎design/tak/MOLD.md‎ قانون ٢: الفعل الأساسي يفوق
   **أكبر أداة أخرى على شاشته** ٣–٥ أضعاف مساحةً، على كل بوابة —
   والمقيس ضدّه يُسمّى **دورًا لا صنفًا**، لأن قانونًا يسمّي
   ‎.tkb-2‎ يسقط يوم ينتقل الصنف. وكان مكتوبًا هنا عكسه («ضدّ
   ‎.tkb-2‎ وحده») وفي ‎styles/tak.css‎ مثله، فثلاثة ملفّات وقانون
   واحد بمحتوًى متعاكس. انشال النصّ من الاثنين، وبقي الإسناد.
   الفرق مقصود ومكتوب: أثقل جسم بعد الفعل الأساسي في الردهة هو
   **الرزمة** (‎.tkfan‎)، والفعل الأساسي ما يفوقها بثلاثة أضعاف.
   هذي ملاحظة تُسجَّل، مو امتثالًا يُدّعى — ولو أردناها امتثالًا
   لصار العلاج تصغير الرزمة أو تكبير الزر، أي إعادة تصميم.
   ولا رقم من هذي النسب ينكتب هنا نصًّا: الأرقام كلها من الرِّج
   المحصَّن، تُولَّد ولا تُنسخ —
       ‎_probe/a-rects.html?w=390&h=844‎  (شرطه ‎STABLE=true‎)
   ونسبة الوجه على اللوح تعيش في جدول السلّم بـMOLD وحده، ما تنعاد.

   وليش انحذف الجدول اللي كان هنا: كان ينشر «٣٠٦٫٠٠×٨٨٫١١» و
   «١٢١٫٦٩×٥٠٫٠٠» في ثلاثة مواضع، وهما مقاسان ما عادا يتكرّران
   على نفس الرِّج بنفس الشرط. والحزّة على وجه الزرّ (تحت) تغيّر
   مساحته مرّة أخرى. رقمٌ منشور في ثلاثة ملفّات ينبَتّ عن مصدره
   بأول تعديل هندسي — والقاعدة المستفادة في MOLD: «رقم من رِج ما
   انبرهن تكراره ما هو رقمًا»، ومعها الآن: **رقمٌ يقدر الرِّج
   يولّده ما ينكتب نصًّا.**
   وتاريخ العطب باقٍ للسجلّ بلا أرقامه: القالب كان يدّعي «٣ إلى ٥
   أضعاف» والمقيس وقتها بالكاد فوق الواحد؛ ومصدر المكسب إن
   الثانوي انكمش على كلمته، لأن زرّين بعرض كامل ما يقدران
   يختلفان إلا بالارتفاع. ثم انشرت أرقام مقيسة على عنصر يتحرّك
   (‎@keyframes tk-rise‎ يبدأ بـ‎scale(.94)‎ و‎getBoundingClientRect‎
   يرجّع الصندوق *بعد* التحويل) — عرضٌ من خارج الحركة وطولٌ من
   داخلها في سطر واحد.
   ============================================================ */
/* عطب مقيس ومصلَّح (٢٠٢٦-٠٧-٢٨ · الجولة ٣) — العطب الرئيس:
   .tkb-1 تعلن طبقتين (وجه + حدّ)، و.tkb فوقها تعلن قصًّا بثلاث
   قيم. القائمة تنقصّ لطبقتين padding-box، فينرسم --edge-hot تحت
   النحاس السادّ وما يظهر ولا مرّة، وتبقى حلقة الـ1px الشفّافة
   تورّي اللوح: قيس على DPR 3 قبل الإصلاح، شريط #375D4B فوق
   و#345948 يسار يلفّ الشريحة الذهبية كامل. يعني الفعل الأساسي
   كان يُشحن «تعبئة مسطّحة + شعرة» — وهو بالحرف البناء اللي
   ترويسة هذا الملف تسمّيه سبب «بيسك».
   تأرجح حدّه كان ١٫١٨ (حلقة لوح مسطّحة)؛ بعد الإصلاح ينرسم
   --edge-hot فعلًا. والقاعدة العامة مكتوبة عند .tkb:disabled. */
.tkb-1{
  min-height:56px;width:100%;padding-inline:28px;border-radius:var(--r-btn-1);
  background-image:var(--face-hot),var(--edge-hot);
  background-clip:padding-box,border-box;
  box-shadow:var(--rim-hot),var(--sh3),var(--bloom);
  color:var(--ink);                                  /* غامق على حار = إشارة لعبة */
  font-weight:var(--w-lead);font-size:1.3125rem;line-height:1.4;
  text-shadow:0 1px 0 rgba(var(--lit-hot-rgb),.28)}         /* الكلمة محفورة بالنحاس */
/* التحويم خلف الحارس — العلّة مكتوبة كاملةً عند ‎.tkb:hover‎ فوق. */
@media (hover:hover){
.tkb-1:hover,.tkb-1.is-hover{
  background-image:linear-gradient(196deg,var(--a-hov-hi),var(--a-hov) 52%,var(--a-hov-lo)),var(--edge-hot);
  box-shadow:var(--rim-hot),var(--sh3),var(--bloom-wide)}
}

.tkb-1:active,.tkb-1.is-active{box-shadow:var(--sink-hot),var(--sh1),var(--bloom-sunk)}
.tkb-1:disabled,.tkb-1[aria-disabled="true"]{
  background-image:var(--face-hot-off),var(--edge-quiet);
  box-shadow:inset 0 1px 0 rgba(var(--lit-hot-rgb),.10),var(--sh1);   /* الوهج انشال، والنحاس باقٍ */
  color:var(--ink-off);text-shadow:none;cursor:not-allowed;transform:none}
.tkb-1:disabled::after,.tkb-1[aria-disabled="true"]::after{display:none}
/* اللمعة — «مرّة الشمس». تنرسم بموضع خلفية على ::after، مو
   بـtransform داخل overflow:hidden — فما فيه ولا احتمال إن
   حرفًا عربيًّا أو فتحة تنقصّ بسبب نبضة خمول. */
.tkb-1::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background-image:linear-gradient(110deg,
    rgba(var(--lit-sweep-rgb),0) 42%, rgba(var(--lit-sweep-rgb),.17) 50%, rgba(var(--lit-sweep-rgb),0) 58%);
  background-repeat:no-repeat;background-size:260% 100%;
  background-position:-80% 0}

/* ============================================================
   ٣-ب · الحزّة على الفعل الأساسي — «.tkbite»
   ٢٠٢٦-٠٧-٢٨ · الجولة ٥

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

   وترويسة هذا الملف كانت تقاعد الحزّة عن كل عنصر تفاعلي بحجّة
   «clip-path يقصّ box-shadow فيقتل الطبقات الأربع». الحجّة صحيحة
   في نصفها وباطلة في نتيجتها: القصّ فعلًا يمحو الظلّ **الخارجي**،
   لكن الغائر يبقى (ينرسم داخل الشكل ثم ينقصّ معه)، والخارجي له
   بيت معروف مقيس — الغلاف. مقيسة في ‎_probe/clipshadow.html‎:
   صندوق بظلّ، ثم نفسه بـclip-path، ثم نفسه بقناع، ثم غلافٌ يحمل
   الظلّ وابنٌ يحمل القناع — والرابع يرجّع الظلّ كامله. و.tkmark
   نفسها تشحن clip-path و‎filter:drop-shadow‎ على نفس العنصر وترسم.

   وليش القناع لا ‎clip-path:path()‎: مسار العلامة مطلق بالبكسل وما
   يتمدّد، والفعل الأساسي **سائل** — عرضه يتغيّر مع البوابة. بناء
   الحزّة بثلاث طبقات قناع (مربّع الحزّة مثبَّت على ‎right top‎ بضلع
   ‎--nt‎، وطبقتان سادّتان تغطّيان الباقي) يتمدّد بالـcalc، وهو نفسه
   بناء ‎.tknotch‎ و‎.tkledger‎ حرفًا بحرف.

   والدرجة: ‎--nt:40px‎ — عضّة ٣٠٫٣px فيزيائيًّا (‎--nt × 44/58‎، نفس
   حساب الدفتر). والدرجة مختارة بين اللوح والدفتر لا اعتباطًا:
   ترتيب الدرجات يتبع ترتيب المساحة، فاللغة تُقرا سلّمًا لا
   تكرارًا — والفعل الأساسي أصغر من اللوح وأكبر من الدفتر.
   ولا عدد مكتوب هنا: القائمة تُقرا من الملف، مثل ما تقول
   الترويسة —
     grep -nE '^\s*--nt:[0-9]|clip-path:(path|polygon)\([^)]' design/tak/components.css
   (كانت الصياغة ‎--nt:‎ و‎path(‎ وحدهما، و**تفوتها ظهر تَك** لأن
    الظهر مقصوص بـ‎polygon()‎ — وهو أكثر بيت يتكرّر على الشاشة،
    أربع مرّات. انبلّغت وانوسّعت هنا وفي الترويسة وفي MOLD وKIT
    بنفس الصياغة. وقاعدةٌ تُعِدّ ناقصًا أخطر من عددٍ باليد.)

   والعضّة تشيل ذهبًا ما تزيده — فميزانية اللون المحجوز تنزل، لا
   ترتفع. تنقاس بـ‎_probe/a-accent.py‎ على لقطة ‎a-shot.html‎.

   ---- والطبقات، وين راحت كل وحدة ----
     الغائر (‎--rim-hot‎ / ‎--sink-hot‎) ......... باقٍ على الزرّ
     التماس والمحيط (‎--sh3‎) والوهج (‎--bloom‎) ... انتقلت للغلاف
   وdrop-shadow ما عنده انتشار (spread)، فالطبقات معاد اشتقاقها
   بنفس الاتجاه ونفس الترتيب: تماسٌ ضيّق بلا إزاحة، ثم شكلٌ
   يسار-تحت، ثم محيطٌ واسع، ثم الوهج بلا إزاحة أفقية (الإشعاع ما
   يطيع الشمس — نفس نصّ ‎--bloom‎). ولا طبقة بإزاحة +x: قانون الشمس.
   والغلاف يورث الحالة من ابنه بـ‎:has()‎، فالضغطة تنزل الظلّ
   والوهج معًا كما كانت تنزلهما ‎box-shadow‎ بالضبط.

   ---- وحلقة التركيز ----
   القناع يقصّ ‎outline‎ مثل ما يقصّ الظلّ، فالحلقة انتقلت للغلاف
   بـ‎:has(:focus-visible)‎ وانطفت على الزرّ. أربع حالات، كلها
   تنرسم: ‎design/tak/parts.html‎.

   ═══ والحلقة كانت تعبر العضّة، وهذا درس MOLD §٦ نفسه مشحونًا
       مرّةً ثانية (٢٠٢٦-٠٧-٣١ · الدورة ٣ · الجولة ٢) ═══
   ‎outline‎ يرسم **مستطيلًا مدوَّرًا وبس** — مهما كان شكل الجسم.
   فالحلقة كانت تمشي مستقيمةً فوق مربّع العضّة ٤٠×٤٠ في الركن
   الأعلى-يمين: خطٌّ نحاسيّ معلَّق على سرير اللوح، ما تحته زرّ.
   وMOLD يكتب هالدرس بالحرف عن نفس الزرّ: «الجولة ٥ حطّت الحزّة
   على الزرّ وشحنت حلقة تركيزٍ تتجاهلها». انتقلت الحلقة من
   *مقصوصةٍ* إلى *غير مقصوصة* — ومازالت ما تتبع الشكل.

   ---- البناء، وليش هو قطعتان لا واحدة ----
   ما فيه في CSS «حدٌّ يتبع قناعًا»: ‎box-shadow‎ و‎border‎ و‎outline‎
   كلها ترسم على حدّ **الصندوق**، والقناع ينقص منها بعدين — فأي
   حلقةٍ مقنَّعة تنفتح فجوةً عند الدرجة بدل ما تمشي معها. فالحلقة
   قطعتان تتلاقيان في نقطتين محسوبتين:
     ‎::after‎ — الحلقة على المستطيل المدوَّر (‎box-shadow‎ غائر بعرض
       ‎--ring-w‎ داخل صندوقٍ مُزاحٍ للخارج ‎--ring-gap + --ring-w‎)،
       مقنَّعةً بطبقتين سادّتين **تستثنيان مربّع الحلقة كلَّه**
       ‎--nt-r‎ في الركن الأعلى-يمين.
     ‎::before‎ — مربّع ‎--nt-r‎ نفسه، مقنَّعًا بمسارٍ **مرسومٍ خطًّا**
       (‎--nt-ro‎) هو خطّ منتصف الحلقة حول الدرجة.
   ونقطتا اللقاء ليستا تقريبًا: المسار يبدأ عند حرف المربّع الأيسر
   على ارتفاع منتصف الحلقة العليا بالضبط، وينتهي عند حرفه السفلي
   على بُعد منتصف الحلقة اليمنى بالضبط — وهما بعينهما الموضعان
   اللي تنتهي عندهما الطبقتان السادّتان.

   ---- ولماذا نصف قطرٍ جديد لكل قوس، ولا يجوز التمديد ----
   الشكل مُزاحٌ للخارج ‎d‎، والإزاحة ليست تكبيرًا: القوسان
   المحدّبان يزيد نصفهما ‎d‎، والقوس المقعّر ينقص نصفه ‎d‎، والخطوط
   المستقيمة تنتقل ‎d‎. (لو مُدِّد المسار الأصلي بدل ذلك لطلع نصف
   المقعّر **أكبر**، وهو عكس الحقيقة.) والحساب، بالبكسل، على
   ‎--nt = 40‎ و‎d = --ring-gap + --ring-w/2 = 4‎ لخطّ المنتصف
   (المقياس ‎40/58‎، فالأنصاف الأصلية ١٤/١٢/١٤ تصير ٩٫٦٥٥/٨٫٢٧٦/٩٫٦٥٥):
     محدَّب ١  ٩٫٦٥٥ + ٤ = ١٣٫٦٥٥      مقعَّر  ٨٫٢٧٦ − ٤ = ٤٫٢٧٦
     محدَّب ٢  ٩٫٦٥٥ + ٤ = ١٣٫٦٥٥      ضلع المربّع ‎--nt + --ring-gap + --ring-w‎ = ٤٥
   ثم تُردّ للـviewBox ٥٨ بضرب ‎58/45‎، والعرض ‎--ring-w‎ = ٢px يصير
   ‎2 × 58/45 = 2.578‎ وحدة. وهذي كلها هندسةٌ لا صبغة: اللون يجي
   من ‎--ring-c‎ عبر خلفيّة العنصر، والقناع أبيضُ فقط.
   ============================================================ */
.tkbite{
  position:relative;display:block;border-radius:var(--r-btn-1);
  --nt:40px;                                          /* ضلع مربّع الحزّة — ثابت بالبكسل. عضّة ٣٠٫٣ */
  /* نفس المسار الخارجي المشحون في .tknotch و.tkledger حرفًا بحرف.
     ثلاث نسخ لهندسة وحدة — والصحيح بيت واحد في العدّة. مبلَّغ. */
  --nt-o:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58 58'><path fill='white' d='M0 0A14 14 0 0 1 14 14V32A12 12 0 0 0 26 44H44A14 14 0 0 1 58 58H0Z'/></svg>");
  filter:drop-shadow(0 2px 4px rgba(var(--sh-rgb),.48))
         drop-shadow(-4px 8px 10px rgba(var(--sh-rgb),.50))
         drop-shadow(-12px 21px 26px rgba(var(--sh-rgb),.42))
         drop-shadow(0 8px 14px rgba(var(--a-rgb),.45));
  transition:filter var(--t-up) var(--spring)}
.tkbite>.tkb-1{
  box-shadow:var(--rim-hot);                          /* الخارجي انتقل للغلاف */
  -webkit-mask-image:var(--nt-o),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
  /* الـ‎+1px‎ ليست زخرفة — هي إصلاح درزة مقيسة.
     طبقتا القناع السادّتان تتلاقيان عند ‎100% − --nt‎ بالضبط.
     على جسم ساكن بعرض صحيح تقع الملتقى على بكسل صحيح فما تبين،
     لكن الضغطة ‎scale(.96)‎ تحطّها على كسر بكسل، فينزل الطرفان
     دون الواحد الصحيح مجموعًا وتنفتح **درزة عمودية بعرض بكسل
     على وجه النحاس**. مقيسة على المركّب قبل الإصلاح: عند الضغط،
     بكسل ‎(158,130,58)‎ داخل صفٍّ كله ‎(232,179,74)‎ — أي خطٌّ
     غامق يشقّ الزرّ. تراكبٌ بكسل يخلّي المجموع يعدّي الواحد
     فينقصّ عند الحدّ، والعمود الملغيّ أصلًا مرسومٌ في المسار
     نفسه فما ينتقص من الحزّة ولا بكسل.
     (اللوح والدفتر ما فيهما هالدرزة لأنهما ما ينضغطان — والفعل
      الأساسي هو أول سطح محزوز يتحوّل.) */
  -webkit-mask-size:var(--nt) var(--nt),calc(100% - var(--nt) + 1px) 100%,var(--nt) calc(100% - var(--nt) + 1px);
          mask-size:var(--nt) var(--nt),calc(100% - var(--nt) + 1px) 100%,var(--nt) calc(100% - var(--nt) + 1px);
  -webkit-mask-position:right top,left top,right bottom;   /* فيزيائية — ما تنقلب بالـRTL */
          mask-position:right top,left top,right bottom;
  -webkit-mask-repeat:no-repeat;
          mask-repeat:no-repeat}
/* التحويم خلف الحارس — العلّة مكتوبة كاملةً عند ‎.tkb:hover‎ فوق. */
@media (hover:hover){
.tkbite>.tkb-1:hover,.tkbite>.tkb-1.is-hover{box-shadow:var(--rim-hot)}
.tkbite:hover{
  filter:drop-shadow(0 2px 4px rgba(var(--sh-rgb),.48))
         drop-shadow(-4px 8px 10px rgba(var(--sh-rgb),.50))
         drop-shadow(-12px 21px 26px rgba(var(--sh-rgb),.42))
         drop-shadow(0 12px 20px rgba(var(--a-rgb),.55))}
}

.tkbite>.tkb-1:active,.tkbite>.tkb-1.is-active{box-shadow:var(--sink-hot)}
.tkbite:active,.tkbite:has(>.tkb-1.is-active){
  filter:drop-shadow(0 1px 2px rgba(var(--sh-rgb),.45))
         drop-shadow(-1px 2px 3px rgba(var(--sh-rgb),.38))
         drop-shadow(0 4px 8px rgba(var(--a-rgb),.30));
  transition:filter var(--t-down) var(--ease-in)}
/* الموقوف: الوهج ينشال ويبقى المحيط الأدنى — نفس ما كان يفعل
   ‎box-shadow:…,var(--sh1)‎ على الزرّ */
.tkbite:has(>.tkb-1:disabled),.tkbite:has(>.tkb-1[aria-disabled="true"]){
  filter:drop-shadow(0 1px 2px rgba(var(--sh-rgb),.45))
         drop-shadow(-1px 2px 3px rgba(var(--sh-rgb),.38))}
.tkbite>.tkb-1:disabled,.tkbite>.tkb-1[aria-disabled="true"]{
  box-shadow:inset 0 1px 0 rgba(var(--lit-hot-rgb),.10)}
/* الحلقة على الغلاف — القناع يقصّها لو بقيت على الزرّ.
   و‎outline‎ انشال كليًّا: ما يعرف إلا المستطيل المدوَّر. الشرح
   والحساب في ترويسة هذا القسم. */
.tkbite>.tkb-1:focus-visible,.tkbite>.tkb-1.is-focus{outline:none}
.tkbite{--ring-out:calc(var(--ring-gap) + var(--ring-w));
        --nt-r:calc(var(--nt) + var(--ring-out));
        /* خطّ منتصف الحلقة حول الدرجة — مرسومٌ خطًّا لا مملوءًا. */
        --nt-ro:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58 58'><path fill='none' stroke='white' stroke-width='2.578' d='M0 1.289A17.598 17.598 0 0 1 17.598 18.887V34.889A5.511 5.511 0 0 0 23.111 40.4H39.111A17.598 17.598 0 0 1 56.711 58'/></svg>")}
.tkbite::before,.tkbite::after{content:"";position:absolute;pointer-events:none;
  opacity:0;background:var(--ring-c)}
/* القطعة الأولى: الحلقة على المستطيل المدوَّر، والمربّع مستثنًى. */
.tkbite::after{inset:calc(-1 * var(--ring-out));
  border-radius:calc(var(--r-btn-1) + var(--ring-out));
  background:none;box-shadow:inset 0 0 0 var(--ring-w) var(--ring-c);
  /* نفس الطبقتين السادّتين اللي في ‎.tknotch‎، بضلع ‎--nt-r‎ بدل ‎--nt‎.
     و‎+1px‎ درزةٌ مقيسة، نفس علّتها المكتوبة فوق عند ‎.tkbite>.tkb-1‎. */
  -webkit-mask-image:linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
  -webkit-mask-size:calc(100% - var(--nt-r) + 1px) 100%,var(--nt-r) calc(100% - var(--nt-r) + 1px);
          mask-size:calc(100% - var(--nt-r) + 1px) 100%,var(--nt-r) calc(100% - var(--nt-r) + 1px);
  -webkit-mask-position:left top,right bottom;   /* فيزيائية — ما تنقلب بالـRTL */
          mask-position:left top,right bottom;
  -webkit-mask-repeat:no-repeat;
          mask-repeat:no-repeat}
/* القطعة الثانية: الدرجة نفسها، مربّعٌ ثابت بالبكسل فما يتمدّد. */
.tkbite::before{top:calc(-1 * var(--ring-out));right:calc(-1 * var(--ring-out));
  width:var(--nt-r);height:var(--nt-r);
  -webkit-mask-image:var(--nt-ro);mask-image:var(--nt-ro);
  -webkit-mask-size:100% 100%;mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.tkbite:has(>.tkb-1:focus-visible)::before,.tkbite:has(>.tkb-1.is-focus)::before,
.tkbite:has(>.tkb-1:focus-visible)::after,.tkbite:has(>.tkb-1.is-focus)::after{opacity:1}

/* ============================================================
   ٤ · الهادي — الطبقة الثالثة. بالكاد مرفوع: حدّ متدرّج هادي،
   نور علوي رفيع، وظل تماس. ولا وهج.
   ============================================================ */
/* وجهه مقصوص من سواطه (--face-quiet)، مو غسلة نور فوق سريره.
   الغسلة القديمة (١٣٪→٣٪ أبيض) كانت تتلاشى للصفر عند النصف
   الأسفل، فالنصف الأسفل من الزر كان *هو اللوح حرفيًّا* — ومن
   هنا جا رقم panel:.tkb-q بثلاث نسخ متناقضة. انظر --s-quiet. */
.tkb-q{
  min-height:44px;padding-inline:18px;border-radius:var(--r-btn-sm);
  background-image:var(--lamp-catch-q),var(--face-quiet),var(--edge-quiet);
  background-clip:padding-box,padding-box,border-box;
  box-shadow:inset 0 1px 0 rgba(var(--lit-rgb),.06),inset 0 -1px 0 rgba(var(--sh-rgb),.55),var(--sh1);
  /* --tx لا --tx2: بعد ما ارتفع وجه الهادي لتحقيق قانون ١٫٢٠ صار
     --tx2 عليه ٤٫٤٩٧ مقيسة — تحت الأرضية بشعرة، وهذي بالضبط
     الشعرة اللي انفتحت لها هالجولة. وهدوء الزر يعيش في سطحه
     ومقاسه، مو في خفوت حبره. */
  color:var(--tx);font-weight:var(--w-control);font-size:1rem}
/* التحويم خلف الحارس — العلّة مكتوبة كاملةً عند ‎.tkb:hover‎ فوق. */
@media (hover:hover){
.tkb-q:hover,.tkb-q.is-hover{
  background-image:var(--lamp-catch),var(--face-rise),var(--edge-quiet);   /* درجة وحدة فوق، مو درجتين */
  box-shadow:inset 0 1px 0 rgba(var(--lit-rgb),.10),inset 0 -1px 0 rgba(var(--sh-rgb),.55),var(--sh2)}
}

/* الغطسة — إلى --sh0 لا إلى --sh1 (٢٠٢٦-٠٧-٢٨ · الجولة ٥).
   كانت الساكنة والمضغوطة تشحنان --sh1 نفسه، فالمحيط ما ينشال
   والجسم ما يغطس: يلبس داخليًّا وبس. وهذا العطب مفتوح من الجولة ٢
   لأن علاجه ما كان في القاعدة، كان في السلّم — انظر --sh0. */
.tkb-q:active,.tkb-q.is-active{box-shadow:var(--sink),var(--sh0)}

   /* نفس علّة الهادي ونفس علاجها */

/* ============================================================
   ٥ · الحقل — بئر محفورة بالطاولة، عكس اتجاه الزر تمامًا.
   التعبئة أغمق سطح بالنظام، والشفة العليا في الظل.
   وحدّه ما عاد مقلوبًا (٢٠٢٦-٠٧-٢٨ · الجولة ٣): بعد قانون
   الأرضية ما فيه بكسل حدٍّ غامق يقدر يوصل ٣:١ على هذا السرير،
   فالحدّ صار مضيئًا فوق أرضية مثل بقية الأدوات — والانقلاب
   انتقل حيث يجب أن يعيش أصلًا: --well الداخلي والوجه شبه
   الأسود. ثقبٌ مخروط في معدن، حافّته تلمع وقاعه أسود.
   الزر يجي لك، والحقل يروح عنك — وكلاهما تحت نفس المصباح.
   ٥٢px طول · ١٦٫٥px (فوق ١٦ فما فيه تكبير iOS) · leading 1.5
   = ٢٤٫٧px داخل صندوق ٥٢ — خلوص كامل للصاعد وللتشكيل،
   ولا overflow:hidden على أي شي هنا.
   ============================================================ */
.tkfield{display:block;min-width:0}
.tkfield-lb{font-family:var(--fu);font-weight:var(--w-support);font-size:1rem;line-height:1.75;
  color:var(--tx2);margin-block-end:6px;padding-inline-start:2px}
.tkfield-in{
  display:block;width:100%;min-width:0;min-height:52px;
  padding-block:12px 13px;padding-inline:16px;
  border:1px solid transparent;border-radius:var(--r-field);
  background-origin:border-box;background-clip:padding-box,border-box;
  /* الشفة العليا بالظل. وحرف النور اللي كان تحت الفتحة (0 1px 0)
     انشال: الحدّ المتدرّج صار يحمل النور بنفسه بعد قانون الأرضية،
     وذاك الحرف كان يفتّح السرير الملاصق للحافّة السفلى فينزل
     تباين الحدّ هناك تحت ٣:١ — أي أن زينة كانت تكسر قانونًا. */
  color:var(--tx);caret-color:var(--a-hi);
  font-family:var(--fu);font-weight:var(--w-support);font-size:1.03125rem;line-height:1.5;
  appearance:none;-webkit-appearance:none;
  transition:box-shadow 220ms var(--ease-out),background-image var(--t-tint) linear}
.tkfield-in::placeholder{color:var(--tx3);font-weight:var(--w-support);opacity:1}
.tkfield-in:focus{outline:none}                      /* مستبدَلة، مو مشالة */
.tkfield-in:focus,.tkfield-in.is-focus{
  background-image:linear-gradient(196deg,var(--s-well-hi),var(--s-well)),
                   linear-gradient(196deg,var(--a-hi),var(--a) 45%,var(--a-deep));
  box-shadow:var(--well),
             inset 0 1px 0 rgba(var(--sh-rgb),.70),
             inset 0 -1px 0 rgba(var(--a-hi-rgb),.18),
             0 0 0 3px rgba(var(--a-rgb),.20)}
.tkfield-in:disabled{color:var(--tx4);cursor:not-allowed}
.tkfield-in:-webkit-autofill{-webkit-text-fill-color:var(--tx);transition:background-color 9999s}
/* لا حالة ضغط على الحقل — البئر ما تغطس */

/* ============================================================
   ٦ · الأسطح — لوح وورقة وصحيفة. نفس الحقائق الأربع، والمحيط
   يتوسّع كل ما ارتفعت الطبقة. الحشوات مشتقّة فالأركان تبقى
   متحدة المركز.
   ============================================================ */
.tkcard{
  position:relative;border:1px solid transparent;background-color:transparent;
  background-origin:border-box;background-clip:padding-box,border-box}
.tkcard{border-radius:var(--r-card);padding:var(--pad-card);
  background-image:var(--face),var(--edge);box-shadow:var(--rim),var(--sh2)}

/* ============================================================
   ٧ · الورقة — النقشة الكلاسيكية، من الحافة للحافة.
   الورق أفتح قيمة بالعالم عشان اللعب يُقرا أول.
   ============================================================ */

/* ---- ظهر تَك — البيت الثالث للحزّة، وأكبر جسم بالشاشة.
        كان رقاقة ١٨px ما تُستعمل في أي مكان. صار الجهاز الورقي
        الوحيد بالردهة: ورقة حقيقية بحجمها، عليها توقيعنا.

        الطبقات: الغلاف يحمل الدوران والظلّ (بلا قصّ — القصّ على
        الابن، وإلا انمحى الظلّ؛ انظر §٨)، والوجه مقصوص بالحزّة.

        قرار: ولا نقشة على الوجه. جُرّبت أرضية معيّنات ملوّنة
        فانقرأت ورق جدران قديمًا — وهذا فخّ التعتيق نفسه اللي
        نهرب منه. المكتوب في السجلّ هو المكتوب: إطار صامت،
        و«تَك»، وعلامة تحتها. لا رابع.
        والذهب هنا «الخيط» (--kh) مو النحاس المحجوز: النحاس
        ما يقع إلا على اللي ينضغط.

        تغييران ٢٠٢٦-٠٧-٢٨ (الجولة ٣):
        ١ · الخامة صارت كرتونًا (--p-back-*) بدل ورق الوجه
            (--p-card-*). الرمزان كانا معلنَين وما يُستعملان،
            وتعليقهما يقول «كرتون، مو ورقة لعب» — والظهر كان
            مقصوصًا من نفس ورق الوجه، فالظهر والوجه بالرزمة
            كانا مادة وحدة. صارا مادّتين.
        ٢ · الدرزة الذهبية صارت صفّ رموز اللعب الأربعة. الردهة
            كانت ما تقول أي لعبة هي: إطار وكلمة وخطّ. الآن
            تقولها بأصغر إشارة ممكنة — إشارة، مو شعارًا. ---- */
/* عطب مقيس ومصلَّح (٢٠٢٦-٠٧-٢٨ · الجولة ٤): كان هنا --bw:96px
   مُعلنًا على العنصر المستهلِك نفسه، فأي قيمة تجي من --tkfan فوقه
   ما تصل أبدًا — الإعلان على العنصر يغلب الوراثة دايم. النتيجة
   المقيسة: .tkfan تكتب calc(74px + 10.8*--g) وتُقرا «تتنفّس
   ٧٤→٩٦»، والرزمة تنقاس ١٤٢٫٢٤px عرضًا *على كل بوابة* — من
   ٣٢٠×٥٦٨ إلى ٤٣٠×٩٣٢ ما تغيّرت ولا بكسل. أكبر جسم زينة بالشاشة
   ما ينحني ولا مرّة على أقصر شاشة.
   العلاج بالطبقة الصحيحة: العدّة ما تعلن --bw على .tkback أبدًا،
   بل تحلّها مرّة وحدة في اسم خاصّ لها --cardw مع افتراضها ٩٦.
   فالورقة الواقفة وحدها (parts.html) تبقى ٩٦، والورقة داخل رزمة
   ترث مقاس الرزمة. القيمة تُقرا مرّة، وكل الأبناء يرثون --cardw. */
/* ============================================================
   ٧-ب · ‎.tkcardbody‎ — **جسم الورقة**، مكوّنًا واحدًا
   ٢٠٢٦-٠٧-٢٩ · الدورة ٣ · الجولة ١.

   ليش انبنى، ومو زخرفة: لجنة التدقيق قالت «كشفُ الحزّة يُقرا
   لسانَ ورقٍ ممزّق في أهمّ ركنٍ بالشاشة — يبي مكوّن ورقة حقيقي».
   والعلّة انقاست ولا انذوّقت: **الورقة ما كان لها حافّة**.
   ‎.tkback‎ كانت غلافًا فيه دورانٌ وظلّ ‎drop-shadow‎، ووجهًا فيه
   خامةٌ ونصف قطر — وبس. ولا شريطَ نورٍ فوق، ولا شريطَ ظلٍّ تحت،
   يعني **ولا واحدة من حقائق الضوء الأربع** اللي يفرضها القانون
   الأول على كل جسمٍ مرفوع. وجسمٌ بلا حافّة، إذا انقصّ منه ركنٌ
   بنافذة، ما يبقى منه إلا **لون**: مساحةٌ كريمية بلا طرف. وهذا
   بالضبط تعريف «ورقٍ ممزّق»، ومو مسألة موضعٍ ولا زاويةٍ ولا
   حجم — الثلاثة جُرّبت من الجولة ٤ إلى الجولة ٥ وما انحلّت.
   الفرق بين «ورقة» و«لطخة» طرفٌ مضيء وطرفٌ مُظلَّل، ولا شيء غيره.

   والرِّم ‎inset‎ لأن هذا هو الفرق كلّه: الوجه مقصوصٌ بـ‎clip-path‎،
   والمتصفّح يرسم ‎filter → clip-path → mask‎، فالظلّ **الخارجي**
   ينمحي مع القصّ والغائر ينجو (‎_probe/clipshadow.html‎). فالحافّة
   لازم تكون غائرة أو ما تكون. والظلّ الخارجي يبقى وين هو أصلًا:
   على الغلاف، بـ‎--drop-card‎.
   و‎--rim-paper‎ رمزٌ قايم من قبل، مكتوبٌ لهذا الغرض حرفيًّا
   («رِم الورق … نور المصباح على الورق»)، وكان يستعمله ‎.tkcardface‎
   وحده — أي إن **الوجه كان له حافّة والظهر ما له**، وهما نفس
   المادة تحت نفس المصباح. فالمكوّن هنا توحيدٌ لا اختراع.

   الحدود: ‎.tkcardbody‎ يملك الهندسة والضوء؛ والمادة (كرتون الظهر،
   الخامة، الحزّة) تبقى في ‎.tkback‎ فوقه. ورقةٌ وجهها لفوق
   (‎.tkcardface‎) ما تنضمّ له اليوم لأنها عنصرٌ واحد بلا ‎.fc‎
   يحمل القصّ — والدمج مبلَّغ، ما هو معمولًا بالسكوت.
   ============================================================ */
.tkcardbody{position:relative;display:block;
  --cardw:var(--bw,96px);
  width:var(--cardw);aspect-ratio:63/88;
  transform:rotate(var(--rot,0deg));transform-origin:50% 60%;
  filter:brightness(var(--dim,1)) var(--drop-card)}
.tkcardbody>.fc{position:absolute;inset:0;
  border-radius:calc(var(--cardw)*.045);       /* استثناء المادة — قانون الورقة */
  box-shadow:var(--rim-paper)}

.tkback{
  /* الطبقتان اللي ما فيهما خامة، مرمَّزتان هنا لأن الكسوة تعيد
     بناء الخلفية كاملةً فوق الخامة (انظر .tkback>.fc تحت). لو
     انكتبتا مرّتين — هنا وهناك — لانفصلت النسخة الثانية عن
     الأولى بأول تعديل، وهذا بالضبط العطب اللي أقفلته الجولة ٥:
     رقمٌ ينبَتّ عن مصدره صامتًا. اسمٌ واحد، بيتٌ واحد. */
  --lit-card:radial-gradient(74% 56% at 86% 5%,
             rgba(var(--lit-paper-rgb),.55), rgba(var(--lit-paper-rgb),0) 66%);
  --card-bed:linear-gradient(196deg,var(--p-back-hi) 0%,var(--p-back-lo) 100%)}
/* ٢٠٢٦-٠٧-٢٩ · ظهر تَك صار **خامة مولّدة** تحمل العلامة الجديدة
   (شكل ٧) — بدل ما كان اسمًا و١٥٢ مركّبَين بالنصّ.

   ═══ والخامة ما انعرضت ولا مرّة · ٢٠٢٦-٠٧-٢٩ · الجولة ١ ═══
   كان مكتوبًا هنا ‎var(--im-back, none) center/cover‎ — أي إن
   **القالب** هو اللي يستهلك الفتحة. وهذا نفس العطب المقيس اللي
   أقفلته الكسوة لـ‎--im-weave‎ قبله بيوم: الـ‎url()‎ جوّا خاصيّة
   مخصّصة ينحلّ نسبةً للملف اللي **يستعملها** لا اللي يعلنها.
   الإعلان في ‎app_client/frontend-tak/styles/tak.css‎ يقول
   ‎url("../design/assets/back-v3.jpg")‎ — وهو صحيح من بيته — وهذا السطر
   يستعمله من ‎design/tak/‎، فينحلّ إلى ‎design/assets/back-v3.jpg‎
   وهذا مجلّد **ما هو موجودًا أصلًا**.
   مقيسًا لا مستنتَجًا (‎node _probe/fan.mjs‎ يطبع الرابط المحلول
   ورمز الخادم عليه):
     http://localhost:8452/design/assets/back-v3.jpg → HTTP 404
   يعني الأربع ورقات — أكبر جسم بالردهة — كانت تنرسم تدرّجًا
   كرتونيًّا سادًّا من يوم ما انشحنت الخامة. «ورق كريمي فاضي»
   اللي انقرا على الشاشة ما كان حكم ذوق: كان ٤٠٤.

   والعلاج نفس علاج الجوخ بالحرف: **القاعدة اللي تستعمل الفتحة
   تعيش عند الإعلان** — في ‎styles/tak.css‎ عند ‎.tkback.has-art>.fc‎.
   والقالب هنا يبقى بلا خامة (وهذا صحيح: القالب ما يعرف وين
   الخامات)، ويحتفظ بطبقتيه — الوهج فوق والفراش تحت — مرمَّزتين
   في ‎--lit-card‎ و‎--card-bed‎ فوق، فالكسوة تدسّ الخامة بينهما
   بلا ما تعيد كتابة ولا تدرّج. وترتيب الطبقات قانون: **الوهج
   يبقى فوق الخامة** — الورقة ورقةٌ مضاءة بنفس الشمس، مو صورةً
   ملصوقة. */
/* الموضع والشكل ونصف القطر والحافّة كلها من ‎.tkcardbody>.fc‎ فوق —
   وما تنعاد هنا. اللي يبقى للظهر مادّتُه وقصّتُه. */
/* ---- الورقة ما تنقصّ · حكم صاحب البيت ٢٠٢٦-٠٧-٣١ · الجولة ٣ ----
   نصّه: «قصّ الورق من الركن الأعلى، الحزّة في الورق ما هي زينة
   أبدًا، شيلها».
   والقصّ انشال من **كل** ورقة، لا من واحدة. وكان قبله على ثلاثٍ
   من الأربع، والرابعة وحدها ‎.is-uncut‎ — والحجّة اللي انكتبت لها
   يوم ذاك هي حجّته حرفًا، وهذا اللي يخلّي هالتعميم نظيفًا لا
   تنازلًا: «ظهرٌ ما ينكشف منه إلا ركنٌ من نافذة … المكشوف ما فيه
   ولا حافّة ورقة كاملة، ولا ركن، ولا نسبة — يُقرا قصاصة ورق
   ممزّقة، أي عطب رندر»، وثلاثة قرّاء مستقلّين سمّوه أضعف جسم
   بالشاشة (المقيس على ٣٩٠×٨٤٤ بتكبير ٨×: ‎_probe/a-crop.py‎ على
   لقطة ‎a-shot‎). العلّة نفسها في الرزمة الظاهرة: ركنٌ مقصوص من
   ورقةٍ **مرئيّة كاملةً** يُقرا تمزيقًا لا توقيعًا، لأن الحزّة
   توقيعُ **سطحٍ يُضغط أو لوحٍ**، والورقة لا هذا ولا ذاك.
   فالورقة اليوم تحتفظ بركنها وبنسبة ٦٣:٨٨ سليمة، والطاولة تبان
   فوقها ويمينها داخل نفس فتحة اللوح، فتُقرا ورقةً مدسوسةً تحت
   اللوح لا شكلًا مقصوصًا منه.
   و‎.is-uncut‎ انطوى بدل ما يُترك: صنفٌ يستثني من قاعدةٍ ما عادت
   قايمة هو صنفٌ ميّت بتعليقٍ حيّ يشرح حالةً خاصّة ما لها وجود —
   وهذا بالضبط الشكل اللي يعلّم اللي بعدنا إن الملف يوصف شجرةً
   ثانية. (وبيوت الحزّة الباقية معدودة ومقروءة من الملف لا من
   الذاكرة: ‎grep -nE '^\s*--nt:[0-9]|clip-path:(path|polygon)\([^)]'‎
   — اللوح والفعل الأساسي والدفتر، وكلها تُضغط أو تُقرا صحيفة.) */
.tkback>.fc{background:var(--lit-card),var(--card-bed)}
/* الإطار الصامت — خيط، بعرض شعرة، يضوي فوق ويغيب تحت */
.tkback:not(.has-art)>.fc::after{content:"";position:absolute;inset:7.5%;
  border-radius:calc(var(--cardw)*.018);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--kh) 46%,transparent),
             inset 0 1px 0 rgba(var(--lit-paper-rgb),.50)}
.tkback.has-art>.w{display:none}
.tkback>.w{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:calc(var(--cardw)*.055);
  padding-top:calc(var(--cardw)*.070);
  font-family:var(--fd);font-weight:var(--w-display);font-size:calc(var(--cardw)*.26);line-height:1.5;
  /* ١٩٦ لا ١٩٨: كانت هذي ثالث زاوية شمس بالنظام، وتنرسم ثلاث
     مرّات على الشاشة الأولى، وشقيقتها اللي تحتها بسطر واحد
     ١٩٦. القانون زاوية وحدة واستثناءان مكتوبان، ولا ثالث. */
  /* الوقفات انسحبت داخلًا (٢٠٢٦-٠٧-٣١): كانت ‎--kh 72%‎ و‎--kh-d 100%‎،
     والتدرّج يغطّي **صندوق الورقة كامله** بينما ‎background-clip:text‎
     ما يبقي منه إلا ما يقع تحت الحرف — والحرف يقعد في وسط الصندوق،
     فوقفة الـ١٠٠٪ (ركنٌ في زاوية التدرّج) ما تلمس حبرًا أبدًا.
     مقيسًا: ‎--kh-d‎ يحكم **صفر بكسل** على كل صفحةٍ في السلسلة
     (‎node _probe/a-govern.mjs --src /design/tak/parts.html‎)، أي
     رمزٌ حيٌّ في القاعدة وميّتٌ على الشاشة. الوقفتان الآن ٦٢٪ و٨٨٪
     فتقعان تحت الحرف، والرمز يحكم. */
  background:linear-gradient(196deg,var(--kh-sun) 0%,var(--kh-l) 34%,var(--kh) 62%,var(--kh-d) 88%);
  -webkit-background-clip:text;background-clip:text;color:transparent}
/* ---- العلامة تحت «تَك» — ١٥٢، لا ‎♠ ♥ ♦ ♣‎ ----
   ٢٠٢٦-٠٧-٢٨ · الجولة ٥.
   كان هنا صفّ رموز اللعب الأربعة، وكان مسمًّى عطبًا في الجولة ٣
   وشُحن جولتين بعدها. والعلّة إن أربعة رموز أممية هي **أكثر
   علامة قابلة للتبادل** يقدر تطبعها لعبة ورق: هي على ظهر كل
   بوكر وكل سوليتير وكل رزمة بلاستيك في الدنيا، فتقول «ورق»
   وما تقول ولا حرف عن بلوت ولا عن هذا البيت.
   و١٥٢ **هدف الصكّة** — الرقم اللي يعرفه كل من لعب بلوت، وهو
   نفسه اللي يناديه السطر السند تحت الفعل الأساسي («صكّة كاملة
   لين ١٥٢»). فالردهة صارت تقول لعبتها برقمها، مرّتين، بلغة
   واحدة: مرّة بالكلام على الزرّ، ومرّة زينةً على الظهر.

   ثلاثة مرشّحين رُندروا على المقاس المشحون وقُرئوا (٩٦px،
   ‎design/tak/parts.html‎):
     «صن حكم»  أميري ١٣px — سطر عريض من حافّة لحافّة، يُقرا
               نصًّا لا علامة، ويصير لطخة عند ٩٦
     «أبناط»   أميري ١٣px — رفيع ومتّصل، يذوب على الكرتون
     «١٥٢»     زين ٨٠٠ ١١px — مضغوط، وثلاثة أشكال منفصلة تصمد
   والظهر ينرسم أربع مرّات بالردهة بحجم همسة، فالقرار قرار
   قراءة قبل ما يكون قرار ذوق.

   وليش ‎direction:ltr‎ باقية: **لأن العلامة أرقام غربية** (حكم
   صاحب البيت: الأرقام غربية دايم)، والأرقام ترتيبها عالميّ
   يمشي يسار-يمين داخل أي نصّ، فالعزل ‎unicode-bidi:isolate‎
   يحميها من انقلاب سياق الـRTL حولها. لو كانت العلامة كلمةً
   عربية لانقلبت القاعدة إلى ‎rtl‎ حتمًا — وهذا اللي رجّح الرقم
   كذلك: ما يحتاج سياقًا يصحّحه.
   و‎--fu‎ لا ‎--fs‎: العدّة تقول «زين … والواجهة **وكل الأرقام**»،
   وأرقام الدفتر (‎.tkledger .n‎) تشحن ‎--fu‎ نفسه — فوجه الأرقام
   بالنظام واحد لا اثنان. ورقعة الرموز ‎--fs‎ ما لها شغل بالأرقام،
   وقد صارت بلا مستهلك — مبلَّغة لصاحبها، وما تنحذف هنا لأن
   مولّد الـJSON يقرأها.
   و‎--w-control‎ (٨٠٠) لا ‎--w-support‎ (٤٠٠): رُندر الاثنان وقُرئا
   على ٩٦px، والأربعمئة تنحف عند هذا المقاس حتى تُقرا ظِلًّا لا
   حبرًا — لأن الرقم مملوء بتدرّج الخيط، ووقفته الوسطى ‎--kh-l‎
   تقع على أعرض جزء من الساق فتُنحّفه بصريًّا. وما فيه وسط:
   ٥٠٠ و٦٠٠ ممنوعتان في كل الكسوة، فالاختيار ٤٠٠ أو ٨٠٠.
   والوزن ما يخالف قانون الخيط: القانون «شعرة» يخصّ الخيط
   **خطًّا مرسومًا** (إطار الظهر)، والعلامة حبرٌ لا خطّ.
   وانحذفت معها ‎font-variant-emoji:text‎ و‎font-feature-settings‎:
   الاثنتان انوجدتا لمنع الوجه الملوّن عن رموز اللعب، والأرقام
   ما لها شكل إيموجي أصلًا — إعلانٌ سببه راح ينحذف معه.
   والاحتياط أسفلَ (‎@supports not (background-clip:text)‎) باقٍ
   على حاله ويشمل الكلمة والرقم معًا.
   والذهب هنا ‎--kh‎ الخيط لا النحاس، وبلا ‎letter-spacing‎ أبدًا. */
.tkback>.w::after{content:"152";display:block;
  direction:ltr;unicode-bidi:isolate;
  font-family:var(--fu);font-weight:var(--w-control);font-size:calc(var(--cardw)*.115);line-height:1.4;
  background:linear-gradient(196deg,var(--kh-sun),var(--kh-l) 40%,var(--kh));
  -webkit-background-clip:text;background-clip:text;color:transparent}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .tkback>.w,.tkback>.w::after{background:none;color:var(--kh)}}

/* ---- الرزمة — أثاث طاولة، مو ملصق. مطلقة داخل .stage فما تاخذ
        ولا بكسل من الإيقاع الرأسي، ومقاسها مربوط بنَفَس التخطيط. ---- */
.tkfan{position:absolute;inset-inline-start:0;top:0;width:100%;height:100%;
  pointer-events:none;}
/* ---- ‎--o‎ صارت نسبةً من **الورقة** لا من المسرح ----
   ٢٠٢٦-٠٧-٢٩ · الجولة ١.
   كانت ‎calc(var(--o) * 1%)‎ — أي نسبةً من عرض المسرح — و‎--t‎ جنبها
   نسبةٌ من الورقة. رقمان بوحدتين على نفس الجسم.
   والنتيجة إن **شكل الرزمة نفسه يتغيّر مع البوابة**: المكشوف من
   كل ورقة = الفرجة ÷ عرض الورقة، والفرجة تمشي مع المسرح والورقة
   تمشي مع النَفَس، فما يتساويان. المقيس على البناء اللي كان
   (‎node _probe/fan.mjs‎، ‎--o: -10 · 3 · 16‎):
     360×800 → ٤٥٫٦٪ من الورقة · 375×667 → ٥٦٫٧٪
     390×750 → ٥٣٫٠٪            · 390×844 → ٤٧٫٤٪
   أي رزمةٌ مضمومة على شاشة ومفرودة على ثانية — بلا ما يطلبها أحد.
   والسجلّ كان يعرف نصف هالعطب من الجولة ٤: التعليق عند
   ‎.tkfan>:last-child‎ يقول «بالنسبة المئوية ما كانت تنضبط… فالطرفان
   ما يلتقيان إلا على بوابة وحدة» — ونُقلت ورقةٌ وحدة للبكسل وبقيت
   الثلاث على النسبة.
   الآن الاثنتان من الورقة: ‎--t‎ كسرٌ من عرضها، و‎--o‎ نسبةٌ مئوية
   منه. فالرزمة شكلٌ واحد على كل بوابة، والفرجة تُقرا مباشرةً:
   «‎--o‎ ٦٨ يعني الأخت تكشف ٦٨٪ من أختها». */
.tkfan>*{position:absolute;top:calc(var(--bw) * var(--t,-.20));
  inset-inline-end:calc(var(--o,0) * var(--bw) / 100);
  --cw:var(--bw)}
/* ‎.tkcardface-graded‎ انحذفت (٢٠٢٦-٠٧-٢٨ · الجولة ٥). كانت أداة
   خفض إشباع لورقة وجه طرف ثالث (LGPL)، وتلك الورقة انأرشفت خارج
   ‎app_client/‎ في الجولة ٣ — فبقيت القاعدة بلا مستهلك جولتين، في
   *القالب*، حيث أي جولة جاية تقدر تمدّ يدها لها. وخفض الإشباع
   علاجٌ لعرَض لا لعلّة: إذا كان الجسم أعلى كروما من الشاشة كلها،
   يُستبدل الجسم — وهذا اللي صار فعلًا، صار ظهر تَك. أداةٌ ميتة في
   القالب أخطر من أداة ميتة في الكسوة. */

/* ============================================================
   ٨ · العلامة — «الحزّة»
   شريحة بنسبة ورقة بلوت مقلوبة (88:63)، محزوزة من ركنها الأعلى
   جهة البداية، محفوفة بحدّ نحاسي يضوي جهة المصباح ويغيب جهة
   الظل، و«تَك» فيها نحاسًا مصقولًا.

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

   درجة وحدة عميقة (٢١٪ من العرض)، مو درجتين: على ٣٦px الدرجتان
   ٥px لكل وحدة فتنمسخان قطريًّا. الوحدة تُقرا «مقصوصة» بكل مقاس.

   الفتحة U+064E حقيقية داخل الكلمة — ما فيه ولا خط مرسوم باليد.
   والكلمة كلها تُملأ بتدرّج نحاسي بـbackground-clip:text، فالفتحة
   لأنها أعلى حبر تقع تلقائيًّا بأنصع وقفة: قانون الشمس يشتغل وحده.

   خلوص الفتحة مهندَس مو مرجوّ: .w صندوق مرن align-items:center
   زائد padding-top صريح، فينزاح المركز البصري للأسفل — وهذا
   يحصّنه من ارتفاع صاعد أميري الزائد.
     hero  ١٢٣×٨٨ · Amiri 47/1.66 · pt 13
     badge  ٥٠×٣٦ · Amiri 19/1.66 · pt  6
   والخلوص نفسه — بالبكسل — **ما ينكتب هنا** (٢٠٢٦-٠٧-٢٨ · الجولة ٥):
   كان مكتوبًا في هذا الملف وحده مرّتين متناقضتين، ١١٫٧/٥٫٢ هنا
   و١٣٫٠/٦٫٠ بعد ثلاثين سطرًا، وثالثة ١٣٫٣/٥٫٨ في MOLD وKIT —
   ثلاثة أزواج لقياسٍ واحد، ولا واحد منها يقدر أحد يعيده: ما فيه
   مِسبار يطبع خلوص الفتحة. فالأرقام انحذفت كلها. اللي يبقى هو
   البناء اللي يضمن الخلوص (المرن + الحشوة الصريحة) والقانون
   تحته. ومن يبي رقمًا فليشحن رِجًّا يطبعه — والقاعدة من هالجولة:
   **رقمٌ ما يقدر أحد يولّده عيبٌ، صحّ أو غلط.**
   قانون: أقل ارتفاع للشريحة ٢٤px. تحتها الشريحة وحدها بلا كلمة —
   فتحة بحجم بكسل تُقرا وسخًا، وهذا أسوأ من غيابها.

   ملاحظة: clip-path:path() مطلق بالبكسل — ما يتمدّد مع العنصر.
   لأي مقاس جديد: عمق الحزّة N، رأس محدّب T=0.35N، داخلي C=0.31N،
   والمسار الداخلي بإزاحة i بأنصاف R−i / T−i / C+i.

   ---- الانقلاب، الجولة ٤ (٢٠٢٦-٠٧-٢٨) — ولا بكسل هندسة تحرّك ----
   العلّة مقيسة: العلامة كانت ثالث أعلى جسم على شاشتها هي. على
   تغبيش ٦px، وبقياس كل جسم مقابل *محيطه هو* (حلقة ١٤px حوله، لا
   وسيط أرضٍ عام — والعلامة تقعد في ركن المصباح حيث الجوخ أنصع
   ما يكون، فأي رقم عام يجاملها):
                        قبل            بعد
     العلامة : محيطها   1.495:1        **3.257:1**
     لمعة العلامة       0.08433        0.27465
     الزرّ الأساسي      0.36617        0.36617   (باقٍ أعلى ١٫٣٣×)
     الرزمة             0.41464        0.41464   (باقية أعلى ١٫٥١×)
     العلامة : اللوح    ‎—‎              2.125:1 (٢٫٦٧× لمعةً)
   ووجه الشريحة مقابل الطاولة، مسحًا لكل موضع (الوجه ٣px داخل
   مقابل السرير ١px برّا): أسوأ بكسل ١٫٠٠٢ → **٢٫٤٢١**، ووسيط
   ١٫٥٢٧ → **٤٫٤٧٨**.

   والكلمة انقلبت معها: حبرها الآن أغمق شي بالشريحة، ومقيس
   بالرندر الفرقي (رندران، واحد بالكلمة وواحد بالكلمة مُطفأة
   الملء، فالصفيحة تحت كل بكسل حبر معروفة بالضبط):
     الكلمة : الصفيحة  **٥٫٩٧٤:١** (أسوأ بكسل مُشبَع من ٤٢٠٨)
     وتحليليًّا (أنصع وقفة محرَّرة مقابل أنصع بكسل صفيحة تحت
     الحبر): **٦٫٢٢٧:١**.
   وخلوص الفتحة U+064E ما تحرّك — والرقم انحذف، انظر §٨ فوق:
   كان هنا زوجٌ ثالث يناقض الزوج المكتوب في نفس الملف وفي MOLD،
   ولا مِسبار يطبع أيًّا منها.

   وصراحة لازمة عن الحدّ النحاسي: هو **ما يخضع لقانون ٣:١**، لا
   قبل ولا بعد. مسحًا لكل بكسل: فوق ٤٫٤٦٣ · يمين ٢٫٠٠٧ · تحت
   ١٫٠٠١ · يسار ١٫٠٠٥ — لأن سلّم النحاس المصقول ينزل إلى ليله
   (--a-night) عند طرف الظلّ، وبكسل حدٍّ غامق على سرير غامق ما
   يوصل ٣:١ رياضيًّا (نفس الحقيقة الهندسية اللي بُني عليها
   --edge-floor). الفرق إن حدود الأدوات انتقلت لأرضية مضيئة،
   والعلامة ما تقدر: خيطها النحاسي *هو* الاستثناء المكتوب.
   واللي تغيّر إن حدّ الجسم ما عاد يقع على الخيط: الصفيحة نفسها
   صارت تحمل الحافّة (٢٫٤٢١ أسوأ بكسل بدل ١٫٠٠٢).
   ============================================================ */
.tkmark{position:relative;display:block;width:123px;height:88px;padding:0;border:0;
  background:linear-gradient(196deg,var(--a-sun) 0%,var(--a-pol) 15%,var(--a-brz) 40%,var(--a-shade) 72%,var(--a-night) 100%);
  clip-path:path("M 18,0 L 88,0 A 9,9 0 0 1 97,9 L 97,18 A 8,8 0 0 0 105,26 L 114,26 A 9,9 0 0 1 123,35 L 123,70 A 18,18 0 0 1 105,88 L 18,88 A 18,18 0 0 1 0,70 L 0,18 A 18,18 0 0 1 18,0 Z");
  filter:drop-shadow(-2px 3px 3px rgba(var(--sh-rgb),.55)) drop-shadow(-9px 14px 20px rgba(var(--sh-rgb),.60))}
.tkmark .face{position:absolute;inset:0;
  background:
    var(--lamp-catch),
    linear-gradient(196deg,var(--mark-face-hi) 0%,var(--mark-face) 46%,var(--mark-face-lo) 100%);
  clip-path:path("M 18,2 L 92,2 A 7,7 0 0 1 99,9 L 99,18 A 10,10 0 0 0 109,28 L 114,28 A 7,7 0 0 1 121,35 L 121,70 A 16,16 0 0 1 105,86 L 18,86 A 16,16 0 0 1 2,70 L 2,18 A 16,16 0 0 1 18,2 Z")}
.tkmark .w{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--fd);font-weight:var(--w-display);font-size:47px;line-height:1.66;
  /* محاذاة بصرية للحرف، مو مسافة تخطيط — فتبقى فيزيائية.
     صندوق الـflex يوسّط صندوق التقدّم، وحبر «تَك» بأميري ما هو
     موسّطًا داخله. الكلمة عربية دايمًا وما تنعكس أبدًا، فلو صارت
     padding-inline-end وانحطّت الشريحة داخل dir=ltr انقلبت الحشوة
     والحرف ما ينقلب — فينكسر التوسيط. نفس صنف إزاحات الضوء. */
  padding-top:13px;padding-right:8px;
  /* الكلمة انقلبت مع الصفيحة (الجولة ٤): حبر غامق محفور في مرج
     مضاء، بدل نحاس ناصع على وجه غامق. والوقفات من *الطرف الليلي*
     لسلّم النحاس المصقول لا من طرفه الشمسي — فالخيط باقٍ خيطًا،
     بس في الظل.
     ولماذا ما هي --a-shade نفسها: مقيسة تحليليًّا على الصفيحة
     الجديدة، أنصع وقفة يقدر يلبسها الحبر وهو محافظ على ٤٫٥:١
     فوق أنصع بكسل صفيحة لمعتُها ≤ ٠٫٠٣٠. و--a-shade عندها ٠٫٠٤٦٦
     فتعطي ٣٫٧٢ — تحت الأرضية. فمزجناها بحبر الورق: البرونز يبقى
     دافئًا (H≈٣٦) ويهبط تحت السقف. وهذي صراحة لازمة: **على صفيحة
     مضيئة كفاية عشان تكسب شاشتها، النحاس عند ٤٫٥:١ يصير برونزًا
     غامقًا — ما يبقى ذهبًا.** الذهب الباقي هو حدّ الشريحة نفسه،
     وهو الاستثناء المكتوب أصلًا. */
  background:linear-gradient(196deg,
    color-mix(in srgb,var(--a-shade) 55%,var(--ink)) 0%,
    color-mix(in srgb,var(--a-shade) 34%,var(--ink)) 30%,
    var(--ink) 66%,
    color-mix(in srgb,var(--ink) 76%,var(--a-night)) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  /* ولا ظلّ نصّ. الظلّ الغامق القديم (-1px 2px 3px) كان لحبرٍ
     ناصع على وجه غامق، وانقلب معناه. وجُرّب بداله حرف نور تحت
     الحبر مثل «الكلمة محفورة بالنحاس» على الزرّ الأساسي — ورُندر
     الاثنان جنب بعض على ١×: أميري ٤٧px حروفها رفيعة، والنسخة
     المضيئة المزاحة بكسلًا تاكل أسفل كل ضربة فتُقرا الكلمة
     مُغبَّشة ورماديّة بدل محفورة. الأنظف بلا ظلّ. مقيسة بالنظر
     على رندر ١× لا على مبدأ. */
  text-shadow:none}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .tkmark .w{background:none;color:var(--ink)}}   /* الاحتياطي ينقلب معها */
@media (forced-colors:active){.tkmark .w{background:none;color:CanvasText;forced-color-adjust:none}}

  /* فيزيائية بقصد — انظر أعلاه */

/* ---- اللوح المحزوز — البيت الثاني للحزّة، بمقاس كبير.
        نفس البناء: الغلاف يحمل الحدّ المتدرّج والظل (filter،
        لأن القصّ والقناع كلاهما يقصّ box-shadow)، والوجه بداخله
        بإزاحة ١٫٥px بنفس الشكل.

        الشكل ما عاد مسارًا مطلقًا. المسار كان مقفولًا على
        ٣٥٠×٤٢٠، فاللوح ما يقدر يتمدّد ولا يطول مع محتواه —
        وعلى ٣٦٠ كان ينزّ ٣٠px تحت القصّ ويصير ركنه حدًّا حادًّا.
        البناء الجديد ثلاث قطع، والاتحاد هو الافتراضي:
          ١ · الأركان الأربعة = border-radius عادي. ما ينمسخ
              مهما تغيّر العرض أو الطول، لأنه ما ينمط أصلًا.
          ٢ · الحزّة = قناع بمربّع ثابت ٥٨×٥٨px مثبّت على الركن
              الأعلى-يمين. مقاسه بالبكسل، فالحزّة تبقى ٤٤ عرضًا
              و٥٨ عمقًا على ٣٢٠ وعلى ٤٣٠ سواء — توقيع، مو نسبة.
          ٣ · مستطيلان يكمّلان بقيّة الجسم.
        القيم داخل المربّعين هي نفس أنصاف المسار القديم حرفًا
        بحرف: خارجي ١٤/١٢/١٤، وداخلي ١٢٫٥/١٣٫٥/١٢٫٥. مقيسة:
        الصندوق المرسوم مطابق للمسار القديم على ٣٥٠×٤٢٠. ---- */
/* عطب مقيس ومصلَّح (٢٠٢٦-٠٧-٢٨) — ورثناه من الجولة ١، وما هو من القناع:
   ترتيب الرسم في CSS هو filter ثم clip-path ثم mask. يعني الظلّ
   يتولّد أولًا ثم ينقصّ. فأي عنصر يحمل القصّ والظلّ *على نفسه*
   يفقد ظلّه الخارجي بالكامل. مقيسة بتجربة مضبوطة (_probe/clipshadow.html):
     صندوق عادي بظلّ ......... ٤٨٩٢ بكسل ظلّ
     نفسه + clip-path ......... صفر
     نفسه + mask .............. صفر
     غلاف يحمل الظلّ وابنه يحمل القناع ... ٤٨٩٢
   صفر يعني ما فيه ظلّ خارجي أصلًا. فاللوح كان قاعدًا مسطّحًا على
   الطاولة — وهذا بالضبط «فشل الارتفاع» اللي MOLD يسمّيه سبب «بيسك».
   والعلاج ما هو تغيير آلة الشكل (clip-path يسقط بنفس السقوط)، بل
   الطبقات: الجلد أخٌ للمحتوى لا أبٌ له — لأن الظلّ على أبٍ يسيل
   على كل زرّ بداخله. */
.tknotch{position:absolute;inset:0;z-index:0;pointer-events:none;
  --nt:58px;                                          /* ضلع مربّع الحزّة — ثابت بالبكسل */
  /* نصف قطر أركان اللوح = --r-sheet، ما هو رقمًا مكتوبًا باليد.
     كان ٢٦px مضبوطًا هنا بينما tokens.css §٥ وMOLD كلاهما يقول
     إن اللوح المحزوز «صحيفة» بنصف ٢٨ — والحشوة العليا مشتقّة
     من ٢٨ نفسها (--pad-rail = --r-sheet − --r-btn-1 = ١٠). يعني
     الرقم اليدوي كان يكسر تداخل الأنصاف المحفور بالـcalc:
     ٢٦ − ١٨ = ٨ لا ١٠. انصلح ٢٠٢٦-٠٧-٢٨ · الجولة ٤. */
  --nr:var(--r-sheet);
  --nt-o:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58 58'><path fill='white' d='M0 0A14 14 0 0 1 14 14V32A12 12 0 0 0 26 44H44A14 14 0 0 1 58 58H0Z'/></svg>");
  --nt-i:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58 58'><path fill='white' d='M4.5 0A12.5 12.5 0 0 1 17 12.5V30.5A13.5 13.5 0 0 0 30.5 44H45.5A12.5 12.5 0 0 1 58 56.5V58H0V0Z'/></svg>");
  filter:drop-shadow(0 1px 5px rgba(var(--sh-rgb),.55))               /* الحجب حول القاعدة */
         drop-shadow(-3px 5px 6px rgba(var(--sh-rgb),.50))
         drop-shadow(-12px 20px 30px rgba(var(--sh-rgb),.60))}
/* الحدّ المتدرّج — يُرسم خلفيّةً لا box-shadow، لأن القناع يقصّ الظلال.

   عطب مقيس ومصلَّح (٢٠٢٦-٠٧-٢٨ · الجولة ٤): هذا الحدّ كان **الرامب
   الخامس** في النظام، وما كان في جدول الحوافّ بـMOLD أصلًا — أكبر
   جسم بالشاشة، ساقطًا سهوًا من الجدول اللي يقول «أدناها ٣٫٢٥٩».
   وكان مبنيًّا على الشكل اللي ألغاه قانون الحافّة في الجولة ٣: نور
   ٤٠٪ فوق ينزل إلى ‎rgba(4,22,13,.55)‎ تحت. مقيسًا بمسح كل بكسل على
   المحيط كامل (‎_probe/a-edge.py‎، الحزّة مستثناة):
     تحت ١٫٠٠٠ · يسار ١٫٠٠٠ · يمين ١٫٠٠١ · فوق ١٫٣٥٧
   يعني ثلاثة حوافّ من أربعة بلا أي حدٍّ مقروء إطلاقًا.
   الآن على ‎--edge-floor‎ مثل بقيّة النظام: نور فوق، وأرضية ثابتة
   عند طرف الظلّ، وما ينزل تحتها أبدًا. */
.tknotch>.face{position:absolute;inset:0;
  background:linear-gradient(196deg, var(--lit-edge-hi) 0%, var(--lit-edge-mid) 24%,
                                     var(--lit-edge-lo) 54%, var(--edge-floor) 100%);
  -webkit-mask-image:var(--nt-o),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
          mask-image:var(--nt-o),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
  -webkit-mask-size:var(--nt) var(--nt),calc(100% - var(--nt)) 100%,var(--nt) calc(100% - var(--nt));
          mask-size:var(--nt) var(--nt),calc(100% - var(--nt)) 100%,var(--nt) calc(100% - var(--nt));
  -webkit-mask-position:right top,left top,right bottom;   /* فيزيائية — ما تنقلب بالـRTL */
          mask-position:right top,left top,right bottom;
  -webkit-mask-repeat:no-repeat;
          mask-repeat:no-repeat}
/* الوجه — نفس الشكل بإزاحة ١٫٥px، فالحدّ يبقى بعرض واحد حول الحزّة كلها.
   وهو اللي يحمل طرف الجسم المُظلَّل بعد ما ارتفع الحدّ فوق الأرضية:
   --rim-lo داخليًّا، تمامًا كما يفعل .tkledger::after المقنّع.
   والقناع يمحو الظلّ **الخارجي** وحده — الغائر ينرسم داخل الشكل
   ثم ينقصّ معه، فيبقى. مقيس على المركّب، مو مفترضًا (انظر التقرير). */
.tknotch>.face::after{content:"";position:absolute;inset:1.5px;
  box-shadow:var(--rim-lo);
  /* لقطة هادية لا كاملة (٢٠٢٦-٠٧-٢٨ · الجولة ٣): اللوح أكبر سطح
     مرفوع بالشاشة، ولقطة ٢٢٪ كانت ترفع ركنه الأعلى-يمين إلى لمعة
     ٠٫١٦٠ — وعندها *ما فيه حبر بالنظام* يقدر يعطي ٤٫٥:١ فوقه،
     ولا حتى --tx السادّ (مقيسة ٤٫٠٣). والرِّيل يقعد هناك بالضبط.
     السطوح الكبيرة تاخذ --lamp-catch-q، والأجسام الصغيرة تاخذ
     الكاملة: كل ما كبر السطح قلّت حصّته من نفس المصباح. */
  background:
    var(--lamp-catch-q),
    linear-gradient(196deg,var(--s-panel-hi) 0%,var(--s-panel) 44%,var(--s-panel-lo) 100%);
  -webkit-mask-image:var(--nt-i),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
          mask-image:var(--nt-i),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
  -webkit-mask-size:var(--nt) var(--nt),calc(100% - var(--nt)) 100%,var(--nt) calc(100% - var(--nt));
          mask-size:var(--nt) var(--nt),calc(100% - var(--nt)) 100%,var(--nt) calc(100% - var(--nt));
  -webkit-mask-position:right top,left top,right bottom;
          mask-position:right top,left top,right bottom;
  -webkit-mask-repeat:no-repeat;
          mask-repeat:no-repeat}

/* ============================================================
   ٨٫٥ · الطاولة الصغيرة — سطرٌ يقول مين على الطاولة

   الجولة ٧ · ٢٠٢٦-٠٧-٢٩ — الصورة انشالت والخبر بقي. حكم صاحب
   البيت على الورقات الأربع الصغار اللي كانت تحفّ السطر: «هذي ما
   تبيّن زينة، شيلها — تقدر تكتب هنا شي». فانشالت، وما انبدلت
   بعلامةٍ ثانية: لا نقطة ولا شرطة ولا حرف يقعد مقعد الورقة.
   والصفّ صار جملةً واحدة: أنت وخويّك ضد سيكل وخويّه.

   والصورة هنا سقطت مرّتين قبل الحكم، وهذا هو السبب المقيس اللي
   يخلّي هذا الصفّ كلامًا ولا يرجع رسمًا:
     · الجولة ٣ — أربع علامات صغار مصفوفة محوريًّا تُقرا اصطلاح
       «مربّع الاختيار»: ☑ أنت ☑ خويّك ضد ☐ سيكل ☐ خويّه.
     · الجولة ٤ — انبدلت بورقات مقلوبة مايلة عشان الميل يكسر
       الاصطلاح. وانكسر فعلًا، بس صارت أربع ورقات بمقاس همسة على
       شاشةٍ فيها ورقٌ كبير أصلًا، وكل واحدة تطلب حدًّا متدرّجًا
       وخيطًا وثلاث طبقات قصّ وماسحًا مايلًا يخصّها وحدها.
   الأولى بدّلت اصطلاحًا باصطلاح، والثانية اشترت الشكل بثمنٍ يطلب
   رِجًّا يقيسه. والثالثة — الكلام — ما لها ثمن من هذا النوع:
   الجملة تقول «اثنان مقابل اثنين» بالنحو، الواو تجمع كل خويّين
   و«ضد» تفصل اليدين. ولهذا **انحذف قانون الفرج** (بين اليدين ≥
   ضعف داخل اليد، على كل بوابة) ومعه فرجة اليد وspace-between
   والمسارب الثلاثة: ما عاد فيه فرجٌ يحمل المعنى، فما فيه فرجٌ
   ينعاير ولا ينكسر على بوابة ضيّقة.

   والحبر --tx السادّ، ولا --tx2 هنا: الرِّيل يقعد على الركن
   الحارّ من اللوح، وهناك ما فيه إلا السادّ يعطي ٤٫٥:١. (وهدوء
   جهة سيكل كان يعيش في وجه ورقته ومقاسها وميلها؛ وراحت الورقة،
   فما بقي شي يهدّي — والاسم يُقرا مثل أخوانه، وهذا أصدق.)
   الرِّج: **_probe/a-ink.py** — يُعاد قبل أي ادّعاء.

   والمقاس 1rem والرفعة ١٫٧٥ — لا ١٦px ولا ١٫٥٥: جذر النظام
   html{font-size:112.5%} في tokens.css §٧-ب، والـrem هي اللي
   توصّل الرفعة العربية للزجاج وتوصّل معها مقاس متصفّح القارئ؛
   ورقمٌ مطلق هنا يبطّلهما. و١٫٧٥ رفعة كل سطر سند بالنظام
   (.tkfield-lb و.tkledger .k و.tkb-stack .sub) فما لها استثناء.

   والأسماء داخل <bdi> دايم — «سيكل» اسمٌ يجي من الخادم، والعزل هو
   اللي يخلّي اسمًا لاتينيًّا يقعد جنب العربي بلا ما ينقلب ترتيب
   الجملة. والمعنى يوصل للجميع بنفس الطريق: النصّ نفسه يقول مين
   على الطاولة وإنهم اثنان مقابل اثنين، فما فيه شي ينوصل بالصورة
   وحدها عشان يحتاج بديلًا في aria. وrole=group مع اسمه إطارٌ
   للسطر لا حاملٌ للمعنى.

   ولا نحاس هنا ولا خيط: النحاس محرّم على أي شي ما ينضغط، و--kh
   رجع لبيتٍ واحد — ظهر تَك في الرزمة — يوم راحت ظهور المقاعد.

   ---- المقيس · الرِّج هو المرجع، لا هذا التعليق ----
   ما ينقاس برِجٍّ يعيش في _probe/ ما ينكتب هنا رقمًا.

   ١ · الرفّ تحت لسان الحزّة — أرضية الرِّيل مشتقّة من العدّة:
       min-height = ‎--pad-notch − --pad-rail‎ = ضلع الدرجة
       ‎--notch-step‎. فالشرط ‎--pad-rail + الرِّيل ≥ --pad-notch‎
       ينمسك **بالبناء**: لو ضمر المحتوى إلى سطرٍ واحد فالأرضية
       هي اللي تمسك الرفّ، ولو طال زاد الخلوص ولا نقص. والقاعدة
       في MOLD حدٌّ أدنى لا مساواة — «الزيادة مسموحة، والنقص لا».
       وهذي هي الشعرة اللي نجا منها هذا التغيير، وتستاهل تنكتب:
       **الكود كان صحيحًا والشرح كان غلط.** الـmin-height المشتقّة
       شاحنة من الجولة ٤، لكن النصّ اللي تحتها كان يبرّر الرفّ
       بمحتواه — «الرِّيل = ورقة (--sw × ٨٨/٦٣) + سطر اسم، والشرط
       محفوظ بفارق واسع» — يعني يعلّق القانون على جسمين صاحب البيت
       شالهما في هذي الجولة. لو كان القارئ صدّق الشرح وشال معهما
       الأرضية، وقع الرفّ وما اشتكى حارس. **والتبرير الغلط أعمر من
       القيمة الغلط:** القيمة تنقاس فتنكشف، والتبرير يُقرا فيُصدَّق
       ويُعاد بناء العطب عليه. فالشرح الآن يقول اللي يقوله الكود:
       الأرضية من العدّة، والمحتوى ضيف عليها.
   ٢ · الخلوص الأفقي عن لسان الحزّة، اشتقاقًا لا نقلًا:
       padding-right = ‎--pad-notch − --pin-inline‎، فحافّة المحتوى
       اليمنى تقعد على بُعد ‎--pad-notch‎ من حافّة اللوح، أي
       ‎--pad-rail‎ داخل ضلع العضّة ‎--notch-step‎. و--pin-inline
       مرآة حشوة .pin الجانبية، ومكتوبة في الجلد جنب الحشوة نفسها
       (styles/tak.css) لأن بيتها هناك — فما فيه في المكوّن رقم
       خلوصٍ مكتوب باليد يتعتّق يوم تتحرّك الحشوة. وأرضيتها 0px:
       الجهل يعطي خلوصًا أوسع، والأوسع مسموح.
       وهي padding-right فيزيائية لا padding-inline-end: العضّة
       قناع مثبّت على right top وما ينقلب بالـRTL.
   ٣ · الهروب والقصّ — السطر يلفّ ولا ينقصّ: ما فيه nowrap ولا
       text-overflow ولا overflow على هذا الصندوق. اللي ما يسع
       ينزل سطرًا ثانيًا، والأرضية تحتمله والصفحة تدفع طوله؛ وما
       ينقصّ بالنقاط ولا يطلع على الطاولة. (والقصّ القديم — nowrap
       مع ellipsis على <bdi> — انحذف معاه: كان يحرس مسربًا، وما
       عاد فيه مسارب. وهو نفسه كان ينقصّ «سيكل» على ٣٢٠ بفارق
       أقلّ من بكسل — عيبٌ راح مع المسارب.) وoverflow:hidden محرّم
       على الحاويات العربية لأنه يقصّ التشكيل، وما فيه منه هنا حرف.
       **وموضع الكسر منصوص، مو متروك للجشع:** فرجةٌ وحدة تنكسر —
       اللي بين اليدين — والباقي &nbsp; في index.html. ولو انتركن
       كلهن، لفّ المتصفّح عند آخر فرجة تسع فطلع «أنت وخويّك ضد
       سيكل / وخويّه»: شقٌّ *داخل* اليد و«وخويّه» يتيمة. وبالنصّ
       يجي اللفّ على حدّ الفريقين: «أنت وخويّك / ضد سيكل وخويّه».
       الرِّج: **_probe/a-rects.html?w=&h=&sel=.tkseats** —
       يلزم STABLE=true، وOVERFLOW_X صفر، ولا .tkseats في BLEED_X،
       وطول الصندوق يقول كم سطرًا انلفّ (سطر = 1.75rem، وأرضية
       الصندوق ٤٤ فما تحتها ما يبان).
       والمقيس بنفس الأمر (٢٠٢٦-٠٧-٢٩): البوابات الأربع
       (٣٦٠×٨٠٠ · ٣٧٥×٦٦٧ · ٣٩٠×٧٥٠ · ٣٩٠×٨٤٤) كلها سطرٌ واحد
       والصندوق ٤٤٫٠٠؛ وأضيقها فسحةً ٣٦٠. و?w=334 يسع بسطر
       و?w=332 يلفّ — فحدّ اللفّ بينهما، وهو تحت أضيق بوابة
       مشحونة. وعلى ٣٢٠ يلفّ سطرين (٦٣٫٠٠) — ولفٌّ نظيف أشرف من
       قصٍّ، وهذي البوابة أصلًا تحت أرضية المشروع بتمرير مقيس.
   ٤ · وثمن الطول: كل بكسل يطوله الرِّيل فوق أرضيته ياخذه من
       أرضية الطول المتاح للصفحة بلا تمرير، بكسلًا ببكسل.
       الرِّج: **_probe/gates.html?gates=390xH,…** — يطبع التمرير
       المقيس تحت كل إطار، وبـ‎?sa=‎ ينقاس على الطول المتاح.
   ٥ · الحدّ — ما عاد في §٨٫٥ جسمٌ يلبس حدًّا متدرّجًا: الورقات
       الأربع كانت الوحيدة، وراحت معها أربعة صفوف من OBJECTS في
       _probe/a-edge.py وماسح الظلّ المايل كلّه. السطر نصّ، والنصّ
       يُقاس بالحبر لا بالحدّ.
   ============================================================ */
/* السطر — صندوقٌ واحد بلا شبكة ولا مسارب. والأرضية هي رفّ الحزّة،
   والسطر يقعد في أعلاها طبيعيًّا: مع حشوة .pin العليا (--pad-rail)
   يطلع مركزه البصري داخل نطاق اللسان (٠..--notch-step) بلا توسيطٍ
   مكتوب. وتوسيطه في الرفّ ينزّله تحت مركز اللسان لا فوقه، فالطبيعي
   أصدق من المعاير — ومع ذلك ما فيه هنا رقم: الرفّ والحشوة كلاهما
   مشتقّ. */
.tkseats{min-height:calc(var(--pad-notch) - var(--pad-rail));
  padding-right:calc(var(--pad-notch) - var(--pin-inline,0px));
  font-weight:var(--w-support);font-size:1rem;line-height:1.75;color:var(--tx)}

/* ============================================================
   ٩ · الدفتر — نفس الفكرة، ومادة جديدة. سطح الطاولة، مو ورقة
   معتّقة: التعتيق تحلّل، والتحلّل يُقرا أرشيفًا.
   الأرقام غربية دايم — حكم صاحب البيت.
   ============================================================ */
/* عطبان مقيسان ومصلَّحان (٢٠٢٦-٠٧-٢٨ · الجولة ٣):
   ١ · الدفتر كان تعبئة متدرّجة + شعرات داخلية، بلا أي حدّ متدرّج —
       وهو البناء الوحيد اللي تحرّمه ترويسة هذا الملف بالحرف
       («تعبئة مسطّحة + شعرة + غائر خافت على مستوى واحد»).
       الآن ياخذ الحدّ الحقيقي: جلد مقصوص يحمل التدرّج، ووجهٌ
       بإزاحة ١٫٥px فوقه — نفس بناء اللوح المحزوز.
   ٢ · الدفتر كان السطح الكبير الوحيد بأركان سادّة. الثلاثة
       أسطح لازم تتكلّم نفس اللغة، فانتقلت له الحزّة بدرجة
       أصغر — الدفتر عريضٌ قصير، والدرجة ٥٨ تاكل ربع طوله.
       والمقاس ما ينكتب هنا: هو مكتوب مرّةً وحدة تحت،
       ‎--nt‎ على ‎.tkledger‎ نفسها. (كان مكتوبًا هنا «٣٦ بدل ٥٨»
       والمشحون ٣٢ — رقمٌ واحد في مكانين، والشرح هو اللي غلط.
       أُصلح ٢٠٢٦-٠٧-٢٨ · الجولة ٥.)
   الجلد أخٌ للمحتوى لا أبٌ له: ::before و::after إخوة لـ.lg-head
   و.lg-cells داخل نفس الصندوق. القناع يمحو box-shadow، فالظلّ
   الخارجي ينحمل بـfilter:drop-shadow على الجلد نفسه — لو انحطّ
   على .tkledger لسال على المحتوى، ولو انحطّ box-shadow على الجلد
   لانمحى بالقناع. مقيسة في §٨. */
.tkledger{position:relative;border-radius:var(--r-plate);padding:16px 20px 18px;
  --nt:32px;                                          /* ضلع مربّع الحزّة — ثابت بالبكسل. عضّة ٢٤٫٣×٢٤٫٣ */
  --bite:calc(var(--nt) * 44 / 58);                   /* ضلع العضّة نفسها — مشتقّ، ما ينكتب بيده */
  --lg-gap:10px;                                      /* فرجة الأعمدة، والفاصل يعيش في نصّها */
  --nr:var(--r-plate);
  --nt-o:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58 58'><path fill='white' d='M0 0A14 14 0 0 1 14 14V32A12 12 0 0 0 26 44H44A14 14 0 0 1 58 58H0Z'/></svg>");
  --nt-i:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58 58'><path fill='white' d='M4.5 0A12.5 12.5 0 0 1 17 12.5V30.5A13.5 13.5 0 0 0 30.5 44H45.5A12.5 12.5 0 0 1 58 56.5V58H0V0Z'/></svg>")}
.tkledger>*{position:relative;z-index:1}
.tkledger::before,.tkledger::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  -webkit-mask-size:var(--nt) var(--nt),calc(100% - var(--nt)) 100%,var(--nt) calc(100% - var(--nt));
          mask-size:var(--nt) var(--nt),calc(100% - var(--nt)) 100%,var(--nt) calc(100% - var(--nt));
  -webkit-mask-position:right top,left top,right bottom;   /* فيزيائية — ما تنقلب بالـRTL */
          mask-position:right top,left top,right bottom;
  -webkit-mask-repeat:no-repeat;
          mask-repeat:no-repeat}
/* الجلد — الحدّ المتدرّج، ويحمل الظلّ الخارجي كامل */
.tkledger::before{
  background-image:var(--edge);
  -webkit-mask-image:var(--nt-o),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
          mask-image:var(--nt-o),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
  filter:drop-shadow(0 1px 4px rgba(var(--sh-rgb),.50))
         drop-shadow(-3px 5px 6px rgba(var(--sh-rgb),.48))
         drop-shadow(-10px 17px 26px rgba(var(--sh-rgb),.56))}
/* الوجه — نفس الشكل بإزاحة ١٫٥px، فالحدّ يبقى بعرض واحد حول الحزّة كلها */
/* واللقطة هنا **الهادية**، مثل اللوح بالضبط، وهذا قانونٌ قديم طبّق
   على سطحٍ جديد لا استثناءٌ له (٢٠٢٦-٠٧-٢٩ · الجولة ٧):
   القانون مكتوب فوق عند ‎.tknotch>.face::after‎ — «السطوح الكبيرة
   تاخذ ‎--lamp-catch-q‎، والأجسام الصغيرة تاخذ الكاملة: كل ما كبر
   السطح قلّت حصّته من نفس المصباح». والدفتر كان شريطًا منطويًا على
   سطرٍ واحد، فكان جسمًا صغيرًا بحقّ. وبهذي الجولة صار لوحًا بسطرين
   و«دفترك» انتقل إلى ركنه **الأعلى-يمين** — أي إلى بؤرة اللقطة
   نفسها، وهي بالضبط الحالة اللي انكتب لها القانون.
   والثمن انقاس قبل ما ينصلح: «دفترك» على اللقطة الكاملة يعطي
   ‎4.471:1‎ — **تحت أرضية الحبر ٤٫٥** — وهو ‎--tx‎ السادّ، أي أسطع
   حبرٍ بالنظام، فما فيه حبرٌ يعلو عليه ينقذه. العلاج في السطح لا
   في الحبر، تمامًا كما انتهى إليه اللوح في الجولة ٣.
   الأمر اللي يعيد الرقمين: انظر MOLD §الحبر. */
.tkledger::after{inset:1.5px;border-radius:calc(var(--nr) - 1.5px);
  box-shadow:var(--rim-lo);
  -webkit-mask-image:var(--nt-i),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);
          mask-image:var(--nt-i),linear-gradient(#fff,#fff),linear-gradient(#fff,#fff)}
/* الحزّة تاكل من الركن الأعلى-يمين فيزيائيًّا، والعنوان يقعد
   هناك بالضبط في RTL. الخلوص فيزيائي لأن الشكل فيزيائي:
   padding-right لا padding-inline-end. نفس صنف .tkmark .w.
   والمقدار مشتقّ من --bite، ما هو رقمًا مكتوبًا: لو تحرّكت --nt
   يتحرّك الخلوص معها. العنوان صار سطرًا فوق الأعمدة (§الكسوة)،
   فصار داخل نطاق العضّة رأسيًّا — والخلوص هنا هو اللي يمنعه
   يطلع في الهوا المقصوص. */
.tkledger .lg-head{display:flex;align-items:center;gap:12px;
  padding-right:calc(var(--bite) + 8px)}
/* --ty-plate ياخذ ١٫٥٥ سطرًا، وهي رقعة صحيفة لا رأس شريط. العنوان
   هنا سطر واحد بكلمة واحدة، فالسطر ينضمّ على الكلمة والفرق ينزل
   للأعمدة تحت — والرقعة ما تنقصّ بالـline-height، تنقصّ بالقصّ،
   وما فيه قصّ. */
.tkledger h2{margin:0;font:var(--ty-plate);line-height:1.06;color:var(--tx)}
.tkledger .lg-hr{flex:1;height:1px;background:linear-gradient(270deg,rgba(var(--lit-rgb),.26),rgba(var(--lit-rgb),0))}
/* ثلاثة أعمدة متساوية بالبناء، مو بالرجاء: شبكة ١fr×٣ تاخذ عرض
   الصحيفة كامل. و1fr = minmax(auto,1fr)، يعني العمود ما ينزل
   تحت محتواه الأدنى أبدًا — فلمّا يكبر خطّ القارئ، العمود العريض
   ياخذ حقّه والعمودان الباقيان يردّان الفرق، والصفّ يبقى صفًّا.
   وما فيه lg-cells{flex:0 1 auto} يقيس نفسه على محتواه ويخلّي
   الفاضي كله بطرفٍ واحد. */
.tkledger .lg-cells{display:grid;grid-template-columns:repeat(3,1fr);
  column-gap:var(--lg-gap);align-items:end;margin-block-start:10px}
/* عمودٌ مرن لا صندوق نصّ، وهذا مقيس: ‎.tkink‎ عنصر inline-block،
   فلو كان العمود صندوق نصٍّ لقعدت على خطّ القاعدة وجرّت معها
   نزول السطر — فيطول عمود «رقمك» عن جارَيه ويطلع «٥٨٪» أعلى من
   «١٢٨» و«٧٤». المرن يبلّك العنصر فيقصّ الذيل. */
.tkledger .lg-cell{display:flex;flex-direction:column;align-items:center;
  text-align:center;position:relative}
/* الفاصل يعيش في نصّ الفرجة، لا على حافّة العمود. وهذا هو اللي
   يخلّي دايرة القلم ما تركب عليه بالبناء: أقصى ما يوصله المحتوى
   حافّةُ عموده، فيبقى بينه وبين الخيط نصفُ فرجة مهما ضاق العمود. */
.tkledger .lg-cell+.lg-cell::after{content:"";position:absolute;top:4px;bottom:4px;
  inset-inline-start:calc(var(--lg-gap) / -2);width:1px;
  background:linear-gradient(180deg,rgba(var(--tx-rgb),0),rgba(var(--tx-rgb),.13),rgba(var(--tx-rgb),0))}
.tkledger .n{display:block;font-family:var(--fu);font-weight:var(--w-lead);font-size:1.6875rem;line-height:1.25;
  color:var(--tx);font-variant-numeric:tabular-nums lining-nums}
/* ١٫٧٥ باقية، وهي رفعة كل سطر سند بالنظام (§٨٫٥ يسمّيها). جُرّب
   تنزيلها إلى ١٫٥ يوم انضاف سطر العنوان — تشتري ٤٫٥px من طول
   الشريط — وانرفض: رفعتان لسطر السند تعني قانونًا واحدًا في
   ملفَّين بنصّين، وهو العطب اللي انسمّى بهذا المشروع ثلاث مرّات.
   والطول انشترى من الحشوة والهامش، لا من الرفعة.
   والرصاصة اللي تحت الحرف (٠٫٣٧٥ من المقاس) هي اللي يقعد عليها
   أسفل دايرة القلم، و--ink-b صفر لأجلها. */
.tkledger .k{display:block;font-family:var(--fu);font-weight:var(--w-support);font-size:1rem;line-height:1.75;color:var(--tx3)}
/* دايرة الحبر — العقيق، هنا فقط وعلى هالرقم وحده.
   مرسومة سكونًا، بلا حركة: هذي علامة على رقم، مو فرحة طاولة.
   والشاشة عندها نبضة خمول وحدة — لمعة الزر الأساسي — ولا زيادة.
   وحبر يعتمد وجوده على أنيميشن ممكن ما تشتغل = عيب، مو صنعة.

   الهندسة صارت مربوطة بالصندوق، مو مقاسًا مطلقًا: الـsvg ينشدّ
   على صندوق الرقم بهامش صريح لكل جهة (--ink-t/b/s/e)، وviewBox
   ١٠٠×١٠٠ بـpreserveAspectRatio:none. فالهامش متساوٍ عند أي مقاس
   خطّ وأي عرض رقم، و«٥٨٪» ما تنقصّ من فوق ولا يركب الحبر على
   علامة النسبة. عرض القلم ثابت بالشاشة بـnon-scaling-stroke،
   فالمطّ ما يسمّن الخط في محور دون الآخر.

   والحبر جسم على سطح مضاء: يلقّط المصباح فوق-يمين بتدرّج على
   القلم نفسه، ويرمي ظلًّا خفيفًا يسار-تحت. مطفي — ولا وهج. */
/* الهامش الجانبي صار حشوةً، مو إزاحةً سالبة (٢٠٢٦-٠٧-٢٩ · الجولة ٧)،
   والفرق بينهما هو الفرق بين «تنضبط بالضبط» و«تنضبط بالبناء»:
   الـsvg مطلق، فما يدخل في حساب مقاس العمود الأدنى. يعني الشبكة
   ما «تعرف» بالدايرة أصلًا، فتقدر تضيّق العمود تحتها — وهذا اللي
   كان يصير: على جذر ٢٤ ينضغط عمود «رقمك» لأن «قامت لك» تاخذ
   حقّها، فتعبر الدايرة الفاصل. والخلوص ما ينشرى بتصغير الدايرة:
   على رندر ٤× (‎a-shot.html?w=390&h=844‎ ثم ‎a-crop.py‎) الحلقة
   تمرّ ملاصقةً لـ«٪»، فأي نزول في الهامش يخلّي القلم يشطب الرقم.
   العلاج إن .tkink تحمل الهامش حشوةً على نفسها، فمقاسها الطبيعي
   = الرقم + الهامشين = عرض الدايرة. عندها العمود ما ينزل تحت
   الدايرة أبدًا، وأقصى ما توصله الدايرة حافّةُ عمودها — والفاصل
   يقعد في نصّ الفرجة، فيبقى بينهما نصف فرجة مهما ضاق العمود.
   الباقي الوحيد هو انتفاخ الصندوق المحيط من الميلان (٤°)،
   وهو نصف طولِ الدايرة × جيب ٤ — يطبعه ‎node _probe/ledger-fit.mjs‎
   في عمود clear مع كل خانة. */
.tkink{position:relative;display:inline-block;
  padding-inline:var(--ink-s) var(--ink-e);
  --ink-t:8px;--ink-b:0px;--ink-s:10px;--ink-e:10px}
/* المقاس مكتوب صراحةً، مو auto: الـsvg عنصر مُستبدَل، وإذا كان
   مطلقًا بأربع إزاحات وعرضه وطوله auto فالمتصفّح يحلّهما من نسبة
   الـviewBox (١:١) لا من صندوق الإزاحات — فتطلع الدايرة مربّعًا
   يبلع الكلمة تحته. والنسب هنا تنحلّ على صندوق الحشوة لأن الأب
   هو الحاوي: ‎100%‎ عرضًا = الرقم + الهامشين بالضبط. */
.tkink svg{position:absolute;pointer-events:none;overflow:visible;
  inset-block-start:calc(var(--ink-t) * -1);
  inset-inline-start:0;
  width:100%;
  height:calc(100% + var(--ink-t) + var(--ink-b));
  transform:rotate(-4deg);transform-origin:50% 50%;
  filter:drop-shadow(-1px 2px 1.5px rgba(var(--sh-rgb),.55))}
.tkink svg path{fill:none;stroke:url(#tk-ink);stroke-width:2.4;stroke-linecap:round}
@supports not (color:paint(x)){}
.tkink svg .lg-a{stop-color:var(--aqeeq-sun)}
.tkink svg .lg-b{stop-color:var(--aqeeq-lit)}
.tkink svg .lg-c{stop-color:var(--aqeeq-dim)}

/* ============================================================
   ١٠ · الدخول — الردهة تتركّب بنفسها في ~٥٠٠ms
   ٥ عناصر (i = ٠..٤) × ٥٥ms تدرّج + ٢٨٠ms = ٥٠٠ms.
   السلسلة متّصلة: ما فيه رقم مقفول. كان i=3 فاضيًا فيصير
   بالسلسلة فراغ ١١٠ms — الردهة تتوقّف ثم تكمل. انصلح ٢٠٢٦-٠٧-٢٨.
   آمنة الفشل بثلاث طرق: الحالة المستقرّة مكتوبة على .tkin نفسه،
   والحركة محبوسة خلف .js اللي يضيفه السكربت، وخلف تفضيل الحركة.
   لو ما اشتغل شي — المحتوى ظاهر.
   ============================================================ */
.tkin{opacity:1;transform:none}
@keyframes tk-rise{from{opacity:0;transform:translateY(14px) scale(.94)}to{opacity:1;transform:none}}
@keyframes tk-rise-tilt{from{opacity:0;transform:translateY(18px) rotate(var(--rot,-8deg)) scale(.94)}
                        to{opacity:1;transform:rotate(var(--rot,-8deg))}}
@keyframes tk-sweep{0%{background-position:180% 0}17%{background-position:-80% 0}100%{background-position:-80% 0}}

@media (prefers-reduced-motion:no-preference){
  .js .tkin{animation:tk-rise var(--t-enter) var(--ease-out) both;
    animation-delay:calc(var(--i,0) * 55ms)}
  /* نبضة الخمول الوحيدة بالشاشة — على الفعل الأساسي فقط.
     ٨٨٤ms عبور كل ٥٫٢s. بيضا دايم: ذهبي يلمع بالدوران يُقرا معدنًا. */
  .js .tkb-1::after{animation:tk-sweep 5.2s linear 1200ms infinite}
}
@media (prefers-reduced-motion:reduce){
  .tak *,.tak *::before,.tak *::after{animation:none!important;transition:none!important}
  .tkin{opacity:1!important;transform:none!important}
  .tkb-1::after{background-position:-80% 0}
}

/* ---- خطّافات اللقطة: .is-hover / .is-focus / .is-active تفرض
        حالة للتصوير بلا متصفّح تفاعلي. خاملة في الإنتاج. ---- */

/* علامة سيكل — صورةٌ بلونها، لا قناع.
   القاعدة المكتوبة هنا سابقًا («العلامة جسمٌ يلوّن بالسياق») تنطبق
   على ختم تَك: حبرٌ واحد يرث. وعلامة سيكل حبران — ذهبٌ للورق،
   وبنفسجيٌّ للوكيل. والبنفسجي ٥٫٦٪ من حبر العلامة: هو **الغمزة**
   نفسها، فلو ورّثناها ‎currentColor‎ انطفت الإشارة وصار المرسوم
   ورقتين بلا ساكن. فالعلامة هنا ثابتٌ من الهوية لا حبرٌ في نظام،
   وتُقرأ من الأصل الشفّاف كما هو — والدليل مكتوب في README:
   «do not regenerate or redraw the mark». */
/* (كان: قناعٌ لا صورة.
   ‎<img>‎ ما ترث ‎currentColor‎: تطبع لونها وتسكت. القناع يخلّي البكسل
   شكلًا، واللون يجي من السياق — فتبقى العلامة «جسمًا في النظام يلوّن
   بالحبر»، وهو الشرط اللي انكتب يوم أُدمجت العلامة الأولى.
   النسبة مكتوبة لأن ‎<span>‎ ما له نسبة ذاتية مثل ‎<svg viewBox>‎؛
   وبدونها ‎height:auto‎ ينزل صفرًا وتختفي العلامة. */
.tkmark-img{aspect-ratio:512/499;height:auto;
  }

/* ==========================================================================
   Part 2: formerly styles/tak.css
   ========================================================================== */

/* ============================================================
   تَك — كسوة التطبيق · بوابة ١: الديوانية (جوال أولًا)

   هذا الملف يملك **الهندسة السائلة** وحدها: وين يقعد كل جسم،
   وكيف يتنفّس الإيقاع الرأسي مع طول الشاشة، وميزانية الحافّة
   الآمنة، وأي سلّم ينحسب من النَفَس ‎--g‎ — بما فيه سلالم الكسوة
   السائلة، مكتوبةً ‎clamp()‎ وبالـrem فترث رفعة الجذر العربية.
   وما يملك ولا صبغةً ولا نورًا ولا وزنًا ولا نصف قطر ولا **أي
   مقاس مطلق**: ولا ‎#hex‎، ولا ‎rgba()‎، ولا ‎box-shadow‎، ولا
   ‎drop-shadow‎، ولا ‎font-weight‎، ولا ‎border-radius‎، ولا مقاس
   نصٍّ ثابت بالبكسل. هذي كلها من العدّة أو ما توجد.

   (تصحيحان ٢٠٢٦-٠٧-٢٨. الأول: كان مكتوبًا «لا يملك ولا قيمة
    تصميمية» والملف يحمل ٢٨px و٧٠٠ وظلَّ نصٍّ وظلَّين بالبكسل
    وتدرّجًا نحاسيًّا يتيمًا. والثاني، الجولة ٤: انصلحت الجملة
    إلى «ولا مقاس نصّ» — وشُحنت ثلاثة مقاسات نصّ هنا. الجملة
    انكسرت مرّتين لأنها كانت تمنع ما لا يُمنع. الآن الحدّ مكتوب
    كما يقدر البناء أن يحقّقه: الهندسة السائلة ملك الكسوة —
    وحدها هي اللي تعرف طول الشاشة — والصبغة والضوء والوزن
    والنصف والمقاس المطلق ليست ملكها أبدًا.)

   هو خمسة أشياء:
     ١ · يستورد القالب — design/tak/tokens.css ثم components.css
     ٢ · يربط فتحات الصور (--im-*) لأن القالب ما يعرف وين الخامات
     ٣ · يركّب صفحة الديوانية من مكوّنات القالب
     ٤ · يمسك الإيقاع الرأسي السائل (--g) وميزانية الحواف الآمنة
     ٥ · السلالم السائلة اللي تربط الكسوة بالنَفَس

   ورفعة الجذر ما تعيش هنا: بيتها tokens.css §٧-ب، ومكتوبة
   **نسبةً** على جذر القارئ لا رقمًا بالبكسل.

   فالمسار كامل ومتتبَّع، والاتجاه واحد ولا ينعكس:
     design/tak/tokens.css → components.css → styles/tak.css
     → index.html
     وkit/tokens.json يُولَّد **من** tokens.css، ما هو مصدرًا لها.
     (كان مكتوبًا هنا العكس — kit/tokens.json أولًا — وهو نفس
      فخّ الأولوية اللي أعلن السجلّ إغلاقه ثلاث مرّات. انصلح
      ٢٠٢٦-٠٧-٢٨ · الجولة ٤. المولّد:
      node design/tak/gen-tokens-json.mjs --write)
   ============================================================ */

/* ---------- ربط الخامات ----------
   عطب مقيس (٢٠٢٦-٠٧-٢٨): الـurl() جوّا خاصيّة مخصّصة ينحلّ نسبةً
   للملف اللي *يستعملها*، مو اللي يعلنها. فـ--im-weave معلنة هنا
   ومستعملة في design/tak/components.css، فكانت تنحلّ إلى
   design/assets/weave-night.jpg — أي ٤٠٤. الجوخ ما انعرض ولا مرّة
   واحدة من يوم ما انبنت الردهة، والأرض اللي شفناها كانت لون اللوح
   والمصباح وحدهما. ولهذا انقرأت «تدرّج أخضر سادّ».
   الحلّ: القاعدة اللي تستعمل الفتحة تعيش هنا، جنب الإعلان. */
.tak{--im-back:url("../assets/back-v7-bone.jpg")}
.tk-ground{background-image:var(--im-weave),
                           linear-gradient(var(--weave-plate),var(--weave-plate))}
/* ونفس العطب كان قاعدًا على ظهر الورقة يومًا كامل بعد ما انصلح
   الجوخ: ‎--im-back‎ انعلنت هنا وانستُعملت في
   ‎design/tak/components.css‎، فانحلّت إلى ‎design/assets/back-v3.jpg‎
   — مجلّدٌ ما هو موجودًا. مقيسًا: ‎node _probe/fan.mjs‎ يطبع
   ‎HTTP 404‎ على الرابط المحلول، وemb% = صفر على الأربع ورقات.
   فالقاعدة اللي تستعمل الفتحة نزلت هنا، جنب الإعلان، مثل
   ‎.tk-ground‎ بالضبط. وطبقتا القالب تجيان مرمَّزتين
   (‎--lit-card‎ · ‎--card-bed‎) فما تنكتب ولا واحدة منهما مرّتين،
   والوهج يبقى **فوق** الخامة كما كان في القالب. */
.tkback.has-art>.fc{background:
  var(--lit-card),
  var(--im-back) center/cover no-repeat,
  var(--card-bed)}

/* الرفعة العربية تعيش في العدّة، لا هنا: tokens.css §٧-ب يحطّ
   html{font-size:112.5%} (=١٨٫٠٠px على متصفّح افتراضه ١٦) ويكتب
   كل مقاس نصّي بالـrem. هالملف تخطيط وحده، فما يملك ولا مقاسًا:
   الثلاثة اللي كانت مكتوبة px فيه — النداء وعنوان الدفتر وأرقامه —
   انتقلت للـrem بالجولة ٤، وقبلها كان الدفتر ياخذ صفر رفعة.
   اللي يبقى للملف هنا لون الخلفية. */
html{background:var(--s-void)}
html,body{margin:0;padding:0}
body{min-height:100svh;-webkit-text-size-adjust:100%;background:transparent}
::selection{background:var(--a);color:var(--ink)}

/* ============================================================
   الديوانية — عمود واحد، بلا تمرير.

   ═══ العطب اللي كان مكتومًا: الحواف الآمنة ما كان لها ميزانية ═══
   الصفحة تُشحن بـviewport-fit=cover، والغرفة تزيد الحافّة العليا
   والسفلى على حشوتها — بس الإيقاع الرأسي ما كان يخصم شيئًا مقابلها.
   يعني كل رقم «صفر تمرير» بالجولة ٢ كان رقم حافّة-صفر: مقيسًا
   على متصفّح، لا على تطبيق مثبّت. مقيس على بناء الجولة ٢:
     390×844 + 47/34 → تمرير ٣٠px      (آيفون ١٢/١٣/١٤ · PWA)
     393×852 + 59/34 → تمرير ٤٢px      (آيفون ١٥ برو · الجزيرة)
     390×844 + 59/34 → ٤٢ · 360×800 + 47/34 → ٣٤ · 430×932 + 59/34 → ٥
   والعطب ما هو تاريخًا: القسم A0 في _probe/insets.html يعيد
   فرض القاعدة القديمة حرفيًّا على البناء الحالي، فينطلع اليوم
   ٣١ · ٤٣ · ٤٣ · ٢٩ · ١٢ على نفس الترتيب. يعني الميزانية هي
   اللي تشيل التمرير، مو إن التخطيط صار أقصر بالصدفة.
   العلاج مو زيادة قاعدة: الحافّة تُخصم من النَفَس نفسه. الطول
   اللي ياخذه العمود فعلًا هو --vh = 100svh − الحافّتين، والنَفَس
   ينحسب منه. فلمّا تكبر الحافّة، ينقبض الإيقاع بدل ما يفيض.
   وعلّة إعلان --sa-t/--sa-b كخاصيّتين مسمّاتين إن env() ما تنقاس
   في أي مختبر — أما الخاصيّتان فتنكتب فوقهما قيمة، فتصير
   الميزانية قابلة للاختبار. هذا هو الفرق بين رقم ورجاء.

   --g = clamp(0px, --vh × 0.01 − 6.4px, 2.6px)
   على ٦٤٠ فما تحت النَفَس صفر — التخطيط ينزل لأرضياته المقيسة؛
   وكل ما طال العمود فتح؛ وفوق ٩٠٠ يوقف — الطاولة ما تنفخ.
   دالة متّصلة، فما فيه ارتفاع بلا تخطيط ولا قفزة بين ٨٠١ و٨٠٧.

   ═══ صفّان من الجدول اللي كان هنا كانا كاذبَين ═══
   كان مكتوبًا «375×667 sa 47/34 → ٠ / ٠٫٨» و«320×568 → ١٧px».
   المقيس على نفس البناء: ١٦px و٣٤px. و_probe/insets.html نفسه
   كان يطبع ١٦ — أي إن المِسبار كان يناقض التعليق جنبه. أُعيد
   قياس كل صفّ من جديد على شجرة العمل هذي، وما يُكتب إلا المقيس.

   ═══ الطريقة، عشان الرقم ينعاد ═══
   الصفحة تُفتح على مقاس عرض/طول مفروضٍ بـCDP
   (Emulation.setDeviceMetricsOverride) لا بـ--window-size:
   المتصفّح المقطوع الرأس عنده أرضية عرض ~٥٣٢px، فرندرٌ مباشر
   على ٣٩٠ يخطّط على ٥٣٢ ويقصّ الصورة — تخطيطٌ آخر مصوَّرٌ من
   كوّة. تحقّق: الفعل الأساسي هنا يقع على ٤٣٫٠٠–٣٤٦٫٦٧ بكسل
   كسوة، وهو موضعه الحقيقي. ثم يُنتظر document.fonts.ready،
   والحركة مطفيّة على مستوى المتصفّح (prefers-reduced-motion)
   لأن أول إطار من tk-rise فيه scale(.94) — و getBoundingClientRect
   يرجّع الصندوق *بعد* التحويل، فأي قياس أثناء الدخول يطلع
   ٠٫٩٤ من الحقيقة.

   ═══ التمرير والأرضية: رقمٌ واحد، بيتٌ واحد، رِجٌّ واحد ═══
   ٢٠٢٦-٠٧-٢٨ · الجولة ٥.
   كان هنا جدولان بخمسةٍ وعشرين رقمًا مضبوطًا باليد: صفوف تمرير
   بحافّة وبلا حافّة، وفضلات ذيل، و«أرضية القعود ٥٩٢px» ومعها
   خمسة صفوف مشتقّة منها. **والأرضية كانت غلطًا، والخمسة كلها
   غلطٌ بنفس المقدار** — ستّة بكسل تحت الحقيقة، كل صفٍّ منها،
   لأنها انشتقّت من أرضيةٍ واحدة خاطئة. وفي نفس اللحظة كان
   MOLD يقول ٥٩٨ وcomponents.css يقول ٦٠٩: ثلاثة ملفّات، ثلاث
   أرضيات، ولا واحدة منها تنعاد بأمرٍ يُكتب.

   فالأرقام انحذفت، ما انصلحت. القاعدة اللي طلعت من هالجولة:
   **رقمٌ يقدر الرِّج يولّده ما ينكتب نصًّا** — لأن المكتوب
   ينبَتّ عن مصدره بأول تعديل، والمشتقّ منه ينبَتّ معه صامتًا.

   الأرضية تعيش في MOLD.md وحده، وتنعاد بهذا الأمر:
     _probe/gates.html?gates=390x604,390x603
   والبوابات كلها بنفس الرِّج، والحافّة الآمنة تنحقن بـ‎?sa=t,b‎:
     _probe/gates.html?sa=47,34&gates=…
   والتسمية تحت كل إطار تطبع التمرير المقيس: صفر أخضر، وغيره
   أحمر. الأرضية مذكورة على **الطول المتاح** (الشاشة ناقص
   الحافّتين)، لا على طول الشاشة — وهذا هو الفرق اللي كتم عطب
   الجولة ٢ كامله.

   واللي يبقى هنا مبدأ لا رقم: تحت الأرضية الصفحة **تمرّر ولا
   تقصّ**، ومكتوبٌ لا مخفيّ. وجُرّب شراء الأرضية بجعل --g سالبًا
   فانرفض بالقياس: min-height في صفّ الرمز ينزل تحت هدف اللمس
   ٤٤، والحشوات تنقصّ عند الصفر بلا ما تُعلن — فالمكسب وهمٌ
   محسوب غلط. التمرير أشرف من القصّ، وأشرف من رقمٍ اشتُري
   بكسر قانون.
   ============================================================ */
/* overflow:clip مو hidden — في RTL يصير hidden صندوق تمرير،
   وأصل التمرير على اليمين، فتنزاح الصفحة كلها وتتقصّ.
   clip يقصّ بلا ما يصير صندوق تمرير.
   وما بقي شي يحتاج قصًّا غير الورقتين النازفتين وحدهما.

   ═══ الثقب اللي كان تحته (٢٠٢٦-٠٧-٢٨ · الجولة ٤) ═══
   overflow:clip ما وصل سفاري إلا ١٦. وسفاري ١٥ وما دونه ما يفهم
   الكلمة أصلًا فيرميها ويرجع للافتراض visible — يعني الورقة
   اللي نزفها بقصد (تنقاس −٤٣٫٦px يسار حافّة الشاشة على ٣٩٠)
   تصير تمريرًا أفقيًّا على مستوى الصفحة كاملة، وفي RTL هذا
   بالضبط الفخّ اللي فوق: صندوق تمرير أصله على اليمين.
   وأول علاج كُتب هنا كان clip-path:inset(0) — **وقيس ففشل.**
   clip-path يقصّ الرسم ولا يمسّ منطقة التمرير: مقيسًا، الصفحة
   تبقى scrollWidth ٤٣٤ مقابل ٣٩٠ ويطلع تمرير أفقي ٤٤px، تمامًا
   مثل ما لو ما كان فيه علاج أصلًا. الفرق الوحيد إن المقصوص
   يصير فراغًا يُمرَّر له بدل ورقة. كُتب هذا هنا لأن الجولة
   كلها قامت على «قيس، ثم اكتب» — وهذا واحد وقعتُ فيه أنا.

   العلاج المقيس: overflow:hidden على الغرفة، خلف @supports.
   وفخّ الـRTL اللي فوق حقيقي، بس شروطه ما تتحقّق هنا، والثلاثة
   مقيسة لا مفترضة:
     ١ · الرندر مطابق بكسلًا لبكسل لـoverflow:clip — ١٨ بكسل
         من ٢٬٩٦٢٬٤٤٠ يختلف بدرجة قناة واحدة (تنعيم حواف).
     ٢ · تمرير الصفحة صفر في المحورين، و.room scrollLeft صفر.
     ٣ · **ما فيه ولا عنصر قابل للتركيز خارج صندوق الغرفة.**
         الوحيد اللي ينزف هو ظهر الورقة وأبناؤه، وكلهم داخل
         aria-hidden="true" وpointer-events:none وما يستقبلون
         تركيزًا. وهذا هو بالضبط اللي ينزع فتيل الفخّ: صندوق
         التمرير ما ينزاح إلا لمّا يُطلب منه إظهار شي بداخله،
         وما فيه شي يقدر يطلب.

   ═══ والميثاق انعدّل، ما انلفّ عليه (٢٠٢٦-٠٧-٢٨ · الجولة ٥) ═══
   الشروط الثلاثة فوق مقيسة وصحيحة — والعطب إنها كانت **حجّةً
   محلّيةً ضد قانون عامّ**: MOLD كانت تقول «overflow:hidden ممنوع
   على أي حاوية عربية» منعًا مسطّحًا، وهذا الملف يشحنه خلف
   @supports ويشرح ليش. قانونٌ يُلتفّ عليه محلّيًّا بدل ما ينعدّل
   هو الطريقة اللي تموت فيها المواثيق: اللي بعدك يقرا المنع، ثم
   يلقى الاستثناء، فيتعلّم إن الميثاق مجرّد رأي.
   فالمنع انعدّل في MOLD إلى ما يحميه فعلًا — آليّتان: قصّ
   التشكيل، وصندوق التمرير الـRTL — وسُمّيت الحالة الوحيدة اللي
   يُسمح فيها: احتياطُ سفاري ≤١٥ خلف @supports، على صندوق ما هو
   حاوية نصّ، وبالشروط الثلاثة **مقيسةً** لا مفترضة.
   الملفّان نصف قانون واحد، وكلٌّ يسمّي الثاني:
     MOLD.md — «العربي شرط لا ذوق» ← فقرة overflow:hidden. */
.room{position:relative;z-index:10;min-height:100svh;overflow:clip;
  --sa-t:env(safe-area-inset-top, 0px);
  --sa-b:env(safe-area-inset-bottom, 0px);
  --vh:calc(100svh - var(--sa-t) - var(--sa-b));   /* الطول اللي ياخذه العمود فعلًا */
  --g:clamp(0px, var(--vh) * 0.01 - 6.4px, 2.6px);
  display:flex;flex-direction:column;
  padding:var(--sa-t) 20px calc(var(--sa-b) + 12px + 3.2 * var(--g));
  max-width:430px;margin-inline:auto}
@supports not (overflow:clip){.room{overflow:hidden}}

/* ---------- منطقة العلامة ---------- */
/* ملاحظة صنعة: ما نوسّع هالصندوق بهامش سالب. أي عنصر أعرض من
   الغرفة في RTL يخلّي الصفحة كلها تنزاح يمين وتتقصّ — الورقة
   تنزف بإزاحة سالبة داخل صندوق بمقاسه، والغرفة تقصّها.
   والمنطقة صارت عمودًا بالتدفّق بدل ثلاثة عناصر مطلقة، فأي جسم
   يطول ينزّل اللي تحته بدل ما يتراكب معه.
   (كان مكتوبًا هنا «لو طال النداء سطرين نزل اللوح تحته». النداء
   انشال بحكم صاحب البيت، فما بقي في عمود المسرح إلا العلامة —
   والرزمة مطلقة فوقه ما تاخذ منه بكسلًا. السبب باقٍ والمثال راح:
   ‎.stage‎ اليوم صندوقٌ ارتفاعه ارتفاع العلامة وحدها، مقيسًا في
   ‎_probe/a-rects.html‎ عند ‎.stage‎ و‎.tkmark-img‎.) */
/* الطيّة اللي وفّرها الدفتر ما راحت للفراغ تحت — رجعت للإيقاع.
   وكلها معاملات على --g، فما تكلّف الشاشات القصيرة ولا بكسل:
   على ٦٦٧ بحافّة النَفَس صفر فما زاد شي. هذا هو شغل الدالة:
   تحوّل فرق الشاشة إلى نَفَس، لا إلى فراغ في الذيل.
   ═══ والرقم اللي كان هنا انشال، وسببه يستاهل الكتابة ═══
   (٢٠٢٦-٠٧-٢٩ · الجولة ٨.) كان مكتوبًا «فضلة الذيل صارت
   ٤٩٫٩–٥٤٫٦ على كل بوابة»، ومعه «على ٨٤٤ يزيد ٥٥px». ورِجّه —
   عمود ‎slack‎ في ‎_probe/insets.html‎ — كان **ميّتًا**: انشال
   النداء، وبقي في الرِّج سطرٌ ينادي ‎getComputedStyle(q('.lede'))‎
   بلا حارس، فيرمي ‎TypeError‎ ويموت القسمان A وC كلهما قبل ما
   يطبعا سطرًا. يعني الرقم المكتوب هنا ما كان له شاهدٌ يقدر يُسأل
   من يوم ما انشال النداء — وهذا أسوأ من رقمٍ قديم: رقمٌ قديم
   يُكشف أول تشغيلة، ورقمٌ رِجُّه ميّت ما فيه تشغيلة أصلًا.
   انصلح الحارس، وطلع المقيس: ‎١٠٢٫٦–١٢٥٫٤‎ على البوابات الأربع.
   والفرق كله من حذف النداء والسطر السند — أي إن العدد تضاعف
   تقريبًا وما تحرّك ولا معامل في هذا الملف.
   والرقم ما ينكتب هنا مرّةً ثانية: يُقرا من العمود.
     node/msedge → _probe/insets.html  §A عمود slack، و§C «grow (slack)» */
.stage{position:relative;flex:0 0 auto;
  display:flex;flex-direction:column;align-items:flex-start;
  padding-block-start:calc(8px + 19 * var(--g));
  gap:calc(11 * var(--g));
  /* المسافة بين قاع المسرح وقمّة اللوح — تنقرا مرّتين: هنا، وفي
     موضع الورقة المرميّة اللي تنقاس منها. اسمٌ واحد، فما تزيغ. */
  --stage-gap:calc(9px + 21.6 * var(--g));
  }
/* الرزمة — جهاز الورق الوحيد بالشاشة، ومحلّ توقيعنا الأكبر.
   مطلقة داخل .stage، فما تاخذ ولا بكسل من الإيقاع الرأسي، ومقاسها
   مربوط بنَفَس التخطيط نفسه (--g) فتتنفّس معه:
     640→74px · 667→76.9 · 750→85.9 · 844→96.0 */
/* السلّم ينكتب مرّةً وحدة في ‎--fan-bw‎، و‎--bw‎ ياخذه — عشان
   الورقة المرميّة تحت (§٦) تقدر تشتقّ مقاسها **منه** بدل ما
   تعيد كتابة الرامب. نفس علّة ‎--stage-gap‎ فوق: اسمٌ واحد،
   فما يزيغ رقمٌ عن أخيه. */
.tkfan{z-index:2;--fan-bw:calc(74px + 10.8 * var(--g));--bw:var(--fan-bw)}
/* ---------- الورقة المرميّة — الرزمة تلمس الطاولة ----------
   الرزمة كانت محبوسة في الـ٢١٪ العليا وما تلمس مساحة اللعب ولا
   مرّة: أقوى إشارة «لعبة» بالشاشة، وواقفة برّا. والحزّة اللي
   تاكل ركن اللوح الأعلى-يمين كانت تُقرا ركنًا مرسومًا، لأن ما
   وراها إلا الطاولة.
   الآن الورقة الرابعة تنزل تحت الشريحة وتدخل *خلف* اللوح
   (الرزمة z2 واللوح z3)، فتبان شريطًا فوق حافّته ثم تطلع من
   العضّة نفسها. فالعضّة تصير قصًّا حقيقيًّا في جسم، لا زخرفة.

   وين تقعد بالضبط، ولماذا هذي الأرقام:
   ١ · top:calc(100% + …) — الرزمة بطول .stage كامل، و.stage
       ما له حشوة سفلى، فقاعه = قاع آخر جسمٍ فيه بالضبط على كل
       بوابة. كان ذاك الجسم «النداء»؛ النداء انشال، وصار قاع
       المسرح **قاع العلامة**. والشرط اللي بُنيت له الجملة ما
       تغيّر: الورقة تبدأ تحت آخر جسمٍ في المسرح دايمًا، ما تمرّ
       ورا حرف عربي أبدًا. ولو مرّت، فالسرير تحت الحبر يصير ورقًا
       (لمعة ٠٫٨) و--tx عليه ينمحي — فهذا الشرط قانون، مو ذوق.
       والقاع نفسه مقيسٌ لا مفترض: ‎_probe/a-rects.html‎ يطبع
       ‎.stage‎ و‎.tkmark-img‎ في نفس التفريغ، فالمطابقة تُقرا.
   ٢ · inset-inline-start:0 — في RTL البداية يمين، فحافّة الورقة
       اليمنى تنطبق على حافّة اللوح اليمنى مهما تغيّر --bw.
       بالنسبة المئوية ما كانت تنضبط: --o نسبة من ٣٥٠ والورقة
       عرضها يتنفّس، فالطرفان ما يلتقيان إلا على بوابة وحدة.
       (وهذا نصف العطب وحده انصلح يومها — الورقة الرابعة نُقلت
        للبكسل وبقيت الثلاث الظاهرة على نسبة المسرح، فبقي شكل
        الرزمة يتغيّر مع البوابة: المكشوف من كل ورقة ٤٥٫٦٪ على
        ٣٦٠×٨٠٠ و٥٦٫٧٪ على ٣٧٥×٦٦٧، مقيسًا بـ‎node _probe/fan.mjs‎.
        النصف الثاني انصلح ٢٠٢٦-٠٧-٢٩ · الجولة ١: ‎--o‎ صارت نسبةً
        من الورقة نفسها — التعليل في ‎components.css‎ عند ‎.tkfan>*‎.)
   ٣ · الدوران **صفر** على هالورقة وحدها، وهذا انقاس ما انذوّق
       (٢٠٢٦-٠٧-٢٨ · الجولة ٥). كان ٨deg، ومكتوبًا جنبه إنه
       «يكمّل سلّم الرزمة، ٩ درجات لكل ورقة: ٢٤- · ١٥- · ٦- · …».
       والادّعاء نفسه ما كان صحيحًا: السلّم لو مشى ٩ درجات لطلعت
       الرابعة ٣+ لا ٨+. لكن العلّة الحقيقية مو حسابية:
       هالورقة **ما تنشاف إلا من نافذة العضّة** — واللي انقرا
       على الشاشة «ورقة مكرمشة» لا «ورقة تحت قصّة».
       والسبب هندسي: محيط النافذة هو درجة الحزّة نفسها (سلّم
       بزوايا قائمة)، فأي مالئٍ لها ياخذ شكلها هي. ولمّا تكون
       حوافّ الورقة **مايلة**، تقطع الدرجة بزاوية، فيقرا التقاطع
       طيّةً في ورق. رُندرت خمس زوايا وانتُظر لها بمقاس ٣× على
       ٣٩٠×٨٤٤ (‎_probe/out/bite-compare*.png‎): ٨+ · ٥+ · ٣+ ·
       ٤- كلها تُقرا شريطًا مطويًّا، و**صفر** أنظفها بفرق واضح —
       لأن حوافّ الورقة تصير موازيةً لحوافّ اللوح، فالدرجة تُقرا
       قصّةً في اللوح لا كرمشةً في الورق.
       وصفر يضيّق صندوق الورقة كذلك (الدوران يوسّع المحيط)، فتبعد
       عن حدّ اللوح بدل ما تقرب منه — أي إنه يخدم قانون الحافّة
       بدل ما يزاحمه.
       **وما انقفل تمامًا، ومكتوبٌ لا مُدَّعى:** حتى على صفر،
       المكشوف يُقرا شكلًا كريميًّا مدرَّجًا أكثر ممّا يُقرا ورقةً
       — لأن الشكل شكل النافذة. الحلّ الكامل يبي إمّا سحب الورقة
       من النافذة كلها (وتضيع «الرزمة تلمس مساحة اللعب» اللي
       انبنت لها الجولة ٤) أو مكوّنًا جديدًا، والجولة ٥ ما تبني.
       مسجَّل للجولة الجاية.
   ٤ · الورقة تقعد **تحت** قمّة اللوح، مو فوقها. القاعدة الشاحنة
       اليوم ‎top:calc(100% + var(--stage-gap) + 6px)‎.
       (كان مكتوبًا هنا «+2px» ومعه مقياسان — «كلمة تَك تبدأ على
       بُعد ٤١٫٩px من قمّة الورقة» و«عمق العضّة ٤٤» — والثلاثة
       انبتّوا عن مصدرهم: القاعدة تشحن ٦ لا ٢، والكلمة نفسها ما
       عادت تنرسم أصلًا (‎.tkback.has-art>.w{display:none}‎ —
       الظهر صار خامة)، والخامة انتقلت هالجولة. رقمٌ يصف كلمةً
       ما تنطبع ليس رقمًا، فانشال ولا انحطّ بديلٌ عنه: العدد
       الشاحن مكتوبٌ فوق، والباقي سبب.)
       والسبب باقٍ كما هو: أي جزءٍ من الورقة يطلع فوق حافّة اللوح
       يدخل نافذة العضّة من الأعلى، فيُقرا قصاصةً مقصوصة لا ورقةً
       مدسوسة. */
/* ٥ · الورقة تطلع **من نافذة العضّة**، ما تلفّ حول ركن اللوح.
      (تصحيح ٢٠٢٦-٠٧-٢٨ · الجولة ٤، بعد الدمج — انقاس على الشجرة
      المدموجة، لأن العطب ما يظهر إلا بعد ما تلتقي الورقة باللوح.)
      كانت الورقة تنزّ يمين حافّة اللوح وفوق قمّته،
      لأن دوران ٨deg يوسّع صندوقها. والنزّة تقعد ملاصقةً لحدّ اللوح
      من برّا، فالسرير تحت ذاك الحدّ يصير كرتونًا ناصعًا بدل جوخ —
      وحدٌّ مضيء على سرير مضيء ما يقدر يوصل ٣:١ أبدًا (نفس هندسة
      «ما فيه بكسل غامق يوصل ٣:١ على سرير غامق»، مقلوبة).
      وكان معه هنا جدولُ حوافٍّ من ذاك اليوم — ستّة أرقام تصف
      الحالة **قبل** العلاج، على هندسةٍ ما عادت موجودة (الدوران
      صار صفرًا، وانزياح الورقة تغيّر، والخامة تحتها تبدّلت
      هالجولة). انشالت الأرقام وبقي السبب: لا رقم في هذا الملف
      إلا وله رِجٌّ يعيد إنتاجه اليوم. وحال الحوافّ الشاحن يطبعه
      ‎python _probe/a-edge.py … --all … --state rest|open‎، وهو
      أخضر في الحالتين.
      العلاج مو استثناء بالقياس، بل هندسة: تُزاح الورقة داخلًا
      وتنزل (القاعدة تحت: ‎11px‎ و‎+6px‎)، فيصير صندوقها كامله
      **داخل** مستطيل اللوح. واللوح
      فوقها (z3 مقابل z2)، فما يبقى منها ظاهرًا إلا اللي تكشفه
      نافذة العضّة — وهي أصلًا ليست حافّة اللوح، ومستثناة بحقّها في
      كل جولة. الفكرة نفسها اللي أرادها التصميم («ورقة مدسوسة تطلع
      من الحزّة») بلا ما تلمس حدًّا. */
/* ٦ · الورقة المرميّة تنقاس **بالنافذة**، لا بالرزمة ·
      ٢٠٢٦-٠٧-٢٩ · الدورة ٣ · الجولة ١.
      نافذة الحزّة مربّعٌ ‎--nt‎ = ٥٨ في ركن اللوح الأعلى-يمين.
      وهالورقة الجسم الوحيد بالردهة اللي **ما ينشاف منه إلا ما
      تكشفه نافذة**، فالمقاس اللي يخدمها مقاس النافذة لا مقاس
      الرزمة — والرزمة تُشاف كاملةً فوق، وهالورقة ما تُشاف جنبها
      ولا مرّة، فما فيه موضعٌ تنقارن فيه العرضان.
      رقمان يخرجان من هذا، وكلاهما مقيسٌ لا مذوّق:
      أ · **العرض ٧٠٪ من الرزمة.** المكشوف من الورقة =
          مساحة النافذة ÷ مساحة الورقة، والعلامة تملأ الورقة
          (‎x٧٫٣–٩٢٫٦٪ y٥٫٢–٩٤٫٧٪‎ من الخامة، ‎node _probe/fan.mjs‎)
          — فنسبة العلامة المكشوفة تتحرّك بمقاس الورقة وحده،
          وما ينفع تتحرّك بالموضع: على ٩٦px النافذة تغطّي ١٩٪
          من الورقة مهما انزاحت داخل اللوح. الرقم الشاحن يطبعه
          عمود ‎emb%‎، والثلاث حالات (‎a6e364f‎ · الموروثة · هذي)
          في تقرير الجولة، من نفس الأمر بـ‎--css‎.
      ب · **حاشيةٌ من الطاولة على الطرفين، ١١px لكلٍّ.** كان
          الأعلى ٦px، فالكريمي يعبّي النافذة ويُقرا لسانًا
          ممزّقًا. الآن الطاولة تبان فوق الورقة ويمينها داخل
          نفس النافذة، فالنافذة تُقرا **فتحةً في اللوح تحتها
          ورقة**، لا حشوةً مقصوصة. وحافّة الورقة نفسها صارت
          تُقرا لأن ‎.tkcard>.fc‎ لبّسها ‎--rim-paper‎.
      وصندوق الورقة كله يبقى **داخل** مستطيل اللوح كما فرضت
      الجولة ٤ — والمقاس الأصغر يوسّع تلك المسافة، ما يضيّقها. */
/* ٦-ب · والـ٧٠٪ كانت مشتقّةً من حجّةٍ صحيحة عن **الورقة** وغلط عن
      **العلامة** · ٢٠٢٦-٠٧-٣١ · الدورة ٣ · الجولة ٣.
      الحجّة فوق (أ) تقول: نسبة المكشوف من الورقة = مساحة النافذة ÷
      مساحة الورقة، فما تتحرّك بالموضع. صحيحة. والخلاصة اللي بُنيت
      عليها — «فنسبة العلامة المكشوفة تتحرّك بمقاس الورقة وحده» —
      كانت تفترض علامةً **تملأ الورقة** (‎x٧٫٣–٩٢٫٦٪ y٥٫٢–٩٤٫٧٪‎)،
      وذاك الصندوق نفسه كان عطبًا في الرِّج: كان يقيس **الإطار
      الذهبي** لا العلامة، وانصلح في نفس الدورة. والعلامة الحقيقيّة
      على الظهر المشحون شريطٌ ضيّق حوالي منتصف الورقة — يطبع صندوقها
      ‎node _probe/fan.mjs‎ في سطر ‎emblem=‎ ولا ينكتب هنا.
      فالسؤال صار سؤال **موضع**، لا نسبة: النافذة تكشف من قمّة
      الورقة نزولًا بعمق الحزّة (٤٤px فيزيائيّة، ما تتنفّس)، والورقة
      تنزل ١١px تحت قمّة اللوح. يعني المكشوف رأسيًّا هو
      ‎[11, 11+عمق] ÷ طول الورقة‎ — وكل ما طالت الورقة نزل نصيبها
      المكشوف من قمّتها، حتى خرج منتصفها (وفيه العلامة) من النافذة
      تمامًا: ‎emb% 0.0‎ على البوابات الأربع، جولتين.
      والرافعتان اللي سمّاهما الموجز «الانتشار أو العدد» ما تنفعان
      هنا: العدد يعني حذف الورقة، والنافذة ترجع تكشف الجوخ — وهو
      عطب الجولة ٤ بالحرف؛ والانتشار يخصّ الثلاث الظاهرات لا هذي.
      الرافعة الثالثة هي المقاس، وهي **نفس رافعة (أ)** بالاتّجاه
      اللي كانت تطلبه أصلًا. ٧٠٪ → ٤٦٪، وما فيه رقمٌ ثانٍ تحرّك:
      الحاشية ١١px كما هي، والصندوق يبقى داخل مستطيل اللوح
      (والمقاس الأصغر يوسّع تلك المسافة كما يقول السطر فوق).
      والمقيس بعده — الأربع بوابات، عمود ‎emb%‎ وعمود ‎vis-v%‎ —
      من ‎node _probe/fan.mjs‎ وحده، وما ينكتب هنا. */
.tkfan>:last-child{inset-inline-end:auto;inset-inline-start:11px;
  --bw:calc(.46 * var(--fan-bw));
  top:calc(100% + var(--stage-gap) + 11px)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}
.stage .tkmark{position:relative;z-index:5}
/* العلامة الجديدة — شكل ٧. المقاس مشتقّ من النَفَس مثل بقيّة المسرح،
   والعرض والطول متساويان (الشكل مربّع).
   ما تغيّر منه ولا رقم يوم صارت SVG مضمّنة بدل PNG (٢٠٢٦-٠٧-٢٩ ·
   الجولة ١): الصندوق المرسوم انقاس قبل وبعد على البوابات الأربع
   في الحالتين، ‎python _probe/a-boxdiff.py‎ — صفرٌ في كل خانة.
   وviewBox العلامة ١٩٢×١٩٢ = مقاس mark-192.png حرفًا بحرف، فنسبة
   العرض للطول ما تحرّكت وheight:auto يعطي نفس الرقم. */
.stage .tkmark-img{position:relative;z-index:5;display:block;
  width:clamp(104px, 92px + 5.6 * var(--g), 132px);height:auto;
  /* الحبر. الشكل صار يرث اللون — وهذا كل الغرض من الاستبدال — فلازم
     يُقال بأي لونٍ يرث. و#DDAE55 ليس صبغةً جديدة: هو **حبر العلامة
     المعتمدة نفسها**، منوال بكسلاتها المعتمة في mark-512.png، مقيسًا:
       python _probe/a-markink.py design/project-152/archive/v1-marks/mark-512.png
     وما انكتب رمزًا هنا إلا لأن أقرب صبغةٍ في العدّة تبعد عنه
     ΔE76 = ٧٫٨٩ (‎--a-pol‎) — وهذا فرقٌ تشوفه العين، فاستعمالها كان
     بيغيّر علامةً أقرّها صاحب البيت، لا بينقلها.
     يوم يحكم في لون العلامة، السطر يصير ‎color:var(--…)‎ وبس؛
     الشكل جاهزٌ له من اليوم. */
  /* الحبر — والختم يرثه، وهذا كل الغرض من كونه مضمَّنًا: الإطار
     والكلمة على ‎currentColor‎، والوجه على ‎--seal-face‎، والفتحة على
     ‎--aqeeq‎. ثلاثة رموزٍ من العدّة، وما فيه ‎#hex‎ في هذي الكسوة.
     و‎--mark-gold‎ اللي كان هنا **انشُطب مع جسمه** (٢٠٢٦-٠٧-٣١):
     كان ذهب العلامة ذات الورقتين، والعلامة تقاعدت بحكم صاحب البيت —
     ومقيسًا قبل ذلك، كان يحكم **صفر بكسل** على كل صفحةٍ في السلسلة،
     لأن مستهلِكه الوحيد كان ‎color:‎ على ‎<img>‎ والصورة لا ترث لونًا.
     ‎node _probe/a-govern.mjs‎ هو اللي أثبته وهو اللي يحرسه. */
  color:var(--seal-ink)}
/* ---------- النداء انشال، وقاعدته معه ----------
   (٢٠٢٦-٠٧-٢٩ · حكم صاحب البيت.) «اقعد، نبدأ الصكّة.» انشالت من
   المسرح، وما بقي إلا <h1 class="sr-only"> لقارئ الشاشة — وهو ما
   ياخذ سلّمًا ولا ظلًّا ولا لونًا.
   والقاعدة ‎h1.lede‎ قعدت هنا التزامًا كاملًا بعد ما مات جسمها:
   سلّمٌ سائل وظلٌّ ولونٌ لعنصرٍ ما يطابقه شي في الصفحة. وكسوةٌ
   ميّتة تُقرا حيّةً عند اللي يجي بعدك — يفتح الملف فيلقى للنداء
   سلّمًا مضبوطًا فيفترض إنه على الشاشة. انشالت.
   والعلّة اللي كانت مكتوبة هنا تبقى مكتوبة لأنها **قاعدة بيت لا
   واقعة**: أي سلّم خطٍّ ينكتب بالـrem لا بالـpx عشان الرفعة
   العربية ومقاس خطّ المتصفّح يمرّان منه، والزيادة السائلة وحدها
   تبقى بالبكسل فوق الأرضية لأنها دالة طول الشاشة لا دالة مقاس
   الخطّ. أرقام النداء نفسها (٢٣ و٢٨ وسقفها) انشالت مع النداء —
   ما لها رِجٌّ يعيد توليدها بعد اليوم، وما ينكتب رقمٌ بلا رِجّ.
   والعدّة باقية على ‎--ty-lede‎ و‎--tsh-lede‎: القالب يقدر يمسك
   مقاسًا ما تستعمله الكسوة اليوم. */

/* ---------- اللوح المحزوز ---------- */
/* ما عاد بمقاس مقفول. العرض سائل بسقف ٣٥٠ — على ٣٦٠ يملأ
   الغرفة (٣٢٠) بدل ما ينزّ ٣٠px تحت القصّ، وعلى ٣٩٠ فما فوق
   يبقى ٣٥٠ متوسّطًا كما كان. والطول من المحتوى: أي سطر زايد
   في زرّ أو حقل يطوّل اللوح، والحزّة تتبعه لأنها قناع مثبّت
   على الركن، مو مسارًا مرسومًا على ٤٢٠. */
.panel{position:relative;z-index:3;width:100%;max-width:350px;margin-inline:auto}
/* ---------- الحزّة صار لها ساكن ----------
   كان هنا calc(--pad-notch − 9px + 4.4g) ومكتوب جنبه اعتراف إن ٤٥
   «أقلّ رقم آمن»: رقمٌ مضبوط باليد يوم ما كانت هالمساحة فاضية —
   ٥٤px من العدم، وأكبر كتلة خالية بالتخطيط، ولسان الحزّة فوقها
   ما يحمل شيئًا.
   الآن الحشوة العليا = --pad-rail (١٠) وبس، ورِيل المقاعد يقعد
   في الدرجة نفسها بطول --notch-step (٤٤). ١٠ + ٤٤ = --pad-notch
   (٥٤) — نفس الخلوص القديم بالضبط، بس صار محتوى بدل فراغ.
   ولا رقم منهما مكتوب مرّتين: طول الرِّيل ياخذه المكوّن من
   --notch-step، وهذي الحشوة تاخذها من --pad-rail، والاثنان من
   نفس العدّة. فما فيه فرصة زيغ.
   والخلوص الأفقي للسان الحزّة من المكوّن كذلك (padding-right
   فيزيائي — الحزّة ما تنقلب بالـRTL). مقيس: أقرب مقعد يقعد على
   بُعد ٥٤px من حافّة اللوح اليمنى، وقاع الحزّة عند ذاك البعد
   أقلّ من ١px. */
/* ---------- والتداخل هنا سلّمٌ، مو تمركزٌ — بقصد ----------
   ٢٠٢٦-٠٧-٢٨ · الجولة ٥: كان هنا سردٌ كامل مبنيٌّ على أن الجلد
   يشحن ‎--nr:26px‎، وعلى «رقمين لسطح واحد» يبي تبليغًا وإصلاحًا
   عند وكيل آخر. الرقم انصلح في الجولة ٤ — الجلد يشحن
   ‎--nr:var(--r-sheet)‎ — فالسرد كله كان يحاجّ عن قيمة ما عاد لها
   وجود، ويُبلّغ عن عطب مقفول. انحذف. والصحيح منه هذا:
   الفعل الأساسي نصفه ‎--r-btn-1‎ (١٨) داخل صحيفة نصفها
   ‎--r-sheet‎ (٢٨) بحشوة ٢٢. والتمركز الحقيقي يبي حشوة = ٢٨ − ١٨
   = ١٠ بالضبط، وهي ‎--pad-rail‎ نفسها المشتقّة بالـcalc.
   وقاعدة الحشوة في القالب **حدٌّ أدنى لا مساواة**: «الأوسع مسموح
   والأضيق لا». فـ٢٢ ≥ ١٠ سليمة، وما هي زيغًا.
   وليش ما انحطّت ١٠ وخلاص: لأن الحشوة ما هي وحدها في المعادلة —
   ‎--pad-notch‎ (٥٤ = ‎--pad-rail‎ + ‎--notch-step‎) هو سقف الرفّ اللي
   يقعد عليه رِيل المقاعد تحت لسان الحزّة، وتضييق الحشوة الجانبية
   يوسّع الفعل الأساسي فيزيد نصيبه من ميزانية النحاس. والاتجاه
   الثاني ممنوع أصلًا: تثبيت الحشوة ٢٢ يعطي نصفًا داخليًّا ٦،
   والقالب يقول حرفيًّا «نصف قطر ٤–٦px على أداة = عيب تلقائي».
   فالسلّم مقصود: ٢٨ ← ١٨ ← ١٤ نزولًا، وما فيه ركن داخلي أعرض
   من حاضنه. */
.panel .pin{position:relative;z-index:1;
  padding-block:var(--pad-rail) calc(15px + 8 * var(--g));
  padding-inline:22px}
/* المسافة تحت الرِّيل — إيقاع رأسي، وهذا بيته.
   و--pin-inline معها: هي مرآة padding-inline على .pin فوق بسطرين،
   والمكوّن (§٨٫٥) يشتقّ منها خلوصه عن لسان الحزّة —
   padding-right = --pad-notch − --pin-inline. فالرقم اللي يتحرّك
   يتحرّك مرّةً وحدة وفي مكانٍ يشوف اللي يقلّده، وما فيه في المكوّن
   ولا هنا فرقٌ مكتوبٌ باليد يتعتّق. */
/* الزرّ الأساسي — صاحب البيت: «الكبير كان أحسن». فقد ارتفاعه
   لمّا انشال السطر السند، فيرجع بالطول مباشرةً لا بسطرٍ زائد.
   مشتقّ من النَفَس مثل بقيّة الإيقاع، فما يكسر أي بوابة.

   ═══ الرامب انقلب أرضيةً بدل سقف · ٢٠٢٦-٠٧-٣١ · الجولة ٣ ═══
   كان ‎clamp(56px, 56px + 12g, 88px)‎ — أي أن الفعل الأساسي على
   أقصر بوابة (٣٧٥×٦٦٧، والنَفَس هناك ٠٫٢٧) يقرا ٥٩٫٢٣، **وهو
   طول حقل الاسم نفسه زايد أربع بكسلات**. وقانون الوزن ٣–٥×،
   فالقراءة كانت ١٫٠٨٠× — تعادلًا، لا أفضليّة. والعلّة كانت في
   شكل الرامب لا في مقداره: كل مكسبه معلَّق على ‎--g‎، و‎--g‎ صفرٌ
   تقريبًا عند ٦٦٧ — يعني الزرّ يكبر على الشاشات اللي ما تحتاجه
   ويقعد صغيرًا على اللي تحتاجه.
   فالمكسب انتقل إلى **الأرضية**: ٥٦→٦٢، والمعامل ١٢→١٠ عشان
   السقف ٨٨ ما يتحرّك ولا ميزانية النحاس تنفخ. المقيس بعده على
   البوابات الأربع ٦٤٫٧ · ٧٦٫٠ · ٨٢٫٤ · ٨٨٫٠ — أي أطول على كل
   بوابةٍ إلا ٤٢٨ (٨٧٫١٩→٨٨٫٠٠، سقفٌ بلغته)، وهذا مقصود:
   صاحب البيت قال «الكبير أحسن» عن الزرّ، لا عن الرامب.
   وثمنه بكسلاته الستّ على أرضية اللا-تمرير (٥٤١→تُشتقّ في
   ‎node _probe/a-all.mjs‎، ما تنكتب هنا)، و٣٧٥×٥٥٣ لا يزال
   يقراها فوق الأرضية مغلوقًا — وهي في المصفوفة القياسيّة الآن
   فما عادت دعوى.
   وسلّم الأزرار ٥٦/٥٠/٤٤ في القالب ما تحرّك: ‎.tkb-1{min-height:56px}‎
   باقٍ كما هو، وهذا رامب تخطيطٍ في الجلد فوقه — والجلد يملك
   الهندسة السائلة وحدها. */
.panel .tkb-1{min-block-size:clamp(62px, 62px + 10 * var(--g), 88px)}
.panel .tkseats{--pin-inline:8px;margin-block-end:calc(9px + 4.9 * var(--g))}

/* ---------- تحت ٣٩٠: الهوامش تنقبض، والرِّيل ياخذ المكسب ----------
   الرِّيل يشيل جملةً واحدة على سطر واحد، بمقاس النظام (1rem) لا
   بمقاسٍ مخصوص — فعرضها ثابت والبوابة هي اللي تضيق. وطلبها اليوم
   أقلّ ممّا كان: راحت أربع ورقات وفرجتان، وبقي الكلام.
   والمكسب انشترى من الهوامش وحدها، لا من مقاس الحرف ولا من
   النصّ: هامش الغرفة ٢٠→١٢ وحشوة اللوح ٢٢→١٤. والقانون اللي
   ما انكسر: خلوص المحتوى عن عضّة الحزّة يبقى كما هو بالضبط —
   وما عاد يحتاج رقمًا يمشي معاه: --pin-inline تنزل ٢٢→١٤ هنا،
   وpadding-right في المكوّن مشتقّ منها (--pad-notch − هذي)
   فيرتفع وحده. والعضّة ٤٤ فيزيائية ما تتحرّك.
   (كان مكتوبًا هنا «١٤+٤٠ = ٢٢+٣٢»: مجموعٌ صحيح بفرقين مكتوبين
   باليد، وكفايته تعتمد على انتباه القارئ. الآن يعتمد على calc.)
   وفوق ٣٩٠ ما تغيّر شي: البوابة هناك تكفي بذاتها. */
@media (max-width:389px){
  .room{padding-inline:12px}
  .panel .pin{padding-inline:14px}
  .panel .tkseats{--pin-inline:2px}
}

/* الثانوي انكمش على كلمته، وهذا مصدر فرق الوزن كامله: زرّان
   بعرض كامل ما يقدران يختلفان إلا بالارتفاع. الطول باقٍ ٥٠ عشان
   سلّم الأزرار (٥٦/٥٠/٤٤) ما ينكسر، والمكسب من مكانين: الحشوة
   الجانبية ٢٢→١٨، والكلمة انقصرت لأن الرِّيل فوق صار يسمّي سيكل
   بالصورة.
   وقانون الوزن **ما ينكتب هنا**، ينُقل عنه (٢٠٢٦-٠٧-٢٩):
   نصّه الوحيد في ‎design/tak/MOLD.md‎ قانون ٢ — «الفعل الأساسي
   يفوق **أكبر أداة أخرى على شاشته** ٣–٥ أضعاف مساحةً، على كل
   بوابة»، والمقيس ضدّه يُسمّى **دورًا لا صنفًا**، لأن قانونًا
   يسمّي ‎.tkb-2‎ يسقط يوم ينتقل الصنف.
   وكان مكتوبًا هنا عكسه حرفيًّا — «ضدّ ‎.tkb-2‎ ولا شي غيره» —
   فالميثاق والكسوة يقولان قانونًا واحدًا بمحتوًى متعاكس، وهو
   بالضبط صنف العطب اللي أعلن السجلّ إغلاقه مرّتين. انشال النصّ،
   وبقي الإسناد.
   واللي يخصّ هذا الملف ملاحظة لا قانون: أثقل جسم بعد الفعل
   الأساسي في الردهة هو **الرزمة** (‎.tkfan‎)، وهي ليست أداةً،
   فهي خارج المقيس أصلًا — والفعل الأساسي ما يفوقها بثلاثة
   أضعاف. ملاحظة مسجّلة، مو امتثالًا يُدَّعى.
   والجدول اللي كان هنا (خمس بوابات بخمسة أرقام) انحذف بدل ما
   ينُسخ: يولّده الرِّج ولا ينكتب نصًّا، والحزّة على وجه الزرّ
   غيّرت مساحته أصلًا —
       ‎_probe/a-rects.html?w=320&h=568‎ … ‎?w=430&h=932‎
   بشرط ‎STABLE=true‎، وإلا فما فيه رقم. */
.panel .tkb-2{padding-inline:18px}
/* النائب العربي كان ينحاز يسار وهو فاضي لأن dir=auto ينحلّ ltr
   على قيمة فاضية — حقلان بسطر واحد بمحاذاتين متعاكستين. */
.tkfield-in:placeholder-shown{direction:rtl}

/* ============================================================
   سطر الاسم — سؤالٌ وخانة، لا حقلٌ بعرض اللوح
   ٢٠٢٦-٠٧-٣١ · الدورة ٣ · الجولة ٣.

   القانون: «الفعل الأساسي يفوق أكبر أداةٍ أخرى على شاشته ٣–٥
   أضعاف مساحةً، على كل بوابة» (MOLD قانون ٢). والمقارَن مقروءًا
   من التعداد هو ‎#playerName‎ على كل بوابة، وكان **بعرض اللوح
   كامله** — أي جسمَين بعرضٍ واحد، وما يقدران يختلفان إلا
   بالارتفاع، والارتفاعان ٥٩٫٢٣ و٥٤٫٨٤. القراءة ١٫٠٨٠×.
   والحلّان الوحيدان (والمدقّق سمّاهما): زرٌّ بطول ١٦٥px، أو
   حقلٌ يخرج من عرض اللوح. الأول يكسر شيئين مقيسَين — ميزانية
   اللون المحجوز (٣–٨٪ من بكسلات الشاشة) وأرضية اللا-تمرير —
   فانمشى الثاني.

   واللي كسبناه معه أكبر من الهندسة: النداء «وش نناديك؟» كان
   **نائبًا** (‎placeholder‎) واسم الوصول ‎aria-label="اسمك"‎ —
   أي أن المشهود غير المسموع، وهي الملاحظة الوحيدة المفتوحة على
   «عربيّة سليمة» في كشف الجولة ٢. صار ‎<label for>‎: يُقرا
   ويُسمع بنفس الكلمات، ويكبّر هدف اللمس (ضغطة على السؤال تركّز
   الخانة)، وينشال معه النائب فما بقي نصٌّ يُقصّ في خانةٍ ضيّقة.

   والعرض مشتقّ لا مذوّق: يقعد تحت مساحة الثانوي على البوابات
   القصار (فيبقى المقارَن هو الثانوي وما يتحرّك القانون معه)،
   ويتنفّس مع ‎--g‎ فوقها. الأرقام كلها من
   ‎node _probe/a-squint.mjs --gate <بوابة>‎ — التعداد يطبع
   المقارَن ونسبته، وما ينكتب رقمٌ هنا.
   والطول ما تغيّر ولا بكسل: الصفّ طوله طول البئر نفسه (٥٤٫٨٤)،
   والسؤال جنبه لا فوقه، فما دفعت الأرضية شيئًا مقابل هذا. */
.panel>.pin>.tkfield{display:flex;align-items:center;gap:12px}
.panel>.pin>.tkfield>.tkfield-lb{flex:1 1 auto;min-width:0;margin-block-end:0}
.panel>.pin>.tkfield>.tkfield-in{flex:0 0 auto;
  width:clamp(104px, 100px + 6 * var(--g), 116px)}
/* الحشوة الرأسية ١١→١٠: الفعل الأساسي هو تسعة أعشار النحاس
   بالشاشة، وميزانية اللون المحجوز كانت فوق سقف ٨٪ (والحزّة الآن
   تاكل منه، فالرقم يُعاد توليده لا يُنسخ: ‎_probe/a-accent.py‎).
   الطول ما ينزل تحت --r-btn-1 × ٣ ولا تحت ٤٤ هدف اللمس بحال.
   والعرض على الغلاف والزرّ معًا: الغلاف كتلة فياخذ عرض اللوح
   وحده، والزرّ ‎width:100%‎ داخله كما كان — فلو انشال الغلاف
   يومًا بقي الزرّ ملء اللوح، ما ينكمش على كلمته. */
.panel .tkbite{width:100%}
.panel .tkb-1{width:100%;padding-block:10px}

/* ============================================================
   رمز الغرفة — سطر واحد بدل ثلاثة أجسام

   كان: خيط فاصل + حقل نصّ + زرّ. أي: أكبر جسمين داكنين بالشاشة
   بعد الفعل الأساسي (اختبار الغبش يحطّ البئرين في المرتبة ٢ و٣)
   كان أحدهما لطريقٍ يمشيه الأقلّ. ونصف الشاشة صار نموذجًا.
   صار: سطر هادي واحد، واللي يبي الرمز يفتحه.

   البناء <details> بحتة: ولا سطر جافاسكربت زايد. و<summary>
   يستقبل التركيز بنفسه، ويفتح بـEnter وSpace، وحلقة التركيز
   النحاسية تجي من .tkb:focus-visible مثل أي زرّ. ولو ما عرف
   المتصفّح <details> ظهر المحتوى كامل — «إذا ما اشتغل شي،
   كل شي ظاهر» محفوظة بالبناء لا بالرجاء.

   ═══ والحالة المفتوحة صار لها بيت (٢٠٢٦-٠٧-٢٩) ═══
   حكم صاحب البيت: فتح «عندك رمز؟» كان يخلّي الصفحة تمرّر.
   العلاج مو هنا — هو في §«الرفّ الواحد» آخر هذا الملف. وكان
   «الدفتر ينطوي لمّا تنفتح الطيّة»، ثم حكم صاحب البيت إن الدفتر
   ما ينطوي — ينزل وبس — فصار المسرح هو اللي يدفع. واللي يخصّ
   هالقسم ما تغيّر: **طول صفّ الرمز مُعلَنٌ** تحت، فاللي يقوم
   يقدر ينقاس عليه أيًّا كان.

   ═══ والجدول اللي كان هنا انحذف، ما انصلح ═══
   كان مكتوبًا هنا «طول اللوح ÷ طول الشاشة» على خمس بوابات، ومعه
   «ومفتوحًا يطلع ٥٥٫٣٪». الصفّ المفتوح مات بهذي الجولة لأن
   الحالة المفتوحة تغيّرت، وبقية الصفوف ما لها رِجٌّ يولّدها
   أصلًا: ولا مِسبار في ‎_probe/‎ يطبع نسبة لوحٍ إلى شاشة. فانحذفت
   كلها بدل ما ينصلح صفٌّ واحد — **رقمٌ يقدر الرِّج يولّده ما
   ينكتب نصًّا، ورقمٌ ما له رِجٌّ ما ينكتب أصلًا.**
   واللي ينقاس هنا شيئان، وكلٌّ بأمرٍ يُكتب:
     الهندسة — ‎_probe/a-rects.html?w=390&h=844&open‎  (STABLE=true)
     التمرير — ‎_probe/gates.html?open=1&sa=59,34‎
   ============================================================ */
.roomfold{margin-block-start:calc(11px + 3.6 * var(--g))}
/* display:flex (لا inline-flex) عشان التوسيط بـmargin-inline يمشي —
   نفس علّة .tkb-2 حرفيًّا. وتغيير display ينشل علامة القائمة في
   كروم وفَيَرفُكس، وسفاري تبي ::-webkit-details-marker صراحةً. */
.roomfold>summary{display:flex;width:fit-content;margin-inline:auto;list-style:none;
  padding-block:8px}   /* ٤٤٫١ طولًا — على هدف اللمس بالضبط، لا تحته */
.roomfold>summary::-webkit-details-marker{display:none}
/* السهم: حدّان فيزيائيّان مدوَّران — رمز حالة، مو ضوءًا ولا حرفًا،
   فما له زاوية شمس ولا ينقلب بالـRTL (السهم متماثل بعد الدوران). */
.roomfold>summary::after{content:"";width:7px;height:7px;flex:none;
  margin-block-start:-4px;
  border-right:2px solid var(--tx2);border-bottom:2px solid var(--tx2);
  transform:rotate(45deg);
  transition:transform var(--t-tint) var(--ease-out)}
.roomfold[open]>summary::after{transform:rotate(225deg);margin-block-start:2px}
/* مفتوحةً، السطر الهادي فوق يصير عنوان الحقل — فالمسافة بينهما
   قريبة بقصد. ومقيسة: كل بكسل هنا يطلع من ميزانية الحالة
   المفتوحة، وهي أطول حالة بالصفحة. */
.roomfold .joinrow{margin-block-start:calc(5px + 2 * var(--g))}
/* ---------- طول الصفّ مُعلَن، لا موروث (٢٠٢٦-٠٧-٢٩) ----------
   كان مكتوبًا ‎min-height:calc(46px + 3.92g)‎ وجنبه «٤٦ أرضية، و٥٤
   على ٨٤٤» — والسطران معًا كانا يصفان شيئًا ما يشحن. المقيس:
   طول ‎.tkfield-in‎ **الذاتي** من القالب ٥٤٫٨٤ على كل بوابة
   (٢٧٫٨٤ سطرًا + ٢٥ حشوةً + ٢ حدًّا)، فأرضيةٌ بـ‎min-height‎ ما
   تنزل تحته ولا مرّة، وما تعلو فوقه إلا على ٩٣٢ وحدها. يعني
   الصفّ كان ٥٤٫٨٤ ثابتًا على كل بوابة، والإعلان زينة.
   **الإعلان كان مقصودًا والخاصيّة غلطًا**، فصار ‎height‎.

   وهذا مو ترفًا: الرفّ اللي يقوم في §«الرفّ الواحد» آخر الملف
   ينقاس على صفٍّ **معلوم الطول**؛ صفٌّ طوله يجي من صندوق مكوّنٍ
   آخر ما ينقاس عليه شي.

   والمشحون فعلًا — مكتوبٌ كما هو، لا كما نتمنّاه: القالب يحطّ
   ‎.tkfield-in{min-height:52px}‎ وهي **أرضية صلبة تحت إعلاننا**،
   فالطول = ‎max(52, 46 + 3.92g)‎ ← ٥٢ على البوابات القصيرة،
   و٥٣٫٩٨ على ٣٩٠×٨٤٤، و٥٦٫١٩ على ٩٣٢. الأرضية أرضية القالب لا
   أرضيتنا، والكسوة ما تنقضها: صندوق البئر وخلوصه للتشكيل من
   ‎components.css‎ §الحقول، وله سببه المكتوب هناك.
   والمكسب المقيس من هالتصحيح ٢٫٨٤px على أقصر بوابة — صغير،
   ومكتوبٌ بحجمه.
   والحشوة الرأسية تنشال لأن حقل الإدخال يوسّط سطره الوحيد في
   صندوق المحتوى بنفسه: الخلوص فوق الحرف وتحته ١١٫٠٨px داخل
   الـ٥٢، أي عمليًّا نفس خلوص القالب (١٢/١٣)، ولا قصّ على شي —
   وما فيه ‎overflow‎ على هالصندوق أصلًا. والطول ما ينزل تحت هدف
   اللمس ٤٤ بحال. */
.joinrow{display:flex;gap:10px;align-items:stretch;
  --joinrow:calc(46px + 3.92 * var(--g))}
.joinrow .tkfield{flex:1 1 auto;min-width:0}
.joinrow .tkfield-in{height:var(--joinrow);padding-block:0}
/* والزرّ ما ياخذ الطول، ياخذه من الصفّ: ‎align-items:stretch‎ فوق.
   وهذا انقاس، ما انفترض — أول محاولة حطّت ‎height‎ على الاثنين،
   والطول الصريح **يبطّل الشدّ**، فطلع الحقل ٥٢ (أرضية القالب
   تحته) والزرّ ٤٦ جنبه: ستّة بكسلات فرق في صفٍّ واحد، بادية
   بالعين على ٣٧٥ و٣٢٠. الحقل يعلن الطول، والزرّ يشتدّ عليه —
   واحدٌ يقرّر ولا اثنان يتفقان بالصدفة. */
.joinrow .tkb-q{flex:0 0 96px}

/* ---------- الدفتر — سطر، مو لوحة أرقام ----------
   كان صحيفة بطبقتين: عنوان فوق وثلاثة أعمدة تحت. أكبر جسم
   بالثلث الأسفل يقول أرقامًا، والدعوة للّعب تحته وزنًا. وهذي
   إشارة «تطبيق» لا «طاولة». انطوى على شريط قصير: نفس المحتوى،
   ونفس دايرة القلم، بأقصر طول.
   دايرة القلم بقيت كما هي، وهي حكم صاحب البيت: ما تنشال، بس
   تنضبط. هندستها من صندوق الرقم نفسه (--ink-t/b/s/e في
   components.css)، فتصغر مع الرقم بلا ما ينكسر هامشها.
   وكلمات الأعمدة ١rem دايم — أرضية النصّ العربي، ما تنزل تحتها،
   وترث رفعة جذر القارئ كاملةً بلا سقف.
   والسطر ما ينفخ مثل الكتل: نَفَسه ربع نَفَس الباقي — شريط
   منطوٍ يبقى منطويًا مهما طالت الشاشة.

   ═══ حكمان من صاحب البيت (٢٠٢٦-٠٧-٢٩ · الجولة ٧) ═══
   «الدفتر ينكسر سطرين عند مقاسات، وما يصير» و«أرقام الدفتر ما
   تستعمل الفراغ — مايلة يمين». وهما عطبٌ واحد بوجهين، وعلاجهما
   واحد: البناء اللي كان يحكم الصفّ كان يقيس نفسه على محتواه
   بدل ما ياخذ الصحيفة.

   ١ · العنوان كان يزاحم الأعمدة على نفس المحور. وهذا يقفل
       الباب على «أعمدة متساوية» قفلًا حسابيًّا لا ذوقيًّا: أعرض
       عمود («قامت لك») لو تساوت الأعمدة عليه لطلب ثلاثة أضعافه،
       وما يبقى للعنوان مكان. فالعنوان انتقل سطرًا فوق — سطره
       هو، وخيطه معه — والأعمدة ورثت عرض الصحيفة كامل.
   ٢ · و.lg-cells كانت flex:0 1 auto: صندوقٌ بمقاس محتواه. فالفاضي
       ما ينوزّع، ينركم بطرفٍ واحد — والطرف في RTL هو اليسار.
       صارت شبكة ثلاثة أعمدة 1fr: تتساوى بالبناء، وما تقدر تميل.
   ٣ · واللفّ اللي انضاف بالجولة ٦ (‎flex-wrap:wrap‎) انشال. كان
       علاجًا لقارئٍ كبّر خطّ متصفّحه فطلع الصفّ برّا الغرفة
       و‎.room{overflow:clip}‎ ياكل «رقمك» و«٥٨٪» بصمت. واللفّ
       يمنع القصّ لكنه يكسر السطر — وكلاهما مرفوض. الشبكة تحلّ
       الاثنين معًا: ‎1fr = minmax(auto,1fr)‎، فالعمود ما ينزل
       تحت محتواه الأدنى، والزيادة تُردّ من العمودين الباقيين،
       والصفّ يبقى صفًّا واحدًا بلا قصّ.

   ═══ الأرقام كلها من رِجّ واحد، وأمرُه مكتوب ═══
     node _probe/ledger-fit.mjs
   يمشي البوابات الخمس × جذر ١٦/٢٠/٢٤، وعليها ٣٢٠×٥٦٨، ويطبع
   لكل خانة: عرض الصحيفة الداخلي، وعرض كل عمود، ومحتواه الأدنى،
   والفسحة، وخلوص دايرة القلم عن الفاصل، وعدد الصفوف، والقصّ.
   ما يُكتب هنا رقمٌ ما طلع منه.

   ═══ «الدفتر يقصّ رقمك على خطّ متصفّحٍ ٢٠» — ما انعاد ═══
   (٢٠٢٦-٠٧-٢٩ · الدورة ٣ · الجولة ١.) هذي شكوى لجنة التدقيق،
   وهي **العطب اللي انعالج هنا فوق** — لكن بمقاسٍ ثانٍ. انفحصت
   بالأمر نفسه، خمس بوابات × ثلاثة مقاسات، فطلعت كل خانة مطلوبة
   PASS: ما فيه قصّ، ولا تمرير أفقي، ولا عمودٌ محتواه أعرض منه،
   على جذر ٢٢٫٥ (= خطّ متصفّح ٢٠) في أي عرض. والخانة الوحيدة
   اللي يخرج فيها الصفّ من صندوق الصحيفة هي ‎٣٢٠×٥٦٨ على جذر ٢٧‎
   (= خطّ متصفّح **٢٤**) — وهي الخانة اللي يطبعها الرِّج ولا
   يحاسبها بحكم صاحب البيت، لأن عرضًا داخليًّا ٢٧٢px مع قارئٍ رفع
   خطّه ٥٠٪ ما يسعه صفٌّ واحد بلا قصّ عربي، وقصّ العربي ممنوع.
   وانضافت ٣٧٥×٥٥٣ للمصفوفة عشان الفرع الثالث ينسدّ: «بوابةٌ ما
   عند الرِّج» — عندَه الآن، وتمرّ على الثلاثة.
   فالجواب المكتوب هنا هو **«ما انعاد»**، بأمره، لا إصلاحٌ لعطبٍ
   ما انبان: علاجٌ يُشحن لعطبٍ ما يقدر أحدٌ يوريك إياه هو تغييرٌ
   بلا حارس، وهو بالضبط الشي اللي كلّف هالمشروع جولةً كل مرّة. */
.ledger{z-index:3;flex:0 0 auto;width:100%;max-width:350px;margin-inline:auto;
  margin-block-start:calc(6px + 14.75 * var(--g));
  display:grid;row-gap:calc(2px + 0.5 * var(--g));
  padding-block:calc(4px + 0.9 * var(--g)) calc(2px + 0.9 * var(--g))}
/* الحشوة العليا نزلت من ١١ لأن سببها راح: كانت تشيل نتوء دايرة
   القلم فوق صندوق الرقم (--ink-t). والنتوء الآن يعيش في فرجة
   الصفّين تحت سطر العنوان، لا في حرف الصحيفة. */

/* ═══ الرفعة العربية كانت تنقطع هنا بالضبط (٢٠٢٦-٠٧-٢٨ · الجولة ٤) ═══
   ثلاثة مقاسات بهالملف كانت مكتوبة px صريحة، فرفع الجذر ما يمرّ
   منها ولا بالمئة: الدفتر كله كان ياخذ صفر رفعة. الآن الأرضية
   بالـrem والزيادة السائلة بالبكسل فوقها: الرفعة تُحمل، والمنحنى
   السائل يعيش. والسقف بالـrem كذلك فما ينفلت على متصفّح جذره
   ٢٠px.
   والعنوان نزل سقفه من ١٫٢٥rem إلى ١٫١٢٥rem — أي إلى --ty-plate
   نفسها. صار سلّمًا للسعة لا تجاوزًا للعدّة: القالب يحطّ المقاس،
   والكسوة تقول متى الشاشة أقصر من أن تحمله. وثمنه انشترى به
   سطرُ العنوان نفسه. */
.ledger h2{font-size:clamp(1rem, calc(1rem + 1.1 * var(--g)), 1.125rem)}
.ledger .lg-cells{margin-block-start:0}
/* nowrap مو زينة: «قامت لك» كلمتان، ولو انكسرت لصار العمود
   سطرين — وهو نفس العطب اللي انشال، بمكان ثانٍ. الشبكة تضمن إن
   العمود ما ينضغط تحت مقاسه الأدنى، وnowrap تضمن إن مقاسه
   الأدنى كلمةٌ واحدة على سطر. */
.ledger .lg-cell .k{white-space:nowrap}
.ledger .n{font-size:clamp(1.21875rem, calc(1.21875rem + 0.16 * var(--g)), 1.3125rem)}
.grow{flex:1 1 auto;min-height:0}

/* ---------- الشاشات الضيّقة — الشريط ينقبض، ما ينزّ ----------
   تحت ٣٧٥ تنقبض حشوة الصحيفة ٢٠→١٢، فيرجع للأعمدة ١٦px من
   العرض. وهذا كل ما تبقّى من إغاثة كانت أطول: حشوة العمود
   ٧px انشالت لأن العمود ما عاد فيه حشوة أصلًا — الفاصل انتقل
   لنصّ فرجة الشبكة، فخلوص دايرة القلم عنه صار نصف فرجة بالبناء
   بدل ما يكون فرقًا بين حشوة وعرض.
   (وكان مكتوبًا هنا «العمود ٦٧٫٢ عرضًا والدايرة ٦١، فخلوصها
   ٣٫١px». المقيس على البناء اللي كان مشحونًا: العمود ٦٥٫٤١
   والدايرة ٧٨٫١٧ — أي إن الدايرة كانت تعبر الفاصل ولا تخلص عنه.
   رقمٌ مطمئنٌّ عن حالة ما كانت موجودة، وهذا أخطر من عطبٍ مكشوف.) */
@media (max-width:374px){
  .ledger{padding-inline:12px}
}

/* ---------- الشاشات العريضة — تكيّف ثانوي، مو تصميم ثانٍ ---------- */
@media (min-width:720px){
  .room{padding-inline:32px}
}

/* ============================================================
   الجوّال مضجوعًا — انقاس أولًا، ثم انعُولج بقدر ما يسمح القانون
   ٢٠٢٦-٠٧-٣١ · الدورة ٣ · الجولة ٢.

   ═══ الحال قبل هذا القسم، مقيسًا ═══
   ولا كلمة ‎landscape‎ ولا ‎orientation‎ في السلسلة المشحونة كلها،
   ولا بوابةٍ مضجوعة في أي رِجّ. والمقيس على أربع بوابات مضجوعة
   بحافّة ‎0/21‎ (وهي حافّة الآيفون مضجوعًا: ما فيه نتوء فوق،
   وشريط البيت تحت):
     مطويّة  926×428 y134 · 844×390 y172 · 667×375 y187 · 780×360 y202
     مفتوحة  926×428 y167 · 844×390 y205 · 667×375 y220 · 780×360 y235
   والأفقي صفرٌ في الاثنتي عشرة خليّة، والقياس مستقرّ — أي إن
   الصفحة **تمرّر ولا تقصّ**، وهو اللي يقوله MOLD عن كل ما تحت
   الأرضية. الأرقام تُقرا من الرِّج لا من هنا:
     ‎_probe/gates.html?gates=844x390,926x428,780x360,667x375&sa=0,21‎
   وهي خانةٌ في ‎node _probe/a-all.mjs‎ من هذي الجولة.

   ═══ وليش ما انشتري الصفر، مكتوبًا لا مُدَّعى ═══
   الطول المتاح مضجوعًا ٣٣٩–٤٠٧. وأرضية المطويّة ٥٤١، وهي —
   بنصّ MOLD — **ركامٌ من حدودٍ دنيا كلٌّ منها مكتوبٌ في قانون**:
   رفّ الحزّة، وهدف اللمس ٤٤ على السطر الهادي، وسلّم الأزرار
   ٥٦/٥٠/٤٤، وصندوق البئر، وسطر الدعم العربي ١rem×١٫٧٥. فما فيه
   ٢٠٠px تنطلع من عمودٍ واحد بلا ما يُسمّى القانون المكسور، و«ضيّق
   حشوة» مو متاحة. فاللي انشتري هو اللي يقدر البناء يعطيه: **عمودان
   بدل عمود**، والعرض مضجوعًا ٦٦٧–٩٢٦ والغرفة كانت تسقّفه عند ٤٣٠
   فتترك أكثر من نصف الشاشة فاضيًا.

   ═══ والدفتر هو اللي ينتقل، لا المسرح — وهذا شرطٌ لا ذوق ═══
   الورقة المرميّة تقعد بـ‎top:calc(100% + --stage-gap + 11px)‎ من
   **المسرح**، فتدخل خلف اللوح وتطلع من نافذة الحزّة. فلو انتقل
   المسرح لعمودٍ ثانٍ لطاحت الورقة على الطاولة وصارت نافذة الحزّة
   تكشف جوخًا — وهو بالضبط عطب الجولة ٤ («العضّة تُقرا ركنًا
   مرسومًا لأن ما وراها إلا الطاولة»). فالمسرح واللوح يبقيان فوق
   بعض في العمود الأول، والدفتر وحده ينتقل.

   وما يزال تحت الأرضية، ومكتوبٌ إنه كذلك: المكسب يُقرا في نفس
   الرِّج، والخليّة تبقى تمرّر. تمريرٌ أقصر ليس صفرًا، والصفر هنا
   ما يُشترى إلا بكسر قانون.
   ============================================================ */
@media (orientation:landscape) and (max-height:600px){
  .room{max-width:none;display:grid;justify-content:center;
    grid-template-columns:minmax(0,350px) minmax(0,350px);
    grid-template-rows:auto auto;
    align-content:start;column-gap:20px}
  .stage {grid-column:1;grid-row:1}
  .panel {grid-column:1;grid-row:2}
  .ledger{grid-column:2;grid-row:2;align-self:start;margin-block-start:0}
  /* الذيل شغلُه يبلع الفضلة في عمودٍ واحد. ما فيه فضلة هنا، وفي
     الشبكة يصير صفًّا ثالثًا فاضيًا يطوّل الصفحة. */
  .grow{display:none}
}

/* ============================================================
   الرفّ الواحد — الدفتر وصفّ الرمز ما يقعدان مع بعض

   ═══ حكم صاحب البيت (٢٠٢٦-٠٧-٢٩) ═══
   «فتح ‹عندك رمز؟› يخلّي الصفحة تمرّر. وهذا ما ينفع في تطبيق
    جوّال.» فالردهة تقعد في شاشة واحدة **مطويّةً ومفتوحةً**، على
   البوابات الأربع، والحافّة الآمنة شغّالة.

   ═══ ليش ما انشُري المكان من الإيقاع ═══
   الذيل ‎.grow‎ هو الوحيد اللي يقدر يبتلع الطيّة، وطوله يطبعه
   رِجٌّ يُكتب أمره — عمود ‎slack‎ في ‎_probe/insets.html‎ §A، ومعه
   ‎grow (slack)‎ في §C. **اقرا العمود، ولا تنقله هنا.** واللي
   يقوله شكل العمود، وهو المهمّ: الذيل **رقمٌ واحدٌ تقريبًا على
   البوابات الأربع كلها** — ما يفرق بين ٦٦٧ و٨٤٤ إلا كسورًا —
   وينزل صفرًا على اللي تحت الأرضية. وصفّ الرمز يطلبه ونصفه.
   والسبب بنيويّ لا عارض: داخل النطاق السائل (‎--g‎ من ٦٤٠ إلى
   ٩٠٠ طولًا متاحًا) مجموع معاملات ‎--g‎ في العمود **يزيد على ١٠٠
   لكل ١٠٠px**، فالإيقاع ياكل كل بكسل زايد وزيادة — ولهذا الذيل
   ما يكبر مع الشاشة داخل النطاق. وتحت ٦٤٠ ما فيه ذيل أصلًا لأن
   ‎--g‎ صفر. والاستثناء الوحيد فوق ٩٠٠، حيث ‎--g‎ يوقف عند ٢٫٦
   فيرجع الذيل يكبر بكسلًا ببكسل (وينقرا في نفس العمود على
   ٤٣٠×٩٣٢) — بس بواباتنا الأربع كلها **تحت** التسعمئة، فما
   ينفعنا. يعني ما فيه مكانٌ يُشترى من الإيقاع حيث نحتاجه:
   لازم جسمٌ يقوم.
   (وشراؤه بجعل ‎--g‎ سالبًا انرفض بالقياس في جولةٍ سابقة: هدف
    اللمس ينزل تحت ٤٤. والقصّ ممنوع أصلًا، والتمرير هو الشكوى.)

   ═══ الآليّة، بجملة — وانقلبت بحكمٍ ثانٍ، فتُكتب منقلبة ═══
   كانت: **«دفترك» ينطوي لمّا ينفتح «عندك رمز؟»**، فصفّ الرمز
   يقعد في رفٍّ موجود.
   وصارت (٢٠٢٦-٠٧-٢٩ · حكم صاحب البيت): **الدفتر ما ينطوي — ينزل
   وبس، والمسرح هو اللي يدفع.** «الدفتر ما يختفي» كلمته، والثمن
   انطلع من حشوة المسرح العليا وفجوته ومقاس العلامة (القواعد الثلاث
   في آخر هذا القسم)، ومن حذف النداء اللي طلب هو نفسه.
   وكل اللي تحت هذا السطر انكتب للآليّة **الأولى**. الحساب اللي
   يليه — «الرفّ اللي يقوم يتنفّس ١٤٫٧٥+٠٫٩+٠٫٩» — كان يعدّ رفًّا
   ما عاد يقوم؛ خُطّ ولا انمسح، لأن الخلاصة اللي تحته صحيحة وما
   تعتمد عليه: **الشرط المقيس هو الشرط، مو رقمًا يُحفظ.**

   وليش هي بنيويّة لا مضبوطة باليد: ما فيها طرح بكسلات على أطوال
   اليوم. الرفّ اللي يقوم — الدفتر وهامشه — يتنفّس ‎١٤٫٧٥ + ٠٫٩ + ٠٫٩‎
   من ‎--g‎، وصفّ الرمز اللي يقعد يتنفّس ‎٢ + ٣٫٩٢‎ منه **على الأكثر**
   (أرضية القالب ٥٢ تبلع نصيبه على البوابات القصيرة). فالفضل
   موجبٌ عند ‎--g = 0‎ ويكبر كل ما طالت الشاشة، والمعاملات كلها
   مكتوبة في هذا الملف لا مقدَّرة. ولو قصرت الصفحة ٢٠–٤٠px
   (الرِّيل والدفتر يتغيّران في نفس الجولة) قصرت الحالتان
   **سواءً**، لأن الفرق بينهما لا يمرّ على أي جسمٍ ثالث.
   والشرط المقيس هو الشرط، مو رقمٌ يُحفظ: **ولا خليّة حمراء على
   البوابات الأربع، مطويّةً ومفتوحةً، والحافّة الآمنة شغّالة.**
   وهذي هي الصياغة الصامدة. أما «المفتوحة ما تطول المطويّة» فكانت
   نتيجةً لآليّةٍ انقلبت، وانقلبت معها: المفتوحة اليوم **أطول**،
   لأن الدفتر ما عاد ينطوي. والأرضيتان المقيستان بالبحث الثنائي
   على ‎_probe/gates.html‎: المطويّة ‎٥٤١‎، والمفتوحة ‎٥٧٤‎ — وقبل
   حكم صاحب البيت كانتا ‎٥٩٧‎ و‎≤٥٧٦‎ بالترتيب المعكوس. الرقمان
   يعيشان في MOLD.md مع أمرَي توليدهما، وما ينكتبان هنا مرّتين.

   والحارس أمرٌ يُكتب، مو انتباه — وهذي هي الخلاصة اللي المشروع
   دفع ثمنها ثلاث مرّات: أي تغيير يقلب هالعلاقة يطلع خليّةً حمراء
   في نفس الرِّج اللي يطبع الأرضية، وهو صار يقيس الحالتين:
     ‎_probe/gates.html?open=1&sa=59,34‎
     ‎_probe/gates.html?sa=59,34‎          (نفس البوابات، مطويّة)

   ═══ ما لا ينكسر ═══
   ولا سطر جافاسكربت انضاف: الحالة تنقرا من ‎<details open>‎ نفسها،
   والصفحة باقية على سطرها الواحد. و‎:has()‎ مستعملة أصلًا في هذا
   النظام — ‎.tkbite‎ يرث حالة ابنه بها — فما هي اعتمادًا جديدًا.
   ودرجات الفشل كلها تنزل ناحية الظهور لا الإخفاء:
     · ما عرف المتصفّح ‎:has()‎ → القاعدتان تسقطان، فالمسرح يبقى
       على مقاسه المطويّ والصفحة ترجع تمرّر — ما يضيع محتوى.
     · ما عرف ‎<details>‎ → ما فيه ‎[open]‎ أصلًا، فالأبناء ظاهرون
       والدفتر ظاهر: «إذا ما اشتغل شي، كل شي ظاهر».
   والدفتر ما يروح ولا يرجع، فما فيه حركة دخولٍ تتكرّر عليه.

   ═══ وأثرٌ على رِجّ الحوافّ — انقلب هو كمان ═══
   (٢٠٢٦-٠٧-٢٩ · الجولة ٨.) كان مكتوبًا هنا: «‎a-edge.py‎ يعلن
   الدفتر صفًّا حالته ‎("rest",)‎ وحدها… **الدفتر ما له بكسل في
   الحالة المفتوحة أصلًا**. السطر ما يتغيّر، والسبب يتغيّر.»
   والجملة انقلبت مع الآليّة وما انتبه لها أحد: الدفتر ما ينطوي،
   فله بكسل، ومقيسًا على الشجرة المشحونة في الحالة المفتوحة على
   ٣٩٠×٨٤٤ يقعد عند ‎y = 603.69‎ وحرفه السفلي ‎697.16‎ — أي ١٤٧px
   **داخل** الإطار.
   يعني الصفّ كان يتخطّى جسمًا منرسمًا كامل، **ويطبع كلمة
   «skipped» وهو يتخطّاه** — وهذا بالضبط العطب اللي انبنى له
   عمود الحالات. وانمسح الصفّ بـ‎("rest","open")‎، وانقاس، فطلع
   ‎٣٫٤٦٠‎ — أوطأ حافّة في النظام. أي إن الجسم اللي كان يستثني
   نفسه هو الأرضية.
   والخلاصة: عمود الحالة صادقٌ ما دام السبب اللي خلّى الحالة غير
   منطبقة صادقًا. ويوم يغيّر صاحب البيت السلوك، **الصفّ جزءٌ من
   التغيير**، ما هو تعليقًا يتبعه.
   ============================================================ */
/* ٢٠٢٦-٠٧-٢٩ · بكلمة صاحب البيت: الدفتر ما يختفي لمّا ينفتح
   الرمز — ينزل وبس. اللي دفع ثمن الحالة المفتوحة هو حذف النداء
   من المسرح (طلب صاحب البيت نفسه)، وما تبقّى ياخذه المسرح من
   حشوته العليا وفجوته وحدهما. ولا شي ينمسح. */
.room:has(.roomfold[open]) .stage{
  padding-block-start:calc(4px + 9 * var(--g));
  --stage-gap:calc(5px + 11 * var(--g))}

/* ==========================================================================
   Part 3: formerly styles/saikal.css
   ========================================================================== */

/* ============================================================
   سيكل — طبقة الهوية الجديدة
   تُحمَّل بعد components.css فتغلبها بالترتيب لا بالـ!important
   إلا حيث القناع نفسه لازم ينشال.

   ما بقي من تَك (مقصودًا): سلّم الارتفاع، الهندسة السائلة،
   الطباعة العربية، ومروحة الورق. هذي أدوات، ما هي هوية.

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

   والبنفسجي: غمزة الوكيل وحدها. نقطة عند اسم اللاعب الآلي،
   ولا شيء غيرها. أرضيةٌ بنفسجية تقتل الإشارة.
   ============================================================ */

/* ١ · تنشال العضّة — اللوح مستطيل نظيف */
.tknotch,.tknotch>.face,.tknotch>.face::after{
  -webkit-mask-image:none!important;mask-image:none!important}
.tknotch>.face{border-radius:var(--r-sheet)}
.tknotch>.face::after{border-radius:calc(var(--r-sheet) - 1.5px)}

/* ٢ · سطح اللوح: كحل + حدّ شعرة، بلا حوافّ مضاءة ثقيلة */
.tknotch>.face{
  background:linear-gradient(168deg,
    color-mix(in srgb, var(--s-panel-hi) 92%, white 8%) 0%,
    var(--s-panel) 46%,
    var(--s-panel-lo) 100%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.055);
}

/* ٥ · لغة «العضّة» كلها — الزرّ والدفتر والحلقة.
   العضّة كانت توقيع تَك: ركنٌ مقضوم يقول «ورقة». تنشال من كل
   جسم يحملها، فترجع الأشكال مستطيلات نظيفة بنصف قطرٍ واحد.
   ‎!important‎ هنا لأن القناع نفسه مُعلَن على العنصر، وما ينغلب
   بالترتيب وحده. */
.tkbite>.tkb-1{-webkit-mask-image:none!important;mask-image:none!important}
.tkbite::before{display:none!important}
.tkledger::before,.tkledger::after{
  -webkit-mask-image:none!important;mask-image:none!important}

/* ٦ · نصف قطر واحد يحكم كل الأجسام — سلّمٌ لا تشكيلة */
.tkbite>.tkb-1{border-radius:var(--r-btn-1)}
.tkledger::before,.tkledger::after{border-radius:var(--nr)}

/* ٨ · غمزة الوكيل — شكل العلامة نفسه لا نقطة عامّة.
   النقطة الدائرية كانت أي نقطة؛ والعقدة (نقطتان وكوعٌ بينهما)
   هي بالضبط ما في العلامة، فتُقرا استشهادًا لا زينة. */
#soloButton{position:relative;padding-inline-end:2.4em}
#soloButton::before{content:"";position:absolute;
  inset-inline-end:.85em;top:50%;transform:translateY(-50%);

  -webkit-mask:url("../assets/saikal-node.png") center/contain no-repeat;
          mask:url("../assets/saikal-node.png") center/contain no-repeat}

/* ٩ · الورقة الرابعة — يتيمة بعد رحيل العضّة.
   مكتوبٌ عند إعلانها إنها «الوحيدة اللي ما تنشاف إلا من نافذة
   العضّة»، وحافّتها المايلة كانت تقطع درجة الحزّة فتُقرا طيّة.
   فلمّا راحت النافذة، ما بقي لها ما تُقرا فيه: تقعد فوق ركن
   اللوح لصاقةً لا ورقة. تنشال مع سببها. */
.tkfan>:last-child{display:none!important}

/* ١٠ · أرضٌ هادئة تحت العلامة.
   قيسَ: نقاط الوكيل البنفسجية على السدو المزركش تعطي تباينًا
   ‎1.27:1‎ — أي لا تُقرا. والإشارة اللي ما تُقرا ليست إشارة.
   والعلاج ليس تفتيح العلامة (ممنوع تعديل حبرها)، بل تهدئة ما
   تحتها: هالةٌ من لون الأرضية تحت العلامة وحدها، تخفت للشفافية
   قبل حافّتها فما يبين لها حدّ. الزخرفة تكمل، والغمزة تبين. */
.tkmark-img{
  background:
    url("../assets/saikal-mark.png") center/contain no-repeat,
    radial-gradient(ellipse 64% 60% at 50% 47%,
      rgba(10,11,18,.90) 0%, rgba(10,11,18,.72) 42%,
      rgba(10,11,18,.34) 64%, rgba(10,11,18,0) 78%)}

/* ١١ · الطيّة تفتح لتحت، والعلامة ما تصغر.
   كان مكتوبًا: ‎.room:has(.roomfold[open]) .tkmark-img{width:…88px}‎ —
   أي إن فتح «عندك رمز؟» يقلّص العلامة ٤٠px ويسحب اللوح لفوق.
   قيسَ: مغلقًا يبقى ‎120.2px‎ فاضيًا تحت الدفتر، والطيّة تحتاج
   ‎63.1px‎ وحدها. فالمكان موجود تحت، والتصميم كان ياخذه من فوق.
   العلامة تثبت، والنموّ ينزل في الفراغ اللي كان مهدورًا. */
.room:has(.roomfold[open]) .tkmark-img{
  width:clamp(104px, 92px + 5.6 * var(--g), 132px)}

/* ١٢ · المسرح ما ينقبض — لا حشوته ولا فجوته.
   (على الشاشات القصيرة يبقى الانقباض: ما فيه فائض يُؤخذ منه.) */
@media (min-height:700px){
  .room:has(.roomfold[open]) .stage{
    padding-block-start:calc(8px + 19 * var(--g));
    --stage-gap:calc(11 * var(--g))}
}
/* على ٦٦٧ يبقى انقباض المسرح كما صُمّم أصلًا: ما فيه فائضٌ
   يُؤخذ من مكانٍ آخر. العلامة لا تصغر — ذاك التنازل مرفوض. */
@media (max-height:699px){
  /* ثابتٌ في الحالتين — لو انقبض عند الفتح تحرّك العنوان معه. */
  .stage, .room:has(.roomfold[open]) .stage{
    padding-block-start:calc(3px + 9 * var(--g));
    --stage-gap:calc(4px + 7 * var(--g))}
}

/* ١٣ · العمود يملأ الصفحة، والطيّة ما تحرّك شيئًا.
   قيسَ: ‎DIV.grow‎ (‎flex-grow:1‎) كان يبتلع ‎137.8px‎ تحت الدفتر،
   والطيّة تحتاج ‎63.1px‎. فالفائض ينتقل للّوح بدل ما يُهدر: يكبر
   اللوح مقدّمًا حتى يسع حالته **المفتوحة**. وعندها لا ينمو شي
   عند الفتح — المسرح ثابت، والعلامة ثابتة، ولا تمرير. */
/* اللوح يلزم مقاسه: محتواه + حجز الطيّة، بلا تمطّط زائد.
   والفائض الباقي ينزل تحت الدفتر فيُقرا هامشًا، لا فراغًا داخل
   صندوق. (‎.grow‎ يرجع ياخذه، لكن بعد ما قعد الدفتر على قاعه.) */
.panel{flex:0 0 auto}

/* الدفتر أوسع نَفَسًا — لكن بقدر ما تسمح الشاشة.
   ‎--g‎ يقيس فائض الطول: صفرٌ تقريبًا على ٦٦٧، و٢٫٠٤ على ٨٤٤.
   فالنَفَس يزيد حيث يوجد مكان، ولا يفيض على القصيرة (جُرِّب
   حشوٌ ثابت فطلع ‎OVERFLOW=59‎ على ٦٦٧). */
.tkledger{min-block-size:calc(82px + 15 * var(--g))}
.panel>.pin{height:100%;display:flex;flex-direction:column}

/* ١٤ · الطيّة تحجز مكانها مقدّمًا.
   بقيَ اللوح ينمو ٣٠٫٦px عند الفتح فيزحف لفوق، لأن الهامش اللي
   فوقه ‎auto‎ فيبتلع الفائض ويردّه. فالحلّ ألّا يتغيّر طول اللوح
   أصلًا: الطيّة تاخذ طولها **مفتوحةً** وهي مطويّة.
     الملخّص ٤٤ + فجوة الصفّ (٥ + ٢g) + الصفّ (٤٦ + ٣٫٩٢g)
   = ٩٥px + ٥٫٩٢g — مشتقّ من نفس الحسابات المكتوبة، لا رقمًا مقيسًا.
   وعندها: الفتح ما يحرّك بكسلًا واحدًا في الصفحة. */
/* الحجز انتقل من الطيّة إلى اللوح، ومقسومًا نصفين.
   كان الحجز داخل الطيّة فيقعد فراغًا **تحت** «عندك رمز؟» — يُقرا
   عطبًا. الآن يُقسم حشوًا أعلى وأسفل المحتوى: مطويًّا تقعد الأزرار
   في وسط اللوح، ومفتوحًا يُفرَج الحشو فترتفع الأزرار ويحلّ الصفّ
   محلّها. طول اللوح ثابت في الحالتين، فما تتحرّك الصفحة. */
.panel>.pin{justify-content:flex-start}

/* ── الطيّة: الطول ثابت رياضيًّا، لا تقريبًا ────────────────
   الفارق اللي تضيفه الطيّة مكتوبٌ في العدّة نفسها:
     صفّ الرمز = calc(46px + 3.92g)  ·  فجوته = calc(5px + 2g)
     الفارق    = 51px + 5.92g
   فلو حجزنا **نفس** هذا المقدار ورجّعناه عند الفتح، صار طول
   اللوح ثابتًا بالمطابقة لا بالتقريب. (المحاولات السابقة حجزت
   ٥٧ ثم ٤٦ فبقي انزياحٌ صغير — الرقم لازم يطابق، لا يقارب.)

   والحجز يُوزَّع على فجوات العمود الأربع بدل ما يقعد فجوةً واحدة
   فوق أول زرّ: مطويًّا يتنفّس اللوح بانتظام، ومفتوحًا يتقارب
   وينفتح مكان الصفّ. فالأزرار ما تقعد مزحزحةً لتحت بلا سبب. */
/* الفارق مقيسٌ لا مفترَض: صفّ الرمز يتجاوز صيغته على الشاشات
   القصيرة (٥٢ فعلًا مقابل ٤٧٫١ حسابًا) لأن محتواه يفرض حدًّا.
   فالمعادلة مبنيّة على قياسين: ٦٦٧→٥٧٫٥٤ و٨٤٤→٦٣٫٠٨. */
.panel>.pin{--fold-delta:calc(56.7px + 3.13 * var(--g))}
/* الحجز يقعد **تحت الزناد** لا موزَّعًا على فجوات العمود:
   موزَّعًا كان يحرّك خمسة من ستة عناصر، وأكثرها الزرّ اللي
   ضُغط للتوّ (‎-63px‎ = ١٫٤× طوله) فتنزل الإصبع على حقلٍ جديد.
   تحت الزناد: لا يتحرّك شيءٌ فوقه إطلاقًا. */
/* الحجز ينتقل من داخل اللوح إلى **تحته**: داخلًا كان يقعد
   ٧٧px حفرةً ظاهرة في الحالة الافتراضية. تحته: اللوح يلزم
   محتواه، والفجوة اللي فوق الدفتر تحمل الحجز — نفس الحساب،
   بلا حفرة، والدفتر ما يتحرّك. */
/* الحجز يرجع **داخل الطيّة** كطولٍ أدنى: على اللوح كان يترك
   طوله يكبر ٦٣px، فتنهار فجوة اللوح/الدفتر إلى ١٫٧px على ٧٥٠.
   داخلها: طول اللوح ثابت، والفجوة رقمٌ واحد. */
.panel{margin-block-end:0}
.roomfold{min-block-size:calc(101px + 3.1 * var(--g))}

/* ١٥ · الفجوة بين المسرح واللوح تنقفل.
   قيسَ: هامش المسرح السفلي مرن، فيتقلّص ٥٣٫١ ← ٢٢٫٤ عند الفتح
   ويسحب اللوح لفوق ٣٠٫٧px. تثبيته يمنع الزحف، واللوح يكبر لتحت
   داخل حصّته المحجوزة (٤٩٤٫٧ متاحة · ٤٥٦٫٢ مطلوبة مفتوحًا). */
.stage{margin-block-end:calc(49px + 2 * var(--g))}

/* ١٦ · السدو الجديد.
   القديم كان مولَّدًا بنموذج صور، ورموزه ما هي سدوًا: صلبانٌ
   وفصوصٌ مدرّجة، ونسيجٌ يُقرا تريكو (Fair Isle) لا سدوًا. والسدو
   **سداةٌ ظاهرة**: أشرطة أفقية، وعويرجان (مثلّثات متقابلة)، وشجرة.
   الجديد مرسومٌ بالكود لا بنموذج — ‎design/tak/sadu-gen.py‎ —
   فكل شكل فيه له اسمٌ ومصدر في ‎assets/sadu-najdi-v1-SOURCES.md‎،
   ودرزته مُتحقَّق منها برمجيًّا (الحافّتان متطابقتان). */
/* السدو الجديد — مولَّدٌ بنموذج صور (gpt-5.6-terra)، لا مرسومًا بالكود.
   المحاولة الأولى رُسمت بـPillow: رموزها صحّت وخامتها راحت، فطلعت
   هندسةً مسطّحة. والقماش أكثره خامة. هذا فيه صوف حقيقي وسداةٌ
   ظاهرة وشجرةٌ وعويرجان، بلا صلبان ولا تريكو. */
.tak{--im-weave:url("../assets/sadu-woven-v1.jpg")}

/* الأزرار سطران: عنوانٌ ثم شرح. */
.tkb-1,.tkb-2{display:flex;flex-direction:column;align-items:center;
  justify-content:center;line-height:1.22;gap:.12em}
.tkb-t{display:block;font-weight:var(--w-display,800)}
.tkb-s{display:block;font-style:normal;font-weight:400;
  letter-spacing:.01em}
/* الشرح ياخذ الرمزين المُدقَّقين لا خلطةً جديدة: color-mix تجاوزت
   ‎--ink2/--tx2‎ فنزل التباين إلى ٣٫١٥ و٣٫٨٨ (تحت AA). */
.tkb-1 .tkb-s{color:var(--ink2)}
.tkb-2 .tkb-s{color:var(--tx2)}
/* ‎.62em‎ ما تشتري فرقًا في العربية: أذيال الحروف تعيد الطول،
   فبان شرح الزرّ الثاني أطول من عنوانه. درجةٌ حقيقية بدلها. */
.tkb-s{font-size:.5em}

/* ٦٦٧ ضيّقة فعلًا: بعد كل التقليم يبقى ١٠px فائضة. الحجز وحده
   يُقلَّم هناك — الأزرار تنزل أقلّ، والعنوان والدفتر ما ينمسّان.
   (الفتح يكبّر اللوح قليلًا على هذي الشاشة، وينزل في فجوة الدفتر
   بلا تمرير — تنازلٌ مقيس، لا صدفة.) */
/* ٦٦٧: الأزرار تنحف بدل ما ينكسر الثبات (بإذن صاحب البيت). */
@media (max-height:699px){
  .tkb-1{--h-btn-1:64px}
  .tkb-1,.tkb-2{padding-block:calc(6px + 2 * var(--g))}
  .tkb-s{font-size:.58em}
}

/* ١٧ · الحركة — بعد التدقيق.
   العطب المقيس: تحريك ‎row-gap‎ ٣٤٠ms كان يجعل الصفحة **تمرّر
   فعلًا** ١٠٠–١٥٠ms عند الفتح (OVERFLOW_Y=٣٦ على ٨٤٤ و٥٣ على ٦٦٧):
   صفّ الرمز يظهر دفعةً واحدة (٦٣٫٠٦px)، وتعويضه — الفجوة — يمشي
   على ساعةٍ أخرى. نصفا معادلةٍ واحدة بزمنين. فالفجوة تُقفل
   **فورًا** (هي التعويض لا الموضوع)، والحركة تبقى على الصفّ وحده:
   شفافية وإزاحة، وكلاهما على المُركِّب لا على التخطيط.
   والأزمنة صارت من العدّة لا أرقامًا حرّة. */
.roomfold:not([open]) .joinrow{opacity:0;transform:translateY(-6px)}
@media (prefers-reduced-motion:no-preference){
  /* ساعةٌ واحدة للحركة الواحدة: كانت الشفافية ٢٠٠ms والإزاحة
     ٣٠٠ms على نفس العنصر، والشيفرون يخلص قبل الصفّ بـ١٠٠ms. */
  .joinrow{transition:opacity var(--t-tint) linear,
                      transform var(--t-tint) var(--ease-out)}
  .roomfold>summary::after{transition:transform var(--t-tint) var(--ease-out)}
  /* الخروج ما كان ينرسم إطلاقًا: ‎::details-content‎ يقفل فورًا.
     ‎allow-discrete‎ + ‎@starting-style‎ يعطيان الاتجاهين نفس الزمن. */
  .roomfold::details-content{
    transition:content-visibility var(--t-tint) allow-discrete,
               opacity var(--t-tint) linear}
  @starting-style{ .roomfold[open]::details-content{opacity:0} }
}

/* ── إصلاحات تدقيق البصر ─────────────────────────────────── */
/* الحقل كان تجويفًا أسود (‎.0054‎) أغمق من الأرضية، ويقلب السلّم. */
.tkfield{flex:1 1 auto}
/* الخانة كانت تجويفًا (‎#0E0F18‎) أغمق من أرضية الصفحة، فتقلب
   سلّم الارتفاع وتُقرا فتحةً مكسورة. اللون كان يُضبط ثم يُغطّى:
   ‎background-image‎ تُرسم فوق ‎background-color‎، والتدرّج كان
   من ‎--s-well-lo/--s-well‎ — أعمق درجتين في السلّم. */
.tkfield-in{background-color:var(--s-panel-lo)!important;
  background-image:linear-gradient(196deg,
    var(--s-table-lit), var(--s-panel-lo))!important;
  flex:1 1 auto}

/* الدفتر واللوح كانا ١٫٠٢:١ — درجتان بلا درجة. */
.tkledger::after{background-image:none;}

/* المروحة تهدأ فما تزاحم الفعل الأساسي في اختبار الغبش. */
/* ‎--dim‎ معلَّن inline على كل ورقة، وinline يغلب الورقة الخارجية. */
/* تعتيم المجموعة لا الورقة: ‎--dim‎ inline يحمل تدرّج العمق
   (.85/.90/.95)، ودهسه بـ!important سطّح الثلاث إلى ٠٫٩٩ نسبةً. */
.tkfan{filter:brightness(.62)}

/* عقدة الوكيل على الزرّ: ‎1.35:1‎ ما تُقرا — نفس العطب اللي
   عولج في العلامة. ترفع للوني الأفتح وتكبر قليلًا. */
#soloButton::before{width:.92em;height:1.33em}

/* حلقة تركيز الفعل الأساسي كان فيها ثقب ٤٥×٤٥ — قناع الحزّة
   باقٍ على ‎::after‎ بينما الزرّ نفسه انفكّ عنها. */
.tkbite::after{-webkit-mask-image:none!important;mask-image:none!important}

/* ── الجولة ٢: بقيّة تقرير التخطيط ──────────────────────── */
/* هدف اللمس كان ٣١٫٥px — تحت الأرضية ٤٤. */
.tkfield-lb{min-block-size:44px;display:flex;align-items:center}

/* الحقلان ما كانا على محورٍ واحد: ١٠٦px فرقًا في الحافّة.
   الآن يتمدّد كلاهما على نفس العمود ٤٢..٣٤٨. */
.panel>.pin>.tkfield{flex:1 1 auto;min-inline-size:0}
#playerName{flex:1 1 auto;min-inline-size:0}  /* يقاسم السطر مع الوسم، لا يبتلعه */

/* حشوة اللوح كانت ١٠ فوق مقابل ١٧–٣١ تحت في الحالتين — فراغٌ
   دائم تحت الزناد لا حجز. */
.panel>.pin{padding-block-end:calc(10px + 2 * var(--g))}

/* «٥٨٪» كانت تلبس أحمر العقيق (صبغة تَك متقاعدة) بنسبة ٠٫١٥٪
   من الشاشة — أربعة أضعاف إشارة الوكيل، على رقمٍ ثالثيّ. */
/* ‎components.css‎ يكتبها ‎.tkink svg .lg-a‎ (٠،٢،١) فتغلب
   ‎.tkink .lg-a‎ (٠،٢،٠) مهما تأخّر الترتيب. الأولوية تُطابَق. */
.tkink svg .lg-a,.tkink svg .lg-b,.tkink svg .lg-c{stop-color:var(--a-brz)!important}
.tkledger .aqeeq,[class*="aqeeq"]{color:var(--a-brz)}

/* حلقة تركيز الحقل كانت ١٫٣٢:١ — تحت أرضية ٣:١ لغير النصّ. */
.tkfield-in:focus,.tkfield-in:focus-visible,.tkfield-in.is-focus{
  outline:2px solid var(--a-hi);outline-offset:2px;box-shadow:none}

/* ‎tk-sweep‎ يحرّك background-position بلا نهاية = إعادة رسمٍ دائمة
   على ردهةٍ ساكنة. تُوقَف؛ اللمعة تبقى ثابتة. */
.tkb-1::after{animation:none!important}

/* ── الجولة ٣ ────────────────────────────────────────────── */
/* عقدة الزرّ ٢٫١١:١ — ما زالت تحت أرضية ٣:١ لغير النصّ. */
#soloButton::before{background-color:#A99FF9}

/* الدفتر: درجة سطحٍ حقيقية + نَفَس داخلي (كان ٥٫٤/٦٫٢px). */
.tkledger::after{background-color:var(--s-quiet-lo)}
.tkledger{padding-block:calc(9px + 2 * var(--g))}

/* فجوات اللوح على شبكة ٨: كانت ١٠/١٩/٢٥/١٤/١٨ — خمس قيم بلا سلّم. */
.panel>.pin{row-gap:16px}
.panel>.pin>*{margin-block:0}   /* السلّم صار من row-gap وحده */

/* قانون المولد ٣–٥× بين الفعل الأساسي والمُقارَن: كان ٢٫٦٤–٣٫٠٢
   ويسقط في ٣ بوابات من ٤. تقليم الخانة ٥٤٫٨٤→٤٨ يعبّرها كلها
   ويرجّع ٦٫٨px من الميزانية الرأسية (الأرضية ٤٤ سليمة). */
#playerName{block-size:48px}

/* الدفتر يُثبَّت من القاع، فأي بقيّة في طول اللوح (٠–١٫٥٥px بين
   البوابات) ما تنقله. .grow ما عاد يزاحمه. */
.grow{flex-grow:0}
.tkledger{margin-block-start:auto}

/* ٦٦٧ ما فيها فائض يُثبَّت منه: التثبيت من القاع هناك يفيض ٣٣px.
   فتُترك على سلوكها الأصلي — الفجوة مقاسة لا مثبّتة. */
@media (max-height:699px){
  .grow{flex-grow:1}
  .tkledger{margin-block-start:calc(6px + 6 * var(--g));
            padding-block:calc(3px + 2 * var(--g));
            min-block-size:auto}
  .panel>.pin{row-gap:10px;padding-block-end:6px}
}

/* ── الجولة ٤: ما هزمته الأولوية ────────────────────────── */
/* ‎.panel .tkfield+.tkbite‎ (٠،٣،٠) كانت تغلب ‎.panel>.pin>*‎ (٠،٢،٠)،
   فالسلّم طلع ١٦/٤١/٣٠/١٦ لا ١٦ موحّدًا. تُطابَق الأولوية. */
.panel .tkfield+.tkbite{margin-block-start:16px}
.panel .tkbite+.tkb{margin-block-start:0}

/* حجزُ حزّةٍ لم تعد موجودة: العنوان مزاحٌ ٤٦–٥٢px عن عمود اللوح
   بـ‎--pad-notch‎، والحزّة انشالت. يرجع للعمود نفسه ٤٢..٣٤٨. */
.panel .tkseats{padding-inline-end:0}

/* ‎#playerName{block-size:48}‎ كانت ميتة: ‎.tkfield-in{min-height:52}‎
   يفرض الأرضية. تُخفض عند مصدرها. */
.panel .tkfield-in{min-block-size:48px}

/* ==========================================================================
   Part 4: formerly styles/port.css
   ========================================================================== */

/* ============================================================================
   The port layer.

   This is the only stylesheet under `app/client/` that is not the captain's
   file, and it exists so that the other six can stay byte-identical: the
   design's identity stays auditable against `frontend-tak`, line for line,
   while the port gets the elements `GameAPIv1` needs and the imported design
   has no home for.

   It is loaded last, it is purely additive, and it introduces no colour, no
   type family and no radius of its own: every value below is a token from
   `design/tak/tokens.css` or a step of `game.css`'s own vertical rhythm
   (--k1..--k6). Where a token is not in scope on a page - the lobby does not
   load `game.css` - the fallback in `var(..., x)` is that token's own value.

   Each numbered section says what the design does, what `GameAPIv1` needs on
   top of it, and why. The numbers are the ones `lobby.js` and `game/game.js`
   cite next to the element they build.
   ========================================================================= */

/* Both pages budget the visible browser viewport. Dynamic units follow browser
   bars opening/closing; safe-area padding is deducted by each page once. */
:root { --app-vh: 100dvh; --app-vw: 100dvw; }

/* --- 0 · `hidden` means hidden ---------------------------------------------
   Every element this layer adds is shown and hidden with the `hidden`
   attribute, and every one of them is given a `display` here - which wins over
   the user-agent's `[hidden]{display:none}` on specificity alone. Stating it
   once is the whole fix; the alternative is a class per element that says the
   same thing twice. */

.pt-notice[hidden] { display: none; }

/* --- 1 · The lobby's notice line -------------------------------------------
   The imported lobby never called a server, so it has no element for a
   transport failure or one of the nine typed refusals. Creating a room can
   fail; the player has to be told which way, in the panel they pressed. */

#lobbyNotice.pt-notice {
  margin: calc(9px + 2 * var(--g, 0px)) 0 0;
  padding: var(--k2, 8px) var(--k3, 12px);
  border-radius: var(--r-btn-sm, 13px);
  font-family: var(--fu);
  font-size: .82rem;
  line-height: 1.5;
}

/* --- 11 · The lobby's wait -------------------------------------------------
   `createRoom` deals a hand and drives three automated seats before it
   answers, so on a phone the press is followed by seconds of nothing. The
   pressed button says so in its own subtitle - `lobby.js` swaps the text - and
   this is what makes the swap read as work rather than as a different label. */

.tkb.is-busy .tkb-s {
  background: linear-gradient(90deg,
    var(--tx3, rgba(242, 236, 221, .78)) 0%,
    var(--tx, #f2ecdd) 50%,
    var(--tx3, rgba(242, 236, 221, .78)) 100%) 0 0 / 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@media (prefers-reduced-motion: no-preference) {
  .tkb.is-busy .tkb-s { animation: pt-sweep 1.4s linear infinite; }
}

@keyframes pt-sweep {
  from { background-position: 220% 0; }
  to { background-position: -220% 0; }
}

.tkb[disabled] { cursor: progress; }

/* --- 12 · Behaving like an app --------------------------------------------
   The four things iOS Safari does that an app must not: rubber-band the table
   under the player's thumb, select the Arabic labels on a long press, offer to
   save a card face because the card is an image, and flash a tap highlight on
   a control that already has a pressed state. The design's own `viewport-fit`
   and `env(safe-area-inset-*)` budget is untouched: it is the single opinion
   about the notch, and this adds no second one. */

html, body {
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
}

body.gm {
  /* A drag on the board must not peel the page off the top of the screen. That
     is `overscroll-behavior` above, and it is the whole fix: the table is *not*
     `overflow:hidden`, because forbidding the scroll does not make the content
     fit - it makes the overflow land on top of the top bar instead. Where the
     board genuinely does not fit, §13 lets it scroll, which is the captain's
     own ruling for the lobby in the same position: "a shorter scroll is not
     zero, and zero here cannot be bought without breaking a law". */
  touch-action: manipulation;
}

/* Nothing on any page is selected or offered a callout by a long press, by
   mistake or otherwise; only a field a player types into keeps both (owner,
   report 55). One rule for the whole page, not a list of classes: a list
   leaves out whatever it does not name. The history and help pages carry the
   same rule in their own styles, because they load no port sheet. */
:where(html, html *) {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
:where(input, textarea, [contenteditable]) {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

.card > .face {
  pointer-events: none;
}

/* --- 13 · One design on every viewport -------------------------------------
   The desktop is not this layer's business, and that is deliberate: the
   captain's own `game.css` already answers a wide viewport at `min-width:520px`
   - the table becomes a phone-width column that centres, with the room spread
   around it - and its note says why ("the game is phone-first by intent, but
   opening it on a big screen has to read as a choice, not a defect"). One
   design everywhere is that rule, not a second layout, so nothing here widens
   it.

   What a phone turned sideways does is §36. This section's own answer - "what
   does not fit is scrolled to" - was this repository's reading of the captain's
   lobby ruling, and the captain replaced it on 2026-08-20. Nothing is left
   here, because there is nothing left to say: a wide viewport is already
   answered by a captain file. */

/* ============================================================================
   ROUND 1 · what three read-only audits found, fixed here
   ============================================================================
   Round 1 of the captain's design iteration. Three auditors scored the live
   build - visual fidelity 4.8/4.5, ergonomics 6.8, smoothness 6.7, loading
   6.5, asset weight 6.8 - and every numbered item below closes one of their
   ranked defects. The two calls they registered as the captain's are *not*
   here and are not worked around: replacing the card-face and mat art
   (visual D1/D2's art half) and what landscape should do (ergonomics D1).

   Still additive, still no captain file edited.
   ========================================================================= */

/* --- 14 · The mat holds its cards ------------------------------------------
   Visual D1, D7 · ergonomics D3.

   Measured: a 178x223 ornate frame holding four 46x61 cards, so 70% of it is
   empty with a full trick down and ~95% during the auction - "the single
   ugliest element in the app". And المكشوف, the card the whole first auction
   is a decision about, rendered 37x41 (27x25 on an SE) among cards of 66x92.

   The art is the captain's and is not touched. What is wrong is the *ratio*
   between the frame and what sits in it, and that is arithmetic: the played
   cards go from 0.64 of a card to 0.86, the exposed card from 0.56 to 0.92,
   and the frame's own padding drops from 0.30 of a card width to 0.12. The
   frame ends up holding cards instead of framing a hole. */

@keyframes pt-breathe {
  0%, 100% { opacity: .25; transform: scale(1); }
  50% { opacity: .9; transform: scale(1.02); }
}

/* The collision the audit measured was the score chips being *pushed*, so the
   chips are what stops flexing; the contract keeps its two lines rather than
   being truncated to `اخترا…`, which is worse than the wrap it replaced. Only
   the buyer's line - a name, and the one unbounded string here - ellipsises. */
.gm-deal-2 {
  display: block;
  max-inline-size: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- 26 · An outage does not make the dead rail look primary ---------------
   Ergonomics D6: while the server is unreachable the rail is disabled but
   still drawn with the gold outline, so it reads as *more* prominent than
   usual. And the notice covered the top bar outright. */
#act .btn[disabled] { filter: grayscale(.7) brightness(.7); box-shadow: none; }

/* --- 29 · The lobby's small finish -----------------------------------------
   Visual D10, D23, D24, D27 - each small, each the kind of thing a first-time
   player notices once and a returning player stops seeing.

   D10: the notice was a plain grey rectangle with no error colour, no icon and
   none of the panel's language, for a message that was also wrong.
   D23: `ادخل` was near-white, a value that appears nowhere else in the palette.
   D24: the empty ledger printed three literal em-dashes.
   D27: the name field was a borderless dark rectangle with no affordance. */

#lobbyNotice.pt-notice {
  display: flex;
  align-items: flex-start;
  gap: var(--k2, 8px);
  text-align: start;
  background: linear-gradient(180deg, rgba(240, 138, 128, .14), rgba(240, 138, 128, .07));
  box-shadow: inset 0 0 0 1px rgba(240, 138, 128, .45), var(--sh1, 0 1px 2px rgba(4, 22, 13, .45));
  color: var(--tx, #f2ecdd);
}
#lobbyNotice.pt-notice::before {
  content: "!";
  flex: 0 0 auto;
  inline-size: 20px;
  block-size: 20px;
  border-radius: 999px;
  background: var(--suit-dark, #f08a80);
  color: var(--s-void, #0a0b12);
  font-weight: var(--w-lead, 900);
  font-size: .79rem;
  line-height: 20px;
  text-align: center;
}

/* The quiet button takes the design's own quiet body instead of near-white. */
.tkb.tkb-q, .roomfold > summary.tkb-q {
  background: linear-gradient(180deg, var(--s-rise-hi, #4f5766), var(--s-rise-lo, #48505f));
  color: var(--tx, #f2ecdd);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07), 0 1px 2px rgba(0, 0, 0, .4);
}

/* An empty ledger says it is empty. Three em-dashes read as a rendering fault. */
.lg-cell .n[data-empty="1"] {
  color: var(--tx4, rgba(242, 236, 221, .46));
  font-size: .79rem;
  letter-spacing: .04em;
}

/* The name field is a field before it is focused. */
.tkfield-in {
  box-shadow: var(--well, inset 0 2px 5px rgba(4, 22, 13, .55)),
              inset 0 0 0 1px rgba(255, 255, 255, .09);
}
.tkfield-in:focus-visible { box-shadow: var(--well, none), inset 0 0 0 2px var(--a, #ecc330); }

/* --- 30 · A card on the smallest phone has room to be missed ---------------
   Ergonomics D9: with eight legal cards at 375 px the narrowest clickable strip
   measured 44.0 px - on Apple's floor with zero headroom, and only survivable
   because play is two taps. The fan opens a little at the narrowest viewport,
   which costs a few pixels of overlap and buys back the margin. */
@media (max-width: 380px) {
  body.gm { --card-w: clamp(50px, max(13.4vw, 7.4svh), 62px); }
}

/* --- 32 · The support and privacy line --------------------------------------
   The App Store needs reachable support and privacy surfaces, so the lobby
   carries links to `support/` and `privacy/`. The captain's lobby has no legal
   surface - an imported design with no such surface has nothing to link - so
   `lobby.js` creates them and this is their whole appearance.

   Discreet is the requirement and also the design's own manner: they sit under
   everything, in the muted text colour the page already defines, at the size
   the design uses for a caption. They remain underlined links with independent
   44pt-tall targets rather than decoration that has to be guessed at. */

.pt-foot {
  /* No block margin of its own: the lobby column is exactly one screen tall and
     the `.grow` spacer above it absorbs the difference, so anything this line
     adds beyond the targets below is a scrollbar on a page designed not to have
     one. The links' own padding is the whole spacing. */
  margin: 0;
  display: flex;
  justify-content: center;
  text-align: center;
  font-size: .78rem;
  line-height: 1;
}

.pt-foot > a {
  display: inline-block;
  padding: 1rem .75rem;
  color: var(--tx2, #a9a294);
  text-decoration: underline;
  text-underline-offset: .25em;
  opacity: .75;
}

.pt-foot > a:hover,
.pt-foot > a:focus-visible { opacity: 1; }

/* The lobby column is exactly one screen on a modern iPhone and the `.grow`
   spacer absorbs this line there - measured at 390x844: the page does not
   scroll with the link on it. On the shortest supported phone (375x667) that
   spacer is already at zero before this line exists, so the lobby gains a few
   pixels of scroll rather than losing the link or covering the ledger with it.
   The target stays at 44px there; only the air around it goes. */
@media (max-height: 720px) {
  .pt-foot > a {
    padding-block: 0;
    min-block-size: 44px;
    display: inline-flex;
    align-items: center;
  }
}

/* ============================================================================
   ROUND 2 · the second pass of the captain's design iteration
   ============================================================================
   Round 1 closed the three audits' ranked lists and left four calls with the
   captain. All four were ruled on, durably, on 2026-08-20, and §33-§36 below
   are this repository's half of them plus what a fresh audit of every non-lobby
   view found on the merged build. The rulings themselves are in
   `../README.md` ("All three were ruled on") and in `AGENTS.md`.

   Still additive, still no captain file edited, still no colour, type family or
   radius that is not the design's own.
   ========================================================================= */

/* --- 33 · A card has an edge ------------------------------------------------
   The faces are frozen (ruling 1) and nothing here touches one. What is not
   frozen is everything around a face, and around a face there was nothing: the
   design gives `.card` a white body, a 3% corner and a shadow that is invisible
   against navy, and the fan sits its cards 6px apart. Eight white rectangles
   with no edge between them read as one white band across the bottom of the
   screen - the loudest thing on a navy-and-gold table, and a blank one.

   The set's own SVG says where the edge is: inside a 238.1x332.6 viewBox the
   printed body is a 222.2x310.8 rect with a 10.6 corner, so a face is a rounded
   card with 3.3% of transparent margin around it - and `.card`'s white
   background has been filling that margin in, which is exactly why the printed
   corner never showed. Two additive things put it back:

   * the box's corner is taken to 5%, so the clip follows the printed corner
     instead of cutting a square around it, and
   * a hairline sits on the box, in the ink the design already uses for a card's
     own shadow, so where two cards overlap there is a line between them.

   `::after` rather than a `box-shadow` on `.card`: the design's drop shadow and
   §25's winning ring are both `box-shadow` on the same element, and replacing
   that property would take one of them out. */
.card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(4, 22, 13, .34);
  pointer-events: none;
}
.card { border-radius: 5%; }

/* --- 34 · The back behind a face that has not arrived -----------------------
   Ruling 4's backstop, and the invariant the other three parts exist to serve:
   **white is never a frame a player sees**. An `<img>` with nothing decoded in
   it yet paints nothing, so what showed through was `.card`'s own white body -
   a blank card, on the overlapped fan an unreadable one.

   The card back is what belongs behind a face that has not turned over. It is
   the design's own art, it is 46 KB, and every opponent fan on the table is
   already made of it, so by the time a face can be late the bytes are held.
   `game/game.js:cardElement` sets `data-face` the moment the face is decoded -
   from the held `Image` when the bytes are already in, which is every render
   after the first, and from the element's own `load` otherwise. */
.card { background-size: cover; background-position: center; }
.card[data-face="1"] { background-image: none; }

/* --- 36 · Landscape is locked to portrait ----------------------------------
   The captain's ruling 3, durable, 2026-08-20: **no landscape layout is ever
   built**. A rotated phone keeps the portrait arrangement, cleanly, with
   nothing reflowing and nothing to scroll to. `app/ios-shell` is already
   portrait-locked by its own manifest; this is the browser's half of the same
   posture, and it replaces §13's "what does not fit is scrolled to".

   What the ruling replaces, measured on the merged build at 852x393: the
   document is 575px tall in a 393px viewport, the hand starts at y=403 and the
   action rail at y=493 - both below the fold, with no scroll position from
   which the table and the hand are on the screen together.

   A browser rotates the viewport where a portrait-locked app does not, so the
   lock is the page declining the rotation: the column is built at the
   viewport's *other* two dimensions and turned back by a quarter. Nothing
   inside it knows - every rule above, every measurement in this file and every
   captain arithmetic is still reading a 390-ish wide, 844-ish tall column, and
   `--card-w`, the 44pt targets and the button ladder all land where they land
   in portrait. The player sees what a portrait-locked app shows them: the table
   stays with the phone rather than following the hand that turned it.

   `--vh` is restated because the design derives `--g` from it and `100svh` in
   here is the *short* side; the notch is taken from whichever long edge it
   landed on, because a rotation can put it on either. */
@media (orientation: landscape) and (pointer: coarse) and (max-height: 600px) {
  body.gm {
    transform: translateX(100svw) rotate(90deg);
    /* The column's own top is a screen *side* now, and which side depends on
       which way the phone was turned - so the notch is taken as whichever long
       edge reports one, and the home indicator's edge is kept clear on both
       short sides rather than guessed at. */
  }

  /* Which quarter-turn. `orientation: landscape` is true for both, and a
     portrait-locked app puts its top on the screen edge the device's own top
     turned into - the right one way, the left the other. `game/game.js`
     publishes `screen.orientation.type`; with no such reading the rule above
     stands on its own and the lock still holds, one turn out of two. */
  html[data-orient="landscape-secondary"] body.gm {
    transform: translateY(100svh) rotate(-90deg);
  }
}

/* `.gm-mine` is already the strip's containing block in every port layout;
   restating its position here overrode §35 and sent the hand off-screen. */
body[data-project-picker="labels"] .pt-project-tag {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  block-size: 26px;
  padding-inline: 8px 2px;
  border-radius: 13px;
  background: color-mix(in srgb, var(--s-well, #0b1626) 88%, transparent);
  color: var(--tx, #f4ecd8);
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
  border: 1px solid var(--a-hi);
}
body[data-project-picker="labels"] .pt-project-tag[data-pick="2"] { border-color: #b57bee; }
body[data-project-picker="labels"] .pt-project-tag-remove {
  position: relative;
  inline-size: 22px;
  block-size: 22px;
  min-inline-size: 22px;
  min-block-size: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 12px;
  line-height: 22px;
  cursor: pointer;
}
/* The visible ✕ is small; its touch target is not. */
body[data-project-picker="labels"] .pt-project-tag-remove::before {
  content: "";
  position: absolute;
  inset: -11px;
}
body[data-project-picker="labels"] .pt-project-tag-remove:focus-visible {
  outline: 2px solid var(--a-hi);
  outline-offset: 1px;
}
/* The project controls - the four labels, or سوا - are one pill each, all of
   one width, in two rows at the hand's right edge whose lower row shares the
   band of the viewer's name. No control sits over a card. Each pill is 36px
   tall with 9px between the rows, so its hit area reaches exactly 44x44 by
   growing 4px up and down: no two hit areas overlap, and the lower row's
   stops above the resting cards. The strip paints above a prepared card, so a
   control is never hidden by the card it is about. */
body.gm { --pill-w: 64px; --ctl-right: 12px; --ctl-gap-x: 6px; }
/* Narrower phones keep both rows on the name band beside the name, not over
   it: the one pill width steps down (50px, then 44px with a 4px gap on the
   narrowest), and every pill still keeps a 44x44 target. */
@media (max-width: 409px) {
  body.gm { --pill-w: 50px; }
}
@media (max-width: 350px) {
  body.gm { --pill-w: 44px; --ctl-right: 4px; --ctl-gap-x: 4px; }
}

/* ============================================================================
   37 · A2 · SADU COURT / ميدان السدو
   ============================================================================
   The launch redesign supersedes the imported table composition without
   changing its DOM or binding. One arched textile court now owns the scene:
   seats attach to its perimeter, the exposed/trick cards use hand scale, the
   player's fan bleeds to the glass, and decisions sit on the thumb rail.

   This is intentionally one complete presentation layer, rather than another
   sequence of local corrections to the old page-wide frame and miniature mat.
   The frozen face SVGs remain untouched. The lobby's live tokens, woven ground,
   lamp and falloff are the palette authority; the court adds no second colour
   system. Its central surface is the original generated `mat-court-v2.webp`,
   not the superseded tak illustration or a CSS-drawn imitation.
   ========================================================================== */

body.gm {
  --a2-page-pad: 10px;
  --a2-safe-t: max(10px, var(--sa-t));
  --a2-safe-b: max(8px, var(--sa-b));
  /* One physical card system. Every seat starts from the same 5:7 rectangle;
     hierarchy changes scale and orientation, never proportion. */
  --card-h: calc(var(--card-w) * 1.4);
  --a2-played-h: calc(var(--a2-played-w) * 1.4);
  --a2-remote-h: calc(var(--a2-remote-w) * 1.4);
  /* Aliases only: the accepted lobby owns every game-page colour. */
  --a2-focus: var(--a-hi);
  --a2-text: var(--tx);
  --a2-muted: var(--tx3);
  --a2-field: var(--s-table);
  --a2-field-inset: var(--s-well);

  isolation: isolate;
  inline-size: min(100vw, 430px);
  margin: 0 auto;
  padding: var(--a2-safe-t) var(--a2-page-pad) var(--a2-safe-b);
  border: 0;
  border-image: none;
  display: grid;
  grid-template-rows: 64px minmax(0, 1fr) 160px 68px;
  color: var(--a2-text);
  /* `game.css` deliberately remains the one consumer of the lobby's exact
     woven ground, --lamp and --falloff composition. A background shorthand or
     pseudo-element override here would create the second atmosphere we remove. */
}

/* One compact score/contract object. The two 44pt controls remain in their
   original DOM order and every published score/contract field is unchanged. */
.gm-deal-2 { font-size: 12px; color: var(--a2-muted); }

/* Warm restrained thumb rail. One to four choices remain in one row; five to
   eight use two rows with four launch-readable targets rather than scrolling. */
body.gm[data-action-count="5"], body.gm[data-action-count="6"],
body.gm[data-action-count="7"], body.gm[data-action-count="8"],
body.gm.is-leaving {
  grid-template-rows: 64px minmax(0, 1fr) 160px 108px;
}
body.gm.is-waiting.is-leaving {
  grid-template-rows: 64px minmax(0, 1fr) 0 108px;
}

/* Waiting, outcomes and failures retain their lifecycle and controls, now on
   the same court materials. They overlay the field rather than reserving a
   phantom third grid row from the superseded composition. */
body.is-waiting { grid-template-rows: 64px minmax(0, 1fr) 0 68px; }

@media (max-height: 880px) {
  body.gm { grid-template-rows: 60px minmax(0, 1fr) 145px 60px; }
  body.is-waiting { grid-template-rows: 60px minmax(0, 1fr) 0 60px; }
  body.gm[data-action-count="5"], body.gm[data-action-count="6"],
  body.gm[data-action-count="7"], body.gm[data-action-count="8"],
  body.gm.is-leaving {
    grid-template-rows: 60px minmax(0, 1fr) 145px 108px;
  }
  body.gm.is-waiting.is-leaving {
    grid-template-rows: 60px minmax(0, 1fr) 0 108px;
  }
}

@media (min-width: 415px) {
  body.gm { --a2-page-pad: 12px; --a2-played-w: 58px; }
}

@media (max-height: 740px) {
  body.gm {
    grid-template-rows: 58px minmax(0, 1fr) 132px 58px;
  }
  body.is-waiting { grid-template-rows: 58px minmax(0, 1fr) 0 58px; }
  body.gm[data-action-count="5"], body.gm[data-action-count="6"],
  body.gm[data-action-count="7"], body.gm[data-action-count="8"],
  body.gm.is-leaving {
    grid-template-rows: 58px minmax(0, 1fr) 132px 108px;
  }
  body.gm.is-waiting.is-leaving {
    grid-template-rows: 58px minmax(0, 1fr) 0 108px;
  }
}

/* A 360px portrait column has room for eight independent 44px lanes.
   Flatten the eight-card fan there, including the same column after rotation;
   the final viewer sizing and count-aware reserve below own its face strips. */
@media (max-width: 374px),
       (orientation: landscape) and (pointer: coarse) and (max-height: 374px) {
  body.gm { --card-w: 60px; }
}

/* §36 remains the single landscape posture. Restated after A2 because the A2
   body composition intentionally supersedes the ordinary portrait body rule,
   while a coarse rotated phone must still decline the rotation entirely. */
@media (orientation: landscape) and (pointer: coarse) and (max-height: 600px) {
  html { overflow: hidden; }
  body.gm {
    position: fixed;
    top: 0;
    left: 0;
    margin: 0;
    transform-origin: 0 0;
    transform: translateX(100svw) rotate(90deg);
    --sa-t: max(env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
    --sa-b: 0px;
    --sa-x: max(env(safe-area-inset-top, 0px), env(safe-area-inset-bottom, 0px));
    --vh: calc(100svw - var(--sa-t) - var(--sa-b));
    padding: var(--a2-safe-t) var(--sa-x) var(--a2-safe-b);
  }
  html[data-orient="landscape-secondary"] body.gm {
    transform: translateY(100svh) rotate(-90deg);
  }
}

/* ============================================================================
   38 · LAUNCH CONTINUITY · an honest open, a legible partner
   ============================================================================
   A fresh production audit found two first-order states that the completed A2
   composition still answered with placeholders rather than information.

   During the bounded face gate the court showed the imported opponent names,
   empty score labels and the hand's shadow with no sentence saying that the
   table was opening. The binding's `.pt-live` boundary already says exactly
   when the first authoritative frame exists, so the same boundary now owns a
   quiet loading chip and hides every inert example. An opening outage removes
   `aria-busy` and publishes the ordinary retry notice instead; the two states
   never compete.

   A real 32-character teammate name had only 22–32px left in the top seat's
   92px pill after padding, presence and `· خويك`. The seat is centred over a
   375–430px court with no neighbour on its row, so a bounded 148px pill buys
   78–88px for identity at supported phone heights without moving the cards or
   touching either side seat. The complete string remains DOM text and title. */

body.gm:not(.pt-live):not([data-connection="offline"])::after {
  content: "نجهّز الطاولة…";
  z-index: 40;
  inset-block-start: 49%;
  align-items: center;
  color: var(--a2-text);
  background: color-mix(in srgb, var(--s-well) 90%, transparent);
  font-size: 13px;
  font-weight: 800;
}

/* ============================================================================
   39 · INDEPENDENT AUDIT ROUND 1 · truthful status, stable open, short glass
   ============================================================================
   The production-only round-1 audit found three presentation defects whose
   fixes belong together at the court edge rather than in the imported sheets.

   A recovered table changed from a small loading pseudo-element to the full
   court and scored CLS .914. The loading cover now owns the final fixed
   viewport from its first frame; only its paint disappears at `.pt-live`, so
   the unchanged 2.5s decoded-face gate moves no layout box.

   At 844x390 with a non-coarse pointer, the centred 430px portrait court is
   necessarily short. Keep that same court and zero-scroll posture, but fit the
   top seat into the free upper-right perimeter and move the trick cross into
   the free centre-left. The teammate label remains 12pt and the unified 5:7
   fan remains the same fan; only its remote scale and the played-card scale
   tighten. This is not a landscape layout and the coarse-pointer quarter-turn
   in §36 is untouched.

   Exact project declarations can be longer than ordinary action labels. Their
   server-vetted card list may wrap inside the existing button, without adding a
   picker or changing the count-aware rail. */
body.gm:not(.pt-live):not([data-connection="offline"])::after {
  position: fixed;
  inset: 0;
  left: auto;
  transform: none;
  inline-size: auto;
  min-block-size: 0;
  padding: 0;
  display: grid;
  place-items: center;
  contain: strict;
  pointer-events: none;
  border: 0;
  border-radius: 0;
  background: radial-gradient(
    ellipse 92px 30px at center,
    color-mix(in srgb, var(--s-well) 92%, transparent) 0 96%,
    transparent 100%
  );
  box-shadow: none;
  text-shadow: 0 2px 8px rgba(0, 0, 0, .7);
}

/* 40. Captain's September document: one identity, no redundant headings.
   Imported sheets/art remain untouched. #turn stays in the accessibility tree. */
#turn {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
#contract { display: none; }
.card { background-image: url("../assets/back-bone-v8.svg"); }
#hand > .card.is-shown-project { outline: 2px dashed var(--a); outline-offset: 1px; }

/* Captain review: a stable square court and fixed control reservation. */
@media (max-height: 880px) { body.gm { --review-header: 60px; } }
@media (max-height: 740px) { body.gm { --review-header: 58px; } }

/* Modest, proportional viewer/played enlargement; remote backs keep their size. */
body.gm { --a2-played-w: 64px; --a2-remote-w: 38.08px; }
@media (min-width: 415px) { body.gm { --a2-remote-w: 39.2px; } }
@media (max-height: 740px) { body.gm { --a2-played-w: 60px; --a2-remote-w: 35.84px; } }

/* Keep controls below the larger hand: single rows use the rail's lower edge. */
body.gm { --review-hand: 176px; }
@media (max-height: 880px) { body.gm { --review-hand: 161px; } }
@media (max-height: 740px) { body.gm { --review-hand: 148px; } }

/* Review spacing: draw the upper seats toward the court, lower own identity/hand. */
body.gm { --review-lower: 0px; }

/* Larger readable faces retain the accepted bottom crop. The viewer name's
   group height stays fixed as the faces grow, preserving its court clearance. */
body.gm { --review-viewer-viewport: 100svh; --review-viewer-bottom: 30px; }
@media (min-width: 415px) { body.gm { --card-w: 114px; --review-viewer-height: 200.8px; } }
@media (max-height: 740px) { body.gm { --card-w: 100px; --review-viewer-height: 186.8px; } }

/* Taller glass has room to lift the attached viewer group; short glass
   retains the lower anchor that keeps its whole name pill below the mat. */
@media (min-height: 741px) { body.gm { --review-viewer-bottom: 8px; } }

/* The owner's mark as he picked it (C, 2026-09-30: docs/logo/README.md), on the same quiet
   ground and in the same box, so nothing around it moves. mark.svg keeps room past its ink for
   the lamp's glow, so it is drawn on a layer larger than the box and centred on it: the numbers
   are the file's viewBox over its ink, which puts the ink exactly where his first mark filled
   the box, and `node docs/logo/tools/build.mjs --check` holds them to the file. His first mark,
   assets/saikal-mark.png, stays byte-identical as the imported record. The majlis lobby draws C
   on its own layer (styles/majlis-v16.css), so this one steps aside under that lobby: its
   centring transform would otherwise shift the majlis mark by half its size. */
.tak .stage .tkmark-img { background: radial-gradient(ellipse at center, rgba(10,11,18,.96) 0%, rgba(10,11,18,.82) 44%, rgba(10,11,18,0) 74%); }
html:not([data-majlis~="lobby"]) .tak .stage .tkmark-img::before {
  content: ""; position: absolute; left: 50%; top: 50%; pointer-events: none;
  inline-size: calc(100% * 707.97 / 511.97); aspect-ratio: 707.97 / 681.23;
  transform: translate(-50%, -50%);
  background: url("../assets/saikal-mark-v2/mark.svg") center / contain no-repeat;
}
.tak .tkfan > .tkcardbody { --dim: 1 !important; }
.tak .tkback.has-art > .fc { background: url("../assets/back-bone-v8.svg") center / cover no-repeat; }
.tak .ledger { margin-block-start: max(18px, calc(6px + 14.75 * var(--g))); }

/* Gameplay is a fixed viewport; the approved low hand clips, never scrolls it. */
html:has(> body.gm) { overflow: hidden; overscroll-behavior: none; }
body.gm { position: fixed; inset: 0; overflow: clip; }

/* Captain-approved background A on both private-preview pages. */
html:has(> body.gm), .tak .tk-ground {
  background: linear-gradient(rgba(8,13,23,.77), rgba(8,13,23,.77)),
    url("../assets/sadu-woven-v1.jpg") 0 0 / 360px repeat;
  background-blend-mode: normal;
}
body.gm { background: transparent; box-shadow: none; }
body.gm::before, body.gm::after, .tak .tk-lamp, .tak .tk-fall { display: none; }

/* Keep the accepted portrait arrangement when a coarse phone rotates.
   The later inset:0 otherwise over-constrains a fixed-width RTL body: right
   wins and shifts the whole rotated court off the glass. Physical svh is the
   short side here, not the portrait column's height. No portrait change. */
@media (orientation: landscape) and (pointer: coarse) and (max-height: 600px) {
  body.gm {
    right: auto;
    bottom: auto;
    --review-court: min(calc((min(100svh, 430px) - var(--a2-page-pad) * 2 + 4px) * .9), calc(100svw - 260px));
    --review-court-center: calc(50svw + var(--review-lower));
    --review-viewer-viewport: 100svw;
  }
}

/* Sawa: turn held fans toward the table, never throw them into trick slots.
   Only accepted disclosure enables this state. Frozen decoded faces are intact. */
#sawaTitle {
  position: absolute;
  top: calc(var(--review-court-center) - var(--a2-safe-t) - var(--review-header));
  left: 50%; transform: translate(-50%, -50%);
  max-inline-size: 54%; margin: 0; padding: 4px 10px; border-radius: 9px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 20px; line-height: 1.3; color: var(--tx); background: var(--face);
  border: 1px solid var(--a); box-shadow: var(--sh2);
}
@keyframes pt-sawa-open {
  from { transform: translate(calc(var(--sawa-x) * .65), 4px) rotate(var(--sawa-angle)) rotateX(65deg); }
  to { transform: translate(var(--sawa-x), var(--sawa-arc)) rotate(var(--sawa-angle)) rotateX(0deg); }
}
@keyframes pt-sawa-own {
  from { rotate: x 0deg; translate: 0 0; }
  55% { rotate: x 42deg; translate: 0 -10px; }
  to { rotate: x 34deg; translate: 0 -8px; }
}

/* The lobby spends tall-screen space on the notebook before a blank footer
   gap. Short browser glass reduces decoration and panel overhead first; every
   control retains 44px and the join row keeps a stable reservation. */
body.tak:has(#lobbyPanel) { min-block-size: var(--app-vh, 100dvh); overscroll-behavior-y: none; }
#lobbyPanel {
  --vh: calc(var(--app-vh, 100dvh) - var(--sa-t) - var(--sa-b));
  --lobby-notice: 0px;
  --lobby-fit: calc(var(--vh) - var(--lobby-notice));
  --lobby-gap: clamp(4px, calc(6px + (var(--lobby-fit) - 540px) * .03), 12px);
  --lobby-field: clamp(44px, calc(var(--lobby-fit) - 530px), 48px);
  --lobby-mark: clamp(56px, calc(64px + (var(--lobby-fit) - 540px) * .4), 104px);
  block-size: var(--app-vh, 100dvh); min-block-size: var(--app-vh, 100dvh);
  padding-block: var(--sa-t) calc(var(--sa-b) + 8px);
}
#lobbyPanel:has(#lobbyNotice:not([hidden])) { --lobby-notice: 80px; }
#lobbyPanel .stage {
  flex: 1 0 auto; justify-content: center; padding-block-start: 0;
  margin-block-end: clamp(6px, calc((var(--lobby-fit) - 540px) * .1), 28px);
}
#lobbyPanel .stage .tkmark-img {
  inline-size: var(--lobby-mark);
}
/* Keep the three decorative card tops inside browser glass. Their deliberate
   left-edge bleed remains, but negative imported offsets no longer crop the
   whole fan vertically when there is no installed-app top safe area. */
#lobbyPanel .stage .tkfan {
  --fan-bw: calc(var(--lobby-mark) * .56);
  top: calc((100% - var(--lobby-mark) * 499 / 512) / 2 + var(--fan-bw) * .58);
}
#lobbyPanel .panel > .pin {
  padding-block: clamp(4px, calc(6px + (var(--lobby-fit) - 540px) * .015), 12px);
  row-gap: var(--lobby-gap);
}
#lobbyPanel .panel .tkfield + .tkbite { margin-block-start: 0; }
#lobbyPanel .panel .tkseats {
  /* The accepted plain panel has no notch to reserve beside this sentence. */
  padding-inline: 0;
  min-block-size: clamp(26px, calc(26px + (var(--lobby-fit) - 540px) * .05), 40px);
}
/* No tagline under the mark (owner, 2026-10-21): the imported sentence keeps
   its room, unseen and unspoken. */
#lobbyPanel .panel .tkseats { visibility: hidden; }
#lobbyPanel .tkfield-in {
  block-size: var(--lobby-field); min-block-size: var(--lobby-field);
  padding-block: 6px;
}
#lobbyPanel .tkfield-lb { min-block-size: 44px; }
#lobbyPanel .panel .tkb-1 {
  min-block-size: clamp(64px, calc(64px + (var(--lobby-fit) - 600px) * .08), 88px);
  padding-block: 6px;
}
#lobbyPanel .panel .tkb-2 { min-block-size: 50px; padding-block: 4px; }
#lobbyPanel .roomfold { min-block-size: calc(48px + var(--lobby-field)); }
#lobbyPanel .roomfold > summary {
  block-size: 44px; min-block-size: 44px; padding-block: 0;
}
#lobbyPanel .roomfold .joinrow { margin-block-start: 4px; }
#lobbyPanel .joinrow .tkb-q { min-block-size: 44px; }
#lobbyPanel .ledger {
  margin-block-start: clamp(8px, calc(8px + (var(--lobby-fit) - 600px) * .025), 14px);
  min-block-size: clamp(78px, calc(84px + (var(--lobby-fit) - 580px) * .42), 184px);
  padding-block: clamp(3px, calc(6px + (var(--lobby-fit) - 580px) * .045), 18px);
  align-content: center;
  row-gap: clamp(2px, calc(4px + (var(--lobby-fit) - 580px) * .035), 12px);
}
#lobbyPanel .ledger h2 {
  font-size: clamp(18px, calc(18px + (var(--lobby-fit) - 580px) * .025), 24px);
}
#lobbyPanel .ledger .n {
  font-size: clamp(20px, calc(22px + (var(--lobby-fit) - 580px) * .04), 32px);
}
#lobbyPanel .grow { flex: 0 1 12px; }
#lobbyPanel #lobbyHelp { flex: 0 0 44px; }
#lobbyPanel #lobbyHelp > a {
  display: inline-flex; align-items: center; min-block-size: 44px;
  padding-block: 0;
}
#lobbyPanel #lobbyNotice { margin-block: 0; padding-block: 4px; }
#lobbyPanel #lobbyNotice[hidden] { display: none; }

/* A keyboard can leave less glass than the complete lobby's 44px controls
   require. Let the focused form use normal document panning in that editing
   posture; never trap a focused name/code input inside a clipped fixed box. */
@media (max-height: 539px) {
  html:has(#lobbyPanel input:focus) { overflow-y: auto; }
  #lobbyPanel:has(input:focus) {
    block-size: auto; min-block-size: var(--app-vh, 100dvh);
    overflow-y: visible;
  }
}

/* ============================================================================
   45 · September feedback round 2: a slightly higher, more upright viewer fan.
   Start from the landed hand's position and lift by about 5% of visible height.
   Larger width-based faces still bleed below the glass; only the upper table
   gives up space when browser chrome shortens the available portrait viewport.
   ========================================================================== */
body.gm {
  --table-height: var(--app-vh, 100dvh);
  --table-width: min(var(--app-vw, 100dvw), 430px);
  --review-header: 56px;
  --review-rail: 108px;
  /* The previous composition is the height reference, not a second layout. */
  --review-baseline-card: clamp(100px, calc(100px + (var(--table-height) - 740px)), 108px);
  --review-baseline-hand: clamp(112px, calc(112px + (var(--table-height) - 740px)), 126px);
  --review-baseline-height: clamp(186.8px, calc(186.8px + (var(--table-height) - 740px)), 198px);
  --review-baseline-bottom: clamp(8px, calc(30px - (var(--table-height) - 740px)), 30px);
  --review-baseline-court: min(calc((var(--table-width) - var(--a2-page-pad) * 2 + 4px) * .9), calc(var(--table-height) - 260px));
  --review-baseline-start: max(calc(var(--table-height) + var(--review-baseline-bottom) - var(--review-baseline-height)), calc(var(--table-height) / 2 + var(--review-baseline-court) / 2 + 14px));
  --review-baseline-card-top: calc(var(--review-baseline-start) + 78px + var(--review-baseline-hand) - var(--review-baseline-card) * 1.4);
  --review-dense-lift: 0px;
  --review-viewer-height: calc(var(--card-h) + 54px);
  /* Balance the complete upper composition, not the partner in isolation:
     header-to-partner air equals mat-to-viewer air, with the partner's name
     attached 12px above the court. The face fan and name own their real height. */
  --review-partner-scale: 1;
  --review-partner-height: calc(var(--a2-remote-h) + 45px);
  --review-partner-gap: 12px;
  --review-upper-start: calc(var(--a2-safe-t) + var(--review-header));
  --review-court-top: calc(var(--review-upper-start) + 8px + var(--review-partner-height) + var(--review-partner-gap));
  --review-court-bottom: calc(var(--review-viewer-name-top) - 8px);
  --review-court: min(calc((var(--table-width) - var(--a2-page-pad) * 2 + 4px) * .9), calc(var(--review-court-bottom) - var(--review-court-top)));
  --review-court-center: calc((var(--review-upper-start) + var(--review-viewer-name-top) + var(--review-partner-height) + var(--review-partner-gap)) / 2);
  block-size: var(--table-height);
  min-block-size: 0;
}
/* Dense menus may cover the foot of the fan, but never its rank/suit strip.
   Lift only the missing readable space and retain the same bottom-bleed cap. */
body.gm[data-action-count="5"], body.gm[data-action-count="6"],
body.gm[data-action-count="7"], body.gm[data-action-count="8"] {
  --review-dense-lift: max(0px, calc(var(--review-resting-card-top) - var(--table-height) + var(--a2-safe-b) + 126px));
}
@media (min-width: 415px) {
  body.gm {
    --review-baseline-card: clamp(100px, calc(100px + (var(--table-height) - 740px)), 114px);
    --review-baseline-height: clamp(186.8px, calc(186.8px + (var(--table-height) - 740px)), 200.8px);
  }
}
/* Preserve the existing compact remote-seat scale and account for it in the
   same composition budget; viewer faces never inherit this scale. */
@media (max-height: 740px) {
  body.gm {
    --review-partner-scale: .9;
    --review-partner-height: calc((var(--a2-remote-h) + 45px) * .9);
  }
}
body.gm[class] {
  grid-template-rows: var(--review-header) minmax(0, 1fr) 0 var(--review-rail) !important;
}
@media (max-width: 374px),
       (orientation: landscape) and (pointer: coarse) and (max-height: 374px) {
  #hand[data-count="8"] { --a2-hand-treatment-reserve: 0px; }
}
@media (orientation: landscape) and (pointer: coarse) and (max-height: 600px) {
  body.gm {
    --table-height: var(--app-vw, 100dvw);
    --table-width: min(var(--app-vh, 100dvh), 430px);
    --review-baseline-card: clamp(100px, calc(100px + (var(--table-height) - 740px)), 108px);
    --review-baseline-height: clamp(186.8px, calc(186.8px + (var(--table-height) - 740px)), 198px);
    inline-size: var(--table-width);
    block-size: var(--table-height);
    transform: translateX(var(--app-vw, 100dvw)) rotate(90deg);
  }
  html[data-orient="landscape-secondary"] body.gm {
    transform: translateY(var(--app-vh, 100dvh)) rotate(-90deg);
  }
}

@keyframes round2-turn-glow {
  0%, 100% { box-shadow: inset 0 0 0 2px var(--a), 0 0 0 2px rgba(var(--a-rgb), .4), 0 0 10px 1px rgba(var(--a-rgb), .22); }
  50% { box-shadow: inset 0 0 0 2px var(--a), 0 0 0 2px rgba(var(--a-rgb), .8), 0 0 24px 5px rgba(var(--a-rgb), .58); }
}

@keyframes comments2-deny {
  0%, 100% { translate: 0 0; }
  25% { translate: -3px 0; }
  75% { translate: 3px 0; }
}

/* Durable host only: explicit SOLO resume, added by lobby.js, never a DUO picker.
   MAIN152: adjacent equal-width controls, exact captain label كمل صكتك.
   A removed/ineligible resume leaves the ordinary SOLO button full width. */
.pt-solo-controls { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.pt-solo-controls:has(> #resumeSoloButton) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pt-solo-controls > #soloButton,
.pt-solo-controls > #resumeSoloButton { min-inline-size: 0; inline-size: 100%; margin: 0; }
.pt-solo-controls > #resumeSoloButton { padding-inline: 8px; }
.pt-solo-resume {
  min-block-size: 44px; inline-size: 100%; margin-block: 6px;
  border: 1px solid var(--a); border-radius: 12px;
  background: transparent; color: var(--tx); font: inherit; cursor: pointer;
}
.pt-solo-resume:focus-visible { outline: 2px solid var(--a); outline-offset: 2px; }
.pt-solo-resume:disabled { cursor: wait; opacity: .6; }

/* ============================================================================
   46 · September feedback round 3: shown projects rest on display
   ============================================================================
   A shown project stays on display while play goes on, for as long as an إكة
   is read, rather than being picked straight back up.
   The render owns where a shown card is: on the display, so not also in the
   hand or the fan behind it. A card played off the display leaves it for the
   mat (`data-gone`) without the display being rebuilt under its flight. */
#hand > .card.is-shown-project { visibility: hidden; pointer-events: none; }

/* ============================================================================
   47 · September feedback round 3: a prepared card rises half its height
   ============================================================================
   The first tap on a card prepares it: it now rises about half its height
   instead of about a tenth, and the cards beside it part a little to make room,
   both on the same eased transition. Only paint moves - the 44pt hit lanes stay
   where the resting fan put them, and the raised face keeps its own pointer
   target - so nothing shifts under a finger between the two taps. The parting
   uses the individual `translate` property, which composes with each card's
   fan transform rather than replacing it. Reduced motion keeps the pose and
   drops the travel (§36's transition-duration rule). */

/* ============================================================================
   48 · September feedback round 3: the whole hand stays on the glass
   ============================================================================
   The hand's faces had grown past the screen - below its bottom edge and a
   few pixels past each side - so part of every card and of every motion from
   the hand was off screen. The viewer's cards are a little smaller and rest
   on the glass: the whole face, the fan's outer tilt and the prepared card's
   half-height rise stay in view at phone and desktop sizes. Only the viewer's
   hand changes; played, shown and remote cards keep their sizes. The upper
   composition (§45) is computed from this resting line, so it follows. */
body.gm {
  --card-w: clamp(96px, calc(var(--table-width) * .255), 108px);
  /* The fan's rail lift, its own translate and the outer tilt add about 16px
     below the resting line; the whole painted face ends above the safe area. */
  --review-resting-card-top: calc(var(--table-height) - var(--a2-safe-b) - var(--card-h) - 14px + var(--hand-edge-crop));
  /* Keep the original safe-inset compensation and zero-crop override. §55's
     lift is subtracted here: the face rests on the glass and the stand's lip
     holds only its far bottom edge; rank/suit and the dense rail retain their
     clearance. A tall
     portrait table's mat is width-bound, so its hand rises further for free;
     elsewhere 28px is what the mat gives up. */
  --hand-stand-lift: clamp(28px, calc(28px + var(--table-height) - var(--table-width) * 1.95), 44px);
  --hand-edge-crop: calc(var(--card-h) * .18 - var(--hand-stand-lift) + max(0px, var(--a2-safe-b) - 8px));
  /* §45 floored the line at a bottom bleed; the floor is what put faces off
     screen, so the resting line itself is the position now. */
  --review-card-top: calc(var(--review-resting-card-top) - var(--review-dense-lift));
}

/* ============================================================================
   49 · September feedback round 3: the viewer's name beside the controls
   ============================================================================
   The name tag is centred on the two rows of project controls (§P1: 36px
   pills, 9px apart, the lower row ending on the band's baseline), and the
   role labels - الموزّع, the bought contract - sit in one row directly below
   the name instead of beside it, so with both labels nothing reaches the
   controls. The same structure holds with two labels, one or none, so the
   name never jumps. Only the name and its labels move: the speech bubble and the
   project display above keep their anchors. */
/* The court is sized to end above the viewer's name; the name now sits 27px
   higher, so the court's budget ends 27px higher too (only where the court is
   height-bound - short phones - does the mat actually get smaller). */
body.gm { --review-viewer-name-top: calc(var(--review-card-top) - 48.5px - 27px); }

/* ============================================================================
   50 · The viewer's announcements clear the name, roles and controls
   ============================================================================
   A bid, a project declaration, إكة, بلوت or سوا said by the viewer rises from
   above the lifted name tag (§49), never over it or the role row below it.
   While the project controls are up it is also kept narrower than the room
   left of them, so a long call wraps instead of running under a button; the
   centred name is the axis, so that room is the same on both sides. */

/* ============================================================================
   51 · Independent-QA corrections to the viewer's band
   ============================================================================
   Four collisions, one rule: every element in the viewer's band is anchored
   where nothing else can move into it.

   1. The name tag takes only the room the controls leave it. It stays centred,
      so its widest is twice the distance from the centre to the controls, less
      an 8px gap; a long name (32 characters is the lobby's limit) ends in an
      ellipsis rather than running under a button. The same width holds with or
      without the controls, so nothing moves when they appear. */

/* ============================================================================
   52 · No instruction is written over the cards
   ============================================================================
   The rail sits over the hand, and its guidance lines («اضغط مرة ثانية للعب»,
   «بانتظار الطاولة») were painted across the card faces. With a hand on the
   table they are read to assistive technology only; ranks, suits, the calls
   above the seats and the refusal shake are unchanged. The waiting room has
   no hand, so its line stays visible there. */

/* ============================================================================
   53 · LOBBY TO TABLE · one walk from a press to the first deal
   ============================================================================
   A press on a way in used to grey every button - the chosen one with the
   others, so the choice read as refused - then cut to a dark, empty court, then
   switch the whole table on in one frame. Three beats replace that, and none of
   them can hold anything back: `lobby.js` navigates the moment the server
   answers, whatever is still moving.

   1. Departure (`body[data-entering]`, set by `table_entry.js` for the
      server's wait). The chosen way in keeps its own lit face, sunk as if still
      held, and its subtitle keeps §11's sweep; the stage deck comes up to full
      light and lifts card by card, the table being dealt; the rest of the room
      recedes. `filter: opacity()` rather than `opacity`, because the imported
      `.tkin` rise holds `opacity: 1` as its fill and would win over a plain
      declaration. A refusal removes the attribute in the task that reports it.
   2. Handoff. A same-origin cross-document view transition: the lobby eases
      forward and fades while the court settles in over it. Only the lobby and
      the table opt in (an inline head tag on each, where Chrome reliably reads
      it), so only navigations between them take part; the arriving page's
      styles own the pseudo-elements, so the forward beat is scoped to the
      table and the way back to the lobby keeps the plain crossfade. A browser
      without the feature navigates exactly as before.
   3. Arrival. `game/table_arrival.js` fades the names and score up at the
      first authoritative frame, and the existing deal carries the cards.

   Reduced motion keeps the departure's lit choice and receding room as still
   states, and takes no transition and no arrival. */
body[data-entering] .tkb-1.is-busy:disabled {
  background-image: var(--face-hot), var(--edge-hot);
  background-clip: padding-box, border-box;
  box-shadow: var(--sink-hot), var(--sh1), var(--bloom-sunk);
  color: var(--ink);
  cursor: progress;
}
body[data-entering] .tkb-1.is-busy .tkb-s {
  background-image: linear-gradient(90deg, var(--ink2) 0%, var(--ink) 50%, var(--ink2) 100%);
}
body[data-entering] .tkb-2.is-busy:disabled {
  background-image: var(--lamp-catch), var(--face-rise), var(--edge);
  background-clip: padding-box, padding-box, border-box;
  box-shadow: var(--sink), var(--sh1);
  color: var(--tx);
  cursor: progress;
}
body[data-entering] .tkb.tkb-q.is-busy:disabled {
  box-shadow: var(--sink), var(--sh0);
  color: var(--tx);
  cursor: progress;
}
body[data-entering] .pt-solo-resume.is-busy:disabled { opacity: 1; cursor: progress; }

body[data-entering] #lobbyPanel .panel .pin > :not(.is-busy):not(:has(.is-busy)),
body[data-entering] #lobbyPanel .pt-solo-controls > :not(.is-busy),
body[data-entering] #lobbyPanel > .ledger,
body[data-entering] #lobbyPanel > .pt-foot {
  filter: opacity(.42);
}
body[data-entering] #lobbyPanel .stage .tkfan { filter: brightness(1); }

@media (prefers-reduced-motion: no-preference) {
  #lobbyPanel .panel .pin > *,
  #lobbyPanel .pt-solo-controls > *,
  #lobbyPanel > .ledger,
  #lobbyPanel > .pt-foot,
  #lobbyPanel .stage .tkfan {
    transition: filter 280ms var(--ease-out);
  }
  /* `translate` composes with each card's imported `rotate()` transform, so
     the lift is straight up the screen whatever the card's lean. */
  body[data-entering] #lobbyPanel .stage .tkfan > .tkcardbody {
    animation: pt-deck-lift 1.4s var(--ease-out) infinite;
  }
  body[data-entering] #lobbyPanel .stage .tkfan > .tkcardbody:nth-child(2) { animation-delay: 140ms; }
  body[data-entering] #lobbyPanel .stage .tkfan > .tkcardbody:nth-child(3) { animation-delay: 280ms; }

  /* The opt-in itself is an inline head tag on both pages (see there). */
  :root:has(> body.gm)::view-transition-old(root),
  :root:has(> body.gm)::view-transition-new(root) {
    /* The default crossfade adds the two layers (plus-lighter); these two
       are not complementary, so they stack normally, table on top. */
    mix-blend-mode: normal;
  }
  /* The tokens live on `.tak` (the body) and these pseudo-elements hang off
     the root, so the two easings are tokens.css's --ease-in / --ease-out
     written out. */
  :root:has(> body.gm)::view-transition-old(root) {
    animation: pt-lobby-leave 360ms cubic-bezier(.4, 0, 1, 1) both;
  }
  :root:has(> body.gm)::view-transition-new(root) {
    animation: pt-table-settle 300ms cubic-bezier(.2, .7, .3, 1) both;
  }
}

@keyframes pt-deck-lift {
  0%, 44%, 100% { translate: 0 0; }
  16% { translate: 0 calc(var(--bw, 56px) * -.14); }
}
@keyframes pt-lobby-leave {
  to { opacity: 0; transform: scale(1.04); }
}
@keyframes pt-table-settle {
  from { opacity: 0; transform: scale(.985); }
}

/* ============================================================================
   54 · A suit off the card is the card's own pip
   ============================================================================
   Labels, announcements and the حكم ثاني rail used to draw suits as text or as
   hand-drawn shapes, and the small spade read as an arrow beside the real
   cards. `game/suits/*.svg` are the faces' own centre pips, shape and paint,
   cut out of `assets/cards-vector-v3.2/` by `tools/extract-suit-pips.py`
   (`--check` proves them unchanged); every one sits in the same square the pips
   share on the face, so the four keep the deck's relative size. So a spade is
   the card's black and a heart the card's own red wherever it appears - the
   pip paints itself, and no colour here is chosen for it.

   The حكم ثاني choices are the bidding buttons' own shape, size, type and gold
   law with one change the captain asked for (2026-09-23): a suit is only its
   true black or red on the card's paper, so the suit buttons wear the card
   face's paper (`--p-card` -> `--p-card-lo`, the lamp fall-off the faces use)
   with a dark hairline where the slate buttons have a light one. The whole
   button is the paper - no inner tile. The one gold primary keeps its gold;
   black and card red both hold on it. Pressed, focus and the pending/disabled
   filter are the rail's own rules, unchanged. */

/* ============================================================================
   55 · The table's card stand: a lip IN FRONT of the fan, on the fan's curve
   ============================================================================
   It holds the cards by their bottom edge and covers no printed mark. The
   captain rejected a 92px stand and a 46px lip that covered the faces, a
   ledge behind the fan, a lip fitted to the fan's droop as "too curved", and
   a shallow arc that covered writing at 7% and still reached the rightmost
   card's upside-down rank at 4%. The captain's last word (2026-09-24): match
   the bottom fan curve and cover none of the writing.
   The frozen faces print nothing in their bottom 4.4% under the upside-down
   corner index and 7.7% under the court frames and pips, and nothing at all
   near a card's left edge. So the lip's edge is one circle parallel to the
   fan's own bottom, 1-5% up every card: it falls as far as the fan does, and
   clears every printed mark, the rightmost card's upside-down index closest,
   by 1.5px or more. The fan's
   outer cards always turn 6 degrees and drop 6px however many there are, so
   fewer cards bend the same drop over a shorter span: each count has its own
   radius, in card widths. The 8-card column below 375px lays its cards flat
   and steps them, so it takes a flatter circle.
   The lip is the hand's own pseudo-element on the fan's grid lines, centred
   on the fan. The body clips it at the table's edges and at the glass. The
   rail and every overlay stay above it; it takes no pointer. It wears the
   lobby's surface ladder and no brass, because brass is what a player presses. */
/* Below 360px the project controls span most of the column and the court is
   height-bound, so a side seat rises only half as far as a lifted hand. Main's
   own line already lets a control reach a two-label seat there, and every pixel
   of lift adds to it. The narrowest column keeps main's line, where the glass
   crops the far bottom edge and a lip would have no room. */
@media (max-width: 359px),
       (orientation: landscape) and (pointer: coarse) and (max-height: 359px) {
  body.gm { --hand-stand-lift: 0px; }
}

/* Account screens: sign-in, the players' board, the account panel and the
   name options share one sheet, one header row, one type scale and one button
   ladder - brass for the one main action, raised slate for the rest, a quiet
   text link for the alternative, and red text for the destructive one. Sign-in
   borrows the lobby ground and stage; the three sheets sit on a dim backdrop.
   Nothing here may scroll sideways: long or Latin names end in an ellipsis on
   their own side (`dir=auto`), records never wrap mid-figure. */
body:has(#labLogin[open]) #lobbyPanel > :not(.stage) {visibility:hidden}
#labLogin,#labBoard,#labAccount,#labModeration,#labInviteWelcome {--lab-line:rgba(242,236,221,.22);
  --lab-edge:rgba(242,236,221,.36);--lab-alert:color-mix(in srgb,var(--aqeeq-sun) 58%,var(--tx));color:var(--tx);font:400 1rem/1.5 var(--fu);text-align:start}
#labLogin *,#labBoard *,#labAccount *,#labModeration *,#labInviteWelcome * {box-sizing:border-box}
#labLogin [hidden],#labBoard [hidden],#labAccount [hidden],#labModeration [hidden],#labInviteWelcome [hidden] {display:none!important}
#labLogin h2,#labBoard h2,#labAccount h2,#labModeration h2,#labInviteWelcome h2 {margin:0;min-width:0;color:var(--tx);
  font:850 1.4rem/1.25 var(--fu)}

/* The shared button ladder. */
#labLogin button,#labAccount .lab-scroll > button,#labModeration .lab-scroll > button,#labInviteWelcome .lab-scroll > button,
#labAccountMethods > button,#labAccountTrial > button,#labLinkEmail button {
  display:flex;align-items:center;justify-content:center;gap:10px;width:100%;min-height:48px;
  margin:8px 0 0;padding:6px 14px;border:1px solid var(--lab-edge);border-radius:var(--r-btn-sm);
  background:linear-gradient(var(--s-rise-hi),var(--s-rise-lo));color:var(--tx);
  font:700 1rem/1.3 var(--fu);text-align:center;cursor:pointer}
#labLogin #labLoginProfile,#labLoginEmail button[type=submit] {border-color:var(--a);
  background:linear-gradient(var(--a-hi),var(--a-lo));color:var(--ink)}
#labLogin .lab-links button,#labAccount .lab-scroll > .lab-link,#labAccountMethods .lab-own-list button {
  width:auto;min-height:44px;margin:2px auto 0;
  padding:0 12px;border:0;background:transparent;color:var(--tx);opacity:.86;
  font:650 .92rem var(--fu);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
#labLogin .lab-links {display:flex;justify-content:space-between;gap:8px;margin-top:2px}
#labLogin .lab-links button {margin:0;padding:0 4px}
#labLogin .is-email-flow .lab-links {justify-content:center}
#labLogin .lab-login-card.is-email-flow :is(#labLoginApple,#labLoginGoogle,.lab-or) {display:none}
/* صكاتي and الشرح keep the ladder's 8px from the card below them (owner's note 45). */
#labAccount :is(#labAccountGames,#labAccountTutorial) {margin-bottom:8px}
#labAccount .lab-scroll > .lab-link {display:block;margin-top:8px;font-size:.88rem;opacity:.75}
#labAccount .lab-scroll > .lab-danger {border-color:var(--lab-alert);background:transparent;color:var(--lab-alert)}
/* Deleting the account is the sheet's second view, never the browser's confirm box. */
#labAccount:not([data-view="delete"]) .lab-scroll > .lab-delete,
#labAccount[data-view="delete"] .lab-scroll > :not(.lab-delete) {display:none!important}
#labAccount .lab-delete-words {margin:0 0 12px;color:var(--tx);font-size:.98rem;line-height:1.7;text-align:center}
/* The sign-in sheet has no guest row (owner, 2026-10-29), so its waiting slab
   reserves the answered height without one on every route, as /preview/ did. */
html[data-majlis~="lobby"][data-majlis-waited] #labLogin[open] .lab-login-card.is-pending {min-block-size:calc(var(--mj-sheet-answer) - var(--mj-sheet-guest))}
#labLogin button:focus-visible,#labLogin input:focus-visible,#labLogin a:focus-visible,
#labBoard button:focus-visible,#labBoard .lab-row:focus-visible,
#labAccount button:focus-visible,#labModeration button:focus-visible,#labInviteWelcome button:focus-visible {outline:3px solid var(--a-hi);outline-offset:2px}

/* Sign-in. */
#labLogin {position:fixed;inset:0;width:100%;height:100dvh;max-width:none;max-height:none;
  margin:0;padding:0;border:0;background:transparent;overflow:auto}
#labLogin::backdrop {background:transparent}
#labLogin .lab-login-layout {width:min(100%,422px);min-height:100%;margin:auto;
  padding:clamp(132px,24vh,204px) 16px max(16px,env(safe-area-inset-bottom));
  display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start}
#labLogin .lab-login-card {padding:20px 18px 12px;border:1px solid var(--lab-edge);
  border-radius:var(--r-sheet);background:linear-gradient(155deg,var(--s-panel-hi),var(--s-panel-lo));
  box-shadow:0 20px 60px rgba(4,7,16,.52),inset 0 1px rgba(255,250,236,.12)}
#labLogin h2 {margin-bottom:10px}
/* Provider marks are their own sign-in controls, not recoloured lobby buttons:
   the mark leads the label on the reading side. */
#labLogin #labLoginApple,#labLogin #labLoginGoogle,#labAccount #labLoginApple,#labAccount #labLoginGoogle {
  display:flex;align-items:center;justify-content:center;gap:10px;width:100%;min-height:48px;
  margin:8px 0 0;padding:6px 14px;border-radius:var(--r-btn-sm);font-size:1rem;line-height:1.3;cursor:pointer}
#labLoginApple::before,#labLoginGoogle::before {content:"";display:block;flex:none}
#labLoginApple,#labLoginGoogle {white-space:nowrap}
#labLogin #labLoginApple,#labAccount #labLoginApple {border:1px solid #fff;background:#000;color:#fff;
  font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text",var(--fu),sans-serif;font-weight:600}
#labLoginApple::before {width:17px;height:21px;margin-top:-3px;background:#fff;
  -webkit-mask:url('../assets/apple-mark-v1.svg') center/contain no-repeat;
  mask:url('../assets/apple-mark-v1.svg') center/contain no-repeat}
#labLogin #labLoginGoogle,#labAccount #labLoginGoogle {border:1px solid #dadce0;background:#fff;color:#1f1f1f;
  font-family:"Google Sans",Roboto,var(--fu),sans-serif;font-weight:500}
#labLoginGoogle::before {width:20px;height:20px;
  background:url('../assets/google-g-v1.svg') center/contain no-repeat}
#labLogin .lab-or {display:flex;align-items:center;gap:12px;margin:12px 0 2px;
  font-size:.88rem;opacity:.8}
#labLogin .lab-or::before,#labLogin .lab-or::after {content:"";flex:1;height:1px;background:var(--lab-line)}
#labLoginEmail {display:flex;flex-direction:column;gap:8px;margin-top:8px}
#labLoginEmail input {width:100%;min-height:48px;padding:8px 14px;
  border:1px solid var(--lab-edge);border-radius:var(--r-btn-sm);
  background:rgba(8,18,31,.35);color:var(--tx);font:500 1rem var(--fu)}
#labLoginEmail input::placeholder {color:var(--tx);opacity:.62}
#labLoginEmail input[type=email] {direction:ltr;text-align:right}
#labLoginEmail input[type=email]:placeholder-shown {direction:rtl}
#labLoginEmail button {margin:0}
#labLogin .lab-login-status {margin:2px 0 0;font-size:.92rem;text-align:center;color:var(--a-hi)}
#labLogin .lab-login-status.is-error {color:var(--lab-alert)}
#labLogin .lab-login-status:empty {display:none}
#labLogin .lab-legal {display:flex;justify-content:center;gap:20px;margin:12px 0 0}
#labLogin .lab-legal a {display:inline-flex;align-items:center;min-height:44px;color:var(--tx);
  opacity:.72;font-size:.86rem;text-underline-offset:4px}
/* Early access by invitation (app/server/INVITES.md): the line above a signed-out
   visitor's sign-in, and the card a signed-in account waits on until it is
   approved, in the sheet's own type and buttons. */
#labLogin .lab-invite {margin:0 0 6px;color:var(--tx);font-size:.98rem;line-height:1.7;text-align:center}
#labLogin .lab-invite p {margin:0 0 8px}
#labLogin .lab-invite p:first-child {font-weight:700}
#labLogin .lab-login-card.is-invite-pending > :is(#labLoginApple,#labLoginGoogle,.lab-or,#labLoginEmail,
  #labLoginFixtureEmail,#labLoginProfile,#labInviteNote) {display:none}
#labLogin #labInviteCheck {border-color:var(--a);background:linear-gradient(var(--a-hi),var(--a-lo));color:var(--ink)}
#labLogin .lab-login-card > .lab-link {display:block;width:auto;min-height:44px;margin:4px auto 0;padding:0 12px;border:0;
  background:transparent;color:var(--tx);opacity:.86;font:650 .92rem var(--fu);
  text-decoration:underline;text-underline-offset:4px}
#labInviteWelcome .lab-scroll p {margin:0 0 10px;font-size:1rem;line-height:1.7;text-align:center}
#labInviteWelcome .lab-scroll p:first-child {font-weight:700}
#labInviteWelcome #labInviteWelcomeOk {border-color:var(--a);background:linear-gradient(var(--a-hi),var(--a-lo));color:var(--ink)}
#lobbyPanel #soloButton[hidden],#lobbyPanel #duoButton[hidden] {display:none}
/* accounts.js starts the sheet below the lobby's mark and deck; where a screen
   is too short for both it sets `lab-login-compact`, and the sheet takes the
   screen while the deck steps aside rather than showing through behind it. */
body.lab-login-compact:has(#labLogin[open]) #lobbyPanel .stage {visibility:hidden}
body.lab-login-compact #labLogin .lab-login-layout {justify-content:center;
  padding-block:max(12px,env(safe-area-inset-top)) max(12px,env(safe-area-inset-bottom))}
@media (max-height:700px) {
  #labLogin .lab-login-card {padding:14px 14px 6px}
  #labLogin h2 {margin-bottom:4px;font-size:1.28rem}
  #labLogin button,#labLogin #labLoginApple,#labLogin #labLoginGoogle,#labLoginEmail input {min-height:44px}
  #labLogin button,#labLogin #labLoginApple,#labLogin #labLoginGoogle {margin-top:6px}
  #labLoginEmail {gap:6px;margin-top:4px}
  #labLoginEmail button {margin:0}
  #labLogin .lab-links button {min-height:40px}
  #labLogin .lab-or {margin:4px 0 0}
  #labLogin .lab-legal {margin-top:0}
}
@media (max-width:359px) {#labLogin .lab-login-layout {padding-inline:10px}}

/* The lobby's own profile control and the notebook's tap target. */
#lobbyPanel .panel .tkfield:has(#labProfile) {gap:6px}
#lobbyPanel .panel .tkfield #labProfile {flex:0 0 44px;width:44px;min-height:max(44px,var(--lobby-field));
  padding:0 3px;border:1px solid rgba(242,236,221,.45);border-radius:var(--r-btn-sm);
  background:linear-gradient(var(--s-rise-hi),var(--s-rise-lo));color:var(--tx);
  font:700 .8rem var(--fu);white-space:nowrap;cursor:pointer}
#lobbyPanel .panel .tkfield #labProfile[aria-pressed="true"] {border-color:var(--a-hi)}
#labProfile:focus-visible,.tkledger #labBoardOpen:focus-visible {outline:3px solid var(--a-hi);outline-offset:3px}
.tkledger:has(#labBoardOpen) {position:relative}
.tkledger #labBoardOpen {position:absolute;z-index:2;inset:0;width:100%;height:100%;
  border:0;border-radius:var(--r-sheet);background:transparent;color:transparent;
  font-size:0;cursor:pointer}

/* The three sheets: a header row (title, then رجوع at the far end) above a
   body that alone scrolls. Centred, clear of the camera and status bar (owner's
   note 43): the larger safe-area inset plus 12px at both ends, else 16px. */
#labBoard,#labAccount,#labModeration,#labInviteWelcome {width:min(calc(100vw - 32px),390px);
  --lab-safe:max(16px,calc(max(env(safe-area-inset-top,0px),env(safe-area-inset-bottom,0px)) + 12px));
  max-width:none;max-height:calc(100dvh - 2 * var(--lab-safe));margin:auto;padding:0;overflow:hidden;
  border:1px solid var(--lab-edge);border-radius:var(--r-sheet);
  background:linear-gradient(155deg,var(--s-panel-hi),var(--s-panel-lo));
  box-shadow:0 20px 60px rgba(4,7,16,.52),inset 0 1px rgba(255,250,236,.12)}
#labBoard[open],#labAccount[open],#labModeration[open],#labInviteWelcome[open] {display:flex;flex-direction:column}
#labBoard::backdrop,#labAccount::backdrop,#labModeration::backdrop,#labInviteWelcome::backdrop {background:rgba(7,9,17,.9)}
#labBoard .lab-top,#labAccount .lab-top,#labModeration .lab-top,#labInviteWelcome .lab-top {display:flex;flex:none;align-items:center;
  justify-content:space-between;gap:12px;padding:16px 18px 12px;border-bottom:1px solid var(--lab-line)}
#labLogin h2:focus,#labBoard .lab-top h2:focus,#labAccount .lab-top h2:focus,#labModeration .lab-top h2:focus,#labInviteWelcome .lab-top h2:focus {outline:none}
#labBoard .lab-back,#labAccount .lab-back,#labModeration .lab-back,#labInviteWelcome .lab-back {flex:none;min-width:72px;min-height:44px;
  margin:0;padding:0 14px;border:1px solid var(--lab-edge);border-radius:var(--r-btn-sm);
  background:linear-gradient(var(--s-rise-hi),var(--s-rise-lo));color:var(--tx);
  font:700 .95rem var(--fu);cursor:pointer}
#labBoard .lab-scroll,#labAccount .lab-scroll,#labModeration .lab-scroll,#labInviteWelcome .lab-scroll {flex:1 1 auto;min-height:0;
  padding:6px 18px 22px;overflow:auto;overscroll-behavior:contain}
#labAccount .lab-scroll,#labModeration .lab-scroll,#labInviteWelcome .lab-scroll {padding-top:14px}
#labBoard .lab-status,#labAccount .lab-status,#labModeration .lab-status,#labInviteWelcome .lab-status {margin:8px 0 0;font-size:.92rem;text-align:center}
#labBoard .lab-status:empty,#labAccount .lab-status:empty,#labModeration .lab-status:empty,#labInviteWelcome .lab-status:empty {display:none}

/* The board. */
#labBoard .lab-note {margin:8px 0 0;color:var(--a-hi);font-size:.9rem;font-weight:700}
#labBoard .lab-rows {list-style:none;margin:0;padding:0}
#labBoard .lab-empty {padding:18px 6px;text-align:center;opacity:.75}
#labBoard .lab-row {display:flex;align-items:center;gap:10px;min-height:44px;padding:4px 6px;
  border-bottom:1px solid var(--lab-line)}
#labBoard .lab-row:last-child {border-bottom:0}
#labBoard .lab-row[tabindex] {cursor:pointer}
#labBoard .lab-name {flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;text-align:start;font-size:.95rem;font-weight:700}
#labBoard .lab-rate {flex:none;min-width:3ch;color:var(--a-hi);font-size:1.05rem;font-weight:800;
  text-align:end;direction:ltr;unicode-bidi:isolate}
#labBoard .lab-rank {flex:0 0 1.8em;opacity:.7;font-size:.86rem;font-weight:700;text-align:center}
#labBoard .lab-row.is-you {border-radius:10px;background:rgba(242,236,221,.09)}
#labBoard .lab-you {flex:none;padding:1px 8px;border:1px solid var(--a-hi);border-radius:999px;
  color:var(--a-hi);font-size:.74rem;font-weight:800}
/* Each player's @handle under the name (owner's note 43): one isolated LTR line, cut short. */
#labBoard .lab-who {display:flex;flex:1 1 auto;flex-direction:column;min-width:0}
#labBoard .lab-who > .lab-name {flex:none;max-width:100%}
#labBoard .lab-handle {display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right;
  unicode-bidi:isolate;font-size:.78rem;font-weight:600;line-height:1.35;opacity:.72}
html[data-majlis~="lobby"] #labBoard .lab-handle {color:var(--mj-ivory-2);opacity:1;font:400 var(--mj-fs-badge) / 1.35 var(--mj-font-ui)}
/* The viewer's own row, pinned directly under the rated board's last row after a
   dashed rule (owner, 2026-10-30): a placed rank and number, or the placement count,
   its line and meter. A viewer below the page closes the list with a gap. Nothing
   stands between the list and the pin (the notebook download is gone, his word). */
#labBoard .lab-pin {margin:0;padding:8px 0 0;border-top:1px dashed rgba(242,236,221,.25)}
#labBoard .lab-pin .lab-row {flex-wrap:wrap;row-gap:0;min-height:48px;border-bottom:0}
#labBoard .lab-pin .lab-rank {opacity:1}
#labBoard .lab-pin-words {flex:1 0 100%;margin-top:-4px;padding-inline-start:calc(1.8em + 10px);
  color:var(--mj-ivory-2,var(--tx));font-size:.78rem;line-height:1.5}
#labBoard .lab-pin-bar {flex:0 0 calc(100% - 1.8em - 10px);height:6px;margin:4px 0 6px;margin-inline-start:calc(1.8em + 10px);
  border-radius:3px;
  background:linear-gradient(to left,var(--mj-gold-300,var(--a-hi)) var(--done),rgba(242,236,221,.12) var(--done))}
#labBoard .lab-gap {padding:4px 0 0;text-align:center;letter-spacing:4px;line-height:1;opacity:.5}

/* Agent versions stay separate from player ranks and name moderation. Only
   the active executor earns the tag; these are the server's player-scale numbers. */
#labBoard .lab-agents {margin:10px 0 14px;padding:10px 12px;border:1px solid var(--lab-line);
  border-radius:var(--r-btn-sm);background:rgba(242,236,221,.035)}
#labBoard .lab-agents h3 {margin:0 0 4px;color:var(--tx);font:800 .88rem/1.5 var(--fu)}
#labBoard .lab-agent {display:flex;align-items:center;gap:8px;min-height:44px}
#labBoard .lab-agent + .lab-agent {border-top:1px solid var(--lab-line)}
#labBoard .lab-agent-version {font:750 1rem/1.4 var(--fu);unicode-bidi:isolate}
#labBoard .lab-agent .lab-rate {margin-right:auto}
#labBoard .lab-current {flex:none;padding:1px 8px;border:1px solid var(--a-hi);border-radius:999px;
  color:var(--a-hi);font:800 .74rem/1.6 var(--fu)}
/* A non-modal one-line release note, above the lobby furniture, not over the
   notebook button. No focus capture, new local key or game-retirement action. */
.pt-agent-release {position:fixed;z-index:110;top:max(12px,env(safe-area-inset-top));left:50%;
  transform:translateX(-50%);display:flex;align-items:center;justify-content:center;gap:.3em;
  width:min(calc(100% - 32px),358px);min-height:48px;padding:10px 16px;
  border:1px solid var(--a-hi);border-radius:var(--r-btn-sm);
  background:linear-gradient(var(--s-panel-hi),var(--s-panel-lo));color:var(--tx);
  box-shadow:0 8px 30px rgba(4,7,16,.4);font:750 1rem/1.5 var(--fu);cursor:pointer}
.pt-agent-release bdi {unicode-bidi:isolate;direction:ltr}
.pt-agent-release[hidden] {display:none}
.pt-agent-release:focus-visible {outline:3px solid var(--a-hi);outline-offset:3px}

/* The account panel and its rating card. */
#labModeration .lab-subject {margin:0 0 4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  text-align:start;font-size:1.06rem;font-weight:700}
#labAccountRating {margin:0 0 6px;padding:14px 16px;border:1px solid var(--lab-line);
  border-radius:var(--r-btn-sm);background:rgba(242,236,221,.05)}
#labAccountRating p {margin:0}
#labAccountRating .lab-own-head {display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px}
#labAccountRating .lab-own-title {opacity:.86;font-size:.92rem;font-weight:800}
#labAccountRating > .lab-own-title {margin-top:14px}
#labAccountRating .lab-tag {padding:1px 8px;border:1px solid var(--a-hi);border-radius:999px;
  color:var(--a-hi);font-size:.74rem;font-weight:800}
#labAccountRating .lab-own-rate {color:var(--a-hi);font:850 2.2rem/1.15 var(--fu)}
#labAccountRating .lab-own-rate.is-empty {font:700 1.6rem/1.3 var(--fu);opacity:.7}
#labAccountRating .lab-own-hint {text-wrap:balance}
#labAccountRating .lab-own-list {list-style:none;margin:10px 0 0;padding:0}
#labAccountRating .lab-own-pairs {margin-top:4px}
#labAccountRating .lab-own-list li {display:flex;align-items:center;justify-content:space-between;gap:12px;
  min-height:40px;border-top:1px solid var(--lab-line)}
#labAccountRating .lab-own-list span {min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  text-align:start;font-size:1rem;font-weight:700}
#labAccountRating .lab-own-list strong {flex:none;font-size:.92rem;font-weight:700;white-space:nowrap}
/* The account's sign-in methods (app/server/ACCOUNT-LINKING.md) in the same
   card language: a caption, one row per method with a quiet إزالة, then a
   button per method it can add; the add-email form uses the sign-in inputs. */
#labAccountMethods {margin:0 0 6px;padding:14px 16px;border:1px solid var(--lab-line);
  border-radius:var(--r-btn-sm);background:rgba(242,236,221,.05)}
#labAccountMethods h3 {margin:0;opacity:.86;font:800 .92rem var(--fu)}
#labAccountMethods .lab-own-list {list-style:none;margin:10px 0 0;padding:0}
#labAccountMethods .lab-own-list li {display:flex;align-items:center;justify-content:space-between;gap:12px;
  min-height:44px;border-top:1px solid var(--lab-line)}
#labAccountMethods .lab-own-list span {font-size:1rem;font-weight:700;unicode-bidi:isolate}
#labAccountMethods .lab-own-list button {min-width:44px;margin:0;padding:0 8px;font-size:.9rem}
#labAccountMethods #labLinkEmail button[type=submit] {border-color:var(--a);
  background:linear-gradient(var(--a-hi),var(--a-lo));color:var(--ink)}
#labAccountTrial:empty {display:none}
@media (max-width:359px) {
  #labAccountMethods,#labAccountRating {padding-inline:10px}
  #labAccountMethods #labLoginApple,#labAccountMethods #labLoginGoogle {padding-inline:8px;font-size:.94rem}
}
#labLinkEmail {display:flex;flex-direction:column;gap:8px;margin:8px 0 0}
#labLinkEmail input {width:100%;min-height:48px;padding:8px 14px;border:1px solid var(--lab-edge);
  border-radius:var(--r-btn-sm);background:rgba(8,18,31,.35);color:var(--tx);font:500 1rem var(--fu)}
#labLinkEmail input::placeholder {color:var(--tx);opacity:.62}
#labLinkEmail input:focus-visible {outline:3px solid var(--a-hi);outline-offset:2px}
#labLinkEmail button {margin:0}
/* Until the server answers, the sign-in sheet offers nothing to press. */
#labLogin .lab-login-card.is-pending > button {visibility:hidden}
/* The own card: one block per mode (SOLO, then DUO): its rating once placed,
   otherwise the placement count with a thin bar and one line, then wins and
   losses; DUO adds the three partners with the most games together. */
#labAccountRating .lab-own-mode + .lab-own-mode {margin-top:14px;padding-top:12px;border-top:1px solid var(--lab-line)}
#labAccountRating .lab-own-rate.is-placing {font-size:1.8rem}
#labAccountRating .lab-own-bar {display:block;height:6px;margin:6px 0 2px;border-radius:3px;
  background:linear-gradient(to left,var(--a-hi) var(--done),rgba(242,236,221,.14) var(--done))}
#labAccountRating .lab-own-hint {margin-top:4px;font-size:.9rem;font-weight:700;opacity:.9;text-wrap:balance}
#labAccountRating .lab-own-record {margin-top:6px;font-size:.95rem;font-weight:700}
#labAccountRating .lab-own-sub {margin-top:12px}
/* The lobby's notebook card for a signed-in player: their SOLO standing. */
.tkledger[data-account] > .lg-cells:not(.lab-book) {display:none}
.tkledger .lg-cells.lab-book {grid-template-columns:1fr}
.tkledger .lab-book .lg-cell .k {white-space:normal;text-align:center;text-wrap:balance}
.tkledger .lg-cells.lab-book[hidden] {display:none}

/* ============================================================================
   56 · Picks ahead of the turn (premoves, owner 2026-10-16)
   ============================================================================
   Before the viewer's own bidding turn the rail holds that turn's own bid
   buttons in their own slots, so nothing moves when the turn comes. They stay
   quiet until one is picked: a dashed outline and no gold - the gold is the
   turn's primary action alone - but opaque, so no label is ever drawn over a
   card face. The picked one wears a gold ring of the same border width (the
   rest drawn inside), so no neighbour moves. Like every rail line over the
   hand (§52), the line naming the pick is read to assistive technology only;
   on screen the button alone carries it, and nothing is written under the
   viewer's name (owner, 2026-10-21). At the turn the pick is said at once, so
   no button waits. */
/* While the last three cards fly (majlis-table's deal scene) a tap on the
   table skips the deal, so the labels before the turn wait for it to settle. */
html[data-mj-dealing] #projectLabels[data-ahead="1"],
html[data-mj-dealing] #projectTags[data-ahead="1"] { visibility: hidden; }

/* ============================================================================
   57 · The operator's notice (notice_banner.js, app/deploy/oracle/notice.py)
   ============================================================================
   One short message over the top of the lobby - a planned stop and when it
   ends, or a known problem - from a file outside every release. It is not a
   dialog: it floats in the safe area over the lobby's top (the mark and its
   lamp; the lobby's controls sit below it on a phone), takes no focus, and its
   own 44pt close button is the only thing in it to press. While a modal sheet
   is open (the sign-in sheet is drawn above everything) it moves into that
   sheet, at the same place, so it is still seen. Arabic first; the English
   line, when the operator wrote one, reads left to right beneath it. It arrives with a fade only
   when motion is allowed. */
.pt-site-notice {
  position: fixed;
  z-index: 111;
  top: max(10px, env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: flex-start;
  gap: 4px;
  width: min(calc(100% - 32px), 420px);
  padding: 10px 6px 10px 14px;
  padding-inline-start: 14px;
  padding-inline-end: 4px;
  border: 1px solid var(--a-hi);
  border-radius: var(--r-btn-sm);
  background: linear-gradient(var(--s-panel-hi), var(--s-panel-lo));
  color: var(--tx);
  box-shadow: 0 8px 30px rgba(4, 7, 16, .45);
  font: 700 .95rem/1.55 var(--fu);
  text-align: start;
}
.pt-site-notice[hidden] { display: none; }
/* Inside a sheet the sheet's own rules for its buttons and blocks must not
   reach it: the same banner, at the same place, above the sheet's card. */
html #siteNotice.pt-site-notice.is-in-sheet { margin: 0; }
.pt-site-notice[data-kind="issue"] { border-color: #E8A15C; }
.pt-site-notice-words { flex: 1; min-width: 0; padding-block: 2px; }
.pt-site-notice-text,
.pt-site-notice-when,
.pt-site-notice-en { display: block; overflow-wrap: anywhere; text-wrap: pretty; }
.pt-site-notice-when { color: var(--a-hi); font-weight: 800; }
.pt-site-notice-en {
  margin-top: 4px;
  font: 500 .82rem/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: rgba(242, 236, 221, .72);
  text-align: left;
}
html[data-majlis] #siteNotice > button.pt-site-notice-close,
.pt-site-notice-close {
  all: unset;
  box-sizing: border-box;
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  margin: -8px 0 -8px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  font: 400 1.6rem/1 system-ui, sans-serif;
  cursor: pointer;
}
html[data-majlis] #siteNotice > button.pt-site-notice-close:focus-visible,
.pt-site-notice-close:focus-visible { outline: 3px solid var(--a-hi); outline-offset: -3px; }
/* The one-time release note shares the top of the screen: it steps below. */
body:has(.pt-site-notice:not([hidden])) .pt-agent-release { top: auto; bottom: max(12px, env(safe-area-inset-bottom)); }
@media (prefers-reduced-motion: no-preference) {
  .pt-site-notice { animation: pt-site-notice-in 240ms ease-out both; }
  @keyframes pt-site-notice-in { from { opacity: 0; } to { opacity: 1; } }
}

/* --- The feedback button (docs/feedback.md) -----------------------------------
   Owner, 2026-10-19: a temporary beta button, eye-catching like a game beta's
   bug-report button, on the lobby and the table. feedback.js pins it over the
   page, so it never takes a place in any layout and nothing moves when it
   appears: fixed at the top right corner of the lobby's column (`--fb-column`:
   tak.css `.room`, or the majlis lobby's own), so a wide screen keeps it in
   the phone's frame (owner, 2026-10-24); on the table, inside the top
   bar and hanging just below its right end (so a rotated table carries it
   along), and below the notice bar while one shows (--fb-drop).
   FEEDBACK_BUTTON in feedback.js removes it. */
.fb-pin {
  --fb-column: 430px;
  position: fixed;
  z-index: 40;
  inset-block-start: max(10px, env(safe-area-inset-top));
  inset-inline-end: auto;
  /* A fixed box's percentage is of the viewport without its scrollbar, as the
     column is centred in. */
  right: max(10px, env(safe-area-inset-right), calc((100% - var(--fb-column)) / 2 + 10px));
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-block-size: 36px;
  padding: 0 12px 0 10px;
  border: 1px solid rgba(255, 214, 196, .55);
  border-radius: 999px;
  background: linear-gradient(180deg, #e0523b, #b3301f);
  box-shadow: 0 0 0 3px rgba(224, 82, 59, .22), 0 4px 14px rgba(0, 0, 0, .45),
              inset 0 1px 0 rgba(255, 255, 255, .25);
  color: #fff;
  font: 700 15px/1 var(--mj-font-ui, inherit);
  letter-spacing: 0;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 80ms ease-out, filter 150ms linear;
}
html[data-majlis~="lobby"] .fb-pin { --fb-column: calc(358px + 2 * var(--mj-gutter, 16px)); }
.fb-pin[hidden] { display: none; }
.fb-pin svg { inline-size: 18px; block-size: 18px; flex: none; }
.fb-pin:active { transform: translateY(1px); filter: brightness(1.1); }
.fb-pin:focus-visible { outline: 2px solid #ffd7a8; outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) { .fb-pin:hover { filter: brightness(1.08); } }
.fb-pin--under {
  position: absolute;
  inset-block-start: calc(100% + 8px + var(--fb-drop, 0px));
  right: 0;
  /* The lobby's label, a size smaller (owner, 2026-10-22), so the partner's
     fan stays clear from 360px wide. */
  gap: 4px;
  padding: 0 9px 0 8px;
  font-size: 13px;
}
.fb-pin--under svg { inline-size: 16px; block-size: 16px; }
@media (prefers-reduced-motion: reduce) {
  .fb-pin { transition: none; }
  .fb-pin:active { transform: none; }
}

/* ============================================================================
   58 · A call cannot change under a finger (owner, 2026-10-18)
   ============================================================================
   game/tap_guard.js: for the guard's window after the rail's calls change, a
   tap on them is dropped, and the buttons that changed (`data-changed`: new,
   relabelled, moved or re-laned) say so by resting dimmed. The lanes never
   move. The dim is a brightness, never a transparency, so no card face shows
   through a call (owner, 2026-10-22: the buttons "twitch" as they appear and
   change): with motion it is one continuous rise over the window
   (`beginRailMorph` in game.js), with Reduce Motion a step. */
@media (prefers-reduced-motion: reduce) {
  #act[data-settling="1"] > .btn[data-changed]:is([data-action-id], [data-premove-choice]) {
    filter: brightness(.62) saturate(.8);
  }
}
/* The press. The pressed call stays pressed in until the table answers, and
   while the player's own call is on its way (`data-awaiting`) the other calls
   recede in their own colours instead of turning to the outage's grey for one
   round trip; an outage, a failed seat or the exit prompt still grey them. */
html[data-majlis~="system"] body.gm #act > .btn[aria-busy="true"] { transform: translateY(1px); }
#act[data-awaiting="1"] > .btn[disabled]:not([aria-busy="true"]) {
  filter: brightness(.62) saturate(.8);
}
#act[data-awaiting="1"] > .btn[disabled][aria-busy="true"] { filter: none; }
html[data-majlis~="system"] body.gm #act[data-awaiting="1"] > .btn:disabled:not([aria-busy="true"]):not([data-trump]) {
  background: var(--mj-slate-glass);
  color: var(--mj-ivory);
  border-color: rgba(var(--mj-lit-rgb), .42);
  box-shadow: var(--mj-e2);
}
html[data-majlis~="system"] body.gm #act[data-awaiting="1"] > .btn:disabled:not([aria-busy="true"]) {
  filter: brightness(.62) saturate(.8);
}
@media (prefers-reduced-motion: no-preference) {
  #act > .btn {
    transition: transform var(--t-down) var(--ease-out), filter 160ms ease-out;
  }
  html[data-majlis~="system"] body.gm #act > .btn {
    transition: transform var(--mj-t-press) var(--mj-ease-out), filter 160ms ease-out;
  }
}

/* The armed project label's solid gold, and a queued card's dashed gold line
   (owner's pick, 2026-10-26: a solid queued outline read the same as a first
   tap), in the mutable layer. The published v11 sheet stays byte-identical.
   IDs keep first-trick and later queued cards consistent in every phase. */
html[data-majlis~="system"] body.gm #hand > .card[data-premove="1"] {
  box-shadow: 0 0 0 2px var(--mj-night-950), 0 14px 28px rgba(0, 0, 0, .5);
  outline: 2.5px dashed var(--mj-gold-300);
  outline-offset: 3px;
}
html[data-majlis~="system"] body.gm #hand > .card[data-premove="1"]:focus-visible {
  box-shadow: 0 0 0 8.5px var(--mj-night-950), 0 0 0 11px var(--mj-gold-300), 0 14px 28px rgba(0, 0, 0, .5);
}

/* ============================================================================
   59 · Withdrawing from a SOLO (owner, 2026-10-26; feedback #34)
   ============================================================================
   app/server/play/solo_withdraw.py: the exit sheet's third button, «انسحب», ends the
   match at once as a loss. It is filled red, so the one exit that costs the
   game never reads as «اطلع» beside it, which keeps the game for the lobby. */

/* ==========================================================================
   Part 5: formerly styles/quick-v2.css
   ========================================================================== */

/* Quick match and the walkthrough lobby (owner, 2026-10-21): the search, its
   offer, the friend sheet, the «كمّل صكتك» card, and the table's partner lines.
   On the majlis system's tokens and components (styles/majlis-v16.css), in a
   file of its own so that sheet stays byte-identical. Its path names its version:
   v2 is the owner's 2026-10-22 polish (the search in the lobby's own room), and a
   change after it is quick-v3.css (docs/majlis/README.md, "The files name their
   version"). */

/* --- 1 · The lobby's ways in ------------------------------------------------ */

html[data-majlis~="lobby"] #lobbyPanel .pt-solo-controls[data-ways="1"] {
  grid-auto-columns: minmax(0, 1fr);
}
html[data-majlis~="lobby"] #lobbyPanel .panel #soloButton:not(:has(> .tkb-s)) {
  font-size: var(--mj-fs-control);
}
html[data-majlis~="lobby"] #lobbyPanel .panel #friendButton {
  font-size: var(--mj-fs-control);
}
html[data-majlis~="lobby"] #lobbyPanel .pt-solo-controls > :is(#soloButton, #friendButton) {
  padding-inline: 8px;
  white-space: nowrap;
}
/* A game to finish takes the light: the gold العب quiets until it is done. */
html[data-majlis~="lobby"] #lobbyPanel#lobbyPanel[data-resume] .panel .tkbite > #duoButton#duoButton:not(:disabled):not(.is-busy) {
  --mj-btn-face: var(--mj-slate-glass);
  --mj-btn-ink: var(--mj-ivory);
  --mj-btn-sub: var(--mj-ivory-2);
  --mj-btn-edge: rgba(242, 236, 221, .14);
  --mj-btn-shadow: inset 0 1px 0 rgba(255, 246, 222, .18), inset 0 -1px 0 rgba(0, 0, 0, .18);
  --mj-btn-lift: 0 2px 3px rgba(0, 0, 0, .34), 0 10px 20px -8px rgba(0, 0, 0, .55);
  --mj-btn-light: rgba(255, 250, 235, .16);
  font-weight: 800;
  text-shadow: none;
}
html[data-majlis~="lobby"] #lobbyPanel#lobbyPanel#lobbyPanel[data-resume] .panel .tkbite:has(> #duoButton#duoButton) {
  filter: none;
}

/* --- 2 · The «كمّل صكتك» card ------------------------------------------------- */

#resumeCard {
  box-sizing: border-box;
  inline-size: 100%;
  margin: 0 0 var(--mj-lobby-gap, 14px);
  padding: 10px 14px;
  border-radius: var(--mj-r-sheet, 18px);
  background: linear-gradient(180deg, rgba(var(--mj-gold-rgb, 224, 168, 60), .16), rgba(var(--mj-gold-rgb, 224, 168, 60), .05));
  box-shadow: inset 0 0 0 1.5px rgba(var(--mj-gold-rgb, 224, 168, 60), .72), 0 0 30px rgba(var(--mj-gold-rgb, 224, 168, 60), .14);
  color: var(--mj-ivory, #F2ECDD);
  text-align: start;
}
#resumeCard.is-taken {
  background: rgba(233, 163, 91, .08);
  box-shadow: inset 0 0 0 1.5px rgba(233, 163, 91, .6);
}
#resumeCard.is-ended {
  background: rgba(127, 199, 154, .08);
  box-shadow: inset 0 0 0 1.5px rgba(127, 199, 154, .55);
}
#resumeCard .qm-card-kicker {
  margin: 0 0 2px;
  color: var(--mj-gold-300, #FBD549);
  font: 700 .875rem / 1.4 var(--mj-font-ui, Zain, sans-serif);
}
#resumeCard.is-taken .qm-card-kicker { color: #E9A35B; }
#resumeCard.is-ended .qm-card-kicker { color: #7FC79A; }
#resumeCard .qm-card-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
#resumeCard .qm-card-text {
  flex: 1;
  min-inline-size: 0;
  font: 700 var(--mj-fs-body, 1rem) / 1.35 var(--mj-font-ui, Zain, sans-serif);
}
#resumeCard .qm-card-text > span {
  display: block;
}
#resumeCard .qm-card-score {
  color: var(--mj-gold-300, #FBD549);
  font-weight: 800;
  font-size: .9375rem;
}
#resumeCard .qm-card-note {
  color: var(--mj-ivory-2, #B9B2A2);
  font-weight: 400;
  font-size: .875rem;
}
#resumeCard .qm-card-go {
  flex: none;
  min-inline-size: 92px;
  min-block-size: 46px;
  padding: 6px 16px;
}
/* The smallest phones (320x568) keep the lobby on one screen with the card on it. */
@media (max-height: 600px) {
  #resumeCard { padding-block: 8px; margin-block-end: 10px;
    display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; align-items: center; }
  /* كمّل stands beside the heading and the line together. */
  #resumeCard .qm-card-row { display: contents; }
  #resumeCard .qm-card-kicker { grid-column: 1; grid-row: 1; margin: 0; }
  #resumeCard .qm-card-text { grid-column: 1; grid-row: 2; }
  #resumeCard .qm-card-go { grid-column: 2; grid-row: 1 / span 2; }
}
/* A 320-wide phone keeps the card's line on one row: the narrower كمّل gives it room. */
@media (max-width: 360px) {
  #resumeCard { padding-inline: 12px; }
  #resumeCard .qm-card-row { gap: 8px; }
  #resumeCard .qm-card-go { min-inline-size: 72px; padding-inline: 12px; }
  #resumeCard .qm-card-text { font-size: .8333rem; }
}

/* --- 3 · The search, found, the offer ------------------------------------------ */

/* The search happens in the lobby's own room (owner, 2026-10-22: "match the
   background of our game"): the dialog is clear, so the cloth, the lamp and the
   mark behind it are the lobby's own layers, and only the controls under the
   mark dissolve into these words (quick_lobby.js `fadeLobby`). Every colour,
   face and type below is a majlis token. */
html[data-quick] body { overflow: hidden; }
.qm-dialog {
  box-sizing: border-box;
  position: fixed;
  inset: 0;
  inline-size: 100%;
  max-inline-size: none;
  block-size: 100%;
  max-block-size: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--mj-ivory, #F2ECDD);
  font-family: var(--mj-font-ui, Zain, sans-serif);
  overflow: hidden;
}
.qm-dialog::backdrop { background: transparent; }
/* Without the majlis layer there is no lamp room behind: a plain night. */
html:not([data-majlis~="system"]) .qm-dialog { background: #10111B; }
.qm-screen,
.qm-was {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-block-size: 100%;
  padding: var(--qm-top, max(56px, calc(env(safe-area-inset-top, 0px) + 40px))) var(--mj-gutter, 16px)
    max(24px, calc(env(safe-area-inset-bottom, 0px) + 16px));
}
/* The words a state change replaces, fading where they stood. */
.qm-was {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.qm-screen > *,
.qm-was > * {
  inline-size: 100%;
  max-inline-size: 358px;
  margin-inline: auto;
}
.qm-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
/* The count sits in a well cut into the cloth, as the name field is. */
.qm-ring {
  position: relative;
  inline-size: 168px;
  block-size: 168px;
  margin-block-start: 18px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, rgba(var(--mj-lamp-rgb, 255, 214, 150), .06), rgba(var(--mj-lamp-rgb, 255, 214, 150), 0) 64%),
    var(--mj-well, linear-gradient(180deg, #0E0F18, #10111B));
  box-shadow: var(--mj-sunk, inset 0 2px 7px rgba(0, 0, 0, .45)), 0 0 0 1px rgba(242, 236, 221, .06),
    0 18px 40px -18px rgba(0, 0, 0, .7);
}
.qm-ring svg {
  position: absolute;
  inset: -6px;
  inline-size: calc(100% + 12px);
  block-size: calc(100% + 12px);
  transform: rotate(-90deg);
  overflow: visible;
}
.qm-ring circle { fill: none; stroke-width: 4.5; }
.qm-ring-track { stroke: rgba(242, 236, 221, .10); }
.qm-ring-bar {
  stroke: var(--mj-gold-300, #FBD549);
  stroke-linecap: round;
  filter: drop-shadow(0 0 3px rgba(var(--mj-lamp-rgb, 255, 214, 150), .55));
  transition: stroke-dashoffset 1s linear;
}
.qm-ring.is-stopped .qm-ring-bar { stroke: rgba(242, 236, 221, .28); filter: none; transition: none; }
.qm-count {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
}
.qm-sec {
  color: var(--mj-ivory, #F2ECDD);
  font: 800 3.5rem / 1 var(--mj-font-ui, Zain, sans-serif);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 0 rgba(0, 0, 0, .55);
}
.qm-count small {
  display: block;
  margin-top: 2px;
  color: var(--mj-ivory-4, rgba(242, 236, 221, .46));
  font: 400 .9375rem / 1.2 var(--mj-font-ui, Zain, sans-serif);
}
.qm-title {
  margin: 20px 0 2px;
  color: var(--mj-ivory, #F2ECDD);
  font: 800 var(--mj-fs-title, 1.5rem) / 1.4 var(--mj-font-ui, Zain, sans-serif);
  text-shadow: 0 1px 0 rgba(0, 0, 0, .55), 0 0 24px rgba(var(--mj-lamp-rgb, 255, 214, 150), .18);
}
.qm-sub {
  margin: 8px 12px 0;
  color: var(--mj-ivory-2, rgba(242, 236, 221, .8));
  font: 400 var(--mj-fs-body, 1rem) / 1.6 var(--mj-font-ui, Zain, sans-serif);
}
.qm-faint { color: var(--mj-ivory-4, rgba(242, 236, 221, .46)); font-size: .9375rem; }
.qm-dots { display: inline-flex; gap: 6px; margin-top: 4px; }
.qm-dots span {
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: var(--mj-gold-300, #FBD549);
  opacity: .3;
  animation: qm-dot 1.4s ease-in-out infinite;
}
.qm-dots span:nth-child(2) { animation-delay: .2s; }
.qm-dots span:nth-child(3) { animation-delay: .4s; }
@keyframes qm-dot { 50% { opacity: .95; } }
@media (prefers-reduced-motion: reduce) {
  .qm-dots span { animation: none; opacity: .7; }
  .qm-ring-bar { transition: none; }
}
.qm-pair {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 14px;
  margin: 26px 0 18px;
}
.qm-who {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  inline-size: 112px;
}
.qm-who b { font: 800 var(--mj-fs-control, 1.0625rem) / 1.3 var(--mj-font-ui, Zain, sans-serif); overflow-wrap: anywhere; }
.qm-who em { color: var(--mj-ivory-4, rgba(242, 236, 221, .46)); font: 400 .875rem / 1.3 var(--mj-font-ui, Zain, sans-serif); font-style: normal; }
/* A seat badge is a slate tile, lit from the lamp, as the lobby's controls are. */
.qm-av {
  display: grid;
  place-items: center;
  inline-size: 72px;
  block-size: 72px;
  border-radius: 50%;
  background: var(--mj-slate-glass, linear-gradient(#363C4D, #282D3D));
  box-shadow: inset 0 0 0 1.5px rgba(var(--mj-gold-rgb, 224, 168, 60), .7), var(--mj-e2, 0 10px 20px -8px rgba(0, 0, 0, .55));
  color: var(--mj-ivory, #F2ECDD);
  font: 800 1.75rem / 1 var(--mj-font-ui, Zain, sans-serif);
}
.qm-av.is-ai {
  box-shadow: inset 0 0 0 1.5px var(--mj-agent-hi, #7E71F4), var(--mj-e2, 0 10px 20px -8px rgba(0, 0, 0, .55)),
    0 0 22px -6px var(--mj-agent-glow, rgba(92, 76, 238, .34));
}
/* Saikal's badge wears the lobby's own drawing of the mark (styles/majlis-v16.css
   --mj-mark-cards, byte for byte): no SVG filter, so no lamp glow between its lines. */
.qm-av-mark {
  inline-size: 44px;
  block-size: 42.3px;
  background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 707.97 681.23' preserveAspectRatio='none'><defs><clipPath id='c'><path d='M158.59 535.52L98.73 201.96A48 47.4-10.175 0 1 137.6 146.82L405.4 98.76A48 47.4-10.175 0 1 461.02 136.93L466.96 170.06L441.92 166.4L437.39 141.17A24 24.6-10.175 0 0 409.43 121.2L141.63 169.26A24 24.6-10.175 0 0 122.35 197.72L182.46 532.66A1545.4 1545.4 0 0 0 158.59 535.52ZM137.67 560.57A1523.4 1523.4 0 0 1 571.32 560.57A11.4 11.4 0 0 1 568.07 583.13A1500.6 1500.6 0 0 0 140.92 583.13A11.4 11.4 0 0 1 137.67 560.57Z M215.75 529.3L263.08 204.98A48 48 0 0 1 317.5 164.42L568.96 201.11A48 48 0 0 1 609.52 255.54L568.31 537.92A1545.4 1545.4 0 0 0 215.75 529.3Z M209.13 198.75A15 15 0 1 0 239.13 198.75A15 15 0 1 0 209.13 198.75Z M163.1 264.92A15 15 0 1 0 193.1 264.92A15 15 0 1 0 163.1 264.92Z M194.12 198.55L177.88 201.46A16.5 16.5 0 0 0 164.56 220.62L167.47 236.86A5.5 5.5 0 0 0 178.3 234.92L175.39 218.68A5.5 5.5 0 0 1 179.83 212.29L196.07 209.38A5.5 5.5 0 0 0 194.12 198.55Z'/></clipPath><linearGradient id='g1' gradientUnits='userSpaceOnUse' x1='327.75' y1='98' x2='327.75' y2='583.2'><stop offset='0' stop-color='%23fbf3df'/><stop offset='0.05' stop-color='%23f4e3be'/><stop offset='0.5' stop-color='%23e3cd9c'/><stop offset='1' stop-color='%23d9be86'/></linearGradient><linearGradient id='g2' gradientUnits='userSpaceOnUse' x1='413' y1='98' x2='413' y2='583.2'><stop offset='0' stop-color='%23fbf3df'/><stop offset='0.05' stop-color='%23f4e3be'/><stop offset='0.5' stop-color='%23e3cd9c'/><stop offset='1' stop-color='%23d9be86'/></linearGradient><linearGradient id='g3' gradientUnits='userSpaceOnUse' x1='353.98' y1='98' x2='353.99' y2='583.2'><stop offset='0' stop-color='%23eedcb0'/><stop offset='1' stop-color='%23d9be86'/></linearGradient></defs><g clip-path='url(%23c)'><rect x='0' y='0' width='707.97' height='681.23' fill='url(%23g3)'/><rect x='215' y='171' width='396' height='367.5' fill='url(%23g2)'/><rect x='215' y='163' width='225.5' height='18' fill='url(%23g1)'/><rect x='162.5' y='183.5' width='77' height='97' fill='%237e71f4'/></g></svg>") center / contain no-repeat;
}
/* Between the two seats, the woven rule's diamond (the opening's own pip): an
   isolated و in this face reads as a 9. */
.qm-amp {
  align-self: center;
  flex: none;
  inline-size: 8px;
  block-size: 8px;
  margin-block-end: 30px;
  rotate: 45deg;
  background: var(--mj-gold-300, #FBD549);
  box-shadow: 0 0 10px rgba(var(--mj-lamp-rgb, 255, 214, 150), .55);
}
/* The line under a pair is a slate plate, as the notebook is. */
.qm-vs {
  margin: 0;
  padding: 10px 16px;
  border-radius: var(--mj-r-control, 14px);
  background: var(--mj-slate-glass, rgba(40, 45, 61, .9));
  box-shadow: inset 0 0 0 1px var(--mj-slate-edge, rgba(242, 236, 221, .14)), var(--mj-e1, 0 1px 2px rgba(0, 0, 0, .42));
  color: var(--mj-ivory-2, rgba(242, 236, 221, .8));
  font: 400 var(--mj-fs-body, 1rem) / 1.55 var(--mj-font-ui, Zain, sans-serif);
}
.qm-vs b { color: var(--mj-ivory, #F2ECDD); font-weight: 800; }
.qm-vs .qm-keep { white-space: nowrap; }
.qm-line {
  margin: 14px 0 0;
  padding: 10px 14px;
  border-radius: var(--mj-r-control, 14px);
  background: var(--mj-slate-glass, rgba(40, 45, 61, .9));
  box-shadow: inset 0 0 0 1px var(--mj-slate-edge, rgba(242, 236, 221, .14)), var(--mj-e1, 0 1px 2px rgba(0, 0, 0, .42));
  color: var(--mj-ivory, #F2ECDD);
  font: 400 .9375rem / 1.55 var(--mj-font-ui, Zain, sans-serif);
  text-align: start;
}
.qm-line::before {
  content: "!";
  display: inline-grid;
  place-items: center;
  inline-size: 18px;
  block-size: 18px;
  margin-inline-end: 8px;
  border-radius: 50%;
  background: var(--mj-aqeeq-lit, #C4402C);
  color: #fff;
  font-size: .75rem;
  font-weight: 800;
}
.qm-actions {
  display: grid;
  gap: 10px;
}
.qm-actions .mj-btn { inline-size: 100%; }
.qm-dealing {
  justify-items: center;
  color: var(--mj-ivory-2, rgba(242, 236, 221, .8));
  font: 400 var(--mj-fs-body, 1rem) / 1.5 var(--mj-font-ui, Zain, sans-serif);
}
/* Short glass (320x568): the ring and the gaps come down, nothing scrolls. */
@media (max-height: 640px) {
  .qm-ring { inline-size: 136px; block-size: 136px; margin-block-start: 8px; }
  .qm-sec { font-size: 2.75rem; }
  .qm-title { margin-block-start: 12px; font-size: 1.3125rem; }
  .qm-pair { margin: 14px 0 12px; }
  .qm-av { inline-size: 60px; block-size: 60px; font-size: 1.5rem; }
  .qm-av-mark { inline-size: 36px; block-size: 34.6px; }
}
html[data-majlis~="system"] .qm-dialog .mj-btn.qm-ai {
  --mj-btn-face: linear-gradient(180deg, var(--mj-agent-hi, #7E71F4), var(--mj-agent, #5C4CEE));
  --mj-btn-ink: #fff;
  --mj-btn-edge: rgba(58, 47, 168, .9);
  --mj-btn-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), inset 0 -1px 0 rgba(40, 30, 120, .5);
  --mj-btn-lift: 0 2px 3px rgba(0, 0, 0, .34), 0 14px 26px -12px var(--mj-agent-glow, rgba(92, 76, 238, .34));
  min-block-size: 56px;
  font-size: var(--mj-fs-lead, 1.3125rem);
}
html[data-majlis~="system"] .qm-dialog .mj-btn.qm-ghost {
  --mj-btn-face: rgba(16, 17, 27, .35);
  --mj-btn-ink: var(--mj-ivory-2, rgba(242, 236, 221, .8));
  --mj-btn-edge: rgba(242, 236, 221, .18);
  --mj-btn-shadow: none;
  --mj-btn-lift: none;
}
/* main's .tkb display rule would show it: hidden means hidden, with the layer or without. */
#friendButton[hidden] { display: none; }
/* Without the majlis layer the sheets are plain dark sheets, never a browser's white box. */
html:not([data-majlis~="system"]) .qm-sheet {
  box-sizing: border-box;
  inline-size: min(100% - 24px, 460px);
  max-block-size: calc(100dvh - 24px);
  margin: auto auto 12px;
  padding: 20px 18px;
  border: 1px solid #4f5669;
  border-radius: 18px;
  background: #1d2130;
  color: #F2ECDD;
  font: 400 1.0625rem / 1.45 Zain, sans-serif;
}
html:not([data-majlis~="system"]) .qm-sheet::backdrop { background: rgba(8, 9, 14, .72); }
html:not([data-majlis~="system"]) .qm-sheet h2 { margin: 0 0 8px; font-size: 1.375rem; text-align: center; }
html:not([data-majlis~="system"]) .qm-sheet :is(.mj-btn, .qm-link) { display: block; inline-size: 100%; margin-block-start: 10px; }
html:not([data-majlis~="system"]) .qm-sheet .qm-coderow { display: flex; gap: 8px; }
html:not([data-majlis~="system"]) .qm-sheet .qm-coderow .mj-btn { inline-size: auto; margin: 0; }
/* Without the majlis layer the screen keeps plain, readable buttons. */
html:not([data-majlis~="system"]) .qm-dialog button,
html:not([data-majlis~="system"]) .qm-sheet button {
  min-block-size: 48px;
  border-radius: 14px;
  border: 1px solid #4f5669;
  background: #323849;
  color: #F2ECDD;
  font: 800 1.0625rem / 1.3 Zain, sans-serif;
}

/* --- 4 · The sheets: عندك خوي, a guest's العب ----------------------------------- */

/* Clear of the home bar as the lobby's own controls are (quick_lobby.js passes the
   lobby's --sa-b in as --qm-sa-b). */
html[data-majlis~="system"] .hx-dialog.qm-sheet,
html:not([data-majlis~="system"]) .qm-sheet {
  margin-block-end: max(12px, env(safe-area-inset-bottom), var(--qm-sa-b, 0px));
}

.qm-sheet .hx-report { text-align: center; }
.qm-sheet .hx-moment { font-weight: 400; color: var(--mj-ivory-2, #B9B2A2); }
.qm-or {
  margin: 4px 0 0;
  color: rgba(242, 236, 221, .55);
  font: 400 .9375rem / 1.4 var(--mj-font-ui, Zain, sans-serif);
}
.qm-coderow {
  display: flex;
  gap: 8px;
}
.qm-sheet .qm-code {
  flex: 1;
  min-inline-size: 0;
  min-block-size: 48px;
  box-sizing: border-box;
  padding: 0 14px;
  border: 1px solid #4f5669;
  border-radius: 12px;
  background: #0d0e16;
  color: var(--mj-ivory, #F2ECDD);
  font: 700 1.0625rem / 1 var(--mj-font-ui, Zain, sans-serif);
  letter-spacing: 3px;
  text-align: center;
}
.qm-sheet .qm-code:placeholder-shown { direction: rtl; letter-spacing: 0; }
.qm-sheet .qm-code:focus-visible {
  outline: var(--mj-focus-width, 2px) solid var(--mj-focus-color, #FBD549);
  outline-offset: var(--mj-focus-gap, 3px);
}
.qm-sheet .qm-enter { flex: none; min-inline-size: 84px; }
.qm-sheet .qm-error:not(:empty) {
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(10, 11, 18, .5);
  color: var(--mj-ivory, #F2ECDD);
  text-align: start;
}
.qm-sheet .qm-error:not(:empty)::before {
  content: "!";
  display: inline-grid;
  place-items: center;
  inline-size: 18px;
  block-size: 18px;
  margin-inline-end: 6px;
  border-radius: 50%;
  background: #d8473b;
  color: #fff;
  font-size: .75rem;
  font-weight: 800;
}
.qm-link {
  justify-self: center;
  min-block-size: 44px;
  padding: 0 12px;
  border: 0;
  background: none;
  color: var(--mj-ivory-2, #B9B2A2);
  font: 400 1rem / 1.4 var(--mj-font-ui, Zain, sans-serif);
  text-decoration: underline;
  text-underline-offset: 5px;
  cursor: pointer;
}
.qm-link:focus-visible {
  outline: var(--mj-focus-width, 2px) solid var(--mj-focus-color, #FBD549);
  outline-offset: var(--mj-focus-gap, 3px);
}
