/* ==========================================================================
   WeVisit design tokens — issue #261 (WP1).
   Linked on every page BEFORE the page's own stylesheet(s), so any later
   rule wins over the base layer below.

   Authoring rules for this file:
   - Logical properties only (padding-inline, inset-inline-*, text-align:
     start). scripts/gen-ltr.py reads this file first and mirrors any
     physical property it finds into ltr.css.
   - No @layer and no @supports: gen-ltr.py skips every @ block other than
     @media, so a physical property inside one would never be mirrored.
   ========================================================================== */

:root {
    /* ---- Colour: brand ---- */
    --wv-primary: #270442;
    --wv-primary-strong: #1C0133;
    --wv-primary-2: #3A0566;
    --wv-primary-300: #C9B9D8;
    --wv-primary-100: #E6DBF0;
    --wv-primary-50: #F3EDF8;
    --wv-accent: #F87B1B;           /* fills, borders, icons — never text */
    --wv-accent-hover: #E06A0A;
    --wv-accent-soft: #FFF1E6;
    --wv-accent-ink: #C2410C;       /* orange as text on a light surface */
    --wv-on-accent: #270442;        /* text on an orange fill */

    /* ---- Colour: text ---- */
    --wv-text: #2C2C2C;
    --wv-text-2: #555555;
    --wv-text-muted: #6B6B6B;
    --wv-title: #324B51;
    --wv-on-primary: #FFFFFF;
    --wv-on-primary-muted: #C9B9D8;

    /* ---- Colour: surfaces and borders ---- */
    --wv-surface: #FFFFFF;
    --wv-surface-soft: #FAFAFA;
    --wv-surface-warm: #FAF7F2;
    --wv-surface-app: #F4F6F9;
    --wv-border-subtle: #EEEEEE;
    --wv-border: #E0E0E0;
    --wv-border-input: #8C8C8C;

    /* ---- Colour: semantic (solid / soft / ink) ---- */
    --wv-success: #15803D;
    --wv-success-soft: #DCFCE7;
    --wv-success-ink: #15803D;
    --wv-success-fill: #22C55E;     /* dots and bars only, never under text */
    --wv-warning: #FFC107;
    --wv-warning-soft: #FFF3CD;
    --wv-warning-ink: #92400E;
    --wv-danger: #DC2626;
    --wv-danger-soft: #FEE2E2;
    --wv-danger-ink: #B91C1C;
    --wv-info: #1D4ED8;
    --wv-info-soft: #DBEAFE;
    --wv-info-ink: #1D4ED8;

    /* ---- Colour: focus and scrim ---- */
    --wv-focus: #3A0566;            /* outer ring: dark */
    --wv-focus-halo: #FFFFFF;       /* inner ring: light */
    --wv-scrim: rgba(20, 1, 42, .55);

    /* ---- Typography ---- */
    --wv-ff: 'Almarai', 'Segoe UI', Tahoma, system-ui, sans-serif;
    --wv-fw-regular: 400;
    --wv-fw-bold: 700;
    --wv-fw-black: 800;
    --wv-num: tabular-nums;

    /* Fluid sizes: the first clamp() argument is the phone size, the last the
       desktop size. */
    --wv-fs-display: clamp(2.125rem, 1.2rem + 3.6vw, 3.5rem);     /* 34 → 56 */
    --wv-fs-h1: clamp(1.75rem, 1.44rem + 1.33vw, 2.5rem);          /* 28 → 40 */
    --wv-fs-h2: clamp(1.5rem, 1.29rem + 0.88vw, 2rem);             /* 24 → 32 */
    --wv-fs-h3: clamp(1.25rem, 1.15rem + 0.44vw, 1.5rem);          /* 20 → 24 */
    --wv-fs-h4: clamp(1.0625rem, 1.04rem + 0.11vw, 1.125rem);      /* 17 → 18 */
    --wv-fs-body-lg: var(--wv-fs-h4);
    --wv-fs-body: 1rem;
    --wv-fs-label: 0.9375rem;
    --wv-fs-sm: 0.875rem;
    --wv-fs-meta: 0.8125rem;
    --wv-fs-xs: 0.75rem;

    --wv-lh-display: 1.25;
    --wv-lh-h1: 1.3;
    --wv-lh-h2: 1.35;
    --wv-lh-h3: 1.4;
    --wv-lh-h4: 1.45;
    --wv-lh-body-lg: 1.75;
    --wv-lh-body: 1.7;
    --wv-lh-label: 1.4;
    --wv-lh-sm: 1.5;
    --wv-lh-tight: 1.3;
    --wv-lh-normal: 1.7;

    /* ---- Spacing (4px base) ---- */
    --wv-sp-1: 4px;
    --wv-sp-2: 8px;
    --wv-sp-3: 12px;
    --wv-sp-4: 16px;
    --wv-sp-5: 20px;
    --wv-sp-6: 24px;
    --wv-sp-7: 32px;
    --wv-sp-8: 40px;
    --wv-sp-9: 48px;
    --wv-sp-10: 64px;
    --wv-sp-11: 80px;
    --wv-section-y: clamp(48px, 6vw, 80px);

    /* ---- Radii ---- */
    --wv-r-sm: 8px;
    --wv-r-md: 12px;
    --wv-r-lg: 16px;
    --wv-r-xl: 24px;
    --wv-r-pill: 999px;
    --wv-r-circle: 50%;

    /* ---- Shadows ---- */
    --wv-sh-xs: 0 1px 2px rgba(39, 4, 66, .06);
    --wv-sh-sm: 0 2px 12px rgba(0, 0, 0, .05);
    --wv-sh-md: 0 8px 24px rgba(39, 4, 66, .12);
    --wv-sh-lg: 0 20px 60px rgba(0, 0, 0, .2);
    /* Decorative field-focus glow only — it is NOT the focus indicator
       (below 3:1 against white). The indicator is the two-tone
       :focus-visible rule below, which replaces this glow while it shows. */
    --wv-sh-focus: 0 0 0 3px rgba(58, 5, 102, .35);

    /* ---- Widths ---- */
    --wv-w-page: 1600px;
    --wv-w-content: 1200px;
    --wv-w-form: 560px;
    --wv-w-prose: 68ch;
    --wv-gutter: clamp(16px, 4vw, 40px);

    /* ---- Motion ---- */
    --wv-t-fast: 150ms;
    --wv-t-base: 250ms;
    --wv-ease: ease;

    /* ---- Layers (z-index) ---- */
    /* Issue #265: the controls a page lays over a map (the failure notice,
       «موقعي الحالي», the mobile preview card). They sit in the map wrapper
       beside the isolated .leaflet-container (rule below), so 20 puts them
       above the whole map and below every page layer. */
    --wv-z-map-controls: 20;
    --wv-z-sticky: 100;
    --wv-z-dropdown: 200;
    --wv-z-action-bar: 300;
    --wv-z-floating: 400;
    --wv-z-drawer: 910;
    --wv-z-chatbot: 950;
    --wv-z-modal: 1010;
    --wv-z-modal-nested: 1020;
    --wv-z-popover: 1100;
    --wv-z-toast: 1200;
    /* Issue #262: the skip link (css/header.css) sits above every layer —
       it is the first tab stop and must never be covered. */
    --wv-z-skip: 1300;

    /* ---- Legacy names (issue #261 PR-2) ----
       The names the pages used before the tokens existed, defined once here
       as aliases. The :root blocks that used to define them (style.css,
       dashboard.css, destination-details.html) are deleted, not overridden:
       a later :root would win over this file. */
    --primary: var(--wv-primary);
    --primary-dark: var(--wv-primary);
    --primary-light: var(--wv-primary-2);
    --secondary: var(--wv-accent);
    --title: var(--wv-title);
    --white: var(--wv-surface);
    --gray5: var(--wv-border);
    --text-muted: var(--wv-text-muted);
    --text-main: var(--wv-text);
    --bg-color: var(--wv-surface-soft);
    --bg: var(--wv-surface-app);
    --card-bg: var(--wv-surface);
    --border: var(--wv-border-subtle);
    --success: var(--wv-success);
    --card-shadow: 0 10px 40px rgba(0, 0, 0, .06);
    --border-radius: var(--wv-r-xl);
    --transition: all var(--wv-t-base) var(--wv-ease);
}

