/*
 * TARS | ترس - Automotive Spare Parts.
 *
 * The one place the brand is defined. Everything below is either a token from the TARS
 * identity or a rule that teaches Bootstrap to use those tokens, so a new page, button,
 * card or admin screen is on-brand by default and nobody has to restyle it by hand.
 *
 * Written with CSS logical properties and Bootstrap's own RTL stylesheet doing the
 * mirroring, so the same rules serve both Arabic (RTL) and English (LTR) without any
 * direction-specific overrides. Arabic is not a translation of the design; it is the
 * same design read the other way.
 */

/* ==================================================================================
   1. BRAND TOKENS - from the TARS identity, section 3
   ================================================================================== */
:root {
    /* Palette. These five are the whole brand; nothing else is a brand colour. */
    --tars-dark: #0F1115;
    --tars-orange: #F26522;
    --tars-orange-secondary: #FF7A38;
    --tars-neutral: #9EA3AE;
    --tars-white: #FFFFFF;

    /* Working shades derived from the five, so tints stay in the family. */
    --tars-dark-soft: #1A1D24;
    --tars-dark-line: #2A2E37;
    --tars-orange-soft: rgba(242, 101, 34, 0.12);
    --tars-surface: #F5F6F8;
    --tars-border: #E2E5EA;
    --tars-ink: #14161B;
    --tars-ink-muted: #5C6270;

    /* Type scale. The identity gives these in pixels; they are rem here so a reader who
       enlarges their browser text is not fighting the design. */
    --tars-fs-hero: clamp(2.25rem, 1.9rem + 1.6vw, 3rem);      /* 36 - 48px */
    --tars-fs-section: clamp(1.5rem, 1.35rem + 0.7vw, 2rem);   /* 24 - 32px */
    --tars-fs-body: 1rem;                                       /* 16px */
    --tars-fs-button: 0.975rem;                                 /* 15 - 16px */
    --tars-fs-part: clamp(1.125rem, 1.05rem + 0.35vw, 1.375rem);/* 18 - 22px */

    /* The identity puts the horizontal logo at 180px minimum on screen. */
    --tars-logo-min: 180px;

    /* Structure. Cards are 8-12px in the identity - square enough to read as industrial. */
    --tars-radius: 10px;
    --tars-radius-sm: 6px;
    --tars-shadow: 0 1px 2px rgba(15, 17, 21, 0.06), 0 8px 24px rgba(15, 17, 21, 0.06);
    --tars-shadow-lift: 0 4px 12px rgba(15, 17, 21, 0.10), 0 16px 40px rgba(15, 17, 21, 0.10);

    /* Bootstrap's own theme variables, pointed at the brand. Doing it here means every
       component that reads them - links, focus rings, spinners, progress, form checks -
       follows without being touched individually. */
    --bs-primary: #F26522;
    --bs-primary-rgb: 242, 101, 34;
    --bs-link-color: #D9531A;
    --bs-link-color-rgb: 217, 83, 26;
    --bs-link-hover-color: #B8430F;
    --bs-border-radius: var(--tars-radius);
    --bs-border-radius-sm: var(--tars-radius-sm);
    --bs-body-color: var(--tars-ink);
    --bs-heading-color: inherit;
    --bs-body-font-size: var(--tars-fs-body);
    --bs-secondary-color: var(--tars-ink-muted);
    --bs-focus-ring-color: rgba(242, 101, 34, 0.25);
}

/* Legacy aliases. The old blue-and-amber tokens are gone, but anything still asking for
   them by name gets the brand instead of a broken colour. */
:root {
    --ap-navy: var(--tars-dark);
    --ap-navy-dark: var(--tars-dark);
    --ap-amber: var(--tars-orange);
    --ap-surface: var(--tars-surface);
}

body {
    background-color: var(--tars-surface);
    color: var(--tars-ink);
    font-size: var(--tars-fs-body);
}

/* Arabic renders better with a system Arabic face; the size is already the brand's. */
html[dir="rtl"] body {
    font-family: "Segoe UI", Tahoma, "Noto Naskh Arabic", "Arial", sans-serif;
}

/* ==================================================================================
   2. BOOTSTRAP, RETHEMED - so a new page is on-brand without knowing this file exists
   ================================================================================== */

/* Primary means TARS orange. Danger, success and warning keep their own meaning: a
   destructive button that is merely on-brand is a destructive button nobody reads. */
.btn-primary {
    --bs-btn-bg: var(--tars-orange);
    --bs-btn-border-color: var(--tars-orange);
    --bs-btn-hover-bg: var(--tars-orange-secondary);
    --bs-btn-hover-border-color: var(--tars-orange-secondary);
    --bs-btn-active-bg: #D9531A;
    --bs-btn-active-border-color: #D9531A;
    --bs-btn-disabled-bg: var(--tars-orange);
    --bs-btn-disabled-border-color: var(--tars-orange);
    --bs-btn-focus-shadow-rgb: 242, 101, 34;
}

.btn-outline-primary {
    --bs-btn-color: #D9531A;
    --bs-btn-border-color: var(--tars-orange);
    --bs-btn-hover-bg: var(--tars-orange);
    --bs-btn-hover-border-color: var(--tars-orange);
    --bs-btn-active-bg: var(--tars-orange);
    --bs-btn-active-border-color: var(--tars-orange);
    --bs-btn-focus-shadow-rgb: 242, 101, 34;
}

/* Dark is the brand's structural colour, not Bootstrap's near-black. */
.btn-dark {
    --bs-btn-bg: var(--tars-dark);
    --bs-btn-border-color: var(--tars-dark);
    --bs-btn-hover-bg: var(--tars-dark-soft);
    --bs-btn-hover-border-color: var(--tars-dark-soft);
}

.btn { font-size: var(--tars-fs-button); font-weight: 500; }
.btn-lg { font-size: 1.0625rem; }

