/* ==========================================================================
   a11y.css - CelestInfo accessibility layer (WCAG 2.2 A/AA)
   ADDITIVE ONLY. Never edit main.min.css / common.min.css.

   Design contract: this file must not change how the site looks to a mouse
   user at rest. Everything here is either (a) keyboard-focus-only state,
   (b) a reduced-motion opt-in, or (c) a fix to something that is already
   invisible on screen.

   Palette borrowed from the site: #7584D6 / #5967b5 / #908eed, #1a1a2e.

   NOTE ON !important: common.min.css declares `.skip-nav { ... !important }`
   and `.nav-dropdown { ... !important }`. Because this file is loaded via a
   <link> whose position relative to those async ("media=print" swap)
   stylesheets is not guaranteed, the overrides below rely on BOTH higher
   specificity and !important so they win deterministically, in any order.
   ========================================================================== */


/* ==========================================================================
   1. SKIP LINK - visible on focus
   WCAG 2.4.1 Bypass Blocks (A), 2.4.7 Focus Visible (AA),
        2.4.11 Focus Not Obscured (Minimum) (AA)

   The link exists in every page and is correctly first in the DOM, but
   common.min.css clips it to 1x1px with !important, which also defeats
   main.min.css's `.skip-nav:focus` un-clip rule. Result: a keyboard user
   tabs onto an invisible control. `.skip-nav:focus` beats `.skip-nav` on
   specificity, so these !important declarations win regardless of order.
   position:fixed (not static) means revealing it causes no layout shift.
   ========================================================================== */
.skip-nav:focus,
.skip-nav:focus-visible {
    position: fixed !important;
    top: 12px !important;
    left: 12px !important;
    right: auto !important;
    bottom: auto !important;
    width: auto !important;
    height: auto !important;
    padding: 12px 22px !important;
    margin: 0 !important;
    overflow: visible !important;
    clip: auto !important;
    clip-path: none !important;
    white-space: nowrap !important;
    background: #ffffff !important;
    color: #5967b5 !important;
    border: 2px solid #7584D6 !important;
    border-radius: 12px !important;
    box-shadow: 0 8px 24px rgba(89, 103, 181, 0.28) !important;
    font-family: 'Manrope', sans-serif !important;
    font-size: 15px !important;
    font-weight: 700 !important;
    line-height: 1.2 !important;
    text-decoration: none !important;
    outline: 3px solid #7584D6 !important;
    outline-offset: 2px !important;
    z-index: 100000 !important;
    display: block !important;
    pointer-events: auto !important;
}


/* ==========================================================================
   2. FOCUS INDICATORS - keyboard only
   WCAG 2.4.7 Focus Visible (AA), 2.4.11 Focus Not Obscured (AA),
        2.4.13 Focus Appearance, 1.4.11 Non-text Contrast (AA)

   :focus-visible is only matched when the UA decides a focus ring is
   warranted - i.e. keyboard / assistive tech, NOT a mouse click. Mouse
   users see exactly what they see today.

   #7584D6 measures 3.48:1 against #ffffff and 4.90:1 against the dark
   #1a1a2e footer, so it clears the 3:1 non-text contrast threshold on
   both of the site's surface colours.
   ========================================================================== */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[role="button"]:focus-visible,
[role="link"]:focus-visible,
[role="tab"]:focus-visible,
[tabindex]:focus-visible {
    /* Dual-tone ring. A single colour cannot clear 3:1 on every surface this
       site uses: #7584D6 measures 1.00:1 against the footer, whose gradient
       terminates in that same purple, and 1.49:1 against #5967B5. Measured
       ratios for this pair - dark ring / white halo:
         white page   17.13 / 1.00      footer purple  4.92 / 3.48
         deep purple   3.29 / 5.21      near-black     1.00 / 17.06
       At least one ring clears 3:1 on all four, satisfying WCAG 2.4.11.
       The outline is never clipped by an ancestor; the halo is the backup. */
    outline: 3px solid #1A1B24;
    outline-offset: 2px;
    box-shadow: 0 0 0 6px #FFFFFF;
}

/* Deliberately NOT setting `border-radius` here. An outline already follows
   the element's own corner radius in every current browser, whereas writing
   `border-radius: inherit` would repaint the element's corners from its
   PARENT on focus - square corners on a pill button, for instance. That is a
   visible geometry change for keyboard users, which this file must not make. */

/* Belt and braces for UAs that still paint the legacy :focus ring on click.
   Anything matched here is re-decorated by the :focus-visible block above. */
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
[role="button"]:focus:not(:focus-visible),
[tabindex]:focus:not(:focus-visible) {
    outline: none;
}