/* ==========================================================================
   Base layer
   ========================================================================== */

html,
body {
    font-family: var(--wv-ff);
}

button,
input,
select,
textarea {
    font-family: inherit;
}

/* Leaflet 1.9.4's stylesheet gives its panes and controls z-index values up
   to 1000 (the controls). isolation: isolate makes the map container its own
   stacking context, so those values order the map's layers among
   themselves and are not compared with the page's layer scale above. */
.leaflet-container {
    isolation: isolate;
}

/* Keyboard focus: one two-tone ring on every interactive element.
   A 2px light ring (the box-shadow, which fills the 2px outline-offset gap)
   sits inside a 3px dark ring (the outline). Whatever the colour behind
   the control, one of the two tones contrasts with it by at least 3.88:1
   (the worst case, a surface of relative luminance about 0.22): the dark
   ring on light surfaces, the light ring on dark ones. No list of dark
   containers is needed.
   Specificity (0,1,0): the two :where() count 0, only :focus-visible
   counts. The !important declarations apply only in the :focus-visible
   state, so they override the inline and stylesheet `outline: none`
   exactly when a ring is required, and a mouse click on a button still
   draws none. While a control has the ring, the box-shadow replaces its
   own shadow, which returns when focus leaves. Any element
   carrying tabindex="-1" (a programmatic focus target, or a control
   deliberately taken out of the tab order) is excluded, native controls
   included; the second :where() keeps that exclusion at specificity 0. */