.bg-primary { background-color: var(--tars-orange) !important; }
.text-primary { color: #D9531A !important; }
.border-primary { border-color: var(--tars-orange) !important; }
.bg-dark { background-color: var(--tars-dark) !important; }

.form-control:focus,
.form-select:focus {
    border-color: var(--tars-orange-secondary);
    box-shadow: 0 0 0 0.2rem rgba(242, 101, 34, 0.18);
}

.form-check-input:checked {
    background-color: var(--tars-orange);
    border-color: var(--tars-orange);
}

.card {
    --bs-card-border-color: var(--tars-border);
    --bs-card-border-radius: var(--tars-radius);
    box-shadow: var(--tars-shadow);
}

.card-header {
    background-color: var(--tars-white);
    border-bottom-color: var(--tars-border);
    color: var(--tars-ink);
}

/* Headings carry the identity's weight and scale. Deliberately no colour: they inherit
   it, so a heading on a light page is brand ink and a heading inside a dark section stays
   white. Setting a colour here beat that inheritance and put dark text on the dark hero. */
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
    font-weight: 700;
}

h1, .h1 { font-size: var(--tars-fs-hero); }
h2, .h2 { font-size: var(--tars-fs-section); }

.page-link { color: #D9531A; }
.page-item.active .page-link {
    background-color: var(--tars-orange);
    border-color: var(--tars-orange);
}

/* ==================================================================================
   3. BRAND LOCKUP
   ================================================================================== */

/* The identity sets a 180px floor for the horizontal logo on screen. These base rules size
   the banner lockup where it still appears (the admin sidebar and the invoice); the
   storefront header overrides them below for the official wordmark. */
.tars-logo {
    display: block;
    width: auto;
    height: 44px;
    /* The identity's 180px floor, enforced rather than hoped for. */
    min-width: var(--tars-logo-min);
    /* Both of these matter inside the navbar's flex row: without them the lockup was
       squeezed to 177px wide at 44px tall - under the floor, and at 4.02:1 against the
       artwork's 4.55:1, which is the stretching the identity forbids. The row gives up
       its own space now instead of taking it out of the logo. */
    flex: 0 0 auto;
    object-fit: contain;
}

.tars-logo-mark {
    display: block;
    height: 38px;
    width: auto;
    flex: 0 0 auto;
    object-fit: contain;
    border-radius: var(--tars-radius-sm);
}

/* Below the point where the banner lockup and a full navigation can share a row, the
   compact mark stands in - which is what the identity asks for when space is short. */
@media (max-width: 1199.98px) {
    .tars-logo { height: 40px; }
}

/* ---- Storefront header ------------------------------------------------------------
   The official wordmark is the header's first element - the far right in Arabic, the far
   left in English; the flex row follows the reading direction, which is why nothing here
   is positioned by hand. The logo width is a per-breakpoint custom property so the ranges
   the brand asked for are in one place; height is always auto, so the file is never
   stretched, and max-width: 100% means it can never be wider than the row it sits in.

   From the `lg` breakpoint the header is two tiers: a bar with the logo, the search and
   the actions (cart, language, account), and a strip with the section links under it.
   A single row was measured and does not fit: with a 300px logo, five links, a 220px
   search and four actions, the English header needs 1440px inside a 1320px container,
   and Bootstrap's expanded navbar is `flex-wrap: nowrap`, so the overflow would push the
   actions out of the viewport. Two tiers hold the brand's sizes at every width, in both
   languages, with nothing wrapping or clipped, and give the search its full width. Below
   `lg` the row is the logo and the existing toggler; the menu collapses as before. */
.ap-navbar {
    --ap-header-logo-width: 300px;
    --ap-header-bar-height: 60px;                     /* + 2 x 8px padding = 76px bar */
    --ap-header-gap: clamp(1.25rem, 1.6vw, 1.75rem); /* 20 - 28px */
    padding-block: 0.5rem;
    background-color: var(--tars-dark);
    border-bottom: 3px solid var(--tars-orange);
}

/* Bootstrap's `.navbar > .container-xxl` is `flex-wrap: inherit` (nowrap once expanded);
   the row wraps here so the link strip can take its own line and nothing can ever leave
   the viewport, whatever the font metrics on the visitor's machine. */
.ap-navbar .ap-header-row {
    flex-wrap: wrap;
    align-items: center;
    column-gap: var(--ap-header-gap);
}

.ap-header-brand {
    flex: 0 0 auto;
    /* The brand is a link around the image; the image decides the width. The min-height
       is what sets the bar's height, and the logo is centred inside it. */
    min-height: var(--ap-header-bar-height);
    max-width: 100%;
}

/* More specific than both `.tars-logo` and its 1199.98px override above, so the header
   never inherits the fixed 44px/40px banner height. */
.ap-navbar .tars-logo {
    display: block;
    width: var(--ap-header-logo-width);
    max-width: 100%;
    height: auto;
    min-width: 0;
    object-fit: contain;
}

/* The nav list, the search and the actions keep their labels on one line, so a long
   Arabic label can never wrap mid-header. */
.ap-header-links,
.ap-header-actions {
    flex: 0 0 auto;
    white-space: nowrap;
}

.ap-header-links .nav-link,
.ap-header-actions .nav-link {
    white-space: nowrap;
}

@media (min-width: 992px) {
    /* The collapse wrapper stops being a box and its three groups become items of the
       header row directly, so `order` can put the search and the actions beside the logo
       and the links on the strip beneath. Bootstrap sets `display: flex !important` on the
       expanded collapse, hence the matching importance at a higher specificity. */
    .ap-navbar.navbar-expand-lg .ap-header-nav {
        display: contents !important;
    }

    .ap-search { order: 1; }
    .ap-header-actions { order: 2; }

    .ap-header-links {
        order: 3;
        flex: 1 0 100%;
        margin-block-start: 0.25rem;
        padding-block-start: 0.125rem;
        border-block-start: 1px solid var(--tars-dark-line);
    }

    .ap-header-links .nav-link {
        padding-block: 0.35rem;
    }

    /* The first link sits flush with the logo's edge, so the strip reads as the same
       column as the brand rather than as an indented list. */
    .ap-header-links .nav-item:first-child .nav-link {
        padding-inline-start: 0;
    }
}

.ap-navbar .navbar-brand,
.ap-navbar .nav-link {
    color: rgba(255, 255, 255, 0.9);
}

.ap-navbar .nav-link:hover,
.ap-navbar .nav-link:focus {
    color: var(--tars-orange-secondary);
}

/* The identity asks for a clear, uncluttered header whose one prominent control is the
   part-number search, so the active section is marked by the accent rather than by a
   heavier background. */
.ap-navbar .nav-link.active {
    color: var(--tars-orange);
    font-weight: 600;
    text-decoration: underline;
    text-decoration-color: var(--tars-orange);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.45em;
}

/* The search is the one control that flexes: it opens up to 380px when the row has room
   and gives width back first when it does not, but never below a usable 220px. The
   endpoint and the field are untouched - this is only how wide the box is drawn. */
/* A required field is marked next to its label. The mark is the danger colour, which keeps
   its own meaning here as everywhere else, and is hidden from assistive technology because
   the input itself is marked required. Optional fields carry the word "optional" instead. */
.ap-required {
    color: var(--bs-danger);
    font-weight: 700;
    margin-inline-start: 0.15rem;
}

/* The branch card on checkout and the confirmation: the brand dark with the orange rule, so
   the one place the customer must go to reads as part of the brand rather than as a notice. */
.ap-branch-card {
    background-color: var(--tars-dark);
    color: var(--tars-white);
    border: 0;
    border-inline-start: 4px solid var(--tars-orange);
    border-radius: var(--tars-radius);
}

.ap-branch-card .ap-branch-icon {
    color: var(--tars-orange);
    font-size: 1.75rem;
    line-height: 1;
}

.ap-branch-card dt {
    color: var(--tars-neutral);
    font-weight: 500;
    font-size: 0.85rem;
}

.ap-branch-card dd {
    margin-block-end: 0.5rem;
}

.ap-branch-card a.btn {
    white-space: nowrap;
}

/* The one fulfilment option, shown selected: a bordered choice with the brand accent. */
.ap-fulfillment-option {
    border: 1px solid var(--tars-border);
    border-radius: var(--tars-radius);
    padding: 1rem;
}

.ap-fulfillment-option.is-selected {
    border-color: var(--tars-orange);
    box-shadow: 0 0 0 1px var(--tars-orange);
}

.ap-search {
    flex: 1 1 320px;
    min-width: 220px;
    max-width: 380px;
}

/* Logo widths by breakpoint. Each range is what the brand asked for, expressed as a clamp
   so the logo eases across the range instead of jumping at the boundary. */
@media (min-width: 1200px) and (max-width: 1439.98px) {
    .ap-navbar { --ap-header-logo-width: clamp(260px, 20vw, 290px); }
}

@media (min-width: 992px) and (max-width: 1199.98px) {
    .ap-navbar { --ap-header-logo-width: clamp(220px, 21vw, 250px); }
}

@media (max-width: 991.98px) {
    /* Tablet: the lockup and the existing toggler share the row; the menu collapses. */
    .ap-navbar {
        --ap-header-logo-width: clamp(190px, 24vw, 220px);
        --ap-header-bar-height: 56px;                 /* 72px bar */
    }
}

@media (max-width: 767.98px) {
    /* Phone: the identity's 180px floor is the lower bound, not the 160px the range allows,
       because the wordmark is still the brand and it fits beside the hamburger at 320px. */
    .ap-navbar {
        --ap-header-logo-width: clamp(var(--tars-logo-min), 46vw, 190px);
        --ap-header-bar-height: 48px;                 /* 64px bar */
    }
}

/* The links have a strip of their own from `lg` up, so they no longer need the tightened
   padding and type that once kept a single row from wrapping at laptop widths. */

.ap-cart-badge {
    inset-block-start: 0.35rem;
    inset-inline-start: 100%;
    font-size: 0.7rem;
}

/* Flat brand dark, not a gradient: the identity calls for an industrial, uncrowded
   surface and names gradients as something to avoid. */
.ap-hero {
    background-color: var(--tars-dark);
    border-bottom: 4px solid var(--tars-orange);
}

/* The decorative gear in the Hero is the TARS gear mark itself, not a generic icon: the
   supplied artwork with its white background made transparent and nothing else changed.
   Width-driven with height auto so it is never distorted; capped at the column so it can
   never push the panel wider. The opacity keeps it a background element - clearly the brand,
   still behind the headline - and there is no glow, shadow or border, which the identity
   forbids. Its column is `d-none d-lg-block`, so under 992px it is simply not there. */
.ap-hero-icon {
    display: inline-block;
    width: clamp(220px, 20vw, 310px);
    max-width: 100%;
    height: auto;
    opacity: 0.35;
}

.ap-hero-search {
    max-width: 34rem;
}

/* A part number is a left-to-right identifier whatever language the page is in.
   Without this it is not merely mis-aligned on an Arabic page - it is displayed WRONG:
   the bidirectional algorithm treats the hyphen as neutral and reorders the segments
   around it, so 90915-YZZD2 was painted as YZZD2-90915 and 15400-PLM-A02 as
   PLM-A02-15400. A shopper matching that against the part in their hand would reject a
   part that was in fact correct. Isolating rather than merely overriding also stops the
   code from disturbing the direction of the Arabic text it sits in. */
.ap-part-number {
    direction: ltr;
    unicode-bidi: isolate;
}

/* In a spare-parts shop the part number is the identifier a customer actually shops by -
   they arrive knowing it and scan for it - so where it is presented as that identifier it
   is typed as a primary field, not as metadata under the name. As a plain Bootstrap badge
   it was the opposite: .badge sizes itself in em and sat inside a .small block, which
   compounded to roughly 0.66rem.

   The identity sets this field at 18-22px and calls it out by name, so the token carries
   that range rather than a size chosen here. It lands above the card title (16px) and
   just under the price - prominent enough to scan a grid by, without competing with the
   price for the loudest thing on the card. */
.ap-part-number-value {
    font-size: var(--tars-fs-part);
    font-weight: 700;
    color: var(--tars-ink);
    letter-spacing: 0.02em;
    padding: 0.3em 0.6em;
    line-height: 1.3;
    /* .badge is nowrap, which would push a long code out past the edge of a narrow card.
       Wrapping inside the chip keeps every character visible at every width - a truncated
       part number is worse than a wrapped one, because it looks like a complete number. */
    white-space: normal;
    overflow-wrap: anywhere;
}

/* Quiet, small and set above the value, so the number is unmistakably the thing being
   read and the caption only says what it is. */
.ap-part-number-label {
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.2;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--bs-secondary-color, #6c757d);
}

/* On the product page the number is a headline field under the product name, so it takes
   a step up again rather than matching the card. */
.ap-part-number-hero .ap-part-number-value {
    font-size: clamp(1.375rem, 1.2rem + 0.7vw, 1.75rem);
    border-color: var(--tars-orange) !important;
    background-color: var(--tars-orange-soft) !important;
}

.ap-part-number-hero .ap-part-number-label {
    font-size: 0.75rem;
}

/* Card corners sit in the identity's 8-12px band: square enough to read as industrial,
   soft enough not to look unfinished. */
.ap-product-card {
    transition: box-shadow 0.15s ease-in-out, transform 0.15s ease-in-out;
}

.ap-product-card:hover {
    box-shadow: var(--tars-shadow-lift);
    transform: translateY(-2px);
    border-color: var(--tars-orange);
}

/* Fixed aspect ratio keeps the grid tidy whatever the source image dimensions are. */
/* Product photography is square (the part, its carton and the TARS mark on a branded
   background), so the boxes are 1:1 and the image is contained, never cropped: a cut-off
   carton or logo is worse than a little air around the part. The box is sized by the CSS
   aspect ratio and the img carries its pixel size, so nothing shifts while it loads. */
.ap-product-image {
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background-color: var(--tars-white);
    padding: 0.75rem;
}

.ap-product-image img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ap-detail-image {
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--tars-white);
    padding: 1.5rem;
}

