{"id":"l-ds-5-2","courseId":"design-systems","lang":"ar","kind":"lesson","summary":"أضف علامة تجارية ثانية إلى نظام التصميم بطبقة علامة صغيرة بين الـ primitives والـ semantic tokens، وتحقّق من التباين لكل علامة، وحدّد ما يحقّ للعلامات تغييره وما لا يحقّ لها.","html":"<p>بعد ثمانية أشهر من استحواذ Northwind على Tidewater، انتقل موقعها التسويقي إلى Northwind UI. جاء فريق علامة Tidewater ومعه دليل علامة من 60 صفحة، وخط serif، ولوحة ألوان فيروزية، وأزرار على شكل حبّة دواء (pill). وجاء أيضًا بقائمة من 23 «متطلّبًا للعلامة» في المكوّنات. كانت مهمّتنا أن نقول نعم للعلامة ولا لمعظم القائمة، وأن نجعل الأمرين يبدوان معقولين.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">ما يحقّ للعلامة تغييره</h2>\n<p>رسم الحوار الأول حدًّا واضحًا. العلامة تغيّر <strong>الشخصية</strong>: لوحة الألوان، والخطوط، ونصف قطر الزوايا، وأسلوب الرسوم، ونبرة الكتابة. ولا تغيّر <strong>السلوك أو البنية</strong>: التعامل مع لوحة المفاتيح، وإدارة التركيز، وسُلّم المسافات، وشبكات التخطيط، والـ component APIs، وإمكانية الوصول. يمكن أن تكون أزرار Tidewater حبّات فيروزية بتسمية بخط serif. لكن لا يمكنها أن تغلق النوافذ عند النقر خارجها بينما لا تفعل نوافذ Northwind ذلك، لأن هذا قرار منتج لا قرار علامة.</p>\n<p>من المتطلّبات الثلاثة والعشرين، تبيّن أن 15 منها بصرية وتناسب الـ tokens. وستة كانت طلبات سلوك، فمرّت عبر مراجعة الـ API كاقتراحات عادية للعلامتين معًا (قُبل اثنان منها، للعلامتين). وأُسقط اثنان.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">طبقة العلامة</h2>\n<p>قدّم القسم 2 تدرّجًا للعلامة حتى يستطيع الوضع الداكن اختيار الدرجات. ولعلامة ثانية كاملة، يكبر ذلك التدرّج ليصبح طبقة خاصة بين الـ primitives والـ semantic tokens:</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 660 230\" role=\"img\" aria-labelledby=\"l-ds-5-2-t1\"><defs><marker id=\"arrow-l-ds-5-2-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-ds-5-2-t1\">الـ primitives تضم لوحتي الأزرق والفيروزي وعائلتي خطوط. طبقة علامة Northwind تربط الـ brand tokens بالأزرق وInter؛ وطبقة علامة Tidewater تربطها بالفيروزي وGeorgia. الـ semantic tokens تشير إلى الـ brand tokens، والمكوّنات تشير إلى الـ semantic tokens.</title>\n  <rect class=\"d-box\" x=\"20\" y=\"20\" width=\"140\" height=\"190\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"90\" y=\"46\" text-anchor=\"middle\">Primitives</text>\n  <text class=\"d-code\" x=\"90\" y=\"80\" text-anchor=\"middle\">blue-*</text>\n  <text class=\"d-code\" x=\"90\" y=\"106\" text-anchor=\"middle\">teal-*</text>\n  <text class=\"d-code\" x=\"90\" y=\"132\" text-anchor=\"middle\">inter</text>\n  <text class=\"d-code\" x=\"90\" y=\"158\" text-anchor=\"middle\">georgia</text>\n  <rect class=\"d-box-primary\" x=\"200\" y=\"20\" width=\"160\" height=\"84\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"280\" y=\"48\" text-anchor=\"middle\">العلامة: Northwind</text>\n  <text class=\"d-code\" x=\"280\" y=\"78\" text-anchor=\"middle\">brand-600 → blue</text>\n  <rect class=\"d-box-success\" x=\"200\" y=\"126\" width=\"160\" height=\"84\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"280\" y=\"154\" text-anchor=\"middle\">العلامة: Tidewater</text>\n  <text class=\"d-code\" x=\"280\" y=\"184\" text-anchor=\"middle\">brand-600 → teal</text>\n  <rect class=\"d-box-accent\" x=\"400\" y=\"80\" width=\"120\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"460\" y=\"120\" text-anchor=\"middle\">Semantic</text>\n  <rect class=\"d-box\" x=\"550\" y=\"80\" width=\"100\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"600\" y=\"120\" text-anchor=\"middle\">المكوّنات</text>\n  <path class=\"d-arrow\" d=\"M200 62 L164 90\" marker-end=\"url(#arrow-l-ds-5-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M200 168 L164 140\" marker-end=\"url(#arrow-l-ds-5-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M400 105 L364 70\" marker-end=\"url(#arrow-l-ds-5-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M400 125 L364 160\" marker-end=\"url(#arrow-l-ds-5-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M550 115 L524 115\" marker-end=\"url(#arrow-l-ds-5-2-1)\"/>\n</svg><figcaption>طبقة العلامة تقع بين الـ primitives والـ semantic tokens</figcaption></figure>\n<p>طبقة العلامة صغيرة عن قصد. في Northwind تضم 24 token: تدرّج ألوان من 50 إلى 900، وعائلة خط للعناوين وأخرى للمتن، ونصفا قطر، ولون لحلقة التركيز. الـ semantic tokens تشير إلى الـ brand tokens، والمكوّنات لا تعرف أبدًا أن هناك علامة أصلًا.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">CSS</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">:root</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">data-brand</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] {</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-color-action-bg</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">--nw-brand-600</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-color-action-text</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">--nw-white</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-font-heading</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">--nw-brand-font-heading</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-radius-control</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">--nw-brand-radius-control</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">data-brand</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"tidewater\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] {</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-brand-600</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">--nw-teal-600</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-brand-700</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">--nw-teal-700</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-brand-font-heading</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">Georgia</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Times New Roman'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">serif</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-brand-radius-control</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">999</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">px</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#6E7781;--shiki-dark:#8B949E\">  /* Tidewater's 600 fails contrast with white text: use the darker step. */</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">  --nw-color-action-bg</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">--nw-brand-700</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>الـ selector المسمّى <code dir=\"ltr\">:root, [data-brand]</code> مهمّ. تذكّر من درس الـ themes أن الـ custom property التي تحتوي <code dir=\"ltr\">var()</code> تُحسب حيث عُرّفت. لو عُرّف <code dir=\"ltr\">--nw-color-action-bg</code> على <code dir=\"ltr\">:root</code> وحده، لحُسب مرة واحدة بتدرّج Northwind، ولورث قسم Tidewater في الصفحة نفسها أزرق Northwind. أما إعادة تعريف الروابط الدلالية على كل عنصر <code dir=\"ltr\">[data-brand]</code> فتجعلها تُحسب داخل نطاق كل علامة. وهذا ما يسمح لصفحة المقارنة المشتركة في Northwind بعرض العلامتين جنبًا إلى جنب.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">التباين لكل علامة</h2>\n<p>السطر الأخير في كتلة Tidewater هو المثير للاهتمام. لون الإجراء في Northwind هو الدرجة 600 من تدرّجها. أما 600 في Tidewater فأفتح، فيفشل نص الزر الأبيض فوقه:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"1\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> luminance</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">hex</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">r</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">g</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">b</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">i</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> parseInt</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(hex.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">slice</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(i, i </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">16</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 255</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    .</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">v</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (v </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">&#x3C;=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.04045</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> v </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 12.92</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> ((v </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.055</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 1.055</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">**</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2.4</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">));</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.2126</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> r </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.7152</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> g </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.0722</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> *</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> b;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> contrast</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">a</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">b</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">hi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">lo</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">luminance</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(a), </span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">luminance</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(b)].</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">sort</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">x</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">y</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> y </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> x);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (hi </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.05</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (lo </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.05</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> pairs</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'northwind blue-600'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'#1f5ae0'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'tidewater teal-600'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'#0d9488'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'tidewater teal-700'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'#0f766e'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">name</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">bg</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">of</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> Object.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">entries</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(pairs)) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> ratio</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> contrast</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(bg, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'#ffffff'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">`${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">name</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">} + white text: ${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">ratio</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">toFixed</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">}:1 ${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">ratio</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> >=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 4.5</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ?</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'pass'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'FAIL'}`</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>لذا تربط Tidewater الدور الدلالي نفسه بدرجة مختلفة. ولهذا لا تكتفي طبقة العلامة بتبديل لوحات الألوان عشوائيًا: فالربط الدلالي لكل علامة مصمَّم ومفحوص. وفحص التباين في خط الإنتاج لدى Northwind يمرّ على كل زوج موثّق في كل علامة وكل theme، وقد التقط هذه المشكلة قبل أن يرى فريق العلامة زرًا واحدًا.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>منطق العلامة داخل المكوّنات</span></p>\n<p>أضاف أول pull request لـ Tidewater الشرط <code dir=\"ltr\">if (brand === 'tidewater')</code> إلى الـ Button. وخلال شهر صار في خمسة مكوّنات شروط خاصة بالعلامة، ولم يعد أحد قادرًا على إضافة علامة ثالثة دون لمسها كلها. إن تعذّر التعبير عن اختلاف ما بـ token، فاسأل هل هو حقًّا اختلاف علامة.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">تسليم العلامات</h2>\n<p>كل واجهة تحمّل ما تحتاجه. المواقع التسويقية تضع <code dir=\"ltr\">data-brand</code> على <code dir=\"ltr\">&lt;html&gt;</code> ولا تحمّل إلا ملف CSS الخاص بعلامتها، الذي يولّده خط الإنتاج من <code dir=\"ltr\">primitives</code> + <code dir=\"ltr\">brand-tidewater</code> + <code dir=\"ltr\">semantic</code>. أما تطبيق الـ dispatch، الذي يعرض العلامتين في شاشات الإدارة، فيحمّل الكتلتين. وفي Figma تعيش البنية نفسها في المجموعات الممتدّة، فيرى مصمّمو Tidewater المتغيّرات الدلالية المشتركة بقيم علامتهم.</p>\n<p>وكل علامة تضاعف أيضًا مصفوفة الاختبار. مع علامتين ونظامي ألوان ومستويي كثافة، يُعرض كل مكوّن أساسي في ثماني تركيبات في المجموعة البصرية من القسم 4. يبدو ذلك مكلفًا حتى تتذكّر البديل: مصمّم في Tidewater يكتشف في الإنتاج أن حلقة التركيز في الوضع الداكن غير مرئية على الفيروزي. الآلات مراجِعون رخيصون للتركيبات؛ والبشر لا ينظرون إلا إلى الفروقات.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>ضع ميزانية لمساحة العلامة</span></p>\n<p>تراجع Northwind أي طلب لتوسيع طبقة العلامة بعد الـ 24 token. كل brand token جديد يضاعف التركيبات التي تختبرها. ومساحة علامة صغيرة وثابتة هي ما يجعل إضافة علامة ثالثة عمل أسبوعين بدل ربع سنة.</p>\n</aside>\n<p>في التمرين تضيف Tidewater إلى صفحة تظهر فيها العلامتان جنبًا إلى جنب. وبعدها تقيس هل يُستخدم كل هذا فعلًا.</p>\n","toc":[{"id":"sec-1","text":"ما يحقّ للعلامة تغييره","level":2},{"id":"sec-2","text":"طبقة العلامة","level":2},{"id":"sec-3","text":"التباين لكل علامة","level":2},{"id":"sec-4","text":"تسليم العلامات","level":2}],"takeaways":["العلامة تغيّر الشخصية (تدرّج الألوان، والخطوط، والأشكال) عبر مجموعة صغيرة من brand tokens؛ أما السلوك والمسافات وإمكانية الوصول فتبقى مشتركة.","ضع طبقة للعلامة بين الـ primitives والـ semantic tokens، حتى تربط كل علامة الأسماء الدلالية نفسها بلوحة ألوانها الخاصة.","يجب فحص التباين لكل علامة على حدة، وقد تحتاج علامة درجة مختلفة من تدرّجها للدور الدلالي نفسه.","حين يمكن أن تظهر العلامات جنبًا إلى جنب، أعد تعريف الروابط الدلالية تحت الـ selector الخاص بالعلامة حتى تُحسب داخل نطاق كل علامة."],"further":[{"title":"Understanding SC 1.4.3 Contrast (Minimum) (W3C)","url":"https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html"},{"title":"Extend a variable collection (Figma)","url":"https://help.figma.com/hc/en-us/articles/36346281624471-Extend-a-variable-collection"},{"title":"Using CSS custom properties (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascading_variables/Using_custom_properties"}],"quiz":[{"q":"<p>يطلب فريق علامة Tidewater أن يُغلق الـ Dialog الخاص بها حين ينقر الناس خارجه، بينما لا يفعل ذلك Dialog الخاص بـ Northwind. كيف يجب أن يستجيب النظام؟</p>","options":[{"text":"إضافة prop باسم <code dir=\"ltr\">brand</code> إلى Dialog يبدّل السلوك.","why":"السلوك الخاص بكل علامة داخل المكوّنات يعني أن كل مكوّن يجب أن يعرف عن كل علامة، وهذا لا يصمد بعد علامتين."},{"text":"نسخ Dialog منفصل لـ Tidewater.","why":"نسختا Dialog ستتباعدان في الإصلاحات وإمكانية الوصول، وهذه هي التكلفة التي وُجد النظام لتجنّبها."},{"text":"معاملته كسؤال عن سلوك المنتج للعلامتين معًا يُحسم في مراجعة الـ API؛ فالعلامات تغيّر الشكل والصوت لا السلوك.","why":"صحيح. إن كان الإغلاق بالنقر خارجًا صحيحًا فهو صحيح للعلامتين؛ وإن لم يكن، فهو خاطئ للاثنتين."},{"text":"ترك Tidewater تخصّص JavaScript الخاص بالـ Dialog عبر theme token.","why":"الـ tokens تصف قيمًا بصرية؛ والسلوك المخبّأ في الـ tokens غير قابل للاختبار ومفاجئ."}],"answer":2},{"q":"<p>نسبة التباين لنص أبيض على teal-600 الخاص بـ Tidewater هي 3.74:1. ماذا يجب أن يكون ربط Tidewater لـ <code dir=\"ltr\">--nw-color-action-bg</code>؟</p>","options":[{"text":"إبقاء teal-600؛ فألوان العلامة مستثناة من قواعد التباين.","why":"لا يستثني WCAG العلامات؛ ونص الزر على تلك الخلفية يجب أن يصل إلى 4.5:1 في الحجم العادي."},{"text":"ربطه بـ teal-700 ‏(5.47:1 مع النص الأبيض) في كتلة علامة Tidewater.","why":"صحيح. الدور الدلالي نفسه، بدرجة أغمق من تدرّج العلامة نفسها، فينجح نص الزر."},{"text":"جعل نص الزر عريضًا حتى تكفي 3.74:1.","why":"عتبة 3:1 تنطبق على النص الكبير (نحو 18.66px عريض أو 24px عادي)؛ وتسمية الزر العريضة بالحجم العادي ما زالت تحتاج 4.5:1."},{"text":"استخدام أزرق Northwind لأزرار Tidewater.","why":"هذا ينجح في التباين لكنه يُسقط هوية Tidewater من أكثر عناصرها ظهورًا."}],"answer":1},{"q":"<p>في صفحة المقارنة المشتركة بين العلامتين، تبقى أزرار قسم Tidewater بأزرق Northwind، رغم أن <code dir=\"ltr\">[data-brand=&quot;tidewater&quot;]</code> يحدّد <code dir=\"ltr\">--nw-brand-600</code> بشكل صحيح. ما الناقص؟</p>","options":[{"text":"الـ semantic token المسمّى <code dir=\"ltr\">--nw-color-action-bg</code> معرّف على <code dir=\"ltr\">:root</code> وحده، فحُسبت قيمته بتدرّج Northwind عند الجذر.","why":"صحيح. إعادة تعريف الروابط الدلالية تحت <code dir=\"ltr\">[data-brand]</code> تجعلها تُحسب داخل قسم كل علامة."},{"text":"سمات <code dir=\"ltr\">data-brand</code> لا تعمل إلا على <code dir=\"ltr\">&lt;html&gt;</code>.","why":"الـ attribute selectors تطابق أي عنصر؛ المشكلة في مكان حساب الـ semantic token."},{"text":"يحتاج الزر إلى class باسم <code dir=\"ltr\">.tidewater</code>.","why":"الـ classes الواعية بالعلامة على المكوّنات هي بالضبط ما تتجنّبه طبقات الـ tokens."},{"text":"الـ custom properties لا يمكن تخصيصها مرتين في صفحة واحدة.","why":"يمكن إعادة تعريف الـ custom properties في أي مستوى؛ وكل عنصر يرى أقرب تعريف إليه."}],"answer":0}],"exercise":{"kind":"web","mode":"dom","starter":{"html":"<div class=\"compare\">\n  <section data-brand=\"northwind\" id=\"nw\">\n    <h2 class=\"nw-heading\">Northwind Dispatch</h2>\n    <button class=\"nw-button\" type=\"button\">Start trial</button>\n  </section>\n  <section data-brand=\"tidewater\" id=\"tw\">\n    <h2 class=\"nw-heading\">Tidewater Freight</h2>\n    <button class=\"nw-button\" type=\"button\">Get a quote</button>\n  </section>\n</div>","css":":root {\n  /* Primitives */\n  --nw-white: #ffffff;\n  --nw-blue-600: #1f5ae0;\n  --nw-blue-700: #1848b8;\n  --nw-teal-600: #0d9488;\n  --nw-teal-700: #0f766e;\n  --nw-font-inter: Inter, system-ui, sans-serif;\n  --nw-font-georgia: Georgia, 'Times New Roman', serif;\n\n  /* Brand tier: Northwind is the default */\n  --nw-brand-600: var(--nw-blue-600);\n  --nw-brand-700: var(--nw-blue-700);\n  --nw-brand-font-heading: var(--nw-font-inter);\n  --nw-brand-radius-control: 6px;\n}\n\n/* Semantic tier */\n:root {\n  --nw-color-action-bg: var(--nw-brand-600);\n  --nw-color-action-text: var(--nw-white);\n  --nw-font-heading: var(--nw-brand-font-heading);\n  --nw-radius-control: var(--nw-brand-radius-control);\n}\n\n/* Add the Tidewater brand here */\n\n/* Components: brand-agnostic, don't change */\n.nw-heading { font-family: var(--nw-font-heading); margin: 0 0 12px; }\n.nw-button {\n  --nw-button-bg: var(--nw-color-action-bg);\n  --nw-button-text: var(--nw-color-action-text);\n  background: var(--nw-button-bg);\n  color: var(--nw-button-text);\n  border: 0;\n  border-radius: var(--nw-radius-control);\n  padding: 8px 16px;\n  font: inherit;\n}\n.compare { display: grid; gap: 24px; }\n","js":""},"solution":{"html":"<div class=\"compare\">\n  <section data-brand=\"northwind\" id=\"nw\">\n    <h2 class=\"nw-heading\">Northwind Dispatch</h2>\n    <button class=\"nw-button\" type=\"button\">Start trial</button>\n  </section>\n  <section data-brand=\"tidewater\" id=\"tw\">\n    <h2 class=\"nw-heading\">Tidewater Freight</h2>\n    <button class=\"nw-button\" type=\"button\">Get a quote</button>\n  </section>\n</div>","css":":root {\n  /* Primitives */\n  --nw-white: #ffffff;\n  --nw-blue-600: #1f5ae0;\n  --nw-blue-700: #1848b8;\n  --nw-teal-600: #0d9488;\n  --nw-teal-700: #0f766e;\n  --nw-font-inter: Inter, system-ui, sans-serif;\n  --nw-font-georgia: Georgia, 'Times New Roman', serif;\n\n  /* Brand tier: Northwind is the default */\n  --nw-brand-600: var(--nw-blue-600);\n  --nw-brand-700: var(--nw-blue-700);\n  --nw-brand-font-heading: var(--nw-font-inter);\n  --nw-brand-radius-control: 6px;\n}\n\n/* Semantic tier, re-declared in every brand scope */\n:root,\n[data-brand] {\n  --nw-color-action-bg: var(--nw-brand-600);\n  --nw-color-action-text: var(--nw-white);\n  --nw-font-heading: var(--nw-brand-font-heading);\n  --nw-radius-control: var(--nw-brand-radius-control);\n}\n\n[data-brand=\"tidewater\"] {\n  --nw-brand-600: var(--nw-teal-600);\n  --nw-brand-700: var(--nw-teal-700);\n  --nw-brand-font-heading: var(--nw-font-georgia);\n  --nw-brand-radius-control: 999px;\n  /* teal-600 fails 4.5:1 with white text */\n  --nw-color-action-bg: var(--nw-brand-700);\n}\n\n/* Components: brand-agnostic, don't change */\n.nw-heading { font-family: var(--nw-font-heading); margin: 0 0 12px; }\n.nw-button {\n  --nw-button-bg: var(--nw-color-action-bg);\n  --nw-button-text: var(--nw-color-action-text);\n  background: var(--nw-button-bg);\n  color: var(--nw-button-text);\n  border: 0;\n  border-radius: var(--nw-radius-control);\n  padding: 8px 16px;\n  font: inherit;\n}\n.compare { display: grid; gap: 24px; }\n","js":""},"checks":[{"id":"northwind-intact","test":"const b = $('#nw .nw-button'); return style(b, 'background-color') === 'rgb(31, 90, 224)' && style(b, 'border-top-left-radius') === '6px' && style('#nw .nw-heading', 'font-family').startsWith('Inter');"},{"id":"tidewater-font","test":"return style('#tw .nw-heading', 'font-family').startsWith('Georgia');"},{"id":"tidewater-shape","test":"return style('#tw .nw-button', 'border-top-left-radius') === '999px';"},{"id":"tidewater-contrast","test":"const b = $('#tw .nw-button'); return style(b, 'background-color') === 'rgb(15, 118, 110)' && style(b, 'color') === 'rgb(255, 255, 255)';"},{"id":"no-brand-in-components","test":"const rules = [...document.styleSheets].flatMap((s) => [...s.cssRules]).filter((r) => r.selectorText); return rules.every((r) => !(/tidewater|data-brand/.test(r.selectorText) && /nw-(button|heading)/.test(r.selectorText)));"}],"title":"أضف Tidewater إلى صفحة المقارنة","prompt":"<p>صفحة المقارنة المشتركة تعرض العلامتين جنبًا إلى جنب، كلٌّ منهما في قسم له <code dir=\"ltr\">data-brand</code> خاص به. أضف علامة Tidewater <strong>دون لمس قواعد المكوّنات</strong>:</p>\n<ul>\n<li>العناوين تستخدم مجموعة خطوط Georgia ‏(<code dir=\"ltr\">--nw-font-georgia</code>)،</li>\n<li>الأزرار على شكل حبّة (نصف قطر <code dir=\"ltr\">999px</code>)،</li>\n<li>خلفية الزر هي <code dir=\"ltr\">--nw-teal-700</code>، لأن teal-600 يفشل في التباين مع النص الأبيض،</li>\n<li>يجب أن يبقى قسم Northwind تمامًا كما هو.</li>\n</ul>\n<p>حاليًا الطبقة الدلالية معرّفة على <code dir=\"ltr\">:root</code> وحده. فكّر أين تُحسب قيمها.</p>\n","hints":["اكتب كتلة <code dir=\"ltr\">[data-brand=&quot;tidewater&quot;] { … }</code> تربط الـ brand tokens (<code dir=\"ltr\">--nw-brand-font-heading</code> و<code dir=\"ltr\">--nw-brand-radius-control</code> والتدرّج) بقيم Tidewater.","الـ brand tokens وحدها لن تصل إلى القسم: فالـ semantic tokens حُسبت على <code dir=\"ltr\">:root</code> بقيم Northwind. غيّر الـ selector الخاص بالقاعدة الدلالية إلى <code dir=\"ltr\">:root, [data-brand]</code>.","داخل كتلة Tidewater، اربط أيضًا <code dir=\"ltr\">--nw-color-action-bg</code> بـ <code dir=\"ltr\">var(--nw-brand-700)</code>."],"explanation":"<p>كتلة العلامة لا تبدّل إلا قيم طبقة العلامة، ومعها ربط دلالي واحد تحتاجه Tidewater فعلًا من أجل التباين. وإعادة تعريف الطبقة الدلالية تحت <code dir=\"ltr\">[data-brand]</code> هي ما يجعل كل قسم يحسب <code dir=\"ltr\">--nw-color-action-bg</code> و<code dir=\"ltr\">--nw-font-heading</code> و<code dir=\"ltr\">--nw-radius-control</code> من الـ brand tokens الخاصة به، بدل أن يرث قيمًا حُسبت مسبقًا عند الجذر. والمكوّنات لا تذكر أي علامة أبدًا، فالعلامة الثالثة مجرّد كتلة إضافية.</p>\n","checkLabels":{"northwind-intact":"قسم Northwind يحتفظ بزرّه الأزرق ونصف القطر 6px وعناوين Inter","tidewater-font":"عناوين Tidewater تستخدم Georgia","tidewater-shape":"أزرار Tidewater على شكل حبّة (نصف قطر 999px)","tidewater-contrast":"أزرار Tidewater تستخدم teal-700 مع نص أبيض","no-brand-in-components":"لا توجد قاعدة تستهدف المكوّنات بحسب العلامة"}},"words":620,"readMinutes":4}