/**
 * Biscutery — UX polish layer
 *
 * Sits on top of bysk-glass.css (surfaces) and design-eng-motion.css (motion).
 * Revert: delete this file and its <link> in partials/bysk_glass_assets.blade.php.
 *
 * Covers what the surface and motion layers left out:
 *  1. Keyboard focus (:focus-visible) — the app had no focus ring anywhere.
 *  2. Skip-to-content link.
 *  3. Overflow affordance on the horizontally scrolling nav clusters.
 *  4. Pending state for forms being submitted.
 *  5. Flash-alert entrance / exit and origin-aware dropdown entrance.
 *
 * Same rules as the motion layer: animate transform/opacity/scale/filter only,
 * everything under 300ms, and every motion rule has a reduced-motion escape.
 */

:root {
    --bysk-focus-ring: #2563eb;
    --bysk-focus-ring-on-dark: #bfdbfe;
    --bysk-focus-ring-danger: #dc2626;
    --bysk-focus-halo: rgba(37, 99, 235, 0.25);
    --bysk-focus-width: 2px;
    --bysk-focus-offset: 2px;
}

/* =========================================================
   1. Keyboard focus
   Mouse and touch never see a ring; keyboard always does.
   ========================================================= */

/* Bootstrap paints a :focus box-shadow on .btn — it fires on tap too,
   leaving a halo stuck under the cashier's finger. Ring goes to
   :focus-visible only. */
body.bysk-glass .btn:focus:not(:focus-visible),
body.bysk-glass .page-link:focus:not(:focus-visible),
body.bysk-glass .nav-link:focus:not(:focus-visible),
body.bysk-glass .form-check-input:focus:not(:focus-visible) {
    box-shadow: none;
    outline: none;
}

body.bysk-glass a:focus-visible,
body.bysk-glass .btn:focus-visible,
body.bysk-glass .nav-link:focus-visible,
body.bysk-glass .page-link:focus-visible,
body.bysk-glass .dropdown-item:focus-visible,
body.bysk-glass .list-group-item-action:focus-visible,
body.bysk-glass .form-check-input:focus-visible,
body.bysk-glass .btn-close:focus-visible,
body.bysk-glass summary:focus-visible,
body.bysk-glass [role='button']:focus-visible,
body.bysk-glass [tabindex]:not([tabindex='-1']):focus-visible {
    outline: var(--bysk-focus-width) solid var(--bysk-focus-ring);
    outline-offset: var(--bysk-focus-offset);
    box-shadow: 0 0 0 4px var(--bysk-focus-halo);
}

/* Text inputs keep their tinted border and gain a real outline on top —
   the border alone reads as "styled", not as "focused". */
body.bysk-glass .form-control:focus-visible,
body.bysk-glass .form-select:focus-visible {
    outline: var(--bysk-focus-width) solid var(--bysk-focus-ring);
    outline-offset: 1px;
}

/* Destructive actions get a red ring so the keyboard user knows what is
   under the Enter key before pressing it. */
body.bysk-glass .btn-danger:focus-visible,
body.bysk-glass .btn-outline-danger:focus-visible {
    --bysk-focus-ring: var(--bysk-focus-ring-danger);
    --bysk-focus-halo: rgba(220, 38, 38, 0.25);
}

/* Dark navbar / offcanvas: a blue ring on #0f172a is invisible. */
body.bysk-glass nav.bysk-topnav a:focus-visible,
body.bysk-glass nav.bysk-topnav .btn:focus-visible,
body.bysk-glass nav.dress-topnav a:focus-visible,
body.bysk-glass nav.dress-topnav .btn:focus-visible,
body.bysk-glass nav.dress-desk-nav a:focus-visible,
body.bysk-glass nav.dress-desk-nav .btn:focus-visible,
body.bysk-glass .offcanvas.text-bg-dark a:focus-visible,
body.bysk-glass .offcanvas.text-bg-dark .btn:focus-visible,
body.bysk-glass .app-mobile-nav-offcanvas .btn-close:focus-visible,
body.bysk-glass .glass-dark a:focus-visible,
body.bysk-glass .glass-dark .btn:focus-visible,
body.bysk-glass #loginVkbPanel .login-vkb-key:focus-visible {
    outline-color: var(--bysk-focus-ring-on-dark);
    box-shadow: 0 0 0 4px rgba(191, 219, 254, 0.28);
}

/* The offcanvas menu items sit on their own dark panel inside the drawer. */
body.bysk-glass .app-mobile-nav-cluster .dropdown-item:focus-visible {
    outline-color: var(--bysk-focus-ring);
    box-shadow: 0 0 0 3px var(--bysk-focus-halo);
}