.ap-detail-image img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* The gallery stage is positioned so the counter and the arrows can sit over the image. */
.ap-detail-image { position: relative; }

.ap-gallery-counter {
    position: absolute;
    inset-block-end: 0.75rem;
    inset-inline-end: 0.75rem;
    background: var(--tars-dark);
    color: var(--tars-white);
    font-size: 0.8rem;
    font-weight: 600;
    padding: 0.15rem 0.6rem;
    border-radius: var(--tars-radius-sm);
    pointer-events: none;
    direction: ltr;
}

.ap-gallery-nav {
    position: absolute;
    inset-block-start: 50%;
    transform: translateY(-50%);
    width: 2.5rem;
    height: 2.5rem;
    border: 1px solid var(--tars-border);
    border-radius: 50%;
    background: var(--tars-white);
    color: var(--tars-ink);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.85;
}

.ap-gallery-nav:hover,
.ap-gallery-nav:focus-visible { opacity: 1; border-color: var(--tars-orange); color: var(--tars-orange); }
/* Logical sides: previous at the inline start, next at the inline end, so in Arabic "next"
   is on the left and its chevron (chosen in the view) points left. */
.ap-gallery-prev { inset-inline-start: 0.5rem; }
.ap-gallery-next { inset-inline-end: 0.5rem; }

