/*
 * Small, deliberate overrides on top of front/'s own main.css (which is kept
 * byte-for-byte as shipped - see resources/views/public.blade.php). Each
 * rule here should be commented with why it exists; nothing here should
 * change front/'s original design, only fix gaps that front/'s own demo
 * content never happened to expose.
 */

/* `.zq_mobile_menu .logo img` has no width rule anywhere in main.css - the
   logo renders at its natural image size, which for our real logo file
   overwhelms the off-canvas menu (the grid icon opens this same panel at
   every viewport width, not just mobile - see main.js's Navbar Menu block),
   so this isn't scoped to a breakpoint. */
.zq_mobile_menu .logo img {
    max-width: 20%;
}

/* front/'s template has no back-to-top button at all (checked every page,
   main.css and main.js) - new addition, styled after the site's existing
   white pill-button look (`.zq_theme-btn`) rather than a new visual style. */
.zq_scroll-top {
    position: fixed;
    right: 30px;
    bottom: 30px;
    z-index: 99;
    width: 50px;
    height: 50px;
    border: none;
    border-radius: 50%;
    background: var(--clr-theme-primary);
    color: var(--clr-common-black);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: translateY(15px);
    transition: all 0.3s ease;
}

.zq_scroll-top.is-visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.zq_scroll-top:hover {
    background: #fff;
}

@media (max-width: 575px) {
    .zq_scroll-top {
        right: 16px;
        bottom: 16px;
        width: 42px;
        height: 42px;
    }
}

/* Top-of-page loading bar for Inertia navigations (see PageLoader) - front/'s
   template is fully server-rendered and has no equivalent. Glowing white
   trail on the black background matches the site's existing white-accent /
   black-base palette rather than introducing a new brand color. */
.zq_page-loader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    z-index: 9999;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
}

.zq_page-loader.is-active {
    opacity: 1;
}

.zq_page-loader-bar {
    height: 100%;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #fff 70%, #fff 100%);
    box-shadow:
        0 0 12px 2px rgba(255, 255, 255, 0.85),
        0 0 4px rgba(255, 255, 255, 0.9);
    transition: width 0.2s ease-out;
}

/* Pricing cards (pricing-section.tsx) moved the "Get this Plan Now" button
   to sit right after the description, above the feature list, instead of
   below it (front/'s original order) - per request. main.css's own
   `.zq_price-btn` has no bottom margin since it was always the last element
   in the card; now that `.zq_price-feature` follows it instead of the other
   way round, it needs one to keep the same visual rhythm. */
.zq_price-btn {
    margin-bottom: 30px;
}

/* 404 page (404.tsx) - same glow-card visual language as the standalone
   error pages (resources/views/components/error-page.blade.php), so the
   whole error-page family reads as one deliberate design. This one keeps
   the real header/footer via FrontLayout (the app is healthy when a 404
   happens), so only the illustration+text block front/'s own template used
   is replaced - not the surrounding page chrome. */
.zq_error-glow-card {
    position: relative;
    padding: 64px 40px 56px;
    border-radius: 28px;
    background: #141414;
    border: 1px solid rgba(255, 255, 255, 0.08);
    box-shadow:
        0 30px 80px rgba(0, 0, 0, 0.55),
        0 0 0 1px rgba(255, 255, 255, 0.03) inset,
        0 0 90px rgba(255, 255, 255, 0.06);
}