/* Custom pressables that are not <button>/.btn and so had nothing at all. */
body.pos-page .pos-product-card:focus-visible,
body.pos-page .pos-seg-control__btn:focus-visible,
body.pos-page #itemExtrasModalOptions .pos-extra-modifier-card:focus-visible,
.kitchen-screen-11 .kitchen-order-card:focus-visible,
.kitchen-station-pill:focus-visible,
.st-material-card:focus-visible {
    outline: var(--bysk-focus-width) solid var(--bysk-focus-ring);
    outline-offset: var(--bysk-focus-offset);
    box-shadow: 0 0 0 4px var(--bysk-focus-halo);
}

/* Windows High Contrast / forced colors: system colors, no custom halo. */
@media (forced-colors: active) {
    body.bysk-glass a:focus-visible,
    body.bysk-glass .btn:focus-visible,
    body.bysk-glass .form-control:focus-visible,
    body.bysk-glass .form-select:focus-visible,
    body.bysk-glass [role='button']:focus-visible {
        outline: 3px solid Highlight;
        box-shadow: none;
    }
}

/* =========================================================
   2. Skip to content
   Off-screen until focused, then parks under the navbar.
   ========================================================= */
.bysk-skip-link {
    position: fixed;
    inset-block-start: 0.5rem;
    inset-inline-start: 0.5rem;
    z-index: 2000001; /* above #main-navbar's z-index: 2000000 */
    padding: 0.6rem 1rem;
    border-radius: 0.65rem;
    background: #0f172a;
    color: #f8fafc;
    font-weight: 700;
    text-decoration: none;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.32);
    transform: translateY(calc(-100% - 1rem));
    transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}

.bysk-skip-link:focus,
.bysk-skip-link:focus-visible {
    transform: translateY(0);
    color: #f8fafc;
    outline: 2px solid var(--bysk-focus-ring-on-dark);
    outline-offset: 2px;
}

/* Inside the desk iframe the navbar is hidden, so there is nothing to skip. */
html.desk-iframe-child .bysk-skip-link,
body.desk-embed-body .bysk-skip-link {
    display: none;
}

/* The <main> takes focus after the jump but must not draw a ring for it. */
main[tabindex='-1']:focus,
main[tabindex='-1']:focus-visible {
    outline: none;
}

/* =========================================================
   3. Horizontal overflow affordance
   Nav buttons scrolled out of view looked like they did not exist.
   Classes are toggled by bysk_ux_polish.blade.php.
   ========================================================= */
.app-topnav-cluster,
nav.dress-topnav .app-topnav-scroll {
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
}

/* The dress navbar is flex-nowrap with no scroller — on a tablet the
   buttons squeezed together instead of scrolling. */
nav.dress-topnav .app-topnav-scroll {
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap;
}

nav.dress-topnav .app-topnav-scroll > * {
    flex-shrink: 0;
}

.app-topnav-cluster::-webkit-scrollbar,
nav.dress-topnav .app-topnav-scroll::-webkit-scrollbar {
    height: 3px;
}

.app-topnav-cluster::-webkit-scrollbar-thumb,
nav.dress-topnav .app-topnav-scroll::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.28);
    border-radius: 999px;
}

/* Neither element paints its own background, so masking only fades the
   buttons — the navbar surface behind them stays solid. */