.ap-lightbox .ap-gallery-nav { background: var(--tars-white); }
.ap-lightbox-counter { inset-block-end: 1rem; inset-inline-start: 1rem; inset-inline-end: auto; }

/* Cart line: the primary's thumbnail, small and square. */
.ap-cart-thumb {
    width: 4rem;
    height: 4rem;
    object-fit: contain;
    background: var(--tars-white);
}

/* The product-page main image opens a larger view; a button so it works from a keyboard. */
.ap-detail-image-button {
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
}

.ap-thumb {
    width: 4.5rem;
    height: 4.5rem;
    overflow: hidden;
    background: var(--tars-white);
}

.ap-thumb[aria-current="true"] {
    border-color: var(--tars-orange) !important;
    box-shadow: 0 0 0 2px var(--tars-orange);
}

.ap-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* The larger view: a native dialog, so Escape and the backdrop behave without script. */
.ap-lightbox {
    border: 0;
    padding: 0;
    background: transparent;
    max-width: min(96vw, 1200px);
    max-height: 96vh;
}

.ap-lightbox::backdrop { background: rgba(15, 17, 21, 0.85); }

.ap-lightbox img {
    display: block;
    max-width: min(96vw, 1200px);
    max-height: 90vh;
    width: auto;
    height: auto;
    object-fit: contain;
    background: var(--tars-white);
    border-radius: var(--tars-radius);
}

.ap-lightbox-close {
    position: absolute;
    inset-block-start: 0.5rem;
    inset-inline-end: 0.5rem;
}

/* Admin product list: a small square preview of the primary image next to the part number. */
.ap-admin-thumb {
    width: 2.75rem;
    height: 2.75rem;
    object-fit: contain;
    background: var(--tars-white);
    border: 1px solid var(--tars-border);
    border-radius: var(--tars-radius-sm);
}

/* ---- Admin: product image management ------------------------------------------------ */

.ap-dropzone {
    position: relative;
    border: 2px dashed var(--tars-border);
    border-radius: var(--tars-radius);
    padding: 1.5rem 1rem;
    text-align: center;
    background: var(--tars-surface);
    cursor: pointer;
    transition: border-color 0.15s ease-in-out, background-color 0.15s ease-in-out;
}

.ap-dropzone:hover,
.ap-dropzone:focus-visible,
.ap-dropzone.is-over {
    border-color: var(--tars-orange);
    background: var(--tars-white);
    outline: none;
}

.ap-dropzone-icon {
    font-size: 2rem;
    color: var(--tars-orange);
    display: block;
    margin-block-end: 0.25rem;
}

/* The real input stays in the form (it is what posts the files) but out of sight; the
   label and the zone open it. */
.ap-dropzone-input {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
}

.ap-image-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    gap: 0.75rem;
}