.zq_error-glow-line {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 50%;
    height: 2px;
    background: linear-gradient(90deg, transparent, #fff, transparent);
    box-shadow: 0 0 20px 2px rgba(255, 255, 255, 0.8);
}

.zq_error-glow-code {
    font-family: 'ClashDisplay', sans-serif;
    font-weight: 700;
    font-size: clamp(64px, 10vw, 100px);
    line-height: 1;
    margin: 0 0 8px;
    color: #fff;
    text-shadow:
        0 0 20px rgba(255, 255, 255, 0.55),
        0 0 60px rgba(255, 255, 255, 0.25);
}

.zq_error-glow-card h2 {
    color: #fff;
    font-family: 'ClashDisplay', sans-serif;
    font-size: 32px;
    font-weight: 600;
    line-height: 1.2;
    margin-bottom: 16px;
}

.zq_error-glow-text {
    color: rgba(255, 255, 255, 0.65);
    font-family: 'Inter', sans-serif;
    font-size: 16px;
    line-height: 26px;
    margin-bottom: 32px;
}

@media (max-width: 767px) {
    .zq_error-glow-card {
        padding: 48px 24px 40px;
    }

    .zq_error-glow-text br {
        display: none;
    }
}

/* "Meet Our Trusted Clients" logo marquee (partners-section.tsx) - two
   deliberate changes on top of front/'s own design, per request. The
   subtitle text itself is NOT touched - it stays the site's normal white,
   exactly as front/ had it; only the logo boxes change.

   1. front/'s own `.zq_brand-item img` / `.zq_h5_brand-item img` dim every
      logo to 60% opacity until hovered (`filter: opacity(0.6)`, full
      brightness only on :hover) - fine for a demo, but real client logos
      you're vouching for read as washed-out and low-trust at a glance
      rather than a confident "these are our clients" statement. Forced to
      full opacity always; the :hover rule already sets opacity(1) so this
      doesn't touch hover behavior, just removes the default dim state. */
.zq_brand-item img,
.zq_h5_brand-item img,
.zq_inner_brand-item img {
    filter: opacity(1);
}

/* main.css never constrains these logos' own size - each `<img>` just
   renders at whatever natural pixel size the uploaded file happens to be,
   centered in the (fixed-height) box. A small source image ends up looking
   tiny and lost with lots of empty padding around it; scaling each logo up
   to actually fill most of its box (while keeping its own aspect ratio,
   never stretching) is what makes them read as bold and "zoomed in" instead
   of shrunk. */
.zq_brand-item img,
.zq_h5_brand-item img,
.zq_inner_brand-item img {
    max-height: 70%;
    max-width: 85%;
    width: auto;
    object-fit: contain;
}

/* 2. Each logo box's border becomes a neon lime line (front/'s own is a
      barely-visible `rgba(255,255,255,0.08)` hairline) - the same lime
      introduced on the login page, with a soft glow to actually read as
      "neon" rather than just a colored border. */
.zq_brand-item,
.zq_h5_brand-item,
.zq_inner_brand-item {
    border: 1px solid rgba(163, 230, 53, 0.5);
    box-shadow: 0 0 12px rgba(163, 230, 53, 0.25);
}

/* The video-stats play button (video-stats-section.tsx) is a real <button>
   now instead of a dead `<a href="#">` (see getVideoEmbedUrl) - main.css's
   own `.zq_video-img-icon` rule never needed a border/background reset
   since it only ever styled an <a>. */
.zq_video-img-icon {
    border: none;
    cursor: pointer;
}

/* React-mounted video modal/backdrop - reuses Bootstrap's own `.modal`/
   `.modal-backdrop` classes (bootstrap.min.css is already loaded) for
   consistent overlay styling, but visibility is driven by React state
   rather than Bootstrap's JS instance, so the <iframe> can be unmounted on
   close - undoing that, a closed modal would leave the video's audio
   playing silently in the background. `.fade`+`.show` alone doesn't
   guarantee a high enough stacking context here since these aren't
   appended to <body> the way Bootstrap's own JS would. */
.zq_video-modal {
    z-index: 1060;
}

.zq_video-modal-close {
    position: absolute;
    top: -40px;
    right: 0;
    z-index: 1;
}

/* main.css's own `.zq_video-img img` rule sets `height: 100%` + object-fit:
   cover, but `.zq_video-img` (its parent) has no height of its own anywhere
   in main.css - a percentage height with no defined ancestor height is
   simply ignored, so object-fit:cover never has a box to crop into. The
   image was rendering at its own natural aspect ratio instead of filling a
   wide banner - invisible in front/'s own demo (its placeholder happened to
   be roughly landscape already) but very visible with a portrait photo.

   A *fixed* 700px height (an earlier version of this rule) only matches a
   1920x700 upload's own proportions when the viewport happens to be exactly
   1920px wide - on any narrower window the box stays 700px tall while its
   width shrinks, so the box becomes relatively taller/narrower than the
   image's actual 1920:700 shape, and object-fit:cover crops in hard on the
   left/right to fill it - the uploaded banner reading as oddly "zoomed in".
   `aspect-ratio` instead keeps the box always proportioned like the
   recommended 1920x700 upload, at any width, so cover never has to crop
   more than that image's own edges - `max-height` just stops it growing
   past 700px tall on wider-than-1920px screens, and `min-height` stops it
   getting too short to read on narrow phones (where some left/right crop is
   an acceptable trade-off, same as any responsive hero banner). */
.zq_video-img {
    aspect-ratio: 1920 / 700;
    max-height: 700px;
    min-height: 320px;
}

/* Hero section animated "tech network" visual (hero-tech-animation.tsx) -
   replaces the hero's static stock photo. `.zq_hero-img` (main.css) only
   ever set `max-width: 662px; width: 100%` for the old <img>, with no fixed
   height - this card needs its own since there's no longer an image to
   derive one from. Square-ish like the photo it replaces, dark card with a
   lime glow matching the site's established neon-lime accent (login page,
   partners section borders). */
.zq_hero_tech {
    position: relative;
    width: 100%;
    max-width: 662px;
    aspect-ratio: 1 / 1;
    border-radius: 28px;
    overflow: hidden;
    background: #0a0a0a;
    border: 1px solid rgba(255, 255, 255, 0.08);
    box-shadow:
        0 30px 80px rgba(0, 0, 0, 0.5),
        0 0 70px -20px rgba(163, 230, 53, 0.35);
}

/* Faint drifting grid - gives the card a "circuit board" sense of depth
   without competing with the node network drawn on top of it. Masked to a
   radial fade so it reads as atmosphere, not a literal grid to the edges. */
.zq_hero_tech-grid {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(255, 255, 255, 0.06) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, 0.06) 1px, transparent 1px);
    background-size: 36px 36px;
    -webkit-mask-image: radial-gradient(circle at center, black 10%, transparent 75%);
    mask-image: radial-gradient(circle at center, black 10%, transparent 75%);
    animation: zq_hero_tech_grid_drift 18s linear infinite;
}