:where(a, button, input, select, textarea, summary, [role="button"], [tabindex]):where(:not([tabindex="-1"])):focus-visible {
    outline: 3px solid var(--wv-focus) !important;
    outline-offset: 2px !important;
    box-shadow: 0 0 0 2px var(--wv-focus-halo) !important;
}

/* Controls inside a box with overflow: hidden that they fill or reach the
   edge of (everything in a .destination-card, the links of a slider slide,
   the dashboard sidebar's links in its scrolling list, the newsletter
   field, whose form is wider than the box at 375px): a ring drawn outside
   them is cut off by that box, so theirs is drawn inside instead, in the same
   two tones: a 3px light ring just inside the border (an inset
   box-shadow; 3px, not 2px, because anti-aliasing at rounded corners can
   take the outermost pixel) and the dark ring 3-6px in (a negative
   outline-offset). Same specificity (0,1,0) as the rule above; declared
   later, so it wins. */
:where(.destination-card a, .destination-card button, .splide__slide a, .sidebar-nav a, .newsletter-box input):where(:not([tabindex="-1"])):focus-visible {
    outline-offset: -6px !important;
    box-shadow: inset 0 0 0 3px var(--wv-focus-halo) !important;
}

/* ==========================================================================
   Buttons (issue #261 WP1 PR-3)
   One family: .wv-btn + one variant (--primary | --secondary | --tertiary |
   --danger | --danger-soft | --accent | --on-dark | --on-dark-outline),
   an optional size (--sm | --lg; md is the default), --block and --icon.
   The legacy class names are listed beside each .wv-btn selector, so the
   existing markup renders through this family with no markup edit. Their
   own rules in style.css and dash-pages.css carry no background, colour,
   border, padding, font, radius or shadow declaration; what stays there is
   layout (flex, margins), the .ev-btn.is-busy opacity, the focus outline
   list and .act-go.ok, a success fill this family has no variant for. That
   layout reaches only the pages that link the sheet: institutions.html
   links no dash-pages.css, so it keeps flex: 1 on its two modal buttons in
   its own <style>, where the visual copies were deleted (as were those in
   settings.html). The bare
   .btn class is not aliased (the header's .btn-primary-nav and
   .btn-outline-nav it used to style were replaced by .wv-btn in issue
   #262), and each .btn.btn-* pair below outranks it by specificity
   (0,2,0 against 0,1,0).
   ========================================================================== */