.ap-image-tile {
    border: 1px solid var(--tars-border);
    border-radius: var(--tars-radius);
    background: var(--tars-white);
    padding: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.ap-image-tile.is-primary { border-color: var(--tars-orange); box-shadow: 0 0 0 1px var(--tars-orange); }
.ap-image-tile.is-dragging { opacity: 0.4; }
.ap-image-tile[draggable="true"] .ap-image-tile-frame { cursor: grab; }

.ap-image-tile-frame {
    position: relative;
    aspect-ratio: 1 / 1;
    background: var(--tars-surface);
    border-radius: var(--tars-radius-sm);
    overflow: hidden;
}

.ap-image-tile-frame img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ap-image-badge {
    position: absolute;
    inset-block-start: 0.35rem;
    inset-inline-start: 0.35rem;
    background: var(--tars-orange);
    color: var(--tars-white);
    font-size: 0.7rem;
    font-weight: 700;
    padding: 0.15rem 0.45rem;
    border-radius: var(--tars-radius-sm);
}

.ap-image-order {
    position: absolute;
    inset-block-end: 0.35rem;
    inset-inline-end: 0.35rem;
    background: var(--tars-dark);
    color: var(--tars-white);
    font-size: 0.7rem;
    font-weight: 700;
    min-inline-size: 1.4rem;
    text-align: center;
    padding: 0.1rem 0.3rem;
    border-radius: var(--tars-radius-sm);
}

.ap-image-tile-name { color: var(--tars-ink-muted); }

.ap-image-tile-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.ap-image-tile-actions .btn { padding-inline: 0.45rem; }

/* Upload progress for the "Upload images" button: the bar fills as the bytes leave. */
.ap-upload-progress { height: 0.5rem; }

.ap-category-card {
    transition: border-color 0.15s ease-in-out;
    border: 1px solid rgba(0, 0, 0, 0.08);
}

.ap-category-card:hover {
    border-color: var(--ap-amber);
}

.ap-footer {
    background-color: var(--ap-navy-dark);
    color: rgba(255, 255, 255, 0.75);
}

.ap-footer a {
    color: rgba(255, 255, 255, 0.75);
    text-decoration: none;
}

.ap-footer a:hover {
    color: var(--ap-amber);
}

/* Admin portal: denser and more utilitarian than the storefront. */
/* The employee portal is the same brand seen from the inside: dark structural sidebar,
   light working area, accent reserved for the current section and for primary actions.
   The identity is explicit that the portal must stay operational and readable rather
   than decorated. */
.ap-admin-body {
    background-color: var(--tars-surface);
}

.ap-admin-sidebar {
    background-color: var(--tars-dark);
    min-height: 100%;
}

.ap-admin-sidebar .nav-link {
    color: rgba(255, 255, 255, 0.8);
    border-radius: 0.375rem;
    padding: 0.5rem 0.75rem;
}

.ap-admin-sidebar .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.08);
    color: #fff;
}

.ap-admin-sidebar .nav-link.active {
    background-color: var(--tars-orange);
    color: var(--tars-white);
    font-weight: 600;
}

.ap-admin-sidebar hr { border-color: var(--tars-dark-line); opacity: 1; }

/* The sidebar column is narrower than the identity's 180px floor at most widths, so the
   lockup only appears where it clears that floor and the mark stands in elsewhere. */
.ap-admin-sidebar .tars-logo { height: 40px; min-width: var(--tars-logo-min); }

.ap-admin-topbar-actions { min-width: 0; max-width: 100%; }

.ap-stat-card .ap-stat-value {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.2;
}

.ap-table-compact td,
.ap-table-compact th {
    padding-block: 0.45rem;
    font-size: 0.9rem;
}

/* Table headers read as brand structure rather than as a grey stripe, which is what
   makes the admin tables and the invoice look like the same document family. */
.table > thead {
    --bs-table-bg: var(--tars-dark);
    --bs-table-color: var(--tars-white);
}

.table > thead th {
    font-weight: 600;
    letter-spacing: 0.01em;
    border-bottom-color: var(--tars-dark) !important;
}

/* Under the collapse breakpoint the search sits inside the opened menu and takes the
   full width, as it always has. */
@media (max-width: 991.98px) {
    .ap-search {
        flex-basis: auto;
        min-width: 0;
        max-width: none;
    }
}

/* A button mid-submission. Pointer events are off so a further click cannot even reach it,
   which matters on touch devices where a "click" can repeat faster than the script runs. */
.ap-busy {
    pointer-events: none;
    cursor: progress;
}

/* Whole-page waiting state. Only used where nothing else on the page is worth doing while
   the operation runs - placing an order, in practice. Covering the page is also what stops
   a second click reaching anything underneath it, which makes it a guard as well as a
   message. */
.ap-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.82);
    backdrop-filter: blur(2px);
}

.ap-overlay-box {
    text-align: center;
    padding: 1.5rem 2rem;
}

.ap-overlay-text {
    font-weight: 600;
    color: var(--ap-navy);
}

/* A busy button keeps its footprint so the layout does not jump when its label is swapped
   for a shorter or longer one. */
.ap-busy {
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .ap-overlay { backdrop-filter: none; }
}

/* ==================================================================================
   4. TAX INVOICE
   Follows the identity's invoice section: white sheet, dark headers, orange detail,
   and a table that stays the clearest thing on the page.
   ================================================================================== */
.tars-invoice-body {
    background-color: var(--tars-surface);
    color: var(--tars-ink);
}

.tars-invoice {
    background: var(--tars-white);
    max-width: 60rem;
    margin-inline: auto;
    margin-block-end: 2rem;
    padding: 1.75rem;
    border: 1px solid var(--tars-border);
    border-radius: var(--tars-radius);
}

/* The letterhead: a row with the gear and the wordmark, then the document's title. The
   dark banner lockup used to sit here in a rectangle of its own; the official wordmark is
   orange on transparent, so it lies on the white sheet with no box behind it. */
.tars-invoice-head {
    display: grid;
    gap: 0.75rem;
    padding-block-end: 1rem;
    border-block-end: 3px solid var(--tars-orange);
}

