/* ==========================================================================
   a11y.css — accessibility layer
   ==========================================================================
   Loaded in includes/footer.php immediately BEFORE css/responsive.css, which
   stays the last element before </body> (DESIGN-SPEC §7). That position means
   this file wins over theme.css, style.css and page-level <style> blocks, but
   responsive.css still wins over this file — so the overflow contract in
   DESIGN-SPEC §5 can never be broken from here.

   Colours are taken only from the DESIGN-SPEC §1 token list. Nothing in this
   file redefines a brand token; where a contrast pair failed WCAG AA the *use*
   was moved to a darker token that already exists in the palette.
   ========================================================================== */

/* ==========================================================================
   1. VISIBLE FOCUS — WCAG 2.4.7 Focus Visible / 2.4.11 Focus Appearance
   --------------------------------------------------------------------------
   One ring for the whole site. :focus-visible so it appears for keyboard and
   assistive-tech users without putting a ring on every mouse click.

   The ring is gray-900 (17.7:1 on white) with an orange halo for brand
   identity. `outline` is painted outside the border box and does not
   contribute to scrollable overflow, so this cannot introduce horizontal
   scroll at any width.
   ========================================================================== */

:where(a, button, input, select, textarea, summary, [tabindex], [role="button"],
       [role="link"], [role="tab"], [role="menuitem"]):focus-visible {
    outline: 3px solid var(--gray-900, #111827);
    outline-offset: 2px;
    box-shadow: 0 0 0 6px rgba(249, 115, 22, .45);
    /* Keep the ring above neighbouring cards so it is never half-hidden. */
    position: relative;
    z-index: 10;
}

/* Dark surfaces: a gray-900 ring is invisible on gray-900. Invert to white
   (17.7:1 against the dark nav/footer gradients). */
:where(.main-nav, .top-strip, .main-footer, .bottom-nav .menu-btn,
       .card-header, .footer-top, .footer-bottom)
  :where(a, button, input, select, textarea, [tabindex], [role="button"]):focus-visible {
    outline-color: var(--white, #fff);
    box-shadow: 0 0 0 6px rgba(249, 115, 22, .55);
}

/* Elements that set `outline: none` in style.css / theme.css / header.php and
   replace it with nothing. The border/box-shadow treatment those rules apply
   to the *wrapper* is not a focus indicator on the control itself, so give the
   control a real ring of its own. */
.search-form input:focus-visible,
.search-input-wrapper input:focus-visible,
.main-header .search-form input:focus-visible,
.mobile-search-bar .search-form input:focus-visible,
.form-control:focus-visible,
.select2-container--default .select2-search--dropdown .select2-search__field:focus-visible {
    outline: 3px solid var(--gray-900, #111827);
    outline-offset: 2px;
    box-shadow: 0 0 0 6px rgba(249, 115, 22, .45);
}

/* Windows High Contrast / forced-colors: let the OS draw the ring. */
@media (forced-colors: active) {
    :where(a, button, input, select, textarea, summary, [tabindex],
           [role="button"]):focus-visible {
        outline: 3px solid CanvasText;
        outline-offset: 2px;
        box-shadow: none;
    }
}

/* ==========================================================================
   2. SKIP TO CONTENT — WCAG 2.4.1 Bypass Blocks
   --------------------------------------------------------------------------
   Off-screen until focused. position:fixed with a single inline offset, so
   per DESIGN-SPEC §5.9 it also caps its own width and can never push layout.
   The element is injected by js/main.js so every page gets one.
   ========================================================================== */

.skip-link {
    position: fixed;
    top: 0;
    inset-inline-start: 8px;
    inset-inline-end: auto;
    max-width: calc(100% - 16px);
    z-index: 100000;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 10px 20px;
    background: var(--gray-900, #111827);
    color: var(--white, #fff);
    font-family: 'Cairo', sans-serif;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.4;
    text-decoration: none;
    white-space: nowrap;
    border-bottom-left-radius: var(--radius, 10px);
    border-bottom-right-radius: var(--radius, 10px);
    box-shadow: var(--shadow-lg, 0 16px 32px -8px rgba(0, 0, 0, .12));
    transform: translateY(-110%);
    transition: transform 160ms ease;
}

.skip-link:focus,
.skip-link:focus-visible {
    transform: translateY(0);
    outline: 3px solid var(--primary, #f97316);
    outline-offset: -3px;
    box-shadow: var(--shadow-lg, 0 16px 32px -8px rgba(0, 0, 0, .12));
}

/* The <main> the skip link jumps to is given tabindex="-1" so focus really
   lands there; that must not paint a ring of its own. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none;
    box-shadow: none;
}

/* Visually hidden but available to screen readers.
   The geometry is forced. `clip`/`clip-path` only hide the *paint*: the layout
   box is still measured, so a `.sr-only` label that inherits `width: 100%`
   from a form rule becomes a full-width invisible element that pushes the
   layout and breaks the DESIGN-SPEC §5 overflow contract. Pinning the box to
   1x1 makes that impossible. */
.sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    max-width: 1px !important;
    min-width: 0 !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   3. COLOUR CONTRAST — WCAG 1.4.3 (AA)
   --------------------------------------------------------------------------
   Measured in the rendered page, not guessed. Only the *usage* changes; the
   §1 brand tokens are untouched.

     PASS, left alone
       --gray-900 #111827 on #fff  17.74:1   body text
       --gray-500 #6b7280 on #fff   4.83:1   muted text (clears 4.5)

     FIXED here
       --gray-400 #9ca3af on #fff   2.54:1  ->  --gray-600 #4b5563  7.55:1
       --primary  #f97316 on #fff   2.79:1  ->  --primary-dark #ea580c  3.54:1
       #fff on --primary #f97316    2.79:1  ->  #fff on --primary-dark  3.54:1
       --primary on --primary-lighter 2.64:1 -> --gray-900 on tint    14.9:1

   NOTE: 3.54:1 clears the 3:1 bar for large text and for non-text UI
   components, but not the 4.5:1 bar for body-size text. #f97316 and #ea580c
   are the only two oranges in DESIGN-SPEC §1 and neither reaches 4.5:1 on
   white — closing that gap needs a spec decision, not a CSS change.
   ========================================================================== */

/* A note on the repeated class names below (`.old-price.old-price`):
   these corrections have to beat rules such as `.product-card .old-price` and
   `.summary-row.total .amount` that live in page-level <style> blocks and in
   includes/product-card.php. Repeating the class raises specificity without
   inventing a parent selector that may not exist on every page, and without
   reaching for !important — which would be unbeatable by the page templates
   when their owners come to restyle them. */

/* --- gray-400 used as text: one step darker ------------------------------ */
.old-price.old-price,
.product-card .old-price.old-price,
.product-card .product-price .old-price.old-price,
.was.was,
.cart-item-price .was.was,
.qv-price .was.was,
.rating-count.rating-count,
.product-card .rating-count.rating-count,
.product-card .product-rating .rating-count.rating-count,
.review-count.review-count,
.product-meta,
.empty-state p,
.no-results,
.text-muted {
    color: var(--gray-600, #4b5563);
}

/* --- orange text on white/near-white: darken to --primary-dark ----------- */
.current-price.current-price,
.product-card .current-price.current-price,
.product-price .current-price.current-price,
.cart-item-price.cart-item-price,
.price-amount.price-amount,
.amount.amount.amount,
.summary-row.total .amount.amount,
.view-all.view-all,
.read-more.read-more,
.section-header .view-all.view-all,
.btn-outline.btn-outline,
.btn-link,
.link-primary {
    color: var(--primary-dark, #ea580c);
}

.btn-outline {
    border-color: var(--primary-dark, #ea580c);
}

/* --- white text on orange: darken the background ------------------------- */
.btn-primary,
.btn-orange,
.main-header .search-form button,
.mobile-search-bar .search-form button,
.chat-start-btn,
.rating-submit {
    background-color: var(--primary-dark, #ea580c);
}

.btn-primary:hover,
.btn-orange:hover,
.main-header .search-form button:hover,
.mobile-search-bar .search-form button:hover {
    background-color: var(--secondary, #1f2937);
}

/* --- small count chips: dark text passes comfortably on every tint -------
   These sit on --primary-lighter / --primary-100 / --gray-100, where neither
   orange reaches 4.5:1 (2.64:1 and 3.11:1 measured). Keeping the tint and
   darkening only the numerals gets to ~14:1 without losing the accent. */
.category-count.category-count,
.badge-count.badge-count,
.filter-count.filter-count,
.count.count.count,
.category-item .count.count.count,
.category-item.active .count.count {
    color: var(--gray-900, #111827);
}

/* --- muted placeholder text is exempt from 1.4.3 but still shouldn't be
       invisible; gray-500 clears 4.5:1 while reading as placeholder. ------ */
::placeholder {
    color: var(--gray-500, #6b7280);
    opacity: 1;
}

/* ==========================================================================
   4. REDUCED MOTION — WCAG 2.3.3 / 2.2.2
   --------------------------------------------------------------------------
   The ticker in the header scrolls forever and the homepage banner slider
   auto-advances every 5s. Both are pure decoration and both are stopped here.
   The slider's JS timer is cleared in js/main.js — CSS alone cannot stop it.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 1ms !important;
        animation-delay: 0ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 1ms !important;
        transition-delay: 0ms !important;
        scroll-behavior: auto !important;
    }

    /* Infinite marquees must be *stopped*, not fast-forwarded: a 1ms duration
       would snap the track to translateX(-50%) and hide half the items. */
    .ticker-track,
    .marquee-content,
    .marquee-track,
    .news-ticker-track {
        animation: none !important;
        transform: none !important;
    }

    /* Attention-seeking loops. */
    .chat-widget-badge,
    .typing-dots span,
    .badge,
    .pulse,
    .blink {
        animation: none !important;
    }

    /* Hover lifts and scale effects. */
    .float-btn:hover,
    .product-card:hover,
    .btn:hover,
    .chat-widget-button:hover,
    .chat-send-btn:hover {
        transform: none !important;
    }
}

/* ==========================================================================
   5. TARGET SIZE — WCAG 2.2 §2.5.8 (AA, 24x24) and DESIGN-SPEC §5.4
   --------------------------------------------------------------------------
   Standalone link CTAs and list navigation measured 19-23px tall at 390px.
   Inline links inside running prose are exempt by the success criterion and
   are deliberately left alone so Arabic body copy keeps its natural leading.

   `min-height` needs a non-inline box; vertical padding raises the border box
   of an inline one. Both are applied so the rule works either way, and
   `box-sizing: border-box` keeps widths unchanged.
   ========================================================================== */

@media (max-width: 768px) {
    .view-all,
    .read-more,
    .continue-shopping,
    .product-breadcrumb a,
    .breadcrumb a,
    .breadcrumbs a,
    .product-meta-row a,
    .product-meta a,
    .meta-row a,
    .orders-card-header a,
    .section-header a,
    .related-header a,
    .blog-card-footer a,
    .card-header a,
    .card-body > a,
    .footer-col li > a,
    .sidebar li > a,
    .blog-sidebar li > a,
    aside li > a,
    .widget li > a {
        box-sizing: border-box;
        min-height: 24px;
        padding-block: 3px;
    }

    /* Icon-only controls get a full 44px touch target (2.5.5 AAA / spec §5.4)
       without changing the visual size of the icon itself. */
    .mobile-menu-btn,
    .bottom-nav .menu-btn,
    .float-btn,
    .banner-nav,
    .qty-btn,
    .zoom-btn,
    .mobile-search-bar .search-form button,
    .social-links a {
        min-width: 44px;
        min-height: 44px;
    }

    .social-links a {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* Slider dots are 8px wide (20px when active). Grow the *target* to 24px
       with transparent padding and clip the paint to the content box, so the
       hit area passes 2.5.8 while the dot still looks exactly the same. */
    .banner-dot {
        box-sizing: border-box;
        min-width: 24px;
        min-height: 24px;
        padding: 8px;
        background-clip: content-box;
    }

    .banner-dot.active {
        /* 36 - 2*8 padding = the 20px active pill, unchanged. */
        min-width: 36px;
    }

    /* Native radios and checkboxes render at 13x13. They are usually wrapped
       in a label that is comfortably tappable, but the control itself is the
       target a pointer has to hit when the label is a card with its own
       interactive children. */
    input[type="radio"],
    input[type="checkbox"] {
        min-width: 24px;
        min-height: 24px;
    }
}

/* ==========================================================================
   6. LAYOUT STABILITY (CLS)
   --------------------------------------------------------------------------
   Product thumbnails arrive without intrinsic dimensions, so every grid reflows
   as images decode. Reserving a square box up front removes that shift.
   `height: auto` is NOT set here — aspect-ratio plus width:100% is enough and
   keeps DESIGN-SPEC §5.7 (`max-width:100%`) intact.
   ========================================================================== */

.product-card .product-image img,
.product-card img.product-img,
img.product-img {
    aspect-ratio: 1 / 1;
    object-fit: cover;
    background-color: var(--gray-100, #f3f4f6);
}

/* Anything still missing width/height gets a neutral placeholder box rather
   than collapsing to zero and then jumping. */
img:not([width]):not([height]):not([src$=".svg"]) {
    background-color: var(--gray-100, #f3f4f6);
}

/* ==========================================================================
   7. MISC
   ========================================================================== */

/* Decorative Font Awesome glyphs are marked aria-hidden by js/main.js; make
   sure a screen reader never gets the private-use codepoint as text. */
i[aria-hidden="true"]::before,
span[aria-hidden="true"]::before {
    speak: never;
}

/* A live region must never become a layout artefact when it is empty. */
[aria-live]:empty {
    display: block;
}