/* --------------------------------------------------------------------------
   2b. Re-arm focus on controls where the theme killed the outline outright.
   main.css / common.css set `outline: none` on plain :focus for these inputs
   (leaving only a border-colour change), which is a 2.4.7 failure for
   keyboard users. Restore an outline for :focus-visible only. !important is
   required because these override rules are order-independent.
   -------------------------------------------------------------------------- */
.search-bar input:focus-visible,
.form .input:focus-visible,
.footer-nl-form input[type="email"]:focus-visible,
.footer-nl-form button:focus-visible {
    outline: 3px solid #7584D6 !important;
    outline-offset: 2px !important;
}

/* On the dark footer the purple sits on near-black; lift it so the ring is
   unmistakable there too (still 3:1+, still keyboard-only). */
.footer-nl-form input[type="email"]:focus-visible,
.footer-nl-form button:focus-visible {
    outline-color: #908eed !important;
}

/* --------------------------------------------------------------------------
   2c. The primary CTA had an INVISIBLE focus ring.
   WCAG 2.4.7 Focus Visible (AA), 1.4.11 Non-text Contrast (AA)

   main.css ships `.cta-button:focus-visible { outline: white solid 2px }`.
   Every .cta-button on the site sits on a white surface (the white navbar
   pill, or the plain white page body), and an outline is painted OUTSIDE the
   element, so that ring is white-on-white: the site's main conversion control
   had no visible keyboard focus state at all.

   `.cta-button:focus-visible` is 0,0,2,0 and beats the generic
   `button:focus-visible` rule above (0,0,1,1), which is why this needs its own
   override rather than relying on section 2. Same specificity as main.css's
   rule, later in the cascade, so it wins without !important.

   Scope of the bug: the navbar CTA was already safe, because common.min.css
   carries `.navbar .cta-button:focus { outline: #7584D6 solid 2px !important }`
   (0,0,3,0 + !important) which outranks the white rule. The unprotected ones
   are every CTA OUTSIDE the navbar - hero, in-page and closing CTAs - which is
   the majority of them.

   Only `outline` is touched. These buttons carry layered decorative
   box-shadows, and overwriting those on focus would visibly flatten the
   button, so they are left exactly as they are.

   Deliberately NOT touching `.lets-talk-section .header > a:focus-visible`:
   that section has a purple gradient background (#a5a4fa -> #7584D6), where
   the existing white ring is the correct, readable choice.
   -------------------------------------------------------------------------- */
.cta-button:focus-visible {
    outline: 3px solid #7584D6;
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   2d. Nav hamburger. It does get a ring from the generic rule in section 2,
   but this control is the entry point to the whole menu, so pin it explicitly
   in the brand purple rather than leaving it to inherit a UA default ring.
   Keyboard-only, and the button has no border or box-shadow at rest, so
   nothing here is visible until the control is focused from the keyboard.
   WCAG 2.4.7 Focus Visible (AA), 1.4.11 Non-text Contrast (AA).
   -------------------------------------------------------------------------- */
.menu-hamburger:focus-visible,
#menu-toggle:focus-visible {
    outline: 3px solid #7584D6 !important;
    outline-offset: 2px !important;
}


/* ==========================================================================
   3. COLLAPSED FAQ PANELS - remove from tab order and a11y tree
   WCAG 2.4.3 Focus Order (A), 1.3.1 Info and Relationships (A),
        4.1.2 Name Role Value (A)

   `.faq-answer` collapses with `max-height:0; overflow:hidden` only. The
   content is invisible but still rendered, so screen readers announce every
   answer as though it were open, and any link inside a closed panel is
   still tabbable while off-screen (snowflake-consulting.html has exactly
   such a link, inside a collapsed answer).

   `visibility:hidden` fixes both. The zero-duration/0.3s-delay transition
   means visibility only flips back to hidden AFTER the max-height collapse
   has finished, so the close animation is pixel-identical to today's.
   The panel is already 0px tall in this state, so nothing moves.

   `visibility:hidden` (rather than `display:none`) is also what keeps the
   widget working: the panel still generates a box, so `scrollHeight` in
   script.js's expand() still measures the real content height.

   CASCADE NOTE - this is why the transition is declared twice.
   main.css owns the animation as `.faq-main .faq-answer` (specificity 0,0,2,0).
   A bare `.faq-answer` rule here (0,0,1,0) LOSES, so the visibility hand-off
   would be dropped from the shorthand and visibility would flip instantly:
   on close the answer would blink out instead of sliding up - a visible
   regression. The `.faq-main`-scoped selectors below tie or beat main.css and,
   being later in the cascade, win. The bare selectors are kept alongside so
   any FAQ that is not inside `.faq-main` still gets the same behaviour.
   The declared timings are copied verbatim from main.css, so the animation
   is unchanged; only `visibility` is added to it.
   ========================================================================== */