/* Physical, not logical, on purpose: the gear stays at the top left and the wordmark at
   the top right in Arabic and in English alike, so every invoice carries the same
   letterhead. `direction: ltr` on a row that holds only two images changes nothing else;
   the title below it still follows the reading direction. */
.tars-invoice-brand {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem 1.5rem;
    direction: ltr;
}

/* The Hero's gear mark at its own proportions (840:624), sized by height so the wordmark,
   which is far wider than tall, reads as its equal rather than its shadow. */
.tars-invoice-gear {
    display: block;
    height: 6rem;
    width: auto;
    flex: 0 0 auto;
}

/* The wordmark comes from _BrandLogo, so its base rule is the 44px banner height above;
   here it is sized by width instead (never distorted: height auto) and may shrink to the
   identity's 180px floor on a narrow screen before the row wraps. */
.tars-invoice-wordmark {
    flex: 0 1 18rem;
    min-width: 0;
}

.tars-invoice-wordmark .tars-logo {
    display: block;
    width: 18rem;
    max-width: 100%;
    height: auto;
    min-width: var(--tars-logo-min);
    object-fit: contain;
}

.tars-invoice-title { text-align: start; }
.tars-invoice-title-ar { font-size: 1.5rem; font-weight: 700; color: var(--tars-ink); }
.tars-invoice-title-en {
    font-size: 0.9rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: var(--tars-orange);
}

.tars-invoice-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 2rem;
    margin-block: 1rem;
    padding: 0.75rem 1rem;
    background: var(--tars-surface);
    border-inline-start: 4px solid var(--tars-orange);
    border-radius: var(--tars-radius-sm);
}

.tars-invoice-meta span {
    display: block;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tars-ink-muted);
}

.tars-invoice-h2 {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--tars-white);
    background: var(--tars-dark);
    padding: 0.4rem 0.75rem;
    border-radius: var(--tars-radius-sm);
    margin-block-end: 0.6rem;
}

.tars-invoice-parties dl {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.25rem 0.75rem;
    margin: 0;
    font-size: 0.9rem;
}

.tars-invoice-parties dt { font-weight: 600; color: var(--tars-ink-muted); }
.tars-invoice-parties dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

.tars-invoice-table-wrap { overflow-x: auto; margin-block: 1.25rem; }
.tars-invoice-table { margin-block: 0; font-size: 0.9rem; }
.tars-invoice-table > thead th { white-space: nowrap; font-size: 0.8rem; }
.tars-invoice-table > tbody td { border-color: var(--tars-border); vertical-align: middle; }
.tars-invoice-table > tbody tr:nth-child(even) { background: var(--tars-surface); }

.tars-invoice-totals th { background: var(--tars-surface); font-weight: 600; }
.tars-invoice-totals th,
.tars-invoice-totals td { border-color: var(--tars-border); }

.tars-invoice-grand th,
.tars-invoice-grand td {
    background: var(--tars-dark);
    color: var(--tars-white);
    font-size: 1.05rem;
    font-weight: 700;
}

.tars-invoice-notes {
    font-size: 0.85rem;
    color: var(--tars-ink-muted);
    padding-inline-start: 1.1rem;
    margin-block-end: 0.75rem;
}

.tars-invoice-foot {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem 1.5rem;
    margin-block-start: 1.5rem;
    padding: 0.75rem 1rem;
    background: var(--tars-dark);
    color: var(--tars-white);
    border-radius: var(--tars-radius-sm);
    font-size: 0.85rem;
}