:root {
    --wv-btn-radius: var(--wv-r-pill);
}

body.dashboard-body {
    --wv-btn-radius: var(--wv-r-md);
}

.wv-btn,
.btn.btn-primary,
.btn.btn-secondary,
.btn.btn-outline-primary,
.btn.btn-white,
.btn.btn-outline-white,
.btn-apply-filter,
.btn-clear-filter,
.ev-actions .btn-book,
.sticky-action-bar .btn-book,
.ev-modal .btn-modal,
.dp-btn-add,
.dp-btn-edit,
.dp-btn-filter,
.dp-btn-del,
.ev-btn,
.ev-rep-del,
.act-go,
.act-cancel,
.btn-confirm-delete,
.btn-cancel-modal,
.btn-save-settings {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--wv-sp-2);
    min-width: 0;
    min-height: 44px;
    padding-block: var(--wv-sp-2);
    padding-inline: var(--wv-sp-6);
    border: 1.5px solid transparent;
    border-radius: var(--wv-btn-radius);
    box-shadow: none;
    font-family: inherit;
    font-size: var(--wv-fs-label);
    font-weight: var(--wv-fw-bold);
    line-height: var(--wv-lh-label);
    text-align: center;
    text-decoration: none;
    white-space: normal;
    cursor: pointer;
    transition: background-color var(--wv-t-fast) var(--wv-ease), border-color var(--wv-t-fast) var(--wv-ease), color var(--wv-t-fast) var(--wv-ease);
}

/* Issue #497: the display rule above outranks the UA `[hidden] { display: none }`,
   so `el.hidden = true` on any of these controls left it painted (#pv-add-slot at
   the slot cap). Same fix as #201's .logo-box[hidden]. Direction-neutral. */
.wv-btn[hidden],
.btn.btn-primary[hidden],
.btn.btn-secondary[hidden],
.btn.btn-outline-primary[hidden],
.btn.btn-white[hidden],
.btn.btn-outline-white[hidden],
.btn-apply-filter[hidden],
.btn-clear-filter[hidden],
.ev-actions .btn-book[hidden],
.sticky-action-bar .btn-book[hidden],
.ev-modal .btn-modal[hidden],
.dp-btn-add[hidden],
.dp-btn-edit[hidden],
.dp-btn-filter[hidden],
.dp-btn-del[hidden],
.ev-btn[hidden],
.ev-rep-del[hidden],
.act-go[hidden],
.act-cancel[hidden],
.btn-confirm-delete[hidden],
.btn-cancel-modal[hidden],
.btn-save-settings[hidden] {
    display: none;
}

.wv-btn i,
.btn.btn-primary i,
.btn.btn-secondary i,
.btn.btn-outline-primary i,
.btn.btn-white i,
.btn.btn-outline-white i,
.btn-apply-filter i,
.btn-clear-filter i,
.ev-actions .btn-book i,
.sticky-action-bar .btn-book i,
.ev-modal .btn-modal i,
.dp-btn-add i,
.dp-btn-edit i,
.dp-btn-filter i,
.dp-btn-del i,
.ev-btn i,
.ev-rep-del i,
.act-go i,
.act-cancel i,
.btn-confirm-delete i,
.btn-cancel-modal i,
.btn-save-settings i {
    font-size: 18px;
}

.wv-btn--sm,
.btn-apply-filter,
.dp-btn-add,
.dp-btn-edit,
.dp-btn-filter,
.dp-btn-del,
.ev-btn,
.ev-rep-del {
    min-height: 36px;
    padding-inline: var(--wv-sp-4);
    border-radius: var(--wv-r-sm);
    font-size: var(--wv-fs-sm);
}

.wv-btn--lg,
.btn.btn-primary,
.btn.btn-secondary,
.btn.btn-outline-primary,
.btn.btn-white,
.btn.btn-outline-white {
    min-height: 52px;
    padding-inline: var(--wv-sp-7);
    font-size: var(--wv-fs-body);
}