.faq-answer {
    visibility: hidden;
}

.faq-answer.open {
    visibility: visible;
}

.faq-answer,
.faq-main .faq-answer {
    transition: max-height 0.3s ease, padding 0.3s ease, visibility 0s linear 0.3s;
}

.faq-answer.open,
.faq-main .faq-answer.open {
    transition: max-height 0.3s ease, padding 0.3s ease, visibility 0s linear 0s;
}


/* ==========================================================================
   4. DECORATIVE CUSTOM CURSOR - never intercept pointer input
   WCAG 1.1.1 Non-text Content (A), 2.5.1 Pointer Gestures (A)

   #custom-cursor is a purely decorative follower graphic pinned at
   z-index 9999 across the whole viewport. `aria-hidden` is applied by
   a11y.py in the markup; this guarantees it can never swallow a click,
   independently of the theme stylesheets' load order.
   ========================================================================== */
#custom-cursor,
#custom-cursor * {
    pointer-events: none !important;
    -webkit-user-select: none;
    user-select: none;
}


/* ==========================================================================
   5. REDUCED MOTION
   WCAG 2.3.3 Animation from Interactions, 2.2.2 Pause Stop Hide (A)

   The site animates constantly: slide-in-on-scroll for most sections, an
   infinitely rotating cursor sprite, staggered menu drop-in, marquee logo
   rails and digit-roll counters. Honour the OS-level request to stop.

   Durations are collapsed to ~0 rather than set to `animation: none`, so
   every animation still lands on its END state - content stays visible.
   ========================================================================== */
@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;
    }

    /* Scroll reveals: show content immediately and unconditionally, so it is
       never left at opacity:0 waiting on an IntersectionObserver. */
    .slide-in-right,
    .slide-in-bottom,
    .slide-in-left,
    .slide-in-top,
    .fade-in {
        transform: none !important;
        opacity: 1 !important;
        transition: none !important;
        animation: none !important;
    }

    /* Keep the navbar's containing-block workaround intact. */
    .navbar.slide-in-bottom,
    .navbar.slide-in-bottom.active {
        transform: none !important;
    }

    /* Decorative rotating cursor sprite: remove it entirely. */
    #custom-cursor {
        display: none !important;
    }

    #custom-cursor img {
        animation: none !important;
    }

    /* Menu: open/close instantly, no staggered drop-in. */
    .nav-dropdown {
        transition: none !important;
    }

    .nav-dropdown.active .menu-left > *,
    .nav-dropdown.active .menu-right > *:not(.social-links),
    .nav-dropdown.active .menu-left > a,
    .nav-dropdown.active .menu-right > a {
        animation: none !important;
        animation-delay: 0s !important;
        opacity: 1 !important;
        transform: none !important;
    }

    /* Infinite marquee logo rails. */
    .logos-slide,
    .logos-slide-1 {
        animation: none !important;
        transform: none !important;
    }

    /* Digit-roll counters land on their final value with no roll. */
    .digit-scroll {
        transition: none !important;
    }

    /* FAQ: collapse instantly, so drop the delayed visibility hand-off too.
       !important is what makes this beat the `.faq-main`-scoped rules above. */
    .faq-answer,
    .faq-main .faq-answer,
    .faq-answer.open,
    .faq-main .faq-answer.open {
        transition: none !important;
        transition-delay: 0s !important;
    }

    /* Full-bleed autoplaying background video on the homepage. script.js
       pauses it (a paused <video> still paints its current frame, so the
       hero keeps its backdrop); this is the belt-and-braces half in case the
       script has not run yet. WCAG 2.2.2 Pause, Stop, Hide (A). */
    #bg-video {
        animation-play-state: paused !important;
    }
}


/* -------------------------------------------------------------------------
   Mobile navigation overflow
   .nav-dropdown is position:fixed with height:auto and overflow:visible, so on
   a short viewport the lower menu items (Blog, Contact) render past the bottom
   edge with no way to reach them. Constrain the height and let it scroll.
   Scoped to small or short viewports, so the desktop panel is untouched.
   ------------------------------------------------------------------------- */
@media (max-width: 640px), (max-height: 720px) {
    .nav-dropdown {
        max-height: calc(100vh - 104px) !important;
        overflow-y: auto !important;
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
    }
}