/* Printing is what an invoice is for, so the sheet has to survive leaving the browser. */
@media print {
    /* A4 is what the store prints on; the margin keeps the letterhead off the paper's edge. */
    @page { size: A4; margin: 10mm; }
    .tars-invoice-body { background: var(--tars-white); }
    .tars-invoice {
        max-width: none;
        margin: 0;
        padding: 0;
        border: 0;
    }
    /* The two logos and the title are one letterhead; a page break must not split it, and
       the images keep the size the screen rules give them so nothing is clipped or scaled. */
    .tars-invoice-head { break-inside: avoid; page-break-inside: avoid; }
    .tars-invoice-gear { height: 22mm; }
    .tars-invoice-wordmark .tars-logo { width: 66mm; }
    /* The printable width is 190mm, so the line table and the totals are set a step
       smaller and their part numbers and amounts are kept on one line; a figure that
       wraps mid-amount is the one thing a printed invoice must never do. */
    .tars-invoice-table { font-size: 0.8rem; }
    .tars-invoice-table > thead th { font-size: 0.7rem; }
    .tars-invoice-table > tbody td,
    .tars-invoice-totals th,
    .tars-invoice-totals td { white-space: nowrap; }
    .tars-invoice-totals { font-size: 0.9rem; }
    .tars-invoice-grand th,
    .tars-invoice-grand td { font-size: 1rem; }
    .tars-invoice-h2,
    .tars-invoice-foot,
    .tars-invoice-grand th,
    .tars-invoice-grand td,
    .tars-invoice-table > thead {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
    .tars-invoice-table-wrap { overflow: visible; }
    .tars-invoice-table { page-break-inside: auto; }
    .tars-invoice-table tr { page-break-inside: avoid; }
}

/* ==================================================================================
   5. WHOLESALE PRICING
   A quiet accent, not a shout: the identity reserves orange for what needs attention, and
   "a trade price exists" earns a mention rather than a banner.
   ================================================================================== */
.ap-wholesale-chip {
    display: inline-flex;
    align-items: center;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.2;
    padding: 0.22em 0.6em;
    border-radius: 999px;
    color: #B8430F;
    background: var(--tars-orange-soft);
    border: 1px solid rgba(242, 101, 34, 0.35);
    white-space: nowrap;
}

.ap-wholesale-note {
    font-size: 0.9rem;
    font-weight: 600;
    color: #B8430F;
}

/* Shown only once the server has said the quantity qualifies. */
.ap-wholesale-quote {
    display: inline-flex;
    align-items: baseline;
    gap: 0.25rem;
    font-size: 0.95rem;
    color: var(--tars-ink);
    background: var(--tars-orange-soft);
    border-inline-start: 3px solid var(--tars-orange);
    padding: 0.35rem 0.6rem;
    border-radius: var(--tars-radius-sm);
}
.ap-wholesale-quote strong { color: #B8430F; font-size: 1.05em; }

/* ==================================================================================
   6. INVENTORY MOVEMENT TYPES
   One colour family per meaning, chosen by the stored movement type (see
   DisplayHelpers.MovementBadgeClass), never by the translated label. Every pair is
   white text on a colour that clears WCAG AA (4.5:1) for small text, and every badge
   also carries an icon and its name, so colour is never the only signal.
   ================================================================================== */
:root {
    --ap-move-in: #1E7B3A;        /* stock in, opening stock: green            */
    --ap-move-return: #0F766E;    /* return: teal                              */
    --ap-move-release: #1D4ED8;   /* reservation release: blue                 */
    --ap-move-hold: #B8430F;      /* reservation: TARS orange, deepened for AA */
    --ap-move-sale: #C81E1E;      /* sale: red                                 */
    --ap-move-out: #7F1D1D;       /* stock out: dark red                       */
    --ap-move-adjust: #6D28D9;    /* adjustment: purple                        */
    --ap-move-other: #5C6270;
    --ap-delta-pos: #15803D;
    --ap-delta-neg: #B91C1C;
    --ap-delta-zero: #6B7280;
}

.ap-move {
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.2;
    padding: 0.3em 0.65em;
    border-radius: 999px;
    color: var(--tars-white);
    background: var(--ap-move-other);
    white-space: nowrap;
    max-width: 100%;
}
.ap-move .bi { font-size: 0.95em; line-height: 1; }
.ap-move-stock-in,
.ap-move-opening      { background: var(--ap-move-in); }
.ap-move-return       { background: var(--ap-move-return); }
.ap-move-release      { background: var(--ap-move-release); }
.ap-move-reservation  { background: var(--ap-move-hold); }
.ap-move-sale         { background: var(--ap-move-sale); }
.ap-move-stock-out    { background: var(--ap-move-out); }
.ap-move-adjustment   { background: var(--ap-move-adjust); }

/* The legend under the filter: the same badges, each a link that applies the filter.
   The active one is ringed so the current filter can be seen without reading the select. */
.ap-move-legend { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.ap-move-legend a.ap-move { text-decoration: none; opacity: 0.92; }
.ap-move-legend a.ap-move:hover,
.ap-move-legend a.ap-move:focus-visible { opacity: 1; box-shadow: 0 0 0 3px rgba(15, 17, 21, 0.18); outline: none; }
.ap-move-legend a.ap-move.is-active { opacity: 1; box-shadow: 0 0 0 3px var(--tars-dark); }

/* The select keeps its native look; a coloured start edge mirrors the chosen type. */
.ap-move-select { border-inline-start-width: 4px; transition: border-color 0.15s ease; }
.ap-move-select[data-movement="StockIn"],
.ap-move-select[data-movement="OpeningStock"]      { border-inline-start-color: var(--ap-move-in); }
.ap-move-select[data-movement="Return"]            { border-inline-start-color: var(--ap-move-return); }
.ap-move-select[data-movement="ReleaseReservation"]{ border-inline-start-color: var(--ap-move-release); }
.ap-move-select[data-movement="Reservation"]       { border-inline-start-color: var(--ap-move-hold); }
.ap-move-select[data-movement="Sale"]              { border-inline-start-color: var(--ap-move-sale); }
.ap-move-select[data-movement="StockOut"]          { border-inline-start-color: var(--ap-move-out); }
.ap-move-select[data-movement="Adjustment"]        { border-inline-start-color: var(--ap-move-adjust); }

/* Signed quantity changes in the ledger. */
.ap-delta { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.ap-delta-pos  { color: var(--ap-delta-pos); }
.ap-delta-neg  { color: var(--ap-delta-neg); }
.ap-delta-zero { color: var(--ap-delta-zero); font-weight: 400; }

@media (max-width: 575.98px) {
    .ap-move { font-size: 0.72rem; padding: 0.28em 0.55em; }
}

/* =============================================================================
   7. NOTIFICATION CENTRE
   The bell, its panel, the toast, the list rows and the two badges. Colours are the
   identity's: the panel is white on the brand dark chrome, unread rows carry the orange
   accent, and the priority edge uses the semantic colours the ledger already uses (green,
   orange, red) - chosen from the stored priority, never from the words. Logical properties
   throughout, so the panel opens on the correct side in either direction.
   ============================================================================= */
:root {
    --ap-notif-info: var(--tars-dark);
    --ap-notif-success: #1E7B3A;
    --ap-notif-warning: #B8430F;
    --ap-notif-critical: #C81E1E;
}

.ap-bell-button { min-width: 2.25rem; }
.ap-bell-badge {
    position: absolute;
    inset-block-start: -0.35rem;
    inset-inline-end: -0.35rem;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--tars-orange);
    color: var(--tars-white);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1.25rem;
    text-align: center;
    box-shadow: 0 0 0 2px var(--tars-white);
    font-variant-numeric: tabular-nums;
}

.ap-orders-badge,
.ap-notif-count {
    background: var(--tars-orange);
    color: var(--tars-white);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* The panel is a Bootstrap dropdown menu: closed until the bell toggles .show, closed again by
   the bell, a click outside, or Escape. Its display is therefore set ONLY on .show - a
   display value on the base rule would override Bootstrap's "display: none" and leave the
   panel permanently open, whatever the toggle did. */
.ap-notif-panel {
    width: min(26rem, calc(100vw - 2rem));
    max-height: min(70vh, 34rem);
    flex-direction: column;
    border: 1px solid var(--tars-border);
    border-radius: var(--tars-radius);
    box-shadow: var(--tars-shadow-lift);
    overflow: hidden;
}
.ap-notif-panel.show { display: flex; }
.ap-notif-panel-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    padding: 0.65rem 0.9rem;
    background: var(--tars-dark);
    color: var(--tars-white);
    border-block-end: 3px solid var(--tars-orange);
}
.ap-notif-panel-head .btn-link { color: var(--tars-white); text-decoration: none; font-size: 0.8rem; }
.ap-notif-panel-head .btn-link:hover { color: var(--tars-orange-secondary); }
.ap-notif-panel-head .btn-link:disabled { color: var(--tars-neutral); }
.ap-notif-panel .ap-notif-list { overflow-y: auto; flex: 1 1 auto; }
.ap-notif-panel-foot {
    display: block;
    padding: 0.6rem;
    text-align: center;
    font-weight: 600;
    text-decoration: none;
    background: var(--tars-surface);
    border-block-start: 1px solid var(--tars-border);
}

.ap-notif-list { margin: 0; padding: 0; }
.ap-notif { list-style: none; border-block-end: 1px solid var(--tars-border); }
.ap-notif:last-of-type { border-block-end: 0; }
.ap-notif-link {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 0.7rem 0.9rem;
    color: var(--tars-ink);
    text-decoration: none;
    border-inline-start: 4px solid transparent;
    position: relative;
}
.ap-notif-link:hover, .ap-notif-link:focus-visible { background: var(--tars-surface); color: var(--tars-ink); outline: none; }
.ap-notif.is-unread .ap-notif-link { background: var(--tars-orange-soft); }
.ap-notif.is-unread .ap-notif-title { font-weight: 700; }
.ap-notif.is-read .ap-notif-link { opacity: 0.85; }
.ap-notif-info .ap-notif-link { border-inline-start-color: var(--ap-notif-info); }
.ap-notif-success .ap-notif-link { border-inline-start-color: var(--ap-notif-success); }
.ap-notif-warning .ap-notif-link { border-inline-start-color: var(--ap-notif-warning); }
.ap-notif-critical .ap-notif-link { border-inline-start-color: var(--ap-notif-critical); }

.ap-notif-icon {
    flex: 0 0 auto;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--tars-dark);
    color: var(--tars-white);
    font-size: 1rem;
}
.ap-notif-success .ap-notif-icon { background: var(--ap-notif-success); }
.ap-notif-warning .ap-notif-icon { background: var(--ap-notif-warning); }
.ap-notif-critical .ap-notif-icon { background: var(--ap-notif-critical); }

.ap-notif-body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; flex: 1 1 auto; }
.ap-notif-title { font-weight: 600; line-height: 1.25; }
.ap-notif-text { color: var(--tars-ink-muted); font-size: 0.875rem; line-height: 1.35; overflow-wrap: anywhere; }
.ap-notif-meta { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; font-size: 0.72rem; color: var(--tars-ink-muted); }
.ap-notif-meta time { margin-inline-start: auto; white-space: nowrap; }
.ap-notif-cat {
    padding: 0.1em 0.5em;
    border-radius: 999px;
    color: var(--tars-white);
    font-weight: 600;
    letter-spacing: 0.01em;
}
.ap-notif-cat-orders { background: var(--tars-dark); }
.ap-notif-cat-inventory { background: #6D28D9; }
.ap-notif-cat-payments { background: #0F766E; }
.ap-notif-cat-catalog { background: #1D4ED8; }
.ap-notif-cat-system { background: #5C6270; }
.ap-notif-priority { text-transform: uppercase; letter-spacing: 0.04em; }
.ap-notif-dot {
    position: absolute;
    inset-block-start: 0.85rem;
    inset-inline-end: 0.75rem;
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
    background: var(--tars-orange);
}

.ap-notif-tabs .nav-link { padding: 0.3rem 0.75rem; font-size: 0.9rem; }
.ap-stat-link { color: inherit; transition: box-shadow 0.15s ease; }
.ap-stat-link:hover { box-shadow: var(--tars-shadow-lift); color: inherit; }

/* Toasts sit at the top of the reading side, above everything, and never trap the pointer. */
.ap-toast-region {
    position: fixed;
    inset-block-start: 1rem;
    inset-inline-end: 1rem;
    z-index: 2100;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    width: min(24rem, calc(100vw - 2rem));
    pointer-events: none;
}
.ap-toast {
    pointer-events: auto;
    background: var(--tars-dark);
    color: var(--tars-white);
    border-radius: var(--tars-radius);
    box-shadow: var(--tars-shadow-lift);
    border-inline-start: 5px solid var(--tars-orange);
    padding: 0.7rem 0.85rem;
    animation: ap-toast-in 0.25s ease-out;
}
.ap-toast.is-leaving { opacity: 0; transform: translateY(-0.5rem); transition: opacity 0.25s, transform 0.25s; }
.ap-toast-success { border-inline-start-color: var(--ap-notif-success); }
.ap-toast-warning, .ap-toast.ap-notif-warning { border-inline-start-color: #FF7A38; }
.ap-toast.ap-notif-critical { border-inline-start-color: var(--ap-notif-critical); }
.ap-toast-head { display: flex; align-items: center; gap: 0.6rem; }
.ap-toast-head .ap-notif-icon { background: var(--tars-orange); width: 1.8rem; height: 1.8rem; font-size: 0.9rem; }
.ap-toast.ap-notif-critical .ap-notif-icon { background: var(--ap-notif-critical); }
.ap-toast.ap-notif-success .ap-notif-icon { background: var(--ap-notif-success); }
.ap-toast-body { margin-block-start: 0.35rem; color: var(--tars-neutral); font-size: 0.9rem; line-height: 1.4; }
.ap-toast-actions { margin-block-start: 0.6rem; display: flex; gap: 0.5rem; }
@keyframes ap-toast-in { from { opacity: 0; transform: translateY(-0.5rem); } to { opacity: 1; transform: none; } }

@media (max-width: 575.98px) {
    /* On a phone the panel becomes a sheet under the header rather than a floating menu. */
    .ap-notif-panel { width: calc(100vw - 1rem); max-height: 75vh; }
    .ap-toast-region { inset-inline-start: 0.5rem; inset-inline-end: 0.5rem; width: auto; }
}

@media (prefers-reduced-motion: reduce) {
    .ap-toast { animation: none; }
}