@supports (mask-image: linear-gradient(#000, #000)) {
    /* `to right` runs 0% at the left edge -> fades the inline-start side in LTR. */
    .bysk-overflow-fade.is-fade-start {
        -webkit-mask-image: linear-gradient(to right, transparent 0, #000 28px);
        mask-image: linear-gradient(to right, transparent 0, #000 28px);
    }

    .bysk-overflow-fade.is-fade-end {
        -webkit-mask-image: linear-gradient(to left, transparent 0, #000 28px);
        mask-image: linear-gradient(to left, transparent 0, #000 28px);
    }

    /* RTL: inline-start is the right edge, so the two single-sided masks swap. */
    [dir='rtl'] .bysk-overflow-fade.is-fade-start {
        -webkit-mask-image: linear-gradient(to left, transparent 0, #000 28px);
        mask-image: linear-gradient(to left, transparent 0, #000 28px);
    }

    [dir='rtl'] .bysk-overflow-fade.is-fade-end {
        -webkit-mask-image: linear-gradient(to right, transparent 0, #000 28px);
        mask-image: linear-gradient(to right, transparent 0, #000 28px);
    }

    /* Both edges cut: declared last so it beats the equal-specificity
       single-sided rules above in either direction. */
    .bysk-overflow-fade.is-fade-start.is-fade-end,
    [dir='rtl'] .bysk-overflow-fade.is-fade-start.is-fade-end {
        -webkit-mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
        mask-image: linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
    }
}

/* A masked element clips the focus ring of the button inside it. Drop the
   mask while anything in the strip has keyboard focus. */
.bysk-overflow-fade:focus-within {
    -webkit-mask-image: none !important;
    mask-image: none !important;
}

/* =========================================================
   4. Form pending state
   Feedback that the tap landed, plus a visible reason the second tap
   does nothing.
   ========================================================= */
.bysk-is-pending {
    position: relative;
    pointer-events: none;
    opacity: 0.78;
}

/* Reserve the spinner's room so the label does not shift under it. */
.btn.bysk-is-pending,
button.bysk-is-pending,
[type='submit'].bysk-is-pending {
    padding-inline-end: 2.4em;
}

.bysk-is-pending::after {
    content: '';
    position: absolute;
    inset-block-start: 50%;
    inset-inline-end: 0.75em;
    width: 1em;
    height: 1em;
    margin-block-start: -0.5em;
    border: 2px solid currentColor;
    border-inline-start-color: transparent;
    border-radius: 50%;
    opacity: 0.85;
    animation: bysk-pending-spin 640ms linear infinite;
}

@keyframes bysk-pending-spin {
    to {
        transform: rotate(360deg);
    }
}

/* The whole form dims so a second field edit does not look accepted. */
form.bysk-form-submitting {
    opacity: 0.92;
    transition: opacity 140ms cubic-bezier(0.23, 1, 0.32, 1);
}

form.bysk-form-submitting :is(input, select, textarea, button, .btn):not(.bysk-is-pending) {
    pointer-events: none;
}

/* =========================================================
   5. Flash alerts + dropdown entrance
   ========================================================= */
body.bysk-glass > main > .alert,
body.bysk-glass .bysk-flash-alert {
    opacity: 1;
    transform: translateY(0);
    transition:
        opacity 220ms cubic-bezier(0.23, 1, 0.32, 1),
        transform 220ms cubic-bezier(0.23, 1, 0.32, 1);
}

@supports (transition-behavior: allow-discrete) {
    body.bysk-glass > main > .alert,
    body.bysk-glass .bysk-flash-alert {
        @starting-style {
            opacity: 0;
            transform: translateY(-0.4rem);
        }
    }
}

/* Exit is faster than entry — the system responding, not the user deciding. */
body.bysk-glass .alert.bysk-flash-leaving {
    opacity: 0;
    transform: translateY(-0.4rem);
    transition:
        opacity 160ms cubic-bezier(0.23, 1, 0.32, 1),
        transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}

/* Dropdowns scale in from the trigger, not from the middle of the panel. */
body.bysk-glass .dropdown-menu.show {
    animation: bysk-dropdown-in 160ms cubic-bezier(0.23, 1, 0.32, 1);
    transform-origin: top center;
}

body.bysk-glass .dropdown-menu.show[data-popper-placement^='top'] {
    transform-origin: bottom center;
}

body.bysk-glass .dropdown-menu.show[data-popper-placement^='start'],
body.bysk-glass .dropdown-menu.show[data-popper-placement^='right'] {
    transform-origin: center left;
}

body.bysk-glass .dropdown-menu.show[data-popper-placement^='end'],
body.bysk-glass .dropdown-menu.show[data-popper-placement^='left'] {
    transform-origin: center right;
}

@keyframes bysk-dropdown-in {
    from {
        opacity: 0;
        /* Never from scale(0) — nothing in the world appears from nothing. */
        transform: scale(0.96);
    }
}

/* The nav menus are pinned open as static blocks inside the mobile drawer;
   animating them there fights the offcanvas slide. */
body.bysk-glass .app-mobile-nav-cluster .dropdown-menu.show {
    animation: none;
}

/* =========================================================
   Reduced motion — keep the meaning, drop the movement
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
    .bysk-skip-link {
        transition: none;
    }

    .bysk-is-pending::after {
        animation-duration: 1600ms;
    }

    form.bysk-form-submitting {
        transition: none;
    }

    body.bysk-glass > main > .alert,
    body.bysk-glass .bysk-flash-alert,
    body.bysk-glass .alert.bysk-flash-leaving {
        transform: none !important;
        transition: opacity 160ms ease !important;
    }

    body.bysk-glass .dropdown-menu.show {
        animation: none;
    }
}