.wv-btn--block,
.btn-apply-filter,
.ev-modal .btn-modal {
    width: 100%;
}

.wv-btn--icon,
.ev-rep-del {
    width: 44px;
    padding-inline: 0;
}

.wv-btn--sm.wv-btn--icon,
.ev-rep-del {
    width: 36px;
}

.wv-btn--primary,
.btn.btn-primary,
.btn.btn-secondary,
.btn-apply-filter,
.ev-actions .btn-book,
.sticky-action-bar .btn-book,
.ev-modal .btn-modal,
.dp-btn-add,
.dp-btn-edit,
.ev-btn-primary,
.act-go,
.btn-save-settings {
    background: var(--wv-primary);
    color: var(--wv-on-primary);
}

.wv-btn--primary:hover:not(:disabled):not([aria-disabled="true"]),
.btn.btn-primary:hover:not(:disabled):not([aria-disabled="true"]),
.btn.btn-secondary:hover:not(:disabled):not([aria-disabled="true"]),
.btn-apply-filter:hover:not(:disabled):not([aria-disabled="true"]),
.ev-actions .btn-book:hover:not(:disabled):not([aria-disabled="true"]),
.sticky-action-bar .btn-book:hover:not(:disabled):not([aria-disabled="true"]),
.ev-modal .btn-modal:hover:not(:disabled):not([aria-disabled="true"]),
.dp-btn-add:hover:not(:disabled):not([aria-disabled="true"]),
.dp-btn-edit:hover:not(:disabled):not([aria-disabled="true"]),
.ev-btn-primary:hover:not(:disabled):not([aria-disabled="true"]),
.act-go:hover:not(:disabled):not([aria-disabled="true"]),
.btn-save-settings:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--wv-primary-strong);
}

.wv-btn--primary:active:not(:disabled),
.btn.btn-primary:active:not(:disabled),
.btn.btn-secondary:active:not(:disabled),
.btn-apply-filter:active:not(:disabled),
.ev-actions .btn-book:active:not(:disabled),
.sticky-action-bar .btn-book:active:not(:disabled),
.ev-modal .btn-modal:active:not(:disabled),
.dp-btn-add:active:not(:disabled),
.dp-btn-edit:active:not(:disabled),
.ev-btn-primary:active:not(:disabled),
.act-go:active:not(:disabled),
.btn-save-settings:active:not(:disabled) {
    background: #14012A;
}

.wv-btn--secondary,
.btn.btn-outline-primary,
.dp-btn-filter,
.ev-btn-outline,
.btn-cancel-modal,
.act-cancel {
    background: var(--wv-surface);
    border-color: var(--wv-primary);
    color: var(--wv-primary);
}

.wv-btn--secondary:hover:not(:disabled):not([aria-disabled="true"]),
.btn.btn-outline-primary:hover:not(:disabled):not([aria-disabled="true"]),
.dp-btn-filter:hover:not(:disabled):not([aria-disabled="true"]),
.ev-btn-outline:hover:not(:disabled):not([aria-disabled="true"]),
.btn-cancel-modal:hover:not(:disabled):not([aria-disabled="true"]),
.act-cancel:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--wv-primary-50);
}

.wv-btn--tertiary,
.btn-clear-filter,
.ev-btn-ghost {
    background: transparent;
    color: var(--wv-primary);
}

.wv-btn--tertiary:hover:not(:disabled):not([aria-disabled="true"]),
.btn-clear-filter:hover:not(:disabled):not([aria-disabled="true"]),
.ev-btn-ghost:hover:not(:disabled):not([aria-disabled="true"]) {
    text-decoration: underline;
}

.wv-btn--danger,
.ev-btn-danger,
.btn-confirm-delete,
.act-go.danger {
    background: var(--wv-danger);
    color: var(--wv-on-primary);
}