@keyframes zq_hero_tech_grid_drift {
    to {
        background-position: 36px 36px;
    }
}

.zq_hero_tech-glow {
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at 30% 70%, rgba(163, 230, 53, 0.18) 0%, rgba(0, 0, 0, 0) 55%);
    pointer-events: none;
}

.zq_hero_tech-network {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Each node "breathes" - a slow scale+glow pulse, staggered per node via an
   inline animation-delay (see hero-tech-animation.tsx) so they don't all
   pulse in lockstep. `transform-box: fill-box` is needed for `transform` to
   scale an SVG <circle> around its own center rather than the SVG
   viewport's origin. */
.zq_hero_tech-node {
    transform-origin: center;
    transform-box: fill-box;
    animation: zq_hero_tech_pulse 2.6s ease-in-out infinite;
}

@keyframes zq_hero_tech_pulse {
    0%,
    100% {
        opacity: 0.55;
        transform: scale(0.85);
    }
    50% {
        opacity: 1;
        transform: scale(1.15);
        filter: drop-shadow(0 0 6px rgba(163, 230, 53, 0.9));
    }
}

/* Marching dashes along each connecting line - a subtle sense of current/data
   flowing through the network, independent of the traveling pulse dots
   (<animateMotion> in the component) riding along a few of the same lines. */
.zq_hero_tech-lines line {
    stroke-dasharray: 6 6;
    animation: zq_hero_tech_dash 6s linear infinite;
}

@keyframes zq_hero_tech_dash {
    to {
        stroke-dashoffset: -120;
    }
}

.zq_hero_tech-pulse {
    filter: drop-shadow(0 0 4px rgba(163, 230, 53, 0.8));
}

/* Site-wide network background (site-network-background.tsx) - fixed behind
   every page, never intercepts clicks (`pointer-events: none`) and never
   covers real content. The negative z-index is what actually makes "behind
   everything" true: body's own background-color paint sits one layer below
   even a negative-z-index child, so the canvas is visible over it, while
   every normal (non-positioned) in-flow element on the page - which is
   nearly all of front/'s own markup - paints in the next layer up,
   regardless of DOM order. See the component for why it must live outside
   #smooth-wrapper/#smooth-content specifically. */
.zq_site_network {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
}

/* Full-screen boot splash (site-intro-loader.tsx) - shown once per real page
   load, never on an in-app navigation. z-index is the highest value
   anywhere in this stylesheet or main.css (the next-highest, 99999, belongs
   to a search popup overlay) so this always sits above literally everything
   else, including the mobile menu. */
.zq_intro-loader {
    position: fixed;
    inset: 0;
    z-index: 999999;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 22px;
    background: #050505;
    transition: opacity 0.45s ease;
}

.zq_intro-loader.is-fading {
    opacity: 0;
    pointer-events: none;
}

.zq_intro-loader-ring {
    position: relative;
    width: 120px;
    height: 120px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(163, 230, 53, 0.25);
    box-shadow: 0 0 50px -10px rgba(163, 230, 53, 0.45);
}

/* The rotating "scan ring" - a dashed-looking spinner made from two
   differently-opaque border segments, same lime accent as the hero/
   background animations, tying this splash into the same visual language
   rather than introducing a new one. */
.zq_intro-loader-ring::before {
    content: '';
    position: absolute;
    inset: -10px;
    border-radius: 50%;
    border: 2px solid transparent;
    border-top-color: rgba(163, 230, 53, 0.9);
    border-right-color: rgba(163, 230, 53, 0.3);
    animation: zq_intro_spin 1.4s linear infinite;
}

@keyframes zq_intro_spin {
    to {
        transform: rotate(360deg);
    }
}

.zq_intro-loader-logo {
    width: 58%;
}

.zq_intro-loader-status {
    color: rgba(255, 255, 255, 0.65);
    font-family: 'Inter', sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 4px;
    text-transform: uppercase;
}

.zq_intro-loader-bar {
    width: 220px;
    height: 2px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 2px;
    overflow: hidden;
}

.zq_intro-loader-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, rgba(163, 230, 53, 0.2), #a3e635);
    box-shadow: 0 0 12px rgba(163, 230, 53, 0.8);
}

.zq_intro-loader-percent {
    color: rgba(163, 230, 53, 0.9);
    font-family: 'Inter', sans-serif;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 1px;
}
