/* css/components.css - Blockout Hybrid UI/UX Components */

/* Modals */
.modal-overlay {
    position: fixed; top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0,0,0,0.4);
    backdrop-filter: blur(4px);
    z-index: 2000;
    display: none;
    align-items: center; justify-content: center;
    padding: 16px;
}
.modal-content {
    background: var(--bg-surface);
    border-radius: var(--radius-xl);
    width: 100%; max-width: 500px;
    box-shadow: var(--shadow-lg);
    animation: modalSlideUp 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    overflow: hidden;
}
@keyframes modalSlideUp { from { transform: translateY(30px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

/* "See details" cue on product cards — a hint, not a competing
   CTA. margin-top:auto is a deliberate no-op outside a flex
   column (resolves to 0), so the same class works unmodified in
   both flex-column cards (where it pins to the bottom) and plain
   list rows (where it just sits under the text with a small gap). */
.card-detail-cue {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 6px;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-tertiary);
    white-space: nowrap;
}
.card-detail-cue i,
.card-detail-cue svg {
    width: 13px;
    height: 13px;
    color: var(--primary);
    flex-shrink: 0;
}

/* Cards */
.card {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: 24px;
    box-shadow: var(--shadow-sm);
    margin-bottom: 24px;
    transition: var(--transition-normal);
}
.card:hover {
    box-shadow: var(--shadow-md);
}
.card-header {
    display: flex; justify-content: space-between; align-items: center;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 12px;
}
.card-title {
    font-size: 18px; font-weight: 800; color: var(--text-primary); margin: 0;
}

/* Timeline */
.timeline {
    position: relative;
    padding-right: 20px;
    margin-top: 16px;
}
.timeline::before {
    content: ''; position: absolute; top: 0; bottom: 0; right: 6px;
    width: 2px; background: var(--border-color);
}
.timeline-item {
    position: relative; padding-bottom: 24px;
}
.timeline-dot {
    position: absolute; right: -20px; top: 4px;
    width: 14px; height: 14px; border-radius: 50%;
    background: var(--primary); border: 3px solid var(--bg-surface);
    z-index: 2;
}
.timeline-date {
    font-size: 12px; font-weight: 700; color: var(--primary); margin-bottom: 4px;
}
.timeline-content {
    background: var(--bg-surface-hover);
    padding: 12px 16px; border-radius: var(--radius-md);
    font-size: 14px; color: var(--text-secondary);
}

/* Badges */
.badge {
    padding: 6px 12px; border-radius: var(--radius-full);
    font-size: 11px; font-weight: 700; display: inline-block;
}
.badge-danger { background: var(--primary); color: white; }
.badge-success { background: var(--success); color: white; }
.badge-info { background: var(--info, #007AFF); color: white; }
.badge-warning { background: var(--warning); color: #111827; }
.badge-orange { background: #f97316; color: white; }
.badge-secondary { background: #6b7280; color: white; }
.badge-outline { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); }

/* Buttons */
.btn {
    padding: 12px 24px; border-radius: var(--radius-md);
    font-family: var(--font-ar); font-size: 15px; font-weight: 700;
    cursor: pointer; border: none; transition: var(--transition-fast);
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn-primary { background: var(--primary); color: white; }
.btn-primary:hover { background: var(--primary-hover); }
.btn-outline { background: transparent; border: 1px solid var(--border-color); color: var(--text-primary); }
.btn-outline:hover { background: var(--bg-surface-hover); }
.btn-success { background: var(--success); color: white; }

/* Skeletons */
.skeleton {
    background: linear-gradient(90deg, var(--bg-surface-hover) 25%, var(--border-color) 50%, var(--bg-surface-hover) 75%);
    background-size: 200% 100%;
    animation: loading 1.5s infinite;
    border-radius: var(--radius-sm);
}
@keyframes loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* Map Container */
.gis-map-container {
    height: 400px; width: 100%; border-radius: var(--radius-lg); overflow: hidden;
    border: 1px solid var(--border-color);
}

/* iOS Safari Zoom Fix for Inputs */
@media screen and (max-width: 768px) {
    input, select, textarea {
        font-size: 16px !important;
    }
}

/* ===== صف الرجوع الموحّد ===== */
.page-back-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 20px; }
.page-back-btn { background: none; border: none; font-family: var(--font-ar); font-size: 14px; font-weight: 700;
    color: var(--text-secondary); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; padding: 6px 0; }
.page-back-btn:hover { color: var(--primary); }
.page-back-btn i { width: 18px; height: 18px; }
.page-back-title { font-size: 18px; font-weight: 800; margin: 0; color: var(--text-primary); text-align: left; }

/* ═════ صفّ التنبيه — المشترك بين /notifications ومعاينة /settings ═════
   الوسم في `views/components/notification-rows.php` والسلوك في
   `public/js/notifications.js`، فشكلُ المشترك بينهما هنا لا في رأس صفحة:
   قاعدةٌ في رأس /notifications وحدها تعني معاينةً بلا «جديد» مرئيّ على
   /settings — وهو الانحراف نفسه في ثوبٍ ثالث. و`.notif-alert` تُطبع من
   الخادم أيضاً (إخفاق التحميل) لا من جافاسكربت وحدها، فلا يجوز أن يتعلّق
   شكلها بتضمين المُصيِّر: القائمة الفارغة لا تضمّه أصلاً. */
/* ── لون الصفّ: صريحٌ هنا، لا موروثٌ من `a` العامّة ──
   `theme.css` يعطي كلّ رابط `color: var(--primary)` — وهو الأحمر. وصفُّ
   التنبيه رابطٌ كلّه (أو يحوي رابطاً)، فما لم يُنَصَّ على لونه صار نصُّه
   أحمر. كان القديم ينجو بحيلتين متفرّقتين: `style="color:inherit"` مكرّرة
   في كلّ صفٍّ من جافاسكربت، و`color: inherit` في `.notif-item` برأس
   /notifications. المُصيِّر الواحد لا يرث حيلتين، فالعقد صار قاعدةً واحدة.

   ولا `!important` هنا بحال: لوحة الإعدادات كانت تحقن `--primary` و
   `icon_color` بـ`!important` من `storage/settings.json`، فحُذف المصدر
   (`AdminController` يرفض الحقلين، و`head-assets.php` لا يحقن لوناً).
   `!important` مضادّة كانت ستعيد الكسر أوّل مرّة يُغيَّر فيها لون. الألوان
   رموزُ سمة، فتتبع الوضع الفاتح والمظلم وأيّ تبديل لاحق. */
.notif-row,
.notif-row a,
.notif-row:hover,
.notif-row a:hover        { color: var(--text-primary); text-decoration: none; }
.notif-row p              { color: var(--text-secondary); }
.notif-row .when          { color: var(--text-tertiary); }
/* الشارة تحمل لونها بنفسها فلا ترثه — أحمر بنصٍّ أبيض */
.notif-new-tag {
    display: inline-block; font-size: 10px; font-weight: 800; padding: 2px 8px;
    border-radius: 999px; background: var(--primary); color: #fff; margin-inline-start: 6px;
}
.activity-row .notif-compact-icon { width: 16px; height: 16px; color: var(--primary); margin-top: 3px; flex: 0 0 auto; }
.notif-alert {
    display: flex; gap: 10px; align-items: flex-start;
    border: 1px solid var(--danger, #e5484d); border-radius: 14px;
    padding: 12px 14px; margin-bottom: 12px; font-size: 13px;
    color: var(--danger, #e5484d); background: color-mix(in srgb, var(--danger, #e5484d) 8%, transparent);
}


/* ═════ بطاقة ملاحظة الحالة — `views/components/status-note.php` ═════

   بطاقةٌ واحدة لكلّ المنتجات: الحقل واحد (`products.boycott_reason`)
   والعنوان يتبع الحالة، فلا يجوز أن يتبع **الشكلُ** صنفين متفرّقين.
   كانت `.evidence-block` (أحمر + مثلّث) و`.info-block` (رماديّ + بلا
   أيقونة) في رأس `views/product.php`: البديل المحليّ الذي نوصي به يخرج
   بلا نبرة أصلاً، و«تحذير - غير مؤكد» يخرج تحت المثلّث الأحمر نفسه الذي
   يقول «مقاطعة موثّقة».

   ── النبرة رمزٌ واحد ──
   `--note-tone` يُضبط بصنف المُعدِّل، وكلّ لونٍ في البطاقة مشتقّ منه
   بـ`color-mix` — فلا قيمة سداسية جديدة، ولا مطابقةَ نصّ عنوان. تُشتقّ
   في PHP من `BoycottStatus::tone()` أي من العمود، لا من المفردة المعروضة.

   ── المقادير ──
   نصف القطر والحشو والهامش كما كانت في `.evidence-block` بالضبط:
   `--radius-lg` و24px و24px.

   ── لماذا تغيّر التلوين ──
   كان التلوين `6%` فوق `transparent`، أي `rgba(tone, .06)` تُركَّب على
   خلفية الصفحة `--bg-app`. في الوضع المظلم (‎#0E0E10‎) ينتج عن ذلك
   ‎#170F11‎ — فارقٌ قدره ‎(9,1,1)‎ في RGB، أي لا شيء على شاشة هاتف.
   وهذا كان حال `.evidence-block` نفسه قبل إعادة البناء: الرقم واحد،
   فالبطاقة لم تكن مرئية في المظلم قطّ، لا أنّ إعادة البناء أضاعتها.

   التلوين الآن **مصمت** ومبنيّ على `--bg-surface` لا على الشفافية:
   `color-mix(tone 12%, var(--bg-surface))`. فيرتفع السطح فوق خلفية
   الصفحة في المظلم (‎#18181B‎ مقابل ‎#0E0E10‎) ويحمل نبرته معه، ولا
   يتعلّق بما تحته. والإطار ‎38%‎ يُركَّب فوق هذا التلوين نفسه
   (`background-clip: border-box` الافتراضي).

   ── حبر العنوان ──
   `--note-ink` رمزٌ **خاصّ بالمكوّن**: النبرات الثلاث بلا نظير مظلم في
   `variables.css`، فـ`--danger` يقيس ‎2.27:1‎ على تلوينه في المظلم
   و`--warning` يقيس ‎1.96:1‎ في الفاتح. لا تُعدَّل الرموز العامّة —
   فلها نحو ٣٨ مستعمِلاً آخر — بل يُزاح الحبر داخل المكوّن وحده حتى
   يجتاز ‎4.5:1‎ على تلوينه المركَّب في الوضعين. القياسات في التقرير. */
.status-note {
    --note-tone: var(--danger);
    --note-ink: var(--note-tone);
    background: color-mix(in srgb, var(--note-tone) 12%, var(--bg-surface));
    border: 1px solid color-mix(in srgb, var(--note-tone) 38%, transparent);
    border-radius: var(--radius-lg);
    padding: 24px;
    margin-bottom: 24px;
}
.status-note--danger  { --note-tone: var(--danger); }
.status-note--warning { --note-tone: var(--warning); }
.status-note--success { --note-tone: var(--success); }

/* الكهرماني أفتحُ من أن يكون حبراً على تلوينه في الوضع الفاتح: ‎1.96:1‎.
   يُغمَّق داخل المكوّن وحده فيصير ‎4.95:1‎. */
.status-note--warning { --note-ink: color-mix(in srgb, var(--warning) 60%, black); }

/* في الوضع المظلم النبرات الثلاث داكنة على تلوينها الداكن (‎2.27:1‎ للأحمر
   و‎2.52:1‎ للأخضر)، فيُفتَّح الحبر وحده. المُحدِّد ‎(0,2,0)‎ فيغلب قاعدة
   الكهرماني ‎(0,1,0)‎ أعلاه مهما كان الترتيب — قاعدةٌ واحدة للنبرات الثلاث. */
[data-theme="dark"] .status-note { --note-ink: color-mix(in srgb, var(--note-tone) 62%, white); }

/* الأيقونة والعنوان في صفّ واحد — والأيقونة أوّلاً، أي **يميناً** في RTL */
.status-note__title {
    color: var(--note-ink);
    margin: 0 0 12px;
    font-size: 16px;
    display: flex;
    align-items: center;
    gap: 8px;
}
/* لا مقاس هنا عمداً: لا قاعدة تحكم أيقونة `h3` في الصفحة اليوم، فتُرسم
   بمقاس lucide الافتراضي (24). فرضُ مقاسٍ كان سيغيّر بطاقة المقاطعة. */

/* المتن بلون النصّ المعتاد. الارتفاع السطريّ والتباعد كما هما — النصّ
   عربيّ طويل وقد تُخالطه أسماءٌ لاتينية، وتضييقه يُتعب القراءة. */
.status-note__body {
    line-height: 1.6;
    color: var(--text-primary);
    font-size: 15px;
    margin-bottom: 16px;
    font-weight: 600;
}

.status-note__sources { border-top: 1px solid color-mix(in srgb, var(--note-tone) 25%, transparent); padding-top: 16px; }
.status-note__sources-label {
    font-size: 12px; font-weight: 800; color: var(--text-secondary);
    display: block; margin-bottom: 12px; text-transform: uppercase;
}
/* لونٌ صريح بمُحدِّد صنف: `theme.css` يصبغ كلّ `a` بـ`--primary` */
.status-note__source,
.status-note__source:hover {
    display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
    color: var(--note-ink); background: var(--bg-surface);
    padding: 8px 12px; border-radius: var(--radius-sm);
    border: 1px solid color-mix(in srgb, var(--note-tone) 10%, transparent);
    text-decoration: none; margin-left: 8px; margin-bottom: 8px; font-weight: 700;
}
.status-note__source i { width: 14px; }


/* ═════ Brand-mark tile — `views/components/logo-tile.php` ═════

   One box for every product and company logo on the site. The scale is the
   only thing a surface changes: `--logo-tile-size` on the element. Hero 160,
   home shelf 96, alternatives 64, listing row 48, admin row 32.

   ── The tile is light in BOTH themes, on purpose ──
   `--bg-surface` is white in light and #18181B in dark, so using it would put
   a black wordmark on a near-black tile — invisible in exactly the theme most
   visitors get. The value here is a literal white because it has to match the
   white canvas `LogoNormalizer` bakes into every derivative; a near-white grey
   would draw a visible square where the derivative's canvas ends. This is the
   one place that white is written, and the normalizer's canvas colour is the
   reason.

   ── No layout shift ──
   The tile is sized by `--logo-tile-size` + `aspect-ratio`, not by its image,
   so the space is reserved before anything loads. The letter is already
   painted there; the image lands on top of it. */
.logo-tile {
    --logo-tile-size: 96px;
    --logo-tile-bg: #FFFFFF;
    position: relative;
    flex: 0 0 auto;
    width: var(--logo-tile-size);
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: var(--logo-tile-bg);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    line-height: 1;
    user-select: none;
}
/* The fallback for a product with no logo — and the thing an image with a
   dead URL falls back to, since `onerror` removes only the <img>. */
.logo-tile__letter {
    font-weight: 800;
    color: var(--text-tertiary);
    font-size: calc(var(--logo-tile-size) * 0.42);
}
/* `contain` never `cover`: cropping a brand mark is worse than the problem
   this component exists to fix. Percentage padding resolves against the
   tile's own width, so ~10% on every side at every scale. */
/* The class is doubled on purpose. `.logo-tile img` is (0,1,1), and any page
   rule of the shape `.some-section img` — which is how every one of these
   surfaces used to size its own logo — ties that and wins on source order,
   because page <style> blocks come after this file. That is exactly how the
   product hero ended up re-imposing a 112px box, a second radius, a dark fill
   and `object-fit: cover` on the tile. (0,2,1) puts the component out of reach
   of a single-class descendant selector. */
.logo-tile.logo-tile img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 10%;
    background: var(--logo-tile-bg);
    border-radius: inherit;
    border: 0;
    box-shadow: none;
    margin: 0;
}
/* Safety net for the other shape of this bug — a tile nested inside a tile.
   The markup should never do it; if it ever does, only the outer one draws. */
.logo-tile .logo-tile {
    background: none;
    padding: 0;
    border: 0;
    border-radius: 0;
}
/* Centring a stacked tile.

   `.logo-tile` is `display: flex`, which makes it a BLOCK-level box. Two
   consequences that bit here:

     - `text-align: center` on an ancestor does not move it. The product hero
       has carried `text-align: center` all along and centred its logo purely
       because that logo was a bare <img> — inline-level, so the rule applied.
       The moment the <img> became this component the rule stopped reaching it.
     - At a fixed width with no inline margins it parks against the inline
       START of its container, which under `dir="rtl"` is the RIGHT edge.

   So every context that stacks the tile above a name centres it with auto
   inline margins. That is direction-agnostic — it needs no RTL/LTR variant —
   and it is not a nudge: there is no leftover margin on the other side.

   The alternatives card also centres via its own `align-items: center`; the
   auto margin here makes the tile self-sufficient rather than dependent on a
   style attribute in the template.

   Bottom margins restore exactly what the pre-component inline styles set:
   10px under the shelf thumb, 12px under the alternatives logo, 24px under
   the hero. (`.alt-card .logo-tile` used to be written here and matched
   nothing — the class on the tile is `alt-card-logo`.) */
.product-card .logo-tile,
.alt-card-logo,
.logo-tile--hero        { margin-inline: auto; }
.product-card .logo-tile { margin-bottom: 10px; }
.alt-card-logo           { margin-bottom: 12px; }
.logo-tile--hero         { margin-bottom: 24px; }