.wv-btn--danger:hover:not(:disabled):not([aria-disabled="true"]),
.ev-btn-danger:hover:not(:disabled):not([aria-disabled="true"]),
.btn-confirm-delete:hover:not(:disabled):not([aria-disabled="true"]),
.act-go.danger:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--wv-danger-ink);
}

.wv-btn--danger-soft,
.dp-btn-del,
.ev-rep-del {
    background: var(--wv-danger-soft);
    color: var(--wv-danger-ink);
}

.wv-btn--danger-soft:hover:not(:disabled):not([aria-disabled="true"]),
.dp-btn-del:hover:not(:disabled):not([aria-disabled="true"]),
.ev-rep-del:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--wv-danger);
    color: var(--wv-on-primary);
}

.wv-btn--accent {
    background: var(--wv-accent);
    color: var(--wv-on-accent);
}

.wv-btn--accent:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--wv-accent-hover);
}

.wv-btn--on-dark,
.btn.btn-white {
    background: var(--wv-surface);
    color: var(--wv-primary);
}

.wv-btn--on-dark:hover:not(:disabled):not([aria-disabled="true"]),
.btn.btn-white:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--wv-primary-50);
}

.wv-btn--on-dark-outline,
.btn.btn-outline-white {
    background: transparent;
    border-color: var(--wv-on-primary);
    color: var(--wv-on-primary);
}

.wv-btn--on-dark-outline:hover:not(:disabled):not([aria-disabled="true"]),
.btn.btn-outline-white:hover:not(:disabled):not([aria-disabled="true"]) {
    background: rgba(255, 255, 255, .15);
}

.wv-btn:disabled,
.btn.btn-primary:disabled,
.btn.btn-secondary:disabled,
.btn.btn-outline-primary:disabled,
.btn.btn-white:disabled,
.btn.btn-outline-white:disabled,
.btn-apply-filter:disabled,
.btn-clear-filter:disabled,
.ev-actions .btn-book:disabled,
.sticky-action-bar .btn-book:disabled,
.ev-modal .btn-modal:disabled,
.dp-btn-add:disabled,
.dp-btn-edit:disabled,
.dp-btn-filter:disabled,
.dp-btn-del:disabled,
.ev-btn:disabled,
.ev-rep-del:disabled,
.act-go:disabled,
.act-cancel:disabled,
.btn-confirm-delete:disabled,
.btn-cancel-modal:disabled,
.btn-save-settings:disabled,
.wv-btn[aria-disabled="true"],
.btn.btn-primary[aria-disabled="true"],
.btn.btn-secondary[aria-disabled="true"],
.btn.btn-outline-primary[aria-disabled="true"],
.btn.btn-white[aria-disabled="true"],
.btn.btn-outline-white[aria-disabled="true"],
.btn-apply-filter[aria-disabled="true"],
.btn-clear-filter[aria-disabled="true"],
.ev-actions .btn-book[aria-disabled="true"],
.sticky-action-bar .btn-book[aria-disabled="true"],
.ev-modal .btn-modal[aria-disabled="true"],
.dp-btn-add[aria-disabled="true"],
.dp-btn-edit[aria-disabled="true"],
.dp-btn-filter[aria-disabled="true"],
.dp-btn-del[aria-disabled="true"],
.ev-btn[aria-disabled="true"],
.ev-rep-del[aria-disabled="true"],
.act-go[aria-disabled="true"],
.act-cancel[aria-disabled="true"],
.btn-confirm-delete[aria-disabled="true"],
.btn-cancel-modal[aria-disabled="true"],
.btn-save-settings[aria-disabled="true"] {
    background: var(--wv-surface-app);
    border-color: transparent;
    color: var(--wv-text-muted);
    cursor: not-allowed;
}

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

/* Toast entrance (js/api.js showToast: `animation: slideUp .3s ease`). Until
   issue #266 these keyframes lived only in index.html's inline chat-widget
   <style>, so the toast animated on the home page alone. A vertical move is
   the same in both directions; the reduced-motion rule above shortens it. */
@keyframes slideUp {
    from { opacity: 0; transform: translateY(30px); }
    to { opacity: 1; transform: translateY(0); }
}
